@linzjs/step-ag-grid 7.12.0 → 7.13.1
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/GridTheme.scss +0 -4
- package/dist/src/components/GridCell.d.ts +3 -3
- package/dist/src/components/GridCellMultiEditor.d.ts +15 -0
- package/dist/src/components/gridForm/GridFormDropDown.d.ts +2 -2
- package/dist/src/components/gridRender/GridRenderGenericCell.d.ts +5 -1
- package/dist/src/contexts/GridContext.d.ts +2 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/step-ag-grid.esm.js +119 -67
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +3 -2
- package/src/components/Grid.tsx +19 -4
- package/src/components/GridCell.tsx +21 -16
- package/src/components/GridCellMultiEditor.tsx +52 -0
- package/src/components/GridCellMultiSelectClassRules.tsx +16 -5
- package/src/components/gridForm/GridFormDropDown.tsx +34 -32
- package/src/components/gridForm/GridFormTextArea.tsx +1 -1
- package/src/components/gridRender/GridRenderGenericCell.tsx +6 -1
- package/src/contexts/GridContext.tsx +6 -0
- package/src/contexts/GridContextProvider.tsx +12 -7
- package/src/index.ts +6 -0
- package/src/stories/grid/GridPopoutEditGenericTextArea.stories.tsx +41 -3
- package/src/styles/GridTheme.scss +0 -4
- package/dist/index.js +0 -24853
- package/dist/index.js.map +0 -1
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": "7.
|
|
5
|
+
"version": "7.13.1",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"aggrid",
|
|
8
8
|
"ag-grid",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"react",
|
|
13
13
|
"react-component"
|
|
14
14
|
],
|
|
15
|
-
"main": "dist/
|
|
15
|
+
"main": "dist/step-ag-grid.esm.js",
|
|
16
|
+
"type": "module",
|
|
16
17
|
"typings": "dist/src/index.d.ts",
|
|
17
18
|
"module": "dist/step-ag-grid.esm.js",
|
|
18
19
|
"files": [
|
package/src/components/Grid.tsx
CHANGED
|
@@ -48,8 +48,10 @@ export const Grid = (params: GridProps): JSX.Element => {
|
|
|
48
48
|
setQuickFilter,
|
|
49
49
|
ensureRowVisible,
|
|
50
50
|
selectRowsById,
|
|
51
|
+
focusByRowById,
|
|
51
52
|
ensureSelectedRowIsVisible,
|
|
52
53
|
sizeColumnsToFit,
|
|
54
|
+
externallySelectedItemsAreInSync,
|
|
53
55
|
setExternallySelectedItemsAreInSync,
|
|
54
56
|
} = useContext(GridContext);
|
|
55
57
|
const { checkUpdating } = useContext(GridUpdatingContext);
|
|
@@ -64,12 +66,25 @@ export const Grid = (params: GridProps): JSX.Element => {
|
|
|
64
66
|
*/
|
|
65
67
|
const hasSelectedFirstItem = useRef(false);
|
|
66
68
|
useEffect(() => {
|
|
67
|
-
if (!gridReady ||
|
|
69
|
+
if (!gridReady || hasSelectedFirstItem.current || !params.rowData || !externallySelectedItemsAreInSync) return;
|
|
68
70
|
hasSelectedFirstItem.current = true;
|
|
69
71
|
if (isNotEmpty(params.rowData) && isEmpty(params.externalSelectedItems)) {
|
|
70
|
-
|
|
72
|
+
const firstRowId = params.rowData[0].id;
|
|
73
|
+
if (params.autoSelectFirstRow) {
|
|
74
|
+
selectRowsById([firstRowId]);
|
|
75
|
+
} else {
|
|
76
|
+
focusByRowById(firstRowId);
|
|
77
|
+
}
|
|
71
78
|
}
|
|
72
|
-
}, [
|
|
79
|
+
}, [
|
|
80
|
+
externallySelectedItemsAreInSync,
|
|
81
|
+
focusByRowById,
|
|
82
|
+
gridReady,
|
|
83
|
+
params,
|
|
84
|
+
params.autoSelectFirstRow,
|
|
85
|
+
params.rowData,
|
|
86
|
+
selectRowsById,
|
|
87
|
+
]);
|
|
73
88
|
|
|
74
89
|
/**
|
|
75
90
|
* AgGrid checkbox select does not pass clicks within cell but not on the checkbox to checkbox.
|
|
@@ -176,7 +191,7 @@ export const Grid = (params: GridProps): JSX.Element => {
|
|
|
176
191
|
checkboxSelection: true,
|
|
177
192
|
headerComponent: GridHeaderSelect,
|
|
178
193
|
suppressHeaderKeyboardEvent: (e) => {
|
|
179
|
-
if (e.event.key === "Enter" && !e.event.repeat) {
|
|
194
|
+
if ((e.event.key === "Enter" || e.event.key === " ") && !e.event.repeat) {
|
|
180
195
|
const selectedNodeCount = e.api.getSelectedRows().length;
|
|
181
196
|
if (selectedNodeCount == 0) {
|
|
182
197
|
e.api.selectAllFiltered();
|
|
@@ -6,7 +6,7 @@ import { GenericCellColDef, GenericCellRendererParams } from "./gridRender/GridR
|
|
|
6
6
|
import { ColDef, ICellEditorParams, ICellRendererParams } from "ag-grid-community";
|
|
7
7
|
import { GridLoadableCell } from "./GridLoadableCell";
|
|
8
8
|
import { GridIcon } from "./GridIcon";
|
|
9
|
-
import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
9
|
+
import { SuppressKeyboardEventParams, ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
10
10
|
import { GridPopoverContextProvider } from "../contexts/GridPopoverContextProvider";
|
|
11
11
|
import { fnOrVar } from "../utils/util";
|
|
12
12
|
|
|
@@ -52,6 +52,20 @@ export interface ColDefT<RowType extends GridBaseRow> extends ColDef {
|
|
|
52
52
|
editor?: (editorProps: any) => JSX.Element;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
export const suppressCellKeyboardEvents = (e: SuppressKeyboardEventParams) => {
|
|
56
|
+
const shortcutKeys = e.colDef.cellRendererParams?.shortcutKeys ?? {};
|
|
57
|
+
const exec = shortcutKeys[e.event.key];
|
|
58
|
+
if (!e.editing && !e.event.repeat && e.event.type === "keypress" && exec) {
|
|
59
|
+
const editable = fnOrVar(e.colDef?.editable, e);
|
|
60
|
+
return editable ? exec(e) ?? true : true;
|
|
61
|
+
}
|
|
62
|
+
// It's important that aggrid doesn't trigger edit on enter
|
|
63
|
+
// as the incorrect selected rows will be returned
|
|
64
|
+
return !["ArrowLeft", "ArrowRight", "ArrowDown", "ArrowUp", "Tab", " ", "Home", "End", "PageUp", "PageDown"].includes(
|
|
65
|
+
e.event.key,
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
55
69
|
/*
|
|
56
70
|
* All cells should use this
|
|
57
71
|
*/
|
|
@@ -68,21 +82,11 @@ export const GridCell = <RowType extends GridBaseRow, Props extends CellEditorCo
|
|
|
68
82
|
sortable: !!(props?.field || props?.valueGetter),
|
|
69
83
|
resizable: true,
|
|
70
84
|
...(custom?.editor && {
|
|
71
|
-
cellClassRules:
|
|
85
|
+
cellClassRules: GridCellMultiSelectClassRules,
|
|
72
86
|
editable: props.editable ?? true,
|
|
73
|
-
cellEditor: GenericCellEditorComponentWrapper(custom),
|
|
87
|
+
cellEditor: GenericCellEditorComponentWrapper(custom?.editor),
|
|
74
88
|
}),
|
|
75
|
-
suppressKeyboardEvent:
|
|
76
|
-
const shortcutKeys = e.colDef.cellRendererParams?.shortcutKeys ?? {};
|
|
77
|
-
const exec = shortcutKeys[e.event.key];
|
|
78
|
-
if (!e.editing && !e.event.repeat && e.event.type === "keypress" && exec) {
|
|
79
|
-
const editable = fnOrVar(e.colDef?.editable, e);
|
|
80
|
-
return editable ? exec(e) ?? true : true;
|
|
81
|
-
}
|
|
82
|
-
// It's important that aggrid doesn't trigger edit on enter
|
|
83
|
-
// as the incorrect selected rows will be returned
|
|
84
|
-
return !["ArrowLeft", "ArrowRight", "ArrowDown", "ArrowUp", "Tab", " "].includes(e.event.key);
|
|
85
|
-
},
|
|
89
|
+
suppressKeyboardEvent: suppressCellKeyboardEvents,
|
|
86
90
|
...(custom?.editorParams && {
|
|
87
91
|
cellEditorParams: { ...custom.editorParams, multiEdit: custom.multiEdit },
|
|
88
92
|
}),
|
|
@@ -106,7 +110,8 @@ export interface CellEditorCommon {
|
|
|
106
110
|
className?: string | undefined;
|
|
107
111
|
}
|
|
108
112
|
|
|
109
|
-
export const GenericCellEditorComponentWrapper = (
|
|
113
|
+
export const GenericCellEditorComponentWrapper = (editor?: (props: any) => JSX.Element) => {
|
|
114
|
+
const obj = { editor };
|
|
110
115
|
return forwardRef(function GenericCellEditorComponentFr(cellEditorParams: ICellEditorParams, _) {
|
|
111
116
|
const valueFormatted = cellEditorParams.formatValue
|
|
112
117
|
? cellEditorParams.formatValue(cellEditorParams.value)
|
|
@@ -120,7 +125,7 @@ export const GenericCellEditorComponentWrapper = (custom?: { editor?: (props: an
|
|
|
120
125
|
{...cellEditorParams.colDef.cellRendererParams}
|
|
121
126
|
/>
|
|
122
127
|
}
|
|
123
|
-
{
|
|
128
|
+
{obj.editor && <obj.editor {...cellEditorParams} />}
|
|
124
129
|
</GridPopoverContextProvider>
|
|
125
130
|
);
|
|
126
131
|
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { GridBaseRow } from "./Grid";
|
|
2
|
+
import { GridCellMultiSelectClassRules } from "./GridCellMultiSelectClassRules";
|
|
3
|
+
import { GenericCellColDef } from "./gridRender/GridRenderGenericCell";
|
|
4
|
+
import { CellEditorSelectorResult, ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
5
|
+
import { ColDefT, GenericCellEditorComponentWrapper, GridCellRenderer, suppressCellKeyboardEvents } from "./GridCell";
|
|
6
|
+
import { ComponentProps } from "react";
|
|
7
|
+
import { ICellEditorParams } from "ag-grid-community/dist/lib/interfaces/iCellEditor";
|
|
8
|
+
|
|
9
|
+
export const Editor = <FN extends (param: any) => JSX.Element>(props: {
|
|
10
|
+
multiEdit: boolean;
|
|
11
|
+
editor: FN;
|
|
12
|
+
editorParams: ComponentProps<FN>;
|
|
13
|
+
}): CellEditorSelectorResult => ({
|
|
14
|
+
component: GenericCellEditorComponentWrapper(props.editor),
|
|
15
|
+
params: { ...props.editorParams, multiEdit: props.multiEdit },
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export interface RowCellEditorParams<RowType extends GridBaseRow> extends ICellEditorParams {
|
|
19
|
+
data: RowType;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* All cells should use this
|
|
24
|
+
*/
|
|
25
|
+
export const GridCellMultiEditor = <RowType extends GridBaseRow>(
|
|
26
|
+
props: GenericCellColDef<RowType>,
|
|
27
|
+
cellEditorSelector: (params: RowCellEditorParams<RowType>) => CellEditorSelectorResult,
|
|
28
|
+
): ColDefT<RowType> => {
|
|
29
|
+
return {
|
|
30
|
+
colId: props.colId ?? props.field,
|
|
31
|
+
field: props.field,
|
|
32
|
+
sortable: !!(props?.field || props?.valueGetter),
|
|
33
|
+
resizable: true,
|
|
34
|
+
editable: props.editable ?? true,
|
|
35
|
+
cellClassRules: GridCellMultiSelectClassRules,
|
|
36
|
+
cellEditorSelector,
|
|
37
|
+
suppressKeyboardEvent: suppressCellKeyboardEvents,
|
|
38
|
+
// Default value formatter, otherwise react freaks out on objects
|
|
39
|
+
valueFormatter: (params: ValueFormatterParams) => {
|
|
40
|
+
if (params.value == null) return "–";
|
|
41
|
+
const types = ["number", "boolean", "string"];
|
|
42
|
+
if (types.includes(typeof params.value)) return `${params.value}`;
|
|
43
|
+
else return JSON.stringify(params.value);
|
|
44
|
+
},
|
|
45
|
+
...props,
|
|
46
|
+
cellRenderer: GridCellRenderer,
|
|
47
|
+
cellRendererParams: {
|
|
48
|
+
originalCellRenderer: props.cellRenderer,
|
|
49
|
+
...props.cellRendererParams,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
};
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { CellClassParams, CellClassRules } from "ag-grid-community/dist/lib/entities/colDef";
|
|
2
|
+
import { ICellEditorParams } from "ag-grid-community/dist/lib/interfaces/iCellEditor";
|
|
2
3
|
|
|
3
4
|
export const GridCellMultiSelectClassRules: CellClassRules = {
|
|
4
|
-
"ag-selected-for-edit": (
|
|
5
|
-
api
|
|
6
|
-
|
|
7
|
-
.
|
|
8
|
-
|
|
5
|
+
"ag-selected-for-edit": (params: CellClassParams) => {
|
|
6
|
+
const { api, node, colDef } = params;
|
|
7
|
+
const cep = colDef.cellEditorSelector
|
|
8
|
+
? colDef.cellEditorSelector(params as ICellEditorParams)?.params
|
|
9
|
+
: colDef.cellEditorParams;
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
cep?.multiEdit &&
|
|
13
|
+
api
|
|
14
|
+
.getSelectedNodes()
|
|
15
|
+
.map((row) => row.id)
|
|
16
|
+
.includes(node.id) &&
|
|
17
|
+
api.getEditingCells().some((cell) => cell.column.getColDef() === colDef)
|
|
18
|
+
);
|
|
19
|
+
},
|
|
9
20
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { FocusableItem, MenuDivider, MenuHeader, MenuItem } from "../../react-menu3";
|
|
2
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { GridBaseRow } from "../Grid";
|
|
4
4
|
import { ComponentLoadingWrapper } from "../ComponentLoadingWrapper";
|
|
5
|
-
import {
|
|
5
|
+
import { isEmpty } from "lodash-es";
|
|
6
6
|
import debounce from "debounce-promise";
|
|
7
7
|
import { CellEditorCommon } from "../GridCell";
|
|
8
8
|
import { useGridPopoverHook } from "../GridPopoverHook";
|
|
@@ -49,10 +49,13 @@ export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow> extend
|
|
|
49
49
|
filtered?: "local" | "reload";
|
|
50
50
|
filterPlaceholder?: string;
|
|
51
51
|
filterHelpText?: string;
|
|
52
|
+
noOptionsMessage?: string;
|
|
52
53
|
onSelectedItem?: (props: GridPopoutEditDropDownSelectedItem<RowType>) => Promise<void>;
|
|
53
54
|
onSelectFilter?: (props: GridPopoutEditDropDownSelectedItem<RowType>) => Promise<void>;
|
|
54
|
-
options:
|
|
55
|
-
|
|
55
|
+
options:
|
|
56
|
+
| SelectOption[]
|
|
57
|
+
| ((selectedRows: RowType[], filter?: string) => Promise<SelectOption[] | undefined> | SelectOption[] | undefined)
|
|
58
|
+
| undefined;
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
const fieldToString = (field: any) => {
|
|
@@ -65,7 +68,6 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
|
|
|
65
68
|
// Save triggers during async action processing which triggers another selectItem(), this ref blocks that
|
|
66
69
|
const [filter, setFilter] = useState("");
|
|
67
70
|
const [filteredValues, setFilteredValues] = useState<any[]>();
|
|
68
|
-
const optionsInitialising = useRef(false);
|
|
69
71
|
const [options, setOptions] = useState<FinalSelectOption[] | null>(null);
|
|
70
72
|
const subComponentIsValid = useRef(false);
|
|
71
73
|
const subComponentInitialValue = useRef<string | null>(null);
|
|
@@ -92,33 +94,33 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
|
|
|
92
94
|
|
|
93
95
|
// Load up options list if it's async function
|
|
94
96
|
useEffect(() => {
|
|
95
|
-
if (options
|
|
96
|
-
|
|
97
|
-
let optionsConf = props.options ?? [];
|
|
97
|
+
if (options) return;
|
|
98
|
+
let optionsConf = props.options;
|
|
98
99
|
|
|
99
100
|
(async () => {
|
|
100
101
|
if (typeof optionsConf == "function") {
|
|
101
102
|
optionsConf = await optionsConf(selectedRows, filter);
|
|
102
103
|
}
|
|
104
|
+
if (optionsConf !== undefined) {
|
|
105
|
+
const optionsList = optionsConf?.map((item) =>
|
|
106
|
+
item == null || typeof item == "string"
|
|
107
|
+
? ({
|
|
108
|
+
value: item,
|
|
109
|
+
label: item,
|
|
110
|
+
disabled: false,
|
|
111
|
+
} as FinalSelectOption)
|
|
112
|
+
: item,
|
|
113
|
+
);
|
|
103
114
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
if (props.filtered) {
|
|
115
|
-
// This is needed otherwise when filter input is rendered and sets autofocus
|
|
116
|
-
// the mouse up of the double click edit triggers the cell to cancel editing
|
|
117
|
-
delay(() => setOptions(optionsList), 100);
|
|
118
|
-
} else {
|
|
119
|
-
setOptions(optionsList);
|
|
115
|
+
if (props.filtered) {
|
|
116
|
+
// This is needed otherwise when filter input is rendered and sets autofocus
|
|
117
|
+
// the mouse up of the double click edit triggers the cell to cancel editing
|
|
118
|
+
setOptions(optionsList);
|
|
119
|
+
//delay(() => setOptions(optionsList), 100);
|
|
120
|
+
} else {
|
|
121
|
+
setOptions(optionsList);
|
|
122
|
+
}
|
|
120
123
|
}
|
|
121
|
-
optionsInitialising.current = false;
|
|
122
124
|
})();
|
|
123
125
|
}, [filter, options, props, selectedRows]);
|
|
124
126
|
|
|
@@ -141,11 +143,12 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
|
|
|
141
143
|
}
|
|
142
144
|
}, [props.filtered, filter, options]);
|
|
143
145
|
|
|
144
|
-
const researchOnFilterChange =
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
const researchOnFilterChange = useMemo(
|
|
147
|
+
() =>
|
|
148
|
+
debounce(() => {
|
|
149
|
+
setOptions(null);
|
|
150
|
+
}, 500),
|
|
151
|
+
[],
|
|
149
152
|
);
|
|
150
153
|
|
|
151
154
|
const previousFilter = useRef<string>(filter);
|
|
@@ -154,7 +157,6 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
|
|
|
154
157
|
useEffect(() => {
|
|
155
158
|
if (previousFilter.current != filter && props.filtered == "reload") {
|
|
156
159
|
previousFilter.current = filter;
|
|
157
|
-
props.optionsRequestCancel && props.optionsRequestCancel();
|
|
158
160
|
researchOnFilterChange().then();
|
|
159
161
|
}
|
|
160
162
|
}, [filter, props, researchOnFilterChange]);
|
|
@@ -232,7 +234,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
|
|
|
232
234
|
<>
|
|
233
235
|
{options && (isEmpty(options) || (filteredValues && isEmpty(filteredValues))) && (
|
|
234
236
|
<MenuItem key={`${fieldToString(field)}-empty`} className={"GridPopoverEditDropDown-noOptions"}>
|
|
235
|
-
No Options
|
|
237
|
+
{props.noOptionsMessage ?? "No Options"}
|
|
236
238
|
</MenuItem>
|
|
237
239
|
)}
|
|
238
240
|
{options?.map((item: FinalSelectOption, index) =>
|
|
@@ -15,7 +15,7 @@ export interface GridFormTextAreaProps<RowType extends GridBaseRow>
|
|
|
15
15
|
helpText?: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export const GridFormTextArea = <RowType extends GridBaseRow>(props: GridFormTextAreaProps<RowType>) => {
|
|
18
|
+
export const GridFormTextArea = <RowType extends GridBaseRow>(props: GridFormTextAreaProps<RowType>): JSX.Element => {
|
|
19
19
|
const { field, value: initialVale, data } = useGridPopoverContext<RowType>();
|
|
20
20
|
|
|
21
21
|
const initValue = useMemo(() => (initialVale == null ? "" : `${initialVale}`), [initialVale]);
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { ICellRendererParams } from "ag-grid-community";
|
|
2
2
|
import { GridBaseRow } from "../Grid";
|
|
3
3
|
import { ColDefT } from "../GridCell";
|
|
4
|
-
import { SuppressKeyboardEventParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
4
|
+
import { EditableCallbackParams, SuppressKeyboardEventParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
5
5
|
|
|
6
6
|
export interface RowICellRendererParams<RowType extends GridBaseRow> extends ICellRendererParams {
|
|
7
7
|
data: RowType;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
export interface RowEditableCallbackParams<RowType extends GridBaseRow> extends EditableCallbackParams {
|
|
11
|
+
data: RowType;
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
export interface GenericCellColDef<RowType extends GridBaseRow> extends ColDefT<RowType> {
|
|
11
15
|
cellRendererParams?: GenericCellRendererParams<RowType>;
|
|
16
|
+
editable?: boolean | ((params: RowEditableCallbackParams<RowType>) => boolean);
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
export interface GenericCellRendererParams<RowType extends GridBaseRow> {
|
|
@@ -15,6 +15,7 @@ export interface GridContextType {
|
|
|
15
15
|
selectRowsByIdWithFlash: (rowIds?: number[]) => void;
|
|
16
16
|
flashRows: (rowIds?: number[]) => void;
|
|
17
17
|
flashRowsDiff: (updateFn: () => Promise<any>) => Promise<void>;
|
|
18
|
+
focusByRowById: (rowId: number) => void;
|
|
18
19
|
ensureRowVisible: (id: number | string) => boolean;
|
|
19
20
|
ensureSelectedRowIsVisible: () => void;
|
|
20
21
|
sizeColumnsToFit: () => void;
|
|
@@ -26,12 +27,14 @@ export interface GridContextType {
|
|
|
26
27
|
tabDirection?: 1 | 0 | -1,
|
|
27
28
|
) => Promise<boolean>;
|
|
28
29
|
redrawRows: (rowNodes?: RowNode[]) => void;
|
|
30
|
+
externallySelectedItemsAreInSync: boolean;
|
|
29
31
|
setExternallySelectedItemsAreInSync: (inSync: boolean) => void;
|
|
30
32
|
waitForExternallySelectedItemsToBeInSync: () => Promise<void>;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
export const GridContext = createContext<GridContextType>({
|
|
34
36
|
gridReady: false,
|
|
37
|
+
externallySelectedItemsAreInSync: false,
|
|
35
38
|
setGridApi: () => {
|
|
36
39
|
console.error("no context provider for setGridApi");
|
|
37
40
|
},
|
|
@@ -64,6 +67,9 @@ export const GridContext = createContext<GridContextType>({
|
|
|
64
67
|
flashRowsDiff: async () => {
|
|
65
68
|
console.error("no context provider for flashRows");
|
|
66
69
|
},
|
|
70
|
+
focusByRowById: async () => {
|
|
71
|
+
console.error("no context provider for focusByRowById");
|
|
72
|
+
},
|
|
67
73
|
ensureRowVisible: () => {
|
|
68
74
|
console.error("no context provider for ensureRowVisible");
|
|
69
75
|
return true;
|
|
@@ -20,7 +20,7 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
|
|
|
20
20
|
const [gridApi, _setGridApi] = useState<GridApi>();
|
|
21
21
|
const [gridReady, setGridReady] = useState(false);
|
|
22
22
|
const idsBeforeUpdate = useRef<number[]>([]);
|
|
23
|
-
const externallySelectedItemsAreInSync =
|
|
23
|
+
const [externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync] = useState(false);
|
|
24
24
|
|
|
25
25
|
const setGridApi = useCallback((gridApi: GridApi | undefined) => {
|
|
26
26
|
_setGridApi(gridApi);
|
|
@@ -181,10 +181,12 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
|
|
|
181
181
|
(rowIds?: number[]) => _selectRowsWithOptionalFlash(rowIds, true, false),
|
|
182
182
|
[_selectRowsWithOptionalFlash],
|
|
183
183
|
);
|
|
184
|
+
|
|
184
185
|
const selectRowsByIdWithFlash = useCallback(
|
|
185
186
|
(rowIds?: number[]) => _selectRowsWithOptionalFlash(rowIds, true, true),
|
|
186
187
|
[_selectRowsWithOptionalFlash],
|
|
187
188
|
);
|
|
189
|
+
|
|
188
190
|
const flashRows = useCallback(
|
|
189
191
|
(rowIds?: number[]) => _selectRowsWithOptionalFlash(rowIds, false, true),
|
|
190
192
|
[_selectRowsWithOptionalFlash],
|
|
@@ -217,6 +219,11 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
|
|
|
217
219
|
[_selectRowsWithOptionalFlash, beforeUpdate],
|
|
218
220
|
);
|
|
219
221
|
|
|
222
|
+
const focusByRowById = useCallback(
|
|
223
|
+
(rowId: number) => _selectRowsWithOptionalFlash([rowId], false, false),
|
|
224
|
+
[_selectRowsWithOptionalFlash],
|
|
225
|
+
);
|
|
226
|
+
|
|
220
227
|
const getSelectedRows = useCallback(<T extends unknown>(): T[] => {
|
|
221
228
|
return gridApiOp(
|
|
222
229
|
(gridApi) => gridApi.getSelectedRows(),
|
|
@@ -350,16 +357,12 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
|
|
|
350
357
|
[gridApiOp],
|
|
351
358
|
);
|
|
352
359
|
|
|
353
|
-
const setExternallySelectedItemsAreInSync = useCallback((inSync: boolean) => {
|
|
354
|
-
externallySelectedItemsAreInSync.current = inSync;
|
|
355
|
-
}, []);
|
|
356
|
-
|
|
357
360
|
const waitForExternallySelectedItemsToBeInSync = useCallback(async () => {
|
|
358
361
|
// Wait for up to 5 seconds
|
|
359
|
-
for (let i = 0; i < 5000 / 200 && !externallySelectedItemsAreInSync
|
|
362
|
+
for (let i = 0; i < 5000 / 200 && !externallySelectedItemsAreInSync; i++) {
|
|
360
363
|
await wait(200);
|
|
361
364
|
}
|
|
362
|
-
}, []);
|
|
365
|
+
}, [externallySelectedItemsAreInSync]);
|
|
363
366
|
|
|
364
367
|
return (
|
|
365
368
|
<GridContext.Provider
|
|
@@ -373,6 +376,7 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
|
|
|
373
376
|
selectRowsWithFlashDiff,
|
|
374
377
|
flashRows,
|
|
375
378
|
flashRowsDiff,
|
|
379
|
+
focusByRowById,
|
|
376
380
|
getSelectedRows,
|
|
377
381
|
getSelectedRowIds,
|
|
378
382
|
editingCells,
|
|
@@ -382,6 +386,7 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
|
|
|
382
386
|
stopEditing,
|
|
383
387
|
updatingCells,
|
|
384
388
|
redrawRows,
|
|
389
|
+
externallySelectedItemsAreInSync,
|
|
385
390
|
setExternallySelectedItemsAreInSync,
|
|
386
391
|
waitForExternallySelectedItemsToBeInSync,
|
|
387
392
|
}}
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,8 @@ export * from "./contexts/GridSubComponentContext";
|
|
|
12
12
|
export type { GridBaseRow } from "./components/Grid";
|
|
13
13
|
export { Grid } from "./components/Grid";
|
|
14
14
|
export * from "./components/GridCell";
|
|
15
|
+
export * from "./components/GridCellMultiEditor";
|
|
16
|
+
|
|
15
17
|
export { GridIcon } from "./components/GridIcon";
|
|
16
18
|
export { ComponentLoadingWrapper } from "./components/ComponentLoadingWrapper";
|
|
17
19
|
export { GridCellMultiSelectClassRules } from "./components/GridCellMultiSelectClassRules";
|
|
@@ -34,6 +36,10 @@ export { GridFormSubComponentTextInput } from "./components/gridForm/GridFormSub
|
|
|
34
36
|
export * from "./components/gridForm/GridFormDropDown";
|
|
35
37
|
export * from "./components/gridForm/GridFormMultiSelect";
|
|
36
38
|
export * from "./components/gridForm/GridFormPopoverMenu";
|
|
39
|
+
export * from "./components/gridForm/GridFormTextInput";
|
|
40
|
+
export * from "./components/gridForm/GridFormTextArea";
|
|
41
|
+
export * from "./components/gridForm/GridFormMessage";
|
|
42
|
+
export * from "./components/gridForm/GridFormEditBearing";
|
|
37
43
|
|
|
38
44
|
export { GridHeaderSelect } from "./components/gridHeader/GridHeaderSelect";
|
|
39
45
|
|
|
@@ -16,6 +16,9 @@ import { GridPopoverTextInput } from "../../components/gridPopoverEdit/GridPopov
|
|
|
16
16
|
import { ActionButton } from "../../lui/ActionButton";
|
|
17
17
|
import { GridPopoverMenu } from "../../components/gridPopoverEdit/GridPopoverMenu";
|
|
18
18
|
import { GridContext } from "../../contexts/GridContext";
|
|
19
|
+
import { Editor, GridCellMultiEditor } from "../../components/GridCellMultiEditor";
|
|
20
|
+
import { GridFormTextArea } from "../../components/gridForm/GridFormTextArea";
|
|
21
|
+
import { GridFormDropDown } from "../../components/gridForm/GridFormDropDown";
|
|
19
22
|
|
|
20
23
|
export default {
|
|
21
24
|
title: "Components / Grids",
|
|
@@ -88,7 +91,7 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
88
91
|
},
|
|
89
92
|
},
|
|
90
93
|
{
|
|
91
|
-
multiEdit:
|
|
94
|
+
multiEdit: false,
|
|
92
95
|
editorParams: {
|
|
93
96
|
maxLength: 12,
|
|
94
97
|
placeholder: "Enter distance...",
|
|
@@ -119,7 +122,6 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
119
122
|
required: true,
|
|
120
123
|
maxLength: 32,
|
|
121
124
|
placeholder: "Enter some text...",
|
|
122
|
-
|
|
123
125
|
invalid: (value: string) => {
|
|
124
126
|
if (value === "never") return "The value 'never' is not allowed";
|
|
125
127
|
return null;
|
|
@@ -132,6 +134,32 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
132
134
|
},
|
|
133
135
|
},
|
|
134
136
|
),
|
|
137
|
+
GridCellMultiEditor(
|
|
138
|
+
{
|
|
139
|
+
colId: "plan2",
|
|
140
|
+
field: "plan",
|
|
141
|
+
headerName: "Multi-editor",
|
|
142
|
+
maxWidth: 140,
|
|
143
|
+
},
|
|
144
|
+
(_params) =>
|
|
145
|
+
_params.rowIndex == 0
|
|
146
|
+
? Editor({
|
|
147
|
+
multiEdit: true,
|
|
148
|
+
editor: GridFormTextArea,
|
|
149
|
+
editorParams: {
|
|
150
|
+
required: true,
|
|
151
|
+
maxLength: 32,
|
|
152
|
+
placeholder: "Enter some text...",
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
: Editor({
|
|
156
|
+
multiEdit: false,
|
|
157
|
+
editor: GridFormDropDown,
|
|
158
|
+
editorParams: {
|
|
159
|
+
options: [{ label: "One", value: 1 }],
|
|
160
|
+
},
|
|
161
|
+
}),
|
|
162
|
+
),
|
|
135
163
|
GridPopoverMenu(
|
|
136
164
|
{
|
|
137
165
|
headerName: "Delete menu",
|
|
@@ -160,7 +188,17 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
160
188
|
|
|
161
189
|
const lastRow = rowData[rowData.length - 1];
|
|
162
190
|
await selectRowsWithFlashDiff(async () => {
|
|
163
|
-
setRowData([
|
|
191
|
+
setRowData([
|
|
192
|
+
...rowData,
|
|
193
|
+
{
|
|
194
|
+
id: lastRow.id + 1,
|
|
195
|
+
name: "?",
|
|
196
|
+
nameType: "?",
|
|
197
|
+
numba: "?",
|
|
198
|
+
plan: "",
|
|
199
|
+
distance: null,
|
|
200
|
+
},
|
|
201
|
+
]);
|
|
164
202
|
});
|
|
165
203
|
}, [rowData, selectRowsWithFlashDiff]);
|
|
166
204
|
|