|
|
# field — ficha de auditoría (RE-AUDITADA 2026-07-07, profundidad piloto)
|
|
|
|
|
|
- **Familia**: fields — LA BASE · **Método**: solo análisis; evidencia leída por dimensión (`file:line`) · demos fuera de alcance
|
|
|
- **Capas leídas**: [morfo](../../../src/uix/morfo/components/field.ts) completo · [soma types](../../../src/uix/soma/components/field/types.ts) completo · [provider](../../../src/uix/soma/components/field/field-provider.svelte.ts) dirigido (estado 145-152 · describedBy 344-350 · props 359-376 · focusout 166-169) · [eidos wrapper](../../../src/uix/eidos/components/field/field.svelte) completo · recipe `field` (58 claves) · field.css (censo de estados) · sema: sin capa POR CONTRATO (`scope: ['soma','eidos']`, field.ts:7)
|
|
|
- **Máquina**: PASS limpio · tests 8KB ✓ · README soma+eidos ✓
|
|
|
|
|
|
## Dimensiones (evidencia leída)
|
|
|
|
|
|
| # | Dimensión | Estado | Evidencia |
|
|
|
| --- | -------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
| 1 | Composición vs declaración | ✓ | 10 partes como children compositivos (morfo field.ts:13-180); indicators/error con render condicional por prop (`onlyWhenRequired/Optional/Invalid`, types.ts:89/96/121) — no árboles declarativos |
|
|
|
| 2 | Naming de props | ✓ canónico | `value`+`onValueChange` (types.ts:107-109 — EL patrón del catálogo); `disabled/readonly/required/invalid` planos; overrides `dirty/touched/state` documentados (types.ts:63-78); patrón `onlyWhen*` ×3 coherente → alimenta [\_naming.md](./_naming.md) |
|
|
|
| 3 | Coherencia semántica | ✓ con hallazgo | La base NO emite eventos y lo DECLARA en scope (field.ts:7 ✓); pero **F-2**: Field.Input (texto de una línea) no tiene contrato de commit mientras textarea tiene `commit-submit` (textarea.ts, verificado) — el par de inputs de texto es asimétrico |
|
|
|
| 4 | API normalizada | ✓ | Estado compuesto con precedencia documentada y verificada (provider 145-152: explicit > invalid > disabled > readonly); snippetProps completos (154-164); OR-merge con Form (types.ts:36-38, provider 138-142 markTouched→form) |
|
|
|
| 5 | Tokens usados | ✓ | Recipe 58 claves TODAS canónicas §1 (control-height-{k}, padding-inline, gap, radius, font-size 1:1, floating-label-top temable, segment-active-_ de V4); css consume solo `--field-_` |
|
|
|
| 6 | Parte semántica | ✓ by-contract | Sin sema por scope (los commits los emiten los fields concretos) — coherente, salvo F-2 |
|
|
|
| 7 | Animaciones | ✓ | 4 `transition:` con tokens (R-limpio máquina); 0 `@keyframes`; floatingLabel = CSS-only (11 reglas `floating`), sin JS |
|
|
|
| 8 | Contrato morfo | **hallazgo doble** | **F-1**: enum `data-state` de 5 valores emitido en Provider/Control/Input (field.ts:24-27/88-91/106-110) con **0 consumidores en TODO el CSS de eidos** (verificado catálogo entero) — el estilo real va por los flags de presencia (data-invalid ×4, data-disabled ×7 en field.css); además emite `data-state="idle"` en reposo — el patrón exacto que button PURGÓ (su morfo documenta el clobbering, audit 05-27). Doble codificación: enum muerto + flags vivos |
|
|
|
| 9 | Accesibilidad | ✓ ejemplar | Auto-wiring completo: label for→input condicional part-present (field.ts:52-56), aria-invalid ariaBoolean (120), aria-busy loading (128-132), aria-required (134-138), ErrorText role=alert+aria-live (157-160); `describedBy` une helper+error-solo-si-invalid y SOBRESCRIBE el morfo con el valor más rico — documentado (provider 344-350 + 371-373) |
|
|
|
| 10 | Adopción theming | ✓ con remanente | Focus: el ÚNICO box-shadow dos-anillos superviviente del catálogo vive aquí → ancla del veredicto SYS-5; states-layer n/a (chrome no interactivo) |
|
|
|
| 11 | Composición interna | mandato | Es la base que los hijos DEBEN envolver (SYS-6/B.1): la familia de alturas + el chrome label/helper/error existen aquí y los segment-fields los re-implementan |
|
|
|
| 12 | Estados y ciclo | ✓ con gap visual | invalid/disabled/readonly estilados; **`loading` definido en el contrato (morfo+types+aria-busy) pero SIN visual en css** (0 reglas) — estado fantasma a nivel eidos (parte de F-1) |
|
|
|
| 13 | Disciplina runtime | ✓ | 0 timers/listeners crudos; focusout→markTouched vía prop de runtime (166-175); `$derived` puros |
|
|
|
| 14 | Docs + tests | ✓ | README ×2; suite 8KB (provider) |
|
|
|
| 15 | i18n | ✓ | texts localizados incl. indicadores `*`/`(optional)` (field.ts:8-12); langs.ts propio |
|
|
|
|
|
|
## Hallazgos y propuestas — del componente
|
|
|
|
|
|
| ID | Hallazgo | Propuesta |
|
|
|
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
| **F-1** | Enum `data-state` (5 valores, 3 partes) sin NINGÚN consumidor CSS + `idle` emitido en reposo + `loading` sin visual — doble codificación con los flags | Dos salidas para el veredicto: (a) **podar el enum** (como button: flags de presencia bastan; `loading` se convierte en flag `data-loading` + visual definido) — recomendada por coherencia con la doctrina button; (b) adoptarlo (estilar error/loading/readonly por el enum y podar flags redundantes). En ambas: definir el visual de `loading` que hoy no existe |
|
|
|
| **F-2** | Field.Input sin contrato de commit vs textarea `commit-submit` — el par texto asimétrico. **Refinado tras leer password-field**: la doctrina de familia YA existe y está documentada con incidente (password-field morfo :40-47 — teclear NO es commit; `commit-submit` al Enter ES el patrón, alineado con editable/number/search/combobox) | Field.Input adopta `commit-submit` (Enter) siguiendo la doctrina escrita de password-field — morfo + provider; el veredicto es de adopción, no de diseño (el diseño ya está canonizado en el hermano) |
|
|
|
| **F-3** | El morfo declara `aria-describedby` solo desde helper-text; el valor real (helper+error) lo compone soma en override | Menor: reflejar en el morfo la relación con error-text (severity optional + condición) para que el contrato no infra-declare lo que se renderiza |
|
|
|
|
|
|
## Escalan al sistema
|
|
|
|
|
|
- **F-1 alimenta una regla de catálogo**: "enum de estado solo si el CSS lo consume; si los flags bastan, el enum es deuda" — censar en el resto de la re-auditoría quién más emite enums muertos (→ SYS-10 nuevo en \_system al cierre de familia).
|
|
|
- SYS-5 (ancla del focus) · SYS-6 (destino del mandato) — ya registrados.
|
|
|
|
|
|
## Veredictos
|
|
|
|
|
|
_(pendiente — checkpoint post-barrido)_
|