@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/README.md +48 -42
- package/dist/index.cjs +424 -121
- package/dist/index.d.cts +7 -7
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +424 -121
- package/package.json +2 -2
- package/src/Column.tsx +2 -2
- package/src/DataTable.tsx +232 -29
- package/src/themes/base.css +38 -25
- package/src/themes/bootstrap.css +11 -0
- package/src/themes/material.css +11 -0
- package/src/themes/shadcn.css +11 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rozie-ui/data-table-solid",
|
|
3
|
-
"version": "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.
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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',
|
|
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 `
|
|
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).
|
|
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 `
|
|
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'`
|
|
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
|
|
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
|
|
1831
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
7745
|
+
{(_props.detailSlot ?? _props.slots?.['detail'])?.({ get row() { return wr().row.original; } })}
|
|
7543
7746
|
</td>
|
|
7544
7747
|
</tr></Show>}</>}</Key>
|
|
7545
7748
|
|