Skip to content

feat(line-items): add cell editing with shared table core - #682

Draft
IzumiSy wants to merge 8 commits into
feat/line-items-documentfrom
refactor/table-core-cell-session
Draft

IzumiSy wants to merge 8 commits into
feat/line-items-documentfrom
refactor/table-core-cell-session

Conversation

@IzumiSy

@IzumiSy IzumiSy commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Stacked on #679, with feat/line-items-document as the base branch.

The preceding slices established shared value rendering, an internal readonly LineItems table, and document-owned row commands. This slice makes that table editable while reusing DataTable's interaction mechanics rather than introducing a second set of inputs, calendars, dropdowns, and error popovers.

Supported kinds, display defaults, and editor behavior should not require synchronizing separate type lists and scattered parsing/rendering branches. Custom controls also need incomplete input and explicit parsing, not just a callback that produces a ready-to-adopt value.

Design Decision

Share controls while preserving DataTable policy

table-core owns React-independent edit sessions, the editable cell surface, error presentation, reusable input parsing, and typing/calendar/choice/boolean controls. It does not own collection callbacks or document rows.

DataTable retains value lookup, badge-choice fallback, datetime/timezone conversion, raw draft notifications, callback ordering, and public CellEditError identity. Its existing confirm(): void adapter remains intact; shared dropdowns use an awaitable confirmation result. The relocated error class remains included in DataTable's authored documentation source binding.

Resolve presentation and editing at their boundaries

Shared createDisplayFactories<TRow> defines display rendering and default alignment together. Display kinds, configuration, and accepted value types derive from the specialized factory signatures rather than independent kind/value maps.

DataTable's column adapter interprets its existing API into display-label policy, editor configuration, icons, badge-array restrictions, and loading placeholders. LineItems' column adapter instead combines type/typeOptions or custom display rendering with an explicitly selected edit.editor. Display and editor kinds remain independent: money presentation can use numeric editing without a combined registry or a new kind switch in cells.

Custom column rendering remains authoritative, including null. Link suppression retains each API's existing condition: actual per-row editability for DataTable, presence of edit configuration for LineItems. Display formatters remain cached by column/timezone while editor getters read current configuration. Editor component references stay stable rather than being recreated during resolution.

Derive LineItems editor contracts from factory signatures

In LineItems, common policy (canEdit, onValueCommitted, and error) stays under edit. The editor is selected by edit.editor.type, with configuration under edit.editor.options. DataTable's public API is unchanged.

createEditorFactories<TRow, TValue> is the single declaration of supported LineItems editors and their configuration/field-compatibility signatures. Specializing those signatures before extracting parameters preserves exact row types, literal choice values, and nullable-output restrictions without a separately maintained type map.

Built-in and custom definitions use the same adapter packing and execution path. The generic controller and cell view do not branch on editor kinds. The LineItems resolver validates own registry keys and editor configuration.

Keep custom drafts separate from adopted values

defineLineItemsEditor<TRow, TValue, TDraft>({ toDraft, parse, render }) supports immutable drafts whose shape differs from the adopted value. Parsing is synchronous and returns a value or an explicit input error; malformed results and unexpected exceptions retain the draft without adopting data or exposing private exception details.

render is constrained by TypeScript's ComponentType and mounted as a React component, so Hooks and component identity work normally. React handles invalid component types at render time; the adapter does not duplicate that check by inspecting React's internal tags. Public custom context exposes value, draft, edit actions, status/error, and accessibility information without leaking session or cell-frame internals. Untouched structured drafts skip parsing/adoption and do not dirty the document; structured values are adopted without serialization or deep cloning.

Give sessions the document owner's lifetime

Editors are available only on accessorKey properties, with one edit owner per property; duplicate readonly displays remain supported. Server identity properties cannot have editors.

Sessions bind to the existing store without duplicating row state or baseline tracking. Table-view detachment retains logical drafts and in-flight checks; owner disposal invalidates them. Revert, removal, conflicting writes, and editor/callback/permission changes prevent stale asynchronous adoption. Configuration is applied only after React commits, and replacement editors never receive incompatible drafts.

Successful onValueCommitted checks precede adoption and may retain failures for retry. error: false remains the explicit eager-adoption exception, leaving callback failures caller-owned. isDirty compares adopted document data with its persisted baseline, not unconfirmed drafts.

Keep the slice internal

LineItems remains absent from package-root exports. No LineItems consumer documentation, showcase, or changeset is introduced. Save preparation, persistence/reconciliation, document-level validation, generic equality/normalization, sorting, selection, and row-movement UI remain deferred. Existing document identity, baseline, and boolean orderer behavior are preserved.

Summary

  • Extract shared cell sessions, controls, layout, error UI, and input parsing from DataTable while retaining its adapter contracts.
  • Centralize shared display definitions and API-specific column adapters so views consume resolved presentation/editing policy instead of repeating type-name decisions.
  • Add LineItems text, number, boolean, date, fixed/remote choice, and draft-aware custom property editors with factory-derived configuration types.
  • Coordinate typed adoption, cancellation, committed configuration, and asynchronous checks through the existing document owner.
  • Cover display/edit independence, formatter caching, live configuration, type contracts, component identity, parser boundaries, and stale-confirmation races alongside DataTable regressions.
  • Hoist the i18n label factory to handle the initialization path safely and regenerate the affected API documentation metadata.

@IzumiSy
IzumiSy added this pull request to stack #680 November 5, 2026 05:59
IzumiSy and others added 5 commits November 5, 2026 21:57
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep document-owned session coordination in a shared hook and isolate editor-specific controls, presentation, and transient choice state within the same file.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@IzumiSy
IzumiSy force-pushed the refactor/table-core-cell-session branch from 2a0bed3 to 365d0b6 Compare November 5, 2026 12:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant