ta
TanStack
GitHub
table
Workspace
GitHub
CI Pipeline Executions
Current execution
Succeeded
fix/expanding-sorting-state-contents
Configuration
Self-Healing CI
Project Graph
Resource Usage
Analysis
Conformance
Runs
Current run
Succeeded
Tasks
Resource Usage
Insights
Compare tasks
Analytics
Sign in
Toggle sidebar
fix(table-core): correct expanded/paginated state contents and sorting toggle defaults Two independent clusters of default-behavior bugs from the beta triage. Expanded and paginated state contents: Expand-all materialized every id in `rowsById`, including leaf rows that can never expand, so a serialized `ExpandedState` was polluted with dead keys and `getExpandedDepth` was skewed by them. Materialization now writes only ids where `row.getCanExpand()` is true, chosen over `subRows.length` so `getRowCanExpand` lazy-load overrides stay expandable. `getExpandedDepth` filters the same way, and `getIsAllRowsExpanded` now only considers expandable rows so the materialized map still round-trips as "all expanded" (a map of stale ids with no expandable rows is false). Paginated `flatRows` pushed each row and then recursed into its subRows, but page rows already contain expanded descendants inline, so those rows appeared twice. The rebuild now dedupes by row id. Collapsed descendants stay included, consistent with every other row model, where `flatRows` ignores expansion state. `row.toggleExpanded(bool)` and `table.toggleAllRowsExpanded(bool)` fired `onExpandedChange` even when the requested state already matched, so controlled consumers got spurious callbacks. Both now early-return. Neither toggle consulted `row.getCanExpand()`, unlike their row-selection equivalents, so a non-expandable row could be written into expanded state imperatively. The expand direction is now guarded; collapsing is always allowed so stale expanded ids can still be cleaned up. Sorting toggle defaults: `column.toggleSorting()` called `column.getNextSortingOrder(column)` with no `multi` argument, so `enableMultiRemove` was dead on every path. The argument is now forwarded as `multi && column.getCanMultiSort()`, matching the multi-mode condition the updater itself uses. The public `getNextSortingOrder` type now accepts the `multi` argument it always supported at runtime. `column.getAutoSortDir()` sampled only `flatRows[0]`, so a leading null or a manual-sorting data swap flipped the inferred first direction mid-cycle and silently dropped a state from the toggle cycle. It now samples the first 10 rows for a non-nullish value, matching `getAutoSortFn`. Docs: `sortUndefined: false` was documented as "considered tied" in all framework sorting guides; undefined values are actually passed straight to the sorting function with no special handling. Corrected, and the missing `'first'`/`'last'` bullets were added to the generated reference. Also fixes three crashes in the MRT examples surfaced while testing the sorting changes. The MUI and Mantine sort labels read `sorting` off `state`, which does not carry it, and crashed on `sorting.length`; they now read it through `table.Subscribe` on `table.atoms.sorting`, which also makes the badge reactive. The row-action edit handler passed a shallow row copy to `setEditingRow`, breaking the row identity the edit modal needs. `mrtRefsFeature` seeded the keyed `editInputRefs`/`filterInputRefs` bags with `null` instead of `{}`, crashing on first keyed write. New e2e coverage pins all three plus the sort-direction indicator. Closes #6115 Closes #5833 Closes #6136 Closes #4939 Closes #4946 Closes #5147 Closes #5832 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nx affected --targets=test:eslint,test:sherif,test:knip,test:lib,test:types,test:build,build --parallel=4
⌘K
Succeeded
nx affected --targets=test:eslint,test:sherif,test:knip,test:lib,test:types,test:build,build --parallel=4
Click to copy
read-write
access token used
2271af67
6501
99%
Cache hits
858 of 869 tasks used cache.
Atomizer enabled
405 groups of tasks optimized.