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/eidos/components/format-date/README.md

102 lines
5.0 KiB

# Eidos FormatDate
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
`<FormatDate>` es un **service component** — un wrapper greppable de
`getActiveUix().format.dates.formatDate / formatTime / formatDateTime`.
Renderiza un valor `Date | number | string` a traves del runtime activo
de UIX y emite `<time datetime="ISO 8601">` por defecto para asistencia
tecnica y SEO.
Familia con `<Trans>`, `<FormatNumber>`, `<RelativeTime>`: todos son
wrappers tipados del runtime para que un audit i18n/l10n encuentre cada
sitio de formateo con `grep "<FormatDate"`.
## Superficie
```svelte
<FormatDate value={post.publishedAt} />
<FormatDate value={meeting.startsAt} mode="dateTime" dateStyle="short" timeStyle="short" />
<FormatDate value={createdAt} mode="time" timeZone="UTC" timeZoneName="short" />
<FormatDate value={anniversary} weekday="long" day="numeric" month="long" />
<FormatDate value={now} locale="ja-JP" dateStyle="full" />
<FormatDate value={start} mode="time" hourCycle="h12" />
```
## Props clave
| Prop | Tipo | Default | Notas |
| --- | --- | --- | --- |
| `value` | `Date \| number \| string \| null` | — | `null` o invalid → renderiza `fallback`. |
| `mode` | `'date' \| 'time' \| 'dateTime'` | `'date'` | Decide a que metodo del runtime se rutea. |
| `dateStyle` | `'short' \| 'medium' \| 'long' \| 'full'` | — | Preset. Por defecto `'medium'` cuando aplique. |
| `timeStyle` | idem | — | Preset. Por defecto `'short'` cuando aplique. |
| `weekday / era / year / month / day` | per-axis | — | Override fino. Drop-ea los presets. |
| `hour / minute / second / dayPeriod / fractionalSecondDigits` | per-axis | — | Idem para axis temporal. |
| `timeZone` | `string` | local | IANA zone (`Europe/Madrid`, …). |
| `timeZoneName` | `'short' \| 'long' \| 'shortOffset' \| 'longOffset' \| 'shortGeneric' \| 'longGeneric'` | — | Label de zona. Drop-ea presets. |
| `hourCycle` | `'h11' \| 'h12' \| 'h23' \| 'h24'` | — | Caller gana sobre preferencia del engine. |
| `calendar / numberingSystem` | `string` | — | Orthogonal a presets. |
| `locale` | `SupportedLocale` | runtime | Override por llamada. No muta el runtime. |
| `fallback` | `string` | `''` | Render cuando `value` es `null` / invalid. |
| `as` | `keyof HTMLElementTagNameMap` | `'time'` | Tag HTML. |
## Decisiones
- **Siempre rutea por `uix.format.dates`** (no llama a `Intl` directamente
excepto cuando no hay runtime). Esto preserva el cache
(`getCachedDateFormat`), la preferencia de `hourCycle` del engine, el
conflict handling, y la reactividad del locale activo.
- **`locale` se pasa como tercer arg al runtime** (`dates.formatDate(value,
options, locale)`) — el engine acepta override por llamada sin mutar
state. El cache keyea por `(locale × options)`.
- **Mode + presets**: `mode` decide a que metodo del runtime se rutea
(`formatDate / formatTime / formatDateTime`). Cada uno inyecta su
preset default (`dateStyle: 'medium'`, `timeStyle: 'short'`) solo si
no hay conflict con per-axis fields o `timeZoneName`.
- **`<time datetime="ISO 8601">` por defecto**: el ISO original queda
disponible para asistencia tecnica y crawlers. Si el caller pasa
`as="span"`, el `datetime` se aplica al span (validado por Svelte) pero
pierde la semantica nativa.
- **No CSS recipe**: el marker `[data-format-date]` existe solo para
tooling — no hay estilos a nivel de eidos porque el output es texto
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
puro.
- **No emite eventos sema**: no es una acto perceptivo del usuario.
## Conflict handling (Intl rules)
`Intl.DateTimeFormat` lanza si mezclas `dateStyle` / `timeStyle` con
cualquier per-axis field (`weekday`, `era`, `year`, `month`, `day`,
`dayPeriod`, `hour`, `minute`, `second`, `fractionalSecondDigits`) o con
`timeZoneName`. El engine drop-ea los defaults cuando detecta conflict —
**ambos presets** caen juntos porque la regla es estricta.
Si quieres mostrar timezone label (`timeZoneName`), usa per-axis:
```svelte
<FormatDate
value={createdAt}
year="numeric" month="short" day="numeric"
hour="2-digit" minute="2-digit"
timeZone="UTC" timeZoneName="short"
/>
<!-- '25 may 2026, 14:30 UTC' -->
```
## Comparativa
| Capacidad | Eidos | date-fns | Day.js | luxon | Intl.DateTimeFormat |
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
| --- | --- | --- | --- | --- | --- |
| Modo `date`/`time`/`dateTime` | Si | Manual via format strings | Manual | Si (`toLocaleString`) | Manual |
| Locale reactivo desde runtime | Si | No | No | No | No |
| Cache de instancias por options | Si | No | No | No | No (creas instancia) |
| Conflict handling automatico | Si | N/A | N/A | N/A | No (lanza error) |
| HourCycle preference + override | Si | Manual | Manual | Si | No persistencia |
| `<time datetime>` semantico | Si | No | No | No | No |
| Per-call locale override | Si | Cambia DateLocale global | Manual | Manual | Si por instancia |
## Referencias
- Intl.DateTimeFormat: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat
- Engine wiring: `src/arts/format/dates/engine-dates.ts`
- Active runtime: `src/arts/format/dates/active-dates.svelte.ts`
- Conflict tests: `src/arts/format/dates/test/engine-dates.test.ts`

Powered by TurnKey Linux.