Skip to content

refactor(plugin-grid): move ObjectGrid's authored-input diagnostics into a sibling hook (slice 3) - #26364

Merged
objectstack-fleet[bot] merged 8 commits into
mainfrom
claude/project-thread-mbvzks
Oct 27, 2026
Merged

objectstack-fleet[bot] merged 8 commits into
mainfrom
claude/project-thread-mbvzks

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread

Part of #25994 (slice 3 of the move-only split, the first slice inside the ObjectGrid component body; slices 1 and 2 landed as #26323 and #26354, and the card stays open for the slices listed below).

Clause-②: no
Metadata-protocol: none

What moved

Base 222755eb (slice 2 merged). ui/packages/plugin-grid/src/ObjectGrid.tsx is 6637 lines there: imports and re-exports, the module-level code that tests pin in place, and the ObjectGrid component from line 673 to the end.

This slice moves concern Q of the seam table below, verbatim, into a custom hook useObjectGridDiagnostics in a new sibling module ui/packages/plugin-grid/src/objectGridDiagnostics.ts. Q is the three authored-input diagnostics, each a useEffect with one console.warn, with their whole comment blocks:

  • a columns entry the renderer cannot read (objectui#5349), through describeUnresolvedColumns;
  • an unusable bulkActionDefs member (objectui#8730), through describeUnusableBulkActionDefs;
  • a pagination.pageSize or flat pageSize that is not a positive integer (objectui#9853), through describeNonPositivePageSize.

Q reads only schema and declares nothing any other region reads, so the hook takes schema: ObjectGridSchema and nothing else. It declares no state, adds no context and returns nothing. ObjectGrid calls useObjectGridDiagnostics(schema) at the exact place the moved lines stood (after the column summaries, before generateColumns), so the order of the component's hooks does not change. The three describe* import specifiers move with their only readers. No identifier is renamed. Nothing new is exported from ObjectGrid.tsx, and the package entry is untouched. ObjectGrid.tsx goes from 6637 to 6563 lines.

Move-only proof: the multiset of non-blank lines of the base ObjectGrid.tsx equals the new ObjectGrid.tsx plus objectGridDiagnostics.ts. Nothing is missing. The only added lines are the new module's header comment, its five imports, the hook's docblock, signature and closing brace, and in ObjectGrid.tsx the new import plus the call with its two-line comment. The three edited import lines differ only by the removed specifiers.

Kept away from #26341 (#25884): its ObjectGrid.tsx edits are temporalGroupHeading and the seven column-cell call sites inside generateColumns (region R). This slice touches neither, and its only hunk in the component body ends above generateColumns.

Test edits

None. No test reads the moved lines as source: I checked every test that reads ObjectGrid.tsx (the nine in plugin-grid/src/__tests__ and the fourteen elsewhere that key a census row by that path), and none names describeUnresolvedColumns, describeUnusableBulkActionDefs, describeNonPositivePageSize or the three diagnostic slices. The behavioural tests that spy on console.warn render the real ObjectGrid, so they cover the hook.

Seam table of the ObjectGrid component (measured on 222755eb)

Lines are in the base file. "Reads" names inputs from other regions; the props and schema are left out. "Read by" names the regions that use what a region declares. A region after the first early return (line 3758) cannot become a hook, because a hook may not run after a conditional return; it can become a plain function or a sub-component with explicit props.

# Concern Lines Declares (main) Reads Read by Slice
A Props destructure 673–709 the host props — all stays
B Core state: rows, loading, error, i18n, metadata, object schema, card view, refresh key, row versions, row conflict, export flags, row height, selection, bulk dialog, grouped paging 710–763 data, loading, objectSchema, refreshKey, selectedRows, rowConflict, … and setters — all stays (shared state)
C Row-height sync effect 765–776 — B — 8 (with AD)
D Column state persistence 778–849 columnStorageKey, columnState, saveColumnState — U, AA 11 (pinned: gridNonAuthorKeys reads the NON-AUTHOR SURFACE — columnState block here)
E Pull to refresh, card-view breakpoint 851–870 pullRef, isRefreshing, pullDistance B AC, AH 4
F Record source: bound data, data config, inline data, host paging mode, object name and fields 873–950 dataConfig, hasInlineData, externalManualPagination, objectName, objectFields B most stays (shared; base-bind-declared keys the bind read to this file)
G Permissions, row affordances, operations, row actions, CRUD verdicts 951–1171 perms, operations, canEdit, canDelete, resolvedRowActionDefs, recordVerdict, … B, F K, V, X, Y, AF 11 (pinned: NON-AUTHOR SURFACE — rowActionDefs block)
H Projection keys (grouping, predicates, row colour, concurrency token) 1172–1264 groupingProjectionKey, predicateProjectionKey, carriesConcurrencyToken, rowColorField B, F K 5 (with I)
I Filter, sort, search and server paging state 1265–1390 schemaFilter, headerSort, searchTerm, querySearchTerm, serverPage, searchFieldsKey B, F K, Z, AF 5 (with H)
J Grouping decisions: masked grouping refusal, server-grouped fetch, header-query and whole-rows refusals, fetch window 1391–1548 serverGroupedFetch, groupingNeedsHeaderQuery, groupingNeedsWholeRows, fetchWindow, groupRowQuery B, F, I K, O, T 6 (with O)
K The row load effect 1549–2168 invalidationNonce (the effect sets B's state) B, F, G, H, I, J O 7 (largest effect; one hook with typed inputs)
L Host findParams sync 2169–2187 — B — 4 (with E)
M Navigation overlay, action runtime, row colour, predicate scope, capability gate, row style 2188–2276 navigation, executeAction, getRowClassName, mayInvokeRowAction, getRowStyle B, F R, V, AA, AB, AC stays (shared; pinned: NON-AUTHOR SURFACE — onNavigate block and the onNavigate: onNavigate ?? schema.onNavigate read)
N Group value formatter and temporal group faces 2277–2381 groupValueFormatter, temporalGroupFaces B, F O, AE after #26341 lands (it edits temporalGroupHeading, which N calls)
O Server grouping: headers, rows, grouped data, grouped totals 2382–2557 groups, isGrouped, toggleGroup, groupHeaders, serverGroupTotal B, F, I, J, K, N P, T, W, Z, AA, AE 6 (with J)
P Bulk fan-out params, column summaries 2558–2624 bulkFanoutParams, summaries, hasSummary B, F, O X, AE 9 (with X)
Q Authored-input diagnostics 2625–2702 (nothing anyone reads) (schema only) none 3, this PR
R generateColumns 2704–3590 generateColumns B, F, G, M U 12, after #26341 (it edits the seven cell call sites here; pinned by columnReadBoundary-6458, relationalMetaCopySet, cellRendererResolutionBoundary-8920, percent-storage-callers-11475, column-identity.ratchet)
S Export: formats, format warning, handleExport 3591–3755 exportableFormats, handleExport B, F AD 8 (pinned: ObjectGrid.exportOptionsKeys reads the schema.exportOptions reads here)
T Early returns: filter refusal, whole-rows refusal, load error, loading, header-query refusal 3756–3853 — B, I, J, O — 10 (sub-components)
U Column post-processing: persisted widths and order 3854–4040 columns, persistedColumns D, R V, W 12 (with R)
V Actions column and pinning 4041–4213 columnsWithActions, pinned column sets G, M, U W, AA 12 (pinned: NON-AUTHOR SURFACE — maxInlineRowActions)
W Density, sortability, column chrome, frozen columns, manual paging flags 4214–4406 orderedColumns, manualPaginationOn, manualSearchOn, effectiveFrozenColumns B, F, O, U, V Z, AA, AF 12
X Bulk actions and selection 4407–4783 bulkActionDefs, selectionMode, dispatchBulkAction, handleBulkDialogClose, … B, F, G, P AA, AG 9 (with P)
Y Row save and optimistic-concurrency conflict 4784–5012 defaultRowSave, defaultBatchSave, settleRowConflict B, F, G AA, AG 11 (pinned: affordanceGrantMap-12082 keys ObjectGrid > writeRowGuarded and ObjectGrid > resolveRowConflict to this file)
Z Pagination, sort and search wiring 5013–5118 pageSize, manualPage, manualSort, manualOnSortChange, manualSearch B, F, I, W AA 12 (with AA)
AA dataTableSchema, grouped table schema 5119–5466 tableColumns, dataTableSchema, buildGroupedTableSchema most AE, AH 12
AB Record detail overlay 5467–5692 recordOverlayShellProps, renderRecordDetail B, F, M AC, AH 10
AC Mobile card view (an early return) 5693–6025 — B, E, M, AB — 10 (pinned: clickableNonControlCensus-13461 keys its clickable div to this file)
AD Toolbar: row height toggle, export menu 6026–6128 gridToolbar B, C, S AH 8 (with C, S)
AE Summary footer, group headers and footers, group bands, grouped pager, grid content 6129–6408 summaryFooter, groupedPager, gridContent B, N, O, P, AA AF 10 (pinned: iconOnlyButtonCensus-12143 counts two icon-only pagers in this file)
AF Empty states 6409–6514 renderedGridContent B, G, I, W, AE AH 10
AG Bulk and row-conflict dialogs 6515–6553 bulkDialog, rowConflictDialog B, X, Y AH 9 (with X)
AH The final return 6554–6637 — everything — stays

Remaining slices (one PR each; the last closes the card)

  • Slice 4 — E + L: pull to refresh, the card-view breakpoint effect and the host findParams sync into a sibling hook.
  • Slice 5 — H + I: the projection keys and the filter, sort, search and server-paging state into a sibling hook.
  • Slice 6 — J + O: the grouping decisions and server grouping into a sibling hook.
  • Slice 7 — K: the row load effect into a sibling hook, every input typed from its source.
  • Slice 8 — C + S + AD: the row-height sync, export and the toolbar into a hook plus a toolbar sub-component. S is pinned by ObjectGrid.exportOptionsKeys; this slice needs that test to read the new module too.
  • Slice 9 — P + X + AG: bulk fan-out, bulk actions, selection and the bulk dialog into a hook (above the early returns) plus plain functions or a sub-component (below them).
  • Slice 10 — T + AB + AC + AE + AF: the early-return panels, the record detail overlay, the mobile card view, the grouped content and the empty states into sub-components with explicit props. AC and AE carry census rows keyed to ObjectGrid.tsx.
  • Slice 11 — D + G + Y: the column-state persistence, the row affordances and the row save handlers. They are pinned by file and symbol (gridNonAuthorKeys, affordanceGrantMap-12082); moving them needs those rows re-keyed to the new file, which is more than the import-path edits the card allows. If the seat does not grant that, they stay in ObjectGrid.tsx as the component's core.
  • Slice 12 — R + U + V + W + Z + AA (closes the card): generateColumns and the column pipeline into the table schema, after fix(fields,plugin-grid): a grid date column reads in one absolute face #26341 lands. Five source-reading tests pin R, so this slice needs the same allowance as slice 11, or these regions stay and slice 11 or 10 closes the card.

A, B, F and M stay in the component in every plan: they are the shared state most other concerns read. Each later slice re-measures the line spans and the source-scan pins at its claim, because the file moves daily.

Verification

Run on head fb3f7f50:

  • pnpm --dir ui exec vitest run packages/plugin-grid/ --maxWorkers=2, the whole package suite, under the verification lock: 251 of 251 files and 2247 of 2247 tests passed after the move. The before reading is the same suite on slice 2's tested tree (the package tree of main 222755eb): 251 of 251 files, 2247 of 2247 tests, locally and in CI on refactor(plugin-grid): move ObjectGrid's host-facing props types and FooterSummaryReport into sibling modules (slice 2) #26354.
  • The 52 test files outside plugin-grid that read sources (the list slices 1 and 2 used): 52 of 52 files, 2258 of 2258 tests passed.
  • pnpm --filter @object-ui/plugin-grid type-check exit 0.
  • eslint on the two touched files: 0 errors. objectGridDiagnostics.ts draws no warning at all, so the hook's dependency arrays raise no react-hooks/exhaustive-deps finding.
  • pnpm --dir ui run check:doc-example-readers exit 0.
  • node scripts/gen-sdui-manifest-node.mjs: the manifest is byte-identical (sha256 1f6e1ccb…). Only scripts/sdui-manifest.sources/plugin-grid.json is re-recorded. node scripts/check-sdui-manifest.mjs exit 0.
  • node scripts/pm/dispatch-gates.mjs --commands: 41 derived gates, all exit 0; --ran reconciles 41 of 41 (0 NOT-MEASURED, 0 UNRUN).

Acceptance notes

  • The moved comments still say "resolvesToDataColumn above" and "the export format warning below", about code that stays in ObjectGrid.tsx. They are kept verbatim because the slice is move-only.

Landing

On the plugin-grid line this goes after #26358 and #26341, so it stays a draft. Expect a merge of main and a re-record of plugin-grid.json before it lands.

Changeset: .changeset/25994-objectgrid-diagnostics-hook.md (patch, @object-ui/plugin-grid).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Bdrd2yH4eqnz2QobtN3haE

…FooterSummaryReport into sibling modules (slice 2)

Move-only: ObjectGridColumnState, ObjectGridFooterSummary and
ObjectGridExternalPaginationProps go verbatim to objectGridProps.ts, and the
renderless FooterSummaryReport to objectGridFooterSummaryReport.tsx.
ObjectGrid.tsx imports them back and re-exports the three types, so its
exported names and the package entry do not move.

Also corrects slice 1's changeset: getDataConfig (the record-source ladder)
stayed in ObjectGrid.tsx, so it is no longer listed as moved.

Claude-Session: https://claude.ai/code/session_01Bdrd2yH4eqnz2QobtN3haE
Co-authored-by: Claude <noreply@anthropic.com>
…in slice 2's note

Claude-Session: https://claude.ai/code/session_01Bdrd2yH4eqnz2QobtN3haE
Co-authored-by: Claude <noreply@anthropic.com>
…nto a sibling hook (slice 3)

Move-only: the three console.warn effects for unreadable columns, unusable
bulkActionDefs members and a non-positive page size move verbatim into
useObjectGridDiagnostics(schema) in objectGridDiagnostics.ts. ObjectGrid
calls the hook where the effects stood, so hook order does not change.

Claude-Session: https://claude.ai/code/session_01Bdrd2yH4eqnz2QobtN3haE
Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bdrd2yH4eqnz2QobtN3haE
Co-authored-by: Claude <noreply@anthropic.com>

# Conflicts:
#	scripts/sdui-manifest.sources/plugin-grid.json
#	ui/packages/plugin-grid/src/ObjectGrid.tsx
Claude-Session: https://claude.ai/code/session_01Bdrd2yH4eqnz2QobtN3haE
Co-authored-by: Claude <noreply@anthropic.com>

# Conflicts:
#	scripts/sdui-manifest.sources/plugin-grid.json
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Test UI (4/16) red on 3ecb9b23 is inherited, not this PR's.

The only failure is ui/scripts/__tests__/doc-version-claims.test.ts (2 tests: "implausibly few node-version declarations were read from ../.github/workflows"). It reads .github/workflows, which this PR does not touch (its diff is ObjectGrid.tsx, the new objectGridDiagnostics.ts and one changeset). The same test has been red on main since #26419 merged (03:41Z), and the fix is #26421. This PR does not port it because that fix is outside this card's file surface. The seat will re-run this leg after #26421 lands; no push is needed here.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · seat domain:ui#1 · 2026-10-27T04:24Z

Head b871ab8f (read from the PR object). It is 3ecb9b23 plus the platform's base sync (pr_update_branch through the relay), which brings in #26432's fix for the doc-version-claims red that #26419 left on main. The PR's own diff is unchanged. Before that, on 3ecb9b23, Test UI 4/16 was red on the inherited failure only. It merges main 9a0108cd, which is after seat 2's #26341 (also on ObjectGrid.tsx) and after #26367 retired the sdui records. The only conflict was the modify/delete on plugin-grid.json, taken with git rm.

  • Shape. Draft on main, Part of #25994, slice 3. 3 files.
  • Checks pinned to the head. All check runs completed: 0 failing, 0 pending. The seat's landing script checked this before posting.
  • Governed surface. check-governed-merges.mjs --pr 26364: not governed.
  • Seat review. The move-only multiset was re-run against the new base: ObjectGrid.tsx goes from 6645 to 6571 lines. Nothing is missing except 3 edited import lines; the extras are only the module header, the hook signature and the call. fix(fields,plugin-grid): a grid date column reads in one absolute face #26341's hunks (temporalGroupHeading and the seven generateColumns call sites) are untouched. ObjectGrid.tsx auto-merged.
  • Evidence (dev, on 3ecb9b23).
    • plugin-grid type-check exit 0, after the Console build rebuilt a stale fields dist.
    • plugin-grid suite 253 files / 2256 tests, plus 52 outside readers / 2258 tests.
    • Console build 70/70.
    • check-empty-changeset and check:doc-example-readers exit 0.
  • Serial constraints. No other open PR touches ObjectGrid.tsx or its new siblings. The ⛔ paths are untouched.

Landing: ready + auto-merge through the relay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants