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.
9.2 KiB
9.2 KiB
Words Eidos
Words es el editor rich-text visual de ActiveUIX. Eidos no implementa el
motor: envuelve las partes publicas de Soma y pinta los data-* declarados por
Morfo.
Baseline
Air/morfo-runtime no tenia un componente Words equivalente. La comprobacion
contra la rama morfo-runtime solo encontro el icono swords; no habia editor
rich-text ni wrapper visual reutilizable.
Words audit - 2026-05-24
Feature parity matrix
| Feature | React Aria / WAI-ARIA | Lexical / svelte-lexical | Edra / Tiptap | UIX V1 | Decision |
|---|---|---|---|---|---|
| Multiline editable | Textbox multiline + toolbar pattern | ContentEditable root | Editor view | Words.Content role textbox |
implement |
| Document state | Consumer-owned value | EditorState | ProseMirror doc | JSON canonico WordsDocument |
implement |
| Toolbar commands | Native buttons with labels | Commands/plugins | Command chain | Words.CommandButton + root toolbar presets |
implement |
| Active formatting state | aria-pressed on toggles | Selection state | Extension state | data-state, aria-pressed |
implement |
| Placeholder | Input hint pattern | Plugin/placeholder | Placeholder extension | Words.Placeholder |
implement |
| Form serialization | Native input when needed | external | external | Words.HiddenInput JSON |
implement |
| Import/export HTML | not owned | available | available | clean export; defer importer | partial |
| Link editing | not owned | command/plugin UI | extension UI | Words.LinkEditor + Words.ToolPopover |
implement |
| Bubble menu | contextual toolbar pattern | plugins | extension UI | Words.BubbleMenu anchored to text selection |
implement |
| Images/tables/collab | not owned | plugins | extensions | outside V1 core | defer |
Architectural choices
- Layer ownership: Morfo declares parts/attrs/ARIA/events; Soma owns document,
selection, input, history and commands; Sema maps high-level events; Eidos
owns only wrappers,
size/variant/colorattrs and CSS. - Composition: one compound root
<Words>with explicit children<Words.Toolbar>,<Words.Content>,<Words.HiddenInput>, etc. The root also offers atoolbarpreset/config prop as a convenience renderer; manual composition remains the full custom path. - Sizes covered:
sm,md,lgas composite panel sizes. - Variants: full
ControlVariant:surface,outline,ghost. - Color intent palette: full
ColorRole:primary,secondary,neutral,affirm,fulfill,risk,threat,loss.
Reference comparison summary
| Library | Closest equivalent | Difference vs UIX | Why we differ |
|---|---|---|---|
| WAI-ARIA/APG | Multiline textbox + toolbar | UIX exposes Morfo/Sema event contract | Needed for perceptual and visual layers |
| React Aria | TextField/TextArea primitives | No rich editor engine | We keep browser a11y contract but add Words document model |
| Lexical / svelte-lexical | Composer + ContentEditable + plugins | No runtime dependency | Ecosystem rule: zero editor dependency |
| Edra / Tiptap | Rich editor benchmark | Tiptap/ProseMirror dependency | Benchmark only, not acceptable runtime |
| Slate / ProseMirror | JSON/schema/history concepts | external engines | Concepts inform operations, not shipped code |
Decision log
- Air parity: no Air component existed; implement from UIX architecture.
- Link editing: implemented as a stable form part over Soma selection state.
Toolbar tool popovers use a reusable
Words.ToolPopovershell; contextual formatting usesWords.BubbleMenuanchored to the real DOM selection rect. - HTML export and conservative safe HTML import are implemented in Soma. Markdown import/export is implemented in Soma V1 with a conservative zero-dependency parser.
- Tables/images/collaboration: defer to V2 or ActiveApp-backed packs.
- Demo scope signed by user on 2026-05-24 via "continua" after the Eidos/demo slice was proposed.
Comparativa
| Capacidad | Morfo/Soma | Eidos |
|---|---|---|
| Root editor | Words.Provider |
<Words> stamps data-size, data-variant, data-color |
| Editable surface | Words.Content |
<Words.Content> passthrough + recipe |
| Placeholder | Words.Placeholder |
styled from [data-hidden] |
| Toolbar | Words.Toolbar, Words.ToolbarGroup |
horizontal/vertical visual treatment |
| Commands | Words.CommandButton |
active/disabled/commit styling |
| Bubble menu | Words.BubbleMenu |
fixed selection toolbar with tokenized offset |
| Tool popover | Popover composition | reusable trigger/content/close shell for toolbar tools |
| Link editor | Words.LinkEditor |
default URL/title form + invalid feedback |
| Form | Words.HiddenInput |
passthrough hidden JSON input |
| Status | Words.Status |
idle/error status recipe |
Decisiones
WordsSize = Extract<Size, 'sm' | 'md' | 'lg'>.WordsVariant = ControlVariant.WordsColor = ColorRole, no paleta truncada.- Los wrappers no exportan
Provider; la API publica es compound. toolbaren el root aceptafalse,true,minimal,formatting,fullo grupos de comandos. Es un renderer de conveniencia; no reemplaza la composicion manual de<Words.Toolbar>. El presetfullexpone los tres tipos de lista del motor: unordered, ordered y check, y la accionunlinkcuando la seleccion esta dentro de un enlace.- La demo UIX expone tanto presets como grupos custom en la prop
toolbar, de forma que la personalizacion visible del toolbar queda validada contra el wrapper Eidos y no solo contra composicion manual Soma. Words.LinkEditores una parte compuesta real, no markup de demo: Soma aplicainsertLink/unlink, Morfo declaracommit-linkycommit-unlink, y Eidos ofrece una UI por defecto que puede reemplazarse con snippet.Words.ToolPopovercentraliza el patron de herramientas flotantes de toolbar: trigger iconico, popover intrinseco, boton de cierre/cancelacion y guardia de cierre.Words.LinkEditorlo usa para validar URL al intentar cerrar por outside/Escape sin confirmar.Words.BubbleMenues una parte publica compuesta: solo aparece para seleccion de rango, toma su ancla del rectangulo real deSelection APIy preserva la seleccion enpointerdownpara que los command buttons operen sobre el texto seleccionado.- El trigger del popover captura la seleccion DOM de
Words.Contentantes de mover foco al formulario. Esto evita que aplicar un enlace dependa del timing deselectionchangedel navegador. words.cssusa solo tokens publicos--words-*declarados enTHEME_BASE_RECIPE_TOKENS.words.- Las marcas inline se pintan desde
data-words-marks, emitido por el motor Soma, no desde HTML inventado en la demo. Words.Contentfuerzawhite-space: pre-wrappara que los saltos de linea reales del motor (insertLineBreak, paste de texto plano) sean visibles sin transformar el documento.- La seleccion nativa se pinta con el acento solido del componente y se fuerza
user-select: texten la superficie editable para que la seleccion de rango sea perceptible incluso dentro de la shell UIX.
Gaps
| Gap | Decision |
|---|---|
| HTML avanzado arbitrario | diferir a Soma V1.1 |
| Images/files | diferir a ActiveApp storage/upload |
| Tables | diferir V2 |
| Collaboration | diferir; no core |