@linzjs/step-ag-grid 7.19.6 → 8.1.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.
Files changed (39) hide show
  1. package/dist/index.css +4 -0
  2. package/dist/src/components/Grid.d.ts +2 -1
  3. package/dist/src/components/gridForm/GridFormDropDown.d.ts +1 -0
  4. package/dist/src/components/gridForm/GridFormEditBearing.d.ts +5 -1
  5. package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +8 -2
  6. package/dist/src/components/gridForm/GridFormPopoverMenu.d.ts +11 -6
  7. package/dist/src/components/gridForm/GridFormTextArea.d.ts +4 -1
  8. package/dist/src/components/gridForm/GridFormTextInput.d.ts +4 -1
  9. package/dist/src/components/gridPopoverEdit/GridPopoverEditBearing.d.ts +10 -1
  10. package/dist/src/components/gridPopoverEdit/GridPopoverMenu.d.ts +2 -2
  11. package/dist/src/lui/ActionButton.d.ts +2 -1
  12. package/dist/src/utils/bearing.d.ts +2 -3
  13. package/dist/step-ag-grid.esm.js +135 -98
  14. package/dist/step-ag-grid.esm.js.map +1 -1
  15. package/package.json +1 -1
  16. package/src/components/Grid.tsx +3 -3
  17. package/src/components/gridForm/GridFormDropDown.tsx +86 -71
  18. package/src/components/gridForm/GridFormEditBearing.tsx +9 -4
  19. package/src/components/gridForm/GridFormMultiSelect.tsx +7 -7
  20. package/src/components/gridForm/GridFormPopoverMenu.tsx +62 -53
  21. package/src/components/gridForm/GridFormTextArea.tsx +2 -2
  22. package/src/components/gridForm/GridFormTextInput.tsx +2 -2
  23. package/src/components/gridPopoverEdit/GridPopoverEditBearing.ts +40 -32
  24. package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +3 -3
  25. package/src/lui/ActionButton.tsx +3 -1
  26. package/src/react-menu3/components/ControlledMenu.tsx +5 -1
  27. package/src/react-menu3/styles/index.scss +4 -0
  28. package/src/stories/components/ActionButton.stories.tsx +11 -0
  29. package/src/stories/grid/GridNonEditableRow.stories.tsx +6 -6
  30. package/src/stories/grid/GridPopoutBearing.stories.tsx +1 -1
  31. package/src/stories/grid/GridPopoutEditGenericTextArea.stories.tsx +5 -5
  32. package/src/stories/grid/GridPopoutEditMultiSelect.stories.tsx +3 -3
  33. package/src/stories/grid/GridReadOnly.stories.tsx +6 -6
  34. package/src/stories/grid/gridForm/GridFormDropDown.stories.tsx +109 -0
  35. package/src/stories/grid/gridForm/GridFormEditBearing.stories.tsx +54 -0
  36. package/src/stories/grid/gridForm/GridFormEditBearingCorrection.stories.tsx +54 -0
  37. package/src/stories/grid/gridForm/GridFormMessage.stories.tsx +32 -0
  38. package/src/stories/grid/gridForm/GridFormPopoverMenu.stories.tsx +55 -0
  39. package/src/utils/bearing.ts +10 -12
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.19.6",
5
+ "version": "8.1.0",
6
6
  "keywords": [
7
7
  "aggrid",
8
8
  "ag-grid",
@@ -27,7 +27,7 @@ export interface GridProps {
27
27
  externalSelectedItems?: any[];
28
28
  setExternalSelectedItems?: (items: any[]) => void;
29
29
  defaultColDef?: GridOptions["defaultColDef"];
30
- columnDefs: GridOptions["columnDefs"];
30
+ columnDefs: ColDef[];
31
31
  rowData: GridOptions["rowData"];
32
32
  noRowsOverlayText?: string;
33
33
  postSortRows?: GridOptions["postSortRows"];
@@ -168,8 +168,8 @@ export const Grid = (params: GridProps): JSX.Element => {
168
168
  synchroniseExternallySelectedItemsToGrid();
169
169
  }, [synchroniseExternallySelectedItemsToGrid]);
170
170
 
171
- const columnDefs = useMemo((): GridOptions["columnDefs"] => {
172
- const adjustColDefs = (params.columnDefs as ColDef[]).map((colDef) => {
171
+ const columnDefs = useMemo((): ColDef[] => {
172
+ const adjustColDefs = params.columnDefs.map((colDef) => {
173
173
  return {
174
174
  ...colDef,
175
175
  editable: params.readOnly ? false : params.defaultColDef?.editable ?? colDef.editable,
@@ -45,8 +45,9 @@ export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow> extend
45
45
  | "GridPopoverEditDropDown-containerUnlimited"
46
46
  | string
47
47
  | undefined;
48
- // local means the filter won't change if it's reloaded, reload means it does change
48
+ // local means the use the local filter, otherwise it's expected options will be passed a function that takes a filter
49
49
  filtered?: "local" | "reload";
50
+ filterDefaultValue?: string;
50
51
  filterPlaceholder?: string;
51
52
  filterHelpText?: string;
52
53
  noOptionsMessage?: string;
@@ -66,7 +67,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
66
67
  const { selectedRows, field, data } = useGridPopoverContext<RowType>();
67
68
 
68
69
  // Save triggers during async action processing which triggers another selectItem(), this ref blocks that
69
- const [filter, setFilter] = useState("");
70
+ const [filter, setFilter] = useState(props.filterDefaultValue ?? "");
70
71
  const [filteredValues, setFilteredValues] = useState<any[]>();
71
72
  const [options, setOptions] = useState<FinalSelectOption[] | null>(null);
72
73
  const subComponentIsValid = useRef(false);
@@ -143,7 +144,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
143
144
  }
144
145
  }, [props.filtered, filter, options]);
145
146
 
146
- const researchOnFilterChange = useMemo(
147
+ const reSearchOnFilterChange = useMemo(
147
148
  () =>
148
149
  debounce(() => {
149
150
  setOptions(null);
@@ -157,9 +158,9 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
157
158
  useEffect(() => {
158
159
  if (previousFilter.current != filter && props.filtered == "reload") {
159
160
  previousFilter.current = filter;
160
- researchOnFilterChange().then();
161
+ reSearchOnFilterChange().then();
161
162
  }
162
- }, [filter, props, researchOnFilterChange]);
163
+ }, [filter, props, reSearchOnFilterChange]);
163
164
 
164
165
  /**
165
166
  * Saves are wrapped in updateValue and triggered by blur events
@@ -193,6 +194,9 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
193
194
  save,
194
195
  });
195
196
 
197
+ let lastHeader: JSX.Element | null = null;
198
+ let showHeader: JSX.Element | null = null;
199
+
196
200
  return popoverWrapper(
197
201
  <>
198
202
  {props.filtered && (
@@ -237,76 +241,87 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
237
241
  {props.noOptionsMessage ?? "No Options"}
238
242
  </MenuItem>
239
243
  )}
240
- {options?.map((item: FinalSelectOption, index) =>
241
- item.value === MenuSeparatorString ? (
242
- <MenuDivider key={`$$divider_${index}`} />
243
- ) : item.value === MenuHeaderString ? (
244
- <MenuHeader key={`$$header_${index}`}>{item.label}</MenuHeader>
245
- ) : (
244
+ {options?.map((item: FinalSelectOption, index) => {
245
+ showHeader = null;
246
+ if (item.value === MenuSeparatorString) {
247
+ return <MenuDivider key={`$$divider_${index}`} />;
248
+ } else if (item.value === MenuHeaderString) {
249
+ lastHeader = <MenuHeader key={`$$header_${index}`}>{item.label}</MenuHeader>;
250
+ return <></>;
251
+ } else {
252
+ if (lastHeader) {
253
+ showHeader = lastHeader;
254
+ lastHeader = null;
255
+ }
256
+ }
257
+ return (
246
258
  (!filteredValues || filteredValues.includes(item)) && (
247
- <div key={`menu-wrapper-${index}`}>
248
- <MenuItem
249
- key={`${fieldToString(field)}-${index}`}
250
- disabled={!!item.disabled}
251
- title={item.disabled && typeof item.disabled !== "boolean" ? item.disabled : ""}
252
- value={item.value}
253
- onFocus={() => {
254
- setSelectedItem(item);
255
- if (item.subComponent) {
259
+ <>
260
+ {showHeader}
261
+ <div key={`menu-wrapper-${index}`}>
262
+ <MenuItem
263
+ key={`${fieldToString(field)}-${index}`}
264
+ disabled={!!item.disabled}
265
+ title={item.disabled && typeof item.disabled !== "boolean" ? item.disabled : ""}
266
+ value={item.value}
267
+ onFocus={() => {
256
268
  setSelectedItem(item);
257
- subComponentIsValid.current = true;
258
- subComponentInitialValue.current = null;
259
- } else {
260
- setSubSelectedValue(null);
261
- subComponentIsValid.current = true;
262
- }
263
- }}
264
- onClick={(e: ClickEvent) => {
265
- if (item.subComponent) {
266
- e.keepOpen = true;
267
- }
268
- }}
269
- >
270
- {item.label ?? (item.value == null ? `<${item.value}>` : `${item.value}`)}
271
- {item.subComponent ? "..." : ""}
272
- </MenuItem>
269
+ if (item.subComponent) {
270
+ setSelectedItem(item);
271
+ subComponentIsValid.current = true;
272
+ subComponentInitialValue.current = null;
273
+ } else {
274
+ setSubSelectedValue(null);
275
+ subComponentIsValid.current = true;
276
+ }
277
+ }}
278
+ onClick={(e: ClickEvent) => {
279
+ if (item.subComponent) {
280
+ e.keepOpen = true;
281
+ }
282
+ }}
283
+ >
284
+ {item.label ?? (item.value == null ? `<${item.value}>` : `${item.value}`)}
285
+ {item.subComponent ? "..." : ""}
286
+ </MenuItem>
273
287
 
274
- {item.subComponent && selectedItem === item && (
275
- <FocusableItem className={"LuiDeprecatedForms"} key={`${item.label}_subcomponent`}>
276
- {(ref: MenuInstance) => (
277
- <GridSubComponentContext.Provider
278
- value={{
279
- context: { options },
280
- data,
281
- value: subSelectedValue,
282
- setValue: (value: any) => {
283
- setSubSelectedValue(value);
284
- if (subComponentInitialValue.current === null) {
285
- // copy the default value of the sub-component so we can change detect on save
286
- subComponentInitialValue.current = JSON.stringify(value);
287
- }
288
- },
289
- setValid: (valid: boolean) => {
290
- subComponentIsValid.current = valid;
291
- },
292
- triggerSave: async () => {
293
- ref.closeMenu();
294
- },
295
- }}
296
- >
297
- {item.subComponent && (
298
- <div className={"subComponent"}>
299
- <item.subComponent key={`${fieldToString(field)}-${index}_subcomponent_inner`} />
300
- </div>
301
- )}
302
- </GridSubComponentContext.Provider>
303
- )}
304
- </FocusableItem>
305
- )}
306
- </div>
288
+ {item.subComponent && selectedItem === item && (
289
+ <FocusableItem className={"LuiDeprecatedForms"} key={`${item.label}_subcomponent`}>
290
+ {(ref: MenuInstance) => (
291
+ <GridSubComponentContext.Provider
292
+ value={{
293
+ context: { options },
294
+ data,
295
+ value: subSelectedValue,
296
+ setValue: (value: any) => {
297
+ setSubSelectedValue(value);
298
+ if (subComponentInitialValue.current === null) {
299
+ // copy the default value of the subcomponent so we can change detect on save
300
+ subComponentInitialValue.current = JSON.stringify(value);
301
+ }
302
+ },
303
+ setValid: (valid: boolean) => {
304
+ subComponentIsValid.current = valid;
305
+ },
306
+ triggerSave: async () => {
307
+ ref.closeMenu();
308
+ },
309
+ }}
310
+ >
311
+ {item.subComponent && (
312
+ <div className={"subComponent"}>
313
+ <item.subComponent key={`${fieldToString(field)}-${index}_subcomponent_inner`} />
314
+ </div>
315
+ )}
316
+ </GridSubComponentContext.Provider>
317
+ )}
318
+ </FocusableItem>
319
+ )}
320
+ </div>
321
+ </>
307
322
  )
308
- ),
309
- )}
323
+ );
324
+ })}
310
325
  </>
311
326
  </ComponentLoadingWrapper>
312
327
  </>,
@@ -7,13 +7,14 @@ import { CellEditorCommon } from "../GridCell";
7
7
  import { useGridPopoverContext } from "../../contexts/GridPopoverContext";
8
8
 
9
9
  export interface GridFormEditBearingProps<RowType extends GridBaseRow> extends CellEditorCommon {
10
+ formatValue?: (value: any) => string;
10
11
  placeHolder?: string;
11
12
  range?: (value: number | null) => string | null;
12
- onSave?: (selectedRows: RowType[], value: number | null) => Promise<boolean>;
13
+ onSave?: (props: { selectedRows: RowType[]; value: number | null }) => Promise<boolean>;
13
14
  }
14
15
 
15
16
  export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridFormEditBearingProps<RowType>) => {
16
- const { field, value: initialValue, formatValue } = useGridPopoverContext<RowType>();
17
+ const { field, value: initialValue } = useGridPopoverContext<RowType>();
17
18
 
18
19
  // This clears out any scientific precision
19
20
  const defaultValue = useMemo(
@@ -34,7 +35,7 @@ export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridForm
34
35
  }
35
36
 
36
37
  if (props.onSave) {
37
- return await props.onSave(selectedRows, parsedValue);
38
+ return await props.onSave({ selectedRows, value: parsedValue });
38
39
  } else {
39
40
  if (field == null) {
40
41
  console.error("field is not defined in ColDef");
@@ -63,7 +64,11 @@ export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridForm
63
64
  }}
64
65
  autoFocus={true}
65
66
  placeholder={props.placeHolder}
66
- formatted={bearingStringValidator(value, props.range) ? "?" : formatValue(bearingNumberParser(value))}
67
+ formatted={
68
+ bearingStringValidator(value, props.range) || !props.formatValue
69
+ ? "?"
70
+ : props.formatValue(bearingNumberParser(value))
71
+ }
67
72
  error={bearingStringValidator(value, props.range)}
68
73
  helpText={"Press enter or tab to save"}
69
74
  />
@@ -52,8 +52,8 @@ export interface GridFormMultiSelectProps<RowType extends GridBaseRow> extends C
52
52
  filtered?: boolean;
53
53
  filterPlaceholder?: string;
54
54
  filterHelpText?: string | ((filter: string, options: MultiSelectOption[]) => string | undefined);
55
- onSelectFilter?: (filter: string, options: MultiSelectOption[]) => void;
56
- onSave?: (selectedRows: RowType[], selectedOptions: MultiSelectOption[]) => Promise<boolean>;
55
+ onSelectFilter?: (props: { filter: string; options: MultiSelectOption[] }) => void;
56
+ onSave?: (props: { selectedRows: RowType[]; selectedOptions: MultiSelectOption[] }) => Promise<boolean>;
57
57
  headers?: GridFormMultiSelectGroup[];
58
58
  options: MultiSelectOption[] | ((selectedRows: RowType[]) => Promise<MultiSelectOption[]> | MultiSelectOption[]);
59
59
  invalid?: (selectedRows: RowType[], selectedOptions: MultiSelectOption[]) => boolean;
@@ -90,10 +90,10 @@ export const GridFormMultiSelect = <RowType extends GridBaseRow>(props: GridForm
90
90
  // Any changes to save?
91
91
  if (initialValues === JSON.stringify(options)) return true;
92
92
 
93
- return props.onSave(
93
+ return props.onSave({
94
94
  selectedRows,
95
- options.filter((o) => o.checked),
96
- );
95
+ selectedOptions: options.filter((o) => o.checked),
96
+ });
97
97
  },
98
98
  [initialValues, options, props],
99
99
  );
@@ -203,7 +203,7 @@ export const GridFormMultiSelect = <RowType extends GridBaseRow>(props: GridForm
203
203
  const FilterInput = (props: {
204
204
  options: MultiSelectOption[];
205
205
  setOptions: (options: MultiSelectOption[]) => void;
206
- onSelectFilter?: (filter: string, options: MultiSelectOption[]) => void;
206
+ onSelectFilter?: (props: { filter: string; options: MultiSelectOption[] }) => void;
207
207
  filter: string;
208
208
  setFilter: Dispatch<SetStateAction<string>>;
209
209
  headerGroups: HeaderGroupType;
@@ -259,7 +259,7 @@ const FilterInput = (props: {
259
259
  }
260
260
 
261
261
  const preFilterOptions = JSON.stringify(options);
262
- onSelectFilter(filterTrimmed, options);
262
+ onSelectFilter({ filter: filterTrimmed, options });
263
263
  // Detect if options list changed and update
264
264
  if (preFilterOptions === JSON.stringify(options)) return;
265
265
 
@@ -8,13 +8,14 @@ import { GridSubComponentContext } from "../../contexts/GridSubComponentContext"
8
8
  import { ClickEvent } from "../../react-menu3/types";
9
9
  import { useGridPopoverContext } from "../../contexts/GridPopoverContext";
10
10
 
11
- export interface GridFormPopoutMenuProps<RowType extends GridBaseRow> extends CellEditorCommon {
11
+ export interface GridFormPopoverMenuProps<RowType extends GridBaseRow> extends CellEditorCommon {
12
12
  options: (selectedRows: RowType[]) => Promise<MenuOption<RowType>[]>;
13
- defaultAction?: (selectedRows: RowType[], menuOption: SelectedMenuOptionResult<RowType>) => Promise<void>;
13
+ defaultAction?: (props: { selectedRows: RowType[]; menuOption: SelectedMenuOptionResult<RowType> }) => Promise<void>;
14
14
  }
15
15
 
16
16
  /** Menu configuration types **/
17
- export const PopoutMenuSeparator = Object.freeze({ __isMenuSeparator__: true });
17
+ const __isMenuSeparator__ = "__isMenuSeparator__";
18
+ export const PopoutMenuSeparator = Object.freeze({ label: __isMenuSeparator__ });
18
19
 
19
20
  interface MenuSeparatorType {
20
21
  __isMenuSeparator__: boolean;
@@ -26,7 +27,7 @@ export interface SelectedMenuOptionResult<RowType extends GridBaseRow> extends M
26
27
 
27
28
  export interface MenuOption<RowType extends GridBaseRow> {
28
29
  label: JSX.Element | string | MenuSeparatorType;
29
- action?: (selectedRows: RowType[], menuOption: SelectedMenuOptionResult<RowType>) => Promise<void>;
30
+ action?: (props: { selectedRows: RowType[]; menuOption: SelectedMenuOptionResult<RowType> }) => Promise<void>;
30
31
  disabled?: string | boolean;
31
32
  hidden?: boolean;
32
33
  subComponent?: (props: any) => JSX.Element;
@@ -36,7 +37,7 @@ export interface MenuOption<RowType extends GridBaseRow> {
36
37
  * NOTE: If the popout menu doesn't appear on single click when also selecting row it's because
37
38
  * you need a useMemo around your columnDefs
38
39
  */
39
- export const GridFormPopoverMenu = <RowType extends GridBaseRow>(props: GridFormPopoutMenuProps<RowType>) => {
40
+ export const GridFormPopoverMenu = <RowType extends GridBaseRow>(props: GridFormPopoverMenuProps<RowType>) => {
40
41
  const { selectedRows, updateValue, data } = useGridPopoverContext<RowType>();
41
42
 
42
43
  const optionsInitialising = useRef(false);
@@ -47,9 +48,9 @@ export const GridFormPopoverMenu = <RowType extends GridBaseRow>(props: GridForm
47
48
  const [subSelectedValue, setSubSelectedValue] = useState<any>();
48
49
 
49
50
  const defaultAction = useCallback(
50
- async (selectedRows: RowType[], menuOption: SelectedMenuOptionResult<RowType>) => {
51
- if (props.defaultAction) await props.defaultAction(selectedRows, menuOption);
52
- else console.error(`No action specified for ${menuOption.label} menu options`);
51
+ async (params: { selectedRows: RowType[]; menuOption: SelectedMenuOptionResult<RowType> }) => {
52
+ if (props.defaultAction) await props.defaultAction(params);
53
+ else console.error(`No action specified for ${params.menuOption.label} menu options`);
53
54
  },
54
55
  [props],
55
56
  );
@@ -77,8 +78,10 @@ export const GridFormPopoverMenu = <RowType extends GridBaseRow>(props: GridForm
77
78
 
78
79
  const actionClick = useCallback(
79
80
  async (menuOption: MenuOption<RowType>) => {
80
- const result = { ...menuOption, subValue: subSelectedValue };
81
- await (menuOption.action ?? defaultAction)(selectedRows, result);
81
+ await (menuOption.action ?? defaultAction)({
82
+ selectedRows,
83
+ menuOption: { ...menuOption, subValue: subSelectedValue },
84
+ });
82
85
  return true;
83
86
  },
84
87
  [defaultAction, selectedRows, subSelectedValue],
@@ -117,49 +120,55 @@ export const GridFormPopoverMenu = <RowType extends GridBaseRow>(props: GridForm
117
120
  return popoverWrapper(
118
121
  <ComponentLoadingWrapper loading={!options} className={"GridFormPopupMenu"}>
119
122
  <>
120
- {options?.map((item, index) =>
121
- item.label === PopoutMenuSeparator ? (
122
- <MenuDivider key={`$$divider_${index}`} />
123
- ) : (
124
- !item.hidden && (
125
- <Fragment key={`${item.label}`}>
126
- <MenuItem
127
- key={`${item.label}`}
128
- onClick={(e: ClickEvent) => onMenuItemClick(e, item)}
129
- disabled={!!item.disabled}
130
- title={item.disabled && typeof item.disabled !== "boolean" ? item.disabled : ""}
131
- >
132
- {item.label as JSX.Element | string}
133
- </MenuItem>
134
- {item.subComponent && subComponentSelected === item && (
135
- <FocusableItem className={"LuiDeprecatedForms"} key={`${item.label}_subcomponent`}>
136
- {(_: any) =>
137
- item.subComponent && (
138
- <GridSubComponentContext.Provider
139
- value={{
140
- context: {},
141
- data,
142
- value: subSelectedValue,
143
- setValue: (value: any) => {
144
- setSubSelectedValue(value);
145
- },
146
- setValid: (valid: boolean) => {
147
- subComponentIsValid.current = valid;
148
- },
149
- triggerSave,
150
- }}
151
- >
152
- <div className={"subComponent"}>
153
- <item.subComponent />
154
- </div>
155
- </GridSubComponentContext.Provider>
156
- )
157
- }
158
- </FocusableItem>
159
- )}
160
- </Fragment>
161
- )
162
- ),
123
+ {options?.length === 0 ? (
124
+ <MenuItem key={`GridPopoverMenu-empty`} className={"GridPopoverMenu-noOptions"} disabled={true}>
125
+ No actions
126
+ </MenuItem>
127
+ ) : (
128
+ options?.map((item, index) =>
129
+ item.label === "__isMenuSeparator__" ? (
130
+ <MenuDivider key={`$$divider_${index}`} />
131
+ ) : (
132
+ !item.hidden && (
133
+ <Fragment key={`${item.label}`}>
134
+ <MenuItem
135
+ key={`${item.label}`}
136
+ onClick={(e: ClickEvent) => onMenuItemClick(e, item)}
137
+ disabled={!!item.disabled}
138
+ title={item.disabled && typeof item.disabled !== "boolean" ? item.disabled : ""}
139
+ >
140
+ {item.label as JSX.Element | string}
141
+ </MenuItem>
142
+ {item.subComponent && subComponentSelected === item && (
143
+ <FocusableItem className={"LuiDeprecatedForms"} key={`${item.label}_subcomponent`}>
144
+ {(_: any) =>
145
+ item.subComponent && (
146
+ <GridSubComponentContext.Provider
147
+ value={{
148
+ context: {},
149
+ data,
150
+ value: subSelectedValue,
151
+ setValue: (value: any) => {
152
+ setSubSelectedValue(value);
153
+ },
154
+ setValid: (valid: boolean) => {
155
+ subComponentIsValid.current = valid;
156
+ },
157
+ triggerSave,
158
+ }}
159
+ >
160
+ <div className={"subComponent"}>
161
+ <item.subComponent />
162
+ </div>
163
+ </GridSubComponentContext.Provider>
164
+ )
165
+ }
166
+ </FocusableItem>
167
+ )}
168
+ </Fragment>
169
+ )
170
+ ),
171
+ )
163
172
  )}
164
173
  </>
165
174
  </ComponentLoadingWrapper>,
@@ -11,7 +11,7 @@ export interface GridFormTextAreaProps<RowType extends GridBaseRow>
11
11
  CellEditorCommon {
12
12
  placeholder?: string;
13
13
  width?: string | number;
14
- onSave?: (selectedRows: RowType[], value: string) => Promise<boolean>;
14
+ onSave?: (props: { selectedRows: RowType[]; value: string }) => Promise<boolean>;
15
15
  helpText?: string;
16
16
  }
17
17
 
@@ -34,7 +34,7 @@ export const GridFormTextArea = <RowType extends GridBaseRow>(props: GridFormTex
34
34
  if (initValue === trimmedValue) return true;
35
35
 
36
36
  if (props.onSave) {
37
- return await props.onSave(selectedRows, trimmedValue);
37
+ return await props.onSave({ selectedRows, value: trimmedValue });
38
38
  }
39
39
 
40
40
  selectedRows.forEach((row) => (row[field] = trimmedValue as any));
@@ -12,7 +12,7 @@ export interface GridFormTextInputProps<RowType extends GridBaseRow>
12
12
  placeholder?: string;
13
13
  units?: string;
14
14
  width?: string | number;
15
- onSave?: (selectedRows: RowType[], value: string) => Promise<boolean>;
15
+ onSave?: (props: { selectedRows: RowType[]; value: string }) => Promise<boolean>;
16
16
  helpText?: string;
17
17
  }
18
18
 
@@ -35,7 +35,7 @@ export const GridFormTextInput = <RowType extends GridBaseRow>(props: GridFormTe
35
35
  if (initValue === trimmedValue) return true;
36
36
 
37
37
  if (props.onSave) {
38
- return await props.onSave(selectedRows, trimmedValue);
38
+ return await props.onSave({ selectedRows, value: trimmedValue });
39
39
  }
40
40
 
41
41
  selectedRows.forEach((row) => (row[field] = trimmedValue as any));
@@ -3,15 +3,19 @@ import { ColDefT, GenericCellEditorProps, GridCell } from "../GridCell";
3
3
  import { GridFormEditBearing, GridFormEditBearingProps } from "../gridForm/GridFormEditBearing";
4
4
  import { GridBaseRow } from "../Grid";
5
5
  import { GenericCellColDef } from "../gridRender/GridRenderGenericCell";
6
+ import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
6
7
 
7
- export const GridPopoverEditBearingLike = <RowType extends GridBaseRow>(
8
+ const GridPopoverEditBearingLike = <RowType extends GridBaseRow>(
8
9
  colDef: GenericCellColDef<RowType>,
9
- props: GenericCellEditorProps<GridFormEditBearingProps<RowType>>,
10
+ props: GenericCellEditorProps<GridFormEditBearingProps<RowType>> & {
11
+ editorParams: { formatValue: (value: any) => any };
12
+ },
10
13
  ): ColDefT<RowType> =>
11
14
  GridCell(
12
15
  {
13
16
  initialWidth: 65,
14
17
  maxWidth: 150,
18
+ valueFormatter: (params: ValueFormatterParams) => props.editorParams?.formatValue(params.value) ?? "",
15
19
  ...colDef,
16
20
  },
17
21
  {
@@ -20,44 +24,48 @@ export const GridPopoverEditBearingLike = <RowType extends GridBaseRow>(
20
24
  },
21
25
  );
22
26
 
27
+ export const GridPopoverEditBearingEditorParams = {
28
+ placeHolder: "Enter bearing",
29
+ formatValue: bearingValueFormatter,
30
+ range: (value: number | null) => {
31
+ if (value === null) return "Bearing is required";
32
+ if (value >= 360) return "Bearing must be less than 360 degrees";
33
+ if (value < 0) return "Bearing must not be negative";
34
+ return null;
35
+ },
36
+ };
37
+
23
38
  export const GridPopoverEditBearing = <RowType extends GridBaseRow>(
24
39
  colDef: GenericCellColDef<RowType>,
25
40
  props: GenericCellEditorProps<GridFormEditBearingProps<RowType>>,
26
41
  ): ColDefT<RowType> =>
27
- GridPopoverEditBearingLike(
28
- { valueFormatter: bearingValueFormatter, ...colDef },
29
- {
30
- multiEdit: !!props.multiEdit,
31
- editorParams: {
32
- placeHolder: "Enter bearing correction",
33
- range: (value: number | null) => {
34
- if (value === null) return "Bearing correction is required";
35
- if (value >= 360) return "Bearing correction must be less than 360 degrees";
36
- if (value < 0) return "Bearing correction must not be negative";
37
- return null;
38
- },
39
- ...props.editorParams,
40
- },
42
+ GridPopoverEditBearingLike(colDef, {
43
+ multiEdit: !!props.multiEdit,
44
+ editorParams: {
45
+ ...GridPopoverEditBearingEditorParams,
46
+ ...props.editorParams,
41
47
  },
42
- );
48
+ });
49
+
50
+ export const GridPopoverEditBearingCorrectionEditorParams = {
51
+ placeHolder: "Enter bearing correction",
52
+ formatValue: bearingCorrectionValueFormatter,
53
+ range: (value: number | null) => {
54
+ if (value === null) return "Bearing correction is required";
55
+ if (value >= 360) return "Bearing correction must be less than 360 degrees";
56
+ if (value <= -180) return "Bearing correction must be greater then -180 degrees";
57
+ return null;
58
+ },
59
+ };
43
60
 
44
61
  export const GridPopoverEditBearingCorrection = <RowType extends GridBaseRow>(
45
62
  colDef: GenericCellColDef<RowType>,
46
63
  props: GenericCellEditorProps<GridFormEditBearingProps<RowType>>,
47
64
  ): ColDefT<RowType> =>
48
- GridPopoverEditBearingLike(
49
- { valueFormatter: bearingCorrectionValueFormatter, ...colDef },
50
- {
51
- multiEdit: !!props.multiEdit,
52
- editorParams: {
53
- placeHolder: "Enter bearing correction",
54
- range: (value: number | null) => {
55
- if (value === null) return "Bearing is required";
56
- if (value >= 360) return "Bearing must be less than 360 degrees";
57
- if (value <= -180) return "Bearing must be greater then -180 degrees";
58
- return null;
59
- },
60
- ...props.editorParams,
61
- },
65
+ GridPopoverEditBearingLike(colDef, {
66
+ multiEdit: !!props.multiEdit,
67
+ editorParams: {
68
+ ...GridPopoverEditBearingCorrectionEditorParams,
69
+ ...props.editorParams,
62
70
  },
63
- );
71
+ });
@@ -1,6 +1,6 @@
1
1
  import { GridBaseRow } from "../Grid";
2
2
  import { ColDefT, GenericCellEditorProps, GridCell } from "../GridCell";
3
- import { GridFormPopoverMenu, GridFormPopoutMenuProps } from "../gridForm/GridFormPopoverMenu";
3
+ import { GridFormPopoverMenu, GridFormPopoverMenuProps } from "../gridForm/GridFormPopoverMenu";
4
4
  import { GridRenderPopoutMenuCell } from "../gridRender/GridRenderPopoutMenuCell";
5
5
  import { GenericCellColDef } from "../gridRender/GridRenderGenericCell";
6
6
 
@@ -9,9 +9,9 @@ import { GenericCellColDef } from "../gridRender/GridRenderGenericCell";
9
9
  */
10
10
  export const GridPopoverMenu = <RowType extends GridBaseRow>(
11
11
  colDef: GenericCellColDef<RowType>,
12
- custom: GenericCellEditorProps<GridFormPopoutMenuProps<RowType>>,
12
+ custom: GenericCellEditorProps<GridFormPopoverMenuProps<RowType>>,
13
13
  ): ColDefT<RowType> =>
14
- GridCell<RowType, GridFormPopoutMenuProps<RowType>>(
14
+ GridCell<RowType, GridFormPopoverMenuProps<RowType>>(
15
15
  {
16
16
  minWidth: 40,
17
17
  maxWidth: 40,