@alaarab/ogrid-react 2.0.23 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/ColumnHeaderFilterContent.js +0 -2
- package/dist/esm/components/MarchingAntsOverlay.js +2 -3
- package/dist/esm/components/SideBar.js +8 -7
- package/dist/esm/components/createOGrid.js +1 -4
- package/dist/esm/hooks/index.js +10 -0
- package/dist/esm/hooks/useActiveCell.js +2 -4
- package/dist/esm/hooks/useCellSelection.js +85 -52
- package/dist/esm/hooks/useClipboard.js +15 -54
- package/dist/esm/hooks/useColumnChooserState.js +25 -13
- package/dist/esm/hooks/useColumnHeaderFilterState.js +22 -11
- package/dist/esm/hooks/useColumnHeaderMenuState.js +1 -1
- package/dist/esm/hooks/useColumnMeta.js +61 -0
- package/dist/esm/hooks/useColumnPinning.js +11 -12
- package/dist/esm/hooks/useColumnReorder.js +8 -1
- package/dist/esm/hooks/useColumnResize.js +6 -2
- package/dist/esm/hooks/useDataGridContextMenu.js +24 -0
- package/dist/esm/hooks/useDataGridEditing.js +56 -0
- package/dist/esm/hooks/useDataGridInteraction.js +109 -0
- package/dist/esm/hooks/useDataGridLayout.js +172 -0
- package/dist/esm/hooks/useDataGridState.js +83 -318
- package/dist/esm/hooks/useDataGridTableOrchestration.js +2 -4
- package/dist/esm/hooks/useFillHandle.js +60 -55
- package/dist/esm/hooks/useFilterOptions.js +2 -4
- package/dist/esm/hooks/useInlineCellEditorState.js +7 -13
- package/dist/esm/hooks/useKeyboardNavigation.js +19 -132
- package/dist/esm/hooks/useMultiSelectFilterState.js +1 -1
- package/dist/esm/hooks/useOGrid.js +159 -301
- package/dist/esm/hooks/useOGridDataFetching.js +74 -0
- package/dist/esm/hooks/useOGridFilters.js +59 -0
- package/dist/esm/hooks/useOGridPagination.js +24 -0
- package/dist/esm/hooks/useOGridSorting.js +24 -0
- package/dist/esm/hooks/usePaginationControls.js +2 -5
- package/dist/esm/hooks/usePeopleFilterState.js +6 -1
- package/dist/esm/hooks/useRichSelectState.js +7 -5
- package/dist/esm/hooks/useRowSelection.js +6 -26
- package/dist/esm/hooks/useSelectState.js +2 -5
- package/dist/esm/hooks/useShallowEqualMemo.js +14 -0
- package/dist/esm/hooks/useTableLayout.js +3 -11
- package/dist/esm/hooks/useUndoRedo.js +16 -10
- package/dist/esm/index.js +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/dist/types/components/ColumnChooserProps.d.ts +2 -0
- package/dist/types/components/ColumnHeaderFilterContent.d.ts +0 -2
- package/dist/types/hooks/index.d.ts +19 -0
- package/dist/types/hooks/useClipboard.d.ts +0 -1
- package/dist/types/hooks/useColumnChooserState.d.ts +2 -0
- package/dist/types/hooks/useColumnHeaderFilterState.d.ts +0 -2
- package/dist/types/hooks/useColumnHeaderMenuState.d.ts +0 -2
- package/dist/types/hooks/useColumnMeta.d.ts +34 -0
- package/dist/types/hooks/useDataGridContextMenu.d.ts +20 -0
- package/dist/types/hooks/useDataGridEditing.d.ts +39 -0
- package/dist/types/hooks/useDataGridInteraction.d.ts +95 -0
- package/dist/types/hooks/useDataGridLayout.d.ts +45 -0
- package/dist/types/hooks/useDataGridState.d.ts +7 -1
- package/dist/types/hooks/useDataGridTableOrchestration.d.ts +1 -2
- package/dist/types/hooks/useOGrid.d.ts +4 -2
- package/dist/types/hooks/useOGridDataFetching.d.ts +29 -0
- package/dist/types/hooks/useOGridFilters.d.ts +24 -0
- package/dist/types/hooks/useOGridPagination.d.ts +18 -0
- package/dist/types/hooks/useOGridSorting.d.ts +23 -0
- package/dist/types/hooks/usePaginationControls.d.ts +1 -1
- package/dist/types/hooks/useRichSelectState.d.ts +2 -0
- package/dist/types/hooks/useShallowEqualMemo.d.ts +7 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/utils/index.d.ts +2 -2
- package/package.json +12 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, useCallback
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* Load filter options for the given fields from a data source.
|
|
4
4
|
*
|
|
@@ -7,7 +7,6 @@ import { useState, useEffect, useCallback, useMemo } from 'react';
|
|
|
7
7
|
export function useFilterOptions(dataSource, fields) {
|
|
8
8
|
const [filterOptions, setFilterOptions] = useState({});
|
|
9
9
|
const [loadingOptions, setLoadingOptions] = useState({});
|
|
10
|
-
const fieldsKey = useMemo(() => [...fields].sort().join(','), [fields]);
|
|
11
10
|
const load = useCallback(async () => {
|
|
12
11
|
const fetcher = 'fetchFilterOptions' in dataSource && typeof dataSource.fetchFilterOptions === 'function'
|
|
13
12
|
? dataSource.fetchFilterOptions.bind(dataSource)
|
|
@@ -31,8 +30,7 @@ export function useFilterOptions(dataSource, fields) {
|
|
|
31
30
|
}));
|
|
32
31
|
setFilterOptions(results);
|
|
33
32
|
setLoadingOptions({});
|
|
34
|
-
|
|
35
|
-
}, [dataSource, fieldsKey]);
|
|
33
|
+
}, [dataSource, fields]);
|
|
36
34
|
useEffect(() => {
|
|
37
35
|
load().catch(() => { });
|
|
38
36
|
}, [load]);
|
|
@@ -10,35 +10,29 @@ import { useState, useCallback } from 'react';
|
|
|
10
10
|
export function useInlineCellEditorState(params) {
|
|
11
11
|
const { value, editorType, onCommit, onCancel } = params;
|
|
12
12
|
const [localValue, setLocalValue] = useState(value !== null && value !== undefined ? String(value) : '');
|
|
13
|
-
const commit = useCallback((v) => {
|
|
14
|
-
onCommit(v);
|
|
15
|
-
}, [onCommit]);
|
|
16
|
-
const cancel = useCallback(() => {
|
|
17
|
-
onCancel();
|
|
18
|
-
}, [onCancel]);
|
|
19
13
|
const handleKeyDown = useCallback((e) => {
|
|
20
14
|
if (e.key === 'Escape') {
|
|
21
15
|
e.preventDefault();
|
|
22
16
|
e.stopPropagation(); // Don't let the grid handler clear selection on Escape
|
|
23
|
-
|
|
17
|
+
onCancel();
|
|
24
18
|
}
|
|
25
19
|
if (e.key === 'Enter' && editorType === 'text') {
|
|
26
20
|
e.preventDefault();
|
|
27
21
|
e.stopPropagation(); // Don't let the grid handler re-open an editor
|
|
28
|
-
|
|
22
|
+
onCommit(localValue);
|
|
29
23
|
}
|
|
30
|
-
}, [
|
|
24
|
+
}, [onCancel, onCommit, localValue, editorType]);
|
|
31
25
|
const handleBlur = useCallback(() => {
|
|
32
26
|
if (editorType === 'text') {
|
|
33
|
-
|
|
27
|
+
onCommit(localValue);
|
|
34
28
|
}
|
|
35
|
-
}, [editorType, localValue,
|
|
29
|
+
}, [editorType, localValue, onCommit]);
|
|
36
30
|
return {
|
|
37
31
|
localValue,
|
|
38
32
|
setLocalValue,
|
|
39
33
|
handleKeyDown,
|
|
40
34
|
handleBlur,
|
|
41
|
-
commit,
|
|
42
|
-
cancel,
|
|
35
|
+
commit: onCommit,
|
|
36
|
+
cancel: onCancel,
|
|
43
37
|
};
|
|
44
38
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useCallback, useRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { getCellValue, parseValue, findCtrlArrowTarget, computeTabNavigation } from '../utils';
|
|
2
|
+
import { getCellValue, computeTabNavigation, computeArrowNavigation, applyCellDeletion } from '../utils';
|
|
4
3
|
/**
|
|
5
4
|
* Handles all keyboard navigation, shortcuts, and cell editing triggers for the grid.
|
|
6
5
|
* @param params - Grouped data, state, handlers, and feature flags for keyboard interactions.
|
|
@@ -70,114 +69,23 @@ export function useKeyboardNavigation(params) {
|
|
|
70
69
|
void handlePaste();
|
|
71
70
|
}
|
|
72
71
|
break;
|
|
73
|
-
case 'ArrowDown':
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const newRow = ctrl
|
|
77
|
-
? findCtrlArrowTarget(rowIndex, maxRowIndex, 1, (r) => isEmptyAt(r, Math.max(0, dataColIndex)))
|
|
78
|
-
: Math.min(rowIndex + 1, maxRowIndex);
|
|
79
|
-
if (shift) {
|
|
80
|
-
setSelectionRange(normalizeSelectionRange({
|
|
81
|
-
startRow: selectionRange?.startRow ?? rowIndex,
|
|
82
|
-
startCol: selectionRange?.startCol ?? dataColIndex,
|
|
83
|
-
endRow: newRow,
|
|
84
|
-
endCol: selectionRange?.endCol ?? dataColIndex,
|
|
85
|
-
}));
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
setSelectionRange({
|
|
89
|
-
startRow: newRow,
|
|
90
|
-
startCol: dataColIndex,
|
|
91
|
-
endRow: newRow,
|
|
92
|
-
endCol: dataColIndex,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
setActiveCell({ rowIndex: newRow, columnIndex });
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
case 'ArrowUp': {
|
|
99
|
-
e.preventDefault();
|
|
100
|
-
const ctrl = e.ctrlKey || e.metaKey;
|
|
101
|
-
const newRowUp = ctrl
|
|
102
|
-
? findCtrlArrowTarget(rowIndex, 0, -1, (r) => isEmptyAt(r, Math.max(0, dataColIndex)))
|
|
103
|
-
: Math.max(rowIndex - 1, 0);
|
|
104
|
-
if (shift) {
|
|
105
|
-
setSelectionRange(normalizeSelectionRange({
|
|
106
|
-
startRow: selectionRange?.startRow ?? rowIndex,
|
|
107
|
-
startCol: selectionRange?.startCol ?? dataColIndex,
|
|
108
|
-
endRow: newRowUp,
|
|
109
|
-
endCol: selectionRange?.endCol ?? dataColIndex,
|
|
110
|
-
}));
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
setSelectionRange({
|
|
114
|
-
startRow: newRowUp,
|
|
115
|
-
startCol: dataColIndex,
|
|
116
|
-
endRow: newRowUp,
|
|
117
|
-
endCol: dataColIndex,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
setActiveCell({ rowIndex: newRowUp, columnIndex });
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
case 'ArrowRight': {
|
|
124
|
-
e.preventDefault();
|
|
125
|
-
const ctrl = e.ctrlKey || e.metaKey;
|
|
126
|
-
let newCol;
|
|
127
|
-
if (ctrl && dataColIndex >= 0) {
|
|
128
|
-
newCol = findCtrlArrowTarget(dataColIndex, visibleCols.length - 1, 1, (c) => isEmptyAt(rowIndex, c)) + colOffset;
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
newCol = Math.min(columnIndex + 1, maxColIndex);
|
|
132
|
-
}
|
|
133
|
-
const newDataCol = newCol - colOffset;
|
|
134
|
-
if (shift) {
|
|
135
|
-
setSelectionRange(normalizeSelectionRange({
|
|
136
|
-
startRow: selectionRange?.startRow ?? rowIndex,
|
|
137
|
-
startCol: selectionRange?.startCol ?? dataColIndex,
|
|
138
|
-
endRow: selectionRange?.endRow ?? rowIndex,
|
|
139
|
-
endCol: newDataCol,
|
|
140
|
-
}));
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
setSelectionRange({
|
|
144
|
-
startRow: rowIndex,
|
|
145
|
-
startCol: newDataCol,
|
|
146
|
-
endRow: rowIndex,
|
|
147
|
-
endCol: newDataCol,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
setActiveCell({ rowIndex, columnIndex: newCol });
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
72
|
+
case 'ArrowDown':
|
|
73
|
+
case 'ArrowUp':
|
|
74
|
+
case 'ArrowRight':
|
|
153
75
|
case 'ArrowLeft': {
|
|
154
76
|
e.preventDefault();
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
startCol: selectionRange?.startCol ?? dataColIndex,
|
|
168
|
-
endRow: selectionRange?.endRow ?? rowIndex,
|
|
169
|
-
endCol: newDataColLeft,
|
|
170
|
-
}));
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
setSelectionRange({
|
|
174
|
-
startRow: rowIndex,
|
|
175
|
-
startCol: newDataColLeft,
|
|
176
|
-
endRow: rowIndex,
|
|
177
|
-
endCol: newDataColLeft,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
setActiveCell({ rowIndex, columnIndex: newColLeft });
|
|
77
|
+
const { newRowIndex, newColumnIndex, newRange } = computeArrowNavigation({
|
|
78
|
+
direction: e.key,
|
|
79
|
+
rowIndex, columnIndex, dataColIndex, colOffset,
|
|
80
|
+
maxRowIndex, maxColIndex,
|
|
81
|
+
visibleColCount: visibleCols.length,
|
|
82
|
+
isCtrl: e.ctrlKey || e.metaKey,
|
|
83
|
+
isShift: shift,
|
|
84
|
+
selectionRange,
|
|
85
|
+
isEmptyAt,
|
|
86
|
+
});
|
|
87
|
+
setSelectionRange(newRange);
|
|
88
|
+
setActiveCell({ rowIndex: newRowIndex, columnIndex: newColumnIndex });
|
|
181
89
|
break;
|
|
182
90
|
}
|
|
183
91
|
case 'Tab': {
|
|
@@ -317,30 +225,9 @@ export function useKeyboardNavigation(params) {
|
|
|
317
225
|
if (range == null)
|
|
318
226
|
break;
|
|
319
227
|
e.preventDefault();
|
|
320
|
-
const
|
|
321
|
-
for (
|
|
322
|
-
|
|
323
|
-
if (r >= items.length || c >= visibleCols.length)
|
|
324
|
-
continue;
|
|
325
|
-
const item = items[r];
|
|
326
|
-
const col = visibleCols[c];
|
|
327
|
-
const colEditable = col.editable === true ||
|
|
328
|
-
(typeof col.editable === 'function' && col.editable(item));
|
|
329
|
-
if (!colEditable)
|
|
330
|
-
continue;
|
|
331
|
-
const oldValue = getCellValue(item, col);
|
|
332
|
-
const result = parseValue('', oldValue, item, col);
|
|
333
|
-
if (!result.valid)
|
|
334
|
-
continue;
|
|
335
|
-
onCellValueChanged({
|
|
336
|
-
item,
|
|
337
|
-
columnId: col.columnId,
|
|
338
|
-
oldValue,
|
|
339
|
-
newValue: result.value,
|
|
340
|
-
rowIndex: r,
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
}
|
|
228
|
+
const deleteEvents = applyCellDeletion(range, items, visibleCols);
|
|
229
|
+
for (const evt of deleteEvents)
|
|
230
|
+
onCellValueChanged(evt);
|
|
344
231
|
break;
|
|
345
232
|
}
|
|
346
233
|
case 'F10':
|
|
@@ -38,7 +38,7 @@ export function useMultiSelectFilterState(params) {
|
|
|
38
38
|
});
|
|
39
39
|
}, []);
|
|
40
40
|
const handleSelectAll = useCallback(() => {
|
|
41
|
-
setTempSelected(new Set(filteredOptions));
|
|
41
|
+
setTempSelected((prev) => new Set([...prev, ...filteredOptions]));
|
|
42
42
|
}, [filteredOptions]);
|
|
43
43
|
const handleClearSelection = useCallback(() => setTempSelected(new Set()), []);
|
|
44
44
|
const handleApplyMultiSelect = useCallback(() => {
|