@rozie-ui/data-table-solid 0.3.1 → 0.4.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 +51 -2
- package/dist/index.cjs +275 -108
- package/dist/index.d.cts +40 -11
- package/dist/index.d.mts +40 -11
- package/dist/index.mjs +275 -108
- package/package.json +2 -2
- package/src/DataTable.tsx +373 -130
- package/src/helpers/columnDefUtils.ts +77 -1
package/src/DataTable.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { Show, createEffect, createSignal, mergeProps, on, onCleanup, onMount, s
|
|
|
3
3
|
import { Key } from '@solid-primitives/keyed';
|
|
4
4
|
import { __rozieInjectStyle, createControllableSignal, parseInlineStyle, rozieAttr, rozieClass, rozieContext, rozieDisplay } from '@rozie/runtime-solid';
|
|
5
5
|
import Popover from '@rozie-ui/popover-solid';
|
|
6
|
-
import { isSafeKey, wrapAggregationFn } from './helpers/columnDefUtils';
|
|
6
|
+
import { isSafeKey, wrapAggregationFn, indexDefsById, collectGroupableLeafDefs } from './helpers/columnDefUtils';
|
|
7
7
|
import { applyUpdater, clamp, focusables } from './helpers/indexMath';
|
|
8
8
|
import { escapeTsvField, parseTsv, tileGridToBox, tileIndex } from './helpers/tsvGrid';
|
|
9
9
|
import { replaceRowValue, indexOfRowIn, replaceRowValues } from './helpers/rowValueUtils';
|
|
@@ -353,18 +353,18 @@ interface GroupBarSlotCtx { grouping: any; groupableColumns: any; applyGrouping:
|
|
|
353
353
|
|
|
354
354
|
interface SelectAllSlotCtx { checked: any; indeterminate: any; toggle: any; }
|
|
355
355
|
|
|
356
|
+
interface SelectCellSlotCtx { row: any; checked: any; toggle: any; }
|
|
357
|
+
|
|
358
|
+
interface DetailSlotCtx { row: any; }
|
|
359
|
+
|
|
356
360
|
interface ColHeaderSlotCtx { columnId: any; column: any; label: any; }
|
|
357
361
|
|
|
358
362
|
interface FilterSlotCtx { columnId: any; value: any; uniqueValues: any; minMax: any; setFilter: any; }
|
|
359
363
|
|
|
360
|
-
interface SelectCellSlotCtx { row: any; checked: any; toggle: any; }
|
|
361
|
-
|
|
362
364
|
interface CellSlotCtx { columnId: any; column: any; row: any; value: any; }
|
|
363
365
|
|
|
364
366
|
interface EditorSlotCtx { columnId: any; column: any; row: any; value: any; commit: any; cancel: any; autofocus: any; }
|
|
365
367
|
|
|
366
|
-
interface DetailSlotCtx { row: any; }
|
|
367
|
-
|
|
368
368
|
interface DataTableProps {
|
|
369
369
|
/**
|
|
370
370
|
* The row data — `model: true`, so a committed cell/row edit writes a **fresh** array back through `r-model:data` (uncontrolled fallback `dataDefault`). A stable reference per Rozie's setup-once model — fed directly into table-core (never map/cloned in the watcher).
|
|
@@ -527,13 +527,13 @@ interface DataTableProps {
|
|
|
527
527
|
children?: JSX.Element;
|
|
528
528
|
groupBarSlot?: (ctx: GroupBarSlotCtx) => JSX.Element;
|
|
529
529
|
selectAllSlot?: (ctx: SelectAllSlotCtx) => JSX.Element;
|
|
530
|
+
selectCellSlot?: (ctx: SelectCellSlotCtx) => JSX.Element;
|
|
531
|
+
detailSlot?: (ctx: DetailSlotCtx) => JSX.Element;
|
|
530
532
|
colHeaderSlot?: (ctx: ColHeaderSlotCtx) => JSX.Element;
|
|
531
533
|
filterSlot?: (ctx: FilterSlotCtx) => JSX.Element;
|
|
532
|
-
selectCellSlot?: (ctx: SelectCellSlotCtx) => JSX.Element;
|
|
533
534
|
cellSlot?: (ctx: CellSlotCtx) => JSX.Element;
|
|
534
535
|
editorSlot?: (ctx: EditorSlotCtx) => JSX.Element;
|
|
535
|
-
|
|
536
|
-
slots?: Record<string, (ctx: any) => JSX.Element>;
|
|
536
|
+
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
537
|
ref?: (h: DataTableHandle) => void;
|
|
538
538
|
}
|
|
539
539
|
|
|
@@ -1304,6 +1304,12 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
1304
1304
|
let columnDefsCache: any[] | null = null;
|
|
1305
1305
|
let columnDefsCacheColumnsRef: any = undefined;
|
|
1306
1306
|
let columnDefsCacheColRegRef: any = undefined;
|
|
1307
|
+
// B1 (quick 260906-afh) — the def-lookup index, populated INSIDE this SAME memo block on
|
|
1308
|
+
// a cache MISS only (never rebuilt per call — a per-call recursive scan would restore the
|
|
1309
|
+
// O(N^2 x M) blowup D-23 removed, T-AFH-03). A top-level `let` lowers to a per-instance
|
|
1310
|
+
// `useRef` on React (verified in the emitted leaf), so this is instance-scoped like
|
|
1311
|
+
// columnDefsCache above.
|
|
1312
|
+
let columnDefsIndexCache: any = null;
|
|
1307
1313
|
function columnDefs() {
|
|
1308
1314
|
const cfg = local.columns || [];
|
|
1309
1315
|
const reg = colReg() || {};
|
|
@@ -1352,9 +1358,20 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
1352
1358
|
columnDefsCache = out;
|
|
1353
1359
|
columnDefsCacheColumnsRef = local.columns;
|
|
1354
1360
|
columnDefsCacheColRegRef = colReg();
|
|
1361
|
+
columnDefsIndexCache = indexDefsById(out);
|
|
1355
1362
|
return out;
|
|
1356
1363
|
}
|
|
1357
1364
|
|
|
1365
|
+
// defIndex: the def-lookup map for the CURRENT columnDefs() array. Calling columnDefs()
|
|
1366
|
+
// first is deliberate — either an O(1) reference-equality cache hit (columnDefsIndexCache
|
|
1367
|
+
// is already fresh) or a miss that repopulates BOTH slots together, so the index can never
|
|
1368
|
+
// go stale relative to the array. Falls back to an empty null-prototype map (never null/
|
|
1369
|
+
// undefined) so a caller can read it unconditionally.
|
|
1370
|
+
function defIndex() {
|
|
1371
|
+
columnDefs();
|
|
1372
|
+
return columnDefsIndexCache || Object.create(null);
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1358
1375
|
// The constant id of the auto-injected leading checkbox column (D-04). Distinct from
|
|
1359
1376
|
// any consumer column id (the registry/config guard never produces a leading "__").
|
|
1360
1377
|
const SELECT_COL_ID = '__rdt_select';
|
|
@@ -3034,10 +3051,18 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3034
3051
|
|
|
3035
3052
|
// Template helpers reading the resolved column-def metadata by id (plain fns — used
|
|
3036
3053
|
// in template predicates + interpolation; uniform on all 6, no $computed alias trap).
|
|
3054
|
+
// B1 (quick 260906-afh): reads the O(1) def-lookup index (defIndex(), columnBuilders.rzts)
|
|
3055
|
+
// instead of linearly scanning columnDefs() — which only ever held TOP-LEVEL entries, so a
|
|
3056
|
+
// NESTED group leaf (a `columns:` group child) was invisible to every caller (headerLabel,
|
|
3057
|
+
// columnIsFilterable, editMetaOf/columnEditable/editorTypeOf/editorOptionsOf) and silently
|
|
3058
|
+
// took the "no def" fallback. defIndex() resolves both top-level AND nested leaf ids. This
|
|
3059
|
+
// also removes the per-cell O(N) scan D-23 left in place — defIndex() is memoized in the
|
|
3060
|
+
// SAME cache-invalidation block as columnDefs() itself, never rebuilt per call.
|
|
3037
3061
|
function defFor(colId: any) {
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3062
|
+
if (colId == null) return null;
|
|
3063
|
+
const idx = defIndex();
|
|
3064
|
+
const d = idx[String(colId)];
|
|
3065
|
+
return d != null ? d : null;
|
|
3041
3066
|
}
|
|
3042
3067
|
// Per-row visible cells for the body loop. table-core memoizes row objects by id,
|
|
3043
3068
|
// so a re-pull after a column change (visibility/reorder/pin, or the late <Column>
|
|
@@ -3077,20 +3102,6 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3077
3102
|
const m = editMetaOf(colId);
|
|
3078
3103
|
return m && m.editorOptions != null ? m.editorOptions : [];
|
|
3079
3104
|
}
|
|
3080
|
-
// hasEditorSlot: this column routes through the consumer's #editor scoped slot (req-2)
|
|
3081
|
-
// — true only when the column declared editor='custom' AND the consumer actually
|
|
3082
|
-
// provided an #editor slot. Falls through to the built-in editor otherwise (e.g. a
|
|
3083
|
-
// column marked 'custom' with no slot supplied degrades to the text editor, never blank).
|
|
3084
|
-
function hasEditorSlot(colId: any) {
|
|
3085
|
-
return editorTypeOf(colId) === 'custom' && !!(_props.editorSlot ?? _props.slots?.["editor"]);
|
|
3086
|
-
}
|
|
3087
|
-
|
|
3088
|
-
// hasFilterSlot: the consumer supplied a #filter scoped slot, so it OWNS the per-column
|
|
3089
|
-
// filter UI (re-added in 72-05 alongside the dedicated filter row's `<slot name="filter">`
|
|
3090
|
-
// host — see the 72-03 removal note in that plan's SUMMARY for why this was briefly gone).
|
|
3091
|
-
function hasFilterSlot() {
|
|
3092
|
-
return !!(_props.filterSlot ?? _props.slots?.["filter"]);
|
|
3093
|
-
}
|
|
3094
3105
|
function columnIsFilterable(colId: any) {
|
|
3095
3106
|
const d = defFor(colId);
|
|
3096
3107
|
return !!(d && d.filterable);
|
|
@@ -3101,13 +3112,27 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3101
3112
|
}
|
|
3102
3113
|
|
|
3103
3114
|
// ── Column-management chrome (req-8/9/10/11) ────────────────────────────────────────
|
|
3104
|
-
// Live header width (px) for a
|
|
3105
|
-
//
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3115
|
+
// Live header width (px) for a <th> — drives the :style width binding. Takes the table-core
|
|
3116
|
+
// HEADER object (not a column id / Column lookup) and reads header.getSize() — deliberately,
|
|
3117
|
+
// NOT column.getSize(). table-core's own ColumnSizing feature (createHeader, always present —
|
|
3118
|
+
// it is in table-core's builtInFeatures, never opt-in) gives Header.getSize() a recursive
|
|
3119
|
+
// implementation: a LEAF header returns its own column's getSize() (identical to the old
|
|
3120
|
+
// column.getSize() path — byte-identical output there), but a GROUP header (one with
|
|
3121
|
+
// subHeaders, e.g. a multi-level `columns:` entry from buildConfigDef) SUMS every descendant
|
|
3122
|
+
// leaf column's getSize() instead of returning the group's own meaningless single-column
|
|
3123
|
+
// default (150px, table-core's defaultColumnSizing.size — group ColumnDefs never set `size`).
|
|
3124
|
+
// Before this fix, a colspan-N grouped <th> asked the browser for ONE column's worth of width
|
|
3125
|
+
// (150px) while spanning N columns; under `table-layout:fixed` the browser then divides that
|
|
3126
|
+
// single declared width ACROSS all N spanned <th>s (150/5 = 30px for this codebase's 5-column
|
|
3127
|
+
// "Group A" fixture) — a 5x collapse of the actual rendered column width, independent of (and
|
|
3128
|
+
// invisible to) columnSize()/the column virtualizer's windowing math, which reads
|
|
3129
|
+
// table.getVisibleLeafColumns()[i].getSize() directly and was never affected. Root cause +
|
|
3130
|
+
// fix confirmed via .planning/debug/datatable-d13-column-axis-all-targets.md and previously
|
|
3131
|
+
// documented as "Gap 1" in .planning/phases/87-.../deferred-items.md (the identical grouped-
|
|
3132
|
+
// header/colspan mismatch, found independently during 87-05/87-06 authoring and deferred).
|
|
3133
|
+
function headerWidth(header: any) {
|
|
3134
|
+
if (tick() < 0 || !header || typeof header.getSize !== 'function') return null;
|
|
3135
|
+
const w = header.getSize();
|
|
3111
3136
|
return w != null && w > 0 ? w + 'px' : null;
|
|
3112
3137
|
}
|
|
3113
3138
|
|
|
@@ -3224,15 +3249,18 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3224
3249
|
}
|
|
3225
3250
|
return '';
|
|
3226
3251
|
}
|
|
3227
|
-
// Combined inline style for a <th> (width + pin)
|
|
3228
|
-
//
|
|
3229
|
-
//
|
|
3230
|
-
//
|
|
3231
|
-
|
|
3252
|
+
// Combined inline style for a <th> (width + pin). Plain string concat — uniform on all 6, no
|
|
3253
|
+
// bound-object trap. zIndex=2 (see pinStyle) so a pinned header cell — which hosts the ⋯ menu's
|
|
3254
|
+
// floating content — always stacks above the pinned filter-row cell for the same column
|
|
3255
|
+
// (zIndex=1, its own default). Takes the HEADER object (not a bare colId) so headerWidth() can
|
|
3256
|
+
// read header.getSize() — the group-aware size (see headerWidth's own comment). pinStyle still
|
|
3257
|
+
// keys off the plain column id (pinning is a leaf-column-only concern; a grouped header never
|
|
3258
|
+
// pins as a unit in this codebase's model).
|
|
3259
|
+
function thStyle(header: any) {
|
|
3232
3260
|
let s = '';
|
|
3233
|
-
const w = headerWidth(
|
|
3261
|
+
const w = headerWidth(header);
|
|
3234
3262
|
if (w) s += 'width:' + w + ';';
|
|
3235
|
-
s += pinStyle(
|
|
3263
|
+
s += pinStyle(header && header.column ? header.column.id : null, 2);
|
|
3236
3264
|
return s;
|
|
3237
3265
|
}
|
|
3238
3266
|
|
|
@@ -3390,6 +3418,16 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3390
3418
|
function rowIsGrouped(row: any) {
|
|
3391
3419
|
return !!(tick() >= 0 && row && row.getIsGrouped && row.getIsGrouped());
|
|
3392
3420
|
}
|
|
3421
|
+
// rowIndexIsGrouped (quick 260906-cvo, C1/C2): THE single row-level editability/writability
|
|
3422
|
+
// predicate — a group-header row is a SYNTHETIC row whose `original` is table-core's
|
|
3423
|
+
// `leafRows[0].original` (the same fact cellSlotRow's header comment documents), so any
|
|
3424
|
+
// edit or bulk write resolved through it silently lands on an UNRELATED record. Every edit/
|
|
3425
|
+
// write guard in this component calls THIS predicate — never a re-implemented inline
|
|
3426
|
+
// `getIsGrouped()` check — so the invariant has one definition. Indexes into the SAME
|
|
3427
|
+
// `$data.rows` flattened row list rowIsGrouped reads.
|
|
3428
|
+
function rowIndexIsGrouped(rowIndex: any) {
|
|
3429
|
+
return rowIsGrouped((rows() || [])[rowIndex]);
|
|
3430
|
+
}
|
|
3393
3431
|
// groupingActive: grouping is currently engaged (a non-empty ordered key list). Drives the
|
|
3394
3432
|
// data-group-leaf marker so it is ABSENT when ungrouped (byte-identical-off, req-10).
|
|
3395
3433
|
function groupingActive() {
|
|
@@ -3405,22 +3443,100 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3405
3443
|
function cellIsAggregated(cellCtx: any) {
|
|
3406
3444
|
return !!(tick() >= 0 && cellCtx && cellCtx.getIsAggregated && cellCtx.getIsAggregated());
|
|
3407
3445
|
}
|
|
3408
|
-
// cellIsPlaceholder:
|
|
3409
|
-
//
|
|
3410
|
-
//
|
|
3411
|
-
//
|
|
3412
|
-
//
|
|
3446
|
+
// cellIsPlaceholder: VERIFIED against @tanstack/table-core@8.21.3 (ColumnGrouping.js:120-121,
|
|
3447
|
+
// quick 260906-afh premise correction). A placeholder cell is a cell IN A GROUPING COLUMN
|
|
3448
|
+
// that is NOT the row's OWN grouping column — `!cell.getIsGrouped() && column.getIsGrouped()`.
|
|
3449
|
+
// That is true both on a group-header row (for every OTHER grouping column) and on every leaf
|
|
3450
|
+
// row (for every grouping column) — it is NOT "never true on a group-header row" and it is NOT
|
|
3451
|
+
// "any non-grouped, non-aggregated cell". The operative consequence for this component: a
|
|
3452
|
+
// placeholder can only EVER be a grouping-column cell, so this branch can never reach a
|
|
3453
|
+
// non-grouping column — it does NOT and CANNOT guard the AGGREGATED-cell `row` leak
|
|
3454
|
+
// (cellSlotRow, below) fixes. Where it DOES apply (e.g. under multi-level grouping, the
|
|
3455
|
+
// OTHER grouping column on a group-header row), table-core still fills cell.getValue() with
|
|
3456
|
+
// the FIRST leaf row's value (cell.getValue() leaks e.g. "Oslo" onto a region-level group
|
|
3457
|
+
// line whose grouping is 'region', not 'city'); this branch renders BLANK via a dedicated
|
|
3458
|
+
// empty template so that leaked value never paints. Tick-gated exactly like cellIsGrouped so
|
|
3459
|
+
// the group chrome re-derives on a re-pull on the fine-grained targets (Solid/Lit).
|
|
3413
3460
|
function cellIsPlaceholder(cellCtx: any) {
|
|
3414
3461
|
return !!(tick() >= 0 && cellCtx && cellCtx.getIsPlaceholder && cellCtx.getIsPlaceholder());
|
|
3415
3462
|
}
|
|
3416
|
-
// groupSubRowCount: the number of underlying LEAF RECORDS under a group-header row (the
|
|
3417
|
-
// shown in the header, e.g. "North (40)"). row.subRows is the IMMEDIATE members — for
|
|
3418
|
-
// grouping those are sub-GROUPS, not records, so "North" with 2 categories / 40
|
|
3419
|
-
// "North (2)"
|
|
3420
|
-
// subRows
|
|
3421
|
-
//
|
|
3463
|
+
// groupSubRowCount: the number of underlying TRUE LEAF RECORDS under a group-header row (the
|
|
3464
|
+
// count shown in the header, e.g. "North (40)"). row.subRows is the IMMEDIATE members — for
|
|
3465
|
+
// MULTI-LEVEL grouping those are sub-GROUPS, not records, so "North" with 2 categories / 40
|
|
3466
|
+
// records would show "North (2)" off subRows alone. row.getLeafRows() is table-core's
|
|
3467
|
+
// `flattenBy(row.subRows, d => d.subRows)` (ColumnGrouping.js / utils.js, verified against
|
|
3468
|
+
// @tanstack/table-core@8.21.3) — it pushes EVERY node it walks, INCLUDING intermediate group
|
|
3469
|
+
// nodes, so under multi-level grouping it over-counts by exactly the number of sub-group
|
|
3470
|
+
// nodes between the row and its true leaves (C4, quick 260906-cvo: North with 2 city
|
|
3471
|
+
// sub-groups + 3 records reported 5, not 3). `row.getIsGrouped()` is `!!row.groupingColumnId`
|
|
3472
|
+
// — precisely the predicate that separates a group node from a real record — so filter the
|
|
3473
|
+
// flattened list on it rather than hand-rolling a recursive `subRows` walk (getLeafRows()
|
|
3474
|
+
// already flattens; the defect is purely that it does not filter). Single-level grouping is
|
|
3475
|
+
// numerically UNCHANGED: a leaf row has no `subRows`, so no node was ever miscounted there.
|
|
3422
3476
|
function groupSubRowCount(row: any) {
|
|
3423
|
-
|
|
3477
|
+
if (row && row.getLeafRows) {
|
|
3478
|
+
const leaves = row.getLeafRows();
|
|
3479
|
+
let n = 0;
|
|
3480
|
+
for (let i = 0; i < leaves.length; i++) {
|
|
3481
|
+
const r = leaves[i];
|
|
3482
|
+
if (!(r && r.getIsGrouped && r.getIsGrouped())) n = n + 1;
|
|
3483
|
+
}
|
|
3484
|
+
return n;
|
|
3485
|
+
}
|
|
3486
|
+
return row && row.subRows ? row.subRows.length : 0;
|
|
3487
|
+
}
|
|
3488
|
+
|
|
3489
|
+
// ── B2 (quick 260906-afh) — group-header row #cell slot descriptor ─────────────────────
|
|
3490
|
+
// PROBLEM: table-core builds a flattened group-header row via
|
|
3491
|
+
// `createRow(table, id, leafRows[0].original, …)` (getGroupedRowModel.js), so `row.original`
|
|
3492
|
+
// on a group row IS the FIRST LEAF's record. The #cell scoped slot's existing 4 call sites
|
|
3493
|
+
// all bound `:row="row.original"` (or `wr.row.original`), so an AGGREGATED cell (a
|
|
3494
|
+
// non-grouping column on a group row — cellIsGrouped()===false, cellIsPlaceholder()===false,
|
|
3495
|
+
// so it takes the #cell r-else branch, same as any ordinary leaf cell) silently handed a
|
|
3496
|
+
// consumer template the WRONG record's fields (T-AFH-05). The grouped cell itself (the
|
|
3497
|
+
// group's own column, .rdt-group-value) has the same #cell binding and the same leak.
|
|
3498
|
+
//
|
|
3499
|
+
// FIX: `cellSlotRow(row)` returns a STABLE GROUP DESCRIPTOR — never `row.original` — for a
|
|
3500
|
+
// group-header row, and `row.original` unchanged for every other row. The descriptor is an
|
|
3501
|
+
// OBJECT, never `null` (T-AFH-06 — a consumer already reading `row.foo` would throw on
|
|
3502
|
+
// Vue/Angular if handed null).
|
|
3503
|
+
//
|
|
3504
|
+
// Descriptor cache (T-AFH-02/T-AFH-04): a null-prototype map keyed on `String(row.id)`,
|
|
3505
|
+
// invalidated wholesale whenever `$data.rowModelVer` (bumped by every refreshRowModel, the
|
|
3506
|
+
// SAME reactive re-derivation discipline visibleCellsFor/rowIsGrouped use) differs from the
|
|
3507
|
+
// generation the map was built for — so the descriptor's REFERENCE IDENTITY is stable
|
|
3508
|
+
// across every cell of one group row within a row-model generation (an unstable reference
|
|
3509
|
+
// would thrash the fine-grained targets, Solid/Lit) and refreshed the moment the grouping
|
|
3510
|
+
// changes. Group row ids are built from consumer grouping VALUES, so the map MUST be
|
|
3511
|
+
// null-prototype — a `__proto__` grouping value must not reach Object.prototype.
|
|
3512
|
+
let groupRowDescriptorCache: any = null;
|
|
3513
|
+
let groupRowDescriptorCacheVer: any = undefined;
|
|
3514
|
+
function groupRowDescriptor(row: any) {
|
|
3515
|
+
const ver = rowModelVer();
|
|
3516
|
+
if (!groupRowDescriptorCache || groupRowDescriptorCacheVer !== ver) {
|
|
3517
|
+
groupRowDescriptorCache = Object.create(null);
|
|
3518
|
+
groupRowDescriptorCacheVer = ver;
|
|
3519
|
+
}
|
|
3520
|
+
const key = String(row.id);
|
|
3521
|
+
let d = groupRowDescriptorCache[key];
|
|
3522
|
+
if (!d) {
|
|
3523
|
+
const groupingColumnId = row.groupingColumnId != null ? row.groupingColumnId : '';
|
|
3524
|
+
const groupingValue = row.getGroupingValue ? row.getGroupingValue(groupingColumnId) : row.groupingValue;
|
|
3525
|
+
d = {
|
|
3526
|
+
isGroupRow: true,
|
|
3527
|
+
groupId: row.id,
|
|
3528
|
+
groupingColumnId,
|
|
3529
|
+
groupingValue,
|
|
3530
|
+
leafCount: groupSubRowCount(row)
|
|
3531
|
+
};
|
|
3532
|
+
groupRowDescriptorCache[key] = d;
|
|
3533
|
+
}
|
|
3534
|
+
return d;
|
|
3535
|
+
}
|
|
3536
|
+
// cellSlotRow: the #cell slot's `:row=` value. A group-header row gets the stable
|
|
3537
|
+
// descriptor above (never the leaked first-leaf record); every other row is unchanged.
|
|
3538
|
+
function cellSlotRow(row: any) {
|
|
3539
|
+
return rowIsGrouped(row) ? groupRowDescriptor(row) : row ? row.original : null;
|
|
3424
3540
|
}
|
|
3425
3541
|
// groupingKeys: the live ordered grouping array — slot prop for the headless #groupBar + the
|
|
3426
3542
|
// default styled-token reflection. Reads currentState() ($props.grouping ?? $data.groupingDefault),
|
|
@@ -3428,14 +3544,18 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
3428
3544
|
function groupingKeys() {
|
|
3429
3545
|
return currentState().grouping || [];
|
|
3430
3546
|
}
|
|
3431
|
-
// groupableColumns: the data columns OFFERED to the headless #groupBar
|
|
3432
|
-
//
|
|
3433
|
-
//
|
|
3547
|
+
// groupableColumns: the data columns OFFERED to the headless #groupBar — `[{ id, label }]`.
|
|
3548
|
+
// Excludes the chrome columns (select/expander are not in columnDefs()). C5+C6 (quick
|
|
3549
|
+
// 260906-cvo): delegates the actual walk to collectGroupableLeafDefs (columnDefUtils.ts) —
|
|
3550
|
+
// a GROUP column (a `columns:` group's own entry) is NEVER offered (it has no accessor and
|
|
3551
|
+
// cannot produce a grouping value, regardless of any `groupable` flag on it), and every
|
|
3552
|
+
// groupable NESTED leaf (a `columns:` group child, opted out via `groupable: false` like any
|
|
3553
|
+
// top-level leaf) IS offered, in declaration order. The consumer builds any bar/drag UI from
|
|
3554
|
+
// this; the component ships none.
|
|
3434
3555
|
function groupableColumns() {
|
|
3435
3556
|
const out = [];
|
|
3436
|
-
const defs = columnDefs();
|
|
3557
|
+
const defs = collectGroupableLeafDefs(columnDefs());
|
|
3437
3558
|
for (const d of defs as any) {
|
|
3438
|
-
if (!d || d.groupable === false) continue;
|
|
3439
3559
|
out.push({
|
|
3440
3560
|
id: d.id,
|
|
3441
3561
|
label: d.header != null ? d.header : d.id
|
|
@@ -4450,11 +4570,18 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
4450
4570
|
return;
|
|
4451
4571
|
}
|
|
4452
4572
|
// ── C2 (phase 63 wave-8): Enter on a GROUP-HEADER cell toggles that group's collapse/
|
|
4453
|
-
// expand (APG treegrid).
|
|
4454
|
-
//
|
|
4455
|
-
//
|
|
4456
|
-
//
|
|
4457
|
-
//
|
|
4573
|
+
// expand (APG treegrid). C1 (quick 260906-cvo) CORRECTION: the comment here used to claim
|
|
4574
|
+
// "a group cell is non-editable" as "the verified invariant" — that was FALSE AS WRITTEN.
|
|
4575
|
+
// It held only for the grouping column's OWN cell (cellIsGrouped's branch renders before
|
|
4576
|
+
// the editor branch); a non-grouping EDITABLE column's cell on a group row fell straight
|
|
4577
|
+
// through the branch chain to isEditing(...) and opened an editor (the C1 defect this
|
|
4578
|
+
// quick task closed). What is now TRUE, and WHY: isActiveCellEditable() carries an
|
|
4579
|
+
// explicit rowIndexIsGrouped(...) row guard (filterPaginationRowChrome.rzts), so EVERY
|
|
4580
|
+
// editable column's cell on a group row is non-editable — that is what makes the four
|
|
4581
|
+
// edit-entry branches above fall through to this one, not an incidental property of the
|
|
4582
|
+
// grouping column alone. Route it to the SAME onToggleExpand path the chevron uses (group
|
|
4583
|
+
// rows ride the expand model) so one Enter toggles the group. Body cells only (a
|
|
4584
|
+
// header-active Enter is unchanged);
|
|
4458
4585
|
// ($data.rows || [])[$data.activeRow] is the active flattened row (page-relative non-virtual /
|
|
4459
4586
|
// full-model virtual — both index $data.rows). Placed BEFORE the reserved enterControl branch.
|
|
4460
4587
|
else if (key === 'Enter' && !activeIsHeader() && rowIsGrouped((rows() || [])[activeRow()])) {
|
|
@@ -5243,6 +5370,11 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5243
5370
|
// rangeToTsv(): serialize the current range to TSV — rows joined by '\n', cells by '\t',
|
|
5244
5371
|
// reading each cell's value off the visible model by index (cellValueAt). A single active
|
|
5245
5372
|
// cell (no range) serializes that one cell. Each field is B10-escaped. Pure read — never writes.
|
|
5373
|
+
// C2 (quick 260906-cvo) — DELIBERATE NON-CHANGE: this is a READ, unlike applyGridToRange's
|
|
5374
|
+
// write funnel, and stays UNGUARDED for a group-header row on purpose. cellValueAt reads the
|
|
5375
|
+
// column's DISPLAYED aggregate value on a group row (table-core's cell.getValue()), which is
|
|
5376
|
+
// exactly what the user sees — serializing it is correct behavior, not a leak. Do not "fix"
|
|
5377
|
+
// this asymmetry; it is intentional.
|
|
5246
5378
|
function rangeToTsv() {
|
|
5247
5379
|
const box = normalizedRange();
|
|
5248
5380
|
const r0 = box ? box.r0 : activeRow();
|
|
@@ -5296,11 +5428,22 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5296
5428
|
for (let gr = 0; gr < grid.length; gr++) {
|
|
5297
5429
|
const r = originRow + gr;
|
|
5298
5430
|
if (r > maxRow) break;
|
|
5431
|
+
// C2 (quick 260906-cvo) — hoisted ONCE per ROW (never per cell): a group-header row's
|
|
5432
|
+
// `original` is table-core's `leafRows[0].original` (a synthetic row), so a write
|
|
5433
|
+
// resolved through it silently lands on an unrelated record. This ONE placement closes
|
|
5434
|
+
// pasteRange, cutRange, clearActiveRange AND fillRange — all four build a grid and hand
|
|
5435
|
+
// it to this single funnel, so guarding the four callers individually would be four
|
|
5436
|
+
// chances to miss one.
|
|
5437
|
+
const rowGrouped = rowIndexIsGrouped(r);
|
|
5299
5438
|
const cols = grid[gr] || [];
|
|
5300
5439
|
for (let gc = 0; gc < cols.length; gc++) {
|
|
5301
5440
|
const c = originCol + gc;
|
|
5302
5441
|
if (c > maxCol) break;
|
|
5442
|
+
// A group-row cell still counts toward `total` — it is a skipped TARGET, exactly like
|
|
5443
|
+
// a non-editable or validator-rejected cell — so the "N of M cells pasted" / "no cells
|
|
5444
|
+
// pasted" announce keeps its existing semantics (never silently under-reports M).
|
|
5303
5445
|
total = total + 1;
|
|
5446
|
+
if (rowGrouped) continue;
|
|
5304
5447
|
const colId = columnIdAt(r, c);
|
|
5305
5448
|
if (colId == null || !columnEditable(colId)) continue;
|
|
5306
5449
|
const rowObj = rowOriginalAt(r);
|
|
@@ -5579,8 +5722,25 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5579
5722
|
fillEdgeScrollRaf = null;
|
|
5580
5723
|
}
|
|
5581
5724
|
}
|
|
5582
|
-
|
|
5583
|
-
|
|
5725
|
+
// FILL_HITTEST_PROBE_RADIUS_PX / FILL_HITTEST_PROBE_STEP_PX (hardening, authorized alongside the
|
|
5726
|
+
// D-13 grouped-header width fix — .planning/debug/datatable-d13-column-axis-all-targets.md):
|
|
5727
|
+
// resolveCellAt() below hit-tests document.elementFromPoint at ONE exact pixel — structurally
|
|
5728
|
+
// fragile against a scrolling DOM by construction: any narrow column transiting past that fixed
|
|
5729
|
+
// screen point (the edge-auto-scroll rAF loop in fillDrag re-probes the SAME fixed point every
|
|
5730
|
+
// frame while gridScrollEl's content slides underneath it) has only a single-frame-scale window
|
|
5731
|
+
// to be caught, and a probe pixel landing exactly on a border/rounding edge between two adjacent
|
|
5732
|
+
// `<td>`/`<th>`s can miss both. cellIndexFromPoint widens the miss case ONLY: it tries the exact
|
|
5733
|
+
// point first (byte-identical to the pre-hardening behavior on a hit — this is not a behavior
|
|
5734
|
+
// change to the common case) and, only if that misses, fans out a small nearest-first horizontal
|
|
5735
|
+
// search before giving up. Vertical-only misses are not probed (rows are >=24px tall by design —
|
|
5736
|
+
// FILL_EDGE_SCROLL_PX itself — so a row is never narrower than a single scroll step; only COLUMN
|
|
5737
|
+
// width has no such floor, hence a horizontal-only widening).
|
|
5738
|
+
const FILL_HITTEST_PROBE_RADIUS_PX = 8;
|
|
5739
|
+
const FILL_HITTEST_PROBE_STEP_PX = 2;
|
|
5740
|
+
|
|
5741
|
+
// resolveCellAt: the exact-point hit-test (identical logic to the pre-hardening
|
|
5742
|
+
// cellIndexFromPoint body) extracted so it can be re-tried at nearby x-offsets below.
|
|
5743
|
+
function resolveCellAt(clientX: any, clientY: any) {
|
|
5584
5744
|
let el = document.elementFromPoint(clientX, clientY);
|
|
5585
5745
|
// Pierce OPEN shadow roots (Lit): document.elementFromPoint retargets to the shadow HOST, so
|
|
5586
5746
|
// a drag over the Lit data-table's shadow content would otherwise resolve the host (no cell)
|
|
@@ -5605,6 +5765,22 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5605
5765
|
c
|
|
5606
5766
|
};
|
|
5607
5767
|
}
|
|
5768
|
+
function cellIndexFromPoint(clientX: any, clientY: any) {
|
|
5769
|
+
if (typeof document === 'undefined' || !document.elementFromPoint) return null;
|
|
5770
|
+
const direct = resolveCellAt(clientX, clientY);
|
|
5771
|
+
if (direct) return direct;
|
|
5772
|
+
// Widened nearest-cell search: only reached when the exact point misses. Fans outward
|
|
5773
|
+
// (nearest-first, alternating +/-x) up to FILL_HITTEST_PROBE_RADIUS_PX before giving up —
|
|
5774
|
+
// catches a narrow column that transited past the fixed probe point on this exact frame
|
|
5775
|
+
// without changing which cell wins on an ordinary (non-edge-case) hit.
|
|
5776
|
+
for (let d = FILL_HITTEST_PROBE_STEP_PX; d <= FILL_HITTEST_PROBE_RADIUS_PX; d += FILL_HITTEST_PROBE_STEP_PX) {
|
|
5777
|
+
const right = resolveCellAt(clientX + d, clientY);
|
|
5778
|
+
if (right) return right;
|
|
5779
|
+
const left = resolveCellAt(clientX - d, clientY);
|
|
5780
|
+
if (left) return left;
|
|
5781
|
+
}
|
|
5782
|
+
return null;
|
|
5783
|
+
}
|
|
5608
5784
|
function onFillHandlePointerDown(e: any) {
|
|
5609
5785
|
if (!e) return;
|
|
5610
5786
|
if (e.preventDefault) e.preventDefault();
|
|
@@ -5806,7 +5982,13 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5806
5982
|
// isActiveCellEditable: the active cell sits in an editable column AND is a body cell
|
|
5807
5983
|
// (req-1). Gates the F2/Enter/printable edit-entry branches in onGridKeyDown; a
|
|
5808
5984
|
// non-editable active cell falls through to the reserved enterControl path.
|
|
5985
|
+
// C1 (quick 260906-cvo) — Layer 1: a group-header row is NEVER editable, regardless of
|
|
5986
|
+
// column. This is the single highest-value guard in the cluster: it closes Shift+F2, the
|
|
5987
|
+
// checkbox toggle, and the F2/Enter/printable edit-entry branches in ONE edit (they are all
|
|
5988
|
+
// `else if` branches gated on this predicate), AND restores fallthrough so Enter on a group
|
|
5989
|
+
// row reaches the group-toggle branch below them instead of opening an editor.
|
|
5809
5990
|
function isActiveCellEditable() {
|
|
5991
|
+
if (rowIndexIsGrouped(activeRow())) return false;
|
|
5810
5992
|
const colId = activeCellColumnId();
|
|
5811
5993
|
return colId != null && columnEditable(colId);
|
|
5812
5994
|
}
|
|
@@ -5824,6 +6006,14 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5824
6006
|
// non-virtual, wr.vi.index virtual).
|
|
5825
6007
|
function isEditing(rowIndex: any, colIndex: any) {
|
|
5826
6008
|
if (editVer() < 0) return false;
|
|
6009
|
+
// C1 (quick 260906-cvo) — Layer 6: the ONLY layer whose reachability does not depend on a
|
|
6010
|
+
// keystroke. Editing state is INDEX-based over the visible model, and nothing clears it
|
|
6011
|
+
// when the row model re-derives — a consumer that changes the grouping model WHILE a cell
|
|
6012
|
+
// editor is open can move a group-header row under the index $data.editingRow/
|
|
6013
|
+
// editingRowIndex still holds, rendering the editor on a group row with no beginEdit
|
|
6014
|
+
// involved. Placed AFTER the editVer read (preserves the Svelte/Solid re-derivation
|
|
6015
|
+
// discipline the header comment above documents).
|
|
6016
|
+
if (rowIndexIsGrouped(rowIndex)) return false;
|
|
5827
6017
|
if (editingRowIndex() != null && editingRowIndex() === rowIndex) {
|
|
5828
6018
|
const colId = columnIdAt(rowIndex, colIndex);
|
|
5829
6019
|
return colId != null && columnEditable(colId);
|
|
@@ -5915,39 +6105,73 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5915
6105
|
return row ? row.id : null;
|
|
5916
6106
|
}
|
|
5917
6107
|
|
|
6108
|
+
// resolveEditFocusCellEl(rowIndex, colIndex): the DOM cell element for an edit-focus
|
|
6109
|
+
// target, given an EXPLICIT index pair — NEVER a $data re-read inside this function or its
|
|
6110
|
+
// caller's poll closure. Every call site already knows this pair SYNCHRONOUSLY at the
|
|
6111
|
+
// moment it calls (beginEdit's own rowIndex/colIndex params; commitEdit's stable, already-
|
|
6112
|
+
// settled $data.editingRow/editingCol; beginRowEdit's rowIndex + the target column's
|
|
6113
|
+
// editable[].colIndex from editableColumnsForRow) — threading them through as PARAMETERS,
|
|
6114
|
+
// mirroring focusRowEditorAt's already-proven resolveCellEl(String(rowIndex), colIndex)
|
|
6115
|
+
// shape, closes the React batched-setState staleness class 88-05-SUMMARY.md documented
|
|
6116
|
+
// (REACT_STALE_GATE_SINGLE_CELL_BUG): the OLD gate read $data.editFocusColId SYNCHRONOUSLY,
|
|
6117
|
+
// in the SAME tick beginEdit's own setState call set it, and React's batching meant that
|
|
6118
|
+
// read saw the PRE-edit (null) value. A plain function argument threaded through — never a
|
|
6119
|
+
// reactive re-read — is not subject to that race, uniformly on all 6 targets.
|
|
6120
|
+
function resolveEditFocusCellEl(rowIndex: any, colIndex: any) {
|
|
6121
|
+
if (rowIndex == null || colIndex == null || rowIndex < 0 || colIndex < 0) return null;
|
|
6122
|
+
return resolveCellEl(String(rowIndex), colIndex);
|
|
6123
|
+
}
|
|
6124
|
+
|
|
5918
6125
|
// Focus the freshly-mounted editor (Pitfall 1, ROZ123): after beginEdit flips the editing
|
|
5919
6126
|
// state, the editor <input> does not exist until the framework commits the r-if branch
|
|
5920
|
-
// (React setState async; Solid/Lit/Svelte next reactive tick). Poll for the
|
|
5921
|
-
//
|
|
5922
|
-
//
|
|
6127
|
+
// (React setState async; Solid/Lit/Svelte next reactive tick). Poll for the target CELL's
|
|
6128
|
+
// marked built-in editor for ~30 frames — the five fast targets resolve on attempt 1, React
|
|
6129
|
+
// retries across its async commit. NEVER read $refs eagerly.
|
|
5923
6130
|
// B2: selectAll gates the post-focus el.select(). Select-all is right when entering
|
|
5924
6131
|
// edit IN PLACE (F2/Enter/click/row-edit/validation-reject — no seeded char, the user
|
|
5925
6132
|
// retypes), but WRONG on a type-to-edit entry where a printable key already seeded the
|
|
5926
6133
|
// draft (selecting the seeded char makes the next keystroke replace it: Zeta → eta).
|
|
5927
6134
|
// beginEdit threads `seed == null` so a seeded entry skips the select and the caret sits
|
|
5928
6135
|
// AFTER the seeded char; every other caller keeps the default select-all.
|
|
5929
|
-
//
|
|
5930
|
-
//
|
|
5931
|
-
//
|
|
5932
|
-
//
|
|
5933
|
-
//
|
|
5934
|
-
//
|
|
5935
|
-
//
|
|
5936
|
-
|
|
6136
|
+
// D-01/D-02 (88-07): REPLACES the deleted presence-check early-return gate AND the
|
|
6137
|
+
// gridRoot-wide `[data-editing-cell]` first-match query with a column-scoped, marker-driven
|
|
6138
|
+
// poll. Resolves the TARGET cell first (resolveEditFocusCellEl, mirroring
|
|
6139
|
+
// focusRowEditorAt's already-shipped two-step resolve), then queries for an editor carrying
|
|
6140
|
+
// BOTH `data-editing-cell` and the host-owned `data-builtin-editor` marker WITHIN that one
|
|
6141
|
+
// cell — "no marker found" (a drop-in target, D-01) bails immediately rather than reaching
|
|
6142
|
+
// into DOM the host does not own; "no editor at all yet" keeps polling (the framework hasn't
|
|
6143
|
+
// committed the r-if branch). This closes the D-02 wrong-column hole the old grid-wide query
|
|
6144
|
+
// left open (every editable cell mounts an editor at once in row-edit mode) AND fixes the
|
|
6145
|
+
// React staleness race documented above, as a side effect of no longer reading
|
|
6146
|
+
// $data.editFocusColId anywhere in this function.
|
|
6147
|
+
function focusEditorWhenReady(rowIndex: any, colIndex: any, selectAll = true) {
|
|
5937
6148
|
if (!gridRoot) return;
|
|
5938
|
-
// Editor-owns-focus contract: when the CURRENT focus target is a #editor drop-in, the host
|
|
5939
|
-
// does NOT reach into its DOM — the drop-in self-focuses via its own autofocus prop.
|
|
5940
|
-
if (editFocusColId() != null && hasEditorSlot(editFocusColId())) return;
|
|
5941
6149
|
let attempts = 0;
|
|
5942
6150
|
const tryFocus = () => {
|
|
5943
|
-
const
|
|
6151
|
+
const cellEl = resolveEditFocusCellEl(rowIndex, colIndex);
|
|
6152
|
+
const el = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell][data-builtin-editor]') : null;
|
|
6153
|
+
if (!el) {
|
|
6154
|
+
// Editor-owns-focus contract (quick 260711-i5m, D-01): if the cell ALREADY holds an
|
|
6155
|
+
// editor that carries only the base marker, it's a consumer drop-in — it owns its own
|
|
6156
|
+
// focus (EditorText's own $onMount + reactive `autofocus`). Bail immediately, zero
|
|
6157
|
+
// wasted frames, rather than burning the retry ceiling on DOM the host does not own.
|
|
6158
|
+
const anyEditor = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell]') : null;
|
|
6159
|
+
if (anyEditor) return;
|
|
6160
|
+
attempts = attempts + 1;
|
|
6161
|
+
if (attempts >= 30) return;
|
|
6162
|
+
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 16);
|
|
6163
|
+
return;
|
|
6164
|
+
}
|
|
5944
6165
|
// Do NOT stomp focus a later interaction already placed in a DIFFERENT column's editor of
|
|
5945
6166
|
// this row: focusEditorWhenReady only needs to get focus INTO the (first) freshly-mounted
|
|
5946
6167
|
// editor; if focus already sits in another editable cell, a late rAF re-focus would steal it
|
|
5947
6168
|
// back to the first editor and break row-mode Tab containment (the non-deterministic B21
|
|
5948
6169
|
// focus-theft). Compare the OWNING cell's data-col-index (NOT node identity) so a stale
|
|
5949
6170
|
// SAME-column editor node on Solid's node-replacing re-render still resolves as the target —
|
|
5950
|
-
// a genuinely dropped focus is still recovered.
|
|
6171
|
+
// a genuinely dropped focus is still recovered. Stays BROAD on `data-editing-cell` (NOT
|
|
6172
|
+
// narrowed to the builtin marker, D-02): focus validly placed inside a drop-in must still
|
|
6173
|
+
// count as "already placed" — narrowing this check would let a late rAF poll steal focus
|
|
6174
|
+
// back from a drop-in that legitimately holds it.
|
|
5951
6175
|
const ae = gridRoot && gridRoot.getRootNode ? gridRoot.getRootNode().activeElement : null;
|
|
5952
6176
|
if (ae && el && ae !== el && ae.closest && gridRoot.contains(ae) && ae.hasAttribute && ae.hasAttribute('data-editing-cell')) {
|
|
5953
6177
|
const aeCell = ae.closest('[data-grid-cell]');
|
|
@@ -5956,18 +6180,12 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5956
6180
|
const elCol = elCell ? elCell.getAttribute('data-col-index') : null;
|
|
5957
6181
|
if (aeCol != null && aeCol !== elCol) return;
|
|
5958
6182
|
}
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
} catch (e: any) {}
|
|
5965
|
-
}
|
|
5966
|
-
return;
|
|
6183
|
+
el.focus();
|
|
6184
|
+
if (selectAll && el.select) {
|
|
6185
|
+
try {
|
|
6186
|
+
el.select();
|
|
6187
|
+
} catch (e: any) {}
|
|
5967
6188
|
}
|
|
5968
|
-
attempts = attempts + 1;
|
|
5969
|
-
if (attempts >= 30) return;
|
|
5970
|
-
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 16);
|
|
5971
6189
|
};
|
|
5972
6190
|
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 0);
|
|
5973
6191
|
}
|
|
@@ -5998,6 +6216,10 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
5998
6216
|
// $data) so a Tab-advance that just setState'd activeRow/Col works on React. Clears any
|
|
5999
6217
|
// prior invalid state. Focus moves into the editor.
|
|
6000
6218
|
function beginEdit(rowIndex: any, colIndex: any, seed: any) {
|
|
6219
|
+
// C1 (quick 260906-cvo) — Layer 2: closes the `onGridClick` (singleClickEdit) path, which
|
|
6220
|
+
// calls beginEdit directly gated ONLY on columnEditable — isActiveCellEditable (Layer 1)
|
|
6221
|
+
// does not run on that path at all.
|
|
6222
|
+
if (rowIndexIsGrouped(rowIndex)) return;
|
|
6001
6223
|
const colId = columnIdAt(rowIndex, colIndex);
|
|
6002
6224
|
if (colId == null || !columnEditable(colId)) return;
|
|
6003
6225
|
// A new edit session starts — reset the sync idempotency latch so THIS session's eventual
|
|
@@ -6018,8 +6240,10 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6018
6240
|
// from it. Cleared on endEdit.
|
|
6019
6241
|
setEditFocusColId(colId);
|
|
6020
6242
|
// B2: a seeded (type-to-edit) entry must NOT select-all — keep the caret after the
|
|
6021
|
-
// seeded char so subsequent typing appends instead of replacing it.
|
|
6022
|
-
|
|
6243
|
+
// seeded char so subsequent typing appends instead of replacing it. rowIndex/colIndex
|
|
6244
|
+
// are THIS call's own params — passed through directly (D-02), never re-read off
|
|
6245
|
+
// $data.editingRow/editingCol inside the poll.
|
|
6246
|
+
focusEditorWhenReady(rowIndex, colIndex, seed == null);
|
|
6023
6247
|
}
|
|
6024
6248
|
|
|
6025
6249
|
// Return focus to a body cell AFTER the editor unmounts (commit/cancel). The display↔
|
|
@@ -6133,8 +6357,10 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6133
6357
|
const err = runValidator(colId, newValue, rowOriginal);
|
|
6134
6358
|
if (err !== true) {
|
|
6135
6359
|
// D-01: reject — keep the editor open, announce, re-trap focus, NEVER write the model.
|
|
6360
|
+
// $data.editingRow/editingCol are STABLE here (set by a prior beginEdit call, not this
|
|
6361
|
+
// same tick) — safe to read directly, unlike the deleted $data.editFocusColId gate.
|
|
6136
6362
|
setInvalid(err);
|
|
6137
|
-
focusEditorWhenReady();
|
|
6363
|
+
focusEditorWhenReady(editingRow(), editingCol());
|
|
6138
6364
|
return false;
|
|
6139
6365
|
}
|
|
6140
6366
|
setInvalid('');
|
|
@@ -6204,6 +6430,11 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6204
6430
|
// editor:'checkbox' columns only (Space/Enter/F2), full-row edit mode is unaffected (the
|
|
6205
6431
|
// editingRowIndex early return in onGridKeyDown already excludes it).
|
|
6206
6432
|
function toggleActiveBooleanCell() {
|
|
6433
|
+
// C1 (quick 260906-cvo) — Layer 4: the only write funnel bypassing both beginEdit/
|
|
6434
|
+
// commitEdit and applyGridToRange. Reachable today only through the Layer-1-gated
|
|
6435
|
+
// checkbox branch, so this line is redundant AT HEAD — it earns its place by making "no
|
|
6436
|
+
// write ever targets a group row" a property of the write funnels themselves.
|
|
6437
|
+
if (rowIndexIsGrouped(activeRow())) return;
|
|
6207
6438
|
const colId = columnIdAt(activeRow(), activeColIndex());
|
|
6208
6439
|
if (colId == null || !columnEditable(colId)) return;
|
|
6209
6440
|
const rowList = rows() || [];
|
|
@@ -6290,22 +6521,22 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6290
6521
|
|
|
6291
6522
|
// B21/B22: focus the row-mode editor at a given VISIBLE col index. In full-row edit every
|
|
6292
6523
|
// editable cell is already mounted as an editor, so this resolves the cell off gridRoot and
|
|
6293
|
-
// focuses its [data-editing-cell] control. Bounded rAF-poll (mirrors
|
|
6294
|
-
// so a React re-render that recreates the input across the focus call
|
|
6295
|
-
// all on text/number editors (a no-op try/catch on select/checkbox).
|
|
6296
|
-
//
|
|
6297
|
-
//
|
|
6298
|
-
//
|
|
6299
|
-
//
|
|
6300
|
-
//
|
|
6524
|
+
// focuses its [data-editing-cell][data-builtin-editor] control. Bounded rAF-poll (mirrors
|
|
6525
|
+
// focusEditorWhenReady) so a React re-render that recreates the input across the focus call
|
|
6526
|
+
// still lands it. select-all on text/number editors (a no-op try/catch on select/checkbox).
|
|
6527
|
+
// D-01/D-02 (88-07): the old columnIdAt + presence-check early-return gate is DELETED — the
|
|
6528
|
+
// host-owned data-builtin-editor marker replaces it. If the resolved cell already holds an
|
|
6529
|
+
// editor carrying ONLY the base data-editing-cell marker (no builtin marker), that's a
|
|
6530
|
+
// consumer drop-in — bail immediately, it owns its own focus (EditorText's own $onMount +
|
|
6531
|
+
// reactive `autofocus`, which the caller already flips via $data.editFocusColId). This
|
|
6532
|
+
// two-step resolve (resolveCellEl THEN a scoped query within that one cell) was ALREADY
|
|
6533
|
+
// column-scoped and correct — it is the shape focusEditorWhenReady's D-02 rework adopts.
|
|
6301
6534
|
function focusRowEditorAt(rowIndex: any, colIndex: any) {
|
|
6302
6535
|
if (!gridRoot) return;
|
|
6303
|
-
const colId = columnIdAt(rowIndex, colIndex);
|
|
6304
|
-
if (colId != null && hasEditorSlot(colId)) return;
|
|
6305
6536
|
let attempts = 0;
|
|
6306
6537
|
const tryFocus = () => {
|
|
6307
6538
|
const cellEl = resolveCellEl(String(rowIndex), colIndex);
|
|
6308
|
-
const ed = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell]') : null;
|
|
6539
|
+
const ed = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell][data-builtin-editor]') : null;
|
|
6309
6540
|
if (ed) {
|
|
6310
6541
|
ed.focus();
|
|
6311
6542
|
if (ed.select) {
|
|
@@ -6315,6 +6546,11 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6315
6546
|
}
|
|
6316
6547
|
return;
|
|
6317
6548
|
}
|
|
6549
|
+
// No marked built-in editor yet in this cell: a drop-in mounted there owns its own
|
|
6550
|
+
// focus — bail immediately (D-02) rather than burning the retry ceiling on DOM the
|
|
6551
|
+
// host does not own. No editor at all yet just means "keep polling."
|
|
6552
|
+
const any = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell]') : null;
|
|
6553
|
+
if (any) return;
|
|
6318
6554
|
attempts = attempts + 1;
|
|
6319
6555
|
if (attempts >= 30) return;
|
|
6320
6556
|
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 16);
|
|
@@ -6331,6 +6567,11 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6331
6567
|
function beginRowEdit(row: any) {
|
|
6332
6568
|
const rowIndex = rowIndexOf(row);
|
|
6333
6569
|
if (rowIndex < 0) return;
|
|
6570
|
+
// C1 (quick 260906-cvo) — Layer 5: a second, independent editing-state funnel that takes a
|
|
6571
|
+
// row OBJECT from its caller. Reachable today only via Shift+F2 (Layer 1), so also
|
|
6572
|
+
// redundant at HEAD; kept for the same reason as Layer 4 — it is a mutation entry point,
|
|
6573
|
+
// and the natural call site for a future #rowActions "Edit" drop-in button.
|
|
6574
|
+
if (rowIndexIsGrouped(rowIndex)) return;
|
|
6334
6575
|
const editable = editableColumnsForRow(rowIndex);
|
|
6335
6576
|
if (editable.length === 0) return;
|
|
6336
6577
|
// A new edit session starts — reset the sync idempotency latch (see editCellLifecycle.rzts).
|
|
@@ -6356,9 +6597,11 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
6356
6597
|
// Editor-owns-focus contract (quick 260711-i5m): the row's FIRST editable column is the
|
|
6357
6598
|
// initial focus target — editorAutofocusFor derives the reactive `autofocus` #editor scope
|
|
6358
6599
|
// prop from it (a built-in column is also host-focused below via focusEditorWhenReady; a
|
|
6359
|
-
// drop-in column self-focuses via its own $onMount, gated off the host reach-in
|
|
6600
|
+
// drop-in column self-focuses via its own $onMount, gated off the host reach-in via D-01's
|
|
6601
|
+
// marker). editable[0].colIndex is THIS call's own already-resolved value (D-02) — passed
|
|
6602
|
+
// through directly, never re-read off $data.editFocusColId inside the poll.
|
|
6360
6603
|
setEditFocusColId(editable[0].colId);
|
|
6361
|
-
focusEditorWhenReady();
|
|
6604
|
+
focusEditorWhenReady(rowIndex, editable[0].colIndex);
|
|
6362
6605
|
}
|
|
6363
6606
|
|
|
6364
6607
|
// commitRow(): validate EVERY edited column (D-01 — keep the row open if ANY fails: set
|
|
@@ -7153,19 +7396,19 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7153
7396
|
</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="">
|
|
7154
7397
|
<thead class={"rdt-thead"} role="rowgroup" data-rozie-s-d5dcab4c="">
|
|
7155
7398
|
<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="">
|
|
7156
|
-
<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()
|
|
7399
|
+
<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="">
|
|
7157
7400
|
|
|
7158
7401
|
|
|
7159
7402
|
{<Show when={isSelectColumn(header().column.id)} fallback={<Show when={isExpanderColumn(header().column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7160
7403
|
|
|
7161
7404
|
{<Show when={header().column.getCanSort && header().column.getCanSort()} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7162
7405
|
<span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
|
|
7163
|
-
{(_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? rozieDisplay(headerLabel(header().column.id))}
|
|
7406
|
+
{_props.slots?.[`colHeader-${header().column.id}`]?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? rozieDisplay(headerLabel(header().column.id))}
|
|
7164
7407
|
</span>
|
|
7165
7408
|
</span>}><button type="button" class={"rdt-sort-btn"} onClick={($event: MouseEvent & { currentTarget: HTMLButtonElement; target: Element }) => { onHeaderSort(header().column.id, $event); }} data-rozie-s-d5dcab4c="">
|
|
7166
7409
|
|
|
7167
7410
|
<span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
|
|
7168
|
-
{(_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? rozieDisplay(headerLabel(header().column.id))}
|
|
7411
|
+
{_props.slots?.[`colHeader-${header().column.id}`]?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: header().column.id, column: header().column, label: headerLabel(header().column.id) }) ?? rozieDisplay(headerLabel(header().column.id))}
|
|
7169
7412
|
</span>
|
|
7170
7413
|
<span class={"rdt-sort-ind"} aria-hidden="true" data-rozie-s-d5dcab4c="">{rozieDisplay(sortIndicator(header().column.id))}</span>
|
|
7171
7414
|
</button></Show>}<Popover trigger="click" placement="bottom-end" strategy="fixed" offset={4} data-rozie-s-d5dcab4c="" anchorSlot={() => (<>
|
|
@@ -7187,8 +7430,8 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7187
7430
|
{<Show when={hasAnyFilterableColumn()}><tr class={"rdt-filter-row"} data-rozie-s-d5dcab4c="">
|
|
7188
7431
|
<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="">
|
|
7189
7432
|
{<Show when={isSelectColumn(header().column.id)} fallback={<Show when={isExpanderColumn(header().column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7190
|
-
{<Show when={columnIsFilterable(header().column.id)
|
|
7191
|
-
{(_props.filterSlot ?? _props.slots?.['filter'])?.({ columnId: header().column.id, value: columnFilterValue(header().column.id), uniqueValues: getFacetedUniqueValues(header().column.id), minMax: getFacetedMinMaxValues(header().column.id), setFilter: setColumnFilter })}
|
|
7433
|
+
{<Show when={columnIsFilterable(header().column.id)}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7434
|
+
{_props.slots?.[`filter-${header().column.id}`]?.({ columnId: header().column.id, value: columnFilterValue(header().column.id), uniqueValues: getFacetedUniqueValues(header().column.id), minMax: getFacetedMinMaxValues(header().column.id), setFilter: setColumnFilter }) ?? (_props.filterSlot ?? _props.slots?.['filter'])?.({ columnId: header().column.id, value: columnFilterValue(header().column.id), uniqueValues: getFacetedUniqueValues(header().column.id), minMax: getFacetedMinMaxValues(header().column.id), setFilter: setColumnFilter }) ?? <input type="text" aria-label={rozieAttr('Filter ' + headerLabel(header().column.id))} class={"rdt-col-filter"} value={columnFilterValue(header().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onColumnFilterInput(header().column.id, $event); }} onClick={($event: MouseEvent & { currentTarget: HTMLInputElement; target: Element }) => { stopEvent($event); }} data-rozie-s-d5dcab4c="" />}
|
|
7192
7435
|
</span></Show>}</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}</th>}</Key>
|
|
7193
7436
|
</tr></Show>}</thead>
|
|
7194
7437
|
|
|
@@ -7199,20 +7442,20 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7199
7442
|
<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="">
|
|
7200
7443
|
|
|
7201
7444
|
{<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="">
|
|
7202
|
-
{(_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: row()
|
|
7445
|
+
{_props.slots?.[`cell-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: cell().getValue() }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: cell().getValue() }) ?? rozieDisplay(cell().getValue())}
|
|
7203
7446
|
</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7204
|
-
{<Show when={
|
|
7447
|
+
{<Show when={editorTypeOf(cell().column.id) === 'number'} fallback={<Show when={editorTypeOf(cell().column.id) === 'select'} fallback={<Show when={editorTypeOf(cell().column.id) === 'checkbox'} fallback={<Show when={editorTypeOf(cell().column.id) === 'custom'} fallback={<input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7448
|
+
{_props.slots?.[`editor-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, rowIndexOf(row())) }) ?? (_props.editorSlot ?? _props.slots?.['editor'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, rowIndexOf(row())) }) ?? <input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}
|
|
7449
|
+
</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="">
|
|
7205
7450
|
<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>
|
|
7206
|
-
</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="">
|
|
7207
|
-
{(_props.editorSlot ?? _props.slots?.['editor'])?.({ columnId: cell().column.id, column: cell().column, row: row().original, value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, rowIndexOf(row())) })}
|
|
7208
|
-
</span></Show>}</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7451
|
+
</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="">
|
|
7209
7452
|
<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>
|
|
7210
7453
|
<span class={"rdt-group-value"} data-rozie-s-d5dcab4c="">
|
|
7211
|
-
{(_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: row()
|
|
7454
|
+
{_props.slots?.[`cell-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: cell().getValue() }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(row()), value: cell().getValue() }) ?? rozieDisplay(cell().getValue())}
|
|
7212
7455
|
</span>
|
|
7213
7456
|
<span class={"rdt-group-count"} data-rozie-s-d5dcab4c="">{rozieDisplay('(' + groupSubRowCount(row()) + ')')}</span>
|
|
7214
7457
|
</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7215
|
-
{(_props.selectCellSlot ?? _props.slots?.['selectCell'])?.({ row: row()
|
|
7458
|
+
{(_props.selectCellSlot ?? _props.slots?.['selectCell'])?.({ row: cellSlotRow(row()), checked: rowIsSelected(row()), toggle: e => onToggleRow(row(), e) }) ?? <input type="checkbox" aria-label="Select row" class={"rdt-select-row"} checked={rowIsSelected(row())} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleRow(row(), $event); }} data-rozie-s-d5dcab4c="" />}
|
|
7216
7459
|
</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7217
7460
|
{<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>
|
|
7218
7461
|
</tr>
|
|
@@ -7228,15 +7471,15 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7228
7471
|
<thead class={"rdt-thead"} role="rowgroup" data-rozie-s-d5dcab4c="">
|
|
7229
7472
|
<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="">
|
|
7230
7473
|
|
|
7231
|
-
{<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
|
|
7474
|
+
{<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="">
|
|
7232
7475
|
{<Show when={isSelectColumn(wh().header.column.id)} fallback={<Show when={isExpanderColumn(wh().header.column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7233
7476
|
{<Show when={wh().header.column.getCanSort && wh().header.column.getCanSort()} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7234
7477
|
<span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
|
|
7235
|
-
{(_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
|
|
7478
|
+
{_props.slots?.[`colHeader-${wh().header.column.id}`]?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
|
|
7236
7479
|
</span>
|
|
7237
7480
|
</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="">
|
|
7238
7481
|
<span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
|
|
7239
|
-
{(_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
|
|
7482
|
+
{_props.slots?.[`colHeader-${wh().header.column.id}`]?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? (_props.colHeaderSlot ?? _props.slots?.['colHeader'])?.({ columnId: wh().header.column.id, column: wh().header.column, label: headerLabel(wh().header.column.id) }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
|
|
7240
7483
|
</span>
|
|
7241
7484
|
<span class={"rdt-sort-ind"} aria-hidden="true" data-rozie-s-d5dcab4c="">{rozieDisplay(sortIndicator(wh().header.column.id))}</span>
|
|
7242
7485
|
</button></Show>}<Popover trigger="click" placement="bottom-end" strategy="fixed" offset={4} data-rozie-s-d5dcab4c="" anchorSlot={() => (<>
|
|
@@ -7258,8 +7501,8 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7258
7501
|
{<Show when={hasAnyFilterableColumn()}><tr class={"rdt-filter-row"} data-rozie-s-d5dcab4c="">
|
|
7259
7502
|
{<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="">
|
|
7260
7503
|
{<Show when={isSelectColumn(wh().header.column.id)} fallback={<Show when={isExpanderColumn(wh().header.column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7261
|
-
{<Show when={columnIsFilterable(wh().header.column.id)
|
|
7262
|
-
{(_props.filterSlot ?? _props.slots?.['filter'])?.({ columnId: wh().header.column.id, value: columnFilterValue(wh().header.column.id), uniqueValues: getFacetedUniqueValues(wh().header.column.id), minMax: getFacetedMinMaxValues(wh().header.column.id), setFilter: setColumnFilter })}
|
|
7504
|
+
{<Show when={columnIsFilterable(wh().header.column.id)}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7505
|
+
{_props.slots?.[`filter-${wh().header.column.id}`]?.({ columnId: wh().header.column.id, value: columnFilterValue(wh().header.column.id), uniqueValues: getFacetedUniqueValues(wh().header.column.id), minMax: getFacetedMinMaxValues(wh().header.column.id), setFilter: setColumnFilter }) ?? (_props.filterSlot ?? _props.slots?.['filter'])?.({ columnId: wh().header.column.id, value: columnFilterValue(wh().header.column.id), uniqueValues: getFacetedUniqueValues(wh().header.column.id), minMax: getFacetedMinMaxValues(wh().header.column.id), setFilter: setColumnFilter }) ?? <input type="text" aria-label={rozieAttr('Filter ' + headerLabel(wh().header.column.id))} class={"rdt-col-filter"} value={columnFilterValue(wh().header.column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onColumnFilterInput(wh().header.column.id, $event); }} onClick={($event: MouseEvent & { currentTarget: HTMLInputElement; target: Element }) => { stopEvent($event); }} data-rozie-s-d5dcab4c="" />}
|
|
7263
7506
|
</span></Show>}</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}</th>}</Key>
|
|
7264
7507
|
{<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>
|
|
7265
7508
|
|
|
@@ -7275,20 +7518,20 @@ export default function DataTable(_props: DataTableProps): JSX.Element {
|
|
|
7275
7518
|
{<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="">
|
|
7276
7519
|
|
|
7277
7520
|
{<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="">
|
|
7278
|
-
{(_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: wr().row
|
|
7521
|
+
{_props.slots?.[`cell-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: cell().getValue() }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: cell().getValue() }) ?? rozieDisplay(cell().getValue())}
|
|
7279
7522
|
</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7280
|
-
{<Show when={
|
|
7523
|
+
{<Show when={editorTypeOf(cell().column.id) === 'number'} fallback={<Show when={editorTypeOf(cell().column.id) === 'select'} fallback={<Show when={editorTypeOf(cell().column.id) === 'checkbox'} fallback={<Show when={editorTypeOf(cell().column.id) === 'custom'} fallback={<input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7524
|
+
{_props.slots?.[`editor-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, wr().vi.index) }) ?? (_props.editorSlot ?? _props.slots?.['editor'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, wr().vi.index) }) ?? <input type="text" data-editing-cell="" data-builtin-editor="" class={"rdt-cell-editor"} value={editorValueFor(cell().column.id)} onInput={($event: InputEvent & { currentTarget: HTMLInputElement; target: Element }) => { onCellEditorInput(cell().column.id, $event); }} onKeyDown={($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorKeyDown($event); }} onBlur={($event: FocusEvent & { currentTarget: HTMLInputElement; target: Element }) => { onEditorBlur($event); }} data-rozie-s-d5dcab4c="" />}
|
|
7525
|
+
</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="">
|
|
7281
7526
|
<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>
|
|
7282
|
-
</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="">
|
|
7283
|
-
{(_props.editorSlot ?? _props.slots?.['editor'])?.({ columnId: cell().column.id, column: cell().column, row: wr().row.original, value: editorValueFor(cell().column.id), commit: editorCommitFor(cell().column.id), cancel: editorCancelFor(), autofocus: editorAutofocusFor(cell().column.id, wr().vi.index) })}
|
|
7284
|
-
</span></Show>}</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7527
|
+
</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="">
|
|
7285
7528
|
<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>
|
|
7286
7529
|
<span class={"rdt-group-value"} data-rozie-s-d5dcab4c="">
|
|
7287
|
-
{(_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: wr().row
|
|
7530
|
+
{_props.slots?.[`cell-${cell().column.id}`]?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: cell().getValue() }) ?? (_props.cellSlot ?? _props.slots?.['cell'])?.({ columnId: cell().column.id, column: cell().column, row: cellSlotRow(wr().row), value: cell().getValue() }) ?? rozieDisplay(cell().getValue())}
|
|
7288
7531
|
</span>
|
|
7289
7532
|
<span class={"rdt-group-count"} data-rozie-s-d5dcab4c="">{rozieDisplay('(' + groupSubRowCount(wr().row) + ')')}</span>
|
|
7290
7533
|
</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7291
|
-
{(_props.selectCellSlot ?? _props.slots?.['selectCell'])?.({ row: wr().row
|
|
7534
|
+
{(_props.selectCellSlot ?? _props.slots?.['selectCell'])?.({ row: cellSlotRow(wr().row), checked: rowIsSelected(wr().row), toggle: e => onToggleRow(wr().row, e) }) ?? <input type="checkbox" aria-label="Select row" class={"rdt-select-row"} checked={rowIsSelected(wr().row)} onChange={($event: Event & { currentTarget: HTMLInputElement; target: Element }) => { onToggleRow(wr().row, $event); }} data-rozie-s-d5dcab4c="" />}
|
|
7292
7535
|
</span></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
|
|
7293
7536
|
{<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>
|
|
7294
7537
|
|