@coreui/react-data-grid 0.1.0-rc.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 (104) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +33 -0
  3. package/dist/cjs/CDataGrid.d.ts +8 -0
  4. package/dist/cjs/CDataGrid.js +903 -0
  5. package/dist/cjs/CDataGrid.js.map +1 -0
  6. package/dist/cjs/CDataGridBody.d.ts +40 -0
  7. package/dist/cjs/CDataGridBody.js +144 -0
  8. package/dist/cjs/CDataGridBody.js.map +1 -0
  9. package/dist/cjs/CDataGridCellEditor.d.ts +8 -0
  10. package/dist/cjs/CDataGridCellEditor.js +67 -0
  11. package/dist/cjs/CDataGridCellEditor.js.map +1 -0
  12. package/dist/cjs/CDataGridColumnChooser.d.ts +23 -0
  13. package/dist/cjs/CDataGridColumnChooser.js +71 -0
  14. package/dist/cjs/CDataGridColumnChooser.js.map +1 -0
  15. package/dist/cjs/CDataGridFilterMenu.d.ts +22 -0
  16. package/dist/cjs/CDataGridFilterMenu.js +177 -0
  17. package/dist/cjs/CDataGridFilterMenu.js.map +1 -0
  18. package/dist/cjs/CDataGridHeader.d.ts +36 -0
  19. package/dist/cjs/CDataGridHeader.js +232 -0
  20. package/dist/cjs/CDataGridHeader.js.map +1 -0
  21. package/dist/cjs/CDataGridHeaderMenu.d.ts +29 -0
  22. package/dist/cjs/CDataGridHeaderMenu.js +127 -0
  23. package/dist/cjs/CDataGridHeaderMenu.js.map +1 -0
  24. package/dist/cjs/CDataGridPagination.d.ts +18 -0
  25. package/dist/cjs/CDataGridPagination.js +39 -0
  26. package/dist/cjs/CDataGridPagination.js.map +1 -0
  27. package/dist/cjs/CDataGridToolbar.d.ts +32 -0
  28. package/dist/cjs/CDataGridToolbar.js +49 -0
  29. package/dist/cjs/CDataGridToolbar.js.map +1 -0
  30. package/dist/cjs/active-cell.d.ts +22 -0
  31. package/dist/cjs/active-cell.js +89 -0
  32. package/dist/cjs/active-cell.js.map +1 -0
  33. package/dist/cjs/columns.d.ts +37 -0
  34. package/dist/cjs/columns.js +170 -0
  35. package/dist/cjs/columns.js.map +1 -0
  36. package/dist/cjs/icons.d.ts +22 -0
  37. package/dist/cjs/icons.js +40 -0
  38. package/dist/cjs/icons.js.map +1 -0
  39. package/dist/cjs/index.d.ts +12 -0
  40. package/dist/cjs/index.js +39 -0
  41. package/dist/cjs/index.js.map +1 -0
  42. package/dist/cjs/labels.d.ts +7 -0
  43. package/dist/cjs/pinning.d.ts +19 -0
  44. package/dist/cjs/pinning.js +32 -0
  45. package/dist/cjs/pinning.js.map +1 -0
  46. package/dist/cjs/toolbar.d.ts +22 -0
  47. package/dist/cjs/toolbar.js +43 -0
  48. package/dist/cjs/toolbar.js.map +1 -0
  49. package/dist/cjs/tooltip.d.ts +10 -0
  50. package/dist/cjs/tooltip.js +102 -0
  51. package/dist/cjs/tooltip.js.map +1 -0
  52. package/dist/cjs/types.d.ts +287 -0
  53. package/dist/esm/CDataGrid.d.ts +8 -0
  54. package/dist/esm/CDataGrid.mjs +901 -0
  55. package/dist/esm/CDataGrid.mjs.map +1 -0
  56. package/dist/esm/CDataGridBody.d.ts +40 -0
  57. package/dist/esm/CDataGridBody.mjs +142 -0
  58. package/dist/esm/CDataGridBody.mjs.map +1 -0
  59. package/dist/esm/CDataGridCellEditor.d.ts +8 -0
  60. package/dist/esm/CDataGridCellEditor.mjs +65 -0
  61. package/dist/esm/CDataGridCellEditor.mjs.map +1 -0
  62. package/dist/esm/CDataGridColumnChooser.d.ts +23 -0
  63. package/dist/esm/CDataGridColumnChooser.mjs +69 -0
  64. package/dist/esm/CDataGridColumnChooser.mjs.map +1 -0
  65. package/dist/esm/CDataGridFilterMenu.d.ts +22 -0
  66. package/dist/esm/CDataGridFilterMenu.mjs +175 -0
  67. package/dist/esm/CDataGridFilterMenu.mjs.map +1 -0
  68. package/dist/esm/CDataGridHeader.d.ts +36 -0
  69. package/dist/esm/CDataGridHeader.mjs +230 -0
  70. package/dist/esm/CDataGridHeader.mjs.map +1 -0
  71. package/dist/esm/CDataGridHeaderMenu.d.ts +29 -0
  72. package/dist/esm/CDataGridHeaderMenu.mjs +125 -0
  73. package/dist/esm/CDataGridHeaderMenu.mjs.map +1 -0
  74. package/dist/esm/CDataGridPagination.d.ts +18 -0
  75. package/dist/esm/CDataGridPagination.mjs +37 -0
  76. package/dist/esm/CDataGridPagination.mjs.map +1 -0
  77. package/dist/esm/CDataGridToolbar.d.ts +32 -0
  78. package/dist/esm/CDataGridToolbar.mjs +47 -0
  79. package/dist/esm/CDataGridToolbar.mjs.map +1 -0
  80. package/dist/esm/active-cell.d.ts +22 -0
  81. package/dist/esm/active-cell.mjs +86 -0
  82. package/dist/esm/active-cell.mjs.map +1 -0
  83. package/dist/esm/columns.d.ts +37 -0
  84. package/dist/esm/columns.mjs +163 -0
  85. package/dist/esm/columns.mjs.map +1 -0
  86. package/dist/esm/icons.d.ts +22 -0
  87. package/dist/esm/icons.mjs +24 -0
  88. package/dist/esm/icons.mjs.map +1 -0
  89. package/dist/esm/index.d.mts +1 -0
  90. package/dist/esm/index.d.ts +12 -0
  91. package/dist/esm/index.mjs +5 -0
  92. package/dist/esm/index.mjs.map +1 -0
  93. package/dist/esm/labels.d.ts +7 -0
  94. package/dist/esm/pinning.d.ts +19 -0
  95. package/dist/esm/pinning.mjs +29 -0
  96. package/dist/esm/pinning.mjs.map +1 -0
  97. package/dist/esm/toolbar.d.ts +22 -0
  98. package/dist/esm/toolbar.mjs +41 -0
  99. package/dist/esm/toolbar.mjs.map +1 -0
  100. package/dist/esm/tooltip.d.ts +10 -0
  101. package/dist/esm/tooltip.mjs +100 -0
  102. package/dist/esm/tooltip.mjs.map +1 -0
  103. package/dist/esm/types.d.ts +287 -0
  104. package/package.json +92 -0
@@ -0,0 +1,903 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var filters = require('@coreui/data-grid/filters');
5
+ var reactTable = require('@tanstack/react-table');
6
+ var react = require('react');
7
+ var activeCell = require('./active-cell.js');
8
+ var CDataGridBody = require('./CDataGridBody.js');
9
+ var CDataGridCellEditor = require('./CDataGridCellEditor.js');
10
+ var CDataGridHeader = require('./CDataGridHeader.js');
11
+ var CDataGridPagination = require('./CDataGridPagination.js');
12
+ var CDataGridToolbar = require('./CDataGridToolbar.js');
13
+ var columns = require('./columns.js');
14
+ var icons = require('./icons.js');
15
+ var labels = require('@coreui/data-grid/labels');
16
+ var toolbar = require('./toolbar.js');
17
+ var tooltip = require('./tooltip.js');
18
+
19
+ const DEFAULT_PAGE_SIZE_OPTIONS = [5, 10, 20, 50];
20
+ const STATE_STORAGE_PREFIX = 'coreui-data-grid:';
21
+ const HISTORY_LIMIT = 100;
22
+ const readPersistedState = (stateKey) => {
23
+ if (!stateKey) {
24
+ return null;
25
+ }
26
+ try {
27
+ const raw = window.localStorage.getItem(`${STATE_STORAGE_PREFIX}${stateKey}`);
28
+ return raw ? JSON.parse(raw) : null;
29
+ }
30
+ catch (_a) {
31
+ return null;
32
+ }
33
+ };
34
+ const FETCH_DEBOUNCE_MS = 100;
35
+ // Module-level so an omitted `items` prop keeps a stable identity - a fresh
36
+ // array per render would force TanStack to recompute row models every time.
37
+ const EMPTY_ITEMS = [];
38
+ const toTanStackFilterFn = (column) => {
39
+ const { filterFn } = column;
40
+ if (filterFn) {
41
+ return (row, columnId, filterValue) => filterFn(row.getValue(columnId), filterValue, row.original);
42
+ }
43
+ return (row, columnId, filterValue) => filters.evaluateColumnFilter(row.getValue(columnId), filterValue, column.filterType);
44
+ };
45
+ const CDataGrid = react.forwardRef((props, ref) => {
46
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
47
+ const { cellNavigation = false, className, columnFilters = false, columnMenu = false, columnMenuIcon = icons.DEFAULT_COLUMN_MENU_ICON, columnOrder = false, columnPinning = false, columnSizing = false, columnVisibility = false, columns: columns$1, dataProvider, editing = false, empty = 'No items found', filterIcon = icons.DEFAULT_FILTER_ICON, globalFilter = false, hideColumnIcon = icons.DEFAULT_HIDE_COLUMN_ICON, history = false, itemKey, items = EMPTY_ITEMS, labels: labels$1, moveLeftIcon = icons.DEFAULT_MOVE_LEFT_ICON, moveRightIcon = icons.DEFAULT_MOVE_RIGHT_ICON, onDataError, onDataLoad, onEditCancel, onEditCommit, onEditStart, onFilterChange, onOrderChange, onPaginationChange, onPinningChange, onSelectionChange, onSizingChange, onSortingChange, onVisibilityChange, overscan = 10, pagination = false, pinLeftIcon = icons.DEFAULT_PIN_LEFT_ICON, pinRightIcon = icons.DEFAULT_PIN_RIGHT_ICON, rowHeight = 44, rowSelection = false, slots, sortAscendingIcon = icons.DEFAULT_SORT_ASCENDING_ICON, sortDescendingIcon = icons.DEFAULT_SORT_DESCENDING_ICON, sortNeutralIcon = icons.DEFAULT_SORT_NEUTRAL_ICON, sorterVisibility, sorting = true, stateKey, tableRef, toolbar: toolbar$1 = false, toolbarColumnsIcon = icons.DEFAULT_TOOLBAR_COLUMNS_ICON, toolbarExportIcon = icons.DEFAULT_TOOLBAR_EXPORT_ICON, toolbarRedoIcon = icons.DEFAULT_TOOLBAR_REDO_ICON, toolbarUndoIcon = icons.DEFAULT_TOOLBAR_UNDO_ICON, unpinIcon = icons.DEFAULT_UNPIN_ICON, virtualization = true, ...rest } = props;
48
+ const mergedLabels = react.useMemo(() => ({ ...labels.DEFAULT_LABELS, ...labels$1 }), [labels$1]);
49
+ const menuIcons = react.useMemo(() => ({
50
+ columnMenu: columnMenuIcon,
51
+ filter: filterIcon,
52
+ hideColumn: hideColumnIcon,
53
+ moveLeft: moveLeftIcon,
54
+ moveRight: moveRightIcon,
55
+ pinLeft: pinLeftIcon,
56
+ pinRight: pinRightIcon,
57
+ sortAscending: sortAscendingIcon,
58
+ sortDescending: sortDescendingIcon,
59
+ sortNeutral: sortNeutralIcon,
60
+ unpin: unpinIcon
61
+ }), [
62
+ columnMenuIcon,
63
+ filterIcon,
64
+ hideColumnIcon,
65
+ moveLeftIcon,
66
+ moveRightIcon,
67
+ pinLeftIcon,
68
+ pinRightIcon,
69
+ sortAscendingIcon,
70
+ sortDescendingIcon,
71
+ sortNeutralIcon,
72
+ unpinIcon
73
+ ]);
74
+ const menuBuilder = typeof columnMenu === 'function' ? columnMenu : null;
75
+ // Editing needs the active-cell substrate (Enter/F2 target the active cell).
76
+ const cellNavigationEnabled = cellNavigation || editing;
77
+ const sortingOptions = typeof sorting === 'object' ? sorting : {};
78
+ const sizingEnabled = Boolean(columnSizing);
79
+ const sizingOptions = typeof columnSizing === 'object' ? columnSizing : {};
80
+ const pinningEnabled = Boolean(columnPinning);
81
+ const widthsEnabled = sizingEnabled || pinningEnabled;
82
+ const selectionEnabled = Boolean(rowSelection);
83
+ const selectionOptions = typeof rowSelection === 'object' ? rowSelection : {};
84
+ const serverSide = Boolean(dataProvider);
85
+ // Server-side mode implies pagination — virtualized infinite scroll over a
86
+ // dataProvider is out of scope until 0.3.0.
87
+ const paginationEnabled = Boolean(pagination) || serverSide;
88
+ const paginationOptions = typeof pagination === 'object' ? pagination : {};
89
+ const virtualizationEnabled = virtualization && !paginationEnabled;
90
+ const resolvedToolbar = toolbar.resolveToolbar({
91
+ columnVisibility: Boolean(columnVisibility),
92
+ globalFilter,
93
+ history,
94
+ toolbar: toolbar$1
95
+ });
96
+ const isColumnSortable = (column) => Boolean(sorting) && column.sortable !== false;
97
+ const isColumnFilterable = (column) => columnFilters && column.filterable !== false;
98
+ const isColumnResizable = (column) => sizingEnabled && column.resizable !== false;
99
+ // A persisted view (stateKey) seeds the initial state - read once.
100
+ const persistedStateRef = react.useRef(undefined);
101
+ if (persistedStateRef.current === undefined) {
102
+ persistedStateRef.current = readPersistedState(stateKey);
103
+ }
104
+ const persisted = persistedStateRef.current;
105
+ const [sortingState, setSortingState] = react.useState((_a = persisted === null || persisted === void 0 ? void 0 : persisted.sorting) !== null && _a !== void 0 ? _a : []);
106
+ const [columnFiltersState, setColumnFiltersState] = react.useState((_b = persisted === null || persisted === void 0 ? void 0 : persisted.columnFilters) !== null && _b !== void 0 ? _b : []);
107
+ const [globalFilterState, setGlobalFilterState] = react.useState((persisted === null || persisted === void 0 ? void 0 : persisted.globalFilter) === undefined || persisted.globalFilter === '' ? undefined : persisted.globalFilter);
108
+ const [rowSelectionState, setRowSelectionState] = react.useState((_c = persisted === null || persisted === void 0 ? void 0 : persisted.rowSelection) !== null && _c !== void 0 ? _c : {});
109
+ const [columnSizingState, setColumnSizingState] = react.useState((_d = persisted === null || persisted === void 0 ? void 0 : persisted.columnSizing) !== null && _d !== void 0 ? _d : {});
110
+ const [columnPinningState, setColumnPinningState] = react.useState((_e = persisted === null || persisted === void 0 ? void 0 : persisted.columnPinning) !== null && _e !== void 0 ? _e : (typeof columnPinning === 'object' ? columnPinning : {}));
111
+ const [columnOrderState, setColumnOrderState] = react.useState((_f = persisted === null || persisted === void 0 ? void 0 : persisted.columnOrder) !== null && _f !== void 0 ? _f : (Array.isArray(columnOrder) ? columnOrder : []));
112
+ const [columnVisibilityState, setColumnVisibilityState] = react.useState((_g = persisted === null || persisted === void 0 ? void 0 : persisted.columnVisibility) !== null && _g !== void 0 ? _g : (typeof columnVisibility === 'object' ? columnVisibility : {}));
113
+ // The chooser's Reset restores the initial columnVisibility object, captured
114
+ // once (initial-value-only, like the state seed above).
115
+ const initialColumnVisibility = react.useRef(typeof columnVisibility === 'object' ? columnVisibility : {});
116
+ const [paginationState, setPaginationState] = react.useState({
117
+ pageIndex: (_j = (_h = persisted === null || persisted === void 0 ? void 0 : persisted.pagination) === null || _h === void 0 ? void 0 : _h.pageIndex) !== null && _j !== void 0 ? _j : 0,
118
+ pageSize: (_m = (_l = (_k = persisted === null || persisted === void 0 ? void 0 : persisted.pagination) === null || _k === void 0 ? void 0 : _k.pageSize) !== null && _l !== void 0 ? _l : paginationOptions.pageSize) !== null && _m !== void 0 ? _m : 10
119
+ });
120
+ const [activeCell$1, setActiveCell] = react.useState(null);
121
+ // A pending focus request survives renders until the target cell exists in
122
+ // the DOM (the body's focus pass consumes it) - focus is derived from
123
+ // state, never from what the recycler left behind.
124
+ const focusRequestRef = react.useRef(null);
125
+ const containsFocusRef = react.useRef(false);
126
+ const scrollToIndexRef = react.useRef(null);
127
+ // The ref mirrors the state so keydown/pointerdown handlers stay
128
+ // synchronous (start-then-stop in one handler must not race renders).
129
+ const [editingCell, setEditingCellState] = react.useState(null);
130
+ const editingCellRef = react.useRef(null);
131
+ const setEditingCell = (next) => {
132
+ editingCellRef.current = next;
133
+ setEditingCellState(next);
134
+ };
135
+ const [editorInvalid, setEditorInvalid] = react.useState(null);
136
+ const [editorPopupStyle, setEditorPopupStyle] = react.useState(null);
137
+ const editorHandleRef = react.useRef(null);
138
+ // The draft survives the editor's unmount (a recycled editing row) so the
139
+ // scroll-away commit still carries the value.
140
+ const editorDraftRef = react.useRef(null);
141
+ const editorFocusPendingRef = react.useRef(false);
142
+ const registerEditorHandle = (handle) => {
143
+ var _a;
144
+ if (handle === null && ((_a = editorHandleRef.current) === null || _a === void 0 ? void 0 : _a.getValue) && editingCellRef.current) {
145
+ editorDraftRef.current = { value: editorHandleRef.current.getValue() };
146
+ }
147
+ editorHandleRef.current = handle;
148
+ if (handle !== null) {
149
+ editorDraftRef.current = null;
150
+ }
151
+ };
152
+ const [serverItems, setServerItems] = react.useState([]);
153
+ const [serverTotalRows, setServerTotalRows] = react.useState(0);
154
+ const [loading, setLoading] = react.useState(false);
155
+ const [loadFailed, setLoadFailed] = react.useState(false);
156
+ const [announcement, setAnnouncement] = react.useState('');
157
+ const columnDefs = react.useMemo(() => columns$1.map(column => {
158
+ var _a;
159
+ const size = (_a = column.width) !== null && _a !== void 0 ? _a : null;
160
+ return {
161
+ accessorKey: column.key,
162
+ enableColumnFilter: column.filterable !== false,
163
+ enableHiding: column.hideable !== false,
164
+ enableResizing: column.resizable !== false,
165
+ enableSorting: column.sortable !== false,
166
+ filterFn: toTanStackFilterFn(column),
167
+ id: column.key,
168
+ meta: { label: column.label, formatter: column.formatter },
169
+ ...(widthsEnabled && size !== null && { size })
170
+ };
171
+ }), [columns$1, widthsEnabled]);
172
+ const table = reactTable.useReactTable({
173
+ columns: columnDefs,
174
+ columnResizeMode: (_o = sizingOptions.mode) !== null && _o !== void 0 ? _o : 'onChange',
175
+ data: serverSide ? serverItems : items,
176
+ enableColumnFilters: columnFilters,
177
+ enableColumnPinning: pinningEnabled,
178
+ enableColumnResizing: sizingEnabled,
179
+ enableGlobalFilter: resolvedToolbar.search,
180
+ enableHiding: Boolean(columnVisibility),
181
+ enableMultiSort: sortingOptions.multiple !== false,
182
+ enableRowSelection: selectionEnabled,
183
+ enableSorting: Boolean(sorting),
184
+ enableSortingRemoval: Boolean(sortingOptions.resetable),
185
+ getCoreRowModel: reactTable.getCoreRowModel(),
186
+ // Faceting powers custom filter UIs (column.getFacetedUniqueValues()).
187
+ getFacetedRowModel: reactTable.getFacetedRowModel(),
188
+ getFacetedUniqueValues: reactTable.getFacetedUniqueValues(),
189
+ getFilteredRowModel: reactTable.getFilteredRowModel(),
190
+ getSortedRowModel: reactTable.getSortedRowModel(),
191
+ globalFilterFn: 'includesString',
192
+ ...(serverSide && {
193
+ manualFiltering: true,
194
+ manualPagination: true,
195
+ manualSorting: true,
196
+ rowCount: serverTotalRows
197
+ }),
198
+ ...(paginationEnabled && { getPaginationRowModel: reactTable.getPaginationRowModel() }),
199
+ ...(itemKey && { getRowId: itemKey }),
200
+ onColumnFiltersChange: setColumnFiltersState,
201
+ onColumnOrderChange: setColumnOrderState,
202
+ onColumnPinningChange: setColumnPinningState,
203
+ onColumnSizingChange: setColumnSizingState,
204
+ onColumnVisibilityChange: setColumnVisibilityState,
205
+ onGlobalFilterChange: setGlobalFilterState,
206
+ onPaginationChange: setPaginationState,
207
+ onRowSelectionChange: setRowSelectionState,
208
+ onSortingChange: setSortingState,
209
+ state: {
210
+ columnFilters: columnFiltersState,
211
+ columnOrder: columnOrderState,
212
+ columnPinning: columnPinningState,
213
+ columnSizing: columnSizingState,
214
+ columnVisibility: columnVisibilityState,
215
+ globalFilter: globalFilterState,
216
+ pagination: paginationState,
217
+ rowSelection: rowSelectionState,
218
+ sorting: sortingState
219
+ }
220
+ });
221
+ const rootRef = react.useRef(null);
222
+ // Stable across renders - an inline callback ref would be detached/reattached
223
+ // (null, node) on every render, hammering consumer callback refs.
224
+ const setRootRef = react.useCallback((node) => {
225
+ rootRef.current = node;
226
+ if (typeof ref === 'function') {
227
+ ref(node);
228
+ }
229
+ else if (ref) {
230
+ ref.current = node;
231
+ }
232
+ }, [ref]);
233
+ // The viewport element travels to the body as STATE, not a ref - the body's
234
+ // virtualizer reads it in a layout effect that runs before an ancestor ref
235
+ // would be attached, so a plain ref would still be null there on mount.
236
+ const [viewportElement, setViewportElement] = react.useState(null);
237
+ react.useEffect(() => {
238
+ if (!tableRef) {
239
+ return;
240
+ }
241
+ if (typeof tableRef === 'function') {
242
+ tableRef(table);
243
+ return () => {
244
+ tableRef(null);
245
+ };
246
+ }
247
+ tableRef.current = table;
248
+ return () => {
249
+ tableRef.current = null;
250
+ };
251
+ }, [table, tableRef]);
252
+ react.useEffect(() => {
253
+ if (!rootRef.current) {
254
+ return;
255
+ }
256
+ const tooltip$1 = tooltip.createTooltip(rootRef.current);
257
+ return () => tooltip$1.dispose();
258
+ }, []);
259
+ const requestIdRef = react.useRef(0);
260
+ const lastFilterKeyRef = react.useRef(null);
261
+ react.useEffect(() => {
262
+ if (!dataProvider) {
263
+ return;
264
+ }
265
+ const filterKey = JSON.stringify([sortingState, columnFiltersState, globalFilterState !== null && globalFilterState !== void 0 ? globalFilterState : '']);
266
+ const filtersChanged = lastFilterKeyRef.current !== null && lastFilterKeyRef.current !== filterKey;
267
+ lastFilterKeyRef.current = filterKey;
268
+ if (filtersChanged && paginationState.pageIndex !== 0) {
269
+ // Back to page one first; the pagination change re-runs this effect and
270
+ // fetches exactly once.
271
+ setPaginationState(previous => ({ ...previous, pageIndex: 0 }));
272
+ return;
273
+ }
274
+ const id = ++requestIdRef.current;
275
+ const timeout = setTimeout(async () => {
276
+ setLoading(true);
277
+ try {
278
+ const response = await dataProvider({
279
+ columnFilters: columnFiltersState,
280
+ globalFilter: globalFilterState !== null && globalFilterState !== void 0 ? globalFilterState : '',
281
+ pagination: paginationState,
282
+ sorting: sortingState
283
+ });
284
+ if (id !== requestIdRef.current) {
285
+ return;
286
+ }
287
+ setServerItems(response.items);
288
+ setServerTotalRows(response.totalRows);
289
+ setLoadFailed(false);
290
+ setAnnouncement(labels.interpolate(mergedLabels.resultsAnnouncement, { count: response.totalRows }));
291
+ onDataLoad === null || onDataLoad === void 0 ? void 0 : onDataLoad(response);
292
+ }
293
+ catch (error) {
294
+ if (id !== requestIdRef.current) {
295
+ return;
296
+ }
297
+ setServerItems([]);
298
+ setServerTotalRows(0);
299
+ setLoadFailed(true);
300
+ onDataError === null || onDataError === void 0 ? void 0 : onDataError(error);
301
+ }
302
+ finally {
303
+ if (id === requestIdRef.current) {
304
+ setLoading(false);
305
+ }
306
+ }
307
+ }, FETCH_DEBOUNCE_MS);
308
+ return () => clearTimeout(timeout);
309
+ // eslint-disable-next-line react-hooks/exhaustive-deps
310
+ }, [dataProvider, sortingState, columnFiltersState, globalFilterState, paginationState]);
311
+ const mounted = react.useRef(false);
312
+ const totalRows = serverSide ? serverTotalRows : table.getFilteredRowModel().rows.length;
313
+ react.useEffect(() => {
314
+ if (mounted.current) {
315
+ onSortingChange === null || onSortingChange === void 0 ? void 0 : onSortingChange(sortingState);
316
+ }
317
+ // eslint-disable-next-line react-hooks/exhaustive-deps
318
+ }, [sortingState]);
319
+ react.useEffect(() => {
320
+ if (mounted.current) {
321
+ onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange(columnFiltersState, globalFilterState !== null && globalFilterState !== void 0 ? globalFilterState : '');
322
+ }
323
+ // eslint-disable-next-line react-hooks/exhaustive-deps
324
+ }, [columnFiltersState, globalFilterState]);
325
+ react.useEffect(() => {
326
+ if (mounted.current) {
327
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(rowSelectionState, table.getSelectedRowModel().rows.map(row => row.original));
328
+ }
329
+ // eslint-disable-next-line react-hooks/exhaustive-deps
330
+ }, [rowSelectionState]);
331
+ react.useEffect(() => {
332
+ if (mounted.current) {
333
+ onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(paginationState);
334
+ }
335
+ // eslint-disable-next-line react-hooks/exhaustive-deps
336
+ }, [paginationState]);
337
+ react.useEffect(() => {
338
+ if (mounted.current) {
339
+ onSizingChange === null || onSizingChange === void 0 ? void 0 : onSizingChange(columnSizingState);
340
+ }
341
+ // eslint-disable-next-line react-hooks/exhaustive-deps
342
+ }, [columnSizingState]);
343
+ react.useEffect(() => {
344
+ if (mounted.current) {
345
+ onPinningChange === null || onPinningChange === void 0 ? void 0 : onPinningChange(columnPinningState);
346
+ }
347
+ // eslint-disable-next-line react-hooks/exhaustive-deps
348
+ }, [columnPinningState]);
349
+ react.useEffect(() => {
350
+ if (mounted.current) {
351
+ onOrderChange === null || onOrderChange === void 0 ? void 0 : onOrderChange(columnOrderState);
352
+ }
353
+ // eslint-disable-next-line react-hooks/exhaustive-deps
354
+ }, [columnOrderState]);
355
+ react.useEffect(() => {
356
+ if (mounted.current) {
357
+ onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(columnVisibilityState);
358
+ }
359
+ // eslint-disable-next-line react-hooks/exhaustive-deps
360
+ }, [columnVisibilityState]);
361
+ react.useEffect(() => {
362
+ if (mounted.current && !serverSide) {
363
+ setAnnouncement(labels.interpolate(mergedLabels.resultsAnnouncement, { count: totalRows }));
364
+ }
365
+ // eslint-disable-next-line react-hooks/exhaustive-deps
366
+ }, [columnFiltersState, globalFilterState]);
367
+ // Pagination joins by VALUE: a data replacement makes TanStack auto-reset
368
+ // the page index, which replaces the state object without changing it -
369
+ // identity alone would kill an edit right after its onEditCommit handler
370
+ // applied the change.
371
+ const rowSetSignatureRef = react.useRef(null);
372
+ react.useEffect(() => {
373
+ // The active cell indexes into the current row set; any transition that
374
+ // reshuffles rows would make it point at an arbitrary one. An in-flight
375
+ // edit stops (commit) first. A pending focus request marks an intentional
376
+ // navigation (PageUp/PageDown page flip) - keep the cell it just set.
377
+ const signature = JSON.stringify([
378
+ sortingState, columnFiltersState,
379
+ globalFilterState !== null && globalFilterState !== void 0 ? globalFilterState : '',
380
+ paginationState.pageIndex, paginationState.pageSize
381
+ ]);
382
+ if (rowSetSignatureRef.current === signature) {
383
+ return;
384
+ }
385
+ rowSetSignatureRef.current = signature;
386
+ if (mounted.current) {
387
+ stopEditingRef.current({ commit: true, force: true });
388
+ if (!focusRequestRef.current) {
389
+ setActiveCell(null);
390
+ }
391
+ }
392
+ }, [sortingState, columnFiltersState, globalFilterState, paginationState]);
393
+ react.useEffect(() => {
394
+ mounted.current = true;
395
+ // Reset on unmount, or StrictMode's mount-unmount-remount cycle would fire
396
+ // every change callback once with the initial state.
397
+ return () => {
398
+ mounted.current = false;
399
+ };
400
+ }, []);
401
+ const hasCustomFilterRow = columnFilters && columns$1.some(column => column.filter && column.filterable !== false);
402
+ const headerRowCount = hasCustomFilterRow ? 2 : 1;
403
+ const position = (_p = paginationOptions.position) !== null && _p !== void 0 ? _p : 'bottom';
404
+ const rowCount = table.getRowModel().rows.length;
405
+ const visibleColumnIds = columns.visibleColumns(table, columns$1).map(column => column.key);
406
+ const activeCellContext = () => {
407
+ var _a;
408
+ return ({
409
+ columnIds: visibleColumnIds,
410
+ rowCount,
411
+ pageStep: paginationEnabled ?
412
+ paginationState.pageSize :
413
+ Math.max(1, Math.floor(((_a = viewportElement === null || viewportElement === void 0 ? void 0 : viewportElement.clientHeight) !== null && _a !== void 0 ? _a : 0) / rowHeight) || rowCount),
414
+ paginated: paginationEnabled
415
+ });
416
+ };
417
+ // Clamped for rendering only - the state stays as set and re-clamps as the
418
+ // column set or row count changes.
419
+ const effectiveActiveCell = cellNavigationEnabled ? activeCell.clampActiveCell(activeCell$1, activeCellContext()) : null;
420
+ // With no active cell yet, the first data cell (or first header cell in an
421
+ // empty grid) is the grid's single tab stop.
422
+ const tabStop = cellNavigationEnabled ?
423
+ effectiveActiveCell !== null && effectiveActiveCell !== void 0 ? effectiveActiveCell : (visibleColumnIds.length > 0 ?
424
+ { rowIndex: rowCount > 0 ? 0 : -1, columnId: visibleColumnIds[0] } :
425
+ null) :
426
+ null;
427
+ // Maps an event target to the navigable cell that holds it: a data cell
428
+ // (rowIndex from data-coreui-index) or a header label-row cell (rowIndex
429
+ // -1). Selection cells, the filter row, and grid chrome map to null.
430
+ const navigableCellFromTarget = (target) => {
431
+ const cellElement = target.closest('td, th');
432
+ const tableElement = viewportElement === null || viewportElement === void 0 ? void 0 : viewportElement.querySelector('table');
433
+ if (!cellElement || !(tableElement === null || tableElement === void 0 ? void 0 : tableElement.contains(cellElement))) {
434
+ return null;
435
+ }
436
+ const columnId = cellElement.dataset.coreuiColumn;
437
+ if (!columnId) {
438
+ return null;
439
+ }
440
+ const rowElement = cellElement.closest('tr');
441
+ if (rowElement.closest('tbody')) {
442
+ const index = rowElement.dataset.coreuiIndex;
443
+ if (index === undefined) {
444
+ return null;
445
+ }
446
+ return { cellElement, cell: { rowIndex: Number(index), columnId } };
447
+ }
448
+ const headerElement = rowElement.closest('thead');
449
+ if (headerElement && rowElement === headerElement.querySelector('tr')) {
450
+ return { cellElement, cell: { rowIndex: -1, columnId } };
451
+ }
452
+ return null;
453
+ };
454
+ const requestActiveCell = (cell) => {
455
+ var _a;
456
+ focusRequestRef.current = cell;
457
+ setActiveCell(cell);
458
+ if (virtualizationEnabled && cell.rowIndex >= 0) {
459
+ // No-op when the row is already in view (align: auto); otherwise the
460
+ // focus request stays pending until the row renders.
461
+ (_a = scrollToIndexRef.current) === null || _a === void 0 ? void 0 : _a.call(scrollToIndexRef, cell.rowIndex);
462
+ }
463
+ };
464
+ const isColumnEditable = (column) =>
465
+ // Opt-IN, unlike the opt-out feature booleans - editing is invasive. A
466
+ // custom editor is itself the opt-in.
467
+ editing && (Boolean(column.editor) || column.editable === true || typeof column.editable === 'object');
468
+ const editingCellElement = (session) => {
469
+ var _a;
470
+ return (_a = viewportElement === null || viewportElement === void 0 ? void 0 : viewportElement.querySelector(`tbody tr[data-coreui-index="${session.rowIndex}"] td[data-coreui-column="${session.columnId}"]`)) !== null && _a !== void 0 ? _a : null;
471
+ };
472
+ // The edit scope: the editing cell, its popup layer, and anything the
473
+ // editor claims via contains() (portaled overlays).
474
+ const editScopeContains = (target) => {
475
+ var _a, _b, _c, _d, _e;
476
+ const session = editingCellRef.current;
477
+ if (!target || !session) {
478
+ return false;
479
+ }
480
+ if ((_b = (_a = editorHandleRef.current) === null || _a === void 0 ? void 0 : _a.contains) === null || _b === void 0 ? void 0 : _b.call(_a, target)) {
481
+ return true;
482
+ }
483
+ if ((_d = (_c = rootRef.current) === null || _c === void 0 ? void 0 : _c.querySelector('.data-grid-editor-popup')) === null || _d === void 0 ? void 0 : _d.contains(target)) {
484
+ return true;
485
+ }
486
+ return Boolean((_e = editingCellElement(session)) === null || _e === void 0 ? void 0 : _e.contains(target));
487
+ };
488
+ const finishEdit = (session) => {
489
+ editorHandleRef.current = null;
490
+ setEditingCell(null);
491
+ setEditorInvalid(null);
492
+ setEditorPopupStyle(null);
493
+ const cell = { rowIndex: session.rowIndex, columnId: session.columnId };
494
+ focusRequestRef.current = cell;
495
+ setActiveCell(cell);
496
+ };
497
+ const commitEdit = (value) => {
498
+ var _a;
499
+ const session = editingCellRef.current;
500
+ if (!session) {
501
+ return;
502
+ }
503
+ const validate = (_a = columns$1.find(column => column.key === session.columnId)) === null || _a === void 0 ? void 0 : _a.editValidate;
504
+ if (validate) {
505
+ const result = validate(value, session.item);
506
+ if (result !== true) {
507
+ setEditorInvalid(typeof result === 'string' ? result : '');
508
+ return;
509
+ }
510
+ }
511
+ finishEdit(session);
512
+ if (history) {
513
+ undoStackRef.current.push({
514
+ rowId: session.rowId, columnId: session.columnId, value, previousValue: session.previousValue
515
+ });
516
+ if (undoStackRef.current.length > HISTORY_LIMIT) {
517
+ undoStackRef.current.shift();
518
+ }
519
+ redoStackRef.current = [];
520
+ syncHistoryFlags();
521
+ }
522
+ // The grid never mutates items - the app applies the change and stays
523
+ // the single source of truth.
524
+ onEditCommit === null || onEditCommit === void 0 ? void 0 : onEditCommit({
525
+ item: session.item,
526
+ columnId: session.columnId,
527
+ value,
528
+ previousValue: session.previousValue
529
+ });
530
+ };
531
+ const cancelEdit = () => {
532
+ const session = editingCellRef.current;
533
+ if (!session) {
534
+ return;
535
+ }
536
+ finishEdit(session);
537
+ onEditCancel === null || onEditCancel === void 0 ? void 0 : onEditCancel(session.item, session.columnId);
538
+ };
539
+ const stopEditing = (options) => {
540
+ var _a;
541
+ const session = editingCellRef.current;
542
+ if (!session) {
543
+ return;
544
+ }
545
+ const getValue = (_a = editorHandleRef.current) === null || _a === void 0 ? void 0 : _a.getValue;
546
+ if (options.commit && (getValue || editorDraftRef.current)) {
547
+ commitEdit(getValue ? getValue() : editorDraftRef.current.value);
548
+ // An invalid value blocks the commit; when the edit cannot survive
549
+ // anyway (row recycled away, row set changed), drop the draft.
550
+ if (editingCellRef.current && options.force) {
551
+ cancelEdit();
552
+ }
553
+ return;
554
+ }
555
+ // A custom editor without getValue owns its commits - stopping from the
556
+ // outside can only cancel.
557
+ cancelEdit();
558
+ };
559
+ const stopEditingRef = react.useRef(stopEditing);
560
+ stopEditingRef.current = stopEditing;
561
+ const startEditing = (cell) => {
562
+ var _a;
563
+ const config = columns$1.find(column => column.key === cell.columnId);
564
+ if (!config || !isColumnEditable(config)) {
565
+ return;
566
+ }
567
+ stopEditing({ commit: true, force: true });
568
+ const row = table.getRowModel().rows[cell.rowIndex];
569
+ if (!row) {
570
+ return;
571
+ }
572
+ const session = {
573
+ rowId: row.id,
574
+ columnId: cell.columnId,
575
+ rowIndex: cell.rowIndex,
576
+ item: row.original,
577
+ previousValue: row.getValue(cell.columnId)
578
+ };
579
+ if (config.editorPopup) {
580
+ const cellElement = editingCellElement(session);
581
+ const rootRect = (_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
582
+ const cellRect = cellElement === null || cellElement === void 0 ? void 0 : cellElement.getBoundingClientRect();
583
+ setEditorPopupStyle(cellRect && rootRect ?
584
+ { top: cellRect.top - rootRect.top, left: cellRect.left - rootRect.left, minWidth: cellRect.width } :
585
+ { top: 0, left: 0, minWidth: 0 });
586
+ }
587
+ editorFocusPendingRef.current = true;
588
+ setEditorInvalid(null);
589
+ setEditingCell(session);
590
+ onEditStart === null || onEditStart === void 0 ? void 0 : onEditStart(row.original, cell.columnId);
591
+ };
592
+ const moveEditing = (direction) => {
593
+ const session = editingCellRef.current;
594
+ if (!session) {
595
+ return;
596
+ }
597
+ const visible = columns.visibleColumns(table, columns$1);
598
+ const currentIndex = visible.findIndex(column => column.key === session.columnId);
599
+ let next = null;
600
+ for (let index = currentIndex + direction; index >= 0 && index < visible.length; index += direction) {
601
+ if (isColumnEditable(visible[index])) {
602
+ next = visible[index];
603
+ break;
604
+ }
605
+ }
606
+ stopEditing({ commit: true });
607
+ if (editingCellRef.current) {
608
+ // An invalid value blocked the commit - stay.
609
+ return;
610
+ }
611
+ if (next) {
612
+ const cell = { rowIndex: session.rowIndex, columnId: next.key };
613
+ requestActiveCell(cell);
614
+ startEditing(cell);
615
+ }
616
+ };
617
+ const snapshotState = () => ({
618
+ columnFilters: columnFiltersState,
619
+ columnOrder: columnOrderState,
620
+ columnPinning: columnPinningState,
621
+ columnSizing: columnSizingState,
622
+ columnVisibility: columnVisibilityState,
623
+ globalFilter: globalFilterState !== null && globalFilterState !== void 0 ? globalFilterState : '',
624
+ pagination: paginationState,
625
+ rowSelection: rowSelectionState,
626
+ sorting: sortingState
627
+ });
628
+ // stateKey persistence is automatic - every state change (debounced)
629
+ // rewrites the snapshot, so the view survives a reload.
630
+ const persistTimeoutRef = react.useRef(undefined);
631
+ react.useEffect(() => {
632
+ if (!stateKey || !mounted.current) {
633
+ return;
634
+ }
635
+ clearTimeout(persistTimeoutRef.current);
636
+ persistTimeoutRef.current = setTimeout(() => {
637
+ try {
638
+ window.localStorage.setItem(`${STATE_STORAGE_PREFIX}${stateKey}`, JSON.stringify(snapshotState()));
639
+ }
640
+ catch (_a) {
641
+ // Quota/privacy-mode failures degrade to a non-persistent grid.
642
+ }
643
+ }, 250);
644
+ return () => clearTimeout(persistTimeoutRef.current);
645
+ // eslint-disable-next-line react-hooks/exhaustive-deps
646
+ }, [
647
+ sortingState,
648
+ columnFiltersState,
649
+ globalFilterState,
650
+ columnOrderState,
651
+ columnPinningState,
652
+ columnSizingState,
653
+ columnVisibilityState,
654
+ paginationState,
655
+ rowSelectionState,
656
+ stateKey
657
+ ]);
658
+ // Undo/redo of edit commits. Entries hold the ROW ID, not the item
659
+ // reference - an immutable app replaces the object on every commit, so
660
+ // undo/redo resolve the current item at emit time.
661
+ const undoStackRef = react.useRef([]);
662
+ const redoStackRef = react.useRef([]);
663
+ const [canUndo, setCanUndo] = react.useState(false);
664
+ const [canRedo, setCanRedo] = react.useState(false);
665
+ const syncHistoryFlags = () => {
666
+ setCanUndo(undoStackRef.current.length > 0);
667
+ setCanRedo(redoStackRef.current.length > 0);
668
+ };
669
+ const applyHistoryEntry = (from, to, inverted) => {
670
+ const entry = from.pop();
671
+ if (!entry) {
672
+ return;
673
+ }
674
+ // The row may be gone (data replaced without it) - drop the entry.
675
+ const row = table.getCoreRowModel().rowsById[entry.rowId];
676
+ if (!row) {
677
+ syncHistoryFlags();
678
+ return;
679
+ }
680
+ to.push(entry);
681
+ onEditCommit === null || onEditCommit === void 0 ? void 0 : onEditCommit({
682
+ item: row.original,
683
+ columnId: entry.columnId,
684
+ value: inverted ? entry.previousValue : entry.value,
685
+ previousValue: inverted ? entry.value : entry.previousValue
686
+ });
687
+ setAnnouncement(inverted ? mergedLabels.undoneAnnouncement : mergedLabels.redoneAnnouncement);
688
+ syncHistoryFlags();
689
+ };
690
+ const undo = () => applyHistoryEntry(undoStackRef.current, redoStackRef.current, true);
691
+ const redo = () => applyHistoryEntry(redoStackRef.current, undoStackRef.current, false);
692
+ // Commit on pointerdown outside the edit scope - blur alone cannot commit,
693
+ // picking a date in a calendar blurs the input mid-edit.
694
+ react.useEffect(() => {
695
+ if (!editingCell) {
696
+ return;
697
+ }
698
+ const handler = (event) => {
699
+ if (!editScopeContains(event.target)) {
700
+ stopEditingRef.current({ commit: true });
701
+ }
702
+ };
703
+ document.addEventListener('pointerdown', handler);
704
+ return () => document.removeEventListener('pointerdown', handler);
705
+ // eslint-disable-next-line react-hooks/exhaustive-deps
706
+ }, [editingCell]);
707
+ // The editor mounts during the body render - focus it right after (the
708
+ // child effect registering the handle runs before this one).
709
+ react.useEffect(() => {
710
+ var _a, _b;
711
+ if (editingCell && editorFocusPendingRef.current) {
712
+ editorFocusPendingRef.current = false;
713
+ (_b = (_a = editorHandleRef.current) === null || _a === void 0 ? void 0 : _a.focus) === null || _b === void 0 ? void 0 : _b.call(_a);
714
+ }
715
+ }, [editingCell]);
716
+ const handleEditingDoubleClick = (event) => {
717
+ if (!editing) {
718
+ return;
719
+ }
720
+ const found = navigableCellFromTarget(event.target);
721
+ if (found && found.cell.rowIndex >= 0) {
722
+ setActiveCell(found.cell);
723
+ startEditing(found.cell);
724
+ }
725
+ };
726
+ const handleNavigationFocus = (event) => {
727
+ containsFocusRef.current = true;
728
+ if (!cellNavigationEnabled) {
729
+ return;
730
+ }
731
+ const found = navigableCellFromTarget(event.target);
732
+ if (found) {
733
+ // The browser already moved focus (click, descend) - only sync state.
734
+ setActiveCell(found.cell);
735
+ }
736
+ };
737
+ const handleNavigationBlur = (event) => {
738
+ var _a;
739
+ const related = event.relatedTarget;
740
+ if (!related || !((_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.contains(related))) {
741
+ containsFocusRef.current = false;
742
+ }
743
+ };
744
+ const handleNavigationKeydown = (event) => {
745
+ var _a, _b, _c, _d;
746
+ if (!cellNavigationEnabled) {
747
+ return;
748
+ }
749
+ const target = event.target;
750
+ // Ctrl/Cmd+Z / Ctrl+Shift+Z / Ctrl+Y - edit history (MUI/AG parity).
751
+ if (history &&
752
+ (event.ctrlKey || event.metaKey) &&
753
+ !editingCellRef.current &&
754
+ !target.matches('input, textarea, select')) {
755
+ const key = event.key.toLowerCase();
756
+ if (key === 'z' && !event.shiftKey) {
757
+ event.preventDefault();
758
+ undo();
759
+ return;
760
+ }
761
+ if ((key === 'z' && event.shiftKey) || key === 'y') {
762
+ event.preventDefault();
763
+ redo();
764
+ return;
765
+ }
766
+ }
767
+ if (editingCellRef.current && editScopeContains(target)) {
768
+ // A defaultPrevented key was consumed by the editor (a rich editor
769
+ // closing its own overlay on Escape, an autocomplete accepting on
770
+ // Enter) - one key, one layer.
771
+ if (event.key === 'Enter') {
772
+ if (!event.defaultPrevented) {
773
+ event.preventDefault();
774
+ stopEditing({ commit: true });
775
+ }
776
+ return;
777
+ }
778
+ if (event.key === 'Escape') {
779
+ if (!event.defaultPrevented) {
780
+ cancelEdit();
781
+ }
782
+ return;
783
+ }
784
+ if (event.key === 'Tab') {
785
+ event.preventDefault();
786
+ moveEditing(event.shiftKey ? -1 : 1);
787
+ return;
788
+ }
789
+ // Everything else (arrows, typing) stays native inside the editor.
790
+ return;
791
+ }
792
+ // Focus fell back to the viewport after the active row was recycled out
793
+ // of the window: any navigation key scrolls the active cell back in view
794
+ // and refocuses it.
795
+ if (target === viewportElement) {
796
+ if (effectiveActiveCell && event.key !== 'Tab') {
797
+ event.preventDefault();
798
+ requestActiveCell(effectiveActiveCell);
799
+ }
800
+ return;
801
+ }
802
+ const found = navigableCellFromTarget(target);
803
+ if (!found) {
804
+ return;
805
+ }
806
+ if (target !== found.cellElement) {
807
+ // Focus is descended into the cell's content; Escape ascends back.
808
+ if (event.key === 'Escape') {
809
+ found.cellElement.focus({ preventScroll: true });
810
+ }
811
+ return;
812
+ }
813
+ if (event.key === 'Enter' || event.key === 'F2') {
814
+ event.preventDefault();
815
+ const config = columns$1.find(column => column.key === found.cell.columnId);
816
+ if (found.cell.rowIndex === -1) {
817
+ if (event.key === 'Enter' && config && isColumnSortable(config)) {
818
+ (_b = (_a = table.getColumn(found.cell.columnId)) === null || _a === void 0 ? void 0 : _a.getToggleSortingHandler()) === null || _b === void 0 ? void 0 : _b(event);
819
+ }
820
+ return;
821
+ }
822
+ if (config && isColumnEditable(config)) {
823
+ startEditing(found.cell);
824
+ return;
825
+ }
826
+ if (event.key === 'Enter') {
827
+ (_c = found.cellElement
828
+ .querySelector('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]')) === null || _c === void 0 ? void 0 : _c.focus({ preventScroll: true });
829
+ }
830
+ return;
831
+ }
832
+ if (event.key === ' ') {
833
+ if (selectionEnabled && found.cell.rowIndex >= 0) {
834
+ event.preventDefault();
835
+ (_d = table.getRowModel().rows[found.cell.rowIndex]) === null || _d === void 0 ? void 0 : _d.toggleSelected();
836
+ }
837
+ return;
838
+ }
839
+ const result = activeCell.resolveNavigation(event.key, event.ctrlKey || event.metaKey, found.cell, activeCellContext());
840
+ if (!result) {
841
+ return;
842
+ }
843
+ event.preventDefault();
844
+ if (result.pageDelta === 1 && table.getCanNextPage()) {
845
+ table.nextPage();
846
+ }
847
+ else if (result.pageDelta === -1 && table.getCanPreviousPage()) {
848
+ table.previousPage();
849
+ }
850
+ requestActiveCell(result.cell);
851
+ };
852
+ const ToolbarSlot = slots === null || slots === void 0 ? void 0 : slots.toolbar;
853
+ const PaginationSlot = slots === null || slots === void 0 ? void 0 : slots.pagination;
854
+ const EmptySlot = slots === null || slots === void 0 ? void 0 : slots.empty;
855
+ const paginationElement = (paginationPosition) => {
856
+ var _a, _b;
857
+ return PaginationSlot ?
858
+ (jsxRuntime.jsx(PaginationSlot, { table: table, labels: mergedLabels })) :
859
+ (jsxRuntime.jsx(CDataGridPagination.CDataGridPagination, { info: (_a = paginationOptions.info) !== null && _a !== void 0 ? _a : true, labels: mergedLabels, pageSizeOptions: (_b = paginationOptions.pageSizeOptions) !== null && _b !== void 0 ? _b : DEFAULT_PAGE_SIZE_OPTIONS, position: paginationPosition, table: table, totalRows: totalRows }));
860
+ };
861
+ const emptyContent = EmptySlot ?
862
+ jsxRuntime.jsx(EmptySlot, { table: table, labels: mergedLabels }) :
863
+ (loadFailed ? mergedLabels.loadError : empty);
864
+ const editingConfig = editingCell ?
865
+ (_q = columns$1.find(column => column.key === editingCell.columnId)) !== null && _q !== void 0 ? _q : null :
866
+ null;
867
+ const EditorComponent = (_r = editingConfig === null || editingConfig === void 0 ? void 0 : editingConfig.editor) !== null && _r !== void 0 ? _r : CDataGridCellEditor.CDataGridCellEditor;
868
+ const editorSession = editingCell && editingConfig ?
869
+ {
870
+ rowId: editingCell.rowId,
871
+ columnId: editingCell.columnId,
872
+ rowIndex: editingCell.rowIndex,
873
+ popup: Boolean(editingConfig.editorPopup),
874
+ render: () => (jsxRuntime.jsx(EditorComponent, { cancel: cancelEdit, column: editingConfig, commit: commitEdit, handleRef: registerEditorHandle, invalid: editorInvalid, item: editingCell.item, labels: mergedLabels, value: editingCell.previousValue })),
875
+ // Blur commits (inline editors) unless focus moved within the edit
876
+ // scope - the outside-pointerdown listener covers pointer-only flows.
877
+ onBlur(event) {
878
+ const related = event.relatedTarget;
879
+ if (related && !editScopeContains(related)) {
880
+ stopEditingRef.current({ commit: true });
881
+ }
882
+ },
883
+ onHidden: () => stopEditingRef.current({ commit: true, force: true })
884
+ } :
885
+ null;
886
+ return (jsxRuntime.jsxs("div", { className: `data-grid${sizingEnabled ? ' data-grid-resizable' : ''}${pinningEnabled ? ' data-grid-pinned' : ''}${className ? ` ${className}` : ''}`, "data-coreui-sorter-visibility": sorterVisibility || undefined, ref: setRootRef, ...rest, children: [jsxRuntime.jsx("div", { className: "visually-hidden", "aria-live": "polite", children: announcement }), ToolbarSlot ?
887
+ jsxRuntime.jsx(ToolbarSlot, { table: table, labels: mergedLabels }) :
888
+ (resolvedToolbar.columns || resolvedToolbar.export || resolvedToolbar.search || resolvedToolbar.history) && (jsxRuntime.jsx(CDataGridToolbar.CDataGridToolbar, { columns: columns$1, columnsIcon: toolbarColumnsIcon, container: rootRef, export: resolvedToolbar.export, exportIcon: toolbarExportIcon, exportOptions: resolvedToolbar.exportOptions, initialVisibility: initialColumnVisibility.current, labels: mergedLabels, canRedo: canRedo, canUndo: canUndo, onRedo: redo, onUndo: undo, redoIcon: toolbarRedoIcon, search: resolvedToolbar.search, searchValue: globalFilterState !== null && globalFilterState !== void 0 ? globalFilterState : '', showColumns: resolvedToolbar.columns, showHistory: resolvedToolbar.history, undoIcon: toolbarUndoIcon, table: table })), paginationEnabled && (position === 'top' || position === 'both') && paginationElement('top'), jsxRuntime.jsxs("div", { className: "data-grid-viewport", ref: setViewportElement, ...(serverSide && { 'aria-busy': loading }), ...(cellNavigationEnabled && {
889
+ // Focus parks here when the focused row is recycled out of the
890
+ // window; the keydown fallback then scrolls the active cell back.
891
+ tabIndex: -1,
892
+ onBlur: handleNavigationBlur,
893
+ onFocus: handleNavigationFocus,
894
+ onKeyDown: handleNavigationKeydown
895
+ }), ...(editing && { onDoubleClick: handleEditingDoubleClick }), children: [jsxRuntime.jsxs("table", { className: "table", "aria-rowcount": headerRowCount + totalRows, ...(cellNavigationEnabled && {
896
+ role: 'grid',
897
+ 'aria-colcount': visibleColumnIds.length + (selectionEnabled ? 1 : 0)
898
+ }), children: [jsxRuntime.jsx(CDataGridHeader.CDataGridHeader, { cellNavigation: cellNavigationEnabled, columnFilters: columnFilters, columns: columns$1, draggable: Boolean(columnOrder), icons: menuIcons, isFilterable: isColumnFilterable, isResizable: isColumnResizable, isSortable: isColumnSortable, labels: mergedLabels, menu: Boolean(columnMenu), menuBuilder: menuBuilder, menuContainer: rootRef, pinning: pinningEnabled, resizable: sizingEnabled, selectAll: selectionEnabled && selectionOptions.selectAll !== false, selection: selectionEnabled, tabStop: tabStop, table: table, visibility: Boolean(columnVisibility) }), jsxRuntime.jsx(CDataGridBody.CDataGridBody, { cellNavigation: cellNavigationEnabled, columns: columns$1, containsFocusRef: containsFocusRef, editorSession: editorSession, empty: emptyContent, focusRequestRef: focusRequestRef, headerRowCount: headerRowCount, labels: mergedLabels, overscan: overscan, pinning: pinningEnabled, rowHeight: rowHeight, rowIndexOffset: paginationEnabled ? paginationState.pageIndex * paginationState.pageSize : 0, scrollElement: viewportElement, scrollToIndexRef: scrollToIndexRef, selection: selectionEnabled, tabStop: tabStop, table: table, virtualization: virtualizationEnabled })] }), serverSide && (jsxRuntime.jsx("div", { className: "data-grid-loading", hidden: !loading, children: jsxRuntime.jsx("div", { className: "spinner-border", role: "status", children: jsxRuntime.jsx("span", { className: "visually-hidden", children: mergedLabels.loading }) }) }))] }), (editorSession === null || editorSession === void 0 ? void 0 : editorSession.popup) && (jsxRuntime.jsx("div", { className: "data-grid-editor-popup", style: editorPopupStyle !== null && editorPopupStyle !== void 0 ? editorPopupStyle : undefined, onBlur: editorSession.onBlur, onKeyDown: handleNavigationKeydown, children: editorSession.render() })), paginationEnabled && (position === 'bottom' || position === 'both') && paginationElement('bottom')] }));
899
+ });
900
+ CDataGrid.displayName = 'CDataGrid';
901
+
902
+ exports.CDataGrid = CDataGrid;
903
+ //# sourceMappingURL=CDataGrid.js.map