@gridkitjs/react 0.0.0-dev-20261106222533
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/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/index.d.ts +495 -0
- package/dist/index.js +4978 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,4978 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/DataGrid/DataGrid.tsx
|
|
4
|
+
import {
|
|
5
|
+
useEffect as useEffect7,
|
|
6
|
+
useId as useId2,
|
|
7
|
+
useImperativeHandle as useImperativeHandle3,
|
|
8
|
+
useMemo as useMemo5,
|
|
9
|
+
useRef as useRef21,
|
|
10
|
+
useState as useState20
|
|
11
|
+
} from "react";
|
|
12
|
+
import {
|
|
13
|
+
moveColumnBefore,
|
|
14
|
+
resolveColumnHeaderText as resolveColumnHeaderText2,
|
|
15
|
+
resolveMessages,
|
|
16
|
+
resolveRows,
|
|
17
|
+
totalColumnWidth
|
|
18
|
+
} from "@gridkitjs/core";
|
|
19
|
+
|
|
20
|
+
// src/DataGrid/components/GridColgroup.tsx
|
|
21
|
+
import { jsx } from "react/jsx-runtime";
|
|
22
|
+
function GridColgroup({ columns }) {
|
|
23
|
+
return /* @__PURE__ */ jsx("colgroup", { children: columns.map((entry) => /* @__PURE__ */ jsx("col", { style: { width: entry.width } }, entry.id)) });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/DataGrid/components/GridHeader.tsx
|
|
27
|
+
import { createPortal } from "react-dom";
|
|
28
|
+
import {
|
|
29
|
+
buildKeyShortcuts,
|
|
30
|
+
intentOf,
|
|
31
|
+
isColumnFiltered,
|
|
32
|
+
KEYBOARD_STEP,
|
|
33
|
+
resolveColumnFilterMenu,
|
|
34
|
+
sortDirectionFor,
|
|
35
|
+
sortPriorityFor
|
|
36
|
+
} from "@gridkitjs/core";
|
|
37
|
+
|
|
38
|
+
// src/DataGrid/ariaAttr.ts
|
|
39
|
+
function ariaAttr(condition, key, value) {
|
|
40
|
+
return condition ? { [key]: value } : {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/DataGrid/classNames.ts
|
|
44
|
+
function classNames(...values) {
|
|
45
|
+
return values.filter(Boolean).join(" ");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/DataGrid/icons.tsx
|
|
49
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
50
|
+
function Icon({ children }) {
|
|
51
|
+
return /* @__PURE__ */ jsx2(
|
|
52
|
+
"svg",
|
|
53
|
+
{
|
|
54
|
+
viewBox: "0 0 24 24",
|
|
55
|
+
fill: "none",
|
|
56
|
+
stroke: "currentColor",
|
|
57
|
+
strokeWidth: 2,
|
|
58
|
+
strokeLinecap: "round",
|
|
59
|
+
strokeLinejoin: "round",
|
|
60
|
+
"aria-hidden": "true",
|
|
61
|
+
children
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
function ChevronsUpDownIcon() {
|
|
66
|
+
return /* @__PURE__ */ jsxs(Icon, { children: [
|
|
67
|
+
/* @__PURE__ */ jsx2("path", { d: "m7 15 5 5 5-5" }),
|
|
68
|
+
/* @__PURE__ */ jsx2("path", { d: "m7 9 5-5 5 5" })
|
|
69
|
+
] });
|
|
70
|
+
}
|
|
71
|
+
function ChevronUpIcon() {
|
|
72
|
+
return /* @__PURE__ */ jsx2(Icon, { children: /* @__PURE__ */ jsx2("path", { d: "m18 15-6-6-6 6" }) });
|
|
73
|
+
}
|
|
74
|
+
function GroupIcon() {
|
|
75
|
+
return /* @__PURE__ */ jsxs(Icon, { children: [
|
|
76
|
+
/* @__PURE__ */ jsx2("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }),
|
|
77
|
+
/* @__PURE__ */ jsx2("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }),
|
|
78
|
+
/* @__PURE__ */ jsx2("rect", { x: "8.5", y: "14", width: "7", height: "7", rx: "1" })
|
|
79
|
+
] });
|
|
80
|
+
}
|
|
81
|
+
function FilterIcon() {
|
|
82
|
+
return /* @__PURE__ */ jsx2(Icon, { children: /* @__PURE__ */ jsx2("path", { d: "M22 3H2l8 9.46V19l4 2v-8.54z" }) });
|
|
83
|
+
}
|
|
84
|
+
function ChevronLeftIcon() {
|
|
85
|
+
return /* @__PURE__ */ jsx2(Icon, { children: /* @__PURE__ */ jsx2("path", { d: "m15 18-6-6 6-6" }) });
|
|
86
|
+
}
|
|
87
|
+
function ChevronRightIcon() {
|
|
88
|
+
return /* @__PURE__ */ jsx2(Icon, { children: /* @__PURE__ */ jsx2("path", { d: "m9 18 6-6-6-6" }) });
|
|
89
|
+
}
|
|
90
|
+
function ChevronsLeftIcon() {
|
|
91
|
+
return /* @__PURE__ */ jsxs(Icon, { children: [
|
|
92
|
+
/* @__PURE__ */ jsx2("path", { d: "m11 17-5-5 5-5" }),
|
|
93
|
+
/* @__PURE__ */ jsx2("path", { d: "m18 17-5-5 5-5" })
|
|
94
|
+
] });
|
|
95
|
+
}
|
|
96
|
+
function ChevronsRightIcon() {
|
|
97
|
+
return /* @__PURE__ */ jsxs(Icon, { children: [
|
|
98
|
+
/* @__PURE__ */ jsx2("path", { d: "m6 17 5-5-5-5" }),
|
|
99
|
+
/* @__PURE__ */ jsx2("path", { d: "m13 17 5-5-5-5" })
|
|
100
|
+
] });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/DataGrid/isOwnEvent.ts
|
|
104
|
+
function isOwnEvent(event) {
|
|
105
|
+
return event.target instanceof Node && event.currentTarget.contains(event.target);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/DataGrid/useGridNavigation.ts
|
|
109
|
+
import {
|
|
110
|
+
useEffect,
|
|
111
|
+
useLayoutEffect,
|
|
112
|
+
useState,
|
|
113
|
+
useSyncExternalStore
|
|
114
|
+
} from "react";
|
|
115
|
+
import { HEADER_ROW } from "@gridkitjs/core";
|
|
116
|
+
import {
|
|
117
|
+
createGridFocus,
|
|
118
|
+
findBodyRow,
|
|
119
|
+
measurePageSize
|
|
120
|
+
} from "@gridkitjs/dom";
|
|
121
|
+
function tabIndexFor(columnIndex, focusedColumnIndex) {
|
|
122
|
+
return columnIndex === focusedColumnIndex ? 0 : -1;
|
|
123
|
+
}
|
|
124
|
+
function useGridNavigation({
|
|
125
|
+
headerTableRef,
|
|
126
|
+
bodyTableRef,
|
|
127
|
+
rowCount,
|
|
128
|
+
columnCount,
|
|
129
|
+
isSkippableRow,
|
|
130
|
+
virtualRange
|
|
131
|
+
}) {
|
|
132
|
+
const options = {
|
|
133
|
+
rowCount,
|
|
134
|
+
columnCount,
|
|
135
|
+
isSkippableRow,
|
|
136
|
+
virtualRange
|
|
137
|
+
};
|
|
138
|
+
const [gridFocus] = useState(() => createGridFocus(options));
|
|
139
|
+
gridFocus.setOptions(options);
|
|
140
|
+
const focus = useSyncExternalStore(
|
|
141
|
+
gridFocus.subscribe,
|
|
142
|
+
gridFocus.getFocus,
|
|
143
|
+
gridFocus.getFocus
|
|
144
|
+
);
|
|
145
|
+
const [rows] = useState(() => ({
|
|
146
|
+
getHeaderRow: () => headerTableRef.current?.tHead?.rows[0] ?? null,
|
|
147
|
+
getBodyRow: (rowIndex) => findBodyRow(bodyTableRef.current, rowIndex)
|
|
148
|
+
}));
|
|
149
|
+
useLayoutEffect(() => gridFocus.attach(rows), [gridFocus, rows]);
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
gridFocus.focusDrawnCell(focus);
|
|
152
|
+
});
|
|
153
|
+
return {
|
|
154
|
+
focus,
|
|
155
|
+
tabIndexFor: (rowIndex, columnIndex) => tabIndexFor(
|
|
156
|
+
columnIndex,
|
|
157
|
+
rowIndex === focus.rowIndex ? focus.columnIndex : null
|
|
158
|
+
),
|
|
159
|
+
focusCell: gridFocus.focusCell,
|
|
160
|
+
focusCellNow: (rowIndex, columnIndex) => {
|
|
161
|
+
gridFocus.focusCell(rowIndex, columnIndex);
|
|
162
|
+
gridFocus.focusDrawnCell(gridFocus.getFocus());
|
|
163
|
+
},
|
|
164
|
+
focusTabStop: () => {
|
|
165
|
+
const cells = (focus.rowIndex === HEADER_ROW ? rows.getHeaderRow() : rows.getBodyRow(focus.rowIndex))?.cells;
|
|
166
|
+
cells?.[Math.min(focus.columnIndex, cells.length - 1)]?.focus();
|
|
167
|
+
},
|
|
168
|
+
onKeyDown: (event) => {
|
|
169
|
+
if (gridFocus.handleKey(
|
|
170
|
+
event.key,
|
|
171
|
+
event,
|
|
172
|
+
measurePageSize(bodyTableRef.current)
|
|
173
|
+
)) {
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/DataGrid/useGridSelection.ts
|
|
181
|
+
import { useMemo } from "react";
|
|
182
|
+
function keyboardSelectIntent(event) {
|
|
183
|
+
return {
|
|
184
|
+
ctrlKey: event.key === " " || event.ctrlKey,
|
|
185
|
+
metaKey: event.metaKey,
|
|
186
|
+
shiftKey: event.shiftKey
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function useGridSelection({
|
|
190
|
+
controller,
|
|
191
|
+
state,
|
|
192
|
+
selectable
|
|
193
|
+
}) {
|
|
194
|
+
const selectedRowIds = useMemo(
|
|
195
|
+
() => new Set(state.rowSelection),
|
|
196
|
+
[state.rowSelection]
|
|
197
|
+
);
|
|
198
|
+
const selectedColumnIds = useMemo(
|
|
199
|
+
() => new Set(state.columnSelection),
|
|
200
|
+
[state.columnSelection]
|
|
201
|
+
);
|
|
202
|
+
return {
|
|
203
|
+
rowMode: selectable?.rows ?? false,
|
|
204
|
+
columnMode: selectable?.columns ?? false,
|
|
205
|
+
cellMode: selectable?.cells ?? false,
|
|
206
|
+
toggleOnClick: selectable?.toggleOnClick ?? false,
|
|
207
|
+
selectedRowIds,
|
|
208
|
+
selectedColumnIds,
|
|
209
|
+
selectedCell: state.cellSelection,
|
|
210
|
+
selectRow: controller.selectRow,
|
|
211
|
+
selectColumn: controller.selectColumn,
|
|
212
|
+
selectCell: controller.selectCell,
|
|
213
|
+
selectAllRows: controller.selectAllRows,
|
|
214
|
+
clear: controller.clearSelection
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/DataGrid/components/GridHeader.tsx
|
|
219
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
220
|
+
function GridHeader({
|
|
221
|
+
columns,
|
|
222
|
+
resize,
|
|
223
|
+
drag,
|
|
224
|
+
controller,
|
|
225
|
+
state,
|
|
226
|
+
sortableColumns,
|
|
227
|
+
groupableColumns,
|
|
228
|
+
groupToggleIconColumns,
|
|
229
|
+
headerMenu,
|
|
230
|
+
panels,
|
|
231
|
+
messages,
|
|
232
|
+
nav,
|
|
233
|
+
selection
|
|
234
|
+
}) {
|
|
235
|
+
const { columnSort, groupBy, filter } = state;
|
|
236
|
+
const beforeId = drag.dropTarget?.kind === "column-order" ? drag.dropTarget.beforeId : void 0;
|
|
237
|
+
const draggedEntry = columns.find((entry) => entry.id === drag.draggedColumnId) ?? null;
|
|
238
|
+
function toggleFilterMenu(columnId) {
|
|
239
|
+
const { panel } = panels;
|
|
240
|
+
if (panel?.kind === "filter" && panel.target.area === "header" && panel.target.columnId === columnId) {
|
|
241
|
+
panels.close();
|
|
242
|
+
} else {
|
|
243
|
+
panels.open("filter", { area: "header", columnId });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return /* @__PURE__ */ jsxs2("thead", { role: "rowgroup", children: [
|
|
247
|
+
/* @__PURE__ */ jsx3("tr", { className: "grid-header", role: "row", "aria-rowindex": 1, children: columns.map((entry, index) => {
|
|
248
|
+
const { column } = entry;
|
|
249
|
+
const resizing = resize.activeColumnId === entry.id;
|
|
250
|
+
const dragging = drag.draggedColumnId === entry.id;
|
|
251
|
+
const dropBefore = beforeId !== void 0 && beforeId === entry.id;
|
|
252
|
+
const dropAfter = beforeId === null && index === columns.length - 1;
|
|
253
|
+
const selected = selection.selectedColumnIds.has(entry.id);
|
|
254
|
+
const sortable = column.sortable ?? sortableColumns;
|
|
255
|
+
const sortDirection = sortDirectionFor(columnSort, entry.id);
|
|
256
|
+
const sortPriority = sortPriorityFor(columnSort, entry.id);
|
|
257
|
+
const groupable = column.groupable ?? groupableColumns;
|
|
258
|
+
const showGroupToggleIcon = column.groupToggleIcon ?? groupToggleIconColumns;
|
|
259
|
+
const isGrouped = groupBy.some(
|
|
260
|
+
(level) => level.columnId === entry.id
|
|
261
|
+
);
|
|
262
|
+
const filterable = resolveColumnFilterMenu(controller.getOptions(), column) !== null;
|
|
263
|
+
const filtered = filterable && isColumnFiltered(filter, entry.id);
|
|
264
|
+
const shortcuts = buildKeyShortcuts({
|
|
265
|
+
reorderable: entry.reorderable,
|
|
266
|
+
resizable: entry.resizable,
|
|
267
|
+
sortable,
|
|
268
|
+
groupable,
|
|
269
|
+
filterable,
|
|
270
|
+
contextMenu: headerMenu
|
|
271
|
+
});
|
|
272
|
+
return /* @__PURE__ */ jsxs2(
|
|
273
|
+
"th",
|
|
274
|
+
{
|
|
275
|
+
scope: "col",
|
|
276
|
+
role: "columnheader",
|
|
277
|
+
"data-gridkit-column": entry.id,
|
|
278
|
+
"aria-colindex": index + 1,
|
|
279
|
+
tabIndex: nav.tabIndexFor(HEADER_ROW, index),
|
|
280
|
+
...ariaAttr(
|
|
281
|
+
selection.columnMode !== false,
|
|
282
|
+
"aria-selected",
|
|
283
|
+
selected
|
|
284
|
+
),
|
|
285
|
+
onFocus: () => {
|
|
286
|
+
nav.focusCell(HEADER_ROW, index);
|
|
287
|
+
},
|
|
288
|
+
onClick: (event) => {
|
|
289
|
+
if (drag.justDragged()) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (event.target instanceof Element && (event.target.closest(".header-resize-handle") !== null || event.target.closest(".header-sort-toggle") !== null || event.target.closest(".header-group-toggle") !== null || event.target.closest(".header-filter-toggle") !== null)) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
selection.selectColumn(entry.id, intentOf(event));
|
|
296
|
+
},
|
|
297
|
+
onKeyDown: (event) => {
|
|
298
|
+
if (!isOwnEvent(event)) return;
|
|
299
|
+
const horizontal = event.key === "ArrowLeft" || event.key === "ArrowRight";
|
|
300
|
+
const direction = event.key === "ArrowLeft" ? -1 : 1;
|
|
301
|
+
if (horizontal && event.ctrlKey && entry.reorderable) {
|
|
302
|
+
event.preventDefault();
|
|
303
|
+
drag.moveByKeyboard(entry, direction);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (horizontal && event.altKey && entry.resizable) {
|
|
307
|
+
event.preventDefault();
|
|
308
|
+
resize.nudge(entry, direction * KEYBOARD_STEP);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
if (event.key === "Enter" && event.altKey && entry.resizable) {
|
|
312
|
+
event.preventDefault();
|
|
313
|
+
resize.sizeToContent(entry);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
if (event.key === "ArrowUp" && event.altKey && sortable) {
|
|
317
|
+
event.preventDefault();
|
|
318
|
+
controller.toggleColumnSort(entry.id, {
|
|
319
|
+
stack: event.shiftKey
|
|
320
|
+
});
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (event.key === "ArrowDown" && event.altKey && event.shiftKey && filterable) {
|
|
324
|
+
event.preventDefault();
|
|
325
|
+
toggleFilterMenu(entry.id);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
if (event.key === "ArrowDown" && event.altKey && !event.shiftKey && groupable) {
|
|
329
|
+
event.preventDefault();
|
|
330
|
+
controller.toggleGroupBy(entry.id);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (event.key === " " || event.key === "Enter") {
|
|
334
|
+
event.preventDefault();
|
|
335
|
+
selection.selectColumn(
|
|
336
|
+
entry.id,
|
|
337
|
+
intentOf(keyboardSelectIntent(event))
|
|
338
|
+
);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
nav.onKeyDown(event);
|
|
342
|
+
},
|
|
343
|
+
className: classNames(
|
|
344
|
+
"header-cell",
|
|
345
|
+
// The grab affordance a header showing either drag
|
|
346
|
+
// destination shares — a column dragged only for grouping
|
|
347
|
+
// (`groupByDraggable` without `reorderable`) grabs the same
|
|
348
|
+
// way one dragged only for reordering does.
|
|
349
|
+
entry.reorderable || entry.groupByDraggable ? "is-reorderable" : "",
|
|
350
|
+
selected ? "is-selected" : "",
|
|
351
|
+
resizing ? "is-resizing" : "",
|
|
352
|
+
dragging ? "is-dragging" : "",
|
|
353
|
+
dropBefore ? "is-drop-before" : "",
|
|
354
|
+
dropAfter ? "is-drop-after" : "",
|
|
355
|
+
column.wrap?.header ? "is-wrapped" : "",
|
|
356
|
+
column.headerClassName ?? ""
|
|
357
|
+
),
|
|
358
|
+
...ariaAttr(shortcuts !== "", "aria-keyshortcuts", shortcuts),
|
|
359
|
+
...ariaAttr(
|
|
360
|
+
filtered,
|
|
361
|
+
"aria-description",
|
|
362
|
+
messages.columnFiltered
|
|
363
|
+
),
|
|
364
|
+
...ariaAttr(
|
|
365
|
+
sortable && sortDirection !== null,
|
|
366
|
+
"aria-sort",
|
|
367
|
+
sortDirection === "asc" ? "ascending" : "descending"
|
|
368
|
+
),
|
|
369
|
+
...(entry.reorderable || entry.groupByDraggable) && {
|
|
370
|
+
onPointerDown: (event) => {
|
|
371
|
+
drag.startDrag(entry, event);
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
children: [
|
|
375
|
+
groupable && showGroupToggleIcon && /*
|
|
376
|
+
* Inline, before the label, rather than absolutely
|
|
377
|
+
* positioned like the sort toggle and resize handle: those
|
|
378
|
+
* two already share the header's right edge, and a third
|
|
379
|
+
* overlay there would need its own carve-out. Sitting in
|
|
380
|
+
* normal flow costs nothing but a few pixels of label width.
|
|
381
|
+
* A pointer affordance only, same as the other two — the
|
|
382
|
+
* keyboard equivalent is Alt+ArrowDown on the header itself.
|
|
383
|
+
*/
|
|
384
|
+
/* @__PURE__ */ jsx3(
|
|
385
|
+
"span",
|
|
386
|
+
{
|
|
387
|
+
className: classNames(
|
|
388
|
+
"header-group-toggle",
|
|
389
|
+
isGrouped ? "is-grouped" : ""
|
|
390
|
+
),
|
|
391
|
+
"aria-hidden": "true",
|
|
392
|
+
tabIndex: -1,
|
|
393
|
+
onPointerDown: (event) => {
|
|
394
|
+
event.stopPropagation();
|
|
395
|
+
},
|
|
396
|
+
onClick: (event) => {
|
|
397
|
+
event.stopPropagation();
|
|
398
|
+
controller.toggleGroupBy(entry.id);
|
|
399
|
+
},
|
|
400
|
+
children: /* @__PURE__ */ jsx3(GroupIcon, {})
|
|
401
|
+
}
|
|
402
|
+
),
|
|
403
|
+
entry.label,
|
|
404
|
+
sortable && /*
|
|
405
|
+
* A pointer affordance only, and hidden from assistive
|
|
406
|
+
* technology like the resize handle: the keyboard equivalent
|
|
407
|
+
* lives on the header itself, under Alt+ArrowUp (plain) /
|
|
408
|
+
* Alt+Shift+ArrowUp (stacking).
|
|
409
|
+
*/
|
|
410
|
+
/* @__PURE__ */ jsxs2(
|
|
411
|
+
"span",
|
|
412
|
+
{
|
|
413
|
+
className: classNames(
|
|
414
|
+
"header-sort-toggle",
|
|
415
|
+
sortDirection !== null ? `is-sorted-${sortDirection}` : ""
|
|
416
|
+
),
|
|
417
|
+
"aria-hidden": "true",
|
|
418
|
+
tabIndex: -1,
|
|
419
|
+
onPointerDown: (event) => {
|
|
420
|
+
event.stopPropagation();
|
|
421
|
+
},
|
|
422
|
+
onClick: (event) => {
|
|
423
|
+
controller.toggleColumnSort(entry.id, {
|
|
424
|
+
stack: event.shiftKey
|
|
425
|
+
});
|
|
426
|
+
},
|
|
427
|
+
children: [
|
|
428
|
+
sortDirection === null ? /* @__PURE__ */ jsx3(ChevronsUpDownIcon, {}) : /* @__PURE__ */ jsx3(ChevronUpIcon, {}),
|
|
429
|
+
sortPriority !== null && sortPriority > 1 && /* @__PURE__ */ jsx3("span", { className: "header-sort-priority", children: sortPriority })
|
|
430
|
+
]
|
|
431
|
+
}
|
|
432
|
+
),
|
|
433
|
+
filterable && /*
|
|
434
|
+
* A pointer affordance only, like the sort toggle: the
|
|
435
|
+
* keyboard opens the menu from the header itself, under
|
|
436
|
+
* Alt+Shift+ArrowDown, and a screen reader hears the
|
|
437
|
+
* filtered state as the header's description.
|
|
438
|
+
*/
|
|
439
|
+
/* @__PURE__ */ jsx3(
|
|
440
|
+
"span",
|
|
441
|
+
{
|
|
442
|
+
className: classNames(
|
|
443
|
+
"header-filter-toggle",
|
|
444
|
+
filtered ? "is-filtered" : ""
|
|
445
|
+
),
|
|
446
|
+
"aria-hidden": "true",
|
|
447
|
+
tabIndex: -1,
|
|
448
|
+
onPointerDown: (event) => {
|
|
449
|
+
event.stopPropagation();
|
|
450
|
+
},
|
|
451
|
+
onClick: () => {
|
|
452
|
+
toggleFilterMenu(entry.id);
|
|
453
|
+
},
|
|
454
|
+
children: /* @__PURE__ */ jsx3(FilterIcon, {})
|
|
455
|
+
}
|
|
456
|
+
),
|
|
457
|
+
entry.resizable && /*
|
|
458
|
+
* A pointer affordance only, and hidden from assistive
|
|
459
|
+
* technology accordingly: a focusable handle per column would
|
|
460
|
+
* put N tab stops inside a widget that is meant to have one.
|
|
461
|
+
* The keyboard resizes from the header itself, under Alt.
|
|
462
|
+
*/
|
|
463
|
+
/* @__PURE__ */ jsx3(
|
|
464
|
+
"span",
|
|
465
|
+
{
|
|
466
|
+
className: "header-resize-handle",
|
|
467
|
+
"aria-hidden": "true",
|
|
468
|
+
tabIndex: -1,
|
|
469
|
+
onPointerDown: (event) => {
|
|
470
|
+
resize.startResize(entry, event);
|
|
471
|
+
},
|
|
472
|
+
onDoubleClick: () => {
|
|
473
|
+
resize.sizeToContent(entry);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
)
|
|
477
|
+
]
|
|
478
|
+
},
|
|
479
|
+
entry.id
|
|
480
|
+
);
|
|
481
|
+
}) }),
|
|
482
|
+
draggedEntry !== null && drag.ghostTransform !== null && createPortal(
|
|
483
|
+
/* @__PURE__ */ jsx3(
|
|
484
|
+
"div",
|
|
485
|
+
{
|
|
486
|
+
className: "gridkit-data-grid header-cell drag-ghost",
|
|
487
|
+
style: {
|
|
488
|
+
width: draggedEntry.width,
|
|
489
|
+
transform: drag.ghostTransform
|
|
490
|
+
},
|
|
491
|
+
"aria-hidden": "true",
|
|
492
|
+
children: draggedEntry.label
|
|
493
|
+
}
|
|
494
|
+
),
|
|
495
|
+
document.body
|
|
496
|
+
)
|
|
497
|
+
] });
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// src/DataGrid/components/GridBody.tsx
|
|
501
|
+
import {
|
|
502
|
+
useMemo as useMemo2,
|
|
503
|
+
useState as useState2
|
|
504
|
+
} from "react";
|
|
505
|
+
import {
|
|
506
|
+
groupRowId,
|
|
507
|
+
intentOf as intentOf2
|
|
508
|
+
} from "@gridkitjs/core";
|
|
509
|
+
import {
|
|
510
|
+
bodyCellFrom,
|
|
511
|
+
bodyRowFrom,
|
|
512
|
+
groupRowFrom
|
|
513
|
+
} from "@gridkitjs/dom";
|
|
514
|
+
|
|
515
|
+
// src/DataGrid/rowProps.ts
|
|
516
|
+
var NO_ATTRIBUTES = {};
|
|
517
|
+
var NO_ROW_PROPS = {
|
|
518
|
+
className: "",
|
|
519
|
+
attributes: NO_ATTRIBUTES
|
|
520
|
+
};
|
|
521
|
+
function sameAttributes(a, b) {
|
|
522
|
+
const keys = Object.keys(a);
|
|
523
|
+
return keys.length === Object.keys(b).length && keys.every((key) => a[key] === b[key]);
|
|
524
|
+
}
|
|
525
|
+
function createRowPropsResolver() {
|
|
526
|
+
let previous = /* @__PURE__ */ new Map();
|
|
527
|
+
return (rows, getRowProps) => {
|
|
528
|
+
if (getRowProps === void 0) {
|
|
529
|
+
previous = /* @__PURE__ */ new Map();
|
|
530
|
+
return () => NO_ROW_PROPS;
|
|
531
|
+
}
|
|
532
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
533
|
+
const attributesById = /* @__PURE__ */ new Map();
|
|
534
|
+
for (const entry of rows) {
|
|
535
|
+
const { className = "", attributes = NO_ATTRIBUTES } = getRowProps(entry);
|
|
536
|
+
const last = previous.get(entry.rowId);
|
|
537
|
+
const stable = last !== void 0 && sameAttributes(last, attributes) ? last : attributes;
|
|
538
|
+
attributesById.set(entry.rowId, stable);
|
|
539
|
+
resolved.set(entry.rowId, { className, attributes: stable });
|
|
540
|
+
}
|
|
541
|
+
previous = attributesById;
|
|
542
|
+
return (rowId) => resolved.get(rowId) ?? NO_ROW_PROPS;
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// src/DataGrid/components/GridGroupRow.tsx
|
|
547
|
+
import { memo } from "react";
|
|
548
|
+
import {
|
|
549
|
+
formatGroupValue,
|
|
550
|
+
resolveColumnLabel
|
|
551
|
+
} from "@gridkitjs/core";
|
|
552
|
+
|
|
553
|
+
// src/DataGrid/components/renderAggregate.ts
|
|
554
|
+
import {
|
|
555
|
+
formatAggregateValue
|
|
556
|
+
} from "@gridkitjs/core";
|
|
557
|
+
function renderAggregate(value, spec, column, rows, locale) {
|
|
558
|
+
if (column?.footerTemplate) {
|
|
559
|
+
return column.footerTemplate({ value, rows });
|
|
560
|
+
}
|
|
561
|
+
if (value === null || value === void 0) {
|
|
562
|
+
return "\u2014";
|
|
563
|
+
}
|
|
564
|
+
return formatAggregateValue(value, spec, column, locale);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// src/DataGrid/components/GridGroupRow.tsx
|
|
568
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
569
|
+
function GridGroupRowComponent({
|
|
570
|
+
columnCount,
|
|
571
|
+
groupId,
|
|
572
|
+
level,
|
|
573
|
+
groupColumn,
|
|
574
|
+
value,
|
|
575
|
+
expanded,
|
|
576
|
+
count,
|
|
577
|
+
rowIndex,
|
|
578
|
+
datasetIndex,
|
|
579
|
+
posinset,
|
|
580
|
+
setsize,
|
|
581
|
+
focused,
|
|
582
|
+
contextMenu,
|
|
583
|
+
aggregates,
|
|
584
|
+
results,
|
|
585
|
+
definitions,
|
|
586
|
+
locale,
|
|
587
|
+
cellMessages,
|
|
588
|
+
ref
|
|
589
|
+
}) {
|
|
590
|
+
return /* @__PURE__ */ jsx4(
|
|
591
|
+
"tr",
|
|
592
|
+
{
|
|
593
|
+
ref,
|
|
594
|
+
role: "row",
|
|
595
|
+
"aria-rowindex": datasetIndex + 2,
|
|
596
|
+
"aria-level": level + 1,
|
|
597
|
+
"aria-expanded": expanded,
|
|
598
|
+
"aria-setsize": setsize,
|
|
599
|
+
"aria-posinset": posinset,
|
|
600
|
+
"data-gridkit-group": groupId,
|
|
601
|
+
"data-gridkit-row-index": rowIndex,
|
|
602
|
+
className: classNames(
|
|
603
|
+
"grid-group-row",
|
|
604
|
+
`is-group-level-${String(level)}`
|
|
605
|
+
),
|
|
606
|
+
children: /* @__PURE__ */ jsx4(
|
|
607
|
+
"td",
|
|
608
|
+
{
|
|
609
|
+
role: "gridcell",
|
|
610
|
+
colSpan: columnCount,
|
|
611
|
+
tabIndex: focused ? 0 : -1,
|
|
612
|
+
"aria-keyshortcuts": contextMenu ? "Space Enter Shift+F10" : "Space Enter",
|
|
613
|
+
className: "grid-group-cell",
|
|
614
|
+
children: /* @__PURE__ */ jsxs3(
|
|
615
|
+
"div",
|
|
616
|
+
{
|
|
617
|
+
className: "grid-group-cell-content",
|
|
618
|
+
style: { paddingInlineStart: `${String(level * 1.25 + 0.5)}rem` },
|
|
619
|
+
children: [
|
|
620
|
+
/* @__PURE__ */ jsx4(
|
|
621
|
+
"span",
|
|
622
|
+
{
|
|
623
|
+
className: classNames(
|
|
624
|
+
"group-toggle",
|
|
625
|
+
expanded ? "is-expanded" : "is-collapsed"
|
|
626
|
+
),
|
|
627
|
+
"aria-hidden": "true"
|
|
628
|
+
}
|
|
629
|
+
),
|
|
630
|
+
/* @__PURE__ */ jsxs3("span", { className: "group-label", children: [
|
|
631
|
+
resolveColumnLabel(groupColumn),
|
|
632
|
+
":",
|
|
633
|
+
" ",
|
|
634
|
+
formatGroupValue(value, groupColumn, locale, cellMessages)
|
|
635
|
+
] }),
|
|
636
|
+
/* @__PURE__ */ jsxs3("span", { className: "group-count", children: [
|
|
637
|
+
"(",
|
|
638
|
+
count,
|
|
639
|
+
")"
|
|
640
|
+
] }),
|
|
641
|
+
aggregates.length > 0 && /* @__PURE__ */ jsx4("span", { className: "group-aggregates", children: aggregates.map((spec) => {
|
|
642
|
+
const key = spec.id ?? spec.columnId;
|
|
643
|
+
const aggregateValue = results.get(key);
|
|
644
|
+
const column = definitions.get(spec.columnId);
|
|
645
|
+
const rendered = renderAggregate(
|
|
646
|
+
aggregateValue,
|
|
647
|
+
spec,
|
|
648
|
+
column,
|
|
649
|
+
[],
|
|
650
|
+
locale
|
|
651
|
+
);
|
|
652
|
+
const aggregateLabel = spec.id ?? (column === void 0 ? spec.columnId : resolveColumnLabel(column));
|
|
653
|
+
return /* @__PURE__ */ jsxs3("span", { className: "group-aggregate", children: [
|
|
654
|
+
aggregateLabel,
|
|
655
|
+
": ",
|
|
656
|
+
rendered
|
|
657
|
+
] }, key);
|
|
658
|
+
}) })
|
|
659
|
+
]
|
|
660
|
+
}
|
|
661
|
+
)
|
|
662
|
+
}
|
|
663
|
+
)
|
|
664
|
+
}
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
var GridGroupRow = memo(
|
|
668
|
+
GridGroupRowComponent
|
|
669
|
+
);
|
|
670
|
+
var GridGroupRow_default = GridGroupRow;
|
|
671
|
+
|
|
672
|
+
// src/DataGrid/components/GridGroupSummaryRow.tsx
|
|
673
|
+
import { memo as memo2 } from "react";
|
|
674
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
675
|
+
function GridGroupSummaryRowComponent({
|
|
676
|
+
groupId,
|
|
677
|
+
level,
|
|
678
|
+
rowIndex,
|
|
679
|
+
datasetIndex,
|
|
680
|
+
results,
|
|
681
|
+
aggregates,
|
|
682
|
+
columns,
|
|
683
|
+
locale,
|
|
684
|
+
ref
|
|
685
|
+
}) {
|
|
686
|
+
return /* @__PURE__ */ jsx5(
|
|
687
|
+
"tr",
|
|
688
|
+
{
|
|
689
|
+
ref,
|
|
690
|
+
role: "row",
|
|
691
|
+
"aria-rowindex": datasetIndex + 2,
|
|
692
|
+
"data-gridkit-group-summary": groupId,
|
|
693
|
+
"data-gridkit-row-index": rowIndex,
|
|
694
|
+
className: classNames(
|
|
695
|
+
"grid-group-summary-row",
|
|
696
|
+
`is-group-level-${String(level)}`
|
|
697
|
+
),
|
|
698
|
+
children: columns.map((entry) => {
|
|
699
|
+
const specs = aggregates.filter(
|
|
700
|
+
(candidate) => candidate.columnId === entry.id
|
|
701
|
+
);
|
|
702
|
+
return /* @__PURE__ */ jsxs4(
|
|
703
|
+
"td",
|
|
704
|
+
{
|
|
705
|
+
role: "gridcell",
|
|
706
|
+
"data-gridkit-column": entry.id,
|
|
707
|
+
className: "grid-group-summary-cell",
|
|
708
|
+
style: { textAlign: specs[0]?.alignment ?? entry.alignment },
|
|
709
|
+
children: [
|
|
710
|
+
entry.id === columns[0]?.id && /* @__PURE__ */ jsx5(
|
|
711
|
+
"span",
|
|
712
|
+
{
|
|
713
|
+
className: "grid-group-summary-indent",
|
|
714
|
+
style: { width: `${String(level * 1.25 + 0.5)}rem` },
|
|
715
|
+
"aria-hidden": "true"
|
|
716
|
+
}
|
|
717
|
+
),
|
|
718
|
+
specs.map(
|
|
719
|
+
(spec) => renderAggregate(
|
|
720
|
+
results.get(spec.id ?? spec.columnId),
|
|
721
|
+
spec,
|
|
722
|
+
entry.column,
|
|
723
|
+
[],
|
|
724
|
+
locale
|
|
725
|
+
)
|
|
726
|
+
).flatMap(
|
|
727
|
+
(rendered, index) => index === 0 ? [rendered] : [", ", rendered]
|
|
728
|
+
)
|
|
729
|
+
]
|
|
730
|
+
},
|
|
731
|
+
entry.id
|
|
732
|
+
);
|
|
733
|
+
})
|
|
734
|
+
}
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
var GridGroupSummaryRow = memo2(
|
|
738
|
+
GridGroupSummaryRowComponent
|
|
739
|
+
);
|
|
740
|
+
var GridGroupSummaryRow_default = GridGroupSummaryRow;
|
|
741
|
+
|
|
742
|
+
// src/DataGrid/components/GridRow.tsx
|
|
743
|
+
import {
|
|
744
|
+
accessDotted,
|
|
745
|
+
formatCellValue
|
|
746
|
+
} from "@gridkitjs/core";
|
|
747
|
+
import { memo as memo3 } from "react";
|
|
748
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
749
|
+
function GridRowComponent({
|
|
750
|
+
columns,
|
|
751
|
+
rowId,
|
|
752
|
+
row,
|
|
753
|
+
rowIndex,
|
|
754
|
+
datasetIndex,
|
|
755
|
+
activeColumnId,
|
|
756
|
+
selectedColumnIds,
|
|
757
|
+
selected,
|
|
758
|
+
selectedColumnId,
|
|
759
|
+
focusedColumnIndex,
|
|
760
|
+
rowsSelectable,
|
|
761
|
+
cellsSelectable,
|
|
762
|
+
contextMenu,
|
|
763
|
+
locale,
|
|
764
|
+
cellMessages,
|
|
765
|
+
rowClassName,
|
|
766
|
+
rowAttributes,
|
|
767
|
+
ref
|
|
768
|
+
}) {
|
|
769
|
+
const shortcuts = [
|
|
770
|
+
cellsSelectable ? "Space Enter" : "",
|
|
771
|
+
contextMenu ? "Shift+F10" : ""
|
|
772
|
+
].filter(Boolean).join(" ");
|
|
773
|
+
return /* @__PURE__ */ jsx6(
|
|
774
|
+
"tr",
|
|
775
|
+
{
|
|
776
|
+
...rowAttributes,
|
|
777
|
+
ref,
|
|
778
|
+
role: "row",
|
|
779
|
+
"aria-rowindex": datasetIndex + 2,
|
|
780
|
+
"data-gridkit-row-index": rowIndex,
|
|
781
|
+
"data-gridkit-row-id": rowId,
|
|
782
|
+
...ariaAttr(rowsSelectable, "aria-selected", selected),
|
|
783
|
+
className: classNames(
|
|
784
|
+
"grid-row",
|
|
785
|
+
selected ? "is-selected" : "",
|
|
786
|
+
rowClassName
|
|
787
|
+
),
|
|
788
|
+
children: columns.map(({ id, column, alignment }, columnIndex) => {
|
|
789
|
+
const value = accessDotted(row, column.field);
|
|
790
|
+
const cellSelected = id === selectedColumnId;
|
|
791
|
+
return /* @__PURE__ */ jsx6(
|
|
792
|
+
"td",
|
|
793
|
+
{
|
|
794
|
+
role: "gridcell",
|
|
795
|
+
"data-gridkit-column": id,
|
|
796
|
+
"aria-colindex": columnIndex + 1,
|
|
797
|
+
tabIndex: tabIndexFor(columnIndex, focusedColumnIndex),
|
|
798
|
+
...ariaAttr(cellsSelectable, "aria-selected", cellSelected),
|
|
799
|
+
...ariaAttr(shortcuts !== "", "aria-keyshortcuts", shortcuts),
|
|
800
|
+
className: classNames(
|
|
801
|
+
"grid-cell",
|
|
802
|
+
id === activeColumnId ? "is-resizing" : "",
|
|
803
|
+
cellSelected || selectedColumnIds.has(id) ? "is-selected" : "",
|
|
804
|
+
column.wrap?.cells ? "is-wrapped" : "",
|
|
805
|
+
column.cellClassName ?? ""
|
|
806
|
+
),
|
|
807
|
+
style: { textAlign: alignment },
|
|
808
|
+
children: column.cellTemplate ? column.cellTemplate({
|
|
809
|
+
value,
|
|
810
|
+
row,
|
|
811
|
+
rowIndex,
|
|
812
|
+
datasetIndex,
|
|
813
|
+
rowId,
|
|
814
|
+
selected
|
|
815
|
+
}) : formatCellValue(value, column, locale, row, cellMessages)
|
|
816
|
+
},
|
|
817
|
+
id
|
|
818
|
+
);
|
|
819
|
+
})
|
|
820
|
+
}
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
var GridRow = memo3(GridRowComponent);
|
|
824
|
+
var GridRow_default = GridRow;
|
|
825
|
+
|
|
826
|
+
// src/DataGrid/components/GridBody.tsx
|
|
827
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
828
|
+
function groupAriaMeta(rows) {
|
|
829
|
+
const totals = /* @__PURE__ */ new Map();
|
|
830
|
+
for (const entry of rows) {
|
|
831
|
+
if (!("kind" in entry) || entry.kind !== "group") continue;
|
|
832
|
+
const parentKey = groupRowId(entry.path.slice(0, -1));
|
|
833
|
+
totals.set(parentKey, (totals.get(parentKey) ?? 0) + 1);
|
|
834
|
+
}
|
|
835
|
+
const seen = /* @__PURE__ */ new Map();
|
|
836
|
+
const meta = /* @__PURE__ */ new Map();
|
|
837
|
+
for (const entry of rows) {
|
|
838
|
+
if (!("kind" in entry) || entry.kind !== "group") continue;
|
|
839
|
+
const parentKey = groupRowId(entry.path.slice(0, -1));
|
|
840
|
+
const posinset = (seen.get(parentKey) ?? 0) + 1;
|
|
841
|
+
seen.set(parentKey, posinset);
|
|
842
|
+
meta.set(entry.groupId, {
|
|
843
|
+
posinset,
|
|
844
|
+
setsize: totals.get(parentKey) ?? posinset
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
return meta;
|
|
848
|
+
}
|
|
849
|
+
function GridBody({
|
|
850
|
+
columns,
|
|
851
|
+
definitions,
|
|
852
|
+
rows,
|
|
853
|
+
activeColumnId,
|
|
854
|
+
nav,
|
|
855
|
+
selection,
|
|
856
|
+
controller,
|
|
857
|
+
aggregates,
|
|
858
|
+
groupAggregateDisplay,
|
|
859
|
+
virtualRange,
|
|
860
|
+
infiniteScroll,
|
|
861
|
+
sentinelRef,
|
|
862
|
+
locale,
|
|
863
|
+
getRowProps,
|
|
864
|
+
onRowClick,
|
|
865
|
+
onRowDoubleClick,
|
|
866
|
+
messages,
|
|
867
|
+
cellMenu,
|
|
868
|
+
groupMenu
|
|
869
|
+
}) {
|
|
870
|
+
const { selectedCell, rowMode, cellMode, toggleOnClick } = selection;
|
|
871
|
+
const ariaMeta = useMemo2(() => groupAriaMeta(rows), [rows]);
|
|
872
|
+
const visibleRows = virtualRange === null ? rows : rows.slice(virtualRange.startIndex, virtualRange.endIndex + 1);
|
|
873
|
+
const { booleanTrue, booleanFalse, blankGroupValue } = messages;
|
|
874
|
+
const cellMessages = useMemo2(
|
|
875
|
+
() => ({ booleanTrue, booleanFalse, blankGroupValue }),
|
|
876
|
+
[booleanTrue, booleanFalse, blankGroupValue]
|
|
877
|
+
);
|
|
878
|
+
const [resolveRowProps] = useState2(() => createRowPropsResolver());
|
|
879
|
+
const rowPropsOf = resolveRowProps(
|
|
880
|
+
visibleRows.filter(
|
|
881
|
+
(entry) => !("kind" in entry)
|
|
882
|
+
),
|
|
883
|
+
getRowProps
|
|
884
|
+
);
|
|
885
|
+
function targetOf(target) {
|
|
886
|
+
const position = bodyCellFrom(target);
|
|
887
|
+
const entry = position === null ? void 0 : rows[position.rowIndex];
|
|
888
|
+
if (position === null || entry === void 0 || "kind" in entry) {
|
|
889
|
+
return null;
|
|
890
|
+
}
|
|
891
|
+
return { position, rowId: entry.rowId };
|
|
892
|
+
}
|
|
893
|
+
function select(rowId, columnId, modifiers) {
|
|
894
|
+
if (rowMode !== false) {
|
|
895
|
+
selection.selectRow(rowId, intentOf2(modifiers, { toggleOnClick }));
|
|
896
|
+
}
|
|
897
|
+
if (cellMode !== false) {
|
|
898
|
+
selection.selectCell({ rowId, columnId }, intentOf2(modifiers));
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
function rowPointerEventOf(event) {
|
|
902
|
+
const target = bodyRowFrom(event.target);
|
|
903
|
+
const entry = target === null ? void 0 : rows[target.rowIndex];
|
|
904
|
+
if (target === null || entry === void 0 || "kind" in entry) {
|
|
905
|
+
return null;
|
|
906
|
+
}
|
|
907
|
+
return {
|
|
908
|
+
row: entry,
|
|
909
|
+
columnId: target.columnId,
|
|
910
|
+
native: {
|
|
911
|
+
ctrlKey: event.ctrlKey,
|
|
912
|
+
metaKey: event.metaKey,
|
|
913
|
+
shiftKey: event.shiftKey,
|
|
914
|
+
altKey: event.altKey,
|
|
915
|
+
button: event.button
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
function reportRowPointer(event, callback) {
|
|
920
|
+
if (callback === void 0) return;
|
|
921
|
+
const pointer = rowPointerEventOf(event);
|
|
922
|
+
if (pointer !== null) {
|
|
923
|
+
callback(pointer);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
return /* @__PURE__ */ jsxs5(
|
|
927
|
+
"tbody",
|
|
928
|
+
{
|
|
929
|
+
role: "rowgroup",
|
|
930
|
+
className: "grid-body",
|
|
931
|
+
onFocus: (event) => {
|
|
932
|
+
const group = groupRowFrom(event.target);
|
|
933
|
+
if (group !== null) {
|
|
934
|
+
nav.focusCell(group.rowIndex, 0);
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
const found = targetOf(event.target);
|
|
938
|
+
if (found === null) return;
|
|
939
|
+
nav.focusCell(found.position.rowIndex, found.position.columnIndex);
|
|
940
|
+
},
|
|
941
|
+
onClick: (event) => {
|
|
942
|
+
const group = groupRowFrom(event.target);
|
|
943
|
+
if (group !== null) {
|
|
944
|
+
controller.toggleGroupExpansion(group.groupId);
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
const found = targetOf(event.target);
|
|
948
|
+
if (found !== null) {
|
|
949
|
+
select(found.rowId, found.position.columnId, event);
|
|
950
|
+
}
|
|
951
|
+
reportRowPointer(event, onRowClick);
|
|
952
|
+
},
|
|
953
|
+
onDoubleClick: (event) => {
|
|
954
|
+
reportRowPointer(event, onRowDoubleClick);
|
|
955
|
+
},
|
|
956
|
+
onKeyDown: (event) => {
|
|
957
|
+
if (!isOwnEvent(event)) return;
|
|
958
|
+
const group = groupRowFrom(event.target);
|
|
959
|
+
if (group !== null) {
|
|
960
|
+
if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
|
|
961
|
+
event.preventDefault();
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
if (event.key === " " || event.key === "Enter") {
|
|
965
|
+
event.preventDefault();
|
|
966
|
+
controller.toggleGroupExpansion(group.groupId);
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
nav.onKeyDown(event);
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
if (event.key === " " || event.key === "Enter") {
|
|
973
|
+
const found = targetOf(event.target);
|
|
974
|
+
if (found === null) return;
|
|
975
|
+
event.preventDefault();
|
|
976
|
+
select(
|
|
977
|
+
found.rowId,
|
|
978
|
+
found.position.columnId,
|
|
979
|
+
keyboardSelectIntent(event)
|
|
980
|
+
);
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
nav.onKeyDown(event);
|
|
984
|
+
},
|
|
985
|
+
children: [
|
|
986
|
+
virtualRange !== null && virtualRange.offsetBefore > 0 && // `aria-hidden` and carrying neither `data-gridkit-column` nor
|
|
987
|
+
// `data-gridkit-group`/`data-gridkit-row-index`, so `bodyCellFrom`/
|
|
988
|
+
// `groupRowFrom` never mistake it for a real row — it exists purely
|
|
989
|
+
// to give the browser's scrollbar the correct total height and thumb
|
|
990
|
+
// position, the same way `GridFooter`'s `<tfoot>` isn't a "row" to
|
|
991
|
+
// any of this grid's own row-counting logic.
|
|
992
|
+
/* @__PURE__ */ jsx7("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx7(
|
|
993
|
+
"td",
|
|
994
|
+
{
|
|
995
|
+
style: {
|
|
996
|
+
height: virtualRange.offsetBefore,
|
|
997
|
+
padding: 0,
|
|
998
|
+
border: "none"
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
) }),
|
|
1002
|
+
visibleRows.map((entry) => {
|
|
1003
|
+
if (!("kind" in entry)) {
|
|
1004
|
+
const rowProps = rowPropsOf(entry.rowId);
|
|
1005
|
+
return /* @__PURE__ */ jsx7(
|
|
1006
|
+
GridRow_default,
|
|
1007
|
+
{
|
|
1008
|
+
ref: virtualRange?.measureRow(entry.rowIndex),
|
|
1009
|
+
columns,
|
|
1010
|
+
rowId: entry.rowId,
|
|
1011
|
+
row: entry.row,
|
|
1012
|
+
rowIndex: entry.rowIndex,
|
|
1013
|
+
datasetIndex: entry.datasetIndex,
|
|
1014
|
+
activeColumnId,
|
|
1015
|
+
selectedColumnIds: selection.selectedColumnIds,
|
|
1016
|
+
selected: selection.selectedRowIds.has(entry.rowId),
|
|
1017
|
+
selectedColumnId: selectedCell?.rowId === entry.rowId ? selectedCell.columnId : null,
|
|
1018
|
+
focusedColumnIndex: nav.focus.rowIndex === entry.rowIndex ? nav.focus.columnIndex : null,
|
|
1019
|
+
rowsSelectable: rowMode !== false,
|
|
1020
|
+
cellsSelectable: cellMode !== false,
|
|
1021
|
+
contextMenu: cellMenu,
|
|
1022
|
+
locale,
|
|
1023
|
+
cellMessages,
|
|
1024
|
+
rowClassName: rowProps.className,
|
|
1025
|
+
rowAttributes: rowProps.attributes
|
|
1026
|
+
},
|
|
1027
|
+
entry.rowId
|
|
1028
|
+
);
|
|
1029
|
+
}
|
|
1030
|
+
if (entry.kind === "group-summary") {
|
|
1031
|
+
return /* @__PURE__ */ jsx7(
|
|
1032
|
+
GridGroupSummaryRow_default,
|
|
1033
|
+
{
|
|
1034
|
+
ref: virtualRange?.measureRow(entry.rowIndex),
|
|
1035
|
+
groupId: entry.groupId,
|
|
1036
|
+
level: entry.level,
|
|
1037
|
+
rowIndex: entry.rowIndex,
|
|
1038
|
+
datasetIndex: entry.datasetIndex,
|
|
1039
|
+
results: entry.aggregates,
|
|
1040
|
+
aggregates,
|
|
1041
|
+
columns,
|
|
1042
|
+
locale
|
|
1043
|
+
},
|
|
1044
|
+
`${entry.groupId}-summary`
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
return /* @__PURE__ */ jsx7(
|
|
1048
|
+
GridGroupRow_default,
|
|
1049
|
+
{
|
|
1050
|
+
ref: virtualRange?.measureRow(entry.rowIndex),
|
|
1051
|
+
columnCount: columns.length,
|
|
1052
|
+
groupId: entry.groupId,
|
|
1053
|
+
level: entry.level,
|
|
1054
|
+
groupColumn: definitions.get(entry.columnId) ?? { field: entry.columnId },
|
|
1055
|
+
value: entry.value,
|
|
1056
|
+
expanded: entry.expanded,
|
|
1057
|
+
count: entry.count,
|
|
1058
|
+
rowIndex: entry.rowIndex,
|
|
1059
|
+
datasetIndex: entry.datasetIndex,
|
|
1060
|
+
posinset: ariaMeta.get(entry.groupId)?.posinset ?? 1,
|
|
1061
|
+
setsize: ariaMeta.get(entry.groupId)?.setsize ?? 1,
|
|
1062
|
+
aggregates: groupAggregateDisplay === "inline" ? aggregates : [],
|
|
1063
|
+
results: entry.aggregates,
|
|
1064
|
+
definitions,
|
|
1065
|
+
locale,
|
|
1066
|
+
cellMessages,
|
|
1067
|
+
focused: nav.focus.rowIndex === entry.rowIndex,
|
|
1068
|
+
contextMenu: groupMenu
|
|
1069
|
+
},
|
|
1070
|
+
entry.groupId
|
|
1071
|
+
);
|
|
1072
|
+
}),
|
|
1073
|
+
virtualRange !== null && virtualRange.offsetAfter > 0 && /* @__PURE__ */ jsx7("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx7(
|
|
1074
|
+
"td",
|
|
1075
|
+
{
|
|
1076
|
+
style: {
|
|
1077
|
+
height: virtualRange.offsetAfter,
|
|
1078
|
+
padding: 0,
|
|
1079
|
+
border: "none"
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
) }),
|
|
1083
|
+
infiniteScroll?.hasMore && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
1084
|
+
infiniteScroll.isLoadingMore === true && /* @__PURE__ */ jsx7("tr", { "aria-hidden": "true", className: "grid-loading-row", children: /* @__PURE__ */ jsx7("td", { colSpan: columns.length, className: "grid-loading-cell", children: infiniteScroll.loadingTemplate ? infiniteScroll.loadingTemplate() : messages.loadingMore }) }),
|
|
1085
|
+
/* @__PURE__ */ jsx7(
|
|
1086
|
+
"tr",
|
|
1087
|
+
{
|
|
1088
|
+
"aria-hidden": "true",
|
|
1089
|
+
ref: sentinelRef,
|
|
1090
|
+
className: "grid-sentinel-row",
|
|
1091
|
+
children: /* @__PURE__ */ jsx7(
|
|
1092
|
+
"td",
|
|
1093
|
+
{
|
|
1094
|
+
colSpan: columns.length,
|
|
1095
|
+
style: { padding: 0, border: "none" }
|
|
1096
|
+
}
|
|
1097
|
+
)
|
|
1098
|
+
}
|
|
1099
|
+
)
|
|
1100
|
+
] })
|
|
1101
|
+
]
|
|
1102
|
+
}
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
// src/DataGrid/components/GridFooter.tsx
|
|
1107
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1108
|
+
function GridFooter({
|
|
1109
|
+
columns,
|
|
1110
|
+
aggregates,
|
|
1111
|
+
results,
|
|
1112
|
+
rows,
|
|
1113
|
+
locale,
|
|
1114
|
+
ariaRowIndex
|
|
1115
|
+
}) {
|
|
1116
|
+
return /* @__PURE__ */ jsx8("tfoot", { role: "rowgroup", children: /* @__PURE__ */ jsx8("tr", { className: "grid-footer", role: "row", "aria-rowindex": ariaRowIndex, children: columns.map((entry) => {
|
|
1117
|
+
const specs = aggregates.filter(
|
|
1118
|
+
(candidate) => candidate.columnId === entry.id
|
|
1119
|
+
);
|
|
1120
|
+
return /* @__PURE__ */ jsx8(
|
|
1121
|
+
"td",
|
|
1122
|
+
{
|
|
1123
|
+
role: "gridcell",
|
|
1124
|
+
"data-gridkit-column": entry.id,
|
|
1125
|
+
className: "grid-footer-cell",
|
|
1126
|
+
style: { textAlign: specs[0]?.alignment ?? entry.alignment },
|
|
1127
|
+
children: specs.map(
|
|
1128
|
+
(spec) => renderAggregate(
|
|
1129
|
+
results.get(spec.id ?? spec.columnId),
|
|
1130
|
+
spec,
|
|
1131
|
+
entry.column,
|
|
1132
|
+
rows,
|
|
1133
|
+
locale
|
|
1134
|
+
)
|
|
1135
|
+
).flatMap(
|
|
1136
|
+
(rendered, index) => index === 0 ? [rendered] : [", ", rendered]
|
|
1137
|
+
)
|
|
1138
|
+
},
|
|
1139
|
+
entry.id
|
|
1140
|
+
);
|
|
1141
|
+
}) }) });
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
// src/DataGrid/components/GridPager.tsx
|
|
1145
|
+
import { paginationWindow } from "@gridkitjs/core";
|
|
1146
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1147
|
+
function PagerNavButton({
|
|
1148
|
+
className,
|
|
1149
|
+
label,
|
|
1150
|
+
disabled,
|
|
1151
|
+
onClick,
|
|
1152
|
+
children
|
|
1153
|
+
}) {
|
|
1154
|
+
return /* @__PURE__ */ jsx9(
|
|
1155
|
+
"button",
|
|
1156
|
+
{
|
|
1157
|
+
type: "button",
|
|
1158
|
+
className: `grid-pager-button grid-pager-nav ${className}`,
|
|
1159
|
+
"aria-label": label,
|
|
1160
|
+
title: label,
|
|
1161
|
+
...ariaAttr(disabled, "aria-disabled", true),
|
|
1162
|
+
onClick: () => {
|
|
1163
|
+
if (!disabled) onClick();
|
|
1164
|
+
},
|
|
1165
|
+
children
|
|
1166
|
+
}
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
function GridPager({ pager, config, messages }) {
|
|
1170
|
+
const { pagination, pageCount, currentPage } = pager;
|
|
1171
|
+
const variant = config?.variant ?? "compact";
|
|
1172
|
+
const sizeOptions = config?.sizeOptions;
|
|
1173
|
+
const atFirst = pagination.pageIndex <= 0;
|
|
1174
|
+
const atLast = pagination.pageIndex >= pageCount - 1;
|
|
1175
|
+
const barStyle = {
|
|
1176
|
+
"--gridkit-pager-digits": String(String(Math.max(1, pageCount)).length)
|
|
1177
|
+
};
|
|
1178
|
+
return /* @__PURE__ */ jsxs6(
|
|
1179
|
+
"div",
|
|
1180
|
+
{
|
|
1181
|
+
className: "gridkit-grid-pager",
|
|
1182
|
+
role: "group",
|
|
1183
|
+
"aria-label": messages.pagerLabel,
|
|
1184
|
+
children: [
|
|
1185
|
+
/* @__PURE__ */ jsxs6("div", { className: "grid-pager-bar", style: barStyle, children: [
|
|
1186
|
+
/* @__PURE__ */ jsx9(
|
|
1187
|
+
PagerNavButton,
|
|
1188
|
+
{
|
|
1189
|
+
className: "grid-pager-first",
|
|
1190
|
+
label: messages.firstPage,
|
|
1191
|
+
disabled: atFirst,
|
|
1192
|
+
onClick: () => {
|
|
1193
|
+
pager.goToPage(0);
|
|
1194
|
+
},
|
|
1195
|
+
children: /* @__PURE__ */ jsx9(ChevronsLeftIcon, {})
|
|
1196
|
+
}
|
|
1197
|
+
),
|
|
1198
|
+
/* @__PURE__ */ jsx9(
|
|
1199
|
+
PagerNavButton,
|
|
1200
|
+
{
|
|
1201
|
+
className: "grid-pager-previous",
|
|
1202
|
+
label: messages.previousPage,
|
|
1203
|
+
disabled: atFirst,
|
|
1204
|
+
onClick: () => {
|
|
1205
|
+
pager.previousPage();
|
|
1206
|
+
},
|
|
1207
|
+
children: /* @__PURE__ */ jsx9(ChevronLeftIcon, {})
|
|
1208
|
+
}
|
|
1209
|
+
),
|
|
1210
|
+
variant === "numbered" ? paginationWindow(currentPage, pageCount, {
|
|
1211
|
+
boundaryCount: config?.boundaryCount,
|
|
1212
|
+
siblingCount: config?.siblingCount
|
|
1213
|
+
}).map(
|
|
1214
|
+
(entry, index) => entry === "ellipsis" ? /* @__PURE__ */ jsx9(
|
|
1215
|
+
"span",
|
|
1216
|
+
{
|
|
1217
|
+
className: "grid-pager-ellipsis",
|
|
1218
|
+
"aria-hidden": "true",
|
|
1219
|
+
children: "\u2026"
|
|
1220
|
+
},
|
|
1221
|
+
`ellipsis-${String(index)}`
|
|
1222
|
+
) : /* @__PURE__ */ jsx9(
|
|
1223
|
+
"button",
|
|
1224
|
+
{
|
|
1225
|
+
type: "button",
|
|
1226
|
+
className: "grid-pager-button grid-pager-page",
|
|
1227
|
+
"aria-label": messages.pageButtonLabel(entry),
|
|
1228
|
+
"aria-current": entry === currentPage ? "page" : void 0,
|
|
1229
|
+
onClick: () => {
|
|
1230
|
+
pager.goToPage(entry - 1);
|
|
1231
|
+
},
|
|
1232
|
+
children: entry
|
|
1233
|
+
},
|
|
1234
|
+
entry
|
|
1235
|
+
)
|
|
1236
|
+
) : /* @__PURE__ */ jsxs6("span", { className: "grid-pager-status-slot", children: [
|
|
1237
|
+
/* @__PURE__ */ jsx9("span", { className: "grid-pager-status", children: messages.pageStatus(
|
|
1238
|
+
pageCount === 0 ? 0 : currentPage,
|
|
1239
|
+
pageCount
|
|
1240
|
+
) }),
|
|
1241
|
+
/* @__PURE__ */ jsx9("span", { className: "grid-pager-status-sizer", "aria-hidden": "true", children: messages.pageStatus(pageCount, pageCount) })
|
|
1242
|
+
] }),
|
|
1243
|
+
/* @__PURE__ */ jsx9(
|
|
1244
|
+
PagerNavButton,
|
|
1245
|
+
{
|
|
1246
|
+
className: "grid-pager-next",
|
|
1247
|
+
label: messages.nextPage,
|
|
1248
|
+
disabled: atLast,
|
|
1249
|
+
onClick: () => {
|
|
1250
|
+
pager.nextPage();
|
|
1251
|
+
},
|
|
1252
|
+
children: /* @__PURE__ */ jsx9(ChevronRightIcon, {})
|
|
1253
|
+
}
|
|
1254
|
+
),
|
|
1255
|
+
/* @__PURE__ */ jsx9(
|
|
1256
|
+
PagerNavButton,
|
|
1257
|
+
{
|
|
1258
|
+
className: "grid-pager-last",
|
|
1259
|
+
label: messages.lastPage,
|
|
1260
|
+
disabled: atLast,
|
|
1261
|
+
onClick: () => {
|
|
1262
|
+
pager.goToPage(pageCount - 1);
|
|
1263
|
+
},
|
|
1264
|
+
children: /* @__PURE__ */ jsx9(ChevronsRightIcon, {})
|
|
1265
|
+
}
|
|
1266
|
+
)
|
|
1267
|
+
] }),
|
|
1268
|
+
sizeOptions !== void 0 && sizeOptions.length > 0 && /* @__PURE__ */ jsxs6("label", { className: "grid-pager-page-size", children: [
|
|
1269
|
+
/* @__PURE__ */ jsx9(
|
|
1270
|
+
"select",
|
|
1271
|
+
{
|
|
1272
|
+
value: pagination.pageSize,
|
|
1273
|
+
onChange: (event) => {
|
|
1274
|
+
pager.setPageSize(Number(event.target.value));
|
|
1275
|
+
},
|
|
1276
|
+
children: sizeOptions.map((size) => /* @__PURE__ */ jsx9("option", { value: size, children: size }, size))
|
|
1277
|
+
}
|
|
1278
|
+
),
|
|
1279
|
+
/* @__PURE__ */ jsx9("span", { className: "grid-pager-page-size-label", children: messages.pageSizeLabel })
|
|
1280
|
+
] })
|
|
1281
|
+
]
|
|
1282
|
+
}
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// src/DataGrid/components/GroupByBar.tsx
|
|
1287
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
1288
|
+
import {
|
|
1289
|
+
resolveColumnLabel as resolveColumnLabel2,
|
|
1290
|
+
resolveKeyboardDropTarget
|
|
1291
|
+
} from "@gridkitjs/core";
|
|
1292
|
+
|
|
1293
|
+
// src/DataGrid/useGroupByDrag.ts
|
|
1294
|
+
import {
|
|
1295
|
+
resolveGroupByDropTarget
|
|
1296
|
+
} from "@gridkitjs/dom";
|
|
1297
|
+
|
|
1298
|
+
// src/DataGrid/useDragReorder.ts
|
|
1299
|
+
import {
|
|
1300
|
+
useRef,
|
|
1301
|
+
useState as useState3
|
|
1302
|
+
} from "react";
|
|
1303
|
+
import {
|
|
1304
|
+
NO_DRAG,
|
|
1305
|
+
startDragReorder
|
|
1306
|
+
} from "@gridkitjs/dom";
|
|
1307
|
+
function useDragReorder({
|
|
1308
|
+
resolveTarget,
|
|
1309
|
+
onDrop
|
|
1310
|
+
}) {
|
|
1311
|
+
const [drag, setDrag] = useState3(NO_DRAG);
|
|
1312
|
+
const dragged = useRef(false);
|
|
1313
|
+
function justDragged() {
|
|
1314
|
+
const answer = dragged.current;
|
|
1315
|
+
dragged.current = false;
|
|
1316
|
+
return answer;
|
|
1317
|
+
}
|
|
1318
|
+
function startDrag(id, grabElement, event) {
|
|
1319
|
+
startDragReorder(id, grabElement, event, {
|
|
1320
|
+
resolveTarget,
|
|
1321
|
+
onState(state) {
|
|
1322
|
+
if (state.draggedId !== null) {
|
|
1323
|
+
dragged.current = true;
|
|
1324
|
+
}
|
|
1325
|
+
setDrag(state);
|
|
1326
|
+
},
|
|
1327
|
+
onDrop
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
return {
|
|
1331
|
+
draggedId: drag.draggedId,
|
|
1332
|
+
dropTarget: drag.dropTarget,
|
|
1333
|
+
ghostTransform: drag.ghostTransform,
|
|
1334
|
+
startDrag,
|
|
1335
|
+
justDragged
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
// src/DataGrid/useGroupByDrag.ts
|
|
1340
|
+
function useGroupByDrag({
|
|
1341
|
+
groupBy,
|
|
1342
|
+
onDrop
|
|
1343
|
+
}) {
|
|
1344
|
+
const drag = useDragReorder({
|
|
1345
|
+
resolveTarget: (clientX, clientY, movedId) => resolveGroupByDropTarget(clientX, clientY, movedId, groupBy),
|
|
1346
|
+
onDrop: (target, movedId) => {
|
|
1347
|
+
onDrop(movedId, target.beforeColumnId);
|
|
1348
|
+
}
|
|
1349
|
+
});
|
|
1350
|
+
return {
|
|
1351
|
+
draggedColumnId: drag.draggedId,
|
|
1352
|
+
dropTarget: drag.dropTarget,
|
|
1353
|
+
ghostTransform: drag.ghostTransform,
|
|
1354
|
+
startDrag: (columnId, event) => {
|
|
1355
|
+
drag.startDrag(columnId, event.currentTarget, event);
|
|
1356
|
+
},
|
|
1357
|
+
justDragged: drag.justDragged
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
// src/DataGrid/components/GroupByBar.tsx
|
|
1362
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1363
|
+
function GroupByBar({
|
|
1364
|
+
columns,
|
|
1365
|
+
definitions,
|
|
1366
|
+
groupBy,
|
|
1367
|
+
controller,
|
|
1368
|
+
columnName,
|
|
1369
|
+
headerDragEligible,
|
|
1370
|
+
headerDragBlocked,
|
|
1371
|
+
headerDropTarget,
|
|
1372
|
+
messages
|
|
1373
|
+
}) {
|
|
1374
|
+
const groupByIds = groupBy.map((entry) => entry.columnId);
|
|
1375
|
+
const chipDrag = useGroupByDrag({
|
|
1376
|
+
groupBy,
|
|
1377
|
+
onDrop: (movedId, beforeColumnId) => {
|
|
1378
|
+
controller.moveGroupBy(movedId, beforeColumnId);
|
|
1379
|
+
}
|
|
1380
|
+
});
|
|
1381
|
+
const activeDropTarget = chipDrag.dropTarget ?? headerDropTarget;
|
|
1382
|
+
const isDragTarget = chipDrag.draggedColumnId !== null || headerDragEligible;
|
|
1383
|
+
const showPlaceholder = groupBy.length === 0 && columns.some((entry) => entry.groupByDraggable);
|
|
1384
|
+
function labelFor(columnId) {
|
|
1385
|
+
const definition = definitions.get(columnId);
|
|
1386
|
+
return definition === void 0 ? columnId : resolveColumnLabel2(definition);
|
|
1387
|
+
}
|
|
1388
|
+
function moveByKeyboard(columnId, direction) {
|
|
1389
|
+
const beforeColumnId = resolveKeyboardDropTarget(
|
|
1390
|
+
groupByIds,
|
|
1391
|
+
columnId,
|
|
1392
|
+
direction
|
|
1393
|
+
);
|
|
1394
|
+
if (beforeColumnId === void 0) {
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
controller.moveGroupBy(columnId, beforeColumnId);
|
|
1398
|
+
}
|
|
1399
|
+
return /* @__PURE__ */ jsxs7(
|
|
1400
|
+
"div",
|
|
1401
|
+
{
|
|
1402
|
+
className: classNames(
|
|
1403
|
+
"gridkit-group-by-bar",
|
|
1404
|
+
isDragTarget ? "is-drag-target" : "",
|
|
1405
|
+
headerDragBlocked ? "is-drag-blocked" : ""
|
|
1406
|
+
),
|
|
1407
|
+
"data-gridkit-group-by-bar": "",
|
|
1408
|
+
role: "group",
|
|
1409
|
+
"aria-label": messages.groupByBarLabel,
|
|
1410
|
+
children: [
|
|
1411
|
+
showPlaceholder && /* @__PURE__ */ jsx10("span", { className: "group-by-bar-placeholder", children: messages.groupByBarPlaceholder }),
|
|
1412
|
+
groupBy.map((entry, index) => {
|
|
1413
|
+
const dropBefore = activeDropTarget?.beforeColumnId === entry.columnId;
|
|
1414
|
+
const dropAfter = activeDropTarget?.beforeColumnId === null && index === groupBy.length - 1;
|
|
1415
|
+
const dragging = chipDrag.draggedColumnId === entry.columnId;
|
|
1416
|
+
return /* @__PURE__ */ jsxs7(
|
|
1417
|
+
"span",
|
|
1418
|
+
{
|
|
1419
|
+
className: classNames(
|
|
1420
|
+
"group-by-chip",
|
|
1421
|
+
dragging ? "is-dragging" : "",
|
|
1422
|
+
dropBefore ? "is-drop-before" : "",
|
|
1423
|
+
dropAfter ? "is-drop-after" : ""
|
|
1424
|
+
),
|
|
1425
|
+
"data-gridkit-group-chip": entry.columnId,
|
|
1426
|
+
tabIndex: 0,
|
|
1427
|
+
"aria-label": messages.groupByChipLabel(
|
|
1428
|
+
columnName(entry.columnId),
|
|
1429
|
+
index + 1,
|
|
1430
|
+
groupBy.length
|
|
1431
|
+
),
|
|
1432
|
+
"aria-keyshortcuts": "Control+ArrowLeft Control+ArrowRight",
|
|
1433
|
+
onPointerDown: (event) => {
|
|
1434
|
+
chipDrag.startDrag(entry.columnId, event);
|
|
1435
|
+
},
|
|
1436
|
+
onKeyDown: (event) => {
|
|
1437
|
+
const horizontal = event.key === "ArrowLeft" || event.key === "ArrowRight";
|
|
1438
|
+
if (horizontal && event.ctrlKey) {
|
|
1439
|
+
event.preventDefault();
|
|
1440
|
+
moveByKeyboard(
|
|
1441
|
+
entry.columnId,
|
|
1442
|
+
event.key === "ArrowLeft" ? -1 : 1
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
},
|
|
1446
|
+
children: [
|
|
1447
|
+
/* @__PURE__ */ jsx10("span", { className: "group-by-chip-label", children: labelFor(entry.columnId) }),
|
|
1448
|
+
/* @__PURE__ */ jsx10(
|
|
1449
|
+
"button",
|
|
1450
|
+
{
|
|
1451
|
+
type: "button",
|
|
1452
|
+
className: "group-by-chip-remove",
|
|
1453
|
+
"aria-label": messages.removeGroupBy(columnName(entry.columnId)),
|
|
1454
|
+
onPointerDown: (event) => {
|
|
1455
|
+
event.stopPropagation();
|
|
1456
|
+
},
|
|
1457
|
+
onClick: () => {
|
|
1458
|
+
controller.toggleGroupBy(entry.columnId);
|
|
1459
|
+
},
|
|
1460
|
+
children: "\xD7"
|
|
1461
|
+
}
|
|
1462
|
+
)
|
|
1463
|
+
]
|
|
1464
|
+
},
|
|
1465
|
+
entry.columnId
|
|
1466
|
+
);
|
|
1467
|
+
}),
|
|
1468
|
+
chipDrag.draggedColumnId !== null && chipDrag.ghostTransform !== null && createPortal2(
|
|
1469
|
+
/* @__PURE__ */ jsx10(
|
|
1470
|
+
"span",
|
|
1471
|
+
{
|
|
1472
|
+
className: "group-by-chip drag-ghost",
|
|
1473
|
+
style: { transform: chipDrag.ghostTransform },
|
|
1474
|
+
"aria-hidden": "true",
|
|
1475
|
+
children: labelFor(chipDrag.draggedColumnId)
|
|
1476
|
+
}
|
|
1477
|
+
),
|
|
1478
|
+
document.body
|
|
1479
|
+
)
|
|
1480
|
+
]
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// src/DataGrid/announcedCallbacks.ts
|
|
1486
|
+
import {
|
|
1487
|
+
isColumnVisible
|
|
1488
|
+
} from "@gridkitjs/core";
|
|
1489
|
+
function announcedCallbacks({
|
|
1490
|
+
callbacks,
|
|
1491
|
+
announce,
|
|
1492
|
+
messages,
|
|
1493
|
+
columnName,
|
|
1494
|
+
columnOf
|
|
1495
|
+
}) {
|
|
1496
|
+
return {
|
|
1497
|
+
/**
|
|
1498
|
+
* Announced only once the drag ends: the controller reports the
|
|
1499
|
+
* continuous `"move"` phase as well, and a live region given every frame
|
|
1500
|
+
* of a drag says nothing an assistive technology can keep up with.
|
|
1501
|
+
*/
|
|
1502
|
+
onColumnResize: (event) => {
|
|
1503
|
+
callbacks.onColumnResize?.(event);
|
|
1504
|
+
if (event.phase === "end") {
|
|
1505
|
+
announce(
|
|
1506
|
+
messages.columnResized(
|
|
1507
|
+
columnName(event.columnId),
|
|
1508
|
+
Math.round(event.width)
|
|
1509
|
+
)
|
|
1510
|
+
);
|
|
1511
|
+
}
|
|
1512
|
+
},
|
|
1513
|
+
/**
|
|
1514
|
+
* Naming a column shown or hidden alone, and counting several — "Show
|
|
1515
|
+
* all" in the column chooser, or `hideColumns` given a list. A change
|
|
1516
|
+
* that shows some and hides others, as restoring a layout can, has no
|
|
1517
|
+
* one thing to say, and says nothing.
|
|
1518
|
+
*/
|
|
1519
|
+
onColumnVisibilityChange: (event) => {
|
|
1520
|
+
callbacks.onColumnVisibilityChange?.(event);
|
|
1521
|
+
const { columnIds, visibility } = event;
|
|
1522
|
+
const [columnId] = columnIds;
|
|
1523
|
+
const shownCount = columnIds.filter((id) => {
|
|
1524
|
+
const column = columnOf(id);
|
|
1525
|
+
return column !== void 0 && isColumnVisible(column, visibility);
|
|
1526
|
+
}).length;
|
|
1527
|
+
if (columnId === void 0 || shownCount !== 0 && shownCount !== columnIds.length) {
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
const shown = shownCount > 0;
|
|
1531
|
+
if (columnIds.length > 1) {
|
|
1532
|
+
announce(
|
|
1533
|
+
shown ? messages.columnsShown(columnIds.length) : messages.columnsHidden(columnIds.length)
|
|
1534
|
+
);
|
|
1535
|
+
return;
|
|
1536
|
+
}
|
|
1537
|
+
announce(
|
|
1538
|
+
shown ? messages.columnShown(columnName(columnId)) : messages.columnHidden(columnName(columnId))
|
|
1539
|
+
);
|
|
1540
|
+
},
|
|
1541
|
+
/** A toggle, a stack, or a clear back to "none" each get their own. */
|
|
1542
|
+
onColumnSortChange: (event) => {
|
|
1543
|
+
callbacks.onColumnSortChange?.(event);
|
|
1544
|
+
const entry = event.sort.find(
|
|
1545
|
+
(candidate) => candidate.columnId === event.columnId
|
|
1546
|
+
);
|
|
1547
|
+
if (entry === void 0) {
|
|
1548
|
+
announce(messages.sortCleared(columnName(event.columnId)));
|
|
1549
|
+
return;
|
|
1550
|
+
}
|
|
1551
|
+
announce(
|
|
1552
|
+
messages.columnSorted(
|
|
1553
|
+
columnName(event.columnId),
|
|
1554
|
+
entry.direction,
|
|
1555
|
+
event.sort.indexOf(entry) + 1,
|
|
1556
|
+
event.sort.length
|
|
1557
|
+
)
|
|
1558
|
+
);
|
|
1559
|
+
},
|
|
1560
|
+
onGroupByChange: (event) => {
|
|
1561
|
+
callbacks.onGroupByChange?.(event);
|
|
1562
|
+
const entry = event.groupBy.find(
|
|
1563
|
+
(candidate) => candidate.columnId === event.columnId
|
|
1564
|
+
);
|
|
1565
|
+
if (entry === void 0) {
|
|
1566
|
+
announce(messages.groupingRemoved(columnName(event.columnId)));
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1569
|
+
announce(
|
|
1570
|
+
messages.groupedBy(
|
|
1571
|
+
columnName(event.columnId),
|
|
1572
|
+
event.groupBy.indexOf(entry) + 1,
|
|
1573
|
+
event.groupBy.length
|
|
1574
|
+
)
|
|
1575
|
+
);
|
|
1576
|
+
},
|
|
1577
|
+
/**
|
|
1578
|
+
* `groupId: null` marks `expandAll`/`collapseAll`, which touch every
|
|
1579
|
+
* group in one call rather than one at a time — announced as a single
|
|
1580
|
+
* summary instead of naming a group that doesn't apply.
|
|
1581
|
+
*/
|
|
1582
|
+
onGroupExpansionChange: (event) => {
|
|
1583
|
+
callbacks.onGroupExpansionChange?.(event);
|
|
1584
|
+
if (event.groupId === null) {
|
|
1585
|
+
announce(
|
|
1586
|
+
event.expansion.length === 0 ? messages.allGroupsExpanded : messages.allGroupsCollapsed
|
|
1587
|
+
);
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
1590
|
+
announce(
|
|
1591
|
+
event.expansion.includes(event.groupId) ? messages.groupCollapsed : messages.groupExpanded
|
|
1592
|
+
);
|
|
1593
|
+
},
|
|
1594
|
+
onPaginationChange: (event) => {
|
|
1595
|
+
callbacks.onPaginationChange?.(event);
|
|
1596
|
+
announce(
|
|
1597
|
+
messages.pageStatus(event.pagination.pageIndex + 1, event.pageCount)
|
|
1598
|
+
);
|
|
1599
|
+
},
|
|
1600
|
+
/**
|
|
1601
|
+
* Unlike rows and columns, a cell selection is always exactly one cell —
|
|
1602
|
+
* there is no multi-cell range — so it never crosses the count's >1
|
|
1603
|
+
* threshold and the focused cell's own `aria-selected` is the only
|
|
1604
|
+
* feedback a screen-reader user would otherwise get. Announced on every
|
|
1605
|
+
* change that lands on a cell instead.
|
|
1606
|
+
*/
|
|
1607
|
+
onCellSelectionChange: (event) => {
|
|
1608
|
+
callbacks.onCellSelectionChange?.(event);
|
|
1609
|
+
if (event.selected !== null) {
|
|
1610
|
+
announce(
|
|
1611
|
+
messages.cellSelected(
|
|
1612
|
+
columnName(event.selected.columnId),
|
|
1613
|
+
event.selected.rowIndex + 1
|
|
1614
|
+
)
|
|
1615
|
+
);
|
|
1616
|
+
}
|
|
1617
|
+
},
|
|
1618
|
+
/**
|
|
1619
|
+
* Announced only for a change touching more than one row or column. A
|
|
1620
|
+
* single selection is already carried by the focused member's own
|
|
1621
|
+
* `aria-selected`, and repeating it here would talk over that. Counted
|
|
1622
|
+
* by id, so rows the change touched off screen — on another page, in a
|
|
1623
|
+
* collapsed group — count too.
|
|
1624
|
+
*/
|
|
1625
|
+
onSelectionDiff: (event) => {
|
|
1626
|
+
if (event.added.length + event.removed.length > 1) {
|
|
1627
|
+
announce(messages.selectedCount(event.selection.length, event.target));
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
};
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
// src/DataGrid/clipboard/useGridCopy.ts
|
|
1634
|
+
import { runCommand } from "@gridkitjs/core";
|
|
1635
|
+
import { isNativeCopy } from "@gridkitjs/dom";
|
|
1636
|
+
function isCopyKey(event) {
|
|
1637
|
+
return (event.ctrlKey || event.metaKey) && !event.altKey && (event.key === "c" || event.key === "C");
|
|
1638
|
+
}
|
|
1639
|
+
function useGridCopy({
|
|
1640
|
+
controller,
|
|
1641
|
+
commands,
|
|
1642
|
+
nav
|
|
1643
|
+
}) {
|
|
1644
|
+
function run(commandId, target) {
|
|
1645
|
+
const command = commands.commands.get(commandId);
|
|
1646
|
+
return command !== void 0 && runCommand(command, commands.contextFor(target));
|
|
1647
|
+
}
|
|
1648
|
+
function focusedCell() {
|
|
1649
|
+
const { rowIndex, columnIndex } = nav.focus;
|
|
1650
|
+
if (rowIndex === HEADER_ROW) {
|
|
1651
|
+
return null;
|
|
1652
|
+
}
|
|
1653
|
+
const { pageRows, columns } = controller.getView();
|
|
1654
|
+
const entry = pageRows[rowIndex];
|
|
1655
|
+
const column = columns[columnIndex];
|
|
1656
|
+
return entry === void 0 || "kind" in entry || column === void 0 ? null : { area: "cell", rowId: entry.rowId, columnId: column.id };
|
|
1657
|
+
}
|
|
1658
|
+
return (event) => {
|
|
1659
|
+
if (!isCopyKey(event) || isNativeCopy(event.target)) {
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1662
|
+
const cell = focusedCell();
|
|
1663
|
+
if (run("copy.selection", { area: "grid" }) || cell !== null && run("copy.cell", cell)) {
|
|
1664
|
+
event.preventDefault();
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
// src/DataGrid/commands/useGridCommands.ts
|
|
1670
|
+
import { useMemo as useMemo3 } from "react";
|
|
1671
|
+
import {
|
|
1672
|
+
createCommandContext,
|
|
1673
|
+
resolveCommands,
|
|
1674
|
+
runCommand as runCommand2
|
|
1675
|
+
} from "@gridkitjs/core";
|
|
1676
|
+
|
|
1677
|
+
// src/DataGrid/clipboard/copyToClipboard.ts
|
|
1678
|
+
import { writeClipboard } from "@gridkitjs/dom";
|
|
1679
|
+
function copyToClipboard(content, { messages, announce }) {
|
|
1680
|
+
writeClipboard(content).then(
|
|
1681
|
+
() => {
|
|
1682
|
+
announce(messages.copied(content.count, content.unit));
|
|
1683
|
+
},
|
|
1684
|
+
(error) => {
|
|
1685
|
+
console.error("DataGrid: the clipboard could not be written.", error);
|
|
1686
|
+
announce(messages.copyFailed);
|
|
1687
|
+
}
|
|
1688
|
+
);
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
// src/DataGrid/export/useSaveFile.ts
|
|
1692
|
+
import { useRef as useRef2 } from "react";
|
|
1693
|
+
import { downloadBlob } from "@gridkitjs/dom";
|
|
1694
|
+
|
|
1695
|
+
// src/DataGrid/export/exportApi.ts
|
|
1696
|
+
import {
|
|
1697
|
+
exportFile,
|
|
1698
|
+
resolveExportWriters
|
|
1699
|
+
} from "@gridkitjs/core";
|
|
1700
|
+
function exportBlob({ content, mimeType }) {
|
|
1701
|
+
const part = typeof content === "string" ? content : content.slice();
|
|
1702
|
+
return new Blob([part], { type: mimeType });
|
|
1703
|
+
}
|
|
1704
|
+
function exportApi({
|
|
1705
|
+
contextFor
|
|
1706
|
+
}) {
|
|
1707
|
+
return {
|
|
1708
|
+
exportData: async (format, options) => {
|
|
1709
|
+
const context = contextFor({ area: "grid" });
|
|
1710
|
+
const { export: defaults, exportWriters } = context.options;
|
|
1711
|
+
const file = exportFile(
|
|
1712
|
+
context,
|
|
1713
|
+
format,
|
|
1714
|
+
{ ...defaults, ...options },
|
|
1715
|
+
resolveExportWriters(exportWriters)
|
|
1716
|
+
);
|
|
1717
|
+
if (file === null) {
|
|
1718
|
+
throw new Error(
|
|
1719
|
+
"DataGrid: there is no export writer for that format \u2014 register one through `exportWriters`."
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
return exportBlob(await file);
|
|
1723
|
+
}
|
|
1724
|
+
};
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
// src/DataGrid/export/useSaveFile.ts
|
|
1728
|
+
function download(file) {
|
|
1729
|
+
downloadBlob(exportBlob(file), file.fileName);
|
|
1730
|
+
}
|
|
1731
|
+
function useSaveFile({
|
|
1732
|
+
messages,
|
|
1733
|
+
announce
|
|
1734
|
+
}) {
|
|
1735
|
+
const writingRef = useRef2(false);
|
|
1736
|
+
return (file) => {
|
|
1737
|
+
if (writingRef.current) {
|
|
1738
|
+
console.error(
|
|
1739
|
+
"DataGrid: an export is still being written, so this one was dropped."
|
|
1740
|
+
);
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
if (!(file instanceof Promise)) {
|
|
1744
|
+
download(file);
|
|
1745
|
+
return;
|
|
1746
|
+
}
|
|
1747
|
+
writingRef.current = true;
|
|
1748
|
+
file.then(download, (error) => {
|
|
1749
|
+
console.error("DataGrid: the export's writer failed.", error);
|
|
1750
|
+
announce(messages.exportFailed);
|
|
1751
|
+
}).finally(() => {
|
|
1752
|
+
writingRef.current = false;
|
|
1753
|
+
});
|
|
1754
|
+
};
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
// src/DataGrid/print/printApi.ts
|
|
1758
|
+
import {
|
|
1759
|
+
exportPrintDocument
|
|
1760
|
+
} from "@gridkitjs/core";
|
|
1761
|
+
import { printDocument, printStyles } from "@gridkitjs/dom";
|
|
1762
|
+
function printGrid(document2, { styles = "" }) {
|
|
1763
|
+
return printDocument({
|
|
1764
|
+
title: document2.title,
|
|
1765
|
+
bodyHtml: document2.bodyHtml,
|
|
1766
|
+
styles: printStyles(document2.page) + styles
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
function printApi({
|
|
1770
|
+
contextFor
|
|
1771
|
+
}) {
|
|
1772
|
+
return {
|
|
1773
|
+
print: (options) => {
|
|
1774
|
+
const context = contextFor({ area: "grid" });
|
|
1775
|
+
const merged = { ...context.options.print, ...options };
|
|
1776
|
+
return printGrid(exportPrintDocument(context, merged), merged);
|
|
1777
|
+
}
|
|
1778
|
+
};
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
// src/DataGrid/commands/useGridCommands.ts
|
|
1782
|
+
function useGridCommands({
|
|
1783
|
+
controller,
|
|
1784
|
+
commands: appCommands,
|
|
1785
|
+
onCommand,
|
|
1786
|
+
messages,
|
|
1787
|
+
announce,
|
|
1788
|
+
resize,
|
|
1789
|
+
openPanel
|
|
1790
|
+
}) {
|
|
1791
|
+
const commands = useMemo3(() => resolveCommands(appCommands), [appCommands]);
|
|
1792
|
+
const saveFile = useSaveFile({ messages, announce });
|
|
1793
|
+
const host = {
|
|
1794
|
+
autoFitColumns: (columnIds) => {
|
|
1795
|
+
const { columns } = controller.getView();
|
|
1796
|
+
let fitted = 0;
|
|
1797
|
+
for (const columnId of columnIds) {
|
|
1798
|
+
const entry = columns.find((candidate) => candidate.id === columnId);
|
|
1799
|
+
if (entry !== void 0 && resize.sizeToContent(entry)) {
|
|
1800
|
+
fitted += 1;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
if (fitted > 1) {
|
|
1804
|
+
announce(messages.columnsAutoFitted(fitted));
|
|
1805
|
+
}
|
|
1806
|
+
},
|
|
1807
|
+
openPanel,
|
|
1808
|
+
announce,
|
|
1809
|
+
saveFile,
|
|
1810
|
+
writeClipboard: (content) => {
|
|
1811
|
+
copyToClipboard(content, { messages, announce });
|
|
1812
|
+
},
|
|
1813
|
+
print: (document2, options) => {
|
|
1814
|
+
printGrid(document2, options).catch((error) => {
|
|
1815
|
+
console.error("DataGrid: the print failed.", error);
|
|
1816
|
+
});
|
|
1817
|
+
}
|
|
1818
|
+
};
|
|
1819
|
+
function contextFor(target) {
|
|
1820
|
+
return createCommandContext({ controller, target, messages, host });
|
|
1821
|
+
}
|
|
1822
|
+
function report(commandId, target, source) {
|
|
1823
|
+
onCommand?.({ commandId, target, source });
|
|
1824
|
+
}
|
|
1825
|
+
return {
|
|
1826
|
+
commands,
|
|
1827
|
+
host,
|
|
1828
|
+
contextFor,
|
|
1829
|
+
report,
|
|
1830
|
+
run: (commandId, target, source) => {
|
|
1831
|
+
const command = commands.get(commandId);
|
|
1832
|
+
if (command === void 0) {
|
|
1833
|
+
console.error(`DataGrid: there is no command \`${commandId}\` to run.`);
|
|
1834
|
+
return false;
|
|
1835
|
+
}
|
|
1836
|
+
if (!runCommand2(command, contextFor(target))) {
|
|
1837
|
+
return false;
|
|
1838
|
+
}
|
|
1839
|
+
report(commandId, target, source);
|
|
1840
|
+
return true;
|
|
1841
|
+
}
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
// src/DataGrid/menu/GridMenu.tsx
|
|
1846
|
+
import { useLayoutEffect as useLayoutEffect3, useRef as useRef4, useState as useState4 } from "react";
|
|
1847
|
+
import {
|
|
1848
|
+
attachMenu
|
|
1849
|
+
} from "@gridkitjs/dom";
|
|
1850
|
+
|
|
1851
|
+
// src/DataGrid/overlay/Overlay.tsx
|
|
1852
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef3 } from "react";
|
|
1853
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
1854
|
+
import {
|
|
1855
|
+
attachOverlay
|
|
1856
|
+
} from "@gridkitjs/dom";
|
|
1857
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1858
|
+
var ANCHOR_GAP = 4;
|
|
1859
|
+
function attachedFocus(focus) {
|
|
1860
|
+
return typeof focus === "object" && !(focus instanceof HTMLElement) ? focus.current ?? "first" : focus;
|
|
1861
|
+
}
|
|
1862
|
+
function overlayThemeClassName(element) {
|
|
1863
|
+
const scope = element?.closest(".gridkit-light, .gridkit-dark");
|
|
1864
|
+
if (scope === null || scope === void 0) {
|
|
1865
|
+
return "";
|
|
1866
|
+
}
|
|
1867
|
+
return scope.classList.contains("gridkit-dark") ? "gridkit-dark" : "gridkit-light";
|
|
1868
|
+
}
|
|
1869
|
+
function Overlay({
|
|
1870
|
+
anchor,
|
|
1871
|
+
placement,
|
|
1872
|
+
gap,
|
|
1873
|
+
offset,
|
|
1874
|
+
initialFocus,
|
|
1875
|
+
returnFocusTo,
|
|
1876
|
+
ignoreScrollAfterInput,
|
|
1877
|
+
trapFocus,
|
|
1878
|
+
themeClassName,
|
|
1879
|
+
onDismiss,
|
|
1880
|
+
children
|
|
1881
|
+
}) {
|
|
1882
|
+
const panelRef = useRef3(null);
|
|
1883
|
+
const onDismissRef = useRef3(onDismiss);
|
|
1884
|
+
useLayoutEffect2(() => {
|
|
1885
|
+
onDismissRef.current = onDismiss;
|
|
1886
|
+
});
|
|
1887
|
+
useLayoutEffect2(() => {
|
|
1888
|
+
const panel = panelRef.current;
|
|
1889
|
+
if (panel === null) {
|
|
1890
|
+
return void 0;
|
|
1891
|
+
}
|
|
1892
|
+
return attachOverlay(anchor, panel, {
|
|
1893
|
+
placement,
|
|
1894
|
+
gap,
|
|
1895
|
+
offset,
|
|
1896
|
+
initialFocus: attachedFocus(initialFocus),
|
|
1897
|
+
returnFocusTo,
|
|
1898
|
+
ignoreScrollAfterInput,
|
|
1899
|
+
trapFocus,
|
|
1900
|
+
onDismiss: (reason) => {
|
|
1901
|
+
onDismissRef.current(reason);
|
|
1902
|
+
}
|
|
1903
|
+
});
|
|
1904
|
+
}, [
|
|
1905
|
+
anchor,
|
|
1906
|
+
placement,
|
|
1907
|
+
gap,
|
|
1908
|
+
offset,
|
|
1909
|
+
initialFocus,
|
|
1910
|
+
returnFocusTo,
|
|
1911
|
+
ignoreScrollAfterInput,
|
|
1912
|
+
trapFocus
|
|
1913
|
+
]);
|
|
1914
|
+
return createPortal3(
|
|
1915
|
+
/* @__PURE__ */ jsx11(
|
|
1916
|
+
"div",
|
|
1917
|
+
{
|
|
1918
|
+
ref: panelRef,
|
|
1919
|
+
className: classNames("gridkit-overlay", themeClassName),
|
|
1920
|
+
children
|
|
1921
|
+
}
|
|
1922
|
+
),
|
|
1923
|
+
document.body
|
|
1924
|
+
);
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
// src/DataGrid/menu/menuIcons.tsx
|
|
1928
|
+
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1929
|
+
var BUILT_IN_ICONS = {
|
|
1930
|
+
sortAscending: () => /* @__PURE__ */ jsxs8(Icon, { children: [
|
|
1931
|
+
/* @__PURE__ */ jsx12("path", { d: "m3 8 4-4 4 4" }),
|
|
1932
|
+
/* @__PURE__ */ jsx12("path", { d: "M7 4v16" }),
|
|
1933
|
+
/* @__PURE__ */ jsx12("path", { d: "M11 12h4" }),
|
|
1934
|
+
/* @__PURE__ */ jsx12("path", { d: "M11 16h7" }),
|
|
1935
|
+
/* @__PURE__ */ jsx12("path", { d: "M11 20h10" })
|
|
1936
|
+
] }),
|
|
1937
|
+
sortDescending: () => /* @__PURE__ */ jsxs8(Icon, { children: [
|
|
1938
|
+
/* @__PURE__ */ jsx12("path", { d: "m3 16 4 4 4-4" }),
|
|
1939
|
+
/* @__PURE__ */ jsx12("path", { d: "M7 20V4" }),
|
|
1940
|
+
/* @__PURE__ */ jsx12("path", { d: "M11 4h10" }),
|
|
1941
|
+
/* @__PURE__ */ jsx12("path", { d: "M11 8h7" }),
|
|
1942
|
+
/* @__PURE__ */ jsx12("path", { d: "M11 12h4" })
|
|
1943
|
+
] }),
|
|
1944
|
+
group: () => /* @__PURE__ */ jsx12(GroupIcon, {}),
|
|
1945
|
+
hide: () => /* @__PURE__ */ jsxs8(Icon, { children: [
|
|
1946
|
+
/* @__PURE__ */ jsx12("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }),
|
|
1947
|
+
/* @__PURE__ */ jsx12("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }),
|
|
1948
|
+
/* @__PURE__ */ jsx12("path", { d: "M6.61 6.61A13.53 13.53 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }),
|
|
1949
|
+
/* @__PURE__ */ jsx12("path", { d: "m2 2 20 20" })
|
|
1950
|
+
] }),
|
|
1951
|
+
autoFit: () => /* @__PURE__ */ jsxs8(Icon, { children: [
|
|
1952
|
+
/* @__PURE__ */ jsx12("path", { d: "m18 8 4 4-4 4" }),
|
|
1953
|
+
/* @__PURE__ */ jsx12("path", { d: "M2 12h20" }),
|
|
1954
|
+
/* @__PURE__ */ jsx12("path", { d: "m6 8-4 4 4 4" })
|
|
1955
|
+
] }),
|
|
1956
|
+
copy: () => /* @__PURE__ */ jsxs8(Icon, { children: [
|
|
1957
|
+
/* @__PURE__ */ jsx12("rect", { x: "8", y: "8", width: "14", height: "14", rx: "2" }),
|
|
1958
|
+
/* @__PURE__ */ jsx12("path", { d: "M4 16a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2" })
|
|
1959
|
+
] }),
|
|
1960
|
+
print: () => /* @__PURE__ */ jsxs8(Icon, { children: [
|
|
1961
|
+
/* @__PURE__ */ jsx12("path", { d: "M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2" }),
|
|
1962
|
+
/* @__PURE__ */ jsx12("path", { d: "M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6" }),
|
|
1963
|
+
/* @__PURE__ */ jsx12("rect", { x: "6", y: "14", width: "12", height: "8", rx: "1" })
|
|
1964
|
+
] })
|
|
1965
|
+
};
|
|
1966
|
+
var ICONS = new Map(Object.entries(BUILT_IN_ICONS));
|
|
1967
|
+
function MenuIcon({ name }) {
|
|
1968
|
+
const draw = name === void 0 ? void 0 : ICONS.get(name);
|
|
1969
|
+
return draw === void 0 ? null : draw();
|
|
1970
|
+
}
|
|
1971
|
+
function CheckIcon() {
|
|
1972
|
+
return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "M20 6 9 17l-5-5" }) });
|
|
1973
|
+
}
|
|
1974
|
+
function ChevronDownIcon() {
|
|
1975
|
+
return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" }) });
|
|
1976
|
+
}
|
|
1977
|
+
function ChevronLeftIcon2() {
|
|
1978
|
+
return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "m15 18-6-6 6-6" }) });
|
|
1979
|
+
}
|
|
1980
|
+
function ChevronRightIcon2() {
|
|
1981
|
+
return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "m9 18 6-6-6-6" }) });
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
// src/DataGrid/menu/GridMenu.tsx
|
|
1985
|
+
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1986
|
+
function itemElement(menu, id) {
|
|
1987
|
+
return Array.from(
|
|
1988
|
+
menu.querySelectorAll("[data-gridkit-menu-item]")
|
|
1989
|
+
).find((item) => item.getAttribute("data-gridkit-menu-item") === id) ?? null;
|
|
1990
|
+
}
|
|
1991
|
+
function topInset(menu) {
|
|
1992
|
+
const style = getComputedStyle(menu);
|
|
1993
|
+
return parseFloat(style.borderTopWidth) + parseFloat(style.paddingTop);
|
|
1994
|
+
}
|
|
1995
|
+
function MenuItem({
|
|
1996
|
+
entry,
|
|
1997
|
+
expanded
|
|
1998
|
+
}) {
|
|
1999
|
+
const isItem2 = entry.type === "item";
|
|
2000
|
+
const checked = isItem2 ? entry.checked : void 0;
|
|
2001
|
+
const shortcut = isItem2 ? entry.shortcut : void 0;
|
|
2002
|
+
return /* @__PURE__ */ jsxs9(
|
|
2003
|
+
"div",
|
|
2004
|
+
{
|
|
2005
|
+
role: checked === void 0 ? "menuitem" : "menuitemcheckbox",
|
|
2006
|
+
"data-gridkit-menu-item": entry.id,
|
|
2007
|
+
className: "menu-item",
|
|
2008
|
+
...ariaAttr(isItem2 && entry.disabled, "aria-disabled", true),
|
|
2009
|
+
...ariaAttr(checked !== void 0, "aria-checked", checked),
|
|
2010
|
+
...ariaAttr(shortcut !== void 0, "aria-keyshortcuts", shortcut),
|
|
2011
|
+
...ariaAttr(!isItem2, "aria-haspopup", "menu"),
|
|
2012
|
+
...ariaAttr(!isItem2, "aria-expanded", expanded),
|
|
2013
|
+
children: [
|
|
2014
|
+
/* @__PURE__ */ jsx13("span", { className: "menu-item-icon", "aria-hidden": "true", children: checked === true ? /* @__PURE__ */ jsx13(CheckIcon, {}) : /* @__PURE__ */ jsx13(MenuIcon, { name: entry.icon }) }),
|
|
2015
|
+
/* @__PURE__ */ jsx13("span", { className: "menu-item-label", children: entry.label }),
|
|
2016
|
+
shortcut !== void 0 && /* @__PURE__ */ jsx13("span", { className: "menu-item-shortcut", "aria-hidden": "true", children: shortcut }),
|
|
2017
|
+
!isItem2 && /* @__PURE__ */ jsx13("span", { className: "menu-submenu-indicator", "aria-hidden": "true", children: /* @__PURE__ */ jsx13(ChevronRightIcon2, {}) })
|
|
2018
|
+
]
|
|
2019
|
+
}
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
2022
|
+
function GridMenu({
|
|
2023
|
+
entries,
|
|
2024
|
+
label,
|
|
2025
|
+
themeClassName,
|
|
2026
|
+
onRun,
|
|
2027
|
+
onClose,
|
|
2028
|
+
onCloseSubmenu,
|
|
2029
|
+
behaviourRef
|
|
2030
|
+
}) {
|
|
2031
|
+
const menuRef = useRef4(null);
|
|
2032
|
+
const submenuBehaviourRef = useRef4(null);
|
|
2033
|
+
const [submenu, setSubmenu] = useState4(null);
|
|
2034
|
+
const isSubmenu = onCloseSubmenu !== void 0;
|
|
2035
|
+
const latest = useRef4({ entries, submenu, onRun, onClose, onCloseSubmenu });
|
|
2036
|
+
useLayoutEffect3(() => {
|
|
2037
|
+
latest.current = { entries, submenu, onRun, onClose, onCloseSubmenu };
|
|
2038
|
+
});
|
|
2039
|
+
useLayoutEffect3(() => {
|
|
2040
|
+
const menu = menuRef.current;
|
|
2041
|
+
if (menu === null) {
|
|
2042
|
+
return void 0;
|
|
2043
|
+
}
|
|
2044
|
+
const behaviour = attachMenu(menu, {
|
|
2045
|
+
onActivate: (id) => {
|
|
2046
|
+
const item = latest.current.entries.find(
|
|
2047
|
+
(entry) => entry.type === "item" && entry.id === id
|
|
2048
|
+
);
|
|
2049
|
+
if (item !== void 0) {
|
|
2050
|
+
latest.current.onRun(item);
|
|
2051
|
+
}
|
|
2052
|
+
},
|
|
2053
|
+
onOpenSubmenu: (id, { focus }) => {
|
|
2054
|
+
if (latest.current.submenu?.id === id) {
|
|
2055
|
+
if (focus === "first") {
|
|
2056
|
+
submenuBehaviourRef.current?.focusItem(0);
|
|
2057
|
+
}
|
|
2058
|
+
return;
|
|
2059
|
+
}
|
|
2060
|
+
const anchor = itemElement(menu, id);
|
|
2061
|
+
if (anchor !== null) {
|
|
2062
|
+
setSubmenu({ id, anchor, focus, offset: -topInset(menu) });
|
|
2063
|
+
}
|
|
2064
|
+
},
|
|
2065
|
+
onCollapseSubmenu: () => {
|
|
2066
|
+
setSubmenu(null);
|
|
2067
|
+
},
|
|
2068
|
+
onCloseSubmenu: isSubmenu ? () => {
|
|
2069
|
+
latest.current.onCloseSubmenu?.();
|
|
2070
|
+
} : void 0,
|
|
2071
|
+
onClose: () => {
|
|
2072
|
+
latest.current.onClose();
|
|
2073
|
+
}
|
|
2074
|
+
});
|
|
2075
|
+
if (behaviourRef !== void 0) {
|
|
2076
|
+
behaviourRef.current = behaviour;
|
|
2077
|
+
}
|
|
2078
|
+
return () => {
|
|
2079
|
+
if (behaviourRef !== void 0) {
|
|
2080
|
+
behaviourRef.current = null;
|
|
2081
|
+
}
|
|
2082
|
+
behaviour.detach();
|
|
2083
|
+
};
|
|
2084
|
+
}, [isSubmenu, behaviourRef]);
|
|
2085
|
+
function closeSubmenu() {
|
|
2086
|
+
setSubmenu(null);
|
|
2087
|
+
}
|
|
2088
|
+
const openEntry = submenu === null ? void 0 : entries.find(
|
|
2089
|
+
(entry) => entry.type === "submenu" && entry.id === submenu.id
|
|
2090
|
+
);
|
|
2091
|
+
return /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
2092
|
+
/* @__PURE__ */ jsx13(
|
|
2093
|
+
"div",
|
|
2094
|
+
{
|
|
2095
|
+
ref: menuRef,
|
|
2096
|
+
role: "menu",
|
|
2097
|
+
"aria-label": label,
|
|
2098
|
+
className: "gridkit-menu",
|
|
2099
|
+
children: entries.map(
|
|
2100
|
+
(entry) => entry.type === "separator" ? /* @__PURE__ */ jsx13("div", { role: "separator", className: "menu-separator" }, entry.key) : /* @__PURE__ */ jsx13(
|
|
2101
|
+
MenuItem,
|
|
2102
|
+
{
|
|
2103
|
+
entry,
|
|
2104
|
+
expanded: entry.id === submenu?.id
|
|
2105
|
+
},
|
|
2106
|
+
entry.id
|
|
2107
|
+
)
|
|
2108
|
+
)
|
|
2109
|
+
}
|
|
2110
|
+
),
|
|
2111
|
+
submenu !== null && openEntry !== void 0 && /* @__PURE__ */ jsx13(
|
|
2112
|
+
Overlay,
|
|
2113
|
+
{
|
|
2114
|
+
anchor: submenu.anchor,
|
|
2115
|
+
placement: "right-start",
|
|
2116
|
+
offset: submenu.offset,
|
|
2117
|
+
initialFocus: submenu.focus,
|
|
2118
|
+
themeClassName,
|
|
2119
|
+
onDismiss: closeSubmenu,
|
|
2120
|
+
children: /* @__PURE__ */ jsx13(
|
|
2121
|
+
GridMenu,
|
|
2122
|
+
{
|
|
2123
|
+
entries: openEntry.items,
|
|
2124
|
+
label: openEntry.label,
|
|
2125
|
+
themeClassName,
|
|
2126
|
+
onRun,
|
|
2127
|
+
onClose,
|
|
2128
|
+
onCloseSubmenu: closeSubmenu,
|
|
2129
|
+
behaviourRef: submenuBehaviourRef
|
|
2130
|
+
}
|
|
2131
|
+
)
|
|
2132
|
+
},
|
|
2133
|
+
submenu.id
|
|
2134
|
+
)
|
|
2135
|
+
] });
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
// src/DataGrid/contextMenu/GridContextMenu.tsx
|
|
2139
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
2140
|
+
function GridContextMenu({
|
|
2141
|
+
contextMenu
|
|
2142
|
+
}) {
|
|
2143
|
+
const { menu, run, close } = contextMenu;
|
|
2144
|
+
if (menu === null) {
|
|
2145
|
+
return null;
|
|
2146
|
+
}
|
|
2147
|
+
return /* @__PURE__ */ jsx14(
|
|
2148
|
+
Overlay,
|
|
2149
|
+
{
|
|
2150
|
+
anchor: menu.anchor,
|
|
2151
|
+
gap: menu.anchor instanceof Element ? ANCHOR_GAP : 0,
|
|
2152
|
+
returnFocusTo: menu.cell ?? void 0,
|
|
2153
|
+
themeClassName: menu.themeClassName,
|
|
2154
|
+
onDismiss: close,
|
|
2155
|
+
children: /* @__PURE__ */ jsx14(
|
|
2156
|
+
GridMenu,
|
|
2157
|
+
{
|
|
2158
|
+
entries: menu.entries,
|
|
2159
|
+
label: menu.label,
|
|
2160
|
+
themeClassName: menu.themeClassName,
|
|
2161
|
+
onRun: run,
|
|
2162
|
+
onClose: close
|
|
2163
|
+
}
|
|
2164
|
+
)
|
|
2165
|
+
},
|
|
2166
|
+
menu.key
|
|
2167
|
+
);
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
// src/DataGrid/contextMenu/useContextMenu.ts
|
|
2171
|
+
import {
|
|
2172
|
+
useEffect as useEffect2,
|
|
2173
|
+
useLayoutEffect as useLayoutEffect4,
|
|
2174
|
+
useRef as useRef5,
|
|
2175
|
+
useState as useState5
|
|
2176
|
+
} from "react";
|
|
2177
|
+
import {
|
|
2178
|
+
contextMenuEntries,
|
|
2179
|
+
hasContextMenu,
|
|
2180
|
+
isSameCell,
|
|
2181
|
+
resolveMenu
|
|
2182
|
+
} from "@gridkitjs/core";
|
|
2183
|
+
import {
|
|
2184
|
+
attachContextMenuTrigger
|
|
2185
|
+
} from "@gridkitjs/dom";
|
|
2186
|
+
|
|
2187
|
+
// src/DataGrid/contextMenu/contextMenuPlaces.ts
|
|
2188
|
+
import {
|
|
2189
|
+
HEADER_ROW as HEADER_ROW2
|
|
2190
|
+
} from "@gridkitjs/core";
|
|
2191
|
+
import {
|
|
2192
|
+
bodyCellFrom as bodyCellFrom2,
|
|
2193
|
+
bodyRowFrom as bodyRowFrom2,
|
|
2194
|
+
findBodyRow as findBodyRow2,
|
|
2195
|
+
groupRowFrom as groupRowFrom2
|
|
2196
|
+
} from "@gridkitjs/dom";
|
|
2197
|
+
function headerCell(parts, columnIndex) {
|
|
2198
|
+
const element = parts.headerTable?.tHead?.rows[0]?.cells[columnIndex];
|
|
2199
|
+
return element === void 0 ? null : { element, rowIndex: HEADER_ROW2, columnIndex };
|
|
2200
|
+
}
|
|
2201
|
+
function bodyCell(parts, rowIndex, columnIndex) {
|
|
2202
|
+
const element = findBodyRow2(parts.bodyTable, rowIndex)?.cells[columnIndex];
|
|
2203
|
+
return element === void 0 ? null : { element, rowIndex, columnIndex };
|
|
2204
|
+
}
|
|
2205
|
+
function viewOf(element, parts) {
|
|
2206
|
+
const root = parts.root?.getBoundingClientRect();
|
|
2207
|
+
if (root === void 0) {
|
|
2208
|
+
return null;
|
|
2209
|
+
}
|
|
2210
|
+
const body = parts.body?.contains(element) === true ? parts.body.getBoundingClientRect() : root;
|
|
2211
|
+
const left = Math.max(root.left, body.left);
|
|
2212
|
+
const top = Math.max(root.top, body.top);
|
|
2213
|
+
return new DOMRect(
|
|
2214
|
+
left,
|
|
2215
|
+
top,
|
|
2216
|
+
Math.max(0, Math.min(root.right, body.right) - left),
|
|
2217
|
+
Math.max(0, Math.min(root.bottom, body.bottom) - top)
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2220
|
+
function clamp(value, min, max) {
|
|
2221
|
+
return Math.min(Math.max(value, min), max);
|
|
2222
|
+
}
|
|
2223
|
+
function onCell(target, cell, parts) {
|
|
2224
|
+
if (cell === null) {
|
|
2225
|
+
return null;
|
|
2226
|
+
}
|
|
2227
|
+
const box = cell.element.getBoundingClientRect();
|
|
2228
|
+
const view = viewOf(cell.element, parts);
|
|
2229
|
+
if (view === null || box.right > view.left && box.left < view.right && box.bottom > view.top && box.top < view.bottom) {
|
|
2230
|
+
return { target, cell, anchor: cell.element };
|
|
2231
|
+
}
|
|
2232
|
+
return {
|
|
2233
|
+
target,
|
|
2234
|
+
cell,
|
|
2235
|
+
anchor: {
|
|
2236
|
+
x: clamp(box.left, view.left, view.right),
|
|
2237
|
+
y: clamp(box.bottom, view.top, view.bottom)
|
|
2238
|
+
}
|
|
2239
|
+
};
|
|
2240
|
+
}
|
|
2241
|
+
function onBody(body) {
|
|
2242
|
+
const { left, top } = body.getBoundingClientRect();
|
|
2243
|
+
return { target: { area: "body" }, cell: null, anchor: { x: left, y: top } };
|
|
2244
|
+
}
|
|
2245
|
+
function headerPlaceAt(element, parts) {
|
|
2246
|
+
const cell = element.closest("th[data-gridkit-column]");
|
|
2247
|
+
const columnId = cell?.getAttribute("data-gridkit-column");
|
|
2248
|
+
if (cell === null || cell.parentElement !== parts.headerTable?.tHead?.rows[0] || columnId === null || columnId === void 0) {
|
|
2249
|
+
return null;
|
|
2250
|
+
}
|
|
2251
|
+
return onCell(
|
|
2252
|
+
{ area: "header", columnId },
|
|
2253
|
+
headerCell(parts, cell.cellIndex),
|
|
2254
|
+
parts
|
|
2255
|
+
);
|
|
2256
|
+
}
|
|
2257
|
+
function bodyPlaceAt(element, parts) {
|
|
2258
|
+
const { body, pageRows } = parts;
|
|
2259
|
+
if (body === null || !body.contains(element)) {
|
|
2260
|
+
return null;
|
|
2261
|
+
}
|
|
2262
|
+
const group = groupRowFrom2(element);
|
|
2263
|
+
if (group !== null) {
|
|
2264
|
+
const entry = pageRows[group.rowIndex];
|
|
2265
|
+
const cell = bodyCell(parts, group.rowIndex, 0);
|
|
2266
|
+
return entry !== void 0 && "kind" in entry && entry.kind === "group" && cell?.element.contains(element) === true ? onCell(
|
|
2267
|
+
{ area: "group", groupId: entry.groupId, columnId: entry.columnId },
|
|
2268
|
+
cell,
|
|
2269
|
+
parts
|
|
2270
|
+
) : null;
|
|
2271
|
+
}
|
|
2272
|
+
const position = bodyCellFrom2(element);
|
|
2273
|
+
if (position !== null) {
|
|
2274
|
+
const entry = pageRows[position.rowIndex];
|
|
2275
|
+
const cell = bodyCell(parts, position.rowIndex, position.columnIndex);
|
|
2276
|
+
return entry !== void 0 && !("kind" in entry) && cell?.element.contains(element) === true ? onCell(
|
|
2277
|
+
{ area: "cell", rowId: entry.rowId, columnId: position.columnId },
|
|
2278
|
+
cell,
|
|
2279
|
+
parts
|
|
2280
|
+
) : null;
|
|
2281
|
+
}
|
|
2282
|
+
return bodyRowFrom2(element) === null ? onBody(body) : null;
|
|
2283
|
+
}
|
|
2284
|
+
function placeAt(element, parts) {
|
|
2285
|
+
return headerPlaceAt(element, parts) ?? bodyPlaceAt(element, parts);
|
|
2286
|
+
}
|
|
2287
|
+
function placeOf(target, parts) {
|
|
2288
|
+
const columnIndexOf = (columnId) => parts.columns.findIndex((column) => column.id === columnId);
|
|
2289
|
+
switch (target.area) {
|
|
2290
|
+
case "header":
|
|
2291
|
+
return onCell(
|
|
2292
|
+
target,
|
|
2293
|
+
headerCell(parts, columnIndexOf(target.columnId)),
|
|
2294
|
+
parts
|
|
2295
|
+
);
|
|
2296
|
+
case "cell": {
|
|
2297
|
+
const rowIndex = parts.pageRows.findIndex(
|
|
2298
|
+
(entry) => !("kind" in entry) && entry.rowId === target.rowId
|
|
2299
|
+
);
|
|
2300
|
+
return onCell(
|
|
2301
|
+
target,
|
|
2302
|
+
bodyCell(parts, rowIndex, columnIndexOf(target.columnId)),
|
|
2303
|
+
parts
|
|
2304
|
+
);
|
|
2305
|
+
}
|
|
2306
|
+
case "group": {
|
|
2307
|
+
const rowIndex = parts.pageRows.findIndex(
|
|
2308
|
+
(entry) => "kind" in entry && entry.kind === "group" && entry.groupId === target.groupId
|
|
2309
|
+
);
|
|
2310
|
+
return onCell(target, bodyCell(parts, rowIndex, 0), parts);
|
|
2311
|
+
}
|
|
2312
|
+
case "body":
|
|
2313
|
+
return parts.body === null ? null : onBody(parts.body);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
// src/DataGrid/contextMenu/useContextMenu.ts
|
|
2318
|
+
function useContextMenu({
|
|
2319
|
+
rootRef,
|
|
2320
|
+
headerTableRef,
|
|
2321
|
+
bodyTableRef,
|
|
2322
|
+
bodyScrollRef,
|
|
2323
|
+
contextMenu,
|
|
2324
|
+
onContextMenuOpenChange,
|
|
2325
|
+
controller,
|
|
2326
|
+
commands,
|
|
2327
|
+
nav,
|
|
2328
|
+
selection,
|
|
2329
|
+
messages,
|
|
2330
|
+
columnName
|
|
2331
|
+
}) {
|
|
2332
|
+
const [menu, setMenu] = useState5(null);
|
|
2333
|
+
const current = useRef5(null);
|
|
2334
|
+
const openings = useRef5(0);
|
|
2335
|
+
const enabled = contextMenu !== void 0 && contextMenu !== false;
|
|
2336
|
+
function parts() {
|
|
2337
|
+
const { columns, pageRows } = controller.getView();
|
|
2338
|
+
return {
|
|
2339
|
+
root: rootRef.current,
|
|
2340
|
+
headerTable: headerTableRef.current,
|
|
2341
|
+
bodyTable: bodyTableRef.current,
|
|
2342
|
+
body: bodyScrollRef.current,
|
|
2343
|
+
columns,
|
|
2344
|
+
pageRows
|
|
2345
|
+
};
|
|
2346
|
+
}
|
|
2347
|
+
function labelOf(target) {
|
|
2348
|
+
switch (target.area) {
|
|
2349
|
+
case "header":
|
|
2350
|
+
return messages.headerMenuLabel(columnName(target.columnId));
|
|
2351
|
+
case "cell":
|
|
2352
|
+
return messages.cellMenuLabel;
|
|
2353
|
+
case "group":
|
|
2354
|
+
return messages.groupMenuLabel;
|
|
2355
|
+
case "body":
|
|
2356
|
+
return messages.bodyMenuLabel;
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
function selectTarget(target) {
|
|
2360
|
+
const state = controller.getState();
|
|
2361
|
+
if (target.area === "header") {
|
|
2362
|
+
if (selection.columnMode === false || state.columnSelection.includes(target.columnId)) {
|
|
2363
|
+
return false;
|
|
2364
|
+
}
|
|
2365
|
+
controller.selectColumn(target.columnId, "replace");
|
|
2366
|
+
return true;
|
|
2367
|
+
}
|
|
2368
|
+
if (target.area !== "cell") {
|
|
2369
|
+
return false;
|
|
2370
|
+
}
|
|
2371
|
+
const cell = { rowId: target.rowId, columnId: target.columnId };
|
|
2372
|
+
const selectRow = selection.rowMode !== false && !state.rowSelection.includes(target.rowId);
|
|
2373
|
+
const selectCell = selection.cellMode !== false && !isSameCell(state.cellSelection, cell);
|
|
2374
|
+
if (selectRow) {
|
|
2375
|
+
controller.selectRow(target.rowId, "replace");
|
|
2376
|
+
}
|
|
2377
|
+
if (selectCell) {
|
|
2378
|
+
controller.selectCell(cell, "replace");
|
|
2379
|
+
}
|
|
2380
|
+
return selectRow || selectCell;
|
|
2381
|
+
}
|
|
2382
|
+
function resolveFor(target) {
|
|
2383
|
+
const context = commands.contextFor(target);
|
|
2384
|
+
return resolveMenu(contextMenuEntries(contextMenu, context), {
|
|
2385
|
+
commands: commands.commands,
|
|
2386
|
+
context
|
|
2387
|
+
});
|
|
2388
|
+
}
|
|
2389
|
+
function show(next) {
|
|
2390
|
+
const previous = current.current;
|
|
2391
|
+
if (previous === next) {
|
|
2392
|
+
return;
|
|
2393
|
+
}
|
|
2394
|
+
current.current = next;
|
|
2395
|
+
setMenu(next);
|
|
2396
|
+
if (previous !== null) {
|
|
2397
|
+
onContextMenuOpenChange?.({ open: false, target: previous.target });
|
|
2398
|
+
}
|
|
2399
|
+
if (next !== null) {
|
|
2400
|
+
onContextMenuOpenChange?.({ open: true, target: next.target });
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
function openAt({ target, cell, anchor }, point) {
|
|
2404
|
+
let resolved = resolveFor(target);
|
|
2405
|
+
if (resolved.length === 0) {
|
|
2406
|
+
return false;
|
|
2407
|
+
}
|
|
2408
|
+
if (selectTarget(target)) {
|
|
2409
|
+
resolved = resolveFor(target);
|
|
2410
|
+
}
|
|
2411
|
+
if (cell !== null && document.activeElement !== cell.element) {
|
|
2412
|
+
cell.element.focus({ preventScroll: true });
|
|
2413
|
+
nav.focusCellNow(cell.rowIndex, cell.columnIndex);
|
|
2414
|
+
}
|
|
2415
|
+
openings.current += 1;
|
|
2416
|
+
show({
|
|
2417
|
+
key: openings.current,
|
|
2418
|
+
target,
|
|
2419
|
+
entries: resolved,
|
|
2420
|
+
label: labelOf(target),
|
|
2421
|
+
anchor: point ?? anchor,
|
|
2422
|
+
cell: cell?.element ?? null,
|
|
2423
|
+
themeClassName: overlayThemeClassName(rootRef.current)
|
|
2424
|
+
});
|
|
2425
|
+
return true;
|
|
2426
|
+
}
|
|
2427
|
+
function handleRequest({ target, point }) {
|
|
2428
|
+
const place = placeAt(target, parts());
|
|
2429
|
+
return place !== null && openAt(place, point);
|
|
2430
|
+
}
|
|
2431
|
+
const latestRequest = useRef5(handleRequest);
|
|
2432
|
+
useLayoutEffect4(() => {
|
|
2433
|
+
latestRequest.current = handleRequest;
|
|
2434
|
+
});
|
|
2435
|
+
useEffect2(() => {
|
|
2436
|
+
const root = rootRef.current;
|
|
2437
|
+
if (!enabled || root === null) {
|
|
2438
|
+
return void 0;
|
|
2439
|
+
}
|
|
2440
|
+
return attachContextMenuTrigger(root, {
|
|
2441
|
+
onRequest: (request) => latestRequest.current(request)
|
|
2442
|
+
});
|
|
2443
|
+
}, [rootRef, enabled]);
|
|
2444
|
+
const shown = useRef5(null);
|
|
2445
|
+
useLayoutEffect4(() => {
|
|
2446
|
+
const closed = shown.current;
|
|
2447
|
+
shown.current = menu;
|
|
2448
|
+
if (menu === null && closed !== null && closed.cell !== null && !closed.cell.isConnected && document.activeElement === document.body) {
|
|
2449
|
+
nav.focusTabStop();
|
|
2450
|
+
}
|
|
2451
|
+
});
|
|
2452
|
+
function close() {
|
|
2453
|
+
show(null);
|
|
2454
|
+
}
|
|
2455
|
+
return {
|
|
2456
|
+
menu,
|
|
2457
|
+
opens: (area) => hasContextMenu(contextMenu, area),
|
|
2458
|
+
open: (target, anchor) => {
|
|
2459
|
+
const place = placeOf(target, parts());
|
|
2460
|
+
return place !== null && openAt(place, anchor ?? null);
|
|
2461
|
+
},
|
|
2462
|
+
run: (item) => {
|
|
2463
|
+
const open = current.current;
|
|
2464
|
+
if (item.run() && open !== null) {
|
|
2465
|
+
commands.report(item.id, open.target, "contextMenu");
|
|
2466
|
+
}
|
|
2467
|
+
close();
|
|
2468
|
+
},
|
|
2469
|
+
close
|
|
2470
|
+
};
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
// src/DataGrid/panels/GridPanels.tsx
|
|
2474
|
+
import { useRef as useRef13 } from "react";
|
|
2475
|
+
|
|
2476
|
+
// src/DataGrid/columnChooser/ColumnChooser.tsx
|
|
2477
|
+
import { useLayoutEffect as useLayoutEffect5, useRef as useRef6, useState as useState6 } from "react";
|
|
2478
|
+
import { resolveColumnChooser } from "@gridkitjs/core";
|
|
2479
|
+
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2480
|
+
function ColumnChooser({
|
|
2481
|
+
controller,
|
|
2482
|
+
messages
|
|
2483
|
+
}) {
|
|
2484
|
+
const [search, setSearch] = useState6("");
|
|
2485
|
+
const showAllRef = useRef6(null);
|
|
2486
|
+
const { entries, selectAll, toggleAll } = resolveColumnChooser({
|
|
2487
|
+
columns: controller.getView().dataColumns,
|
|
2488
|
+
visibility: controller.getState().columnVisibility,
|
|
2489
|
+
search
|
|
2490
|
+
});
|
|
2491
|
+
useLayoutEffect5(() => {
|
|
2492
|
+
if (showAllRef.current !== null) {
|
|
2493
|
+
showAllRef.current.indeterminate = selectAll === "mixed";
|
|
2494
|
+
}
|
|
2495
|
+
});
|
|
2496
|
+
function setVisible(columnIds, visible) {
|
|
2497
|
+
if (visible) {
|
|
2498
|
+
controller.showColumns(columnIds);
|
|
2499
|
+
} else {
|
|
2500
|
+
controller.hideColumns(columnIds);
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
return /* @__PURE__ */ jsxs10(
|
|
2504
|
+
"div",
|
|
2505
|
+
{
|
|
2506
|
+
role: "dialog",
|
|
2507
|
+
"aria-label": messages.columnChooserLabel,
|
|
2508
|
+
className: "gridkit-column-chooser",
|
|
2509
|
+
children: [
|
|
2510
|
+
/* @__PURE__ */ jsx15(
|
|
2511
|
+
"input",
|
|
2512
|
+
{
|
|
2513
|
+
type: "search",
|
|
2514
|
+
className: "column-chooser-search",
|
|
2515
|
+
"aria-label": messages.columnChooserSearchLabel,
|
|
2516
|
+
placeholder: messages.searchPlaceholder,
|
|
2517
|
+
value: search,
|
|
2518
|
+
onChange: (event) => {
|
|
2519
|
+
setSearch(event.currentTarget.value);
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
),
|
|
2523
|
+
entries.length === 0 ? /* @__PURE__ */ jsx15("p", { role: "status", className: "column-chooser-empty", children: messages.noMatchingColumns }) : /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2524
|
+
/* @__PURE__ */ jsxs10("label", { className: "column-chooser-option column-chooser-all", children: [
|
|
2525
|
+
/* @__PURE__ */ jsx15(
|
|
2526
|
+
"input",
|
|
2527
|
+
{
|
|
2528
|
+
ref: showAllRef,
|
|
2529
|
+
type: "checkbox",
|
|
2530
|
+
checked: selectAll === "checked",
|
|
2531
|
+
disabled: toggleAll === null,
|
|
2532
|
+
onChange: () => {
|
|
2533
|
+
if (toggleAll !== null) {
|
|
2534
|
+
setVisible(toggleAll.columnIds, toggleAll.visible);
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
),
|
|
2539
|
+
messages.showAllColumns
|
|
2540
|
+
] }),
|
|
2541
|
+
/* @__PURE__ */ jsx15("ul", { className: "column-chooser-list", children: entries.map((entry) => /* @__PURE__ */ jsx15("li", { children: /* @__PURE__ */ jsxs10("label", { className: "column-chooser-option", children: [
|
|
2542
|
+
/* @__PURE__ */ jsx15(
|
|
2543
|
+
"input",
|
|
2544
|
+
{
|
|
2545
|
+
type: "checkbox",
|
|
2546
|
+
checked: entry.visible,
|
|
2547
|
+
disabled: entry.disabled,
|
|
2548
|
+
onChange: () => {
|
|
2549
|
+
setVisible([entry.columnId], !entry.visible);
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
),
|
|
2553
|
+
entry.label
|
|
2554
|
+
] }) }, entry.columnId)) })
|
|
2555
|
+
] })
|
|
2556
|
+
]
|
|
2557
|
+
}
|
|
2558
|
+
);
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
// src/DataGrid/filterMenu/FilterMenu.tsx
|
|
2562
|
+
import { useEffect as useEffect3, useRef as useRef11 } from "react";
|
|
2563
|
+
import {
|
|
2564
|
+
resolveColumnFilterMenu as resolveColumnFilterMenu2,
|
|
2565
|
+
resolveColumnHeaderText,
|
|
2566
|
+
resolveMenu as resolveMenu2
|
|
2567
|
+
} from "@gridkitjs/core";
|
|
2568
|
+
|
|
2569
|
+
// src/DataGrid/filterMenu/ExcelFilterEditor.tsx
|
|
2570
|
+
import {
|
|
2571
|
+
useImperativeHandle as useImperativeHandle2,
|
|
2572
|
+
useLayoutEffect as useLayoutEffect9,
|
|
2573
|
+
useMemo as useMemo4,
|
|
2574
|
+
useReducer,
|
|
2575
|
+
useRef as useRef10,
|
|
2576
|
+
useState as useState10
|
|
2577
|
+
} from "react";
|
|
2578
|
+
import {
|
|
2579
|
+
describeColumnFilter as describeColumnFilter2,
|
|
2580
|
+
draftToFilter as draftToFilter2,
|
|
2581
|
+
filterChecklist,
|
|
2582
|
+
filterEditorReducer as filterEditorReducer2,
|
|
2583
|
+
initialFilterEditorDraft as initialFilterEditorDraft2,
|
|
2584
|
+
selectAllState
|
|
2585
|
+
} from "@gridkitjs/core";
|
|
2586
|
+
|
|
2587
|
+
// src/DataGrid/filterMenu/OperatorMenuButton.tsx
|
|
2588
|
+
import { useLayoutEffect as useLayoutEffect6, useRef as useRef7, useState as useState7 } from "react";
|
|
2589
|
+
import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2590
|
+
function gapBeside(button) {
|
|
2591
|
+
const dialog = button.closest('[role="dialog"]') ?? button;
|
|
2592
|
+
return dialog.getBoundingClientRect().right - button.getBoundingClientRect().right + ANCHOR_GAP;
|
|
2593
|
+
}
|
|
2594
|
+
function OperatorMenuButton({
|
|
2595
|
+
menu,
|
|
2596
|
+
active,
|
|
2597
|
+
messages,
|
|
2598
|
+
onChoose,
|
|
2599
|
+
ref
|
|
2600
|
+
}) {
|
|
2601
|
+
const [open, setOpen] = useState7(null);
|
|
2602
|
+
const menuBehaviourRef = useRef7(null);
|
|
2603
|
+
const label = messages.filterOperatorMenu(menu.family);
|
|
2604
|
+
useLayoutEffect6(() => {
|
|
2605
|
+
if (open !== null && open.focusItem > 0) {
|
|
2606
|
+
menuBehaviourRef.current?.focusItem(open.focusItem);
|
|
2607
|
+
}
|
|
2608
|
+
}, [open]);
|
|
2609
|
+
function show(button, onLast = false) {
|
|
2610
|
+
setOpen({
|
|
2611
|
+
anchor: button,
|
|
2612
|
+
themeClassName: overlayThemeClassName(button),
|
|
2613
|
+
gap: gapBeside(button),
|
|
2614
|
+
focusItem: onLast ? menu.operators.length - 1 : 0
|
|
2615
|
+
});
|
|
2616
|
+
}
|
|
2617
|
+
function close() {
|
|
2618
|
+
setOpen(null);
|
|
2619
|
+
}
|
|
2620
|
+
const entries = menu.operators.map((operator) => ({
|
|
2621
|
+
type: "item",
|
|
2622
|
+
id: operator,
|
|
2623
|
+
label: messages.filterOperatorLabel(operator, menu.family),
|
|
2624
|
+
disabled: false,
|
|
2625
|
+
checked: active?.includes(operator),
|
|
2626
|
+
run: () => {
|
|
2627
|
+
close();
|
|
2628
|
+
onChoose(operator);
|
|
2629
|
+
return true;
|
|
2630
|
+
}
|
|
2631
|
+
}));
|
|
2632
|
+
return /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
2633
|
+
/* @__PURE__ */ jsxs11(
|
|
2634
|
+
"button",
|
|
2635
|
+
{
|
|
2636
|
+
ref,
|
|
2637
|
+
type: "button",
|
|
2638
|
+
className: "filter-menu-submenu",
|
|
2639
|
+
"aria-haspopup": "menu",
|
|
2640
|
+
"aria-expanded": open !== null,
|
|
2641
|
+
onClick: (event) => {
|
|
2642
|
+
if (open === null) {
|
|
2643
|
+
show(event.currentTarget);
|
|
2644
|
+
} else {
|
|
2645
|
+
close();
|
|
2646
|
+
}
|
|
2647
|
+
},
|
|
2648
|
+
onKeyDown: (event) => {
|
|
2649
|
+
if ((event.key === "ArrowDown" || event.key === "ArrowUp") && open === null) {
|
|
2650
|
+
event.preventDefault();
|
|
2651
|
+
show(event.currentTarget, event.key === "ArrowUp");
|
|
2652
|
+
}
|
|
2653
|
+
},
|
|
2654
|
+
children: [
|
|
2655
|
+
/* @__PURE__ */ jsx16("span", { className: "filter-menu-submenu-icon", "aria-hidden": "true", children: active !== void 0 && /* @__PURE__ */ jsx16(CheckIcon, {}) }),
|
|
2656
|
+
label,
|
|
2657
|
+
/* @__PURE__ */ jsx16("span", { className: "filter-menu-submenu-indicator", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(ChevronRightIcon2, {}) })
|
|
2658
|
+
]
|
|
2659
|
+
}
|
|
2660
|
+
),
|
|
2661
|
+
open !== null && /* @__PURE__ */ jsx16(
|
|
2662
|
+
Overlay,
|
|
2663
|
+
{
|
|
2664
|
+
anchor: open.anchor,
|
|
2665
|
+
placement: "right-start",
|
|
2666
|
+
gap: open.gap,
|
|
2667
|
+
returnFocusTo: open.anchor,
|
|
2668
|
+
themeClassName: open.themeClassName,
|
|
2669
|
+
onDismiss: close,
|
|
2670
|
+
children: /* @__PURE__ */ jsx16(
|
|
2671
|
+
GridMenu,
|
|
2672
|
+
{
|
|
2673
|
+
entries,
|
|
2674
|
+
label,
|
|
2675
|
+
themeClassName: open.themeClassName,
|
|
2676
|
+
behaviourRef: menuBehaviourRef,
|
|
2677
|
+
onRun: (item) => {
|
|
2678
|
+
item.run();
|
|
2679
|
+
},
|
|
2680
|
+
onClose: close
|
|
2681
|
+
}
|
|
2682
|
+
)
|
|
2683
|
+
}
|
|
2684
|
+
)
|
|
2685
|
+
] });
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2688
|
+
// src/DataGrid/filterMenu/SimpleFilterEditor.tsx
|
|
2689
|
+
import {
|
|
2690
|
+
Fragment as Fragment5,
|
|
2691
|
+
useId,
|
|
2692
|
+
useImperativeHandle,
|
|
2693
|
+
useLayoutEffect as useLayoutEffect7,
|
|
2694
|
+
useRef as useRef8,
|
|
2695
|
+
useState as useState8
|
|
2696
|
+
} from "react";
|
|
2697
|
+
import {
|
|
2698
|
+
conditionRowsFrom,
|
|
2699
|
+
conditionsFromRows,
|
|
2700
|
+
describeColumnFilter,
|
|
2701
|
+
draftToFilter,
|
|
2702
|
+
filterEditorReducer,
|
|
2703
|
+
initialFilterEditorDraft
|
|
2704
|
+
} from "@gridkitjs/core";
|
|
2705
|
+
|
|
2706
|
+
// src/DataGrid/filterMenu/ConditionRow.tsx
|
|
2707
|
+
import {
|
|
2708
|
+
filterOperandArity,
|
|
2709
|
+
parseFilterOperand
|
|
2710
|
+
} from "@gridkitjs/core";
|
|
2711
|
+
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2712
|
+
function inputType(family, type) {
|
|
2713
|
+
switch (family) {
|
|
2714
|
+
case "text":
|
|
2715
|
+
return "text";
|
|
2716
|
+
case "number":
|
|
2717
|
+
return "number";
|
|
2718
|
+
case "date":
|
|
2719
|
+
return type === "date" ? "date" : "datetime-local";
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
function OperandField({
|
|
2723
|
+
family,
|
|
2724
|
+
type,
|
|
2725
|
+
text,
|
|
2726
|
+
label,
|
|
2727
|
+
invalidMessageId,
|
|
2728
|
+
fieldRef,
|
|
2729
|
+
messages,
|
|
2730
|
+
onChange
|
|
2731
|
+
}) {
|
|
2732
|
+
const field = {
|
|
2733
|
+
ref: fieldRef,
|
|
2734
|
+
className: "filter-menu-value",
|
|
2735
|
+
"aria-label": label,
|
|
2736
|
+
"aria-invalid": invalidMessageId === void 0 ? void 0 : true,
|
|
2737
|
+
"aria-describedby": invalidMessageId,
|
|
2738
|
+
value: text,
|
|
2739
|
+
onChange: (event) => {
|
|
2740
|
+
onChange(event.currentTarget.value);
|
|
2741
|
+
}
|
|
2742
|
+
};
|
|
2743
|
+
if (family === "boolean") {
|
|
2744
|
+
return /* @__PURE__ */ jsxs12("select", { ...field, children: [
|
|
2745
|
+
/* @__PURE__ */ jsx17("option", { value: "" }),
|
|
2746
|
+
/* @__PURE__ */ jsx17("option", { value: "true", children: messages.booleanTrue }),
|
|
2747
|
+
/* @__PURE__ */ jsx17("option", { value: "false", children: messages.booleanFalse })
|
|
2748
|
+
] });
|
|
2749
|
+
}
|
|
2750
|
+
return /* @__PURE__ */ jsx17("input", { ...field, type: inputType(family, type) });
|
|
2751
|
+
}
|
|
2752
|
+
function ConditionRow({
|
|
2753
|
+
row,
|
|
2754
|
+
position,
|
|
2755
|
+
menu,
|
|
2756
|
+
type,
|
|
2757
|
+
messages,
|
|
2758
|
+
invalidMessageId,
|
|
2759
|
+
focusRef,
|
|
2760
|
+
onChange,
|
|
2761
|
+
ref
|
|
2762
|
+
}) {
|
|
2763
|
+
const arity = filterOperandArity(row.operator);
|
|
2764
|
+
const operators = menu.operators.includes(row.operator) ? menu.operators : [row.operator, ...menu.operators];
|
|
2765
|
+
const operand = { family: menu.family, type, messages };
|
|
2766
|
+
function messageIdFor(text) {
|
|
2767
|
+
return parseFilterOperand(text, type) === void 0 ? invalidMessageId : void 0;
|
|
2768
|
+
}
|
|
2769
|
+
return /* @__PURE__ */ jsxs12(
|
|
2770
|
+
"div",
|
|
2771
|
+
{
|
|
2772
|
+
ref,
|
|
2773
|
+
role: "group",
|
|
2774
|
+
"aria-label": messages.filterConditionLabel(position),
|
|
2775
|
+
className: "filter-menu-condition",
|
|
2776
|
+
children: [
|
|
2777
|
+
/* @__PURE__ */ jsx17(
|
|
2778
|
+
"select",
|
|
2779
|
+
{
|
|
2780
|
+
ref: arity === 0 ? focusRef : void 0,
|
|
2781
|
+
className: "filter-menu-operator",
|
|
2782
|
+
"aria-label": messages.filterOperatorFieldLabel,
|
|
2783
|
+
value: row.operator,
|
|
2784
|
+
onChange: (event) => {
|
|
2785
|
+
const operator = operators[event.currentTarget.selectedIndex];
|
|
2786
|
+
if (operator !== void 0) {
|
|
2787
|
+
onChange({ ...row, operator });
|
|
2788
|
+
}
|
|
2789
|
+
},
|
|
2790
|
+
children: operators.map((operator) => /* @__PURE__ */ jsx17("option", { value: operator, children: messages.filterOperatorLabel(operator, menu.family) }, operator))
|
|
2791
|
+
}
|
|
2792
|
+
),
|
|
2793
|
+
arity > 0 && /* @__PURE__ */ jsx17(
|
|
2794
|
+
OperandField,
|
|
2795
|
+
{
|
|
2796
|
+
...operand,
|
|
2797
|
+
text: row.text,
|
|
2798
|
+
label: arity === 2 ? messages.filterFromLabel : messages.filterValueLabel,
|
|
2799
|
+
invalidMessageId: messageIdFor(row.text),
|
|
2800
|
+
fieldRef: focusRef,
|
|
2801
|
+
onChange: (text) => {
|
|
2802
|
+
onChange({ ...row, text });
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
),
|
|
2806
|
+
arity === 2 && /* @__PURE__ */ jsx17(
|
|
2807
|
+
OperandField,
|
|
2808
|
+
{
|
|
2809
|
+
...operand,
|
|
2810
|
+
text: row.textTo,
|
|
2811
|
+
label: messages.filterToLabel,
|
|
2812
|
+
invalidMessageId: messageIdFor(row.textTo),
|
|
2813
|
+
fieldRef: void 0,
|
|
2814
|
+
onChange: (textTo) => {
|
|
2815
|
+
onChange({ ...row, textTo });
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
)
|
|
2819
|
+
]
|
|
2820
|
+
}
|
|
2821
|
+
);
|
|
2822
|
+
}
|
|
2823
|
+
|
|
2824
|
+
// src/DataGrid/filterMenu/SimpleFilterEditor.tsx
|
|
2825
|
+
import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2826
|
+
var COMBINATORS = ["and", "or"];
|
|
2827
|
+
var NO_ROWS = [];
|
|
2828
|
+
var NO_VALUES = {
|
|
2829
|
+
options: [],
|
|
2830
|
+
total: 0,
|
|
2831
|
+
truncated: false,
|
|
2832
|
+
blanks: 0
|
|
2833
|
+
};
|
|
2834
|
+
function holdsUnreadable(row) {
|
|
2835
|
+
return Array.from(row?.querySelectorAll("input") ?? []).some(
|
|
2836
|
+
(input) => input.validity.badInput
|
|
2837
|
+
);
|
|
2838
|
+
}
|
|
2839
|
+
function CombinatorChoice({
|
|
2840
|
+
name,
|
|
2841
|
+
combinator,
|
|
2842
|
+
messages,
|
|
2843
|
+
onChange
|
|
2844
|
+
}) {
|
|
2845
|
+
return /* @__PURE__ */ jsx18(
|
|
2846
|
+
"div",
|
|
2847
|
+
{
|
|
2848
|
+
role: "radiogroup",
|
|
2849
|
+
"aria-label": messages.filterCombinatorLabel,
|
|
2850
|
+
className: "filter-menu-combinator",
|
|
2851
|
+
children: COMBINATORS.map((choice) => /* @__PURE__ */ jsxs13("label", { className: "filter-menu-combinator-option", children: [
|
|
2852
|
+
/* @__PURE__ */ jsx18(
|
|
2853
|
+
"input",
|
|
2854
|
+
{
|
|
2855
|
+
type: "radio",
|
|
2856
|
+
name,
|
|
2857
|
+
checked: choice === combinator,
|
|
2858
|
+
onChange: () => {
|
|
2859
|
+
onChange(choice);
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
),
|
|
2863
|
+
choice === "and" ? messages.filterAnd : messages.filterOr
|
|
2864
|
+
] }, choice))
|
|
2865
|
+
}
|
|
2866
|
+
);
|
|
2867
|
+
}
|
|
2868
|
+
function SimpleFilterEditor({
|
|
2869
|
+
column,
|
|
2870
|
+
menu,
|
|
2871
|
+
controller,
|
|
2872
|
+
messages,
|
|
2873
|
+
initialFocusRef,
|
|
2874
|
+
applyFilter,
|
|
2875
|
+
operator,
|
|
2876
|
+
ref
|
|
2877
|
+
}) {
|
|
2878
|
+
const type = column.column.type;
|
|
2879
|
+
const [opened] = useState8(() => {
|
|
2880
|
+
const shape = describeColumnFilter(controller.getState().filter, column.id);
|
|
2881
|
+
const rows = conditionRowsFrom(shape, menu.operators, type);
|
|
2882
|
+
const draft2 = {
|
|
2883
|
+
// Its typed values kept, as picking the operator in the row keeps them.
|
|
2884
|
+
rows: operator === void 0 ? rows : rows.map(
|
|
2885
|
+
(row, index) => index === 0 ? { ...row, operator } : row
|
|
2886
|
+
),
|
|
2887
|
+
combinator: shape.kind === "conditions" ? shape.combinator : "and"
|
|
2888
|
+
};
|
|
2889
|
+
return {
|
|
2890
|
+
custom: shape.kind === "custom" || shape.kind === "values" && operator === void 0,
|
|
2891
|
+
draft: draft2
|
|
2892
|
+
};
|
|
2893
|
+
});
|
|
2894
|
+
const [draft, setDraft] = useState8(opened.draft);
|
|
2895
|
+
const [invalid, setInvalid] = useState8(NO_ROWS);
|
|
2896
|
+
const rowElements = useRef8([]);
|
|
2897
|
+
const invalidMessageId = useId();
|
|
2898
|
+
const combinatorName = useId();
|
|
2899
|
+
function update(next) {
|
|
2900
|
+
setDraft(next);
|
|
2901
|
+
setInvalid(NO_ROWS);
|
|
2902
|
+
}
|
|
2903
|
+
function applyConditions(conditions) {
|
|
2904
|
+
const applied = filterEditorReducer(
|
|
2905
|
+
initialFilterEditorDraft({ kind: "none" }, NO_VALUES),
|
|
2906
|
+
{ type: "setConditions", conditions, combinator: draft.combinator }
|
|
2907
|
+
);
|
|
2908
|
+
applyFilter(
|
|
2909
|
+
draftToFilter(applied, column.id, controller.getState().filter)
|
|
2910
|
+
);
|
|
2911
|
+
}
|
|
2912
|
+
useImperativeHandle(ref, () => ({
|
|
2913
|
+
apply: () => {
|
|
2914
|
+
const parsed = conditionsFromRows(draft.rows, column.id, type);
|
|
2915
|
+
const unreadable = draft.rows.map(
|
|
2916
|
+
(_, index) => holdsUnreadable(rowElements.current[index])
|
|
2917
|
+
);
|
|
2918
|
+
const marked = draft.rows.flatMap(
|
|
2919
|
+
(_, index) => parsed.invalid.includes(index) || unreadable[index] === true ? [index] : []
|
|
2920
|
+
);
|
|
2921
|
+
if (marked.length === 0) {
|
|
2922
|
+
applyConditions(parsed.conditions);
|
|
2923
|
+
return true;
|
|
2924
|
+
}
|
|
2925
|
+
if (draft === opened.draft && !unreadable.includes(true)) {
|
|
2926
|
+
return true;
|
|
2927
|
+
}
|
|
2928
|
+
setInvalid(marked);
|
|
2929
|
+
return false;
|
|
2930
|
+
}
|
|
2931
|
+
}));
|
|
2932
|
+
useLayoutEffect7(() => {
|
|
2933
|
+
const [first] = invalid;
|
|
2934
|
+
if (first !== void 0) {
|
|
2935
|
+
rowElements.current[first]?.querySelector('[aria-invalid="true"]')?.focus();
|
|
2936
|
+
}
|
|
2937
|
+
}, [invalid]);
|
|
2938
|
+
return /* @__PURE__ */ jsxs13("div", { className: "filter-menu-conditions", children: [
|
|
2939
|
+
opened.custom && /* @__PURE__ */ jsx18("p", { className: "filter-menu-custom", children: messages.customFilter }),
|
|
2940
|
+
draft.rows.map((row, index) => (
|
|
2941
|
+
// A row is its place: the first condition, or the second.
|
|
2942
|
+
/* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
2943
|
+
index > 0 && /* @__PURE__ */ jsx18(
|
|
2944
|
+
CombinatorChoice,
|
|
2945
|
+
{
|
|
2946
|
+
name: combinatorName,
|
|
2947
|
+
combinator: draft.combinator,
|
|
2948
|
+
messages,
|
|
2949
|
+
onChange: (combinator) => {
|
|
2950
|
+
update({ ...draft, combinator });
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
),
|
|
2954
|
+
/* @__PURE__ */ jsx18(
|
|
2955
|
+
ConditionRow,
|
|
2956
|
+
{
|
|
2957
|
+
ref: (element) => {
|
|
2958
|
+
rowElements.current[index] = element;
|
|
2959
|
+
},
|
|
2960
|
+
row,
|
|
2961
|
+
position: index + 1,
|
|
2962
|
+
menu,
|
|
2963
|
+
type,
|
|
2964
|
+
messages,
|
|
2965
|
+
invalidMessageId: invalid.includes(index) ? invalidMessageId : void 0,
|
|
2966
|
+
focusRef: index === 0 ? initialFocusRef : void 0,
|
|
2967
|
+
onChange: (next) => {
|
|
2968
|
+
update({
|
|
2969
|
+
...draft,
|
|
2970
|
+
rows: draft.rows.map(
|
|
2971
|
+
(current, at) => at === index ? next : current
|
|
2972
|
+
)
|
|
2973
|
+
});
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
)
|
|
2977
|
+
] }, index)
|
|
2978
|
+
)),
|
|
2979
|
+
invalid.length > 0 && /* @__PURE__ */ jsx18("p", { id: invalidMessageId, className: "filter-menu-invalid", children: messages.filterValueInvalid(menu.family) })
|
|
2980
|
+
] });
|
|
2981
|
+
}
|
|
2982
|
+
|
|
2983
|
+
// src/DataGrid/filterMenu/ValueChecklist.tsx
|
|
2984
|
+
import { useLayoutEffect as useLayoutEffect8, useRef as useRef9, useState as useState9 } from "react";
|
|
2985
|
+
import {
|
|
2986
|
+
attachChecklist,
|
|
2987
|
+
createRowVirtualizer
|
|
2988
|
+
} from "@gridkitjs/dom";
|
|
2989
|
+
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2990
|
+
var ESTIMATED_ITEM_HEIGHT = 28;
|
|
2991
|
+
var OVERSCAN = 4;
|
|
2992
|
+
var NO_RANGE = {
|
|
2993
|
+
startIndex: 0,
|
|
2994
|
+
endIndex: -1,
|
|
2995
|
+
offsetBefore: 0,
|
|
2996
|
+
offsetAfter: 0
|
|
2997
|
+
};
|
|
2998
|
+
function ValueChecklist({
|
|
2999
|
+
items,
|
|
3000
|
+
showCounts,
|
|
3001
|
+
label,
|
|
3002
|
+
onToggle
|
|
3003
|
+
}) {
|
|
3004
|
+
const listRef = useRef9(null);
|
|
3005
|
+
const checklistRef = useRef9(null);
|
|
3006
|
+
const [virtualizer, setVirtualizer] = useState9(null);
|
|
3007
|
+
const [range, setRange] = useState9(NO_RANGE);
|
|
3008
|
+
const latest = useRef9({ items, onToggle });
|
|
3009
|
+
useLayoutEffect8(() => {
|
|
3010
|
+
latest.current = { items, onToggle };
|
|
3011
|
+
});
|
|
3012
|
+
useLayoutEffect8(() => {
|
|
3013
|
+
const list = listRef.current;
|
|
3014
|
+
if (list === null) {
|
|
3015
|
+
return void 0;
|
|
3016
|
+
}
|
|
3017
|
+
const rows = createRowVirtualizer(list, {
|
|
3018
|
+
estimatedRowHeight: ESTIMATED_ITEM_HEIGHT,
|
|
3019
|
+
overscan: OVERSCAN,
|
|
3020
|
+
onRange: setRange
|
|
3021
|
+
});
|
|
3022
|
+
const checklist = attachChecklist(list, {
|
|
3023
|
+
onToggle: (index) => {
|
|
3024
|
+
const item = latest.current.items[index];
|
|
3025
|
+
if (item !== void 0) {
|
|
3026
|
+
latest.current.onToggle(item);
|
|
3027
|
+
}
|
|
3028
|
+
},
|
|
3029
|
+
scrollToIndex: (index) => {
|
|
3030
|
+
rows.scrollToIndex(index, { block: "nearest" });
|
|
3031
|
+
}
|
|
3032
|
+
});
|
|
3033
|
+
checklistRef.current = checklist;
|
|
3034
|
+
setVirtualizer(rows);
|
|
3035
|
+
return () => {
|
|
3036
|
+
checklistRef.current = null;
|
|
3037
|
+
checklist.detach();
|
|
3038
|
+
rows.destroy();
|
|
3039
|
+
};
|
|
3040
|
+
}, []);
|
|
3041
|
+
useLayoutEffect8(() => {
|
|
3042
|
+
virtualizer?.setRowCount(items.length);
|
|
3043
|
+
checklistRef.current?.setCount(items.length);
|
|
3044
|
+
}, [virtualizer, items.length]);
|
|
3045
|
+
const shown = items.slice(range.startIndex, range.endIndex + 1);
|
|
3046
|
+
return /* @__PURE__ */ jsxs14(
|
|
3047
|
+
"div",
|
|
3048
|
+
{
|
|
3049
|
+
ref: listRef,
|
|
3050
|
+
role: "listbox",
|
|
3051
|
+
"aria-multiselectable": "true",
|
|
3052
|
+
"aria-label": label,
|
|
3053
|
+
className: "filter-menu-checklist",
|
|
3054
|
+
children: [
|
|
3055
|
+
/* @__PURE__ */ jsx19("div", { role: "presentation", style: { height: range.offsetBefore } }),
|
|
3056
|
+
shown.map((item, offset) => {
|
|
3057
|
+
const index = range.startIndex + offset;
|
|
3058
|
+
return /* @__PURE__ */ jsxs14(
|
|
3059
|
+
"div",
|
|
3060
|
+
{
|
|
3061
|
+
ref: virtualizer?.measureRow(index),
|
|
3062
|
+
role: "option",
|
|
3063
|
+
"data-gridkit-checklist-item": "",
|
|
3064
|
+
"data-gridkit-checklist-index": index,
|
|
3065
|
+
"aria-checked": item.checked,
|
|
3066
|
+
"aria-setsize": items.length,
|
|
3067
|
+
"aria-posinset": index + 1,
|
|
3068
|
+
className: "filter-menu-option",
|
|
3069
|
+
children: [
|
|
3070
|
+
/* @__PURE__ */ jsx19("span", { className: "filter-menu-option-check", "aria-hidden": "true", children: /* @__PURE__ */ jsx19(CheckIcon, {}) }),
|
|
3071
|
+
/* @__PURE__ */ jsx19("span", { className: "filter-menu-option-label", children: item.label }),
|
|
3072
|
+
showCounts && /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
3073
|
+
" ",
|
|
3074
|
+
/* @__PURE__ */ jsx19("span", { className: "filter-menu-option-count", children: String(item.count) })
|
|
3075
|
+
] })
|
|
3076
|
+
]
|
|
3077
|
+
},
|
|
3078
|
+
item.key
|
|
3079
|
+
);
|
|
3080
|
+
}),
|
|
3081
|
+
/* @__PURE__ */ jsx19("div", { role: "presentation", style: { height: range.offsetAfter } })
|
|
3082
|
+
]
|
|
3083
|
+
}
|
|
3084
|
+
);
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
// src/DataGrid/filterMenu/ExcelFilterEditor.tsx
|
|
3088
|
+
import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3089
|
+
function toggleOf(item) {
|
|
3090
|
+
return item.kind === "blanks" ? { type: "setIncludeBlanks", includeBlanks: !item.checked } : { type: "toggleValue", value: item.value };
|
|
3091
|
+
}
|
|
3092
|
+
function ExcelFilterEditor({
|
|
3093
|
+
column,
|
|
3094
|
+
menu,
|
|
3095
|
+
controller,
|
|
3096
|
+
messages,
|
|
3097
|
+
initialFocusRef,
|
|
3098
|
+
applyFilter,
|
|
3099
|
+
columnValues,
|
|
3100
|
+
ref
|
|
3101
|
+
}) {
|
|
3102
|
+
const [opened] = useState10(() => {
|
|
3103
|
+
const shape2 = describeColumnFilter2(controller.getState().filter, column.id);
|
|
3104
|
+
return {
|
|
3105
|
+
shape: shape2,
|
|
3106
|
+
draft: initialFilterEditorDraft2(shape2, columnValues(column.id))
|
|
3107
|
+
};
|
|
3108
|
+
});
|
|
3109
|
+
const [draft, dispatch] = useReducer(filterEditorReducer2, opened.draft);
|
|
3110
|
+
const [operator, setOperator] = useState10(null);
|
|
3111
|
+
const conditions = useRef10(null);
|
|
3112
|
+
const conditionsFocus = useRef10(null);
|
|
3113
|
+
const operatorButton = useRef10(null);
|
|
3114
|
+
const switched = useRef10(false);
|
|
3115
|
+
const selectAllRef = useRef10(null);
|
|
3116
|
+
const selectAll = useMemo4(() => selectAllState(draft), [draft]);
|
|
3117
|
+
const checklist = useMemo4(
|
|
3118
|
+
() => filterChecklist(draft, {
|
|
3119
|
+
valueLimit: menu.valueLimit,
|
|
3120
|
+
blanksLabel: messages.filterBlanks
|
|
3121
|
+
}),
|
|
3122
|
+
[draft, menu.valueLimit, messages.filterBlanks]
|
|
3123
|
+
);
|
|
3124
|
+
useLayoutEffect9(() => {
|
|
3125
|
+
if (selectAllRef.current !== null) {
|
|
3126
|
+
selectAllRef.current.indeterminate = selectAll === "mixed";
|
|
3127
|
+
}
|
|
3128
|
+
});
|
|
3129
|
+
useLayoutEffect9(() => {
|
|
3130
|
+
if (switched.current) {
|
|
3131
|
+
switched.current = false;
|
|
3132
|
+
(operator === null ? operatorButton.current : conditionsFocus.current)?.focus();
|
|
3133
|
+
}
|
|
3134
|
+
}, [operator]);
|
|
3135
|
+
function switchTo(chosen) {
|
|
3136
|
+
switched.current = true;
|
|
3137
|
+
setOperator(chosen);
|
|
3138
|
+
}
|
|
3139
|
+
useImperativeHandle2(ref, () => ({
|
|
3140
|
+
apply: () => {
|
|
3141
|
+
if (operator !== null) {
|
|
3142
|
+
return conditions.current?.apply() ?? true;
|
|
3143
|
+
}
|
|
3144
|
+
const picked = draft.checked !== opened.draft.checked || draft.includeBlanks !== opened.draft.includeBlanks;
|
|
3145
|
+
if (picked) {
|
|
3146
|
+
applyFilter(
|
|
3147
|
+
draftToFilter2(draft, column.id, controller.getState().filter)
|
|
3148
|
+
);
|
|
3149
|
+
}
|
|
3150
|
+
return true;
|
|
3151
|
+
}
|
|
3152
|
+
}));
|
|
3153
|
+
if (operator !== null) {
|
|
3154
|
+
return /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
3155
|
+
/* @__PURE__ */ jsxs15(
|
|
3156
|
+
"button",
|
|
3157
|
+
{
|
|
3158
|
+
type: "button",
|
|
3159
|
+
className: "filter-menu-back",
|
|
3160
|
+
onClick: () => {
|
|
3161
|
+
switchTo(null);
|
|
3162
|
+
},
|
|
3163
|
+
children: [
|
|
3164
|
+
/* @__PURE__ */ jsx20("span", { className: "filter-menu-back-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx20(ChevronLeftIcon2, {}) }),
|
|
3165
|
+
messages.filterBackToValues
|
|
3166
|
+
]
|
|
3167
|
+
}
|
|
3168
|
+
),
|
|
3169
|
+
/* @__PURE__ */ jsx20(
|
|
3170
|
+
SimpleFilterEditor,
|
|
3171
|
+
{
|
|
3172
|
+
ref: conditions,
|
|
3173
|
+
column,
|
|
3174
|
+
menu,
|
|
3175
|
+
controller,
|
|
3176
|
+
messages,
|
|
3177
|
+
initialFocusRef: (element) => {
|
|
3178
|
+
conditionsFocus.current = element;
|
|
3179
|
+
},
|
|
3180
|
+
applyFilter,
|
|
3181
|
+
operator
|
|
3182
|
+
}
|
|
3183
|
+
)
|
|
3184
|
+
] });
|
|
3185
|
+
}
|
|
3186
|
+
const { shape } = opened;
|
|
3187
|
+
return /* @__PURE__ */ jsxs15("div", { className: "filter-menu-values", children: [
|
|
3188
|
+
menu.operators.length > 0 && /* @__PURE__ */ jsx20(
|
|
3189
|
+
OperatorMenuButton,
|
|
3190
|
+
{
|
|
3191
|
+
ref: operatorButton,
|
|
3192
|
+
menu,
|
|
3193
|
+
active: shape.kind === "conditions" ? shape.conditions.map((condition) => condition.operator) : void 0,
|
|
3194
|
+
messages,
|
|
3195
|
+
onChoose: switchTo
|
|
3196
|
+
}
|
|
3197
|
+
),
|
|
3198
|
+
(shape.kind === "conditions" || shape.kind === "custom") && /* @__PURE__ */ jsx20("p", { className: "filter-menu-custom", children: shape.kind === "conditions" ? messages.filterByCondition : messages.customFilter }),
|
|
3199
|
+
/* @__PURE__ */ jsx20(
|
|
3200
|
+
"input",
|
|
3201
|
+
{
|
|
3202
|
+
ref: initialFocusRef,
|
|
3203
|
+
type: "search",
|
|
3204
|
+
className: "filter-menu-search",
|
|
3205
|
+
"aria-label": messages.filterSearchLabel,
|
|
3206
|
+
placeholder: messages.searchPlaceholder,
|
|
3207
|
+
value: draft.search,
|
|
3208
|
+
onChange: (event) => {
|
|
3209
|
+
dispatch({ type: "search", search: event.currentTarget.value });
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
),
|
|
3213
|
+
/* @__PURE__ */ jsxs15("label", { className: "filter-menu-select-all", children: [
|
|
3214
|
+
/* @__PURE__ */ jsx20(
|
|
3215
|
+
"input",
|
|
3216
|
+
{
|
|
3217
|
+
ref: selectAllRef,
|
|
3218
|
+
type: "checkbox",
|
|
3219
|
+
checked: selectAll === "checked",
|
|
3220
|
+
disabled: !checklist.needsSearch && checklist.items.length === 0,
|
|
3221
|
+
onChange: () => {
|
|
3222
|
+
dispatch({ type: "toggleAll" });
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
),
|
|
3226
|
+
messages.filterSelectAll
|
|
3227
|
+
] }),
|
|
3228
|
+
checklist.needsSearch ? /* @__PURE__ */ jsx20("p", { className: "filter-menu-search-first", children: messages.filterSearchFirst(checklist.total) }) : /* @__PURE__ */ jsx20(
|
|
3229
|
+
ValueChecklist,
|
|
3230
|
+
{
|
|
3231
|
+
items: checklist.items,
|
|
3232
|
+
showCounts: menu.showCounts,
|
|
3233
|
+
label: messages.filterValuesLabel,
|
|
3234
|
+
onToggle: (item) => {
|
|
3235
|
+
dispatch(toggleOf(item));
|
|
3236
|
+
}
|
|
3237
|
+
}
|
|
3238
|
+
),
|
|
3239
|
+
checklist.hiddenCount > 0 && /* @__PURE__ */ jsx20("p", { role: "status", className: "filter-menu-more", children: messages.filterMoreValues(checklist.hiddenCount) })
|
|
3240
|
+
] });
|
|
3241
|
+
}
|
|
3242
|
+
|
|
3243
|
+
// src/DataGrid/filterMenu/FilterMenu.tsx
|
|
3244
|
+
import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3245
|
+
var SORT_COMMANDS = [
|
|
3246
|
+
"sort.ascending",
|
|
3247
|
+
"sort.descending",
|
|
3248
|
+
"sort.clear"
|
|
3249
|
+
];
|
|
3250
|
+
function isItem(entry) {
|
|
3251
|
+
return entry.type === "item";
|
|
3252
|
+
}
|
|
3253
|
+
function FilterMenu({
|
|
3254
|
+
target,
|
|
3255
|
+
controller,
|
|
3256
|
+
commands,
|
|
3257
|
+
messages,
|
|
3258
|
+
close,
|
|
3259
|
+
initialFocusRef,
|
|
3260
|
+
applyFilter,
|
|
3261
|
+
columnValues
|
|
3262
|
+
}) {
|
|
3263
|
+
const editor = useRef11(null);
|
|
3264
|
+
const column = target.area === "header" ? controller.getView().dataColumns.find((entry) => entry.id === target.columnId) : void 0;
|
|
3265
|
+
const menu = column === void 0 ? null : resolveColumnFilterMenu2(controller.getOptions(), column.column);
|
|
3266
|
+
useEffect3(() => {
|
|
3267
|
+
if (menu === null) {
|
|
3268
|
+
close();
|
|
3269
|
+
}
|
|
3270
|
+
});
|
|
3271
|
+
if (column === void 0 || menu === null) {
|
|
3272
|
+
return null;
|
|
3273
|
+
}
|
|
3274
|
+
const resolveOptions = {
|
|
3275
|
+
commands: commands.commands,
|
|
3276
|
+
context: commands.contextFor(target)
|
|
3277
|
+
};
|
|
3278
|
+
const sortItems = resolveMenu2(SORT_COMMANDS, resolveOptions).filter(isItem);
|
|
3279
|
+
const [clearItem] = resolveMenu2(["filter.clear"], resolveOptions).filter(
|
|
3280
|
+
isItem
|
|
3281
|
+
);
|
|
3282
|
+
function run(item) {
|
|
3283
|
+
commands.run(item.id, target, "filterMenu");
|
|
3284
|
+
close();
|
|
3285
|
+
}
|
|
3286
|
+
const editorProps = {
|
|
3287
|
+
ref: editor,
|
|
3288
|
+
column,
|
|
3289
|
+
menu,
|
|
3290
|
+
controller,
|
|
3291
|
+
messages,
|
|
3292
|
+
initialFocusRef,
|
|
3293
|
+
applyFilter
|
|
3294
|
+
};
|
|
3295
|
+
function apply(event) {
|
|
3296
|
+
event.preventDefault();
|
|
3297
|
+
if (editor.current?.apply() ?? true) {
|
|
3298
|
+
close();
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
return /* @__PURE__ */ jsx21(
|
|
3302
|
+
"div",
|
|
3303
|
+
{
|
|
3304
|
+
role: "dialog",
|
|
3305
|
+
"aria-label": messages.filterMenuLabel(
|
|
3306
|
+
resolveColumnHeaderText(column.column)
|
|
3307
|
+
),
|
|
3308
|
+
className: "gridkit-filter-menu",
|
|
3309
|
+
children: /* @__PURE__ */ jsxs16(
|
|
3310
|
+
"form",
|
|
3311
|
+
{
|
|
3312
|
+
className: "filter-menu-form",
|
|
3313
|
+
noValidate: true,
|
|
3314
|
+
onSubmit: apply,
|
|
3315
|
+
onKeyDown: (event) => {
|
|
3316
|
+
if (event.key === "Enter" && event.target instanceof Element && event.target.closest("select, [role=listbox]") !== null) {
|
|
3317
|
+
event.preventDefault();
|
|
3318
|
+
event.currentTarget.requestSubmit();
|
|
3319
|
+
}
|
|
3320
|
+
},
|
|
3321
|
+
children: [
|
|
3322
|
+
sortItems.length > 0 && /* @__PURE__ */ jsx21("div", { className: "filter-menu-sort", children: sortItems.map((item) => /* @__PURE__ */ jsxs16(
|
|
3323
|
+
"button",
|
|
3324
|
+
{
|
|
3325
|
+
type: "button",
|
|
3326
|
+
className: "filter-menu-sort-item",
|
|
3327
|
+
disabled: item.disabled,
|
|
3328
|
+
...ariaAttr(
|
|
3329
|
+
item.checked !== void 0,
|
|
3330
|
+
"aria-pressed",
|
|
3331
|
+
item.checked
|
|
3332
|
+
),
|
|
3333
|
+
onClick: () => {
|
|
3334
|
+
run(item);
|
|
3335
|
+
},
|
|
3336
|
+
children: [
|
|
3337
|
+
/* @__PURE__ */ jsx21("span", { className: "filter-menu-sort-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx21(MenuIcon, { name: item.icon }) }),
|
|
3338
|
+
item.label
|
|
3339
|
+
]
|
|
3340
|
+
},
|
|
3341
|
+
item.id
|
|
3342
|
+
)) }),
|
|
3343
|
+
menu.ui === "excel" ? /* @__PURE__ */ jsx21(ExcelFilterEditor, { ...editorProps, columnValues }) : /* @__PURE__ */ jsx21(SimpleFilterEditor, { ...editorProps }),
|
|
3344
|
+
/* @__PURE__ */ jsxs16("div", { className: "filter-menu-actions", children: [
|
|
3345
|
+
clearItem !== void 0 && /* @__PURE__ */ jsx21(
|
|
3346
|
+
"button",
|
|
3347
|
+
{
|
|
3348
|
+
type: "button",
|
|
3349
|
+
className: "filter-menu-clear",
|
|
3350
|
+
disabled: clearItem.disabled,
|
|
3351
|
+
onClick: () => {
|
|
3352
|
+
run(clearItem);
|
|
3353
|
+
},
|
|
3354
|
+
children: clearItem.label
|
|
3355
|
+
}
|
|
3356
|
+
),
|
|
3357
|
+
/* @__PURE__ */ jsx21("button", { type: "button", className: "filter-menu-cancel", onClick: close, children: messages.cancelFilter }),
|
|
3358
|
+
/* @__PURE__ */ jsx21("button", { type: "submit", className: "filter-menu-apply", children: messages.applyFilter })
|
|
3359
|
+
] })
|
|
3360
|
+
]
|
|
3361
|
+
}
|
|
3362
|
+
)
|
|
3363
|
+
}
|
|
3364
|
+
);
|
|
3365
|
+
}
|
|
3366
|
+
|
|
3367
|
+
// src/DataGrid/filterMenu/useApplyFilter.ts
|
|
3368
|
+
import { useEffect as useEffect4, useRef as useRef12 } from "react";
|
|
3369
|
+
function useApplyFilter(controller, messages, announce) {
|
|
3370
|
+
const unannounced = useRef12(null);
|
|
3371
|
+
useEffect4(() => {
|
|
3372
|
+
if (unannounced.current === controller.getState().filter) {
|
|
3373
|
+
unannounced.current = null;
|
|
3374
|
+
announce(
|
|
3375
|
+
messages.filterResults(
|
|
3376
|
+
controller.getView().rows.length,
|
|
3377
|
+
controller.getOptions().dataSource?.length ?? 0
|
|
3378
|
+
)
|
|
3379
|
+
);
|
|
3380
|
+
}
|
|
3381
|
+
});
|
|
3382
|
+
return (filter) => {
|
|
3383
|
+
unannounced.current = filter;
|
|
3384
|
+
controller.setFilter(filter);
|
|
3385
|
+
};
|
|
3386
|
+
}
|
|
3387
|
+
|
|
3388
|
+
// src/DataGrid/filterMenu/useFilterValueCache.ts
|
|
3389
|
+
import { useState as useState11 } from "react";
|
|
3390
|
+
import {
|
|
3391
|
+
createColumnValueOptionsCache
|
|
3392
|
+
} from "@gridkitjs/core";
|
|
3393
|
+
var NO_ROWS2 = [];
|
|
3394
|
+
function useFilterValueCache(controller, messages) {
|
|
3395
|
+
const [cache] = useState11(createColumnValueOptionsCache);
|
|
3396
|
+
return (columnId) => {
|
|
3397
|
+
const { dataSource = NO_ROWS2, locale } = controller.getOptions();
|
|
3398
|
+
return cache.get(
|
|
3399
|
+
dataSource,
|
|
3400
|
+
controller.getView().dataColumns,
|
|
3401
|
+
controller.getState().filter,
|
|
3402
|
+
columnId,
|
|
3403
|
+
locale === void 0 ? { messages } : { locale, messages }
|
|
3404
|
+
);
|
|
3405
|
+
};
|
|
3406
|
+
}
|
|
3407
|
+
|
|
3408
|
+
// src/DataGrid/panels/GridPanels.tsx
|
|
3409
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
3410
|
+
var panelKinds = {
|
|
3411
|
+
columnChooser: { component: ColumnChooser, trapFocus: false },
|
|
3412
|
+
filter: { component: FilterMenu, trapFocus: true }
|
|
3413
|
+
};
|
|
3414
|
+
function GridPanels({
|
|
3415
|
+
panels,
|
|
3416
|
+
controller,
|
|
3417
|
+
commands,
|
|
3418
|
+
messages
|
|
3419
|
+
}) {
|
|
3420
|
+
const initialFocus = useRef13(null);
|
|
3421
|
+
const applyFilter = useApplyFilter(
|
|
3422
|
+
controller,
|
|
3423
|
+
messages,
|
|
3424
|
+
commands.host.announce
|
|
3425
|
+
);
|
|
3426
|
+
const columnValues = useFilterValueCache(controller, messages);
|
|
3427
|
+
const { panel, close } = panels;
|
|
3428
|
+
if (panel === null) {
|
|
3429
|
+
return null;
|
|
3430
|
+
}
|
|
3431
|
+
const { component: Panel, trapFocus } = panelKinds[panel.kind];
|
|
3432
|
+
return /* @__PURE__ */ jsx22(
|
|
3433
|
+
Overlay,
|
|
3434
|
+
{
|
|
3435
|
+
anchor: panel.anchor,
|
|
3436
|
+
placement: panel.placement,
|
|
3437
|
+
gap: panel.anchor instanceof Element ? ANCHOR_GAP : 0,
|
|
3438
|
+
initialFocus,
|
|
3439
|
+
returnFocusTo: panel.returnFocusTo,
|
|
3440
|
+
ignoreScrollAfterInput: true,
|
|
3441
|
+
trapFocus,
|
|
3442
|
+
themeClassName: panel.themeClassName,
|
|
3443
|
+
onDismiss: close,
|
|
3444
|
+
children: /* @__PURE__ */ jsx22(
|
|
3445
|
+
Panel,
|
|
3446
|
+
{
|
|
3447
|
+
target: panel.target,
|
|
3448
|
+
controller,
|
|
3449
|
+
commands,
|
|
3450
|
+
messages,
|
|
3451
|
+
close,
|
|
3452
|
+
initialFocusRef: (element) => {
|
|
3453
|
+
initialFocus.current = element;
|
|
3454
|
+
},
|
|
3455
|
+
applyFilter,
|
|
3456
|
+
columnValues
|
|
3457
|
+
}
|
|
3458
|
+
)
|
|
3459
|
+
},
|
|
3460
|
+
panel.key
|
|
3461
|
+
);
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3464
|
+
// src/DataGrid/panels/panelApi.ts
|
|
3465
|
+
import { resolveColumnFilterMenu as resolveColumnFilterMenu3 } from "@gridkitjs/core";
|
|
3466
|
+
function panelApi(panels, controller) {
|
|
3467
|
+
return {
|
|
3468
|
+
openColumnChooser: () => {
|
|
3469
|
+
panels.open("columnChooser", { area: "grid" });
|
|
3470
|
+
},
|
|
3471
|
+
openFilterMenu: (columnId) => {
|
|
3472
|
+
const shown = controller.getView().columns.find((entry) => entry.id === columnId);
|
|
3473
|
+
if (shown === void 0 || resolveColumnFilterMenu3(controller.getOptions(), shown.column) === null) {
|
|
3474
|
+
return false;
|
|
3475
|
+
}
|
|
3476
|
+
panels.open("filter", { area: "header", columnId });
|
|
3477
|
+
return true;
|
|
3478
|
+
},
|
|
3479
|
+
closeFilterMenu: () => {
|
|
3480
|
+
if (panels.panel?.kind === "filter") {
|
|
3481
|
+
panels.close();
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
};
|
|
3485
|
+
}
|
|
3486
|
+
|
|
3487
|
+
// src/DataGrid/panels/useGridPanels.ts
|
|
3488
|
+
import { useLayoutEffect as useLayoutEffect10, useRef as useRef14, useState as useState12 } from "react";
|
|
3489
|
+
function toolbarItem(root, itemId) {
|
|
3490
|
+
const items = root.querySelectorAll(
|
|
3491
|
+
":scope > .gridkit-toolbar > [data-gridkit-toolbar-item]"
|
|
3492
|
+
);
|
|
3493
|
+
return Array.from(items).find(
|
|
3494
|
+
(item) => item.getAttribute("data-gridkit-toolbar-item") === itemId
|
|
3495
|
+
) ?? // In "More" while the toolbar is narrow: the button it is chosen from.
|
|
3496
|
+
Array.from(items).find(
|
|
3497
|
+
(item) => item.hasAttribute("data-gridkit-toolbar-more")
|
|
3498
|
+
) ?? null;
|
|
3499
|
+
}
|
|
3500
|
+
function headerCell2(headerTable, columnId) {
|
|
3501
|
+
const cells = headerTable?.tHead?.rows[0]?.cells;
|
|
3502
|
+
return cells === void 0 ? null : Array.from(cells).find(
|
|
3503
|
+
(cell) => cell.getAttribute("data-gridkit-column") === columnId
|
|
3504
|
+
) ?? null;
|
|
3505
|
+
}
|
|
3506
|
+
function useGridPanels({
|
|
3507
|
+
rootRef,
|
|
3508
|
+
headerTableRef,
|
|
3509
|
+
nav
|
|
3510
|
+
}) {
|
|
3511
|
+
const [panel, setPanel] = useState12(null);
|
|
3512
|
+
const openings = useRef14(0);
|
|
3513
|
+
function placeFor(root, target) {
|
|
3514
|
+
const element = target.area === "toolbar" ? toolbarItem(root, target.itemId) : target.area === "header" ? headerCell2(headerTableRef.current, target.columnId) : null;
|
|
3515
|
+
if (element !== null) {
|
|
3516
|
+
return {
|
|
3517
|
+
anchor: element,
|
|
3518
|
+
// The toolbar's own button sits at its far end.
|
|
3519
|
+
placement: target.area === "toolbar" ? "bottom-end" : "bottom-start",
|
|
3520
|
+
returnFocusTo: element
|
|
3521
|
+
};
|
|
3522
|
+
}
|
|
3523
|
+
const { right, top } = root.getBoundingClientRect();
|
|
3524
|
+
return {
|
|
3525
|
+
anchor: { x: right, y: top },
|
|
3526
|
+
placement: "bottom-end",
|
|
3527
|
+
returnFocusTo: void 0
|
|
3528
|
+
};
|
|
3529
|
+
}
|
|
3530
|
+
const shown = useRef14(null);
|
|
3531
|
+
useLayoutEffect10(() => {
|
|
3532
|
+
const closed = shown.current;
|
|
3533
|
+
shown.current = panel;
|
|
3534
|
+
if (panel === null && closed?.returnFocusTo?.isConnected === false && document.activeElement === document.body) {
|
|
3535
|
+
nav.focusTabStop();
|
|
3536
|
+
}
|
|
3537
|
+
});
|
|
3538
|
+
return {
|
|
3539
|
+
panel,
|
|
3540
|
+
open: (kind, target) => {
|
|
3541
|
+
const root = rootRef.current;
|
|
3542
|
+
if (root === null) {
|
|
3543
|
+
return;
|
|
3544
|
+
}
|
|
3545
|
+
openings.current += 1;
|
|
3546
|
+
setPanel({
|
|
3547
|
+
key: openings.current,
|
|
3548
|
+
kind,
|
|
3549
|
+
target,
|
|
3550
|
+
...placeFor(root, target),
|
|
3551
|
+
themeClassName: overlayThemeClassName(root)
|
|
3552
|
+
});
|
|
3553
|
+
},
|
|
3554
|
+
close: () => {
|
|
3555
|
+
setPanel(null);
|
|
3556
|
+
}
|
|
3557
|
+
};
|
|
3558
|
+
}
|
|
3559
|
+
|
|
3560
|
+
// src/DataGrid/toolbar/GridToolbar.tsx
|
|
3561
|
+
import { useLayoutEffect as useLayoutEffect13, useRef as useRef18 } from "react";
|
|
3562
|
+
import {
|
|
3563
|
+
resolveToolbar,
|
|
3564
|
+
splitToolbarItems,
|
|
3565
|
+
toolbarEntries
|
|
3566
|
+
} from "@gridkitjs/core";
|
|
3567
|
+
import { attachToolbar } from "@gridkitjs/dom";
|
|
3568
|
+
|
|
3569
|
+
// src/DataGrid/toolbar/ToolbarMenuButton.tsx
|
|
3570
|
+
import { useLayoutEffect as useLayoutEffect11, useRef as useRef15, useState as useState13 } from "react";
|
|
3571
|
+
import { Fragment as Fragment8, jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3572
|
+
function ToolbarMenuButton({
|
|
3573
|
+
itemKey,
|
|
3574
|
+
label,
|
|
3575
|
+
icon,
|
|
3576
|
+
entries,
|
|
3577
|
+
more = false,
|
|
3578
|
+
onMenuClose
|
|
3579
|
+
}) {
|
|
3580
|
+
const [menu, setMenu] = useState13(null);
|
|
3581
|
+
const menuBehaviourRef = useRef15(null);
|
|
3582
|
+
useLayoutEffect11(() => {
|
|
3583
|
+
if (menu !== null && menu.focusItem > 0) {
|
|
3584
|
+
menuBehaviourRef.current?.focusItem(menu.focusItem);
|
|
3585
|
+
}
|
|
3586
|
+
}, [menu]);
|
|
3587
|
+
function open(button, onLast = false) {
|
|
3588
|
+
setMenu({
|
|
3589
|
+
anchor: button,
|
|
3590
|
+
themeClassName: overlayThemeClassName(button),
|
|
3591
|
+
focusItem: onLast ? entries.filter((entry) => entry.type !== "separator").length - 1 : 0
|
|
3592
|
+
});
|
|
3593
|
+
}
|
|
3594
|
+
function close() {
|
|
3595
|
+
setMenu(null);
|
|
3596
|
+
onMenuClose();
|
|
3597
|
+
}
|
|
3598
|
+
return /* @__PURE__ */ jsxs17(Fragment8, { children: [
|
|
3599
|
+
/* @__PURE__ */ jsxs17(
|
|
3600
|
+
"button",
|
|
3601
|
+
{
|
|
3602
|
+
type: "button",
|
|
3603
|
+
className: classNames("toolbar-button", more && "toolbar-more"),
|
|
3604
|
+
"data-gridkit-toolbar-item": itemKey,
|
|
3605
|
+
...ariaAttr(more, "data-gridkit-toolbar-more", ""),
|
|
3606
|
+
"aria-haspopup": "menu",
|
|
3607
|
+
"aria-expanded": menu !== null,
|
|
3608
|
+
onClick: (event) => {
|
|
3609
|
+
if (menu === null) {
|
|
3610
|
+
open(event.currentTarget);
|
|
3611
|
+
} else {
|
|
3612
|
+
close();
|
|
3613
|
+
}
|
|
3614
|
+
},
|
|
3615
|
+
onKeyDown: (event) => {
|
|
3616
|
+
if ((event.key === "ArrowDown" || event.key === "ArrowUp") && menu === null) {
|
|
3617
|
+
event.preventDefault();
|
|
3618
|
+
open(event.currentTarget, event.key === "ArrowUp");
|
|
3619
|
+
}
|
|
3620
|
+
},
|
|
3621
|
+
children: [
|
|
3622
|
+
icon !== void 0 && /* @__PURE__ */ jsx23("span", { className: "toolbar-button-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx23(MenuIcon, { name: icon }) }),
|
|
3623
|
+
label,
|
|
3624
|
+
/* @__PURE__ */ jsx23("span", { className: "toolbar-button-indicator", "aria-hidden": "true", children: /* @__PURE__ */ jsx23(ChevronDownIcon, {}) })
|
|
3625
|
+
]
|
|
3626
|
+
}
|
|
3627
|
+
),
|
|
3628
|
+
menu !== null && /* @__PURE__ */ jsx23(
|
|
3629
|
+
Overlay,
|
|
3630
|
+
{
|
|
3631
|
+
anchor: menu.anchor,
|
|
3632
|
+
placement: "bottom-start",
|
|
3633
|
+
gap: ANCHOR_GAP,
|
|
3634
|
+
returnFocusTo: menu.anchor,
|
|
3635
|
+
themeClassName: menu.themeClassName,
|
|
3636
|
+
onDismiss: close,
|
|
3637
|
+
children: /* @__PURE__ */ jsx23(
|
|
3638
|
+
GridMenu,
|
|
3639
|
+
{
|
|
3640
|
+
entries,
|
|
3641
|
+
label,
|
|
3642
|
+
themeClassName: menu.themeClassName,
|
|
3643
|
+
behaviourRef: menuBehaviourRef,
|
|
3644
|
+
onRun: (item) => {
|
|
3645
|
+
item.run();
|
|
3646
|
+
close();
|
|
3647
|
+
},
|
|
3648
|
+
onClose: close
|
|
3649
|
+
}
|
|
3650
|
+
)
|
|
3651
|
+
}
|
|
3652
|
+
)
|
|
3653
|
+
] });
|
|
3654
|
+
}
|
|
3655
|
+
|
|
3656
|
+
// src/DataGrid/toolbar/ToolbarSearch.tsx
|
|
3657
|
+
import { useEffect as useEffect5, useRef as useRef16, useState as useState14 } from "react";
|
|
3658
|
+
import {
|
|
3659
|
+
searchTextOf,
|
|
3660
|
+
setSearchText
|
|
3661
|
+
} from "@gridkitjs/core";
|
|
3662
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
3663
|
+
var SEARCH_DELAY_MS = 250;
|
|
3664
|
+
function ToolbarSearch({
|
|
3665
|
+
itemKey,
|
|
3666
|
+
controller,
|
|
3667
|
+
messages,
|
|
3668
|
+
announce
|
|
3669
|
+
}) {
|
|
3670
|
+
const applied = searchTextOf(controller.getState().filter);
|
|
3671
|
+
const [draft, setDraft] = useState14(null);
|
|
3672
|
+
const timer = useRef16(void 0);
|
|
3673
|
+
const unannounced = useRef16(null);
|
|
3674
|
+
const text = draft !== null && draft.over === applied ? draft.text : applied;
|
|
3675
|
+
function apply(next, over) {
|
|
3676
|
+
clearTimeout(timer.current);
|
|
3677
|
+
setDraft(null);
|
|
3678
|
+
const filter = controller.getState().filter;
|
|
3679
|
+
if (searchTextOf(filter) !== over) {
|
|
3680
|
+
return;
|
|
3681
|
+
}
|
|
3682
|
+
const searched = setSearchText(filter, next);
|
|
3683
|
+
if (searched !== filter) {
|
|
3684
|
+
unannounced.current = next;
|
|
3685
|
+
controller.setFilter(searched);
|
|
3686
|
+
}
|
|
3687
|
+
}
|
|
3688
|
+
useEffect5(() => {
|
|
3689
|
+
if (unannounced.current === applied) {
|
|
3690
|
+
unannounced.current = null;
|
|
3691
|
+
announce(messages.searchResults(controller.getView().rows.length));
|
|
3692
|
+
}
|
|
3693
|
+
});
|
|
3694
|
+
useEffect5(
|
|
3695
|
+
() => () => {
|
|
3696
|
+
clearTimeout(timer.current);
|
|
3697
|
+
},
|
|
3698
|
+
[]
|
|
3699
|
+
);
|
|
3700
|
+
return /* @__PURE__ */ jsx24(
|
|
3701
|
+
"input",
|
|
3702
|
+
{
|
|
3703
|
+
type: "search",
|
|
3704
|
+
className: "toolbar-search",
|
|
3705
|
+
"data-gridkit-toolbar-item": itemKey,
|
|
3706
|
+
"aria-label": messages.searchLabel,
|
|
3707
|
+
placeholder: messages.searchPlaceholder,
|
|
3708
|
+
value: text,
|
|
3709
|
+
onChange: (event) => {
|
|
3710
|
+
const typed = event.target.value;
|
|
3711
|
+
setDraft({ text: typed, over: applied });
|
|
3712
|
+
clearTimeout(timer.current);
|
|
3713
|
+
timer.current = setTimeout(() => {
|
|
3714
|
+
apply(typed, applied);
|
|
3715
|
+
}, SEARCH_DELAY_MS);
|
|
3716
|
+
},
|
|
3717
|
+
onKeyDown: (event) => {
|
|
3718
|
+
if (event.key === "Enter") {
|
|
3719
|
+
apply(text, applied);
|
|
3720
|
+
} else if (event.key === "Escape" && text !== "") {
|
|
3721
|
+
event.preventDefault();
|
|
3722
|
+
apply("", applied);
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
}
|
|
3726
|
+
);
|
|
3727
|
+
}
|
|
3728
|
+
|
|
3729
|
+
// src/DataGrid/toolbar/useToolbarOverflow.ts
|
|
3730
|
+
import { useLayoutEffect as useLayoutEffect12, useRef as useRef17, useState as useState15 } from "react";
|
|
3731
|
+
import { observeToolbarOverflow } from "@gridkitjs/dom";
|
|
3732
|
+
function useToolbarOverflow(toolbarRef, items) {
|
|
3733
|
+
const [fit, setFit] = useState15(items.length);
|
|
3734
|
+
const overflow = useRef17(null);
|
|
3735
|
+
const measuredLayout = useRef17("");
|
|
3736
|
+
const layout = JSON.stringify(
|
|
3737
|
+
items.map((item) => [
|
|
3738
|
+
item.type,
|
|
3739
|
+
item.key,
|
|
3740
|
+
"label" in item ? item.label : null
|
|
3741
|
+
])
|
|
3742
|
+
);
|
|
3743
|
+
useLayoutEffect12(() => {
|
|
3744
|
+
const toolbar = toolbarRef.current;
|
|
3745
|
+
if (toolbar === null || layout === measuredLayout.current) {
|
|
3746
|
+
return;
|
|
3747
|
+
}
|
|
3748
|
+
measuredLayout.current = layout;
|
|
3749
|
+
const options = { items, onChange: setFit };
|
|
3750
|
+
if (overflow.current === null) {
|
|
3751
|
+
overflow.current = observeToolbarOverflow(toolbar, options);
|
|
3752
|
+
} else {
|
|
3753
|
+
overflow.current.update(options);
|
|
3754
|
+
}
|
|
3755
|
+
}, [toolbarRef, layout, items]);
|
|
3756
|
+
useLayoutEffect12(
|
|
3757
|
+
() => () => {
|
|
3758
|
+
overflow.current?.detach();
|
|
3759
|
+
overflow.current = null;
|
|
3760
|
+
measuredLayout.current = "";
|
|
3761
|
+
},
|
|
3762
|
+
[]
|
|
3763
|
+
);
|
|
3764
|
+
return fit;
|
|
3765
|
+
}
|
|
3766
|
+
|
|
3767
|
+
// src/DataGrid/toolbar/GridToolbar.tsx
|
|
3768
|
+
import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3769
|
+
function reporting(run, report) {
|
|
3770
|
+
return () => {
|
|
3771
|
+
const ran = run();
|
|
3772
|
+
if (ran) {
|
|
3773
|
+
report();
|
|
3774
|
+
}
|
|
3775
|
+
return ran;
|
|
3776
|
+
};
|
|
3777
|
+
}
|
|
3778
|
+
function reportingEntries(entries, report) {
|
|
3779
|
+
return entries.map((entry) => {
|
|
3780
|
+
switch (entry.type) {
|
|
3781
|
+
case "item":
|
|
3782
|
+
return {
|
|
3783
|
+
...entry,
|
|
3784
|
+
run: reporting(entry.run, () => {
|
|
3785
|
+
report(entry.id);
|
|
3786
|
+
})
|
|
3787
|
+
};
|
|
3788
|
+
case "submenu":
|
|
3789
|
+
return { ...entry, items: reportingEntries(entry.items, report) };
|
|
3790
|
+
default:
|
|
3791
|
+
return entry;
|
|
3792
|
+
}
|
|
3793
|
+
});
|
|
3794
|
+
}
|
|
3795
|
+
function reportingItem(item, report) {
|
|
3796
|
+
switch (item.type) {
|
|
3797
|
+
case "button":
|
|
3798
|
+
return {
|
|
3799
|
+
...item,
|
|
3800
|
+
run: reporting(item.run, () => {
|
|
3801
|
+
report(item.id, item.id);
|
|
3802
|
+
})
|
|
3803
|
+
};
|
|
3804
|
+
case "menu":
|
|
3805
|
+
return {
|
|
3806
|
+
...item,
|
|
3807
|
+
items: reportingEntries(item.items, (commandId) => {
|
|
3808
|
+
report(commandId, item.id);
|
|
3809
|
+
})
|
|
3810
|
+
};
|
|
3811
|
+
default:
|
|
3812
|
+
return item;
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
function GridToolbar(props) {
|
|
3816
|
+
const entries = toolbarEntries(props.toolbar);
|
|
3817
|
+
if (entries.length === 0) {
|
|
3818
|
+
return null;
|
|
3819
|
+
}
|
|
3820
|
+
const label = (typeof props.toolbar === "object" ? props.toolbar.label : void 0) ?? props.messages.toolbarLabel;
|
|
3821
|
+
return /* @__PURE__ */ jsx25(Toolbar, { ...props, entries, label });
|
|
3822
|
+
}
|
|
3823
|
+
function Toolbar({
|
|
3824
|
+
entries,
|
|
3825
|
+
label,
|
|
3826
|
+
renderItem,
|
|
3827
|
+
gridId,
|
|
3828
|
+
controller,
|
|
3829
|
+
commands,
|
|
3830
|
+
messages,
|
|
3831
|
+
announce
|
|
3832
|
+
}) {
|
|
3833
|
+
const toolbarRef = useRef18(null);
|
|
3834
|
+
const menuClosed = useRef18(false);
|
|
3835
|
+
const items = resolveToolbar(entries, {
|
|
3836
|
+
commands: commands.commands,
|
|
3837
|
+
contextFor: commands.contextFor
|
|
3838
|
+
}).map(
|
|
3839
|
+
(item) => reportingItem(item, (commandId, itemId) => {
|
|
3840
|
+
commands.report(commandId, { area: "toolbar", itemId }, "toolbar");
|
|
3841
|
+
})
|
|
3842
|
+
);
|
|
3843
|
+
const fit = useToolbarOverflow(toolbarRef, items);
|
|
3844
|
+
const { shown, overflow } = splitToolbarItems(items, fit);
|
|
3845
|
+
useLayoutEffect13(() => {
|
|
3846
|
+
const toolbar = toolbarRef.current;
|
|
3847
|
+
return toolbar === null ? void 0 : attachToolbar(toolbar);
|
|
3848
|
+
}, []);
|
|
3849
|
+
useLayoutEffect13(() => {
|
|
3850
|
+
if (!menuClosed.current) {
|
|
3851
|
+
return;
|
|
3852
|
+
}
|
|
3853
|
+
menuClosed.current = false;
|
|
3854
|
+
const toolbar = toolbarRef.current;
|
|
3855
|
+
if (toolbar !== null && document.activeElement === document.body) {
|
|
3856
|
+
(toolbar.querySelector('[tabindex="0"]') ?? toolbar.querySelector("button, input"))?.focus();
|
|
3857
|
+
}
|
|
3858
|
+
});
|
|
3859
|
+
function onMenuClose() {
|
|
3860
|
+
menuClosed.current = true;
|
|
3861
|
+
}
|
|
3862
|
+
function draw(item) {
|
|
3863
|
+
switch (item.type) {
|
|
3864
|
+
case "button":
|
|
3865
|
+
return /* @__PURE__ */ jsxs18(
|
|
3866
|
+
"button",
|
|
3867
|
+
{
|
|
3868
|
+
type: "button",
|
|
3869
|
+
className: "toolbar-button",
|
|
3870
|
+
"data-gridkit-toolbar-item": item.key,
|
|
3871
|
+
...ariaAttr(item.disabled, "aria-disabled", true),
|
|
3872
|
+
...ariaAttr(
|
|
3873
|
+
item.pressed !== void 0,
|
|
3874
|
+
"aria-pressed",
|
|
3875
|
+
item.pressed
|
|
3876
|
+
),
|
|
3877
|
+
...ariaAttr(
|
|
3878
|
+
item.shortcut !== void 0,
|
|
3879
|
+
"aria-keyshortcuts",
|
|
3880
|
+
item.shortcut
|
|
3881
|
+
),
|
|
3882
|
+
onClick: () => {
|
|
3883
|
+
item.run();
|
|
3884
|
+
},
|
|
3885
|
+
children: [
|
|
3886
|
+
item.icon !== void 0 && /* @__PURE__ */ jsx25("span", { className: "toolbar-button-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx25(MenuIcon, { name: item.icon }) }),
|
|
3887
|
+
item.label
|
|
3888
|
+
]
|
|
3889
|
+
},
|
|
3890
|
+
item.key
|
|
3891
|
+
);
|
|
3892
|
+
case "menu":
|
|
3893
|
+
return /* @__PURE__ */ jsx25(
|
|
3894
|
+
ToolbarMenuButton,
|
|
3895
|
+
{
|
|
3896
|
+
itemKey: item.key,
|
|
3897
|
+
label: item.label,
|
|
3898
|
+
icon: item.icon,
|
|
3899
|
+
entries: item.items,
|
|
3900
|
+
onMenuClose
|
|
3901
|
+
},
|
|
3902
|
+
item.key
|
|
3903
|
+
);
|
|
3904
|
+
case "search":
|
|
3905
|
+
return /* @__PURE__ */ jsx25(
|
|
3906
|
+
ToolbarSearch,
|
|
3907
|
+
{
|
|
3908
|
+
itemKey: item.key,
|
|
3909
|
+
controller,
|
|
3910
|
+
messages,
|
|
3911
|
+
announce
|
|
3912
|
+
},
|
|
3913
|
+
item.key
|
|
3914
|
+
);
|
|
3915
|
+
case "separator":
|
|
3916
|
+
return /* @__PURE__ */ jsx25(
|
|
3917
|
+
"div",
|
|
3918
|
+
{
|
|
3919
|
+
role: "separator",
|
|
3920
|
+
"aria-orientation": "vertical",
|
|
3921
|
+
className: "toolbar-separator",
|
|
3922
|
+
"data-gridkit-toolbar-item": item.key
|
|
3923
|
+
},
|
|
3924
|
+
item.key
|
|
3925
|
+
);
|
|
3926
|
+
case "spacer":
|
|
3927
|
+
return /* @__PURE__ */ jsx25(
|
|
3928
|
+
"div",
|
|
3929
|
+
{
|
|
3930
|
+
className: "toolbar-spacer",
|
|
3931
|
+
"data-gridkit-toolbar-item": item.key
|
|
3932
|
+
},
|
|
3933
|
+
item.key
|
|
3934
|
+
);
|
|
3935
|
+
case "custom":
|
|
3936
|
+
return /* @__PURE__ */ jsx25(
|
|
3937
|
+
"div",
|
|
3938
|
+
{
|
|
3939
|
+
className: "toolbar-custom",
|
|
3940
|
+
"data-gridkit-toolbar-item": item.key,
|
|
3941
|
+
children: renderItem?.(item.id)
|
|
3942
|
+
},
|
|
3943
|
+
item.key
|
|
3944
|
+
);
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
return /* @__PURE__ */ jsxs18(
|
|
3948
|
+
"div",
|
|
3949
|
+
{
|
|
3950
|
+
ref: toolbarRef,
|
|
3951
|
+
role: "toolbar",
|
|
3952
|
+
"aria-label": label,
|
|
3953
|
+
"aria-controls": gridId,
|
|
3954
|
+
className: "gridkit-toolbar",
|
|
3955
|
+
children: [
|
|
3956
|
+
shown.map(draw),
|
|
3957
|
+
overflow.length > 0 && /* @__PURE__ */ jsx25(
|
|
3958
|
+
ToolbarMenuButton,
|
|
3959
|
+
{
|
|
3960
|
+
itemKey: "more",
|
|
3961
|
+
label: messages.moreToolbarItems,
|
|
3962
|
+
entries: overflow,
|
|
3963
|
+
more: true,
|
|
3964
|
+
onMenuClose
|
|
3965
|
+
}
|
|
3966
|
+
)
|
|
3967
|
+
]
|
|
3968
|
+
}
|
|
3969
|
+
);
|
|
3970
|
+
}
|
|
3971
|
+
|
|
3972
|
+
// src/DataGrid/useColumnDrag.ts
|
|
3973
|
+
import {
|
|
3974
|
+
resolveKeyboardDropTarget as resolveKeyboardDropTarget2
|
|
3975
|
+
} from "@gridkitjs/core";
|
|
3976
|
+
import { resolveColumnDropTarget } from "@gridkitjs/dom";
|
|
3977
|
+
function useColumnDrag({
|
|
3978
|
+
order,
|
|
3979
|
+
groupBy,
|
|
3980
|
+
groupByDraggableIds,
|
|
3981
|
+
onDrop
|
|
3982
|
+
}) {
|
|
3983
|
+
const drag = useDragReorder({
|
|
3984
|
+
resolveTarget: (clientX, clientY, movedId) => resolveColumnDropTarget(clientX, clientY, movedId, {
|
|
3985
|
+
order,
|
|
3986
|
+
groupBy,
|
|
3987
|
+
groupByDraggableIds
|
|
3988
|
+
}),
|
|
3989
|
+
onDrop
|
|
3990
|
+
});
|
|
3991
|
+
function startDrag(entry, event) {
|
|
3992
|
+
drag.startDrag(entry.id, event.currentTarget, event);
|
|
3993
|
+
}
|
|
3994
|
+
function moveByKeyboard(entry, direction) {
|
|
3995
|
+
const beforeId = resolveKeyboardDropTarget2(order, entry.id, direction);
|
|
3996
|
+
if (beforeId === void 0) {
|
|
3997
|
+
return;
|
|
3998
|
+
}
|
|
3999
|
+
onDrop({ kind: "column-order", beforeId }, entry.id);
|
|
4000
|
+
}
|
|
4001
|
+
return {
|
|
4002
|
+
draggedColumnId: drag.draggedId,
|
|
4003
|
+
dropTarget: drag.dropTarget,
|
|
4004
|
+
ghostTransform: drag.ghostTransform,
|
|
4005
|
+
startDrag,
|
|
4006
|
+
moveByKeyboard,
|
|
4007
|
+
justDragged: drag.justDragged
|
|
4008
|
+
};
|
|
4009
|
+
}
|
|
4010
|
+
|
|
4011
|
+
// src/DataGrid/useColumnResize.ts
|
|
4012
|
+
import {
|
|
4013
|
+
useState as useState16
|
|
4014
|
+
} from "react";
|
|
4015
|
+
import {
|
|
4016
|
+
beginColumnResize,
|
|
4017
|
+
clampColumnWidth,
|
|
4018
|
+
resolveColumnConstraints,
|
|
4019
|
+
sizeColumnToContent
|
|
4020
|
+
} from "@gridkitjs/core";
|
|
4021
|
+
import { measureColumnContent, startColumnResizeGesture } from "@gridkitjs/dom";
|
|
4022
|
+
function useColumnResize({
|
|
4023
|
+
tableRef,
|
|
4024
|
+
controller,
|
|
4025
|
+
columnSizeDefaults
|
|
4026
|
+
}) {
|
|
4027
|
+
const [activeColumnId, setActiveColumnId] = useState16(null);
|
|
4028
|
+
function startResize(entry, event) {
|
|
4029
|
+
event.stopPropagation();
|
|
4030
|
+
const session = beginColumnResize(
|
|
4031
|
+
entry.column,
|
|
4032
|
+
entry.width,
|
|
4033
|
+
event.clientX,
|
|
4034
|
+
columnSizeDefaults
|
|
4035
|
+
);
|
|
4036
|
+
const base = controller.getState().columnSizing;
|
|
4037
|
+
const started = startColumnResizeGesture(
|
|
4038
|
+
event.currentTarget,
|
|
4039
|
+
event,
|
|
4040
|
+
session,
|
|
4041
|
+
{
|
|
4042
|
+
onMove(width) {
|
|
4043
|
+
controller.resizeColumn(session.columnId, width, "move");
|
|
4044
|
+
},
|
|
4045
|
+
onEnd(width) {
|
|
4046
|
+
setActiveColumnId(null);
|
|
4047
|
+
if (width !== null) {
|
|
4048
|
+
controller.resizeColumn(session.columnId, width, "end");
|
|
4049
|
+
}
|
|
4050
|
+
},
|
|
4051
|
+
/**
|
|
4052
|
+
* Escape puts back only the dragged column's pre-drag width, merged
|
|
4053
|
+
* into whatever the sizing state is *now* — not the `base` snapshot
|
|
4054
|
+
* taken at drag-start — so a different column resized via keyboard
|
|
4055
|
+
* while this drag was still open keeps its change instead of being
|
|
4056
|
+
* clobbered by a stale restore.
|
|
4057
|
+
*/
|
|
4058
|
+
onCancel() {
|
|
4059
|
+
setActiveColumnId(null);
|
|
4060
|
+
controller.cancelColumnResize(
|
|
4061
|
+
session.columnId,
|
|
4062
|
+
base,
|
|
4063
|
+
session.startWidth
|
|
4064
|
+
);
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
);
|
|
4068
|
+
if (started) {
|
|
4069
|
+
setActiveColumnId(session.columnId);
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
function sizeToContent(entry) {
|
|
4073
|
+
const table = tableRef.current;
|
|
4074
|
+
if (table === null) {
|
|
4075
|
+
return false;
|
|
4076
|
+
}
|
|
4077
|
+
const measured = measureColumnContent(table, entry.id);
|
|
4078
|
+
if (measured === null) {
|
|
4079
|
+
return false;
|
|
4080
|
+
}
|
|
4081
|
+
controller.resizeColumn(
|
|
4082
|
+
entry.id,
|
|
4083
|
+
sizeColumnToContent(
|
|
4084
|
+
measured,
|
|
4085
|
+
resolveColumnConstraints(entry.column, columnSizeDefaults)
|
|
4086
|
+
),
|
|
4087
|
+
"end"
|
|
4088
|
+
);
|
|
4089
|
+
return true;
|
|
4090
|
+
}
|
|
4091
|
+
function nudge(entry, delta) {
|
|
4092
|
+
controller.resizeColumn(
|
|
4093
|
+
entry.id,
|
|
4094
|
+
clampColumnWidth(
|
|
4095
|
+
entry.width + delta,
|
|
4096
|
+
resolveColumnConstraints(entry.column, columnSizeDefaults)
|
|
4097
|
+
),
|
|
4098
|
+
"end"
|
|
4099
|
+
);
|
|
4100
|
+
}
|
|
4101
|
+
return { activeColumnId, startResize, sizeToContent, nudge };
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
// src/DataGrid/useElementWidth.ts
|
|
4105
|
+
import { useLayoutEffect as useLayoutEffect14, useState as useState17 } from "react";
|
|
4106
|
+
import { observeElementWidth } from "@gridkitjs/dom";
|
|
4107
|
+
function useElementWidth(ref, enabled) {
|
|
4108
|
+
const [width, setWidth] = useState17(null);
|
|
4109
|
+
useLayoutEffect14(() => {
|
|
4110
|
+
const element = ref.current;
|
|
4111
|
+
if (element === null || !enabled) {
|
|
4112
|
+
return void 0;
|
|
4113
|
+
}
|
|
4114
|
+
return observeElementWidth(element, setWidth);
|
|
4115
|
+
}, [ref, enabled]);
|
|
4116
|
+
return width;
|
|
4117
|
+
}
|
|
4118
|
+
|
|
4119
|
+
// src/DataGrid/useGridController.ts
|
|
4120
|
+
import { useState as useState18, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
4121
|
+
import {
|
|
4122
|
+
createGridController
|
|
4123
|
+
} from "@gridkitjs/core";
|
|
4124
|
+
function useGridController(options) {
|
|
4125
|
+
const [controller] = useState18(
|
|
4126
|
+
() => createGridController(options)
|
|
4127
|
+
);
|
|
4128
|
+
controller.setOptions(options);
|
|
4129
|
+
const state = useSyncExternalStore2(
|
|
4130
|
+
controller.subscribe,
|
|
4131
|
+
controller.getState,
|
|
4132
|
+
controller.getState
|
|
4133
|
+
);
|
|
4134
|
+
return { controller, state, view: controller.getView() };
|
|
4135
|
+
}
|
|
4136
|
+
|
|
4137
|
+
// src/DataGrid/useInfiniteScroll.ts
|
|
4138
|
+
import { useEffect as useEffect6, useRef as useRef19 } from "react";
|
|
4139
|
+
import { attachInfiniteScroll } from "@gridkitjs/dom";
|
|
4140
|
+
function useInfiniteScroll({
|
|
4141
|
+
rootRef,
|
|
4142
|
+
sentinelRef,
|
|
4143
|
+
config
|
|
4144
|
+
}) {
|
|
4145
|
+
const scroll = useRef19(null);
|
|
4146
|
+
useEffect6(() => {
|
|
4147
|
+
const root = rootRef.current;
|
|
4148
|
+
if (root === null) {
|
|
4149
|
+
return void 0;
|
|
4150
|
+
}
|
|
4151
|
+
const attached = attachInfiniteScroll(root, {
|
|
4152
|
+
sentinel: null,
|
|
4153
|
+
hasMore: false
|
|
4154
|
+
});
|
|
4155
|
+
scroll.current = attached;
|
|
4156
|
+
return () => {
|
|
4157
|
+
attached.detach();
|
|
4158
|
+
scroll.current = null;
|
|
4159
|
+
};
|
|
4160
|
+
}, [rootRef]);
|
|
4161
|
+
useEffect6(() => {
|
|
4162
|
+
scroll.current?.update({
|
|
4163
|
+
sentinel: sentinelRef.current,
|
|
4164
|
+
hasMore: config?.hasMore ?? false,
|
|
4165
|
+
onLoadMore: config?.onLoadMore,
|
|
4166
|
+
isLoadingMore: config?.isLoadingMore,
|
|
4167
|
+
rootMargin: config?.rootMargin
|
|
4168
|
+
});
|
|
4169
|
+
});
|
|
4170
|
+
}
|
|
4171
|
+
|
|
4172
|
+
// src/DataGrid/useLiveAnnouncer.ts
|
|
4173
|
+
import { useCallback, useLayoutEffect as useLayoutEffect15, useRef as useRef20 } from "react";
|
|
4174
|
+
import { createLiveAnnouncer } from "@gridkitjs/dom";
|
|
4175
|
+
function useLiveAnnouncer(containerRef) {
|
|
4176
|
+
const announcer = useRef20(null);
|
|
4177
|
+
useLayoutEffect15(() => {
|
|
4178
|
+
const container = containerRef.current;
|
|
4179
|
+
if (container === null) {
|
|
4180
|
+
return void 0;
|
|
4181
|
+
}
|
|
4182
|
+
const created = createLiveAnnouncer(container);
|
|
4183
|
+
announcer.current = created;
|
|
4184
|
+
return () => {
|
|
4185
|
+
created.destroy();
|
|
4186
|
+
announcer.current = null;
|
|
4187
|
+
};
|
|
4188
|
+
}, [containerRef]);
|
|
4189
|
+
return useCallback((text) => {
|
|
4190
|
+
announcer.current?.announce(text);
|
|
4191
|
+
}, []);
|
|
4192
|
+
}
|
|
4193
|
+
|
|
4194
|
+
// src/DataGrid/useRowVirtualizer.ts
|
|
4195
|
+
import { useLayoutEffect as useLayoutEffect16, useState as useState19 } from "react";
|
|
4196
|
+
import { createRowVirtualizer as createRowVirtualizer2 } from "@gridkitjs/dom";
|
|
4197
|
+
var EMPTY_RANGE = {
|
|
4198
|
+
startIndex: 0,
|
|
4199
|
+
endIndex: -1,
|
|
4200
|
+
offsetBefore: 0,
|
|
4201
|
+
offsetAfter: 0
|
|
4202
|
+
};
|
|
4203
|
+
function ignoreRow() {
|
|
4204
|
+
return () => void 0;
|
|
4205
|
+
}
|
|
4206
|
+
function useRowVirtualizer({
|
|
4207
|
+
enabled,
|
|
4208
|
+
rows,
|
|
4209
|
+
bodyScrollRef,
|
|
4210
|
+
estimatedRowHeight,
|
|
4211
|
+
overscan
|
|
4212
|
+
}) {
|
|
4213
|
+
const [virtualizer, setVirtualizer] = useState19(null);
|
|
4214
|
+
const [range, setRange] = useState19(EMPTY_RANGE);
|
|
4215
|
+
useLayoutEffect16(() => {
|
|
4216
|
+
const element = bodyScrollRef.current;
|
|
4217
|
+
if (!enabled || element === null) {
|
|
4218
|
+
return void 0;
|
|
4219
|
+
}
|
|
4220
|
+
const created = createRowVirtualizer2(element, {
|
|
4221
|
+
estimatedRowHeight,
|
|
4222
|
+
overscan,
|
|
4223
|
+
onRange: setRange
|
|
4224
|
+
});
|
|
4225
|
+
setVirtualizer(created);
|
|
4226
|
+
return () => {
|
|
4227
|
+
created.destroy();
|
|
4228
|
+
};
|
|
4229
|
+
}, [enabled, bodyScrollRef, estimatedRowHeight, overscan]);
|
|
4230
|
+
useLayoutEffect16(() => {
|
|
4231
|
+
virtualizer?.setRowCount(rows.length);
|
|
4232
|
+
virtualizer?.resetHeights();
|
|
4233
|
+
}, [virtualizer, rows]);
|
|
4234
|
+
return {
|
|
4235
|
+
startIndex: range.startIndex,
|
|
4236
|
+
endIndex: range.endIndex,
|
|
4237
|
+
offsetBefore: range.offsetBefore,
|
|
4238
|
+
offsetAfter: range.offsetAfter,
|
|
4239
|
+
measureRow: virtualizer?.measureRow ?? ignoreRow,
|
|
4240
|
+
scrollToIndex: (index, options) => {
|
|
4241
|
+
virtualizer?.scrollToIndex(index, options);
|
|
4242
|
+
}
|
|
4243
|
+
};
|
|
4244
|
+
}
|
|
4245
|
+
|
|
4246
|
+
// src/DataGrid/DataGrid.tsx
|
|
4247
|
+
import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4248
|
+
var NO_AGGREGATES = [];
|
|
4249
|
+
function paginationReader(controller) {
|
|
4250
|
+
let last;
|
|
4251
|
+
return () => {
|
|
4252
|
+
const { pageIndex } = controller.getView();
|
|
4253
|
+
const { pageSize } = controller.getState().pagination;
|
|
4254
|
+
if (last?.pageIndex !== pageIndex || last.pageSize !== pageSize) {
|
|
4255
|
+
last = { pageIndex, pageSize };
|
|
4256
|
+
}
|
|
4257
|
+
return last;
|
|
4258
|
+
};
|
|
4259
|
+
}
|
|
4260
|
+
function selectedRowsReader(controller) {
|
|
4261
|
+
let last;
|
|
4262
|
+
return () => {
|
|
4263
|
+
const { rows } = controller.getView();
|
|
4264
|
+
const selection = controller.getState().rowSelection;
|
|
4265
|
+
if (last?.rows !== rows || last.selection !== selection) {
|
|
4266
|
+
const rowsById = new Map(rows.map((entry) => [entry.rowId, entry]));
|
|
4267
|
+
last = { rows, selection, selected: resolveRows(rowsById, selection) };
|
|
4268
|
+
}
|
|
4269
|
+
return last.selected;
|
|
4270
|
+
};
|
|
4271
|
+
}
|
|
4272
|
+
function DataGrid(props) {
|
|
4273
|
+
const {
|
|
4274
|
+
borders,
|
|
4275
|
+
hoverable,
|
|
4276
|
+
selectable,
|
|
4277
|
+
resizeMode = "fit",
|
|
4278
|
+
columnSizeDefaults,
|
|
4279
|
+
sortableColumns = false,
|
|
4280
|
+
groupableColumns = false,
|
|
4281
|
+
groupToggleIconColumns = true,
|
|
4282
|
+
groupByBarVisibility = "auto",
|
|
4283
|
+
paginated = false,
|
|
4284
|
+
pager,
|
|
4285
|
+
infiniteScroll,
|
|
4286
|
+
aggregates = NO_AGGREGATES,
|
|
4287
|
+
groupAggregateDisplay = "inline",
|
|
4288
|
+
height,
|
|
4289
|
+
virtualized = false,
|
|
4290
|
+
overscan = 4,
|
|
4291
|
+
estimatedRowHeight = 40,
|
|
4292
|
+
label,
|
|
4293
|
+
labelledBy,
|
|
4294
|
+
locale,
|
|
4295
|
+
getRowProps,
|
|
4296
|
+
onRowClick,
|
|
4297
|
+
onRowDoubleClick,
|
|
4298
|
+
messages: messageOverrides,
|
|
4299
|
+
ref
|
|
4300
|
+
} = props;
|
|
4301
|
+
const hoverRows = hoverable?.rows ?? true;
|
|
4302
|
+
const hoverColumns = hoverable?.columns ?? true;
|
|
4303
|
+
const hoverCells = hoverable?.cells ?? true;
|
|
4304
|
+
const viewportRef = useRef21(null);
|
|
4305
|
+
const headerTableRef = useRef21(null);
|
|
4306
|
+
const bodyTableRef = useRef21(null);
|
|
4307
|
+
const bodyScrollRef = useRef21(null);
|
|
4308
|
+
const sentinelRef = useRef21(null);
|
|
4309
|
+
const viewportWidth = useElementWidth(viewportRef, resizeMode === "fit");
|
|
4310
|
+
const subscribersRef = useRef21(/* @__PURE__ */ new Set());
|
|
4311
|
+
const gridId = useId2();
|
|
4312
|
+
const announce = useLiveAnnouncer(viewportRef);
|
|
4313
|
+
const messages = useMemo5(
|
|
4314
|
+
() => resolveMessages(messageOverrides, locale),
|
|
4315
|
+
[messageOverrides, locale]
|
|
4316
|
+
);
|
|
4317
|
+
const { controller, state, view } = useGridController({
|
|
4318
|
+
...props,
|
|
4319
|
+
viewportWidth,
|
|
4320
|
+
...announcedCallbacks({
|
|
4321
|
+
callbacks: props,
|
|
4322
|
+
announce,
|
|
4323
|
+
messages,
|
|
4324
|
+
columnName,
|
|
4325
|
+
columnOf
|
|
4326
|
+
})
|
|
4327
|
+
});
|
|
4328
|
+
const [readPagination] = useState20(() => paginationReader(controller));
|
|
4329
|
+
const [readSelectedRows] = useState20(() => selectedRowsReader(controller));
|
|
4330
|
+
const virtualizer = useRowVirtualizer({
|
|
4331
|
+
enabled: virtualized,
|
|
4332
|
+
rows: view.pageRows,
|
|
4333
|
+
bodyScrollRef,
|
|
4334
|
+
estimatedRowHeight,
|
|
4335
|
+
overscan
|
|
4336
|
+
});
|
|
4337
|
+
useEffect7(() => {
|
|
4338
|
+
if (virtualized && height === void 0) {
|
|
4339
|
+
console.error(
|
|
4340
|
+
"DataGrid: `virtualized` has no effect without `height` \u2014 a body with no bounded height has no viewport to window rows against."
|
|
4341
|
+
);
|
|
4342
|
+
}
|
|
4343
|
+
}, [virtualized, height]);
|
|
4344
|
+
const hasInfiniteScroll = infiniteScroll !== void 0;
|
|
4345
|
+
useEffect7(() => {
|
|
4346
|
+
if (paginated && hasInfiniteScroll) {
|
|
4347
|
+
console.error(
|
|
4348
|
+
"DataGrid: `paginated` and `infiniteScroll` are mutually exclusive \u2014 only `paginated` takes effect while both are set."
|
|
4349
|
+
);
|
|
4350
|
+
}
|
|
4351
|
+
}, [paginated, hasInfiniteScroll]);
|
|
4352
|
+
useInfiniteScroll({
|
|
4353
|
+
rootRef: bodyScrollRef,
|
|
4354
|
+
sentinelRef,
|
|
4355
|
+
config: infiniteScroll
|
|
4356
|
+
});
|
|
4357
|
+
function columnOf(columnId) {
|
|
4358
|
+
return view.dataColumns.find((candidate) => candidate.id === columnId)?.column;
|
|
4359
|
+
}
|
|
4360
|
+
function columnName(columnId) {
|
|
4361
|
+
const column = columnOf(columnId);
|
|
4362
|
+
return column === void 0 ? columnId : resolveColumnHeaderText2(column);
|
|
4363
|
+
}
|
|
4364
|
+
const resize = useColumnResize({
|
|
4365
|
+
// `@gridkitjs/dom`'s `measureColumnContent` only ever matches
|
|
4366
|
+
// `td[data-gridkit-column]` (never `th`), so the header table has nothing
|
|
4367
|
+
// for it to find — the body table alone was already the effective scope
|
|
4368
|
+
// before this split.
|
|
4369
|
+
tableRef: bodyTableRef,
|
|
4370
|
+
controller,
|
|
4371
|
+
columnSizeDefaults
|
|
4372
|
+
});
|
|
4373
|
+
const nav = useGridNavigation({
|
|
4374
|
+
headerTableRef,
|
|
4375
|
+
bodyTableRef,
|
|
4376
|
+
// `null` when virtualization is off, in which case behavior is
|
|
4377
|
+
// byte-for-byte unchanged from before this feature existed.
|
|
4378
|
+
virtualRange: virtualized ? virtualizer : null,
|
|
4379
|
+
// Group headers are addressable rows too — the whole point of the flat
|
|
4380
|
+
// `DisplayRow[]` shape is that they share one position space with data
|
|
4381
|
+
// rows, so navigation counts them the same way. Page-relative
|
|
4382
|
+
// (`view.pageRows`, not `view.displayRows`): arrow keys operate on what's
|
|
4383
|
+
// actually in the DOM, which is the current page — a different "page"
|
|
4384
|
+
// concept than `useGridNavigation`'s own Page Up/Down viewport scrolling.
|
|
4385
|
+
rowCount: view.pageRows.length,
|
|
4386
|
+
columnCount: view.columns.length,
|
|
4387
|
+
// A group's own summary row (`groupAggregateDisplay: "row"`) occupies a
|
|
4388
|
+
// real slot in `rowCount` above — its DOM position has to line up with
|
|
4389
|
+
// everything else — but is presentational, never a tab stop: arrow-key
|
|
4390
|
+
// vertical movement steps over it rather than landing there.
|
|
4391
|
+
isSkippableRow: (rowIndex) => {
|
|
4392
|
+
const entry = view.pageRows[rowIndex];
|
|
4393
|
+
return entry !== void 0 && "kind" in entry && entry.kind === "group-summary";
|
|
4394
|
+
}
|
|
4395
|
+
});
|
|
4396
|
+
const panels = useGridPanels({ rootRef: viewportRef, headerTableRef, nav });
|
|
4397
|
+
const commands = useGridCommands({
|
|
4398
|
+
controller,
|
|
4399
|
+
commands: props.commands,
|
|
4400
|
+
onCommand: props.onCommand,
|
|
4401
|
+
messages,
|
|
4402
|
+
announce,
|
|
4403
|
+
resize,
|
|
4404
|
+
openPanel: panels.open
|
|
4405
|
+
});
|
|
4406
|
+
const handleCopyKey = useGridCopy({ controller, commands, nav });
|
|
4407
|
+
const orderedIds = useMemo5(
|
|
4408
|
+
() => view.dataColumns.map((entry) => entry.id),
|
|
4409
|
+
[view.dataColumns]
|
|
4410
|
+
);
|
|
4411
|
+
const displayedIds = useMemo5(
|
|
4412
|
+
() => view.columns.map((entry) => entry.id),
|
|
4413
|
+
[view.columns]
|
|
4414
|
+
);
|
|
4415
|
+
const definitions = useMemo5(
|
|
4416
|
+
() => new Map(view.dataColumns.map((entry) => [entry.id, entry.column])),
|
|
4417
|
+
[view.dataColumns]
|
|
4418
|
+
);
|
|
4419
|
+
const groupByDraggableIds = useMemo5(
|
|
4420
|
+
() => new Set(
|
|
4421
|
+
view.columns.filter((entry) => entry.groupByDraggable).map((entry) => entry.id)
|
|
4422
|
+
),
|
|
4423
|
+
[view.columns]
|
|
4424
|
+
);
|
|
4425
|
+
function handleDrop(target, movedId) {
|
|
4426
|
+
if (target.kind === "group-by") {
|
|
4427
|
+
controller.moveGroupBy(movedId, target.beforeColumnId);
|
|
4428
|
+
return;
|
|
4429
|
+
}
|
|
4430
|
+
const next = moveColumnBefore(orderedIds, movedId, target.beforeId);
|
|
4431
|
+
if (next === orderedIds) {
|
|
4432
|
+
return;
|
|
4433
|
+
}
|
|
4434
|
+
controller.moveColumn(movedId, target.beforeId);
|
|
4435
|
+
const shown = next.filter((id) => displayedIds.includes(id));
|
|
4436
|
+
const position = shown.indexOf(movedId);
|
|
4437
|
+
announce(
|
|
4438
|
+
messages.columnMoved(columnName(movedId), position + 1, shown.length)
|
|
4439
|
+
);
|
|
4440
|
+
nav.focusCell(HEADER_ROW, position);
|
|
4441
|
+
}
|
|
4442
|
+
const drag = useColumnDrag({
|
|
4443
|
+
order: displayedIds,
|
|
4444
|
+
groupBy: state.groupBy,
|
|
4445
|
+
groupByDraggableIds,
|
|
4446
|
+
onDrop: handleDrop
|
|
4447
|
+
});
|
|
4448
|
+
const draggedColumnAlreadyGrouped = drag.draggedColumnId !== null && state.groupBy.some((entry) => entry.columnId === drag.draggedColumnId);
|
|
4449
|
+
const dragEligibleForGroupBy = drag.draggedColumnId !== null && groupByDraggableIds.has(drag.draggedColumnId) && !draggedColumnAlreadyGrouped;
|
|
4450
|
+
const showGroupByBar = groupByBarVisibility === "always" || groupByBarVisibility === "auto" && (state.groupBy.length > 0 || dragEligibleForGroupBy);
|
|
4451
|
+
const headerGroupByDropTarget = drag.dropTarget?.kind === "group-by" ? drag.dropTarget : null;
|
|
4452
|
+
const pagerContext = {
|
|
4453
|
+
pagination: state.pagination,
|
|
4454
|
+
currentPage: Math.min(state.pagination.pageIndex + 1, view.pageCount),
|
|
4455
|
+
pageCount: view.pageCount,
|
|
4456
|
+
pageSizeOptions: pager?.sizeOptions,
|
|
4457
|
+
goToPage: controller.goToPage,
|
|
4458
|
+
nextPage: controller.nextPage,
|
|
4459
|
+
previousPage: controller.previousPage,
|
|
4460
|
+
setPageSize: controller.setPageSize
|
|
4461
|
+
};
|
|
4462
|
+
const selection = useGridSelection({ controller, state, selectable });
|
|
4463
|
+
const multiselectable = selection.rowMode === "multiple" || selection.columnMode === "multiple";
|
|
4464
|
+
const contextMenu = useContextMenu({
|
|
4465
|
+
rootRef: viewportRef,
|
|
4466
|
+
headerTableRef,
|
|
4467
|
+
bodyTableRef,
|
|
4468
|
+
bodyScrollRef,
|
|
4469
|
+
contextMenu: props.contextMenu,
|
|
4470
|
+
onContextMenuOpenChange: props.onContextMenuOpenChange,
|
|
4471
|
+
controller,
|
|
4472
|
+
commands,
|
|
4473
|
+
nav,
|
|
4474
|
+
selection,
|
|
4475
|
+
messages,
|
|
4476
|
+
columnName
|
|
4477
|
+
});
|
|
4478
|
+
useEffect7(() => {
|
|
4479
|
+
for (const listener of subscribersRef.current) {
|
|
4480
|
+
listener();
|
|
4481
|
+
}
|
|
4482
|
+
}, [view, state, nav.focus]);
|
|
4483
|
+
useImperativeHandle3(ref, () => ({
|
|
4484
|
+
get element() {
|
|
4485
|
+
return viewportRef.current;
|
|
4486
|
+
},
|
|
4487
|
+
get table() {
|
|
4488
|
+
return bodyTableRef.current;
|
|
4489
|
+
},
|
|
4490
|
+
getRows: () => controller.getView().rows,
|
|
4491
|
+
// Every group header's own `aggregates` field is populated here — the
|
|
4492
|
+
// whole reason `getDisplayRows()` is where a consumer reads a specific
|
|
4493
|
+
// group's computed results from.
|
|
4494
|
+
getDisplayRows: () => controller.getView().displayRows,
|
|
4495
|
+
getPageRows: () => controller.getView().pageRows,
|
|
4496
|
+
getColumns: () => controller.getView().columns,
|
|
4497
|
+
getDataColumns: () => controller.getView().dataColumns,
|
|
4498
|
+
getColumnSizing: () => controller.getState().columnSizing,
|
|
4499
|
+
getColumnOrder: () => controller.getState().columnOrder,
|
|
4500
|
+
getColumnVisibility: () => controller.getState().columnVisibility,
|
|
4501
|
+
getColumnSort: () => controller.getState().columnSort,
|
|
4502
|
+
getFilter: () => controller.getState().filter,
|
|
4503
|
+
getGroupBy: () => controller.getState().groupBy,
|
|
4504
|
+
getGroupExpansion: () => controller.getState().groupExpansion,
|
|
4505
|
+
getPagination: readPagination,
|
|
4506
|
+
getPageCount: () => controller.getView().pageCount,
|
|
4507
|
+
getAggregates: () => controller.getView().grandTotal,
|
|
4508
|
+
getRowSelection: () => controller.getState().rowSelection,
|
|
4509
|
+
getSelectedRows: readSelectedRows,
|
|
4510
|
+
getColumnSelection: () => controller.getState().columnSelection,
|
|
4511
|
+
getCellSelection: () => controller.getState().cellSelection,
|
|
4512
|
+
getFocusedCell: () => nav.focus,
|
|
4513
|
+
getState: controller.getState,
|
|
4514
|
+
restoreState: controller.restoreState,
|
|
4515
|
+
focusCell: nav.focusCell,
|
|
4516
|
+
clearSelection: controller.clearSelection,
|
|
4517
|
+
selectAllRows: controller.selectAllRows,
|
|
4518
|
+
selectRows: controller.selectRows,
|
|
4519
|
+
expandAllGroups: controller.expandAllGroups,
|
|
4520
|
+
collapseAllGroups: controller.collapseAllGroups,
|
|
4521
|
+
goToPage: controller.goToPage,
|
|
4522
|
+
nextPage: controller.nextPage,
|
|
4523
|
+
previousPage: controller.previousPage,
|
|
4524
|
+
setPageSize: controller.setPageSize,
|
|
4525
|
+
showColumns: controller.showColumns,
|
|
4526
|
+
hideColumns: controller.hideColumns,
|
|
4527
|
+
setFilter: controller.setFilter,
|
|
4528
|
+
setColumnSort: controller.setColumnSort,
|
|
4529
|
+
setGroupBy: controller.setGroupBy,
|
|
4530
|
+
setGroupExpansion: controller.setGroupExpansion,
|
|
4531
|
+
setPagination: controller.setPagination,
|
|
4532
|
+
setColumnSizing: controller.setColumnSizing,
|
|
4533
|
+
setColumnOrder: controller.setColumnOrder,
|
|
4534
|
+
setColumnVisibility: controller.setColumnVisibility,
|
|
4535
|
+
setRowSelection: controller.setRowSelection,
|
|
4536
|
+
setColumnSelection: controller.setColumnSelection,
|
|
4537
|
+
setCellSelection: controller.setCellSelection,
|
|
4538
|
+
autoFitColumn: (columnId) => {
|
|
4539
|
+
commands.host.autoFitColumns([columnId]);
|
|
4540
|
+
},
|
|
4541
|
+
autoFitColumns: (columnIds) => {
|
|
4542
|
+
commands.host.autoFitColumns(
|
|
4543
|
+
columnIds ?? controller.getView().columns.map((entry) => entry.id)
|
|
4544
|
+
);
|
|
4545
|
+
},
|
|
4546
|
+
openContextMenu: contextMenu.open,
|
|
4547
|
+
closeContextMenu: contextMenu.close,
|
|
4548
|
+
...exportApi(commands),
|
|
4549
|
+
...printApi(commands),
|
|
4550
|
+
...panelApi(panels, controller),
|
|
4551
|
+
runCommand: (commandId, target = { area: "grid" }) => commands.run(commandId, target, "api"),
|
|
4552
|
+
scrollToRow: (rowId, options) => {
|
|
4553
|
+
const index = controller.getView().pageRows.findIndex(
|
|
4554
|
+
(entry) => !("kind" in entry) && entry.rowId === rowId
|
|
4555
|
+
);
|
|
4556
|
+
if (index === -1) return;
|
|
4557
|
+
if (virtualized) {
|
|
4558
|
+
virtualizer.scrollToIndex(index, options);
|
|
4559
|
+
return;
|
|
4560
|
+
}
|
|
4561
|
+
bodyTableRef.current?.tBodies[0]?.rows[index]?.scrollIntoView(options);
|
|
4562
|
+
},
|
|
4563
|
+
scrollToColumn: (columnId, options) => {
|
|
4564
|
+
const cells = viewportRef.current?.querySelectorAll(
|
|
4565
|
+
"[data-gridkit-column]"
|
|
4566
|
+
);
|
|
4567
|
+
const cell = cells ? Array.from(cells).find(
|
|
4568
|
+
(entry) => entry.getAttribute("data-gridkit-column") === columnId
|
|
4569
|
+
) : void 0;
|
|
4570
|
+
cell?.scrollIntoView(options);
|
|
4571
|
+
},
|
|
4572
|
+
subscribe: (listener) => {
|
|
4573
|
+
subscribersRef.current.add(listener);
|
|
4574
|
+
return () => {
|
|
4575
|
+
subscribersRef.current.delete(listener);
|
|
4576
|
+
};
|
|
4577
|
+
}
|
|
4578
|
+
}));
|
|
4579
|
+
const gridTableClassName = classNames(
|
|
4580
|
+
"gridkit-data-grid",
|
|
4581
|
+
borders ? `borders-${borders}` : "",
|
|
4582
|
+
// Hover is on by default and selection off, so one set of classes
|
|
4583
|
+
// turns styling off and the other turns it on. The polarity differs
|
|
4584
|
+
// because the defaults do.
|
|
4585
|
+
hoverRows ? "" : "no-hover-rows",
|
|
4586
|
+
hoverColumns ? "" : "no-hover-columns",
|
|
4587
|
+
hoverCells ? "" : "no-hover-cells",
|
|
4588
|
+
selection.rowMode === false ? "" : "selectable-rows",
|
|
4589
|
+
selection.columnMode === false ? "" : "selectable-columns",
|
|
4590
|
+
selection.cellMode === false ? "" : "selectable-cells"
|
|
4591
|
+
);
|
|
4592
|
+
const hasFooter = aggregates.length > 0;
|
|
4593
|
+
return /* @__PURE__ */ jsxs19("div", { className: "gridkit-data-grid-viewport", ref: viewportRef, children: [
|
|
4594
|
+
/* @__PURE__ */ jsx26(
|
|
4595
|
+
GridToolbar,
|
|
4596
|
+
{
|
|
4597
|
+
toolbar: props.toolbar,
|
|
4598
|
+
renderItem: props.renderToolbarItem,
|
|
4599
|
+
gridId,
|
|
4600
|
+
controller,
|
|
4601
|
+
commands,
|
|
4602
|
+
messages,
|
|
4603
|
+
announce
|
|
4604
|
+
}
|
|
4605
|
+
),
|
|
4606
|
+
showGroupByBar && /* @__PURE__ */ jsx26(
|
|
4607
|
+
GroupByBar,
|
|
4608
|
+
{
|
|
4609
|
+
columns: view.columns,
|
|
4610
|
+
definitions,
|
|
4611
|
+
groupBy: state.groupBy,
|
|
4612
|
+
controller,
|
|
4613
|
+
columnName,
|
|
4614
|
+
headerDragEligible: dragEligibleForGroupBy,
|
|
4615
|
+
headerDragBlocked: draggedColumnAlreadyGrouped,
|
|
4616
|
+
headerDropTarget: headerGroupByDropTarget,
|
|
4617
|
+
messages
|
|
4618
|
+
}
|
|
4619
|
+
),
|
|
4620
|
+
/* @__PURE__ */ jsxs19(
|
|
4621
|
+
"div",
|
|
4622
|
+
{
|
|
4623
|
+
id: gridId,
|
|
4624
|
+
className: "gridkit-data-grid-tables",
|
|
4625
|
+
role: state.groupBy.length > 0 ? "treegrid" : "grid",
|
|
4626
|
+
"aria-rowcount": view.displayRows.length + (hasFooter ? 2 : 1),
|
|
4627
|
+
"aria-colcount": view.columns.length,
|
|
4628
|
+
...ariaAttr(multiselectable, "aria-multiselectable", true),
|
|
4629
|
+
...ariaAttr(labelledBy !== void 0, "aria-labelledby", labelledBy),
|
|
4630
|
+
...ariaAttr(
|
|
4631
|
+
labelledBy === void 0 && label !== void 0,
|
|
4632
|
+
"aria-label",
|
|
4633
|
+
label
|
|
4634
|
+
),
|
|
4635
|
+
onKeyDown: (event) => {
|
|
4636
|
+
if (!isOwnEvent(event)) return;
|
|
4637
|
+
handleCopyKey(event);
|
|
4638
|
+
if (event.key === "Escape") {
|
|
4639
|
+
if (drag.draggedColumnId !== null || resize.activeColumnId !== null)
|
|
4640
|
+
return;
|
|
4641
|
+
selection.clear();
|
|
4642
|
+
return;
|
|
4643
|
+
}
|
|
4644
|
+
if ((event.ctrlKey || event.metaKey) && (event.key === "a" || event.key === "A")) {
|
|
4645
|
+
if (selection.rowMode !== "multiple") return;
|
|
4646
|
+
event.preventDefault();
|
|
4647
|
+
selection.selectAllRows();
|
|
4648
|
+
}
|
|
4649
|
+
},
|
|
4650
|
+
children: [
|
|
4651
|
+
/* @__PURE__ */ jsxs19(
|
|
4652
|
+
"table",
|
|
4653
|
+
{
|
|
4654
|
+
ref: headerTableRef,
|
|
4655
|
+
role: "presentation",
|
|
4656
|
+
style: { width: totalColumnWidth(view.columns) },
|
|
4657
|
+
className: classNames(gridTableClassName, "gridkit-data-grid-header"),
|
|
4658
|
+
children: [
|
|
4659
|
+
/* @__PURE__ */ jsx26(GridColgroup, { columns: view.columns }),
|
|
4660
|
+
/* @__PURE__ */ jsx26(
|
|
4661
|
+
GridHeader,
|
|
4662
|
+
{
|
|
4663
|
+
columns: view.columns,
|
|
4664
|
+
resize,
|
|
4665
|
+
drag,
|
|
4666
|
+
controller,
|
|
4667
|
+
state,
|
|
4668
|
+
sortableColumns,
|
|
4669
|
+
groupableColumns,
|
|
4670
|
+
groupToggleIconColumns,
|
|
4671
|
+
headerMenu: contextMenu.opens("header"),
|
|
4672
|
+
panels,
|
|
4673
|
+
messages,
|
|
4674
|
+
nav,
|
|
4675
|
+
selection
|
|
4676
|
+
}
|
|
4677
|
+
)
|
|
4678
|
+
]
|
|
4679
|
+
}
|
|
4680
|
+
),
|
|
4681
|
+
/* @__PURE__ */ jsx26(
|
|
4682
|
+
"div",
|
|
4683
|
+
{
|
|
4684
|
+
className: "gridkit-data-grid-body",
|
|
4685
|
+
ref: bodyScrollRef,
|
|
4686
|
+
style: height === void 0 ? void 0 : {
|
|
4687
|
+
"--gridkit-body-height": typeof height === "number" ? `${String(height)}px` : height
|
|
4688
|
+
},
|
|
4689
|
+
children: /* @__PURE__ */ jsxs19(
|
|
4690
|
+
"table",
|
|
4691
|
+
{
|
|
4692
|
+
ref: bodyTableRef,
|
|
4693
|
+
role: "presentation",
|
|
4694
|
+
style: { width: totalColumnWidth(view.columns) },
|
|
4695
|
+
className: gridTableClassName,
|
|
4696
|
+
children: [
|
|
4697
|
+
/* @__PURE__ */ jsx26(GridColgroup, { columns: view.columns }),
|
|
4698
|
+
/* @__PURE__ */ jsx26(
|
|
4699
|
+
GridBody,
|
|
4700
|
+
{
|
|
4701
|
+
columns: view.columns,
|
|
4702
|
+
definitions,
|
|
4703
|
+
rows: view.pageRows,
|
|
4704
|
+
activeColumnId: resize.activeColumnId,
|
|
4705
|
+
nav,
|
|
4706
|
+
selection,
|
|
4707
|
+
controller,
|
|
4708
|
+
aggregates,
|
|
4709
|
+
groupAggregateDisplay,
|
|
4710
|
+
virtualRange: virtualized ? virtualizer : null,
|
|
4711
|
+
infiniteScroll,
|
|
4712
|
+
sentinelRef,
|
|
4713
|
+
locale,
|
|
4714
|
+
getRowProps,
|
|
4715
|
+
onRowClick,
|
|
4716
|
+
onRowDoubleClick,
|
|
4717
|
+
messages,
|
|
4718
|
+
cellMenu: contextMenu.opens("cell"),
|
|
4719
|
+
groupMenu: contextMenu.opens("group")
|
|
4720
|
+
}
|
|
4721
|
+
)
|
|
4722
|
+
]
|
|
4723
|
+
}
|
|
4724
|
+
)
|
|
4725
|
+
}
|
|
4726
|
+
),
|
|
4727
|
+
hasFooter && /* @__PURE__ */ jsxs19(
|
|
4728
|
+
"table",
|
|
4729
|
+
{
|
|
4730
|
+
role: "presentation",
|
|
4731
|
+
style: { width: totalColumnWidth(view.columns) },
|
|
4732
|
+
className: classNames(
|
|
4733
|
+
gridTableClassName,
|
|
4734
|
+
"gridkit-data-grid-footer"
|
|
4735
|
+
),
|
|
4736
|
+
children: [
|
|
4737
|
+
/* @__PURE__ */ jsx26(GridColgroup, { columns: view.columns }),
|
|
4738
|
+
/* @__PURE__ */ jsx26(
|
|
4739
|
+
GridFooter,
|
|
4740
|
+
{
|
|
4741
|
+
columns: view.columns,
|
|
4742
|
+
aggregates,
|
|
4743
|
+
results: view.grandTotal,
|
|
4744
|
+
rows: view.rows.map((entry) => entry.row),
|
|
4745
|
+
locale,
|
|
4746
|
+
ariaRowIndex: view.displayRows.length + 2
|
|
4747
|
+
}
|
|
4748
|
+
)
|
|
4749
|
+
]
|
|
4750
|
+
}
|
|
4751
|
+
)
|
|
4752
|
+
]
|
|
4753
|
+
}
|
|
4754
|
+
),
|
|
4755
|
+
/* @__PURE__ */ jsx26(GridContextMenu, { contextMenu }),
|
|
4756
|
+
/* @__PURE__ */ jsx26(
|
|
4757
|
+
GridPanels,
|
|
4758
|
+
{
|
|
4759
|
+
panels,
|
|
4760
|
+
controller,
|
|
4761
|
+
commands,
|
|
4762
|
+
messages
|
|
4763
|
+
}
|
|
4764
|
+
),
|
|
4765
|
+
paginated && (pager?.template ? pager.template(pagerContext) : /* @__PURE__ */ jsx26(GridPager, { pager: pagerContext, config: pager, messages }))
|
|
4766
|
+
] });
|
|
4767
|
+
}
|
|
4768
|
+
|
|
4769
|
+
// src/index.ts
|
|
4770
|
+
import { serializeGridState } from "@gridkitjs/core";
|
|
4771
|
+
|
|
4772
|
+
// src/DataGrid/hooks/usePaginationState.ts
|
|
4773
|
+
import { useCallback as useCallback3 } from "react";
|
|
4774
|
+
|
|
4775
|
+
// src/DataGrid/hooks/useGridSnapshot.ts
|
|
4776
|
+
import { useCallback as useCallback2, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
4777
|
+
function useGridSnapshot(gridRef, getSnapshot, fallback) {
|
|
4778
|
+
const subscribe = useCallback2(
|
|
4779
|
+
(listener) => {
|
|
4780
|
+
const api = gridRef.current;
|
|
4781
|
+
if (api === null) {
|
|
4782
|
+
return () => {
|
|
4783
|
+
};
|
|
4784
|
+
}
|
|
4785
|
+
return api.subscribe(listener);
|
|
4786
|
+
},
|
|
4787
|
+
[gridRef]
|
|
4788
|
+
);
|
|
4789
|
+
return useSyncExternalStore3(
|
|
4790
|
+
subscribe,
|
|
4791
|
+
() => {
|
|
4792
|
+
const api = gridRef.current;
|
|
4793
|
+
return api === null ? fallback : getSnapshot(api);
|
|
4794
|
+
},
|
|
4795
|
+
() => fallback
|
|
4796
|
+
);
|
|
4797
|
+
}
|
|
4798
|
+
|
|
4799
|
+
// src/DataGrid/hooks/usePaginationState.ts
|
|
4800
|
+
var FALLBACK_PAGINATION = { pageIndex: 0, pageSize: 0 };
|
|
4801
|
+
function usePaginationState(gridRef) {
|
|
4802
|
+
const pagination = useGridSnapshot(
|
|
4803
|
+
gridRef,
|
|
4804
|
+
useCallback3((api) => api.getPagination(), []),
|
|
4805
|
+
FALLBACK_PAGINATION
|
|
4806
|
+
);
|
|
4807
|
+
const pageCount = useGridSnapshot(
|
|
4808
|
+
gridRef,
|
|
4809
|
+
useCallback3((api) => api.getPageCount(), []),
|
|
4810
|
+
0
|
|
4811
|
+
);
|
|
4812
|
+
return {
|
|
4813
|
+
pagination,
|
|
4814
|
+
pageCount,
|
|
4815
|
+
goToPage: (pageIndex) => {
|
|
4816
|
+
gridRef.current?.goToPage(pageIndex);
|
|
4817
|
+
},
|
|
4818
|
+
nextPage: () => {
|
|
4819
|
+
gridRef.current?.nextPage();
|
|
4820
|
+
},
|
|
4821
|
+
previousPage: () => {
|
|
4822
|
+
gridRef.current?.previousPage();
|
|
4823
|
+
},
|
|
4824
|
+
setPageSize: (pageSize) => {
|
|
4825
|
+
gridRef.current?.setPageSize(pageSize);
|
|
4826
|
+
}
|
|
4827
|
+
};
|
|
4828
|
+
}
|
|
4829
|
+
|
|
4830
|
+
// src/DataGrid/hooks/useGroupByState.ts
|
|
4831
|
+
import { useCallback as useCallback4 } from "react";
|
|
4832
|
+
var FALLBACK_GROUP_BY = [];
|
|
4833
|
+
var FALLBACK_EXPANSION = [];
|
|
4834
|
+
function useGroupByState(gridRef) {
|
|
4835
|
+
const groupBy = useGridSnapshot(
|
|
4836
|
+
gridRef,
|
|
4837
|
+
useCallback4((api) => api.getGroupBy(), []),
|
|
4838
|
+
FALLBACK_GROUP_BY
|
|
4839
|
+
);
|
|
4840
|
+
const groupExpansion = useGridSnapshot(
|
|
4841
|
+
gridRef,
|
|
4842
|
+
useCallback4((api) => api.getGroupExpansion(), []),
|
|
4843
|
+
FALLBACK_EXPANSION
|
|
4844
|
+
);
|
|
4845
|
+
return {
|
|
4846
|
+
groupBy,
|
|
4847
|
+
groupExpansion,
|
|
4848
|
+
expandAllGroups: () => {
|
|
4849
|
+
gridRef.current?.expandAllGroups();
|
|
4850
|
+
},
|
|
4851
|
+
collapseAllGroups: () => {
|
|
4852
|
+
gridRef.current?.collapseAllGroups();
|
|
4853
|
+
}
|
|
4854
|
+
};
|
|
4855
|
+
}
|
|
4856
|
+
|
|
4857
|
+
// src/DataGrid/hooks/useColumnSortState.ts
|
|
4858
|
+
import { useCallback as useCallback5 } from "react";
|
|
4859
|
+
var FALLBACK_SORT = [];
|
|
4860
|
+
function useColumnSortState(gridRef) {
|
|
4861
|
+
return useGridSnapshot(
|
|
4862
|
+
gridRef,
|
|
4863
|
+
useCallback5((api) => api.getColumnSort(), []),
|
|
4864
|
+
FALLBACK_SORT
|
|
4865
|
+
);
|
|
4866
|
+
}
|
|
4867
|
+
|
|
4868
|
+
// src/DataGrid/hooks/useSelectionState.ts
|
|
4869
|
+
import { useCallback as useCallback6 } from "react";
|
|
4870
|
+
var FALLBACK_SELECTION = [];
|
|
4871
|
+
var FALLBACK_CELL_SELECTION = null;
|
|
4872
|
+
function useSelectionState(gridRef) {
|
|
4873
|
+
const rowSelection = useGridSnapshot(
|
|
4874
|
+
gridRef,
|
|
4875
|
+
useCallback6((api) => api.getRowSelection(), []),
|
|
4876
|
+
FALLBACK_SELECTION
|
|
4877
|
+
);
|
|
4878
|
+
const columnSelection = useGridSnapshot(
|
|
4879
|
+
gridRef,
|
|
4880
|
+
useCallback6((api) => api.getColumnSelection(), []),
|
|
4881
|
+
FALLBACK_SELECTION
|
|
4882
|
+
);
|
|
4883
|
+
const cellSelection = useGridSnapshot(
|
|
4884
|
+
gridRef,
|
|
4885
|
+
useCallback6((api) => api.getCellSelection(), []),
|
|
4886
|
+
FALLBACK_CELL_SELECTION
|
|
4887
|
+
);
|
|
4888
|
+
return {
|
|
4889
|
+
rowSelection,
|
|
4890
|
+
columnSelection,
|
|
4891
|
+
cellSelection,
|
|
4892
|
+
clearSelection: () => {
|
|
4893
|
+
gridRef.current?.clearSelection();
|
|
4894
|
+
},
|
|
4895
|
+
selectAllRows: () => {
|
|
4896
|
+
gridRef.current?.selectAllRows();
|
|
4897
|
+
}
|
|
4898
|
+
};
|
|
4899
|
+
}
|
|
4900
|
+
|
|
4901
|
+
// src/DataGrid/hooks/useAggregateState.ts
|
|
4902
|
+
import { useCallback as useCallback7 } from "react";
|
|
4903
|
+
var FALLBACK_AGGREGATES = /* @__PURE__ */ new Map();
|
|
4904
|
+
function useAggregateState(gridRef) {
|
|
4905
|
+
return useGridSnapshot(
|
|
4906
|
+
gridRef,
|
|
4907
|
+
useCallback7((api) => api.getAggregates(), []),
|
|
4908
|
+
FALLBACK_AGGREGATES
|
|
4909
|
+
);
|
|
4910
|
+
}
|
|
4911
|
+
|
|
4912
|
+
// src/DataGrid/hooks/useColumnSizingState.ts
|
|
4913
|
+
import { useCallback as useCallback8 } from "react";
|
|
4914
|
+
var FALLBACK_SIZING = {};
|
|
4915
|
+
function useColumnSizingState(gridRef) {
|
|
4916
|
+
return useGridSnapshot(
|
|
4917
|
+
gridRef,
|
|
4918
|
+
useCallback8((api) => api.getColumnSizing(), []),
|
|
4919
|
+
FALLBACK_SIZING
|
|
4920
|
+
);
|
|
4921
|
+
}
|
|
4922
|
+
|
|
4923
|
+
// src/DataGrid/hooks/useColumnOrderState.ts
|
|
4924
|
+
import { useCallback as useCallback9 } from "react";
|
|
4925
|
+
var FALLBACK_ORDER = [];
|
|
4926
|
+
function useColumnOrderState(gridRef) {
|
|
4927
|
+
return useGridSnapshot(
|
|
4928
|
+
gridRef,
|
|
4929
|
+
useCallback9((api) => api.getColumnOrder(), []),
|
|
4930
|
+
FALLBACK_ORDER
|
|
4931
|
+
);
|
|
4932
|
+
}
|
|
4933
|
+
|
|
4934
|
+
// src/DataGrid/hooks/useColumnVisibilityState.ts
|
|
4935
|
+
import { useCallback as useCallback10 } from "react";
|
|
4936
|
+
var FALLBACK_VISIBILITY = {};
|
|
4937
|
+
function useColumnVisibilityState(gridRef) {
|
|
4938
|
+
return useGridSnapshot(
|
|
4939
|
+
gridRef,
|
|
4940
|
+
useCallback10((api) => api.getColumnVisibility(), []),
|
|
4941
|
+
FALLBACK_VISIBILITY
|
|
4942
|
+
);
|
|
4943
|
+
}
|
|
4944
|
+
|
|
4945
|
+
// src/DataGrid/hooks/useFilterState.ts
|
|
4946
|
+
import { useCallback as useCallback11, useState as useState21 } from "react";
|
|
4947
|
+
function useFilterState(gridRef) {
|
|
4948
|
+
const [fallback] = useState21(() => []);
|
|
4949
|
+
const filter = useGridSnapshot(
|
|
4950
|
+
gridRef,
|
|
4951
|
+
useCallback11((api) => api.getFilter(), []),
|
|
4952
|
+
fallback
|
|
4953
|
+
);
|
|
4954
|
+
return {
|
|
4955
|
+
filter,
|
|
4956
|
+
setFilter: (next) => {
|
|
4957
|
+
gridRef.current?.setFilter(next);
|
|
4958
|
+
}
|
|
4959
|
+
};
|
|
4960
|
+
}
|
|
4961
|
+
|
|
4962
|
+
// src/index.ts
|
|
4963
|
+
import { excelFilter } from "@gridkitjs/core";
|
|
4964
|
+
export {
|
|
4965
|
+
DataGrid,
|
|
4966
|
+
excelFilter,
|
|
4967
|
+
serializeGridState,
|
|
4968
|
+
useAggregateState,
|
|
4969
|
+
useColumnOrderState,
|
|
4970
|
+
useColumnSizingState,
|
|
4971
|
+
useColumnSortState,
|
|
4972
|
+
useColumnVisibilityState,
|
|
4973
|
+
useFilterState,
|
|
4974
|
+
useGroupByState,
|
|
4975
|
+
usePaginationState,
|
|
4976
|
+
useSelectionState
|
|
4977
|
+
};
|
|
4978
|
+
//# sourceMappingURL=index.js.map
|