@linzjs/step-ag-grid 14.3.2 → 14.4.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/src/contexts/GridContext.d.ts +7 -2
- package/dist/src/contexts/GridUpdatingContext.d.ts +1 -1
- package/dist/step-ag-grid.esm.js +95 -59
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Grid.tsx +37 -61
- package/src/contexts/GridContext.tsx +11 -2
- package/src/contexts/GridContextProvider.tsx +43 -1
- package/src/contexts/GridUpdatingContext.tsx +3 -3
- package/src/contexts/GridUpdatingContextProvider.tsx +3 -4
package/package.json
CHANGED
package/src/components/Grid.tsx
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { CellClickedEvent, ColDef, ColumnResizedEvent, ModelUpdatedEvent } from "ag-grid-community";
|
|
2
2
|
import { CellClassParams, EditableCallback, EditableCallbackParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
3
3
|
import { GridOptions } from "ag-grid-community/dist/lib/entities/gridOptions";
|
|
4
|
-
import {
|
|
5
|
-
CellEditingStoppedEvent,
|
|
6
|
-
CellEvent,
|
|
7
|
-
GridReadyEvent,
|
|
8
|
-
SelectionChangedEvent,
|
|
9
|
-
} from "ag-grid-community/dist/lib/events";
|
|
4
|
+
import { CellEvent, GridReadyEvent, SelectionChangedEvent } from "ag-grid-community/dist/lib/events";
|
|
10
5
|
import { AgGridReact } from "ag-grid-react";
|
|
11
6
|
import clsx from "clsx";
|
|
12
7
|
import { difference, isEmpty, last, omit, xorBy } from "lodash-es";
|
|
@@ -88,7 +83,6 @@ export const Grid = ({
|
|
|
88
83
|
const {
|
|
89
84
|
gridReady,
|
|
90
85
|
setApis,
|
|
91
|
-
prePopupOps,
|
|
92
86
|
ensureRowVisible,
|
|
93
87
|
getFirstRowId,
|
|
94
88
|
selectRowsById,
|
|
@@ -101,8 +95,10 @@ export const Grid = ({
|
|
|
101
95
|
isExternalFilterPresent,
|
|
102
96
|
doesExternalFilterPass,
|
|
103
97
|
setOnCellEditingComplete,
|
|
98
|
+
getColDef,
|
|
104
99
|
} = useContext(GridContext);
|
|
105
|
-
const {
|
|
100
|
+
const { updatedDep, updatingCols } = useContext(GridUpdatingContext);
|
|
101
|
+
const gridContext = useContext(GridContext);
|
|
106
102
|
|
|
107
103
|
const gridDivRef = useRef<HTMLDivElement>(null);
|
|
108
104
|
|
|
@@ -351,12 +347,12 @@ export const Grid = ({
|
|
|
351
347
|
lastUpdatedDep.current = updatedDep;
|
|
352
348
|
|
|
353
349
|
// Don't update while there are spinners
|
|
354
|
-
if (
|
|
350
|
+
if (!isEmpty(updatingCols())) return;
|
|
355
351
|
|
|
356
352
|
const skipHeader = sizeColumns === "auto-skip-headers";
|
|
357
353
|
autoSizeColumns({ skipHeader, userSizedColIds: userSizedColIds.current, colIds: colIdsEdited.current });
|
|
358
354
|
colIdsEdited.current.clear();
|
|
359
|
-
}, [autoSizeColumns,
|
|
355
|
+
}, [autoSizeColumns, params.rowData?.length, setInitialContentSize, sizeColumns, updatedDep, updatingCols]);
|
|
360
356
|
|
|
361
357
|
/**
|
|
362
358
|
* Show/hide no rows overlay when model changes.
|
|
@@ -391,23 +387,13 @@ export const Grid = ({
|
|
|
391
387
|
*/
|
|
392
388
|
const startCellEditing = useCallback(
|
|
393
389
|
(event: CellEvent) => {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
// Cell already being edited, so don't re-edit until finished
|
|
399
|
-
if (checkUpdating([event.colDef.field ?? ""], event.data.id)) {
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (event.rowIndex !== null) {
|
|
404
|
-
event.api.startEditingCell({
|
|
405
|
-
rowIndex: event.rowIndex,
|
|
406
|
-
colKey: event.column.getColId(),
|
|
390
|
+
event.data.id &&
|
|
391
|
+
gridContext.startCellEditing({
|
|
392
|
+
rowId: event.data.id,
|
|
393
|
+
colId: event.column.getColId(),
|
|
407
394
|
});
|
|
408
|
-
}
|
|
409
395
|
},
|
|
410
|
-
[
|
|
396
|
+
[gridContext],
|
|
411
397
|
);
|
|
412
398
|
|
|
413
399
|
/**
|
|
@@ -478,48 +464,39 @@ export const Grid = ({
|
|
|
478
464
|
* Set of colIds that need auto-sizing.
|
|
479
465
|
*/
|
|
480
466
|
const colIdsEdited = useRef(new Set<string>());
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* When cell editing has completed tag the colId as needing auto-sizing
|
|
484
|
-
*/
|
|
485
|
-
const onCellEditingStopped = useCallback(
|
|
486
|
-
(e: CellEditingStoppedEvent) => {
|
|
487
|
-
const skipHeader = sizeColumns === "auto-skip-headers";
|
|
488
|
-
if (sizeColumns === "auto" || skipHeader) {
|
|
489
|
-
// This may be wrong as the cell update hasn't completed?
|
|
490
|
-
const colId = e.colDef.colId;
|
|
491
|
-
if (colId && !e.colDef.flex) {
|
|
492
|
-
// This auto-sizes based on updatingContext completing
|
|
493
|
-
colIdsEdited.current.add(colId);
|
|
494
|
-
// This auto-sizes immediately in case it was an in place update
|
|
495
|
-
!isUpdating() &&
|
|
496
|
-
autoSizeColumns({
|
|
497
|
-
skipHeader,
|
|
498
|
-
userSizedColIds: userSizedColIds.current,
|
|
499
|
-
colIds: [colId],
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
},
|
|
504
|
-
[autoSizeColumns, isUpdating, sizeColumns],
|
|
505
|
-
);
|
|
506
|
-
|
|
507
467
|
const lastUpdatedDep = useRef(updatedDep);
|
|
508
468
|
|
|
509
469
|
/**
|
|
510
|
-
*
|
|
470
|
+
* When cell editing has completed the colId as needing auto-sizing
|
|
511
471
|
*/
|
|
512
472
|
useEffect(() => {
|
|
513
|
-
if (lastUpdatedDep.current === updatedDep
|
|
473
|
+
if (lastUpdatedDep.current === updatedDep) return;
|
|
514
474
|
lastUpdatedDep.current = updatedDep;
|
|
515
475
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
476
|
+
const colIds = updatingCols();
|
|
477
|
+
// Updating possibly completed
|
|
478
|
+
if (isEmpty(colIds)) {
|
|
479
|
+
// Columns to resize?
|
|
480
|
+
if (!isEmpty(colIdsEdited.current)) {
|
|
481
|
+
const skipHeader = sizeColumns === "auto-skip-headers";
|
|
482
|
+
if (sizeColumns === "auto" || skipHeader) {
|
|
483
|
+
autoSizeColumns({
|
|
484
|
+
skipHeader,
|
|
485
|
+
userSizedColIds: userSizedColIds.current,
|
|
486
|
+
colIds: colIdsEdited.current,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
colIdsEdited.current.clear();
|
|
490
|
+
}
|
|
491
|
+
} else {
|
|
492
|
+
// Updates not complete, add them to a list of columns needing resize
|
|
493
|
+
colIds.forEach((colId) => {
|
|
494
|
+
if (colId && !getColDef(colId)?.flex) {
|
|
495
|
+
colIdsEdited.current.add(colId);
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
}, [autoSizeColumns, getColDef, sizeColumns, updatedDep, updatingCols]);
|
|
523
500
|
|
|
524
501
|
/**
|
|
525
502
|
* Resize columns to fit if required on window/container resize
|
|
@@ -583,7 +560,6 @@ export const Grid = ({
|
|
|
583
560
|
onCellDoubleClicked={onCellDoubleClick}
|
|
584
561
|
onCellEditingStarted={refreshSelectedRows}
|
|
585
562
|
domLayout={params.domLayout}
|
|
586
|
-
onCellEditingStopped={onCellEditingStopped}
|
|
587
563
|
onColumnResized={onColumnResized}
|
|
588
564
|
defaultColDef={{ minWidth: 48, ...omit(params.defaultColDef, ["editable"]) }}
|
|
589
565
|
columnDefs={columnDefsAdjusted}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColumnApi, GridApi, RowNode } from "ag-grid-community";
|
|
1
|
+
import { ColDef, ColumnApi, GridApi, RowNode } from "ag-grid-community";
|
|
2
2
|
import { CsvExportParams } from "ag-grid-community/dist/lib/interfaces/exportParams";
|
|
3
3
|
import { createContext, useContext } from "react";
|
|
4
4
|
|
|
@@ -16,6 +16,8 @@ export type AutoSizeColumnsResult = { width: number } | null;
|
|
|
16
16
|
|
|
17
17
|
export interface GridContextType<RowType extends GridBaseRow> {
|
|
18
18
|
gridReady: boolean;
|
|
19
|
+
getColDef: (colId?: string) => ColDef | undefined;
|
|
20
|
+
getColumns: () => ColDefT<RowType>[];
|
|
19
21
|
setApis: (gridApi: GridApi | undefined, columnApi: ColumnApi | undefined, dataTestId?: string) => void;
|
|
20
22
|
prePopupOps: () => void;
|
|
21
23
|
setQuickFilter: (quickFilter: string) => void;
|
|
@@ -37,6 +39,7 @@ export interface GridContextType<RowType extends GridBaseRow> {
|
|
|
37
39
|
autoSizeColumns: (props?: AutoSizeColumnsProps) => AutoSizeColumnsResult;
|
|
38
40
|
sizeColumnsToFit: () => void;
|
|
39
41
|
cancelEdit: () => void;
|
|
42
|
+
startCellEditing: ({ rowId, colId }: { rowId: number; colId: string }) => void;
|
|
40
43
|
stopEditing: () => void;
|
|
41
44
|
updatingCells: (
|
|
42
45
|
props: { selectedRows: GridBaseRow[]; field?: string },
|
|
@@ -52,7 +55,6 @@ export interface GridContextType<RowType extends GridBaseRow> {
|
|
|
52
55
|
removeExternalFilter: (filter: GridFilterExternal<RowType>) => void;
|
|
53
56
|
isExternalFilterPresent: () => boolean;
|
|
54
57
|
doesExternalFilterPass: (node: RowNode) => boolean;
|
|
55
|
-
getColumns: () => ColDefT<RowType>[];
|
|
56
58
|
invisibleColumnIds: string[];
|
|
57
59
|
setInvisibleColumnIds: (colIds: string[]) => void;
|
|
58
60
|
downloadCsv: (csvExportParams?: CsvExportParams) => void;
|
|
@@ -61,6 +63,10 @@ export interface GridContextType<RowType extends GridBaseRow> {
|
|
|
61
63
|
|
|
62
64
|
export const GridContext = createContext<GridContextType<any>>({
|
|
63
65
|
gridReady: false,
|
|
66
|
+
getColDef: () => {
|
|
67
|
+
console.error("no context provider for getColDef");
|
|
68
|
+
return undefined;
|
|
69
|
+
},
|
|
64
70
|
getColumns: () => {
|
|
65
71
|
console.error("no context provider for getColumns");
|
|
66
72
|
return [];
|
|
@@ -142,6 +148,9 @@ export const GridContext = createContext<GridContextType<any>>({
|
|
|
142
148
|
cancelEdit: () => {
|
|
143
149
|
console.error("no context provider for cancelEdit");
|
|
144
150
|
},
|
|
151
|
+
startCellEditing: () => {
|
|
152
|
+
console.error("no context provider for startCellEditing");
|
|
153
|
+
},
|
|
145
154
|
stopEditing: () => {
|
|
146
155
|
console.error("no context provider for stopEditing");
|
|
147
156
|
},
|
|
@@ -21,7 +21,7 @@ interface GridContextProps {
|
|
|
21
21
|
* Also, make sure the provider is created in a separate component, otherwise it won't be found.
|
|
22
22
|
*/
|
|
23
23
|
export const GridContextProvider = <RowType extends GridBaseRow>(props: GridContextProps): ReactElement => {
|
|
24
|
-
const { modifyUpdating } = useContext(GridUpdatingContext);
|
|
24
|
+
const { modifyUpdating, checkUpdating } = useContext(GridUpdatingContext);
|
|
25
25
|
const [gridApi, setGridApi] = useState<GridApi>();
|
|
26
26
|
const [columnApi, setColumnApi] = useState<ColumnApi>();
|
|
27
27
|
const [gridReady, setGridReady] = useState(false);
|
|
@@ -377,6 +377,41 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
377
377
|
gridApi.stopEditing();
|
|
378
378
|
}, [gridApi]);
|
|
379
379
|
|
|
380
|
+
const startCellEditing = useCallback(
|
|
381
|
+
async ({ rowId, colId }: { rowId: number; colId: string }) => {
|
|
382
|
+
if (!gridApi) return;
|
|
383
|
+
|
|
384
|
+
const colDef = gridApi.getColumnDef(colId);
|
|
385
|
+
if (!colDef) return;
|
|
386
|
+
|
|
387
|
+
// Cell already being edited, so don't re-edit until finished
|
|
388
|
+
if (checkUpdating([colDef.field ?? ""], rowId)) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const rowNode = gridApi.getRowNode(`${rowId}`);
|
|
392
|
+
if (!rowNode) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (!rowNode.isSelected()) {
|
|
397
|
+
rowNode.setSelected(true, true);
|
|
398
|
+
}
|
|
399
|
+
prePopupOps();
|
|
400
|
+
|
|
401
|
+
const rowIndex = rowNode.rowIndex;
|
|
402
|
+
if (rowIndex != null) {
|
|
403
|
+
const focusAndEdit = () => {
|
|
404
|
+
gridApi.startEditingCell({
|
|
405
|
+
rowIndex,
|
|
406
|
+
colKey: colId,
|
|
407
|
+
});
|
|
408
|
+
};
|
|
409
|
+
defer(focusAndEdit);
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
[checkUpdating, gridApi, prePopupOps],
|
|
413
|
+
);
|
|
414
|
+
|
|
380
415
|
/**
|
|
381
416
|
* This differs from stopEdit in that it will also invoke cellEditingCompleteCallback
|
|
382
417
|
*/
|
|
@@ -544,6 +579,11 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
544
579
|
return externalFilters.current.every((filter) => filter(node.data, node));
|
|
545
580
|
};
|
|
546
581
|
|
|
582
|
+
const getColDef = useCallback(
|
|
583
|
+
(colId?: string): ColDef | undefined => (!!colId && gridApi?.getColumnDef(colId)) || undefined,
|
|
584
|
+
[gridApi],
|
|
585
|
+
);
|
|
586
|
+
|
|
547
587
|
const getColumns: () => ColDefT<RowType>[] = useCallback(() => gridApi?.getColumnDefs() ?? [], [gridApi]);
|
|
548
588
|
|
|
549
589
|
useEffect(() => {
|
|
@@ -588,6 +628,7 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
588
628
|
return (
|
|
589
629
|
<GridContext.Provider
|
|
590
630
|
value={{
|
|
631
|
+
getColDef,
|
|
591
632
|
getColumns,
|
|
592
633
|
invisibleColumnIds,
|
|
593
634
|
setInvisibleColumnIds,
|
|
@@ -612,6 +653,7 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
612
653
|
ensureSelectedRowIsVisible,
|
|
613
654
|
sizeColumnsToFit,
|
|
614
655
|
autoSizeColumns,
|
|
656
|
+
startCellEditing,
|
|
615
657
|
stopEditing,
|
|
616
658
|
cancelEdit,
|
|
617
659
|
updatingCells,
|
|
@@ -2,13 +2,13 @@ import { createContext } from "react";
|
|
|
2
2
|
|
|
3
3
|
export type GridUpdatingContextType = {
|
|
4
4
|
checkUpdating: (fields: string | string[], id: number | string) => boolean;
|
|
5
|
-
isUpdating: () => boolean;
|
|
6
5
|
modifyUpdating: (
|
|
7
6
|
fields: string | string[],
|
|
8
7
|
ids: (number | string)[],
|
|
9
8
|
fn: () => void | Promise<void>,
|
|
10
9
|
) => Promise<void>;
|
|
11
10
|
updatedDep: number;
|
|
11
|
+
updatingCols: () => string[];
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const GridUpdatingContext = createContext<GridUpdatingContextType>({
|
|
@@ -16,9 +16,9 @@ export const GridUpdatingContext = createContext<GridUpdatingContextType>({
|
|
|
16
16
|
console.error("Missing GridUpdatingContext");
|
|
17
17
|
return false;
|
|
18
18
|
},
|
|
19
|
-
|
|
19
|
+
updatingCols: () => {
|
|
20
20
|
console.error("Missing GridUpdatingContext");
|
|
21
|
-
return
|
|
21
|
+
return [];
|
|
22
22
|
},
|
|
23
23
|
modifyUpdating: async () => {
|
|
24
24
|
console.error("Missing GridUpdatingContext");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { castArray, flatten,
|
|
1
|
+
import { castArray, flatten, remove } from "lodash-es";
|
|
2
2
|
import { ReactNode, useRef, useState } from "react";
|
|
3
3
|
|
|
4
4
|
import { GridUpdatingContext } from "./GridUpdatingContext";
|
|
@@ -29,8 +29,7 @@ export const GridUpdatingContextProvider = (props: UpdatingContextProviderProps)
|
|
|
29
29
|
updating.current = mergedUpdatingBlocks;
|
|
30
30
|
setUpdatedDep((updatedDep) => updatedDep + 1);
|
|
31
31
|
};
|
|
32
|
-
|
|
33
|
-
const isUpdating = () => !isEmpty(updating.current);
|
|
32
|
+
const updatingCols = () => Object.keys(updating.current);
|
|
34
33
|
|
|
35
34
|
const modifyUpdating = async (
|
|
36
35
|
fields: string | string[],
|
|
@@ -55,7 +54,7 @@ export const GridUpdatingContextProvider = (props: UpdatingContextProviderProps)
|
|
|
55
54
|
castArray(fields).some((f) => updating.current[f]?.includes(id));
|
|
56
55
|
|
|
57
56
|
return (
|
|
58
|
-
<GridUpdatingContext.Provider value={{ modifyUpdating, checkUpdating,
|
|
57
|
+
<GridUpdatingContext.Provider value={{ modifyUpdating, checkUpdating, updatingCols, updatedDep }}>
|
|
59
58
|
{props.children}
|
|
60
59
|
</GridUpdatingContext.Provider>
|
|
61
60
|
);
|