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/README.md

503 lines
15 KiB

# UIX
Documento corto de posicionamiento arquitectonico para `src/uix`.
Nota de continuidad más reciente:
[src/uix/CONTINUITY_2026-04-24.md](/G:/dev/svelte/vicen/src/uix/CONTINUITY_2026-04-24.md)
UIX no intenta ser "otra libreria de componentes". La apuesta es mas ambiciosa y
mas estructural: **separar capas que casi todos los frameworks actuales mantienen
mezcladas**.
En la mayoria de sistemas de UI, estas cosas viven pegadas:
- contrato publico del DOM
- comportamiento headless
- accesibilidad
- semantica del evento
- capa visual
- motores modales (sound, vibra, motion)
- integracion con servicios de app
UIX intenta partir ese bloque en piezas con fronteras fuertes.
---
## 1. La idea central
UIX modela la interfaz como varias capas cooperando, no como un unico componente
gigante que hace todo a la vez.
```text
App
├─ servicios transversales
│ └─ ADom
└─ componentes
└─ capa estructural / semantica / comportamental / visual
```
La intuicion es esta:
- la estructura publica del componente no es lo mismo que su comportamiento
- la semantica de un evento no es lo mismo que su materializacion
- el DOM activo no es lo mismo que utilidades DOM puras
- la app no deberia acoplar motores modales entre si
UIX pone nombres y contratos explicitos a esas separaciones.
---
## 2. Las capas de UIX
### `Morfo`
Contrato estructural cross-layer del componente.
Define:
- partes
- `data-*`
- ARIA
- foco
- teclado
- eventos
No es prose ni runtime. Es la forma canonica publica del componente.
Ver: [src/uix/morfo/README.md](/G:/dev/svelte/vicen/src/uix/morfo/README.md)
### `Sema`
Vocabulario semantico y canalizador de senales perceptivas.
Su trabajo:
- definir las familias canonicas (`contact | commit | alert | handle | emerge | sustain`)
- definir los intents canonicos (`neutral | affirm | fulfill | risk | threat`)
- exponer `EngineSemantic.emit(event)` para que el provider publique ocurrencias
- garantizar la secuencia perceptiva: escribir senal `data-event*`, esperar 1 rAF
para que CSS la observe, resolver, mantener y limpiar
`Sema` no decide que ocurrio (eso lo decide el provider). Solo orquesta la
ocurrencia que recibe.
Ver: [src/uix/sema/README.md](/G:/dev/svelte/vicen/src/uix/sema/README.md)
### `Soma`
Capa headless de comportamiento.
Gestiona:
- estado
- contexto
- a11y
- keyboard / pointer / focus
- emision de eventos hacia `ADom`
`Soma` no deberia conocer la implementacion concreta de los engines modales. Su
trabajo es emitir hechos del componente, no materializarlos.
Ver: [src/uix/soma/SOMA_ARCHITECTURE.md](/G:/dev/svelte/vicen/src/uix/soma/SOMA_ARCHITECTURE.md)
### `Eidos`
Capa visual.
Reacciona a contratos DOM y a senales reflejadas, pero no implementa la logica
headless del componente. Su responsabilidad es apariencia, no comportamiento.
### `ADom`
Runtime DOM activo de aplicacion.
No es semantic engine. No conoce Morfo, ni Sema, ni Soma, ni Eidos. Su unica
funcion es **coordinar y sincronizar mutaciones DOM**.
API publica (mutaciones):
- `app.dom.apply(change)` — aplica un paquete de attrs sobre un target
- `app.dom.remove(target, names)` — quita attrs
API publica (servicios reactivos pre-existentes):
- `viewport`, `breakpoints`, `currentBreakpoint`, `resolve`, `isAtLeast`, `matches`
- `BodyScrollLock`, `DOMContext`, `RovingFocusGroup`
ADom recibe instrucciones ya resueltas. No las interpreta.
Ver: [src/uix/adom/README.md](/G:/dev/svelte/vicen/src/uix/adom/README.md)
### `uix/lib/dom`
Utilidades DOM puras o casi puras.
Aqui viven:
- `contains`
- `getDocument`
- `getWindow`
- foco
- traversal
- wrappers base de observers
No contiene el runtime activo. Ese papel pertenece a `ADom`.
---
## 2.bis Como se ejecuta un componente
La arquitectura cerrada (post-2026-04-25) define seis piezas con
responsabilidades disjuntas. Ninguna invade a la siguiente.
```
Morfo declara
MorfoRuntime transcribe
Provider aporta sources, targets y handlers
Effects sincronizan attrs derivados
EngineSemantic emite senales perceptivas
ADom aplica mutaciones DOM
```
### El reparto operativo
`Morfo` es DNA: un fichero por componente que declara `parts`, `data-*`,
`aria-*`, `role`, `keyboard`, `focus`, `events`. No ejecuta nada.
`MorfoRuntime` (en `soma/`) interpreta el morfo. Una instancia por componente
recibe del provider las fuentes de estado, los targets DOM y los handlers de
eventos. Expone:
- `partProps(part)` — devuelve solo identidad estatica del nodo (id, marker,
ref attachment). Nada mutable.
- `attachPart(part, target)` — el provider registra el nodo DOM real cuando
monta.
- `keydown(part, event)` — dispatch de teclas declaradas en `morfo.keyboard`.
- `trigger(eventName)` — orquesta la secuencia perceptiva + state.
`Provider` aporta lo que el morfo no puede inferir:
- getters reactivos para `states` y `props`
- getters reactivos para los `parts` (ids dinamicos)
- handlers sincronos para los `events`
- glue de layers ortogonales (Presence, Dismissal, ScrollLock — no son morfo)
`Effects` (registrados por el runtime al montar) escuchan cambios en los
sources y aplican los attrs derivados via `dom.apply`.
`EngineSemantic` recibe el evento desde `runtime.trigger`. Escribe la senal
`data-event*` via `dom.apply`, espera 1 rAF, resuelve, mantiene la senal el
hold configurado y limpia.
`ADom` solo aplica. No interpreta.
### La secuencia de `runtime.trigger(eventName)`
```
1. prewrite imperativo (transient markers como data-last-action)
2. await semantic.emit(event)
3. handler sincrono del provider muta state
4. effects derivan y aplican attrs estructurales (data-state, aria-*)
```
El handler muta state. Los effects ven el cambio y reescriben el DOM. ADom es
el unico escritor de attrs mutables.
### Tres escenarios de Soma
```ts
// Cambio estructural sin senal
provider.commitState(change)
// internamente: dom.apply(change)
// Cambio estructural con senal
provider.commitState(change, event)
// internamente: await semantic.emit(event); dom.apply(change)
// Senal sin cambio estructural
provider.emitEvent(event)
// internamente: void semantic.emit(event)
```
### Reglas operativas
- Lo que `dom.apply` escribe, Svelte no lo renderiza. `partProps` solo emite
identidad estatica (id, marker, ref).
- Los handlers de `events` son sincronos. Async va fuera del trigger.
- Los guards (`if (disabled) return`) van en el call-site, no dentro del
handler — si entran al handler, ya emitieron senal perceptiva.
- `Semantic` puede usar `Dom` (dependencia hacia abajo). `Dom` no conoce
`Semantic`.
- `morfo.events.commits` es descriptivo: documenta lo observable, no lo
ejecuta. La cadena causal real es handler -> state -> effect.
---
## 3. Que hace distinto a UIX
### 3.1 El contrato estructural es una capa propia
En la mayoria de librerias, la estructura publica del componente esta dispersa:
- atributos en el provider
- roles en el render
- partes en CSS
- selector names en docs
- contratos en tests
UIX intenta concentrar eso en `Morfo`.
Eso no es una comodidad menor; cambia el tipo de sistema que puedes construir:
- docs derivadas del contrato
- validacion cross-layer
- menos drift entre headless y visual
- tooling mas fiable
### 3.2 La semantica no se mezcla con la ejecucion
UIX separa el **nombre de la ocurrencia** de su **materializacion modal**.
Eso permite que:
- sonido
- vibracion
- CSS
- motores futuros
usen el mismo vocabulario sin quedar pegados entre si.
### 3.3 El comportamiento headless no carga con toda la modalidad
`Soma` no deberia ser un mega-engine que sabe de todo:
- no sabe reproducir WAVs
- no sabe vibrar
- no sabe decidir la fisica perceptiva de cada canal
`Soma` emite. Los engines ejecutan.
### 3.4 El DOM activo es infraestructura de app, no detalle incidental
Muchos sistemas tratan el DOM como detalle local del componente.
UIX da un paso mas: reconoce que hay hechos transversales del DOM que varios
consumidores quieren escuchar, y por eso introduce `ADom`.
Eso permite:
- un solo punto de publicacion
- listeners tipados
- reflection uniforme en atributos
- menos `MutationObserver` duplicados
- mejor tooling y debug
### 3.5 La app compone servicios, no "super componentes"
UIX se apoya en un modelo donde la app compone servicios transversales y los
componentes los consumen. `langs`, `presentation`, `logger` y `ADom` viven mejor
como servicios de app que como dependencias ocultas dentro de cada componente.
---
## 4. Lo que UIX no es
UIX no es:
- una coleccion plana de componentes visuales
- un simple wrapper opinionated sobre primitives existentes
- un design system clasico donde visual, comportamiento y contratos viven juntos
- un semantic engine centralizado que ejecuta todas las modalidades
- un `EventEmitter` global disfrazado de arquitectura
Tampoco busca novedad gratuita.
La originalidad de UIX no esta en inventar nombres exoticos, sino en **separar
problemas reales** que otros sistemas suelen aceptar como un unico bloque.
---
## 5. Comparacion honesta con otros enfoques
### Frente a headless libraries clasicas
Librerias como Radix, Ariakit o React Aria resuelven muy bien comportamiento y
accesibilidad. Pero normalmente no separan:
- contrato estructural declarativo
- vocabulario semantico independiente
- runtime transversal de DOM activo
UIX quiere cubrir ese espacio.
### Frente a design systems clasicos
Muchos design systems tienen tokens, componentes y guidelines, pero la frontera
entre:
- estructura
- comportamiento
- visualidad
- semantica
queda difusa.
UIX intenta que cada una tenga una capa reconocible.
### Frente a engines modales aislados
Es relativamente comun encontrar sistemas de motion o sound por separado.
Lo raro es tener:
- headless primitives
- contrato estructural machine-readable
- vocabulario comun
- servicio de DOM activo
- engines modales desacoplados
trabajando juntos sin colapsar en un runtime monolitico.
---
## 6. Por que esto puede ser valioso
Si sale bien, UIX ofrece algo poco comun:
- mejor explicabilidad arquitectonica
- menos drift entre capas
- mas capacidad de validacion automatica
- mejor testabilidad
- mas libertad para introducir nuevos engines
- mas honestidad sobre que pertenece al framework y que pertenece al integrador
Especialmente importante:
**la coherencia cross-modal puede tratarse como responsabilidad del integrador, no
como una falsa promesa de un runtime centralizado que pretende saberlo todo.**
El framework puede proveer:
- vocabulario
- contratos
- transporte
- puntos de extension
Pero no debe fingir que puede decidir por todas las modalidades de todas las apps.
---
## 7. Los riesgos reales
UIX tambien tiene riesgos claros, y conviene decirlos sin adornos.
### 7.1 Exceso de capas
Si las fronteras no estan clarisimas, el sistema puede sentirse mas complejo de lo
que realmente resuelve.
### 7.2 Nombres sin disciplina
Si `Morfo`, `Sema`, `Soma`, `Eidos`, `ADom` no mantienen contratos nitidos, los
nombres se convierten en decoracion y no en arquitectura.
### 7.3 Invasion de responsabilidades
El peligro constante es que una capa intente hacer el trabajo de otra:
- `Sema` convirtiendose en runtime
- `Soma` convirtiendose en engine modal
- `ADom` convirtiendose en semantic engine
- `Eidos` acoplandose a detalles incidentales
UIX solo funciona si cada capa acepta sus limites.
### 7.4 Falta de precedentes
No hay demasiados sistemas con esta composicion exacta. Eso significa mas libertad,
pero tambien menos patrones externos que copiar. Hay que inventar con disciplina.
---
## 8. Reglas de dependencia
UIX preserva una direccion clara de acoplamiento.
```text
Morfo -> declara contratos
MorfoRuntime -> interpreta morfo dentro de Soma
Provider -> aporta sources, targets, handlers
Effects -> sincronizan state -> attrs
EngineSemantic -> emite senales perceptivas (depende de Dom)
ADom -> aplica mutaciones DOM
Eidos -> materializa visualmente leyendo DOM
App -> compone servicios
```
Reglas duras:
- `Morfo` no conoce `Soma`, ni codigo de runtime
- `MorfoRuntime` lee `Morfo` y depende de `Dom` y `Semantic`
- `Provider` no escribe attrs mutables al DOM directamente; los aporta como
sources al runtime
- `EngineSemantic` puede usar `Dom` (hacia abajo); `Dom` no conoce `Semantic`
- `ADom` no conoce `Morfo`, ni `Sema`, ni `Soma`, ni `Eidos`
- `Eidos` consume DOM y `data-*`, no internals de `Soma` ni `Sema`
- Lo que `dom.apply` escribe, Svelte no lo renderiza
docs: cross-layer articulation — eidos README + 2-of-3 rule across all layer docs Closes the documentation loop on the cross-layer extension pass: morfo now articulates between soma, sema, and (future) eidos. The "2-of-3 rule" formalizes when an extension to morfo is justified vs when it should stay as provider logic. src/uix/eidos/README.md (new) - Documents eidos's role and what it consumes from morfo + sema BEFORE any code exists, so the contract is preparedly clean when implementation starts. - Catalogs which morfo fields eidos reads (parts, archetype, states, data values, events, prewrite, focus, supportsNesting) and which it ignores (computed state, runtime internals, layers). - Documents the DOM-as-channel pattern: sema writes data-event* on emit; eidos reacts to selectors like `[data-event^="dismiss"]`. - Establishes the boundary with `air` (dead branch reference, not base). src/uix/README.md (top-level) - §8 Reglas de dependencia: adds the 2-of-3 rule table making the morfo-extension contract explicit, plus a list of canonical vocabularies (archetypes, verbs). - §10 Reading order: includes eidos README + lib/dom + clarifies which layers are dead branches. src/uix/morfo/README.md - New "Archetypes" section documenting the 24-verb vocabulary, the Provider-as-trigger vs Provider-as-container distinction, and the rule for adding new archetypes (≥2 components share the role). - New "The 2-of-3 rule" section with the same table as the top-level, listing which extensions did/didn't make it past the rule and why. - `parts[].archetype` mentioned in the "What morfo contains" list. src/uix/sema/README.md - New "Vocabulario canónico de verbs" section listing SEMA_VERBS by family and the `{verb}-{variant}` composite naming convention. - Documents `validateEventName()` as advisory tooling. src/uix/soma/SOMA_ARCHITECTURE.md - partProps documentation now mentions data-archetype emission. - New "Cross-layer hooks que soma emite por la regla 2-de-3" section listing the data-* attrs soma writes that sema and eidos consume. - Reading-order links updated. No code changes — all docs.
6 months ago
### Regla 2-de-3 para extender Morfo
Una extension a Morfo solo se justifica si **al menos dos de las tres
capas** (soma, sema, eidos) la consumen. Si solo soma se beneficia, el
patron es virtual prop en provider — no extender el contrato.
Bajo esa regla:
| Extension | Soma | Sema | Eidos | En morfo |
|---|---|---|---|---|
| `parts[].archetype` | ✅ emit | ✅ verbs por rol | ✅ selectores transversales | ✅ |
| `events[].semantic` | ✅ payload | ✅ vocabulario | ✅ tinta | ✅ |
| `events[].prewrite` | ✅ ejecuta | ✅ secuencia | ✅ tinta exit | ✅ |
| `firstOf` value source | ✅ only | — | — | ❌ |
| `prop-not-nullish` cond | ✅ only | — | — | ❌ |
| Field-context OR | — virtual prop | — | — | ❌ |
### Vocabularios canonicos cross-layer
- **Archetypes** (24): clasificacion de partes cross-component. Definida
en `src/uix/morfo/types.ts:ARCHETYPE_VOCABULARY`. Emitida como
`data-archetype="..."` por `runtime.partProps`.
- **Verbs** (24): action verbs canonicos para `morfo.events[].name`.
Definida en `src/uix/sema/verbs.ts:SEMA_VERBS`. Convencion para
composite names: `{verb}-{variant}` (e.g. `commit-save`,
`dismiss-outside`).
---
## 9. La diferencia en una frase
Si hubiera que resumir UIX en una sola idea, seria esta:
> Morfo declara, MorfoRuntime transcribe, Provider aporta, Effects sincronizan,
> Semantic emite, Dom aplica.
Seis piezas, seis responsabilidades, ninguna invade a la siguiente.
---
## 10. Orden de lectura sugerido
Para entender el sistema en su estado actual:
docs: cross-layer articulation — eidos README + 2-of-3 rule across all layer docs Closes the documentation loop on the cross-layer extension pass: morfo now articulates between soma, sema, and (future) eidos. The "2-of-3 rule" formalizes when an extension to morfo is justified vs when it should stay as provider logic. src/uix/eidos/README.md (new) - Documents eidos's role and what it consumes from morfo + sema BEFORE any code exists, so the contract is preparedly clean when implementation starts. - Catalogs which morfo fields eidos reads (parts, archetype, states, data values, events, prewrite, focus, supportsNesting) and which it ignores (computed state, runtime internals, layers). - Documents the DOM-as-channel pattern: sema writes data-event* on emit; eidos reacts to selectors like `[data-event^="dismiss"]`. - Establishes the boundary with `air` (dead branch reference, not base). src/uix/README.md (top-level) - §8 Reglas de dependencia: adds the 2-of-3 rule table making the morfo-extension contract explicit, plus a list of canonical vocabularies (archetypes, verbs). - §10 Reading order: includes eidos README + lib/dom + clarifies which layers are dead branches. src/uix/morfo/README.md - New "Archetypes" section documenting the 24-verb vocabulary, the Provider-as-trigger vs Provider-as-container distinction, and the rule for adding new archetypes (≥2 components share the role). - New "The 2-of-3 rule" section with the same table as the top-level, listing which extensions did/didn't make it past the rule and why. - `parts[].archetype` mentioned in the "What morfo contains" list. src/uix/sema/README.md - New "Vocabulario canónico de verbs" section listing SEMA_VERBS by family and the `{verb}-{variant}` composite naming convention. - Documents `validateEventName()` as advisory tooling. src/uix/soma/SOMA_ARCHITECTURE.md - partProps documentation now mentions data-archetype emission. - New "Cross-layer hooks que soma emite por la regla 2-de-3" section listing the data-* attrs soma writes that sema and eidos consume. - Reading-order links updated. No code changes — all docs.
6 months ago
1. [src/uix/morfo/README.md](/G:/dev/svelte/vicen/src/uix/morfo/README.md) — declaracion, archetypes, regla 2-de-3
2. [src/uix/sema/README.md](/G:/dev/svelte/vicen/src/uix/sema/README.md) — `emit` contract, verbs canonicos
3. [src/uix/eidos/README.md](/G:/dev/svelte/vicen/src/uix/eidos/README.md) — qué consume eidos del DOM (capa por construir)
4. [src/uix/soma/SOMA_ARCHITECTURE.md](/G:/dev/svelte/vicen/src/uix/soma/SOMA_ARCHITECTURE.md) — runtime que transcribe morfo
5. [src/uix/adom/README.md](/G:/dev/svelte/vicen/src/uix/adom/README.md) — `dom.apply`
6. [src/uix/lib/dom/README.md](/G:/dev/svelte/vicen/src/uix/lib/dom/README.md) — primitives DOM puras
7. [src/uix/terra/README.md](/G:/dev/svelte/vicen/src/uix/terra/README.md) — capa anterior, dead branch (referencia)
8. [src/uix/air/README.md](/G:/dev/svelte/vicen/src/uix/air/README.md) — capa visual anterior, dead branch (referencia)
La arquitectura final seguira cambiando, pero esta es la idea fundacional que
explica por que UIX no se parece demasiado a otros frameworks de UI.

Powered by TurnKey Linux.