Revisadas las demas graficas del catalogo tras el eje Y. Dos rotas, y arreglarlas enseño donde estaba mi error de criterio. FUNNEL. En RTL las etiquetas y sus lineas guia se dibujaban ENCIMA del embudo. Su `labelPosition` ofrece `'inside' | 'right' | 'none'`: `'right'` es el UNICO valor lateral —no existe `'left'`—, asi que ese nombre no es una eleccion fisica del consumidor (a diferencia del `side` de drawer, que ofrece los dos) sino una suposicion LTR. Bajo RTL la columna de etiquetas va al lado de lectura contrario, asi que se espeja la composicion entera: embudo a la derecha, etiquetas a la izquierda. El cuerpo del embudo es simetrico respecto a `cx`, de modo que espejarlo es solo mover ese centro. CALENDAR-HEATMAP. Sus etiquetas de mes y de dia viven en canalones FIJOS y sus anchors `start`/`end` se volteaban, dejando "lun/mié/vie" pegadas a las celdas. Ahi si hay que forzar el anchor fisico, porque el canalon no se mueve. LA REGLA, que me costo dos intentos en el funnel: si la composicion SE ESPEJA, el anchor LOGICO ya es el correcto y voltearlo ademas deshace el espejo —lo hice y las etiquetas volvieron sobre el embudo—. Si la composicion NO se espeja (el canalon del eje Y, los de este calendario), hay que forzar el fisico. Queda escrito en rtl.svelte.ts, que centraliza las dos piezas: `physicalAnchor()` y un `createChartRtl()` que lee la direccion RESUELTA del elemento —las graficas sueltas no tienen el contexto de <Chart>, y `prefs.getDir()` devuelve undefined en este arbol mientras el elemento computa rtl bien—. Verificado MIRANDO capturas en oscuro, en RTL y en la pagina, antes y despues de cada cambio, no midiendo en LTR como hice las tres primeras veces. QUEDA, y no esta hecho: el calendario no se espeja —enero sigue a la izquierda en RTL, igual que le pasaba al eje X del chart antes de 55070c688—. Y de la misma clase sin revisar: heatmap.svelte:145 (`end` en el canalon izquierdo) y los anchors calculados de radar-chart. check 74 = linea base exacta. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>alpha-0.1-dir-prefs
parent
6e8d2d9223
commit
2636b40eaf
@ -0,0 +1,69 @@
|
||||
import type { ActiveEidos } from '$uix/eidos';
|
||||
|
||||
/**
|
||||
* Direction helpers shared by the chart family.
|
||||
*
|
||||
* SVG's `text-anchor` is LOGICAL: under `direction: rtl`, `end` means the LEFT
|
||||
* side. Chart gutters are not logical — the y-axis labels, a calendar's weekday
|
||||
* column and a funnel's leader labels all sit on a fixed PHYSICAL side of the
|
||||
* drawing. Left alone, every one of those anchors flips when the page does and
|
||||
* the text grows back across the graphic: measured on the y axis, a label ran
|
||||
* from x=32 to x=59.9 with the axis at 46, i.e. straight through it. The funnel
|
||||
* put its whole label column on top of the funnel body.
|
||||
*/
|
||||
|
||||
/** Flip a logical `text-anchor` so it lands on the intended PHYSICAL side. */
|
||||
export function physicalAnchor(
|
||||
anchor: 'start' | 'middle' | 'end',
|
||||
rtl: boolean
|
||||
): 'start' | 'middle' | 'end' {
|
||||
if (!rtl || anchor === 'middle') return anchor;
|
||||
return anchor === 'start' ? 'end' : 'start';
|
||||
}
|
||||
|
||||
/**
|
||||
* Reactive "is this element resolved RTL?" for a chart that has no `<Chart>`
|
||||
* frame above it.
|
||||
*
|
||||
* Reads the RESOLVED direction off the element rather than a preference: a
|
||||
* chart can sit in a subtree with its own `dir`, and the `ActiveEidos` the demo
|
||||
* shell builds does not always carry the prefs the topbar writes (`getDir()`
|
||||
* returns undefined there while the element computes `rtl` correctly). Same
|
||||
* source `$ethereal/compute.ts` uses. `direction` is a computed STYLE, not
|
||||
* geometry, so reading it forces no layout — and nothing else fires on a
|
||||
* direction change, hence the attribute observer.
|
||||
*/
|
||||
export function createChartRtl(eidos: ActiveEidos) {
|
||||
let rtl = $state(false);
|
||||
let el = $state<Element | null>(null);
|
||||
|
||||
$effect(() => {
|
||||
const node = el;
|
||||
if (!node) return;
|
||||
const read = () => {
|
||||
rtl = eidos.dom.getWindow(node).getComputedStyle(node).direction === 'rtl';
|
||||
};
|
||||
read();
|
||||
return eidos.dom.observeMutation(eidos.dom.getDocument(node).documentElement, read, {
|
||||
attributes: true,
|
||||
attributeFilter: ['dir']
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
/** Bind to the element whose direction decides (`bind:this`). */
|
||||
set ref(node: Element | null) {
|
||||
el = node;
|
||||
},
|
||||
get ref() {
|
||||
return el;
|
||||
},
|
||||
get current() {
|
||||
return rtl;
|
||||
},
|
||||
/** `text-anchor` that lands on the intended physical side. */
|
||||
anchor(a: 'start' | 'middle' | 'end') {
|
||||
return physicalAnchor(a, rtl);
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Reference in new issue