@linzjs/step-ag-grid 29.1.3 → 29.1.5

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.
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { LuiMiniSpinner, LuiStatusSpinner, LuiIcon, LuiButtonGroup, LuiButton, LuiCheckboxInput } from '@linzjs/lui';
3
3
  import { ModuleRegistry, AllCommunityModule } from 'ag-grid-community';
4
4
  import { AgGridReact } from 'ag-grid-react';
5
- import { negate, isEmpty, findIndex, defer, debounce as debounce$1, xorBy, last, difference, omit, sortBy, delay, partition, pick, groupBy, fromPairs, toPairs, isEqual, pull, compact, filter, sumBy, remove, flatten, castArray } from 'lodash-es';
5
+ import { negate, isEmpty, findIndex, defer, debounce as debounce$1, xorBy, last, difference, omit, sortBy, delay, partition, compact, pick, groupBy, fromPairs, toPairs, isEqual, pull, filter, sumBy, remove, flatten, castArray } from 'lodash-es';
6
6
  import React, { useRef, useLayoutEffect, useEffect, createContext, useContext, useState, useMemo, memo, forwardRef, useCallback, useReducer, cloneElement, useImperativeHandle, Fragment as Fragment$1, useId } from 'react';
7
7
  import { unstable_batchedUpdates, flushSync, createPortal } from 'react-dom';
8
8
 
@@ -3799,6 +3799,19 @@ const FormError = (props) => {
3799
3799
  return (jsxs(Fragment, { children: [props.error && (jsxs("div", { className: "FormError", children: [jsx(LuiIcon, { alt: "error", name: "ic_error", className: "FormError-text-icon", size: "sm", status: "error" }), jsx("span", { className: "FormError-error", children: props.error })] })), props.helpText && !props.error && jsx("span", { className: 'FormError-helpText', children: props.helpText })] }));
3800
3800
  };
3801
3801
 
3802
+ /**
3803
+ * Track previous values of states.
3804
+ *
3805
+ * @param value Value to track.
3806
+ */
3807
+ const usePrevious = (value) => {
3808
+ const ref = useRef();
3809
+ useEffect(() => {
3810
+ ref.current = value;
3811
+ }, [value]);
3812
+ return ref.current;
3813
+ };
3814
+
3802
3815
  function escapeStringRegexp(string) {
3803
3816
  if (typeof string !== 'string') {
3804
3817
  throw new TypeError('Expected a string');
@@ -4015,10 +4028,11 @@ const fieldToString = (field) => {
4015
4028
  };
4016
4029
  const GridFormDropDown = (props) => {
4017
4030
  const { selectedRows, field, data } = useGridPopoverContext();
4031
+ const { onSelectFilter, options: propOptions, onSelectedItem } = props;
4018
4032
  // Save triggers during async action processing which triggers another selectItem(), this ref blocks that
4019
4033
  const [filter, setFilter] = useState(props.filterDefaultValue ?? '');
4020
4034
  const [filteredValues, setFilteredValues] = useState();
4021
- const [options, setOptions] = useState(null);
4035
+ const [options, setOptions] = useState(!!propOptions && typeof propOptions !== 'function' ? propOptions : null);
4022
4036
  const subComponentIsValid = useRef(false);
4023
4037
  const subComponentInitialValue = useRef(null);
4024
4038
  const [subSelectedValue, setSubSelectedValue] = useState(null);
@@ -4028,8 +4042,8 @@ const GridFormDropDown = (props) => {
4028
4042
  const hasChanged = selectedRows.some((row) => row[field] !== value) ||
4029
4043
  (subComponentValue !== undefined && subComponentInitialValue.current !== JSON.stringify(subComponentValue));
4030
4044
  if (hasChanged) {
4031
- if (props.onSelectedItem) {
4032
- await props.onSelectedItem({
4045
+ if (onSelectedItem) {
4046
+ await onSelectedItem({
4033
4047
  selectedRows,
4034
4048
  selectedRowIds: selectedRows.map((row) => row.id),
4035
4049
  value,
@@ -4041,58 +4055,17 @@ const GridFormDropDown = (props) => {
4041
4055
  }
4042
4056
  }
4043
4057
  return true;
4044
- }, [field, props, selectedRows]);
4045
- // Load up options list if it's async function
4046
- useEffect(() => {
4047
- if (options)
4048
- return;
4049
- let optionsConf = props.options;
4050
- void (async () => {
4051
- if (typeof optionsConf === 'function') {
4052
- optionsConf = await optionsConf(selectedRows, filter);
4053
- }
4054
- if (optionsConf !== undefined) {
4055
- setOptions(optionsConf);
4056
- }
4057
- })();
4058
- }, [filter, options, props, selectedRows]);
4059
- // Local filtering.
4060
- useEffect(() => {
4061
- if (props.filtered == 'local') {
4062
- if (options == null)
4063
- return;
4064
- setFilteredValues(options
4065
- .map((option) => {
4066
- if (option.label != null && typeof option.label !== 'string') {
4067
- console.error('Cannot filter non-string labels', option);
4068
- return undefined;
4069
- }
4070
- return textMatch(option.label || '', filter) ? option : undefined;
4071
- })
4072
- .filter((r) => r !== undefined));
4073
- }
4074
- }, [props.filtered, filter, options]);
4075
- const reSearchOnFilterChange = useMemo(() => debounce(() => {
4076
- setOptions(null);
4077
- }, 500), []);
4078
- const previousFilter = useRef(filter);
4079
- // Reload filtering.
4080
- useEffect(() => {
4081
- if (previousFilter.current != filter && props.filtered == 'reload') {
4082
- previousFilter.current = filter;
4083
- void reSearchOnFilterChange();
4084
- }
4085
- }, [filter, props, reSearchOnFilterChange]);
4058
+ }, [field, onSelectedItem, selectedRows]);
4086
4059
  /**
4087
4060
  * Saves are wrapped in updateValue and triggered by blur events
4088
4061
  */
4089
4062
  const save = useCallback(async () => {
4090
- if (!options)
4063
+ if (!options) {
4091
4064
  return true;
4065
+ }
4092
4066
  // Filter saved
4093
4067
  if (selectedItem === null) {
4094
- if (props.onSelectFilter) {
4095
- const { onSelectFilter } = props;
4068
+ if (onSelectFilter) {
4096
4069
  if (!isEmpty(filter)) {
4097
4070
  await onSelectFilter({
4098
4071
  selectedRows,
@@ -4111,17 +4084,73 @@ const GridFormDropDown = (props) => {
4111
4084
  }
4112
4085
  return false;
4113
4086
  }
4114
- if (selectedItem.subComponent && !subComponentIsValid.current)
4087
+ if (selectedItem.subComponent && !subComponentIsValid.current) {
4115
4088
  return false;
4089
+ }
4116
4090
  await selectItemHandler(selectedItem.value, subSelectedValue);
4117
4091
  return true;
4118
- }, [filter, filteredValues, options, props, selectItemHandler, selectedItem, selectedRows, subSelectedValue]);
4092
+ }, [
4093
+ filter,
4094
+ filteredValues,
4095
+ onSelectFilter,
4096
+ options,
4097
+ selectItemHandler,
4098
+ selectedItem,
4099
+ selectedRows,
4100
+ subSelectedValue,
4101
+ ]);
4119
4102
  const { popoverWrapper } = useGridPopoverHook({
4120
4103
  className: props.className,
4121
4104
  invalid: () => !options || !!(selectedItem && !subComponentIsValid.current),
4122
4105
  save,
4123
4106
  dontSaveOnExternalClick: true,
4124
4107
  });
4108
+ // Load up options list if it's async function
4109
+ useEffect(() => {
4110
+ // If options is null then we need to load/reload
4111
+ // Options will be set to null during a reload based filter, or on open popup
4112
+ if (options !== null) {
4113
+ return;
4114
+ }
4115
+ // propOptions is a const list
4116
+ if (typeof propOptions !== 'function') {
4117
+ if (propOptions) {
4118
+ setOptions(propOptions);
4119
+ }
4120
+ return;
4121
+ }
4122
+ // propOptions is function, probably loading from web
4123
+ void (async () => {
4124
+ const r = await propOptions(selectedRows, filter);
4125
+ setOptions(r ?? []);
4126
+ })();
4127
+ }, [filter, options, propOptions, selectedRows]);
4128
+ // Local filtering.
4129
+ useEffect(() => {
4130
+ if (props.filtered !== 'local') {
4131
+ return;
4132
+ }
4133
+ if (options == null) {
4134
+ setFilteredValues([]);
4135
+ return;
4136
+ }
4137
+ setFilteredValues(compact(options.map((option) => {
4138
+ if (option.label != null && typeof option.label !== 'string') {
4139
+ console.warn('GridFormDropDown: Cannot filter non-string labels', option);
4140
+ return undefined;
4141
+ }
4142
+ return textMatch(option.label || '', filter) ? option : undefined;
4143
+ })));
4144
+ }, [props.filtered, filter, options]);
4145
+ const reSearchOnFilterChange = useMemo(() => debounce(() => {
4146
+ setOptions(null);
4147
+ }, 500), []);
4148
+ const previousFilter = usePrevious(filter);
4149
+ useEffect(() => {
4150
+ if (previousFilter != null && previousFilter != filter && props.filtered === 'reload') {
4151
+ void reSearchOnFilterChange();
4152
+ }
4153
+ }, [filter, previousFilter, props.filtered, reSearchOnFilterChange]);
4125
4154
  let lastHeader = null;
4126
4155
  let showHeader = null;
4127
4156
  return popoverWrapper(jsxs(Fragment, { children: [props.filtered && (jsxs("div", { className: 'GridFormDropDown-filter', children: [jsx(FocusableItem, { className: 'filter-item', onFocus: () => {
@@ -5805,19 +5834,6 @@ const GridUpdatingContextProvider = (props) => {
5805
5834
  var css_248z = ".ActionButton{align-items:center;display:flex}.ActionButton-inProgress .LuiIcon{visibility:hidden}.ActionButton-minimal.lui-button-lg.lui-button-icon-right{padding-right:38px}.ActionButton.lui-button-lg.lui-button-icon-right:not(.ActionButton-tight) .LuiIcon{margin:0 4px}.ActionButton.ActionButton-tight.lui-button-lg.lui-button-icon-right .LuiIcon{margin:0}.ActionButton-iconOnly.lui-button-lg.lui-button-icon-right:not(.ActionButton-tight){padding:8px 5px}.ActionButton-iconOnly.lui-button-lg.lui-button-icon-right.ActionButton-tight{padding:0}.ActionButton-minimalArea{position:relative}.ActionButton-minimalAreaDisplay{position:absolute}.ActionButton-minimalAreaExpand{visibility:hidden}.ActionButton-inProgress.lui-button-lg.lui-button-icon-right{background-color:#e2f3f7;color:#007198;cursor:progress}.ActionButton-fill{justify-content:center;width:100%}";
5806
5835
  styleInject(css_248z);
5807
5836
 
5808
- /**
5809
- * Track previous values of states.
5810
- *
5811
- * @param value Value to track.
5812
- */
5813
- const usePrevious = (value) => {
5814
- const ref = useRef();
5815
- useEffect(() => {
5816
- ref.current = value;
5817
- }, [value]);
5818
- return ref.current;
5819
- };
5820
-
5821
5837
  // Kept this less than one second, so I don't have issues with waitFor as it defaults to 1s
5822
5838
  const minimumInProgressTimeMs = 950;
5823
5839
  const ActionButton = ({ icon, name, inProgressName, disabled, dataTestId, style, className, title, onClick, size = 'sm', iconPosition = 'left', level = 'tertiary', 'aria-label': ariaLabel, }) => {