@coreui/react-data-grid 0.1.0-rc.0 → 0.3.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 (88) hide show
  1. package/README.md +9 -5
  2. package/dist/cjs/CDataGrid.d.ts +11 -1
  3. package/dist/cjs/CDataGrid.js +241 -46
  4. package/dist/cjs/CDataGrid.js.map +1 -1
  5. package/dist/cjs/CDataGridBody.d.ts +9 -4
  6. package/dist/cjs/CDataGridBody.js +54 -11
  7. package/dist/cjs/CDataGridBody.js.map +1 -1
  8. package/dist/cjs/CDataGridColumnChooser.d.ts +2 -3
  9. package/dist/cjs/CDataGridColumnChooser.js.map +1 -1
  10. package/dist/cjs/CDataGridFilterMenu.d.ts +2 -3
  11. package/dist/cjs/CDataGridFilterMenu.js.map +1 -1
  12. package/dist/cjs/CDataGridHeader.d.ts +4 -4
  13. package/dist/cjs/CDataGridHeader.js +31 -67
  14. package/dist/cjs/CDataGridHeader.js.map +1 -1
  15. package/dist/cjs/CDataGridHeaderMenu.d.ts +2 -3
  16. package/dist/cjs/CDataGridHeaderMenu.js.map +1 -1
  17. package/dist/cjs/CDataGridPagination.d.ts +2 -3
  18. package/dist/cjs/CDataGridPagination.js +1 -1
  19. package/dist/cjs/CDataGridPagination.js.map +1 -1
  20. package/dist/cjs/CDataGridToolbar.d.ts +8 -6
  21. package/dist/cjs/CDataGridToolbar.js +7 -2
  22. package/dist/cjs/CDataGridToolbar.js.map +1 -1
  23. package/dist/cjs/active-cell.d.ts +1 -0
  24. package/dist/cjs/active-cell.js +7 -3
  25. package/dist/cjs/active-cell.js.map +1 -1
  26. package/dist/cjs/columns.d.ts +38 -12
  27. package/dist/cjs/columns.js +51 -31
  28. package/dist/cjs/columns.js.map +1 -1
  29. package/dist/cjs/features.d.ts +52 -0
  30. package/dist/cjs/features.js +66 -0
  31. package/dist/cjs/features.js.map +1 -0
  32. package/dist/cjs/icons.d.ts +6 -4
  33. package/dist/cjs/icons.js +12 -8
  34. package/dist/cjs/icons.js.map +1 -1
  35. package/dist/cjs/index.d.ts +2 -1
  36. package/dist/cjs/index.js +3 -0
  37. package/dist/cjs/index.js.map +1 -1
  38. package/dist/cjs/pinning.d.ts +4 -5
  39. package/dist/cjs/pinning.js +10 -8
  40. package/dist/cjs/pinning.js.map +1 -1
  41. package/dist/cjs/toolbar.d.ts +3 -2
  42. package/dist/cjs/toolbar.js +5 -2
  43. package/dist/cjs/toolbar.js.map +1 -1
  44. package/dist/cjs/types.d.ts +81 -29
  45. package/dist/esm/CDataGrid.d.ts +11 -1
  46. package/dist/esm/CDataGrid.mjs +244 -49
  47. package/dist/esm/CDataGrid.mjs.map +1 -1
  48. package/dist/esm/CDataGridBody.d.ts +9 -4
  49. package/dist/esm/CDataGridBody.mjs +55 -12
  50. package/dist/esm/CDataGridBody.mjs.map +1 -1
  51. package/dist/esm/CDataGridColumnChooser.d.ts +2 -3
  52. package/dist/esm/CDataGridColumnChooser.mjs.map +1 -1
  53. package/dist/esm/CDataGridFilterMenu.d.ts +2 -3
  54. package/dist/esm/CDataGridFilterMenu.mjs.map +1 -1
  55. package/dist/esm/CDataGridHeader.d.ts +4 -4
  56. package/dist/esm/CDataGridHeader.mjs +33 -69
  57. package/dist/esm/CDataGridHeader.mjs.map +1 -1
  58. package/dist/esm/CDataGridHeaderMenu.d.ts +2 -3
  59. package/dist/esm/CDataGridHeaderMenu.mjs.map +1 -1
  60. package/dist/esm/CDataGridPagination.d.ts +2 -3
  61. package/dist/esm/CDataGridPagination.mjs +1 -1
  62. package/dist/esm/CDataGridPagination.mjs.map +1 -1
  63. package/dist/esm/CDataGridToolbar.d.ts +8 -6
  64. package/dist/esm/CDataGridToolbar.mjs +7 -2
  65. package/dist/esm/CDataGridToolbar.mjs.map +1 -1
  66. package/dist/esm/active-cell.d.ts +1 -0
  67. package/dist/esm/active-cell.mjs +7 -3
  68. package/dist/esm/active-cell.mjs.map +1 -1
  69. package/dist/esm/columns.d.ts +38 -12
  70. package/dist/esm/columns.mjs +51 -32
  71. package/dist/esm/columns.mjs.map +1 -1
  72. package/dist/esm/features.d.ts +52 -0
  73. package/dist/esm/features.mjs +63 -0
  74. package/dist/esm/features.mjs.map +1 -0
  75. package/dist/esm/icons.d.ts +6 -4
  76. package/dist/esm/icons.mjs +7 -5
  77. package/dist/esm/icons.mjs.map +1 -1
  78. package/dist/esm/index.d.ts +2 -1
  79. package/dist/esm/index.mjs +1 -0
  80. package/dist/esm/index.mjs.map +1 -1
  81. package/dist/esm/pinning.d.ts +4 -5
  82. package/dist/esm/pinning.mjs +10 -8
  83. package/dist/esm/pinning.mjs.map +1 -1
  84. package/dist/esm/toolbar.d.ts +3 -2
  85. package/dist/esm/toolbar.mjs +5 -2
  86. package/dist/esm/toolbar.mjs.map +1 -1
  87. package/dist/esm/types.d.ts +81 -29
  88. package/package.json +6 -6
@@ -1,6 +1,11 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { evaluateColumnFilter } from '@coreui/data-grid/filters';
3
- import { useReactTable, getPaginationRowModel, getSortedRowModel, getFilteredRowModel, getFacetedUniqueValues, getFacetedRowModel, getCoreRowModel } from '@tanstack/react-table';
3
+ import { copyCellSelection } from '@coreui/data-grid/clipboard';
4
+ import { printGrid } from '@coreui/data-grid/print';
5
+ import { isElementRTL } from '@coreui/data-grid/direction';
6
+ import { createColumnDragController, createRowDragController } from '@coreui/data-grid/drag';
7
+ import { assertFeatureCoverage } from '@coreui/data-grid/validate';
8
+ import { useTable } from '@tanstack/react-table';
4
9
  import { forwardRef, useMemo, useRef, useState, useCallback, useEffect } from 'react';
5
10
  import { clampActiveCell, resolveNavigation } from './active-cell.mjs';
6
11
  import { CDataGridBody } from './CDataGridBody.mjs';
@@ -8,8 +13,9 @@ import { CDataGridCellEditor } from './CDataGridCellEditor.mjs';
8
13
  import { CDataGridHeader } from './CDataGridHeader.mjs';
9
14
  import { CDataGridPagination } from './CDataGridPagination.mjs';
10
15
  import { CDataGridToolbar } from './CDataGridToolbar.mjs';
11
- import { visibleColumns } from './columns.mjs';
12
- import { DEFAULT_COLUMN_MENU_ICON, DEFAULT_FILTER_ICON, DEFAULT_HIDE_COLUMN_ICON, DEFAULT_MOVE_LEFT_ICON, DEFAULT_MOVE_RIGHT_ICON, DEFAULT_PIN_LEFT_ICON, DEFAULT_PIN_RIGHT_ICON, DEFAULT_SORT_ASCENDING_ICON, DEFAULT_SORT_DESCENDING_ICON, DEFAULT_SORT_NEUTRAL_ICON, DEFAULT_TOOLBAR_COLUMNS_ICON, DEFAULT_TOOLBAR_EXPORT_ICON, DEFAULT_TOOLBAR_REDO_ICON, DEFAULT_TOOLBAR_UNDO_ICON, DEFAULT_UNPIN_ICON } from './icons.mjs';
16
+ import { reorderColumn, canReorderColumn, visibleColumns } from './columns.mjs';
17
+ import { dataGridFeatures } from './features.mjs';
18
+ import { DEFAULT_COLUMN_MENU_ICON, DEFAULT_FILTER_ICON, DEFAULT_HIDE_COLUMN_ICON, DEFAULT_MOVE_START_ICON, DEFAULT_MOVE_END_ICON, DEFAULT_PIN_START_ICON, DEFAULT_PIN_END_ICON, DEFAULT_ROW_HANDLE_ICON, DEFAULT_SORT_ASCENDING_ICON, DEFAULT_SORT_DESCENDING_ICON, DEFAULT_SORT_NEUTRAL_ICON, DEFAULT_TOOLBAR_COLUMNS_ICON, DEFAULT_TOOLBAR_EXPORT_ICON, DEFAULT_TOOLBAR_PRINT_ICON, DEFAULT_TOOLBAR_REDO_ICON, DEFAULT_TOOLBAR_UNDO_ICON, DEFAULT_UNPIN_ICON } from './icons.mjs';
13
19
  import { DEFAULT_LABELS, interpolate } from '@coreui/data-grid/labels';
14
20
  import { resolveToolbar } from './toolbar.mjs';
15
21
  import { createTooltip } from './tooltip.mjs';
@@ -17,6 +23,8 @@ import { createTooltip } from './tooltip.mjs';
17
23
  const DEFAULT_PAGE_SIZE_OPTIONS = [5, 10, 20, 50];
18
24
  const STATE_STORAGE_PREFIX = 'coreui-data-grid:';
19
25
  const HISTORY_LIMIT = 100;
26
+ const INFINITE_SCROLL_PAGE_SIZE = 50;
27
+ const UNPAGINATED_PAGE_SIZE = Number.MAX_SAFE_INTEGER;
20
28
  const readPersistedState = (stateKey) => {
21
29
  if (!stateKey) {
22
30
  return null;
@@ -29,6 +37,17 @@ const readPersistedState = (stateKey) => {
29
37
  return null;
30
38
  }
31
39
  };
40
+ // Under RTL the two horizontal keys point at the opposite logical neighbour.
41
+ const INVERTED_ARROWS = {
42
+ ArrowLeft: 'ArrowRight',
43
+ ArrowRight: 'ArrowLeft'
44
+ };
45
+ const CELL_SELECTION_DIRECTIONS = {
46
+ ArrowDown: 'down',
47
+ ArrowLeft: 'left',
48
+ ArrowRight: 'right',
49
+ ArrowUp: 'up'
50
+ };
32
51
  const FETCH_DEBOUNCE_MS = 100;
33
52
  // Module-level so an omitted `items` prop keeps a stable identity - a fresh
34
53
  // array per render would force TanStack to recompute row models every time.
@@ -41,17 +60,17 @@ const toTanStackFilterFn = (column) => {
41
60
  return (row, columnId, filterValue) => evaluateColumnFilter(row.getValue(columnId), filterValue, column.filterType);
42
61
  };
43
62
  const CDataGrid = forwardRef((props, ref) => {
44
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
45
- const { cellNavigation = false, className, columnFilters = false, columnMenu = false, columnMenuIcon = DEFAULT_COLUMN_MENU_ICON, columnOrder = false, columnPinning = false, columnSizing = false, columnVisibility = false, columns, dataProvider, editing = false, empty = 'No items found', filterIcon = DEFAULT_FILTER_ICON, globalFilter = false, hideColumnIcon = DEFAULT_HIDE_COLUMN_ICON, history = false, itemKey, items = EMPTY_ITEMS, labels, moveLeftIcon = DEFAULT_MOVE_LEFT_ICON, moveRightIcon = DEFAULT_MOVE_RIGHT_ICON, onDataError, onDataLoad, onEditCancel, onEditCommit, onEditStart, onFilterChange, onOrderChange, onPaginationChange, onPinningChange, onSelectionChange, onSizingChange, onSortingChange, onVisibilityChange, overscan = 10, pagination = false, pinLeftIcon = DEFAULT_PIN_LEFT_ICON, pinRightIcon = DEFAULT_PIN_RIGHT_ICON, rowHeight = 44, rowSelection = false, slots, sortAscendingIcon = DEFAULT_SORT_ASCENDING_ICON, sortDescendingIcon = DEFAULT_SORT_DESCENDING_ICON, sortNeutralIcon = DEFAULT_SORT_NEUTRAL_ICON, sorterVisibility, sorting = true, stateKey, tableRef, toolbar = false, toolbarColumnsIcon = DEFAULT_TOOLBAR_COLUMNS_ICON, toolbarExportIcon = DEFAULT_TOOLBAR_EXPORT_ICON, toolbarRedoIcon = DEFAULT_TOOLBAR_REDO_ICON, toolbarUndoIcon = DEFAULT_TOOLBAR_UNDO_ICON, unpinIcon = DEFAULT_UNPIN_ICON, virtualization = true, ...rest } = props;
63
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
64
+ const { autoRowHeight = false, cellNavigation = false, cellSelection = false, className, columnFilters = false, columnMenu = false, columnMenuIcon = DEFAULT_COLUMN_MENU_ICON, columnOrder = false, columnPinning = false, columnSizing = false, columnVisibility = false, columns, dataProvider, editing = false, empty = 'No items found', features = dataGridFeatures, filterIcon = DEFAULT_FILTER_ICON, globalFilter = false, hideColumnIcon = DEFAULT_HIDE_COLUMN_ICON, history = false, infiniteScroll = false, itemKey, items = EMPTY_ITEMS, labels, moveStartIcon = DEFAULT_MOVE_START_ICON, moveEndIcon = DEFAULT_MOVE_END_ICON, onDataError, onDataLoad, onEditCancel, onEditCommit, onEditStart, onFilterChange, onOrderChange, onPaginationChange, onPinningChange, onSelectionChange, onRowOrderChange, onCellCopy, onSizingChange, onSortingChange, onVisibilityChange, overscan = 10, pagination = false, pinStartIcon = DEFAULT_PIN_START_ICON, pinEndIcon = DEFAULT_PIN_END_ICON, rowHandleIcon = DEFAULT_ROW_HANDLE_ICON, rowHeight = 44, rowOrder = false, rowSelection = false, slots, sortAscendingIcon = DEFAULT_SORT_ASCENDING_ICON, sortDescendingIcon = DEFAULT_SORT_DESCENDING_ICON, sortNeutralIcon = DEFAULT_SORT_NEUTRAL_ICON, sorterVisibility, sorting = true, stateKey, tableRef, toolbar = false, toolbarColumnsIcon = DEFAULT_TOOLBAR_COLUMNS_ICON, printTitle, toolbarExportIcon = DEFAULT_TOOLBAR_EXPORT_ICON, toolbarPrintIcon = DEFAULT_TOOLBAR_PRINT_ICON, toolbarRedoIcon = DEFAULT_TOOLBAR_REDO_ICON, toolbarUndoIcon = DEFAULT_TOOLBAR_UNDO_ICON, unpinIcon = DEFAULT_UNPIN_ICON, virtualization = true, ...rest } = props;
46
65
  const mergedLabels = useMemo(() => ({ ...DEFAULT_LABELS, ...labels }), [labels]);
47
66
  const menuIcons = useMemo(() => ({
48
67
  columnMenu: columnMenuIcon,
49
68
  filter: filterIcon,
50
69
  hideColumn: hideColumnIcon,
51
- moveLeft: moveLeftIcon,
52
- moveRight: moveRightIcon,
53
- pinLeft: pinLeftIcon,
54
- pinRight: pinRightIcon,
70
+ moveStart: moveStartIcon,
71
+ moveEnd: moveEndIcon,
72
+ pinStart: pinStartIcon,
73
+ pinEnd: pinEndIcon,
55
74
  sortAscending: sortAscendingIcon,
56
75
  sortDescending: sortDescendingIcon,
57
76
  sortNeutral: sortNeutralIcon,
@@ -60,18 +79,19 @@ const CDataGrid = forwardRef((props, ref) => {
60
79
  columnMenuIcon,
61
80
  filterIcon,
62
81
  hideColumnIcon,
63
- moveLeftIcon,
64
- moveRightIcon,
65
- pinLeftIcon,
66
- pinRightIcon,
82
+ moveStartIcon,
83
+ moveEndIcon,
84
+ pinStartIcon,
85
+ pinEndIcon,
67
86
  sortAscendingIcon,
68
87
  sortDescendingIcon,
69
88
  sortNeutralIcon,
70
89
  unpinIcon
71
90
  ]);
72
91
  const menuBuilder = typeof columnMenu === 'function' ? columnMenu : null;
73
- // Editing needs the active-cell substrate (Enter/F2 target the active cell).
74
- const cellNavigationEnabled = cellNavigation || editing;
92
+ // Both need the active-cell substrate: editing targets it with Enter/F2,
93
+ // cell selection anchors ranges on it.
94
+ const cellNavigationEnabled = cellNavigation || editing || cellSelection;
75
95
  const sortingOptions = typeof sorting === 'object' ? sorting : {};
76
96
  const sizingEnabled = Boolean(columnSizing);
77
97
  const sizingOptions = typeof columnSizing === 'object' ? columnSizing : {};
@@ -80,9 +100,23 @@ const CDataGrid = forwardRef((props, ref) => {
80
100
  const selectionEnabled = Boolean(rowSelection);
81
101
  const selectionOptions = typeof rowSelection === 'object' ? rowSelection : {};
82
102
  const serverSide = Boolean(dataProvider);
83
- // Server-side mode implies pagination — virtualized infinite scroll over a
84
- // dataProvider is out of scope until 0.3.0.
85
- const paginationEnabled = Boolean(pagination) || serverSide;
103
+ if (infiniteScroll) {
104
+ if (!serverSide) {
105
+ throw new TypeError('DATA-GRID: Option "infiniteScroll" requires "dataProvider".');
106
+ }
107
+ if (pagination) {
108
+ throw new TypeError('DATA-GRID: Option "infiniteScroll" cannot be combined with "pagination".');
109
+ }
110
+ if (!virtualization) {
111
+ throw new TypeError('DATA-GRID: Option "infiniteScroll" requires "virtualization".');
112
+ }
113
+ }
114
+ const infiniteOptions = typeof infiniteScroll === 'object' ? infiniteScroll : {};
115
+ // Server-side mode implies pagination unless it scrolls infinitely, where
116
+ // the pages accumulate behind the virtualizer instead of replacing. The
117
+ // pagination STATE stays either way — infinite scroll pages the requests.
118
+ const paginationEnabled = Boolean(pagination) || (serverSide && !infiniteScroll);
119
+ const paginated = paginationEnabled || Boolean(infiniteScroll);
86
120
  const paginationOptions = typeof pagination === 'object' ? pagination : {};
87
121
  const virtualizationEnabled = virtualization && !paginationEnabled;
88
122
  const resolvedToolbar = resolveToolbar({
@@ -95,6 +129,7 @@ const CDataGrid = forwardRef((props, ref) => {
95
129
  const isColumnFilterable = (column) => columnFilters && column.filterable !== false;
96
130
  const isColumnResizable = (column) => sizingEnabled && column.resizable !== false;
97
131
  // A persisted view (stateKey) seeds the initial state - read once.
132
+ const rootRef = useRef(null);
98
133
  const persistedStateRef = useRef(undefined);
99
134
  if (persistedStateRef.current === undefined) {
100
135
  persistedStateRef.current = readPersistedState(stateKey);
@@ -105,7 +140,11 @@ const CDataGrid = forwardRef((props, ref) => {
105
140
  const [globalFilterState, setGlobalFilterState] = useState((persisted === null || persisted === void 0 ? void 0 : persisted.globalFilter) === undefined || persisted.globalFilter === '' ? undefined : persisted.globalFilter);
106
141
  const [rowSelectionState, setRowSelectionState] = useState((_c = persisted === null || persisted === void 0 ? void 0 : persisted.rowSelection) !== null && _c !== void 0 ? _c : {});
107
142
  const [columnSizingState, setColumnSizingState] = useState((_d = persisted === null || persisted === void 0 ? void 0 : persisted.columnSizing) !== null && _d !== void 0 ? _d : {});
108
- const [columnPinningState, setColumnPinningState] = useState((_e = persisted === null || persisted === void 0 ? void 0 : persisted.columnPinning) !== null && _e !== void 0 ? _e : (typeof columnPinning === 'object' ? columnPinning : {}));
143
+ const [columnPinningState, setColumnPinningState] = useState({
144
+ start: [],
145
+ end: [],
146
+ ...((_e = persisted === null || persisted === void 0 ? void 0 : persisted.columnPinning) !== null && _e !== void 0 ? _e : (typeof columnPinning === 'object' ? columnPinning : {}))
147
+ });
109
148
  const [columnOrderState, setColumnOrderState] = useState((_f = persisted === null || persisted === void 0 ? void 0 : persisted.columnOrder) !== null && _f !== void 0 ? _f : (Array.isArray(columnOrder) ? columnOrder : []));
110
149
  const [columnVisibilityState, setColumnVisibilityState] = useState((_g = persisted === null || persisted === void 0 ? void 0 : persisted.columnVisibility) !== null && _g !== void 0 ? _g : (typeof columnVisibility === 'object' ? columnVisibility : {}));
111
150
  // The chooser's Reset restores the initial columnVisibility object, captured
@@ -113,7 +152,13 @@ const CDataGrid = forwardRef((props, ref) => {
113
152
  const initialColumnVisibility = useRef(typeof columnVisibility === 'object' ? columnVisibility : {});
114
153
  const [paginationState, setPaginationState] = useState({
115
154
  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,
116
- 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
155
+ // Pagination is a registered feature on every grid (v9 features are
156
+ // static), so an unpaginated grid is one page holding every row.
157
+ pageSize: infiniteScroll ?
158
+ (_k = infiniteOptions.pageSize) !== null && _k !== void 0 ? _k : INFINITE_SCROLL_PAGE_SIZE :
159
+ (paginationEnabled ?
160
+ (_o = (_m = (_l = persisted === null || persisted === void 0 ? void 0 : persisted.pagination) === null || _l === void 0 ? void 0 : _l.pageSize) !== null && _m !== void 0 ? _m : paginationOptions.pageSize) !== null && _o !== void 0 ? _o : 10 :
161
+ UNPAGINATED_PAGE_SIZE)
117
162
  });
118
163
  const [activeCell, setActiveCell] = useState(null);
119
164
  // A pending focus request survives renders until the target cell exists in
@@ -163,14 +208,31 @@ const CDataGrid = forwardRef((props, ref) => {
163
208
  enableSorting: column.sortable !== false,
164
209
  filterFn: toTanStackFilterFn(column),
165
210
  id: column.key,
166
- meta: { label: column.label, formatter: column.formatter },
211
+ meta: { label: column.label, formatter: column.formatter, width: column.width },
167
212
  ...(widthsEnabled && size !== null && { size })
168
213
  };
169
214
  }), [columns, widthsEnabled]);
170
- const table = useReactTable({
215
+ assertFeatureCoverage('data-grid', features, {
216
+ cellSelection,
217
+ columnFilters,
218
+ columnOrder: Boolean(columnOrder),
219
+ columnPinning: pinningEnabled,
220
+ columnSizing: sizingEnabled,
221
+ columnVisibility: Boolean(columnVisibility),
222
+ globalFilter: resolvedToolbar.search,
223
+ pagination: paginated,
224
+ rowSelection: selectionEnabled,
225
+ selectFilters: columnFilters && columns.some(column => column.filterType === 'select'),
226
+ sorting: Boolean(sorting)
227
+ });
228
+ const table = useTable({
171
229
  columns: columnDefs,
172
- columnResizeMode: (_o = sizingOptions.mode) !== null && _o !== void 0 ? _o : 'onChange',
230
+ columnResizeMode: (_p = sizingOptions.mode) !== null && _p !== void 0 ? _p : 'onChange',
231
+ // Construction-time only — table-core copies the options object. A
232
+ // direction flipped later is picked up when a resize starts.
233
+ columnResizeDirection: isElementRTL(rootRef.current) ? 'rtl' : 'ltr',
173
234
  data: serverSide ? serverItems : items,
235
+ enableCellSelection: cellSelection,
174
236
  enableColumnFilters: columnFilters,
175
237
  enableColumnPinning: pinningEnabled,
176
238
  enableColumnResizing: sizingEnabled,
@@ -180,12 +242,10 @@ const CDataGrid = forwardRef((props, ref) => {
180
242
  enableRowSelection: selectionEnabled,
181
243
  enableSorting: Boolean(sorting),
182
244
  enableSortingRemoval: Boolean(sortingOptions.resetable),
183
- getCoreRowModel: getCoreRowModel(),
184
- // Faceting powers custom filter UIs (column.getFacetedUniqueValues()).
185
- getFacetedRowModel: getFacetedRowModel(),
186
- getFacetedUniqueValues: getFacetedUniqueValues(),
187
- getFilteredRowModel: getFilteredRowModel(),
188
- getSortedRowModel: getSortedRowModel(),
245
+ // The runtime set may be smaller than the DataGridFeatures the table is
246
+ // typed against - internals stay typed on the full set and every call
247
+ // into an optional feature is capability-guarded.
248
+ features,
189
249
  globalFilterFn: 'includesString',
190
250
  ...(serverSide && {
191
251
  manualFiltering: true,
@@ -193,7 +253,6 @@ const CDataGrid = forwardRef((props, ref) => {
193
253
  manualSorting: true,
194
254
  rowCount: serverTotalRows
195
255
  }),
196
- ...(paginationEnabled && { getPaginationRowModel: getPaginationRowModel() }),
197
256
  ...(itemKey && { getRowId: itemKey }),
198
257
  onColumnFiltersChange: setColumnFiltersState,
199
258
  onColumnOrderChange: setColumnOrderState,
@@ -216,7 +275,6 @@ const CDataGrid = forwardRef((props, ref) => {
216
275
  sorting: sortingState
217
276
  }
218
277
  });
219
- const rootRef = useRef(null);
220
278
  // Stable across renders - an inline callback ref would be detached/reattached
221
279
  // (null, node) on every render, hammering consumer callback refs.
222
280
  const setRootRef = useCallback((node) => {
@@ -254,8 +312,68 @@ const CDataGrid = forwardRef((props, ref) => {
254
312
  const tooltip = createTooltip(rootRef.current);
255
313
  return () => tooltip.dispose();
256
314
  }, []);
315
+ // Pointer-based column drag: the shared controller owns the ghost, the drop
316
+ // indicator and the edge auto-scroll, and writes to the DOM directly, so a
317
+ // drag costs no React renders. The table is read through a ref so the
318
+ // controller survives every unrelated re-render.
319
+ const tableRefForDrag = useRef(table);
320
+ tableRefForDrag.current = table;
321
+ useEffect(() => {
322
+ const root = rootRef.current;
323
+ if (!columnOrder || !root) {
324
+ return;
325
+ }
326
+ const controller = createColumnDragController({
327
+ root,
328
+ getScrollElement: () => viewportElement,
329
+ canDrop: (sourceKey, targetKey) => canReorderColumn(tableRefForDrag.current, sourceKey, targetKey),
330
+ onReorder: (sourceKey, targetKey, after) => reorderColumn(tableRefForDrag.current, sourceKey, targetKey, after)
331
+ });
332
+ return () => controller.dispose();
333
+ }, [columnOrder, viewportElement]);
334
+ // The grid never mutates `items` — it hands the reordered array to the app
335
+ // through onRowOrderChange, the same contract inline editing uses.
336
+ const rowOrderRef = useRef({ items, rowIndexOffset: 0, onRowOrderChange });
337
+ rowOrderRef.current = {
338
+ items,
339
+ rowIndexOffset: paginationEnabled ? paginationState.pageIndex * paginationState.pageSize : 0,
340
+ onRowOrderChange
341
+ };
342
+ useEffect(() => {
343
+ const root = rootRef.current;
344
+ if (!rowOrder || !root) {
345
+ return;
346
+ }
347
+ const controller = createRowDragController({
348
+ root,
349
+ getScrollElement: () => viewportElement,
350
+ onReorder(sourceIndex, targetIndex, after) {
351
+ var _a;
352
+ const { current } = rowOrderRef;
353
+ const next = [...current.items];
354
+ const from = current.rowIndexOffset + sourceIndex;
355
+ const [item] = next.splice(from, 1);
356
+ if (item === undefined) {
357
+ return;
358
+ }
359
+ // Resolved AFTER the removal, so the index still points at the target
360
+ // whichever direction the row travelled.
361
+ const target = current.rowIndexOffset + targetIndex;
362
+ const to = target > from ? target - 1 : target;
363
+ const newIndex = after ? to + 1 : to;
364
+ next.splice(newIndex, 0, item);
365
+ (_a = current.onRowOrderChange) === null || _a === void 0 ? void 0 : _a.call(current, {
366
+ items: next, item, oldIndex: from, newIndex
367
+ });
368
+ }
369
+ });
370
+ return () => controller.dispose();
371
+ }, [rowOrder, viewportElement]);
257
372
  const requestIdRef = useRef(0);
258
373
  const lastFilterKeyRef = useRef(null);
374
+ // One page bump per fetch: the body re-renders many times before the next
375
+ // page lands, and each of those passes still sees the end of the buffer.
376
+ const loadMorePendingRef = useRef(false);
259
377
  useEffect(() => {
260
378
  if (!dataProvider) {
261
379
  return;
@@ -282,7 +400,14 @@ const CDataGrid = forwardRef((props, ref) => {
282
400
  if (id !== requestIdRef.current) {
283
401
  return;
284
402
  }
285
- setServerItems(response.items);
403
+ // Infinite scroll accumulates: only a first page replaces what is on
404
+ // screen, every later one appends to it. A replacement also shrinks
405
+ // the buffer back under a viewport scrolled far past it.
406
+ loadMorePendingRef.current = false;
407
+ if (infiniteScroll && paginationState.pageIndex === 0 && viewportElement) {
408
+ viewportElement.scrollTop = 0;
409
+ }
410
+ setServerItems(previous => (infiniteScroll && paginationState.pageIndex > 0 ? [...previous, ...response.items] : response.items));
286
411
  setServerTotalRows(response.totalRows);
287
412
  setLoadFailed(false);
288
413
  setAnnouncement(interpolate(mergedLabels.resultsAnnouncement, { count: response.totalRows }));
@@ -292,7 +417,8 @@ const CDataGrid = forwardRef((props, ref) => {
292
417
  if (id !== requestIdRef.current) {
293
418
  return;
294
419
  }
295
- setServerItems([]);
420
+ loadMorePendingRef.current = false;
421
+ setServerItems(EMPTY_ITEMS);
296
422
  setServerTotalRows(0);
297
423
  setLoadFailed(true);
298
424
  onDataError === null || onDataError === void 0 ? void 0 : onDataError(error);
@@ -307,7 +433,9 @@ const CDataGrid = forwardRef((props, ref) => {
307
433
  // eslint-disable-next-line react-hooks/exhaustive-deps
308
434
  }, [dataProvider, sortingState, columnFiltersState, globalFilterState, paginationState]);
309
435
  const mounted = useRef(false);
310
- const totalRows = serverSide ? serverTotalRows : table.getFilteredRowModel().rows.length;
436
+ const totalRows = serverSide ?
437
+ serverTotalRows :
438
+ (typeof table.getFilteredRowModel === 'function' ? table.getFilteredRowModel() : table.getCoreRowModel()).rows.length;
311
439
  useEffect(() => {
312
440
  if (mounted.current) {
313
441
  onSortingChange === null || onSortingChange === void 0 ? void 0 : onSortingChange(sortingState);
@@ -321,13 +449,15 @@ const CDataGrid = forwardRef((props, ref) => {
321
449
  // eslint-disable-next-line react-hooks/exhaustive-deps
322
450
  }, [columnFiltersState, globalFilterState]);
323
451
  useEffect(() => {
324
- if (mounted.current) {
452
+ if (mounted.current && typeof table.getSelectedRowModel === 'function') {
325
453
  onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(rowSelectionState, table.getSelectedRowModel().rows.map(row => row.original));
326
454
  }
327
455
  // eslint-disable-next-line react-hooks/exhaustive-deps
328
456
  }, [rowSelectionState]);
457
+ // No onPaginationChange under infinite scroll — pagination is internal
458
+ // there (no widget, not user-adjustable); onDataLoad is the page signal.
329
459
  useEffect(() => {
330
- if (mounted.current) {
460
+ if (mounted.current && !infiniteScroll) {
331
461
  onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(paginationState);
332
462
  }
333
463
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -372,11 +502,17 @@ const CDataGrid = forwardRef((props, ref) => {
372
502
  // reshuffles rows would make it point at an arbitrary one. An in-flight
373
503
  // edit stops (commit) first. A pending focus request marks an intentional
374
504
  // navigation (PageUp/PageDown page flip) - keep the cell it just set.
375
- const signature = JSON.stringify([
376
- sortingState, columnFiltersState,
377
- globalFilterState !== null && globalFilterState !== void 0 ? globalFilterState : '',
378
- paginationState.pageIndex, paginationState.pageSize
379
- ]);
505
+ // Infinite scroll is the exception: its page bumps only append, so every
506
+ // row already on screen keeps its index and its focus.
507
+ const signature = JSON.stringify(infiniteScroll ?
508
+ [sortingState, columnFiltersState, globalFilterState !== null && globalFilterState !== void 0 ? globalFilterState : ''] :
509
+ [
510
+ sortingState,
511
+ columnFiltersState,
512
+ globalFilterState !== null && globalFilterState !== void 0 ? globalFilterState : '',
513
+ paginationState.pageIndex,
514
+ paginationState.pageSize
515
+ ]);
380
516
  if (rowSetSignatureRef.current === signature) {
381
517
  return;
382
518
  }
@@ -387,6 +523,7 @@ const CDataGrid = forwardRef((props, ref) => {
387
523
  setActiveCell(null);
388
524
  }
389
525
  }
526
+ // eslint-disable-next-line react-hooks/exhaustive-deps
390
527
  }, [sortingState, columnFiltersState, globalFilterState, paginationState]);
391
528
  useEffect(() => {
392
529
  mounted.current = true;
@@ -398,9 +535,31 @@ const CDataGrid = forwardRef((props, ref) => {
398
535
  }, []);
399
536
  const hasCustomFilterRow = columnFilters && columns.some(column => column.filter && column.filterable !== false);
400
537
  const headerRowCount = hasCustomFilterRow ? 2 : 1;
401
- const position = (_p = paginationOptions.position) !== null && _p !== void 0 ? _p : 'bottom';
538
+ const position = (_q = paginationOptions.position) !== null && _q !== void 0 ? _q : 'bottom';
402
539
  const rowCount = table.getRowModel().rows.length;
540
+ const appending = Boolean(infiniteScroll) && serverItems.length > 0;
541
+ const loadMore = () => {
542
+ if (loadMorePendingRef.current || rowCount === 0 || rowCount >= totalRows) {
543
+ return;
544
+ }
545
+ loadMorePendingRef.current = true;
546
+ setPaginationState(previous => ({ ...previous, pageIndex: previous.pageIndex + 1 }));
547
+ };
403
548
  const visibleColumnIds = visibleColumns(table, columns).map(column => column.key);
549
+ // The columns the selection's column indexes address, with the formatter
550
+ // each cell displays through — a copied date pastes as the date on screen.
551
+ const clipboardColumns = () => visibleColumns(table, columns).map(column => ({ id: column.key, formatter: column.formatter }));
552
+ // Prints every sorted and filtered row, not the virtual window or the
553
+ // current page: the grid renders a plain complete table, prints it, and
554
+ // throws it away.
555
+ const printGridTable = () => printGrid(table, visibleColumns(table, columns).map(column => {
556
+ var _a;
557
+ return ({
558
+ id: column.key,
559
+ label: (_a = column.label) !== null && _a !== void 0 ? _a : column.key,
560
+ formatter: column.formatter
561
+ });
562
+ }), { title: printTitle });
404
563
  const activeCellContext = () => {
405
564
  var _a;
406
565
  return ({
@@ -409,7 +568,8 @@ const CDataGrid = forwardRef((props, ref) => {
409
568
  pageStep: paginationEnabled ?
410
569
  paginationState.pageSize :
411
570
  Math.max(1, Math.floor(((_a = viewportElement === null || viewportElement === void 0 ? void 0 : viewportElement.clientHeight) !== null && _a !== void 0 ? _a : 0) / rowHeight) || rowCount),
412
- paginated: paginationEnabled
571
+ paginated: paginationEnabled,
572
+ rtl: isElementRTL(rootRef.current)
413
573
  });
414
574
  };
415
575
  // Clamped for rendering only - the state stays as set and re-clamps as the
@@ -453,6 +613,14 @@ const CDataGrid = forwardRef((props, ref) => {
453
613
  var _a;
454
614
  focusRequestRef.current = cell;
455
615
  setActiveCell(cell);
616
+ // The active cell is the grid's single focus owner; cell selection follows
617
+ // it rather than keeping a second anchor of its own.
618
+ if (cellSelection && cell.rowIndex >= 0) {
619
+ const row = table.getRowModel().rows[cell.rowIndex];
620
+ if (row) {
621
+ table.setFocusedCell(row.id, cell.columnId);
622
+ }
623
+ }
456
624
  if (virtualizationEnabled && cell.rowIndex >= 0) {
457
625
  // No-op when the row is already in view (align: auto); otherwise the
458
626
  // focus request stays pending until the row renders.
@@ -740,7 +908,7 @@ const CDataGrid = forwardRef((props, ref) => {
740
908
  }
741
909
  };
742
910
  const handleNavigationKeydown = (event) => {
743
- var _a, _b, _c, _d;
911
+ var _a, _b, _c, _d, _e;
744
912
  if (!cellNavigationEnabled) {
745
913
  return;
746
914
  }
@@ -834,11 +1002,37 @@ const CDataGrid = forwardRef((props, ref) => {
834
1002
  }
835
1003
  return;
836
1004
  }
1005
+ if (cellSelection && (event.ctrlKey || event.metaKey) && found.cell.rowIndex >= 0) {
1006
+ const key = event.key.toLowerCase();
1007
+ if (key === 'a') {
1008
+ event.preventDefault();
1009
+ table.selectAllCells();
1010
+ return;
1011
+ }
1012
+ if (key === 'c') {
1013
+ event.preventDefault();
1014
+ copyCellSelection(table, clipboardColumns()).then(text => {
1015
+ if (text !== '') {
1016
+ onCellCopy === null || onCellCopy === void 0 ? void 0 : onCellCopy({ text });
1017
+ }
1018
+ }, () => { });
1019
+ return;
1020
+ }
1021
+ }
837
1022
  const result = resolveNavigation(event.key, event.ctrlKey || event.metaKey, found.cell, activeCellContext());
838
1023
  if (!result) {
839
1024
  return;
840
1025
  }
841
1026
  event.preventDefault();
1027
+ // Shift+arrow grows the range from its anchor and leaves focus put; a
1028
+ // plain arrow moves focus and collapses the range to the new cell.
1029
+ if (cellSelection && found.cell.rowIndex >= 0 && result.cell.rowIndex >= 0) {
1030
+ const direction = CELL_SELECTION_DIRECTIONS[isElementRTL(rootRef.current) ? ((_e = INVERTED_ARROWS[event.key]) !== null && _e !== void 0 ? _e : event.key) : event.key];
1031
+ if (event.shiftKey && direction) {
1032
+ table.extendCellSelection(direction);
1033
+ return;
1034
+ }
1035
+ }
842
1036
  if (result.pageDelta === 1 && table.getCanNextPage()) {
843
1037
  table.nextPage();
844
1038
  }
@@ -860,9 +1054,9 @@ const CDataGrid = forwardRef((props, ref) => {
860
1054
  jsx(EmptySlot, { table: table, labels: mergedLabels }) :
861
1055
  (loadFailed ? mergedLabels.loadError : empty);
862
1056
  const editingConfig = editingCell ?
863
- (_q = columns.find(column => column.key === editingCell.columnId)) !== null && _q !== void 0 ? _q : null :
1057
+ (_r = columns.find(column => column.key === editingCell.columnId)) !== null && _r !== void 0 ? _r : null :
864
1058
  null;
865
- const EditorComponent = (_r = editingConfig === null || editingConfig === void 0 ? void 0 : editingConfig.editor) !== null && _r !== void 0 ? _r : CDataGridCellEditor;
1059
+ const EditorComponent = (_s = editingConfig === null || editingConfig === void 0 ? void 0 : editingConfig.editor) !== null && _s !== void 0 ? _s : CDataGridCellEditor;
866
1060
  const editorSession = editingCell && editingConfig ?
867
1061
  {
868
1062
  rowId: editingCell.rowId,
@@ -881,9 +1075,10 @@ const CDataGrid = forwardRef((props, ref) => {
881
1075
  onHidden: () => stopEditingRef.current({ commit: true, force: true })
882
1076
  } :
883
1077
  null;
884
- return (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: [jsx("div", { className: "visually-hidden", "aria-live": "polite", children: announcement }), ToolbarSlot ?
1078
+ return (jsxs("div", { className: `data-grid${autoRowHeight && virtualizationEnabled ? ' data-grid-auto-row-height' : ''}${sizingEnabled ? ' data-grid-resizable' : ''}${pinningEnabled ? ' data-grid-pinned' : ''}${className ? ` ${className}` : ''}`, "data-coreui-sorter-visibility": sorterVisibility || undefined, ref: setRootRef, ...rest, children: [jsx("div", { className: "visually-hidden", "aria-live": "polite", children: announcement }), ToolbarSlot ?
885
1079
  jsx(ToolbarSlot, { table: table, labels: mergedLabels }) :
886
- (resolvedToolbar.columns || resolvedToolbar.export || resolvedToolbar.search || resolvedToolbar.history) && (jsx(CDataGridToolbar, { columns: columns, 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'), jsxs("div", { className: "data-grid-viewport", ref: setViewportElement, ...(serverSide && { 'aria-busy': loading }), ...(cellNavigationEnabled && {
1080
+ (resolvedToolbar.columns || resolvedToolbar.export || resolvedToolbar.print ||
1081
+ resolvedToolbar.search || resolvedToolbar.history) && (jsx(CDataGridToolbar, { columns: columns, columnsIcon: toolbarColumnsIcon, container: rootRef, export: resolvedToolbar.export, exportIcon: toolbarExportIcon, exportOptions: resolvedToolbar.exportOptions, initialVisibility: initialColumnVisibility.current, labels: mergedLabels, canRedo: canRedo, canUndo: canUndo, onPrint: printGridTable, onRedo: redo, onUndo: undo, print: resolvedToolbar.print, printIcon: toolbarPrintIcon, 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'), jsxs("div", { className: "data-grid-viewport", ref: setViewportElement, ...(serverSide && { 'aria-busy': loading }), ...(cellNavigationEnabled && {
887
1082
  // Focus parks here when the focused row is recycled out of the
888
1083
  // window; the keydown fallback then scrolls the active cell back.
889
1084
  tabIndex: -1,
@@ -893,7 +1088,7 @@ const CDataGrid = forwardRef((props, ref) => {
893
1088
  }), ...(editing && { onDoubleClick: handleEditingDoubleClick }), children: [jsxs("table", { className: "table", "aria-rowcount": headerRowCount + totalRows, ...(cellNavigationEnabled && {
894
1089
  role: 'grid',
895
1090
  'aria-colcount': visibleColumnIds.length + (selectionEnabled ? 1 : 0)
896
- }), children: [jsx(CDataGridHeader, { cellNavigation: cellNavigationEnabled, columnFilters: columnFilters, columns: columns, 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) }), jsx(CDataGridBody, { cellNavigation: cellNavigationEnabled, columns: columns, 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 && (jsx("div", { className: "data-grid-loading", hidden: !loading, children: jsx("div", { className: "spinner-border", role: "status", children: jsx("span", { className: "visually-hidden", children: mergedLabels.loading }) }) }))] }), (editorSession === null || editorSession === void 0 ? void 0 : editorSession.popup) && (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')] }));
1091
+ }), children: [jsx(CDataGridHeader, { cellNavigation: cellNavigationEnabled, columnFilters: columnFilters, columns: columns, draggable: Boolean(columnOrder), icons: menuIcons, isFilterable: isColumnFilterable, isResizable: isColumnResizable, isSortable: isColumnSortable, labels: mergedLabels, menu: Boolean(columnMenu), menuBuilder: menuBuilder, menuContainer: rootRef, pinning: pinningEnabled, resizable: sizingEnabled, rowOrder: rowOrder, selectAll: selectionEnabled && selectionOptions.selectAll !== false, selection: selectionEnabled, tabStop: tabStop, table: table, visibility: Boolean(columnVisibility) }), jsx(CDataGridBody, { cellNavigation: cellNavigationEnabled, columns: columns, containsFocusRef: containsFocusRef, editorSession: editorSession, empty: emptyContent, focusRequestRef: focusRequestRef, headerRowCount: headerRowCount, labels: mergedLabels, loadMoreThreshold: infiniteScroll ? (_t = infiniteOptions.threshold) !== null && _t !== void 0 ? _t : overscan : null, onLoadMore: loadMore, overscan: overscan, pinning: pinningEnabled, autoRowHeight: autoRowHeight && virtualizationEnabled, rowHeight: rowHeight, cellSelection: cellSelection, rowHandleIcon: rowHandleIcon, rowIndexOffset: paginationEnabled ? paginationState.pageIndex * paginationState.pageSize : 0, rowOrder: rowOrder, scrollElement: viewportElement, scrollToIndexRef: scrollToIndexRef, selection: selectionEnabled, tabStop: tabStop, table: table, virtualization: virtualizationEnabled })] }), serverSide && (jsx("div", { className: "data-grid-loading", hidden: !loading || appending, children: jsx("div", { className: "spinner-border", role: "status", children: jsx("span", { className: "visually-hidden", children: mergedLabels.loading }) }) })), Boolean(infiniteScroll) && (jsx("div", { className: "data-grid-loading-more", hidden: !loading || !appending, children: jsx("div", { className: "spinner-border", role: "status", children: jsx("span", { className: "visually-hidden", children: mergedLabels.loading }) }) }))] }), (editorSession === null || editorSession === void 0 ? void 0 : editorSession.popup) && (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')] }));
897
1092
  });
898
1093
  CDataGrid.displayName = 'CDataGrid';
899
1094