@linzjs/step-ag-grid 28.5.0 → 29.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +11 -7
- package/dist/src/components/Grid.d.ts +5 -1
- package/dist/src/contexts/GridContext.d.ts +3 -4
- package/dist/src/contexts/GridPopoverContext.d.ts +1 -0
- package/dist/src/contexts/GridUpdatingContext.d.ts +1 -0
- package/dist/src/lui/reactUtils.d.ts +4 -0
- package/dist/step-ag-grid.cjs +265 -247
- package/dist/step-ag-grid.cjs.map +1 -1
- package/dist/step-ag-grid.esm.js +266 -248
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +21 -22
- package/src/components/Grid.tsx +118 -113
- package/src/components/GridPopoverHook.tsx +25 -20
- package/src/components/gridFilter/useGridFilter.ts +3 -3
- package/src/components/gridHook/useGridContextMenu.tsx +3 -3
- package/src/contexts/GridContext.tsx +11 -14
- package/src/contexts/GridContextProvider.tsx +164 -137
- package/src/contexts/GridPopoverContext.tsx +2 -0
- package/src/contexts/GridPopoverContextProvider.tsx +9 -5
- package/src/contexts/GridUpdatingContext.tsx +5 -0
- package/src/contexts/GridUpdatingContextProvider.tsx +35 -28
- package/src/lui/reactUtils.tsx +24 -0
- package/src/react-menu3/components/MenuList.tsx +3 -0
- package/src/stories/grid/GridFilterButtons.stories.tsx +1 -1
- package/src/stories/grid/GridNonEditableRow.stories.tsx +1 -1
- package/src/stories/grid/GridPinnedRow.stories.tsx +1 -1
- package/src/stories/grid/GridPopoutContextMenu.stories.tsx +3 -3
- package/src/stories/grid/GridPopoutEditGenericTextArea.stories.tsx +2 -2
- package/src/stories/grid/GridPopoverEditDropDown.stories.tsx +8 -4
- package/src/stories/grid/GridPopoverEditMultiSelect.stories.tsx +1 -0
- package/src/stories/grid/GridReadOnly.stories.tsx +1 -1
- package/src/stories/grid/GridViewList.stories.tsx +1 -1
- package/src/stories/grid/gridFormInteraction/GridFormDropDownInteraction.stories.tsx +5 -3
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectGridInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormPopoverMenuInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormTextAreaInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormTextInputInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormStatic/GridFormDropDown.stories.tsx +2 -2
- package/src/stories/grid/interactions/GridKeyboardInteractions.stories.tsx +2 -2
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@linzjs/step-ag-grid",
|
|
3
3
|
"repository": "github:linz/step-ag-grid.git",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "29.0.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"aggrid",
|
|
8
8
|
"ag-grid",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"@linzjs/lui": ">=21",
|
|
31
|
-
"ag-grid-community": "^34.
|
|
32
|
-
"ag-grid-react": "^34.
|
|
31
|
+
"ag-grid-community": "^34.2.0",
|
|
32
|
+
"ag-grid-react": "^34.2.0",
|
|
33
33
|
"lodash-es": ">=4",
|
|
34
34
|
"react": ">=18",
|
|
35
35
|
"react-dom": ">=18"
|
|
@@ -76,21 +76,21 @@
|
|
|
76
76
|
]
|
|
77
77
|
},
|
|
78
78
|
"optionalDependencies": {
|
|
79
|
-
"@rollup/rollup-linux-x64-gnu": "^4.
|
|
80
|
-
"@swc/core-linux-x64-gnu": "^1.13.
|
|
79
|
+
"@rollup/rollup-linux-x64-gnu": "^4.52.3",
|
|
80
|
+
"@swc/core-linux-x64-gnu": "^1.13.20"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@chromatic-com/storybook": "^4.
|
|
83
|
+
"@chromatic-com/storybook": "^4.1.1",
|
|
84
84
|
"@linzjs/lui": "^23.11.1",
|
|
85
85
|
"@linzjs/style": "^5.4.0",
|
|
86
86
|
"@rollup/plugin-commonjs": "^28.0.6",
|
|
87
87
|
"@rollup/plugin-json": "^6.1.0",
|
|
88
88
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
89
89
|
"@semantic-release/git": "^10.0.1",
|
|
90
|
-
"@storybook/addon-docs": "^9.1.
|
|
91
|
-
"@storybook/addon-links": "^9.1.
|
|
92
|
-
"@storybook/react": "^9.1.
|
|
93
|
-
"@storybook/react-vite": "^9.1.
|
|
90
|
+
"@storybook/addon-docs": "^9.1.8",
|
|
91
|
+
"@storybook/addon-links": "^9.1.8",
|
|
92
|
+
"@storybook/react": "^9.1.8",
|
|
93
|
+
"@storybook/react-vite": "^9.1.8",
|
|
94
94
|
"@testing-library/dom": "^10.4.1",
|
|
95
95
|
"@testing-library/react": "^16.3.0",
|
|
96
96
|
"@testing-library/user-event": "^14.6.1",
|
|
@@ -100,42 +100,41 @@
|
|
|
100
100
|
"@types/node": "^22.17.0",
|
|
101
101
|
"@types/react": "^18.3.23",
|
|
102
102
|
"@types/react-dom": "^18.3.7",
|
|
103
|
-
"@types/uuid": "^10.0.0",
|
|
104
103
|
"@vitejs/plugin-react-swc": "^3.11.0",
|
|
105
104
|
"@vitest/ui": "^3.2.4",
|
|
106
|
-
"ag-grid-community": "^34.
|
|
107
|
-
"ag-grid-react": "^34.
|
|
105
|
+
"ag-grid-community": "^34.2.0",
|
|
106
|
+
"ag-grid-react": "^34.2.0",
|
|
108
107
|
"babel-preset-react-app": "^10.1.0",
|
|
109
108
|
"canvas": "^3.2.0",
|
|
110
|
-
"chromatic": "^13.
|
|
111
|
-
"cross-env": "^10.
|
|
109
|
+
"chromatic": "^13.3.0",
|
|
110
|
+
"cross-env": "^10.1.0",
|
|
112
111
|
"css-loader": "^7.1.2",
|
|
113
112
|
"eslint-plugin-react": "^7.37.5",
|
|
114
|
-
"eslint-plugin-storybook": "^9.1.
|
|
113
|
+
"eslint-plugin-storybook": "^9.1.8",
|
|
115
114
|
"jsdom": "^26.1.0",
|
|
116
115
|
"lodash-es": "^4.17.21",
|
|
117
116
|
"mkdirp": "^3.0.1",
|
|
118
117
|
"npm-run-all": "^4.1.5",
|
|
119
118
|
"postcss": "^8.5.6",
|
|
120
|
-
"postcss-loader": "^8.
|
|
119
|
+
"postcss-loader": "^8.2.0",
|
|
121
120
|
"postcss-scss": "^4.0.9",
|
|
122
121
|
"react": ">=18",
|
|
123
122
|
"react-app-polyfill": "^3.0.0",
|
|
124
123
|
"react-dom": "^18.3.1",
|
|
125
124
|
"rimraf": "^6.0.1",
|
|
126
|
-
"rollup": "^4.
|
|
125
|
+
"rollup": "^4.52.3",
|
|
127
126
|
"rollup-plugin-copy": "^3.5.0",
|
|
128
127
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
129
128
|
"rollup-plugin-postcss": "^4.0.2",
|
|
130
129
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
131
|
-
"sass": "^1.
|
|
130
|
+
"sass": "^1.93.2",
|
|
132
131
|
"sass-loader": "^16.0.5",
|
|
133
|
-
"semantic-release": "^24.2.
|
|
134
|
-
"storybook": "^9.1.
|
|
132
|
+
"semantic-release": "^24.2.9",
|
|
133
|
+
"storybook": "^9.1.8",
|
|
135
134
|
"storybook-css-modules-preset": "^1.1.1",
|
|
136
135
|
"style-loader": "^4.0.0",
|
|
137
136
|
"typescript": "^5.9.2",
|
|
138
|
-
"vite": "^
|
|
137
|
+
"vite": "^7.1.7",
|
|
139
138
|
"vite-plugin-html": "^3.2.2",
|
|
140
139
|
"vite-tsconfig-paths": "^5.1.4",
|
|
141
140
|
"vitest": "^3.2.4"
|
package/src/components/Grid.tsx
CHANGED
|
@@ -4,13 +4,14 @@ import {
|
|
|
4
4
|
CellClassParams,
|
|
5
5
|
CellClickedEvent,
|
|
6
6
|
CellDoubleClickedEvent,
|
|
7
|
-
|
|
7
|
+
CellFocusedEvent,
|
|
8
8
|
CellKeyDownEvent,
|
|
9
9
|
ColDef,
|
|
10
10
|
ColGroupDef,
|
|
11
11
|
ColumnResizedEvent,
|
|
12
12
|
EditableCallback,
|
|
13
13
|
EditableCallbackParams,
|
|
14
|
+
GetRowIdParams,
|
|
14
15
|
GridOptions,
|
|
15
16
|
GridReadyEvent,
|
|
16
17
|
ModelUpdatedEvent,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
RowDragEndEvent,
|
|
19
20
|
RowDragMoveEvent,
|
|
20
21
|
SelectionChangedEvent,
|
|
22
|
+
SelectionColumnDef,
|
|
21
23
|
} from 'ag-grid-community';
|
|
22
24
|
import { AgGridReact } from 'ag-grid-react';
|
|
23
25
|
import clsx from 'clsx';
|
|
@@ -25,7 +27,7 @@ import { defer, difference, isEmpty, last, omit, xorBy } from 'lodash-es';
|
|
|
25
27
|
import { ReactElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
26
28
|
import { useInterval } from 'usehooks-ts';
|
|
27
29
|
|
|
28
|
-
import {
|
|
30
|
+
import { useGridContext } from '../contexts/GridContext';
|
|
29
31
|
import { GridUpdatingContext } from '../contexts/GridUpdatingContext';
|
|
30
32
|
import { fnOrVar, isNotEmpty } from '../utils/util';
|
|
31
33
|
import { clickInputWhenContainingCellClicked } from './clickInputWhenContainingCellClicked';
|
|
@@ -36,36 +38,6 @@ import { usePostSortRowsHook } from './PostSortRowsHook';
|
|
|
36
38
|
|
|
37
39
|
ModuleRegistry.registerModules([AllCommunityModule]);
|
|
38
40
|
|
|
39
|
-
let timeOfLastSingleClick = 0;
|
|
40
|
-
let lastClickColId: unknown;
|
|
41
|
-
let lastClickRowIndex: unknown;
|
|
42
|
-
|
|
43
|
-
const resetClickDebounce = () => {
|
|
44
|
-
timeOfLastSingleClick = 0;
|
|
45
|
-
lastClickColId = '';
|
|
46
|
-
lastClickRowIndex = -1;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* If click is more than 200ms since last click return true.
|
|
51
|
-
*/
|
|
52
|
-
const clickDebounceSkipClick = (colId: unknown, rowIndex: unknown): boolean => {
|
|
53
|
-
const doubleClickMs = 200;
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
Date.now() - timeOfLastSingleClick < doubleClickMs &&
|
|
57
|
-
lastClickColId === colId &&
|
|
58
|
-
lastClickRowIndex === rowIndex
|
|
59
|
-
) {
|
|
60
|
-
// Skipping double click due to single click edit
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
timeOfLastSingleClick = Date.now();
|
|
64
|
-
lastClickColId = colId;
|
|
65
|
-
lastClickRowIndex = rowIndex;
|
|
66
|
-
return false;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
41
|
export interface GridBaseRow {
|
|
70
42
|
id: string | number;
|
|
71
43
|
}
|
|
@@ -99,6 +71,7 @@ export interface GridProps<TData extends GridBaseRow = GridBaseRow> {
|
|
|
99
71
|
rowClassRules?: GridOptions['rowClassRules'];
|
|
100
72
|
rowSelection?: 'single' | 'multiple';
|
|
101
73
|
autoSelectFirstRow?: boolean;
|
|
74
|
+
onCellFocused?: (props: { colDef: ColDef<TData>; data: TData }) => void;
|
|
102
75
|
onColumnMoved?: GridOptions['onColumnMoved'];
|
|
103
76
|
rowDragText?: GridOptions['rowDragText'];
|
|
104
77
|
onRowDragEnd?: (props: GridOnRowDragEndProps<TData>) => Promise<void> | void;
|
|
@@ -126,7 +99,7 @@ export interface GridProps<TData extends GridBaseRow = GridBaseRow> {
|
|
|
126
99
|
* When pressing tab whilst editing the grid will select and edit the next cell if available.
|
|
127
100
|
* Once the last cell to edit closes this callback is called.
|
|
128
101
|
*/
|
|
129
|
-
|
|
102
|
+
onBulkEditingComplete?: () => void;
|
|
130
103
|
|
|
131
104
|
/**
|
|
132
105
|
* Context menu definition if required.
|
|
@@ -182,13 +155,13 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
182
155
|
setExternallySelectedItemsAreInSync,
|
|
183
156
|
isExternalFilterPresent,
|
|
184
157
|
doesExternalFilterPass,
|
|
185
|
-
|
|
158
|
+
setOnBulkEditingComplete,
|
|
186
159
|
getColDef,
|
|
187
160
|
showNoRowsOverlay,
|
|
188
161
|
prePopupOps,
|
|
189
|
-
|
|
190
|
-
} =
|
|
191
|
-
|
|
162
|
+
startCellEditing,
|
|
163
|
+
} = useGridContext<TData>();
|
|
164
|
+
|
|
192
165
|
const { updatedDep, updatingCols } = useContext(GridUpdatingContext);
|
|
193
166
|
|
|
194
167
|
const gridDivRef = useRef<HTMLDivElement>(null);
|
|
@@ -273,7 +246,10 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
273
246
|
needsAutoSize.current = true;
|
|
274
247
|
}
|
|
275
248
|
}
|
|
276
|
-
if (
|
|
249
|
+
if (
|
|
250
|
+
needsAutoSize.current ||
|
|
251
|
+
(!hasSetContentSize.current && (sizeColumns === 'auto' || sizeColumns === 'auto-skip-headers'))
|
|
252
|
+
) {
|
|
277
253
|
needsAutoSize.current = false;
|
|
278
254
|
setInitialContentSize();
|
|
279
255
|
}
|
|
@@ -438,28 +414,11 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
438
414
|
event.api.showNoRowsOverlay();
|
|
439
415
|
}, []);
|
|
440
416
|
|
|
441
|
-
/**
|
|
442
|
-
* Force-refresh all selected rows to re-run class function, to update selection highlighting
|
|
443
|
-
*/
|
|
444
|
-
const refreshSelectedRows = useCallback((_event: CellEditingStartedEvent): void => {
|
|
445
|
-
// MATT Disabled I don't believe these are needed anymore
|
|
446
|
-
// I've left them here just in case they are
|
|
447
|
-
/*event.api.refreshCells({
|
|
448
|
-
force: true,
|
|
449
|
-
rowNodes: event.api.getSelectedNodes(),
|
|
450
|
-
});*/
|
|
451
|
-
}, []);
|
|
452
|
-
|
|
453
417
|
/**
|
|
454
418
|
* Handle double click edit
|
|
455
419
|
*/
|
|
456
420
|
const onCellDoubleClick = useCallback(
|
|
457
421
|
(event: CellDoubleClickedEvent) => {
|
|
458
|
-
if (clickDebounceSkipClick(event.colDef.colId, event.rowIndex)) {
|
|
459
|
-
// the next click will be a single click, we want it to pass
|
|
460
|
-
resetClickDebounce();
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
422
|
const editable = fnOrVar(event.colDef?.editable, event);
|
|
464
423
|
if (editable && !invokeEditAction(event)) {
|
|
465
424
|
void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
|
|
@@ -475,9 +434,6 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
475
434
|
(event: CellClickedEvent) => {
|
|
476
435
|
const editable = fnOrVar(event.colDef?.editable, event);
|
|
477
436
|
if ((editable && event.colDef.singleClickEdit) ?? singleClickEdit) {
|
|
478
|
-
if (clickDebounceSkipClick(event.colDef.colId, event.rowIndex)) {
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
437
|
void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
|
|
482
438
|
}
|
|
483
439
|
},
|
|
@@ -587,11 +543,10 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
587
543
|
useEffect(() => {
|
|
588
544
|
const newLoading = !rowData || params.loading === true;
|
|
589
545
|
if (newLoading && !prevLoading.current) {
|
|
590
|
-
stopEditing();
|
|
591
546
|
showNoRowsOverlay();
|
|
592
547
|
}
|
|
593
548
|
prevLoading.current = newLoading;
|
|
594
|
-
}, [params.loading, rowData, showNoRowsOverlay
|
|
549
|
+
}, [params.loading, rowData, showNoRowsOverlay]);
|
|
595
550
|
|
|
596
551
|
/**
|
|
597
552
|
* Resize columns to fit if required on window/container resize
|
|
@@ -664,6 +619,27 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
664
619
|
[clearHighlightRowClasses],
|
|
665
620
|
);
|
|
666
621
|
|
|
622
|
+
const onCellFocused = useCallback(
|
|
623
|
+
(event: CellFocusedEvent<TData>) => {
|
|
624
|
+
if (!params.onCellFocused || event.rowIndex == null) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
const api = event.api;
|
|
628
|
+
const rowNode = api.getDisplayedRowAtIndex(event.rowIndex);
|
|
629
|
+
const data = rowNode?.data;
|
|
630
|
+
const column = event.column;
|
|
631
|
+
if (!data || !column || typeof column === 'string') {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
const colDef = column.getColDef();
|
|
635
|
+
if (!colDef || typeof colDef === 'string') {
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
params.onCellFocused({ colDef, data });
|
|
639
|
+
},
|
|
640
|
+
[params],
|
|
641
|
+
);
|
|
642
|
+
|
|
667
643
|
const onRowDragEnd = useCallback(
|
|
668
644
|
(event: RowDragEndEvent<TData>) => {
|
|
669
645
|
clearHighlightRowClasses();
|
|
@@ -695,10 +671,77 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
695
671
|
}, [params.setExternalSelectedItems, selectable]);
|
|
696
672
|
|
|
697
673
|
// This is setting a ref in the GridContext so won't be triggering an update loop
|
|
698
|
-
|
|
674
|
+
setOnBulkEditingComplete(params.onBulkEditingComplete);
|
|
675
|
+
|
|
676
|
+
const getRowId = useCallback((params: GetRowIdParams<TData, unknown>) => `${params.data.id}`, []);
|
|
677
|
+
const defaultColDef = useMemo(
|
|
678
|
+
(): ColDef<TData, unknown> => ({
|
|
679
|
+
minWidth: 48,
|
|
680
|
+
...omit(params.defaultColDef, ['editable', 'field', 'colId', 'tooltipField']),
|
|
681
|
+
}),
|
|
682
|
+
[params.defaultColDef],
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
const noRowsOverlayComponent = useCallback(
|
|
686
|
+
(event: AgGridEvent) => {
|
|
687
|
+
const headerRowCount = columnDefs.some((c) => (c as any).children) ? 2 : 1;
|
|
688
|
+
|
|
689
|
+
let rowCount = 0;
|
|
690
|
+
event.api.forEachNode(() => rowCount++);
|
|
691
|
+
return (
|
|
692
|
+
<GridNoRowsOverlay
|
|
693
|
+
loading={!rowData || params.loading === true}
|
|
694
|
+
rowCount={rowCount}
|
|
695
|
+
headerRowHeight={headerRowCount * rowHeight}
|
|
696
|
+
filteredRowCount={event.api.getDisplayedRowCount()}
|
|
697
|
+
noRowsOverlayText={params.noRowsOverlayText}
|
|
698
|
+
noRowsMatchingOverlayText={params.noRowsMatchingOverlayText}
|
|
699
|
+
/>
|
|
700
|
+
);
|
|
701
|
+
},
|
|
702
|
+
[columnDefs, params.loading, params.noRowsMatchingOverlayText, params.noRowsOverlayText, rowData, rowHeight],
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
const selectionColumnDef = useMemo((): SelectionColumnDef => {
|
|
706
|
+
const selectWidth = params.hideSelectColumn ? 0 : selectable && params.onRowDragEnd ? 76 : 48;
|
|
707
|
+
return {
|
|
708
|
+
suppressNavigable: params.hideSelectColumn,
|
|
709
|
+
rowDrag: !!params.onRowDragEnd,
|
|
710
|
+
minWidth: selectWidth,
|
|
711
|
+
maxWidth: selectWidth,
|
|
712
|
+
pinned: selectColumnPinned,
|
|
713
|
+
headerComponentParams: {
|
|
714
|
+
exportable: false,
|
|
715
|
+
},
|
|
716
|
+
headerClass: clsx('ag-header-hide-default-select', params.onRowDragEnd && 'ag-header-select-draggable'),
|
|
717
|
+
headerComponent: rowSelection == 'multiple' ? GridHeaderSelect : undefined,
|
|
718
|
+
suppressHeaderKeyboardEvent: (e) => {
|
|
719
|
+
if (!selectable) return false;
|
|
720
|
+
if ((e.event.key === 'Enter' || e.event.key === ' ') && !e.event.repeat) {
|
|
721
|
+
if (isEmpty(e.api.getSelectedRows())) {
|
|
722
|
+
e.api.selectAll('filtered');
|
|
723
|
+
} else {
|
|
724
|
+
e.api.deselectAll();
|
|
725
|
+
}
|
|
726
|
+
return true;
|
|
727
|
+
}
|
|
728
|
+
return false;
|
|
729
|
+
},
|
|
730
|
+
onCellClicked:
|
|
731
|
+
params.enableSelectionWithoutKeys || params.enableClickSelection
|
|
732
|
+
? undefined
|
|
733
|
+
: clickInputWhenContainingCellClicked,
|
|
734
|
+
};
|
|
735
|
+
}, [
|
|
736
|
+
params.enableClickSelection,
|
|
737
|
+
params.enableSelectionWithoutKeys,
|
|
738
|
+
params.hideSelectColumn,
|
|
739
|
+
params.onRowDragEnd,
|
|
740
|
+
rowSelection,
|
|
741
|
+
selectColumnPinned,
|
|
742
|
+
selectable,
|
|
743
|
+
]);
|
|
699
744
|
|
|
700
|
-
const selectWidth = params.hideSelectColumn ? 0 : selectable && params.onRowDragEnd ? 76 : 48;
|
|
701
|
-
const headerRowCount = columnDefs.some((c) => (c as any).children) ? 2 : 1;
|
|
702
745
|
return (
|
|
703
746
|
<div
|
|
704
747
|
data-testid={dataTestId}
|
|
@@ -726,45 +769,30 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
726
769
|
rowHeight={rowHeight}
|
|
727
770
|
animateRows={params.animateRows ?? false}
|
|
728
771
|
rowClassRules={params.rowClassRules}
|
|
729
|
-
getRowId={
|
|
772
|
+
getRowId={getRowId}
|
|
730
773
|
onGridSizeChanged={onGridSizeChanged}
|
|
731
774
|
suppressColumnVirtualisation={suppressColumnVirtualization}
|
|
732
775
|
suppressClickEdit={true}
|
|
733
776
|
onColumnVisible={setInitialContentSize}
|
|
734
777
|
onRowDataUpdated={onRowDataChanged}
|
|
778
|
+
onCellFocused={onCellFocused}
|
|
735
779
|
onCellKeyDown={onCellKeyPress}
|
|
736
780
|
onCellClicked={onCellClicked}
|
|
737
781
|
onCellDoubleClicked={onCellDoubleClick}
|
|
738
|
-
onCellEditingStarted={refreshSelectedRows}
|
|
739
782
|
domLayout={params.domLayout}
|
|
740
783
|
onColumnResized={onColumnResized}
|
|
741
|
-
defaultColDef={
|
|
784
|
+
defaultColDef={defaultColDef}
|
|
742
785
|
columnDefs={columnDefsAdjusted}
|
|
786
|
+
selectionColumnDef={selectionColumnDef}
|
|
743
787
|
rowData={rowData}
|
|
744
|
-
|
|
745
|
-
let rowCount = 0;
|
|
746
|
-
event.api.forEachNode(() => rowCount++);
|
|
747
|
-
return (
|
|
748
|
-
<GridNoRowsOverlay
|
|
749
|
-
loading={!rowData || params.loading === true}
|
|
750
|
-
rowCount={rowCount}
|
|
751
|
-
headerRowHeight={headerRowCount * rowHeight}
|
|
752
|
-
filteredRowCount={event.api.getDisplayedRowCount()}
|
|
753
|
-
noRowsOverlayText={params.noRowsOverlayText}
|
|
754
|
-
noRowsMatchingOverlayText={params.noRowsMatchingOverlayText}
|
|
755
|
-
/>
|
|
756
|
-
);
|
|
757
|
-
}}
|
|
758
|
-
quickFilterParser={(filterStr) => {
|
|
759
|
-
// filter is exact matches exactly groups separated by commas
|
|
760
|
-
return filterStr.split(',').map((str) => str.trim());
|
|
761
|
-
}}
|
|
788
|
+
postSortRows={params.onRowDragEnd || !defaultPostSort ? undefined : postSortRows}
|
|
762
789
|
onModelUpdated={onModelUpdated}
|
|
763
790
|
onGridReady={onGridReady}
|
|
764
791
|
onSortChanged={ensureSelectedRowIsVisible}
|
|
765
|
-
|
|
792
|
+
quickFilterParser={quickFilterParser}
|
|
766
793
|
onSelectionChanged={synchroniseExternalStateToGridSelection}
|
|
767
794
|
onColumnMoved={params.onColumnMoved}
|
|
795
|
+
noRowsOverlayComponent={noRowsOverlayComponent}
|
|
768
796
|
alwaysShowVerticalScroll={params.alwaysShowVerticalScroll}
|
|
769
797
|
isExternalFilterPresent={isExternalFilterPresent}
|
|
770
798
|
doesExternalFilterPass={doesExternalFilterPass}
|
|
@@ -778,36 +806,13 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
778
806
|
suppressCellFocus={params.suppressCellFocus}
|
|
779
807
|
pinnedTopRowData={params.pinnedTopRowData}
|
|
780
808
|
pinnedBottomRowData={params.pinnedBottomRowData}
|
|
781
|
-
selectionColumnDef={{
|
|
782
|
-
suppressNavigable: params.hideSelectColumn,
|
|
783
|
-
rowDrag: !!params.onRowDragEnd,
|
|
784
|
-
minWidth: selectWidth,
|
|
785
|
-
maxWidth: selectWidth,
|
|
786
|
-
pinned: selectColumnPinned,
|
|
787
|
-
headerComponentParams: {
|
|
788
|
-
exportable: false,
|
|
789
|
-
},
|
|
790
|
-
headerClass: clsx('ag-header-hide-default-select', params.onRowDragEnd && 'ag-header-select-draggable'),
|
|
791
|
-
headerComponent: rowSelection == 'multiple' ? GridHeaderSelect : undefined,
|
|
792
|
-
suppressHeaderKeyboardEvent: (e) => {
|
|
793
|
-
if (!selectable) return false;
|
|
794
|
-
if ((e.event.key === 'Enter' || e.event.key === ' ') && !e.event.repeat) {
|
|
795
|
-
if (isEmpty(e.api.getSelectedRows())) {
|
|
796
|
-
e.api.selectAll('filtered');
|
|
797
|
-
} else {
|
|
798
|
-
e.api.deselectAll();
|
|
799
|
-
}
|
|
800
|
-
return true;
|
|
801
|
-
}
|
|
802
|
-
return false;
|
|
803
|
-
},
|
|
804
|
-
onCellClicked:
|
|
805
|
-
params.enableSelectionWithoutKeys || params.enableClickSelection
|
|
806
|
-
? undefined
|
|
807
|
-
: clickInputWhenContainingCellClicked,
|
|
808
|
-
}}
|
|
809
809
|
/>
|
|
810
810
|
</div>
|
|
811
811
|
</div>
|
|
812
812
|
);
|
|
813
813
|
};
|
|
814
|
+
|
|
815
|
+
const quickFilterParser = (filterStr: string) => {
|
|
816
|
+
// filter is exact matches exactly groups separated by commas
|
|
817
|
+
return filterStr.split(',').map((str) => str.trim());
|
|
818
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ReactElement, useCallback,
|
|
1
|
+
import { ReactElement, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useGridContext } from '../contexts/GridContext';
|
|
4
4
|
import { useGridPopoverContext } from '../contexts/GridPopoverContext';
|
|
5
5
|
import { ControlledMenu } from '../react-menu3';
|
|
6
6
|
import { MenuCloseEvent } from '../react-menu3/types';
|
|
@@ -21,8 +21,8 @@ export interface GridPopoverHookProps<TData> {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export const useGridPopoverHook = <TData extends GridBaseRow>(props: GridPopoverHookProps<TData>) => {
|
|
24
|
-
const {
|
|
25
|
-
const { anchorRef, saving, updateValue } = useGridPopoverContext<TData>();
|
|
24
|
+
const { onBulkEditingComplete } = useGridContext<TData>();
|
|
25
|
+
const { anchorRef, saving, updateValue, stopEditing } = useGridPopoverContext<TData>();
|
|
26
26
|
const saveButtonRef = useRef<HTMLButtonElement>(null);
|
|
27
27
|
const [isOpen, setOpen] = useState(false);
|
|
28
28
|
|
|
@@ -33,29 +33,32 @@ export const useGridPopoverHook = <TData extends GridBaseRow>(props: GridPopover
|
|
|
33
33
|
const triggerSave = useCallback(
|
|
34
34
|
async (reason?: string) => {
|
|
35
35
|
if (reason == CloseReason.CANCEL) {
|
|
36
|
-
|
|
36
|
+
stopEditing();
|
|
37
|
+
onBulkEditingComplete();
|
|
37
38
|
return;
|
|
38
39
|
}
|
|
39
|
-
if (props
|
|
40
|
+
if (props?.invalid?.()) {
|
|
41
|
+
// Don't close, don't do anything it's invalid
|
|
40
42
|
return;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
if (!props.save) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
// No save method so just close
|
|
47
|
+
stopEditing();
|
|
48
|
+
onBulkEditingComplete();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (
|
|
53
|
+
await updateValue(
|
|
54
|
+
props.save,
|
|
55
|
+
reason === CloseReason.TAB_FORWARD ? 1 : reason === CloseReason.TAB_BACKWARD ? -1 : 0,
|
|
56
|
+
)
|
|
57
|
+
) {
|
|
58
|
+
stopEditing();
|
|
56
59
|
}
|
|
57
60
|
},
|
|
58
|
-
[
|
|
61
|
+
[onBulkEditingComplete, props, stopEditing, updateValue],
|
|
59
62
|
);
|
|
60
63
|
|
|
61
64
|
const popoverWrapper = useCallback(
|
|
@@ -72,7 +75,9 @@ export const useGridPopoverHook = <TData extends GridBaseRow>(props: GridPopover
|
|
|
72
75
|
menuClassName={'step-ag-grid-react-menu'}
|
|
73
76
|
onClose={(event: MenuCloseEvent) => {
|
|
74
77
|
// Prevent menu from closing when modals are invoked
|
|
75
|
-
if (event.reason === CloseReason.BLUR)
|
|
78
|
+
if (event.reason === CloseReason.BLUR) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
76
81
|
void triggerSave(event.reason);
|
|
77
82
|
}}
|
|
78
83
|
viewScroll={'auto'}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { GridFilterExternal, useGridContext } from '../../contexts/GridContext';
|
|
4
4
|
import { GridBaseRow } from '../Grid';
|
|
5
5
|
|
|
6
6
|
export const useGridFilter = <TData extends GridBaseRow>(filter: GridFilterExternal<TData> | undefined) => {
|
|
7
|
-
const { addExternalFilter, removeExternalFilter } =
|
|
7
|
+
const { addExternalFilter, removeExternalFilter } = useGridContext<TData>();
|
|
8
8
|
|
|
9
9
|
useEffect(() => {
|
|
10
10
|
const thisFilter = filter;
|
|
@@ -24,7 +24,7 @@ export const useGridContextMenu = <TData extends GridBaseRow>({
|
|
|
24
24
|
contextMenuSelectRow: boolean;
|
|
25
25
|
contextMenu?: GridContextMenuComponent<TData>;
|
|
26
26
|
}) => {
|
|
27
|
-
const { redrawRows, prePopupOps,
|
|
27
|
+
const { redrawRows, prePopupOps, resetFocusedCellAfterCellEditing, getSelectedRows } = useContext(GridContext);
|
|
28
28
|
|
|
29
29
|
const [isOpen, setOpen] = useState(false);
|
|
30
30
|
const [anchorPoint, setAnchorPoint] = useState({ x: 0, y: 0 });
|
|
@@ -47,8 +47,8 @@ export const useGridContextMenu = <TData extends GridBaseRow>({
|
|
|
47
47
|
const closeMenu = useCallback(() => {
|
|
48
48
|
setOpen(false);
|
|
49
49
|
redrawRows();
|
|
50
|
-
|
|
51
|
-
}, [
|
|
50
|
+
resetFocusedCellAfterCellEditing();
|
|
51
|
+
}, [resetFocusedCellAfterCellEditing, redrawRows]);
|
|
52
52
|
|
|
53
53
|
const cellContextMenu = useCallback(
|
|
54
54
|
(event: CellContextMenuEvent) => {
|
|
@@ -25,7 +25,6 @@ export interface GridContextType<TData extends GridBaseRow> {
|
|
|
25
25
|
getColumnIds: (filter?: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string)) => string[];
|
|
26
26
|
setApis: (gridApi: GridApi | undefined, hasExternallySelectedItems: boolean, dataTestId?: string) => void;
|
|
27
27
|
prePopupOps: () => void;
|
|
28
|
-
postPopupOps: () => void;
|
|
29
28
|
setQuickFilter: (quickFilter: string) => void;
|
|
30
29
|
editingCells: () => boolean;
|
|
31
30
|
getSelectedRows: <T extends GridBaseRow>() => T[];
|
|
@@ -44,9 +43,9 @@ export interface GridContextType<TData extends GridBaseRow> {
|
|
|
44
43
|
getFirstRowId: () => number;
|
|
45
44
|
autoSizeColumns: (props?: AutoSizeColumnsProps) => AutoSizeColumnsResult;
|
|
46
45
|
sizeColumnsToFit: () => void;
|
|
47
|
-
cancelEdit: () => void;
|
|
48
46
|
startCellEditing: ({ rowId, colId }: { rowId: number; colId: string }) => Promise<void>;
|
|
49
|
-
|
|
47
|
+
// Restores the previous focus after cell editing
|
|
48
|
+
resetFocusedCellAfterCellEditing: () => void;
|
|
50
49
|
updatingCells: (
|
|
51
50
|
props: { selectedRows: GridBaseRow[]; field?: string },
|
|
52
51
|
fnUpdate: (selectedRows: any[]) => Promise<boolean>,
|
|
@@ -64,7 +63,8 @@ export interface GridContextType<TData extends GridBaseRow> {
|
|
|
64
63
|
invisibleColumnIds: string[] | undefined;
|
|
65
64
|
setInvisibleColumnIds: (colIds: string[]) => void;
|
|
66
65
|
downloadCsv: (csvExportParams?: CsvExportParams) => void;
|
|
67
|
-
|
|
66
|
+
onBulkEditingComplete: () => void;
|
|
67
|
+
setOnBulkEditingComplete: (callback: (() => void) | undefined) => void;
|
|
68
68
|
showNoRowsOverlay: () => void;
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -90,9 +90,6 @@ export const GridContext = createContext<GridContextType<any>>({
|
|
|
90
90
|
prePopupOps: () => {
|
|
91
91
|
console.error('no context provider for prePopupOps');
|
|
92
92
|
},
|
|
93
|
-
postPopupOps: () => {
|
|
94
|
-
console.error('no context provider for prePopupOps');
|
|
95
|
-
},
|
|
96
93
|
externallySelectedItemsAreInSync: false,
|
|
97
94
|
setApis: () => {
|
|
98
95
|
console.error('no context provider for setApis');
|
|
@@ -164,15 +161,12 @@ export const GridContext = createContext<GridContextType<any>>({
|
|
|
164
161
|
console.error('no context provider for editingCells');
|
|
165
162
|
return false;
|
|
166
163
|
},
|
|
167
|
-
cancelEdit: () => {
|
|
168
|
-
console.error('no context provider for cancelEdit');
|
|
169
|
-
},
|
|
170
164
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
171
165
|
startCellEditing: async () => {
|
|
172
166
|
console.error('no context provider for startCellEditing');
|
|
173
167
|
},
|
|
174
|
-
|
|
175
|
-
console.error('no context provider for
|
|
168
|
+
resetFocusedCellAfterCellEditing: () => {
|
|
169
|
+
console.error('no context provider for resetFocusedCellAfterCellEditing');
|
|
176
170
|
},
|
|
177
171
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
178
172
|
updatingCells: async () => {
|
|
@@ -206,8 +200,11 @@ export const GridContext = createContext<GridContextType<any>>({
|
|
|
206
200
|
downloadCsv: () => {
|
|
207
201
|
console.error('no context provider for downloadCsv');
|
|
208
202
|
},
|
|
209
|
-
|
|
210
|
-
console.error('no context provider for
|
|
203
|
+
onBulkEditingComplete: () => {
|
|
204
|
+
console.error('no context provider for onBulkEditingComplete');
|
|
205
|
+
},
|
|
206
|
+
setOnBulkEditingComplete: () => {
|
|
207
|
+
console.error('no context provider for setOnBulkEditingComplete');
|
|
211
208
|
},
|
|
212
209
|
showNoRowsOverlay: () => {
|
|
213
210
|
console.error('no context provider for showLoadingOverlay');
|