@gridkitjs/react 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/DataGrid/DataGrid.tsx
2
2
  import {
3
3
  useImperativeHandle,
4
- useMemo as useMemo2,
4
+ useMemo as useMemo3,
5
5
  useRef as useRef4,
6
6
  useState as useState5
7
7
  } from "react";
@@ -9,6 +9,7 @@ import {
9
9
  applyColumnOrder,
10
10
  defineColumnsFromRows,
11
11
  fitColumnsToWidth,
12
+ groupRows,
12
13
  moveColumnBefore,
13
14
  resolveColumnWidths,
14
15
  resolveRowId,
@@ -47,7 +48,11 @@ function tabIndexFor(columnIndex, focusedColumnIndex) {
47
48
  }
48
49
  function cellAt(table, focus) {
49
50
  const row = focus.rowIndex === HEADER_ROW ? table.tHead?.rows[0] ?? null : table.tBodies[0]?.rows[focus.rowIndex] ?? null;
50
- return row?.cells[focus.columnIndex] ?? null;
51
+ if (row === null) {
52
+ return null;
53
+ }
54
+ const columnIndex = Math.min(focus.columnIndex, row.cells.length - 1);
55
+ return row.cells[columnIndex] ?? null;
51
56
  }
52
57
  function useGridNavigation({
53
58
  tableRef,
@@ -366,16 +371,26 @@ function ChevronsUpDownIcon() {
366
371
  function ChevronUpIcon() {
367
372
  return /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx("path", { d: "m18 15-6-6-6 6" }) });
368
373
  }
374
+ function GroupIcon() {
375
+ return /* @__PURE__ */ jsxs(Icon, { children: [
376
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }),
377
+ /* @__PURE__ */ jsx("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }),
378
+ /* @__PURE__ */ jsx("rect", { x: "8.5", y: "14", width: "7", height: "7", rx: "1" })
379
+ ] });
380
+ }
369
381
  function GridHeader({
370
382
  columns,
371
383
  resize,
372
384
  drag,
373
385
  sort,
374
386
  sortableColumns,
387
+ grouping,
388
+ groupableColumns,
389
+ groupToggleIconColumns,
375
390
  nav,
376
391
  selection
377
392
  }) {
378
- const { beforeId } = drag.dropTarget ?? {};
393
+ const beforeId = drag.dropTarget?.kind === "column-order" ? drag.dropTarget.beforeId : void 0;
379
394
  const draggedEntry = columns.find((entry) => entry.id === drag.draggedColumnId) ?? null;
380
395
  return /* @__PURE__ */ jsxs("thead", { children: [
381
396
  /* @__PURE__ */ jsx("tr", { className: "grid-header", role: "row", "aria-rowindex": 1, children: columns.map((entry, index) => {
@@ -388,10 +403,16 @@ function GridHeader({
388
403
  const sortable = column.sortable ?? sortableColumns;
389
404
  const sortDirection = sort.directionFor(entry.id);
390
405
  const sortPriority = sort.priorityFor(entry.id);
406
+ const groupable = column.groupable ?? groupableColumns;
407
+ const showGroupToggleIcon = column.groupToggleIcon ?? groupToggleIconColumns;
408
+ const isGrouped = grouping.groupBy.some(
409
+ (level) => level.columnId === entry.id
410
+ );
391
411
  const shortcuts = buildKeyShortcuts({
392
412
  reorderable: entry.reorderable,
393
413
  resizable: entry.resizable,
394
- sortable
414
+ sortable,
415
+ groupable
395
416
  });
396
417
  return /* @__PURE__ */ jsxs(
397
418
  "th",
@@ -413,7 +434,7 @@ function GridHeader({
413
434
  if (drag.justDragged()) {
414
435
  return;
415
436
  }
416
- if (event.target instanceof Element && (event.target.closest(".header-resize-handle") !== null || event.target.closest(".header-sort-toggle") !== null)) {
437
+ if (event.target instanceof Element && (event.target.closest(".header-resize-handle") !== null || event.target.closest(".header-sort-toggle") !== null || event.target.closest(".header-group-toggle") !== null)) {
417
438
  return;
418
439
  }
419
440
  selection.selectColumn(entry.id, intentOf(event));
@@ -441,6 +462,11 @@ function GridHeader({
441
462
  sort.toggle(entry, { shiftKey: event.shiftKey });
442
463
  return;
443
464
  }
465
+ if (event.key === "ArrowDown" && event.altKey && groupable) {
466
+ event.preventDefault();
467
+ grouping.toggleGroupBy(entry.id);
468
+ return;
469
+ }
444
470
  if (event.key === " " || event.key === "Enter") {
445
471
  event.preventDefault();
446
472
  selection.selectColumn(
@@ -453,7 +479,11 @@ function GridHeader({
453
479
  },
454
480
  className: classNames(
455
481
  "header-cell",
456
- entry.reorderable ? "is-reorderable" : "",
482
+ // The grab affordance a header showing either drag
483
+ // destination shares — a column dragged only for grouping
484
+ // (`groupByDraggable` without `reorderable`) grabs the same
485
+ // way one dragged only for reordering does.
486
+ entry.reorderable || entry.groupByDraggable ? "is-reorderable" : "",
457
487
  selected ? "is-selected" : "",
458
488
  resizing ? "is-resizing" : "",
459
489
  dragging ? "is-dragging" : "",
@@ -468,12 +498,40 @@ function GridHeader({
468
498
  "aria-sort",
469
499
  sortDirection === "asc" ? "ascending" : "descending"
470
500
  ),
471
- ...entry.reorderable && {
501
+ ...(entry.reorderable || entry.groupByDraggable) && {
472
502
  onPointerDown: (event) => {
473
503
  drag.startDrag(entry, event);
474
504
  }
475
505
  },
476
506
  children: [
507
+ groupable && showGroupToggleIcon && /*
508
+ * Inline, before the label, rather than absolutely
509
+ * positioned like the sort toggle and resize handle: those
510
+ * two already share the header's right edge, and a third
511
+ * overlay there would need its own carve-out. Sitting in
512
+ * normal flow costs nothing but a few pixels of label width.
513
+ * A pointer affordance only, same as the other two — the
514
+ * keyboard equivalent is Alt+ArrowDown on the header itself.
515
+ */
516
+ /* @__PURE__ */ jsx(
517
+ "span",
518
+ {
519
+ className: classNames(
520
+ "header-group-toggle",
521
+ isGrouped ? "is-grouped" : ""
522
+ ),
523
+ "aria-hidden": "true",
524
+ tabIndex: -1,
525
+ onPointerDown: (event) => {
526
+ event.stopPropagation();
527
+ },
528
+ onClick: (event) => {
529
+ event.stopPropagation();
530
+ grouping.toggleGroupBy(entry.id);
531
+ },
532
+ children: /* @__PURE__ */ jsx(GroupIcon, {})
533
+ }
534
+ ),
477
535
  entry.label,
478
536
  sortable && /*
479
537
  * A pointer affordance only, and hidden from assistive
@@ -546,12 +604,108 @@ function GridHeader({
546
604
  }
547
605
 
548
606
  // src/DataGrid/components/GridBody.tsx
549
- import { intentOf as intentOf2 } from "@gridkitjs/core";
607
+ import { useMemo as useMemo2 } from "react";
608
+ import { groupRowId, intentOf as intentOf2 } from "@gridkitjs/core";
609
+
610
+ // src/DataGrid/components/GridGroupRow.tsx
611
+ import { memo } from "react";
612
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
613
+ function formatGroupValue(value) {
614
+ if (value === null || value === void 0) {
615
+ return "(blank)";
616
+ }
617
+ if (value instanceof Date) {
618
+ return value.toLocaleString();
619
+ }
620
+ switch (typeof value) {
621
+ case "string":
622
+ case "number":
623
+ case "boolean":
624
+ case "bigint":
625
+ case "symbol":
626
+ return String(value);
627
+ case "function":
628
+ return "(function)";
629
+ default:
630
+ return JSON.stringify(value);
631
+ }
632
+ }
633
+ function GridGroupRowComponent({
634
+ columnCount,
635
+ groupId,
636
+ level,
637
+ columnLabel,
638
+ value,
639
+ expanded,
640
+ count,
641
+ rowIndex,
642
+ posinset,
643
+ setsize,
644
+ focused
645
+ }) {
646
+ return /* @__PURE__ */ jsx2(
647
+ "tr",
648
+ {
649
+ role: "row",
650
+ "aria-rowindex": rowIndex + 2,
651
+ "aria-level": level + 1,
652
+ "aria-expanded": expanded,
653
+ "aria-setsize": setsize,
654
+ "aria-posinset": posinset,
655
+ "data-gridkit-group": groupId,
656
+ className: classNames(
657
+ "grid-group-row",
658
+ `is-group-level-${String(level)}`
659
+ ),
660
+ children: /* @__PURE__ */ jsx2(
661
+ "td",
662
+ {
663
+ role: "gridcell",
664
+ colSpan: columnCount,
665
+ tabIndex: focused ? 0 : -1,
666
+ "aria-keyshortcuts": "Space Enter",
667
+ className: "grid-group-cell",
668
+ children: /* @__PURE__ */ jsxs2(
669
+ "div",
670
+ {
671
+ className: "grid-group-cell-content",
672
+ style: { paddingInlineStart: `${String(level * 1.25 + 0.5)}rem` },
673
+ children: [
674
+ /* @__PURE__ */ jsx2(
675
+ "span",
676
+ {
677
+ className: classNames(
678
+ "group-toggle",
679
+ expanded ? "is-expanded" : "is-collapsed"
680
+ ),
681
+ "aria-hidden": "true"
682
+ }
683
+ ),
684
+ /* @__PURE__ */ jsxs2("span", { className: "group-label", children: [
685
+ columnLabel,
686
+ ": ",
687
+ formatGroupValue(value)
688
+ ] }),
689
+ /* @__PURE__ */ jsxs2("span", { className: "group-count", children: [
690
+ "(",
691
+ count,
692
+ ")"
693
+ ] })
694
+ ]
695
+ }
696
+ )
697
+ }
698
+ )
699
+ }
700
+ );
701
+ }
702
+ var GridGroupRow = memo(GridGroupRowComponent);
703
+ var GridGroupRow_default = GridGroupRow;
550
704
 
551
705
  // src/DataGrid/components/GridRow.tsx
552
706
  import { accessDotted } from "@gridkitjs/core";
553
- import { memo } from "react";
554
- import { jsx as jsx2 } from "react/jsx-runtime";
707
+ import { memo as memo2 } from "react";
708
+ import { jsx as jsx3 } from "react/jsx-runtime";
555
709
  function GridRowComponent({
556
710
  columns,
557
711
  rowId,
@@ -565,7 +719,7 @@ function GridRowComponent({
565
719
  rowsSelectable,
566
720
  cellsSelectable
567
721
  }) {
568
- return /* @__PURE__ */ jsx2(
722
+ return /* @__PURE__ */ jsx3(
569
723
  "tr",
570
724
  {
571
725
  role: "row",
@@ -575,7 +729,7 @@ function GridRowComponent({
575
729
  children: columns.map(({ id, column, alignment }, columnIndex) => {
576
730
  const value = accessDotted(row, column.field);
577
731
  const cellSelected = id === selectedColumnId;
578
- return /* @__PURE__ */ jsx2(
732
+ return /* @__PURE__ */ jsx3(
579
733
  "td",
580
734
  {
581
735
  role: "gridcell",
@@ -600,11 +754,11 @@ function GridRowComponent({
600
754
  }
601
755
  );
602
756
  }
603
- var GridRow = memo(GridRowComponent);
757
+ var GridRow = memo2(GridRowComponent);
604
758
  var GridRow_default = GridRow;
605
759
 
606
760
  // src/DataGrid/components/GridBody.tsx
607
- import { jsx as jsx3 } from "react/jsx-runtime";
761
+ import { jsx as jsx4 } from "react/jsx-runtime";
608
762
  function cellFrom(target) {
609
763
  if (!(target instanceof Element)) {
610
764
  return null;
@@ -621,18 +775,55 @@ function cellFrom(target) {
621
775
  columnId
622
776
  };
623
777
  }
778
+ function groupRowFrom(target) {
779
+ if (!(target instanceof Element)) {
780
+ return null;
781
+ }
782
+ const row = target.closest("tr[data-gridkit-group]");
783
+ const groupId = row?.getAttribute("data-gridkit-group");
784
+ if (!(row instanceof HTMLTableRowElement) || groupId === null || groupId === void 0) {
785
+ return null;
786
+ }
787
+ return { rowIndex: row.sectionRowIndex, groupId };
788
+ }
789
+ function groupAriaMeta(rows) {
790
+ const totals = /* @__PURE__ */ new Map();
791
+ for (const entry of rows) {
792
+ if (!("kind" in entry)) continue;
793
+ const parentKey = groupRowId(entry.path.slice(0, -1));
794
+ totals.set(parentKey, (totals.get(parentKey) ?? 0) + 1);
795
+ }
796
+ const seen = /* @__PURE__ */ new Map();
797
+ const meta = /* @__PURE__ */ new Map();
798
+ for (const entry of rows) {
799
+ if (!("kind" in entry)) continue;
800
+ const parentKey = groupRowId(entry.path.slice(0, -1));
801
+ const posinset = (seen.get(parentKey) ?? 0) + 1;
802
+ seen.set(parentKey, posinset);
803
+ meta.set(entry.groupId, {
804
+ posinset,
805
+ setsize: totals.get(parentKey) ?? posinset
806
+ });
807
+ }
808
+ return meta;
809
+ }
624
810
  function GridBody({
625
811
  columns,
626
812
  rows,
627
813
  activeColumnId,
628
814
  nav,
629
- selection
815
+ selection,
816
+ grouping
630
817
  }) {
631
818
  const { selectedCell, rowMode, cellMode } = selection;
819
+ const ariaMeta = useMemo2(() => groupAriaMeta(rows), [rows]);
632
820
  function targetOf(target) {
633
821
  const position = cellFrom(target);
634
822
  const entry = position === null ? void 0 : rows[position.rowIndex];
635
- return position === null || entry === void 0 ? null : { position, rowId: entry.rowId };
823
+ if (position === null || entry === void 0 || "kind" in entry) {
824
+ return null;
825
+ }
826
+ return { position, rowId: entry.rowId };
636
827
  }
637
828
  function select(rowId, columnId, modifiers) {
638
829
  const intent = intentOf2(modifiers);
@@ -643,21 +834,45 @@ function GridBody({
643
834
  selection.selectCell({ rowId, columnId }, intent);
644
835
  }
645
836
  }
646
- return /* @__PURE__ */ jsx3(
837
+ return /* @__PURE__ */ jsx4(
647
838
  "tbody",
648
839
  {
649
840
  className: "grid-body",
650
841
  onFocus: (event) => {
842
+ const group = groupRowFrom(event.target);
843
+ if (group !== null) {
844
+ nav.focusCell(group.rowIndex, 0);
845
+ return;
846
+ }
651
847
  const found = targetOf(event.target);
652
848
  if (found === null) return;
653
849
  nav.focusCell(found.position.rowIndex, found.position.columnIndex);
654
850
  },
655
851
  onClick: (event) => {
852
+ const group = groupRowFrom(event.target);
853
+ if (group !== null) {
854
+ grouping.toggleExpansion(group.groupId);
855
+ return;
856
+ }
656
857
  const found = targetOf(event.target);
657
858
  if (found === null) return;
658
859
  select(found.rowId, found.position.columnId, event);
659
860
  },
660
861
  onKeyDown: (event) => {
862
+ const group = groupRowFrom(event.target);
863
+ if (group !== null) {
864
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
865
+ event.preventDefault();
866
+ return;
867
+ }
868
+ if (event.key === " " || event.key === "Enter") {
869
+ event.preventDefault();
870
+ grouping.toggleExpansion(group.groupId);
871
+ return;
872
+ }
873
+ nav.onKeyDown(event);
874
+ return;
875
+ }
661
876
  if (event.key === " " || event.key === "Enter") {
662
877
  const found = targetOf(event.target);
663
878
  if (found === null) return;
@@ -671,37 +886,60 @@ function GridBody({
671
886
  }
672
887
  nav.onKeyDown(event);
673
888
  },
674
- children: rows.map(({ rowId, row, rowIndex }) => /* @__PURE__ */ jsx3(
675
- GridRow_default,
676
- {
677
- columns,
678
- rowId,
679
- row,
680
- rowIndex,
681
- activeColumnId,
682
- selectedColumnIds: selection.selectedColumnIds,
683
- selected: selection.selectedRowIds.has(rowId),
684
- selectedColumnId: selectedCell?.rowId === rowId ? selectedCell.columnId : null,
685
- focusedColumnIndex: nav.focus.rowIndex === rowIndex ? nav.focus.columnIndex : null,
686
- rowsSelectable: rowMode !== false,
687
- cellsSelectable: cellMode !== false
688
- },
689
- rowId
690
- ))
889
+ children: rows.map(
890
+ (entry) => "kind" in entry ? /* @__PURE__ */ jsx4(
891
+ GridGroupRow_default,
892
+ {
893
+ columnCount: columns.length,
894
+ groupId: entry.groupId,
895
+ level: entry.level,
896
+ columnLabel: columns.find((column) => column.id === entry.columnId)?.label ?? entry.columnId,
897
+ value: entry.value,
898
+ expanded: entry.expanded,
899
+ count: entry.count,
900
+ rowIndex: entry.rowIndex,
901
+ posinset: ariaMeta.get(entry.groupId)?.posinset ?? 1,
902
+ setsize: ariaMeta.get(entry.groupId)?.setsize ?? 1,
903
+ focused: nav.focus.rowIndex === entry.rowIndex
904
+ },
905
+ entry.groupId
906
+ ) : /* @__PURE__ */ jsx4(
907
+ GridRow_default,
908
+ {
909
+ columns,
910
+ rowId: entry.rowId,
911
+ row: entry.row,
912
+ rowIndex: entry.rowIndex,
913
+ activeColumnId,
914
+ selectedColumnIds: selection.selectedColumnIds,
915
+ selected: selection.selectedRowIds.has(entry.rowId),
916
+ selectedColumnId: selectedCell?.rowId === entry.rowId ? selectedCell.columnId : null,
917
+ focusedColumnIndex: nav.focus.rowIndex === entry.rowIndex ? nav.focus.columnIndex : null,
918
+ rowsSelectable: rowMode !== false,
919
+ cellsSelectable: cellMode !== false
920
+ },
921
+ entry.rowId
922
+ )
923
+ )
691
924
  }
692
925
  );
693
926
  }
694
927
 
695
- // src/DataGrid/useColumnDrag.ts
928
+ // src/DataGrid/components/GroupByBar.tsx
929
+ import { createPortal as createPortal2 } from "react-dom";
930
+ import { resolveKeyboardDropTarget } from "@gridkitjs/core";
931
+
932
+ // src/DataGrid/groupByDropTarget.ts
933
+ import {
934
+ movesGroupBy,
935
+ resolveDropBefore
936
+ } from "@gridkitjs/core";
937
+
938
+ // src/DataGrid/useDragReorder.ts
696
939
  import {
697
940
  useRef as useRef3,
698
941
  useState as useState2
699
942
  } from "react";
700
- import {
701
- movesColumn,
702
- resolveDropBefore,
703
- resolveKeyboardDropTarget
704
- } from "@gridkitjs/core";
705
943
 
706
944
  // src/DataGrid/pointerGesture.ts
707
945
  function startPointerGesture(element, pointerId, handlers) {
@@ -737,21 +975,20 @@ function startPointerGesture(element, pointerId, handlers) {
737
975
  window.addEventListener("keydown", onKeyDown);
738
976
  }
739
977
 
740
- // src/DataGrid/useColumnDrag.ts
978
+ // src/DataGrid/useDragReorder.ts
741
979
  var DRAG_THRESHOLD = 4;
742
- function headerAt(x, y) {
743
- const element = document.elementFromPoint(x, y);
744
- return element?.closest("th[data-gridkit-column]") ?? null;
980
+ function elementAt(x, y, selector) {
981
+ return document.elementFromPoint(x, y)?.closest(selector) ?? null;
745
982
  }
746
983
  function sideOf(element, x) {
747
984
  const rect = element.getBoundingClientRect();
748
985
  return x < rect.left + rect.width / 2 ? "before" : "after";
749
986
  }
750
- function useColumnDrag({
751
- order,
987
+ function useDragReorder({
988
+ resolveTarget,
752
989
  onDrop
753
990
  }) {
754
- const [draggedColumnId, setDraggedColumnId] = useState2(null);
991
+ const [draggedId, setDraggedId] = useState2(null);
755
992
  const [dropTarget, setDropTarget] = useState2(null);
756
993
  const [ghostTransform, setGhostTransform] = useState2(null);
757
994
  const dragged = useRef3(false);
@@ -760,10 +997,9 @@ function useColumnDrag({
760
997
  dragged.current = false;
761
998
  return answer;
762
999
  }
763
- function startDrag(entry, event) {
764
- const header = event.currentTarget;
1000
+ function startDrag(id, grabElement, event) {
765
1001
  const { pointerId, clientX: startX } = event;
766
- const grabX = startX - header.getBoundingClientRect().left;
1002
+ const grabX = startX - grabElement.getBoundingClientRect().left;
767
1003
  let dragging = false;
768
1004
  let target = null;
769
1005
  function placeGhost(x, y) {
@@ -771,10 +1007,10 @@ function useColumnDrag({
771
1007
  }
772
1008
  function reset() {
773
1009
  setGhostTransform(null);
774
- setDraggedColumnId(null);
1010
+ setDraggedId(null);
775
1011
  setDropTarget(null);
776
1012
  }
777
- startPointerGesture(header, pointerId, {
1013
+ startPointerGesture(grabElement, pointerId, {
778
1014
  onMove(moveEvent) {
779
1015
  const { clientX, clientY } = moveEvent;
780
1016
  if (!dragging) {
@@ -783,20 +1019,17 @@ function useColumnDrag({
783
1019
  }
784
1020
  dragging = true;
785
1021
  dragged.current = true;
786
- setDraggedColumnId(entry.id);
1022
+ setDraggedId(id);
787
1023
  }
788
1024
  placeGhost(clientX, clientY);
789
- const over = headerAt(clientX, clientY);
790
- const overId = over?.getAttribute("data-gridkit-column");
791
- const beforeId = over && overId ? resolveDropBefore(order, overId, sideOf(over, clientX)) : void 0;
792
- target = beforeId !== void 0 && movesColumn(order, entry.id, beforeId) ? { kind: "column-order", beforeId } : null;
1025
+ target = resolveTarget(clientX, clientY, id);
793
1026
  setDropTarget(target);
794
1027
  },
795
1028
  onEnd() {
796
1029
  const dropped = target;
797
1030
  reset();
798
1031
  if (dragging && dropped !== null) {
799
- onDrop(dropped, entry.id);
1032
+ onDrop(dropped, id);
800
1033
  }
801
1034
  },
802
1035
  // Escape and a cancelled pointer both leave the order as it was.
@@ -806,20 +1039,214 @@ function useColumnDrag({
806
1039
  }
807
1040
  });
808
1041
  }
1042
+ return {
1043
+ draggedId,
1044
+ dropTarget,
1045
+ ghostTransform,
1046
+ startDrag,
1047
+ justDragged
1048
+ };
1049
+ }
1050
+
1051
+ // src/DataGrid/groupByDropTarget.ts
1052
+ function resolveGroupByDropTarget(clientX, clientY, movedId, groupBy) {
1053
+ const overBar = elementAt(clientX, clientY, "[data-gridkit-group-by-bar]");
1054
+ if (overBar === null) {
1055
+ return null;
1056
+ }
1057
+ const overChip = elementAt(clientX, clientY, "[data-gridkit-group-chip]");
1058
+ const chipId = overChip?.getAttribute("data-gridkit-group-chip");
1059
+ const beforeColumnId = overChip && chipId ? resolveDropBefore(
1060
+ groupBy.map((entry) => entry.columnId),
1061
+ chipId,
1062
+ sideOf(overChip, clientX)
1063
+ ) : null;
1064
+ return movesGroupBy(groupBy, movedId, beforeColumnId) ? { kind: "group-by", beforeColumnId } : null;
1065
+ }
1066
+
1067
+ // src/DataGrid/useGroupByDrag.ts
1068
+ function useGroupByDrag({
1069
+ groupBy,
1070
+ onDrop
1071
+ }) {
1072
+ const drag = useDragReorder({
1073
+ resolveTarget: (clientX, clientY, movedId) => resolveGroupByDropTarget(clientX, clientY, movedId, groupBy),
1074
+ onDrop: (target, movedId) => {
1075
+ onDrop(movedId, target.beforeColumnId);
1076
+ }
1077
+ });
1078
+ return {
1079
+ draggedColumnId: drag.draggedId,
1080
+ dropTarget: drag.dropTarget,
1081
+ ghostTransform: drag.ghostTransform,
1082
+ startDrag: (columnId, event) => {
1083
+ drag.startDrag(columnId, event.currentTarget, event);
1084
+ },
1085
+ justDragged: drag.justDragged
1086
+ };
1087
+ }
1088
+
1089
+ // src/DataGrid/components/GroupByBar.tsx
1090
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1091
+ function GroupByBar({
1092
+ columns,
1093
+ grouping,
1094
+ columnName,
1095
+ headerDragEligible,
1096
+ headerDragBlocked,
1097
+ headerDropTarget
1098
+ }) {
1099
+ const { groupBy } = grouping;
1100
+ const groupByIds = groupBy.map((entry) => entry.columnId);
1101
+ const chipDrag = useGroupByDrag({
1102
+ groupBy,
1103
+ onDrop: (movedId, beforeColumnId) => {
1104
+ grouping.moveGroupBy(movedId, beforeColumnId);
1105
+ }
1106
+ });
1107
+ const activeDropTarget = chipDrag.dropTarget ?? headerDropTarget;
1108
+ const isDragTarget = chipDrag.draggedColumnId !== null || headerDragEligible;
1109
+ const showPlaceholder = groupBy.length === 0 && columns.some((entry) => entry.groupByDraggable);
1110
+ function labelFor(columnId) {
1111
+ return columns.find((entry) => entry.id === columnId)?.label ?? columnId;
1112
+ }
1113
+ function moveByKeyboard(columnId, direction) {
1114
+ const beforeColumnId = resolveKeyboardDropTarget(
1115
+ groupByIds,
1116
+ columnId,
1117
+ direction
1118
+ );
1119
+ if (beforeColumnId === void 0) {
1120
+ return;
1121
+ }
1122
+ grouping.moveGroupBy(columnId, beforeColumnId);
1123
+ }
1124
+ return /* @__PURE__ */ jsxs3(
1125
+ "div",
1126
+ {
1127
+ className: classNames(
1128
+ "gridkit-group-by-bar",
1129
+ isDragTarget ? "is-drag-target" : "",
1130
+ headerDragBlocked ? "is-drag-blocked" : ""
1131
+ ),
1132
+ "data-gridkit-group-by-bar": "",
1133
+ role: "group",
1134
+ "aria-label": "Grouped by",
1135
+ children: [
1136
+ showPlaceholder && /* @__PURE__ */ jsx5("span", { className: "group-by-bar-placeholder", children: "Drag a column here to group by it" }),
1137
+ groupBy.map((entry, index) => {
1138
+ const dropBefore = activeDropTarget?.beforeColumnId === entry.columnId;
1139
+ const dropAfter = activeDropTarget?.beforeColumnId === null && index === groupBy.length - 1;
1140
+ const dragging = chipDrag.draggedColumnId === entry.columnId;
1141
+ return /* @__PURE__ */ jsxs3(
1142
+ "span",
1143
+ {
1144
+ className: classNames(
1145
+ "group-by-chip",
1146
+ dragging ? "is-dragging" : "",
1147
+ dropBefore ? "is-drop-before" : "",
1148
+ dropAfter ? "is-drop-after" : ""
1149
+ ),
1150
+ "data-gridkit-group-chip": entry.columnId,
1151
+ tabIndex: 0,
1152
+ "aria-label": groupBy.length > 1 ? `${columnName(entry.columnId)}, level ${String(index + 1)} of ${String(groupBy.length)}` : columnName(entry.columnId),
1153
+ "aria-keyshortcuts": "Control+ArrowLeft Control+ArrowRight",
1154
+ onPointerDown: (event) => {
1155
+ chipDrag.startDrag(entry.columnId, event);
1156
+ },
1157
+ onKeyDown: (event) => {
1158
+ const horizontal = event.key === "ArrowLeft" || event.key === "ArrowRight";
1159
+ if (horizontal && event.ctrlKey) {
1160
+ event.preventDefault();
1161
+ moveByKeyboard(
1162
+ entry.columnId,
1163
+ event.key === "ArrowLeft" ? -1 : 1
1164
+ );
1165
+ }
1166
+ },
1167
+ children: [
1168
+ /* @__PURE__ */ jsx5("span", { className: "group-by-chip-label", children: labelFor(entry.columnId) }),
1169
+ /* @__PURE__ */ jsx5(
1170
+ "button",
1171
+ {
1172
+ type: "button",
1173
+ className: "group-by-chip-remove",
1174
+ "aria-label": `Stop grouping by ${columnName(entry.columnId)}`,
1175
+ onPointerDown: (event) => {
1176
+ event.stopPropagation();
1177
+ },
1178
+ onClick: () => {
1179
+ grouping.toggleGroupBy(entry.columnId);
1180
+ },
1181
+ children: "\xD7"
1182
+ }
1183
+ )
1184
+ ]
1185
+ },
1186
+ entry.columnId
1187
+ );
1188
+ }),
1189
+ chipDrag.draggedColumnId !== null && chipDrag.ghostTransform !== null && createPortal2(
1190
+ /* @__PURE__ */ jsx5(
1191
+ "span",
1192
+ {
1193
+ className: "group-by-chip drag-ghost",
1194
+ style: { transform: chipDrag.ghostTransform },
1195
+ "aria-hidden": "true",
1196
+ children: labelFor(chipDrag.draggedColumnId)
1197
+ }
1198
+ ),
1199
+ document.body
1200
+ )
1201
+ ]
1202
+ }
1203
+ );
1204
+ }
1205
+
1206
+ // src/DataGrid/useColumnDrag.ts
1207
+ import {
1208
+ movesColumn,
1209
+ resolveDropBefore as resolveDropBefore2,
1210
+ resolveKeyboardDropTarget as resolveKeyboardDropTarget2
1211
+ } from "@gridkitjs/core";
1212
+ function useColumnDrag({
1213
+ order,
1214
+ groupBy,
1215
+ groupByDraggableIds,
1216
+ onDrop
1217
+ }) {
1218
+ const drag = useDragReorder({
1219
+ resolveTarget(clientX, clientY, movedId) {
1220
+ const over = elementAt(clientX, clientY, "th[data-gridkit-column]");
1221
+ const overId = over?.getAttribute("data-gridkit-column");
1222
+ const beforeId = over && overId ? resolveDropBefore2(order, overId, sideOf(over, clientX)) : void 0;
1223
+ if (beforeId !== void 0) {
1224
+ return movesColumn(order, movedId, beforeId) ? { kind: "column-order", beforeId } : null;
1225
+ }
1226
+ const alreadyGrouped = groupBy.some(
1227
+ (entry) => entry.columnId === movedId
1228
+ );
1229
+ return groupByDraggableIds.has(movedId) && !alreadyGrouped ? resolveGroupByDropTarget(clientX, clientY, movedId, groupBy) : null;
1230
+ },
1231
+ onDrop
1232
+ });
1233
+ function startDrag(entry, event) {
1234
+ drag.startDrag(entry.id, event.currentTarget, event);
1235
+ }
809
1236
  function moveByKeyboard(entry, direction) {
810
- const beforeId = resolveKeyboardDropTarget(order, entry.id, direction);
1237
+ const beforeId = resolveKeyboardDropTarget2(order, entry.id, direction);
811
1238
  if (beforeId === void 0) {
812
1239
  return;
813
1240
  }
814
1241
  onDrop({ kind: "column-order", beforeId }, entry.id);
815
1242
  }
816
1243
  return {
817
- draggedColumnId,
818
- dropTarget,
819
- ghostTransform,
1244
+ draggedColumnId: drag.draggedId,
1245
+ dropTarget: drag.dropTarget,
1246
+ ghostTransform: drag.ghostTransform,
820
1247
  startDrag,
821
1248
  moveByKeyboard,
822
- justDragged
1249
+ justDragged: drag.justDragged
823
1250
  };
824
1251
  }
825
1252
 
@@ -994,8 +1421,62 @@ function useElementWidth(ref, enabled) {
994
1421
  return width;
995
1422
  }
996
1423
 
1424
+ // src/DataGrid/useRowGrouping.ts
1425
+ import {
1426
+ collapseAllGroups,
1427
+ expandAllGroups,
1428
+ moveGroupByBefore,
1429
+ toggleGroupExpansion
1430
+ } from "@gridkitjs/core";
1431
+ function useRowGrouping({
1432
+ groupBy,
1433
+ setGroupBy,
1434
+ expansion,
1435
+ setExpansion,
1436
+ onGroupByChange,
1437
+ onGroupExpansionChange
1438
+ }) {
1439
+ function commitExpansion(next, groupId) {
1440
+ commitIfChanged(expansion, next, setExpansion, (committed) => {
1441
+ onGroupExpansionChange?.({ groupId, expansion: committed });
1442
+ });
1443
+ }
1444
+ function commitGroupBy(next, columnId) {
1445
+ commitIfChanged(groupBy, next, setGroupBy, (committed) => {
1446
+ onGroupByChange?.({ columnId, groupBy: committed });
1447
+ });
1448
+ }
1449
+ function toggleGroupBy(columnId) {
1450
+ const isGrouped = groupBy.some((entry) => entry.columnId === columnId);
1451
+ const next = isGrouped ? groupBy.filter((entry) => entry.columnId !== columnId) : [...groupBy, { columnId }];
1452
+ commitGroupBy(next, columnId);
1453
+ }
1454
+ function moveGroupBy(columnId, beforeColumnId) {
1455
+ commitGroupBy(
1456
+ moveGroupByBefore(groupBy, columnId, beforeColumnId),
1457
+ columnId
1458
+ );
1459
+ }
1460
+ return {
1461
+ groupBy,
1462
+ expansion,
1463
+ isExpanded: (groupId) => !expansion.includes(groupId),
1464
+ toggleExpansion: (groupId) => {
1465
+ commitExpansion(toggleGroupExpansion(expansion, groupId), groupId);
1466
+ },
1467
+ expandAll: () => {
1468
+ commitExpansion(expandAllGroups(expansion), null);
1469
+ },
1470
+ collapseAll: (rows) => {
1471
+ commitExpansion(collapseAllGroups(rows), null);
1472
+ },
1473
+ toggleGroupBy,
1474
+ moveGroupBy
1475
+ };
1476
+ }
1477
+
997
1478
  // src/DataGrid/DataGrid.tsx
998
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1479
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
999
1480
  function DataGridComponent({
1000
1481
  dataSource,
1001
1482
  columns,
@@ -1017,6 +1498,14 @@ function DataGridComponent({
1017
1498
  sortableColumns = false,
1018
1499
  defaultColumnSort,
1019
1500
  onColumnSortChange,
1501
+ groupableColumns = false,
1502
+ groupToggleIconColumns = true,
1503
+ groupByDraggableColumns = false,
1504
+ groupByBarVisibility = "auto",
1505
+ defaultGroupBy,
1506
+ onGroupByChange,
1507
+ defaultGroupExpansion,
1508
+ onGroupExpansionChange,
1020
1509
  defaultFilter,
1021
1510
  label,
1022
1511
  labelledBy,
@@ -1036,6 +1525,10 @@ function DataGridComponent({
1036
1525
  defaultColumnOrder ?? []
1037
1526
  );
1038
1527
  const [sort, setSort] = useState5(defaultColumnSort ?? []);
1528
+ const [groupBy, setGroupBy] = useState5(defaultGroupBy ?? []);
1529
+ const [expansion, setExpansion] = useState5(
1530
+ defaultGroupExpansion ?? []
1531
+ );
1039
1532
  const [filter] = useState5(defaultFilter ?? []);
1040
1533
  const [announcement, setAnnouncement] = useState5("");
1041
1534
  const [rowSelection, setRowSelection] = useState5(
@@ -1047,7 +1540,7 @@ function DataGridComponent({
1047
1540
  const [cellSelection, setCellSelection] = useState5(
1048
1541
  defaultCellSelection ?? null
1049
1542
  );
1050
- const rows = useMemo2(
1543
+ const rows = useMemo3(
1051
1544
  () => dataSource?.map((row, rowIndex) => ({
1052
1545
  rowId: resolveRowId(row, rowIndex, getRowId),
1053
1546
  row,
@@ -1055,21 +1548,22 @@ function DataGridComponent({
1055
1548
  })) ?? [],
1056
1549
  [dataSource, getRowId]
1057
1550
  );
1058
- const definedColumns = useMemo2(() => {
1551
+ const definedColumns = useMemo3(() => {
1059
1552
  if (columns && columns.length !== 0) return columns;
1060
1553
  if (dataSource && dataSource.length > 0)
1061
1554
  return defineColumnsFromRows(dataSource);
1062
1555
  return [];
1063
1556
  }, [columns, dataSource]);
1064
- const orderedColumns = useMemo2(
1557
+ const orderedColumns = useMemo3(
1065
1558
  () => applyColumnOrder(definedColumns, order),
1066
1559
  [definedColumns, order]
1067
1560
  );
1068
- const resolved = useMemo2(() => {
1561
+ const resolved = useMemo3(() => {
1069
1562
  const widths = resolveColumnWidths(orderedColumns, sizing, {
1070
1563
  sizes: columnSizeDefaults,
1071
1564
  resizable: resizableColumns,
1072
- reorderable: reorderableColumns
1565
+ reorderable: reorderableColumns,
1566
+ groupByDraggable: groupByDraggableColumns
1073
1567
  });
1074
1568
  return resizeMode === "fit" && viewportWidth !== null ? fitColumnsToWidth(widths, viewportWidth, columnSizeDefaults) : widths;
1075
1569
  }, [
@@ -1079,12 +1573,23 @@ function DataGridComponent({
1079
1573
  viewportWidth,
1080
1574
  columnSizeDefaults,
1081
1575
  resizableColumns,
1082
- reorderableColumns
1576
+ reorderableColumns,
1577
+ groupByDraggableColumns
1083
1578
  ]);
1084
- const shownRows = useMemo2(
1579
+ const shownRows = useMemo3(
1085
1580
  () => resolveShownRows(rows, filter, sort, resolved),
1086
1581
  [rows, filter, sort, resolved]
1087
1582
  );
1583
+ const displayRows = useMemo3(
1584
+ () => groupRows(shownRows, groupBy, expansion, resolved),
1585
+ [shownRows, groupBy, expansion, resolved]
1586
+ );
1587
+ const displayDataRows = useMemo3(
1588
+ () => groupBy.length === 0 ? shownRows : displayRows.filter(
1589
+ (entry) => !("kind" in entry)
1590
+ ),
1591
+ [displayRows, groupBy.length, shownRows]
1592
+ );
1088
1593
  function columnName(columnId) {
1089
1594
  const entry = resolved.find((candidate) => candidate.id === columnId);
1090
1595
  if (entry === void 0) {
@@ -1110,16 +1615,62 @@ function DataGridComponent({
1110
1615
  columnSizeDefaults,
1111
1616
  onColumnResize: handleColumnResize
1112
1617
  });
1618
+ function handleGroupByChange(event) {
1619
+ onGroupByChange?.(event);
1620
+ const entry = event.groupBy.find(
1621
+ (candidate) => candidate.columnId === event.columnId
1622
+ );
1623
+ if (entry === void 0) {
1624
+ announce(`${columnName(event.columnId)}, grouping removed`);
1625
+ return;
1626
+ }
1627
+ announce(
1628
+ event.groupBy.length > 1 ? `Grouped by ${columnName(event.columnId)}, level ${String(event.groupBy.indexOf(entry) + 1)} of ${String(event.groupBy.length)}` : `Grouped by ${columnName(event.columnId)}`
1629
+ );
1630
+ }
1631
+ function handleGroupExpansionChange(event) {
1632
+ onGroupExpansionChange?.(event);
1633
+ if (event.groupId === null) {
1634
+ announce(
1635
+ event.expansion.length === 0 ? "All groups expanded" : "All groups collapsed"
1636
+ );
1637
+ return;
1638
+ }
1639
+ announce(
1640
+ event.expansion.includes(event.groupId) ? "Group collapsed" : "Group expanded"
1641
+ );
1642
+ }
1643
+ const grouping = useRowGrouping({
1644
+ groupBy,
1645
+ setGroupBy,
1646
+ expansion,
1647
+ setExpansion,
1648
+ onGroupByChange: handleGroupByChange,
1649
+ onGroupExpansionChange: handleGroupExpansionChange
1650
+ });
1113
1651
  const nav = useGridNavigation({
1114
1652
  tableRef,
1115
- rowCount: shownRows.length,
1653
+ // Group headers are addressable rows too — the whole point of the flat
1654
+ // `DisplayRow[]` shape is that they share one position space with data
1655
+ // rows, so navigation counts them the same way.
1656
+ rowCount: displayRows.length,
1116
1657
  columnCount: resolved.length
1117
1658
  });
1118
- const displayedIds = useMemo2(
1659
+ const displayedIds = useMemo3(
1119
1660
  () => orderedColumns.map((column) => column.id ?? column.field),
1120
1661
  [orderedColumns]
1121
1662
  );
1663
+ const groupByDraggableIds = useMemo3(
1664
+ () => new Set(
1665
+ resolved.filter((entry) => entry.groupByDraggable).map((entry) => entry.id)
1666
+ ),
1667
+ [resolved]
1668
+ );
1122
1669
  function handleDrop(target, movedId) {
1670
+ if (target.kind === "group-by") {
1671
+ grouping.moveGroupBy(movedId, target.beforeColumnId);
1672
+ return;
1673
+ }
1123
1674
  const next = moveColumnBefore(displayedIds, movedId, target.beforeId);
1124
1675
  if (next === displayedIds) {
1125
1676
  return;
@@ -1132,7 +1683,16 @@ function DataGridComponent({
1132
1683
  );
1133
1684
  nav.focusCell(HEADER_ROW, position);
1134
1685
  }
1135
- const drag = useColumnDrag({ order: displayedIds, onDrop: handleDrop });
1686
+ const drag = useColumnDrag({
1687
+ order: displayedIds,
1688
+ groupBy,
1689
+ groupByDraggableIds,
1690
+ onDrop: handleDrop
1691
+ });
1692
+ const draggedColumnAlreadyGrouped = drag.draggedColumnId !== null && groupBy.some((entry) => entry.columnId === drag.draggedColumnId);
1693
+ const dragEligibleForGroupBy = drag.draggedColumnId !== null && groupByDraggableIds.has(drag.draggedColumnId) && !draggedColumnAlreadyGrouped;
1694
+ const showGroupByBar = groupByBarVisibility === "always" || groupByBarVisibility === "auto" && (groupBy.length > 0 || dragEligibleForGroupBy);
1695
+ const headerGroupByDropTarget = drag.dropTarget?.kind === "group-by" ? drag.dropTarget : null;
1136
1696
  function handleColumnSortChange(event) {
1137
1697
  onColumnSortChange?.(event);
1138
1698
  const entry = event.sort.find(
@@ -1153,7 +1713,7 @@ function DataGridComponent({
1153
1713
  onColumnSortChange: handleColumnSortChange
1154
1714
  });
1155
1715
  const selection = useGridSelection({
1156
- rows: shownRows,
1716
+ rows: displayDataRows,
1157
1717
  columns: resolved,
1158
1718
  selectable,
1159
1719
  rowSelection,
@@ -1175,10 +1735,13 @@ function DataGridComponent({
1175
1735
  return tableRef.current;
1176
1736
  },
1177
1737
  getRows: () => shownRows,
1738
+ getDisplayRows: () => displayRows,
1178
1739
  getColumns: () => resolved,
1179
1740
  getColumnSizing: () => sizing,
1180
1741
  getColumnOrder: () => order,
1181
1742
  getColumnSort: () => sort,
1743
+ getGroupBy: () => groupBy,
1744
+ getGroupExpansion: () => expansion,
1182
1745
  getRowSelection: () => rowSelection,
1183
1746
  getColumnSelection: () => columnSelection,
1184
1747
  getCellSelection: () => cellSelection,
@@ -1186,8 +1749,14 @@ function DataGridComponent({
1186
1749
  focusCell: nav.focusCell,
1187
1750
  clearSelection: selection.clear,
1188
1751
  selectAllRows: selection.selectAllRows,
1752
+ expandAllGroups: grouping.expandAll,
1753
+ collapseAllGroups: () => {
1754
+ grouping.collapseAll(displayRows);
1755
+ },
1189
1756
  scrollToRow: (rowId, options) => {
1190
- const index = shownRows.findIndex((entry) => entry.rowId === rowId);
1757
+ const index = displayRows.findIndex(
1758
+ (entry) => !("kind" in entry) && entry.rowId === rowId
1759
+ );
1191
1760
  if (index === -1) return;
1192
1761
  tableRef.current?.tBodies[0]?.rows[index]?.scrollIntoView(options);
1193
1762
  },
@@ -1199,13 +1768,24 @@ function DataGridComponent({
1199
1768
  cell?.scrollIntoView(options);
1200
1769
  }
1201
1770
  }));
1202
- return /* @__PURE__ */ jsxs2("div", { className: "gridkit-data-grid-viewport", ref: viewportRef, children: [
1203
- /* @__PURE__ */ jsxs2(
1771
+ return /* @__PURE__ */ jsxs4("div", { className: "gridkit-data-grid-viewport", ref: viewportRef, children: [
1772
+ showGroupByBar && /* @__PURE__ */ jsx6(
1773
+ GroupByBar,
1774
+ {
1775
+ columns: resolved,
1776
+ grouping,
1777
+ columnName,
1778
+ headerDragEligible: dragEligibleForGroupBy,
1779
+ headerDragBlocked: draggedColumnAlreadyGrouped,
1780
+ headerDropTarget: headerGroupByDropTarget
1781
+ }
1782
+ ),
1783
+ /* @__PURE__ */ jsxs4(
1204
1784
  "table",
1205
1785
  {
1206
1786
  ref: tableRef,
1207
- role: "grid",
1208
- "aria-rowcount": shownRows.length + 1,
1787
+ role: groupBy.length > 0 ? "treegrid" : "grid",
1788
+ "aria-rowcount": displayRows.length + 1,
1209
1789
  "aria-colcount": resolved.length,
1210
1790
  ...ariaAttr(multiselectable, "aria-multiselectable", true),
1211
1791
  ...ariaAttr(labelledBy !== void 0, "aria-labelledby", labelledBy),
@@ -1242,8 +1822,8 @@ function DataGridComponent({
1242
1822
  selection.cellMode === false ? "" : "selectable-cells"
1243
1823
  ),
1244
1824
  children: [
1245
- /* @__PURE__ */ jsx4("colgroup", { children: resolved.map((entry) => /* @__PURE__ */ jsx4("col", { style: { width: entry.width } }, entry.id)) }),
1246
- /* @__PURE__ */ jsx4(
1825
+ /* @__PURE__ */ jsx6("colgroup", { children: resolved.map((entry) => /* @__PURE__ */ jsx6("col", { style: { width: entry.width } }, entry.id)) }),
1826
+ /* @__PURE__ */ jsx6(
1247
1827
  GridHeader,
1248
1828
  {
1249
1829
  columns: resolved,
@@ -1251,24 +1831,28 @@ function DataGridComponent({
1251
1831
  drag,
1252
1832
  sort: columnSort,
1253
1833
  sortableColumns,
1834
+ grouping,
1835
+ groupableColumns,
1836
+ groupToggleIconColumns,
1254
1837
  nav,
1255
1838
  selection
1256
1839
  }
1257
1840
  ),
1258
- /* @__PURE__ */ jsx4(
1841
+ /* @__PURE__ */ jsx6(
1259
1842
  GridBody,
1260
1843
  {
1261
1844
  columns: resolved,
1262
- rows: shownRows,
1845
+ rows: displayRows,
1263
1846
  activeColumnId: resize.activeColumnId,
1264
1847
  nav,
1265
- selection
1848
+ selection,
1849
+ grouping
1266
1850
  }
1267
1851
  )
1268
1852
  ]
1269
1853
  }
1270
1854
  ),
1271
- /* @__PURE__ */ jsx4("div", { className: "gridkit-sr-only", role: "status", "aria-live": "polite", children: announcement })
1855
+ /* @__PURE__ */ jsx6("div", { className: "gridkit-sr-only", role: "status", "aria-live": "polite", children: announcement })
1272
1856
  ] });
1273
1857
  }
1274
1858
  export {