You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/soma/components/relative-time/README.md

79 lines
3.8 KiB

refactor(soma/eidos): migrate 4 service components from Eidos to Soma Architectural cleanup: Trans, FormatDate, FormatNumber, RelativeTime no son visuales — son behavior alrededor del runtime (`uix.langs.t/ts`, `uix.format.*`). Estaban en `eidos/components/` solo porque ahi se inventariaban los wrappers. Naturaleza real: Soma. Beneficio principal: el invariante "Eidos no importa `getActiveUix()`" recupera su pureza — los 4 service components ya no contaban como violación del audit Codex (P1 #1 reducido en 4 archivos + dependencias). Movimientos (4 componentes, 31 archivos staged): - src/uix/eidos/components/{kebab}/ → src/uix/soma/components/{kebab}/ - {kebab}.svelte → components/{kebab}.svelte (subdir convencion Soma) - types.ts → types.ts - README.md → README.md - index.ts → exports.ts (Soma pattern: index re-exports from exports) - + nuevo index.ts: `export * from './exports';` - Eidos dirs eliminados (4 directories). Morfos: scope `['eidos']` → scope `['soma']` (4 archivos): - morfo/components/trans.ts - morfo/components/format-date.ts - morfo/components/format-number.ts - morfo/components/relative-time.ts Demos (4 +page.svelte) updated: - import paths `$uix/eidos/components/{kebab}` → `$soma/components/{kebab}` - meta-pill `scope: eidos` → `scope: soma` Headers de los .svelte updated: "Eidos `<X>`" → "Soma `<X>` — service component" + parrafo explicando por que vive en Soma (behavior, no visual primitive). Verificación: - `npm run check`: 0 errors (mantenido). - HTTP probes /uix/components/{trans,format-date,format-number,relative-time}: todos 200. Sin barrel re-exports a limpiar (no existían). Sin consumers fuera de los 4 demos. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
# Soma RelativeTime
feat(eidos): Card, Avatar ext, Image, SText, Badge, service components + dates engine fixes Sprint completo: - Card (eidos + sema): elevation/intent/interactive, eventos select+activate. - Avatar: ring, AvatarBadge, AvatarGroup separados; demo Avatar standalone. - Image: status surface (idle/loading/loaded/error) consumiendo soma ImageProvider. - SText + STextVirtualList: canvas-text engine portado de morfo-driven-soma como componentes separados para optimizar bundle (no se importa canvas si no se usa). - Badge: primitivo eidos puro. - Trans, FormatNumber, FormatDate, RelativeTime: 4 service components greppables alrededor de uix.langs y uix.format. Nav group "Utilities". Bugs fix arts/format/dates (engine-dates.ts): 1. Preset / per-axis conflict: Intl.DateTimeFormat rechaza dateStyle/timeStyle con cualquier per-axis (weekday/era/year/month/day/dayPeriod/hour/minute/ second/fractionalSecondDigits) o con timeZoneName. Engine drop-ea ambos presets por defecto cuando detecta conflict (regla estricta — un solo per-axis hace ilegales los dos presets). 2. Per-call locale override: formatDate/Time/DateTime aceptan tercer arg locale?: string. No muta engine state. Cache (getCachedDateFormat) keyea por (locale x options). resolveCallHourCycle: cuando hay locale override y pref auto, el ciclo horario se resuelve desde el locale OVERRIDE. 3. withHourCycle precedence: caller hourCycle/hour12 ahora gana sobre preferencia del engine. Antes spread mal ordenado sobrescribia 'h12' del caller con 'h23' del engine cuando locale resolvia a 24h. FormatDate component vuelve a rutear siempre por uix.format.dates (cache + hourCycle + locale reactivo), pasando locale como tercer arg. Demos service components autonomos del toolbar global: cada uno owns su demoLocale state con 7 chips (es-ES/en-US/en-GB/de-DE/fr-FR/ja-JP/ar-EG). FormatDate stage filtra dateStyle/timeStyle por mode + chip hourCycle anadido. Tests: 14/14 passing en engine-dates.test.ts (+6 nuevos: conflict handling, locale override, hourCycle precedence). Docs: arts/format/README.md (handoff 2026-05-25 con las 3 reglas), README.md por service component, project_service_components_sprint_2026-05-25.md, feedback_service_demos_own_locale.md (pattern reusable). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
`<RelativeTime>` es un **service component** que envuelve
`Intl.RelativeTimeFormat` con auto-refresh tick. Renderiza frases
relativas como `"hace 2 horas"` / `"in 3 days"` y se refresca a si mismo
cuando pasa el tiempo.
Familia con `<Trans>`, `<FormatDate>`, `<FormatNumber>`.
refactor(soma/eidos): migrate 4 service components from Eidos to Soma Architectural cleanup: Trans, FormatDate, FormatNumber, RelativeTime no son visuales — son behavior alrededor del runtime (`uix.langs.t/ts`, `uix.format.*`). Estaban en `eidos/components/` solo porque ahi se inventariaban los wrappers. Naturaleza real: Soma. Beneficio principal: el invariante "Eidos no importa `getActiveUix()`" recupera su pureza — los 4 service components ya no contaban como violación del audit Codex (P1 #1 reducido en 4 archivos + dependencias). Movimientos (4 componentes, 31 archivos staged): - src/uix/eidos/components/{kebab}/ → src/uix/soma/components/{kebab}/ - {kebab}.svelte → components/{kebab}.svelte (subdir convencion Soma) - types.ts → types.ts - README.md → README.md - index.ts → exports.ts (Soma pattern: index re-exports from exports) - + nuevo index.ts: `export * from './exports';` - Eidos dirs eliminados (4 directories). Morfos: scope `['eidos']` → scope `['soma']` (4 archivos): - morfo/components/trans.ts - morfo/components/format-date.ts - morfo/components/format-number.ts - morfo/components/relative-time.ts Demos (4 +page.svelte) updated: - import paths `$uix/eidos/components/{kebab}` → `$soma/components/{kebab}` - meta-pill `scope: eidos` → `scope: soma` Headers de los .svelte updated: "Eidos `<X>`" → "Soma `<X>` — service component" + parrafo explicando por que vive en Soma (behavior, no visual primitive). Verificación: - `npm run check`: 0 errors (mantenido). - HTTP probes /uix/components/{trans,format-date,format-number,relative-time}: todos 200. Sin barrel re-exports a limpiar (no existían). Sin consumers fuera de los 4 demos. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Vive en `soma/components/` (no `eidos/components/`) porque es una pieza
de comportamiento alrededor de `getActiveUix()`. La invariante "Eidos no
importa runtime" se preserva sacando los 4 service components a Soma.
feat(eidos): Card, Avatar ext, Image, SText, Badge, service components + dates engine fixes Sprint completo: - Card (eidos + sema): elevation/intent/interactive, eventos select+activate. - Avatar: ring, AvatarBadge, AvatarGroup separados; demo Avatar standalone. - Image: status surface (idle/loading/loaded/error) consumiendo soma ImageProvider. - SText + STextVirtualList: canvas-text engine portado de morfo-driven-soma como componentes separados para optimizar bundle (no se importa canvas si no se usa). - Badge: primitivo eidos puro. - Trans, FormatNumber, FormatDate, RelativeTime: 4 service components greppables alrededor de uix.langs y uix.format. Nav group "Utilities". Bugs fix arts/format/dates (engine-dates.ts): 1. Preset / per-axis conflict: Intl.DateTimeFormat rechaza dateStyle/timeStyle con cualquier per-axis (weekday/era/year/month/day/dayPeriod/hour/minute/ second/fractionalSecondDigits) o con timeZoneName. Engine drop-ea ambos presets por defecto cuando detecta conflict (regla estricta — un solo per-axis hace ilegales los dos presets). 2. Per-call locale override: formatDate/Time/DateTime aceptan tercer arg locale?: string. No muta engine state. Cache (getCachedDateFormat) keyea por (locale x options). resolveCallHourCycle: cuando hay locale override y pref auto, el ciclo horario se resuelve desde el locale OVERRIDE. 3. withHourCycle precedence: caller hourCycle/hour12 ahora gana sobre preferencia del engine. Antes spread mal ordenado sobrescribia 'h12' del caller con 'h23' del engine cuando locale resolvia a 24h. FormatDate component vuelve a rutear siempre por uix.format.dates (cache + hourCycle + locale reactivo), pasando locale como tercer arg. Demos service components autonomos del toolbar global: cada uno owns su demoLocale state con 7 chips (es-ES/en-US/en-GB/de-DE/fr-FR/ja-JP/ar-EG). FormatDate stage filtra dateStyle/timeStyle por mode + chip hourCycle anadido. Tests: 14/14 passing en engine-dates.test.ts (+6 nuevos: conflict handling, locale override, hourCycle precedence). Docs: arts/format/README.md (handoff 2026-05-25 con las 3 reglas), README.md por service component, project_service_components_sprint_2026-05-25.md, feedback_service_demos_own_locale.md (pattern reusable). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## Superficie
```svelte
<RelativeTime value={post.publishedAt} />
<RelativeTime value={createdAt} style="short" />
<RelativeTime value={dueDate} unit="day" />
<RelativeTime value={deadline} now={projectStart} unit="week" />
<RelativeTime value={start} updateInterval={0} />
<RelativeTime value={now} locale="ja-JP" />
```
## Props clave
| Prop | Tipo | Default | Notas |
| --- | --- | --- | --- |
| `value` | `Date \| number \| string \| null` | — | `null` o invalid → `fallback`. |
| `now` | `Date \| number \| string` | `Date.now()` | Punto de referencia. Permite anclar el "ahora". |
| `unit` | `'auto' \| 'year' \| 'quarter' \| 'month' \| 'week' \| 'day' \| 'hour' \| 'minute' \| 'second'` | `'auto'` | `'auto'` escoge la granularidad mas natural. |
| `numeric` | `'auto' \| 'always'` | `'auto'` | `'auto'` colapsa 0/-1/+1 en palabras (`"yesterday"`, `"today"`). |
| `style` | `'long' \| 'short' \| 'narrow'` | `'long'` | Flavor del label. |
| `updateInterval` | `'auto' \| number` | `'auto'` | Cadencia de tick en ms; `0` = sin auto-refresh. |
| `locale` | `SupportedLocale` | runtime dates | Override por instancia. |
| `fallback` | `string` | `''` | Render cuando `value` es invalid. |
| `as` | `keyof HTMLElementTagNameMap` | `'time'` | Tag HTML. |
## Decisiones
- **Auto-unit**: cuando `unit='auto'`, el componente escoge la unidad de
mayor magnitud que aplique (`year → quarter → month → week → day →
hour → minute → second`). Cae a `'second'` si la magnitud no llega a
60s.
- **Auto-tick cadence**: cuando `updateInterval='auto'`, la cadencia se
deriva del unit resuelto: `1s` para `second`, `30s` para `minute`,
`5min` para `hour`, `1h` para `day`. Para units mayores no hay tick.
- **`updateInterval={0}`** apaga el auto-refresh — util para snapshots
estaticos en tablas / patterns.
feat(format/dates): add formatRelative to engine + route RelativeTime through runtime $libs/days/format.ts: - Nuevo `getCachedRelativeTimeFormat(locale, options)` — twin del cache ya existente `getCachedDateFormat`. Key `${locale}:${JSON.stringify(opts)}`. Sites que renderizan listas de timestamps relativos (feeds, activity logs) hit identical pairs y mantienen el loop caliente. arts/format/dates/engine-dates.ts + types.ts: - Nuevo `formatRelative(value, unit, options?, locale?)` en EngineDates. Defaults: `numeric: 'auto'` (colapsa 0/-1/+1 en "yesterday"/"today"), `style: 'long'`. Per-call locale override no muta engine state. arts/format/dates/active-dates.svelte.ts: - formatRelative wired via `readFrom(runtime, engine.formatRelative)` para que el $derived del componente sea reactivo al cambio de locale. Componente relative-time.svelte: - Drop del bypass directo a `new Intl.RelativeTimeFormat(locale, opts)`. Ahora SIEMPRE rutea por `uix.format.dates.formatRelative(magnitude, unit, { numeric, style }, locale)`. El componente sigue haciendo la matematica del delta + auto-unit + magnitud — el engine solo expone la operacion atomica. - Fallback a Intl directo solo cuando no hay runtime (eidos fuera de UixApp). Tests: 17/17 en engine-dates.test.ts (+3 nuevos: formatRelative con locale del engine, numeric/style options, per-call locale override sin mutar state). Docs: arts/format/README.md sub-seccion en Dates con la nueva API. relative-time/README.md decisiones actualizadas (ya no es la excepcion). Cierra el ultimo follow-up del sprint de service components — los 4 componentes (Trans, FormatNumber, FormatDate, RelativeTime) ahora rutean uniformemente por el runtime UIX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- **Siempre rutea por `uix.format.dates.formatRelative`** (no llama a
`Intl.RelativeTimeFormat` directamente excepto cuando no hay runtime).
El engine envuelve el cache compartido (`getCachedRelativeTimeFormat`
en `$libs/days`), preserva la reactividad del locale activo, y acepta
el `locale` prop como override por llamada sin mutar engine state.
- **El componente sigue haciendo la matematica del delta + auto-unit + magnitud**
— el engine solo expone la operacion atomica `(magnitude, unit,
options, locale) → string`.
feat(eidos): Card, Avatar ext, Image, SText, Badge, service components + dates engine fixes Sprint completo: - Card (eidos + sema): elevation/intent/interactive, eventos select+activate. - Avatar: ring, AvatarBadge, AvatarGroup separados; demo Avatar standalone. - Image: status surface (idle/loading/loaded/error) consumiendo soma ImageProvider. - SText + STextVirtualList: canvas-text engine portado de morfo-driven-soma como componentes separados para optimizar bundle (no se importa canvas si no se usa). - Badge: primitivo eidos puro. - Trans, FormatNumber, FormatDate, RelativeTime: 4 service components greppables alrededor de uix.langs y uix.format. Nav group "Utilities". Bugs fix arts/format/dates (engine-dates.ts): 1. Preset / per-axis conflict: Intl.DateTimeFormat rechaza dateStyle/timeStyle con cualquier per-axis (weekday/era/year/month/day/dayPeriod/hour/minute/ second/fractionalSecondDigits) o con timeZoneName. Engine drop-ea ambos presets por defecto cuando detecta conflict (regla estricta — un solo per-axis hace ilegales los dos presets). 2. Per-call locale override: formatDate/Time/DateTime aceptan tercer arg locale?: string. No muta engine state. Cache (getCachedDateFormat) keyea por (locale x options). resolveCallHourCycle: cuando hay locale override y pref auto, el ciclo horario se resuelve desde el locale OVERRIDE. 3. withHourCycle precedence: caller hourCycle/hour12 ahora gana sobre preferencia del engine. Antes spread mal ordenado sobrescribia 'h12' del caller con 'h23' del engine cuando locale resolvia a 24h. FormatDate component vuelve a rutear siempre por uix.format.dates (cache + hourCycle + locale reactivo), pasando locale como tercer arg. Demos service components autonomos del toolbar global: cada uno owns su demoLocale state con 7 chips (es-ES/en-US/en-GB/de-DE/fr-FR/ja-JP/ar-EG). FormatDate stage filtra dateStyle/timeStyle por mode + chip hourCycle anadido. Tests: 14/14 passing en engine-dates.test.ts (+6 nuevos: conflict handling, locale override, hourCycle precedence). Docs: arts/format/README.md (handoff 2026-05-25 con las 3 reglas), README.md por service component, project_service_components_sprint_2026-05-25.md, feedback_service_demos_own_locale.md (pattern reusable). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- **`<time datetime="ISO 8601">` por defecto** para a11y / SEO.
- **`data-unit`** expuesto en el DOM para CSS/tooling que quiera estilar
por granularidad (ej. iconos diferentes para "second" vs "year").
- **No emite eventos sema**.
## Comparativa
refactor(soma/eidos): migrate 4 service components from Eidos to Soma Architectural cleanup: Trans, FormatDate, FormatNumber, RelativeTime no son visuales — son behavior alrededor del runtime (`uix.langs.t/ts`, `uix.format.*`). Estaban en `eidos/components/` solo porque ahi se inventariaban los wrappers. Naturaleza real: Soma. Beneficio principal: el invariante "Eidos no importa `getActiveUix()`" recupera su pureza — los 4 service components ya no contaban como violación del audit Codex (P1 #1 reducido en 4 archivos + dependencias). Movimientos (4 componentes, 31 archivos staged): - src/uix/eidos/components/{kebab}/ → src/uix/soma/components/{kebab}/ - {kebab}.svelte → components/{kebab}.svelte (subdir convencion Soma) - types.ts → types.ts - README.md → README.md - index.ts → exports.ts (Soma pattern: index re-exports from exports) - + nuevo index.ts: `export * from './exports';` - Eidos dirs eliminados (4 directories). Morfos: scope `['eidos']` → scope `['soma']` (4 archivos): - morfo/components/trans.ts - morfo/components/format-date.ts - morfo/components/format-number.ts - morfo/components/relative-time.ts Demos (4 +page.svelte) updated: - import paths `$uix/eidos/components/{kebab}` → `$soma/components/{kebab}` - meta-pill `scope: eidos` → `scope: soma` Headers de los .svelte updated: "Eidos `<X>`" → "Soma `<X>` — service component" + parrafo explicando por que vive en Soma (behavior, no visual primitive). Verificación: - `npm run check`: 0 errors (mantenido). - HTTP probes /uix/components/{trans,format-date,format-number,relative-time}: todos 200. Sin barrel re-exports a limpiar (no existían). Sin consumers fuera de los 4 demos. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
| Capacidad | Soma | date-fns `formatDistance` | Day.js `from` | luxon `toRelative` | Intl.RelativeTimeFormat |
feat(eidos): Card, Avatar ext, Image, SText, Badge, service components + dates engine fixes Sprint completo: - Card (eidos + sema): elevation/intent/interactive, eventos select+activate. - Avatar: ring, AvatarBadge, AvatarGroup separados; demo Avatar standalone. - Image: status surface (idle/loading/loaded/error) consumiendo soma ImageProvider. - SText + STextVirtualList: canvas-text engine portado de morfo-driven-soma como componentes separados para optimizar bundle (no se importa canvas si no se usa). - Badge: primitivo eidos puro. - Trans, FormatNumber, FormatDate, RelativeTime: 4 service components greppables alrededor de uix.langs y uix.format. Nav group "Utilities". Bugs fix arts/format/dates (engine-dates.ts): 1. Preset / per-axis conflict: Intl.DateTimeFormat rechaza dateStyle/timeStyle con cualquier per-axis (weekday/era/year/month/day/dayPeriod/hour/minute/ second/fractionalSecondDigits) o con timeZoneName. Engine drop-ea ambos presets por defecto cuando detecta conflict (regla estricta — un solo per-axis hace ilegales los dos presets). 2. Per-call locale override: formatDate/Time/DateTime aceptan tercer arg locale?: string. No muta engine state. Cache (getCachedDateFormat) keyea por (locale x options). resolveCallHourCycle: cuando hay locale override y pref auto, el ciclo horario se resuelve desde el locale OVERRIDE. 3. withHourCycle precedence: caller hourCycle/hour12 ahora gana sobre preferencia del engine. Antes spread mal ordenado sobrescribia 'h12' del caller con 'h23' del engine cuando locale resolvia a 24h. FormatDate component vuelve a rutear siempre por uix.format.dates (cache + hourCycle + locale reactivo), pasando locale como tercer arg. Demos service components autonomos del toolbar global: cada uno owns su demoLocale state con 7 chips (es-ES/en-US/en-GB/de-DE/fr-FR/ja-JP/ar-EG). FormatDate stage filtra dateStyle/timeStyle por mode + chip hourCycle anadido. Tests: 14/14 passing en engine-dates.test.ts (+6 nuevos: conflict handling, locale override, hourCycle precedence). Docs: arts/format/README.md (handoff 2026-05-25 con las 3 reglas), README.md por service component, project_service_components_sprint_2026-05-25.md, feedback_service_demos_own_locale.md (pattern reusable). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
| --- | --- | --- | --- | --- | --- |
| Auto-unit | Si | Si | Si | Si | No (manual) |
| Auto-tick | Si | No | No | No | No |
| Numeric=auto (`"yesterday"`) | Si | No | No | No | Si |
| Style short/narrow | Si | No | No | Manual | Si |
| Reactivo al locale UIX | Si | No | No | No | No |
| `<time datetime>` semantico | Si | No | No | No | No |
| `data-unit` | Si | No | No | No | No |
## Referencias
- Intl.RelativeTimeFormat: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat
- Dates engine: `src/arts/format/dates/engine-dates.ts` (de donde lee el locale activo)

Powered by TurnKey Linux.