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>
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>