@linzjs/step-ag-grid 5.0.1 → 6.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.js +100 -84
- package/dist/index.js.map +1 -1
- package/dist/src/components/gridForm/GridFormDropDown.d.ts +11 -11
- package/dist/src/components/gridPopoverEdit/GridPopoverEditDropDown.d.ts +1 -1
- package/dist/src/contexts/GridContext.d.ts +1 -2
- package/dist/src/utils/bearing.d.ts +1 -1
- package/dist/src/utils/textValidator.d.ts +2 -1
- package/dist/step-ag-grid.esm.js +100 -84
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/GridPopoverHook.tsx +2 -2
- package/src/components/gridForm/GridFormDropDown.tsx +49 -46
- package/src/components/gridForm/GridFormPopoverMenu.tsx +10 -24
- package/src/components/gridPopoverEdit/GridPopoverEditDropDown.ts +3 -3
- package/src/contexts/GridContext.tsx +1 -4
- package/src/contexts/GridContextProvider.tsx +16 -2
- package/src/contexts/GridPopoverContextProvider.tsx +8 -12
- package/src/react-menu3/components/ControlledMenu.tsx +6 -4
- package/src/stories/grid/GridPopoutEditDropDown.stories.tsx +4 -39
- package/src/stories/grid/GridPopoutEditGenericTextArea.stories.tsx +3 -4
- package/src/stories/grid/GridReadOnly.stories.tsx +0 -1
- package/src/utils/bearing.ts +2 -2
- package/src/utils/textValidator.ts +7 -3
package/package.json
CHANGED
|
@@ -24,7 +24,7 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(props: GridPopov
|
|
|
24
24
|
|
|
25
25
|
const triggerSave = useCallback(
|
|
26
26
|
async (reason?: string) => {
|
|
27
|
-
if (reason ==
|
|
27
|
+
if (reason == CloseReason.CANCEL) {
|
|
28
28
|
stopEditing();
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
@@ -64,7 +64,7 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(props: GridPopov
|
|
|
64
64
|
menuClassName={"step-ag-grid-react-menu"}
|
|
65
65
|
onClose={(event: MenuCloseEvent) => {
|
|
66
66
|
// Prevent menu from closing when modals are invoked
|
|
67
|
-
if (event.reason ===
|
|
67
|
+
if (event.reason === CloseReason.BLUR) return;
|
|
68
68
|
triggerSave(event.reason).then();
|
|
69
69
|
}}
|
|
70
70
|
viewScroll={"auto"}
|
|
@@ -13,15 +13,15 @@ import { GridSubComponentContext } from "contexts/GridSubComponentContext";
|
|
|
13
13
|
import { ClickEvent, MenuInstance } from "../../react-menu3/types";
|
|
14
14
|
import { CloseReason } from "../../react-menu3/utils";
|
|
15
15
|
|
|
16
|
-
export interface GridPopoutEditDropDownSelectedItem<RowType
|
|
16
|
+
export interface GridPopoutEditDropDownSelectedItem<RowType> {
|
|
17
17
|
// Note the row that was clicked on will be first
|
|
18
18
|
selectedRows: RowType[];
|
|
19
|
-
value:
|
|
20
|
-
subComponentValue?:
|
|
19
|
+
value: any;
|
|
20
|
+
subComponentValue?: any;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
interface FinalSelectOption
|
|
24
|
-
value:
|
|
23
|
+
interface FinalSelectOption {
|
|
24
|
+
value: any;
|
|
25
25
|
label?: JSX.Element | string;
|
|
26
26
|
disabled?: boolean | string;
|
|
27
27
|
subComponent?: (props: any, ref: any) => any;
|
|
@@ -35,9 +35,9 @@ export const MenuHeaderItem = (title: string) => {
|
|
|
35
35
|
return { label: title, value: MenuHeaderString };
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
export type SelectOption
|
|
38
|
+
export type SelectOption = null | string | FinalSelectOption;
|
|
39
39
|
|
|
40
|
-
export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow
|
|
40
|
+
export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow> extends CellEditorCommon {
|
|
41
41
|
// This overrides CellEditorCommon to provide some common class options
|
|
42
42
|
className?:
|
|
43
43
|
| "GridPopoverEditDropDown-containerSmall"
|
|
@@ -49,11 +49,9 @@ export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow, ValueT
|
|
|
49
49
|
// local means the filter won't change if it's reloaded, reload means it does change
|
|
50
50
|
filtered?: "local" | "reload";
|
|
51
51
|
filterPlaceholder?: string;
|
|
52
|
-
onSelectedItem?: (props: GridPopoutEditDropDownSelectedItem<RowType
|
|
53
|
-
onSelectFilter?: (props: GridPopoutEditDropDownSelectedItem<RowType
|
|
54
|
-
options:
|
|
55
|
-
| SelectOption<ValueType>[]
|
|
56
|
-
| ((selectedRows: RowType[], filter?: string) => Promise<SelectOption<ValueType>[]> | SelectOption<ValueType>[]);
|
|
52
|
+
onSelectedItem?: (props: GridPopoutEditDropDownSelectedItem<RowType>) => Promise<void>;
|
|
53
|
+
onSelectFilter?: (props: GridPopoutEditDropDownSelectedItem<RowType>) => Promise<void>;
|
|
54
|
+
options: SelectOption[] | ((selectedRows: RowType[], filter?: string) => Promise<SelectOption[]> | SelectOption[]);
|
|
57
55
|
optionsRequestCancel?: () => void;
|
|
58
56
|
}
|
|
59
57
|
|
|
@@ -61,41 +59,44 @@ const fieldToString = (field: any) => {
|
|
|
61
59
|
return typeof field == "symbol" ? field.toString() : `${field}`;
|
|
62
60
|
};
|
|
63
61
|
|
|
64
|
-
export const GridFormDropDown = <RowType extends GridBaseRow
|
|
65
|
-
props: GridFormPopoutDropDownProps<RowType, ValueType>,
|
|
66
|
-
) => {
|
|
62
|
+
export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPopoutDropDownProps<RowType>) => {
|
|
67
63
|
const { selectedRows, field, updateValue, data } = useGridPopoverContext<RowType>();
|
|
68
64
|
|
|
69
65
|
// Save triggers during async action processing which triggers another selectItem(), this ref blocks that
|
|
70
|
-
const hasSubmitted = useRef(false);
|
|
71
66
|
const [filter, setFilter] = useState("");
|
|
72
67
|
const [filteredValues, setFilteredValues] = useState<any[]>([]);
|
|
73
68
|
const optionsInitialising = useRef(false);
|
|
74
|
-
const [options, setOptions] = useState<FinalSelectOption
|
|
69
|
+
const [options, setOptions] = useState<FinalSelectOption[] | null>(null);
|
|
75
70
|
const subComponentIsValid = useRef(false);
|
|
76
71
|
const [subSelectedValue, setSubSelectedValue] = useState<any>();
|
|
77
|
-
const [selectedSubComponent, setSelectedSubComponent] = useState<FinalSelectOption
|
|
72
|
+
const [selectedSubComponent, setSelectedSubComponent] = useState<FinalSelectOption | null>(null);
|
|
78
73
|
|
|
79
74
|
const selectItemHandler = useCallback(
|
|
80
|
-
async (value:
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
async (value: any, subComponentValue?: any): Promise<boolean> => {
|
|
76
|
+
const hasChanged = selectedRows.some((row) => row[field as keyof RowType] !== value);
|
|
77
|
+
if (hasChanged) {
|
|
78
|
+
if (props.onSelectedItem) {
|
|
79
|
+
await props.onSelectedItem({ selectedRows, value, subComponentValue });
|
|
80
|
+
} else {
|
|
81
|
+
selectedRows.forEach((row) => (row[field] = value as any));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
},
|
|
86
|
+
[field, props, selectedRows],
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const clickItemHandler = useCallback(
|
|
90
|
+
async (value: any, subComponentValue?: any, reason?: string): Promise<boolean> => {
|
|
91
|
+
if (subComponentValue !== undefined && !subComponentIsValid.current) return false;
|
|
83
92
|
return updateValue(
|
|
84
|
-
async (
|
|
85
|
-
|
|
86
|
-
if (hasChanged) {
|
|
87
|
-
if (props.onSelectedItem) {
|
|
88
|
-
await props.onSelectedItem({ selectedRows, value, subComponentValue });
|
|
89
|
-
} else {
|
|
90
|
-
selectedRows.forEach((row) => (row[field as keyof RowType] = value));
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return true;
|
|
93
|
+
async () => {
|
|
94
|
+
return await selectItemHandler(value, subComponentValue);
|
|
94
95
|
},
|
|
95
96
|
reason === CloseReason.TAB_FORWARD ? 1 : reason === CloseReason.TAB_BACKWARD ? -1 : 0,
|
|
96
97
|
);
|
|
97
98
|
},
|
|
98
|
-
[
|
|
99
|
+
[selectItemHandler, updateValue],
|
|
99
100
|
);
|
|
100
101
|
|
|
101
102
|
const selectFilterHandler = useCallback(
|
|
@@ -118,16 +119,15 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(
|
|
|
118
119
|
optionsConf = await optionsConf(selectedRows, filter);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
const optionsList = optionsConf?.map((item) =>
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}) as any as FinalSelectOption<ValueType>[];
|
|
122
|
+
const optionsList = optionsConf?.map((item) =>
|
|
123
|
+
item == null || typeof item == "string"
|
|
124
|
+
? ({
|
|
125
|
+
value: item,
|
|
126
|
+
label: item,
|
|
127
|
+
disabled: false,
|
|
128
|
+
} as FinalSelectOption)
|
|
129
|
+
: item,
|
|
130
|
+
);
|
|
131
131
|
|
|
132
132
|
if (props.filtered) {
|
|
133
133
|
// This is needed otherwise when filter input is rendered and sets autofocus
|
|
@@ -177,6 +177,9 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(
|
|
|
177
177
|
}
|
|
178
178
|
}, [filter, props, researchOnFilterChange]);
|
|
179
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Saves are wrapped in updateValue and triggered by blur events
|
|
182
|
+
*/
|
|
180
183
|
const save = useCallback(async () => {
|
|
181
184
|
if (!options) return true;
|
|
182
185
|
const activeOptions = options.filter((option) => !filteredValues.includes(option.value));
|
|
@@ -188,7 +191,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(
|
|
|
188
191
|
// Handler for sub-selected value
|
|
189
192
|
if (!selectedSubComponent) return true;
|
|
190
193
|
if (selectedSubComponent.subComponent && !subComponentIsValid.current) return false;
|
|
191
|
-
await selectItemHandler(selectedSubComponent.value
|
|
194
|
+
await selectItemHandler(selectedSubComponent.value, subSelectedValue);
|
|
192
195
|
}
|
|
193
196
|
return true;
|
|
194
197
|
}, [
|
|
@@ -237,7 +240,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(
|
|
|
237
240
|
{options && options.length == filteredValues?.length && (
|
|
238
241
|
<MenuItem key={`${fieldToString(field)}-empty`}>[Empty]</MenuItem>
|
|
239
242
|
)}
|
|
240
|
-
{options?.map((item: FinalSelectOption
|
|
243
|
+
{options?.map((item: FinalSelectOption, index) =>
|
|
241
244
|
item.value === MenuSeparatorString ? (
|
|
242
245
|
<MenuDivider key={`$$divider_${index}`} />
|
|
243
246
|
) : item.value === MenuHeaderString ? (
|
|
@@ -261,8 +264,8 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(
|
|
|
261
264
|
}
|
|
262
265
|
e.keepOpen = true;
|
|
263
266
|
} else {
|
|
264
|
-
|
|
265
|
-
item.value
|
|
267
|
+
clickItemHandler(
|
|
268
|
+
item.value,
|
|
266
269
|
undefined,
|
|
267
270
|
e.key === "Tab"
|
|
268
271
|
? e.shiftKey
|
|
@@ -7,7 +7,6 @@ import { CellEditorCommon } from "../GridCell";
|
|
|
7
7
|
import { GridSubComponentContext } from "../../contexts/GridSubComponentContext";
|
|
8
8
|
import { ClickEvent } from "../../react-menu3/types";
|
|
9
9
|
import { useGridPopoverContext } from "../../contexts/GridPopoverContext";
|
|
10
|
-
import { CloseReason } from "../../react-menu3/utils";
|
|
11
10
|
|
|
12
11
|
export interface GridFormPopoutMenuProps<RowType extends GridBaseRow> extends CellEditorCommon {
|
|
13
12
|
options: (selectedRows: RowType[]) => Promise<MenuOption<RowType>[]>;
|
|
@@ -43,8 +42,6 @@ export const GridFormPopoverMenu = <RowType extends GridBaseRow>(props: GridForm
|
|
|
43
42
|
const optionsInitialising = useRef(false);
|
|
44
43
|
const [options, setOptions] = useState<MenuOption<RowType>[]>();
|
|
45
44
|
|
|
46
|
-
// Save triggers during async action processing which triggers another action(), this ref blocks that
|
|
47
|
-
const actionProcessing = useRef(false);
|
|
48
45
|
const [subComponentSelected, setSubComponentSelected] = useState<MenuOption<RowType> | null>(null);
|
|
49
46
|
const subComponentIsValid = useRef(false);
|
|
50
47
|
const [subSelectedValue, setSubSelectedValue] = useState<any>();
|
|
@@ -79,19 +76,12 @@ export const GridFormPopoverMenu = <RowType extends GridBaseRow>(props: GridForm
|
|
|
79
76
|
}, [options, props.defaultAction, props.options, selectedRows]);
|
|
80
77
|
|
|
81
78
|
const actionClick = useCallback(
|
|
82
|
-
async (menuOption: MenuOption<RowType
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const result = { ...menuOption, subValue: subSelectedValue };
|
|
87
|
-
await (menuOption.action ?? defaultAction)(selectedRows, result);
|
|
88
|
-
actionProcessing.current = false;
|
|
89
|
-
return true;
|
|
90
|
-
},
|
|
91
|
-
reason === CloseReason.TAB_FORWARD ? 1 : reason === CloseReason.TAB_BACKWARD ? -1 : 0,
|
|
92
|
-
);
|
|
79
|
+
async (menuOption: MenuOption<RowType>) => {
|
|
80
|
+
const result = { ...menuOption, subValue: subSelectedValue };
|
|
81
|
+
await (menuOption.action ?? defaultAction)(selectedRows, result);
|
|
82
|
+
return true;
|
|
93
83
|
},
|
|
94
|
-
[defaultAction, selectedRows, subSelectedValue
|
|
84
|
+
[defaultAction, selectedRows, subSelectedValue],
|
|
95
85
|
);
|
|
96
86
|
|
|
97
87
|
const onMenuItemClick = useCallback(
|
|
@@ -102,23 +92,19 @@ export const GridFormPopoverMenu = <RowType extends GridBaseRow>(props: GridForm
|
|
|
102
92
|
setSubComponentSelected(subComponentSelected === item ? null : item);
|
|
103
93
|
e.keepOpen = true;
|
|
104
94
|
} else {
|
|
105
|
-
await actionClick(
|
|
106
|
-
item,
|
|
107
|
-
e.key === "Tab" ? (e.shiftKey ? CloseReason.TAB_BACKWARD : CloseReason.TAB_FORWARD) : CloseReason.CLICK,
|
|
108
|
-
).then();
|
|
95
|
+
await updateValue(async () => actionClick(item), e.key === "Tab" ? (e.shiftKey ? -1 : 1) : 0);
|
|
109
96
|
}
|
|
110
97
|
},
|
|
111
|
-
[actionClick, subComponentSelected],
|
|
98
|
+
[actionClick, subComponentSelected, updateValue],
|
|
112
99
|
);
|
|
113
100
|
|
|
114
101
|
const save = useCallback(async () => {
|
|
115
102
|
// if a subcomponent is open we assume that it's meant to be saved.
|
|
116
|
-
if (
|
|
103
|
+
if (subComponentSelected) {
|
|
117
104
|
if (!subComponentIsValid.current) return false;
|
|
118
|
-
await actionClick(subComponentSelected
|
|
119
|
-
return true;
|
|
105
|
+
await actionClick(subComponentSelected);
|
|
120
106
|
}
|
|
121
|
-
//
|
|
107
|
+
// Close the menu
|
|
122
108
|
return true;
|
|
123
109
|
}, [actionClick, subComponentSelected]);
|
|
124
110
|
|
|
@@ -3,9 +3,9 @@ import { GridBaseRow } from "../Grid";
|
|
|
3
3
|
import { GridFormDropDown, GridFormPopoutDropDownProps } from "../gridForm/GridFormDropDown";
|
|
4
4
|
import { GenericCellColDef } from "../gridRender/GridRenderGenericCell";
|
|
5
5
|
|
|
6
|
-
export const GridPopoverEditDropDown = <RowType extends GridBaseRow
|
|
6
|
+
export const GridPopoverEditDropDown = <RowType extends GridBaseRow>(
|
|
7
7
|
colDef: GenericCellColDef<RowType>,
|
|
8
|
-
props: GenericCellEditorProps<GridFormPopoutDropDownProps<RowType
|
|
8
|
+
props: GenericCellEditorProps<GridFormPopoutDropDownProps<RowType>>,
|
|
9
9
|
): ColDefT<RowType> =>
|
|
10
10
|
GridCell(colDef, {
|
|
11
11
|
editor: GridFormDropDown,
|
|
@@ -13,6 +13,6 @@ export const GridPopoverEditDropDown = <RowType extends GridBaseRow, ValueType>(
|
|
|
13
13
|
editorParams: {
|
|
14
14
|
// Defaults to medium size container
|
|
15
15
|
className: "GridPopoverEditDropDown-containerMedium",
|
|
16
|
-
...(props.editorParams as GridFormPopoutDropDownProps<RowType
|
|
16
|
+
...(props.editorParams as GridFormPopoutDropDownProps<RowType>),
|
|
17
17
|
},
|
|
18
18
|
});
|
|
@@ -23,9 +23,9 @@ export interface GridContextType {
|
|
|
23
23
|
props: { selectedRows: GridBaseRow[]; field?: string },
|
|
24
24
|
fnUpdate: (selectedRows: any[]) => Promise<boolean>,
|
|
25
25
|
setSaving?: (saving: boolean) => void,
|
|
26
|
+
tabDirection?: 1 | 0 | -1,
|
|
26
27
|
) => Promise<boolean>;
|
|
27
28
|
redrawRows: (rowNodes?: RowNode[]) => void;
|
|
28
|
-
selectNextCell: (tabDirection: -1 | 0 | 1) => void;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export const GridContext = createContext<GridContextType>({
|
|
@@ -88,7 +88,4 @@ export const GridContext = createContext<GridContextType>({
|
|
|
88
88
|
redrawRows: () => {
|
|
89
89
|
console.error("no context provider for redrawRows");
|
|
90
90
|
},
|
|
91
|
-
selectNextCell: () => {
|
|
92
|
-
console.error("no context provider for selectNextCell");
|
|
93
|
-
},
|
|
94
91
|
});
|
|
@@ -234,10 +234,12 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
|
|
|
234
234
|
props: { selectedRows: GridBaseRow[]; field?: string },
|
|
235
235
|
fnUpdate: (selectedRows: any[]) => Promise<boolean>,
|
|
236
236
|
setSaving?: (saving: boolean) => void,
|
|
237
|
+
tabDirection?: 1 | 0 | -1,
|
|
237
238
|
): Promise<boolean> => {
|
|
238
239
|
setSaving && setSaving(true);
|
|
239
|
-
|
|
240
240
|
return await gridApiOp(async (gridApi) => {
|
|
241
|
+
const preOpCell = gridApi.getFocusedCell();
|
|
242
|
+
|
|
241
243
|
const selectedRows = props.selectedRows;
|
|
242
244
|
|
|
243
245
|
let ok = false;
|
|
@@ -265,6 +267,19 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
|
|
|
265
267
|
// Don't set saving if ok as the form has already closed
|
|
266
268
|
setSaving && setSaving(false);
|
|
267
269
|
}
|
|
270
|
+
|
|
271
|
+
// Only focus next cell if user hasn't already manually changed focus
|
|
272
|
+
const postOpCell = gridApi.getFocusedCell();
|
|
273
|
+
if (
|
|
274
|
+
tabDirection &&
|
|
275
|
+
preOpCell &&
|
|
276
|
+
postOpCell &&
|
|
277
|
+
preOpCell.rowIndex == postOpCell.rowIndex &&
|
|
278
|
+
preOpCell.column.getColId() == postOpCell.column.getColId()
|
|
279
|
+
) {
|
|
280
|
+
selectNextCell(tabDirection);
|
|
281
|
+
}
|
|
282
|
+
|
|
268
283
|
return ok;
|
|
269
284
|
});
|
|
270
285
|
};
|
|
@@ -303,7 +318,6 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
|
|
|
303
318
|
stopEditing,
|
|
304
319
|
updatingCells,
|
|
305
320
|
redrawRows,
|
|
306
|
-
selectNextCell,
|
|
307
321
|
}}
|
|
308
322
|
>
|
|
309
323
|
{props.children}
|
|
@@ -11,9 +11,10 @@ interface GridPopoverContextProps {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const GridPopoverContextProvider = ({ props, children }: GridPopoverContextProps) => {
|
|
14
|
-
const { getSelectedRows, updatingCells
|
|
14
|
+
const { getSelectedRows, updatingCells } = useContext(GridContext);
|
|
15
15
|
const anchorRef = useRef<Element>(props.eGridCell);
|
|
16
16
|
|
|
17
|
+
const hasSaved = useRef(false);
|
|
17
18
|
const [saving, setSaving] = useState(false);
|
|
18
19
|
|
|
19
20
|
const { colDef } = props;
|
|
@@ -28,18 +29,13 @@ export const GridPopoverContextProvider = ({ props, children }: GridPopoverConte
|
|
|
28
29
|
|
|
29
30
|
const updateValue = useCallback(
|
|
30
31
|
async (saveFn: (selectedRows: any[]) => Promise<boolean>, tabDirection: 1 | 0 | -1): Promise<boolean> => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
tabDirection && selectNextCell(tabDirection);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return result;
|
|
32
|
+
if (hasSaved.current) return true;
|
|
33
|
+
hasSaved.current = true;
|
|
34
|
+
const r = saving ? false : await updatingCells({ selectedRows, field }, saveFn, setSaving, tabDirection);
|
|
35
|
+
//if (r) stopEditing();
|
|
36
|
+
return r;
|
|
41
37
|
},
|
|
42
|
-
[field, saving,
|
|
38
|
+
[field, saving, selectedRows, updatingCells],
|
|
43
39
|
);
|
|
44
40
|
|
|
45
41
|
return (
|
|
@@ -82,8 +82,10 @@ export const ControlledMenuFr = (
|
|
|
82
82
|
// the cell doesn't refresh during update if save is invoked from a native event
|
|
83
83
|
// This doesn't happen in React18
|
|
84
84
|
// To work around it, I invoke the save by clicking on a passed in invisible button ref
|
|
85
|
-
if (saveButtonRef?.current)
|
|
86
|
-
|
|
85
|
+
if (saveButtonRef?.current) {
|
|
86
|
+
saveButtonRef.current.setAttribute("data-reason", CloseReason.BLUR);
|
|
87
|
+
saveButtonRef.current.click();
|
|
88
|
+
} else safeCall(onClose, { reason: CloseReason.BLUR });
|
|
87
89
|
|
|
88
90
|
// If a user clicks on the menu button when a menu is open, we need to close the menu.
|
|
89
91
|
// However, a blur event will be fired prior to the click event on menu button,
|
|
@@ -221,8 +223,8 @@ export const ControlledMenuFr = (
|
|
|
221
223
|
thisDocument.addEventListener("click", handleScreenEventForCancel, true);
|
|
222
224
|
thisDocument.addEventListener("dblclick", handleScreenEventForCancel, true);
|
|
223
225
|
return () => {
|
|
224
|
-
thisDocument.
|
|
225
|
-
thisDocument.
|
|
226
|
+
thisDocument.removeEventListener("keydown", handleKeydownTabAndEnter, true);
|
|
227
|
+
thisDocument.removeEventListener("keyup", handleKeyupTabAndEnter, true);
|
|
226
228
|
thisDocument.removeEventListener("mousedown", handleScreenEventForSave, true);
|
|
227
229
|
thisDocument.removeEventListener("mouseup", handleScreenEventForCancel, true);
|
|
228
230
|
thisDocument.removeEventListener("click", handleScreenEventForCancel, true);
|
|
@@ -66,7 +66,7 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
66
66
|
"Scrum Master",
|
|
67
67
|
"Tester",
|
|
68
68
|
MenuSeparatorString,
|
|
69
|
-
"
|
|
69
|
+
"Custom",
|
|
70
70
|
].filter((v) => (filter != null ? v != null && v.toLowerCase().indexOf(filter) === 0 : true));
|
|
71
71
|
}, []);
|
|
72
72
|
|
|
@@ -86,20 +86,6 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
86
86
|
initialWidth: 65,
|
|
87
87
|
maxWidth: 85,
|
|
88
88
|
}),
|
|
89
|
-
GridPopoverEditDropDown(
|
|
90
|
-
{
|
|
91
|
-
field: "position",
|
|
92
|
-
initialWidth: 65,
|
|
93
|
-
maxWidth: 150,
|
|
94
|
-
headerName: "Position",
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
multiEdit: false,
|
|
98
|
-
editorParams: {
|
|
99
|
-
options: ["Architect", "Developer", "Product Owner", "Scrum Master", "Tester", MenuSeparator, "(other)"],
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
),
|
|
103
89
|
GridPopoverEditDropDown(
|
|
104
90
|
{
|
|
105
91
|
field: "position2",
|
|
@@ -133,7 +119,7 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
133
119
|
{
|
|
134
120
|
multiEdit: true,
|
|
135
121
|
editorParams: {
|
|
136
|
-
options: [null, "Architect", "Developer", "Product Owner", "Scrum Master", "Tester"
|
|
122
|
+
options: [null, "Architect", "Developer", "Product Owner", "Scrum Master", "Tester"],
|
|
137
123
|
onSelectedItem: async (selected) => {
|
|
138
124
|
await wait(2000);
|
|
139
125
|
selected.selectedRows.forEach((row) => {
|
|
@@ -178,7 +164,7 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
178
164
|
editorParams: {
|
|
179
165
|
filtered: "local",
|
|
180
166
|
filterPlaceholder: "Filter this",
|
|
181
|
-
options: [null, "Architect", "Developer", "Product Owner", "Scrum Master", "Tester"
|
|
167
|
+
options: [null, "Architect", "Developer", "Product Owner", "Scrum Master", "Tester"],
|
|
182
168
|
},
|
|
183
169
|
},
|
|
184
170
|
),
|
|
@@ -201,33 +187,12 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
201
187
|
},
|
|
202
188
|
},
|
|
203
189
|
),
|
|
204
|
-
GridPopoverEditDropDown(
|
|
205
|
-
{
|
|
206
|
-
field: "code",
|
|
207
|
-
initialWidth: 65,
|
|
208
|
-
maxWidth: 150,
|
|
209
|
-
headerName: "Max height",
|
|
210
|
-
valueGetter: (params) => params.data.code,
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
multiEdit: true,
|
|
214
|
-
editorParams: {
|
|
215
|
-
className: "GridPopoverEditDropDown-containerSmall",
|
|
216
|
-
filtered: "local",
|
|
217
|
-
filterPlaceholder: "Filter this",
|
|
218
|
-
options: Array.from(Array(30).keys()).map((o) => {
|
|
219
|
-
return { value: o, label: `${o}` };
|
|
220
|
-
}),
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
),
|
|
224
190
|
GridPopoverEditDropDown(
|
|
225
191
|
{
|
|
226
192
|
field: "code",
|
|
227
193
|
initialWidth: 65,
|
|
228
194
|
maxWidth: 150,
|
|
229
195
|
headerName: "Filter Selectable",
|
|
230
|
-
valueGetter: (params) => params.data.code,
|
|
231
196
|
},
|
|
232
197
|
{
|
|
233
198
|
multiEdit: true,
|
|
@@ -291,7 +256,7 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
|
|
|
291
256
|
{},
|
|
292
257
|
{
|
|
293
258
|
editorParams: {
|
|
294
|
-
options: async () => [{ label: "Hello", action: async () => {}
|
|
259
|
+
options: async () => [{ label: "Hello", action: async () => {} }],
|
|
295
260
|
},
|
|
296
261
|
},
|
|
297
262
|
),
|
|
@@ -63,7 +63,7 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
63
63
|
required: true,
|
|
64
64
|
maxLength: 12,
|
|
65
65
|
placeholder: "Enter some text...",
|
|
66
|
-
|
|
66
|
+
invalid: (value: string) => {
|
|
67
67
|
if (value === "never") return "The value 'never' is not allowed";
|
|
68
68
|
return null;
|
|
69
69
|
},
|
|
@@ -91,7 +91,7 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
91
91
|
maxLength: 12,
|
|
92
92
|
placeholder: "Enter distance...",
|
|
93
93
|
units: "m",
|
|
94
|
-
|
|
94
|
+
invalid: (value: string) => {
|
|
95
95
|
if (value.length && !isFloat(value)) return "Value must be a number";
|
|
96
96
|
return null;
|
|
97
97
|
},
|
|
@@ -118,7 +118,7 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
118
118
|
maxLength: 32,
|
|
119
119
|
placeholder: "Enter some text...",
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
invalid: (value: string) => {
|
|
122
122
|
if (value === "never") return "The value 'never' is not allowed";
|
|
123
123
|
return null;
|
|
124
124
|
},
|
|
@@ -144,7 +144,6 @@ const GridPopoutEditGenericTemplate: ComponentStory<typeof Grid> = (props: GridP
|
|
|
144
144
|
await wait(1500);
|
|
145
145
|
setRowData(rowData.filter((data) => !selectedRows.some((row) => row.id == data.id)));
|
|
146
146
|
},
|
|
147
|
-
supportsMultiEdit: true,
|
|
148
147
|
},
|
|
149
148
|
],
|
|
150
149
|
},
|
|
@@ -139,7 +139,6 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
|
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
141
|
label: "Other (TextArea)",
|
|
142
|
-
supportsMultiEdit: true,
|
|
143
142
|
action: async (_, menuOptionResult) => {
|
|
144
143
|
// eslint-disable-next-line no-console
|
|
145
144
|
console.log(`Sub selected value was ${JSON.stringify(menuOptionResult.subValue)}`);
|
package/src/utils/bearing.ts
CHANGED
|
@@ -27,7 +27,7 @@ export const bearingNumberParser = (value: string): number | null => {
|
|
|
27
27
|
const validMaskForDmsBearing = /^((-)?\d+)?(\.([0-5](\d([0-5](\d(\d+)?)?)?)?)?)?$/;
|
|
28
28
|
export const bearingStringValidator = (
|
|
29
29
|
value: string,
|
|
30
|
-
|
|
30
|
+
customInvalid?: (value: number | null) => string | null,
|
|
31
31
|
): string | null => {
|
|
32
32
|
value = value.trim();
|
|
33
33
|
if (value === "") return null;
|
|
@@ -39,7 +39,7 @@ export const bearingStringValidator = (
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
const bearing = parseFloat(value);
|
|
42
|
-
return
|
|
42
|
+
return customInvalid ? customInvalid(bearing) : null;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
// Decimal-ish degrees to Degrees Minutes Seconds converter
|
|
@@ -3,7 +3,8 @@ import { GridBaseRow } from "../components/Grid";
|
|
|
3
3
|
export interface TextInputValidatorProps<RowType extends GridBaseRow> {
|
|
4
4
|
required?: boolean;
|
|
5
5
|
maxLength?: number;
|
|
6
|
-
|
|
6
|
+
maxBytes?: number;
|
|
7
|
+
invalid?: (value: string, data: RowType) => string | null;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export const TextInputValidator = <RowType extends GridBaseRow>(
|
|
@@ -23,8 +24,11 @@ export const TextInputValidator = <RowType extends GridBaseRow>(
|
|
|
23
24
|
if (props.maxLength && value.length > props.maxLength) {
|
|
24
25
|
return `Text must be no longer than ${props.maxLength} characters`;
|
|
25
26
|
}
|
|
26
|
-
if (props.
|
|
27
|
-
return props.
|
|
27
|
+
if (props.maxBytes && new TextEncoder().encode(value).length > props.maxBytes) {
|
|
28
|
+
return `Text must be no longer than ${props.maxLength} bytes`;
|
|
29
|
+
}
|
|
30
|
+
if (props.invalid) {
|
|
31
|
+
return props.invalid(value, data);
|
|
28
32
|
}
|
|
29
33
|
return null;
|
|
30
34
|
};
|