@comitor/ui 1.10.0 → 2.0.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.
Files changed (110) hide show
  1. package/README.md +24 -5
  2. package/dist/data-grid/compose-refs.d.ts +19 -0
  3. package/dist/data-grid/compose-refs.js +41 -0
  4. package/dist/data-grid/compose-refs.js.map +1 -0
  5. package/dist/data-grid/data-grid-cell-variants.d.ts +15 -0
  6. package/dist/data-grid/data-grid-cell-variants.js +1738 -0
  7. package/dist/data-grid/data-grid-cell-variants.js.map +1 -0
  8. package/dist/data-grid/data-grid-cell-wrapper.d.ts +9 -0
  9. package/dist/data-grid/data-grid-cell-wrapper.js +179 -0
  10. package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -0
  11. package/dist/data-grid/data-grid-cell.d.ts +8 -0
  12. package/dist/data-grid/data-grid-cell.js +101 -0
  13. package/dist/data-grid/data-grid-cell.js.map +1 -0
  14. package/dist/data-grid/data-grid-column-header.d.ts +12 -0
  15. package/dist/data-grid/data-grid-column-header.js +207 -0
  16. package/dist/data-grid/data-grid-column-header.js.map +1 -0
  17. package/dist/data-grid/data-grid-context-menu.d.ts +12 -0
  18. package/dist/data-grid/data-grid-context-menu.js +161 -0
  19. package/dist/data-grid/data-grid-context-menu.js.map +1 -0
  20. package/dist/data-grid/data-grid-filter-menu.d.ts +23 -0
  21. package/dist/data-grid/data-grid-filter-menu.js +725 -0
  22. package/dist/data-grid/data-grid-filter-menu.js.map +1 -0
  23. package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +31 -0
  24. package/dist/data-grid/data-grid-keyboard-shortcuts.js +229 -0
  25. package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -0
  26. package/dist/data-grid/data-grid-locale.d.ts +24 -0
  27. package/dist/data-grid/data-grid-locale.js +25 -0
  28. package/dist/data-grid/data-grid-locale.js.map +1 -0
  29. package/dist/data-grid/data-grid-paste-dialog.d.ts +11 -0
  30. package/dist/data-grid/data-grid-paste-dialog.js +104 -0
  31. package/dist/data-grid/data-grid-paste-dialog.js.map +1 -0
  32. package/dist/data-grid/data-grid-presence.d.ts +14 -0
  33. package/dist/data-grid/data-grid-presence.js +16 -0
  34. package/dist/data-grid/data-grid-presence.js.map +1 -0
  35. package/dist/data-grid/data-grid-row-height-menu.d.ts +25 -0
  36. package/dist/data-grid/data-grid-row-height-menu.js +53 -0
  37. package/dist/data-grid/data-grid-row-height-menu.js.map +1 -0
  38. package/dist/data-grid/data-grid-row.d.ts +28 -0
  39. package/dist/data-grid/data-grid-row.js +206 -0
  40. package/dist/data-grid/data-grid-row.js.map +1 -0
  41. package/dist/data-grid/data-grid-search.d.ts +10 -0
  42. package/dist/data-grid/data-grid-search.js +184 -0
  43. package/dist/data-grid/data-grid-search.js.map +1 -0
  44. package/dist/data-grid/data-grid-select-column.d.ts +12 -0
  45. package/dist/data-grid/data-grid-select-column.js +179 -0
  46. package/dist/data-grid/data-grid-select-column.js.map +1 -0
  47. package/dist/data-grid/data-grid-skeleton.d.ts +13 -0
  48. package/dist/data-grid/data-grid-skeleton.js +52 -0
  49. package/dist/data-grid/data-grid-skeleton.js.map +1 -0
  50. package/dist/data-grid/data-grid-sort-menu.d.ts +23 -0
  51. package/dist/data-grid/data-grid-sort-menu.js +283 -0
  52. package/dist/data-grid/data-grid-sort-menu.js.map +1 -0
  53. package/dist/data-grid/data-grid-view-menu.d.ts +24 -0
  54. package/dist/data-grid/data-grid-view-menu.js +74 -0
  55. package/dist/data-grid/data-grid-view-menu.js.map +1 -0
  56. package/dist/data-grid/data-grid.d.ts +44 -0
  57. package/dist/data-grid/data-grid.js +238 -0
  58. package/dist/data-grid/data-grid.js.map +1 -0
  59. package/dist/data-grid/filters.d.ts +27 -0
  60. package/dist/data-grid/filters.js +233 -0
  61. package/dist/data-grid/filters.js.map +1 -0
  62. package/dist/data-grid/index.d.ts +25 -0
  63. package/dist/data-grid/index.js +95 -0
  64. package/dist/data-grid/index.js.map +1 -0
  65. package/dist/data-grid/messages-en.d.ts +294 -0
  66. package/dist/data-grid/messages-en.js +279 -0
  67. package/dist/data-grid/messages-en.js.map +1 -0
  68. package/dist/data-grid/messages-vi.d.ts +12 -0
  69. package/dist/data-grid/messages-vi.js +279 -0
  70. package/dist/data-grid/messages-vi.js.map +1 -0
  71. package/dist/data-grid/messages.d.ts +567 -0
  72. package/dist/data-grid/messages.js +20 -0
  73. package/dist/data-grid/messages.js.map +1 -0
  74. package/dist/data-grid/sortable.d.ts +50 -0
  75. package/dist/data-grid/sortable.js +361 -0
  76. package/dist/data-grid/sortable.js.map +1 -0
  77. package/dist/data-grid/toast.d.ts +10 -0
  78. package/dist/data-grid/toast.js +21 -0
  79. package/dist/data-grid/toast.js.map +1 -0
  80. package/dist/data-grid/types.d.ts +189 -0
  81. package/dist/data-grid/types.js +1 -0
  82. package/dist/data-grid/types.js.map +1 -0
  83. package/dist/data-grid/use-as-ref.d.ts +5 -0
  84. package/dist/data-grid/use-as-ref.js +13 -0
  85. package/dist/data-grid/use-as-ref.js.map +1 -0
  86. package/dist/data-grid/use-badge-overflow.d.ts +24 -0
  87. package/dist/data-grid/use-badge-overflow.js +123 -0
  88. package/dist/data-grid/use-badge-overflow.js.map +1 -0
  89. package/dist/data-grid/use-callback-ref.d.ts +10 -0
  90. package/dist/data-grid/use-callback-ref.js +12 -0
  91. package/dist/data-grid/use-callback-ref.js.map +1 -0
  92. package/dist/data-grid/use-data-grid-undo-redo.d.ts +45 -0
  93. package/dist/data-grid/use-data-grid-undo-redo.js +348 -0
  94. package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -0
  95. package/dist/data-grid/use-data-grid.d.ts +372 -0
  96. package/dist/data-grid/use-data-grid.js +2697 -0
  97. package/dist/data-grid/use-data-grid.js.map +1 -0
  98. package/dist/data-grid/use-debounced-callback.d.ts +6 -0
  99. package/dist/data-grid/use-debounced-callback.js +19 -0
  100. package/dist/data-grid/use-debounced-callback.js.map +1 -0
  101. package/dist/data-grid/use-isomorphic-layout-effect.d.ts +5 -0
  102. package/dist/data-grid/use-isomorphic-layout-effect.js +6 -0
  103. package/dist/data-grid/use-isomorphic-layout-effect.js.map +1 -0
  104. package/dist/data-grid/use-lazy-ref.d.ts +5 -0
  105. package/dist/data-grid/use-lazy-ref.js +12 -0
  106. package/dist/data-grid/use-lazy-ref.js.map +1 -0
  107. package/dist/data-grid/utils.d.ts +81 -0
  108. package/dist/data-grid/utils.js +409 -0
  109. package/dist/data-grid/utils.js.map +1 -0
  110. package/package.json +33 -15
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-grid/use-as-ref.ts"],"sourcesContent":["import * as React from \"react\";\n\nimport { useIsomorphicLayoutEffect } from \"./use-isomorphic-layout-effect.js\";\n\nfunction useAsRef<T>(props: T) {\n const ref = React.useRef<T>(props);\n\n useIsomorphicLayoutEffect(() => {\n ref.current = props;\n });\n\n return ref;\n}\n\nexport { useAsRef };\n"],"mappings":"AAAA,YAAY,WAAW;AAEvB,SAAS,iCAAiC;AAE1C,SAAS,SAAY,OAAU;AAC7B,QAAM,MAAM,MAAM,OAAU,KAAK;AAEjC,4BAA0B,MAAM;AAC9B,QAAI,UAAU;AAAA,EAChB,CAAC;AAED,SAAO;AACT;","names":[]}
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+
3
+ interface UseBadgeOverflowProps<T> {
4
+ items: T[];
5
+ getLabel: (item: T) => string;
6
+ containerRef: React.RefObject<HTMLElement | null>;
7
+ lineCount: number;
8
+ cacheKeyPrefix?: string;
9
+ iconSize?: number;
10
+ maxWidth?: number;
11
+ className?: string;
12
+ containerPadding?: number;
13
+ badgeGap?: number;
14
+ overflowBadgeWidth?: number;
15
+ }
16
+ interface UseBadgeOverflowReturn<T> {
17
+ visibleItems: T[];
18
+ hiddenCount: number;
19
+ containerWidth: number;
20
+ }
21
+ declare function useBadgeOverflow<T>({ items, getLabel, containerRef, lineCount, cacheKeyPrefix, containerPadding, badgeGap, overflowBadgeWidth, iconSize, maxWidth, className }: UseBadgeOverflowProps<T>): UseBadgeOverflowReturn<T>;
22
+ declare function clearBadgeWidthCache(): void;
23
+
24
+ export { clearBadgeWidthCache, useBadgeOverflow };
@@ -0,0 +1,123 @@
1
+ import * as React from "react";
2
+ const badgeWidthCache = /* @__PURE__ */ new Map();
3
+ const DEFAULT_CONTAINER_PADDING = 16;
4
+ const DEFAULT_BADGE_GAP = 4;
5
+ const DEFAULT_OVERFLOW_BADGE_WIDTH = 40;
6
+ function measureBadgeWidth({ label, cacheKey, iconSize, maxWidth, className }) {
7
+ const cached = badgeWidthCache.get(cacheKey);
8
+ if (cached !== void 0) {
9
+ return cached;
10
+ }
11
+ const measureEl = document.createElement("div");
12
+ measureEl.className = `inline-flex items-center rounded-md border px-1.5 text-xs font-semibold h-5 gap-1 shrink-0 absolute invisible pointer-events-none ${className ?? ""}`;
13
+ measureEl.style.whiteSpace = "nowrap";
14
+ if (iconSize) {
15
+ const icon = document.createElement("span");
16
+ icon.className = "shrink-0";
17
+ icon.style.width = `${iconSize}px`;
18
+ icon.style.height = `${iconSize}px`;
19
+ measureEl.appendChild(icon);
20
+ }
21
+ if (maxWidth) {
22
+ const text = document.createElement("span");
23
+ text.className = "truncate";
24
+ text.style.maxWidth = `${maxWidth}px`;
25
+ text.textContent = label;
26
+ measureEl.appendChild(text);
27
+ } else {
28
+ measureEl.textContent = label;
29
+ }
30
+ document.body.appendChild(measureEl);
31
+ const width = measureEl.offsetWidth;
32
+ document.body.removeChild(measureEl);
33
+ badgeWidthCache.set(cacheKey, width);
34
+ return width;
35
+ }
36
+ function useBadgeOverflow({
37
+ items,
38
+ getLabel,
39
+ containerRef,
40
+ lineCount,
41
+ cacheKeyPrefix = "",
42
+ containerPadding = DEFAULT_CONTAINER_PADDING,
43
+ badgeGap = DEFAULT_BADGE_GAP,
44
+ overflowBadgeWidth = DEFAULT_OVERFLOW_BADGE_WIDTH,
45
+ iconSize,
46
+ maxWidth,
47
+ className
48
+ }) {
49
+ const [containerWidth, setContainerWidth] = React.useState(0);
50
+ React.useEffect(() => {
51
+ if (!containerRef.current) return;
52
+ function measureWidth() {
53
+ if (containerRef.current) {
54
+ const width = containerRef.current.clientWidth - containerPadding;
55
+ setContainerWidth(width);
56
+ }
57
+ }
58
+ measureWidth();
59
+ const resizeObserver = new ResizeObserver(measureWidth);
60
+ resizeObserver.observe(containerRef.current);
61
+ return () => {
62
+ resizeObserver.disconnect();
63
+ };
64
+ }, [containerRef, containerPadding]);
65
+ const result = React.useMemo(() => {
66
+ if (!containerWidth || items.length === 0) {
67
+ return { visibleItems: items, hiddenCount: 0, containerWidth };
68
+ }
69
+ let currentLineWidth = 0;
70
+ let currentLine = 1;
71
+ const visible = [];
72
+ for (const item of items) {
73
+ const label = getLabel(item);
74
+ const cacheKey = cacheKeyPrefix ? `${cacheKeyPrefix}:${label}` : label;
75
+ const badgeWidth = measureBadgeWidth({
76
+ label,
77
+ cacheKey,
78
+ iconSize,
79
+ maxWidth,
80
+ className
81
+ });
82
+ const widthWithGap = badgeWidth + badgeGap;
83
+ if (currentLineWidth + widthWithGap <= containerWidth) {
84
+ currentLineWidth += widthWithGap;
85
+ visible.push(item);
86
+ } else if (currentLine < lineCount) {
87
+ currentLine++;
88
+ currentLineWidth = widthWithGap;
89
+ visible.push(item);
90
+ } else {
91
+ if (currentLineWidth + overflowBadgeWidth > containerWidth && visible.length > 0) {
92
+ visible.pop();
93
+ }
94
+ break;
95
+ }
96
+ }
97
+ return {
98
+ visibleItems: visible,
99
+ hiddenCount: Math.max(0, items.length - visible.length),
100
+ containerWidth
101
+ };
102
+ }, [
103
+ items,
104
+ getLabel,
105
+ containerWidth,
106
+ lineCount,
107
+ cacheKeyPrefix,
108
+ iconSize,
109
+ maxWidth,
110
+ className,
111
+ badgeGap,
112
+ overflowBadgeWidth
113
+ ]);
114
+ return result;
115
+ }
116
+ function clearBadgeWidthCache() {
117
+ badgeWidthCache.clear();
118
+ }
119
+ export {
120
+ clearBadgeWidthCache,
121
+ useBadgeOverflow
122
+ };
123
+ //# sourceMappingURL=use-badge-overflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-grid/use-badge-overflow.ts"],"sourcesContent":["import * as React from \"react\";\n\nconst badgeWidthCache = new Map<string, number>();\n\nconst DEFAULT_CONTAINER_PADDING = 16; // px-2 = 8px * 2\nconst DEFAULT_BADGE_GAP = 4; // gap-1 = 4px\nconst DEFAULT_OVERFLOW_BADGE_WIDTH = 40; // Approximate width of \"+N\" badge\n\ninterface MeasureBadgeWidthProps {\n label: string;\n cacheKey: string;\n iconSize?: number;\n maxWidth?: number;\n className?: string;\n}\n\nfunction measureBadgeWidth({ label, cacheKey, iconSize, maxWidth, className }: MeasureBadgeWidthProps): number {\n const cached = badgeWidthCache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n\n const measureEl = document.createElement(\"div\");\n measureEl.className = `inline-flex items-center rounded-md border px-1.5 text-xs font-semibold h-5 gap-1 shrink-0 absolute invisible pointer-events-none ${\n className ?? \"\"\n }`;\n measureEl.style.whiteSpace = \"nowrap\";\n\n if (iconSize) {\n const icon = document.createElement(\"span\");\n icon.className = \"shrink-0\";\n icon.style.width = `${iconSize}px`;\n icon.style.height = `${iconSize}px`;\n measureEl.appendChild(icon);\n }\n\n if (maxWidth) {\n const text = document.createElement(\"span\");\n text.className = \"truncate\";\n text.style.maxWidth = `${maxWidth}px`;\n text.textContent = label;\n measureEl.appendChild(text);\n } else {\n measureEl.textContent = label;\n }\n\n document.body.appendChild(measureEl);\n const width = measureEl.offsetWidth;\n document.body.removeChild(measureEl);\n\n badgeWidthCache.set(cacheKey, width);\n return width;\n}\n\ninterface UseBadgeOverflowProps<T> {\n items: T[];\n getLabel: (item: T) => string;\n containerRef: React.RefObject<HTMLElement | null>;\n lineCount: number;\n cacheKeyPrefix?: string;\n iconSize?: number;\n maxWidth?: number;\n className?: string;\n containerPadding?: number;\n badgeGap?: number;\n overflowBadgeWidth?: number;\n}\n\ninterface UseBadgeOverflowReturn<T> {\n visibleItems: T[];\n hiddenCount: number;\n containerWidth: number;\n}\n\nexport function useBadgeOverflow<T>({\n items,\n getLabel,\n containerRef,\n lineCount,\n cacheKeyPrefix = \"\",\n containerPadding = DEFAULT_CONTAINER_PADDING,\n badgeGap = DEFAULT_BADGE_GAP,\n overflowBadgeWidth = DEFAULT_OVERFLOW_BADGE_WIDTH,\n iconSize,\n maxWidth,\n className\n}: UseBadgeOverflowProps<T>): UseBadgeOverflowReturn<T> {\n const [containerWidth, setContainerWidth] = React.useState(0);\n\n React.useEffect(() => {\n if (!containerRef.current) return;\n\n function measureWidth() {\n if (containerRef.current) {\n const width = containerRef.current.clientWidth - containerPadding;\n setContainerWidth(width);\n }\n }\n\n measureWidth();\n\n const resizeObserver = new ResizeObserver(measureWidth);\n resizeObserver.observe(containerRef.current);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [containerRef, containerPadding]);\n\n const result = React.useMemo(() => {\n if (!containerWidth || items.length === 0) {\n return { visibleItems: items, hiddenCount: 0, containerWidth };\n }\n\n let currentLineWidth = 0;\n let currentLine = 1;\n const visible: T[] = [];\n\n for (const item of items) {\n const label = getLabel(item);\n const cacheKey = cacheKeyPrefix ? `${cacheKeyPrefix}:${label}` : label;\n const badgeWidth = measureBadgeWidth({\n label,\n cacheKey,\n iconSize,\n maxWidth,\n className\n });\n const widthWithGap = badgeWidth + badgeGap;\n\n if (currentLineWidth + widthWithGap <= containerWidth) {\n currentLineWidth += widthWithGap;\n visible.push(item);\n } else if (currentLine < lineCount) {\n currentLine++;\n currentLineWidth = widthWithGap;\n visible.push(item);\n } else {\n if (currentLineWidth + overflowBadgeWidth > containerWidth && visible.length > 0) {\n visible.pop();\n }\n\n break;\n }\n }\n\n return {\n visibleItems: visible,\n hiddenCount: Math.max(0, items.length - visible.length),\n containerWidth\n };\n }, [\n items,\n getLabel,\n containerWidth,\n lineCount,\n cacheKeyPrefix,\n iconSize,\n maxWidth,\n className,\n badgeGap,\n overflowBadgeWidth\n ]);\n\n return result;\n}\n\nexport function clearBadgeWidthCache(): void {\n badgeWidthCache.clear();\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @see https://github.com/radix-ui/primitives/blob/main/packages/react/use-callback-ref/src/useCallbackRef.tsx
3
+ */
4
+ /**
5
+ * A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a
6
+ * prop or avoid re-executing effects when passed as a dependency
7
+ */
8
+ declare function useCallbackRef<T extends (...args: never[]) => unknown>(callback: T | undefined): T;
9
+
10
+ export { useCallbackRef };
@@ -0,0 +1,12 @@
1
+ import * as React from "react";
2
+ function useCallbackRef(callback) {
3
+ const callbackRef = React.useRef(callback);
4
+ React.useEffect(() => {
5
+ callbackRef.current = callback;
6
+ });
7
+ return React.useMemo(() => ((...args) => callbackRef.current?.(...args)), []);
8
+ }
9
+ export {
10
+ useCallbackRef
11
+ };
12
+ //# sourceMappingURL=use-callback-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-grid/use-callback-ref.ts"],"sourcesContent":["import * as React from \"react\";\n\n/**\n * @see https://github.com/radix-ui/primitives/blob/main/packages/react/use-callback-ref/src/useCallbackRef.tsx\n */\n\n/**\n * A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a\n * prop or avoid re-executing effects when passed as a dependency\n */\nfunction useCallbackRef<T extends (...args: never[]) => unknown>(callback: T | undefined): T {\n const callbackRef = React.useRef(callback);\n\n React.useEffect(() => {\n callbackRef.current = callback;\n });\n\n // https://github.com/facebook/react/issues/19240\n return React.useMemo(() => ((...args) => callbackRef.current?.(...args)) as T, []);\n}\n\nexport { useCallbackRef };\n"],"mappings":"AAAA,YAAY,WAAW;AAUvB,SAAS,eAAwD,UAA4B;AAC3F,QAAM,cAAc,MAAM,OAAO,QAAQ;AAEzC,QAAM,UAAU,MAAM;AACpB,gBAAY,UAAU;AAAA,EACxB,CAAC;AAGD,SAAO,MAAM,QAAQ,OAAO,IAAI,SAAS,YAAY,UAAU,GAAG,IAAI,IAAS,CAAC,CAAC;AACnF;","names":[]}
@@ -0,0 +1,45 @@
1
+ import { DataGridLocale } from './messages.js';
2
+ import { DataGridMessages } from './messages-en.js';
3
+ import './messages-vi.js';
4
+
5
+ interface UndoRedoCellUpdate {
6
+ rowId: string;
7
+ columnId: string;
8
+ previousValue: unknown;
9
+ newValue: unknown;
10
+ }
11
+ /**
12
+ * Tuỳ chọn của {@link useDataGridUndoRedo}. Lịch sử nằm hoàn toàn ở phía trình duyệt:
13
+ * hook tính ra mảng dữ liệu trước/sau rồi trả về qua `onDataChange` — ứng dụng tự
14
+ * đồng bộ lên máy chủ (hoặc bỏ qua nếu chỉ làm việc với state cục bộ).
15
+ */
16
+ interface UseDataGridUndoRedoProps<TData> {
17
+ data: TData[];
18
+ onDataChange: (data: TData[]) => void;
19
+ /** Khoá định danh bản ghi — phải khớp với `getRowId` của lưới */
20
+ getRowId: (row: TData) => string;
21
+ /** Số thao tác giữ trong lịch sử (mặc định 100) */
22
+ maxHistory?: number;
23
+ enabled?: boolean;
24
+ /**
25
+ * Ngôn ngữ của toast mà hook bắn ra (`"en"` mặc định · `"vi"`, hoặc cả bảng chuỗi tự soạn).
26
+ *
27
+ * Hook giữ bảng chuỗi của RIÊNG nó chứ không đọc `DataGridLocaleProvider`: toast render ở gốc
28
+ * app qua `<Toaster />`, ngoài hẳn cây DOM của lưới, nên không có context nào để đọc. Truyền
29
+ * cùng giá trị đã truyền cho `useDataGrid`.
30
+ */
31
+ locale?: DataGridLocale | DataGridMessages;
32
+ }
33
+ interface UseDataGridUndoRedoReturn<TData> {
34
+ canUndo: boolean;
35
+ canRedo: boolean;
36
+ onUndo: () => void;
37
+ onRedo: () => void;
38
+ onClear: () => void;
39
+ trackCellsUpdate: (updates: UndoRedoCellUpdate[]) => void;
40
+ trackRowsAdd: (rows: TData[]) => void;
41
+ trackRowsDelete: (rows: TData[]) => void;
42
+ }
43
+ declare function useDataGridUndoRedo<TData>({ data, onDataChange, getRowId, maxHistory, enabled, locale }: UseDataGridUndoRedoProps<TData>): UseDataGridUndoRedoReturn<TData>;
44
+
45
+ export { type UndoRedoCellUpdate, useDataGridUndoRedo };
@@ -0,0 +1,348 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ import { getDataGridMessages } from "./messages.js";
4
+ import { toastInfo, toastSuccess } from "./toast.js";
5
+ import { useAsRef } from "./use-as-ref.js";
6
+ import { useLazyRef } from "./use-lazy-ref.js";
7
+ import { getIsInPopover } from "./utils.js";
8
+ const DEFAULT_MAX_HISTORY = 100;
9
+ const BATCH_TIMEOUT = 300;
10
+ function useStore(store, selector) {
11
+ const getSnapshot = React.useCallback(() => selector(store.getState()), [store, selector]);
12
+ return React.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);
13
+ }
14
+ function buildIndexById(data, getRowId) {
15
+ const map = /* @__PURE__ */ new Map();
16
+ for (let i = 0; i < data.length; i++) {
17
+ const row = data[i];
18
+ if (row) {
19
+ map.set(getRowId(row), i);
20
+ }
21
+ }
22
+ return map;
23
+ }
24
+ function getPendingKey(rowId, columnId) {
25
+ return `${rowId}\0${columnId}`;
26
+ }
27
+ function useDataGridUndoRedo({
28
+ data,
29
+ onDataChange,
30
+ getRowId,
31
+ maxHistory = DEFAULT_MAX_HISTORY,
32
+ enabled = true,
33
+ locale
34
+ }) {
35
+ const msg = React.useMemo(() => getDataGridMessages(locale), [locale]);
36
+ const msgRef = useAsRef(msg);
37
+ const propsRef = useAsRef({
38
+ data,
39
+ onDataChange,
40
+ getRowId,
41
+ maxHistory,
42
+ enabled
43
+ });
44
+ const listenersRef = useLazyRef(() => /* @__PURE__ */ new Set());
45
+ const stateRef = useLazyRef(() => ({
46
+ undoStack: [],
47
+ redoStack: [],
48
+ hasPendingChanges: false
49
+ }));
50
+ const pendingBatchRef = React.useRef({
51
+ byKey: /* @__PURE__ */ new Map(),
52
+ timeoutId: null
53
+ });
54
+ const pendingNotifyRef = React.useRef(false);
55
+ const store = React.useMemo(() => {
56
+ return {
57
+ subscribe: (callback) => {
58
+ listenersRef.current.add(callback);
59
+ return () => listenersRef.current.delete(callback);
60
+ },
61
+ getState: () => stateRef.current,
62
+ push: (entry) => {
63
+ const state = stateRef.current;
64
+ const newUndoStack = [...state.undoStack, entry];
65
+ if (newUndoStack.length > propsRef.current.maxHistory) {
66
+ newUndoStack.shift();
67
+ }
68
+ stateRef.current = {
69
+ undoStack: newUndoStack,
70
+ redoStack: [],
71
+ hasPendingChanges: false
72
+ };
73
+ store.notify();
74
+ },
75
+ undo: () => {
76
+ const state = stateRef.current;
77
+ if (state.undoStack.length === 0) return null;
78
+ const entry = state.undoStack[state.undoStack.length - 1];
79
+ if (!entry) return null;
80
+ stateRef.current = {
81
+ undoStack: state.undoStack.slice(0, -1),
82
+ redoStack: [...state.redoStack, entry],
83
+ hasPendingChanges: false
84
+ };
85
+ store.notify();
86
+ return entry;
87
+ },
88
+ redo: () => {
89
+ const state = stateRef.current;
90
+ if (state.redoStack.length === 0) return null;
91
+ const entry = state.redoStack[state.redoStack.length - 1];
92
+ if (!entry) return null;
93
+ stateRef.current = {
94
+ undoStack: [...state.undoStack, entry],
95
+ redoStack: state.redoStack.slice(0, -1),
96
+ hasPendingChanges: false
97
+ };
98
+ store.notify();
99
+ return entry;
100
+ },
101
+ clear: () => {
102
+ stateRef.current = {
103
+ undoStack: [],
104
+ redoStack: [],
105
+ hasPendingChanges: false
106
+ };
107
+ store.notify();
108
+ },
109
+ setPendingChanges: (value) => {
110
+ if (stateRef.current.hasPendingChanges === value) return;
111
+ stateRef.current = {
112
+ ...stateRef.current,
113
+ hasPendingChanges: value
114
+ };
115
+ if (!pendingNotifyRef.current) {
116
+ pendingNotifyRef.current = true;
117
+ queueMicrotask(() => {
118
+ pendingNotifyRef.current = false;
119
+ store.notify();
120
+ });
121
+ }
122
+ },
123
+ notify: () => {
124
+ for (const listener of listenersRef.current) {
125
+ listener();
126
+ }
127
+ }
128
+ };
129
+ }, [listenersRef, stateRef, propsRef]);
130
+ const canUndo = useStore(store, (state) => state.undoStack.length > 0 || state.hasPendingChanges);
131
+ const canRedo = useStore(store, (state) => state.redoStack.length > 0);
132
+ const onCommit = React.useCallback(() => {
133
+ const pending = pendingBatchRef.current;
134
+ if (pending.byKey.size === 0) return;
135
+ if (pending.timeoutId) {
136
+ clearTimeout(pending.timeoutId);
137
+ pending.timeoutId = null;
138
+ }
139
+ const updates = Array.from(pending.byKey.values());
140
+ pending.byKey.clear();
141
+ const { getRowId: getRowId2 } = propsRef.current;
142
+ const entry = {
143
+ variant: "cells_update",
144
+ count: updates.length,
145
+ timestamp: Date.now(),
146
+ undo: (currentData) => {
147
+ const newData = [...currentData];
148
+ const indexById = buildIndexById(newData, getRowId2);
149
+ for (const update of updates) {
150
+ const index = indexById.get(update.rowId);
151
+ if (index !== void 0) {
152
+ const row = newData[index];
153
+ if (row) {
154
+ newData[index] = {
155
+ ...row,
156
+ [update.columnId]: update.previousValue
157
+ };
158
+ }
159
+ }
160
+ }
161
+ return newData;
162
+ },
163
+ redo: (currentData) => {
164
+ const newData = [...currentData];
165
+ const indexById = buildIndexById(newData, getRowId2);
166
+ for (const update of updates) {
167
+ const index = indexById.get(update.rowId);
168
+ if (index !== void 0) {
169
+ const row = newData[index];
170
+ if (row) {
171
+ newData[index] = { ...row, [update.columnId]: update.newValue };
172
+ }
173
+ }
174
+ }
175
+ return newData;
176
+ }
177
+ };
178
+ store.push(entry);
179
+ }, [store, propsRef]);
180
+ const onUndo = React.useCallback(() => {
181
+ if (!propsRef.current.enabled) return;
182
+ onCommit();
183
+ const entry = store.undo();
184
+ if (!entry) {
185
+ toastInfo(msgRef.current.toast.nothingToUndo);
186
+ return;
187
+ }
188
+ const newData = entry.undo(propsRef.current.data);
189
+ propsRef.current.onDataChange(newData);
190
+ toastSuccess(msgRef.current.toast.undone(entry.count));
191
+ }, [store, propsRef, onCommit, msgRef]);
192
+ const onRedo = React.useCallback(() => {
193
+ if (!propsRef.current.enabled) return;
194
+ onCommit();
195
+ const entry = store.redo();
196
+ if (!entry) {
197
+ toastInfo(msgRef.current.toast.nothingToRedo);
198
+ return;
199
+ }
200
+ const newData = entry.redo(propsRef.current.data);
201
+ propsRef.current.onDataChange(newData);
202
+ toastSuccess(msgRef.current.toast.redone(entry.count));
203
+ }, [store, propsRef, onCommit, msgRef]);
204
+ const onClear = React.useCallback(() => {
205
+ const pending = pendingBatchRef.current;
206
+ if (pending.timeoutId) {
207
+ clearTimeout(pending.timeoutId);
208
+ pending.timeoutId = null;
209
+ }
210
+ pending.byKey.clear();
211
+ store.clear();
212
+ }, [store]);
213
+ const trackCellsUpdate = React.useCallback(
214
+ (updates) => {
215
+ if (!propsRef.current.enabled || updates.length === 0) return;
216
+ const filteredUpdates = updates.filter((u) => !Object.is(u.previousValue, u.newValue));
217
+ if (filteredUpdates.length === 0) return;
218
+ const pending = pendingBatchRef.current;
219
+ for (const update of filteredUpdates) {
220
+ const key = getPendingKey(update.rowId, update.columnId);
221
+ const existing = pending.byKey.get(key);
222
+ if (existing) {
223
+ pending.byKey.set(key, { ...existing, newValue: update.newValue });
224
+ } else {
225
+ pending.byKey.set(key, update);
226
+ }
227
+ }
228
+ store.setPendingChanges(true);
229
+ if (pending.timeoutId) {
230
+ clearTimeout(pending.timeoutId);
231
+ }
232
+ pending.timeoutId = setTimeout(onCommit, BATCH_TIMEOUT);
233
+ },
234
+ [store, propsRef, onCommit]
235
+ );
236
+ const trackRowsAdd = React.useCallback(
237
+ (rows) => {
238
+ if (!propsRef.current.enabled || rows.length === 0) return;
239
+ onCommit();
240
+ const { getRowId: getRowId2 } = propsRef.current;
241
+ const rowIds = new Set(rows.map((row) => getRowId2(row)));
242
+ const rowsCopy = rows.map((row) => ({ ...row }));
243
+ const entry = {
244
+ variant: "rows_add",
245
+ count: rows.length,
246
+ timestamp: Date.now(),
247
+ undo: (currentData) => {
248
+ return currentData.filter((row) => !rowIds.has(getRowId2(row)));
249
+ },
250
+ redo: (currentData) => {
251
+ return [...currentData, ...rowsCopy.map((row) => ({ ...row }))];
252
+ }
253
+ };
254
+ store.push(entry);
255
+ },
256
+ [store, propsRef, onCommit]
257
+ );
258
+ const trackRowsDelete = React.useCallback(
259
+ (rows) => {
260
+ if (!propsRef.current.enabled || rows.length === 0) return;
261
+ onCommit();
262
+ const { getRowId: getRowId2, data: currentData } = propsRef.current;
263
+ const indexById = buildIndexById(currentData, getRowId2);
264
+ const rowsWithPositions = [];
265
+ for (const row of rows) {
266
+ const rowId = getRowId2(row);
267
+ const currentIndex = indexById.get(rowId);
268
+ if (currentIndex !== void 0) {
269
+ rowsWithPositions.push({
270
+ index: currentIndex,
271
+ row: { ...row }
272
+ });
273
+ }
274
+ }
275
+ rowsWithPositions.sort((a, b) => a.index - b.index);
276
+ const rowIds = new Set(rows.map((row) => getRowId2(row)));
277
+ const entry = {
278
+ variant: "rows_delete",
279
+ count: rows.length,
280
+ timestamp: Date.now(),
281
+ undo: (currentData2) => {
282
+ const newData = [...currentData2];
283
+ for (const { index, row } of rowsWithPositions) {
284
+ const insertIndex = Math.min(index, newData.length);
285
+ newData.splice(insertIndex, 0, { ...row });
286
+ }
287
+ return newData;
288
+ },
289
+ redo: (currentData2) => {
290
+ return currentData2.filter((row) => !rowIds.has(getRowId2(row)));
291
+ }
292
+ };
293
+ store.push(entry);
294
+ },
295
+ [store, propsRef, onCommit]
296
+ );
297
+ React.useEffect(() => {
298
+ const pending = pendingBatchRef.current;
299
+ return () => {
300
+ if (pending.timeoutId) {
301
+ clearTimeout(pending.timeoutId);
302
+ }
303
+ };
304
+ }, []);
305
+ React.useEffect(() => {
306
+ if (!enabled) return;
307
+ function onKeyDown(event) {
308
+ const isCtrlOrCmd = event.ctrlKey || event.metaKey;
309
+ const key = event.key.toLowerCase();
310
+ if (!isCtrlOrCmd || key !== "z" && key !== "y") return;
311
+ const activeElement = document.activeElement;
312
+ if (activeElement) {
313
+ const isInput = activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA";
314
+ const isContentEditable = activeElement.getAttribute("contenteditable") === "true";
315
+ const isInPopover = getIsInPopover(activeElement);
316
+ if (isInput || isContentEditable || isInPopover) return;
317
+ }
318
+ if (key === "z" && !event.shiftKey) {
319
+ event.preventDefault();
320
+ onUndo();
321
+ return;
322
+ }
323
+ if (key === "z" && event.shiftKey || key === "y") {
324
+ event.preventDefault();
325
+ onRedo();
326
+ }
327
+ }
328
+ document.addEventListener("keydown", onKeyDown);
329
+ return () => document.removeEventListener("keydown", onKeyDown);
330
+ }, [enabled, onUndo, onRedo]);
331
+ return React.useMemo(
332
+ () => ({
333
+ canUndo,
334
+ canRedo,
335
+ onUndo,
336
+ onRedo,
337
+ onClear,
338
+ trackCellsUpdate,
339
+ trackRowsAdd,
340
+ trackRowsDelete
341
+ }),
342
+ [canUndo, canRedo, onUndo, onRedo, onClear, trackCellsUpdate, trackRowsAdd, trackRowsDelete]
343
+ );
344
+ }
345
+ export {
346
+ useDataGridUndoRedo
347
+ };
348
+ //# sourceMappingURL=use-data-grid-undo-redo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-grid/use-data-grid-undo-redo.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { type DataGridLocale, type DataGridMessages, getDataGridMessages } from \"./messages.js\";\nimport { toastInfo, toastSuccess } from \"./toast.js\";\nimport { useAsRef } from \"./use-as-ref.js\";\nimport { useLazyRef } from \"./use-lazy-ref.js\";\nimport { getIsInPopover } from \"./utils.js\";\n\nconst DEFAULT_MAX_HISTORY = 100;\nconst BATCH_TIMEOUT = 300;\n\ninterface HistoryEntry<TData> {\n variant: \"cells_update\" | \"rows_add\" | \"rows_delete\";\n count: number;\n timestamp: number;\n undo: (currentData: TData[]) => TData[];\n redo: (currentData: TData[]) => TData[];\n}\n\ninterface UndoRedoCellUpdate {\n rowId: string;\n columnId: string;\n previousValue: unknown;\n newValue: unknown;\n}\n\ninterface StoreState<TData> {\n undoStack: HistoryEntry<TData>[];\n redoStack: HistoryEntry<TData>[];\n hasPendingChanges: boolean;\n}\n\ninterface Store<TData> {\n subscribe: (callback: () => void) => () => void;\n getState: () => StoreState<TData>;\n push: (entry: HistoryEntry<TData>) => void;\n undo: () => HistoryEntry<TData> | null;\n redo: () => HistoryEntry<TData> | null;\n clear: () => void;\n setPendingChanges: (value: boolean) => void;\n notify: () => void;\n}\n\nfunction useStore<T>(store: Store<T>, selector: (state: StoreState<T>) => boolean): boolean {\n const getSnapshot = React.useCallback(() => selector(store.getState()), [store, selector]);\n\n return React.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n}\n\nfunction buildIndexById<TData>(data: TData[], getRowId: (row: TData) => string): Map<string, number> {\n const map = new Map<string, number>();\n for (let i = 0; i < data.length; i++) {\n const row = data[i];\n if (row) {\n map.set(getRowId(row), i);\n }\n }\n return map;\n}\n\nfunction getPendingKey(rowId: string, columnId: string): string {\n return `${rowId}\\0${columnId}`;\n}\n\n/**\n * Tuỳ chọn của {@link useDataGridUndoRedo}. Lịch sử nằm hoàn toàn ở phía trình duyệt:\n * hook tính ra mảng dữ liệu trước/sau rồi trả về qua `onDataChange` — ứng dụng tự\n * đồng bộ lên máy chủ (hoặc bỏ qua nếu chỉ làm việc với state cục bộ).\n */\ninterface UseDataGridUndoRedoProps<TData> {\n data: TData[];\n onDataChange: (data: TData[]) => void;\n /** Khoá định danh bản ghi — phải khớp với `getRowId` của lưới */\n getRowId: (row: TData) => string;\n /** Số thao tác giữ trong lịch sử (mặc định 100) */\n maxHistory?: number;\n enabled?: boolean;\n /**\n * Ngôn ngữ của toast mà hook bắn ra (`\"en\"` mặc định · `\"vi\"`, hoặc cả bảng chuỗi tự soạn).\n *\n * Hook giữ bảng chuỗi của RIÊNG nó chứ không đọc `DataGridLocaleProvider`: toast render ở gốc\n * app qua `<Toaster />`, ngoài hẳn cây DOM của lưới, nên không có context nào để đọc. Truyền\n * cùng giá trị đã truyền cho `useDataGrid`.\n */\n locale?: DataGridLocale | DataGridMessages;\n}\n\ninterface UseDataGridUndoRedoReturn<TData> {\n canUndo: boolean;\n canRedo: boolean;\n onUndo: () => void;\n onRedo: () => void;\n onClear: () => void;\n trackCellsUpdate: (updates: UndoRedoCellUpdate[]) => void;\n trackRowsAdd: (rows: TData[]) => void;\n trackRowsDelete: (rows: TData[]) => void;\n}\n\nfunction useDataGridUndoRedo<TData>({\n data,\n onDataChange,\n getRowId,\n maxHistory = DEFAULT_MAX_HISTORY,\n enabled = true,\n locale\n}: UseDataGridUndoRedoProps<TData>): UseDataGridUndoRedoReturn<TData> {\n const msg = React.useMemo(() => getDataGridMessages(locale), [locale]);\n const msgRef = useAsRef(msg);\n const propsRef = useAsRef({\n data,\n onDataChange,\n getRowId,\n maxHistory,\n enabled\n });\n\n const listenersRef = useLazyRef(() => new Set<() => void>());\n\n const stateRef = useLazyRef<StoreState<TData>>(() => ({\n undoStack: [],\n redoStack: [],\n hasPendingChanges: false\n }));\n\n const pendingBatchRef = React.useRef<{\n byKey: Map<string, UndoRedoCellUpdate>;\n timeoutId: ReturnType<typeof setTimeout> | null;\n }>({\n byKey: new Map(),\n timeoutId: null\n });\n\n const pendingNotifyRef = React.useRef(false);\n\n const store = React.useMemo<Store<TData>>(() => {\n return {\n subscribe: (callback) => {\n listenersRef.current.add(callback);\n return () => listenersRef.current.delete(callback);\n },\n getState: () => stateRef.current,\n push: (entry) => {\n const state = stateRef.current;\n const newUndoStack = [...state.undoStack, entry];\n\n if (newUndoStack.length > propsRef.current.maxHistory) {\n newUndoStack.shift();\n }\n\n stateRef.current = {\n undoStack: newUndoStack,\n redoStack: [],\n hasPendingChanges: false\n };\n store.notify();\n },\n undo: () => {\n const state = stateRef.current;\n if (state.undoStack.length === 0) return null;\n\n const entry = state.undoStack[state.undoStack.length - 1];\n if (!entry) return null;\n\n stateRef.current = {\n undoStack: state.undoStack.slice(0, -1),\n redoStack: [...state.redoStack, entry],\n hasPendingChanges: false\n };\n store.notify();\n return entry;\n },\n redo: () => {\n const state = stateRef.current;\n if (state.redoStack.length === 0) return null;\n\n const entry = state.redoStack[state.redoStack.length - 1];\n if (!entry) return null;\n\n stateRef.current = {\n undoStack: [...state.undoStack, entry],\n redoStack: state.redoStack.slice(0, -1),\n hasPendingChanges: false\n };\n store.notify();\n return entry;\n },\n clear: () => {\n stateRef.current = {\n undoStack: [],\n redoStack: [],\n hasPendingChanges: false\n };\n store.notify();\n },\n setPendingChanges: (value) => {\n if (stateRef.current.hasPendingChanges === value) return;\n stateRef.current = {\n ...stateRef.current,\n hasPendingChanges: value\n };\n\n if (!pendingNotifyRef.current) {\n pendingNotifyRef.current = true;\n queueMicrotask(() => {\n pendingNotifyRef.current = false;\n store.notify();\n });\n }\n },\n notify: () => {\n for (const listener of listenersRef.current) {\n listener();\n }\n }\n };\n }, [listenersRef, stateRef, propsRef]);\n\n const canUndo = useStore(store, (state) => state.undoStack.length > 0 || state.hasPendingChanges);\n const canRedo = useStore(store, (state) => state.redoStack.length > 0);\n\n const onCommit = React.useCallback(() => {\n const pending = pendingBatchRef.current;\n if (pending.byKey.size === 0) return;\n\n if (pending.timeoutId) {\n clearTimeout(pending.timeoutId);\n pending.timeoutId = null;\n }\n\n const updates = Array.from(pending.byKey.values());\n pending.byKey.clear();\n\n const { getRowId } = propsRef.current;\n\n const entry: HistoryEntry<TData> = {\n variant: \"cells_update\",\n count: updates.length,\n timestamp: Date.now(),\n undo: (currentData) => {\n const newData = [...currentData];\n const indexById = buildIndexById(newData, getRowId);\n\n for (const update of updates) {\n const index = indexById.get(update.rowId);\n if (index !== undefined) {\n const row = newData[index];\n if (row) {\n newData[index] = {\n ...row,\n [update.columnId]: update.previousValue\n };\n }\n }\n }\n return newData;\n },\n redo: (currentData) => {\n const newData = [...currentData];\n const indexById = buildIndexById(newData, getRowId);\n\n for (const update of updates) {\n const index = indexById.get(update.rowId);\n if (index !== undefined) {\n const row = newData[index];\n if (row) {\n newData[index] = { ...row, [update.columnId]: update.newValue };\n }\n }\n }\n return newData;\n }\n };\n\n store.push(entry);\n }, [store, propsRef]);\n\n const onUndo = React.useCallback(() => {\n if (!propsRef.current.enabled) return;\n\n onCommit();\n\n const entry = store.undo();\n if (!entry) {\n toastInfo(msgRef.current.toast.nothingToUndo);\n return;\n }\n\n const newData = entry.undo(propsRef.current.data);\n propsRef.current.onDataChange(newData);\n\n toastSuccess(msgRef.current.toast.undone(entry.count));\n }, [store, propsRef, onCommit, msgRef]);\n\n const onRedo = React.useCallback(() => {\n if (!propsRef.current.enabled) return;\n\n onCommit();\n\n const entry = store.redo();\n if (!entry) {\n toastInfo(msgRef.current.toast.nothingToRedo);\n return;\n }\n\n const newData = entry.redo(propsRef.current.data);\n propsRef.current.onDataChange(newData);\n\n toastSuccess(msgRef.current.toast.redone(entry.count));\n }, [store, propsRef, onCommit, msgRef]);\n\n const onClear = React.useCallback(() => {\n const pending = pendingBatchRef.current;\n if (pending.timeoutId) {\n clearTimeout(pending.timeoutId);\n pending.timeoutId = null;\n }\n pending.byKey.clear();\n\n store.clear();\n }, [store]);\n\n const trackCellsUpdate = React.useCallback(\n (updates: UndoRedoCellUpdate[]) => {\n if (!propsRef.current.enabled || updates.length === 0) return;\n\n const filteredUpdates = updates.filter((u) => !Object.is(u.previousValue, u.newValue));\n if (filteredUpdates.length === 0) return;\n\n const pending = pendingBatchRef.current;\n\n for (const update of filteredUpdates) {\n const key = getPendingKey(update.rowId, update.columnId);\n const existing = pending.byKey.get(key);\n\n if (existing) {\n pending.byKey.set(key, { ...existing, newValue: update.newValue });\n } else {\n pending.byKey.set(key, update);\n }\n }\n\n store.setPendingChanges(true);\n\n if (pending.timeoutId) {\n clearTimeout(pending.timeoutId);\n }\n pending.timeoutId = setTimeout(onCommit, BATCH_TIMEOUT);\n },\n [store, propsRef, onCommit]\n );\n\n const trackRowsAdd = React.useCallback(\n (rows: TData[]) => {\n if (!propsRef.current.enabled || rows.length === 0) return;\n\n onCommit();\n\n const { getRowId } = propsRef.current;\n\n const rowIds = new Set(rows.map((row) => getRowId(row)));\n const rowsCopy = rows.map((row) => ({ ...row }));\n\n const entry: HistoryEntry<TData> = {\n variant: \"rows_add\",\n count: rows.length,\n timestamp: Date.now(),\n undo: (currentData) => {\n return currentData.filter((row) => !rowIds.has(getRowId(row)));\n },\n redo: (currentData) => {\n return [...currentData, ...rowsCopy.map((row) => ({ ...row }))];\n }\n };\n\n store.push(entry);\n },\n [store, propsRef, onCommit]\n );\n\n const trackRowsDelete = React.useCallback(\n (rows: TData[]) => {\n if (!propsRef.current.enabled || rows.length === 0) return;\n\n onCommit();\n\n const { getRowId, data: currentData } = propsRef.current;\n\n const indexById = buildIndexById(currentData, getRowId);\n\n const rowsWithPositions: Array<{ index: number; row: TData }> = [];\n for (const row of rows) {\n const rowId = getRowId(row);\n const currentIndex = indexById.get(rowId);\n if (currentIndex !== undefined) {\n rowsWithPositions.push({\n index: currentIndex,\n row: { ...row }\n });\n }\n }\n\n rowsWithPositions.sort((a, b) => a.index - b.index);\n\n const rowIds = new Set(rows.map((row) => getRowId(row)));\n\n const entry: HistoryEntry<TData> = {\n variant: \"rows_delete\",\n count: rows.length,\n timestamp: Date.now(),\n undo: (currentData) => {\n const newData = [...currentData];\n for (const { index, row } of rowsWithPositions) {\n const insertIndex = Math.min(index, newData.length);\n newData.splice(insertIndex, 0, { ...row });\n }\n return newData;\n },\n redo: (currentData) => {\n return currentData.filter((row) => !rowIds.has(getRowId(row)));\n }\n };\n\n store.push(entry);\n },\n [store, propsRef, onCommit]\n );\n\n React.useEffect(() => {\n const pending = pendingBatchRef.current;\n return () => {\n if (pending.timeoutId) {\n clearTimeout(pending.timeoutId);\n }\n };\n }, []);\n\n React.useEffect(() => {\n if (!enabled) return;\n\n function onKeyDown(event: KeyboardEvent) {\n const isCtrlOrCmd = event.ctrlKey || event.metaKey;\n const key = event.key.toLowerCase();\n\n if (!isCtrlOrCmd || (key !== \"z\" && key !== \"y\")) return;\n\n const activeElement = document.activeElement;\n if (activeElement) {\n const isInput = activeElement.tagName === \"INPUT\" || activeElement.tagName === \"TEXTAREA\";\n const isContentEditable = activeElement.getAttribute(\"contenteditable\") === \"true\";\n const isInPopover = getIsInPopover(activeElement);\n\n if (isInput || isContentEditable || isInPopover) return;\n }\n\n if (key === \"z\" && !event.shiftKey) {\n event.preventDefault();\n onUndo();\n return;\n }\n\n if ((key === \"z\" && event.shiftKey) || key === \"y\") {\n event.preventDefault();\n onRedo();\n }\n }\n\n document.addEventListener(\"keydown\", onKeyDown);\n return () => document.removeEventListener(\"keydown\", onKeyDown);\n }, [enabled, onUndo, onRedo]);\n\n return React.useMemo(\n () => ({\n canUndo,\n canRedo,\n onUndo,\n onRedo,\n onClear,\n trackCellsUpdate,\n trackRowsAdd,\n trackRowsDelete\n }),\n [canUndo, canRedo, onUndo, onRedo, onClear, trackCellsUpdate, trackRowsAdd, trackRowsDelete]\n );\n}\n\nexport {\n //\n type UndoRedoCellUpdate,\n useDataGridUndoRedo\n};\n"],"mappings":"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","names":["getRowId","currentData"]}