@linzjs/step-ag-grid 1.5.4 → 2.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.
Files changed (61) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.js +241 -200
  3. package/dist/index.js.map +1 -1
  4. package/dist/src/components/GridCell.d.ts +18 -27
  5. package/dist/src/components/GridPopoverHook.d.ts +4 -2
  6. package/dist/src/components/gridForm/GridFormDropDown.d.ts +8 -3
  7. package/dist/src/components/gridForm/GridFormEditBearing.d.ts +3 -4
  8. package/dist/src/components/gridForm/GridFormMessage.d.ts +4 -5
  9. package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +2 -3
  10. package/dist/src/components/gridForm/GridFormPopoutMenu.d.ts +2 -3
  11. package/dist/src/components/gridForm/GridFormTextArea.d.ts +2 -3
  12. package/dist/src/components/gridForm/GridFormTextInput.d.ts +2 -3
  13. package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.d.ts +3 -2
  14. package/dist/src/components/gridPopoverEdit/GridPopoverEditBearing.d.ts +5 -270
  15. package/dist/src/components/gridPopoverEdit/GridPopoverEditDropDown.d.ts +3 -2
  16. package/dist/src/components/gridPopoverEdit/GridPopoverMenu.d.ts +2 -2
  17. package/dist/src/components/gridPopoverEdit/GridPopoverMessage.d.ts +3 -2
  18. package/dist/src/components/gridPopoverEdit/GridPopoverTextArea.d.ts +3 -2
  19. package/dist/src/components/gridPopoverEdit/GridPopoverTextInput.d.ts +3 -2
  20. package/dist/src/components/gridRender/GridRenderGenericCell.d.ts +1 -3
  21. package/dist/src/contexts/GridPopoverContext.d.ts +17 -0
  22. package/dist/src/contexts/GridPopoverContextProvider.d.ts +6 -0
  23. package/dist/src/contexts/{UpdatingContext.d.ts → GridUpdatingContext.d.ts} +2 -2
  24. package/dist/src/contexts/GridUpdatingContextProvider.d.ts +7 -0
  25. package/dist/src/stories/components/FormTest.d.ts +1 -2
  26. package/dist/step-ag-grid.esm.js +238 -198
  27. package/dist/step-ag-grid.esm.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/components/Grid.tsx +2 -2
  30. package/src/components/GridCell.tsx +57 -79
  31. package/src/components/GridLoadableCell.tsx +4 -1
  32. package/src/components/GridPopoverHook.tsx +10 -14
  33. package/src/components/gridForm/GridFormDropDown.tsx +41 -30
  34. package/src/components/gridForm/GridFormEditBearing.tsx +13 -13
  35. package/src/components/gridForm/GridFormMessage.tsx +8 -13
  36. package/src/components/gridForm/GridFormMultiSelect.tsx +19 -19
  37. package/src/components/gridForm/GridFormPopoutMenu.tsx +7 -8
  38. package/src/components/gridForm/GridFormTextArea.tsx +16 -17
  39. package/src/components/gridForm/GridFormTextInput.tsx +17 -17
  40. package/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.ts +17 -16
  41. package/src/components/gridPopoverEdit/GridPopoverEditBearing.ts +53 -45
  42. package/src/components/gridPopoverEdit/GridPopoverEditDropDown.ts +17 -16
  43. package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +20 -21
  44. package/src/components/gridPopoverEdit/GridPopoverMessage.ts +18 -16
  45. package/src/components/gridPopoverEdit/GridPopoverTextArea.ts +12 -16
  46. package/src/components/gridPopoverEdit/GridPopoverTextInput.ts +15 -15
  47. package/src/components/gridRender/GridRenderGenericCell.tsx +3 -5
  48. package/src/components/gridRender/GridRenderPopoutMenuCell.tsx +2 -2
  49. package/src/contexts/GridContextProvider.tsx +3 -5
  50. package/src/contexts/GridPopoverContext.tsx +32 -0
  51. package/src/contexts/GridPopoverContextProvider.tsx +53 -0
  52. package/src/contexts/{UpdatingContext.tsx → GridUpdatingContext.tsx} +2 -2
  53. package/src/contexts/{UpdatingContextProvider.tsx → GridUpdatingContextProvider.tsx} +8 -6
  54. package/src/stories/components/FormTest.tsx +4 -3
  55. package/src/stories/components/GridPopoutBearing.stories.tsx +28 -25
  56. package/src/stories/components/GridPopoutEditDropDown.stories.tsx +91 -50
  57. package/src/stories/components/GridPopoutEditGeneric.stories.tsx +18 -13
  58. package/src/stories/components/GridPopoutEditGenericTextArea.stories.tsx +76 -61
  59. package/src/stories/components/GridPopoutEditMultiSelect.stories.tsx +58 -51
  60. package/src/stories/components/GridReadOnly.stories.tsx +73 -57
  61. package/dist/src/contexts/UpdatingContextProvider.d.ts +0 -7
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": "1.5.4",
5
+ "version": "2.0.0",
6
6
  "main": "dist/index.js",
7
7
  "typings": "dist/index.d.ts",
8
8
  "module": "dist/step-ag-grid.esm.js",
@@ -12,7 +12,7 @@ import { GridContext } from "@contexts/GridContext";
12
12
  import { usePostSortRowsHook } from "./PostSortRowsHook";
13
13
  import { isNotEmpty } from "@utils/util";
14
14
  import { GridHeaderSelect } from "./gridHeader/GridHeaderSelect";
15
- import { UpdatingContext } from "@contexts/UpdatingContext";
15
+ import { GridUpdatingContext } from "@contexts/GridUpdatingContext";
16
16
 
17
17
  export interface GridBaseRow {
18
18
  id: string | number;
@@ -47,7 +47,7 @@ export const Grid = (params: GridProps): JSX.Element => {
47
47
  ensureSelectedRowIsVisible,
48
48
  sizeColumnsToFit,
49
49
  } = useContext(GridContext);
50
- const { checkUpdating } = useContext(UpdatingContext);
50
+ const { checkUpdating } = useContext(GridUpdatingContext);
51
51
 
52
52
  const [internalQuickFilter, setInternalQuickFilter] = useState("");
53
53
  const lastSelectedIds = useRef<number[]>([]);
@@ -1,40 +1,27 @@
1
- import { ForwardedRef, forwardRef, useCallback, useContext, useMemo, useState } from "react";
1
+ import { forwardRef, useContext } from "react";
2
2
  import { GridBaseRow } from "./Grid";
3
- import { UpdatingContext } from "@contexts/UpdatingContext";
4
- import { GridContext } from "@contexts/GridContext";
3
+ import { GridUpdatingContext } from "@contexts/GridUpdatingContext";
5
4
  import { GenericMultiEditCellClass } from "./GenericCellClass";
6
- import { GenericCellRendererParams, GridRendererGenericCell } from "./gridRender/GridRenderGenericCell";
5
+ import {
6
+ GenericCellColDef,
7
+ GenericCellRendererParams,
8
+ GridRendererGenericCell,
9
+ } from "./gridRender/GridRenderGenericCell";
7
10
  import { ColDef, ICellEditorParams, ICellRendererParams } from "ag-grid-community";
8
11
  import { GridLoadableCell } from "./GridLoadableCell";
9
12
  import { GridIcon } from "@components/GridIcon";
10
13
  import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
14
+ import { GridPopoverContext } from "@contexts/GridPopoverContext";
15
+ import { GridPopoverContextProvider } from "@contexts/GridPopoverContextProvider";
11
16
 
12
- export interface GridFormProps<RowType extends GridBaseRow> {
13
- cellEditorParams: ICellEditorParams;
14
- updateValue: (saveFn: (selectedRows: RowType[]) => Promise<boolean>) => Promise<boolean>;
15
- saving: boolean;
16
- data: RowType;
17
- value: any;
18
- field: string | undefined;
19
- selectedRows: RowType[];
20
- formProps: Record<string, any>;
21
- }
22
-
23
- export interface GenericCellEditorParams<RowType extends GridBaseRow> {
17
+ export interface GenericCellEditorProps<E> {
24
18
  multiEdit?: boolean;
25
- form?: (props: GridFormProps<RowType>) => JSX.Element;
26
- }
27
-
28
- export interface GenericCellEditorColDef<
29
- RowType extends GridBaseRow,
30
- FormProps extends GenericCellEditorParams<RowType>,
31
- > extends ColDef {
32
- cellEditorParams?: FormProps;
33
- cellRendererParams?: GenericCellRendererParams<RowType>;
19
+ editor?: (editorProps: E) => JSX.Element;
20
+ editorParams?: E; // Omit<E, keyof CellParams<IFormTestRow>>
34
21
  }
35
22
 
36
23
  export const GridCellRenderer = (props: ICellRendererParams) => {
37
- const { checkUpdating } = useContext(UpdatingContext);
24
+ const { checkUpdating } = useContext(GridUpdatingContext);
38
25
  const colDef = props.colDef as ColDef;
39
26
 
40
27
  const rendererParams = colDef.cellRendererParams as GenericCellRendererParams<any> | undefined;
@@ -56,19 +43,32 @@ export const GridCellRenderer = (props: ICellRendererParams) => {
56
43
  );
57
44
  };
58
45
 
59
- /**
46
+ // This is so that typescript retains the row type to pass to the GridCells
47
+ export interface ColDefT<RowType extends GridBaseRow> extends ColDef {
48
+ _?: RowType;
49
+ }
50
+
51
+ /*
60
52
  * For editing a text area.
61
53
  */
62
- export const GridCell = <RowType extends GridBaseRow, FormProps extends GenericCellEditorParams<RowType>>(
63
- props: GenericCellEditorColDef<RowType, FormProps>,
64
- ): ColDef => {
54
+ export const GridCell = <RowType extends GridBaseRow, Props>(
55
+ props: GenericCellColDef<RowType>,
56
+ custom?: {
57
+ multiEdit?: boolean;
58
+ editor?: (editorProps: Props) => JSX.Element;
59
+ editorParams?: Props;
60
+ },
61
+ ): ColDefT<RowType> => {
65
62
  return {
66
63
  sortable: !!(props?.field || props?.valueGetter),
67
64
  resizable: true,
68
- ...(props.cellEditorParams && {
69
- cellClass: props?.cellEditorParams?.multiEdit ? GenericMultiEditCellClass : undefined,
70
- editable: true,
71
- cellEditor: GenericCellEditorComponent,
65
+ ...(custom?.editor && {
66
+ cellClass: custom?.multiEdit ? GenericMultiEditCellClass : undefined,
67
+ editable: props.editable ?? true,
68
+ cellEditor: GenericCellEditorComponent(custom.editor),
69
+ }),
70
+ ...(custom?.editorParams && {
71
+ cellEditorParams: { ...custom.editorParams, multiEdit: custom.multiEdit },
72
72
  }),
73
73
  // Default value formatter, otherwise react freaks out on objects
74
74
  valueFormatter: (params: ValueFormatterParams) => {
@@ -86,59 +86,37 @@ export const GridCell = <RowType extends GridBaseRow, FormProps extends GenericC
86
86
  };
87
87
  };
88
88
 
89
- interface GenericCellEditorICellEditorParams<RowType extends GridBaseRow, FormProps extends Record<string, any>>
90
- extends ICellEditorParams {
89
+ export interface CellParams<RowType extends GridBaseRow> {
90
+ value: any;
91
91
  data: RowType;
92
- colDef: GenericCellEditorColDef<RowType, FormProps>;
92
+ field: string | undefined;
93
+ selectedRows: RowType[];
93
94
  }
94
95
 
95
- export const GenericCellEditorComponentFr = <RowType extends GridBaseRow, FormProps extends Record<string, any>>(
96
- props: GenericCellEditorICellEditorParams<RowType, FormProps>,
97
- _: ForwardedRef<any>, // We don't forward the ref, as that's for generic aggrid cell editing
98
- ) => {
99
- const { updatingCells, getSelectedRows } = useContext(GridContext);
100
-
101
- const { colDef, data } = props;
102
- const { cellEditorParams } = props.colDef;
96
+ // TODO memo?
97
+ export const GenericCellEditorComponent = (editor: (props: any) => JSX.Element) =>
98
+ forwardRef(function GenericCellEditorComponent2(props: ICellEditorParams, _) {
99
+ return (
100
+ <GridPopoverContextProvider>
101
+ <GenericCellEditorComponent3 {...{ ...props, editor }} />
102
+ </GridPopoverContextProvider>
103
+ );
104
+ });
105
+
106
+ const GenericCellEditorComponent3 = (props: ICellEditorParams & { editor: (props: any) => JSX.Element }) => {
107
+ const { setProps, propsRef } = useContext(GridPopoverContext);
108
+
109
+ const { colDef } = props;
110
+ const { cellEditorParams } = colDef;
103
111
  const multiEdit = cellEditorParams?.multiEdit ?? false;
104
- const field = props.colDef.field ?? "";
105
-
106
- const formProps = colDef.cellEditorParams ?? {};
107
- const value = props.value;
108
-
109
- const selectedRows = useMemo(
110
- () => (multiEdit ? getSelectedRows<RowType>() : [data]),
111
- [data, getSelectedRows, multiEdit],
112
- );
113
112
 
114
- const [saving, setSaving] = useState(false);
115
-
116
- const updateValue = useCallback(
117
- async (saveFn: (selectedRows: any[]) => Promise<boolean>): Promise<boolean> => {
118
- return !saving && (await updatingCells({ selectedRows, field }, saveFn, setSaving));
119
- },
120
- [field, saving, selectedRows, updatingCells],
121
- );
122
-
123
- if (cellEditorParams == null) return <></>;
113
+ // TODO don't need all these props in context
114
+ setProps(props, multiEdit);
124
115
 
125
116
  return (
126
117
  <>
127
- <div>{colDef.cellRenderer ? <colDef.cellRenderer {...props} saving={saving} /> : props.value}</div>
128
- {cellEditorParams?.form && (
129
- <cellEditorParams.form
130
- cellEditorParams={props}
131
- updateValue={updateValue}
132
- saving={saving}
133
- formProps={formProps}
134
- data={data}
135
- value={value}
136
- field={field}
137
- selectedRows={selectedRows}
138
- />
139
- )}
118
+ <div>{colDef.cellRenderer ? <colDef.cellRenderer {...props} /> : props.value}</div>
119
+ {props?.editor && <props.editor {...cellEditorParams} {...propsRef.current} />}
140
120
  </>
141
121
  );
142
122
  };
143
-
144
- export const GenericCellEditorComponent = forwardRef(GenericCellEditorComponentFr);
@@ -2,6 +2,8 @@ import "./GridLoadableCell.scss";
2
2
 
3
3
  import { LuiMiniSpinner } from "@linzjs/lui";
4
4
  import clsx from "clsx";
5
+ import { useContext } from "react";
6
+ import { GridPopoverContext } from "@contexts/GridPopoverContext";
5
7
 
6
8
  export const GridLoadableCell = (props: {
7
9
  isLoading: boolean;
@@ -9,7 +11,8 @@ export const GridLoadableCell = (props: {
9
11
  children: JSX.Element | string;
10
12
  className?: string;
11
13
  }): JSX.Element => {
12
- // console.log(`Rendering LoadableCell - loading: ${props.isLoading}`);
14
+ const { saving } = useContext(GridPopoverContext);
15
+
13
16
  if (props.isLoading) {
14
17
  return (
15
18
  <div style={{ display: "flex", alignItems: "center" }}>
@@ -1,20 +1,17 @@
1
- import { ICellEditorParams } from "ag-grid-community";
2
1
  import { useCallback, useContext, useEffect, useRef, useState } from "react";
3
2
  import { GridContext } from "@contexts/GridContext";
4
- import { GridFormProps } from "./GridCell";
5
3
  import { GridBaseRow } from "./Grid";
6
4
  import { ControlledMenu } from "@react-menu3";
5
+ import { GridPopoverContext } from "@contexts/GridPopoverContext";
7
6
 
8
- export const useGridPopoverHook = <RowType extends GridBaseRow>(
9
- props: GridFormProps<RowType>,
10
- save?: (selectedRows: any[]) => Promise<boolean>,
11
- ) => {
12
- const { cellEditorParams, saving, updateValue } = props;
13
- const { eGridCell } = cellEditorParams as ICellEditorParams;
7
+ export interface GridPopoverHookProps<RowType> {
8
+ save?: (selectedRows: RowType[]) => Promise<boolean>;
9
+ }
10
+
11
+ export const useGridPopoverHook = <RowType extends GridBaseRow>(props: GridPopoverHookProps<RowType> = {}) => {
14
12
  const { stopEditing } = useContext(GridContext);
13
+ const { anchorRef, saving, updateValueRef } = useContext(GridPopoverContext);
15
14
  const saveButtonRef = useRef<HTMLButtonElement>(null);
16
- const anchorRef = useRef(eGridCell);
17
- anchorRef.current = eGridCell;
18
15
  const [isOpen, setOpen] = useState(false);
19
16
 
20
17
  useEffect(() => {
@@ -23,12 +20,12 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(
23
20
 
24
21
  const triggerSave = useCallback(
25
22
  async (reason?: string) => {
26
- if (reason == "cancel" || !save || (await updateValue(save))) {
23
+ if (reason == "cancel" || !props.save || (updateValueRef.current && (await updateValueRef.current(props.save)))) {
27
24
  setOpen(false);
28
25
  stopEditing();
29
26
  }
30
27
  },
31
- [save, stopEditing, updateValue],
28
+ [props, stopEditing, updateValueRef],
32
29
  );
33
30
 
34
31
  const popoverWrapper = useCallback(
@@ -44,7 +41,6 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(
44
41
  saveButtonRef={saveButtonRef}
45
42
  menuClassName={"lui-menu"}
46
43
  onClose={(event: { reason: string }) => triggerSave(event.reason).then()}
47
- reposition={"initial"}
48
44
  viewScroll={"auto"}
49
45
  dontShrinkIfDirectionIsTop={true}
50
46
  >
@@ -68,7 +64,7 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(
68
64
  </>
69
65
  );
70
66
  },
71
- [isOpen, saving, triggerSave],
67
+ [anchorRef, isOpen, saving, triggerSave],
72
68
  );
73
69
 
74
70
  return {
@@ -1,13 +1,13 @@
1
1
  import "../../react-menu3/styles/index.scss";
2
2
 
3
- import { MenuItem, MenuDivider, FocusableItem } from "@react-menu3";
3
+ import { MenuItem, MenuDivider, FocusableItem, MenuHeader } from "@react-menu3";
4
4
  import { useCallback, useContext, useEffect, useRef, useState, KeyboardEvent } from "react";
5
5
  import { GridBaseRow } from "../Grid";
6
6
  import { ComponentLoadingWrapper } from "../ComponentLoadingWrapper";
7
7
  import { GridContext } from "@contexts/GridContext";
8
8
  import { delay } from "lodash-es";
9
9
  import debounce from "debounce-promise";
10
- import { GenericCellEditorParams, GridFormProps } from "../GridCell";
10
+ import { CellParams } from "../GridCell";
11
11
  import { useGridPopoverHook } from "../GridPopoverHook";
12
12
 
13
13
  export interface GridPopoutEditDropDownSelectedItem<RowType, ValueType> {
@@ -24,10 +24,14 @@ interface FinalSelectOption<ValueType> {
24
24
  export const MenuSeparatorString = "_____MENU_SEPARATOR_____";
25
25
  export const MenuSeparator = Object.freeze({ value: MenuSeparatorString });
26
26
 
27
+ export const MenuHeaderString = "_____MENU_HEADER_____";
28
+ export const MenuHeaderItem = (title: string) => {
29
+ return { label: title, value: MenuHeaderString };
30
+ };
31
+
27
32
  export type SelectOption<ValueType> = ValueType | FinalSelectOption<ValueType>;
28
33
 
29
- export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow, ValueType>
30
- extends GenericCellEditorParams<RowType> {
34
+ export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow, ValueType> {
31
35
  filtered?: "local" | "reload";
32
36
  filterPlaceholder?: string;
33
37
  onSelectedItem?: (props: GridPopoutEditDropDownSelectedItem<RowType, ValueType>) => Promise<void>;
@@ -36,12 +40,13 @@ export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow, ValueT
36
40
  | SelectOption<ValueType>[]
37
41
  | ((selectedRows: RowType[], filter?: string) => Promise<SelectOption<ValueType>[]> | SelectOption<ValueType>[]);
38
42
  optionsRequestCancel?: () => void;
43
+ maxRows?: number;
39
44
  }
40
45
 
41
- export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props: GridFormProps<RowType>) => {
42
- const { popoverWrapper } = useGridPopoverHook(props);
43
- const formProps = props.formProps as GridFormPopoutDropDownProps<RowType, ValueType>;
44
-
46
+ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(
47
+ _props: GridFormPopoutDropDownProps<RowType, ValueType>,
48
+ ) => {
49
+ const props = _props as GridFormPopoutDropDownProps<RowType, ValueType> & CellParams<RowType>;
45
50
  const { updatingCells, stopEditing } = useContext(GridContext);
46
51
 
47
52
  const [filter, setFilter] = useState("");
@@ -55,8 +60,8 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
55
60
  return await updatingCells({ selectedRows: props.selectedRows, field }, async (selectedRows) => {
56
61
  const hasChanged = selectedRows.some((row) => row[field as keyof RowType] !== value);
57
62
  if (hasChanged) {
58
- if (formProps.onSelectedItem) {
59
- await formProps.onSelectedItem({ selectedRows, value });
63
+ if (props.onSelectedItem) {
64
+ await props.onSelectedItem({ selectedRows, value });
60
65
  } else {
61
66
  selectedRows.forEach((row) => (row[field as keyof RowType] = value));
62
67
  }
@@ -64,27 +69,27 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
64
69
  return true;
65
70
  });
66
71
  },
67
- [formProps, props.field, props.selectedRows, updatingCells],
72
+ [props, updatingCells],
68
73
  );
69
74
 
70
75
  const selectFilterHandler = useCallback(
71
76
  async (value: string): Promise<boolean> => {
72
77
  const field = props.field;
73
78
  return await updatingCells({ selectedRows: props.selectedRows, field }, async (selectedRows) => {
74
- if (formProps.onSelectFilter) {
75
- await formProps.onSelectFilter({ selectedRows, value });
79
+ if (props.onSelectFilter) {
80
+ await props.onSelectFilter({ selectedRows, value });
76
81
  }
77
82
  return true;
78
83
  });
79
84
  },
80
- [formProps, props.field, props.selectedRows, updatingCells],
85
+ [props, updatingCells],
81
86
  );
82
87
 
83
88
  // Load up options list if it's async function
84
89
  useEffect(() => {
85
90
  if (options || optionsInitialising.current) return;
86
91
  optionsInitialising.current = true;
87
- let optionsConf = formProps.options ?? [];
92
+ let optionsConf = props.options ?? [];
88
93
 
89
94
  (async () => {
90
95
  if (typeof optionsConf == "function") {
@@ -98,7 +103,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
98
103
  return item;
99
104
  }) as any as FinalSelectOption<ValueType>[];
100
105
 
101
- if (formProps.filtered) {
106
+ if (props.filtered) {
102
107
  // This is needed otherwise when filter input is rendered and sets autofocus
103
108
  // the mouse up of the double click edit triggers the cell to cancel editing
104
109
  delay(() => setOptions(optionsList), 100);
@@ -107,11 +112,11 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
107
112
  }
108
113
  optionsInitialising.current = false;
109
114
  })();
110
- }, [filter, options, formProps.filtered, formProps.options, props.selectedRows]);
115
+ }, [filter, options, props]);
111
116
 
112
- // Local filtering
117
+ // Local filtering.
113
118
  useEffect(() => {
114
- if (formProps.filtered == "local") {
119
+ if (props.filtered == "local") {
115
120
  if (options == null) return;
116
121
  setFilteredValues(
117
122
  options
@@ -126,7 +131,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
126
131
  .filter((r) => r !== undefined),
127
132
  );
128
133
  }
129
- }, [formProps.filtered, filter, options]);
134
+ }, [props.filtered, filter, options]);
130
135
 
131
136
  const researchOnFilterChange = debounce(
132
137
  useCallback(() => {
@@ -137,14 +142,14 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
137
142
 
138
143
  const previousFilter = useRef<string>(filter);
139
144
 
140
- // Reload filtering
145
+ // Reload filtering.
141
146
  useEffect(() => {
142
- if (previousFilter.current != filter && formProps.filtered == "reload") {
147
+ if (previousFilter.current != filter && props.filtered == "reload") {
143
148
  previousFilter.current = filter;
144
- formProps.optionsRequestCancel && formProps.optionsRequestCancel();
149
+ props.optionsRequestCancel && props.optionsRequestCancel();
145
150
  researchOnFilterChange().then();
146
151
  }
147
- }, [filter, formProps, props, researchOnFilterChange]);
152
+ }, [filter, props, researchOnFilterChange]);
148
153
 
149
154
  const onFilterKeyDown = useCallback(
150
155
  async (e: KeyboardEvent) => {
@@ -154,7 +159,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
154
159
  if (activeOptions.length == 1) {
155
160
  await selectItemHandler(activeOptions[0].value);
156
161
  stopEditing();
157
- } else if (formProps.onSelectFilter) {
162
+ } else if (props.onSelectFilter) {
158
163
  await selectFilterHandler(filter);
159
164
  stopEditing();
160
165
  } else {
@@ -163,12 +168,16 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
163
168
  }
164
169
  }
165
170
  },
166
- [filteredValues, options, selectItemHandler, selectFilterHandler, stopEditing, filter, formProps],
171
+ [filteredValues, options, selectItemHandler, selectFilterHandler, stopEditing, filter, props],
167
172
  );
168
173
 
174
+ const maxRowsStyles =
175
+ props.maxRows !== undefined ? { maxHeight: 62 + 34 * props.maxRows, overFlowY: "auto" } : undefined;
176
+
177
+ const { popoverWrapper } = useGridPopoverHook();
169
178
  return popoverWrapper(
170
179
  <>
171
- {formProps.filtered && (
180
+ {props.filtered && (
172
181
  <>
173
182
  <FocusableItem className={"filter-item"}>
174
183
  {({ ref }: any) => (
@@ -179,7 +188,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
179
188
  style={{ border: "0px" }}
180
189
  ref={ref}
181
190
  type="text"
182
- placeholder={formProps.filterPlaceholder ?? "Placeholder"}
191
+ placeholder={props.filterPlaceholder ?? "Placeholder"}
183
192
  data-testid={"filteredMenu-free-text-input"}
184
193
  defaultValue={filter}
185
194
  onChange={(e) => setFilter(e.target.value.toLowerCase())}
@@ -192,11 +201,13 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
192
201
  </>
193
202
  )}
194
203
  <ComponentLoadingWrapper loading={!options}>
195
- <>
204
+ <div style={maxRowsStyles}>
196
205
  {options && options.length == filteredValues?.length && <MenuItem>[Empty]</MenuItem>}
197
206
  {options?.map((item, index) =>
198
207
  item.value === MenuSeparatorString ? (
199
208
  <MenuDivider key={`$$divider_${index}`} />
209
+ ) : item.value === MenuHeaderString ? (
210
+ <MenuHeader>{item.label}</MenuHeader>
200
211
  ) : filteredValues.includes(item.value) ? null : (
201
212
  <MenuItem
202
213
  key={`${props.field}-${index}`}
@@ -209,7 +220,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
209
220
  </MenuItem>
210
221
  ),
211
222
  )}
212
- </>
223
+ </div>
213
224
  </ComponentLoadingWrapper>
214
225
  </>,
215
226
  );
@@ -4,19 +4,18 @@ import { useCallback, useState } from "react";
4
4
  import { GridBaseRow } from "../Grid";
5
5
  import { TextInputFormatted } from "../../lui/TextInputFormatted";
6
6
  import { bearingNumberParser, bearingStringValidator, convertDDToDMS } from "@utils/bearing";
7
- import { GenericCellEditorParams, GridFormProps } from "../GridCell";
8
7
  import { useGridPopoverHook } from "../GridPopoverHook";
8
+ import { CellParams } from "@components/GridCell";
9
9
 
10
- export interface GridFormEditBearingProps<RowType extends GridBaseRow> extends GenericCellEditorParams<RowType> {
11
- placeHolder: string;
10
+ export interface GridFormEditBearingProps<RowType extends GridBaseRow> {
11
+ placeHolder?: string;
12
12
  range?: (value: number | null) => string | null;
13
13
  onSave?: (selectedRows: RowType[], value: number | null) => Promise<boolean>;
14
14
  }
15
15
 
16
- export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridFormProps<RowType>) => {
17
- const formProps = props.formProps as GridFormEditBearingProps<RowType>;
16
+ export const GridFormEditBearing = <RowType extends GridBaseRow>(_props: GridFormEditBearingProps<RowType>) => {
17
+ const props = _props as GridFormEditBearingProps<RowType> & CellParams<RowType>;
18
18
  const [value, setValue] = useState<string>(`${props.value ?? ""}`);
19
-
20
19
  const save = useCallback(
21
20
  async (selectedRows: RowType[]): Promise<boolean> => {
22
21
  if (bearingStringValidator(value)) return false;
@@ -25,8 +24,9 @@ export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridForm
25
24
  if (parsedValue === props.value) {
26
25
  return true;
27
26
  }
28
- if (formProps.onSave) {
29
- return await formProps.onSave(selectedRows, parsedValue);
27
+
28
+ if (props.onSave) {
29
+ return await props.onSave(selectedRows, parsedValue);
30
30
  } else {
31
31
  const field = props.field;
32
32
  if (field == null) {
@@ -37,9 +37,9 @@ export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridForm
37
37
  }
38
38
  return true;
39
39
  },
40
- [formProps, props.field, props.value, value],
40
+ [props, value],
41
41
  );
42
- const { popoverWrapper, triggerSave } = useGridPopoverHook(props, save);
42
+ const { triggerSave, popoverWrapper } = useGridPopoverHook({ save });
43
43
 
44
44
  return popoverWrapper(
45
45
  <div className={"GridFormEditBearing-input Grid-popoverContainer"}>
@@ -50,13 +50,13 @@ export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridForm
50
50
  }}
51
51
  inputProps={{
52
52
  autoFocus: true,
53
- placeholder: formProps.placeHolder,
53
+ placeholder: props.placeHolder,
54
54
  disabled: false,
55
55
  maxLength: 16,
56
56
  onKeyDown: async (e) => e.key === "Enter" && triggerSave().then(),
57
57
  }}
58
- formatted={bearingStringValidator(value, formProps.range) ? "?" : convertDDToDMS(bearingNumberParser(value))}
59
- error={bearingStringValidator(value, formProps.range)}
58
+ formatted={bearingStringValidator(value, props.range) ? "?" : convertDDToDMS(bearingNumberParser(value))}
59
+ error={bearingStringValidator(value, props.range)}
60
60
  />
61
61
  </div>,
62
62
  );
@@ -1,28 +1,23 @@
1
1
  import { useEffect, useState } from "react";
2
- import { GenericCellEditorParams, GridFormProps } from "../GridCell";
3
- import { ICellEditorParams } from "ag-grid-community";
4
2
  import { ComponentLoadingWrapper } from "../ComponentLoadingWrapper";
5
3
  import { GridBaseRow } from "../Grid";
6
4
  import { useGridPopoverHook } from "../GridPopoverHook";
5
+ import { CellParams } from "@components/GridCell";
7
6
 
8
- export interface GridFormMessageProps<RowType extends GridBaseRow> extends GenericCellEditorParams<RowType> {
9
- message: (
10
- selectedRows: RowType[],
11
- cellEditorParams: ICellEditorParams,
12
- ) => Promise<string | JSX.Element> | string | JSX.Element;
7
+ export interface GridFormMessageProps<RowType extends GridBaseRow> {
8
+ message: (cellParams: CellParams<RowType>) => Promise<string | JSX.Element> | string | JSX.Element;
13
9
  }
14
10
 
15
- export const GridFormMessage = <RowType extends GridBaseRow>(props: GridFormProps<RowType>) => {
16
- const formProps = props.formProps as GridFormMessageProps<RowType>;
17
-
11
+ export const GridFormMessage = <RowType extends GridBaseRow>(_props: GridFormMessageProps<RowType>) => {
12
+ const props = _props as GridFormMessageProps<RowType> & CellParams<RowType>;
18
13
  const [message, setMessage] = useState<string | JSX.Element | null>(null);
19
- const { popoverWrapper } = useGridPopoverHook(props);
14
+ const { popoverWrapper } = useGridPopoverHook();
20
15
 
21
16
  useEffect(() => {
22
17
  (async () => {
23
- setMessage(await formProps.message(props.selectedRows, props.cellEditorParams));
18
+ setMessage(await props.message(props));
24
19
  })().then();
25
- }, [formProps, props.selectedRows, props]);
20
+ }, [props]);
26
21
 
27
22
  return popoverWrapper(
28
23
  <ComponentLoadingWrapper loading={message === null}>