@rozie-ui/data-table-solid 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rozie-ui/data-table-solid",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "license": "MIT",
@@ -46,7 +46,7 @@
46
46
  ],
47
47
  "dependencies": {
48
48
  "@solid-primitives/keyed": "^1.5.3",
49
- "@rozie/runtime-solid": "0.7.3"
49
+ "@rozie/runtime-solid": "^0.7.4"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "solid-js": "^1.8",
package/src/Column.tsx CHANGED
@@ -26,7 +26,7 @@ interface ColumnProps {
26
26
  */
27
27
  filterable?: boolean;
28
28
  /**
29
- * Pin side: `''` (unpinned) | `'left'` | `'right'`. Reserved metadata carried into the parent's column pinning state.
29
+ * Initial pin side: `''` (unpinned) | `'left'` | `'right'`. Applied once as the table's starting `columnPinning` state, so `getIsPinned()` reports it and the column joins the matching sticky rail — which also reorders it, since visible cells are ordered `[left-pinned, center, right-pinned]`. Ignored if the consumer has already pinned something; an interactive unpin is never re-applied.
30
30
  */
31
31
  pinned?: string;
32
32
  /**
@@ -50,7 +50,7 @@ interface ColumnProps {
50
50
  */
51
51
  editable?: boolean;
52
52
  /**
53
- * Built-in editor type for this column: `'text'` | `'number'` | `'select'` | `'checkbox'`. Ignored when a custom `#editor` scoped slot handles the column. Default `'text'`.
53
+ * Editor type for this column: `'text'` | `'number'` | `'select'` | `'checkbox'` (built-in inputs), or `'custom'` to hand rendering to the `#editor` scoped slot (or a per-column `editor-<columnId>` fill). Default `'text'`. **`'custom'` is the gate:** a column left on a built-in type ignores any `#editor` fill and renders the built-in input. Requires `editable: true` — and, for any pointer or keyboard edit entry, `interactionMode="grid"` on the table.
54
54
  */
55
55
  editor?: string;
56
56
  /**
package/src/DataTable.tsx CHANGED
@@ -35,7 +35,35 @@ import { Virtualizer, elementScroll, observeElementRect, observeElementOffset, m
35
35
  // snapshot (the rete stale-closure anti-pattern — a top-level $computed/useCallback
36
36
  // freezes the table at the empty-initial state on React).
37
37
 
38
- __rozieInjectStyle('DataTable-d5dcab4c', `.rozie-data-table[data-rozie-s-d5dcab4c] {
38
+ __rozieInjectStyle('DataTable-d5dcab4c', `[data-rozie-s-d5dcab4c]:host {
39
+ --rdt-font: var(--rozie-data-table-font);
40
+ --rdt-color: var(--rozie-data-table-fg);
41
+ --rdt-cell-padding: var(--rozie-data-table-cell-padding);
42
+ --rdt-border: 1px solid var(--rozie-data-table-border-color);
43
+ --rdt-header-bg: var(--rozie-data-table-header-bg);
44
+ --rdt-header-weight: var(--rozie-data-table-header-weight);
45
+ --rdt-sort-ind-opacity: var(--rozie-data-table-sort-indicator-opacity);
46
+ --rdt-filter-border: 1px solid var(--rozie-data-table-control-border-color);
47
+ --rdt-filter-radius: var(--rozie-data-table-radius);
48
+ --rdt-page-btn-border: 1px solid var(--rozie-data-table-control-border-color);
49
+ --rdt-page-btn-radius: var(--rozie-data-table-radius);
50
+ --rdt-page-btn-disabled-opacity: var(--rozie-data-table-disabled-opacity);
51
+ --rdt-page-size-border: 1px solid var(--rozie-data-table-control-border-color);
52
+ --rdt-page-size-radius: var(--rozie-data-table-radius);
53
+ --rdt-resize-grip-color: var(--rozie-data-table-resize-grip-color);
54
+ --rdt-resize-grip-active: var(--rozie-data-table-resize-grip-active);
55
+ --rdt-pin-btn-border: 1px solid var(--rozie-data-table-control-border-color);
56
+ --rdt-pin-btn-radius: var(--rozie-data-table-radius);
57
+ --rdt-pin-btn-active-bg: var(--rozie-data-table-pin-active-bg);
58
+ --rdt-colvis-summary-border: 1px solid var(--rozie-data-table-control-border-color);
59
+ --rdt-colvis-summary-radius: var(--rozie-data-table-radius);
60
+ --rdt-colvis-menu-border: 1px solid var(--rozie-data-table-border-color);
61
+ --rdt-colvis-menu-radius: var(--rozie-data-table-radius);
62
+ --rdt-colvis-menu-bg: var(--rozie-data-table-menu-bg);
63
+ --rdt-colvis-menu-shadow: var(--rozie-data-table-menu-shadow);
64
+ --rdt-select-accent: var(--rozie-data-table-select-accent);
65
+ }
66
+ .rozie-data-table[data-rozie-s-d5dcab4c] {
39
67
  border-collapse: collapse;
40
68
  width: 100%;
41
69
  font: var(--rdt-font, 14px system-ui, sans-serif);
@@ -367,7 +395,7 @@ interface EditorSlotCtx { columnId: any; column: any; row: any; value: any; comm
367
395
 
368
396
  interface DataTableProps {
369
397
  /**
370
- * The row data — `model: true`, so a committed cell/row edit writes a **fresh** array back through `r-model:data` (uncontrolled fallback `dataDefault`). A stable reference per Rozie's setup-once model — fed directly into table-core (never map/cloned in the watcher).
398
+ * The row data — `model: true`, so a committed cell/row edit writes a **fresh** array back through the two-way `data` binding (uncontrolled fallback `dataDefault`). A stable reference per Rozie's setup-once model — fed directly into table-core (never map/cloned in the watcher).
371
399
  * @example
372
400
  * <DataTable data={rows()} onDataChange={setRows} columns={cols} />
373
401
  */
@@ -375,7 +403,7 @@ interface DataTableProps {
375
403
  defaultData?: any[];
376
404
  onDataChange?: (data: any[]) => void;
377
405
  /**
378
- * Config-array column fallback (lower precedence than `<Column>` children). Each entry: `{ id?, field, header?, sortable?, filterable?, pinned?, width? }`. Columns may come from this array, from `<Column>` children, or both (id-keyed last-write-wins union).
406
+ * Config-array column fallback (lower precedence than `<Column>` children). Each entry: `{ id?, field, header?, sortable?, filterable?, pinned?, width? }`. Columns may come from this array, from `<Column>` children, or both (id-keyed last-write-wins union). A `pinned` value of `'left'` or `'right'` is applied once as the table's initial `columnPinning` state — identical to `<Column pinned>` — which also REORDERS that column, since table-core orders visible cells `[left-pinned, center, right-pinned]`. A consumer who has already expressed a pin (an initial two-way `columnPinning` model value or an interactive pin) owns the slice and this declaration is ignored.
379
407
  */
380
408
  columns?: any[];
381
409
  /**
@@ -419,7 +447,7 @@ interface DataTableProps {
419
447
  */
420
448
  pageCount?: (number) | null;
421
449
  /**
422
- * Opt-in **expandable rows**. When `true`, a leading chevron expander column auto-injects (after the select column) and `getExpandedRowModel` activates; default `false` is byte-identical-off. Every row can expand to reveal a `#detail` panel unless `getSubRows` is supplied (then only rows with children expand). Bind `:expandable="true"` (a bare attr only coerces on Vue+Lit).
450
+ * Opt-in **expandable rows**. When `true`, a leading chevron expander column auto-injects (after the select column) and `getExpandedRowModel` activates; default `false` is byte-identical-off. Every row can expand to reveal a `#detail` panel unless `getSubRows` is supplied (then only rows with children expand). Pass `expandable` as a real boolean — a valueless attribute only coerces to `true` on Vue and Lit.
423
451
  */
424
452
  expandable?: boolean;
425
453
  /**
@@ -437,7 +465,7 @@ interface DataTableProps {
437
465
  */
438
466
  groupable?: boolean;
439
467
  /**
440
- * `GroupingState` — an ordered `string[]` of column ids (multi-column → nested groups, e.g. `['region','category']`). An empty/unbound list is ungrouped (byte-identical-off). Group-header rows are collapsible (they ride the expand model). Surfaces through `group-change`; uncontrolled fallback (`$data.groupingDefault`, default `[]`) when unbound — the default is `null` (mirroring `expanded`) so the uncontrolled fallback is reachable and the grouping auto-expand default can activate when a consumer applies grouping without binding `r-model:grouping` (a non-null `[]` default would short-circuit it). All reads are null-guarded, so table-core still receives an array.
468
+ * `GroupingState` — an ordered `string[]` of column ids (multi-column → nested groups, e.g. `['region','category']`). An empty/unbound list is ungrouped (byte-identical-off). Group-header rows are collapsible (they ride the expand model). Surfaces through `group-change`; uncontrolled fallback (`$data.groupingDefault`, default `[]`) when unbound — the default is `null` (mirroring `expanded`) so the uncontrolled fallback is reachable and the grouping auto-expand default can activate when a consumer applies grouping without binding the two-way `grouping` model (a non-null `[]` default would short-circuit it). All reads are null-guarded, so table-core still receives an array.
441
469
  */
442
470
  grouping?: (any[]) | null;
443
471
  defaultGrouping?: (any[]) | null;
@@ -477,7 +505,7 @@ interface DataTableProps {
477
505
  */
478
506
  stickyHeader?: boolean;
479
507
  /**
480
- * `'table'` (default, row-oriented, byte-behaviorally identical to a plain accessible table) | `'grid'` (GA since Phase 63) — lights up the full WAI-ARIA **[grid interaction mode](/components/data-table-grid-mode)**: `role="grid"`, a roving single tab-stop, 2-D APG arrow-key cell navigation, range selection, and clipboard support.
508
+ * `'table'` (default, row-oriented, byte-behaviorally identical to a plain accessible table) | `'grid'` — lights up the full WAI-ARIA **[grid interaction mode](/components/data-table-grid-mode)**: `role="grid"`, a roving single tab-stop, 2-D APG arrow-key cell navigation, range selection, and clipboard support.
481
509
  */
482
510
  interactionMode?: string;
483
511
  /**
@@ -653,6 +681,13 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
653
681
  // a one-way `:data`) has a base array to whole-array-replace. currentData() then sources
654
682
  // the bound prop when controlled, this fallback otherwise.
655
683
  setDataDefault(data() || []);
684
+ // Apply any per-column `pinned` declaration as the INITIAL pinning state BEFORE createTable
685
+ // reads currentState() below, so the first row model table-core builds is already correctly
686
+ // ordered (getVisibleCells() returns [left-pinned, center, right-pinned]) rather than
687
+ // re-ordering a render later. Covers the `:columns` config-array form, which is available
688
+ // now; `<Column>` children register during mount and are covered by the re-feed watch's own
689
+ // call. One-shot and self-latching — see seedColumnPinning() in stateAssembly.rzts.
690
+ seedColumnPinning();
656
691
  // Build the table instance HERE so the closures below capture the live `table`.
657
692
  table = createTable({
658
693
  // Plain value (NOT a `get data()` getter): an object-literal getter rebinds
@@ -928,6 +963,31 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
928
963
  if (!w) {
929
964
  console.warn('[rozie-data-table] virtual is on for columns but the scroll container has no bounded width; set a CSS width on an ancestor so the column window can be measured');
930
965
  }
966
+ // COLUMN-AXIS FIRST-WINDOW BUMP (quick 260908-vcy). The mount-kick above fires right
967
+ // after `new Virtualizer(...)` — BEFORE colVirtualizer has measured, and before the
968
+ // spacer effects even exist. Any fine-grained subscriber created inside that measure
969
+ // gap takes colPadLeft()/colPadRight()'s `if (!items.length) return 0` early return,
970
+ // which reads ONLY windowVer + editVer and never reaches the live path's reads
971
+ // (forcedColumns()/columnSize()/column state). Its dependency set is therefore those
972
+ // two counters alone — and without this bump nothing ever touches them again, so the
973
+ // subscriber stays frozen at 0 for the lifetime of the component. Measured on Svelte:
974
+ // the FIRST header row's trailing spacer froze at 0px while its siblings (created
975
+ // after measurement, on the live path) tracked correctly; under table-layout:fixed the
976
+ // first row alone establishes column widths, so that one cell collapsed the whole
977
+ // table's scrollWidth from 9000 to 1350. The five other targets re-render wholesale
978
+ // (Solid re-creates these rows), which masked it.
979
+ //
980
+ // The ROW axis has always been safe here only by accident: remeasureWindow() above
981
+ // already routes through bumpWindowVer() on this same post-first-frame callback. This
982
+ // is the column axis's missing equivalent — not a Svelte workaround (the emitted
983
+ // Svelte binding is a correct reactive template_effect; the dependency set is what was
984
+ // wrong), so it is fixed once, in the shared engine's consumer, for all six targets.
985
+ //
986
+ // Routed through bumpWindowVer() rather than a raw `$data.windowVer = $data.windowVer + 1`
987
+ // to keep 87-10's microtask coalescing AND to avoid manufacturing the ROZ138
988
+ // false positive that a second in-body counter self-read would trip (see the
989
+ // mount-kick's own comment above).
990
+ bumpWindowVer();
931
991
  }
932
992
  };
933
993
  if (typeof requestAnimationFrame === 'function') requestAnimationFrame(() => requestAnimationFrame(afterFirstFrame));else setTimeout(afterFirstFrame, 0);
@@ -962,8 +1022,8 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
962
1022
  maybeClearHistoryOnExternalSwap();
963
1023
  if (!table) return;
964
1024
  // Phase 51 req-4: track currentData() (the bound prop OR the uncontrolled
965
- // $data.dataDefault) so a committed edit re-feeds on Lit whether or not r-model:data is
966
- // bound. Compare by reference AND length so a same-length single-cell edit (fresh array,
1025
+ // $data.dataDefault) so a committed edit re-feeds on Lit whether or not the two-way
1026
+ // `data` model is bound. Compare by reference AND length so a same-length single-cell edit (fresh array,
967
1027
  // identical length) still re-feeds.
968
1028
  const d = currentData() || [];
969
1029
  if (d === lastData && d.length === lastDataLen) return;
@@ -987,6 +1047,12 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
987
1047
  // (Consumers memoize the array as with $props.data/$props.sorting; the uncontrolled
988
1048
  // <Column>-children path leaves $props.columns undefined — a stable no-op getter.)
989
1049
  local.columns, colReg()])(), (v) => untrack(() => (() => {
1050
+ // Seed BEFORE the re-feed so the pinning this call may write is part of the state object
1051
+ // table-core receives on this same tick (rather than landing a frame late and re-ordering
1052
+ // getVisibleCells() a render after the columns appear). One-shot and self-latching — see
1053
+ // seedColumnPinning() in stateAssembly.rzts. This is the `<Column>`-children entry point:
1054
+ // those register during mount, so the $onMount call below can find zero columns.
1055
+ seedColumnPinning();
990
1056
  reFeed();
991
1057
  maybeClearHistoryOnExternalSwap();
992
1058
  })()), { defer: true }));
@@ -1149,6 +1215,95 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
1149
1215
  };
1150
1216
  }
1151
1217
 
1218
+ // seedColumnPinning(): apply the per-column `pinned` declaration ('left' | 'right') — from the
1219
+ // `:columns` config array or a `<Column pinned="...">` child — as the INITIAL columnPinning
1220
+ // state, exactly once.
1221
+ //
1222
+ // Until now that field was carried onto every ColumnDef by columnBuilders.rzts and then read by
1223
+ // nobody: `column.getIsPinned()` returned false for a column declared `pinned="left"`, so the
1224
+ // documented per-column API was inert while `r-model:columnPinning` was the only mechanism that
1225
+ // actually pinned anything.
1226
+ //
1227
+ // Three invariants, each load-bearing:
1228
+ // 1. ONE-SHOT, LATCHED ON THE OUTCOME — never merely on "we ran". The latch flips only when
1229
+ // a seed is actually applied, or when a consumer pin is observed; a call that finds no
1230
+ // declared pins leaves it DOWN and will look again on the next re-feed. Latching on the
1231
+ // first call that saw any column at all was wrong, and Lit proved it: `<Column>` children
1232
+ // register INCREMENTALLY there, one re-feed per child, so the first call sees only
1233
+ // `name` — no pins declared yet — and a run-once latch would disable the seed
1234
+ // permanently before `amount pinned="right"` ever registered. The other five targets
1235
+ // batch all children into a single flush, which hid the race entirely. Once a seed HAS
1236
+ // been applied the latch holds, so a subsequent interactive UNPIN is never re-seeded —
1237
+ // which is the whole reason this is not folded into effectiveColumnPinning().
1238
+ // 2. ONLY WHEN NOTHING IS PINNED YET. Note this is NOT an `$props.columnPinning == null`
1239
+ // check: the prop carries `default: () => ({ left: [], right: [] })`, so it is never null
1240
+ // and a bound-vs-unbound test is impossible here. The meaningful question is whether the
1241
+ // consumer has actually expressed a pin — if they have, they own the slice and the
1242
+ // per-column declaration must not fight it; if the state is empty, `pinned` IS the
1243
+ // initial state and applying it is the whole point.
1244
+ // 3. NO CHROME IDS. The select/expander rail is injected by effectiveColumnPinning() on read
1245
+ // and stripped by writeColumnPinning() on write; the persisted state must never contain
1246
+ // them. Seeding only real column ids keeps that discipline.
1247
+ //
1248
+ // Writes BOTH the uncontrolled holder and `$model.columnPinning` so a consumer with a two-way
1249
+ // binding sees the pinning that is actually in effect rather than a stale empty object — but
1250
+ // does NOT emit `pin-change`: this is initial state derived from the consumer's own markup, not
1251
+ // a user action, and firing a change event for it on mount would be noise.
1252
+ //
1253
+ // Called from $onMount (covers the `:columns` config-array form, known at mount) AND from the
1254
+ // re-feed watch (covers `<Column>` children, which register during mount, and a runtime
1255
+ // `:columns` swap that arrives before any pin interaction). The `!defs.length` bail is what
1256
+ // makes the mount call harmless when columns are not known yet — the latch stays down and the
1257
+ // next re-feed seeds instead.
1258
+ let pinSeedApplied = false;
1259
+ function seedColumnPinning(): void {
1260
+ if (pinSeedApplied) return;
1261
+ // Invariant 2: bail if the consumer already pinned something (either an initial bound value
1262
+ // or an interaction that beat us here). Read the same source order effectiveColumnPinning()
1263
+ // does, minus the chrome rail it injects on read — the rail is structural, not a consumer pin.
1264
+ const live = columnPinning() != null ? columnPinning() : columnPinningDefault();
1265
+ const isRealPin = (id: string) => id !== SELECT_COL_ID && id !== EXPANDER_COL_ID;
1266
+ const pinnedAlready = (live && live.left ? live.left : []).filter(isRealPin).length > 0 || (live && live.right ? live.right : []).filter(isRealPin).length > 0;
1267
+ if (pinnedAlready) {
1268
+ pinSeedApplied = true;
1269
+ return;
1270
+ }
1271
+ const defs = columnDefs();
1272
+ if (!defs.length) return;
1273
+ const left: string[] = [];
1274
+ const right: string[] = [];
1275
+ for (let i = 0; i < defs.length; i++) {
1276
+ const def = defs[i];
1277
+ if (!def) continue;
1278
+ if (def.pinned === 'left') left.push(def.id);else if (def.pinned === 'right') right.push(def.id);
1279
+ }
1280
+ // Invariant 1: no declared pins in the column set we can currently SEE is not evidence there
1281
+ // are none — on Lit the set is still filling in. Leave the latch down and try again on the
1282
+ // next re-feed; the only exits are "seeded" (below) and "consumer already pinned" (above).
1283
+ if (!left.length && !right.length) return;
1284
+ pinSeedApplied = true;
1285
+ // Nothing was pinned (invariant 2 above), so this is a plain assignment, not a merge — the
1286
+ // only ids that could be in `live` are the structural chrome rail, which must never be
1287
+ // persisted (invariant 3). Writes the uncontrolled holder AND the two-way model so both
1288
+ // binding modes observe the pinning that is actually in effect; deliberately does NOT route
1289
+ // through writeColumnPinning(), whose job is to emit `pin-change` for real user actions.
1290
+ // Annotated `any` for the same reason currentState() is (see its comment below): the
1291
+ // uncontrolled holder's initial value is the empty literal `{ left: [], right: [] }`, so the
1292
+ // emitted per-target state holder infers `{ left: never[]; right: never[] }` and a genuinely
1293
+ // populated `{ left: string[]; right: string[] }` will not assign to it under the strict
1294
+ // bundled-leaf tsc (react TS2345 on setColumnPinningDefault, solid TS2769, lit TS2322 — one
1295
+ // per target, all the same never[] inference). The runtime shape is correct; this is the
1296
+ // established idiom here rather than widening three per-leaf strict baselines for it.
1297
+ // writeColumnPinning() never hits this because its payload flows through `strip()`, which
1298
+ // returns `any[]`.
1299
+ const seeded: any = {
1300
+ left,
1301
+ right
1302
+ };
1303
+ setColumnPinningDefault(seeded);
1304
+ setColumnPinning(seeded);
1305
+ }
1306
+
1152
1307
  // Assemble the live state object from bound r-model slices (?? uncontrolled fallback).
1153
1308
  // All NINE slices are wired (each ?? its own $data.<slice>Default). table-core reads
1154
1309
  // this whole object as `state`. Return type annotated `any`: the inferred object-literal
@@ -1826,9 +1981,42 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
1826
1981
  function onColumnPinningChangeCb(updater: any) {
1827
1982
  writeColumnPinning(applyUpdater(updater, currentState().columnPinning));
1828
1983
  }
1984
+ // columnSizingInfo is the ONLY slice table-core drives as a rapid, multi-call gesture: a resize
1985
+ // drag fires this updater once on pointerdown (seeding startOffset/startSize/isResizingColumn)
1986
+ // and then again on EVERY mousemove, each call reading the values the previous one wrote.
1987
+ //
1988
+ // That read-your-own-last-write requirement is what makes a plain `$data` read wrong here on
1989
+ // React. These callbacks are handed to createTable in $onMount, so on React the closure binds a
1990
+ // MOUNT-TIME `$data.columnSizingInfo` and never sees its own writes. Measured on the shipped
1991
+ // leaf (quick 260909, instrumented build): pointerdown correctly wrote
1992
+ // `{ startOffset: 163, isResizingColumn: 'col0' }`, and then every single mousemove still saw
1993
+ // `startOffset: null, isResizingColumn: false` — so it computed deltaOffset from 0 instead of
1994
+ // 163 (179, 195, 211… instead of 16, 32, 48…) AND wrote `isResizingColumn: false` back, wiping
1995
+ // the gesture on the first move. Net effect: column resizing did nothing at all on React while
1996
+ // working on the other five. It was masked because the one VR case that drives a real drag was
1997
+ // `test.fixme`'d on React as a presumed harness limitation (87-05 Task 3) — a real CDP drag
1998
+ // with intermediate steps fails there too, which is what proved it a product bug.
1999
+ //
2000
+ // Why not just read `currentState().columnSizingInfo` like the eleven siblings above: that
2001
+ // idiom relies on the re-feed $watch re-passing fresh callbacks into setOptions, and that watch
2002
+ // fires on data/column changes — NOT on every render, and never mid-gesture. It is sufficient
2003
+ // for one-shot updaters (a sort toggle, a selection click) and insufficient here, where
2004
+ // table-core issues a burst of updaters between any two re-feeds.
2005
+ //
2006
+ // Fix: a synchronous module-scope mirror, written on the same tick as the state. Reads prefer
2007
+ // the mirror, so each updater in a gesture composes on the previous one's result regardless of
2008
+ // when the host framework commits. Behaviourally identical on the five targets whose state read
2009
+ // was already synchronous (mirror and state agree), and the slice is transient gesture state
2010
+ // owned entirely by table-core — nothing else writes it — so the mirror cannot drift.
2011
+ // Same trick as the `committedThisSession` commit latch (editCellLifecycle.rzts), for the same
2012
+ // reason: a sync latch survives React's async window.
2013
+ let columnSizingInfoSync: any = null;
1829
2014
  function onColumnSizingInfoChangeCb(updater: any) {
1830
- const next = applyUpdater(updater, columnSizingInfo());
1831
- setColumnSizingInfo(next != null ? next : columnSizingInfo());
2015
+ const base = columnSizingInfoSync != null ? columnSizingInfoSync : columnSizingInfo();
2016
+ const next = applyUpdater(updater, base);
2017
+ if (next == null) return;
2018
+ columnSizingInfoSync = next;
2019
+ setColumnSizingInfo(next);
1832
2020
  }
1833
2021
 
1834
2022
  // ══ Vertical row windowing (phase 53, req-1/2/3/6/9/10) — the virtual-core bridge ════════
@@ -6258,6 +6446,21 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
6258
6446
  const tryFocus = () => {
6259
6447
  const el = resolveCellEl(String(row), col);
6260
6448
  if (el) {
6449
+ // B-05 / F-07: do NOT stomp focus a later interaction has already placed on a DIFFERENT
6450
+ // grid cell. This poll runs up to 30 frames after commit/cancel, so without this guard a
6451
+ // user (or a test) who moves to the next cell in that window gets yanked BACK to the cell
6452
+ // they just left — and because the steal depends on rAF timing it presents as a flake that
6453
+ // rotates across targets rather than as a reproducible bug. Measured 2026-09-12: the
6454
+ // data-table-dropins editor case failed with the active cell pinned to the PREVIOUS column
6455
+ // (want 0/2, active 0/1; want 0/1, active 0/0) with no editor open.
6456
+ // focusEditorWhenReady already carries the equivalent guard against the same class of
6457
+ // theft; this is its missing twin. Compare the OWNING CELL (not node identity) so a
6458
+ // node-replacing re-render on Solid still resolves a genuinely dropped focus as recoverable.
6459
+ const ae = gridRoot && gridRoot.getRootNode ? gridRoot.getRootNode().activeElement : null;
6460
+ if (ae && ae !== el && gridRoot.contains && gridRoot.contains(ae) && ae.closest) {
6461
+ const aeCell = ae.closest('[data-grid-cell]');
6462
+ if (aeCell && aeCell !== el) return;
6463
+ }
6261
6464
  el.focus();
6262
6465
  return;
6263
6466
  }
@@ -7392,7 +7595,7 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7392
7595
 
7393
7596
 
7394
7597
  {<Show when={local.groupable}><div class={"rdt-group-bar-host"} data-rozie-s-d5dcab4c="">
7395
- {(_props.groupBarSlot ?? _props.slots?.['groupBar'])?.({ grouping: groupingKeys(), groupableColumns: groupableColumns(), applyGrouping, clearGrouping }) ?? <Key each={groupingKeys() as readonly any[]} by={(gk) => gk}>{(gk) => <span class={"rdt-group-token"} data-group-token="" data-rozie-s-d5dcab4c="">{rozieDisplay(gk())}</span>}</Key>}
7598
+ {(_props.groupBarSlot ?? _props.slots?.['groupBar'])?.({ get grouping() { return groupingKeys(); }, get groupableColumns() { return groupableColumns(); }, applyGrouping, clearGrouping }) ?? <Key each={groupingKeys() as readonly any[]} by={(gk) => gk}>{(gk) => <span class={"rdt-group-token"} data-group-token="" data-rozie-s-d5dcab4c="">{rozieDisplay(gk())}</span>}</Key>}
7396
7599
  </div></Show>}{<Show when={isWindowed()} fallback={<table aria-rowcount={rozieAttr(gridAriaRowCount())} class={"rozie-data-table" + " " + rozieClass({ 'rdt-sticky': local.stickyHeader })} role={rozieAttr(tableRole())} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLTableElement; target: Element }) => { onGridKeyDown($event); }} onFocusIn={($event: FocusEvent & { currentTarget: HTMLTableElement; target: Element }) => { syncActiveFromEvent($event); }} onFocusOut={($event: FocusEvent & { currentTarget: HTMLTableElement; target: Element }) => { onGridFocusOut($event); }} onMouseDown={($event: MouseEvent & { currentTarget: HTMLTableElement; target: Element }) => { onGridMouseDown($event); }} onDblClick={($event: MouseEvent & { currentTarget: HTMLTableElement; target: Element }) => { onGridDblClick($event); }} onClick={($event: MouseEvent & { currentTarget: HTMLTableElement; target: Element }) => { onGridClick($event); }} data-rozie-s-d5dcab4c="">
7397
7600
  <thead class={"rdt-thead"} role="rowgroup" data-rozie-s-d5dcab4c="">
7398
7601
  <Key each={headerGroups() as readonly any[]} by={(hg) => hg.id}>{(hg, hgLevel) => <tr class={"rdt-tr"} role="row" aria-rowindex={rozieAttr(hgLevel() + 1)} data-rozie-s-d5dcab4c="">
@@ -7403,12 +7606,12 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7403
7606
 
7404
7607
  {<Show when={header().column.getCanSort && header().column.getCanSort()} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7405
7608
  <span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
7406
- {_props.slots?.[`colHeader-${header().column.id}`]?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? rozieDisplay(headerLabel(header().column.id))}
7609
+ {_props.slots?.[`colHeader-${header().column.id}`]?.({ get columnId() { return header().column.id; }, get column() { return header().column; }, get label() { return headerLabel(header().column.id); } }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ get columnId() { return header().column.id; }, get column() { return header().column; }, get label() { return headerLabel(header().column.id); } }) ?? rozieDisplay(headerLabel(header().column.id))}
7407
7610
  </span>
7408
7611
  </span>}><button type="button" class={"rdt-sort-btn"} onClick={($event: MouseEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onHeaderSort(header().column.id, $event); }} data-rozie-s-d5dcab4c="">
7409
7612
 
7410
7613
  <span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
7411
- {_props.slots?.[`colHeader-${header().column.id}`]?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? rozieDisplay(headerLabel(header().column.id))}
7614
+ {_props.slots?.[`colHeader-${header().column.id}`]?.({ get columnId() { return header().column.id; }, get column() { return header().column; }, get label() { return headerLabel(header().column.id); } }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ get columnId() { return header().column.id; }, get column() { return header().column; }, get label() { return headerLabel(header().column.id); } }) ?? rozieDisplay(headerLabel(header().column.id))}
7412
7615
  </span>
7413
7616
  <span class={"rdt-sort-ind"} aria-hidden="true" data-rozie-s-d5dcab4c="">{rozieDisplay(sortIndicator(header().column.id))}</span>
7414
7617
  </button></Show>}<Popover trigger="click" placement="bottom-end" strategy="fixed" offset={4} data-rozie-s-d5dcab4c="" anchorSlot={() => (<>
@@ -7423,7 +7626,7 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7423
7626
 
7424
7627
  <button type="button" aria-label={rozieAttr('Resize ' + headerLabel(header().column.id))} class={"rdt-resize-handle"} onPointerDown={($event: PointerEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onResizeStart(header().column.id, $event); }} onTouchStart={($event: TouchEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onResizeStart(header().column.id, $event); }} data-rozie-s-d5dcab4c=""><span class={"rdt-resize-grip"} aria-hidden="true" data-rozie-s-d5dcab4c="" /></button>
7425
7628
  </span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7426
- {(_props.selectAllSlot ?? _props.slots?.['selectAll'])?.({ checked: isAllRowsSelected(), indeterminate: isSomeRowsSelected(), toggle: onToggleAllRows }) ?? <Show when={local.selectionMode === 'multiple'}><input type="checkbox" aria-label="Select all rows" class={"rdt-select-all"} checked={isAllRowsSelected()} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleAllRows($event); }} data-rozie-s-d5dcab4c="" /></Show>}
7629
+ {(_props.selectAllSlot ?? _props.slots?.['selectAll'])?.({ get checked() { return isAllRowsSelected(); }, get indeterminate() { return isSomeRowsSelected(); }, get toggle() { return onToggleAllRows; } }) ?? <Show when={local.selectionMode === 'multiple'}><input type="checkbox" aria-label="Select all rows" class={"rdt-select-all"} checked={isAllRowsSelected()} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleAllRows($event); }} data-rozie-s-d5dcab4c="" /></Show>}
7427
7630
  </span></Show>}</th>}</Key>
7428
7631
  </tr>}</Key>
7429
7632
 
@@ -7431,7 +7634,7 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7431
7634
  <Key each={headerGroups()[headerGroups().length - 1].headers as readonly any[]} by={(header) => header.id}>{(header) => <th class={"rdt-filter-cell"} role="presentation" style={parseInlineStyle(pinStyle(header().column.id))} data-rozie-s-d5dcab4c="">
7432
7635
  {<Show when={isSelectColumn(header().column.id)} fallback={<Show when={isExpanderColumn(header().column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7433
7636
  {<Show when={columnIsFilterable(header().column.id)}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7434
- {_props.slots?.[`filter-${header().column.id}`]?.({ columnId: header().column.id, value: columnFilterValue(header().column.id), uniqueValues: getFacetedUniqueValues(header().column.id), minMax: getFacetedMinMaxValues(header().column.id), setFilter: setColumnFilter }) ?? (_props.filterSlot ?? _props.slots?.['filter'])?.({ columnId: header().column.id, value: columnFilterValue(header().column.id), uniqueValues: getFacetedUniqueValues(header().column.id), minMax: getFacetedMinMaxValues(header().column.id), setFilter: setColumnFilter }) ?? <input type="text" aria-label={rozieAttr('Filter ' + headerLabel(header().column.id))} class={"rdt-col-filter"} value={columnFilterValue(header().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onColumnFilterInput(header().column.id, $event); }} onClick={($event: MouseEvent & { currentTarget: HTMLInputElement; target: Element }) => { stopEvent($event); }} data-rozie-s-d5dcab4c="" />}
7637
+ {_props.slots?.[`filter-${header().column.id}`]?.({ get columnId() { return header().column.id; }, get value() { return columnFilterValue(header().column.id); }, get uniqueValues() { return getFacetedUniqueValues(header().column.id); }, get minMax() { return getFacetedMinMaxValues(header().column.id); }, get setFilter() { return setColumnFilter; } }) ?? (_props.filterSlot ?? _props.slots?.['filter'])?.({ get columnId() { return header().column.id; }, get value() { return columnFilterValue(header().column.id); }, get uniqueValues() { return getFacetedUniqueValues(header().column.id); }, get minMax() { return getFacetedMinMaxValues(header().column.id); }, get setFilter() { return setColumnFilter; } }) ?? <input type="text" aria-label={rozieAttr('Filter ' + headerLabel(header().column.id))} class={"rdt-col-filter"} value={columnFilterValue(header().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onColumnFilterInput(header().column.id, $event); }} onClick={($event: MouseEvent & { currentTarget: HTMLInputElement; target: Element }) => { stopEvent($event); }} data-rozie-s-d5dcab4c="" />}
7435
7638
  </span></Show>}</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}</th>}</Key>
7436
7639
  </tr></Show>}</thead>
7437
7640
 
@@ -7442,27 +7645,27 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7442
7645
  <Key each={visibleCellsFor(row()) as readonly any[]} by={(cell) => cell.id}>{(cell) => <td class={"rdt-td" + " " + rozieClass({ 'rdt-select-td': isSelectColumn(cell().column.id), 'rdt-expander-td': isExpanderColumn(cell().column.id), 'rdt-in-range': inRange(rowIndexOf(row()), colIndexOf(row(), cell())), 'rdt-cell-active': isActiveCell(String(rowIndexOf(row())), colIndexOf(row(), cell())) })} role={rozieAttr(cellRole())} data-col={rozieAttr(cell().column.id)} data-grid-cell="" data-row={rozieAttr(rowIndexOf(row()))} data-col-index={rozieAttr(colIndexOf(row(), cell()))} tabIndex={rozieAttr(cellTabindex(String(rowIndexOf(row())), colIndexOf(row(), cell())))} style={parseInlineStyle(bodyCellStyle(row(), cell().column.id))} aria-invalid={rozieAttr(cellAriaInvalid(rowIndexOf(row()), colIndexOf(row(), cell())))} data-in-range={rozieAttr(inRange(rowIndexOf(row()), colIndexOf(row(), cell())) ? 'true' : null)} data-agg-cell={rozieAttr(cellIsAggregated(cell()) ? cell().column.id : null)} data-rozie-s-d5dcab4c="">
7443
7646
 
7444
7647
  {<Show when={isExpanderColumn(cell().column.id)} fallback={<Show when={isSelectColumn(cell().column.id)} fallback={<Show when={cellIsGrouped(cell())} fallback={<Show when={isEditing(rowIndexOf(row()), colIndexOf(row(), cell()))} fallback={<Show when={cellIsPlaceholder(cell())} fallback={<span class={"rdt-cell-value"} data-rozie-s-d5dcab4c="">
7445
- {_props.slots?.[`cell-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: cell().getValue() }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: cell().getValue() }) ?? rozieDisplay(cell().getValue())}
7648
+ {_props.slots?.[`cell-${cell().column.id}`]?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(row()); }, get value() { return cell().getValue(); } }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(row()); }, get value() { return cell().getValue(); } }) ?? rozieDisplay(cell().getValue())}
7446
7649
  </span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7447
7650
  {<Show when={editorTypeOf(cell().column.id) === 'number'} fallback={<Show when={editorTypeOf(cell().column.id) === 'select'} fallback={<Show when={editorTypeOf(cell().column.id) === 'checkbox'} fallback={<Show when={editorTypeOf(cell().column.id) === 'custom'} fallback={<input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7448
- {_props.slots?.[`editor-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, rowIndexOf(row())) }) ?? (_props.editorSlot ?? _props.slots?.['editor'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, rowIndexOf(row())) }) ?? <input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}
7651
+ {_props.slots?.[`editor-${cell().column.id}`]?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(row()); }, get value() { return editorValueFor(cell().column.id); }, get commit() { return editorCommitFor(cell().column.id); }, get cancel() { return editorCancelFor(); }, get autofocus() { return editorAutofocusFor(cell().column.id, rowIndexOf(row())); } }) ?? (_props.editorSlot ?? _props.slots?.['editor'])?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(row()); }, get value() { return editorValueFor(cell().column.id); }, get commit() { return editorCommitFor(cell().column.id); }, get cancel() { return editorCancelFor(); }, get autofocus() { return editorAutofocusFor(cell().column.id, rowIndexOf(row())); } }) ?? <input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}
7449
7652
  </span></Show>}><input type="checkbox" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} checked={editorCheckedFor(cell().column.id)} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorCheckbox(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" /></Show>}><select data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onChange={($event: Event & { currentTarget: HTMLSelectElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLSelectElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLSelectElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="">
7450
7653
  <Key each={editorOptionsOf(cell().column.id) as readonly any[]} by={(opt) => opt.value}>{(opt) => <option value={rozieAttr(opt().value)} data-rozie-s-d5dcab4c="">{rozieDisplay(opt().label)}</option>}</Key>
7451
7654
  </select></Show>}><input type="number" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" /></Show>}</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7452
7655
  <button type="button" data-expander="" aria-expanded={!!rowIsExpanded(row())} aria-label={rozieAttr(rowIsExpanded(row()) ? 'Collapse group' : 'Expand group')} class={"rdt-expander rdt-group-toggle"} onClick={($event: MouseEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onToggleExpand(row(), $event); }} data-rozie-s-d5dcab4c="">{rozieDisplay(rowIsExpanded(row()) ? '▾' : '▸')}</button>
7453
7656
  <span class={"rdt-group-value"} data-rozie-s-d5dcab4c="">
7454
- {_props.slots?.[`cell-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: cell().getValue() }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: cell().getValue() }) ?? rozieDisplay(cell().getValue())}
7657
+ {_props.slots?.[`cell-${cell().column.id}`]?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(row()); }, get value() { return cell().getValue(); } }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(row()); }, get value() { return cell().getValue(); } }) ?? rozieDisplay(cell().getValue())}
7455
7658
  </span>
7456
7659
  <span class={"rdt-group-count"} data-rozie-s-d5dcab4c="">{rozieDisplay('(' + groupSubRowCount(row()) + ')')}</span>
7457
7660
  </span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7458
- {(_props.selectCellSlot ?? _props.slots?.['selectCell'])?.({ row: cellSlotRow(row()), checked: rowIsSelected(row()), toggle: e => onToggleRow(row(), e) }) ?? <input type="checkbox" aria-label="Select row" class={"rdt-select-row"} checked={rowIsSelected(row())} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleRow(row(), $event); }} data-rozie-s-d5dcab4c="" />}
7661
+ {(_props.selectCellSlot ?? _props.slots?.['selectCell'])?.({ get row() { return cellSlotRow(row()); }, get checked() { return rowIsSelected(row()); }, toggle: e => onToggleRow(row(), e) }) ?? <input type="checkbox" aria-label="Select row" class={"rdt-select-row"} checked={rowIsSelected(row())} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleRow(row(), $event); }} data-rozie-s-d5dcab4c="" />}
7459
7662
  </span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7460
7663
  {<Show when={rowCanExpand(row())}><button type="button" data-expander="" aria-expanded={!!rowIsExpanded(row())} aria-label={rozieAttr(rowIsExpanded(row()) ? 'Collapse row' : 'Expand row')} class={"rdt-expander"} onClick={($event: MouseEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onToggleExpand(row(), $event); }} data-rozie-s-d5dcab4c="">{rozieDisplay(rowIsExpanded(row()) ? '▾' : '▸')}</button></Show>}</span></Show>}{<Show when={isFillHandleCell(rowIndexOf(row()), colIndexOf(row(), cell()))}><span data-fill-handle="" data-testid="fill-handle" aria-hidden="true" class={"rdt-fill-handle"} onPointerDown={($event: PointerEvent & { currentTarget: HTMLSpanElement; target: Element }) => { onFillHandlePointerDown($event); }} data-rozie-s-d5dcab4c="" /></Show>}</td>}</Key>
7461
7664
  </tr>
7462
7665
 
7463
7666
  {<Show when={rowShowsDetail(row())}><tr class={"rdt-detail-row"} role="row" data-detail-row={rozieAttr(row().id)} data-rozie-s-d5dcab4c="">
7464
7667
  <td class={"rdt-detail-cell"} colSpan={rozieAttr(visibleColCount())} data-rozie-s-d5dcab4c="">
7465
- {(_props.detailSlot ?? _props.slots?.['detail'])?.({ row: row().original })}
7668
+ {(_props.detailSlot ?? _props.slots?.['detail'])?.({ get row() { return row().original; } })}
7466
7669
  </td>
7467
7670
  </tr></Show>}</>}</Key>
7468
7671
  </tbody>
@@ -7475,11 +7678,11 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7475
7678
  {<Show when={isSelectColumn(wh().header.column.id)} fallback={<Show when={isExpanderColumn(wh().header.column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7476
7679
  {<Show when={wh().header.column.getCanSort && wh().header.column.getCanSort()} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7477
7680
  <span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
7478
- {_props.slots?.[`colHeader-${wh().header.column.id}`]?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
7681
+ {_props.slots?.[`colHeader-${wh().header.column.id}`]?.({ get columnId() { return wh().header.column.id; }, get column() { return wh().header.column; }, get label() { return headerLabel(wh().header.column.id); } }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ get columnId() { return wh().header.column.id; }, get column() { return wh().header.column; }, get label() { return headerLabel(wh().header.column.id); } }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
7479
7682
  </span>
7480
7683
  </span>}><button type="button" class={"rdt-sort-btn"} onClick={($event: MouseEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onHeaderSort(wh().header.column.id, $event); }} data-rozie-s-d5dcab4c="">
7481
7684
  <span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
7482
- {_props.slots?.[`colHeader-${wh().header.column.id}`]?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
7685
+ {_props.slots?.[`colHeader-${wh().header.column.id}`]?.({ get columnId() { return wh().header.column.id; }, get column() { return wh().header.column; }, get label() { return headerLabel(wh().header.column.id); } }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ get columnId() { return wh().header.column.id; }, get column() { return wh().header.column; }, get label() { return headerLabel(wh().header.column.id); } }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
7483
7686
  </span>
7484
7687
  <span class={"rdt-sort-ind"} aria-hidden="true" data-rozie-s-d5dcab4c="">{rozieDisplay(sortIndicator(wh().header.column.id))}</span>
7485
7688
  </button></Show>}<Popover trigger="click" placement="bottom-end" strategy="fixed" offset={4} data-rozie-s-d5dcab4c="" anchorSlot={() => (<>
@@ -7493,7 +7696,7 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7493
7696
  </div></Popover>
7494
7697
  <button type="button" aria-label={rozieAttr('Resize ' + headerLabel(wh().header.column.id))} class={"rdt-resize-handle"} onPointerDown={($event: PointerEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onResizeStart(wh().header.column.id, $event); }} onTouchStart={($event: TouchEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onResizeStart(wh().header.column.id, $event); }} data-rozie-s-d5dcab4c=""><span class={"rdt-resize-grip"} aria-hidden="true" data-rozie-s-d5dcab4c="" /></button>
7495
7698
  </span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7496
- {(_props.selectAllSlot ?? _props.slots?.['selectAll'])?.({ checked: isAllRowsSelected(), indeterminate: isSomeRowsSelected(), toggle: onToggleAllRows }) ?? <Show when={local.selectionMode === 'multiple'}><input type="checkbox" aria-label="Select all rows" class={"rdt-select-all"} checked={isAllRowsSelected()} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleAllRows($event); }} data-rozie-s-d5dcab4c="" /></Show>}
7699
+ {(_props.selectAllSlot ?? _props.slots?.['selectAll'])?.({ get checked() { return isAllRowsSelected(); }, get indeterminate() { return isSomeRowsSelected(); }, get toggle() { return onToggleAllRows; } }) ?? <Show when={local.selectionMode === 'multiple'}><input type="checkbox" aria-label="Select all rows" class={"rdt-select-all"} checked={isAllRowsSelected()} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleAllRows($event); }} data-rozie-s-d5dcab4c="" /></Show>}
7497
7700
  </span></Show>}</th>}</Key>
7498
7701
 
7499
7702
  {<Show when={colsWindowed()}><th class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle('width:' + colPadRight() + 'px;padding:0;border:0')} data-rozie-s-d5dcab4c="" /></Show>}</tr>}</Key>
@@ -7502,7 +7705,7 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7502
7705
  {<Show when={colsWindowed()}><th class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle('width:' + colPadLeft() + 'px;padding:0;border:0')} data-rozie-s-d5dcab4c="" /></Show>}<Key each={windowedHeadersFor(headerGroups()[headerGroups().length - 1], headerGroups().length - 1) as readonly any[]} by={(wh) => wh.header.id}>{(wh) => <th class={"rdt-filter-cell"} role="presentation" data-col={rozieAttr(wh().header.column.id)} style={parseInlineStyle(pinStyle(wh().header.column.id))} data-rozie-s-d5dcab4c="">
7503
7706
  {<Show when={isSelectColumn(wh().header.column.id)} fallback={<Show when={isExpanderColumn(wh().header.column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7504
7707
  {<Show when={columnIsFilterable(wh().header.column.id)}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7505
- {_props.slots?.[`filter-${wh().header.column.id}`]?.({ columnId: wh().header.column.id, value: columnFilterValue(wh().header.column.id), uniqueValues: getFacetedUniqueValues(wh().header.column.id), minMax: getFacetedMinMaxValues(wh().header.column.id), setFilter: setColumnFilter }) ?? (_props.filterSlot ?? _props.slots?.['filter'])?.({ columnId: wh().header.column.id, value: columnFilterValue(wh().header.column.id), uniqueValues: getFacetedUniqueValues(wh().header.column.id), minMax: getFacetedMinMaxValues(wh().header.column.id), setFilter: setColumnFilter }) ?? <input type="text" aria-label={rozieAttr('Filter ' + headerLabel(wh().header.column.id))} class={"rdt-col-filter"} value={columnFilterValue(wh().header.column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onColumnFilterInput(wh().header.column.id, $event); }} onClick={($event: MouseEvent & { currentTarget: HTMLInputElement; target: Element }) => { stopEvent($event); }} data-rozie-s-d5dcab4c="" />}
7708
+ {_props.slots?.[`filter-${wh().header.column.id}`]?.({ get columnId() { return wh().header.column.id; }, get value() { return columnFilterValue(wh().header.column.id); }, get uniqueValues() { return getFacetedUniqueValues(wh().header.column.id); }, get minMax() { return getFacetedMinMaxValues(wh().header.column.id); }, get setFilter() { return setColumnFilter; } }) ?? (_props.filterSlot ?? _props.slots?.['filter'])?.({ get columnId() { return wh().header.column.id; }, get value() { return columnFilterValue(wh().header.column.id); }, get uniqueValues() { return getFacetedUniqueValues(wh().header.column.id); }, get minMax() { return getFacetedMinMaxValues(wh().header.column.id); }, get setFilter() { return setColumnFilter; } }) ?? <input type="text" aria-label={rozieAttr('Filter ' + headerLabel(wh().header.column.id))} class={"rdt-col-filter"} value={columnFilterValue(wh().header.column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onColumnFilterInput(wh().header.column.id, $event); }} onClick={($event: MouseEvent & { currentTarget: HTMLInputElement; target: Element }) => { stopEvent($event); }} data-rozie-s-d5dcab4c="" />}
7506
7709
  </span></Show>}</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}</th>}</Key>
7507
7710
  {<Show when={colsWindowed()}><th class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle('width:' + colPadRight() + 'px;padding:0;border:0')} data-rozie-s-d5dcab4c="" /></Show>}</tr></Show>}</thead>
7508
7711
 
@@ -7518,20 +7721,20 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7518
7721
  {<Show when={colsWindowed()}><td class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle('width:' + colPadLeft() + 'px;padding:0;border:0')} data-rozie-s-d5dcab4c="" /></Show>}<Key each={windowedCells(wr().row) as readonly any[]} by={(cell) => cell.id}>{(cell) => <td class={"rdt-td" + " " + rozieClass({ 'rdt-select-td': isSelectColumn(cell().column.id), 'rdt-expander-td': isExpanderColumn(cell().column.id), 'rdt-in-range': inRange(wr().vi.index, colIndexOf(wr().row, cell())), 'rdt-cell-active': isActiveCell(String(wr().vi.index), colIndexOf(wr().row, cell())) })} role={rozieAttr(cellRole())} data-col={rozieAttr(cell().column.id)} data-grid-cell="" data-row={rozieAttr(wr().vi.index)} data-col-index={rozieAttr(colIndexOf(wr().row, cell()))} tabIndex={rozieAttr(cellTabindex(String(wr().vi.index), colIndexOf(wr().row, cell())))} style={parseInlineStyle(bodyCellStyle(wr().row, cell().column.id))} aria-invalid={rozieAttr(cellAriaInvalid(wr().vi.index, colIndexOf(wr().row, cell())))} data-in-range={rozieAttr(inRange(wr().vi.index, colIndexOf(wr().row, cell())) ? 'true' : null)} data-agg-cell={rozieAttr(cellIsAggregated(cell()) ? cell().column.id : null)} data-rozie-s-d5dcab4c="">
7519
7722
 
7520
7723
  {<Show when={isExpanderColumn(cell().column.id)} fallback={<Show when={isSelectColumn(cell().column.id)} fallback={<Show when={cellIsGrouped(cell())} fallback={<Show when={isEditing(wr().vi.index, colIndexOf(wr().row, cell()))} fallback={<Show when={cellIsPlaceholder(cell())} fallback={<span class={"rdt-cell-value"} data-rozie-s-d5dcab4c="">
7521
- {_props.slots?.[`cell-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: cell().getValue() }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: cell().getValue() }) ?? rozieDisplay(cell().getValue())}
7724
+ {_props.slots?.[`cell-${cell().column.id}`]?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(wr().row); }, get value() { return cell().getValue(); } }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(wr().row); }, get value() { return cell().getValue(); } }) ?? rozieDisplay(cell().getValue())}
7522
7725
  </span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7523
7726
  {<Show when={editorTypeOf(cell().column.id) === 'number'} fallback={<Show when={editorTypeOf(cell().column.id) === 'select'} fallback={<Show when={editorTypeOf(cell().column.id) === 'checkbox'} fallback={<Show when={editorTypeOf(cell().column.id) === 'custom'} fallback={<input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7524
- {_props.slots?.[`editor-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, wr().vi.index) }) ?? (_props.editorSlot ?? _props.slots?.['editor'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, wr().vi.index) }) ?? <input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}
7727
+ {_props.slots?.[`editor-${cell().column.id}`]?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(wr().row); }, get value() { return editorValueFor(cell().column.id); }, get commit() { return editorCommitFor(cell().column.id); }, get cancel() { return editorCancelFor(); }, get autofocus() { return editorAutofocusFor(cell().column.id, wr().vi.index); } }) ?? (_props.editorSlot ?? _props.slots?.['editor'])?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(wr().row); }, get value() { return editorValueFor(cell().column.id); }, get commit() { return editorCommitFor(cell().column.id); }, get cancel() { return editorCancelFor(); }, get autofocus() { return editorAutofocusFor(cell().column.id, wr().vi.index); } }) ?? <input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}
7525
7728
  </span></Show>}><input type="checkbox" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} checked={editorCheckedFor(cell().column.id)} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorCheckbox(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" /></Show>}><select data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onChange={($event: Event & { currentTarget: HTMLSelectElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLSelectElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLSelectElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="">
7526
7729
  <Key each={editorOptionsOf(cell().column.id) as readonly any[]} by={(opt) => opt.value}>{(opt) => <option value={rozieAttr(opt().value)} data-rozie-s-d5dcab4c="">{rozieDisplay(opt().label)}</option>}</Key>
7527
7730
  </select></Show>}><input type="number" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" /></Show>}</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7528
7731
  <button type="button" data-expander="" aria-expanded={!!rowIsExpanded(wr().row)} aria-label={rozieAttr(rowIsExpanded(wr().row) ? 'Collapse group' : 'Expand group')} class={"rdt-expander rdt-group-toggle"} onClick={($event: MouseEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onToggleExpand(wr().row, $event); }} data-rozie-s-d5dcab4c="">{rozieDisplay(rowIsExpanded(wr().row) ? '▾' : '▸')}</button>
7529
7732
  <span class={"rdt-group-value"} data-rozie-s-d5dcab4c="">
7530
- {_props.slots?.[`cell-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: cell().getValue() }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: cell().getValue() }) ?? rozieDisplay(cell().getValue())}
7733
+ {_props.slots?.[`cell-${cell().column.id}`]?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(wr().row); }, get value() { return cell().getValue(); } }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ get columnId() { return cell().column.id; }, get column() { return cell().column; }, get row() { return cellSlotRow(wr().row); }, get value() { return cell().getValue(); } }) ?? rozieDisplay(cell().getValue())}
7531
7734
  </span>
7532
7735
  <span class={"rdt-group-count"} data-rozie-s-d5dcab4c="">{rozieDisplay('(' + groupSubRowCount(wr().row) + ')')}</span>
7533
7736
  </span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7534
- {(_props.selectCellSlot ?? _props.slots?.['selectCell'])?.({ row: cellSlotRow(wr().row), checked: rowIsSelected(wr().row), toggle: e => onToggleRow(wr().row, e) }) ?? <input type="checkbox" aria-label="Select row" class={"rdt-select-row"} checked={rowIsSelected(wr().row)} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleRow(wr().row, $event); }} data-rozie-s-d5dcab4c="" />}
7737
+ {(_props.selectCellSlot ?? _props.slots?.['selectCell'])?.({ get row() { return cellSlotRow(wr().row); }, get checked() { return rowIsSelected(wr().row); }, toggle: e => onToggleRow(wr().row, e) }) ?? <input type="checkbox" aria-label="Select row" class={"rdt-select-row"} checked={rowIsSelected(wr().row)} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleRow(wr().row, $event); }} data-rozie-s-d5dcab4c="" />}
7535
7738
  </span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
7536
7739
  {<Show when={rowCanExpand(wr().row)}><button type="button" data-expander="" aria-expanded={!!rowIsExpanded(wr().row)} aria-label={rozieAttr(rowIsExpanded(wr().row) ? 'Collapse row' : 'Expand row')} class={"rdt-expander"} onClick={($event: MouseEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onToggleExpand(wr().row, $event); }} data-rozie-s-d5dcab4c="">{rozieDisplay(rowIsExpanded(wr().row) ? '▾' : '▸')}</button></Show>}</span></Show>}{<Show when={isFillHandleCell(wr().vi.index, colIndexOf(wr().row, cell()))}><span data-fill-handle="" data-testid="fill-handle" aria-hidden="true" class={"rdt-fill-handle"} onPointerDown={($event: PointerEvent & { currentTarget: HTMLSpanElement; target: Element }) => { onFillHandlePointerDown($event); }} data-rozie-s-d5dcab4c="" /></Show>}</td>}</Key>
7537
7740
 
@@ -7539,7 +7742,7 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
7539
7742
 
7540
7743
  {<Show when={rowShowsDetail(wr().row)}><tr class={"rdt-detail-row"} role="row" data-detail-row={rozieAttr(wr().row.id)} data-rozie-s-d5dcab4c="">
7541
7744
  <td class={"rdt-detail-cell"} colSpan={rozieAttr(windowedColSpan())} data-rozie-s-d5dcab4c="">
7542
- {(_props.detailSlot ?? _props.slots?.['detail'])?.({ row: wr().row.original })}
7745
+ {(_props.detailSlot ?? _props.slots?.['detail'])?.({ get row() { return wr().row.original; } })}
7543
7746
  </td>
7544
7747
  </tr></Show>}</>}</Key>
7545
7748