Skip to content

Run 6: Item-grid Integration — Implementation Summary

Date: 2026-03-19 Branch: jmpicnic/component-consolidation Status: Complete — all exit criteria pass

TaskStatusNotes
6.1 Evaluate factory config vs wrapperDoneThin wrapper required (see decision below)
6.2 Create item-grid implementationDoneThin wrapper over createEntityDataGrid
6.3 Replace useItemGridEditingDoneDeleted; entity-data-grid useRowAutoPublish used
6.4 Replace inline search, drag-to-scroll, toolbar, actionsDoneAll delegated to entity-data-grid factory config
6.5 Preserve domain-specific codeDoneCurated columns, typeahead lookups, renderers all preserved
6.6 Update item-grid storiesDoneStories updated; gridRef changed to ItemGridHandle
6.7 Update item-grid unit testsDone3 count-label assertions updated for new format

Decision: Thin Wrapper with Design-Time Factory Config

Section titled “Decision: Thin Wrapper with Design-Time Factory Config”

Assessment: item-grid uses createEntityDataGrid as its base via a thin forwardRef wrapper that calls the factory inside useMemo. All item-domain configuration is design-time:

  1. onNotesClick callback — passed to createItemGridColumnDefs(lookups, { onNotesClick }) at factory creation time. NotesCellRenderer reads it from cellRendererParams (not AG Grid context). No gridContext needed.

  2. getGridApi() (raw AG Grid API access) — added to EntityDataGridRef for imperative operations (column visibility, deselectAll).

Post-implementation cleanup: An initial approach added gridContext/gridContextOverride to entity-data-grid and DataGrid molecule. This was reverted per the project owner’s design correction — onNotesClick and lookups are stable design-time values, not runtime props. The cellRendererParams approach is the AG Grid-idiomatic solution.

None.

src/components/canary/organisms/shared/entity-data-grid/create-entity-data-grid.tsx

  • Added getGridApi(): GridApi | null to EntityDataGridRef
  • Wired getGridApi() in useImperativeHandle via gridRef.current?.getGridApi()
  • Removed gridContext (factory config) and gridContextOverride (view prop) — not needed after cleanup

src/components/canary/organisms/shared/entity-data-grid-shim/create-entity-data-grid-shim.tsx

  • Added getGridApi: () => baseRef.current?.getGridApi() ?? null to useImperativeHandle to satisfy the updated EntityDataGridRef interface

src/components/canary/organisms/item-grid/item-grid.tsx (complete rewrite)

  • No longer builds on DataGrid molecule directly
  • Uses createEntityDataGrid<Item> inside useMemo keyed on structural props
  • Passes onNotesClick to createItemGridColumnDefs at factory creation time (via cellRendererParams)
  • Maps ItemGridHandleEntityDataGridRef via combinedRef callback
  • Preserves entire public API: ItemGridProps, ItemGridStaticConfig, ItemGridRuntimeConfig
  • Adds ItemGridHandle (extends ItemGridEditingHandle + getGridApi())
  • editingRef and gridRef both satisfied through the combined ref callback

src/components/canary/molecules/item-grid/item-grid-columns.tsx

  • createItemGridColumnDefs now accepts options?: { onNotesClick?: (item: Item) => void }
  • NotesCellRenderer reads onNotesClick from params.colDef?.cellRendererParams instead of params.context
  • Notes column passes onNotesClick via cellRendererParams when provided

src/components/canary/organisms/item-grid/index.ts

  • Removed export of useItemGridEditing types (file deleted)
  • Added export of ItemGridHandle
  • PendingChanges re-exported from entity-data-grid instead of old hook

src/components/canary/molecules/item-grid/item-grid-columns.tsx

  • Changed SelectCellEditor import from ./select-cell-editor to canonical ../../atoms/grid/select/select-cell-editor
  • Updated Order Method column cellEditorParams.valuescellEditorParams.options (canonical API)

src/components/canary/molecules/item-grid/item-grid-molecules.stories.tsx

  • Updated SelectCellEditor import to canonical atom
  • Updated story prop valuesoptions

src/components/canary/organisms/item-grid/item-grid.stories.tsx

  • Removed import type { AgGridReact } from 'ag-grid-react'
  • Added import type { ItemGridHandle } from item-grid
  • Changed gridRef = useRef<AgGridReact<Item>>(null)useRef<ItemGridHandle>(null)
  • Updated gridRef.current?.api?.setColumnsVisible(...)gridRef.current?.getGridApi()?.setColumnsVisible(...)
  • Updated gridRef.current?.api?.deselectAll()gridRef.current?.getGridApi()?.deselectAll()
  • Updated WithSearch play function: '1 item''1 of 12 items' (new count label format)

src/components/canary/organisms/item-grid/item-grid.test.tsx

  • Updated 3 search-count assertions: '1 item''1 of 12 items' to match entity-data-grid count label behavior

src/components/canary/organisms/item-grid/use-item-grid-editing.ts

  • Replaced by entity-data-grid/use-row-auto-publish.ts (same row-level auto-publish lifecycle)

src/components/canary/molecules/item-grid/select-cell-editor.tsx

  • Canonical version is at atoms/grid/select/select-cell-editor.tsx
BehaviorBeforeAfter
Search count (no filter)“12 items""12 items” (same)
Search count (active filter)“1 item""1 of 12 items”
Height when no autoHeight600px fixedFills parent container (flex)
Row selection checkboxesOnly when enableRowSelection: trueAlways enabled (DataGrid default)
editingRef typeRef<ItemGridEditingHandle>Ref<ItemGridEditingHandle> (unchanged)
gridRef type`RefObject<AgGridReactnull>`

The count label change (“1 item” → “1 of 12 items”) is a deliberate improvement that shows search context. Tests and the WithSearch story play function were updated to reflect this.

#CriterionResult
X1npm run lint passesPass
X2npx tsc --noEmit passesPass
X3npm run test passes (1059/1059)Pass
X4npm run build-storybookNot run (requires visual verification)
X5Visual equivalencePending Playwright MCP (6.8)
X6No regressions in entity-data-grid testsPass (included in test run)
X7No duplicated framework codePass (verified by grep)
X8Item-grid play functions passPending visual verification
X9Commits on jmpicnic/component-consolidationPending commit (user requested no commit)