ZDDC/tests
ZDDC e5bb7f216c feat(tables): editable cells phase 2 — schema-driven editor widgets
Replaces the always-text-input cell editor with a per-property
widget factory keyed off the row's JSON Schema (form.yaml). The
table view now picks the right editor for each cell automatically:
strings get text inputs, enums get dropdowns, integers get number
inputs with min/max, dates get date pickers, booleans get
checkboxes, multi-select arrays get a multi-select. Cells whose
schema is a complex type (nested object, generic array, oneOf /
anyOf / allOf) can't be inline-edited and punt to the row's
form-mode editor on Enter / double-click.

Schema discovery:

context.js walkServer fetches <currentdir>/form.yaml as a
companion to <currentdir>/table.yaml — same file the form-mode
renderer already loads, just from the table view's perspective.
Best-effort: a directory with table.yaml but no form.yaml still
renders as a sortable/filterable table; cells just fall back to
plain text inputs without per-property hints. The schema is
exposed as ctx.rowSchema and consumed by the editor's
propertySchemaFor() helper, which walks dot-separated field
names through schema.properties to locate each column's
property schema.

Editor factory (editor.js):

- propertySchemaFor(col) — schema lookup keyed by col.field.
- isComplexSchema(s) — true for nested object, generic array,
  oneOf/anyOf/allOf. Multi-select-friendly arrays
  (string-enum + uniqueItems) are NOT complex; they get an
  inline multi-select widget.
- makeWidget(propSchema, col, initialValue) — dispatches to one
  of the widget builders below based on schema type / format /
  enum + column-spec hints (col.format / col.enum) for tables
  without a form.yaml.

Widget builders, each returning {element, getValue, focus}:

- widgetText        — plain <input type=text>, default fallback.
- widgetTextarea    — for string with maxLength > 200 (long
                      narrative fields).
- widgetTyped(type) — typed inputs the browser can help validate;
                      used for date / date-time / email.
- widgetNumber      — <input type=number> with min/max/step
                      derived from schema.minimum/maximum/
                      multipleOf. Integer schemas force step=1.
                      getValue returns Number, not string, so
                      the draft buffer holds the right type for
                      JSON serialization later.
- widgetCheckbox    — <input type=checkbox>; getValue returns
                      bool. initial value coerces from "true"/
                      true string-or-bool.
- widgetSelect      — <select> with empty placeholder + one
                      option per enum choice; getValue returns
                      the chosen string or null.
- widgetMultiSelect — <select multiple> with size = min(6, N);
                      getValue returns the array of selected
                      values (preserves order in the option list).

Complex-type cells:

isComplexSchema(propSchema) → enterEdit calls navigateToRowForm,
which routes to row.url (already the <id>.yaml.html re-edit URL
the row tracker holds). Phase 5 may swap this for an inline
side-panel mount of form-mode in the same bundle, but the
current navigate-out path delivers the same eventual UX without
needing the side-panel scaffolding.

Type-aware draft equality:

The pre-Phase-2 commit treated every value as a string and
compared via String() equality, which would mark any number-
column edit dirty even when the user re-typed the same number.
The new sameValue() helper handles bool/object via JSON-string
equality and falls back to loose string compare so 42 == "42"
isn't a false dirty. Drafts hold typed values (number, bool,
array) instead of all strings, so when Phase 3 wires the row PUT
the body shape matches the JSON Schema the server validates
against without an additional coercion pass.

Tests (tests/tables.spec.js — 7 new specs, total 22 in the
table view, all 27 in the file):

- enum column edits via select dropdown — verifies the empty
  placeholder + 3 enum options render and the chosen value
  displays back in the cell.
- integer column gives a number input with min/max — verifies
  the type/min/max/step attributes derive from the schema, AND
  the draft buffer holds typeof === 'number'.
- boolean column gives a checkbox — verifies type=checkbox and
  the draft holds true after Space-toggle. (Toggle via Space,
  not Playwright's .check() helper, to dodge the click+blur
  race a focused-checkbox-inside-grid-cell hits.)
- format:date column gives a date input — verifies type=date
  and the existing value pre-populates as YYYY-MM-DD.
- multi-select enum-array column gives a multi-select.
- complex (object) column navigates to the row form on edit —
  verifies no inline editor mounts AND the navigate seam
  receives the row's URL.
- no rowSchema → falls back to plain text editor — verifies the
  best-effort behavior for directories with only table.yaml.

Bundle size: 124 KB → 127 KB (+3 KB for the factory + widget
builders).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 10:18:25 -05:00
..
data test: add tests/data/test-archive.sh — synthetic ZDDC fixture builder 2026-05-08 09:03:38 -05:00
fixtures Initial commit 2026-04-27 11:05:47 -05:00
lib test: server-backed Playwright harness + /.tokens spec 2026-05-08 10:09:54 -05:00
archive-cascade.spec.js feat: lockstep release infra + cascade/.archive fixes + profile perf + page redesign 2026-05-01 20:11:38 -05:00
archive.spec.js feat(tools,build): in-flight HTML-tool reworks and build-infra updates 2026-04-29 12:52:27 -05:00
build-label.spec.js refactor: HTML tools live in website/releases/ as static files + symlink hierarchy 2026-04-30 09:40:16 -05:00
classifier.spec.js Initial commit 2026-04-27 11:05:47 -05:00
form-safety.spec.js refactor(tables): in-dir convention + unified table+form HTML bundle 2026-05-09 09:15:26 -05:00
landing.spec.js feat(landing): groups + click-to-open redesign 2026-05-01 15:23:42 -05:00
mdedit.spec.js feat(tables): new sortable/filterable grid tool for directories of YAML files 2026-05-05 20:32:01 -05:00
schema.spec.js Initial commit 2026-04-27 11:05:47 -05:00
tables.spec.js feat(tables): editable cells phase 2 — schema-driven editor widgets 2026-05-09 10:18:25 -05:00
tokens.spec.js test: server-backed Playwright harness + /.tokens spec 2026-05-08 10:09:54 -05:00
transmittal-drag-drop.spec.js Initial commit 2026-04-27 11:05:47 -05:00
transmittal-init-check.spec.js Initial commit 2026-04-27 11:05:47 -05:00
transmittal.spec.js Initial commit 2026-04-27 11:05:47 -05:00
zddc-filter.spec.js Initial commit 2026-04-27 11:05:47 -05:00
zddc.spec.js Initial commit 2026-04-27 11:05:47 -05:00