@linzjs/step-ag-grid 14.9.3 → 14.10.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/README.md +5 -0
- package/dist/src/components/GridCellFiller.d.ts +4 -0
- package/dist/src/components/gridUtil.d.ts +3 -0
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/contexts/GridContext.d.ts +3 -2
- package/dist/step-ag-grid.esm.js +103 -57
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Grid.tsx +29 -11
- package/src/components/GridCellFiller.tsx +11 -0
- package/src/components/gridFilter/GridFilterColumnsToggle.tsx +52 -51
- package/src/components/gridUtil.ts +6 -0
- package/src/components/index.ts +1 -0
- package/src/contexts/GridContext.tsx +10 -3
- package/src/contexts/GridContextProvider.tsx +63 -35
- package/src/stories/grid/GridReadOnly.stories.tsx +21 -7
package/package.json
CHANGED
package/src/components/Grid.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CellClickedEvent, ColDef, ColumnResizedEvent, ModelUpdatedEvent } from "ag-grid-community";
|
|
1
|
+
import { CellClickedEvent, ColDef, ColGroupDef, 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
4
|
import { CellEvent, GridReadyEvent, SelectionChangedEvent } from "ag-grid-community/dist/lib/events";
|
|
@@ -153,11 +153,21 @@ export const Grid = ({
|
|
|
153
153
|
needsAutoSize.current = false;
|
|
154
154
|
}, [autoSizeColumns, params, sizeColumns, sizeColumnsToFit]);
|
|
155
155
|
|
|
156
|
+
const lastOwnerDocumentRef = useRef<Document>();
|
|
157
|
+
|
|
156
158
|
/**
|
|
157
159
|
* Auto-size windows that had deferred auto-size
|
|
158
160
|
*/
|
|
159
161
|
useIntervalHook({
|
|
160
162
|
callback: () => {
|
|
163
|
+
// Check if window has been popped out and needs resize
|
|
164
|
+
const currentDocument = gridDivRef.current?.ownerDocument;
|
|
165
|
+
if (currentDocument !== lastOwnerDocumentRef.current) {
|
|
166
|
+
lastOwnerDocumentRef.current = currentDocument;
|
|
167
|
+
if (currentDocument) {
|
|
168
|
+
needsAutoSize.current = true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
161
171
|
if (needsAutoSize.current) {
|
|
162
172
|
needsAutoSize.current = false;
|
|
163
173
|
setInitialContentSize();
|
|
@@ -277,7 +287,7 @@ export const Grid = ({
|
|
|
277
287
|
/**
|
|
278
288
|
* Add selectable column to colDefs. Adjust column defs to block fit for auto sized columns.
|
|
279
289
|
*/
|
|
280
|
-
const columnDefs = useMemo((): ColDef[] => {
|
|
290
|
+
const columnDefs = useMemo((): (ColDef | ColGroupDef)[] => {
|
|
281
291
|
const adjustColDefs = params.columnDefs.map((colDef) => {
|
|
282
292
|
const colDefEditable = colDef.editable;
|
|
283
293
|
const editable = combineEditables(params.readOnly !== true, params.defaultColDef?.editable, colDefEditable);
|
|
@@ -471,15 +481,23 @@ export const Grid = ({
|
|
|
471
481
|
* Once the grid has auto-sized we want to run fit to fit the grid in its container,
|
|
472
482
|
* but we don't want the non-flex auto-sized columns to "fit" size, so suppressSizeToFit is set to true.
|
|
473
483
|
*/
|
|
474
|
-
const columnDefsAdjusted = useMemo(
|
|
475
|
-
() =>
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
484
|
+
const columnDefsAdjusted = useMemo(() => {
|
|
485
|
+
const adjustColDefOrGroup = (colDef: ColDef | ColGroupDef) =>
|
|
486
|
+
"children" in colDef ? adjustGroupColDef(colDef) : adjustColDef(colDef);
|
|
487
|
+
|
|
488
|
+
const adjustGroupColDef = (colDef: ColGroupDef): ColGroupDef => ({
|
|
489
|
+
...colDef,
|
|
490
|
+
children: colDef.children.map((colDef) => adjustColDefOrGroup(colDef)),
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
const adjustColDef = (colDef: ColDef): ColDef => ({
|
|
494
|
+
...colDef,
|
|
495
|
+
suppressSizeToFit: (sizeColumns === "auto" || sizeColumns === "auto-skip-headers") && !colDef.flex,
|
|
496
|
+
sortable: colDef.sortable && params.defaultColDef?.sortable !== false,
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
return columnDefs.map((colDef) => adjustColDefOrGroup(colDef));
|
|
500
|
+
}, [columnDefs, params.defaultColDef?.sortable, sizeColumns]);
|
|
483
501
|
|
|
484
502
|
/**
|
|
485
503
|
* Set of colIds that need auto-sizing.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ColDef } from "ag-grid-community";
|
|
2
|
+
|
|
3
|
+
export const GridCellFillerColId = "gridCellFiller";
|
|
4
|
+
|
|
5
|
+
export const isGridCellFiller = (col: ColDef) => col.colId === GridCellFillerColId;
|
|
6
|
+
|
|
7
|
+
export const GridCellFiller = (): ColDef => ({
|
|
8
|
+
colId: GridCellFillerColId,
|
|
9
|
+
headerName: "",
|
|
10
|
+
flex: 1,
|
|
11
|
+
});
|
|
@@ -16,17 +16,20 @@ export interface GridFilterColumnsToggleProps {
|
|
|
16
16
|
|
|
17
17
|
export const GridFilterColumnsToggle = ({ saveState = true }: GridFilterColumnsToggleProps): JSX.Element => {
|
|
18
18
|
const [loaded, setLoaded] = useState(false);
|
|
19
|
-
const { getColumns, invisibleColumnIds, setInvisibleColumnIds } = useContext(GridContext);
|
|
19
|
+
const { getColumns, getColumnIds, invisibleColumnIds, setInvisibleColumnIds } = useContext(GridContext);
|
|
20
20
|
|
|
21
21
|
const columnStorageKey = useMemo(
|
|
22
22
|
() =>
|
|
23
|
-
isEmpty(
|
|
23
|
+
isEmpty(getColumnIds())
|
|
24
24
|
? null // Grid hasn't been initialised yet
|
|
25
|
-
: "stepAgGrid_invisibleColumnIds_" +
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
: "stepAgGrid_invisibleColumnIds_" + getColumnIds().join("_"),
|
|
26
|
+
[getColumnIds],
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// infer the invisible ids from colDefs
|
|
30
|
+
const resetColumns = useCallback(
|
|
31
|
+
() => setInvisibleColumnIds(getColumnIds("initialHide")),
|
|
32
|
+
[getColumnIds, setInvisibleColumnIds],
|
|
30
33
|
);
|
|
31
34
|
|
|
32
35
|
// Load state on start
|
|
@@ -35,20 +38,24 @@ export const GridFilterColumnsToggle = ({ saveState = true }: GridFilterColumnsT
|
|
|
35
38
|
if (saveState) {
|
|
36
39
|
try {
|
|
37
40
|
const stored = window.localStorage.getItem(columnStorageKey);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
console.error(`stored invisible ids not an array: ${stored}`);
|
|
41
|
-
} else if (!invisibleIds.every((id) => typeof id === "string")) {
|
|
42
|
-
console.error(`stored invisible ids not strings: ${stored}`);
|
|
41
|
+
if (!stored) {
|
|
42
|
+
resetColumns();
|
|
43
43
|
} else {
|
|
44
|
-
invisibleIds
|
|
44
|
+
const invisibleIds = JSON.parse(stored ?? "[]");
|
|
45
|
+
if (!Array.isArray(invisibleIds)) {
|
|
46
|
+
console.error(`stored invisible ids not an array: ${stored}`);
|
|
47
|
+
} else if (!invisibleIds.every((id) => typeof id === "string")) {
|
|
48
|
+
console.error(`stored invisible ids not strings: ${stored}`);
|
|
49
|
+
} else {
|
|
50
|
+
invisibleIds && setInvisibleColumnIds(invisibleIds);
|
|
51
|
+
}
|
|
45
52
|
}
|
|
46
53
|
} catch (ex) {
|
|
47
54
|
console.error(ex);
|
|
48
55
|
}
|
|
49
56
|
setLoaded(true);
|
|
50
57
|
}
|
|
51
|
-
}, [columnStorageKey, loaded, saveState, setInvisibleColumnIds]);
|
|
58
|
+
}, [columnStorageKey, getColumns, loaded, resetColumns, saveState, setInvisibleColumnIds]);
|
|
52
59
|
|
|
53
60
|
// Save state on column visibility change
|
|
54
61
|
useEffect(() => {
|
|
@@ -60,7 +67,7 @@ export const GridFilterColumnsToggle = ({ saveState = true }: GridFilterColumnsT
|
|
|
60
67
|
|
|
61
68
|
const toggleColumn = useCallback(
|
|
62
69
|
(colId?: string) => {
|
|
63
|
-
if (!colId) return;
|
|
70
|
+
if (!colId || !invisibleColumnIds) return;
|
|
64
71
|
setInvisibleColumnIds(
|
|
65
72
|
invisibleColumnIds.includes(colId)
|
|
66
73
|
? invisibleColumnIds.filter((id) => id !== colId)
|
|
@@ -70,10 +77,6 @@ export const GridFilterColumnsToggle = ({ saveState = true }: GridFilterColumnsT
|
|
|
70
77
|
[invisibleColumnIds, setInvisibleColumnIds],
|
|
71
78
|
);
|
|
72
79
|
|
|
73
|
-
const resetColumns = () => {
|
|
74
|
-
setInvisibleColumnIds([]);
|
|
75
|
-
};
|
|
76
|
-
|
|
77
80
|
const numericRegExp = /^\d+$/;
|
|
78
81
|
const isNonManageableColumn = (col: ColDefT<GridBaseRow>) => {
|
|
79
82
|
return col.lockVisible || col.colId == null || numericRegExp.test(col.colId);
|
|
@@ -87,40 +90,38 @@ export const GridFilterColumnsToggle = ({ saveState = true }: GridFilterColumnsT
|
|
|
87
90
|
unmountOnClose={true}
|
|
88
91
|
>
|
|
89
92
|
<div className={"GridFilterColumnsToggle-container"}>
|
|
90
|
-
{getColumns()
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (e.key !== "
|
|
99
|
-
|
|
100
|
-
if (e.key !== "Enter") {
|
|
101
|
-
toggleColumn(col.colId);
|
|
102
|
-
}
|
|
93
|
+
{getColumns("headerName").map((col) => (
|
|
94
|
+
<MenuItem
|
|
95
|
+
key={col.colId}
|
|
96
|
+
disabled={isNonManageableColumn(col)}
|
|
97
|
+
onClick={(e: ClickEvent) => {
|
|
98
|
+
// Global react-menu MenuItem handler handles tabs
|
|
99
|
+
if (e.key !== "Tab") {
|
|
100
|
+
e.keepOpen = true;
|
|
101
|
+
if (e.key !== "Enter") {
|
|
102
|
+
toggleColumn(col.colId);
|
|
103
103
|
}
|
|
104
|
+
}
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
<LuiCheckboxInput
|
|
108
|
+
isChecked={!!invisibleColumnIds && !invisibleColumnIds.includes(col.colId ?? "")}
|
|
109
|
+
value={`${col.colId}`}
|
|
110
|
+
label={col.headerName ?? ""}
|
|
111
|
+
isDisabled={isNonManageableColumn(col)}
|
|
112
|
+
inputProps={{
|
|
113
|
+
onClick: (e) => {
|
|
114
|
+
// Click is handled by MenuItem onClick so keyboard events work
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
},
|
|
118
|
+
}}
|
|
119
|
+
onChange={() => {
|
|
120
|
+
/*Do nothing, change handled by menuItem*/
|
|
104
121
|
}}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
value={`${col.colId}`}
|
|
109
|
-
label={col.headerName ?? ""}
|
|
110
|
-
isDisabled={isNonManageableColumn(col)}
|
|
111
|
-
inputProps={{
|
|
112
|
-
onClick: (e) => {
|
|
113
|
-
// Click is handled by MenuItem onClick so keyboard events work
|
|
114
|
-
e.preventDefault();
|
|
115
|
-
e.stopPropagation();
|
|
116
|
-
},
|
|
117
|
-
}}
|
|
118
|
-
onChange={() => {
|
|
119
|
-
/*Do nothing, change handled by menuItem*/
|
|
120
|
-
}}
|
|
121
|
-
/>
|
|
122
|
-
</MenuItem>
|
|
123
|
-
))}
|
|
122
|
+
/>
|
|
123
|
+
</MenuItem>
|
|
124
|
+
))}
|
|
124
125
|
</div>
|
|
125
126
|
<MenuDivider key={`$$divider_reset_columns`} />
|
|
126
127
|
<MenuItem
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ColDef } from "ag-grid-community";
|
|
2
|
+
|
|
3
|
+
import { isGridCellFiller } from "./GridCellFiller";
|
|
4
|
+
|
|
5
|
+
export const getColId = (colDef: ColDef): string => colDef.colId ?? "";
|
|
6
|
+
export const isFlexColumn = (colDef: ColDef): boolean => !!colDef.flex && !isGridCellFiller(colDef);
|
package/src/components/index.ts
CHANGED
|
@@ -17,7 +17,10 @@ export type AutoSizeColumnsResult = { width: number } | null;
|
|
|
17
17
|
export interface GridContextType<RowType extends GridBaseRow> {
|
|
18
18
|
gridReady: boolean;
|
|
19
19
|
getColDef: (colId?: string) => ColDef | undefined;
|
|
20
|
-
getColumns: (
|
|
20
|
+
getColumns: (
|
|
21
|
+
filter?: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string),
|
|
22
|
+
) => ColDefT<RowType>[];
|
|
23
|
+
getColumnIds: (filter?: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string)) => string[];
|
|
21
24
|
setApis: (gridApi: GridApi | undefined, columnApi: ColumnApi | undefined, dataTestId?: string) => void;
|
|
22
25
|
prePopupOps: () => void;
|
|
23
26
|
setQuickFilter: (quickFilter: string) => void;
|
|
@@ -55,7 +58,7 @@ export interface GridContextType<RowType extends GridBaseRow> {
|
|
|
55
58
|
removeExternalFilter: (filter: GridFilterExternal<RowType>) => void;
|
|
56
59
|
isExternalFilterPresent: () => boolean;
|
|
57
60
|
doesExternalFilterPass: (node: RowNode) => boolean;
|
|
58
|
-
invisibleColumnIds: string[];
|
|
61
|
+
invisibleColumnIds: string[] | undefined;
|
|
59
62
|
setInvisibleColumnIds: (colIds: string[]) => void;
|
|
60
63
|
downloadCsv: (csvExportParams?: CsvExportParams) => void;
|
|
61
64
|
setOnCellEditingComplete: (callback: (() => void) | undefined) => void;
|
|
@@ -71,7 +74,11 @@ export const GridContext = createContext<GridContextType<any>>({
|
|
|
71
74
|
console.error("no context provider for getColumns");
|
|
72
75
|
return [];
|
|
73
76
|
},
|
|
74
|
-
|
|
77
|
+
getColumnIds: () => {
|
|
78
|
+
console.error("no context provider for getColumnIds");
|
|
79
|
+
return [];
|
|
80
|
+
},
|
|
81
|
+
invisibleColumnIds: undefined,
|
|
75
82
|
setInvisibleColumnIds: () => {
|
|
76
83
|
console.error("no context provider for setInvisibleColumnIds");
|
|
77
84
|
},
|
|
@@ -3,10 +3,12 @@ import { CellPosition } from "ag-grid-community/dist/lib/entities/cellPosition";
|
|
|
3
3
|
import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
4
4
|
import { CsvExportParams, ProcessCellForExportParams } from "ag-grid-community/dist/lib/interfaces/exportParams";
|
|
5
5
|
import debounce from "debounce-promise";
|
|
6
|
-
import { compact, defer, delay, difference, isEmpty, last, remove, sortBy, sumBy } from "lodash-es";
|
|
6
|
+
import { compact, defer, delay, difference, filter, isEmpty, last, pull, remove, sortBy, sumBy } from "lodash-es";
|
|
7
7
|
import { ReactElement, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
8
8
|
|
|
9
9
|
import { ColDefT, GridBaseRow } from "../components";
|
|
10
|
+
import { GridCellFillerColId, isGridCellFiller } from "../components/GridCellFiller";
|
|
11
|
+
import { getColId, isFlexColumn } from "../components/gridUtil";
|
|
10
12
|
import { isNotEmpty, sanitiseFileName, wait } from "../utils/util";
|
|
11
13
|
import { AutoSizeColumnsProps, AutoSizeColumnsResult, GridContext, GridFilterExternal } from "./GridContext";
|
|
12
14
|
import { GridUpdatingContext } from "./GridUpdatingContext";
|
|
@@ -26,13 +28,19 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
26
28
|
const [columnApi, setColumnApi] = useState<ColumnApi>();
|
|
27
29
|
const [gridReady, setGridReady] = useState(false);
|
|
28
30
|
const [quickFilter, setQuickFilter] = useState("");
|
|
29
|
-
const [invisibleColumnIds,
|
|
31
|
+
const [invisibleColumnIds, _setInvisibleColumnIds] = useState<string[]>();
|
|
30
32
|
const testId = useRef<string | undefined>();
|
|
31
33
|
const idsBeforeUpdate = useRef<number[]>([]);
|
|
32
34
|
const prePopupFocusedCell = useRef<CellPosition>();
|
|
33
35
|
const [externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync] = useState(false);
|
|
34
36
|
const externalFilters = useRef<GridFilterExternal<RowType>[]>([]);
|
|
35
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Make extra sure the GridCellFillerColId never gets added to invisibleColumnIds as it's dynamically determined
|
|
40
|
+
*/
|
|
41
|
+
const setInvisibleColumnIds = (invisibleColumnIds: string[]) =>
|
|
42
|
+
_setInvisibleColumnIds(pull(invisibleColumnIds, GridCellFillerColId));
|
|
43
|
+
|
|
36
44
|
/**
|
|
37
45
|
* Set quick filter directly on grid, based on previously save quickFilter state.
|
|
38
46
|
*/
|
|
@@ -152,9 +160,7 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
152
160
|
const _getNewNodes = useCallback((): RowNode[] => {
|
|
153
161
|
return gridApiOp(
|
|
154
162
|
(gridApi) =>
|
|
155
|
-
difference(_getAllRowIds(), idsBeforeUpdate.current)
|
|
156
|
-
.map((rowId) => gridApi.getRowNode("" + rowId)) //
|
|
157
|
-
.filter((r) => r) as RowNode[],
|
|
163
|
+
compact(difference(_getAllRowIds(), idsBeforeUpdate.current).map((rowId) => gridApi.getRowNode("" + rowId))),
|
|
158
164
|
() => [],
|
|
159
165
|
);
|
|
160
166
|
}, [_getAllRowIds, gridApiOp]);
|
|
@@ -168,16 +174,30 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
168
174
|
const _rowIdsToNodes = useCallback(
|
|
169
175
|
(rowIds: number[]): RowNode[] => {
|
|
170
176
|
return gridApiOp(
|
|
171
|
-
(gridApi) =>
|
|
172
|
-
rowIds
|
|
173
|
-
.map((rowId) => gridApi.getRowNode("" + rowId)) //
|
|
174
|
-
.filter((r) => r) as RowNode[],
|
|
177
|
+
(gridApi) => compact(rowIds.map((rowId) => gridApi.getRowNode("" + rowId))),
|
|
175
178
|
() => [] as RowNode[],
|
|
176
179
|
);
|
|
177
180
|
},
|
|
178
181
|
[gridApiOp],
|
|
179
182
|
);
|
|
180
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Get ColDefs, with flattened ColGroupDefs
|
|
186
|
+
*/
|
|
187
|
+
const getColumns = useCallback(
|
|
188
|
+
(
|
|
189
|
+
filterDef: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string) = () => true,
|
|
190
|
+
): ColDefT<RowType>[] =>
|
|
191
|
+
filter(columnApi?.getAllColumns()?.map((col) => col.getColDef()) ?? [], filterDef) as ColDefT<RowType>[],
|
|
192
|
+
[columnApi],
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
const getColumnIds = useCallback(
|
|
196
|
+
(filterDef: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string) = () => true): string[] =>
|
|
197
|
+
compact(getColumns(filterDef).map(getColId)),
|
|
198
|
+
[getColumns],
|
|
199
|
+
);
|
|
200
|
+
|
|
181
201
|
/**
|
|
182
202
|
* Internal method for selecting and flashing rows.
|
|
183
203
|
*
|
|
@@ -211,9 +231,9 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
211
231
|
const firstNode = rowsThatNeedSelecting[0];
|
|
212
232
|
if (firstNode) {
|
|
213
233
|
defer(() => gridApi.ensureNodeVisible(firstNode));
|
|
214
|
-
const colDefs =
|
|
215
|
-
if (colDefs
|
|
216
|
-
const col = colDefs[0]
|
|
234
|
+
const colDefs = getColumns();
|
|
235
|
+
if (!isEmpty(colDefs)) {
|
|
236
|
+
const col = colDefs[0];
|
|
217
237
|
const rowIndex = firstNode.rowIndex;
|
|
218
238
|
if (rowIndex != null && col != null) {
|
|
219
239
|
const colId = col.colId;
|
|
@@ -244,7 +264,7 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
244
264
|
}
|
|
245
265
|
});
|
|
246
266
|
},
|
|
247
|
-
[_getNewNodes, _rowIdsToNodes, gridApiOp],
|
|
267
|
+
[_getNewNodes, _rowIdsToNodes, getColumns, gridApiOp],
|
|
248
268
|
);
|
|
249
269
|
|
|
250
270
|
const selectRowsById = useCallback(
|
|
@@ -536,9 +556,7 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
536
556
|
|
|
537
557
|
const redrawRows = useCallback(
|
|
538
558
|
(rowNodes?: RowNode[]) => {
|
|
539
|
-
gridApiOp((gridApi) => {
|
|
540
|
-
gridApi.redrawRows(rowNodes ? { rowNodes } : undefined);
|
|
541
|
-
});
|
|
559
|
+
gridApiOp((gridApi) => gridApi.redrawRows(rowNodes ? { rowNodes } : undefined));
|
|
542
560
|
},
|
|
543
561
|
[gridApiOp],
|
|
544
562
|
);
|
|
@@ -574,33 +592,39 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
574
592
|
onFilterChanged().then();
|
|
575
593
|
};
|
|
576
594
|
|
|
577
|
-
const isExternalFilterPresent = (): boolean => externalFilters.current
|
|
595
|
+
const isExternalFilterPresent = (): boolean => !isEmpty(externalFilters.current);
|
|
578
596
|
|
|
579
|
-
const doesExternalFilterPass = (node: RowNode): boolean =>
|
|
580
|
-
|
|
581
|
-
};
|
|
597
|
+
const doesExternalFilterPass = (node: RowNode): boolean =>
|
|
598
|
+
externalFilters.current.every((filter) => filter(node.data, node));
|
|
582
599
|
|
|
583
600
|
const getColDef = useCallback(
|
|
584
601
|
(colId?: string): ColDef | undefined => (!!colId && gridApi?.getColumnDef(colId)) || undefined,
|
|
585
602
|
[gridApi],
|
|
586
603
|
);
|
|
587
604
|
|
|
588
|
-
|
|
589
|
-
|
|
605
|
+
/**
|
|
606
|
+
* Apply column visibility
|
|
607
|
+
*/
|
|
590
608
|
useEffect(() => {
|
|
591
|
-
if (columnApi)
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
);
|
|
601
|
-
|
|
602
|
-
columnApi.setColumnsVisible(invisibleColumnIds, false);
|
|
609
|
+
if (!columnApi || !invisibleColumnIds) return;
|
|
610
|
+
|
|
611
|
+
// show all columns that aren't invisible
|
|
612
|
+
const newVisibleColumns = getColumns(
|
|
613
|
+
(col) => !col.lockVisible && col.colId && !invisibleColumnIds.includes(col.colId) && !isGridCellFiller(col),
|
|
614
|
+
);
|
|
615
|
+
// If there's no flex column showing add the filler column if defined
|
|
616
|
+
const visibleColumnsContainsAFlex = newVisibleColumns.some(isFlexColumn);
|
|
617
|
+
if (!visibleColumnsContainsAFlex) {
|
|
618
|
+
const fillerColumn = getColumns(isGridCellFiller)[0];
|
|
619
|
+
fillerColumn && newVisibleColumns.push(fillerColumn);
|
|
603
620
|
}
|
|
621
|
+
columnApi.setColumnsVisible(compact(newVisibleColumns.map(getColId)), true);
|
|
622
|
+
|
|
623
|
+
// Hide the filler column if there's already a flex column
|
|
624
|
+
const invisibleColumnIdsWithOptionalFiller = visibleColumnsContainsAFlex
|
|
625
|
+
? [...invisibleColumnIds, GridCellFillerColId]
|
|
626
|
+
: invisibleColumnIds;
|
|
627
|
+
columnApi.setColumnsVisible(invisibleColumnIdsWithOptionalFiller, false);
|
|
604
628
|
}, [invisibleColumnIds, columnApi, getColumns]);
|
|
605
629
|
|
|
606
630
|
/**
|
|
@@ -614,7 +638,10 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
614
638
|
|
|
615
639
|
const columnKeys = columnApi
|
|
616
640
|
?.getColumnState()
|
|
617
|
-
.filter((cs) =>
|
|
641
|
+
.filter((cs) => {
|
|
642
|
+
const colDef = gridApi.getColumnDef(cs.colId);
|
|
643
|
+
return !cs.hide && colDef && !isGridCellFiller(colDef) && colDef.headerComponentParams?.exportable !== false;
|
|
644
|
+
})
|
|
618
645
|
.map((cs) => cs.colId);
|
|
619
646
|
gridApi.exportDataAsCsv({
|
|
620
647
|
columnKeys,
|
|
@@ -631,6 +658,7 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
|
|
|
631
658
|
value={{
|
|
632
659
|
getColDef,
|
|
633
660
|
getColumns,
|
|
661
|
+
getColumnIds,
|
|
634
662
|
invisibleColumnIds,
|
|
635
663
|
setInvisibleColumnIds,
|
|
636
664
|
gridReady,
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from "../..";
|
|
26
26
|
import { GridFilterColumnsToggle } from "../../components";
|
|
27
27
|
import { GridFilterDownloadCsvButton } from "../../components";
|
|
28
|
+
import { GridCellFiller } from "../../components/GridCellFiller";
|
|
28
29
|
import "../../styles/GridTheme.scss";
|
|
29
30
|
import "../../styles/index.scss";
|
|
30
31
|
|
|
@@ -55,6 +56,7 @@ interface ITestRow {
|
|
|
55
56
|
id: number;
|
|
56
57
|
position: string;
|
|
57
58
|
age: number;
|
|
59
|
+
height: number;
|
|
58
60
|
desc: string;
|
|
59
61
|
dd: string;
|
|
60
62
|
}
|
|
@@ -76,15 +78,27 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
76
78
|
info: (props) => props.value === "Developer" && "Developers are awesome",
|
|
77
79
|
},
|
|
78
80
|
}),
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
{
|
|
82
|
+
headerName: "Metrics",
|
|
83
|
+
marryChildren: true,
|
|
84
|
+
children: [
|
|
85
|
+
GridCell({
|
|
86
|
+
field: "age",
|
|
87
|
+
headerName: "Age",
|
|
88
|
+
}),
|
|
89
|
+
GridCell({
|
|
90
|
+
field: "height",
|
|
91
|
+
headerName: "Height",
|
|
92
|
+
}),
|
|
93
|
+
],
|
|
94
|
+
},
|
|
83
95
|
GridCell({
|
|
84
96
|
field: "desc",
|
|
85
97
|
headerName: "Description",
|
|
86
98
|
flex: 1,
|
|
99
|
+
initialHide: true,
|
|
87
100
|
}),
|
|
101
|
+
GridCellFiller(),
|
|
88
102
|
GridPopoverMessage(
|
|
89
103
|
{
|
|
90
104
|
headerName: "Popout message",
|
|
@@ -187,9 +201,9 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
187
201
|
);
|
|
188
202
|
|
|
189
203
|
const [rowData] = useState([
|
|
190
|
-
{ id: 1000, position: "Tester", age: 30, desc: "Tests application", dd: "1" },
|
|
191
|
-
{ id: 1001, position: "Developer", age: 12, desc: "Develops application", dd: "2" },
|
|
192
|
-
{ id: 1002, position: "Manager", age: 65, desc: "Manages", dd: "3" },
|
|
204
|
+
{ id: 1000, position: "Tester", age: 30, height: `6'4"`, desc: "Tests application", dd: "1" },
|
|
205
|
+
{ id: 1001, position: "Developer", age: 12, height: `5'3"`, desc: "Develops application", dd: "2" },
|
|
206
|
+
{ id: 1002, position: "Manager", age: 65, height: `5'9"`, desc: "Manages", dd: "3" },
|
|
193
207
|
]);
|
|
194
208
|
|
|
195
209
|
return (
|