Skip to content

Run 5: Entity-data-grid Evolution — Project Plan

Date: 2026-03-19 Status: Pending Risk: Highest complexity — core of the project Effort: Large

Promote general-purpose capabilities from the callil item-grid organism into entity-data-grid, making it the single canonical grid component for all entity types. Run 5 has five sequential sub-runs, each adding one capability with its own stories, tests, and verification gate. Sub-runs are ordered by risk (highest first).

PropertyValue
Repositoryux-prototype
Branchjmpicnic/component-consolidation
Working directory/Users/jmp/code/arda/ux-prototype/
Read-only reference/Users/jmp/code/arda/callil-consolidation-worktree/ (callil branch)
Base componentsrc/components/canary/organisms/shared/entity-data-grid/
Reference implementationcallil-consolidation-worktree/src/components/canary/organisms/item-grid/

Not needed. All tasks write to a single repository (ux-prototype) on a single branch (jmpicnic/component-consolidation). Sub-runs are strictly sequential — only one writer at a time. The callil worktree is read-only reference material, not a write target.

  • Run 4 exit gate passed (SelectCellEditor promoted to atoms/grid/select/, EnumCellEditor replaced, all grid stories with enum columns still work)
  • Branch jmpicnic/component-consolidation clean, all checks passing:
    • npm run lint — pass
    • npx tsc --noEmit — pass
    • npm run test — pass
    • npm run build-storybook — pass

All source paths are relative to ux-prototype/src/components/canary/organisms/shared/entity-data-grid/.

Sub-runFiles Created/ModifiedPurpose
5acreate-entity-data-grid.tsx, use-row-auto-publish.ts (new), use-row-auto-publish.test.ts (new), create-entity-data-grid.test.tsx (modified), create-entity-data-grid.stories.tsx (modified), index.ts (modified)Row auto-publish lifecycle, pending changes, visual states, ref API
5bcreate-entity-data-grid.tsx (modified), create-entity-data-grid.test.tsx (modified), create-entity-data-grid.stories.tsx (modified)Actions column injection
5cuse-grid-search.ts (new), use-grid-search.test.ts (new), create-entity-data-grid.tsx (modified), create-entity-data-grid.test.tsx (modified), create-entity-data-grid.stories.tsx (modified)Search/filter UI
5dcreate-entity-data-grid.tsx (modified), create-entity-data-grid.test.tsx (modified), create-entity-data-grid.stories.tsx (modified)Client-side pagination mode
5euse-drag-to-scroll.ts (new), use-drag-to-scroll.test.ts (new), create-entity-data-grid.tsx (modified), create-entity-data-grid.stories.tsx (modified)Toolbar slot, auto-height, drag-to-scroll
ClassPurposeStyle
.ag-row-savingRow publish in progressbackground-color: color-mix(in srgb, var(--base-primary) 6%, var(--base-background))
.ag-row-errorRow publish failedbackground-color: color-mix(in srgb, var(--destructive) 8%, var(--base-background))

Injected via <style> tag scoped to the grid container, matching the pattern in the callil item-grid.


Sub-run 5a: Row Auto-Publish Lifecycle (Highest Risk)

Section titled “Sub-run 5a: Row Auto-Publish Lifecycle (Highest Risk)”
#TaskPersonaDepends OnStatusAcceptance Criteria
5a.1Implement row-auto-publish as the only editing modefront-end-engineerEntry gatePendingonEntityUpdated callback removed from EntityDataGridModelProps. New onRowPublish(rowId, changes, entity?) async callback added. Cell changes accumulate per row instead of firing individually.
5a.2Add onRowPublish async callbackfront-end-engineer5a.1PendingonRowPublish: (rowId: string, changes: Record<string, unknown>, entity?: T) => Promise<void> added to model props. Callback fires with batched changes for a row.
5a.3Implement pending changes accumulation per rowfront-end-engineer5a.2PendingNew useRowAutoPublish hook extracted. Pending changes tracked per row via Record<string, Record<string, unknown>>. Multiple cell edits in the same row accumulate into a single change set.
5a.4Implement 50ms debounce on row blur before publishfront-end-engineer5a.3PendingWhen onCellEditingStopped fires and no more cells are editing in that row, a 50ms setTimeout defers the publish call. If editing resumes in the same row within 50ms, the publish is cancelled.
5a.5Add row visual states: idle, saving, success/errorfront-end-engineer5a.4PendingRowEditState type ('idle' | 'saving' | 'error') added. CSS classes .ag-row-saving and .ag-row-error injected via getRowClass callback. Styles match callil implementation (color-mix). <style> tag injected in grid container.
5a.6Implement imperative ref APIfront-end-engineer5a.5PendingEntityDataGridRef updated: saveAll(): Promise<void> (publishes all dirty rows sequentially), discardAll(): void (restores original values, clears pending), getDirtyRowIds(): string[] (returns IDs of rows with pending changes). Old saveAllDrafts/discardAllDrafts/getHasUnsavedChanges removed or aliased.
5a.7Add stories: RowAutoPublish, RowAutoPublishError, SaveAllDrafts, DiscardAllDraftsfront-end-engineer5a.6PendingFour stories in create-entity-data-grid.stories.tsx with step DSL play functions. RowAutoPublish: edit cell, edit another in same row, click different row, verify saving callback. RowAutoPublishError: edit, blur, verify error visual persists. SaveAllDrafts/DiscardAllDrafts: toolbar button triggers ref API.
5a.8Add unit tests for pending changes, publish lifecycle, ref API, CSS class injectionfront-end-engineer5a.6PendingTests in use-row-auto-publish.test.ts and create-entity-data-grid.test.tsx. Cover: pending changes accumulate per row, onRowPublish fires with batched changes, dirty state tracking, saveAll/discardAll/getDirtyRowIds ref API, .ag-row-saving/.ag-row-error CSS class injection.
5a.9Playwright MCP visual verificationfront-end-engineer5a.7PendingNavigate to RowAutoPublish story; edit cell, edit another in same row, click different row. Verify saving row background appears briefly then clears. Navigate to RowAutoPublishError; verify error row background persists. Check SaveAllDrafts/DiscardAllDrafts via toolbar button interactions.
5a.10VRT baselines for row visual statesfront-end-engineer5a.9PendingGenerate VRT baselines for RowAutoPublish, RowAutoPublishError stories. Capture: idle state, saving state (light orange tint), error state (light red tint).

Sub-run 5a Gate: npm run test pass + all 4 stories render + play functions pass + VRT baselines captured.

#TaskPersonaDepends OnStatusAcceptance Criteria
5b.1Add actionsColumn as InitConfig propertyfront-end-engineer5a gatePendingNew actionsColumn?: ColDef<T> & { actionCount?: number } in EntityDataGridConfig. Treated as mount-time (InitConfig) — value read once during factory creation, not reactive to prop changes.
5b.2Inject as pinned-right column with auto-width calculationfront-end-engineer5b.1PendingActions column appended to column defs with pinned: 'right', lockPinned: true, suppressHeaderMenuButton: true. Width calculation: actionCount * 28 + (actionCount - 1) * 4 + 16 (28px per button, 4px gap, 16px padding). Falls back to explicit width or 200px default.
5b.3Add WithActionsColumn story with step DSL play functionfront-end-engineer5b.2PendingStory in create-entity-data-grid.stories.tsx. Shows 2-3 action buttons per row. Play function: click action button, verify callback receives correct row data.
5b.4Add unit tests: column injection, width calc, action callbacksfront-end-engineer5b.2PendingTests in create-entity-data-grid.test.tsx. Verify: actions column injected as last column with pinned: 'right', width calculated from actionCount, action callbacks receive correct entity.
5b.5Playwright MCP visual verificationfront-end-engineer5b.3PendingNavigate to WithActionsColumn story. Click action buttons in rows. Verify pinned-right column appearance and button layout.

Sub-run 5b Gate: npm run test pass + WithActionsColumn story renders + play function passes.

Sub-run 5c: Search/Filter UI (Medium Risk)

Section titled “Sub-run 5c: Search/Filter UI (Medium Risk)”
#TaskPersonaDepends OnStatusAcceptance Criteria
5c.1Add searchConfig to factory configfront-end-engineer5b gatePendingNew searchConfig?: { fields: string[], placeholder?: string } in EntityDataGridConfig. When provided, search bar renders above the grid. When absent, no search UI.
5c.2Implement search bar with 150ms debouncefront-end-engineer5c.1PendingNew useGridSearch hook. Search input with type="search", debounced via 150ms setTimeout. Quick filter applied via AG Grid’s quickFilterText or client-side rowData filtering on configured fields. Search icon from lucide-react.
5c.3Implement filtered count displayfront-end-engineer5c.2PendingCount label shows "N items" when no search/selection, "N of M items" when filtered, "N of M selected" when rows selected. Updates reactively as search input changes and selection changes.
5c.4Add WithSearch and WithSearchAndSelection stories with step DSL play functionsfront-end-engineer5c.3PendingTwo stories. WithSearch: type search term, verify row count changes after debounce, verify count display text. WithSearchAndSelection: select rows, verify count switches to selected format.
5c.5Add unit tests: debounce timing, filter predicate, count updatesfront-end-engineer5c.3PendingTests in use-grid-search.test.ts and create-entity-data-grid.test.tsx. Cover: 150ms debounce (vi.useFakeTimers), filter applies to configured fields only, count text formats correctly for all states.
5c.6Playwright MCP visual verificationfront-end-engineer5c.4PendingNavigate to WithSearch story. Type a search term. Verify row count updates after debounce. Verify count display text. Check WithSearchAndSelection: select rows, verify count switches.

Sub-run 5c Gate: npm run test pass + both stories render + play functions pass.

Sub-run 5d: Pagination Modes (Low-Medium Risk)

Section titled “Sub-run 5d: Pagination Modes (Low-Medium Risk)”
#TaskPersonaDepends OnStatusAcceptance Criteria
5d.1Add pagination mode as StaticConfig propertyfront-end-engineer5c gatePendingNew paginationMode in EntityDataGridConfig (factory config, design-time). Two modes: 'server' (existing PaginationData + callbacks) and 'client' (AG Grid built-in pageSize). Modes are mutually exclusive. When 'client', new pageSize: number in config. When 'server', existing paginationData/onNextPage/etc. props used. Default: none (no pagination).
5d.2Implement client-side paginationfront-end-engineer5d.1PendingWhen paginationMode: 'client', pass pagination: true and paginationPageSize to AG Grid. paginationPageSizeSelector: false (no size selector).
5d.3Verify existing server-driven pagination still worksfront-end-engineer5d.2PendingExisting ServerPagination story still renders. Existing pagination tests still pass. No changes to server pagination code path.
5d.4Add ClientPagination storyfront-end-engineer5d.2PendingStory in create-entity-data-grid.stories.tsx. Shows 50 rows with pageSize: 10. AG Grid’s built-in pagination controls visible.
5d.5Add unit tests: both modes correct, mutually exclusivefront-end-engineer5d.2PendingTests verify: client mode passes correct AG Grid props, server mode uses PaginationData, specifying both modes produces a warning or the factory-time mode wins.

Sub-run 5d Gate: npm run test pass + ClientPagination story renders + existing ServerPagination story still works.

Sub-run 5e: Toolbar, Auto-Height, Drag-to-Scroll (Low Risk)

Section titled “Sub-run 5e: Toolbar, Auto-Height, Drag-to-Scroll (Low Risk)”
#TaskPersonaDepends OnStatusAcceptance Criteria
5e.1Add toolbar prop (ReactNode slot above grid)front-end-engineer5d gatePendingNew toolbar?: ReactNode in EntityDataGridViewProps. Rendered in a container div above the grid (between search bar and grid, or at the top if no search). Flex layout with ml-auto for right-alignment.
5e.2Add autoHeight StaticConfig propertyfront-end-engineer5e.1PendingNew autoHeight?: boolean in EntityDataGridConfig (design-time). When true, passes domLayout: 'autoHeight' to DataGrid/AG Grid. Disables explicit height.
5e.3Add enableDragToScroll opt-in with useDragToScroll hookfront-end-engineer5e.2PendingNew enableDragToScroll?: boolean in EntityDataGridConfig. New useDragToScroll(containerRef) hook extracted from callil item-grid. ~80 lines pointer-event logic: 5px threshold, cursor change, cell focus clear, click suppression (100ms timeout), header/popup/input/button ignore.
5e.4Add WithToolbar, AutoHeight, DragToScroll storiesfront-end-engineer5e.3PendingThree stories. WithToolbar: buttons/dropdown above grid. AutoHeight: grid with 3 rows growing to fit. DragToScroll: wide grid with many columns demonstrating horizontal drag.
5e.5Add unit tests: toolbar render, autoHeight pass-throughfront-end-engineer5e.3PendingTests verify: toolbar ReactNode renders in correct position, domLayout: 'autoHeight' passed when autoHeight: true, useDragToScroll hook attaches/detaches event listeners. DragToScroll play function optional (fragile in CI).

Sub-run 5e Gate: npm run test pass + all 3 stories render.

#TaskPersonaDepends OnStatusAcceptance Criteria
5.qrQuality review of sub-run 5aquality-reviewer5a gatePendingReview useRowAutoPublish hook for: race conditions in debounce/publish, memory leaks (timer cleanup), correct useCallback/useMemo dependencies, TypeScript strictness, consistent error handling. Review API surface for breaking changes against existing consumers.

Entry Gate (Run 4 passed)
|
v
Sub-run 5a: Row Auto-Publish Lifecycle (highest risk)
5a.1 -> 5a.2 -> 5a.3 -> 5a.4 -> 5a.5 -> 5a.6 -> 5a.7 ---------> 5a.9 -> 5a.10
\-> 5a.8 ---/
[5a Gate: tests + stories + play functions + VRT]
|
+-- 5.qr (quality review, parallel with 5b start)
|
v
Sub-run 5b: Actions Column (medium risk)
5b.1 -> 5b.2 -> 5b.3 -> 5b.5
\-> 5b.4
[5b Gate: tests + story + play function]
|
v
Sub-run 5c: Search/Filter UI (medium risk)
5c.1 -> 5c.2 -> 5c.3 -> 5c.4 -> 5c.6
\-> 5c.5
[5c Gate: tests + stories + play functions]
|
v
Sub-run 5d: Pagination Modes (low-medium risk)
5d.1 -> 5d.2 -> 5d.3
\-> 5d.4
\-> 5d.5
[5d Gate: tests + stories]
|
v
Sub-run 5e: Toolbar, Auto-Height, Drag-to-Scroll (low risk)
5e.1 -> 5e.2 -> 5e.3 -> 5e.4
\-> 5e.5
[5e Gate: tests + stories]
|
v
Exit Gate

Sub-runs are strictly sequential. Within each sub-run, implementation tasks are sequential, while stories and tests can begin as soon as the implementation they test is complete. The quality review (5.qr) for sub-run 5a can overlap with the start of sub-run 5b since it is read-only.


PersonaTasks AssignedWorking DirectoryAgent Name PatternSpawn Order
front-end-engineer5a.1-5a.10, 5b.1-5b.5, 5c.1-5c.6, 5d.1-5d.5, 5e.1-5e.5/Users/jmp/code/arda/ux-prototype/fe-entity-grid-5x1st
quality-reviewer5.qr/Users/jmp/code/arda/ux-prototype/ (read-only)qr-auto-publishAfter 5a gate

All spawned agents use mode: "bypassPermissions".


  • New useRowAutoPublish hook replacing both useDirtyTracking (entity-data-grid) and useItemGridEditing (item-grid) for the auto-publish lifecycle
  • Removal of cell-granular onEntityUpdated callback from entity-data-grid
  • New onRowPublish async callback with batched per-row changes
  • Row visual states (saving/error) via CSS class injection
  • Updated imperative ref API: saveAll(), discardAll(), getDirtyRowIds()
  • Actions column as InitConfig property with auto-width calculation
  • Search/filter UI with configurable fields, 150ms debounce, filtered count display
  • Client-side pagination mode alongside existing server-driven mode
  • Toolbar ReactNode slot above the grid
  • Auto-height domLayout pass-through
  • Drag-to-scroll horizontal scrolling with useDragToScroll hook
  • 10+ new stories with step DSL play functions
  • Unit tests for every new capability
  • VRT baselines for row visual states
  • Playwright MCP visual verification for all stories
  • Item-grid refactoring to use entity-data-grid (Run 6)
  • TypeaheadCellEditor extraction (already handled as a molecule in Run 3)
  • entity-data-grid-shim changes (deprecated, kept as-is)
  • Barrel export changes (Run 7)
  • Composition/acceptance stories (Run 8)
  • Changes to the DataGrid molecule (theme already migrated in Run 2)
  • Any changes to the callil worktree (read-only reference)

These decisions are recorded in analysis/grid-integration.md and govern this run:

#DecisionRationale
1Row-auto-publish is the ONLY editing modeCell-granular onEntityUpdated does not match the product’s UX pattern. All entity grids auto-publish on row blur. No need to support both modes.
2Actions column is InitConfig (mount-time)Contents may be determined by user/tenant settings in the future. Mount-time evaluation allows the factory to bake in the column definition once.
3Pagination modes are StaticConfig (design-time), mutually exclusiveThe pagination approach is a structural choice made when creating the factory — server-driven (external data source) vs client-side (full dataset in memory). Cannot be switched at runtime.
4entity-data-grid-shim is deprecated but kept in placeNew code uses entity-data-grid directly. The shim remains for any migration needs during Run 6+.
5useDirtyTracking is replaced by useRowAutoPublishThe existing hook tracks dirty state but has no publish lifecycle. The new hook subsumes its functionality and adds pending changes accumulation, debounced publish, and row visual state management.

  • onEntityUpdated callback removed from EntityDataGridModelProps
  • onRowPublish async callback fires with batched per-row changes on row blur
  • Pending changes accumulate across multiple cell edits in the same row
  • 50ms debounce on row blur before publish fires
  • .ag-row-saving and .ag-row-error CSS classes injected during publish lifecycle
  • saveAll(), discardAll(), getDirtyRowIds() ref API works correctly
  • Actions column injected as pinned-right with correct auto-width calculation
  • Search bar renders when searchConfig provided, with 150ms debounce
  • Filtered count displays correctly in all states (no filter, filtered, selected)
  • Client-side pagination works via AG Grid built-in pageSize
  • Server-driven pagination (existing) still works — no regressions
  • Toolbar ReactNode renders above the grid
  • autoHeight passes domLayout: 'autoHeight' to AG Grid
  • useDragToScroll hook provides horizontal drag-scroll with proper threshold and cleanup
  • All new stories (10+) render in Storybook
  • All play functions use step DSL and pass in npm run test:storybook
  • All unit tests pass
  • VRT baselines captured for row visual states
  • All existing entity-data-grid stories still pass (no regressions)
  • npm run lint + npx tsc --noEmit + npm run test + npm run build-storybook all pass

#Risk/BlockerLikelihoodImpactMitigation
R1Removing onEntityUpdated breaks existing consumersMediumHighSearch for all usages of onEntityUpdated before removal. If external consumers exist, provide a migration path or deprecation period. The entity-data-grid-shim may need adjustment.
R2Race condition in debounce + async publishMediumHighQuality review (5.qr) specifically targets this. Use timer cleanup in useEffect return. Cancel pending publishes if component unmounts.
R3AG Grid getRowClass callback timing with React stateLowMediumThe callil useItemGridEditing already proves this pattern works. Follow the same useCallback + state-driven approach.
R4Search debounce conflicts with cell editingLowMediumSearch input is outside the grid — AG Grid’s editing state is independent. Test this interaction in the WithSearch story.
R5useDragToScroll interferes with cell selectionLowLowHook ignores drags on header, popups, inputs, buttons. The callil implementation is battle-tested. Copy it directly.
R6Client-side pagination conflicts with server-driven propsLowMediumModes are mutually exclusive at factory creation time. TypeScript union type prevents passing both. Unit test enforces exclusivity.

#QuestionOptionsRecommendationDecision
1Should useDirtyTracking be removed or kept alongside useRowAutoPublish?(a) Remove — single hook, (b) Keep both — backward compat(a) Remove. The new hook subsumes all functionality. useDirtyTracking has no external consumers beyond entity-data-grid.Accepted (2026-03-19): Remove
2Should the search bar use AG Grid’s quickFilterText or client-side rowData filtering?(a) quickFilterText — simpler but less control, (b) Client-side filter — matches item-grid approach(b) Client-side. Gives control over which fields are searched and allows the filtered count display. Server-side search via Query DSL is a future enhancement (tracked as GitHub ticket).Accepted (2026-03-19): Client-side
3Should the toolbar prop coexist with the search bar in the same row or be a separate row?(a) Same row — toolbar right-aligned after search, (b) Separate row above search(a) Same row. Matches item-grid layout. Toolbar right-aligned with ml-auto.Accepted (2026-03-19): Same row

You are implementing the row-auto-publish lifecycle for entity-data-grid.
Working directory: /Users/jmp/code/arda/ux-prototype/
Branch: jmpicnic/component-consolidation
Entity-data-grid source: src/components/canary/organisms/shared/entity-data-grid/
Reference implementation:
- /Users/jmp/code/arda/callil-consolidation-worktree/src/components/canary/organisms/item-grid/use-item-grid-editing.ts
- /Users/jmp/code/arda/callil-consolidation-worktree/src/components/canary/organisms/item-grid/item-grid.tsx (row state styles, getRowClass usage)
Key decisions:
- Row-auto-publish is the ONLY editing mode. Remove onEntityUpdated.
- New onRowPublish(rowId, changes, entity?) async callback.
- 50ms debounce on row blur before publish.
- Row visual states via CSS classes: .ag-row-saving, .ag-row-error
- Ref API: saveAll(), discardAll(), getDirtyRowIds()
Conventions:
- All play functions use the step DSL (see analysis/test-coverage.md)
- Use storyStepDelay() between major interaction steps
- Follow existing test patterns in create-entity-data-grid.test.tsx
- TypeScript strict mode (exactOptionalPropertyTypes: true)
You are adding capabilities to entity-data-grid. Each sub-run adds one feature.
Working directory: /Users/jmp/code/arda/ux-prototype/
Branch: jmpicnic/component-consolidation
Entity-data-grid source: src/components/canary/organisms/shared/entity-data-grid/
Reference implementation for each feature:
- Actions column: callil-consolidation-worktree/.../item-grid.tsx (actionsColumn prop, width calc)
- Search/filter: callil-consolidation-worktree/.../item-grid.tsx (search state, debounce, count display)
- Pagination: callil-consolidation-worktree/.../item-grid.tsx (pageSize prop, AG Grid pagination)
- Toolbar: callil-consolidation-worktree/.../item-grid.tsx (toolbar prop, flex layout)
- Auto-height: callil-consolidation-worktree/.../item-grid.tsx (autoHeight prop, domLayout)
- Drag-to-scroll: callil-consolidation-worktree/.../item-grid.tsx (useEffect with pointer events)
Config tiers:
- StaticConfig (design-time, in EntityDataGridConfig): paginationMode, autoHeight, enableDragToScroll
- InitConfig (mount-time, in EntityDataGridConfig): actionsColumn, searchConfig
- RuntimeConfig (render-time, in EntityDataGridViewProps): toolbar
Conventions:
- All play functions use the step DSL
- All new hooks get their own test file
- Follow existing patterns in create-entity-data-grid.stories.tsx
You are reviewing the row-auto-publish implementation for correctness and safety.
Files to review:
- src/components/canary/organisms/shared/entity-data-grid/use-row-auto-publish.ts
- src/components/canary/organisms/shared/entity-data-grid/create-entity-data-grid.tsx (changes only)
- src/components/canary/organisms/shared/entity-data-grid/use-row-auto-publish.test.ts
- src/components/canary/organisms/shared/entity-data-grid/create-entity-data-grid.test.tsx (changes only)
Focus areas:
1. Race conditions: debounce timer vs async publish vs component unmount
2. Memory leaks: timer cleanup in useEffect return, abort on unmount
3. useCallback/useMemo dependency arrays — correctness and exhaustiveness
4. TypeScript strictness: no implicit any, exactOptionalPropertyTypes compliance
5. Error handling: what happens when onRowPublish rejects? Does the row stay in error state?
6. API surface: breaking changes to EntityDataGridRef, EntityDataGridProps
7. Test coverage: are edge cases covered (rapid edits, concurrent publishes, empty changes)?
This is a read-only review. Do not modify files.

At run completion, write the following to implementation/run-5-entity-grid-evolution/:

ArtifactFileDescription
Run summarysummary.mdWhat was done, decisions made during implementation, deviations from plan
Byproducts logbyproducts.mdDiscovered issues, TODOs, observations for later runs
Validation outputvalidation-output.txtStdout from validate-exit.sh execution
Session logsession-log.mdAgent session IDs, timestamps, notable events

Path: documentation/src/content/docs/roadmap/backlog/requested/callil-consolidation/implementation/run-5-entity-grid-evolution/

Exit artifacts from Run 5:

  • Entity-data-grid with full API: createEntityDataGrid<T>(config) supporting auto-publish, actions, search, pagination, toolbar, auto-height, drag-to-scroll
  • Updated EntityDataGridConfig type with all new properties
  • Updated EntityDataGridRef type with saveAll(), discardAll(), getDirtyRowIds()
  • 10+ stories demonstrating each capability
  • Unit tests proving each capability

Context for Run 6:

  • Item-grid can now be refactored to call createEntityDataGrid<Item>(itemGridConfig) instead of building on the DataGrid molecule directly
  • Domain-specific code (curated columns, typeahead lookups, notes icon, image renderer) stays in item-grid config
  • The useItemGridEditing hook should be removable — entity-data-grid’s built-in auto-publish replaces it
  • Evaluate whether item-grid becomes a pure factory config call or needs a thin wrapper for domain-specific rendering

All sub-run gates passed:

  • 5a gate: Row auto-publish stories + tests + play functions + VRT pass
  • 5b gate: Actions column story + tests + play function pass
  • 5c gate: Search/filter stories + tests + play functions pass
  • 5d gate: Pagination stories + tests pass
  • 5e gate: Toolbar/auto-height/drag-to-scroll stories + tests pass

Overall:

  • npm run lint — pass
  • npx tsc --noEmit — pass
  • npm run test — pass (all tests, including all new tests)
  • npm run build-storybook — pass
  • npm run test:storybook — all play functions pass
  • VRT: npx playwright test --project=vrt — pass (row visual state baselines captured)
  • All existing entity-data-grid stories still pass (no regressions)
  • Entity-data-grid API supports all capabilities needed for item-grid to use it as a base (Run 6 entry criterion)
  • Quality review (5.qr) completed for sub-run 5a with no blocking findings

DateEvent
2026-03-19Project plan created