@gridkitjs/react 0.10.0 → 0.11.1

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/dist/index.js CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  // src/DataGrid/DataGrid.tsx
4
4
  import {
5
- useEffect as useEffect3,
5
+ useEffect as useEffect5,
6
+ useId,
6
7
  useImperativeHandle,
7
- useMemo as useMemo3,
8
- useRef as useRef4,
9
- useState as useState8
8
+ useMemo as useMemo4,
9
+ useRef as useRef13,
10
+ useState as useState15
10
11
  } from "react";
11
12
  import {
12
13
  moveColumnBefore,
@@ -42,6 +43,45 @@ function classNames(...values) {
42
43
  return values.filter(Boolean).join(" ");
43
44
  }
44
45
 
46
+ // src/DataGrid/icons.tsx
47
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
48
+ function Icon({ children }) {
49
+ return /* @__PURE__ */ jsx2(
50
+ "svg",
51
+ {
52
+ viewBox: "0 0 24 24",
53
+ fill: "none",
54
+ stroke: "currentColor",
55
+ strokeWidth: 2,
56
+ strokeLinecap: "round",
57
+ strokeLinejoin: "round",
58
+ "aria-hidden": "true",
59
+ children
60
+ }
61
+ );
62
+ }
63
+ function ChevronsUpDownIcon() {
64
+ return /* @__PURE__ */ jsxs(Icon, { children: [
65
+ /* @__PURE__ */ jsx2("path", { d: "m7 15 5 5 5-5" }),
66
+ /* @__PURE__ */ jsx2("path", { d: "m7 9 5-5 5 5" })
67
+ ] });
68
+ }
69
+ function ChevronUpIcon() {
70
+ return /* @__PURE__ */ jsx2(Icon, { children: /* @__PURE__ */ jsx2("path", { d: "m18 15-6-6-6 6" }) });
71
+ }
72
+ function GroupIcon() {
73
+ return /* @__PURE__ */ jsxs(Icon, { children: [
74
+ /* @__PURE__ */ jsx2("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }),
75
+ /* @__PURE__ */ jsx2("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }),
76
+ /* @__PURE__ */ jsx2("rect", { x: "8.5", y: "14", width: "7", height: "7", rx: "1" })
77
+ ] });
78
+ }
79
+
80
+ // src/DataGrid/isOwnEvent.ts
81
+ function isOwnEvent(event) {
82
+ return event.target instanceof Node && event.currentTarget.contains(event.target);
83
+ }
84
+
45
85
  // src/DataGrid/useGridNavigation.ts
46
86
  import {
47
87
  useEffect,
@@ -75,13 +115,11 @@ function useGridNavigation({
75
115
  const [gridFocus] = useState(() => createGridFocus(options));
76
116
  gridFocus.setOptions(options);
77
117
  const focus = useSyncExternalStore(gridFocus.subscribe, gridFocus.getFocus);
78
- useLayoutEffect(
79
- () => gridFocus.attach({
80
- getHeaderRow: () => headerTableRef.current?.tHead?.rows[0] ?? null,
81
- getBodyRow: (rowIndex) => findBodyRow(bodyTableRef.current, rowIndex)
82
- }),
83
- [gridFocus, headerTableRef, bodyTableRef]
84
- );
118
+ const [rows] = useState(() => ({
119
+ getHeaderRow: () => headerTableRef.current?.tHead?.rows[0] ?? null,
120
+ getBodyRow: (rowIndex) => findBodyRow(bodyTableRef.current, rowIndex)
121
+ }));
122
+ useLayoutEffect(() => gridFocus.attach(rows), [gridFocus, rows]);
85
123
  useEffect(() => {
86
124
  gridFocus.focusDrawnCell(focus);
87
125
  });
@@ -92,6 +130,14 @@ function useGridNavigation({
92
130
  rowIndex === focus.rowIndex ? focus.columnIndex : null
93
131
  ),
94
132
  focusCell: gridFocus.focusCell,
133
+ focusCellNow: (rowIndex, columnIndex) => {
134
+ gridFocus.focusCell(rowIndex, columnIndex);
135
+ gridFocus.focusDrawnCell(gridFocus.getFocus());
136
+ },
137
+ focusTabStop: () => {
138
+ const cells = (focus.rowIndex === HEADER_ROW ? rows.getHeaderRow() : rows.getBodyRow(focus.rowIndex))?.cells;
139
+ cells?.[Math.min(focus.columnIndex, cells.length - 1)]?.focus();
140
+ },
95
141
  onKeyDown: (event) => {
96
142
  if (gridFocus.handleKey(
97
143
  event.key,
@@ -143,38 +189,7 @@ function useGridSelection({
143
189
  }
144
190
 
145
191
  // src/DataGrid/components/GridHeader.tsx
146
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
147
- function Icon({ children }) {
148
- return /* @__PURE__ */ jsx2(
149
- "svg",
150
- {
151
- viewBox: "0 0 24 24",
152
- fill: "none",
153
- stroke: "currentColor",
154
- strokeWidth: 2,
155
- strokeLinecap: "round",
156
- strokeLinejoin: "round",
157
- "aria-hidden": "true",
158
- children
159
- }
160
- );
161
- }
162
- function ChevronsUpDownIcon() {
163
- return /* @__PURE__ */ jsxs(Icon, { children: [
164
- /* @__PURE__ */ jsx2("path", { d: "m7 15 5 5 5-5" }),
165
- /* @__PURE__ */ jsx2("path", { d: "m7 9 5-5 5 5" })
166
- ] });
167
- }
168
- function ChevronUpIcon() {
169
- return /* @__PURE__ */ jsx2(Icon, { children: /* @__PURE__ */ jsx2("path", { d: "m18 15-6-6-6 6" }) });
170
- }
171
- function GroupIcon() {
172
- return /* @__PURE__ */ jsxs(Icon, { children: [
173
- /* @__PURE__ */ jsx2("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }),
174
- /* @__PURE__ */ jsx2("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }),
175
- /* @__PURE__ */ jsx2("rect", { x: "8.5", y: "14", width: "7", height: "7", rx: "1" })
176
- ] });
177
- }
192
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
178
193
  function GridHeader({
179
194
  columns,
180
195
  resize,
@@ -185,13 +200,14 @@ function GridHeader({
185
200
  groupBy,
186
201
  groupableColumns,
187
202
  groupToggleIconColumns,
203
+ headerMenu,
188
204
  nav,
189
205
  selection
190
206
  }) {
191
207
  const beforeId = drag.dropTarget?.kind === "column-order" ? drag.dropTarget.beforeId : void 0;
192
208
  const draggedEntry = columns.find((entry) => entry.id === drag.draggedColumnId) ?? null;
193
- return /* @__PURE__ */ jsxs("thead", { children: [
194
- /* @__PURE__ */ jsx2("tr", { className: "grid-header", role: "row", "aria-rowindex": 1, children: columns.map((entry, index) => {
209
+ return /* @__PURE__ */ jsxs2("thead", { children: [
210
+ /* @__PURE__ */ jsx3("tr", { className: "grid-header", role: "row", "aria-rowindex": 1, children: columns.map((entry, index) => {
195
211
  const { column } = entry;
196
212
  const resizing = resize.activeColumnId === entry.id;
197
213
  const dragging = drag.draggedColumnId === entry.id;
@@ -210,9 +226,10 @@ function GridHeader({
210
226
  reorderable: entry.reorderable,
211
227
  resizable: entry.resizable,
212
228
  sortable,
213
- groupable
229
+ groupable,
230
+ contextMenu: headerMenu
214
231
  });
215
- return /* @__PURE__ */ jsxs(
232
+ return /* @__PURE__ */ jsxs2(
216
233
  "th",
217
234
  {
218
235
  scope: "col",
@@ -238,6 +255,7 @@ function GridHeader({
238
255
  selection.selectColumn(entry.id, intentOf(event));
239
256
  },
240
257
  onKeyDown: (event) => {
258
+ if (!isOwnEvent(event)) return;
241
259
  const horizontal = event.key === "ArrowLeft" || event.key === "ArrowRight";
242
260
  const direction = event.key === "ArrowLeft" ? -1 : 1;
243
261
  if (horizontal && event.ctrlKey && entry.reorderable) {
@@ -313,7 +331,7 @@ function GridHeader({
313
331
  * A pointer affordance only, same as the other two — the
314
332
  * keyboard equivalent is Alt+ArrowDown on the header itself.
315
333
  */
316
- /* @__PURE__ */ jsx2(
334
+ /* @__PURE__ */ jsx3(
317
335
  "span",
318
336
  {
319
337
  className: classNames(
@@ -329,7 +347,7 @@ function GridHeader({
329
347
  event.stopPropagation();
330
348
  controller.toggleGroupBy(entry.id);
331
349
  },
332
- children: /* @__PURE__ */ jsx2(GroupIcon, {})
350
+ children: /* @__PURE__ */ jsx3(GroupIcon, {})
333
351
  }
334
352
  ),
335
353
  entry.label,
@@ -339,7 +357,7 @@ function GridHeader({
339
357
  * lives on the header itself, under Alt+ArrowUp (plain) /
340
358
  * Alt+Shift+ArrowUp (stacking).
341
359
  */
342
- /* @__PURE__ */ jsxs(
360
+ /* @__PURE__ */ jsxs2(
343
361
  "span",
344
362
  {
345
363
  className: classNames(
@@ -357,8 +375,8 @@ function GridHeader({
357
375
  });
358
376
  },
359
377
  children: [
360
- sortDirection === null ? /* @__PURE__ */ jsx2(ChevronsUpDownIcon, {}) : /* @__PURE__ */ jsx2(ChevronUpIcon, {}),
361
- sortPriority !== null && sortPriority > 1 && /* @__PURE__ */ jsx2("span", { className: "header-sort-priority", children: sortPriority })
378
+ sortDirection === null ? /* @__PURE__ */ jsx3(ChevronsUpDownIcon, {}) : /* @__PURE__ */ jsx3(ChevronUpIcon, {}),
379
+ sortPriority !== null && sortPriority > 1 && /* @__PURE__ */ jsx3("span", { className: "header-sort-priority", children: sortPriority })
362
380
  ]
363
381
  }
364
382
  ),
@@ -368,7 +386,7 @@ function GridHeader({
368
386
  * put N tab stops inside a widget that is meant to have one.
369
387
  * The keyboard resizes from the header itself, under Alt.
370
388
  */
371
- /* @__PURE__ */ jsx2(
389
+ /* @__PURE__ */ jsx3(
372
390
  "span",
373
391
  {
374
392
  className: "header-resize-handle",
@@ -388,7 +406,7 @@ function GridHeader({
388
406
  );
389
407
  }) }),
390
408
  draggedEntry !== null && drag.ghostTransform !== null && createPortal(
391
- /* @__PURE__ */ jsx2(
409
+ /* @__PURE__ */ jsx3(
392
410
  "div",
393
411
  {
394
412
  className: "gridkit-data-grid header-cell drag-ghost",
@@ -473,7 +491,7 @@ function renderAggregate(value, spec, column, rows, locale) {
473
491
  }
474
492
 
475
493
  // src/DataGrid/components/GridGroupRow.tsx
476
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
494
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
477
495
  function formatGroupValue(value, column, locale, messages) {
478
496
  return value === null || value === void 0 ? messages.blankGroupValue : formatCellValue(value, column, locale, void 0, messages);
479
497
  }
@@ -490,6 +508,7 @@ function GridGroupRowComponent({
490
508
  posinset,
491
509
  setsize,
492
510
  focused,
511
+ contextMenu,
493
512
  aggregates,
494
513
  results,
495
514
  definitions,
@@ -497,7 +516,7 @@ function GridGroupRowComponent({
497
516
  cellMessages,
498
517
  ref
499
518
  }) {
500
- return /* @__PURE__ */ jsx3(
519
+ return /* @__PURE__ */ jsx4(
501
520
  "tr",
502
521
  {
503
522
  ref,
@@ -513,21 +532,21 @@ function GridGroupRowComponent({
513
532
  "grid-group-row",
514
533
  `is-group-level-${String(level)}`
515
534
  ),
516
- children: /* @__PURE__ */ jsx3(
535
+ children: /* @__PURE__ */ jsx4(
517
536
  "td",
518
537
  {
519
538
  role: "gridcell",
520
539
  colSpan: columnCount,
521
540
  tabIndex: focused ? 0 : -1,
522
- "aria-keyshortcuts": "Space Enter",
541
+ "aria-keyshortcuts": contextMenu ? "Space Enter Shift+F10" : "Space Enter",
523
542
  className: "grid-group-cell",
524
- children: /* @__PURE__ */ jsxs2(
543
+ children: /* @__PURE__ */ jsxs3(
525
544
  "div",
526
545
  {
527
546
  className: "grid-group-cell-content",
528
547
  style: { paddingInlineStart: `${String(level * 1.25 + 0.5)}rem` },
529
548
  children: [
530
- /* @__PURE__ */ jsx3(
549
+ /* @__PURE__ */ jsx4(
531
550
  "span",
532
551
  {
533
552
  className: classNames(
@@ -537,18 +556,18 @@ function GridGroupRowComponent({
537
556
  "aria-hidden": "true"
538
557
  }
539
558
  ),
540
- /* @__PURE__ */ jsxs2("span", { className: "group-label", children: [
559
+ /* @__PURE__ */ jsxs3("span", { className: "group-label", children: [
541
560
  resolveColumnLabel(groupColumn),
542
561
  ":",
543
562
  " ",
544
563
  formatGroupValue(value, groupColumn, locale, cellMessages)
545
564
  ] }),
546
- /* @__PURE__ */ jsxs2("span", { className: "group-count", children: [
565
+ /* @__PURE__ */ jsxs3("span", { className: "group-count", children: [
547
566
  "(",
548
567
  count,
549
568
  ")"
550
569
  ] }),
551
- aggregates.length > 0 && /* @__PURE__ */ jsx3("span", { className: "group-aggregates", children: aggregates.map((spec) => {
570
+ aggregates.length > 0 && /* @__PURE__ */ jsx4("span", { className: "group-aggregates", children: aggregates.map((spec) => {
552
571
  const key = spec.id ?? spec.columnId;
553
572
  const aggregateValue = results.get(key);
554
573
  const column = definitions.get(spec.columnId);
@@ -560,7 +579,7 @@ function GridGroupRowComponent({
560
579
  locale
561
580
  );
562
581
  const aggregateLabel = spec.id ?? (column === void 0 ? spec.columnId : resolveColumnLabel(column));
563
- return /* @__PURE__ */ jsxs2("span", { className: "group-aggregate", children: [
582
+ return /* @__PURE__ */ jsxs3("span", { className: "group-aggregate", children: [
564
583
  aggregateLabel,
565
584
  ": ",
566
585
  rendered
@@ -581,7 +600,7 @@ var GridGroupRow_default = GridGroupRow;
581
600
 
582
601
  // src/DataGrid/components/GridGroupSummaryRow.tsx
583
602
  import { memo as memo2 } from "react";
584
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
603
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
585
604
  function GridGroupSummaryRowComponent({
586
605
  groupId,
587
606
  level,
@@ -593,7 +612,7 @@ function GridGroupSummaryRowComponent({
593
612
  locale,
594
613
  ref
595
614
  }) {
596
- return /* @__PURE__ */ jsx4(
615
+ return /* @__PURE__ */ jsx5(
597
616
  "tr",
598
617
  {
599
618
  ref,
@@ -609,7 +628,7 @@ function GridGroupSummaryRowComponent({
609
628
  const specs = aggregates.filter(
610
629
  (candidate) => candidate.columnId === entry.id
611
630
  );
612
- return /* @__PURE__ */ jsxs3(
631
+ return /* @__PURE__ */ jsxs4(
613
632
  "td",
614
633
  {
615
634
  role: "gridcell",
@@ -617,7 +636,7 @@ function GridGroupSummaryRowComponent({
617
636
  className: "grid-group-summary-cell",
618
637
  style: { textAlign: specs[0]?.alignment ?? entry.alignment },
619
638
  children: [
620
- entry.id === columns[0]?.id && /* @__PURE__ */ jsx4(
639
+ entry.id === columns[0]?.id && /* @__PURE__ */ jsx5(
621
640
  "span",
622
641
  {
623
642
  className: "grid-group-summary-indent",
@@ -655,7 +674,7 @@ import {
655
674
  formatCellValue as formatCellValue2
656
675
  } from "@gridkitjs/core";
657
676
  import { memo as memo3 } from "react";
658
- import { jsx as jsx5 } from "react/jsx-runtime";
677
+ import { jsx as jsx6 } from "react/jsx-runtime";
659
678
  function GridRowComponent({
660
679
  columns,
661
680
  rowId,
@@ -669,13 +688,18 @@ function GridRowComponent({
669
688
  focusedColumnIndex,
670
689
  rowsSelectable,
671
690
  cellsSelectable,
691
+ contextMenu,
672
692
  locale,
673
693
  cellMessages,
674
694
  rowClassName,
675
695
  rowAttributes,
676
696
  ref
677
697
  }) {
678
- return /* @__PURE__ */ jsx5(
698
+ const shortcuts = [
699
+ cellsSelectable ? "Space Enter" : "",
700
+ contextMenu ? "Shift+F10" : ""
701
+ ].filter(Boolean).join(" ");
702
+ return /* @__PURE__ */ jsx6(
679
703
  "tr",
680
704
  {
681
705
  ...rowAttributes,
@@ -693,7 +717,7 @@ function GridRowComponent({
693
717
  children: columns.map(({ id, column, alignment }, columnIndex) => {
694
718
  const value = accessDotted(row, column.field);
695
719
  const cellSelected = id === selectedColumnId;
696
- return /* @__PURE__ */ jsx5(
720
+ return /* @__PURE__ */ jsx6(
697
721
  "td",
698
722
  {
699
723
  role: "gridcell",
@@ -701,7 +725,7 @@ function GridRowComponent({
701
725
  "aria-colindex": columnIndex + 1,
702
726
  tabIndex: tabIndexFor(columnIndex, focusedColumnIndex),
703
727
  ...ariaAttr(cellsSelectable, "aria-selected", cellSelected),
704
- ...ariaAttr(cellsSelectable, "aria-keyshortcuts", "Space Enter"),
728
+ ...ariaAttr(shortcuts !== "", "aria-keyshortcuts", shortcuts),
705
729
  className: classNames(
706
730
  "grid-cell",
707
731
  id === activeColumnId ? "is-resizing" : "",
@@ -729,7 +753,7 @@ var GridRow = memo3(GridRowComponent);
729
753
  var GridRow_default = GridRow;
730
754
 
731
755
  // src/DataGrid/components/GridBody.tsx
732
- import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
756
+ import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
733
757
  function groupAriaMeta(rows) {
734
758
  const totals = /* @__PURE__ */ new Map();
735
759
  for (const entry of rows) {
@@ -768,7 +792,9 @@ function GridBody({
768
792
  getRowProps,
769
793
  onRowClick,
770
794
  onRowDoubleClick,
771
- messages
795
+ messages,
796
+ cellMenu,
797
+ groupMenu
772
798
  }) {
773
799
  const { selectedCell, rowMode, cellMode, toggleOnClick } = selection;
774
800
  const ariaMeta = useMemo2(() => groupAriaMeta(rows), [rows]);
@@ -826,7 +852,7 @@ function GridBody({
826
852
  callback(pointer);
827
853
  }
828
854
  }
829
- return /* @__PURE__ */ jsxs4(
855
+ return /* @__PURE__ */ jsxs5(
830
856
  "tbody",
831
857
  {
832
858
  className: "grid-body",
@@ -856,6 +882,7 @@ function GridBody({
856
882
  reportRowPointer(event, onRowDoubleClick);
857
883
  },
858
884
  onKeyDown: (event) => {
885
+ if (!isOwnEvent(event)) return;
859
886
  const group = groupRowFrom(event.target);
860
887
  if (group !== null) {
861
888
  if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
@@ -890,7 +917,7 @@ function GridBody({
890
917
  // to give the browser's scrollbar the correct total height and thumb
891
918
  // position, the same way `GridFooter`'s `<tfoot>` isn't a "row" to
892
919
  // any of this grid's own row-counting logic.
893
- /* @__PURE__ */ jsx6("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
920
+ /* @__PURE__ */ jsx7("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx7(
894
921
  "td",
895
922
  {
896
923
  style: {
@@ -903,7 +930,7 @@ function GridBody({
903
930
  visibleRows.map((entry) => {
904
931
  if (!("kind" in entry)) {
905
932
  const rowProps = rowPropsOf(entry.rowId);
906
- return /* @__PURE__ */ jsx6(
933
+ return /* @__PURE__ */ jsx7(
907
934
  GridRow_default,
908
935
  {
909
936
  ref: virtualRange?.measureRow(entry.rowIndex),
@@ -919,6 +946,7 @@ function GridBody({
919
946
  focusedColumnIndex: nav.focus.rowIndex === entry.rowIndex ? nav.focus.columnIndex : null,
920
947
  rowsSelectable: rowMode !== false,
921
948
  cellsSelectable: cellMode !== false,
949
+ contextMenu: cellMenu,
922
950
  locale,
923
951
  cellMessages,
924
952
  rowClassName: rowProps.className,
@@ -928,7 +956,7 @@ function GridBody({
928
956
  );
929
957
  }
930
958
  if (entry.kind === "group-summary") {
931
- return /* @__PURE__ */ jsx6(
959
+ return /* @__PURE__ */ jsx7(
932
960
  GridGroupSummaryRow_default,
933
961
  {
934
962
  ref: virtualRange?.measureRow(entry.rowIndex),
@@ -944,7 +972,7 @@ function GridBody({
944
972
  `${entry.groupId}-summary`
945
973
  );
946
974
  }
947
- return /* @__PURE__ */ jsx6(
975
+ return /* @__PURE__ */ jsx7(
948
976
  GridGroupRow_default,
949
977
  {
950
978
  ref: virtualRange?.measureRow(entry.rowIndex),
@@ -964,12 +992,13 @@ function GridBody({
964
992
  definitions,
965
993
  locale,
966
994
  cellMessages,
967
- focused: nav.focus.rowIndex === entry.rowIndex
995
+ focused: nav.focus.rowIndex === entry.rowIndex,
996
+ contextMenu: groupMenu
968
997
  },
969
998
  entry.groupId
970
999
  );
971
1000
  }),
972
- virtualRange !== null && virtualRange.offsetAfter > 0 && /* @__PURE__ */ jsx6("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx6(
1001
+ virtualRange !== null && virtualRange.offsetAfter > 0 && /* @__PURE__ */ jsx7("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx7(
973
1002
  "td",
974
1003
  {
975
1004
  style: {
@@ -979,15 +1008,15 @@ function GridBody({
979
1008
  }
980
1009
  }
981
1010
  ) }),
982
- infiniteScroll?.hasMore && /* @__PURE__ */ jsxs4(Fragment, { children: [
983
- infiniteScroll.isLoadingMore === true && /* @__PURE__ */ jsx6("tr", { "aria-hidden": "true", className: "grid-loading-row", children: /* @__PURE__ */ jsx6("td", { colSpan: columns.length, className: "grid-loading-cell", children: infiniteScroll.loadingTemplate ? infiniteScroll.loadingTemplate() : messages.loadingMore }) }),
984
- /* @__PURE__ */ jsx6(
1011
+ infiniteScroll?.hasMore && /* @__PURE__ */ jsxs5(Fragment, { children: [
1012
+ infiniteScroll.isLoadingMore === true && /* @__PURE__ */ jsx7("tr", { "aria-hidden": "true", className: "grid-loading-row", children: /* @__PURE__ */ jsx7("td", { colSpan: columns.length, className: "grid-loading-cell", children: infiniteScroll.loadingTemplate ? infiniteScroll.loadingTemplate() : messages.loadingMore }) }),
1013
+ /* @__PURE__ */ jsx7(
985
1014
  "tr",
986
1015
  {
987
1016
  "aria-hidden": "true",
988
1017
  ref: sentinelRef,
989
1018
  className: "grid-sentinel-row",
990
- children: /* @__PURE__ */ jsx6(
1019
+ children: /* @__PURE__ */ jsx7(
991
1020
  "td",
992
1021
  {
993
1022
  colSpan: columns.length,
@@ -1003,7 +1032,7 @@ function GridBody({
1003
1032
  }
1004
1033
 
1005
1034
  // src/DataGrid/components/GridFooter.tsx
1006
- import { jsx as jsx7 } from "react/jsx-runtime";
1035
+ import { jsx as jsx8 } from "react/jsx-runtime";
1007
1036
  function GridFooter({
1008
1037
  columns,
1009
1038
  aggregates,
@@ -1011,11 +1040,11 @@ function GridFooter({
1011
1040
  rows,
1012
1041
  locale
1013
1042
  }) {
1014
- return /* @__PURE__ */ jsx7("tfoot", { children: /* @__PURE__ */ jsx7("tr", { className: "grid-footer", role: "row", children: columns.map((entry) => {
1043
+ return /* @__PURE__ */ jsx8("tfoot", { children: /* @__PURE__ */ jsx8("tr", { className: "grid-footer", role: "row", children: columns.map((entry) => {
1015
1044
  const specs = aggregates.filter(
1016
1045
  (candidate) => candidate.columnId === entry.id
1017
1046
  );
1018
- return /* @__PURE__ */ jsx7(
1047
+ return /* @__PURE__ */ jsx8(
1019
1048
  "td",
1020
1049
  {
1021
1050
  role: "gridcell",
@@ -1041,19 +1070,19 @@ function GridFooter({
1041
1070
 
1042
1071
  // src/DataGrid/components/GridPager.tsx
1043
1072
  import { paginationWindow } from "@gridkitjs/core";
1044
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1073
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1045
1074
  function GridPager({ pager, config, messages }) {
1046
1075
  const { pagination, pageCount, currentPage } = pager;
1047
1076
  const variant = config?.variant ?? "compact";
1048
1077
  const sizeOptions = config?.sizeOptions;
1049
- return /* @__PURE__ */ jsxs5(
1078
+ return /* @__PURE__ */ jsxs6(
1050
1079
  "div",
1051
1080
  {
1052
1081
  className: "gridkit-grid-pager",
1053
1082
  role: "group",
1054
1083
  "aria-label": messages.pagerLabel,
1055
1084
  children: [
1056
- /* @__PURE__ */ jsx8(
1085
+ /* @__PURE__ */ jsx9(
1057
1086
  "button",
1058
1087
  {
1059
1088
  type: "button",
@@ -1069,7 +1098,7 @@ function GridPager({ pager, config, messages }) {
1069
1098
  boundaryCount: config?.boundaryCount,
1070
1099
  siblingCount: config?.siblingCount
1071
1100
  }).map(
1072
- (entry, index) => entry === "ellipsis" ? /* @__PURE__ */ jsx8(
1101
+ (entry, index) => entry === "ellipsis" ? /* @__PURE__ */ jsx9(
1073
1102
  "span",
1074
1103
  {
1075
1104
  className: "grid-pager-ellipsis",
@@ -1077,7 +1106,7 @@ function GridPager({ pager, config, messages }) {
1077
1106
  children: "\u2026"
1078
1107
  },
1079
1108
  `ellipsis-${String(index)}`
1080
- ) : /* @__PURE__ */ jsx8(
1109
+ ) : /* @__PURE__ */ jsx9(
1081
1110
  "button",
1082
1111
  {
1083
1112
  type: "button",
@@ -1091,8 +1120,8 @@ function GridPager({ pager, config, messages }) {
1091
1120
  },
1092
1121
  entry
1093
1122
  )
1094
- ) : /* @__PURE__ */ jsx8("span", { className: "grid-pager-status", children: messages.pageStatus(pageCount === 0 ? 0 : currentPage, pageCount) }),
1095
- /* @__PURE__ */ jsx8(
1123
+ ) : /* @__PURE__ */ jsx9("span", { className: "grid-pager-status", children: messages.pageStatus(pageCount === 0 ? 0 : currentPage, pageCount) }),
1124
+ /* @__PURE__ */ jsx9(
1096
1125
  "button",
1097
1126
  {
1098
1127
  type: "button",
@@ -1104,16 +1133,16 @@ function GridPager({ pager, config, messages }) {
1104
1133
  children: messages.nextPage
1105
1134
  }
1106
1135
  ),
1107
- sizeOptions !== void 0 && sizeOptions.length > 0 && /* @__PURE__ */ jsxs5("label", { className: "grid-pager-page-size", children: [
1136
+ sizeOptions !== void 0 && sizeOptions.length > 0 && /* @__PURE__ */ jsxs6("label", { className: "grid-pager-page-size", children: [
1108
1137
  messages.pageSizeLabel,
1109
- /* @__PURE__ */ jsx8(
1138
+ /* @__PURE__ */ jsx9(
1110
1139
  "select",
1111
1140
  {
1112
1141
  value: pagination.pageSize,
1113
1142
  onChange: (event) => {
1114
1143
  pager.setPageSize(Number(event.target.value));
1115
1144
  },
1116
- children: sizeOptions.map((size) => /* @__PURE__ */ jsx8("option", { value: size, children: size }, size))
1145
+ children: sizeOptions.map((size) => /* @__PURE__ */ jsx9("option", { value: size, children: size }, size))
1117
1146
  }
1118
1147
  )
1119
1148
  ] })
@@ -1198,7 +1227,7 @@ function useGroupByDrag({
1198
1227
  }
1199
1228
 
1200
1229
  // src/DataGrid/components/GroupByBar.tsx
1201
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1230
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1202
1231
  function GroupByBar({
1203
1232
  columns,
1204
1233
  definitions,
@@ -1235,7 +1264,7 @@ function GroupByBar({
1235
1264
  }
1236
1265
  controller.moveGroupBy(columnId, beforeColumnId);
1237
1266
  }
1238
- return /* @__PURE__ */ jsxs6(
1267
+ return /* @__PURE__ */ jsxs7(
1239
1268
  "div",
1240
1269
  {
1241
1270
  className: classNames(
@@ -1247,12 +1276,12 @@ function GroupByBar({
1247
1276
  role: "group",
1248
1277
  "aria-label": messages.groupByBarLabel,
1249
1278
  children: [
1250
- showPlaceholder && /* @__PURE__ */ jsx9("span", { className: "group-by-bar-placeholder", children: messages.groupByBarPlaceholder }),
1279
+ showPlaceholder && /* @__PURE__ */ jsx10("span", { className: "group-by-bar-placeholder", children: messages.groupByBarPlaceholder }),
1251
1280
  groupBy.map((entry, index) => {
1252
1281
  const dropBefore = activeDropTarget?.beforeColumnId === entry.columnId;
1253
1282
  const dropAfter = activeDropTarget?.beforeColumnId === null && index === groupBy.length - 1;
1254
1283
  const dragging = chipDrag.draggedColumnId === entry.columnId;
1255
- return /* @__PURE__ */ jsxs6(
1284
+ return /* @__PURE__ */ jsxs7(
1256
1285
  "span",
1257
1286
  {
1258
1287
  className: classNames(
@@ -1283,8 +1312,8 @@ function GroupByBar({
1283
1312
  }
1284
1313
  },
1285
1314
  children: [
1286
- /* @__PURE__ */ jsx9("span", { className: "group-by-chip-label", children: labelFor(entry.columnId) }),
1287
- /* @__PURE__ */ jsx9(
1315
+ /* @__PURE__ */ jsx10("span", { className: "group-by-chip-label", children: labelFor(entry.columnId) }),
1316
+ /* @__PURE__ */ jsx10(
1288
1317
  "button",
1289
1318
  {
1290
1319
  type: "button",
@@ -1305,7 +1334,7 @@ function GroupByBar({
1305
1334
  );
1306
1335
  }),
1307
1336
  chipDrag.draggedColumnId !== null && chipDrag.ghostTransform !== null && createPortal2(
1308
- /* @__PURE__ */ jsx9(
1337
+ /* @__PURE__ */ jsx10(
1309
1338
  "span",
1310
1339
  {
1311
1340
  className: "group-by-chip drag-ghost",
@@ -1321,127 +1350,1554 @@ function GroupByBar({
1321
1350
  );
1322
1351
  }
1323
1352
 
1324
- // src/DataGrid/useColumnDrag.ts
1353
+ // src/DataGrid/announcedCallbacks.ts
1325
1354
  import {
1326
- resolveKeyboardDropTarget as resolveKeyboardDropTarget2
1355
+ isColumnVisible
1327
1356
  } from "@gridkitjs/core";
1328
- import { resolveColumnDropTarget } from "@gridkitjs/dom";
1329
- function useColumnDrag({
1330
- order,
1331
- groupBy,
1332
- groupByDraggableIds,
1333
- onDrop
1357
+ function announcedCallbacks({
1358
+ callbacks,
1359
+ announce,
1360
+ messages,
1361
+ columnName,
1362
+ columnOf
1334
1363
  }) {
1335
- const drag = useDragReorder({
1336
- resolveTarget: (clientX, clientY, movedId) => resolveColumnDropTarget(clientX, clientY, movedId, {
1337
- order,
1338
- groupBy,
1339
- groupByDraggableIds
1340
- }),
1341
- onDrop
1342
- });
1343
- function startDrag(entry, event) {
1344
- drag.startDrag(entry.id, event.currentTarget, event);
1345
- }
1346
- function moveByKeyboard(entry, direction) {
1347
- const beforeId = resolveKeyboardDropTarget2(order, entry.id, direction);
1348
- if (beforeId === void 0) {
1349
- return;
1350
- }
1351
- onDrop({ kind: "column-order", beforeId }, entry.id);
1352
- }
1353
1364
  return {
1354
- draggedColumnId: drag.draggedId,
1355
- dropTarget: drag.dropTarget,
1356
- ghostTransform: drag.ghostTransform,
1357
- startDrag,
1358
- moveByKeyboard,
1359
- justDragged: drag.justDragged
1365
+ /**
1366
+ * Announced only once the drag ends: the controller reports the
1367
+ * continuous `"move"` phase as well, and a live region given every frame
1368
+ * of a drag says nothing an assistive technology can keep up with.
1369
+ */
1370
+ onColumnResize: (event) => {
1371
+ callbacks.onColumnResize?.(event);
1372
+ if (event.phase === "end") {
1373
+ announce(
1374
+ messages.columnResized(
1375
+ columnName(event.columnId),
1376
+ Math.round(event.width)
1377
+ )
1378
+ );
1379
+ }
1380
+ },
1381
+ /**
1382
+ * Naming a column shown or hidden alone, and counting several — "Show
1383
+ * all" in the column chooser, or `hideColumns` given a list. A change
1384
+ * that shows some and hides others, as restoring a layout can, has no
1385
+ * one thing to say, and says nothing.
1386
+ */
1387
+ onColumnVisibilityChange: (event) => {
1388
+ callbacks.onColumnVisibilityChange?.(event);
1389
+ const { columnIds, visibility } = event;
1390
+ const [columnId] = columnIds;
1391
+ const shownCount = columnIds.filter((id) => {
1392
+ const column = columnOf(id);
1393
+ return column !== void 0 && isColumnVisible(column, visibility);
1394
+ }).length;
1395
+ if (columnId === void 0 || shownCount !== 0 && shownCount !== columnIds.length) {
1396
+ return;
1397
+ }
1398
+ const shown = shownCount > 0;
1399
+ if (columnIds.length > 1) {
1400
+ announce(
1401
+ shown ? messages.columnsShown(columnIds.length) : messages.columnsHidden(columnIds.length)
1402
+ );
1403
+ return;
1404
+ }
1405
+ announce(
1406
+ shown ? messages.columnShown(columnName(columnId)) : messages.columnHidden(columnName(columnId))
1407
+ );
1408
+ },
1409
+ /** A toggle, a stack, or a clear back to "none" each get their own. */
1410
+ onColumnSortChange: (event) => {
1411
+ callbacks.onColumnSortChange?.(event);
1412
+ const entry = event.sort.find(
1413
+ (candidate) => candidate.columnId === event.columnId
1414
+ );
1415
+ if (entry === void 0) {
1416
+ announce(messages.sortCleared(columnName(event.columnId)));
1417
+ return;
1418
+ }
1419
+ announce(
1420
+ messages.columnSorted(
1421
+ columnName(event.columnId),
1422
+ entry.direction,
1423
+ event.sort.indexOf(entry) + 1,
1424
+ event.sort.length
1425
+ )
1426
+ );
1427
+ },
1428
+ onGroupByChange: (event) => {
1429
+ callbacks.onGroupByChange?.(event);
1430
+ const entry = event.groupBy.find(
1431
+ (candidate) => candidate.columnId === event.columnId
1432
+ );
1433
+ if (entry === void 0) {
1434
+ announce(messages.groupingRemoved(columnName(event.columnId)));
1435
+ return;
1436
+ }
1437
+ announce(
1438
+ messages.groupedBy(
1439
+ columnName(event.columnId),
1440
+ event.groupBy.indexOf(entry) + 1,
1441
+ event.groupBy.length
1442
+ )
1443
+ );
1444
+ },
1445
+ /**
1446
+ * `groupId: null` marks `expandAll`/`collapseAll`, which touch every
1447
+ * group in one call rather than one at a time — announced as a single
1448
+ * summary instead of naming a group that doesn't apply.
1449
+ */
1450
+ onGroupExpansionChange: (event) => {
1451
+ callbacks.onGroupExpansionChange?.(event);
1452
+ if (event.groupId === null) {
1453
+ announce(
1454
+ event.expansion.length === 0 ? messages.allGroupsExpanded : messages.allGroupsCollapsed
1455
+ );
1456
+ return;
1457
+ }
1458
+ announce(
1459
+ event.expansion.includes(event.groupId) ? messages.groupCollapsed : messages.groupExpanded
1460
+ );
1461
+ },
1462
+ onPaginationChange: (event) => {
1463
+ callbacks.onPaginationChange?.(event);
1464
+ announce(
1465
+ messages.pageStatus(event.pagination.pageIndex + 1, event.pageCount)
1466
+ );
1467
+ },
1468
+ /**
1469
+ * Unlike rows and columns, a cell selection is always exactly one cell —
1470
+ * there is no multi-cell range — so it never crosses the count's >1
1471
+ * threshold and the focused cell's own `aria-selected` is the only
1472
+ * feedback a screen-reader user would otherwise get. Announced on every
1473
+ * change that lands on a cell instead.
1474
+ */
1475
+ onCellSelectionChange: (event) => {
1476
+ callbacks.onCellSelectionChange?.(event);
1477
+ if (event.selected !== null) {
1478
+ announce(
1479
+ messages.cellSelected(
1480
+ columnName(event.selected.columnId),
1481
+ event.selected.rowIndex + 1
1482
+ )
1483
+ );
1484
+ }
1485
+ },
1486
+ /**
1487
+ * Announced only for a change touching more than one row or column. A
1488
+ * single selection is already carried by the focused member's own
1489
+ * `aria-selected`, and repeating it here would talk over that. Counted
1490
+ * by id, so rows the change touched off screen — on another page, in a
1491
+ * collapsed group — count too.
1492
+ */
1493
+ onSelectionDiff: (event) => {
1494
+ if (event.added.length + event.removed.length > 1) {
1495
+ announce(messages.selectedCount(event.selection.length, event.target));
1496
+ }
1497
+ }
1360
1498
  };
1361
1499
  }
1362
1500
 
1363
- // src/DataGrid/useColumnResize.ts
1364
- import {
1365
- useState as useState4
1366
- } from "react";
1501
+ // src/DataGrid/commands/useGridCommands.ts
1502
+ import { useMemo as useMemo3 } from "react";
1367
1503
  import {
1368
- beginColumnResize,
1369
- clampColumnWidth,
1370
- resolveColumnConstraints,
1371
- sizeColumnToContent
1504
+ createCommandContext,
1505
+ resolveCommands,
1506
+ runCommand
1372
1507
  } from "@gridkitjs/core";
1373
- import { measureColumnContent, startColumnResizeGesture } from "@gridkitjs/dom";
1374
- function useColumnResize({
1375
- tableRef,
1508
+ function useGridCommands({
1376
1509
  controller,
1377
- columnSizeDefaults
1510
+ commands: appCommands,
1511
+ onCommand,
1512
+ messages,
1513
+ announce,
1514
+ resize,
1515
+ openPanel
1378
1516
  }) {
1379
- const [activeColumnId, setActiveColumnId] = useState4(null);
1380
- function startResize(entry, event) {
1381
- event.stopPropagation();
1382
- const session = beginColumnResize(
1383
- entry.column,
1384
- entry.width,
1385
- event.clientX,
1386
- columnSizeDefaults
1387
- );
1388
- const base = controller.getState().columnSizing;
1389
- const started = startColumnResizeGesture(
1390
- event.currentTarget,
1391
- event,
1392
- session,
1393
- {
1394
- onMove(width) {
1395
- controller.resizeColumn(session.columnId, width, "move");
1396
- },
1397
- onEnd(width) {
1398
- setActiveColumnId(null);
1399
- if (width !== null) {
1400
- controller.resizeColumn(session.columnId, width, "end");
1401
- }
1402
- },
1403
- /**
1404
- * Escape puts back only the dragged column's pre-drag width, merged
1405
- * into whatever the sizing state is *now* — not the `base` snapshot
1406
- * taken at drag-start — so a different column resized via keyboard
1407
- * while this drag was still open keeps its change instead of being
1408
- * clobbered by a stale restore.
1409
- */
1410
- onCancel() {
1411
- setActiveColumnId(null);
1412
- controller.cancelColumnResize(
1413
- session.columnId,
1414
- base,
1415
- session.startWidth
1416
- );
1517
+ const commands = useMemo3(() => resolveCommands(appCommands), [appCommands]);
1518
+ const host = {
1519
+ autoFitColumns: (columnIds) => {
1520
+ const { columns } = controller.getView();
1521
+ let fitted = 0;
1522
+ for (const columnId of columnIds) {
1523
+ const entry = columns.find((candidate) => candidate.id === columnId);
1524
+ if (entry !== void 0 && resize.sizeToContent(entry)) {
1525
+ fitted += 1;
1417
1526
  }
1418
1527
  }
1419
- );
1420
- if (started) {
1421
- setActiveColumnId(session.columnId);
1422
- }
1528
+ if (fitted > 1) {
1529
+ announce(messages.columnsAutoFitted(fitted));
1530
+ }
1531
+ },
1532
+ openPanel,
1533
+ announce
1534
+ };
1535
+ function contextFor(target) {
1536
+ return createCommandContext({ controller, target, messages, host });
1423
1537
  }
1424
- function sizeToContent(entry) {
1425
- const table = tableRef.current;
1426
- if (table === null) {
1427
- return;
1428
- }
1429
- const measured = measureColumnContent(table, entry.id);
1430
- if (measured === null) {
1431
- return;
1538
+ function report(commandId, target, source) {
1539
+ onCommand?.({ commandId, target, source });
1540
+ }
1541
+ return {
1542
+ commands,
1543
+ host,
1544
+ contextFor,
1545
+ report,
1546
+ run: (commandId, target, source) => {
1547
+ const command = commands.get(commandId);
1548
+ if (command === void 0) {
1549
+ console.error(`DataGrid: there is no command \`${commandId}\` to run.`);
1550
+ return false;
1551
+ }
1552
+ if (!runCommand(command, contextFor(target))) {
1553
+ return false;
1554
+ }
1555
+ report(commandId, target, source);
1556
+ return true;
1432
1557
  }
1433
- controller.resizeColumn(
1434
- entry.id,
1435
- sizeColumnToContent(
1436
- measured,
1437
- resolveColumnConstraints(entry.column, columnSizeDefaults)
1438
- ),
1439
- "end"
1440
- );
1558
+ };
1559
+ }
1560
+
1561
+ // src/DataGrid/menu/GridMenu.tsx
1562
+ import { useLayoutEffect as useLayoutEffect3, useRef as useRef3, useState as useState4 } from "react";
1563
+ import {
1564
+ attachMenu
1565
+ } from "@gridkitjs/dom";
1566
+
1567
+ // src/DataGrid/overlay/Overlay.tsx
1568
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef2 } from "react";
1569
+ import { createPortal as createPortal3 } from "react-dom";
1570
+ import {
1571
+ attachOverlay
1572
+ } from "@gridkitjs/dom";
1573
+ import { jsx as jsx11 } from "react/jsx-runtime";
1574
+ var ANCHOR_GAP = 4;
1575
+ function overlayThemeClassName(element) {
1576
+ const scope = element?.closest(".gridkit-light, .gridkit-dark");
1577
+ if (scope === null || scope === void 0) {
1578
+ return "";
1441
1579
  }
1442
- function nudge(entry, delta) {
1443
- controller.resizeColumn(
1444
- entry.id,
1580
+ return scope.classList.contains("gridkit-dark") ? "gridkit-dark" : "gridkit-light";
1581
+ }
1582
+ function Overlay({
1583
+ anchor,
1584
+ placement,
1585
+ gap,
1586
+ offset,
1587
+ initialFocus,
1588
+ returnFocusTo,
1589
+ ignoreScrollAfterInput,
1590
+ themeClassName,
1591
+ onDismiss,
1592
+ children
1593
+ }) {
1594
+ const panelRef = useRef2(null);
1595
+ const onDismissRef = useRef2(onDismiss);
1596
+ useLayoutEffect2(() => {
1597
+ onDismissRef.current = onDismiss;
1598
+ });
1599
+ useLayoutEffect2(() => {
1600
+ const panel = panelRef.current;
1601
+ if (panel === null) {
1602
+ return void 0;
1603
+ }
1604
+ return attachOverlay(anchor, panel, {
1605
+ placement,
1606
+ gap,
1607
+ offset,
1608
+ initialFocus,
1609
+ returnFocusTo,
1610
+ ignoreScrollAfterInput,
1611
+ onDismiss: (reason) => {
1612
+ onDismissRef.current(reason);
1613
+ }
1614
+ });
1615
+ }, [
1616
+ anchor,
1617
+ placement,
1618
+ gap,
1619
+ offset,
1620
+ initialFocus,
1621
+ returnFocusTo,
1622
+ ignoreScrollAfterInput
1623
+ ]);
1624
+ return createPortal3(
1625
+ /* @__PURE__ */ jsx11(
1626
+ "div",
1627
+ {
1628
+ ref: panelRef,
1629
+ className: classNames("gridkit-overlay", themeClassName),
1630
+ children
1631
+ }
1632
+ ),
1633
+ document.body
1634
+ );
1635
+ }
1636
+
1637
+ // src/DataGrid/menu/menuIcons.tsx
1638
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1639
+ var BUILT_IN_ICONS = {
1640
+ sortAscending: () => /* @__PURE__ */ jsxs8(Icon, { children: [
1641
+ /* @__PURE__ */ jsx12("path", { d: "m3 8 4-4 4 4" }),
1642
+ /* @__PURE__ */ jsx12("path", { d: "M7 4v16" }),
1643
+ /* @__PURE__ */ jsx12("path", { d: "M11 12h4" }),
1644
+ /* @__PURE__ */ jsx12("path", { d: "M11 16h7" }),
1645
+ /* @__PURE__ */ jsx12("path", { d: "M11 20h10" })
1646
+ ] }),
1647
+ sortDescending: () => /* @__PURE__ */ jsxs8(Icon, { children: [
1648
+ /* @__PURE__ */ jsx12("path", { d: "m3 16 4 4 4-4" }),
1649
+ /* @__PURE__ */ jsx12("path", { d: "M7 20V4" }),
1650
+ /* @__PURE__ */ jsx12("path", { d: "M11 4h10" }),
1651
+ /* @__PURE__ */ jsx12("path", { d: "M11 8h7" }),
1652
+ /* @__PURE__ */ jsx12("path", { d: "M11 12h4" })
1653
+ ] }),
1654
+ group: () => /* @__PURE__ */ jsx12(GroupIcon, {}),
1655
+ hide: () => /* @__PURE__ */ jsxs8(Icon, { children: [
1656
+ /* @__PURE__ */ jsx12("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }),
1657
+ /* @__PURE__ */ jsx12("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }),
1658
+ /* @__PURE__ */ jsx12("path", { d: "M6.61 6.61A13.53 13.53 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }),
1659
+ /* @__PURE__ */ jsx12("path", { d: "m2 2 20 20" })
1660
+ ] }),
1661
+ autoFit: () => /* @__PURE__ */ jsxs8(Icon, { children: [
1662
+ /* @__PURE__ */ jsx12("path", { d: "m18 8 4 4-4 4" }),
1663
+ /* @__PURE__ */ jsx12("path", { d: "M2 12h20" }),
1664
+ /* @__PURE__ */ jsx12("path", { d: "m6 8-4 4 4 4" })
1665
+ ] })
1666
+ };
1667
+ var ICONS = new Map(Object.entries(BUILT_IN_ICONS));
1668
+ function MenuIcon({ name }) {
1669
+ const draw = name === void 0 ? void 0 : ICONS.get(name);
1670
+ return draw === void 0 ? null : draw();
1671
+ }
1672
+ function CheckIcon() {
1673
+ return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "M20 6 9 17l-5-5" }) });
1674
+ }
1675
+ function ChevronDownIcon() {
1676
+ return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" }) });
1677
+ }
1678
+ function ChevronRightIcon() {
1679
+ return /* @__PURE__ */ jsx12(Icon, { children: /* @__PURE__ */ jsx12("path", { d: "m9 18 6-6-6-6" }) });
1680
+ }
1681
+
1682
+ // src/DataGrid/menu/GridMenu.tsx
1683
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1684
+ function itemElement(menu, id) {
1685
+ return Array.from(
1686
+ menu.querySelectorAll("[data-gridkit-menu-item]")
1687
+ ).find((item) => item.getAttribute("data-gridkit-menu-item") === id) ?? null;
1688
+ }
1689
+ function topInset(menu) {
1690
+ const style = getComputedStyle(menu);
1691
+ return parseFloat(style.borderTopWidth) + parseFloat(style.paddingTop);
1692
+ }
1693
+ function MenuItem({
1694
+ entry,
1695
+ expanded
1696
+ }) {
1697
+ const isItem = entry.type === "item";
1698
+ const checked = isItem ? entry.checked : void 0;
1699
+ const shortcut = isItem ? entry.shortcut : void 0;
1700
+ return /* @__PURE__ */ jsxs9(
1701
+ "div",
1702
+ {
1703
+ role: checked === void 0 ? "menuitem" : "menuitemcheckbox",
1704
+ "data-gridkit-menu-item": entry.id,
1705
+ className: "menu-item",
1706
+ ...ariaAttr(isItem && entry.disabled, "aria-disabled", true),
1707
+ ...ariaAttr(checked !== void 0, "aria-checked", checked),
1708
+ ...ariaAttr(shortcut !== void 0, "aria-keyshortcuts", shortcut),
1709
+ ...ariaAttr(!isItem, "aria-haspopup", "menu"),
1710
+ ...ariaAttr(!isItem, "aria-expanded", expanded),
1711
+ children: [
1712
+ /* @__PURE__ */ jsx13("span", { className: "menu-item-icon", "aria-hidden": "true", children: checked === true ? /* @__PURE__ */ jsx13(CheckIcon, {}) : /* @__PURE__ */ jsx13(MenuIcon, { name: entry.icon }) }),
1713
+ /* @__PURE__ */ jsx13("span", { className: "menu-item-label", children: entry.label }),
1714
+ shortcut !== void 0 && /* @__PURE__ */ jsx13("span", { className: "menu-item-shortcut", "aria-hidden": "true", children: shortcut }),
1715
+ !isItem && /* @__PURE__ */ jsx13("span", { className: "menu-submenu-indicator", "aria-hidden": "true", children: /* @__PURE__ */ jsx13(ChevronRightIcon, {}) })
1716
+ ]
1717
+ }
1718
+ );
1719
+ }
1720
+ function GridMenu({
1721
+ entries,
1722
+ label,
1723
+ themeClassName,
1724
+ onRun,
1725
+ onClose,
1726
+ onCloseSubmenu,
1727
+ behaviourRef
1728
+ }) {
1729
+ const menuRef = useRef3(null);
1730
+ const submenuBehaviourRef = useRef3(null);
1731
+ const [submenu, setSubmenu] = useState4(null);
1732
+ const isSubmenu = onCloseSubmenu !== void 0;
1733
+ const latest = useRef3({ entries, submenu, onRun, onClose, onCloseSubmenu });
1734
+ useLayoutEffect3(() => {
1735
+ latest.current = { entries, submenu, onRun, onClose, onCloseSubmenu };
1736
+ });
1737
+ useLayoutEffect3(() => {
1738
+ const menu = menuRef.current;
1739
+ if (menu === null) {
1740
+ return void 0;
1741
+ }
1742
+ const behaviour = attachMenu(menu, {
1743
+ onActivate: (id) => {
1744
+ const item = latest.current.entries.find(
1745
+ (entry) => entry.type === "item" && entry.id === id
1746
+ );
1747
+ if (item !== void 0) {
1748
+ latest.current.onRun(item);
1749
+ }
1750
+ },
1751
+ onOpenSubmenu: (id, { focus }) => {
1752
+ if (latest.current.submenu?.id === id) {
1753
+ if (focus === "first") {
1754
+ submenuBehaviourRef.current?.focusItem(0);
1755
+ }
1756
+ return;
1757
+ }
1758
+ const anchor = itemElement(menu, id);
1759
+ if (anchor !== null) {
1760
+ setSubmenu({ id, anchor, focus, offset: -topInset(menu) });
1761
+ }
1762
+ },
1763
+ onCollapseSubmenu: () => {
1764
+ setSubmenu(null);
1765
+ },
1766
+ onCloseSubmenu: isSubmenu ? () => {
1767
+ latest.current.onCloseSubmenu?.();
1768
+ } : void 0,
1769
+ onClose: () => {
1770
+ latest.current.onClose();
1771
+ }
1772
+ });
1773
+ if (behaviourRef !== void 0) {
1774
+ behaviourRef.current = behaviour;
1775
+ }
1776
+ return () => {
1777
+ if (behaviourRef !== void 0) {
1778
+ behaviourRef.current = null;
1779
+ }
1780
+ behaviour.detach();
1781
+ };
1782
+ }, [isSubmenu, behaviourRef]);
1783
+ function closeSubmenu() {
1784
+ setSubmenu(null);
1785
+ }
1786
+ const openEntry = submenu === null ? void 0 : entries.find(
1787
+ (entry) => entry.type === "submenu" && entry.id === submenu.id
1788
+ );
1789
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
1790
+ /* @__PURE__ */ jsx13(
1791
+ "div",
1792
+ {
1793
+ ref: menuRef,
1794
+ role: "menu",
1795
+ "aria-label": label,
1796
+ className: "gridkit-menu",
1797
+ children: entries.map(
1798
+ (entry) => entry.type === "separator" ? /* @__PURE__ */ jsx13("div", { role: "separator", className: "menu-separator" }, entry.key) : /* @__PURE__ */ jsx13(
1799
+ MenuItem,
1800
+ {
1801
+ entry,
1802
+ expanded: entry.id === submenu?.id
1803
+ },
1804
+ entry.id
1805
+ )
1806
+ )
1807
+ }
1808
+ ),
1809
+ submenu !== null && openEntry !== void 0 && /* @__PURE__ */ jsx13(
1810
+ Overlay,
1811
+ {
1812
+ anchor: submenu.anchor,
1813
+ placement: "right-start",
1814
+ offset: submenu.offset,
1815
+ initialFocus: submenu.focus,
1816
+ themeClassName,
1817
+ onDismiss: closeSubmenu,
1818
+ children: /* @__PURE__ */ jsx13(
1819
+ GridMenu,
1820
+ {
1821
+ entries: openEntry.items,
1822
+ label: openEntry.label,
1823
+ themeClassName,
1824
+ onRun,
1825
+ onClose,
1826
+ onCloseSubmenu: closeSubmenu,
1827
+ behaviourRef: submenuBehaviourRef
1828
+ }
1829
+ )
1830
+ },
1831
+ submenu.id
1832
+ )
1833
+ ] });
1834
+ }
1835
+
1836
+ // src/DataGrid/contextMenu/GridContextMenu.tsx
1837
+ import { jsx as jsx14 } from "react/jsx-runtime";
1838
+ function GridContextMenu({
1839
+ contextMenu
1840
+ }) {
1841
+ const { menu, run, close } = contextMenu;
1842
+ if (menu === null) {
1843
+ return null;
1844
+ }
1845
+ return /* @__PURE__ */ jsx14(
1846
+ Overlay,
1847
+ {
1848
+ anchor: menu.anchor,
1849
+ gap: menu.anchor instanceof Element ? ANCHOR_GAP : 0,
1850
+ returnFocusTo: menu.cell ?? void 0,
1851
+ themeClassName: menu.themeClassName,
1852
+ onDismiss: close,
1853
+ children: /* @__PURE__ */ jsx14(
1854
+ GridMenu,
1855
+ {
1856
+ entries: menu.entries,
1857
+ label: menu.label,
1858
+ themeClassName: menu.themeClassName,
1859
+ onRun: run,
1860
+ onClose: close
1861
+ }
1862
+ )
1863
+ },
1864
+ menu.key
1865
+ );
1866
+ }
1867
+
1868
+ // src/DataGrid/contextMenu/useContextMenu.ts
1869
+ import {
1870
+ useEffect as useEffect2,
1871
+ useLayoutEffect as useLayoutEffect4,
1872
+ useRef as useRef4,
1873
+ useState as useState5
1874
+ } from "react";
1875
+ import {
1876
+ contextMenuEntries,
1877
+ hasContextMenu,
1878
+ isSameCell,
1879
+ resolveMenu
1880
+ } from "@gridkitjs/core";
1881
+ import {
1882
+ attachContextMenuTrigger
1883
+ } from "@gridkitjs/dom";
1884
+
1885
+ // src/DataGrid/contextMenu/contextMenuPlaces.ts
1886
+ import {
1887
+ HEADER_ROW as HEADER_ROW2
1888
+ } from "@gridkitjs/core";
1889
+ import {
1890
+ bodyCellFrom as bodyCellFrom2,
1891
+ bodyRowFrom as bodyRowFrom2,
1892
+ findBodyRow as findBodyRow2,
1893
+ groupRowFrom as groupRowFrom2
1894
+ } from "@gridkitjs/dom";
1895
+ function headerCell(parts, columnIndex) {
1896
+ const element = parts.headerTable?.tHead?.rows[0]?.cells[columnIndex];
1897
+ return element === void 0 ? null : { element, rowIndex: HEADER_ROW2, columnIndex };
1898
+ }
1899
+ function bodyCell(parts, rowIndex, columnIndex) {
1900
+ const element = findBodyRow2(parts.bodyTable, rowIndex)?.cells[columnIndex];
1901
+ return element === void 0 ? null : { element, rowIndex, columnIndex };
1902
+ }
1903
+ function viewOf(element, parts) {
1904
+ const root = parts.root?.getBoundingClientRect();
1905
+ if (root === void 0) {
1906
+ return null;
1907
+ }
1908
+ const body = parts.body?.contains(element) === true ? parts.body.getBoundingClientRect() : root;
1909
+ const left = Math.max(root.left, body.left);
1910
+ const top = Math.max(root.top, body.top);
1911
+ return new DOMRect(
1912
+ left,
1913
+ top,
1914
+ Math.max(0, Math.min(root.right, body.right) - left),
1915
+ Math.max(0, Math.min(root.bottom, body.bottom) - top)
1916
+ );
1917
+ }
1918
+ function clamp(value, min, max) {
1919
+ return Math.min(Math.max(value, min), max);
1920
+ }
1921
+ function onCell(target, cell, parts) {
1922
+ if (cell === null) {
1923
+ return null;
1924
+ }
1925
+ const box = cell.element.getBoundingClientRect();
1926
+ const view = viewOf(cell.element, parts);
1927
+ if (view === null || box.right > view.left && box.left < view.right && box.bottom > view.top && box.top < view.bottom) {
1928
+ return { target, cell, anchor: cell.element };
1929
+ }
1930
+ return {
1931
+ target,
1932
+ cell,
1933
+ anchor: {
1934
+ x: clamp(box.left, view.left, view.right),
1935
+ y: clamp(box.bottom, view.top, view.bottom)
1936
+ }
1937
+ };
1938
+ }
1939
+ function onBody(body) {
1940
+ const { left, top } = body.getBoundingClientRect();
1941
+ return { target: { area: "body" }, cell: null, anchor: { x: left, y: top } };
1942
+ }
1943
+ function headerPlaceAt(element, parts) {
1944
+ const cell = element.closest("th[data-gridkit-column]");
1945
+ const columnId = cell?.getAttribute("data-gridkit-column");
1946
+ if (cell === null || cell.parentElement !== parts.headerTable?.tHead?.rows[0] || columnId === null || columnId === void 0) {
1947
+ return null;
1948
+ }
1949
+ return onCell(
1950
+ { area: "header", columnId },
1951
+ headerCell(parts, cell.cellIndex),
1952
+ parts
1953
+ );
1954
+ }
1955
+ function bodyPlaceAt(element, parts) {
1956
+ const { body, pageRows } = parts;
1957
+ if (body === null || !body.contains(element)) {
1958
+ return null;
1959
+ }
1960
+ const group = groupRowFrom2(element);
1961
+ if (group !== null) {
1962
+ const entry = pageRows[group.rowIndex];
1963
+ const cell = bodyCell(parts, group.rowIndex, 0);
1964
+ return entry !== void 0 && "kind" in entry && entry.kind === "group" && cell?.element.contains(element) === true ? onCell(
1965
+ { area: "group", groupId: entry.groupId, columnId: entry.columnId },
1966
+ cell,
1967
+ parts
1968
+ ) : null;
1969
+ }
1970
+ const position = bodyCellFrom2(element);
1971
+ if (position !== null) {
1972
+ const entry = pageRows[position.rowIndex];
1973
+ const cell = bodyCell(parts, position.rowIndex, position.columnIndex);
1974
+ return entry !== void 0 && !("kind" in entry) && cell?.element.contains(element) === true ? onCell(
1975
+ { area: "cell", rowId: entry.rowId, columnId: position.columnId },
1976
+ cell,
1977
+ parts
1978
+ ) : null;
1979
+ }
1980
+ return bodyRowFrom2(element) === null ? onBody(body) : null;
1981
+ }
1982
+ function placeAt(element, parts) {
1983
+ return headerPlaceAt(element, parts) ?? bodyPlaceAt(element, parts);
1984
+ }
1985
+ function placeOf(target, parts) {
1986
+ const columnIndexOf = (columnId) => parts.columns.findIndex((column) => column.id === columnId);
1987
+ switch (target.area) {
1988
+ case "header":
1989
+ return onCell(
1990
+ target,
1991
+ headerCell(parts, columnIndexOf(target.columnId)),
1992
+ parts
1993
+ );
1994
+ case "cell": {
1995
+ const rowIndex = parts.pageRows.findIndex(
1996
+ (entry) => !("kind" in entry) && entry.rowId === target.rowId
1997
+ );
1998
+ return onCell(
1999
+ target,
2000
+ bodyCell(parts, rowIndex, columnIndexOf(target.columnId)),
2001
+ parts
2002
+ );
2003
+ }
2004
+ case "group": {
2005
+ const rowIndex = parts.pageRows.findIndex(
2006
+ (entry) => "kind" in entry && entry.kind === "group" && entry.groupId === target.groupId
2007
+ );
2008
+ return onCell(target, bodyCell(parts, rowIndex, 0), parts);
2009
+ }
2010
+ case "body":
2011
+ return parts.body === null ? null : onBody(parts.body);
2012
+ }
2013
+ }
2014
+
2015
+ // src/DataGrid/contextMenu/useContextMenu.ts
2016
+ function useContextMenu({
2017
+ rootRef,
2018
+ headerTableRef,
2019
+ bodyTableRef,
2020
+ bodyScrollRef,
2021
+ contextMenu,
2022
+ onContextMenuOpenChange,
2023
+ controller,
2024
+ commands,
2025
+ nav,
2026
+ selection,
2027
+ messages,
2028
+ columnName
2029
+ }) {
2030
+ const [menu, setMenu] = useState5(null);
2031
+ const current = useRef4(null);
2032
+ const openings = useRef4(0);
2033
+ const enabled = contextMenu !== void 0 && contextMenu !== false;
2034
+ function parts() {
2035
+ const { columns, pageRows } = controller.getView();
2036
+ return {
2037
+ root: rootRef.current,
2038
+ headerTable: headerTableRef.current,
2039
+ bodyTable: bodyTableRef.current,
2040
+ body: bodyScrollRef.current,
2041
+ columns,
2042
+ pageRows
2043
+ };
2044
+ }
2045
+ function labelOf(target) {
2046
+ switch (target.area) {
2047
+ case "header":
2048
+ return messages.headerMenuLabel(columnName(target.columnId));
2049
+ case "cell":
2050
+ return messages.cellMenuLabel;
2051
+ case "group":
2052
+ return messages.groupMenuLabel;
2053
+ case "body":
2054
+ return messages.bodyMenuLabel;
2055
+ }
2056
+ }
2057
+ function selectTarget(target) {
2058
+ const state = controller.getState();
2059
+ if (target.area === "header") {
2060
+ if (selection.columnMode === false || state.columnSelection.includes(target.columnId)) {
2061
+ return false;
2062
+ }
2063
+ controller.selectColumn(target.columnId, "replace");
2064
+ return true;
2065
+ }
2066
+ if (target.area !== "cell") {
2067
+ return false;
2068
+ }
2069
+ const cell = { rowId: target.rowId, columnId: target.columnId };
2070
+ const selectRow = selection.rowMode !== false && !state.rowSelection.includes(target.rowId);
2071
+ const selectCell = selection.cellMode !== false && !isSameCell(state.cellSelection, cell);
2072
+ if (selectRow) {
2073
+ controller.selectRow(target.rowId, "replace");
2074
+ }
2075
+ if (selectCell) {
2076
+ controller.selectCell(cell, "replace");
2077
+ }
2078
+ return selectRow || selectCell;
2079
+ }
2080
+ function resolveFor(target) {
2081
+ const context = commands.contextFor(target);
2082
+ return resolveMenu(contextMenuEntries(contextMenu, context), {
2083
+ commands: commands.commands,
2084
+ context
2085
+ });
2086
+ }
2087
+ function show(next) {
2088
+ const previous = current.current;
2089
+ if (previous === next) {
2090
+ return;
2091
+ }
2092
+ current.current = next;
2093
+ setMenu(next);
2094
+ if (previous !== null) {
2095
+ onContextMenuOpenChange?.({ open: false, target: previous.target });
2096
+ }
2097
+ if (next !== null) {
2098
+ onContextMenuOpenChange?.({ open: true, target: next.target });
2099
+ }
2100
+ }
2101
+ function openAt({ target, cell, anchor }, point) {
2102
+ let resolved = resolveFor(target);
2103
+ if (resolved.length === 0) {
2104
+ return false;
2105
+ }
2106
+ if (selectTarget(target)) {
2107
+ resolved = resolveFor(target);
2108
+ }
2109
+ if (cell !== null && document.activeElement !== cell.element) {
2110
+ cell.element.focus({ preventScroll: true });
2111
+ nav.focusCellNow(cell.rowIndex, cell.columnIndex);
2112
+ }
2113
+ openings.current += 1;
2114
+ show({
2115
+ key: openings.current,
2116
+ target,
2117
+ entries: resolved,
2118
+ label: labelOf(target),
2119
+ anchor: point ?? anchor,
2120
+ cell: cell?.element ?? null,
2121
+ themeClassName: overlayThemeClassName(rootRef.current)
2122
+ });
2123
+ return true;
2124
+ }
2125
+ function handleRequest({ target, point }) {
2126
+ const place = placeAt(target, parts());
2127
+ return place !== null && openAt(place, point);
2128
+ }
2129
+ const latestRequest = useRef4(handleRequest);
2130
+ useLayoutEffect4(() => {
2131
+ latestRequest.current = handleRequest;
2132
+ });
2133
+ useEffect2(() => {
2134
+ const root = rootRef.current;
2135
+ if (!enabled || root === null) {
2136
+ return void 0;
2137
+ }
2138
+ return attachContextMenuTrigger(root, {
2139
+ onRequest: (request) => latestRequest.current(request)
2140
+ });
2141
+ }, [rootRef, enabled]);
2142
+ const shown = useRef4(null);
2143
+ useLayoutEffect4(() => {
2144
+ const closed = shown.current;
2145
+ shown.current = menu;
2146
+ if (menu === null && closed !== null && closed.cell !== null && !closed.cell.isConnected && document.activeElement === document.body) {
2147
+ nav.focusTabStop();
2148
+ }
2149
+ });
2150
+ function close() {
2151
+ show(null);
2152
+ }
2153
+ return {
2154
+ menu,
2155
+ opens: (area) => hasContextMenu(contextMenu, area),
2156
+ open: (target, anchor) => {
2157
+ const place = placeOf(target, parts());
2158
+ return place !== null && openAt(place, anchor ?? null);
2159
+ },
2160
+ run: (item) => {
2161
+ const open = current.current;
2162
+ if (item.run() && open !== null) {
2163
+ commands.report(item.id, open.target, "contextMenu");
2164
+ }
2165
+ close();
2166
+ },
2167
+ close
2168
+ };
2169
+ }
2170
+
2171
+ // src/DataGrid/columnChooser/ColumnChooser.tsx
2172
+ import { useLayoutEffect as useLayoutEffect5, useRef as useRef5, useState as useState6 } from "react";
2173
+ import { resolveColumnChooser } from "@gridkitjs/core";
2174
+ import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
2175
+ function ColumnChooser({
2176
+ controller,
2177
+ messages
2178
+ }) {
2179
+ const [search, setSearch] = useState6("");
2180
+ const showAllRef = useRef5(null);
2181
+ const { entries, selectAll, toggleAll } = resolveColumnChooser({
2182
+ columns: controller.getView().dataColumns,
2183
+ visibility: controller.getState().columnVisibility,
2184
+ search
2185
+ });
2186
+ useLayoutEffect5(() => {
2187
+ if (showAllRef.current !== null) {
2188
+ showAllRef.current.indeterminate = selectAll === "mixed";
2189
+ }
2190
+ });
2191
+ function setVisible(columnIds, visible) {
2192
+ if (visible) {
2193
+ controller.showColumns(columnIds);
2194
+ } else {
2195
+ controller.hideColumns(columnIds);
2196
+ }
2197
+ }
2198
+ return /* @__PURE__ */ jsxs10(
2199
+ "div",
2200
+ {
2201
+ role: "dialog",
2202
+ "aria-label": messages.columnChooserLabel,
2203
+ className: "gridkit-column-chooser",
2204
+ children: [
2205
+ /* @__PURE__ */ jsx15(
2206
+ "input",
2207
+ {
2208
+ type: "search",
2209
+ className: "column-chooser-search",
2210
+ "aria-label": messages.columnChooserSearchLabel,
2211
+ placeholder: messages.searchPlaceholder,
2212
+ value: search,
2213
+ onChange: (event) => {
2214
+ setSearch(event.currentTarget.value);
2215
+ }
2216
+ }
2217
+ ),
2218
+ entries.length === 0 ? /* @__PURE__ */ jsx15("p", { role: "status", className: "column-chooser-empty", children: messages.noMatchingColumns }) : /* @__PURE__ */ jsxs10(Fragment3, { children: [
2219
+ /* @__PURE__ */ jsxs10("label", { className: "column-chooser-option column-chooser-all", children: [
2220
+ /* @__PURE__ */ jsx15(
2221
+ "input",
2222
+ {
2223
+ ref: showAllRef,
2224
+ type: "checkbox",
2225
+ checked: selectAll === "checked",
2226
+ disabled: toggleAll === null,
2227
+ onChange: () => {
2228
+ if (toggleAll !== null) {
2229
+ setVisible(toggleAll.columnIds, toggleAll.visible);
2230
+ }
2231
+ }
2232
+ }
2233
+ ),
2234
+ messages.showAllColumns
2235
+ ] }),
2236
+ /* @__PURE__ */ jsx15("ul", { className: "column-chooser-list", children: entries.map((entry) => /* @__PURE__ */ jsx15("li", { children: /* @__PURE__ */ jsxs10("label", { className: "column-chooser-option", children: [
2237
+ /* @__PURE__ */ jsx15(
2238
+ "input",
2239
+ {
2240
+ type: "checkbox",
2241
+ checked: entry.visible,
2242
+ disabled: entry.disabled,
2243
+ onChange: () => {
2244
+ setVisible([entry.columnId], !entry.visible);
2245
+ }
2246
+ }
2247
+ ),
2248
+ entry.label
2249
+ ] }) }, entry.columnId)) })
2250
+ ] })
2251
+ ]
2252
+ }
2253
+ );
2254
+ }
2255
+
2256
+ // src/DataGrid/panels/GridPanels.tsx
2257
+ import { jsx as jsx16 } from "react/jsx-runtime";
2258
+ var panelComponents = {
2259
+ columnChooser: ColumnChooser
2260
+ };
2261
+ function GridPanels({
2262
+ panels,
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
+ }
2293
+
2294
+ // src/DataGrid/panels/useGridPanels.ts
2295
+ import { useLayoutEffect as useLayoutEffect6, useRef as useRef6, useState as useState7 } from "react";
2296
+ function toolbarItem(root, itemId) {
2297
+ const items = root.querySelectorAll(
2298
+ ":scope > .gridkit-toolbar > [data-gridkit-toolbar-item]"
2299
+ );
2300
+ return Array.from(items).find(
2301
+ (item) => item.getAttribute("data-gridkit-toolbar-item") === itemId
2302
+ ) ?? // In "More" while the toolbar is narrow: the button it is chosen from.
2303
+ Array.from(items).find(
2304
+ (item) => item.hasAttribute("data-gridkit-toolbar-more")
2305
+ ) ?? null;
2306
+ }
2307
+ function headerCell2(headerTable, columnId) {
2308
+ const cells = headerTable?.tHead?.rows[0]?.cells;
2309
+ return cells === void 0 ? null : Array.from(cells).find(
2310
+ (cell) => cell.getAttribute("data-gridkit-column") === columnId
2311
+ ) ?? null;
2312
+ }
2313
+ function useGridPanels({
2314
+ rootRef,
2315
+ headerTableRef,
2316
+ nav
2317
+ }) {
2318
+ const [panel, setPanel] = useState7(null);
2319
+ const openings = useRef6(0);
2320
+ function placeFor(root, target) {
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);
2338
+ useLayoutEffect6(() => {
2339
+ const closed = shown.current;
2340
+ shown.current = panel;
2341
+ if (panel === null && closed?.returnFocusTo?.isConnected === false && document.activeElement === document.body) {
2342
+ nav.focusTabStop();
2343
+ }
2344
+ });
2345
+ return {
2346
+ panel,
2347
+ open: (kind, target) => {
2348
+ const root = rootRef.current;
2349
+ if (root === null) {
2350
+ return;
2351
+ }
2352
+ openings.current += 1;
2353
+ setPanel({
2354
+ key: openings.current,
2355
+ kind,
2356
+ target,
2357
+ ...placeFor(root, target),
2358
+ themeClassName: overlayThemeClassName(root)
2359
+ });
2360
+ },
2361
+ close: () => {
2362
+ setPanel(null);
2363
+ }
2364
+ };
2365
+ }
2366
+
2367
+ // src/DataGrid/toolbar/GridToolbar.tsx
2368
+ import { useLayoutEffect as useLayoutEffect9, useRef as useRef10 } from "react";
2369
+ import {
2370
+ resolveToolbar,
2371
+ splitToolbarItems,
2372
+ toolbarEntries
2373
+ } from "@gridkitjs/core";
2374
+ import { attachToolbar } from "@gridkitjs/dom";
2375
+
2376
+ // src/DataGrid/toolbar/ToolbarMenuButton.tsx
2377
+ import { useLayoutEffect as useLayoutEffect7, useRef as useRef7, useState as useState8 } from "react";
2378
+ import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2379
+ function ToolbarMenuButton({
2380
+ itemKey,
2381
+ label,
2382
+ icon,
2383
+ entries,
2384
+ more = false,
2385
+ onMenuClose
2386
+ }) {
2387
+ const [menu, setMenu] = useState8(null);
2388
+ const menuBehaviourRef = useRef7(null);
2389
+ useLayoutEffect7(() => {
2390
+ if (menu !== null && menu.focusItem > 0) {
2391
+ menuBehaviourRef.current?.focusItem(menu.focusItem);
2392
+ }
2393
+ }, [menu]);
2394
+ function open(button, onLast = false) {
2395
+ setMenu({
2396
+ anchor: button,
2397
+ themeClassName: overlayThemeClassName(button),
2398
+ focusItem: onLast ? entries.filter((entry) => entry.type !== "separator").length - 1 : 0
2399
+ });
2400
+ }
2401
+ function close() {
2402
+ setMenu(null);
2403
+ onMenuClose();
2404
+ }
2405
+ return /* @__PURE__ */ jsxs11(Fragment4, { children: [
2406
+ /* @__PURE__ */ jsxs11(
2407
+ "button",
2408
+ {
2409
+ type: "button",
2410
+ className: classNames("toolbar-button", more && "toolbar-more"),
2411
+ "data-gridkit-toolbar-item": itemKey,
2412
+ ...ariaAttr(more, "data-gridkit-toolbar-more", ""),
2413
+ "aria-haspopup": "menu",
2414
+ "aria-expanded": menu !== null,
2415
+ onClick: (event) => {
2416
+ if (menu === null) {
2417
+ open(event.currentTarget);
2418
+ } else {
2419
+ close();
2420
+ }
2421
+ },
2422
+ onKeyDown: (event) => {
2423
+ if ((event.key === "ArrowDown" || event.key === "ArrowUp") && menu === null) {
2424
+ event.preventDefault();
2425
+ open(event.currentTarget, event.key === "ArrowUp");
2426
+ }
2427
+ },
2428
+ children: [
2429
+ icon !== void 0 && /* @__PURE__ */ jsx17("span", { className: "toolbar-button-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx17(MenuIcon, { name: icon }) }),
2430
+ label,
2431
+ /* @__PURE__ */ jsx17("span", { className: "toolbar-button-indicator", "aria-hidden": "true", children: /* @__PURE__ */ jsx17(ChevronDownIcon, {}) })
2432
+ ]
2433
+ }
2434
+ ),
2435
+ menu !== null && /* @__PURE__ */ jsx17(
2436
+ Overlay,
2437
+ {
2438
+ anchor: menu.anchor,
2439
+ placement: "bottom-start",
2440
+ gap: ANCHOR_GAP,
2441
+ returnFocusTo: menu.anchor,
2442
+ themeClassName: menu.themeClassName,
2443
+ onDismiss: close,
2444
+ children: /* @__PURE__ */ jsx17(
2445
+ GridMenu,
2446
+ {
2447
+ entries,
2448
+ label,
2449
+ themeClassName: menu.themeClassName,
2450
+ behaviourRef: menuBehaviourRef,
2451
+ onRun: (item) => {
2452
+ item.run();
2453
+ close();
2454
+ },
2455
+ onClose: close
2456
+ }
2457
+ )
2458
+ }
2459
+ )
2460
+ ] });
2461
+ }
2462
+
2463
+ // src/DataGrid/toolbar/ToolbarSearch.tsx
2464
+ import { useEffect as useEffect3, useRef as useRef8, useState as useState9 } from "react";
2465
+ import {
2466
+ searchTextOf,
2467
+ setSearchText
2468
+ } from "@gridkitjs/core";
2469
+ import { jsx as jsx18 } from "react/jsx-runtime";
2470
+ var SEARCH_DELAY_MS = 250;
2471
+ function ToolbarSearch({
2472
+ itemKey,
2473
+ controller,
2474
+ messages,
2475
+ announce
2476
+ }) {
2477
+ const applied = searchTextOf(controller.getState().filter);
2478
+ const [draft, setDraft] = useState9(null);
2479
+ const timer = useRef8(void 0);
2480
+ const unannounced = useRef8(null);
2481
+ const text = draft !== null && draft.over === applied ? draft.text : applied;
2482
+ function apply(next, over) {
2483
+ clearTimeout(timer.current);
2484
+ setDraft(null);
2485
+ const filter = controller.getState().filter;
2486
+ if (searchTextOf(filter) !== over) {
2487
+ return;
2488
+ }
2489
+ const searched = setSearchText(filter, next);
2490
+ if (searched !== filter) {
2491
+ unannounced.current = next;
2492
+ controller.setFilter(searched);
2493
+ }
2494
+ }
2495
+ useEffect3(() => {
2496
+ if (unannounced.current === applied) {
2497
+ unannounced.current = null;
2498
+ announce(messages.searchResults(controller.getView().rows.length));
2499
+ }
2500
+ });
2501
+ useEffect3(
2502
+ () => () => {
2503
+ clearTimeout(timer.current);
2504
+ },
2505
+ []
2506
+ );
2507
+ return /* @__PURE__ */ jsx18(
2508
+ "input",
2509
+ {
2510
+ type: "search",
2511
+ className: "toolbar-search",
2512
+ "data-gridkit-toolbar-item": itemKey,
2513
+ "aria-label": messages.searchLabel,
2514
+ placeholder: messages.searchPlaceholder,
2515
+ value: text,
2516
+ onChange: (event) => {
2517
+ const typed = event.target.value;
2518
+ setDraft({ text: typed, over: applied });
2519
+ clearTimeout(timer.current);
2520
+ timer.current = setTimeout(() => {
2521
+ apply(typed, applied);
2522
+ }, SEARCH_DELAY_MS);
2523
+ },
2524
+ onKeyDown: (event) => {
2525
+ if (event.key === "Enter") {
2526
+ apply(text, applied);
2527
+ } else if (event.key === "Escape" && text !== "") {
2528
+ event.preventDefault();
2529
+ apply("", applied);
2530
+ }
2531
+ }
2532
+ }
2533
+ );
2534
+ }
2535
+
2536
+ // src/DataGrid/toolbar/useToolbarOverflow.ts
2537
+ import { useLayoutEffect as useLayoutEffect8, useRef as useRef9, useState as useState10 } from "react";
2538
+ import { observeToolbarOverflow } from "@gridkitjs/dom";
2539
+ function useToolbarOverflow(toolbarRef, items) {
2540
+ const [fit, setFit] = useState10(items.length);
2541
+ const overflow = useRef9(null);
2542
+ const measuredLayout = useRef9("");
2543
+ const layout = JSON.stringify(
2544
+ items.map((item) => [
2545
+ item.type,
2546
+ item.key,
2547
+ "label" in item ? item.label : null
2548
+ ])
2549
+ );
2550
+ useLayoutEffect8(() => {
2551
+ const toolbar = toolbarRef.current;
2552
+ if (toolbar === null || layout === measuredLayout.current) {
2553
+ return;
2554
+ }
2555
+ measuredLayout.current = layout;
2556
+ const options = { items, onChange: setFit };
2557
+ if (overflow.current === null) {
2558
+ overflow.current = observeToolbarOverflow(toolbar, options);
2559
+ } else {
2560
+ overflow.current.update(options);
2561
+ }
2562
+ }, [toolbarRef, layout, items]);
2563
+ useLayoutEffect8(
2564
+ () => () => {
2565
+ overflow.current?.detach();
2566
+ overflow.current = null;
2567
+ measuredLayout.current = "";
2568
+ },
2569
+ []
2570
+ );
2571
+ return fit;
2572
+ }
2573
+
2574
+ // src/DataGrid/toolbar/GridToolbar.tsx
2575
+ import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
2576
+ function reporting(run, report) {
2577
+ return () => {
2578
+ const ran = run();
2579
+ if (ran) {
2580
+ report();
2581
+ }
2582
+ return ran;
2583
+ };
2584
+ }
2585
+ function reportingEntries(entries, report) {
2586
+ return entries.map((entry) => {
2587
+ switch (entry.type) {
2588
+ case "item":
2589
+ return {
2590
+ ...entry,
2591
+ run: reporting(entry.run, () => {
2592
+ report(entry.id);
2593
+ })
2594
+ };
2595
+ case "submenu":
2596
+ return { ...entry, items: reportingEntries(entry.items, report) };
2597
+ default:
2598
+ return entry;
2599
+ }
2600
+ });
2601
+ }
2602
+ function reportingItem(item, report) {
2603
+ switch (item.type) {
2604
+ case "button":
2605
+ return {
2606
+ ...item,
2607
+ run: reporting(item.run, () => {
2608
+ report(item.id, item.id);
2609
+ })
2610
+ };
2611
+ case "menu":
2612
+ return {
2613
+ ...item,
2614
+ items: reportingEntries(item.items, (commandId) => {
2615
+ report(commandId, item.id);
2616
+ })
2617
+ };
2618
+ default:
2619
+ return item;
2620
+ }
2621
+ }
2622
+ function GridToolbar(props) {
2623
+ const entries = toolbarEntries(props.toolbar);
2624
+ if (entries.length === 0) {
2625
+ return null;
2626
+ }
2627
+ const label = (typeof props.toolbar === "object" ? props.toolbar.label : void 0) ?? props.messages.toolbarLabel;
2628
+ return /* @__PURE__ */ jsx19(Toolbar, { ...props, entries, label });
2629
+ }
2630
+ function Toolbar({
2631
+ entries,
2632
+ label,
2633
+ renderItem,
2634
+ gridId,
2635
+ controller,
2636
+ commands,
2637
+ messages,
2638
+ announce
2639
+ }) {
2640
+ const toolbarRef = useRef10(null);
2641
+ const menuClosed = useRef10(false);
2642
+ const items = resolveToolbar(entries, {
2643
+ commands: commands.commands,
2644
+ contextFor: commands.contextFor
2645
+ }).map(
2646
+ (item) => reportingItem(item, (commandId, itemId) => {
2647
+ commands.report(commandId, { area: "toolbar", itemId }, "toolbar");
2648
+ })
2649
+ );
2650
+ const fit = useToolbarOverflow(toolbarRef, items);
2651
+ const { shown, overflow } = splitToolbarItems(items, fit);
2652
+ useLayoutEffect9(() => {
2653
+ const toolbar = toolbarRef.current;
2654
+ return toolbar === null ? void 0 : attachToolbar(toolbar);
2655
+ }, []);
2656
+ useLayoutEffect9(() => {
2657
+ if (!menuClosed.current) {
2658
+ return;
2659
+ }
2660
+ menuClosed.current = false;
2661
+ const toolbar = toolbarRef.current;
2662
+ if (toolbar !== null && document.activeElement === document.body) {
2663
+ (toolbar.querySelector('[tabindex="0"]') ?? toolbar.querySelector("button, input"))?.focus();
2664
+ }
2665
+ });
2666
+ function onMenuClose() {
2667
+ menuClosed.current = true;
2668
+ }
2669
+ function draw(item) {
2670
+ switch (item.type) {
2671
+ case "button":
2672
+ return /* @__PURE__ */ jsxs12(
2673
+ "button",
2674
+ {
2675
+ type: "button",
2676
+ className: "toolbar-button",
2677
+ "data-gridkit-toolbar-item": item.key,
2678
+ ...ariaAttr(item.disabled, "aria-disabled", true),
2679
+ ...ariaAttr(
2680
+ item.pressed !== void 0,
2681
+ "aria-pressed",
2682
+ item.pressed
2683
+ ),
2684
+ ...ariaAttr(
2685
+ item.shortcut !== void 0,
2686
+ "aria-keyshortcuts",
2687
+ item.shortcut
2688
+ ),
2689
+ onClick: () => {
2690
+ item.run();
2691
+ },
2692
+ children: [
2693
+ item.icon !== void 0 && /* @__PURE__ */ jsx19("span", { className: "toolbar-button-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx19(MenuIcon, { name: item.icon }) }),
2694
+ item.label
2695
+ ]
2696
+ },
2697
+ item.key
2698
+ );
2699
+ case "menu":
2700
+ return /* @__PURE__ */ jsx19(
2701
+ ToolbarMenuButton,
2702
+ {
2703
+ itemKey: item.key,
2704
+ label: item.label,
2705
+ icon: item.icon,
2706
+ entries: item.items,
2707
+ onMenuClose
2708
+ },
2709
+ item.key
2710
+ );
2711
+ case "search":
2712
+ return /* @__PURE__ */ jsx19(
2713
+ ToolbarSearch,
2714
+ {
2715
+ itemKey: item.key,
2716
+ controller,
2717
+ messages,
2718
+ announce
2719
+ },
2720
+ item.key
2721
+ );
2722
+ case "separator":
2723
+ return /* @__PURE__ */ jsx19(
2724
+ "div",
2725
+ {
2726
+ role: "separator",
2727
+ "aria-orientation": "vertical",
2728
+ className: "toolbar-separator",
2729
+ "data-gridkit-toolbar-item": item.key
2730
+ },
2731
+ item.key
2732
+ );
2733
+ case "spacer":
2734
+ return /* @__PURE__ */ jsx19(
2735
+ "div",
2736
+ {
2737
+ className: "toolbar-spacer",
2738
+ "data-gridkit-toolbar-item": item.key
2739
+ },
2740
+ item.key
2741
+ );
2742
+ case "custom":
2743
+ return /* @__PURE__ */ jsx19(
2744
+ "div",
2745
+ {
2746
+ className: "toolbar-custom",
2747
+ "data-gridkit-toolbar-item": item.key,
2748
+ children: renderItem?.(item.id)
2749
+ },
2750
+ item.key
2751
+ );
2752
+ }
2753
+ }
2754
+ return /* @__PURE__ */ jsxs12(
2755
+ "div",
2756
+ {
2757
+ ref: toolbarRef,
2758
+ role: "toolbar",
2759
+ "aria-label": label,
2760
+ "aria-controls": gridId,
2761
+ className: "gridkit-toolbar",
2762
+ children: [
2763
+ shown.map(draw),
2764
+ overflow.length > 0 && /* @__PURE__ */ jsx19(
2765
+ ToolbarMenuButton,
2766
+ {
2767
+ itemKey: "more",
2768
+ label: messages.moreToolbarItems,
2769
+ entries: overflow,
2770
+ more: true,
2771
+ onMenuClose
2772
+ }
2773
+ )
2774
+ ]
2775
+ }
2776
+ );
2777
+ }
2778
+
2779
+ // src/DataGrid/useColumnDrag.ts
2780
+ import {
2781
+ resolveKeyboardDropTarget as resolveKeyboardDropTarget2
2782
+ } from "@gridkitjs/core";
2783
+ import { resolveColumnDropTarget } from "@gridkitjs/dom";
2784
+ function useColumnDrag({
2785
+ order,
2786
+ groupBy,
2787
+ groupByDraggableIds,
2788
+ onDrop
2789
+ }) {
2790
+ const drag = useDragReorder({
2791
+ resolveTarget: (clientX, clientY, movedId) => resolveColumnDropTarget(clientX, clientY, movedId, {
2792
+ order,
2793
+ groupBy,
2794
+ groupByDraggableIds
2795
+ }),
2796
+ onDrop
2797
+ });
2798
+ function startDrag(entry, event) {
2799
+ drag.startDrag(entry.id, event.currentTarget, event);
2800
+ }
2801
+ function moveByKeyboard(entry, direction) {
2802
+ const beforeId = resolveKeyboardDropTarget2(order, entry.id, direction);
2803
+ if (beforeId === void 0) {
2804
+ return;
2805
+ }
2806
+ onDrop({ kind: "column-order", beforeId }, entry.id);
2807
+ }
2808
+ return {
2809
+ draggedColumnId: drag.draggedId,
2810
+ dropTarget: drag.dropTarget,
2811
+ ghostTransform: drag.ghostTransform,
2812
+ startDrag,
2813
+ moveByKeyboard,
2814
+ justDragged: drag.justDragged
2815
+ };
2816
+ }
2817
+
2818
+ // src/DataGrid/useColumnResize.ts
2819
+ import {
2820
+ useState as useState11
2821
+ } from "react";
2822
+ import {
2823
+ beginColumnResize,
2824
+ clampColumnWidth,
2825
+ resolveColumnConstraints,
2826
+ sizeColumnToContent
2827
+ } from "@gridkitjs/core";
2828
+ import { measureColumnContent, startColumnResizeGesture } from "@gridkitjs/dom";
2829
+ function useColumnResize({
2830
+ tableRef,
2831
+ controller,
2832
+ columnSizeDefaults
2833
+ }) {
2834
+ const [activeColumnId, setActiveColumnId] = useState11(null);
2835
+ function startResize(entry, event) {
2836
+ event.stopPropagation();
2837
+ const session = beginColumnResize(
2838
+ entry.column,
2839
+ entry.width,
2840
+ event.clientX,
2841
+ columnSizeDefaults
2842
+ );
2843
+ const base = controller.getState().columnSizing;
2844
+ const started = startColumnResizeGesture(
2845
+ event.currentTarget,
2846
+ event,
2847
+ session,
2848
+ {
2849
+ onMove(width) {
2850
+ controller.resizeColumn(session.columnId, width, "move");
2851
+ },
2852
+ onEnd(width) {
2853
+ setActiveColumnId(null);
2854
+ if (width !== null) {
2855
+ controller.resizeColumn(session.columnId, width, "end");
2856
+ }
2857
+ },
2858
+ /**
2859
+ * Escape puts back only the dragged column's pre-drag width, merged
2860
+ * into whatever the sizing state is *now* — not the `base` snapshot
2861
+ * taken at drag-start — so a different column resized via keyboard
2862
+ * while this drag was still open keeps its change instead of being
2863
+ * clobbered by a stale restore.
2864
+ */
2865
+ onCancel() {
2866
+ setActiveColumnId(null);
2867
+ controller.cancelColumnResize(
2868
+ session.columnId,
2869
+ base,
2870
+ session.startWidth
2871
+ );
2872
+ }
2873
+ }
2874
+ );
2875
+ if (started) {
2876
+ setActiveColumnId(session.columnId);
2877
+ }
2878
+ }
2879
+ function sizeToContent(entry) {
2880
+ const table = tableRef.current;
2881
+ if (table === null) {
2882
+ return false;
2883
+ }
2884
+ const measured = measureColumnContent(table, entry.id);
2885
+ if (measured === null) {
2886
+ return false;
2887
+ }
2888
+ controller.resizeColumn(
2889
+ entry.id,
2890
+ sizeColumnToContent(
2891
+ measured,
2892
+ resolveColumnConstraints(entry.column, columnSizeDefaults)
2893
+ ),
2894
+ "end"
2895
+ );
2896
+ return true;
2897
+ }
2898
+ function nudge(entry, delta) {
2899
+ controller.resizeColumn(
2900
+ entry.id,
1445
2901
  clampColumnWidth(
1446
2902
  entry.width + delta,
1447
2903
  resolveColumnConstraints(entry.column, columnSizeDefaults)
@@ -1453,11 +2909,11 @@ function useColumnResize({
1453
2909
  }
1454
2910
 
1455
2911
  // src/DataGrid/useElementWidth.ts
1456
- import { useLayoutEffect as useLayoutEffect2, useState as useState5 } from "react";
2912
+ import { useLayoutEffect as useLayoutEffect10, useState as useState12 } from "react";
1457
2913
  import { observeElementWidth } from "@gridkitjs/dom";
1458
2914
  function useElementWidth(ref, enabled) {
1459
- const [width, setWidth] = useState5(null);
1460
- useLayoutEffect2(() => {
2915
+ const [width, setWidth] = useState12(null);
2916
+ useLayoutEffect10(() => {
1461
2917
  const element = ref.current;
1462
2918
  if (element === null || !enabled) {
1463
2919
  return void 0;
@@ -1468,12 +2924,12 @@ function useElementWidth(ref, enabled) {
1468
2924
  }
1469
2925
 
1470
2926
  // src/DataGrid/useGridController.ts
1471
- import { useState as useState6, useSyncExternalStore as useSyncExternalStore2 } from "react";
2927
+ import { useState as useState13, useSyncExternalStore as useSyncExternalStore2 } from "react";
1472
2928
  import {
1473
2929
  createGridController
1474
2930
  } from "@gridkitjs/core";
1475
2931
  function useGridController(options) {
1476
- const [controller] = useState6(
2932
+ const [controller] = useState13(
1477
2933
  () => createGridController(options)
1478
2934
  );
1479
2935
  controller.setOptions(options);
@@ -1482,15 +2938,15 @@ function useGridController(options) {
1482
2938
  }
1483
2939
 
1484
2940
  // src/DataGrid/useInfiniteScroll.ts
1485
- import { useEffect as useEffect2, useRef as useRef2 } from "react";
2941
+ import { useEffect as useEffect4, useRef as useRef11 } from "react";
1486
2942
  import { attachInfiniteScroll } from "@gridkitjs/dom";
1487
2943
  function useInfiniteScroll({
1488
2944
  rootRef,
1489
2945
  sentinelRef,
1490
2946
  config
1491
2947
  }) {
1492
- const scroll = useRef2(null);
1493
- useEffect2(() => {
2948
+ const scroll = useRef11(null);
2949
+ useEffect4(() => {
1494
2950
  const root = rootRef.current;
1495
2951
  if (root === null) {
1496
2952
  return void 0;
@@ -1505,7 +2961,7 @@ function useInfiniteScroll({
1505
2961
  scroll.current = null;
1506
2962
  };
1507
2963
  }, [rootRef]);
1508
- useEffect2(() => {
2964
+ useEffect4(() => {
1509
2965
  scroll.current?.update({
1510
2966
  sentinel: sentinelRef.current,
1511
2967
  hasMore: config?.hasMore ?? false,
@@ -1517,11 +2973,11 @@ function useInfiniteScroll({
1517
2973
  }
1518
2974
 
1519
2975
  // src/DataGrid/useLiveAnnouncer.ts
1520
- import { useCallback, useLayoutEffect as useLayoutEffect3, useRef as useRef3 } from "react";
2976
+ import { useCallback, useLayoutEffect as useLayoutEffect11, useRef as useRef12 } from "react";
1521
2977
  import { createLiveAnnouncer } from "@gridkitjs/dom";
1522
2978
  function useLiveAnnouncer(containerRef) {
1523
- const announcer = useRef3(null);
1524
- useLayoutEffect3(() => {
2979
+ const announcer = useRef12(null);
2980
+ useLayoutEffect11(() => {
1525
2981
  const container = containerRef.current;
1526
2982
  if (container === null) {
1527
2983
  return void 0;
@@ -1539,7 +2995,7 @@ function useLiveAnnouncer(containerRef) {
1539
2995
  }
1540
2996
 
1541
2997
  // src/DataGrid/useRowVirtualizer.ts
1542
- import { useLayoutEffect as useLayoutEffect4, useState as useState7 } from "react";
2998
+ import { useLayoutEffect as useLayoutEffect12, useState as useState14 } from "react";
1543
2999
  import { createRowVirtualizer } from "@gridkitjs/dom";
1544
3000
  var EMPTY_RANGE = {
1545
3001
  startIndex: 0,
@@ -1557,9 +3013,9 @@ function useRowVirtualizer({
1557
3013
  estimatedRowHeight,
1558
3014
  overscan
1559
3015
  }) {
1560
- const [virtualizer, setVirtualizer] = useState7(null);
1561
- const [range, setRange] = useState7(EMPTY_RANGE);
1562
- useLayoutEffect4(() => {
3016
+ const [virtualizer, setVirtualizer] = useState14(null);
3017
+ const [range, setRange] = useState14(EMPTY_RANGE);
3018
+ useLayoutEffect12(() => {
1563
3019
  const element = bodyScrollRef.current;
1564
3020
  if (!enabled || element === null) {
1565
3021
  return void 0;
@@ -1574,7 +3030,7 @@ function useRowVirtualizer({
1574
3030
  created.destroy();
1575
3031
  };
1576
3032
  }, [enabled, bodyScrollRef, estimatedRowHeight, overscan]);
1577
- useLayoutEffect4(() => {
3033
+ useLayoutEffect12(() => {
1578
3034
  virtualizer?.setRowCount(rows.length);
1579
3035
  virtualizer?.resetHeights();
1580
3036
  }, [virtualizer, rows]);
@@ -1591,7 +3047,7 @@ function useRowVirtualizer({
1591
3047
  }
1592
3048
 
1593
3049
  // src/DataGrid/DataGrid.tsx
1594
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
3050
+ import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
1595
3051
  var NO_AGGREGATES = [];
1596
3052
  function paginationReader(controller) {
1597
3053
  let last;
@@ -1623,18 +3079,12 @@ function DataGrid(props) {
1623
3079
  selectable,
1624
3080
  resizeMode = "fit",
1625
3081
  columnSizeDefaults,
1626
- onColumnResize,
1627
3082
  sortableColumns = false,
1628
- onColumnSortChange,
1629
3083
  groupableColumns = false,
1630
3084
  groupToggleIconColumns = true,
1631
3085
  groupByBarVisibility = "auto",
1632
- onGroupByChange,
1633
- onGroupExpansionChange,
1634
3086
  paginated = false,
1635
3087
  pager,
1636
- onPaginationChange,
1637
- onCellSelectionChange,
1638
3088
  infiniteScroll,
1639
3089
  aggregates = NO_AGGREGATES,
1640
3090
  groupAggregateDisplay = "inline",
@@ -1654,31 +3104,32 @@ function DataGrid(props) {
1654
3104
  const hoverRows = hoverable?.rows ?? true;
1655
3105
  const hoverColumns = hoverable?.columns ?? true;
1656
3106
  const hoverCells = hoverable?.cells ?? true;
1657
- const viewportRef = useRef4(null);
1658
- const headerTableRef = useRef4(null);
1659
- const bodyTableRef = useRef4(null);
1660
- const bodyScrollRef = useRef4(null);
1661
- const sentinelRef = useRef4(null);
3107
+ const viewportRef = useRef13(null);
3108
+ const headerTableRef = useRef13(null);
3109
+ const bodyTableRef = useRef13(null);
3110
+ const bodyScrollRef = useRef13(null);
3111
+ const sentinelRef = useRef13(null);
1662
3112
  const viewportWidth = useElementWidth(viewportRef, resizeMode === "fit");
1663
- const subscribersRef = useRef4(/* @__PURE__ */ new Set());
3113
+ const subscribersRef = useRef13(/* @__PURE__ */ new Set());
3114
+ const gridId = useId();
1664
3115
  const announce = useLiveAnnouncer(viewportRef);
1665
- const messages = useMemo3(
3116
+ const messages = useMemo4(
1666
3117
  () => resolveMessages(messageOverrides),
1667
3118
  [messageOverrides]
1668
3119
  );
1669
3120
  const { controller, state, view } = useGridController({
1670
3121
  ...props,
1671
3122
  viewportWidth,
1672
- onColumnResize: handleColumnResize,
1673
- onColumnSortChange: handleColumnSortChange,
1674
- onGroupByChange: handleGroupByChange,
1675
- onGroupExpansionChange: handleGroupExpansionChange,
1676
- onPaginationChange: handlePaginationChange,
1677
- onCellSelectionChange: handleCellSelectionChange,
1678
- onSelectionDiff: handleSelectionDiff
3123
+ ...announcedCallbacks({
3124
+ callbacks: props,
3125
+ announce,
3126
+ messages,
3127
+ columnName,
3128
+ columnOf
3129
+ })
1679
3130
  });
1680
- const [readPagination] = useState8(() => paginationReader(controller));
1681
- const [readSelectedRows] = useState8(() => selectedRowsReader(controller));
3131
+ const [readPagination] = useState15(() => paginationReader(controller));
3132
+ const [readSelectedRows] = useState15(() => selectedRowsReader(controller));
1682
3133
  const virtualizer = useRowVirtualizer({
1683
3134
  enabled: virtualized,
1684
3135
  rows: view.pageRows,
@@ -1686,7 +3137,7 @@ function DataGrid(props) {
1686
3137
  estimatedRowHeight,
1687
3138
  overscan
1688
3139
  });
1689
- useEffect3(() => {
3140
+ useEffect5(() => {
1690
3141
  if (virtualized && height === void 0) {
1691
3142
  console.error(
1692
3143
  "DataGrid: `virtualized` has no effect without `height` \u2014 a body with no bounded height has no viewport to window rows against."
@@ -1694,7 +3145,7 @@ function DataGrid(props) {
1694
3145
  }
1695
3146
  }, [virtualized, height]);
1696
3147
  const hasInfiniteScroll = infiniteScroll !== void 0;
1697
- useEffect3(() => {
3148
+ useEffect5(() => {
1698
3149
  if (paginated && hasInfiniteScroll) {
1699
3150
  console.error(
1700
3151
  "DataGrid: `paginated` and `infiniteScroll` are mutually exclusive \u2014 only `paginated` takes effect while both are set."
@@ -1706,22 +3157,12 @@ function DataGrid(props) {
1706
3157
  sentinelRef,
1707
3158
  config: infiniteScroll
1708
3159
  });
1709
- function columnName(columnId) {
1710
- const entry = view.dataColumns.find(
1711
- (candidate) => candidate.id === columnId
1712
- );
1713
- return entry === void 0 ? columnId : resolveColumnHeaderText(entry.column);
3160
+ function columnOf(columnId) {
3161
+ return view.dataColumns.find((candidate) => candidate.id === columnId)?.column;
1714
3162
  }
1715
- function handleColumnResize(event) {
1716
- onColumnResize?.(event);
1717
- if (event.phase === "end") {
1718
- announce(
1719
- messages.columnResized(
1720
- columnName(event.columnId),
1721
- Math.round(event.width)
1722
- )
1723
- );
1724
- }
3163
+ function columnName(columnId) {
3164
+ const column = columnOf(columnId);
3165
+ return column === void 0 ? columnId : resolveColumnHeaderText(column);
1725
3166
  }
1726
3167
  const resize = useColumnResize({
1727
3168
  // `@gridkitjs/dom`'s `measureColumnContent` only ever matches
@@ -1732,75 +3173,6 @@ function DataGrid(props) {
1732
3173
  controller,
1733
3174
  columnSizeDefaults
1734
3175
  });
1735
- function handleGroupByChange(event) {
1736
- onGroupByChange?.(event);
1737
- const entry = event.groupBy.find(
1738
- (candidate) => candidate.columnId === event.columnId
1739
- );
1740
- if (entry === void 0) {
1741
- announce(messages.groupingRemoved(columnName(event.columnId)));
1742
- return;
1743
- }
1744
- announce(
1745
- messages.groupedBy(
1746
- columnName(event.columnId),
1747
- event.groupBy.indexOf(entry) + 1,
1748
- event.groupBy.length
1749
- )
1750
- );
1751
- }
1752
- function handleGroupExpansionChange(event) {
1753
- onGroupExpansionChange?.(event);
1754
- if (event.groupId === null) {
1755
- announce(
1756
- event.expansion.length === 0 ? messages.allGroupsExpanded : messages.allGroupsCollapsed
1757
- );
1758
- return;
1759
- }
1760
- announce(
1761
- event.expansion.includes(event.groupId) ? messages.groupCollapsed : messages.groupExpanded
1762
- );
1763
- }
1764
- function handleColumnSortChange(event) {
1765
- onColumnSortChange?.(event);
1766
- const entry = event.sort.find(
1767
- (candidate) => candidate.columnId === event.columnId
1768
- );
1769
- if (entry === void 0) {
1770
- announce(messages.sortCleared(columnName(event.columnId)));
1771
- return;
1772
- }
1773
- announce(
1774
- messages.columnSorted(
1775
- columnName(event.columnId),
1776
- entry.direction,
1777
- event.sort.indexOf(entry) + 1,
1778
- event.sort.length
1779
- )
1780
- );
1781
- }
1782
- function handlePaginationChange(event) {
1783
- onPaginationChange?.(event);
1784
- announce(
1785
- messages.pageStatus(event.pagination.pageIndex + 1, event.pageCount)
1786
- );
1787
- }
1788
- function handleSelectionDiff(event) {
1789
- if (event.added.length + event.removed.length > 1) {
1790
- announce(messages.selectedCount(event.selection.length, event.target));
1791
- }
1792
- }
1793
- function handleCellSelectionChange(event) {
1794
- onCellSelectionChange?.(event);
1795
- if (event.selected !== null) {
1796
- announce(
1797
- messages.cellSelected(
1798
- columnName(event.selected.columnId),
1799
- event.selected.rowIndex + 1
1800
- )
1801
- );
1802
- }
1803
- }
1804
3176
  const nav = useGridNavigation({
1805
3177
  headerTableRef,
1806
3178
  bodyTableRef,
@@ -1824,19 +3196,29 @@ function DataGrid(props) {
1824
3196
  return entry !== void 0 && "kind" in entry && entry.kind === "group-summary";
1825
3197
  }
1826
3198
  });
1827
- const orderedIds = useMemo3(
3199
+ const panels = useGridPanels({ rootRef: viewportRef, headerTableRef, nav });
3200
+ const commands = useGridCommands({
3201
+ controller,
3202
+ commands: props.commands,
3203
+ onCommand: props.onCommand,
3204
+ messages,
3205
+ announce,
3206
+ resize,
3207
+ openPanel: panels.open
3208
+ });
3209
+ const orderedIds = useMemo4(
1828
3210
  () => view.dataColumns.map((entry) => entry.id),
1829
3211
  [view.dataColumns]
1830
3212
  );
1831
- const displayedIds = useMemo3(
3213
+ const displayedIds = useMemo4(
1832
3214
  () => view.columns.map((entry) => entry.id),
1833
3215
  [view.columns]
1834
3216
  );
1835
- const definitions = useMemo3(
3217
+ const definitions = useMemo4(
1836
3218
  () => new Map(view.dataColumns.map((entry) => [entry.id, entry.column])),
1837
3219
  [view.dataColumns]
1838
3220
  );
1839
- const groupByDraggableIds = useMemo3(
3221
+ const groupByDraggableIds = useMemo4(
1840
3222
  () => new Set(
1841
3223
  view.columns.filter((entry) => entry.groupByDraggable).map((entry) => entry.id)
1842
3224
  ),
@@ -1881,7 +3263,21 @@ function DataGrid(props) {
1881
3263
  };
1882
3264
  const selection = useGridSelection({ controller, state, selectable });
1883
3265
  const multiselectable = selection.rowMode === "multiple" || selection.columnMode === "multiple";
1884
- useEffect3(() => {
3266
+ const contextMenu = useContextMenu({
3267
+ rootRef: viewportRef,
3268
+ headerTableRef,
3269
+ bodyTableRef,
3270
+ bodyScrollRef,
3271
+ contextMenu: props.contextMenu,
3272
+ onContextMenuOpenChange: props.onContextMenuOpenChange,
3273
+ controller,
3274
+ commands,
3275
+ nav,
3276
+ selection,
3277
+ messages,
3278
+ columnName
3279
+ });
3280
+ useEffect5(() => {
1885
3281
  for (const listener of subscribersRef.current) {
1886
3282
  listener();
1887
3283
  }
@@ -1942,11 +3338,19 @@ function DataGrid(props) {
1942
3338
  setColumnSelection: controller.setColumnSelection,
1943
3339
  setCellSelection: controller.setCellSelection,
1944
3340
  autoFitColumn: (columnId) => {
1945
- const entry = controller.getView().columns.find((candidate) => candidate.id === columnId);
1946
- if (entry !== void 0) {
1947
- resize.sizeToContent(entry);
1948
- }
3341
+ commands.host.autoFitColumns([columnId]);
3342
+ },
3343
+ autoFitColumns: (columnIds) => {
3344
+ commands.host.autoFitColumns(
3345
+ columnIds ?? controller.getView().columns.map((entry) => entry.id)
3346
+ );
1949
3347
  },
3348
+ openContextMenu: contextMenu.open,
3349
+ closeContextMenu: contextMenu.close,
3350
+ openColumnChooser: () => {
3351
+ panels.open("columnChooser", { area: "grid" });
3352
+ },
3353
+ runCommand: (commandId, target = { area: "grid" }) => commands.run(commandId, target, "api"),
1950
3354
  scrollToRow: (rowId, options) => {
1951
3355
  const index = controller.getView().pageRows.findIndex(
1952
3356
  (entry) => !("kind" in entry) && entry.rowId === rowId
@@ -1987,8 +3391,20 @@ function DataGrid(props) {
1987
3391
  selection.columnMode === false ? "" : "selectable-columns",
1988
3392
  selection.cellMode === false ? "" : "selectable-cells"
1989
3393
  );
1990
- return /* @__PURE__ */ jsxs7("div", { className: "gridkit-data-grid-viewport", ref: viewportRef, children: [
1991
- showGroupByBar && /* @__PURE__ */ jsx10(
3394
+ return /* @__PURE__ */ jsxs13("div", { className: "gridkit-data-grid-viewport", ref: viewportRef, children: [
3395
+ /* @__PURE__ */ jsx20(
3396
+ GridToolbar,
3397
+ {
3398
+ toolbar: props.toolbar,
3399
+ renderItem: props.renderToolbarItem,
3400
+ gridId,
3401
+ controller,
3402
+ commands,
3403
+ messages,
3404
+ announce
3405
+ }
3406
+ ),
3407
+ showGroupByBar && /* @__PURE__ */ jsx20(
1992
3408
  GroupByBar,
1993
3409
  {
1994
3410
  columns: view.columns,
@@ -2002,9 +3418,10 @@ function DataGrid(props) {
2002
3418
  messages
2003
3419
  }
2004
3420
  ),
2005
- /* @__PURE__ */ jsxs7(
3421
+ /* @__PURE__ */ jsxs13(
2006
3422
  "div",
2007
3423
  {
3424
+ id: gridId,
2008
3425
  className: "gridkit-data-grid-tables",
2009
3426
  role: state.groupBy.length > 0 ? "treegrid" : "grid",
2010
3427
  "aria-rowcount": view.displayRows.length + 1,
@@ -2017,6 +3434,7 @@ function DataGrid(props) {
2017
3434
  label
2018
3435
  ),
2019
3436
  onKeyDown: (event) => {
3437
+ if (!isOwnEvent(event)) return;
2020
3438
  if (event.key === "Escape") {
2021
3439
  if (drag.draggedColumnId !== null || resize.activeColumnId !== null)
2022
3440
  return;
@@ -2030,15 +3448,15 @@ function DataGrid(props) {
2030
3448
  }
2031
3449
  },
2032
3450
  children: [
2033
- /* @__PURE__ */ jsxs7(
3451
+ /* @__PURE__ */ jsxs13(
2034
3452
  "table",
2035
3453
  {
2036
3454
  ref: headerTableRef,
2037
3455
  style: { width: totalColumnWidth(view.columns) },
2038
3456
  className: classNames(gridTableClassName, "gridkit-data-grid-header"),
2039
3457
  children: [
2040
- /* @__PURE__ */ jsx10(GridColgroup, { columns: view.columns }),
2041
- /* @__PURE__ */ jsx10(
3458
+ /* @__PURE__ */ jsx20(GridColgroup, { columns: view.columns }),
3459
+ /* @__PURE__ */ jsx20(
2042
3460
  GridHeader,
2043
3461
  {
2044
3462
  columns: view.columns,
@@ -2050,6 +3468,7 @@ function DataGrid(props) {
2050
3468
  groupBy: state.groupBy,
2051
3469
  groupableColumns,
2052
3470
  groupToggleIconColumns,
3471
+ headerMenu: contextMenu.opens("header"),
2053
3472
  nav,
2054
3473
  selection
2055
3474
  }
@@ -2057,7 +3476,7 @@ function DataGrid(props) {
2057
3476
  ]
2058
3477
  }
2059
3478
  ),
2060
- /* @__PURE__ */ jsx10(
3479
+ /* @__PURE__ */ jsx20(
2061
3480
  "div",
2062
3481
  {
2063
3482
  className: "gridkit-data-grid-body",
@@ -2065,15 +3484,15 @@ function DataGrid(props) {
2065
3484
  style: height === void 0 ? void 0 : {
2066
3485
  "--gridkit-body-height": typeof height === "number" ? `${String(height)}px` : height
2067
3486
  },
2068
- children: /* @__PURE__ */ jsxs7(
3487
+ children: /* @__PURE__ */ jsxs13(
2069
3488
  "table",
2070
3489
  {
2071
3490
  ref: bodyTableRef,
2072
3491
  style: { width: totalColumnWidth(view.columns) },
2073
3492
  className: gridTableClassName,
2074
3493
  children: [
2075
- /* @__PURE__ */ jsx10(GridColgroup, { columns: view.columns }),
2076
- /* @__PURE__ */ jsx10(
3494
+ /* @__PURE__ */ jsx20(GridColgroup, { columns: view.columns }),
3495
+ /* @__PURE__ */ jsx20(
2077
3496
  GridBody,
2078
3497
  {
2079
3498
  columns: view.columns,
@@ -2092,7 +3511,9 @@ function DataGrid(props) {
2092
3511
  getRowProps,
2093
3512
  onRowClick,
2094
3513
  onRowDoubleClick,
2095
- messages
3514
+ messages,
3515
+ cellMenu: contextMenu.opens("cell"),
3516
+ groupMenu: contextMenu.opens("group")
2096
3517
  }
2097
3518
  )
2098
3519
  ]
@@ -2100,7 +3521,7 @@ function DataGrid(props) {
2100
3521
  )
2101
3522
  }
2102
3523
  ),
2103
- aggregates.length > 0 && /* @__PURE__ */ jsxs7(
3524
+ aggregates.length > 0 && /* @__PURE__ */ jsxs13(
2104
3525
  "table",
2105
3526
  {
2106
3527
  style: { width: totalColumnWidth(view.columns) },
@@ -2109,8 +3530,8 @@ function DataGrid(props) {
2109
3530
  "gridkit-data-grid-footer"
2110
3531
  ),
2111
3532
  children: [
2112
- /* @__PURE__ */ jsx10(GridColgroup, { columns: view.columns }),
2113
- /* @__PURE__ */ jsx10(
3533
+ /* @__PURE__ */ jsx20(GridColgroup, { columns: view.columns }),
3534
+ /* @__PURE__ */ jsx20(
2114
3535
  GridFooter,
2115
3536
  {
2116
3537
  columns: view.columns,
@@ -2126,7 +3547,9 @@ function DataGrid(props) {
2126
3547
  ]
2127
3548
  }
2128
3549
  ),
2129
- paginated && (pager?.template ? pager.template(pagerContext) : /* @__PURE__ */ jsx10(GridPager, { pager: pagerContext, config: pager, messages }))
3550
+ /* @__PURE__ */ jsx20(GridContextMenu, { contextMenu }),
3551
+ /* @__PURE__ */ jsx20(GridPanels, { panels, controller, messages }),
3552
+ paginated && (pager?.template ? pager.template(pagerContext) : /* @__PURE__ */ jsx20(GridPager, { pager: pagerContext, config: pager, messages }))
2130
3553
  ] });
2131
3554
  }
2132
3555
 
@@ -2303,9 +3726,9 @@ function useColumnVisibilityState(gridRef) {
2303
3726
  }
2304
3727
 
2305
3728
  // src/DataGrid/hooks/useFilterState.ts
2306
- import { useCallback as useCallback11, useState as useState9 } from "react";
3729
+ import { useCallback as useCallback11, useState as useState16 } from "react";
2307
3730
  function useFilterState(gridRef) {
2308
- const [fallback] = useState9(() => []);
3731
+ const [fallback] = useState16(() => []);
2309
3732
  const filter = useGridSnapshot(
2310
3733
  gridRef,
2311
3734
  useCallback11((api) => api.getFilter(), []),