@rozie-ui/data-table-solid 0.3.2 → 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 +99 -44
- package/dist/index.cjs +527 -139
- package/dist/index.d.cts +47 -18
- package/dist/index.d.mts +47 -18
- package/dist/index.mjs +527 -139
- package/package.json +2 -2
- package/src/Column.tsx +2 -2
- package/src/DataTable.tsx +397 -119
- 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/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);
|
|
@@ -353,21 +381,21 @@ interface GroupBarSlotCtx { grouping: any; groupableColumns: any; applyGrouping:
|
|
|
353
381
|
|
|
354
382
|
interface SelectAllSlotCtx { checked: any; indeterminate: any; toggle: any; }
|
|
355
383
|
|
|
384
|
+
interface SelectCellSlotCtx { row: any; checked: any; toggle: any; }
|
|
385
|
+
|
|
386
|
+
interface DetailSlotCtx { row: any; }
|
|
387
|
+
|
|
356
388
|
interface ColHeaderSlotCtx { columnId: any; column: any; label: any; }
|
|
357
389
|
|
|
358
390
|
interface FilterSlotCtx { columnId: any; value: any; uniqueValues: any; minMax: any; setFilter: any; }
|
|
359
391
|
|
|
360
|
-
interface SelectCellSlotCtx { row: any; checked: any; toggle: any; }
|
|
361
|
-
|
|
362
392
|
interface CellSlotCtx { columnId: any; column: any; row: any; value: any; }
|
|
363
393
|
|
|
364
394
|
interface EditorSlotCtx { columnId: any; column: any; row: any; value: any; commit: any; cancel: any; autofocus: any; }
|
|
365
395
|
|
|
366
|
-
interface DetailSlotCtx { row: any; }
|
|
367
|
-
|
|
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
|
/**
|
|
@@ -527,13 +555,13 @@ interface DataTableProps {
|
|
|
527
555
|
children?: JSX.Element;
|
|
528
556
|
groupBarSlot?: (ctx: GroupBarSlotCtx) => JSX.Element;
|
|
529
557
|
selectAllSlot?: (ctx: SelectAllSlotCtx) => JSX.Element;
|
|
558
|
+
selectCellSlot?: (ctx: SelectCellSlotCtx) => JSX.Element;
|
|
559
|
+
detailSlot?: (ctx: DetailSlotCtx) => JSX.Element;
|
|
530
560
|
colHeaderSlot?: (ctx: ColHeaderSlotCtx) => JSX.Element;
|
|
531
561
|
filterSlot?: (ctx: FilterSlotCtx) => JSX.Element;
|
|
532
|
-
selectCellSlot?: (ctx: SelectCellSlotCtx) => JSX.Element;
|
|
533
562
|
cellSlot?: (ctx: CellSlotCtx) => JSX.Element;
|
|
534
563
|
editorSlot?: (ctx: EditorSlotCtx) => JSX.Element;
|
|
535
|
-
|
|
536
|
-
slots?: Record<string, (ctx: any) => JSX.Element>;
|
|
564
|
+
slots?: { [key: `colHeader-${string}`]: ((ctx: { columnId: any; column: any; label: any }) => JSX.Element) | undefined; [key: `filter-${string}`]: ((ctx: { columnId: any; value: any; uniqueValues: any; minMax: any; setFilter: any }) => JSX.Element) | undefined; [key: `cell-${string}`]: ((ctx: { columnId: any; column: any; row: any; value: any }) => JSX.Element) | undefined; [key: `editor-${string}`]: ((ctx: { columnId: any; column: any; row: any; value: any; commit: any; cancel: any; autofocus: any }) => JSX.Element) | undefined; [key: string]: ((...args: any[]) => JSX.Element) | undefined; };
|
|
537
565
|
ref?: (h: DataTableHandle) => void;
|
|
538
566
|
}
|
|
539
567
|
|
|
@@ -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 ════════
|
|
@@ -3102,20 +3290,6 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3102
3290
|
const m = editMetaOf(colId);
|
|
3103
3291
|
return m && m.editorOptions != null ? m.editorOptions : [];
|
|
3104
3292
|
}
|
|
3105
|
-
// hasEditorSlot: this column routes through the consumer's #editor scoped slot (req-2)
|
|
3106
|
-
// — true only when the column declared editor='custom' AND the consumer actually
|
|
3107
|
-
// provided an #editor slot. Falls through to the built-in editor otherwise (e.g. a
|
|
3108
|
-
// column marked 'custom' with no slot supplied degrades to the text editor, never blank).
|
|
3109
|
-
function hasEditorSlot(colId: any) {
|
|
3110
|
-
return editorTypeOf(colId) === 'custom' && !!(_props.editorSlot ?? _props.slots?.["editor"]);
|
|
3111
|
-
}
|
|
3112
|
-
|
|
3113
|
-
// hasFilterSlot: the consumer supplied a #filter scoped slot, so it OWNS the per-column
|
|
3114
|
-
// filter UI (re-added in 72-05 alongside the dedicated filter row's `<slot name="filter">`
|
|
3115
|
-
// host — see the 72-03 removal note in that plan's SUMMARY for why this was briefly gone).
|
|
3116
|
-
function hasFilterSlot() {
|
|
3117
|
-
return !!(_props.filterSlot ?? _props.slots?.["filter"]);
|
|
3118
|
-
}
|
|
3119
3293
|
function columnIsFilterable(colId: any) {
|
|
3120
3294
|
const d = defFor(colId);
|
|
3121
3295
|
return !!(d && d.filterable);
|
|
@@ -3126,13 +3300,27 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3126
3300
|
}
|
|
3127
3301
|
|
|
3128
3302
|
// ── Column-management chrome (req-8/9/10/11) ────────────────────────────────────────
|
|
3129
|
-
// Live header width (px) for a
|
|
3130
|
-
//
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3303
|
+
// Live header width (px) for a <th> — drives the :style width binding. Takes the table-core
|
|
3304
|
+
// HEADER object (not a column id / Column lookup) and reads header.getSize() — deliberately,
|
|
3305
|
+
// NOT column.getSize(). table-core's own ColumnSizing feature (createHeader, always present —
|
|
3306
|
+
// it is in table-core's builtInFeatures, never opt-in) gives Header.getSize() a recursive
|
|
3307
|
+
// implementation: a LEAF header returns its own column's getSize() (identical to the old
|
|
3308
|
+
// column.getSize() path — byte-identical output there), but a GROUP header (one with
|
|
3309
|
+
// subHeaders, e.g. a multi-level `columns:` entry from buildConfigDef) SUMS every descendant
|
|
3310
|
+
// leaf column's getSize() instead of returning the group's own meaningless single-column
|
|
3311
|
+
// default (150px, table-core's defaultColumnSizing.size — group ColumnDefs never set `size`).
|
|
3312
|
+
// Before this fix, a colspan-N grouped <th> asked the browser for ONE column's worth of width
|
|
3313
|
+
// (150px) while spanning N columns; under `table-layout:fixed` the browser then divides that
|
|
3314
|
+
// single declared width ACROSS all N spanned <th>s (150/5 = 30px for this codebase's 5-column
|
|
3315
|
+
// "Group A" fixture) — a 5x collapse of the actual rendered column width, independent of (and
|
|
3316
|
+
// invisible to) columnSize()/the column virtualizer's windowing math, which reads
|
|
3317
|
+
// table.getVisibleLeafColumns()[i].getSize() directly and was never affected. Root cause +
|
|
3318
|
+
// fix confirmed via .planning/debug/datatable-d13-column-axis-all-targets.md and previously
|
|
3319
|
+
// documented as "Gap 1" in .planning/phases/87-.../deferred-items.md (the identical grouped-
|
|
3320
|
+
// header/colspan mismatch, found independently during 87-05/87-06 authoring and deferred).
|
|
3321
|
+
function headerWidth(header: any) {
|
|
3322
|
+
if (tick() < 0 || !header || typeof header.getSize !== 'function') return null;
|
|
3323
|
+
const w = header.getSize();
|
|
3136
3324
|
return w != null && w > 0 ? w + 'px' : null;
|
|
3137
3325
|
}
|
|
3138
3326
|
|
|
@@ -3249,15 +3437,18 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3249
3437
|
}
|
|
3250
3438
|
return '';
|
|
3251
3439
|
}
|
|
3252
|
-
// Combined inline style for a <th> (width + pin)
|
|
3253
|
-
//
|
|
3254
|
-
//
|
|
3255
|
-
//
|
|
3256
|
-
|
|
3440
|
+
// Combined inline style for a <th> (width + pin). Plain string concat — uniform on all 6, no
|
|
3441
|
+
// bound-object trap. zIndex=2 (see pinStyle) so a pinned header cell — which hosts the ⋯ menu's
|
|
3442
|
+
// floating content — always stacks above the pinned filter-row cell for the same column
|
|
3443
|
+
// (zIndex=1, its own default). Takes the HEADER object (not a bare colId) so headerWidth() can
|
|
3444
|
+
// read header.getSize() — the group-aware size (see headerWidth's own comment). pinStyle still
|
|
3445
|
+
// keys off the plain column id (pinning is a leaf-column-only concern; a grouped header never
|
|
3446
|
+
// pins as a unit in this codebase's model).
|
|
3447
|
+
function thStyle(header: any) {
|
|
3257
3448
|
let s = '';
|
|
3258
|
-
const w = headerWidth(
|
|
3449
|
+
const w = headerWidth(header);
|
|
3259
3450
|
if (w) s += 'width:' + w + ';';
|
|
3260
|
-
s += pinStyle(
|
|
3451
|
+
s += pinStyle(header && header.column ? header.column.id : null, 2);
|
|
3261
3452
|
return s;
|
|
3262
3453
|
}
|
|
3263
3454
|
|
|
@@ -5719,8 +5910,25 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5719
5910
|
fillEdgeScrollRaf = null;
|
|
5720
5911
|
}
|
|
5721
5912
|
}
|
|
5722
|
-
|
|
5723
|
-
|
|
5913
|
+
// FILL_HITTEST_PROBE_RADIUS_PX / FILL_HITTEST_PROBE_STEP_PX (hardening, authorized alongside the
|
|
5914
|
+
// D-13 grouped-header width fix — .planning/debug/datatable-d13-column-axis-all-targets.md):
|
|
5915
|
+
// resolveCellAt() below hit-tests document.elementFromPoint at ONE exact pixel — structurally
|
|
5916
|
+
// fragile against a scrolling DOM by construction: any narrow column transiting past that fixed
|
|
5917
|
+
// screen point (the edge-auto-scroll rAF loop in fillDrag re-probes the SAME fixed point every
|
|
5918
|
+
// frame while gridScrollEl's content slides underneath it) has only a single-frame-scale window
|
|
5919
|
+
// to be caught, and a probe pixel landing exactly on a border/rounding edge between two adjacent
|
|
5920
|
+
// `<td>`/`<th>`s can miss both. cellIndexFromPoint widens the miss case ONLY: it tries the exact
|
|
5921
|
+
// point first (byte-identical to the pre-hardening behavior on a hit — this is not a behavior
|
|
5922
|
+
// change to the common case) and, only if that misses, fans out a small nearest-first horizontal
|
|
5923
|
+
// search before giving up. Vertical-only misses are not probed (rows are >=24px tall by design —
|
|
5924
|
+
// FILL_EDGE_SCROLL_PX itself — so a row is never narrower than a single scroll step; only COLUMN
|
|
5925
|
+
// width has no such floor, hence a horizontal-only widening).
|
|
5926
|
+
const FILL_HITTEST_PROBE_RADIUS_PX = 8;
|
|
5927
|
+
const FILL_HITTEST_PROBE_STEP_PX = 2;
|
|
5928
|
+
|
|
5929
|
+
// resolveCellAt: the exact-point hit-test (identical logic to the pre-hardening
|
|
5930
|
+
// cellIndexFromPoint body) extracted so it can be re-tried at nearby x-offsets below.
|
|
5931
|
+
function resolveCellAt(clientX: any, clientY: any) {
|
|
5724
5932
|
let el = document.elementFromPoint(clientX, clientY);
|
|
5725
5933
|
// Pierce OPEN shadow roots (Lit): document.elementFromPoint retargets to the shadow HOST, so
|
|
5726
5934
|
// a drag over the Lit data-table's shadow content would otherwise resolve the host (no cell)
|
|
@@ -5745,6 +5953,22 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5745
5953
|
c
|
|
5746
5954
|
};
|
|
5747
5955
|
}
|
|
5956
|
+
function cellIndexFromPoint(clientX: any, clientY: any) {
|
|
5957
|
+
if (typeof document === 'undefined' || !document.elementFromPoint) return null;
|
|
5958
|
+
const direct = resolveCellAt(clientX, clientY);
|
|
5959
|
+
if (direct) return direct;
|
|
5960
|
+
// Widened nearest-cell search: only reached when the exact point misses. Fans outward
|
|
5961
|
+
// (nearest-first, alternating +/-x) up to FILL_HITTEST_PROBE_RADIUS_PX before giving up —
|
|
5962
|
+
// catches a narrow column that transited past the fixed probe point on this exact frame
|
|
5963
|
+
// without changing which cell wins on an ordinary (non-edge-case) hit.
|
|
5964
|
+
for (let d = FILL_HITTEST_PROBE_STEP_PX; d <= FILL_HITTEST_PROBE_RADIUS_PX; d += FILL_HITTEST_PROBE_STEP_PX) {
|
|
5965
|
+
const right = resolveCellAt(clientX + d, clientY);
|
|
5966
|
+
if (right) return right;
|
|
5967
|
+
const left = resolveCellAt(clientX - d, clientY);
|
|
5968
|
+
if (left) return left;
|
|
5969
|
+
}
|
|
5970
|
+
return null;
|
|
5971
|
+
}
|
|
5748
5972
|
function onFillHandlePointerDown(e: any) {
|
|
5749
5973
|
if (!e) return;
|
|
5750
5974
|
if (e.preventDefault) e.preventDefault();
|
|
@@ -6069,39 +6293,73 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6069
6293
|
return row ? row.id : null;
|
|
6070
6294
|
}
|
|
6071
6295
|
|
|
6296
|
+
// resolveEditFocusCellEl(rowIndex, colIndex): the DOM cell element for an edit-focus
|
|
6297
|
+
// target, given an EXPLICIT index pair — NEVER a $data re-read inside this function or its
|
|
6298
|
+
// caller's poll closure. Every call site already knows this pair SYNCHRONOUSLY at the
|
|
6299
|
+
// moment it calls (beginEdit's own rowIndex/colIndex params; commitEdit's stable, already-
|
|
6300
|
+
// settled $data.editingRow/editingCol; beginRowEdit's rowIndex + the target column's
|
|
6301
|
+
// editable[].colIndex from editableColumnsForRow) — threading them through as PARAMETERS,
|
|
6302
|
+
// mirroring focusRowEditorAt's already-proven resolveCellEl(String(rowIndex), colIndex)
|
|
6303
|
+
// shape, closes the React batched-setState staleness class 88-05-SUMMARY.md documented
|
|
6304
|
+
// (REACT_STALE_GATE_SINGLE_CELL_BUG): the OLD gate read $data.editFocusColId SYNCHRONOUSLY,
|
|
6305
|
+
// in the SAME tick beginEdit's own setState call set it, and React's batching meant that
|
|
6306
|
+
// read saw the PRE-edit (null) value. A plain function argument threaded through — never a
|
|
6307
|
+
// reactive re-read — is not subject to that race, uniformly on all 6 targets.
|
|
6308
|
+
function resolveEditFocusCellEl(rowIndex: any, colIndex: any) {
|
|
6309
|
+
if (rowIndex == null || colIndex == null || rowIndex < 0 || colIndex < 0) return null;
|
|
6310
|
+
return resolveCellEl(String(rowIndex), colIndex);
|
|
6311
|
+
}
|
|
6312
|
+
|
|
6072
6313
|
// Focus the freshly-mounted editor (Pitfall 1, ROZ123): after beginEdit flips the editing
|
|
6073
6314
|
// state, the editor <input> does not exist until the framework commits the r-if branch
|
|
6074
|
-
// (React setState async; Solid/Lit/Svelte next reactive tick). Poll for the
|
|
6075
|
-
//
|
|
6076
|
-
//
|
|
6315
|
+
// (React setState async; Solid/Lit/Svelte next reactive tick). Poll for the target CELL's
|
|
6316
|
+
// marked built-in editor for ~30 frames — the five fast targets resolve on attempt 1, React
|
|
6317
|
+
// retries across its async commit. NEVER read $refs eagerly.
|
|
6077
6318
|
// B2: selectAll gates the post-focus el.select(). Select-all is right when entering
|
|
6078
6319
|
// edit IN PLACE (F2/Enter/click/row-edit/validation-reject — no seeded char, the user
|
|
6079
6320
|
// retypes), but WRONG on a type-to-edit entry where a printable key already seeded the
|
|
6080
6321
|
// draft (selecting the seeded char makes the next keystroke replace it: Zeta → eta).
|
|
6081
6322
|
// beginEdit threads `seed == null` so a seeded entry skips the select and the caret sits
|
|
6082
6323
|
// AFTER the seeded char; every other caller keeps the default select-all.
|
|
6083
|
-
//
|
|
6084
|
-
//
|
|
6085
|
-
//
|
|
6086
|
-
//
|
|
6087
|
-
//
|
|
6088
|
-
//
|
|
6089
|
-
//
|
|
6090
|
-
|
|
6324
|
+
// D-01/D-02 (88-07): REPLACES the deleted presence-check early-return gate AND the
|
|
6325
|
+
// gridRoot-wide `[data-editing-cell]` first-match query with a column-scoped, marker-driven
|
|
6326
|
+
// poll. Resolves the TARGET cell first (resolveEditFocusCellEl, mirroring
|
|
6327
|
+
// focusRowEditorAt's already-shipped two-step resolve), then queries for an editor carrying
|
|
6328
|
+
// BOTH `data-editing-cell` and the host-owned `data-builtin-editor` marker WITHIN that one
|
|
6329
|
+
// cell — "no marker found" (a drop-in target, D-01) bails immediately rather than reaching
|
|
6330
|
+
// into DOM the host does not own; "no editor at all yet" keeps polling (the framework hasn't
|
|
6331
|
+
// committed the r-if branch). This closes the D-02 wrong-column hole the old grid-wide query
|
|
6332
|
+
// left open (every editable cell mounts an editor at once in row-edit mode) AND fixes the
|
|
6333
|
+
// React staleness race documented above, as a side effect of no longer reading
|
|
6334
|
+
// $data.editFocusColId anywhere in this function.
|
|
6335
|
+
function focusEditorWhenReady(rowIndex: any, colIndex: any, selectAll = true) {
|
|
6091
6336
|
if (!gridRoot) return;
|
|
6092
|
-
// Editor-owns-focus contract: when the CURRENT focus target is a #editor drop-in, the host
|
|
6093
|
-
// does NOT reach into its DOM — the drop-in self-focuses via its own autofocus prop.
|
|
6094
|
-
if (editFocusColId() != null && hasEditorSlot(editFocusColId())) return;
|
|
6095
6337
|
let attempts = 0;
|
|
6096
6338
|
const tryFocus = () => {
|
|
6097
|
-
const
|
|
6339
|
+
const cellEl = resolveEditFocusCellEl(rowIndex, colIndex);
|
|
6340
|
+
const el = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell][data-builtin-editor]') : null;
|
|
6341
|
+
if (!el) {
|
|
6342
|
+
// Editor-owns-focus contract (quick 260711-i5m, D-01): if the cell ALREADY holds an
|
|
6343
|
+
// editor that carries only the base marker, it's a consumer drop-in — it owns its own
|
|
6344
|
+
// focus (EditorText's own $onMount + reactive `autofocus`). Bail immediately, zero
|
|
6345
|
+
// wasted frames, rather than burning the retry ceiling on DOM the host does not own.
|
|
6346
|
+
const anyEditor = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell]') : null;
|
|
6347
|
+
if (anyEditor) return;
|
|
6348
|
+
attempts = attempts + 1;
|
|
6349
|
+
if (attempts >= 30) return;
|
|
6350
|
+
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 16);
|
|
6351
|
+
return;
|
|
6352
|
+
}
|
|
6098
6353
|
// Do NOT stomp focus a later interaction already placed in a DIFFERENT column's editor of
|
|
6099
6354
|
// this row: focusEditorWhenReady only needs to get focus INTO the (first) freshly-mounted
|
|
6100
6355
|
// editor; if focus already sits in another editable cell, a late rAF re-focus would steal it
|
|
6101
6356
|
// back to the first editor and break row-mode Tab containment (the non-deterministic B21
|
|
6102
6357
|
// focus-theft). Compare the OWNING cell's data-col-index (NOT node identity) so a stale
|
|
6103
6358
|
// SAME-column editor node on Solid's node-replacing re-render still resolves as the target —
|
|
6104
|
-
// a genuinely dropped focus is still recovered.
|
|
6359
|
+
// a genuinely dropped focus is still recovered. Stays BROAD on `data-editing-cell` (NOT
|
|
6360
|
+
// narrowed to the builtin marker, D-02): focus validly placed inside a drop-in must still
|
|
6361
|
+
// count as "already placed" — narrowing this check would let a late rAF poll steal focus
|
|
6362
|
+
// back from a drop-in that legitimately holds it.
|
|
6105
6363
|
const ae = gridRoot && gridRoot.getRootNode ? gridRoot.getRootNode().activeElement : null;
|
|
6106
6364
|
if (ae && el && ae !== el && ae.closest && gridRoot.contains(ae) && ae.hasAttribute && ae.hasAttribute('data-editing-cell')) {
|
|
6107
6365
|
const aeCell = ae.closest('[data-grid-cell]');
|
|
@@ -6110,18 +6368,12 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6110
6368
|
const elCol = elCell ? elCell.getAttribute('data-col-index') : null;
|
|
6111
6369
|
if (aeCol != null && aeCol !== elCol) return;
|
|
6112
6370
|
}
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
} catch (e: any) {}
|
|
6119
|
-
}
|
|
6120
|
-
return;
|
|
6371
|
+
el.focus();
|
|
6372
|
+
if (selectAll && el.select) {
|
|
6373
|
+
try {
|
|
6374
|
+
el.select();
|
|
6375
|
+
} catch (e: any) {}
|
|
6121
6376
|
}
|
|
6122
|
-
attempts = attempts + 1;
|
|
6123
|
-
if (attempts >= 30) return;
|
|
6124
|
-
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 16);
|
|
6125
6377
|
};
|
|
6126
6378
|
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 0);
|
|
6127
6379
|
}
|
|
@@ -6176,8 +6428,10 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6176
6428
|
// from it. Cleared on endEdit.
|
|
6177
6429
|
setEditFocusColId(colId);
|
|
6178
6430
|
// B2: a seeded (type-to-edit) entry must NOT select-all — keep the caret after the
|
|
6179
|
-
// seeded char so subsequent typing appends instead of replacing it.
|
|
6180
|
-
|
|
6431
|
+
// seeded char so subsequent typing appends instead of replacing it. rowIndex/colIndex
|
|
6432
|
+
// are THIS call's own params — passed through directly (D-02), never re-read off
|
|
6433
|
+
// $data.editingRow/editingCol inside the poll.
|
|
6434
|
+
focusEditorWhenReady(rowIndex, colIndex, seed == null);
|
|
6181
6435
|
}
|
|
6182
6436
|
|
|
6183
6437
|
// Return focus to a body cell AFTER the editor unmounts (commit/cancel). The display↔
|
|
@@ -6192,6 +6446,21 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6192
6446
|
const tryFocus = () => {
|
|
6193
6447
|
const el = resolveCellEl(String(row), col);
|
|
6194
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
|
+
}
|
|
6195
6464
|
el.focus();
|
|
6196
6465
|
return;
|
|
6197
6466
|
}
|
|
@@ -6291,8 +6560,10 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6291
6560
|
const err = runValidator(colId, newValue, rowOriginal);
|
|
6292
6561
|
if (err !== true) {
|
|
6293
6562
|
// D-01: reject — keep the editor open, announce, re-trap focus, NEVER write the model.
|
|
6563
|
+
// $data.editingRow/editingCol are STABLE here (set by a prior beginEdit call, not this
|
|
6564
|
+
// same tick) — safe to read directly, unlike the deleted $data.editFocusColId gate.
|
|
6294
6565
|
setInvalid(err);
|
|
6295
|
-
focusEditorWhenReady();
|
|
6566
|
+
focusEditorWhenReady(editingRow(), editingCol());
|
|
6296
6567
|
return false;
|
|
6297
6568
|
}
|
|
6298
6569
|
setInvalid('');
|
|
@@ -6453,22 +6724,22 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6453
6724
|
|
|
6454
6725
|
// B21/B22: focus the row-mode editor at a given VISIBLE col index. In full-row edit every
|
|
6455
6726
|
// editable cell is already mounted as an editor, so this resolves the cell off gridRoot and
|
|
6456
|
-
// focuses its [data-editing-cell] control. Bounded rAF-poll (mirrors
|
|
6457
|
-
// so a React re-render that recreates the input across the focus call
|
|
6458
|
-
// all on text/number editors (a no-op try/catch on select/checkbox).
|
|
6459
|
-
//
|
|
6460
|
-
//
|
|
6461
|
-
//
|
|
6462
|
-
//
|
|
6463
|
-
//
|
|
6727
|
+
// focuses its [data-editing-cell][data-builtin-editor] control. Bounded rAF-poll (mirrors
|
|
6728
|
+
// focusEditorWhenReady) so a React re-render that recreates the input across the focus call
|
|
6729
|
+
// still lands it. select-all on text/number editors (a no-op try/catch on select/checkbox).
|
|
6730
|
+
// D-01/D-02 (88-07): the old columnIdAt + presence-check early-return gate is DELETED — the
|
|
6731
|
+
// host-owned data-builtin-editor marker replaces it. If the resolved cell already holds an
|
|
6732
|
+
// editor carrying ONLY the base data-editing-cell marker (no builtin marker), that's a
|
|
6733
|
+
// consumer drop-in — bail immediately, it owns its own focus (EditorText's own $onMount +
|
|
6734
|
+
// reactive `autofocus`, which the caller already flips via $data.editFocusColId). This
|
|
6735
|
+
// two-step resolve (resolveCellEl THEN a scoped query within that one cell) was ALREADY
|
|
6736
|
+
// column-scoped and correct — it is the shape focusEditorWhenReady's D-02 rework adopts.
|
|
6464
6737
|
function focusRowEditorAt(rowIndex: any, colIndex: any) {
|
|
6465
6738
|
if (!gridRoot) return;
|
|
6466
|
-
const colId = columnIdAt(rowIndex, colIndex);
|
|
6467
|
-
if (colId != null && hasEditorSlot(colId)) return;
|
|
6468
6739
|
let attempts = 0;
|
|
6469
6740
|
const tryFocus = () => {
|
|
6470
6741
|
const cellEl = resolveCellEl(String(rowIndex), colIndex);
|
|
6471
|
-
const ed = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell]') : null;
|
|
6742
|
+
const ed = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell][data-builtin-editor]') : null;
|
|
6472
6743
|
if (ed) {
|
|
6473
6744
|
ed.focus();
|
|
6474
6745
|
if (ed.select) {
|
|
@@ -6478,6 +6749,11 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6478
6749
|
}
|
|
6479
6750
|
return;
|
|
6480
6751
|
}
|
|
6752
|
+
// No marked built-in editor yet in this cell: a drop-in mounted there owns its own
|
|
6753
|
+
// focus — bail immediately (D-02) rather than burning the retry ceiling on DOM the
|
|
6754
|
+
// host does not own. No editor at all yet just means "keep polling."
|
|
6755
|
+
const any = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell]') : null;
|
|
6756
|
+
if (any) return;
|
|
6481
6757
|
attempts = attempts + 1;
|
|
6482
6758
|
if (attempts >= 30) return;
|
|
6483
6759
|
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 16);
|
|
@@ -6524,9 +6800,11 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6524
6800
|
// Editor-owns-focus contract (quick 260711-i5m): the row's FIRST editable column is the
|
|
6525
6801
|
// initial focus target — editorAutofocusFor derives the reactive `autofocus` #editor scope
|
|
6526
6802
|
// prop from it (a built-in column is also host-focused below via focusEditorWhenReady; a
|
|
6527
|
-
// drop-in column self-focuses via its own $onMount, gated off the host reach-in
|
|
6803
|
+
// drop-in column self-focuses via its own $onMount, gated off the host reach-in via D-01's
|
|
6804
|
+
// marker). editable[0].colIndex is THIS call's own already-resolved value (D-02) — passed
|
|
6805
|
+
// through directly, never re-read off $data.editFocusColId inside the poll.
|
|
6528
6806
|
setEditFocusColId(editable[0].colId);
|
|
6529
|
-
focusEditorWhenReady();
|
|
6807
|
+
focusEditorWhenReady(rowIndex, editable[0].colIndex);
|
|
6530
6808
|
}
|
|
6531
6809
|
|
|
6532
6810
|
// commitRow(): validate EVERY edited column (D-01 — keep the row open if ANY fails: set
|
|
@@ -7317,23 +7595,23 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7317
7595
|
|
|
7318
7596
|
|
|
7319
7597
|
{<Show when={local.groupable}><div class={"rdt-group-bar-host"} data-rozie-s-d5dcab4c="">
|
|
7320
|
-
{(_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>}
|
|
7321
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="">
|
|
7322
7600
|
<thead class={"rdt-thead"} role="rowgroup" data-rozie-s-d5dcab4c="">
|
|
7323
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="">
|
|
7324
|
-
<Key each={hg().headers as readonly any[]} by={(header) => header.id}>{(header) => <th class={"rdt-th" + " " + rozieClass({ 'rdt-select-th': isSelectColumn(header().column.id), 'rdt-expander-th': isExpanderColumn(header().column.id), 'rdt-th-resizing': columnIsResizing(header().column.id), 'rdt-cell-active': isActiveCell('__header', headerColIndexOf(hg(), header()), hgLevel()) })} role="columnheader" data-col={rozieAttr(header().column.id)} data-grid-cell="" data-row="__header" data-header-level={rozieAttr(hgLevel())} colSpan={rozieAttr(header().colSpan > 1 ? header().colSpan : null)} data-col-index={rozieAttr(headerColIndexOf(hg(), header()))} tabIndex={rozieAttr(cellTabindex('__header', headerColIndexOf(hg(), header()), hgLevel()))} aria-sort={rozieAttr(ariaSortFor(header().column.id))} style={parseInlineStyle(thStyle(header()
|
|
7602
|
+
<Key each={hg().headers as readonly any[]} by={(header) => header.id}>{(header) => <th class={"rdt-th" + " " + rozieClass({ 'rdt-select-th': isSelectColumn(header().column.id), 'rdt-expander-th': isExpanderColumn(header().column.id), 'rdt-th-resizing': columnIsResizing(header().column.id), 'rdt-cell-active': isActiveCell('__header', headerColIndexOf(hg(), header()), hgLevel()) })} role="columnheader" data-col={rozieAttr(header().column.id)} data-grid-cell="" data-row="__header" data-header-level={rozieAttr(hgLevel())} colSpan={rozieAttr(header().colSpan > 1 ? header().colSpan : null)} data-col-index={rozieAttr(headerColIndexOf(hg(), header()))} tabIndex={rozieAttr(cellTabindex('__header', headerColIndexOf(hg(), header()), hgLevel()))} aria-sort={rozieAttr(ariaSortFor(header().column.id))} style={parseInlineStyle(thStyle(header()))} data-rozie-s-d5dcab4c="">
|
|
7325
7603
|
|
|
7326
7604
|
|
|
7327
7605
|
{<Show when={isSelectColumn(header().column.id)} fallback={<Show when={isExpanderColumn(header().column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7328
7606
|
|
|
7329
7607
|
{<Show when={header().column.getCanSort && header().column.getCanSort()} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7330
7608
|
<span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
|
|
7331
|
-
{(_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ 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))}
|
|
7332
7610
|
</span>
|
|
7333
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="">
|
|
7334
7612
|
|
|
7335
7613
|
<span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
|
|
7336
|
-
{(_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ 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))}
|
|
7337
7615
|
</span>
|
|
7338
7616
|
<span class={"rdt-sort-ind"} aria-hidden="true" data-rozie-s-d5dcab4c="">{rozieDisplay(sortIndicator(header().column.id))}</span>
|
|
7339
7617
|
</button></Show>}<Popover trigger="click" placement="bottom-end" strategy="fixed" offset={4} data-rozie-s-d5dcab4c="" anchorSlot={() => (<>
|
|
@@ -7348,15 +7626,15 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7348
7626
|
|
|
7349
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>
|
|
7350
7628
|
</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7351
|
-
{(_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>}
|
|
7352
7630
|
</span></Show>}</th>}</Key>
|
|
7353
7631
|
</tr>}</Key>
|
|
7354
7632
|
|
|
7355
7633
|
{<Show when={hasAnyFilterableColumn()}><tr class={"rdt-filter-row"} data-rozie-s-d5dcab4c="">
|
|
7356
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="">
|
|
7357
7635
|
{<Show when={isSelectColumn(header().column.id)} fallback={<Show when={isExpanderColumn(header().column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7358
|
-
{<Show when={columnIsFilterable(header().column.id)
|
|
7359
|
-
{(_props.filterSlot ?? _props.slots?.['filter'])?.({ columnId
|
|
7636
|
+
{<Show when={columnIsFilterable(header().column.id)}><span style={{ display: "contents" }} 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="" />}
|
|
7360
7638
|
</span></Show>}</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}</th>}</Key>
|
|
7361
7639
|
</tr></Show>}</thead>
|
|
7362
7640
|
|
|
@@ -7367,27 +7645,27 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7367
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="">
|
|
7368
7646
|
|
|
7369
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="">
|
|
7370
|
-
{(_props.cellSlot ?? _props.slots?.['cell'])?.({ 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())}
|
|
7371
7649
|
</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7372
|
-
{<Show when={
|
|
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="">
|
|
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="" />}
|
|
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="">
|
|
7373
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>
|
|
7374
|
-
</select></Show>}><input type="number" data-editing-cell="" 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 style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7375
|
-
{(_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())) })}
|
|
7376
|
-
</span></Show>}</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
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="">
|
|
7377
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>
|
|
7378
7656
|
<span class={"rdt-group-value"} data-rozie-s-d5dcab4c="">
|
|
7379
|
-
{(_props.cellSlot ?? _props.slots?.['cell'])?.({ 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())}
|
|
7380
7658
|
</span>
|
|
7381
7659
|
<span class={"rdt-group-count"} data-rozie-s-d5dcab4c="">{rozieDisplay('(' + groupSubRowCount(row()) + ')')}</span>
|
|
7382
7660
|
</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7383
|
-
{(_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="" />}
|
|
7384
7662
|
</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7385
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>
|
|
7386
7664
|
</tr>
|
|
7387
7665
|
|
|
7388
7666
|
{<Show when={rowShowsDetail(row())}><tr class={"rdt-detail-row"} role="row" data-detail-row={rozieAttr(row().id)} data-rozie-s-d5dcab4c="">
|
|
7389
7667
|
<td class={"rdt-detail-cell"} colSpan={rozieAttr(visibleColCount())} data-rozie-s-d5dcab4c="">
|
|
7390
|
-
{(_props.detailSlot ?? _props.slots?.['detail'])?.({ row
|
|
7668
|
+
{(_props.detailSlot ?? _props.slots?.['detail'])?.({ get row() { return row().original; } })}
|
|
7391
7669
|
</td>
|
|
7392
7670
|
</tr></Show>}</>}</Key>
|
|
7393
7671
|
</tbody>
|
|
@@ -7396,15 +7674,15 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7396
7674
|
<thead class={"rdt-thead"} role="rowgroup" data-rozie-s-d5dcab4c="">
|
|
7397
7675
|
<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="">
|
|
7398
7676
|
|
|
7399
|
-
{<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(hg(), hgLevel()) as readonly any[]} by={(wh) => wh.header.id}>{(wh) => <th class={"rdt-th" + " " + rozieClass({ 'rdt-select-th': isSelectColumn(wh().header.column.id), 'rdt-expander-th': isExpanderColumn(wh().header.column.id), 'rdt-th-resizing': columnIsResizing(wh().header.column.id), 'rdt-cell-active': isActiveCell('__header', headerColIndexOf(hg(), wh().header), hgLevel()) })} role="columnheader" data-col={rozieAttr(wh().header.column.id)} data-grid-cell="" data-row="__header" data-header-level={rozieAttr(hgLevel())} colSpan={rozieAttr(wh().span > 1 ? wh().span : null)} data-col-index={rozieAttr(headerColIndexOf(hg(), wh().header))} tabIndex={rozieAttr(cellTabindex('__header', headerColIndexOf(hg(), wh().header), hgLevel()))} aria-sort={rozieAttr(ariaSortFor(wh().header.column.id))} style={parseInlineStyle(thStyle(wh().header
|
|
7677
|
+
{<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(hg(), hgLevel()) as readonly any[]} by={(wh) => wh.header.id}>{(wh) => <th class={"rdt-th" + " " + rozieClass({ 'rdt-select-th': isSelectColumn(wh().header.column.id), 'rdt-expander-th': isExpanderColumn(wh().header.column.id), 'rdt-th-resizing': columnIsResizing(wh().header.column.id), 'rdt-cell-active': isActiveCell('__header', headerColIndexOf(hg(), wh().header), hgLevel()) })} role="columnheader" data-col={rozieAttr(wh().header.column.id)} data-grid-cell="" data-row="__header" data-header-level={rozieAttr(hgLevel())} colSpan={rozieAttr(wh().span > 1 ? wh().span : null)} data-col-index={rozieAttr(headerColIndexOf(hg(), wh().header))} tabIndex={rozieAttr(cellTabindex('__header', headerColIndexOf(hg(), wh().header), hgLevel()))} aria-sort={rozieAttr(ariaSortFor(wh().header.column.id))} style={parseInlineStyle(thStyle(wh().header))} data-rozie-s-d5dcab4c="">
|
|
7400
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="">
|
|
7401
7679
|
{<Show when={wh().header.column.getCanSort && wh().header.column.getCanSort()} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7402
7680
|
<span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
|
|
7403
|
-
{(_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ 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))}
|
|
7404
7682
|
</span>
|
|
7405
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="">
|
|
7406
7684
|
<span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
|
|
7407
|
-
{(_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ 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))}
|
|
7408
7686
|
</span>
|
|
7409
7687
|
<span class={"rdt-sort-ind"} aria-hidden="true" data-rozie-s-d5dcab4c="">{rozieDisplay(sortIndicator(wh().header.column.id))}</span>
|
|
7410
7688
|
</button></Show>}<Popover trigger="click" placement="bottom-end" strategy="fixed" offset={4} data-rozie-s-d5dcab4c="" anchorSlot={() => (<>
|
|
@@ -7418,7 +7696,7 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7418
7696
|
</div></Popover>
|
|
7419
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>
|
|
7420
7698
|
</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7421
|
-
{(_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>}
|
|
7422
7700
|
</span></Show>}</th>}</Key>
|
|
7423
7701
|
|
|
7424
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>
|
|
@@ -7426,8 +7704,8 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7426
7704
|
{<Show when={hasAnyFilterableColumn()}><tr class={"rdt-filter-row"} data-rozie-s-d5dcab4c="">
|
|
7427
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="">
|
|
7428
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="">
|
|
7429
|
-
{<Show when={columnIsFilterable(wh().header.column.id)
|
|
7430
|
-
{(_props.filterSlot ?? _props.slots?.['filter'])?.({ columnId
|
|
7707
|
+
{<Show when={columnIsFilterable(wh().header.column.id)}><span style={{ display: "contents" }} 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="" />}
|
|
7431
7709
|
</span></Show>}</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}</th>}</Key>
|
|
7432
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>
|
|
7433
7711
|
|
|
@@ -7443,20 +7721,20 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7443
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="">
|
|
7444
7722
|
|
|
7445
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="">
|
|
7446
|
-
{(_props.cellSlot ?? _props.slots?.['cell'])?.({ 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())}
|
|
7447
7725
|
</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7448
|
-
{<Show when={
|
|
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="">
|
|
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="" />}
|
|
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="">
|
|
7449
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>
|
|
7450
|
-
</select></Show>}><input type="number" data-editing-cell="" 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 style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7451
|
-
{(_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) })}
|
|
7452
|
-
</span></Show>}</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
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="">
|
|
7453
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>
|
|
7454
7732
|
<span class={"rdt-group-value"} data-rozie-s-d5dcab4c="">
|
|
7455
|
-
{(_props.cellSlot ?? _props.slots?.['cell'])?.({ 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())}
|
|
7456
7734
|
</span>
|
|
7457
7735
|
<span class={"rdt-group-count"} data-rozie-s-d5dcab4c="">{rozieDisplay('(' + groupSubRowCount(wr().row) + ')')}</span>
|
|
7458
7736
|
</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7459
|
-
{(_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="" />}
|
|
7460
7738
|
</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7461
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>
|
|
7462
7740
|
|
|
@@ -7464,7 +7742,7 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7464
7742
|
|
|
7465
7743
|
{<Show when={rowShowsDetail(wr().row)}><tr class={"rdt-detail-row"} role="row" data-detail-row={rozieAttr(wr().row.id)} data-rozie-s-d5dcab4c="">
|
|
7466
7744
|
<td class={"rdt-detail-cell"} colSpan={rozieAttr(windowedColSpan())} data-rozie-s-d5dcab4c="">
|
|
7467
|
-
{(_props.detailSlot ?? _props.slots?.['detail'])?.({ row
|
|
7745
|
+
{(_props.detailSlot ?? _props.slots?.['detail'])?.({ get row() { return wr().row.original; } })}
|
|
7468
7746
|
</td>
|
|
7469
7747
|
</tr></Show>}</>}</Key>
|
|
7470
7748
|
|