| name | editable-list |
| description | Build or modify any SolidJS list UI whose rows contain inputs, textareas, contenteditable, VarInput, or KVEditor. Enforces the <Index>-not-<For> rule and its runtime verification. Use for any new form list, row editor, key-value table, or when debugging "typing one character loses focus". |
Editable lists — <Index>, never <For> (ABSOLUTE)
Repeated prod bug: type one char in row input → focus + caret die. Same cause always.
Rule
List rows with focusable edited-in-place element (<input>, <textarea>, contenteditable, VarInput, KVEditor) → iterate <Index each>, NOT <For each>.
Why: <For> key by object ref. Edit handler replace row ref every keystroke (setRows(rows.map((r,i)=> i===idx ? {...r, x} : r))) → <For> dispose/recreate row DOM → focused input unmount → focus die per char. <Index> key by position: DOM node stable, only value signal update.
<For> OK ONLY: non-editable rows (buttons, static text), or <For> over createStore array mutated via path setters (setRows(i,'value',v)) — row ref stay stable.
Converting <For> → <Index> (API differs)
<For> callback: (item, indexAccessor) — item value, index() function.
<Index> callback: (itemAccessor, index) — item() function, index plain number.
- So: every bare
item.field → item().field; every index() → index.
Canonical refs in repo: KVEditor.tsx (house row editor), AssertEditor.tsx, RequestEditor.tsx multipart section.
Mandatory verification (typecheck/vitest CANNOT catch this)
- Grep new/changed UI:
<For near <input/onInput/VarInput/KVEditor — convert hits.
- Run real app (
wails3 dev or bun run dev:mock in frontend/). Type 2+ consecutive characters in row input, no re-click. Focus persist, all chars land. Only claim done after pass.