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>active-uix
parent
546aa8d0ee
commit
540abee026
@ -1,20 +0,0 @@
|
|||||||
// FormatDate — service component wrapping uix.format.dates.
|
|
||||||
//
|
|
||||||
// import { FormatDate } from '$uix/eidos/components/format-date';
|
|
||||||
//
|
|
||||||
// <FormatDate value={post.publishedAt} dateStyle="medium" />
|
|
||||||
// <FormatDate value={meeting.startsAt} mode="dateTime" />
|
|
||||||
// <FormatDate value={now} mode="time" timeZoneName="short" />
|
|
||||||
//
|
|
||||||
// Renders as <time datetime="..."> for semantic ISO 8601 access.
|
|
||||||
import FormatDate from './format-date.svelte';
|
|
||||||
|
|
||||||
export { FormatDate };
|
|
||||||
export default FormatDate;
|
|
||||||
export type {
|
|
||||||
FormatDateProps,
|
|
||||||
FormatDateInput,
|
|
||||||
FormatDateMode,
|
|
||||||
FormatDateStyle,
|
|
||||||
FormatTimeStyle
|
|
||||||
} from './types';
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
// RelativeTime — service component rendering Intl.RelativeTimeFormat
|
|
||||||
// output ("hace 2 horas" / "in 3 days") with an auto-refresh tick.
|
|
||||||
//
|
|
||||||
// import { RelativeTime } from '$uix/eidos/components/relative-time';
|
|
||||||
//
|
|
||||||
// <RelativeTime value={post.publishedAt} />
|
|
||||||
// <RelativeTime value={createdAt} style="short" />
|
|
||||||
// <RelativeTime value={dueDate} unit="day" updateInterval={0} />
|
|
||||||
import RelativeTime from './relative-time.svelte';
|
|
||||||
|
|
||||||
export { RelativeTime };
|
|
||||||
export default RelativeTime;
|
|
||||||
export type {
|
|
||||||
RelativeTimeProps,
|
|
||||||
RelativeTimeInput,
|
|
||||||
RelativeTimeUnit,
|
|
||||||
RelativeTimeNumeric,
|
|
||||||
RelativeTimeStyle
|
|
||||||
} from './types';
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
# Eidos Trans
|
|
||||||
|
|
||||||
`<Trans>` es un **service component** — un wrapper greppable de
|
|
||||||
`getActiveUix().langs.t / ts`. Resuelve un `idlangref` o un `path` a
|
|
||||||
traves del catalogo activo de langs y renderiza el texto traducido.
|
|
||||||
|
|
||||||
Familia con `<FormatDate>`, `<FormatNumber>`, `<RelativeTime>`: todos
|
|
||||||
son wrappers tipados del runtime para que un audit i18n encuentre cada
|
|
||||||
sitio que toca el catalogo con `grep "<Trans"`.
|
|
||||||
|
|
||||||
## Superficie
|
|
||||||
|
|
||||||
```svelte
|
|
||||||
<!-- 5 modos de resolucion -->
|
|
||||||
<Trans>#?common.save|Save</Trans> <!-- children como idlangref -->
|
|
||||||
<Trans value="#?common.save|Save" /> <!-- value prop -->
|
|
||||||
<Trans path="common.save">Save</Trans> <!-- path + children=fallback -->
|
|
||||||
<Trans path="common.greet" params={{name: 'Juan'}} />
|
|
||||||
<Trans as="strong">#?ui.required|Required</Trans>
|
|
||||||
<Trans path="common.save" locale="en-US">Save</Trans>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Props clave
|
|
||||||
|
|
||||||
| Prop | Tipo | Default | Notas |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| `value` | `LangString` | — | `idlangref` (`#?path\|fallback`) o literal. |
|
|
||||||
| `path` | `string` | — | Dotted path al catalogo (ej. `'common.save'`). |
|
|
||||||
| `params` | `Record<string, unknown>` | — | Interpolacion para `path`. |
|
|
||||||
| `locale` | `SupportedLocale` | runtime | Override por instancia. |
|
|
||||||
| `trim` | `boolean` | `true` | Trim del texto capturado de children. |
|
|
||||||
| `as` | `keyof HTMLElementTagNameMap` | `'span'` | Tag HTML. |
|
|
||||||
| `children` | snippet | — | Fallback / source si no hay `value` / `path`. |
|
|
||||||
|
|
||||||
## Modos de resolucion
|
|
||||||
|
|
||||||
| Modo | Forma | Source |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| 1. Children-only | `<Trans>#?common.save\|Save</Trans>` | DOM `textContent` parseado como `idlangref`. |
|
|
||||||
| 2. Value prop | `<Trans value="#?common.save\|Save" />` | `value` parseado. |
|
|
||||||
| 3. Path + children fallback | `<Trans path="common.save">Save</Trans>` | `t(path)` con `children` como fallback si la key no existe. |
|
|
||||||
| 4. Path + params | `<Trans path="common.greet" params={{name}} />` | `t(path, params)`. |
|
|
||||||
| 5. Pass-through | `<Trans value="literal text" />` | Texto literal sin resolver. |
|
|
||||||
|
|
||||||
## Decisiones
|
|
||||||
|
|
||||||
- **Reactivo al locale**: el `$derived` re-corre cuando el locale activo
|
|
||||||
cambia. La lectura va a traves de `uix.langs.t / ts` que estan
|
|
||||||
acopladas al sistema reactivo de runes.
|
|
||||||
- **Captura de children**: cuando ni `value` ni `path` estan
|
|
||||||
presentes, el componente captura `textContent` del nodo via
|
|
||||||
`bind:this={captureNode}` + `$effect`. La primera render emite el
|
|
||||||
children original (`#?path|fallback` sin resolver); en `$effect`
|
|
||||||
intercepta y resuelve.
|
|
||||||
- **Cast del path**: `langs.t()` tipa su primer overload con
|
|
||||||
`${string}.${string}` (template literal estricto). Como el runtime
|
|
||||||
acepta paths dinamicos en runtime, se castea via
|
|
||||||
`Parameters<typeof t>[0]`.
|
|
||||||
- **Fallback a children**: cuando `t(path)` devuelve el path original
|
|
||||||
(signal de "key no encontrada"), el componente cae al `capturedText`
|
|
||||||
si existe.
|
|
||||||
- **No CSS recipe**: marker `[data-trans]` solo para tooling.
|
|
||||||
- **No emite eventos sema**.
|
|
||||||
|
|
||||||
## Comparativa
|
|
||||||
|
|
||||||
| Capacidad | Eidos | i18next `Trans` | formatjs `FormattedMessage` | svelte-i18n `_` |
|
|
||||||
| --- | --- | --- | --- | --- |
|
|
||||||
| Greppable site marker | Si: `<Trans` | Si | Si | No: `$_('key')` inline |
|
|
||||||
| Children-as-idlangref | Si: `#?path\|fallback` | Si | No | No |
|
|
||||||
| Path + params | Si | Si | Si | Si |
|
|
||||||
| Locale override per-instance | Si | Limitado | Si | No |
|
|
||||||
| Reactivo al cambio de locale | Si | Si | Si | Si |
|
|
||||||
| Tag HTML configurable | Si: `as` | Si: `as` | Si: `tagName` | No |
|
|
||||||
| Pluralizacion | Via params del catalogo | Si | Si | Si |
|
|
||||||
|
|
||||||
## Referencias
|
|
||||||
|
|
||||||
- i18next Trans: https://react.i18next.com/latest/trans-component
|
|
||||||
- formatjs: https://formatjs.io/docs/react-intl/components#formattedmessage
|
|
||||||
- Active langs: `src/arts/langs/`
|
|
||||||
- Sistema idlangref: `src/uix/langs/`
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
// Trans — i18n primitive that resolves an idlangref or path through
|
|
||||||
// the active langs catalog and renders the translated string.
|
|
||||||
//
|
|
||||||
// import { Trans } from '$uix/eidos/components/trans';
|
|
||||||
//
|
|
||||||
// <Trans>#?common.save|Save</Trans>
|
|
||||||
// <Trans value="#?common.save|Save" />
|
|
||||||
// <Trans path="common.save">Save</Trans>
|
|
||||||
// <Trans path="common.greet" params={{ name: 'Juan' }} />
|
|
||||||
// <Trans as="strong">#?ui.required|Required</Trans>
|
|
||||||
//
|
|
||||||
// Reactive to locale changes; greppable as the canonical i18n marker.
|
|
||||||
import Trans from './trans.svelte';
|
|
||||||
|
|
||||||
export { Trans };
|
|
||||||
export default Trans;
|
|
||||||
export type { TransProps } from './types';
|
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
// FormatDate — service component wrapping uix.format.dates.
|
||||||
|
//
|
||||||
|
// import { FormatDate } from '$soma/components/format-date';
|
||||||
|
//
|
||||||
|
// <FormatDate value={post.publishedAt} dateStyle="medium" />
|
||||||
|
// <FormatDate value={meeting.startsAt} mode="dateTime" />
|
||||||
|
// <FormatDate value={now} mode="time" timeZoneName="short" />
|
||||||
|
//
|
||||||
|
// Renders as <time datetime="..."> for semantic ISO 8601 access.
|
||||||
|
//
|
||||||
|
// Lives under `soma/` (not `eidos/`) because the component owns runtime
|
||||||
|
// access. Eidos invariant — "no `getActiveUix()` imports" — is enforced
|
||||||
|
// across the visual layer; service components like `Trans` /
|
||||||
|
// `FormatDate` / `FormatNumber` / `RelativeTime` are their Soma-side peers.
|
||||||
|
export { default as FormatDate } from './components/format-date.svelte';
|
||||||
|
export { default as Provider } from './components/format-date.svelte';
|
||||||
|
|
||||||
|
export type {
|
||||||
|
FormatDateProps,
|
||||||
|
FormatDateInput,
|
||||||
|
FormatDateMode,
|
||||||
|
FormatDateStyle,
|
||||||
|
FormatTimeStyle
|
||||||
|
} from './types';
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from './exports';
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from './exports';
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
// RelativeTime — service component rendering Intl.RelativeTimeFormat
|
||||||
|
// output ("hace 2 horas" / "in 3 days") with an auto-refresh tick.
|
||||||
|
//
|
||||||
|
// import { RelativeTime } from '$soma/components/relative-time';
|
||||||
|
//
|
||||||
|
// <RelativeTime value={post.publishedAt} />
|
||||||
|
// <RelativeTime value={createdAt} style="short" />
|
||||||
|
// <RelativeTime value={dueDate} unit="day" updateInterval={0} />
|
||||||
|
//
|
||||||
|
// Lives under `soma/` (not `eidos/`) because the component owns runtime
|
||||||
|
// access. Eidos invariant — "no `getActiveUix()` imports" — is enforced
|
||||||
|
// across the visual layer; service components like `Trans` /
|
||||||
|
// `FormatDate` / `FormatNumber` / `RelativeTime` are their Soma-side peers.
|
||||||
|
export { default as RelativeTime } from './components/relative-time.svelte';
|
||||||
|
export { default as Provider } from './components/relative-time.svelte';
|
||||||
|
|
||||||
|
export type {
|
||||||
|
RelativeTimeProps,
|
||||||
|
RelativeTimeInput,
|
||||||
|
RelativeTimeUnit,
|
||||||
|
RelativeTimeNumeric,
|
||||||
|
RelativeTimeStyle
|
||||||
|
} from './types';
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from './exports';
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
// Trans — i18n service component. Renders translated text through the
|
||||||
|
// active langs catalog (`uix.langs.t / ts`).
|
||||||
|
//
|
||||||
|
// import { Trans } from '$soma/components/trans';
|
||||||
|
//
|
||||||
|
// <Trans>#?common.save|Save</Trans>
|
||||||
|
// <Trans value="#?common.save|Save" />
|
||||||
|
// <Trans path="common.save">Save</Trans>
|
||||||
|
// <Trans path="common.greet" params={{ name: 'Juan' }} />
|
||||||
|
// <Trans as="strong">#?ui.required|Required</Trans>
|
||||||
|
//
|
||||||
|
// Reactive to locale changes; greppable as the canonical i18n marker.
|
||||||
|
//
|
||||||
|
// Lives under `soma/` (not `eidos/`) because the component owns runtime
|
||||||
|
// access. Eidos invariant — "no `getActiveUix()` imports" — is enforced
|
||||||
|
// across the visual layer; service components like `Trans` /
|
||||||
|
// `FormatDate` / `FormatNumber` / `RelativeTime` are their Soma-side
|
||||||
|
// peers.
|
||||||
|
export { default as Trans } from './components/trans.svelte';
|
||||||
|
export { default as Provider } from './components/trans.svelte';
|
||||||
|
|
||||||
|
export type { TransProps } from './types';
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from './exports';
|
||||||
Loading…
Reference in new issue