@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/dist/index.css CHANGED
@@ -313,6 +313,10 @@
313
313
  text-transform: uppercase;
314
314
  }
315
315
 
316
+ .react-menu-inline-test .szh-menu-container, .react-menu-inline-test .szh-menu {
317
+ position: static !important;
318
+ }
319
+
316
320
  .Grid-container {
317
321
  flex: 1;
318
322
  width: 100%;
@@ -1,4 +1,5 @@
1
1
  /// <reference types="react" />
2
+ import { ColDef } from "ag-grid-community";
2
3
  import { GridOptions } from "ag-grid-community/dist/lib/entities/gridOptions";
3
4
  export interface GridBaseRow {
4
5
  id: string | number;
@@ -14,7 +15,7 @@ export interface GridProps {
14
15
  externalSelectedItems?: any[];
15
16
  setExternalSelectedItems?: (items: any[]) => void;
16
17
  defaultColDef?: GridOptions["defaultColDef"];
17
- columnDefs: GridOptions["columnDefs"];
18
+ columnDefs: ColDef[];
18
19
  rowData: GridOptions["rowData"];
19
20
  noRowsOverlayText?: string;
20
21
  postSortRows?: GridOptions["postSortRows"];
@@ -25,6 +25,7 @@ export type SelectOption = null | string | FinalSelectOption;
25
25
  export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow> extends CellEditorCommon {
26
26
  className?: "GridPopoverEditDropDown-containerSmall" | "GridPopoverEditDropDown-containerMedium" | "GridPopoverEditDropDown-containerLarge" | "GridPopoverEditDropDown-containerUnlimited" | string | undefined;
27
27
  filtered?: "local" | "reload";
28
+ filterDefaultValue?: string;
28
29
  filterPlaceholder?: string;
29
30
  filterHelpText?: string;
30
31
  noOptionsMessage?: string;
@@ -2,8 +2,12 @@
2
2
  import { GridBaseRow } from "../Grid";
3
3
  import { CellEditorCommon } from "../GridCell";
4
4
  export interface GridFormEditBearingProps<RowType extends GridBaseRow> extends CellEditorCommon {
5
+ formatValue?: (value: any) => string;
5
6
  placeHolder?: string;
6
7
  range?: (value: number | null) => string | null;
7
- onSave?: (selectedRows: RowType[], value: number | null) => Promise<boolean>;
8
+ onSave?: (props: {
9
+ selectedRows: RowType[];
10
+ value: number | null;
11
+ }) => Promise<boolean>;
8
12
  }
9
13
  export declare const GridFormEditBearing: <RowType extends GridBaseRow>(props: GridFormEditBearingProps<RowType>) => JSX.Element;
@@ -19,8 +19,14 @@ export interface GridFormMultiSelectProps<RowType extends GridBaseRow> extends C
19
19
  filtered?: boolean;
20
20
  filterPlaceholder?: string;
21
21
  filterHelpText?: string | ((filter: string, options: MultiSelectOption[]) => string | undefined);
22
- onSelectFilter?: (filter: string, options: MultiSelectOption[]) => void;
23
- onSave?: (selectedRows: RowType[], selectedOptions: MultiSelectOption[]) => Promise<boolean>;
22
+ onSelectFilter?: (props: {
23
+ filter: string;
24
+ options: MultiSelectOption[];
25
+ }) => void;
26
+ onSave?: (props: {
27
+ selectedRows: RowType[];
28
+ selectedOptions: MultiSelectOption[];
29
+ }) => Promise<boolean>;
24
30
  headers?: GridFormMultiSelectGroup[];
25
31
  options: MultiSelectOption[] | ((selectedRows: RowType[]) => Promise<MultiSelectOption[]> | MultiSelectOption[]);
26
32
  invalid?: (selectedRows: RowType[], selectedOptions: MultiSelectOption[]) => boolean;
@@ -1,13 +1,15 @@
1
1
  /// <reference types="react" />
2
2
  import { GridBaseRow } from "../Grid";
3
3
  import { CellEditorCommon } from "../GridCell";
4
- export interface GridFormPopoutMenuProps<RowType extends GridBaseRow> extends CellEditorCommon {
4
+ export interface GridFormPopoverMenuProps<RowType extends GridBaseRow> extends CellEditorCommon {
5
5
  options: (selectedRows: RowType[]) => Promise<MenuOption<RowType>[]>;
6
- defaultAction?: (selectedRows: RowType[], menuOption: SelectedMenuOptionResult<RowType>) => Promise<void>;
6
+ defaultAction?: (props: {
7
+ selectedRows: RowType[];
8
+ menuOption: SelectedMenuOptionResult<RowType>;
9
+ }) => Promise<void>;
7
10
  }
8
- /** Menu configuration types **/
9
11
  export declare const PopoutMenuSeparator: Readonly<{
10
- __isMenuSeparator__: true;
12
+ label: "__isMenuSeparator__";
11
13
  }>;
12
14
  interface MenuSeparatorType {
13
15
  __isMenuSeparator__: boolean;
@@ -17,7 +19,10 @@ export interface SelectedMenuOptionResult<RowType extends GridBaseRow> extends M
17
19
  }
18
20
  export interface MenuOption<RowType extends GridBaseRow> {
19
21
  label: JSX.Element | string | MenuSeparatorType;
20
- action?: (selectedRows: RowType[], menuOption: SelectedMenuOptionResult<RowType>) => Promise<void>;
22
+ action?: (props: {
23
+ selectedRows: RowType[];
24
+ menuOption: SelectedMenuOptionResult<RowType>;
25
+ }) => Promise<void>;
21
26
  disabled?: string | boolean;
22
27
  hidden?: boolean;
23
28
  subComponent?: (props: any) => JSX.Element;
@@ -26,5 +31,5 @@ export interface MenuOption<RowType extends GridBaseRow> {
26
31
  * NOTE: If the popout menu doesn't appear on single click when also selecting row it's because
27
32
  * you need a useMemo around your columnDefs
28
33
  */
29
- export declare const GridFormPopoverMenu: <RowType extends GridBaseRow>(props: GridFormPopoutMenuProps<RowType>) => JSX.Element;
34
+ export declare const GridFormPopoverMenu: <RowType extends GridBaseRow>(props: GridFormPopoverMenuProps<RowType>) => JSX.Element;
30
35
  export {};
@@ -5,7 +5,10 @@ import { TextInputValidatorProps } from "../../utils/textValidator";
5
5
  export interface GridFormTextAreaProps<RowType extends GridBaseRow> extends TextInputValidatorProps<RowType>, CellEditorCommon {
6
6
  placeholder?: string;
7
7
  width?: string | number;
8
- onSave?: (selectedRows: RowType[], value: string) => Promise<boolean>;
8
+ onSave?: (props: {
9
+ selectedRows: RowType[];
10
+ value: string;
11
+ }) => Promise<boolean>;
9
12
  helpText?: string;
10
13
  }
11
14
  export declare const GridFormTextArea: <RowType extends GridBaseRow>(props: GridFormTextAreaProps<RowType>) => JSX.Element;
@@ -6,7 +6,10 @@ export interface GridFormTextInputProps<RowType extends GridBaseRow> extends Tex
6
6
  placeholder?: string;
7
7
  units?: string;
8
8
  width?: string | number;
9
- onSave?: (selectedRows: RowType[], value: string) => Promise<boolean>;
9
+ onSave?: (props: {
10
+ selectedRows: RowType[];
11
+ value: string;
12
+ }) => Promise<boolean>;
10
13
  helpText?: string;
11
14
  }
12
15
  export declare const GridFormTextInput: <RowType extends GridBaseRow>(props: GridFormTextInputProps<RowType>) => JSX.Element;
@@ -2,6 +2,15 @@ import { ColDefT, GenericCellEditorProps } from "../GridCell";
2
2
  import { GridFormEditBearingProps } from "../gridForm/GridFormEditBearing";
3
3
  import { GridBaseRow } from "../Grid";
4
4
  import { GenericCellColDef } from "../gridRender/GridRenderGenericCell";
5
- export declare const GridPopoverEditBearingLike: <RowType extends GridBaseRow>(colDef: GenericCellColDef<RowType>, props: GenericCellEditorProps<GridFormEditBearingProps<RowType>>) => ColDefT<RowType>;
5
+ export declare const GridPopoverEditBearingEditorParams: {
6
+ placeHolder: string;
7
+ formatValue: (value: any) => string;
8
+ range: (value: number | null) => "Bearing is required" | "Bearing must be less than 360 degrees" | "Bearing must not be negative" | null;
9
+ };
6
10
  export declare const GridPopoverEditBearing: <RowType extends GridBaseRow>(colDef: GenericCellColDef<RowType>, props: GenericCellEditorProps<GridFormEditBearingProps<RowType>>) => ColDefT<RowType>;
11
+ export declare const GridPopoverEditBearingCorrectionEditorParams: {
12
+ placeHolder: string;
13
+ formatValue: (value: any) => string;
14
+ range: (value: number | null) => "Bearing correction is required" | "Bearing correction must be less than 360 degrees" | "Bearing correction must be greater then -180 degrees" | null;
15
+ };
7
16
  export declare const GridPopoverEditBearingCorrection: <RowType extends GridBaseRow>(colDef: GenericCellColDef<RowType>, props: GenericCellEditorProps<GridFormEditBearingProps<RowType>>) => ColDefT<RowType>;
@@ -1,8 +1,8 @@
1
1
  import { GridBaseRow } from "../Grid";
2
2
  import { ColDefT, GenericCellEditorProps } from "../GridCell";
3
- import { GridFormPopoutMenuProps } from "../gridForm/GridFormPopoverMenu";
3
+ import { GridFormPopoverMenuProps } from "../gridForm/GridFormPopoverMenu";
4
4
  import { GenericCellColDef } from "../gridRender/GridRenderGenericCell";
5
5
  /**
6
6
  * Popout burger menu
7
7
  */
8
- export declare const GridPopoverMenu: <RowType extends GridBaseRow>(colDef: GenericCellColDef<RowType>, custom: GenericCellEditorProps<GridFormPopoutMenuProps<RowType>>) => ColDefT<RowType>;
8
+ export declare const GridPopoverMenu: <RowType extends GridBaseRow>(colDef: GenericCellColDef<RowType>, custom: GenericCellEditorProps<GridFormPopoverMenuProps<RowType>>) => ColDefT<RowType>;
@@ -15,5 +15,6 @@ export interface ActionButtonProps {
15
15
  onClick: () => Promise<void> | void;
16
16
  level?: LuiButtonProps["level"];
17
17
  style?: CSSProperties;
18
+ disabled?: boolean;
18
19
  }
19
- export declare const ActionButton: ({ icon, name, inProgressName, dataTestId, style, className, title, onClick, size, iconPosition, level, "aria-label": ariaLabel, }: ActionButtonProps) => JSX.Element;
20
+ export declare const ActionButton: ({ icon, name, inProgressName, disabled, dataTestId, style, className, title, onClick, size, iconPosition, level, "aria-label": ariaLabel, }: ActionButtonProps) => JSX.Element;
@@ -1,6 +1,5 @@
1
- import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
2
- export declare const bearingValueFormatter: (params: ValueFormatterParams) => string;
3
- export declare const bearingCorrectionValueFormatter: (params: ValueFormatterParams) => string;
1
+ export declare const bearingValueFormatter: (value: any) => string;
2
+ export declare const bearingCorrectionValueFormatter: (value: any) => string;
4
3
  export declare const bearingNumberParser: (value: string) => number | null;
5
4
  export declare const bearingStringValidator: (value: string, customInvalid?: ((value: number | null) => string | null) | undefined) => string | null;
6
5
  export declare const convertDDToDMS: (dd: number | null, showPositiveSymbol?: boolean, addTrailingZeros?: boolean) => string;
@@ -1597,7 +1597,12 @@ var ControlledMenuFr = function (_a, externalRef) {
1597
1597
  className: className
1598
1598
  }), style: __assign(__assign({}, containerProps === null || containerProps === void 0 ? void 0 : containerProps.style), { position: "relative" }), ref: containerRef }, { children: state && (jsx(SettingsContext.Provider, __assign({ value: settings }, { children: jsx(ItemSettingsContext.Provider, __assign({ value: itemSettings }, { children: jsx(EventHandlersContext.Provider, __assign({ value: eventHandlers }, { children: jsx(MenuList, __assign({}, restProps, { ariaLabel: ariaLabel || "Menu", externalRef: externalRef, containerRef: containerRef, onClose: onClose })) })) })) }))) })));
1599
1599
  if (portal === true && (anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) != null) {
1600
- portal = { target: anchorRef.current.ownerDocument.body };
1600
+ if (hasParentClass("react-menu-inline-test", anchorRef.current)) {
1601
+ portal = false;
1602
+ }
1603
+ else {
1604
+ portal = { target: anchorRef.current.ownerDocument.body };
1605
+ }
1601
1606
  }
1602
1607
  if (portal) {
1603
1608
  if (typeof portal === "boolean") {
@@ -3273,17 +3278,17 @@ var fieldToString = function (field) {
3273
3278
  return typeof field == "symbol" ? field.toString() : "".concat(field);
3274
3279
  };
3275
3280
  var GridFormDropDown = function (props) {
3276
- var _a;
3277
- var _b = useGridPopoverContext(), selectedRows = _b.selectedRows, field = _b.field, data = _b.data;
3281
+ var _a, _b;
3282
+ var _c = useGridPopoverContext(), selectedRows = _c.selectedRows, field = _c.field, data = _c.data;
3278
3283
  // Save triggers during async action processing which triggers another selectItem(), this ref blocks that
3279
- var _c = useState(""), filter = _c[0], setFilter = _c[1];
3280
- var _d = useState(), filteredValues = _d[0], setFilteredValues = _d[1];
3281
- var _e = useState(null), options = _e[0], setOptions = _e[1];
3284
+ var _d = useState((_a = props.filterDefaultValue) !== null && _a !== void 0 ? _a : ""), filter = _d[0], setFilter = _d[1];
3285
+ var _e = useState(), filteredValues = _e[0], setFilteredValues = _e[1];
3286
+ var _f = useState(null), options = _f[0], setOptions = _f[1];
3282
3287
  var subComponentIsValid = useRef(false);
3283
3288
  var subComponentInitialValue = useRef(null);
3284
- var _f = useState(null), subSelectedValue = _f[0], setSubSelectedValue = _f[1];
3289
+ var _g = useState(null), subSelectedValue = _g[0], setSubSelectedValue = _g[1];
3285
3290
  // Note: null is assumed to be the filter
3286
- var _g = useState(null), selectedItem = _g[0], setSelectedItem = _g[1];
3291
+ var _h = useState(null), selectedItem = _h[0], setSelectedItem = _h[1];
3287
3292
  var selectItemHandler = useCallback(function (value, subComponentValue) { return __awaiter(void 0, void 0, void 0, function () {
3288
3293
  var hasChanged;
3289
3294
  return __generator(this, function (_a) {
@@ -3362,7 +3367,7 @@ var GridFormDropDown = function (props) {
3362
3367
  .filter(function (r) { return r !== undefined; }));
3363
3368
  }
3364
3369
  }, [props.filtered, filter, options]);
3365
- var researchOnFilterChange = useMemo(function () {
3370
+ var reSearchOnFilterChange = useMemo(function () {
3366
3371
  return dist$1(function () {
3367
3372
  setOptions(null);
3368
3373
  }, 500);
@@ -3372,9 +3377,9 @@ var GridFormDropDown = function (props) {
3372
3377
  useEffect(function () {
3373
3378
  if (previousFilter.current != filter && props.filtered == "reload") {
3374
3379
  previousFilter.current = filter;
3375
- researchOnFilterChange().then();
3380
+ reSearchOnFilterChange().then();
3376
3381
  }
3377
- }, [filter, props, researchOnFilterChange]);
3382
+ }, [filter, props, reSearchOnFilterChange]);
3378
3383
  /**
3379
3384
  * Saves are wrapped in updateValue and triggered by blur events
3380
3385
  */
@@ -3414,6 +3419,8 @@ var GridFormDropDown = function (props) {
3414
3419
  invalid: function () { return !!(selectedItem && !subComponentIsValid.current); },
3415
3420
  save: save
3416
3421
  }).popoverWrapper;
3422
+ var lastHeader = null;
3423
+ var showHeader = null;
3417
3424
  return popoverWrapper(jsxs(Fragment$1, { children: [props.filtered && (jsxs("div", __assign({ className: "GridFormDropDown-filter" }, { children: [jsx(FocusableItem, __assign({ className: "filter-item", onFocus: function () {
3418
3425
  setSelectedItem(null);
3419
3426
  setSubSelectedValue(null);
@@ -3423,44 +3430,58 @@ var GridFormDropDown = function (props) {
3423
3430
  var ref = _a.ref;
3424
3431
  return (jsxs("div", __assign({ style: { display: "flex", flexDirection: "column", width: "100%" } }, { children: [jsx("input", { className: "LuiTextInput-input", ref: ref, type: "text", placeholder: (_b = props.filterPlaceholder) !== null && _b !== void 0 ? _b : "Placeholder", "data-testid": "filteredMenu-free-text-input", defaultValue: filter, "data-allowtabtosave": true, "data-disableenterautosave": !props.onSelectFilter &&
3425
3432
  !(filteredValues && filteredValues.length === 1 && !filteredValues[0].subComponent), onChange: function (e) { return setFilter(e.target.value); } }), props.filterHelpText && isNotEmpty(filter) && (jsx(FormError, { error: null, helpText: props.filterHelpText }))] })));
3426
- } })), jsx(MenuDivider, {}, "$$divider_filter")] }))), jsx(ComponentLoadingWrapper, __assign({ loading: !options, className: "GridFormDropDown-options" }, { children: jsxs(Fragment$1, { children: [options && (isEmpty(options) || (filteredValues && isEmpty(filteredValues))) && (jsx(MenuItem, __assign({ className: "GridPopoverEditDropDown-noOptions" }, { children: (_a = props.noOptionsMessage) !== null && _a !== void 0 ? _a : "No Options" }), "".concat(fieldToString(field), "-empty"))), options === null || options === void 0 ? void 0 : options.map(function (item, index) {
3433
+ } })), jsx(MenuDivider, {}, "$$divider_filter")] }))), jsx(ComponentLoadingWrapper, __assign({ loading: !options, className: "GridFormDropDown-options" }, { children: jsxs(Fragment$1, { children: [options && (isEmpty(options) || (filteredValues && isEmpty(filteredValues))) && (jsx(MenuItem, __assign({ className: "GridPopoverEditDropDown-noOptions" }, { children: (_b = props.noOptionsMessage) !== null && _b !== void 0 ? _b : "No Options" }), "".concat(fieldToString(field), "-empty"))), options === null || options === void 0 ? void 0 : options.map(function (item, index) {
3427
3434
  var _a;
3428
- return item.value === MenuSeparatorString ? (jsx(MenuDivider, {}, "$$divider_".concat(index))) : item.value === MenuHeaderString ? (jsx(MenuHeader, { children: item.label }, "$$header_".concat(index))) : ((!filteredValues || filteredValues.includes(item)) && (jsxs("div", { children: [jsxs(MenuItem, __assign({ disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "", value: item.value, onFocus: function () {
3429
- setSelectedItem(item);
3430
- if (item.subComponent) {
3431
- setSelectedItem(item);
3432
- subComponentIsValid.current = true;
3433
- subComponentInitialValue.current = null;
3434
- }
3435
- else {
3436
- setSubSelectedValue(null);
3437
- subComponentIsValid.current = true;
3438
- }
3439
- }, onClick: function (e) {
3440
- if (item.subComponent) {
3441
- e.keepOpen = true;
3442
- }
3443
- } }, { children: [(_a = item.label) !== null && _a !== void 0 ? _a : (item.value == null ? "<".concat(item.value, ">") : "".concat(item.value)), item.subComponent ? "..." : ""] }), "".concat(fieldToString(field), "-").concat(index)), item.subComponent && selectedItem === item && (jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (ref) { return (jsx(GridSubComponentContext.Provider, __assign({ value: {
3444
- context: { options: options },
3445
- data: data,
3446
- value: subSelectedValue,
3447
- setValue: function (value) {
3448
- setSubSelectedValue(value);
3449
- if (subComponentInitialValue.current === null) {
3450
- // copy the default value of the sub-component so we can change detect on save
3451
- subComponentInitialValue.current = JSON.stringify(value);
3435
+ showHeader = null;
3436
+ if (item.value === MenuSeparatorString) {
3437
+ return jsx(MenuDivider, {}, "$$divider_".concat(index));
3438
+ }
3439
+ else if (item.value === MenuHeaderString) {
3440
+ lastHeader = jsx(MenuHeader, { children: item.label }, "$$header_".concat(index));
3441
+ return jsx(Fragment$1, {});
3442
+ }
3443
+ else {
3444
+ if (lastHeader) {
3445
+ showHeader = lastHeader;
3446
+ lastHeader = null;
3447
+ }
3448
+ }
3449
+ return ((!filteredValues || filteredValues.includes(item)) && (jsxs(Fragment$1, { children: [showHeader, jsxs("div", { children: [jsxs(MenuItem, __assign({ disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "", value: item.value, onFocus: function () {
3450
+ setSelectedItem(item);
3451
+ if (item.subComponent) {
3452
+ setSelectedItem(item);
3453
+ subComponentIsValid.current = true;
3454
+ subComponentInitialValue.current = null;
3455
+ }
3456
+ else {
3457
+ setSubSelectedValue(null);
3458
+ subComponentIsValid.current = true;
3459
+ }
3460
+ }, onClick: function (e) {
3461
+ if (item.subComponent) {
3462
+ e.keepOpen = true;
3452
3463
  }
3453
- },
3454
- setValid: function (valid) {
3455
- subComponentIsValid.current = valid;
3456
- },
3457
- triggerSave: function () { return __awaiter(void 0, void 0, void 0, function () {
3458
- return __generator(this, function (_a) {
3459
- ref.closeMenu();
3460
- return [2 /*return*/];
3461
- });
3462
- }); }
3463
- } }, { children: item.subComponent && (jsx("div", __assign({ className: "subComponent" }, { children: jsx(item.subComponent, {}, "".concat(fieldToString(field), "-").concat(index, "_subcomponent_inner")) }))) }))); } }), "".concat(item.label, "_subcomponent")))] }, "menu-wrapper-".concat(index))));
3464
+ } }, { children: [(_a = item.label) !== null && _a !== void 0 ? _a : (item.value == null ? "<".concat(item.value, ">") : "".concat(item.value)), item.subComponent ? "..." : ""] }), "".concat(fieldToString(field), "-").concat(index)), item.subComponent && selectedItem === item && (jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (ref) { return (jsx(GridSubComponentContext.Provider, __assign({ value: {
3465
+ context: { options: options },
3466
+ data: data,
3467
+ value: subSelectedValue,
3468
+ setValue: function (value) {
3469
+ setSubSelectedValue(value);
3470
+ if (subComponentInitialValue.current === null) {
3471
+ // copy the default value of the subcomponent so we can change detect on save
3472
+ subComponentInitialValue.current = JSON.stringify(value);
3473
+ }
3474
+ },
3475
+ setValid: function (valid) {
3476
+ subComponentIsValid.current = valid;
3477
+ },
3478
+ triggerSave: function () { return __awaiter(void 0, void 0, void 0, function () {
3479
+ return __generator(this, function (_a) {
3480
+ ref.closeMenu();
3481
+ return [2 /*return*/];
3482
+ });
3483
+ }); }
3484
+ } }, { children: item.subComponent && (jsx("div", __assign({ className: "subComponent" }, { children: jsx(item.subComponent, {}, "".concat(fieldToString(field), "-").concat(index, "_subcomponent_inner")) }))) }))); } }), "".concat(item.label, "_subcomponent")))] }, "menu-wrapper-".concat(index))] })));
3464
3485
  })] }) }))] }));
3465
3486
  };
3466
3487
 
@@ -3639,7 +3660,10 @@ var GridFormMultiSelect = function (props) {
3639
3660
  // Any changes to save?
3640
3661
  if (initialValues === JSON.stringify(options))
3641
3662
  return [2 /*return*/, true];
3642
- return [2 /*return*/, props.onSave(selectedRows, options.filter(function (o) { return o.checked; }))];
3663
+ return [2 /*return*/, props.onSave({
3664
+ selectedRows: selectedRows,
3665
+ selectedOptions: options.filter(function (o) { return o.checked; })
3666
+ })];
3643
3667
  });
3644
3668
  }); }, [initialValues, options, props]);
3645
3669
  // Load up options list if it's async function
@@ -3752,7 +3776,7 @@ var FilterInput = function (props) {
3752
3776
  return;
3753
3777
  }
3754
3778
  var preFilterOptions = JSON.stringify(options);
3755
- onSelectFilter(filterTrimmed, options);
3779
+ onSelectFilter({ filter: filterTrimmed, options: options });
3756
3780
  // Detect if options list changed and update
3757
3781
  if (preFilterOptions === JSON.stringify(options))
3758
3782
  return;
@@ -3840,7 +3864,8 @@ var GridPopoutEditMultiSelect = function (colDef, props) {
3840
3864
  };
3841
3865
 
3842
3866
  /** Menu configuration types **/
3843
- var PopoutMenuSeparator = Object.freeze({ __isMenuSeparator__: true });
3867
+ var __isMenuSeparator__ = "__isMenuSeparator__";
3868
+ var PopoutMenuSeparator = Object.freeze({ label: __isMenuSeparator__ });
3844
3869
  /**
3845
3870
  * NOTE: If the popout menu doesn't appear on single click when also selecting row it's because
3846
3871
  * you need a useMemo around your columnDefs
@@ -3852,17 +3877,17 @@ var GridFormPopoverMenu = function (props) {
3852
3877
  var _c = useState(null), subComponentSelected = _c[0], setSubComponentSelected = _c[1];
3853
3878
  var subComponentIsValid = useRef(false);
3854
3879
  var _d = useState(), subSelectedValue = _d[0], setSubSelectedValue = _d[1];
3855
- var defaultAction = useCallback(function (selectedRows, menuOption) { return __awaiter(void 0, void 0, void 0, function () {
3880
+ var defaultAction = useCallback(function (params) { return __awaiter(void 0, void 0, void 0, function () {
3856
3881
  return __generator(this, function (_a) {
3857
3882
  switch (_a.label) {
3858
3883
  case 0:
3859
3884
  if (!props.defaultAction) return [3 /*break*/, 2];
3860
- return [4 /*yield*/, props.defaultAction(selectedRows, menuOption)];
3885
+ return [4 /*yield*/, props.defaultAction(params)];
3861
3886
  case 1:
3862
3887
  _a.sent();
3863
3888
  return [3 /*break*/, 3];
3864
3889
  case 2:
3865
- console.error("No action specified for ".concat(menuOption.label, " menu options"));
3890
+ console.error("No action specified for ".concat(params.menuOption.label, " menu options"));
3866
3891
  _a.label = 3;
3867
3892
  case 3: return [2 /*return*/];
3868
3893
  }
@@ -3906,13 +3931,13 @@ var GridFormPopoverMenu = function (props) {
3906
3931
  }); })();
3907
3932
  }, [options, props.defaultAction, props.options, selectedRows]);
3908
3933
  var actionClick = useCallback(function (menuOption) { return __awaiter(void 0, void 0, void 0, function () {
3909
- var result;
3910
3934
  var _a;
3911
3935
  return __generator(this, function (_b) {
3912
3936
  switch (_b.label) {
3913
- case 0:
3914
- result = __assign(__assign({}, menuOption), { subValue: subSelectedValue });
3915
- return [4 /*yield*/, ((_a = menuOption.action) !== null && _a !== void 0 ? _a : defaultAction)(selectedRows, result)];
3937
+ case 0: return [4 /*yield*/, ((_a = menuOption.action) !== null && _a !== void 0 ? _a : defaultAction)({
3938
+ selectedRows: selectedRows,
3939
+ menuOption: __assign(__assign({}, menuOption), { subValue: subSelectedValue })
3940
+ })];
3916
3941
  case 1:
3917
3942
  _b.sent();
3918
3943
  return [2 /*return*/, true];
@@ -3961,8 +3986,8 @@ var GridFormPopoverMenu = function (props) {
3961
3986
  invalid: function () { return subComponentSelected && !subComponentIsValid.current; },
3962
3987
  save: save
3963
3988
  }), popoverWrapper = _e.popoverWrapper, triggerSave = _e.triggerSave;
3964
- return popoverWrapper(jsx(ComponentLoadingWrapper, __assign({ loading: !options, className: "GridFormPopupMenu" }, { children: jsx(Fragment$1, { children: options === null || options === void 0 ? void 0 : options.map(function (item, index) {
3965
- return item.label === PopoutMenuSeparator ? (jsx(MenuDivider, {}, "$$divider_".concat(index))) : (!item.hidden && (jsxs(Fragment, { children: [jsx(MenuItem, __assign({ onClick: function (e) { return onMenuItemClick(e, item); }, disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "" }, { children: item.label }), "".concat(item.label)), item.subComponent && subComponentSelected === item && (jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (_) {
3989
+ return popoverWrapper(jsx(ComponentLoadingWrapper, __assign({ loading: !options, className: "GridFormPopupMenu" }, { children: jsx(Fragment$1, { children: (options === null || options === void 0 ? void 0 : options.length) === 0 ? (jsx(MenuItem, __assign({ className: "GridPopoverMenu-noOptions", disabled: true }, { children: "No actions" }), "GridPopoverMenu-empty")) : (options === null || options === void 0 ? void 0 : options.map(function (item, index) {
3990
+ return item.label === "__isMenuSeparator__" ? (jsx(MenuDivider, {}, "$$divider_".concat(index))) : (!item.hidden && (jsxs(Fragment, { children: [jsx(MenuItem, __assign({ onClick: function (e) { return onMenuItemClick(e, item); }, disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "" }, { children: item.label }), "".concat(item.label)), item.subComponent && subComponentSelected === item && (jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (_) {
3966
3991
  return item.subComponent && (jsx(GridSubComponentContext.Provider, __assign({ value: {
3967
3992
  context: {},
3968
3993
  data: data,
@@ -3976,7 +4001,7 @@ var GridFormPopoverMenu = function (props) {
3976
4001
  triggerSave: triggerSave
3977
4002
  } }, { children: jsx("div", __assign({ className: "subComponent" }, { children: jsx(item.subComponent, {}) })) })));
3978
4003
  } }), "".concat(item.label, "_subcomponent")))] }, "".concat(item.label))));
3979
- }) }) })));
4004
+ })) }) })));
3980
4005
  };
3981
4006
 
3982
4007
  /**
@@ -3989,22 +4014,22 @@ var GridPopoverMenu = function (colDef, custom) {
3989
4014
  } }), __assign({ editor: GridFormPopoverMenu }, custom));
3990
4015
  };
3991
4016
 
3992
- var bearingValueFormatter = function (params) {
3993
- var value = typeof params.value == "string" ? parseFloat(params.value) : params.value;
3994
- if (value == null) {
4017
+ var bearingValueFormatter = function (value) {
4018
+ var safeValue = typeof value == "string" ? parseFloat(value) : value;
4019
+ if (safeValue == null) {
3995
4020
  return "–";
3996
4021
  }
3997
- return convertDDToDMS(value, false, false);
4022
+ return convertDDToDMS(safeValue, false, false);
3998
4023
  };
3999
- var bearingCorrectionValueFormatter = function (params) {
4000
- var value = params.value;
4001
- if (value == null) {
4024
+ var bearingCorrectionValueFormatter = function (value) {
4025
+ var safeValue = value;
4026
+ if (safeValue == null) {
4002
4027
  return "–";
4003
4028
  }
4004
- if (typeof value === "string") {
4005
- return convertDDToDMS(bearingNumberParser(value), true, true);
4029
+ if (typeof safeValue === "string") {
4030
+ return convertDDToDMS(bearingNumberParser(safeValue), true, true);
4006
4031
  }
4007
- return convertDDToDMS(value, true, true);
4032
+ return convertDDToDMS(safeValue, true, true);
4008
4033
  };
4009
4034
  var bearingNumberParser = function (value) {
4010
4035
  if (value === "")
@@ -4078,7 +4103,7 @@ var TextInputFormatted = function (props) {
4078
4103
  };
4079
4104
 
4080
4105
  var GridFormEditBearing = function (props) {
4081
- var _a = useGridPopoverContext(), field = _a.field, initialValue = _a.value, formatValue = _a.formatValue;
4106
+ var _a = useGridPopoverContext(), field = _a.field, initialValue = _a.value;
4082
4107
  // This clears out any scientific precision
4083
4108
  var defaultValue = useMemo(function () { return (initialValue == null ? "" : parseFloat(parseFloat(initialValue).toFixed(10)).toString()); }, [initialValue]);
4084
4109
  var _b = useState(defaultValue), value = _b[0], setValue = _b[1];
@@ -4094,7 +4119,7 @@ var GridFormEditBearing = function (props) {
4094
4119
  return [2 /*return*/, true];
4095
4120
  }
4096
4121
  if (!props.onSave) return [3 /*break*/, 2];
4097
- return [4 /*yield*/, props.onSave(selectedRows, parsedValue)];
4122
+ return [4 /*yield*/, props.onSave({ selectedRows: selectedRows, value: parsedValue })];
4098
4123
  case 1: return [2 /*return*/, _a.sent()];
4099
4124
  case 2:
4100
4125
  if (field == null) {
@@ -4117,38 +4142,50 @@ var GridFormEditBearing = function (props) {
4117
4142
  }).popoverWrapper;
4118
4143
  return popoverWrapper(jsx("div", __assign({ className: "GridFormEditBearing-input Grid-popoverContainer" }, { children: jsx(TextInputFormatted, { value: defaultValue, onChange: function (e) {
4119
4144
  setValue(e.target.value.trim());
4120
- }, autoFocus: true, placeholder: props.placeHolder, formatted: bearingStringValidator(value, props.range) ? "?" : formatValue(bearingNumberParser(value)), error: bearingStringValidator(value, props.range), helpText: "Press enter or tab to save" }) })));
4145
+ }, autoFocus: true, placeholder: props.placeHolder, formatted: bearingStringValidator(value, props.range) || !props.formatValue
4146
+ ? "?"
4147
+ : props.formatValue(bearingNumberParser(value)), error: bearingStringValidator(value, props.range), helpText: "Press enter or tab to save" }) })));
4121
4148
  };
4122
4149
 
4123
4150
  var GridPopoverEditBearingLike = function (colDef, props) {
4124
- return GridCell(__assign({ initialWidth: 65, maxWidth: 150 }, colDef), __assign({ editor: GridFormEditBearing }, props));
4151
+ return GridCell(__assign({ initialWidth: 65, maxWidth: 150, valueFormatter: function (params) { var _a, _b; return (_b = (_a = props.editorParams) === null || _a === void 0 ? void 0 : _a.formatValue(params.value)) !== null && _b !== void 0 ? _b : ""; } }, colDef), __assign({ editor: GridFormEditBearing }, props));
4152
+ };
4153
+ var GridPopoverEditBearingEditorParams = {
4154
+ placeHolder: "Enter bearing",
4155
+ formatValue: bearingValueFormatter,
4156
+ range: function (value) {
4157
+ if (value === null)
4158
+ return "Bearing is required";
4159
+ if (value >= 360)
4160
+ return "Bearing must be less than 360 degrees";
4161
+ if (value < 0)
4162
+ return "Bearing must not be negative";
4163
+ return null;
4164
+ }
4125
4165
  };
4126
4166
  var GridPopoverEditBearing = function (colDef, props) {
4127
- return GridPopoverEditBearingLike(__assign({ valueFormatter: bearingValueFormatter }, colDef), {
4167
+ return GridPopoverEditBearingLike(colDef, {
4128
4168
  multiEdit: !!props.multiEdit,
4129
- editorParams: __assign({ placeHolder: "Enter bearing correction", range: function (value) {
4130
- if (value === null)
4131
- return "Bearing correction is required";
4132
- if (value >= 360)
4133
- return "Bearing correction must be less than 360 degrees";
4134
- if (value < 0)
4135
- return "Bearing correction must not be negative";
4136
- return null;
4137
- } }, props.editorParams)
4169
+ editorParams: __assign(__assign({}, GridPopoverEditBearingEditorParams), props.editorParams)
4138
4170
  });
4139
4171
  };
4172
+ var GridPopoverEditBearingCorrectionEditorParams = {
4173
+ placeHolder: "Enter bearing correction",
4174
+ formatValue: bearingCorrectionValueFormatter,
4175
+ range: function (value) {
4176
+ if (value === null)
4177
+ return "Bearing correction is required";
4178
+ if (value >= 360)
4179
+ return "Bearing correction must be less than 360 degrees";
4180
+ if (value <= -180)
4181
+ return "Bearing correction must be greater then -180 degrees";
4182
+ return null;
4183
+ }
4184
+ };
4140
4185
  var GridPopoverEditBearingCorrection = function (colDef, props) {
4141
- return GridPopoverEditBearingLike(__assign({ valueFormatter: bearingCorrectionValueFormatter }, colDef), {
4186
+ return GridPopoverEditBearingLike(colDef, {
4142
4187
  multiEdit: !!props.multiEdit,
4143
- editorParams: __assign({ placeHolder: "Enter bearing correction", range: function (value) {
4144
- if (value === null)
4145
- return "Bearing is required";
4146
- if (value >= 360)
4147
- return "Bearing must be less than 360 degrees";
4148
- if (value <= -180)
4149
- return "Bearing must be greater then -180 degrees";
4150
- return null;
4151
- } }, props.editorParams)
4188
+ editorParams: __assign(__assign({}, GridPopoverEditBearingCorrectionEditorParams), props.editorParams)
4152
4189
  });
4153
4190
  };
4154
4191
 
@@ -4337,7 +4374,7 @@ var GridFormTextArea = function (props) {
4337
4374
  if (initValue === trimmedValue)
4338
4375
  return [2 /*return*/, true];
4339
4376
  if (!props.onSave) return [3 /*break*/, 2];
4340
- return [4 /*yield*/, props.onSave(selectedRows, trimmedValue)];
4377
+ return [4 /*yield*/, props.onSave({ selectedRows: selectedRows, value: trimmedValue })];
4341
4378
  case 1: return [2 /*return*/, _a.sent()];
4342
4379
  case 2:
4343
4380
  selectedRows.forEach(function (row) { return (row[field] = trimmedValue); });
@@ -4374,7 +4411,7 @@ var GridFormTextInput = function (props) {
4374
4411
  if (initValue === trimmedValue)
4375
4412
  return [2 /*return*/, true];
4376
4413
  if (!props.onSave) return [3 /*break*/, 2];
4377
- return [4 /*yield*/, props.onSave(selectedRows, trimmedValue)];
4414
+ return [4 /*yield*/, props.onSave({ selectedRows: selectedRows, value: trimmedValue })];
4378
4415
  case 1: return [2 /*return*/, _a.sent()];
4379
4416
  case 2:
4380
4417
  selectedRows.forEach(function (row) { return (row[field] = trimmedValue); });
@@ -4499,7 +4536,7 @@ var useStateDeferred = function (initialValue) {
4499
4536
  var minimumInProgressTimeMs = 950;
4500
4537
  var ActionButton = function (_a) {
4501
4538
  var _b, _c, _d;
4502
- var icon = _a.icon, name = _a.name, inProgressName = _a.inProgressName, dataTestId = _a.dataTestId, style = _a.style, className = _a.className, title = _a.title, onClick = _a.onClick, _e = _a.size, size = _e === void 0 ? "sm" : _e, _f = _a.iconPosition, iconPosition = _f === void 0 ? "left" : _f, _g = _a.level, level = _g === void 0 ? "tertiary" : _g, ariaLabel = _a["aria-label"];
4539
+ var icon = _a.icon, name = _a.name, inProgressName = _a.inProgressName, disabled = _a.disabled, dataTestId = _a.dataTestId, style = _a.style, className = _a.className, title = _a.title, onClick = _a.onClick, _e = _a.size, size = _e === void 0 ? "sm" : _e, _f = _a.iconPosition, iconPosition = _f === void 0 ? "left" : _f, _g = _a.level, level = _g === void 0 ? "tertiary" : _g, ariaLabel = _a["aria-label"];
4503
4540
  var _h = useState(false), inProgress = _h[0], setInProgress = _h[1];
4504
4541
  var lastInProgress = usePrevious(inProgress !== null && inProgress !== void 0 ? inProgress : false);
4505
4542
  var _j = useStateDeferred(inProgress), localInProgress = _j[0], setLocalInProgress = _j[1], setLocalInProgressDeferred = _j[2];
@@ -4529,7 +4566,7 @@ var ActionButton = function (_a) {
4529
4566
  case 3: return [2 /*return*/];
4530
4567
  }
4531
4568
  });
4532
- }); }, disabled: localInProgress }, { children: [iconPosition === "right" && buttonText, localInProgress ? (jsx(LuiMiniSpinner, { size: 16, divProps: {
4569
+ }); }, disabled: localInProgress || disabled }, { children: [iconPosition === "right" && buttonText, localInProgress ? (jsx(LuiMiniSpinner, { size: 16, divProps: {
4533
4570
  "data-testid": "loading-spinner",
4534
4571
  style: {
4535
4572
  margin: 0,