@gridkitjs/react 0.11.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +48 -8
- package/dist/index.js +1508 -292
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
// src/DataGrid/DataGrid.tsx
|
|
4
4
|
import {
|
|
5
|
-
useEffect as
|
|
6
|
-
useId,
|
|
7
|
-
useImperativeHandle,
|
|
8
|
-
useMemo as
|
|
9
|
-
useRef as
|
|
10
|
-
useState as
|
|
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
11
|
} from "react";
|
|
12
12
|
import {
|
|
13
13
|
moveColumnBefore,
|
|
14
|
-
resolveColumnHeaderText,
|
|
14
|
+
resolveColumnHeaderText as resolveColumnHeaderText2,
|
|
15
15
|
resolveMessages,
|
|
16
16
|
resolveRows,
|
|
17
17
|
totalColumnWidth
|
|
@@ -28,7 +28,9 @@ import { createPortal } from "react-dom";
|
|
|
28
28
|
import {
|
|
29
29
|
buildKeyShortcuts,
|
|
30
30
|
intentOf,
|
|
31
|
+
isColumnFiltered,
|
|
31
32
|
KEYBOARD_STEP,
|
|
33
|
+
resolveColumnFilterMenu,
|
|
32
34
|
sortDirectionFor,
|
|
33
35
|
sortPriorityFor
|
|
34
36
|
} from "@gridkitjs/core";
|
|
@@ -76,6 +78,27 @@ function GroupIcon() {
|
|
|
76
78
|
/* @__PURE__ */ jsx2("rect", { x: "8.5", y: "14", width: "7", height: "7", rx: "1" })
|
|
77
79
|
] });
|
|
78
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
|
+
}
|
|
79
102
|
|
|
80
103
|
// src/DataGrid/isOwnEvent.ts
|
|
81
104
|
function isOwnEvent(event) {
|
|
@@ -114,7 +137,11 @@ function useGridNavigation({
|
|
|
114
137
|
};
|
|
115
138
|
const [gridFocus] = useState(() => createGridFocus(options));
|
|
116
139
|
gridFocus.setOptions(options);
|
|
117
|
-
const focus = useSyncExternalStore(
|
|
140
|
+
const focus = useSyncExternalStore(
|
|
141
|
+
gridFocus.subscribe,
|
|
142
|
+
gridFocus.getFocus,
|
|
143
|
+
gridFocus.getFocus
|
|
144
|
+
);
|
|
118
145
|
const [rows] = useState(() => ({
|
|
119
146
|
getHeaderRow: () => headerTableRef.current?.tHead?.rows[0] ?? null,
|
|
120
147
|
getBodyRow: (rowIndex) => findBodyRow(bodyTableRef.current, rowIndex)
|
|
@@ -195,18 +222,28 @@ function GridHeader({
|
|
|
195
222
|
resize,
|
|
196
223
|
drag,
|
|
197
224
|
controller,
|
|
198
|
-
|
|
225
|
+
state,
|
|
199
226
|
sortableColumns,
|
|
200
|
-
groupBy,
|
|
201
227
|
groupableColumns,
|
|
202
228
|
groupToggleIconColumns,
|
|
203
229
|
headerMenu,
|
|
230
|
+
panels,
|
|
231
|
+
messages,
|
|
204
232
|
nav,
|
|
205
233
|
selection
|
|
206
234
|
}) {
|
|
235
|
+
const { columnSort, groupBy, filter } = state;
|
|
207
236
|
const beforeId = drag.dropTarget?.kind === "column-order" ? drag.dropTarget.beforeId : void 0;
|
|
208
237
|
const draggedEntry = columns.find((entry) => entry.id === drag.draggedColumnId) ?? null;
|
|
209
|
-
|
|
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: [
|
|
210
247
|
/* @__PURE__ */ jsx3("tr", { className: "grid-header", role: "row", "aria-rowindex": 1, children: columns.map((entry, index) => {
|
|
211
248
|
const { column } = entry;
|
|
212
249
|
const resizing = resize.activeColumnId === entry.id;
|
|
@@ -222,11 +259,14 @@ function GridHeader({
|
|
|
222
259
|
const isGrouped = groupBy.some(
|
|
223
260
|
(level) => level.columnId === entry.id
|
|
224
261
|
);
|
|
262
|
+
const filterable = resolveColumnFilterMenu(controller.getOptions(), column) !== null;
|
|
263
|
+
const filtered = filterable && isColumnFiltered(filter, entry.id);
|
|
225
264
|
const shortcuts = buildKeyShortcuts({
|
|
226
265
|
reorderable: entry.reorderable,
|
|
227
266
|
resizable: entry.resizable,
|
|
228
267
|
sortable,
|
|
229
268
|
groupable,
|
|
269
|
+
filterable,
|
|
230
270
|
contextMenu: headerMenu
|
|
231
271
|
});
|
|
232
272
|
return /* @__PURE__ */ jsxs2(
|
|
@@ -249,7 +289,7 @@ function GridHeader({
|
|
|
249
289
|
if (drag.justDragged()) {
|
|
250
290
|
return;
|
|
251
291
|
}
|
|
252
|
-
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)) {
|
|
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)) {
|
|
253
293
|
return;
|
|
254
294
|
}
|
|
255
295
|
selection.selectColumn(entry.id, intentOf(event));
|
|
@@ -280,7 +320,12 @@ function GridHeader({
|
|
|
280
320
|
});
|
|
281
321
|
return;
|
|
282
322
|
}
|
|
283
|
-
if (event.key === "ArrowDown" && event.altKey &&
|
|
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) {
|
|
284
329
|
event.preventDefault();
|
|
285
330
|
controller.toggleGroupBy(entry.id);
|
|
286
331
|
return;
|
|
@@ -311,6 +356,11 @@ function GridHeader({
|
|
|
311
356
|
column.headerClassName ?? ""
|
|
312
357
|
),
|
|
313
358
|
...ariaAttr(shortcuts !== "", "aria-keyshortcuts", shortcuts),
|
|
359
|
+
...ariaAttr(
|
|
360
|
+
filtered,
|
|
361
|
+
"aria-description",
|
|
362
|
+
messages.columnFiltered
|
|
363
|
+
),
|
|
314
364
|
...ariaAttr(
|
|
315
365
|
sortable && sortDirection !== null,
|
|
316
366
|
"aria-sort",
|
|
@@ -380,6 +430,30 @@ function GridHeader({
|
|
|
380
430
|
]
|
|
381
431
|
}
|
|
382
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
|
+
),
|
|
383
457
|
entry.resizable && /*
|
|
384
458
|
* A pointer affordance only, and hidden from assistive
|
|
385
459
|
* technology accordingly: a focusable handle per column would
|
|
@@ -472,7 +546,7 @@ function createRowPropsResolver() {
|
|
|
472
546
|
// src/DataGrid/components/GridGroupRow.tsx
|
|
473
547
|
import { memo } from "react";
|
|
474
548
|
import {
|
|
475
|
-
|
|
549
|
+
formatGroupValue,
|
|
476
550
|
resolveColumnLabel
|
|
477
551
|
} from "@gridkitjs/core";
|
|
478
552
|
|
|
@@ -492,9 +566,6 @@ function renderAggregate(value, spec, column, rows, locale) {
|
|
|
492
566
|
|
|
493
567
|
// src/DataGrid/components/GridGroupRow.tsx
|
|
494
568
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
495
|
-
function formatGroupValue(value, column, locale, messages) {
|
|
496
|
-
return value === null || value === void 0 ? messages.blankGroupValue : formatCellValue(value, column, locale, void 0, messages);
|
|
497
|
-
}
|
|
498
569
|
function GridGroupRowComponent({
|
|
499
570
|
columnCount,
|
|
500
571
|
groupId,
|
|
@@ -671,7 +742,7 @@ var GridGroupSummaryRow_default = GridGroupSummaryRow;
|
|
|
671
742
|
// src/DataGrid/components/GridRow.tsx
|
|
672
743
|
import {
|
|
673
744
|
accessDotted,
|
|
674
|
-
formatCellValue
|
|
745
|
+
formatCellValue
|
|
675
746
|
} from "@gridkitjs/core";
|
|
676
747
|
import { memo as memo3 } from "react";
|
|
677
748
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
@@ -741,7 +812,7 @@ function GridRowComponent({
|
|
|
741
812
|
datasetIndex,
|
|
742
813
|
rowId,
|
|
743
814
|
selected
|
|
744
|
-
}) :
|
|
815
|
+
}) : formatCellValue(value, column, locale, row, cellMessages)
|
|
745
816
|
},
|
|
746
817
|
id
|
|
747
818
|
);
|
|
@@ -855,6 +926,7 @@ function GridBody({
|
|
|
855
926
|
return /* @__PURE__ */ jsxs5(
|
|
856
927
|
"tbody",
|
|
857
928
|
{
|
|
929
|
+
role: "rowgroup",
|
|
858
930
|
className: "grid-body",
|
|
859
931
|
onFocus: (event) => {
|
|
860
932
|
const group = groupRowFrom(event.target);
|
|
@@ -1040,7 +1112,7 @@ function GridFooter({
|
|
|
1040
1112
|
rows,
|
|
1041
1113
|
locale
|
|
1042
1114
|
}) {
|
|
1043
|
-
return /* @__PURE__ */ jsx8("tfoot", { children: /* @__PURE__ */ jsx8("tr", { className: "grid-footer", role: "row", children: columns.map((entry) => {
|
|
1115
|
+
return /* @__PURE__ */ jsx8("tfoot", { role: "rowgroup", children: /* @__PURE__ */ jsx8("tr", { className: "grid-footer", role: "row", children: columns.map((entry) => {
|
|
1044
1116
|
const specs = aggregates.filter(
|
|
1045
1117
|
(candidate) => candidate.columnId === entry.id
|
|
1046
1118
|
);
|
|
@@ -1071,10 +1143,35 @@ function GridFooter({
|
|
|
1071
1143
|
// src/DataGrid/components/GridPager.tsx
|
|
1072
1144
|
import { paginationWindow } from "@gridkitjs/core";
|
|
1073
1145
|
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1146
|
+
function PagerNavButton({
|
|
1147
|
+
className,
|
|
1148
|
+
label,
|
|
1149
|
+
disabled,
|
|
1150
|
+
onClick,
|
|
1151
|
+
children
|
|
1152
|
+
}) {
|
|
1153
|
+
return /* @__PURE__ */ jsx9(
|
|
1154
|
+
"button",
|
|
1155
|
+
{
|
|
1156
|
+
type: "button",
|
|
1157
|
+
className: `grid-pager-button grid-pager-nav ${className}`,
|
|
1158
|
+
"aria-label": label,
|
|
1159
|
+
title: label,
|
|
1160
|
+
disabled,
|
|
1161
|
+
onClick,
|
|
1162
|
+
children
|
|
1163
|
+
}
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1074
1166
|
function GridPager({ pager, config, messages }) {
|
|
1075
1167
|
const { pagination, pageCount, currentPage } = pager;
|
|
1076
1168
|
const variant = config?.variant ?? "compact";
|
|
1077
1169
|
const sizeOptions = config?.sizeOptions;
|
|
1170
|
+
const atFirst = pagination.pageIndex <= 0;
|
|
1171
|
+
const atLast = pagination.pageIndex >= pageCount - 1;
|
|
1172
|
+
const barStyle = {
|
|
1173
|
+
"--gridkit-pager-digits": String(String(Math.max(1, pageCount)).length)
|
|
1174
|
+
};
|
|
1078
1175
|
return /* @__PURE__ */ jsxs6(
|
|
1079
1176
|
"div",
|
|
1080
1177
|
{
|
|
@@ -1082,59 +1179,90 @@ function GridPager({ pager, config, messages }) {
|
|
|
1082
1179
|
role: "group",
|
|
1083
1180
|
"aria-label": messages.pagerLabel,
|
|
1084
1181
|
children: [
|
|
1085
|
-
/* @__PURE__ */
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
type: "button",
|
|
1089
|
-
className: "grid-pager-button",
|
|
1090
|
-
disabled: pagination.pageIndex <= 0,
|
|
1091
|
-
onClick: () => {
|
|
1092
|
-
pager.previousPage();
|
|
1093
|
-
},
|
|
1094
|
-
children: messages.previousPage
|
|
1095
|
-
}
|
|
1096
|
-
),
|
|
1097
|
-
variant === "numbered" ? paginationWindow(currentPage, pageCount, {
|
|
1098
|
-
boundaryCount: config?.boundaryCount,
|
|
1099
|
-
siblingCount: config?.siblingCount
|
|
1100
|
-
}).map(
|
|
1101
|
-
(entry, index) => entry === "ellipsis" ? /* @__PURE__ */ jsx9(
|
|
1102
|
-
"span",
|
|
1182
|
+
/* @__PURE__ */ jsxs6("div", { className: "grid-pager-bar", style: barStyle, children: [
|
|
1183
|
+
/* @__PURE__ */ jsx9(
|
|
1184
|
+
PagerNavButton,
|
|
1103
1185
|
{
|
|
1104
|
-
className: "grid-pager-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1186
|
+
className: "grid-pager-first",
|
|
1187
|
+
label: messages.firstPage,
|
|
1188
|
+
disabled: atFirst,
|
|
1189
|
+
onClick: () => {
|
|
1190
|
+
pager.goToPage(0);
|
|
1191
|
+
},
|
|
1192
|
+
children: /* @__PURE__ */ jsx9(ChevronsLeftIcon, {})
|
|
1193
|
+
}
|
|
1194
|
+
),
|
|
1195
|
+
/* @__PURE__ */ jsx9(
|
|
1196
|
+
PagerNavButton,
|
|
1111
1197
|
{
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
"aria-current": entry === currentPage ? "page" : void 0,
|
|
1198
|
+
className: "grid-pager-previous",
|
|
1199
|
+
label: messages.previousPage,
|
|
1200
|
+
disabled: atFirst,
|
|
1116
1201
|
onClick: () => {
|
|
1117
|
-
pager.
|
|
1202
|
+
pager.previousPage();
|
|
1118
1203
|
},
|
|
1119
|
-
children:
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1204
|
+
children: /* @__PURE__ */ jsx9(ChevronLeftIcon, {})
|
|
1205
|
+
}
|
|
1206
|
+
),
|
|
1207
|
+
variant === "numbered" ? paginationWindow(currentPage, pageCount, {
|
|
1208
|
+
boundaryCount: config?.boundaryCount,
|
|
1209
|
+
siblingCount: config?.siblingCount
|
|
1210
|
+
}).map(
|
|
1211
|
+
(entry, index) => entry === "ellipsis" ? /* @__PURE__ */ jsx9(
|
|
1212
|
+
"span",
|
|
1213
|
+
{
|
|
1214
|
+
className: "grid-pager-ellipsis",
|
|
1215
|
+
"aria-hidden": "true",
|
|
1216
|
+
children: "\u2026"
|
|
1217
|
+
},
|
|
1218
|
+
`ellipsis-${String(index)}`
|
|
1219
|
+
) : /* @__PURE__ */ jsx9(
|
|
1220
|
+
"button",
|
|
1221
|
+
{
|
|
1222
|
+
type: "button",
|
|
1223
|
+
className: "grid-pager-button grid-pager-page",
|
|
1224
|
+
"aria-label": messages.pageButtonLabel(entry),
|
|
1225
|
+
"aria-current": entry === currentPage ? "page" : void 0,
|
|
1226
|
+
onClick: () => {
|
|
1227
|
+
pager.goToPage(entry - 1);
|
|
1228
|
+
},
|
|
1229
|
+
children: entry
|
|
1230
|
+
},
|
|
1231
|
+
entry
|
|
1232
|
+
)
|
|
1233
|
+
) : /* @__PURE__ */ jsxs6("span", { className: "grid-pager-status-slot", children: [
|
|
1234
|
+
/* @__PURE__ */ jsx9("span", { className: "grid-pager-status", children: messages.pageStatus(
|
|
1235
|
+
pageCount === 0 ? 0 : currentPage,
|
|
1236
|
+
pageCount
|
|
1237
|
+
) }),
|
|
1238
|
+
/* @__PURE__ */ jsx9("span", { className: "grid-pager-status-sizer", "aria-hidden": "true", children: messages.pageStatus(pageCount, pageCount) })
|
|
1239
|
+
] }),
|
|
1240
|
+
/* @__PURE__ */ jsx9(
|
|
1241
|
+
PagerNavButton,
|
|
1242
|
+
{
|
|
1243
|
+
className: "grid-pager-next",
|
|
1244
|
+
label: messages.nextPage,
|
|
1245
|
+
disabled: atLast,
|
|
1246
|
+
onClick: () => {
|
|
1247
|
+
pager.nextPage();
|
|
1248
|
+
},
|
|
1249
|
+
children: /* @__PURE__ */ jsx9(ChevronRightIcon, {})
|
|
1250
|
+
}
|
|
1251
|
+
),
|
|
1252
|
+
/* @__PURE__ */ jsx9(
|
|
1253
|
+
PagerNavButton,
|
|
1254
|
+
{
|
|
1255
|
+
className: "grid-pager-last",
|
|
1256
|
+
label: messages.lastPage,
|
|
1257
|
+
disabled: atLast,
|
|
1258
|
+
onClick: () => {
|
|
1259
|
+
pager.goToPage(pageCount - 1);
|
|
1260
|
+
},
|
|
1261
|
+
children: /* @__PURE__ */ jsx9(ChevronsRightIcon, {})
|
|
1262
|
+
}
|
|
1122
1263
|
)
|
|
1123
|
-
|
|
1124
|
-
/* @__PURE__ */ jsx9(
|
|
1125
|
-
"button",
|
|
1126
|
-
{
|
|
1127
|
-
type: "button",
|
|
1128
|
-
className: "grid-pager-button",
|
|
1129
|
-
disabled: pagination.pageIndex >= pageCount - 1,
|
|
1130
|
-
onClick: () => {
|
|
1131
|
-
pager.nextPage();
|
|
1132
|
-
},
|
|
1133
|
-
children: messages.nextPage
|
|
1134
|
-
}
|
|
1135
|
-
),
|
|
1264
|
+
] }),
|
|
1136
1265
|
sizeOptions !== void 0 && sizeOptions.length > 0 && /* @__PURE__ */ jsxs6("label", { className: "grid-pager-page-size", children: [
|
|
1137
|
-
messages.pageSizeLabel,
|
|
1138
1266
|
/* @__PURE__ */ jsx9(
|
|
1139
1267
|
"select",
|
|
1140
1268
|
{
|
|
@@ -1144,7 +1272,8 @@ function GridPager({ pager, config, messages }) {
|
|
|
1144
1272
|
},
|
|
1145
1273
|
children: sizeOptions.map((size) => /* @__PURE__ */ jsx9("option", { value: size, children: size }, size))
|
|
1146
1274
|
}
|
|
1147
|
-
)
|
|
1275
|
+
),
|
|
1276
|
+
/* @__PURE__ */ jsx9("span", { className: "grid-pager-page-size-label", children: messages.pageSizeLabel })
|
|
1148
1277
|
] })
|
|
1149
1278
|
]
|
|
1150
1279
|
}
|
|
@@ -1498,13 +1627,155 @@ function announcedCallbacks({
|
|
|
1498
1627
|
};
|
|
1499
1628
|
}
|
|
1500
1629
|
|
|
1630
|
+
// src/DataGrid/clipboard/useGridCopy.ts
|
|
1631
|
+
import { runCommand } from "@gridkitjs/core";
|
|
1632
|
+
import { isNativeCopy } from "@gridkitjs/dom";
|
|
1633
|
+
function isCopyKey(event) {
|
|
1634
|
+
return (event.ctrlKey || event.metaKey) && !event.altKey && (event.key === "c" || event.key === "C");
|
|
1635
|
+
}
|
|
1636
|
+
function useGridCopy({
|
|
1637
|
+
controller,
|
|
1638
|
+
commands,
|
|
1639
|
+
nav
|
|
1640
|
+
}) {
|
|
1641
|
+
function run(commandId, target) {
|
|
1642
|
+
const command = commands.commands.get(commandId);
|
|
1643
|
+
return command !== void 0 && runCommand(command, commands.contextFor(target));
|
|
1644
|
+
}
|
|
1645
|
+
function focusedCell() {
|
|
1646
|
+
const { rowIndex, columnIndex } = nav.focus;
|
|
1647
|
+
if (rowIndex === HEADER_ROW) {
|
|
1648
|
+
return null;
|
|
1649
|
+
}
|
|
1650
|
+
const { pageRows, columns } = controller.getView();
|
|
1651
|
+
const entry = pageRows[rowIndex];
|
|
1652
|
+
const column = columns[columnIndex];
|
|
1653
|
+
return entry === void 0 || "kind" in entry || column === void 0 ? null : { area: "cell", rowId: entry.rowId, columnId: column.id };
|
|
1654
|
+
}
|
|
1655
|
+
return (event) => {
|
|
1656
|
+
if (!isCopyKey(event) || isNativeCopy(event.target)) {
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
const cell = focusedCell();
|
|
1660
|
+
if (run("copy.selection", { area: "grid" }) || cell !== null && run("copy.cell", cell)) {
|
|
1661
|
+
event.preventDefault();
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1501
1666
|
// src/DataGrid/commands/useGridCommands.ts
|
|
1502
1667
|
import { useMemo as useMemo3 } from "react";
|
|
1503
1668
|
import {
|
|
1504
1669
|
createCommandContext,
|
|
1505
1670
|
resolveCommands,
|
|
1506
|
-
runCommand
|
|
1671
|
+
runCommand as runCommand2
|
|
1672
|
+
} from "@gridkitjs/core";
|
|
1673
|
+
|
|
1674
|
+
// src/DataGrid/clipboard/copyToClipboard.ts
|
|
1675
|
+
import { writeClipboard } from "@gridkitjs/dom";
|
|
1676
|
+
function copyToClipboard(content, { messages, announce }) {
|
|
1677
|
+
writeClipboard(content).then(
|
|
1678
|
+
() => {
|
|
1679
|
+
announce(messages.copied(content.count, content.unit));
|
|
1680
|
+
},
|
|
1681
|
+
(error) => {
|
|
1682
|
+
console.error("DataGrid: the clipboard could not be written.", error);
|
|
1683
|
+
announce(messages.copyFailed);
|
|
1684
|
+
}
|
|
1685
|
+
);
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
// src/DataGrid/export/useSaveFile.ts
|
|
1689
|
+
import { useRef as useRef2 } from "react";
|
|
1690
|
+
import { downloadBlob } from "@gridkitjs/dom";
|
|
1691
|
+
|
|
1692
|
+
// src/DataGrid/export/exportApi.ts
|
|
1693
|
+
import {
|
|
1694
|
+
exportFile,
|
|
1695
|
+
resolveExportWriters
|
|
1696
|
+
} from "@gridkitjs/core";
|
|
1697
|
+
function exportBlob({ content, mimeType }) {
|
|
1698
|
+
const part = typeof content === "string" ? content : content.slice();
|
|
1699
|
+
return new Blob([part], { type: mimeType });
|
|
1700
|
+
}
|
|
1701
|
+
function exportApi({
|
|
1702
|
+
contextFor
|
|
1703
|
+
}) {
|
|
1704
|
+
return {
|
|
1705
|
+
exportData: async (format, options) => {
|
|
1706
|
+
const context = contextFor({ area: "grid" });
|
|
1707
|
+
const { export: defaults, exportWriters } = context.options;
|
|
1708
|
+
const file = exportFile(
|
|
1709
|
+
context,
|
|
1710
|
+
format,
|
|
1711
|
+
{ ...defaults, ...options },
|
|
1712
|
+
resolveExportWriters(exportWriters)
|
|
1713
|
+
);
|
|
1714
|
+
if (file === null) {
|
|
1715
|
+
throw new Error(
|
|
1716
|
+
"DataGrid: there is no export writer for that format \u2014 register one through `exportWriters`."
|
|
1717
|
+
);
|
|
1718
|
+
}
|
|
1719
|
+
return exportBlob(await file);
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
// src/DataGrid/export/useSaveFile.ts
|
|
1725
|
+
function download(file) {
|
|
1726
|
+
downloadBlob(exportBlob(file), file.fileName);
|
|
1727
|
+
}
|
|
1728
|
+
function useSaveFile({
|
|
1729
|
+
messages,
|
|
1730
|
+
announce
|
|
1731
|
+
}) {
|
|
1732
|
+
const writingRef = useRef2(false);
|
|
1733
|
+
return (file) => {
|
|
1734
|
+
if (writingRef.current) {
|
|
1735
|
+
console.error(
|
|
1736
|
+
"DataGrid: an export is still being written, so this one was dropped."
|
|
1737
|
+
);
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
if (!(file instanceof Promise)) {
|
|
1741
|
+
download(file);
|
|
1742
|
+
return;
|
|
1743
|
+
}
|
|
1744
|
+
writingRef.current = true;
|
|
1745
|
+
file.then(download, (error) => {
|
|
1746
|
+
console.error("DataGrid: the export's writer failed.", error);
|
|
1747
|
+
announce(messages.exportFailed);
|
|
1748
|
+
}).finally(() => {
|
|
1749
|
+
writingRef.current = false;
|
|
1750
|
+
});
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
// src/DataGrid/print/printApi.ts
|
|
1755
|
+
import {
|
|
1756
|
+
exportPrintDocument
|
|
1507
1757
|
} from "@gridkitjs/core";
|
|
1758
|
+
import { printDocument, printStyles } from "@gridkitjs/dom";
|
|
1759
|
+
function printGrid(document2, { styles = "" }) {
|
|
1760
|
+
return printDocument({
|
|
1761
|
+
title: document2.title,
|
|
1762
|
+
bodyHtml: document2.bodyHtml,
|
|
1763
|
+
styles: printStyles(document2.page) + styles
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
function printApi({
|
|
1767
|
+
contextFor
|
|
1768
|
+
}) {
|
|
1769
|
+
return {
|
|
1770
|
+
print: (options) => {
|
|
1771
|
+
const context = contextFor({ area: "grid" });
|
|
1772
|
+
const merged = { ...context.options.print, ...options };
|
|
1773
|
+
return printGrid(exportPrintDocument(context, merged), merged);
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
// src/DataGrid/commands/useGridCommands.ts
|
|
1508
1779
|
function useGridCommands({
|
|
1509
1780
|
controller,
|
|
1510
1781
|
commands: appCommands,
|
|
@@ -1515,6 +1786,7 @@ function useGridCommands({
|
|
|
1515
1786
|
openPanel
|
|
1516
1787
|
}) {
|
|
1517
1788
|
const commands = useMemo3(() => resolveCommands(appCommands), [appCommands]);
|
|
1789
|
+
const saveFile = useSaveFile({ messages, announce });
|
|
1518
1790
|
const host = {
|
|
1519
1791
|
autoFitColumns: (columnIds) => {
|
|
1520
1792
|
const { columns } = controller.getView();
|
|
@@ -1530,7 +1802,16 @@ function useGridCommands({
|
|
|
1530
1802
|
}
|
|
1531
1803
|
},
|
|
1532
1804
|
openPanel,
|
|
1533
|
-
announce
|
|
1805
|
+
announce,
|
|
1806
|
+
saveFile,
|
|
1807
|
+
writeClipboard: (content) => {
|
|
1808
|
+
copyToClipboard(content, { messages, announce });
|
|
1809
|
+
},
|
|
1810
|
+
print: (document2, options) => {
|
|
1811
|
+
printGrid(document2, options).catch((error) => {
|
|
1812
|
+
console.error("DataGrid: the print failed.", error);
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1534
1815
|
};
|
|
1535
1816
|
function contextFor(target) {
|
|
1536
1817
|
return createCommandContext({ controller, target, messages, host });
|
|
@@ -1549,7 +1830,7 @@ function useGridCommands({
|
|
|
1549
1830
|
console.error(`DataGrid: there is no command \`${commandId}\` to run.`);
|
|
1550
1831
|
return false;
|
|
1551
1832
|
}
|
|
1552
|
-
if (!
|
|
1833
|
+
if (!runCommand2(command, contextFor(target))) {
|
|
1553
1834
|
return false;
|
|
1554
1835
|
}
|
|
1555
1836
|
report(commandId, target, source);
|
|
@@ -1559,19 +1840,22 @@ function useGridCommands({
|
|
|
1559
1840
|
}
|
|
1560
1841
|
|
|
1561
1842
|
// src/DataGrid/menu/GridMenu.tsx
|
|
1562
|
-
import { useLayoutEffect as useLayoutEffect3, useRef as
|
|
1843
|
+
import { useLayoutEffect as useLayoutEffect3, useRef as useRef4, useState as useState4 } from "react";
|
|
1563
1844
|
import {
|
|
1564
1845
|
attachMenu
|
|
1565
1846
|
} from "@gridkitjs/dom";
|
|
1566
1847
|
|
|
1567
1848
|
// src/DataGrid/overlay/Overlay.tsx
|
|
1568
|
-
import { useLayoutEffect as useLayoutEffect2, useRef as
|
|
1849
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef3 } from "react";
|
|
1569
1850
|
import { createPortal as createPortal3 } from "react-dom";
|
|
1570
1851
|
import {
|
|
1571
1852
|
attachOverlay
|
|
1572
1853
|
} from "@gridkitjs/dom";
|
|
1573
1854
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1574
1855
|
var ANCHOR_GAP = 4;
|
|
1856
|
+
function attachedFocus(focus) {
|
|
1857
|
+
return typeof focus === "object" && !(focus instanceof HTMLElement) ? focus.current ?? "first" : focus;
|
|
1858
|
+
}
|
|
1575
1859
|
function overlayThemeClassName(element) {
|
|
1576
1860
|
const scope = element?.closest(".gridkit-light, .gridkit-dark");
|
|
1577
1861
|
if (scope === null || scope === void 0) {
|
|
@@ -1587,12 +1871,13 @@ function Overlay({
|
|
|
1587
1871
|
initialFocus,
|
|
1588
1872
|
returnFocusTo,
|
|
1589
1873
|
ignoreScrollAfterInput,
|
|
1874
|
+
trapFocus,
|
|
1590
1875
|
themeClassName,
|
|
1591
1876
|
onDismiss,
|
|
1592
1877
|
children
|
|
1593
1878
|
}) {
|
|
1594
|
-
const panelRef =
|
|
1595
|
-
const onDismissRef =
|
|
1879
|
+
const panelRef = useRef3(null);
|
|
1880
|
+
const onDismissRef = useRef3(onDismiss);
|
|
1596
1881
|
useLayoutEffect2(() => {
|
|
1597
1882
|
onDismissRef.current = onDismiss;
|
|
1598
1883
|
});
|
|
@@ -1605,9 +1890,10 @@ function Overlay({
|
|
|
1605
1890
|
placement,
|
|
1606
1891
|
gap,
|
|
1607
1892
|
offset,
|
|
1608
|
-
initialFocus,
|
|
1893
|
+
initialFocus: attachedFocus(initialFocus),
|
|
1609
1894
|
returnFocusTo,
|
|
1610
1895
|
ignoreScrollAfterInput,
|
|
1896
|
+
trapFocus,
|
|
1611
1897
|
onDismiss: (reason) => {
|
|
1612
1898
|
onDismissRef.current(reason);
|
|
1613
1899
|
}
|
|
@@ -1619,7 +1905,8 @@ function Overlay({
|
|
|
1619
1905
|
offset,
|
|
1620
1906
|
initialFocus,
|
|
1621
1907
|
returnFocusTo,
|
|
1622
|
-
ignoreScrollAfterInput
|
|
1908
|
+
ignoreScrollAfterInput,
|
|
1909
|
+
trapFocus
|
|
1623
1910
|
]);
|
|
1624
1911
|
return createPortal3(
|
|
1625
1912
|
/* @__PURE__ */ jsx11(
|
|
@@ -1662,6 +1949,15 @@ var BUILT_IN_ICONS = {
|
|
|
1662
1949
|
/* @__PURE__ */ jsx12("path", { d: "m18 8 4 4-4 4" }),
|
|
1663
1950
|
/* @__PURE__ */ jsx12("path", { d: "M2 12h20" }),
|
|
1664
1951
|
/* @__PURE__ */ jsx12("path", { d: "m6 8-4 4 4 4" })
|
|
1952
|
+
] }),
|
|
1953
|
+
copy: () => /* @__PURE__ */ jsxs8(Icon, { children: [
|
|
1954
|
+
/* @__PURE__ */ jsx12("rect", { x: "8", y: "8", width: "14", height: "14", rx: "2" }),
|
|
1955
|
+
/* @__PURE__ */ jsx12("path", { d: "M4 16a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2" })
|
|
1956
|
+
] }),
|
|
1957
|
+
print: () => /* @__PURE__ */ jsxs8(Icon, { children: [
|
|
1958
|
+
/* @__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" }),
|
|
1959
|
+
/* @__PURE__ */ jsx12("path", { d: "M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6" }),
|
|
1960
|
+
/* @__PURE__ */ jsx12("rect", { x: "6", y: "14", width: "12", height: "8", rx: "1" })
|
|
1665
1961
|
] })
|
|
1666
1962
|
};
|
|
1667
1963
|
var ICONS = new Map(Object.entries(BUILT_IN_ICONS));
|
|
@@ -1675,7 +1971,10 @@ function CheckIcon() {
|
|
|
1675
1971
|
function ChevronDownIcon() {
|
|
1676
1972
|
return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" }) });
|
|
1677
1973
|
}
|
|
1678
|
-
function
|
|
1974
|
+
function ChevronLeftIcon2() {
|
|
1975
|
+
return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "m15 18-6-6 6-6" }) });
|
|
1976
|
+
}
|
|
1977
|
+
function ChevronRightIcon2() {
|
|
1679
1978
|
return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "m9 18 6-6-6-6" }) });
|
|
1680
1979
|
}
|
|
1681
1980
|
|
|
@@ -1694,25 +1993,25 @@ function MenuItem({
|
|
|
1694
1993
|
entry,
|
|
1695
1994
|
expanded
|
|
1696
1995
|
}) {
|
|
1697
|
-
const
|
|
1698
|
-
const checked =
|
|
1699
|
-
const shortcut =
|
|
1996
|
+
const isItem2 = entry.type === "item";
|
|
1997
|
+
const checked = isItem2 ? entry.checked : void 0;
|
|
1998
|
+
const shortcut = isItem2 ? entry.shortcut : void 0;
|
|
1700
1999
|
return /* @__PURE__ */ jsxs9(
|
|
1701
2000
|
"div",
|
|
1702
2001
|
{
|
|
1703
2002
|
role: checked === void 0 ? "menuitem" : "menuitemcheckbox",
|
|
1704
2003
|
"data-gridkit-menu-item": entry.id,
|
|
1705
2004
|
className: "menu-item",
|
|
1706
|
-
...ariaAttr(
|
|
2005
|
+
...ariaAttr(isItem2 && entry.disabled, "aria-disabled", true),
|
|
1707
2006
|
...ariaAttr(checked !== void 0, "aria-checked", checked),
|
|
1708
2007
|
...ariaAttr(shortcut !== void 0, "aria-keyshortcuts", shortcut),
|
|
1709
|
-
...ariaAttr(!
|
|
1710
|
-
...ariaAttr(!
|
|
2008
|
+
...ariaAttr(!isItem2, "aria-haspopup", "menu"),
|
|
2009
|
+
...ariaAttr(!isItem2, "aria-expanded", expanded),
|
|
1711
2010
|
children: [
|
|
1712
2011
|
/* @__PURE__ */ jsx13("span", { className: "menu-item-icon", "aria-hidden": "true", children: checked === true ? /* @__PURE__ */ jsx13(CheckIcon, {}) : /* @__PURE__ */ jsx13(MenuIcon, { name: entry.icon }) }),
|
|
1713
2012
|
/* @__PURE__ */ jsx13("span", { className: "menu-item-label", children: entry.label }),
|
|
1714
2013
|
shortcut !== void 0 && /* @__PURE__ */ jsx13("span", { className: "menu-item-shortcut", "aria-hidden": "true", children: shortcut }),
|
|
1715
|
-
!
|
|
2014
|
+
!isItem2 && /* @__PURE__ */ jsx13("span", { className: "menu-submenu-indicator", "aria-hidden": "true", children: /* @__PURE__ */ jsx13(ChevronRightIcon2, {}) })
|
|
1716
2015
|
]
|
|
1717
2016
|
}
|
|
1718
2017
|
);
|
|
@@ -1726,11 +2025,11 @@ function GridMenu({
|
|
|
1726
2025
|
onCloseSubmenu,
|
|
1727
2026
|
behaviourRef
|
|
1728
2027
|
}) {
|
|
1729
|
-
const menuRef =
|
|
1730
|
-
const submenuBehaviourRef =
|
|
2028
|
+
const menuRef = useRef4(null);
|
|
2029
|
+
const submenuBehaviourRef = useRef4(null);
|
|
1731
2030
|
const [submenu, setSubmenu] = useState4(null);
|
|
1732
2031
|
const isSubmenu = onCloseSubmenu !== void 0;
|
|
1733
|
-
const latest =
|
|
2032
|
+
const latest = useRef4({ entries, submenu, onRun, onClose, onCloseSubmenu });
|
|
1734
2033
|
useLayoutEffect3(() => {
|
|
1735
2034
|
latest.current = { entries, submenu, onRun, onClose, onCloseSubmenu };
|
|
1736
2035
|
});
|
|
@@ -1869,7 +2168,7 @@ function GridContextMenu({
|
|
|
1869
2168
|
import {
|
|
1870
2169
|
useEffect as useEffect2,
|
|
1871
2170
|
useLayoutEffect as useLayoutEffect4,
|
|
1872
|
-
useRef as
|
|
2171
|
+
useRef as useRef5,
|
|
1873
2172
|
useState as useState5
|
|
1874
2173
|
} from "react";
|
|
1875
2174
|
import {
|
|
@@ -2028,8 +2327,8 @@ function useContextMenu({
|
|
|
2028
2327
|
columnName
|
|
2029
2328
|
}) {
|
|
2030
2329
|
const [menu, setMenu] = useState5(null);
|
|
2031
|
-
const current =
|
|
2032
|
-
const openings =
|
|
2330
|
+
const current = useRef5(null);
|
|
2331
|
+
const openings = useRef5(0);
|
|
2033
2332
|
const enabled = contextMenu !== void 0 && contextMenu !== false;
|
|
2034
2333
|
function parts() {
|
|
2035
2334
|
const { columns, pageRows } = controller.getView();
|
|
@@ -2126,7 +2425,7 @@ function useContextMenu({
|
|
|
2126
2425
|
const place = placeAt(target, parts());
|
|
2127
2426
|
return place !== null && openAt(place, point);
|
|
2128
2427
|
}
|
|
2129
|
-
const latestRequest =
|
|
2428
|
+
const latestRequest = useRef5(handleRequest);
|
|
2130
2429
|
useLayoutEffect4(() => {
|
|
2131
2430
|
latestRequest.current = handleRequest;
|
|
2132
2431
|
});
|
|
@@ -2139,7 +2438,7 @@ function useContextMenu({
|
|
|
2139
2438
|
onRequest: (request) => latestRequest.current(request)
|
|
2140
2439
|
});
|
|
2141
2440
|
}, [rootRef, enabled]);
|
|
2142
|
-
const shown =
|
|
2441
|
+
const shown = useRef5(null);
|
|
2143
2442
|
useLayoutEffect4(() => {
|
|
2144
2443
|
const closed = shown.current;
|
|
2145
2444
|
shown.current = menu;
|
|
@@ -2168,8 +2467,11 @@ function useContextMenu({
|
|
|
2168
2467
|
};
|
|
2169
2468
|
}
|
|
2170
2469
|
|
|
2470
|
+
// src/DataGrid/panels/GridPanels.tsx
|
|
2471
|
+
import { useRef as useRef13 } from "react";
|
|
2472
|
+
|
|
2171
2473
|
// src/DataGrid/columnChooser/ColumnChooser.tsx
|
|
2172
|
-
import { useLayoutEffect as useLayoutEffect5, useRef as
|
|
2474
|
+
import { useLayoutEffect as useLayoutEffect5, useRef as useRef6, useState as useState6 } from "react";
|
|
2173
2475
|
import { resolveColumnChooser } from "@gridkitjs/core";
|
|
2174
2476
|
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2175
2477
|
function ColumnChooser({
|
|
@@ -2177,7 +2479,7 @@ function ColumnChooser({
|
|
|
2177
2479
|
messages
|
|
2178
2480
|
}) {
|
|
2179
2481
|
const [search, setSearch] = useState6("");
|
|
2180
|
-
const showAllRef =
|
|
2482
|
+
const showAllRef = useRef6(null);
|
|
2181
2483
|
const { entries, selectAll, toggleAll } = resolveColumnChooser({
|
|
2182
2484
|
columns: controller.getView().dataColumns,
|
|
2183
2485
|
visibility: controller.getState().columnVisibility,
|
|
@@ -2253,95 +2555,983 @@ function ColumnChooser({
|
|
|
2253
2555
|
);
|
|
2254
2556
|
}
|
|
2255
2557
|
|
|
2256
|
-
// src/DataGrid/
|
|
2257
|
-
import {
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
controller,
|
|
2264
|
-
messages
|
|
2265
|
-
}) {
|
|
2266
|
-
const { panel, close } = panels;
|
|
2267
|
-
if (panel === null) {
|
|
2268
|
-
return null;
|
|
2269
|
-
}
|
|
2270
|
-
const Panel = panelComponents[panel.kind];
|
|
2271
|
-
return /* @__PURE__ */ jsx16(
|
|
2272
|
-
Overlay,
|
|
2273
|
-
{
|
|
2274
|
-
anchor: panel.anchor,
|
|
2275
|
-
placement: panel.placement,
|
|
2276
|
-
gap: panel.anchor instanceof Element ? ANCHOR_GAP : 0,
|
|
2277
|
-
returnFocusTo: panel.returnFocusTo,
|
|
2278
|
-
ignoreScrollAfterInput: true,
|
|
2279
|
-
themeClassName: panel.themeClassName,
|
|
2280
|
-
onDismiss: close,
|
|
2281
|
-
children: /* @__PURE__ */ jsx16(
|
|
2282
|
-
Panel,
|
|
2283
|
-
{
|
|
2284
|
-
target: panel.target,
|
|
2285
|
-
controller,
|
|
2286
|
-
messages
|
|
2287
|
-
}
|
|
2288
|
-
)
|
|
2289
|
-
},
|
|
2290
|
-
panel.key
|
|
2291
|
-
);
|
|
2292
|
-
}
|
|
2558
|
+
// src/DataGrid/filterMenu/FilterMenu.tsx
|
|
2559
|
+
import { useEffect as useEffect3, useRef as useRef11 } from "react";
|
|
2560
|
+
import {
|
|
2561
|
+
resolveColumnFilterMenu as resolveColumnFilterMenu2,
|
|
2562
|
+
resolveColumnHeaderText,
|
|
2563
|
+
resolveMenu as resolveMenu2
|
|
2564
|
+
} from "@gridkitjs/core";
|
|
2293
2565
|
|
|
2294
|
-
// src/DataGrid/
|
|
2295
|
-
import {
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2566
|
+
// src/DataGrid/filterMenu/ExcelFilterEditor.tsx
|
|
2567
|
+
import {
|
|
2568
|
+
useImperativeHandle as useImperativeHandle2,
|
|
2569
|
+
useLayoutEffect as useLayoutEffect9,
|
|
2570
|
+
useMemo as useMemo4,
|
|
2571
|
+
useReducer,
|
|
2572
|
+
useRef as useRef10,
|
|
2573
|
+
useState as useState10
|
|
2574
|
+
} from "react";
|
|
2575
|
+
import {
|
|
2576
|
+
describeColumnFilter as describeColumnFilter2,
|
|
2577
|
+
draftToFilter as draftToFilter2,
|
|
2578
|
+
filterChecklist,
|
|
2579
|
+
filterEditorReducer as filterEditorReducer2,
|
|
2580
|
+
initialFilterEditorDraft as initialFilterEditorDraft2,
|
|
2581
|
+
selectAllState
|
|
2582
|
+
} from "@gridkitjs/core";
|
|
2583
|
+
|
|
2584
|
+
// src/DataGrid/filterMenu/OperatorMenuButton.tsx
|
|
2585
|
+
import { useLayoutEffect as useLayoutEffect6, useRef as useRef7, useState as useState7 } from "react";
|
|
2586
|
+
import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2587
|
+
function gapBeside(button) {
|
|
2588
|
+
const dialog = button.closest('[role="dialog"]') ?? button;
|
|
2589
|
+
return dialog.getBoundingClientRect().right - button.getBoundingClientRect().right + ANCHOR_GAP;
|
|
2312
2590
|
}
|
|
2313
|
-
function
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2591
|
+
function OperatorMenuButton({
|
|
2592
|
+
menu,
|
|
2593
|
+
active,
|
|
2594
|
+
messages,
|
|
2595
|
+
onChoose,
|
|
2596
|
+
ref
|
|
2317
2597
|
}) {
|
|
2318
|
-
const [
|
|
2319
|
-
const
|
|
2320
|
-
|
|
2321
|
-
const element = target.area === "toolbar" ? toolbarItem(root, target.itemId) : target.area === "header" ? headerCell2(headerTableRef.current, target.columnId) : null;
|
|
2322
|
-
if (element !== null) {
|
|
2323
|
-
return {
|
|
2324
|
-
anchor: element,
|
|
2325
|
-
// The toolbar's own button sits at its far end.
|
|
2326
|
-
placement: target.area === "toolbar" ? "bottom-end" : "bottom-start",
|
|
2327
|
-
returnFocusTo: element
|
|
2328
|
-
};
|
|
2329
|
-
}
|
|
2330
|
-
const { right, top } = root.getBoundingClientRect();
|
|
2331
|
-
return {
|
|
2332
|
-
anchor: { x: right, y: top },
|
|
2333
|
-
placement: "bottom-end",
|
|
2334
|
-
returnFocusTo: void 0
|
|
2335
|
-
};
|
|
2336
|
-
}
|
|
2337
|
-
const shown = useRef6(null);
|
|
2598
|
+
const [open, setOpen] = useState7(null);
|
|
2599
|
+
const menuBehaviourRef = useRef7(null);
|
|
2600
|
+
const label = messages.filterOperatorMenu(menu.family);
|
|
2338
2601
|
useLayoutEffect6(() => {
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
if (panel === null && closed?.returnFocusTo?.isConnected === false && document.activeElement === document.body) {
|
|
2342
|
-
nav.focusTabStop();
|
|
2602
|
+
if (open !== null && open.focusItem > 0) {
|
|
2603
|
+
menuBehaviourRef.current?.focusItem(open.focusItem);
|
|
2343
2604
|
}
|
|
2344
|
-
});
|
|
2605
|
+
}, [open]);
|
|
2606
|
+
function show(button, onLast = false) {
|
|
2607
|
+
setOpen({
|
|
2608
|
+
anchor: button,
|
|
2609
|
+
themeClassName: overlayThemeClassName(button),
|
|
2610
|
+
gap: gapBeside(button),
|
|
2611
|
+
focusItem: onLast ? menu.operators.length - 1 : 0
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
function close() {
|
|
2615
|
+
setOpen(null);
|
|
2616
|
+
}
|
|
2617
|
+
const entries = menu.operators.map((operator) => ({
|
|
2618
|
+
type: "item",
|
|
2619
|
+
id: operator,
|
|
2620
|
+
label: messages.filterOperatorLabel(operator, menu.family),
|
|
2621
|
+
disabled: false,
|
|
2622
|
+
checked: active?.includes(operator),
|
|
2623
|
+
run: () => {
|
|
2624
|
+
close();
|
|
2625
|
+
onChoose(operator);
|
|
2626
|
+
return true;
|
|
2627
|
+
}
|
|
2628
|
+
}));
|
|
2629
|
+
return /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
2630
|
+
/* @__PURE__ */ jsxs11(
|
|
2631
|
+
"button",
|
|
2632
|
+
{
|
|
2633
|
+
ref,
|
|
2634
|
+
type: "button",
|
|
2635
|
+
className: "filter-menu-submenu",
|
|
2636
|
+
"aria-haspopup": "menu",
|
|
2637
|
+
"aria-expanded": open !== null,
|
|
2638
|
+
onClick: (event) => {
|
|
2639
|
+
if (open === null) {
|
|
2640
|
+
show(event.currentTarget);
|
|
2641
|
+
} else {
|
|
2642
|
+
close();
|
|
2643
|
+
}
|
|
2644
|
+
},
|
|
2645
|
+
onKeyDown: (event) => {
|
|
2646
|
+
if ((event.key === "ArrowDown" || event.key === "ArrowUp") && open === null) {
|
|
2647
|
+
event.preventDefault();
|
|
2648
|
+
show(event.currentTarget, event.key === "ArrowUp");
|
|
2649
|
+
}
|
|
2650
|
+
},
|
|
2651
|
+
children: [
|
|
2652
|
+
/* @__PURE__ */ jsx16("span", { className: "filter-menu-submenu-icon", "aria-hidden": "true", children: active !== void 0 && /* @__PURE__ */ jsx16(CheckIcon, {}) }),
|
|
2653
|
+
label,
|
|
2654
|
+
/* @__PURE__ */ jsx16("span", { className: "filter-menu-submenu-indicator", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(ChevronRightIcon2, {}) })
|
|
2655
|
+
]
|
|
2656
|
+
}
|
|
2657
|
+
),
|
|
2658
|
+
open !== null && /* @__PURE__ */ jsx16(
|
|
2659
|
+
Overlay,
|
|
2660
|
+
{
|
|
2661
|
+
anchor: open.anchor,
|
|
2662
|
+
placement: "right-start",
|
|
2663
|
+
gap: open.gap,
|
|
2664
|
+
returnFocusTo: open.anchor,
|
|
2665
|
+
themeClassName: open.themeClassName,
|
|
2666
|
+
onDismiss: close,
|
|
2667
|
+
children: /* @__PURE__ */ jsx16(
|
|
2668
|
+
GridMenu,
|
|
2669
|
+
{
|
|
2670
|
+
entries,
|
|
2671
|
+
label,
|
|
2672
|
+
themeClassName: open.themeClassName,
|
|
2673
|
+
behaviourRef: menuBehaviourRef,
|
|
2674
|
+
onRun: (item) => {
|
|
2675
|
+
item.run();
|
|
2676
|
+
},
|
|
2677
|
+
onClose: close
|
|
2678
|
+
}
|
|
2679
|
+
)
|
|
2680
|
+
}
|
|
2681
|
+
)
|
|
2682
|
+
] });
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
// src/DataGrid/filterMenu/SimpleFilterEditor.tsx
|
|
2686
|
+
import {
|
|
2687
|
+
Fragment as Fragment5,
|
|
2688
|
+
useId,
|
|
2689
|
+
useImperativeHandle,
|
|
2690
|
+
useLayoutEffect as useLayoutEffect7,
|
|
2691
|
+
useRef as useRef8,
|
|
2692
|
+
useState as useState8
|
|
2693
|
+
} from "react";
|
|
2694
|
+
import {
|
|
2695
|
+
conditionRowsFrom,
|
|
2696
|
+
conditionsFromRows,
|
|
2697
|
+
describeColumnFilter,
|
|
2698
|
+
draftToFilter,
|
|
2699
|
+
filterEditorReducer,
|
|
2700
|
+
initialFilterEditorDraft
|
|
2701
|
+
} from "@gridkitjs/core";
|
|
2702
|
+
|
|
2703
|
+
// src/DataGrid/filterMenu/ConditionRow.tsx
|
|
2704
|
+
import {
|
|
2705
|
+
filterOperandArity,
|
|
2706
|
+
parseFilterOperand
|
|
2707
|
+
} from "@gridkitjs/core";
|
|
2708
|
+
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2709
|
+
function inputType(family, type) {
|
|
2710
|
+
switch (family) {
|
|
2711
|
+
case "text":
|
|
2712
|
+
return "text";
|
|
2713
|
+
case "number":
|
|
2714
|
+
return "number";
|
|
2715
|
+
case "date":
|
|
2716
|
+
return type === "date" ? "date" : "datetime-local";
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
function OperandField({
|
|
2720
|
+
family,
|
|
2721
|
+
type,
|
|
2722
|
+
text,
|
|
2723
|
+
label,
|
|
2724
|
+
invalidMessageId,
|
|
2725
|
+
fieldRef,
|
|
2726
|
+
messages,
|
|
2727
|
+
onChange
|
|
2728
|
+
}) {
|
|
2729
|
+
const field = {
|
|
2730
|
+
ref: fieldRef,
|
|
2731
|
+
className: "filter-menu-value",
|
|
2732
|
+
"aria-label": label,
|
|
2733
|
+
"aria-invalid": invalidMessageId === void 0 ? void 0 : true,
|
|
2734
|
+
"aria-describedby": invalidMessageId,
|
|
2735
|
+
value: text,
|
|
2736
|
+
onChange: (event) => {
|
|
2737
|
+
onChange(event.currentTarget.value);
|
|
2738
|
+
}
|
|
2739
|
+
};
|
|
2740
|
+
if (family === "boolean") {
|
|
2741
|
+
return /* @__PURE__ */ jsxs12("select", { ...field, children: [
|
|
2742
|
+
/* @__PURE__ */ jsx17("option", { value: "" }),
|
|
2743
|
+
/* @__PURE__ */ jsx17("option", { value: "true", children: messages.booleanTrue }),
|
|
2744
|
+
/* @__PURE__ */ jsx17("option", { value: "false", children: messages.booleanFalse })
|
|
2745
|
+
] });
|
|
2746
|
+
}
|
|
2747
|
+
return /* @__PURE__ */ jsx17("input", { ...field, type: inputType(family, type) });
|
|
2748
|
+
}
|
|
2749
|
+
function ConditionRow({
|
|
2750
|
+
row,
|
|
2751
|
+
position,
|
|
2752
|
+
menu,
|
|
2753
|
+
type,
|
|
2754
|
+
messages,
|
|
2755
|
+
invalidMessageId,
|
|
2756
|
+
focusRef,
|
|
2757
|
+
onChange,
|
|
2758
|
+
ref
|
|
2759
|
+
}) {
|
|
2760
|
+
const arity = filterOperandArity(row.operator);
|
|
2761
|
+
const operators = menu.operators.includes(row.operator) ? menu.operators : [row.operator, ...menu.operators];
|
|
2762
|
+
const operand = { family: menu.family, type, messages };
|
|
2763
|
+
function messageIdFor(text) {
|
|
2764
|
+
return parseFilterOperand(text, type) === void 0 ? invalidMessageId : void 0;
|
|
2765
|
+
}
|
|
2766
|
+
return /* @__PURE__ */ jsxs12(
|
|
2767
|
+
"div",
|
|
2768
|
+
{
|
|
2769
|
+
ref,
|
|
2770
|
+
role: "group",
|
|
2771
|
+
"aria-label": messages.filterConditionLabel(position),
|
|
2772
|
+
className: "filter-menu-condition",
|
|
2773
|
+
children: [
|
|
2774
|
+
/* @__PURE__ */ jsx17(
|
|
2775
|
+
"select",
|
|
2776
|
+
{
|
|
2777
|
+
ref: arity === 0 ? focusRef : void 0,
|
|
2778
|
+
className: "filter-menu-operator",
|
|
2779
|
+
"aria-label": messages.filterOperatorFieldLabel,
|
|
2780
|
+
value: row.operator,
|
|
2781
|
+
onChange: (event) => {
|
|
2782
|
+
const operator = operators[event.currentTarget.selectedIndex];
|
|
2783
|
+
if (operator !== void 0) {
|
|
2784
|
+
onChange({ ...row, operator });
|
|
2785
|
+
}
|
|
2786
|
+
},
|
|
2787
|
+
children: operators.map((operator) => /* @__PURE__ */ jsx17("option", { value: operator, children: messages.filterOperatorLabel(operator, menu.family) }, operator))
|
|
2788
|
+
}
|
|
2789
|
+
),
|
|
2790
|
+
arity > 0 && /* @__PURE__ */ jsx17(
|
|
2791
|
+
OperandField,
|
|
2792
|
+
{
|
|
2793
|
+
...operand,
|
|
2794
|
+
text: row.text,
|
|
2795
|
+
label: arity === 2 ? messages.filterFromLabel : messages.filterValueLabel,
|
|
2796
|
+
invalidMessageId: messageIdFor(row.text),
|
|
2797
|
+
fieldRef: focusRef,
|
|
2798
|
+
onChange: (text) => {
|
|
2799
|
+
onChange({ ...row, text });
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
),
|
|
2803
|
+
arity === 2 && /* @__PURE__ */ jsx17(
|
|
2804
|
+
OperandField,
|
|
2805
|
+
{
|
|
2806
|
+
...operand,
|
|
2807
|
+
text: row.textTo,
|
|
2808
|
+
label: messages.filterToLabel,
|
|
2809
|
+
invalidMessageId: messageIdFor(row.textTo),
|
|
2810
|
+
fieldRef: void 0,
|
|
2811
|
+
onChange: (textTo) => {
|
|
2812
|
+
onChange({ ...row, textTo });
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
)
|
|
2816
|
+
]
|
|
2817
|
+
}
|
|
2818
|
+
);
|
|
2819
|
+
}
|
|
2820
|
+
|
|
2821
|
+
// src/DataGrid/filterMenu/SimpleFilterEditor.tsx
|
|
2822
|
+
import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2823
|
+
var COMBINATORS = ["and", "or"];
|
|
2824
|
+
var NO_ROWS = [];
|
|
2825
|
+
var NO_VALUES = {
|
|
2826
|
+
options: [],
|
|
2827
|
+
total: 0,
|
|
2828
|
+
truncated: false,
|
|
2829
|
+
blanks: 0
|
|
2830
|
+
};
|
|
2831
|
+
function holdsUnreadable(row) {
|
|
2832
|
+
return Array.from(row?.querySelectorAll("input") ?? []).some(
|
|
2833
|
+
(input) => input.validity.badInput
|
|
2834
|
+
);
|
|
2835
|
+
}
|
|
2836
|
+
function CombinatorChoice({
|
|
2837
|
+
name,
|
|
2838
|
+
combinator,
|
|
2839
|
+
messages,
|
|
2840
|
+
onChange
|
|
2841
|
+
}) {
|
|
2842
|
+
return /* @__PURE__ */ jsx18(
|
|
2843
|
+
"div",
|
|
2844
|
+
{
|
|
2845
|
+
role: "radiogroup",
|
|
2846
|
+
"aria-label": messages.filterCombinatorLabel,
|
|
2847
|
+
className: "filter-menu-combinator",
|
|
2848
|
+
children: COMBINATORS.map((choice) => /* @__PURE__ */ jsxs13("label", { className: "filter-menu-combinator-option", children: [
|
|
2849
|
+
/* @__PURE__ */ jsx18(
|
|
2850
|
+
"input",
|
|
2851
|
+
{
|
|
2852
|
+
type: "radio",
|
|
2853
|
+
name,
|
|
2854
|
+
checked: choice === combinator,
|
|
2855
|
+
onChange: () => {
|
|
2856
|
+
onChange(choice);
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2859
|
+
),
|
|
2860
|
+
choice === "and" ? messages.filterAnd : messages.filterOr
|
|
2861
|
+
] }, choice))
|
|
2862
|
+
}
|
|
2863
|
+
);
|
|
2864
|
+
}
|
|
2865
|
+
function SimpleFilterEditor({
|
|
2866
|
+
column,
|
|
2867
|
+
menu,
|
|
2868
|
+
controller,
|
|
2869
|
+
messages,
|
|
2870
|
+
initialFocusRef,
|
|
2871
|
+
applyFilter,
|
|
2872
|
+
operator,
|
|
2873
|
+
ref
|
|
2874
|
+
}) {
|
|
2875
|
+
const type = column.column.type;
|
|
2876
|
+
const [opened] = useState8(() => {
|
|
2877
|
+
const shape = describeColumnFilter(controller.getState().filter, column.id);
|
|
2878
|
+
const rows = conditionRowsFrom(shape, menu.operators, type);
|
|
2879
|
+
const draft2 = {
|
|
2880
|
+
// Its typed values kept, as picking the operator in the row keeps them.
|
|
2881
|
+
rows: operator === void 0 ? rows : rows.map(
|
|
2882
|
+
(row, index) => index === 0 ? { ...row, operator } : row
|
|
2883
|
+
),
|
|
2884
|
+
combinator: shape.kind === "conditions" ? shape.combinator : "and"
|
|
2885
|
+
};
|
|
2886
|
+
return {
|
|
2887
|
+
custom: shape.kind === "custom" || shape.kind === "values" && operator === void 0,
|
|
2888
|
+
draft: draft2
|
|
2889
|
+
};
|
|
2890
|
+
});
|
|
2891
|
+
const [draft, setDraft] = useState8(opened.draft);
|
|
2892
|
+
const [invalid, setInvalid] = useState8(NO_ROWS);
|
|
2893
|
+
const rowElements = useRef8([]);
|
|
2894
|
+
const invalidMessageId = useId();
|
|
2895
|
+
const combinatorName = useId();
|
|
2896
|
+
function update(next) {
|
|
2897
|
+
setDraft(next);
|
|
2898
|
+
setInvalid(NO_ROWS);
|
|
2899
|
+
}
|
|
2900
|
+
function applyConditions(conditions) {
|
|
2901
|
+
const applied = filterEditorReducer(
|
|
2902
|
+
initialFilterEditorDraft({ kind: "none" }, NO_VALUES),
|
|
2903
|
+
{ type: "setConditions", conditions, combinator: draft.combinator }
|
|
2904
|
+
);
|
|
2905
|
+
applyFilter(
|
|
2906
|
+
draftToFilter(applied, column.id, controller.getState().filter)
|
|
2907
|
+
);
|
|
2908
|
+
}
|
|
2909
|
+
useImperativeHandle(ref, () => ({
|
|
2910
|
+
apply: () => {
|
|
2911
|
+
const parsed = conditionsFromRows(draft.rows, column.id, type);
|
|
2912
|
+
const unreadable = draft.rows.map(
|
|
2913
|
+
(_, index) => holdsUnreadable(rowElements.current[index])
|
|
2914
|
+
);
|
|
2915
|
+
const marked = draft.rows.flatMap(
|
|
2916
|
+
(_, index) => parsed.invalid.includes(index) || unreadable[index] === true ? [index] : []
|
|
2917
|
+
);
|
|
2918
|
+
if (marked.length === 0) {
|
|
2919
|
+
applyConditions(parsed.conditions);
|
|
2920
|
+
return true;
|
|
2921
|
+
}
|
|
2922
|
+
if (draft === opened.draft && !unreadable.includes(true)) {
|
|
2923
|
+
return true;
|
|
2924
|
+
}
|
|
2925
|
+
setInvalid(marked);
|
|
2926
|
+
return false;
|
|
2927
|
+
}
|
|
2928
|
+
}));
|
|
2929
|
+
useLayoutEffect7(() => {
|
|
2930
|
+
const [first] = invalid;
|
|
2931
|
+
if (first !== void 0) {
|
|
2932
|
+
rowElements.current[first]?.querySelector('[aria-invalid="true"]')?.focus();
|
|
2933
|
+
}
|
|
2934
|
+
}, [invalid]);
|
|
2935
|
+
return /* @__PURE__ */ jsxs13("div", { className: "filter-menu-conditions", children: [
|
|
2936
|
+
opened.custom && /* @__PURE__ */ jsx18("p", { className: "filter-menu-custom", children: messages.customFilter }),
|
|
2937
|
+
draft.rows.map((row, index) => (
|
|
2938
|
+
// A row is its place: the first condition, or the second.
|
|
2939
|
+
/* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
2940
|
+
index > 0 && /* @__PURE__ */ jsx18(
|
|
2941
|
+
CombinatorChoice,
|
|
2942
|
+
{
|
|
2943
|
+
name: combinatorName,
|
|
2944
|
+
combinator: draft.combinator,
|
|
2945
|
+
messages,
|
|
2946
|
+
onChange: (combinator) => {
|
|
2947
|
+
update({ ...draft, combinator });
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2950
|
+
),
|
|
2951
|
+
/* @__PURE__ */ jsx18(
|
|
2952
|
+
ConditionRow,
|
|
2953
|
+
{
|
|
2954
|
+
ref: (element) => {
|
|
2955
|
+
rowElements.current[index] = element;
|
|
2956
|
+
},
|
|
2957
|
+
row,
|
|
2958
|
+
position: index + 1,
|
|
2959
|
+
menu,
|
|
2960
|
+
type,
|
|
2961
|
+
messages,
|
|
2962
|
+
invalidMessageId: invalid.includes(index) ? invalidMessageId : void 0,
|
|
2963
|
+
focusRef: index === 0 ? initialFocusRef : void 0,
|
|
2964
|
+
onChange: (next) => {
|
|
2965
|
+
update({
|
|
2966
|
+
...draft,
|
|
2967
|
+
rows: draft.rows.map(
|
|
2968
|
+
(current, at) => at === index ? next : current
|
|
2969
|
+
)
|
|
2970
|
+
});
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
)
|
|
2974
|
+
] }, index)
|
|
2975
|
+
)),
|
|
2976
|
+
invalid.length > 0 && /* @__PURE__ */ jsx18("p", { id: invalidMessageId, className: "filter-menu-invalid", children: messages.filterValueInvalid(menu.family) })
|
|
2977
|
+
] });
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2980
|
+
// src/DataGrid/filterMenu/ValueChecklist.tsx
|
|
2981
|
+
import { useLayoutEffect as useLayoutEffect8, useRef as useRef9, useState as useState9 } from "react";
|
|
2982
|
+
import {
|
|
2983
|
+
attachChecklist,
|
|
2984
|
+
createRowVirtualizer
|
|
2985
|
+
} from "@gridkitjs/dom";
|
|
2986
|
+
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2987
|
+
var ESTIMATED_ITEM_HEIGHT = 28;
|
|
2988
|
+
var OVERSCAN = 4;
|
|
2989
|
+
var NO_RANGE = {
|
|
2990
|
+
startIndex: 0,
|
|
2991
|
+
endIndex: -1,
|
|
2992
|
+
offsetBefore: 0,
|
|
2993
|
+
offsetAfter: 0
|
|
2994
|
+
};
|
|
2995
|
+
function ValueChecklist({
|
|
2996
|
+
items,
|
|
2997
|
+
showCounts,
|
|
2998
|
+
label,
|
|
2999
|
+
onToggle
|
|
3000
|
+
}) {
|
|
3001
|
+
const listRef = useRef9(null);
|
|
3002
|
+
const checklistRef = useRef9(null);
|
|
3003
|
+
const [virtualizer, setVirtualizer] = useState9(null);
|
|
3004
|
+
const [range, setRange] = useState9(NO_RANGE);
|
|
3005
|
+
const latest = useRef9({ items, onToggle });
|
|
3006
|
+
useLayoutEffect8(() => {
|
|
3007
|
+
latest.current = { items, onToggle };
|
|
3008
|
+
});
|
|
3009
|
+
useLayoutEffect8(() => {
|
|
3010
|
+
const list = listRef.current;
|
|
3011
|
+
if (list === null) {
|
|
3012
|
+
return void 0;
|
|
3013
|
+
}
|
|
3014
|
+
const rows = createRowVirtualizer(list, {
|
|
3015
|
+
estimatedRowHeight: ESTIMATED_ITEM_HEIGHT,
|
|
3016
|
+
overscan: OVERSCAN,
|
|
3017
|
+
onRange: setRange
|
|
3018
|
+
});
|
|
3019
|
+
const checklist = attachChecklist(list, {
|
|
3020
|
+
onToggle: (index) => {
|
|
3021
|
+
const item = latest.current.items[index];
|
|
3022
|
+
if (item !== void 0) {
|
|
3023
|
+
latest.current.onToggle(item);
|
|
3024
|
+
}
|
|
3025
|
+
},
|
|
3026
|
+
scrollToIndex: (index) => {
|
|
3027
|
+
rows.scrollToIndex(index, { block: "nearest" });
|
|
3028
|
+
}
|
|
3029
|
+
});
|
|
3030
|
+
checklistRef.current = checklist;
|
|
3031
|
+
setVirtualizer(rows);
|
|
3032
|
+
return () => {
|
|
3033
|
+
checklistRef.current = null;
|
|
3034
|
+
checklist.detach();
|
|
3035
|
+
rows.destroy();
|
|
3036
|
+
};
|
|
3037
|
+
}, []);
|
|
3038
|
+
useLayoutEffect8(() => {
|
|
3039
|
+
virtualizer?.setRowCount(items.length);
|
|
3040
|
+
checklistRef.current?.setCount(items.length);
|
|
3041
|
+
}, [virtualizer, items.length]);
|
|
3042
|
+
const shown = items.slice(range.startIndex, range.endIndex + 1);
|
|
3043
|
+
return /* @__PURE__ */ jsxs14(
|
|
3044
|
+
"div",
|
|
3045
|
+
{
|
|
3046
|
+
ref: listRef,
|
|
3047
|
+
role: "listbox",
|
|
3048
|
+
"aria-multiselectable": "true",
|
|
3049
|
+
"aria-label": label,
|
|
3050
|
+
className: "filter-menu-checklist",
|
|
3051
|
+
children: [
|
|
3052
|
+
/* @__PURE__ */ jsx19("div", { role: "presentation", style: { height: range.offsetBefore } }),
|
|
3053
|
+
shown.map((item, offset) => {
|
|
3054
|
+
const index = range.startIndex + offset;
|
|
3055
|
+
return /* @__PURE__ */ jsxs14(
|
|
3056
|
+
"div",
|
|
3057
|
+
{
|
|
3058
|
+
ref: virtualizer?.measureRow(index),
|
|
3059
|
+
role: "option",
|
|
3060
|
+
"data-gridkit-checklist-item": "",
|
|
3061
|
+
"data-gridkit-checklist-index": index,
|
|
3062
|
+
"aria-checked": item.checked,
|
|
3063
|
+
"aria-setsize": items.length,
|
|
3064
|
+
"aria-posinset": index + 1,
|
|
3065
|
+
className: "filter-menu-option",
|
|
3066
|
+
children: [
|
|
3067
|
+
/* @__PURE__ */ jsx19("span", { className: "filter-menu-option-check", "aria-hidden": "true", children: /* @__PURE__ */ jsx19(CheckIcon, {}) }),
|
|
3068
|
+
/* @__PURE__ */ jsx19("span", { className: "filter-menu-option-label", children: item.label }),
|
|
3069
|
+
showCounts && /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
3070
|
+
" ",
|
|
3071
|
+
/* @__PURE__ */ jsx19("span", { className: "filter-menu-option-count", children: String(item.count) })
|
|
3072
|
+
] })
|
|
3073
|
+
]
|
|
3074
|
+
},
|
|
3075
|
+
item.key
|
|
3076
|
+
);
|
|
3077
|
+
}),
|
|
3078
|
+
/* @__PURE__ */ jsx19("div", { role: "presentation", style: { height: range.offsetAfter } })
|
|
3079
|
+
]
|
|
3080
|
+
}
|
|
3081
|
+
);
|
|
3082
|
+
}
|
|
3083
|
+
|
|
3084
|
+
// src/DataGrid/filterMenu/ExcelFilterEditor.tsx
|
|
3085
|
+
import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3086
|
+
function toggleOf(item) {
|
|
3087
|
+
return item.kind === "blanks" ? { type: "setIncludeBlanks", includeBlanks: !item.checked } : { type: "toggleValue", value: item.value };
|
|
3088
|
+
}
|
|
3089
|
+
function ExcelFilterEditor({
|
|
3090
|
+
column,
|
|
3091
|
+
menu,
|
|
3092
|
+
controller,
|
|
3093
|
+
messages,
|
|
3094
|
+
initialFocusRef,
|
|
3095
|
+
applyFilter,
|
|
3096
|
+
columnValues,
|
|
3097
|
+
ref
|
|
3098
|
+
}) {
|
|
3099
|
+
const [opened] = useState10(() => {
|
|
3100
|
+
const shape2 = describeColumnFilter2(controller.getState().filter, column.id);
|
|
3101
|
+
return {
|
|
3102
|
+
shape: shape2,
|
|
3103
|
+
draft: initialFilterEditorDraft2(shape2, columnValues(column.id))
|
|
3104
|
+
};
|
|
3105
|
+
});
|
|
3106
|
+
const [draft, dispatch] = useReducer(filterEditorReducer2, opened.draft);
|
|
3107
|
+
const [operator, setOperator] = useState10(null);
|
|
3108
|
+
const conditions = useRef10(null);
|
|
3109
|
+
const conditionsFocus = useRef10(null);
|
|
3110
|
+
const operatorButton = useRef10(null);
|
|
3111
|
+
const switched = useRef10(false);
|
|
3112
|
+
const selectAllRef = useRef10(null);
|
|
3113
|
+
const selectAll = useMemo4(() => selectAllState(draft), [draft]);
|
|
3114
|
+
const checklist = useMemo4(
|
|
3115
|
+
() => filterChecklist(draft, {
|
|
3116
|
+
valueLimit: menu.valueLimit,
|
|
3117
|
+
blanksLabel: messages.filterBlanks
|
|
3118
|
+
}),
|
|
3119
|
+
[draft, menu.valueLimit, messages.filterBlanks]
|
|
3120
|
+
);
|
|
3121
|
+
useLayoutEffect9(() => {
|
|
3122
|
+
if (selectAllRef.current !== null) {
|
|
3123
|
+
selectAllRef.current.indeterminate = selectAll === "mixed";
|
|
3124
|
+
}
|
|
3125
|
+
});
|
|
3126
|
+
useLayoutEffect9(() => {
|
|
3127
|
+
if (switched.current) {
|
|
3128
|
+
switched.current = false;
|
|
3129
|
+
(operator === null ? operatorButton.current : conditionsFocus.current)?.focus();
|
|
3130
|
+
}
|
|
3131
|
+
}, [operator]);
|
|
3132
|
+
function switchTo(chosen) {
|
|
3133
|
+
switched.current = true;
|
|
3134
|
+
setOperator(chosen);
|
|
3135
|
+
}
|
|
3136
|
+
useImperativeHandle2(ref, () => ({
|
|
3137
|
+
apply: () => {
|
|
3138
|
+
if (operator !== null) {
|
|
3139
|
+
return conditions.current?.apply() ?? true;
|
|
3140
|
+
}
|
|
3141
|
+
const picked = draft.checked !== opened.draft.checked || draft.includeBlanks !== opened.draft.includeBlanks;
|
|
3142
|
+
if (picked) {
|
|
3143
|
+
applyFilter(
|
|
3144
|
+
draftToFilter2(draft, column.id, controller.getState().filter)
|
|
3145
|
+
);
|
|
3146
|
+
}
|
|
3147
|
+
return true;
|
|
3148
|
+
}
|
|
3149
|
+
}));
|
|
3150
|
+
if (operator !== null) {
|
|
3151
|
+
return /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
3152
|
+
/* @__PURE__ */ jsxs15(
|
|
3153
|
+
"button",
|
|
3154
|
+
{
|
|
3155
|
+
type: "button",
|
|
3156
|
+
className: "filter-menu-back",
|
|
3157
|
+
onClick: () => {
|
|
3158
|
+
switchTo(null);
|
|
3159
|
+
},
|
|
3160
|
+
children: [
|
|
3161
|
+
/* @__PURE__ */ jsx20("span", { className: "filter-menu-back-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx20(ChevronLeftIcon2, {}) }),
|
|
3162
|
+
messages.filterBackToValues
|
|
3163
|
+
]
|
|
3164
|
+
}
|
|
3165
|
+
),
|
|
3166
|
+
/* @__PURE__ */ jsx20(
|
|
3167
|
+
SimpleFilterEditor,
|
|
3168
|
+
{
|
|
3169
|
+
ref: conditions,
|
|
3170
|
+
column,
|
|
3171
|
+
menu,
|
|
3172
|
+
controller,
|
|
3173
|
+
messages,
|
|
3174
|
+
initialFocusRef: (element) => {
|
|
3175
|
+
conditionsFocus.current = element;
|
|
3176
|
+
},
|
|
3177
|
+
applyFilter,
|
|
3178
|
+
operator
|
|
3179
|
+
}
|
|
3180
|
+
)
|
|
3181
|
+
] });
|
|
3182
|
+
}
|
|
3183
|
+
const { shape } = opened;
|
|
3184
|
+
return /* @__PURE__ */ jsxs15("div", { className: "filter-menu-values", children: [
|
|
3185
|
+
menu.operators.length > 0 && /* @__PURE__ */ jsx20(
|
|
3186
|
+
OperatorMenuButton,
|
|
3187
|
+
{
|
|
3188
|
+
ref: operatorButton,
|
|
3189
|
+
menu,
|
|
3190
|
+
active: shape.kind === "conditions" ? shape.conditions.map((condition) => condition.operator) : void 0,
|
|
3191
|
+
messages,
|
|
3192
|
+
onChoose: switchTo
|
|
3193
|
+
}
|
|
3194
|
+
),
|
|
3195
|
+
(shape.kind === "conditions" || shape.kind === "custom") && /* @__PURE__ */ jsx20("p", { className: "filter-menu-custom", children: shape.kind === "conditions" ? messages.filterByCondition : messages.customFilter }),
|
|
3196
|
+
/* @__PURE__ */ jsx20(
|
|
3197
|
+
"input",
|
|
3198
|
+
{
|
|
3199
|
+
ref: initialFocusRef,
|
|
3200
|
+
type: "search",
|
|
3201
|
+
className: "filter-menu-search",
|
|
3202
|
+
"aria-label": messages.filterSearchLabel,
|
|
3203
|
+
placeholder: messages.searchPlaceholder,
|
|
3204
|
+
value: draft.search,
|
|
3205
|
+
onChange: (event) => {
|
|
3206
|
+
dispatch({ type: "search", search: event.currentTarget.value });
|
|
3207
|
+
}
|
|
3208
|
+
}
|
|
3209
|
+
),
|
|
3210
|
+
/* @__PURE__ */ jsxs15("label", { className: "filter-menu-select-all", children: [
|
|
3211
|
+
/* @__PURE__ */ jsx20(
|
|
3212
|
+
"input",
|
|
3213
|
+
{
|
|
3214
|
+
ref: selectAllRef,
|
|
3215
|
+
type: "checkbox",
|
|
3216
|
+
checked: selectAll === "checked",
|
|
3217
|
+
disabled: !checklist.needsSearch && checklist.items.length === 0,
|
|
3218
|
+
onChange: () => {
|
|
3219
|
+
dispatch({ type: "toggleAll" });
|
|
3220
|
+
}
|
|
3221
|
+
}
|
|
3222
|
+
),
|
|
3223
|
+
messages.filterSelectAll
|
|
3224
|
+
] }),
|
|
3225
|
+
checklist.needsSearch ? /* @__PURE__ */ jsx20("p", { className: "filter-menu-search-first", children: messages.filterSearchFirst(checklist.total) }) : /* @__PURE__ */ jsx20(
|
|
3226
|
+
ValueChecklist,
|
|
3227
|
+
{
|
|
3228
|
+
items: checklist.items,
|
|
3229
|
+
showCounts: menu.showCounts,
|
|
3230
|
+
label: messages.filterValuesLabel,
|
|
3231
|
+
onToggle: (item) => {
|
|
3232
|
+
dispatch(toggleOf(item));
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
),
|
|
3236
|
+
checklist.hiddenCount > 0 && /* @__PURE__ */ jsx20("p", { role: "status", className: "filter-menu-more", children: messages.filterMoreValues(checklist.hiddenCount) })
|
|
3237
|
+
] });
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3240
|
+
// src/DataGrid/filterMenu/FilterMenu.tsx
|
|
3241
|
+
import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3242
|
+
var SORT_COMMANDS = [
|
|
3243
|
+
"sort.ascending",
|
|
3244
|
+
"sort.descending",
|
|
3245
|
+
"sort.clear"
|
|
3246
|
+
];
|
|
3247
|
+
function isItem(entry) {
|
|
3248
|
+
return entry.type === "item";
|
|
3249
|
+
}
|
|
3250
|
+
function FilterMenu({
|
|
3251
|
+
target,
|
|
3252
|
+
controller,
|
|
3253
|
+
commands,
|
|
3254
|
+
messages,
|
|
3255
|
+
close,
|
|
3256
|
+
initialFocusRef,
|
|
3257
|
+
applyFilter,
|
|
3258
|
+
columnValues
|
|
3259
|
+
}) {
|
|
3260
|
+
const editor = useRef11(null);
|
|
3261
|
+
const column = target.area === "header" ? controller.getView().dataColumns.find((entry) => entry.id === target.columnId) : void 0;
|
|
3262
|
+
const menu = column === void 0 ? null : resolveColumnFilterMenu2(controller.getOptions(), column.column);
|
|
3263
|
+
useEffect3(() => {
|
|
3264
|
+
if (menu === null) {
|
|
3265
|
+
close();
|
|
3266
|
+
}
|
|
3267
|
+
});
|
|
3268
|
+
if (column === void 0 || menu === null) {
|
|
3269
|
+
return null;
|
|
3270
|
+
}
|
|
3271
|
+
const resolveOptions = {
|
|
3272
|
+
commands: commands.commands,
|
|
3273
|
+
context: commands.contextFor(target)
|
|
3274
|
+
};
|
|
3275
|
+
const sortItems = resolveMenu2(SORT_COMMANDS, resolveOptions).filter(isItem);
|
|
3276
|
+
const [clearItem] = resolveMenu2(["filter.clear"], resolveOptions).filter(
|
|
3277
|
+
isItem
|
|
3278
|
+
);
|
|
3279
|
+
function run(item) {
|
|
3280
|
+
commands.run(item.id, target, "filterMenu");
|
|
3281
|
+
close();
|
|
3282
|
+
}
|
|
3283
|
+
const editorProps = {
|
|
3284
|
+
ref: editor,
|
|
3285
|
+
column,
|
|
3286
|
+
menu,
|
|
3287
|
+
controller,
|
|
3288
|
+
messages,
|
|
3289
|
+
initialFocusRef,
|
|
3290
|
+
applyFilter
|
|
3291
|
+
};
|
|
3292
|
+
function apply(event) {
|
|
3293
|
+
event.preventDefault();
|
|
3294
|
+
if (editor.current?.apply() ?? true) {
|
|
3295
|
+
close();
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
return /* @__PURE__ */ jsx21(
|
|
3299
|
+
"div",
|
|
3300
|
+
{
|
|
3301
|
+
role: "dialog",
|
|
3302
|
+
"aria-label": messages.filterMenuLabel(
|
|
3303
|
+
resolveColumnHeaderText(column.column)
|
|
3304
|
+
),
|
|
3305
|
+
className: "gridkit-filter-menu",
|
|
3306
|
+
children: /* @__PURE__ */ jsxs16(
|
|
3307
|
+
"form",
|
|
3308
|
+
{
|
|
3309
|
+
className: "filter-menu-form",
|
|
3310
|
+
noValidate: true,
|
|
3311
|
+
onSubmit: apply,
|
|
3312
|
+
onKeyDown: (event) => {
|
|
3313
|
+
if (event.key === "Enter" && event.target instanceof Element && event.target.closest("select, [role=listbox]") !== null) {
|
|
3314
|
+
event.preventDefault();
|
|
3315
|
+
event.currentTarget.requestSubmit();
|
|
3316
|
+
}
|
|
3317
|
+
},
|
|
3318
|
+
children: [
|
|
3319
|
+
sortItems.length > 0 && /* @__PURE__ */ jsx21("div", { className: "filter-menu-sort", children: sortItems.map((item) => /* @__PURE__ */ jsxs16(
|
|
3320
|
+
"button",
|
|
3321
|
+
{
|
|
3322
|
+
type: "button",
|
|
3323
|
+
className: "filter-menu-sort-item",
|
|
3324
|
+
disabled: item.disabled,
|
|
3325
|
+
...ariaAttr(
|
|
3326
|
+
item.checked !== void 0,
|
|
3327
|
+
"aria-pressed",
|
|
3328
|
+
item.checked
|
|
3329
|
+
),
|
|
3330
|
+
onClick: () => {
|
|
3331
|
+
run(item);
|
|
3332
|
+
},
|
|
3333
|
+
children: [
|
|
3334
|
+
/* @__PURE__ */ jsx21("span", { className: "filter-menu-sort-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx21(MenuIcon, { name: item.icon }) }),
|
|
3335
|
+
item.label
|
|
3336
|
+
]
|
|
3337
|
+
},
|
|
3338
|
+
item.id
|
|
3339
|
+
)) }),
|
|
3340
|
+
menu.ui === "excel" ? /* @__PURE__ */ jsx21(ExcelFilterEditor, { ...editorProps, columnValues }) : /* @__PURE__ */ jsx21(SimpleFilterEditor, { ...editorProps }),
|
|
3341
|
+
/* @__PURE__ */ jsxs16("div", { className: "filter-menu-actions", children: [
|
|
3342
|
+
clearItem !== void 0 && /* @__PURE__ */ jsx21(
|
|
3343
|
+
"button",
|
|
3344
|
+
{
|
|
3345
|
+
type: "button",
|
|
3346
|
+
className: "filter-menu-clear",
|
|
3347
|
+
disabled: clearItem.disabled,
|
|
3348
|
+
onClick: () => {
|
|
3349
|
+
run(clearItem);
|
|
3350
|
+
},
|
|
3351
|
+
children: clearItem.label
|
|
3352
|
+
}
|
|
3353
|
+
),
|
|
3354
|
+
/* @__PURE__ */ jsx21("button", { type: "button", className: "filter-menu-cancel", onClick: close, children: messages.cancelFilter }),
|
|
3355
|
+
/* @__PURE__ */ jsx21("button", { type: "submit", className: "filter-menu-apply", children: messages.applyFilter })
|
|
3356
|
+
] })
|
|
3357
|
+
]
|
|
3358
|
+
}
|
|
3359
|
+
)
|
|
3360
|
+
}
|
|
3361
|
+
);
|
|
3362
|
+
}
|
|
3363
|
+
|
|
3364
|
+
// src/DataGrid/filterMenu/useApplyFilter.ts
|
|
3365
|
+
import { useEffect as useEffect4, useRef as useRef12 } from "react";
|
|
3366
|
+
function useApplyFilter(controller, messages, announce) {
|
|
3367
|
+
const unannounced = useRef12(null);
|
|
3368
|
+
useEffect4(() => {
|
|
3369
|
+
if (unannounced.current === controller.getState().filter) {
|
|
3370
|
+
unannounced.current = null;
|
|
3371
|
+
announce(
|
|
3372
|
+
messages.filterResults(
|
|
3373
|
+
controller.getView().rows.length,
|
|
3374
|
+
controller.getOptions().dataSource?.length ?? 0
|
|
3375
|
+
)
|
|
3376
|
+
);
|
|
3377
|
+
}
|
|
3378
|
+
});
|
|
3379
|
+
return (filter) => {
|
|
3380
|
+
unannounced.current = filter;
|
|
3381
|
+
controller.setFilter(filter);
|
|
3382
|
+
};
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3385
|
+
// src/DataGrid/filterMenu/useFilterValueCache.ts
|
|
3386
|
+
import { useState as useState11 } from "react";
|
|
3387
|
+
import {
|
|
3388
|
+
createColumnValueOptionsCache
|
|
3389
|
+
} from "@gridkitjs/core";
|
|
3390
|
+
var NO_ROWS2 = [];
|
|
3391
|
+
function useFilterValueCache(controller, messages) {
|
|
3392
|
+
const [cache] = useState11(createColumnValueOptionsCache);
|
|
3393
|
+
return (columnId) => {
|
|
3394
|
+
const { dataSource = NO_ROWS2, locale } = controller.getOptions();
|
|
3395
|
+
return cache.get(
|
|
3396
|
+
dataSource,
|
|
3397
|
+
controller.getView().dataColumns,
|
|
3398
|
+
controller.getState().filter,
|
|
3399
|
+
columnId,
|
|
3400
|
+
locale === void 0 ? { messages } : { locale, messages }
|
|
3401
|
+
);
|
|
3402
|
+
};
|
|
3403
|
+
}
|
|
3404
|
+
|
|
3405
|
+
// src/DataGrid/panels/GridPanels.tsx
|
|
3406
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
3407
|
+
var panelKinds = {
|
|
3408
|
+
columnChooser: { component: ColumnChooser, trapFocus: false },
|
|
3409
|
+
filter: { component: FilterMenu, trapFocus: true }
|
|
3410
|
+
};
|
|
3411
|
+
function GridPanels({
|
|
3412
|
+
panels,
|
|
3413
|
+
controller,
|
|
3414
|
+
commands,
|
|
3415
|
+
messages
|
|
3416
|
+
}) {
|
|
3417
|
+
const initialFocus = useRef13(null);
|
|
3418
|
+
const applyFilter = useApplyFilter(
|
|
3419
|
+
controller,
|
|
3420
|
+
messages,
|
|
3421
|
+
commands.host.announce
|
|
3422
|
+
);
|
|
3423
|
+
const columnValues = useFilterValueCache(controller, messages);
|
|
3424
|
+
const { panel, close } = panels;
|
|
3425
|
+
if (panel === null) {
|
|
3426
|
+
return null;
|
|
3427
|
+
}
|
|
3428
|
+
const { component: Panel, trapFocus } = panelKinds[panel.kind];
|
|
3429
|
+
return /* @__PURE__ */ jsx22(
|
|
3430
|
+
Overlay,
|
|
3431
|
+
{
|
|
3432
|
+
anchor: panel.anchor,
|
|
3433
|
+
placement: panel.placement,
|
|
3434
|
+
gap: panel.anchor instanceof Element ? ANCHOR_GAP : 0,
|
|
3435
|
+
initialFocus,
|
|
3436
|
+
returnFocusTo: panel.returnFocusTo,
|
|
3437
|
+
ignoreScrollAfterInput: true,
|
|
3438
|
+
trapFocus,
|
|
3439
|
+
themeClassName: panel.themeClassName,
|
|
3440
|
+
onDismiss: close,
|
|
3441
|
+
children: /* @__PURE__ */ jsx22(
|
|
3442
|
+
Panel,
|
|
3443
|
+
{
|
|
3444
|
+
target: panel.target,
|
|
3445
|
+
controller,
|
|
3446
|
+
commands,
|
|
3447
|
+
messages,
|
|
3448
|
+
close,
|
|
3449
|
+
initialFocusRef: (element) => {
|
|
3450
|
+
initialFocus.current = element;
|
|
3451
|
+
},
|
|
3452
|
+
applyFilter,
|
|
3453
|
+
columnValues
|
|
3454
|
+
}
|
|
3455
|
+
)
|
|
3456
|
+
},
|
|
3457
|
+
panel.key
|
|
3458
|
+
);
|
|
3459
|
+
}
|
|
3460
|
+
|
|
3461
|
+
// src/DataGrid/panels/panelApi.ts
|
|
3462
|
+
import { resolveColumnFilterMenu as resolveColumnFilterMenu3 } from "@gridkitjs/core";
|
|
3463
|
+
function panelApi(panels, controller) {
|
|
3464
|
+
return {
|
|
3465
|
+
openColumnChooser: () => {
|
|
3466
|
+
panels.open("columnChooser", { area: "grid" });
|
|
3467
|
+
},
|
|
3468
|
+
openFilterMenu: (columnId) => {
|
|
3469
|
+
const shown = controller.getView().columns.find((entry) => entry.id === columnId);
|
|
3470
|
+
if (shown === void 0 || resolveColumnFilterMenu3(controller.getOptions(), shown.column) === null) {
|
|
3471
|
+
return false;
|
|
3472
|
+
}
|
|
3473
|
+
panels.open("filter", { area: "header", columnId });
|
|
3474
|
+
return true;
|
|
3475
|
+
},
|
|
3476
|
+
closeFilterMenu: () => {
|
|
3477
|
+
if (panels.panel?.kind === "filter") {
|
|
3478
|
+
panels.close();
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
};
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3484
|
+
// src/DataGrid/panels/useGridPanels.ts
|
|
3485
|
+
import { useLayoutEffect as useLayoutEffect10, useRef as useRef14, useState as useState12 } from "react";
|
|
3486
|
+
function toolbarItem(root, itemId) {
|
|
3487
|
+
const items = root.querySelectorAll(
|
|
3488
|
+
":scope > .gridkit-toolbar > [data-gridkit-toolbar-item]"
|
|
3489
|
+
);
|
|
3490
|
+
return Array.from(items).find(
|
|
3491
|
+
(item) => item.getAttribute("data-gridkit-toolbar-item") === itemId
|
|
3492
|
+
) ?? // In "More" while the toolbar is narrow: the button it is chosen from.
|
|
3493
|
+
Array.from(items).find(
|
|
3494
|
+
(item) => item.hasAttribute("data-gridkit-toolbar-more")
|
|
3495
|
+
) ?? null;
|
|
3496
|
+
}
|
|
3497
|
+
function headerCell2(headerTable, columnId) {
|
|
3498
|
+
const cells = headerTable?.tHead?.rows[0]?.cells;
|
|
3499
|
+
return cells === void 0 ? null : Array.from(cells).find(
|
|
3500
|
+
(cell) => cell.getAttribute("data-gridkit-column") === columnId
|
|
3501
|
+
) ?? null;
|
|
3502
|
+
}
|
|
3503
|
+
function useGridPanels({
|
|
3504
|
+
rootRef,
|
|
3505
|
+
headerTableRef,
|
|
3506
|
+
nav
|
|
3507
|
+
}) {
|
|
3508
|
+
const [panel, setPanel] = useState12(null);
|
|
3509
|
+
const openings = useRef14(0);
|
|
3510
|
+
function placeFor(root, target) {
|
|
3511
|
+
const element = target.area === "toolbar" ? toolbarItem(root, target.itemId) : target.area === "header" ? headerCell2(headerTableRef.current, target.columnId) : null;
|
|
3512
|
+
if (element !== null) {
|
|
3513
|
+
return {
|
|
3514
|
+
anchor: element,
|
|
3515
|
+
// The toolbar's own button sits at its far end.
|
|
3516
|
+
placement: target.area === "toolbar" ? "bottom-end" : "bottom-start",
|
|
3517
|
+
returnFocusTo: element
|
|
3518
|
+
};
|
|
3519
|
+
}
|
|
3520
|
+
const { right, top } = root.getBoundingClientRect();
|
|
3521
|
+
return {
|
|
3522
|
+
anchor: { x: right, y: top },
|
|
3523
|
+
placement: "bottom-end",
|
|
3524
|
+
returnFocusTo: void 0
|
|
3525
|
+
};
|
|
3526
|
+
}
|
|
3527
|
+
const shown = useRef14(null);
|
|
3528
|
+
useLayoutEffect10(() => {
|
|
3529
|
+
const closed = shown.current;
|
|
3530
|
+
shown.current = panel;
|
|
3531
|
+
if (panel === null && closed?.returnFocusTo?.isConnected === false && document.activeElement === document.body) {
|
|
3532
|
+
nav.focusTabStop();
|
|
3533
|
+
}
|
|
3534
|
+
});
|
|
2345
3535
|
return {
|
|
2346
3536
|
panel,
|
|
2347
3537
|
open: (kind, target) => {
|
|
@@ -2365,7 +3555,7 @@ function useGridPanels({
|
|
|
2365
3555
|
}
|
|
2366
3556
|
|
|
2367
3557
|
// src/DataGrid/toolbar/GridToolbar.tsx
|
|
2368
|
-
import { useLayoutEffect as
|
|
3558
|
+
import { useLayoutEffect as useLayoutEffect13, useRef as useRef18 } from "react";
|
|
2369
3559
|
import {
|
|
2370
3560
|
resolveToolbar,
|
|
2371
3561
|
splitToolbarItems,
|
|
@@ -2374,8 +3564,8 @@ import {
|
|
|
2374
3564
|
import { attachToolbar } from "@gridkitjs/dom";
|
|
2375
3565
|
|
|
2376
3566
|
// src/DataGrid/toolbar/ToolbarMenuButton.tsx
|
|
2377
|
-
import { useLayoutEffect as
|
|
2378
|
-
import { Fragment as
|
|
3567
|
+
import { useLayoutEffect as useLayoutEffect11, useRef as useRef15, useState as useState13 } from "react";
|
|
3568
|
+
import { Fragment as Fragment8, jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2379
3569
|
function ToolbarMenuButton({
|
|
2380
3570
|
itemKey,
|
|
2381
3571
|
label,
|
|
@@ -2384,9 +3574,9 @@ function ToolbarMenuButton({
|
|
|
2384
3574
|
more = false,
|
|
2385
3575
|
onMenuClose
|
|
2386
3576
|
}) {
|
|
2387
|
-
const [menu, setMenu] =
|
|
2388
|
-
const menuBehaviourRef =
|
|
2389
|
-
|
|
3577
|
+
const [menu, setMenu] = useState13(null);
|
|
3578
|
+
const menuBehaviourRef = useRef15(null);
|
|
3579
|
+
useLayoutEffect11(() => {
|
|
2390
3580
|
if (menu !== null && menu.focusItem > 0) {
|
|
2391
3581
|
menuBehaviourRef.current?.focusItem(menu.focusItem);
|
|
2392
3582
|
}
|
|
@@ -2402,8 +3592,8 @@ function ToolbarMenuButton({
|
|
|
2402
3592
|
setMenu(null);
|
|
2403
3593
|
onMenuClose();
|
|
2404
3594
|
}
|
|
2405
|
-
return /* @__PURE__ */
|
|
2406
|
-
/* @__PURE__ */
|
|
3595
|
+
return /* @__PURE__ */ jsxs17(Fragment8, { children: [
|
|
3596
|
+
/* @__PURE__ */ jsxs17(
|
|
2407
3597
|
"button",
|
|
2408
3598
|
{
|
|
2409
3599
|
type: "button",
|
|
@@ -2426,13 +3616,13 @@ function ToolbarMenuButton({
|
|
|
2426
3616
|
}
|
|
2427
3617
|
},
|
|
2428
3618
|
children: [
|
|
2429
|
-
icon !== void 0 && /* @__PURE__ */
|
|
3619
|
+
icon !== void 0 && /* @__PURE__ */ jsx23("span", { className: "toolbar-button-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx23(MenuIcon, { name: icon }) }),
|
|
2430
3620
|
label,
|
|
2431
|
-
/* @__PURE__ */
|
|
3621
|
+
/* @__PURE__ */ jsx23("span", { className: "toolbar-button-indicator", "aria-hidden": "true", children: /* @__PURE__ */ jsx23(ChevronDownIcon, {}) })
|
|
2432
3622
|
]
|
|
2433
3623
|
}
|
|
2434
3624
|
),
|
|
2435
|
-
menu !== null && /* @__PURE__ */
|
|
3625
|
+
menu !== null && /* @__PURE__ */ jsx23(
|
|
2436
3626
|
Overlay,
|
|
2437
3627
|
{
|
|
2438
3628
|
anchor: menu.anchor,
|
|
@@ -2441,7 +3631,7 @@ function ToolbarMenuButton({
|
|
|
2441
3631
|
returnFocusTo: menu.anchor,
|
|
2442
3632
|
themeClassName: menu.themeClassName,
|
|
2443
3633
|
onDismiss: close,
|
|
2444
|
-
children: /* @__PURE__ */
|
|
3634
|
+
children: /* @__PURE__ */ jsx23(
|
|
2445
3635
|
GridMenu,
|
|
2446
3636
|
{
|
|
2447
3637
|
entries,
|
|
@@ -2461,12 +3651,12 @@ function ToolbarMenuButton({
|
|
|
2461
3651
|
}
|
|
2462
3652
|
|
|
2463
3653
|
// src/DataGrid/toolbar/ToolbarSearch.tsx
|
|
2464
|
-
import { useEffect as
|
|
3654
|
+
import { useEffect as useEffect5, useRef as useRef16, useState as useState14 } from "react";
|
|
2465
3655
|
import {
|
|
2466
3656
|
searchTextOf,
|
|
2467
3657
|
setSearchText
|
|
2468
3658
|
} from "@gridkitjs/core";
|
|
2469
|
-
import { jsx as
|
|
3659
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
2470
3660
|
var SEARCH_DELAY_MS = 250;
|
|
2471
3661
|
function ToolbarSearch({
|
|
2472
3662
|
itemKey,
|
|
@@ -2475,9 +3665,9 @@ function ToolbarSearch({
|
|
|
2475
3665
|
announce
|
|
2476
3666
|
}) {
|
|
2477
3667
|
const applied = searchTextOf(controller.getState().filter);
|
|
2478
|
-
const [draft, setDraft] =
|
|
2479
|
-
const timer =
|
|
2480
|
-
const unannounced =
|
|
3668
|
+
const [draft, setDraft] = useState14(null);
|
|
3669
|
+
const timer = useRef16(void 0);
|
|
3670
|
+
const unannounced = useRef16(null);
|
|
2481
3671
|
const text = draft !== null && draft.over === applied ? draft.text : applied;
|
|
2482
3672
|
function apply(next, over) {
|
|
2483
3673
|
clearTimeout(timer.current);
|
|
@@ -2492,19 +3682,19 @@ function ToolbarSearch({
|
|
|
2492
3682
|
controller.setFilter(searched);
|
|
2493
3683
|
}
|
|
2494
3684
|
}
|
|
2495
|
-
|
|
3685
|
+
useEffect5(() => {
|
|
2496
3686
|
if (unannounced.current === applied) {
|
|
2497
3687
|
unannounced.current = null;
|
|
2498
3688
|
announce(messages.searchResults(controller.getView().rows.length));
|
|
2499
3689
|
}
|
|
2500
3690
|
});
|
|
2501
|
-
|
|
3691
|
+
useEffect5(
|
|
2502
3692
|
() => () => {
|
|
2503
3693
|
clearTimeout(timer.current);
|
|
2504
3694
|
},
|
|
2505
3695
|
[]
|
|
2506
3696
|
);
|
|
2507
|
-
return /* @__PURE__ */
|
|
3697
|
+
return /* @__PURE__ */ jsx24(
|
|
2508
3698
|
"input",
|
|
2509
3699
|
{
|
|
2510
3700
|
type: "search",
|
|
@@ -2534,12 +3724,12 @@ function ToolbarSearch({
|
|
|
2534
3724
|
}
|
|
2535
3725
|
|
|
2536
3726
|
// src/DataGrid/toolbar/useToolbarOverflow.ts
|
|
2537
|
-
import { useLayoutEffect as
|
|
3727
|
+
import { useLayoutEffect as useLayoutEffect12, useRef as useRef17, useState as useState15 } from "react";
|
|
2538
3728
|
import { observeToolbarOverflow } from "@gridkitjs/dom";
|
|
2539
3729
|
function useToolbarOverflow(toolbarRef, items) {
|
|
2540
|
-
const [fit, setFit] =
|
|
2541
|
-
const overflow =
|
|
2542
|
-
const measuredLayout =
|
|
3730
|
+
const [fit, setFit] = useState15(items.length);
|
|
3731
|
+
const overflow = useRef17(null);
|
|
3732
|
+
const measuredLayout = useRef17("");
|
|
2543
3733
|
const layout = JSON.stringify(
|
|
2544
3734
|
items.map((item) => [
|
|
2545
3735
|
item.type,
|
|
@@ -2547,7 +3737,7 @@ function useToolbarOverflow(toolbarRef, items) {
|
|
|
2547
3737
|
"label" in item ? item.label : null
|
|
2548
3738
|
])
|
|
2549
3739
|
);
|
|
2550
|
-
|
|
3740
|
+
useLayoutEffect12(() => {
|
|
2551
3741
|
const toolbar = toolbarRef.current;
|
|
2552
3742
|
if (toolbar === null || layout === measuredLayout.current) {
|
|
2553
3743
|
return;
|
|
@@ -2560,7 +3750,7 @@ function useToolbarOverflow(toolbarRef, items) {
|
|
|
2560
3750
|
overflow.current.update(options);
|
|
2561
3751
|
}
|
|
2562
3752
|
}, [toolbarRef, layout, items]);
|
|
2563
|
-
|
|
3753
|
+
useLayoutEffect12(
|
|
2564
3754
|
() => () => {
|
|
2565
3755
|
overflow.current?.detach();
|
|
2566
3756
|
overflow.current = null;
|
|
@@ -2572,7 +3762,7 @@ function useToolbarOverflow(toolbarRef, items) {
|
|
|
2572
3762
|
}
|
|
2573
3763
|
|
|
2574
3764
|
// src/DataGrid/toolbar/GridToolbar.tsx
|
|
2575
|
-
import { jsx as
|
|
3765
|
+
import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2576
3766
|
function reporting(run, report) {
|
|
2577
3767
|
return () => {
|
|
2578
3768
|
const ran = run();
|
|
@@ -2625,7 +3815,7 @@ function GridToolbar(props) {
|
|
|
2625
3815
|
return null;
|
|
2626
3816
|
}
|
|
2627
3817
|
const label = (typeof props.toolbar === "object" ? props.toolbar.label : void 0) ?? props.messages.toolbarLabel;
|
|
2628
|
-
return /* @__PURE__ */
|
|
3818
|
+
return /* @__PURE__ */ jsx25(Toolbar, { ...props, entries, label });
|
|
2629
3819
|
}
|
|
2630
3820
|
function Toolbar({
|
|
2631
3821
|
entries,
|
|
@@ -2637,8 +3827,8 @@ function Toolbar({
|
|
|
2637
3827
|
messages,
|
|
2638
3828
|
announce
|
|
2639
3829
|
}) {
|
|
2640
|
-
const toolbarRef =
|
|
2641
|
-
const menuClosed =
|
|
3830
|
+
const toolbarRef = useRef18(null);
|
|
3831
|
+
const menuClosed = useRef18(false);
|
|
2642
3832
|
const items = resolveToolbar(entries, {
|
|
2643
3833
|
commands: commands.commands,
|
|
2644
3834
|
contextFor: commands.contextFor
|
|
@@ -2649,11 +3839,11 @@ function Toolbar({
|
|
|
2649
3839
|
);
|
|
2650
3840
|
const fit = useToolbarOverflow(toolbarRef, items);
|
|
2651
3841
|
const { shown, overflow } = splitToolbarItems(items, fit);
|
|
2652
|
-
|
|
3842
|
+
useLayoutEffect13(() => {
|
|
2653
3843
|
const toolbar = toolbarRef.current;
|
|
2654
3844
|
return toolbar === null ? void 0 : attachToolbar(toolbar);
|
|
2655
3845
|
}, []);
|
|
2656
|
-
|
|
3846
|
+
useLayoutEffect13(() => {
|
|
2657
3847
|
if (!menuClosed.current) {
|
|
2658
3848
|
return;
|
|
2659
3849
|
}
|
|
@@ -2669,7 +3859,7 @@ function Toolbar({
|
|
|
2669
3859
|
function draw(item) {
|
|
2670
3860
|
switch (item.type) {
|
|
2671
3861
|
case "button":
|
|
2672
|
-
return /* @__PURE__ */
|
|
3862
|
+
return /* @__PURE__ */ jsxs18(
|
|
2673
3863
|
"button",
|
|
2674
3864
|
{
|
|
2675
3865
|
type: "button",
|
|
@@ -2690,14 +3880,14 @@ function Toolbar({
|
|
|
2690
3880
|
item.run();
|
|
2691
3881
|
},
|
|
2692
3882
|
children: [
|
|
2693
|
-
item.icon !== void 0 && /* @__PURE__ */
|
|
3883
|
+
item.icon !== void 0 && /* @__PURE__ */ jsx25("span", { className: "toolbar-button-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx25(MenuIcon, { name: item.icon }) }),
|
|
2694
3884
|
item.label
|
|
2695
3885
|
]
|
|
2696
3886
|
},
|
|
2697
3887
|
item.key
|
|
2698
3888
|
);
|
|
2699
3889
|
case "menu":
|
|
2700
|
-
return /* @__PURE__ */
|
|
3890
|
+
return /* @__PURE__ */ jsx25(
|
|
2701
3891
|
ToolbarMenuButton,
|
|
2702
3892
|
{
|
|
2703
3893
|
itemKey: item.key,
|
|
@@ -2709,7 +3899,7 @@ function Toolbar({
|
|
|
2709
3899
|
item.key
|
|
2710
3900
|
);
|
|
2711
3901
|
case "search":
|
|
2712
|
-
return /* @__PURE__ */
|
|
3902
|
+
return /* @__PURE__ */ jsx25(
|
|
2713
3903
|
ToolbarSearch,
|
|
2714
3904
|
{
|
|
2715
3905
|
itemKey: item.key,
|
|
@@ -2720,7 +3910,7 @@ function Toolbar({
|
|
|
2720
3910
|
item.key
|
|
2721
3911
|
);
|
|
2722
3912
|
case "separator":
|
|
2723
|
-
return /* @__PURE__ */
|
|
3913
|
+
return /* @__PURE__ */ jsx25(
|
|
2724
3914
|
"div",
|
|
2725
3915
|
{
|
|
2726
3916
|
role: "separator",
|
|
@@ -2731,7 +3921,7 @@ function Toolbar({
|
|
|
2731
3921
|
item.key
|
|
2732
3922
|
);
|
|
2733
3923
|
case "spacer":
|
|
2734
|
-
return /* @__PURE__ */
|
|
3924
|
+
return /* @__PURE__ */ jsx25(
|
|
2735
3925
|
"div",
|
|
2736
3926
|
{
|
|
2737
3927
|
className: "toolbar-spacer",
|
|
@@ -2740,7 +3930,7 @@ function Toolbar({
|
|
|
2740
3930
|
item.key
|
|
2741
3931
|
);
|
|
2742
3932
|
case "custom":
|
|
2743
|
-
return /* @__PURE__ */
|
|
3933
|
+
return /* @__PURE__ */ jsx25(
|
|
2744
3934
|
"div",
|
|
2745
3935
|
{
|
|
2746
3936
|
className: "toolbar-custom",
|
|
@@ -2751,7 +3941,7 @@ function Toolbar({
|
|
|
2751
3941
|
);
|
|
2752
3942
|
}
|
|
2753
3943
|
}
|
|
2754
|
-
return /* @__PURE__ */
|
|
3944
|
+
return /* @__PURE__ */ jsxs18(
|
|
2755
3945
|
"div",
|
|
2756
3946
|
{
|
|
2757
3947
|
ref: toolbarRef,
|
|
@@ -2761,7 +3951,7 @@ function Toolbar({
|
|
|
2761
3951
|
className: "gridkit-toolbar",
|
|
2762
3952
|
children: [
|
|
2763
3953
|
shown.map(draw),
|
|
2764
|
-
overflow.length > 0 && /* @__PURE__ */
|
|
3954
|
+
overflow.length > 0 && /* @__PURE__ */ jsx25(
|
|
2765
3955
|
ToolbarMenuButton,
|
|
2766
3956
|
{
|
|
2767
3957
|
itemKey: "more",
|
|
@@ -2817,7 +4007,7 @@ function useColumnDrag({
|
|
|
2817
4007
|
|
|
2818
4008
|
// src/DataGrid/useColumnResize.ts
|
|
2819
4009
|
import {
|
|
2820
|
-
useState as
|
|
4010
|
+
useState as useState16
|
|
2821
4011
|
} from "react";
|
|
2822
4012
|
import {
|
|
2823
4013
|
beginColumnResize,
|
|
@@ -2831,7 +4021,7 @@ function useColumnResize({
|
|
|
2831
4021
|
controller,
|
|
2832
4022
|
columnSizeDefaults
|
|
2833
4023
|
}) {
|
|
2834
|
-
const [activeColumnId, setActiveColumnId] =
|
|
4024
|
+
const [activeColumnId, setActiveColumnId] = useState16(null);
|
|
2835
4025
|
function startResize(entry, event) {
|
|
2836
4026
|
event.stopPropagation();
|
|
2837
4027
|
const session = beginColumnResize(
|
|
@@ -2909,11 +4099,11 @@ function useColumnResize({
|
|
|
2909
4099
|
}
|
|
2910
4100
|
|
|
2911
4101
|
// src/DataGrid/useElementWidth.ts
|
|
2912
|
-
import { useLayoutEffect as
|
|
4102
|
+
import { useLayoutEffect as useLayoutEffect14, useState as useState17 } from "react";
|
|
2913
4103
|
import { observeElementWidth } from "@gridkitjs/dom";
|
|
2914
4104
|
function useElementWidth(ref, enabled) {
|
|
2915
|
-
const [width, setWidth] =
|
|
2916
|
-
|
|
4105
|
+
const [width, setWidth] = useState17(null);
|
|
4106
|
+
useLayoutEffect14(() => {
|
|
2917
4107
|
const element = ref.current;
|
|
2918
4108
|
if (element === null || !enabled) {
|
|
2919
4109
|
return void 0;
|
|
@@ -2924,29 +4114,33 @@ function useElementWidth(ref, enabled) {
|
|
|
2924
4114
|
}
|
|
2925
4115
|
|
|
2926
4116
|
// src/DataGrid/useGridController.ts
|
|
2927
|
-
import { useState as
|
|
4117
|
+
import { useState as useState18, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
2928
4118
|
import {
|
|
2929
4119
|
createGridController
|
|
2930
4120
|
} from "@gridkitjs/core";
|
|
2931
4121
|
function useGridController(options) {
|
|
2932
|
-
const [controller] =
|
|
4122
|
+
const [controller] = useState18(
|
|
2933
4123
|
() => createGridController(options)
|
|
2934
4124
|
);
|
|
2935
4125
|
controller.setOptions(options);
|
|
2936
|
-
const state = useSyncExternalStore2(
|
|
4126
|
+
const state = useSyncExternalStore2(
|
|
4127
|
+
controller.subscribe,
|
|
4128
|
+
controller.getState,
|
|
4129
|
+
controller.getState
|
|
4130
|
+
);
|
|
2937
4131
|
return { controller, state, view: controller.getView() };
|
|
2938
4132
|
}
|
|
2939
4133
|
|
|
2940
4134
|
// src/DataGrid/useInfiniteScroll.ts
|
|
2941
|
-
import { useEffect as
|
|
4135
|
+
import { useEffect as useEffect6, useRef as useRef19 } from "react";
|
|
2942
4136
|
import { attachInfiniteScroll } from "@gridkitjs/dom";
|
|
2943
4137
|
function useInfiniteScroll({
|
|
2944
4138
|
rootRef,
|
|
2945
4139
|
sentinelRef,
|
|
2946
4140
|
config
|
|
2947
4141
|
}) {
|
|
2948
|
-
const scroll =
|
|
2949
|
-
|
|
4142
|
+
const scroll = useRef19(null);
|
|
4143
|
+
useEffect6(() => {
|
|
2950
4144
|
const root = rootRef.current;
|
|
2951
4145
|
if (root === null) {
|
|
2952
4146
|
return void 0;
|
|
@@ -2961,7 +4155,7 @@ function useInfiniteScroll({
|
|
|
2961
4155
|
scroll.current = null;
|
|
2962
4156
|
};
|
|
2963
4157
|
}, [rootRef]);
|
|
2964
|
-
|
|
4158
|
+
useEffect6(() => {
|
|
2965
4159
|
scroll.current?.update({
|
|
2966
4160
|
sentinel: sentinelRef.current,
|
|
2967
4161
|
hasMore: config?.hasMore ?? false,
|
|
@@ -2973,11 +4167,11 @@ function useInfiniteScroll({
|
|
|
2973
4167
|
}
|
|
2974
4168
|
|
|
2975
4169
|
// src/DataGrid/useLiveAnnouncer.ts
|
|
2976
|
-
import { useCallback, useLayoutEffect as
|
|
4170
|
+
import { useCallback, useLayoutEffect as useLayoutEffect15, useRef as useRef20 } from "react";
|
|
2977
4171
|
import { createLiveAnnouncer } from "@gridkitjs/dom";
|
|
2978
4172
|
function useLiveAnnouncer(containerRef) {
|
|
2979
|
-
const announcer =
|
|
2980
|
-
|
|
4173
|
+
const announcer = useRef20(null);
|
|
4174
|
+
useLayoutEffect15(() => {
|
|
2981
4175
|
const container = containerRef.current;
|
|
2982
4176
|
if (container === null) {
|
|
2983
4177
|
return void 0;
|
|
@@ -2995,8 +4189,8 @@ function useLiveAnnouncer(containerRef) {
|
|
|
2995
4189
|
}
|
|
2996
4190
|
|
|
2997
4191
|
// src/DataGrid/useRowVirtualizer.ts
|
|
2998
|
-
import { useLayoutEffect as
|
|
2999
|
-
import { createRowVirtualizer } from "@gridkitjs/dom";
|
|
4192
|
+
import { useLayoutEffect as useLayoutEffect16, useState as useState19 } from "react";
|
|
4193
|
+
import { createRowVirtualizer as createRowVirtualizer2 } from "@gridkitjs/dom";
|
|
3000
4194
|
var EMPTY_RANGE = {
|
|
3001
4195
|
startIndex: 0,
|
|
3002
4196
|
endIndex: -1,
|
|
@@ -3013,14 +4207,14 @@ function useRowVirtualizer({
|
|
|
3013
4207
|
estimatedRowHeight,
|
|
3014
4208
|
overscan
|
|
3015
4209
|
}) {
|
|
3016
|
-
const [virtualizer, setVirtualizer] =
|
|
3017
|
-
const [range, setRange] =
|
|
3018
|
-
|
|
4210
|
+
const [virtualizer, setVirtualizer] = useState19(null);
|
|
4211
|
+
const [range, setRange] = useState19(EMPTY_RANGE);
|
|
4212
|
+
useLayoutEffect16(() => {
|
|
3019
4213
|
const element = bodyScrollRef.current;
|
|
3020
4214
|
if (!enabled || element === null) {
|
|
3021
4215
|
return void 0;
|
|
3022
4216
|
}
|
|
3023
|
-
const created =
|
|
4217
|
+
const created = createRowVirtualizer2(element, {
|
|
3024
4218
|
estimatedRowHeight,
|
|
3025
4219
|
overscan,
|
|
3026
4220
|
onRange: setRange
|
|
@@ -3030,7 +4224,7 @@ function useRowVirtualizer({
|
|
|
3030
4224
|
created.destroy();
|
|
3031
4225
|
};
|
|
3032
4226
|
}, [enabled, bodyScrollRef, estimatedRowHeight, overscan]);
|
|
3033
|
-
|
|
4227
|
+
useLayoutEffect16(() => {
|
|
3034
4228
|
virtualizer?.setRowCount(rows.length);
|
|
3035
4229
|
virtualizer?.resetHeights();
|
|
3036
4230
|
}, [virtualizer, rows]);
|
|
@@ -3047,7 +4241,7 @@ function useRowVirtualizer({
|
|
|
3047
4241
|
}
|
|
3048
4242
|
|
|
3049
4243
|
// src/DataGrid/DataGrid.tsx
|
|
3050
|
-
import { jsx as
|
|
4244
|
+
import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3051
4245
|
var NO_AGGREGATES = [];
|
|
3052
4246
|
function paginationReader(controller) {
|
|
3053
4247
|
let last;
|
|
@@ -3104,18 +4298,18 @@ function DataGrid(props) {
|
|
|
3104
4298
|
const hoverRows = hoverable?.rows ?? true;
|
|
3105
4299
|
const hoverColumns = hoverable?.columns ?? true;
|
|
3106
4300
|
const hoverCells = hoverable?.cells ?? true;
|
|
3107
|
-
const viewportRef =
|
|
3108
|
-
const headerTableRef =
|
|
3109
|
-
const bodyTableRef =
|
|
3110
|
-
const bodyScrollRef =
|
|
3111
|
-
const sentinelRef =
|
|
4301
|
+
const viewportRef = useRef21(null);
|
|
4302
|
+
const headerTableRef = useRef21(null);
|
|
4303
|
+
const bodyTableRef = useRef21(null);
|
|
4304
|
+
const bodyScrollRef = useRef21(null);
|
|
4305
|
+
const sentinelRef = useRef21(null);
|
|
3112
4306
|
const viewportWidth = useElementWidth(viewportRef, resizeMode === "fit");
|
|
3113
|
-
const subscribersRef =
|
|
3114
|
-
const gridId =
|
|
4307
|
+
const subscribersRef = useRef21(/* @__PURE__ */ new Set());
|
|
4308
|
+
const gridId = useId2();
|
|
3115
4309
|
const announce = useLiveAnnouncer(viewportRef);
|
|
3116
|
-
const messages =
|
|
3117
|
-
() => resolveMessages(messageOverrides),
|
|
3118
|
-
[messageOverrides]
|
|
4310
|
+
const messages = useMemo5(
|
|
4311
|
+
() => resolveMessages(messageOverrides, locale),
|
|
4312
|
+
[messageOverrides, locale]
|
|
3119
4313
|
);
|
|
3120
4314
|
const { controller, state, view } = useGridController({
|
|
3121
4315
|
...props,
|
|
@@ -3128,8 +4322,8 @@ function DataGrid(props) {
|
|
|
3128
4322
|
columnOf
|
|
3129
4323
|
})
|
|
3130
4324
|
});
|
|
3131
|
-
const [readPagination] =
|
|
3132
|
-
const [readSelectedRows] =
|
|
4325
|
+
const [readPagination] = useState20(() => paginationReader(controller));
|
|
4326
|
+
const [readSelectedRows] = useState20(() => selectedRowsReader(controller));
|
|
3133
4327
|
const virtualizer = useRowVirtualizer({
|
|
3134
4328
|
enabled: virtualized,
|
|
3135
4329
|
rows: view.pageRows,
|
|
@@ -3137,7 +4331,7 @@ function DataGrid(props) {
|
|
|
3137
4331
|
estimatedRowHeight,
|
|
3138
4332
|
overscan
|
|
3139
4333
|
});
|
|
3140
|
-
|
|
4334
|
+
useEffect7(() => {
|
|
3141
4335
|
if (virtualized && height === void 0) {
|
|
3142
4336
|
console.error(
|
|
3143
4337
|
"DataGrid: `virtualized` has no effect without `height` \u2014 a body with no bounded height has no viewport to window rows against."
|
|
@@ -3145,7 +4339,7 @@ function DataGrid(props) {
|
|
|
3145
4339
|
}
|
|
3146
4340
|
}, [virtualized, height]);
|
|
3147
4341
|
const hasInfiniteScroll = infiniteScroll !== void 0;
|
|
3148
|
-
|
|
4342
|
+
useEffect7(() => {
|
|
3149
4343
|
if (paginated && hasInfiniteScroll) {
|
|
3150
4344
|
console.error(
|
|
3151
4345
|
"DataGrid: `paginated` and `infiniteScroll` are mutually exclusive \u2014 only `paginated` takes effect while both are set."
|
|
@@ -3162,7 +4356,7 @@ function DataGrid(props) {
|
|
|
3162
4356
|
}
|
|
3163
4357
|
function columnName(columnId) {
|
|
3164
4358
|
const column = columnOf(columnId);
|
|
3165
|
-
return column === void 0 ? columnId :
|
|
4359
|
+
return column === void 0 ? columnId : resolveColumnHeaderText2(column);
|
|
3166
4360
|
}
|
|
3167
4361
|
const resize = useColumnResize({
|
|
3168
4362
|
// `@gridkitjs/dom`'s `measureColumnContent` only ever matches
|
|
@@ -3206,19 +4400,20 @@ function DataGrid(props) {
|
|
|
3206
4400
|
resize,
|
|
3207
4401
|
openPanel: panels.open
|
|
3208
4402
|
});
|
|
3209
|
-
const
|
|
4403
|
+
const handleCopyKey = useGridCopy({ controller, commands, nav });
|
|
4404
|
+
const orderedIds = useMemo5(
|
|
3210
4405
|
() => view.dataColumns.map((entry) => entry.id),
|
|
3211
4406
|
[view.dataColumns]
|
|
3212
4407
|
);
|
|
3213
|
-
const displayedIds =
|
|
4408
|
+
const displayedIds = useMemo5(
|
|
3214
4409
|
() => view.columns.map((entry) => entry.id),
|
|
3215
4410
|
[view.columns]
|
|
3216
4411
|
);
|
|
3217
|
-
const definitions =
|
|
4412
|
+
const definitions = useMemo5(
|
|
3218
4413
|
() => new Map(view.dataColumns.map((entry) => [entry.id, entry.column])),
|
|
3219
4414
|
[view.dataColumns]
|
|
3220
4415
|
);
|
|
3221
|
-
const groupByDraggableIds =
|
|
4416
|
+
const groupByDraggableIds = useMemo5(
|
|
3222
4417
|
() => new Set(
|
|
3223
4418
|
view.columns.filter((entry) => entry.groupByDraggable).map((entry) => entry.id)
|
|
3224
4419
|
),
|
|
@@ -3277,12 +4472,12 @@ function DataGrid(props) {
|
|
|
3277
4472
|
messages,
|
|
3278
4473
|
columnName
|
|
3279
4474
|
});
|
|
3280
|
-
|
|
4475
|
+
useEffect7(() => {
|
|
3281
4476
|
for (const listener of subscribersRef.current) {
|
|
3282
4477
|
listener();
|
|
3283
4478
|
}
|
|
3284
4479
|
}, [view, state, nav.focus]);
|
|
3285
|
-
|
|
4480
|
+
useImperativeHandle3(ref, () => ({
|
|
3286
4481
|
get element() {
|
|
3287
4482
|
return viewportRef.current;
|
|
3288
4483
|
},
|
|
@@ -3347,9 +4542,9 @@ function DataGrid(props) {
|
|
|
3347
4542
|
},
|
|
3348
4543
|
openContextMenu: contextMenu.open,
|
|
3349
4544
|
closeContextMenu: contextMenu.close,
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
4545
|
+
...exportApi(commands),
|
|
4546
|
+
...printApi(commands),
|
|
4547
|
+
...panelApi(panels, controller),
|
|
3353
4548
|
runCommand: (commandId, target = { area: "grid" }) => commands.run(commandId, target, "api"),
|
|
3354
4549
|
scrollToRow: (rowId, options) => {
|
|
3355
4550
|
const index = controller.getView().pageRows.findIndex(
|
|
@@ -3391,8 +4586,8 @@ function DataGrid(props) {
|
|
|
3391
4586
|
selection.columnMode === false ? "" : "selectable-columns",
|
|
3392
4587
|
selection.cellMode === false ? "" : "selectable-cells"
|
|
3393
4588
|
);
|
|
3394
|
-
return /* @__PURE__ */
|
|
3395
|
-
/* @__PURE__ */
|
|
4589
|
+
return /* @__PURE__ */ jsxs19("div", { className: "gridkit-data-grid-viewport", ref: viewportRef, children: [
|
|
4590
|
+
/* @__PURE__ */ jsx26(
|
|
3396
4591
|
GridToolbar,
|
|
3397
4592
|
{
|
|
3398
4593
|
toolbar: props.toolbar,
|
|
@@ -3404,7 +4599,7 @@ function DataGrid(props) {
|
|
|
3404
4599
|
announce
|
|
3405
4600
|
}
|
|
3406
4601
|
),
|
|
3407
|
-
showGroupByBar && /* @__PURE__ */
|
|
4602
|
+
showGroupByBar && /* @__PURE__ */ jsx26(
|
|
3408
4603
|
GroupByBar,
|
|
3409
4604
|
{
|
|
3410
4605
|
columns: view.columns,
|
|
@@ -3418,7 +4613,7 @@ function DataGrid(props) {
|
|
|
3418
4613
|
messages
|
|
3419
4614
|
}
|
|
3420
4615
|
),
|
|
3421
|
-
/* @__PURE__ */
|
|
4616
|
+
/* @__PURE__ */ jsxs19(
|
|
3422
4617
|
"div",
|
|
3423
4618
|
{
|
|
3424
4619
|
id: gridId,
|
|
@@ -3435,6 +4630,7 @@ function DataGrid(props) {
|
|
|
3435
4630
|
),
|
|
3436
4631
|
onKeyDown: (event) => {
|
|
3437
4632
|
if (!isOwnEvent(event)) return;
|
|
4633
|
+
handleCopyKey(event);
|
|
3438
4634
|
if (event.key === "Escape") {
|
|
3439
4635
|
if (drag.draggedColumnId !== null || resize.activeColumnId !== null)
|
|
3440
4636
|
return;
|
|
@@ -3448,27 +4644,29 @@ function DataGrid(props) {
|
|
|
3448
4644
|
}
|
|
3449
4645
|
},
|
|
3450
4646
|
children: [
|
|
3451
|
-
/* @__PURE__ */
|
|
4647
|
+
/* @__PURE__ */ jsxs19(
|
|
3452
4648
|
"table",
|
|
3453
4649
|
{
|
|
3454
4650
|
ref: headerTableRef,
|
|
4651
|
+
role: "presentation",
|
|
3455
4652
|
style: { width: totalColumnWidth(view.columns) },
|
|
3456
4653
|
className: classNames(gridTableClassName, "gridkit-data-grid-header"),
|
|
3457
4654
|
children: [
|
|
3458
|
-
/* @__PURE__ */
|
|
3459
|
-
/* @__PURE__ */
|
|
4655
|
+
/* @__PURE__ */ jsx26(GridColgroup, { columns: view.columns }),
|
|
4656
|
+
/* @__PURE__ */ jsx26(
|
|
3460
4657
|
GridHeader,
|
|
3461
4658
|
{
|
|
3462
4659
|
columns: view.columns,
|
|
3463
4660
|
resize,
|
|
3464
4661
|
drag,
|
|
3465
4662
|
controller,
|
|
3466
|
-
|
|
4663
|
+
state,
|
|
3467
4664
|
sortableColumns,
|
|
3468
|
-
groupBy: state.groupBy,
|
|
3469
4665
|
groupableColumns,
|
|
3470
4666
|
groupToggleIconColumns,
|
|
3471
4667
|
headerMenu: contextMenu.opens("header"),
|
|
4668
|
+
panels,
|
|
4669
|
+
messages,
|
|
3472
4670
|
nav,
|
|
3473
4671
|
selection
|
|
3474
4672
|
}
|
|
@@ -3476,7 +4674,7 @@ function DataGrid(props) {
|
|
|
3476
4674
|
]
|
|
3477
4675
|
}
|
|
3478
4676
|
),
|
|
3479
|
-
/* @__PURE__ */
|
|
4677
|
+
/* @__PURE__ */ jsx26(
|
|
3480
4678
|
"div",
|
|
3481
4679
|
{
|
|
3482
4680
|
className: "gridkit-data-grid-body",
|
|
@@ -3484,15 +4682,16 @@ function DataGrid(props) {
|
|
|
3484
4682
|
style: height === void 0 ? void 0 : {
|
|
3485
4683
|
"--gridkit-body-height": typeof height === "number" ? `${String(height)}px` : height
|
|
3486
4684
|
},
|
|
3487
|
-
children: /* @__PURE__ */
|
|
4685
|
+
children: /* @__PURE__ */ jsxs19(
|
|
3488
4686
|
"table",
|
|
3489
4687
|
{
|
|
3490
4688
|
ref: bodyTableRef,
|
|
4689
|
+
role: "presentation",
|
|
3491
4690
|
style: { width: totalColumnWidth(view.columns) },
|
|
3492
4691
|
className: gridTableClassName,
|
|
3493
4692
|
children: [
|
|
3494
|
-
/* @__PURE__ */
|
|
3495
|
-
/* @__PURE__ */
|
|
4693
|
+
/* @__PURE__ */ jsx26(GridColgroup, { columns: view.columns }),
|
|
4694
|
+
/* @__PURE__ */ jsx26(
|
|
3496
4695
|
GridBody,
|
|
3497
4696
|
{
|
|
3498
4697
|
columns: view.columns,
|
|
@@ -3521,17 +4720,18 @@ function DataGrid(props) {
|
|
|
3521
4720
|
)
|
|
3522
4721
|
}
|
|
3523
4722
|
),
|
|
3524
|
-
aggregates.length > 0 && /* @__PURE__ */
|
|
4723
|
+
aggregates.length > 0 && /* @__PURE__ */ jsxs19(
|
|
3525
4724
|
"table",
|
|
3526
4725
|
{
|
|
4726
|
+
role: "presentation",
|
|
3527
4727
|
style: { width: totalColumnWidth(view.columns) },
|
|
3528
4728
|
className: classNames(
|
|
3529
4729
|
gridTableClassName,
|
|
3530
4730
|
"gridkit-data-grid-footer"
|
|
3531
4731
|
),
|
|
3532
4732
|
children: [
|
|
3533
|
-
/* @__PURE__ */
|
|
3534
|
-
/* @__PURE__ */
|
|
4733
|
+
/* @__PURE__ */ jsx26(GridColgroup, { columns: view.columns }),
|
|
4734
|
+
/* @__PURE__ */ jsx26(
|
|
3535
4735
|
GridFooter,
|
|
3536
4736
|
{
|
|
3537
4737
|
columns: view.columns,
|
|
@@ -3547,9 +4747,17 @@ function DataGrid(props) {
|
|
|
3547
4747
|
]
|
|
3548
4748
|
}
|
|
3549
4749
|
),
|
|
3550
|
-
/* @__PURE__ */
|
|
3551
|
-
/* @__PURE__ */
|
|
3552
|
-
|
|
4750
|
+
/* @__PURE__ */ jsx26(GridContextMenu, { contextMenu }),
|
|
4751
|
+
/* @__PURE__ */ jsx26(
|
|
4752
|
+
GridPanels,
|
|
4753
|
+
{
|
|
4754
|
+
panels,
|
|
4755
|
+
controller,
|
|
4756
|
+
commands,
|
|
4757
|
+
messages
|
|
4758
|
+
}
|
|
4759
|
+
),
|
|
4760
|
+
paginated && (pager?.template ? pager.template(pagerContext) : /* @__PURE__ */ jsx26(GridPager, { pager: pagerContext, config: pager, messages }))
|
|
3553
4761
|
] });
|
|
3554
4762
|
}
|
|
3555
4763
|
|
|
@@ -3573,10 +4781,14 @@ function useGridSnapshot(gridRef, getSnapshot, fallback) {
|
|
|
3573
4781
|
},
|
|
3574
4782
|
[gridRef]
|
|
3575
4783
|
);
|
|
3576
|
-
return useSyncExternalStore3(
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
4784
|
+
return useSyncExternalStore3(
|
|
4785
|
+
subscribe,
|
|
4786
|
+
() => {
|
|
4787
|
+
const api = gridRef.current;
|
|
4788
|
+
return api === null ? fallback : getSnapshot(api);
|
|
4789
|
+
},
|
|
4790
|
+
() => fallback
|
|
4791
|
+
);
|
|
3580
4792
|
}
|
|
3581
4793
|
|
|
3582
4794
|
// src/DataGrid/hooks/usePaginationState.ts
|
|
@@ -3726,9 +4938,9 @@ function useColumnVisibilityState(gridRef) {
|
|
|
3726
4938
|
}
|
|
3727
4939
|
|
|
3728
4940
|
// src/DataGrid/hooks/useFilterState.ts
|
|
3729
|
-
import { useCallback as useCallback11, useState as
|
|
4941
|
+
import { useCallback as useCallback11, useState as useState21 } from "react";
|
|
3730
4942
|
function useFilterState(gridRef) {
|
|
3731
|
-
const [fallback] =
|
|
4943
|
+
const [fallback] = useState21(() => []);
|
|
3732
4944
|
const filter = useGridSnapshot(
|
|
3733
4945
|
gridRef,
|
|
3734
4946
|
useCallback11((api) => api.getFilter(), []),
|
|
@@ -3741,8 +4953,12 @@ function useFilterState(gridRef) {
|
|
|
3741
4953
|
}
|
|
3742
4954
|
};
|
|
3743
4955
|
}
|
|
4956
|
+
|
|
4957
|
+
// src/index.ts
|
|
4958
|
+
import { excelFilter } from "@gridkitjs/core";
|
|
3744
4959
|
export {
|
|
3745
4960
|
DataGrid,
|
|
4961
|
+
excelFilter,
|
|
3746
4962
|
serializeGridState,
|
|
3747
4963
|
useAggregateState,
|
|
3748
4964
|
useColumnOrderState,
|