@linzjs/step-ag-grid 6.1.1 → 7.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 (44) hide show
  1. package/dist/index.css +12 -2
  2. package/dist/index.js +377 -202
  3. package/dist/index.js.map +1 -1
  4. package/dist/src/components/GridPopoverHook.d.ts +1 -1
  5. package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +17 -12
  6. package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.d.ts +1 -1
  7. package/dist/src/contexts/GridSubComponentContext.d.ts +1 -0
  8. package/dist/src/lui/ActionButton.d.ts +2 -1
  9. package/dist/src/lui/FormError.d.ts +2 -1
  10. package/dist/src/lui/TextAreaInput.d.ts +1 -1
  11. package/dist/src/lui/TextInputFormatted.d.ts +1 -1
  12. package/dist/src/react-menu3/utils/utils.d.ts +1 -0
  13. package/dist/src/utils/textMatcher.d.ts +13 -0
  14. package/dist/src/utils/textValidator.d.ts +3 -2
  15. package/dist/src/utils/util.d.ts +2 -1
  16. package/dist/step-ag-grid.esm.js +378 -204
  17. package/dist/step-ag-grid.esm.js.map +1 -1
  18. package/package.json +9 -8
  19. package/src/components/GridPopoverHook.tsx +7 -1
  20. package/src/components/gridForm/GridFormDropDown.tsx +1 -0
  21. package/src/components/gridForm/GridFormMultiSelect.tsx +290 -188
  22. package/src/components/gridForm/GridFormPopoverMenu.tsx +1 -0
  23. package/src/components/gridForm/GridFormSubComponentTextArea.tsx +2 -2
  24. package/src/components/gridForm/GridFormSubComponentTextInput.tsx +3 -5
  25. package/src/components/gridForm/GridFormTextArea.tsx +13 -13
  26. package/src/components/gridForm/GridFormTextInput.tsx +3 -8
  27. package/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.ts +3 -3
  28. package/src/contexts/GridSubComponentContext.ts +2 -0
  29. package/src/lui/ActionButton.tsx +26 -8
  30. package/src/lui/FormError.scss +7 -0
  31. package/src/lui/FormError.tsx +4 -13
  32. package/src/lui/TextAreaInput.tsx +1 -1
  33. package/src/lui/TextInputFormatted.tsx +1 -1
  34. package/src/react-menu3/components/ControlledMenu.tsx +3 -2
  35. package/src/react-menu3/components/MenuList.tsx +2 -12
  36. package/src/react-menu3/hooks/useItems.ts +5 -2
  37. package/src/react-menu3/utils/utils.ts +15 -0
  38. package/src/stories/components/ActionButton.stories.tsx +9 -0
  39. package/src/stories/grid/GridPopoutEditMultiSelect.stories.tsx +93 -17
  40. package/src/styles/Grid.scss +12 -0
  41. package/src/styles/lui-overrides.scss +0 -2
  42. package/src/utils/textMatcher.ts +31 -0
  43. package/src/utils/textValidator.ts +6 -3
  44. package/src/utils/util.ts +6 -7
@@ -1,6 +1,6 @@
1
1
  import { useMemo, useLayoutEffect, useEffect, createContext, memo, forwardRef, useRef, useContext, useState, useCallback, useReducer, cloneElement, useImperativeHandle, Fragment } from 'react';
2
2
  import { unstable_batchedUpdates, flushSync, createPortal } from 'react-dom';
3
- import { findIndex, debounce, isEmpty, delay, sortBy, last, difference, castArray, remove, flatten, xorBy, fromPairs, pick, omit, toPairs, isEqual } from 'lodash-es';
3
+ import { findIndex, debounce, negate, isEmpty, delay, sortBy, last, difference, castArray, remove, flatten, xorBy, pick, groupBy, toPairs, omit } from 'lodash-es';
4
4
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
5
5
  import { AgGridReact } from 'ag-grid-react';
6
6
  import { LuiMiniSpinner, LuiIcon, LuiCheckboxInput, LuiButton } from '@linzjs/lui';
@@ -178,7 +178,22 @@ function commonProps(isDisabled, isHovering) {
178
178
  tabIndex: isHovering ? 0 : -1
179
179
  };
180
180
  }
181
- var indexOfNode = function (nodeList, node) { return findIndex(nodeList, node); };
181
+ var indexOfNode = function (nodeList, node) { return findIndex(nodeList, node); };
182
+ var focusFirstInput = function (container) {
183
+ if (!(container instanceof Element))
184
+ return false;
185
+ var inputs = container.querySelectorAll("input[type='text'],textarea");
186
+ var input = inputs[0];
187
+ if (input instanceof HTMLElement) {
188
+ input.focus();
189
+ // Text areas should start at end
190
+ if (input instanceof HTMLTextAreaElement) {
191
+ input.selectionStart = input.value.length;
192
+ }
193
+ return true;
194
+ }
195
+ return false;
196
+ };
182
197
 
183
198
  /******************************************************************************
184
199
  Copyright (c) Microsoft Corporation.
@@ -353,8 +368,9 @@ var useItems = function (menuRef, focusRef) {
353
368
  if (index >= items.length)
354
369
  index = 0;
355
370
  newItem = items[index];
371
+ focusFirstInput(newItem);
356
372
  break;
357
- case HoverActionTypes.DECREASE:
373
+ case HoverActionTypes.DECREASE: {
358
374
  sortItems();
359
375
  index = hoverIndex;
360
376
  if (index < 0)
@@ -363,7 +379,9 @@ var useItems = function (menuRef, focusRef) {
363
379
  if (index < 0)
364
380
  index = items.length - 1;
365
381
  newItem = items[index];
382
+ focusFirstInput(newItem);
366
383
  break;
384
+ }
367
385
  default:
368
386
  if (process.env.NODE_ENV !== "production")
369
387
  throw new Error("[React-Menu] Unknown hover action type: ".concat(actionType));
@@ -1199,26 +1217,13 @@ var MenuList = function (_a) {
1199
1217
  else if (captureFocus) {
1200
1218
  // Use a timeout here because if set focus immediately, page might scroll unexpectedly.
1201
1219
  var id_1 = setTimeout(function () {
1202
- var _a, _b, _c;
1220
+ var _a, _b;
1203
1221
  // If focus has already been set to a children element, don't set focus on menu or item
1204
1222
  if (!menuRef.current.contains(document.activeElement)) {
1205
1223
  // Handle popover portal focus
1206
1224
  var popupElement = (_a = focusRef.current) === null || _a === void 0 ? void 0 : _a.nextSibling;
1207
- if (popupElement instanceof Element) {
1208
- var input = popupElement.querySelectorAll("input,textarea")[0];
1209
- if (input) {
1210
- input.focus();
1211
- // Text areas should start at end
1212
- if (input instanceof HTMLTextAreaElement) {
1213
- input.selectionStart = input.value.length;
1214
- }
1215
- }
1216
- else {
1217
- (_b = focusRef.current) === null || _b === void 0 ? void 0 : _b.focus();
1218
- }
1219
- }
1220
- else {
1221
- (_c = focusRef.current) === null || _c === void 0 ? void 0 : _c.focus();
1225
+ if (!focusFirstInput(popupElement)) {
1226
+ (_b = focusRef.current) === null || _b === void 0 ? void 0 : _b.focus();
1222
1227
  }
1223
1228
  setItemFocus();
1224
1229
  }
@@ -1276,10 +1281,7 @@ var MenuList = function (_a) {
1276
1281
  return (jsxs("ul", __assign({ role: "menu", "aria-label": ariaLabel }, mergeProps({ onKeyDown: onKeyDown, onAnimationEnd: onAnimationEnd }, restProps), commonProps(isDisabled), { ref: useCombinedRef(externalRef, menuRef), className: useBEM({ block: menuClass, modifiers: modifiers, className: menuClassName }), style: __assign(__assign(__assign(__assign({}, menuStyle), overflowStyle), dontShrinkOps), { margin: 0, display: state === "closed" ? "none" : undefined, position: "absolute", left: menuPosition.x, top: menuPosition.y }) }, { children: [jsx("div", { ref: focusRef, tabIndex: -1, style: { position: "absolute", left: 0, top: 0 } }), arrow && (jsx("div", { className: _arrowClass, style: __assign(__assign({}, arrowStyle), { position: "absolute", left: arrowPosition.x, top: arrowPosition.y }), ref: arrowRef })), jsx(MenuListContext.Provider, __assign({ value: listContext }, { children: jsx(MenuListItemContext.Provider, __assign({ value: itemContext }, { children: jsx(HoverItemContext.Provider, __assign({ value: hoverItem }, { children: children })) })) }))] })));
1277
1282
  };
1278
1283
 
1279
- // Typed version of lodash !isEmpty
1280
- var isNotEmpty = function (obj) {
1281
- return !isEmpty(obj);
1282
- };
1284
+ var isNotEmpty = negate(isEmpty);
1283
1285
  var wait = function (timeoutMs) {
1284
1286
  return new Promise(function (resolve) {
1285
1287
  setTimeout(resolve, timeoutMs);
@@ -1290,15 +1292,16 @@ var isFloat = function (value) {
1290
1292
  return regexp.test(value);
1291
1293
  };
1292
1294
  var hasParentClass = function (className, child) {
1293
- var node = child;
1294
- while (node) {
1295
+ for (var node = child; node; node = node.parentNode) {
1295
1296
  // When nodes are in portals they aren't type node anymore hence treating it as any here
1296
1297
  if (node.classList && node.classList.contains(className)) {
1297
1298
  return true;
1298
1299
  }
1299
- node = node.parentNode;
1300
1300
  }
1301
1301
  return false;
1302
+ };
1303
+ var stringByteLengthIsInvalid = function (str, maxBytes) {
1304
+ return new TextEncoder().encode(str).length > maxBytes;
1302
1305
  };
1303
1306
 
1304
1307
  var EventHandlersContext = createContext({
@@ -1394,7 +1397,8 @@ var ControlledMenuFr = function (_a, externalRef) {
1394
1397
  if (activeElement !== firstInputEl && activeElement !== lastInputEl)
1395
1398
  return;
1396
1399
  var isTextArea = activeElement.nodeName === "TEXTAREA";
1397
- var suppressEnterAutoSave = activeElement.getAttribute("data-disableEnterAutoSave") || isTextArea;
1400
+ var suppressEnterAutoSave = activeElement.getAttribute("data-disableenterautoSave") || isTextArea;
1401
+ var allowTabToSave = activeElement.getAttribute("data-allowtabtoSave");
1398
1402
  var invokeSave = function (reason) {
1399
1403
  var _a, _b;
1400
1404
  if (!(saveButtonRef === null || saveButtonRef === void 0 ? void 0 : saveButtonRef.current))
@@ -1405,7 +1409,7 @@ var ControlledMenuFr = function (_a, externalRef) {
1405
1409
  switch (activeElement.nodeName) {
1406
1410
  case "TEXTAREA":
1407
1411
  case "INPUT": {
1408
- if (activeElement === lastInputEl && activeElement === firstInputEl) {
1412
+ if ((activeElement === lastInputEl && activeElement === firstInputEl) || allowTabToSave) {
1409
1413
  if (ev.key === "Tab") {
1410
1414
  // Can't forward/backwards tab out of popup
1411
1415
  ev.preventDefault();
@@ -2424,7 +2428,8 @@ var GridSubComponentContext = createContext({
2424
2428
  console.error("GridSubComponentContext triggerSave no context");
2425
2429
  return [2 /*return*/];
2426
2430
  });
2427
- }); }
2431
+ }); },
2432
+ context: null
2428
2433
  });
2429
2434
 
2430
2435
  function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t<e.length;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);else for(t in e)e[t]&&(n&&(n+=" "),n+=t);return n}function clsx(){for(var e,t,f=0,n="";f<arguments.length;)(e=arguments[f++])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
@@ -2822,11 +2827,11 @@ function styleInject(css, ref) {
2822
2827
  }
2823
2828
  }
2824
2829
 
2825
- var css_248z$7 = ".AgGridGenericCellRenderer-icon{margin-right:4px}.AgGridGenericCellRenderer-ic_infoIcon{fill:#3a7cdf;margin-right:4px}.AgGridGenericCellRenderer-ic_warningIcon{fill:#ea6a2e;margin-right:4px}";
2826
- styleInject(css_248z$7);
2830
+ var css_248z$8 = ".AgGridGenericCellRenderer-icon{margin-right:4px}.AgGridGenericCellRenderer-ic_infoIcon{fill:#3a7cdf;margin-right:4px}.AgGridGenericCellRenderer-ic_warningIcon{fill:#ea6a2e;margin-right:4px}";
2831
+ styleInject(css_248z$8);
2827
2832
 
2828
- var css_248z$6 = ".GridLoadableCell-container{align-items:center;display:flex}";
2829
- styleInject(css_248z$6);
2833
+ var css_248z$7 = ".GridLoadableCell-container{align-items:center;display:flex}";
2834
+ styleInject(css_248z$7);
2830
2835
 
2831
2836
  var GridLoadableCell = function (props) {
2832
2837
  if (props.isLoading) {
@@ -3000,11 +3005,11 @@ var GridRenderPopoutMenuCell = function (props) {
3000
3005
  return (jsx(GridLoadableCell, __assign({ isLoading: isLoading, className: disabled ? "GridPopoutMenu-burgerDisabled" : "GridPopoutMenu-burger" }, { children: jsx(LuiIcon, { name: "ic_more_vert", alt: "More actions", size: "md" }) })));
3001
3006
  };
3002
3007
 
3003
- var css_248z$5 = ".GridMultiSelect-containerSmall .GridFormMultiSelect-options{max-height:130px;overflow-y:auto}.GridMultiSelect-containerMedium .GridFormMultiSelect-options{max-height:190px;overflow-y:auto}.GridMultiSelect-containerLarge .GridFormMultiSelect-options{max-height:320px;overflow-y:auto}.GridMultiSelect-containerUnlimited .GridFormMultiSelect-options{overflow-y:auto}";
3004
- styleInject(css_248z$5);
3008
+ var css_248z$6 = ".GridMultiSelect-containerSmall .GridFormMultiSelect-options{max-height:130px;overflow-y:auto}.GridMultiSelect-containerMedium .GridFormMultiSelect-options{max-height:190px;overflow-y:auto}.GridMultiSelect-containerLarge .GridFormMultiSelect-options{max-height:320px;overflow-y:auto}.GridMultiSelect-containerUnlimited .GridFormMultiSelect-options{overflow-y:auto}";
3009
+ styleInject(css_248z$6);
3005
3010
 
3006
- var css_248z$4 = ".GridPopoverEditDropDown-containerSmall .GridFormDropDown-options{max-height:120px;overflow-y:auto}.GridPopoverEditDropDown-containerMedium .GridFormDropDown-options{max-height:220px;overflow-y:auto}.GridPopoverEditDropDown-containerLarge .GridFormDropDown-options{max-height:400px;overflow-y:auto}.GridPopoverEditDropDown-containerUnlimited .GridFormDropDown-options{overflow-y:auto}";
3007
- styleInject(css_248z$4);
3011
+ var css_248z$5 = ".GridPopoverEditDropDown-containerSmall .GridFormDropDown-options{max-height:120px;overflow-y:auto}.GridPopoverEditDropDown-containerMedium .GridFormDropDown-options{max-height:220px;overflow-y:auto}.GridPopoverEditDropDown-containerLarge .GridFormDropDown-options{max-height:400px;overflow-y:auto}.GridPopoverEditDropDown-containerUnlimited .GridFormDropDown-options{overflow-y:auto}";
3012
+ styleInject(css_248z$5);
3008
3013
 
3009
3014
  /* global setTimeout, clearTimeout */
3010
3015
 
@@ -3293,6 +3298,7 @@ var GridFormDropDown = function (props) {
3293
3298
  : CloseReason.CLICK).then();
3294
3299
  }
3295
3300
  } }, { 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 && selectedSubComponent === item && (jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (ref) { return (jsx(GridSubComponentContext.Provider, __assign({ value: {
3301
+ context: { options: options },
3296
3302
  data: data,
3297
3303
  value: subSelectedValue,
3298
3304
  setValue: function (value) {
@@ -3315,154 +3321,326 @@ var GridFormDropDown = function (props) {
3315
3321
  })] }) }))] }));
3316
3322
  };
3317
3323
 
3324
+ var css_248z$4 = ".helpText{color:#6b6966;font-size:.75rem;font-weight:400}";
3325
+ styleInject(css_248z$4);
3326
+
3327
+ var FormError = function (props) {
3328
+ return (jsxs(Fragment$1, { children: [props.error && (jsx("span", __assign({ className: "LuiTextInput-error", style: { paddingLeft: 0 } }, { children: props.error }))), props.helpText && !props.error && jsx("span", __assign({ className: "helpText" }, { children: props.helpText }))] }));
3329
+ };
3330
+
3331
+ function escapeStringRegexp(string) {
3332
+ if (typeof string !== 'string') {
3333
+ throw new TypeError('Expected a string');
3334
+ }
3335
+
3336
+ // Escape characters with special meaning either inside or outside character sets.
3337
+ // Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
3338
+ return string
3339
+ .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
3340
+ .replace(/-/g, '\\x2d');
3341
+ }
3342
+
3343
+ const regexpCache = new Map();
3344
+
3345
+ const sanitizeArray = (input, inputName) => {
3346
+ if (!Array.isArray(input)) {
3347
+ switch (typeof input) {
3348
+ case 'string':
3349
+ input = [input];
3350
+ break;
3351
+ case 'undefined':
3352
+ input = [];
3353
+ break;
3354
+ default:
3355
+ throw new TypeError(`Expected '${inputName}' to be a string or an array, but got a type of '${typeof input}'`);
3356
+ }
3357
+ }
3358
+
3359
+ return input.filter(string => {
3360
+ if (typeof string !== 'string') {
3361
+ if (typeof string === 'undefined') {
3362
+ return false;
3363
+ }
3364
+
3365
+ throw new TypeError(`Expected '${inputName}' to be an array of strings, but found a type of '${typeof string}' in the array`);
3366
+ }
3367
+
3368
+ return true;
3369
+ });
3370
+ };
3371
+
3372
+ const makeRegexp = (pattern, options) => {
3373
+ options = {
3374
+ caseSensitive: false,
3375
+ ...options,
3376
+ };
3377
+
3378
+ const cacheKey = pattern + JSON.stringify(options);
3379
+
3380
+ if (regexpCache.has(cacheKey)) {
3381
+ return regexpCache.get(cacheKey);
3382
+ }
3383
+
3384
+ const negated = pattern[0] === '!';
3385
+
3386
+ if (negated) {
3387
+ pattern = pattern.slice(1);
3388
+ }
3389
+
3390
+ pattern = escapeStringRegexp(pattern).replace(/\\\*/g, '[\\s\\S]*');
3391
+
3392
+ const regexp = new RegExp(`^${pattern}$`, options.caseSensitive ? '' : 'i');
3393
+ regexp.negated = negated;
3394
+ regexpCache.set(cacheKey, regexp);
3395
+
3396
+ return regexp;
3397
+ };
3398
+
3399
+ const baseMatcher = (inputs, patterns, options, firstMatchOnly) => {
3400
+ inputs = sanitizeArray(inputs, 'inputs');
3401
+ patterns = sanitizeArray(patterns, 'patterns');
3402
+
3403
+ if (patterns.length === 0) {
3404
+ return [];
3405
+ }
3406
+
3407
+ patterns = patterns.map(pattern => makeRegexp(pattern, options));
3408
+
3409
+ const {allPatterns} = options || {};
3410
+ const result = [];
3411
+
3412
+ for (const input of inputs) {
3413
+ // String is included only if it matches at least one non-negated pattern supplied.
3414
+ // Note: the `allPatterns` option requires every non-negated pattern to be matched once.
3415
+ // Matching a negated pattern excludes the string.
3416
+ let matches;
3417
+ const didFit = [...patterns].fill(false);
3418
+
3419
+ for (const [index, pattern] of patterns.entries()) {
3420
+ if (pattern.test(input)) {
3421
+ didFit[index] = true;
3422
+ matches = !pattern.negated;
3423
+
3424
+ if (!matches) {
3425
+ break;
3426
+ }
3427
+ }
3428
+ }
3429
+
3430
+ if (
3431
+ !(
3432
+ matches === false
3433
+ || (matches === undefined && patterns.some(pattern => !pattern.negated))
3434
+ || (allPatterns && didFit.some((yes, index) => !yes && !patterns[index].negated))
3435
+ )
3436
+ ) {
3437
+ result.push(input);
3438
+
3439
+ if (firstMatchOnly) {
3440
+ break;
3441
+ }
3442
+ }
3443
+ }
3444
+
3445
+ return result;
3446
+ };
3447
+
3448
+ function isMatch(inputs, patterns, options) {
3449
+ return baseMatcher(inputs, patterns, options, true).length > 0;
3450
+ }
3451
+
3452
+ /**
3453
+ * Text matching with wildcards and multiple matchers.
3454
+ *
3455
+ * "L" => L*
3456
+ * "L*" => L*
3457
+ * "*L*" => *L*
3458
+ * "*L" => *L
3459
+ * "A B" => A* and B*
3460
+ * "A B, C" => (A* and B*) or C*
3461
+ *
3462
+ * Returns ture if there's a text match.
3463
+ */
3464
+ var textMatch = function (text, filter) {
3465
+ if (text == null)
3466
+ return true;
3467
+ var superFilters = filter
3468
+ .split(",")
3469
+ .map(function (sf) { return sf.trim(); })
3470
+ .filter(function (sf) { return sf; });
3471
+ var values = text.replaceAll(",", " ").trim().split(/\s+/);
3472
+ return (isEmpty(superFilters) || // Not filtered
3473
+ superFilters.some(function (superFilter) {
3474
+ var subFilters = superFilter.split(/\s+/).map(function (s) { return s.replaceAll(/([!?])/g, "\\$1"); });
3475
+ return subFilters.every(function (subFilter) { return values.some(function (value) { return isMatch(value, subFilter); }); });
3476
+ }));
3477
+ };
3478
+
3318
3479
  var GridFormMultiSelect = function (props) {
3319
3480
  var _a = useGridPopoverContext(), selectedRows = _a.selectedRows, data = _a.data;
3320
- var initialiseValues = useMemo(function () {
3321
- var r = props.initialSelectedValues && props.initialSelectedValues(selectedRows);
3322
- // convert array of strings to object<value,null>
3323
- return Array.isArray(r) ? fromPairs(r.map(function (v) { return [v, null]; })) : r;
3324
- }, [props, selectedRows]);
3325
- var subComponentIsValid = useRef({});
3326
- var _b = useState(function () { return initialiseValues !== null && initialiseValues !== void 0 ? initialiseValues : {}; }), selectedValues = _b[0], setSelectedValues = _b[1];
3327
- var _c = useState(""), filter = _c[0], setFilter = _c[1];
3328
- var _d = useState([]), filteredValues = _d[0], setFilteredValues = _d[1];
3481
+ var subComponentIsValidRef = useRef({});
3329
3482
  var optionsInitialising = useRef(false);
3330
- var _e = useState(), options = _e[0], setOptions = _e[1];
3483
+ var _b = useState(""), filter = _b[0], setFilter = _b[1];
3484
+ var _c = useState(""), initialValues = _c[0], setInitialValues = _c[1];
3485
+ var _d = useState(), options = _d[0], setOptions = _d[1];
3331
3486
  var invalid = useCallback(function () {
3332
- var validations = pick(subComponentIsValid.current, Object.keys(selectedValues));
3333
- return Object.values(validations).some(function (v) { return !v; });
3334
- }, [selectedValues]);
3487
+ if (!options)
3488
+ return true;
3489
+ var selectedValues = options.filter(function (o) { return o.checked; }).map(function (o) { return o.value; });
3490
+ var subValidations = pick(subComponentIsValidRef.current, selectedValues);
3491
+ if (Object.values(subValidations).some(function (v) { return !v; }))
3492
+ return true;
3493
+ return (props.invalid &&
3494
+ props.invalid(selectedRows, options.filter(function (o) { return o.checked; })));
3495
+ }, [options, props, selectedRows]);
3335
3496
  var save = useCallback(function (selectedRows) { return __awaiter(void 0, void 0, void 0, function () {
3336
- var validations, notValid, menuOptionSubValueResult;
3337
3497
  return __generator(this, function (_a) {
3338
- switch (_a.label) {
3339
- case 0:
3340
- if (!props.onSave) return [3 /*break*/, 2];
3341
- if (!options) {
3342
- console.error("options not initialised");
3343
- return [2 /*return*/, false];
3344
- }
3345
- validations = pick(subComponentIsValid.current, Object.keys(selectedValues));
3346
- notValid = Object.values(validations).some(function (v) { return !v; });
3347
- if (notValid)
3348
- return [2 /*return*/, false];
3349
- menuOptionSubValueResult = toPairs(selectedValues).map(function (_a) {
3350
- var value = _a[0], subValue = _a[1];
3351
- var o = __assign({}, options.find(function (o) { return o.value == value; }));
3352
- o.subValue = subValue;
3353
- return o;
3354
- });
3355
- if (isEqual(initialiseValues, selectedValues)) {
3356
- // No changes to save
3357
- return [2 /*return*/, true];
3358
- }
3359
- return [4 /*yield*/, props.onSave(selectedRows, menuOptionSubValueResult)];
3360
- case 1: return [2 /*return*/, _a.sent()];
3361
- case 2: return [2 /*return*/, true];
3362
- }
3498
+ if (!options || !props.onSave)
3499
+ return [2 /*return*/, true];
3500
+ // Any changes to save?
3501
+ if (initialValues === JSON.stringify(options))
3502
+ return [2 /*return*/, true];
3503
+ return [2 /*return*/, props.onSave(selectedRows, options.filter(function (o) { return o.checked; }))];
3363
3504
  });
3364
- }); }, [initialiseValues, options, props, selectedValues]);
3505
+ }); }, [initialValues, options, props]);
3365
3506
  // Load up options list if it's async function
3366
3507
  useEffect(function () {
3367
- var _a;
3368
3508
  if (options || optionsInitialising.current)
3369
3509
  return;
3370
3510
  optionsInitialising.current = true;
3371
- var optionsConf = (_a = props.options) !== null && _a !== void 0 ? _a : [];
3372
3511
  (function () { return __awaiter(void 0, void 0, void 0, function () {
3373
- var optionsList;
3374
- return __generator(this, function (_a) {
3375
- switch (_a.label) {
3512
+ var optionsList, _a;
3513
+ return __generator(this, function (_b) {
3514
+ switch (_b.label) {
3376
3515
  case 0:
3377
- if (!(typeof optionsConf == "function")) return [3 /*break*/, 2];
3378
- return [4 /*yield*/, optionsConf(selectedRows)];
3516
+ if (!(typeof props.options === "function")) return [3 /*break*/, 2];
3517
+ return [4 /*yield*/, props.options(selectedRows)];
3379
3518
  case 1:
3380
- optionsConf = _a.sent();
3381
- _a.label = 2;
3519
+ _a = _b.sent();
3520
+ return [3 /*break*/, 3];
3382
3521
  case 2:
3383
- optionsList = optionsConf === null || optionsConf === void 0 ? void 0 : optionsConf.map(function (item) {
3384
- if (item == null || typeof item === "string" || typeof item === "number") {
3385
- item = { value: item, label: item };
3386
- }
3387
- return item;
3388
- });
3389
- if (props.filtered) {
3390
- // This is needed otherwise when filter input is rendered and sets autofocus
3391
- // the mouse up of the double click edit triggers the cell to cancel editing
3392
- delay(function () { return setOptions(optionsList); }, 100);
3393
- }
3394
- else {
3395
- setOptions(optionsList);
3396
- }
3522
+ _a = props.options;
3523
+ _b.label = 3;
3524
+ case 3:
3525
+ optionsList = _a;
3526
+ setInitialValues(JSON.stringify(optionsList));
3527
+ setOptions(optionsList);
3397
3528
  optionsInitialising.current = false;
3398
3529
  return [2 /*return*/];
3399
3530
  }
3400
3531
  });
3401
3532
  }); })();
3402
- }, [props.filtered, props.options, options, selectedRows]);
3403
- useEffect(function () {
3404
- if (!props.filtered || options == null)
3533
+ }, [options, props, selectedRows]);
3534
+ /**
3535
+ * Groups options into their header groups
3536
+ */
3537
+ var headerGroups = useMemo(function () {
3538
+ return options &&
3539
+ groupBy(options.filter(function (o) { return textMatch(o.label, filter) && o.value; }), "filter");
3540
+ }, [filter, options]);
3541
+ var headers = useMemo(function () { var _a; return (_a = props.headers) !== null && _a !== void 0 ? _a : [{ header: "" }]; }, [props.headers]);
3542
+ var _e = useGridPopoverHook({
3543
+ className: props.className,
3544
+ invalid: invalid,
3545
+ save: save
3546
+ }), popoverWrapper = _e.popoverWrapper, triggerSave = _e.triggerSave;
3547
+ return popoverWrapper(jsx(ComponentLoadingWrapper, __assign({ loading: !options, className: "GridFormMultiSelect-container" }, { children: options && (jsxs(Fragment$1, { children: [props.filtered && (jsx(FilterInput, __assign({}, { headerGroups: headerGroups, options: options, setOptions: setOptions, filter: filter, setFilter: setFilter }, { filterHelpText: props.filterHelpText, onSelectFilter: props.onSelectFilter, filterPlaceholder: props.filterPlaceholder }))), headerGroups && (jsx("div", __assign({ className: "GridFormMultiSelect-options" }, { children: headers.map(function (header) {
3548
+ var subOptions = headerGroups["".concat(header.filter)];
3549
+ return (!isEmpty(subOptions) && (jsxs(Fragment$1, { children: [header.header && jsx(MenuHeader, { children: header.header }), subOptions.map(function (item, index) {
3550
+ return item.value === MenuSeparatorString ? (jsx(MenuDivider, {}, "div_".concat(index))) : (jsxs(Fragment, { children: [jsx(MenuRadioItem, { item: item, options: options, setOptions: setOptions }), item.checked && item.subComponent && (jsx(MenuSubComponent, __assign({}, { item: item, options: options, setOptions: setOptions, data: data, triggerSave: triggerSave }, { subComponentIsValid: subComponentIsValidRef.current })))] }, "val_".concat(item.value)));
3551
+ })] })));
3552
+ }) })))] })) })));
3553
+ };
3554
+ var FilterInput = function (props) {
3555
+ var options = props.options, setOptions = props.setOptions, onSelectFilter = props.onSelectFilter, filter = props.filter, setFilter = props.setFilter, headerGroups = props.headerGroups, filterPlaceholder = props.filterPlaceholder, filterHelpText = props.filterHelpText;
3556
+ var toggleSelectAllVisible = useCallback(function () {
3557
+ if (!options || !headerGroups)
3405
3558
  return;
3406
- setFilteredValues(options
3407
- .map(function (option) {
3408
- if (option.label != null && typeof option.label !== "string") {
3409
- console.error("Cannot filter non-string labels", option);
3410
- return undefined;
3411
- }
3412
- var str = option.label || "";
3413
- return str.toLowerCase().indexOf(filter.trim()) === -1 ? option.value : undefined;
3414
- })
3415
- .filter(function (r) { return r !== undefined; }));
3416
- }, [props.filtered, filter, options]);
3417
- var toggleValue = useCallback(function (item) {
3418
- var _a;
3419
- if ("".concat(item.value) in selectedValues) {
3420
- setSelectedValues(omit(selectedValues, ["".concat(item.value)]));
3559
+ if (isEmpty(filter.trim())) {
3560
+ // Toggle off if any items are checked otherwise on
3561
+ var anyChecked_1 = options.some(function (o) { return o.checked; });
3562
+ options.forEach(function (o) { return (o.checked = !anyChecked_1); });
3421
3563
  }
3422
3564
  else {
3423
- setSelectedValues(__assign(__assign({}, selectedValues), (_a = {}, _a["".concat(item.value)] = null, _a)));
3565
+ // Toggle on if any filtered items are checked otherwise off
3566
+ var anyChecked_2 = Object.values(headerGroups).some(function (headerOptions) {
3567
+ return headerOptions.some(function (o) { return o.checked === false; });
3568
+ });
3569
+ Object.values(headerGroups).forEach(function (headerOptions) {
3570
+ headerOptions.forEach(function (o) {
3571
+ if (o.checked !== undefined)
3572
+ o.checked = anyChecked_2;
3573
+ });
3574
+ });
3424
3575
  }
3425
- }, [selectedValues]);
3426
- var _f = useGridPopoverHook({
3427
- className: props.className,
3428
- invalid: invalid,
3429
- save: save
3430
- }), popoverWrapper = _f.popoverWrapper, triggerSave = _f.triggerSave;
3431
- return popoverWrapper(jsx(ComponentLoadingWrapper, __assign({ loading: !options, className: "GridFormMultiSelect-container" }, { children: jsxs(Fragment$1, { children: [options && props.filtered && (jsxs(Fragment$1, { children: [jsx(FocusableItem, __assign({ className: "filter-item" }, { children: function (_a) {
3432
- var _b;
3433
- var ref = _a.ref;
3434
- return (jsx("div", __assign({ style: { display: "flex", width: "100%" }, className: "GridFormMultiSelect-filter" }, { children: jsx("input", { autoFocus: true, className: "free-text-input", style: { border: "0px" }, ref: ref, type: "text", placeholder: (_b = props.filterPlaceholder) !== null && _b !== void 0 ? _b : "Placeholder", "data-testid": "filteredMenu-free-text-input", defaultValue: "", onChange: function (e) { return setFilter(e.target.value.toLowerCase()); } }) })));
3435
- } }), "filter"), jsx(MenuDivider, {}, "$$divider_filter")] })), jsx("div", __assign({ className: "GridFormMultiSelect-options" }, { children: options === null || options === void 0 ? void 0 : options.map(function (item, index) {
3436
- var _a;
3437
- return item.value === MenuSeparatorString ? (jsx(MenuDivider, {}, "$$divider_".concat(index))) : filteredValues.includes(item.value) ? null : (jsxs("div", { children: [jsx(MenuItem, __assign({ onClick: function (e) {
3438
- // Global react-menu MenuItem handler handles tabs
3439
- if (e.key !== "Tab") {
3440
- e.keepOpen = true;
3441
- toggleValue(item);
3442
- }
3443
- } }, { children: jsx(LuiCheckboxInput, { isChecked: "".concat(item.value) in selectedValues, value: "".concat(item.value), label: (_a = item.label) !== null && _a !== void 0 ? _a : (item.value == null ? "<".concat(item.value, ">") : "".concat(item.value)), inputProps: {
3444
- onClick: function (e) {
3445
- e.preventDefault();
3446
- e.stopPropagation();
3447
- return false;
3448
- }
3449
- }, onChange: function () {
3450
- /*Do nothing, change handled by menuItem*/
3451
- } }) })), "".concat(item.value) in selectedValues && item.subComponent && (jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (_) {
3452
- return item.subComponent && (jsx(GridSubComponentContext.Provider, __assign({ value: {
3453
- data: data,
3454
- value: selectedValues["".concat(item.value)],
3455
- setValue: function (value) {
3456
- var _a;
3457
- setSelectedValues(__assign(__assign({}, selectedValues), (_a = {}, _a["".concat(item.value)] = value, _a)));
3458
- },
3459
- setValid: function (valid) {
3460
- subComponentIsValid.current["".concat(item.value)] = valid;
3461
- },
3462
- triggerSave: triggerSave
3463
- } }, { children: jsx(item.subComponent, {}) })));
3464
- } }), "".concat(item.value, "_subcomponent")))] }, "".concat(index)));
3465
- }) }))] }) })));
3576
+ setOptions(__spreadArray([], options, true));
3577
+ }, [filter, headerGroups, options, setOptions]);
3578
+ var addCustomFilterValue = useCallback(function () {
3579
+ if (!options || !onSelectFilter)
3580
+ return;
3581
+ var preFilterOptions = JSON.stringify(options);
3582
+ onSelectFilter(filter.trim(), options);
3583
+ // Detect if options list changed and update
3584
+ if (preFilterOptions === JSON.stringify(options))
3585
+ return;
3586
+ setOptions(__spreadArray([], options, true));
3587
+ setFilter("");
3588
+ }, [filter, onSelectFilter, options, setFilter, setOptions]);
3589
+ var handleKeyUp = useCallback(function (e) {
3590
+ if (e.key === "Enter") {
3591
+ e.stopPropagation();
3592
+ e.preventDefault();
3593
+ if (e.ctrlKey)
3594
+ toggleSelectAllVisible();
3595
+ else if (onSelectFilter)
3596
+ addCustomFilterValue();
3597
+ }
3598
+ }, [addCustomFilterValue, onSelectFilter, toggleSelectAllVisible]);
3599
+ return (jsxs(Fragment$1, { children: [jsx(FocusableItem, __assign({ className: "filter-item" }, { children: function (_) { return (jsxs("div", __assign({ style: { width: "100%" }, className: "GridFormMultiSelect-filter" }, { children: [jsx("input", { className: "LuiTextInput-input", type: "text", placeholder: filterPlaceholder !== null && filterPlaceholder !== void 0 ? filterPlaceholder : "Placeholder", "data-testid": "filteredMenu-free-text-input", value: filter, "data-disableenterautosave": true, "data-allowtabtoSave": true, onChange: function (e) { return setFilter(e.target.value); }, onKeyUp: handleKeyUp }), filterHelpText && (jsx(FormError, { error: null, helpText: typeof filterHelpText === "function" ? filterHelpText(filter.trim(), options) : filterHelpText }))] }))); } }), "filter"), jsx(MenuDivider, {}, "$$divider_filter"), headerGroups && !toPairs(headerGroups).some(function (_a) {
3600
+ _a[0]; var options = _a[1];
3601
+ return !isEmpty(options);
3602
+ }) && (jsx("div", __assign({ className: "szh-menu__item" }, { children: "[No items match the filter]" })))] }));
3603
+ };
3604
+ var MenuRadioItem = function (props) {
3605
+ var _a, _b;
3606
+ var item = props.item, options = props.options, setOptions = props.setOptions;
3607
+ var toggleValue = useCallback(function (item) {
3608
+ item.checked = !item.checked;
3609
+ setOptions(__spreadArray([], options, true));
3610
+ }, [options, setOptions]);
3611
+ return (jsx(MenuItem, __assign({ onClick: function (e) {
3612
+ // Global react-menu MenuItem handler handles tabs
3613
+ if (e.key !== "Tab") {
3614
+ e.keepOpen = true;
3615
+ toggleValue(item);
3616
+ }
3617
+ } }, { children: jsx(LuiCheckboxInput, { isChecked: (_a = item.checked) !== null && _a !== void 0 ? _a : false, value: "".concat(item.value), label: (_b = item.label) !== null && _b !== void 0 ? _b : (item.value == null ? "<".concat(item.value, ">") : "".concat(item.value)), inputProps: {
3618
+ onClick: function (e) {
3619
+ // Click is handled by MenuItem onClick
3620
+ e.preventDefault();
3621
+ e.stopPropagation();
3622
+ }
3623
+ }, onChange: function () {
3624
+ /*Do nothing, change handled by menuItem*/
3625
+ } }) })));
3626
+ };
3627
+ var MenuSubComponent = function (props) {
3628
+ var data = props.data, item = props.item, options = props.options, setOptions = props.setOptions, subComponentIsValid = props.subComponentIsValid, triggerSave = props.triggerSave;
3629
+ return (jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (_) {
3630
+ return item.subComponent && (jsx(GridSubComponentContext.Provider, __assign({ value: {
3631
+ context: { options: options },
3632
+ data: data,
3633
+ value: item.subValue,
3634
+ setValue: function (value) {
3635
+ item.subValue = value;
3636
+ setOptions(__spreadArray([], options, true));
3637
+ },
3638
+ setValid: function (valid) {
3639
+ subComponentIsValid["".concat(item.value)] = valid;
3640
+ },
3641
+ triggerSave: triggerSave
3642
+ } }, { children: jsx(item.subComponent, {}) })));
3643
+ } }), "".concat(item.value, "_subcomponent")));
3466
3644
  };
3467
3645
 
3468
3646
  var GridPopoutEditMultiSelect = function (colDef, props) {
@@ -3597,6 +3775,7 @@ var GridFormPopoverMenu = function (props) {
3597
3775
  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) {
3598
3776
  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 (_) {
3599
3777
  return item.subComponent && (jsx(GridSubComponentContext.Provider, __assign({ value: {
3778
+ context: {},
3600
3779
  data: data,
3601
3780
  value: subSelectedValue,
3602
3781
  setValue: function (value) {
@@ -3705,12 +3884,6 @@ styleInject(css_248z$2);
3705
3884
  var css_248z$1 = ".LuiTextInput{margin-bottom:0}.LuiTextInput-formatted{color:#beb9b4;line-height:48px;position:absolute;right:14px;top:0}";
3706
3885
  styleInject(css_248z$1);
3707
3886
 
3708
- var FormError = function (props) {
3709
- return (jsxs(Fragment$1, { children: [props.error && (jsxs("span", __assign({ className: "LuiTextInput-error" }, { children: [jsx(LuiIcon, { alt: "error", name: "ic_error", className: "LuiTextInput-error-icon", size: "sm", status: "error" }), props.error] }))), props.helpText && !props.error && (jsx("span", __assign({ style: {
3710
- fontSize: "0.7rem"
3711
- } }, { children: props.helpText })))] }));
3712
- };
3713
-
3714
3887
  var TextInputFormatted = function (props) {
3715
3888
  return (jsxs("div", __assign({ className: clsx("LuiTextInput Grid-popoverContainer", props.error && "hasError", props.className) }, { children: [jsxs("span", __assign({ className: "LuiTextInput-inputWrapper" }, { children: [jsx("input", __assign({ type: "text", spellCheck: true, defaultValue: props.value }, omit(props, ["error", "value", "helpText", "formatted", "className"]), { className: "LuiTextInput-input", onMouseEnter: function (e) {
3716
3889
  e.currentTarget.focus();
@@ -3906,12 +4079,13 @@ var TextAreaInput = function (props) {
3906
4079
  } }, { children: props.value })) }))] })), jsx(FormError, { error: props.error, helpText: props.helpText })] })));
3907
4080
  };
3908
4081
 
3909
- var TextInputValidator = function (props, value, data) {
4082
+ var TextInputValidator = function (props, value, data, context) {
3910
4083
  if (value == null)
3911
4084
  return null;
3912
4085
  // This can happen because subcomponent is invoked without type safety
3913
4086
  if (typeof value !== "string") {
3914
4087
  console.error("Value is not a string", value);
4088
+ return null;
3915
4089
  }
3916
4090
  if (props.required && value.length === 0) {
3917
4091
  return "Some text is required";
@@ -3919,11 +4093,11 @@ var TextInputValidator = function (props, value, data) {
3919
4093
  if (props.maxLength && value.length > props.maxLength) {
3920
4094
  return "Text must be no longer than ".concat(props.maxLength, " characters");
3921
4095
  }
3922
- if (props.maxBytes && new TextEncoder().encode(value).length > props.maxBytes) {
4096
+ if (props.maxBytes && stringByteLengthIsInvalid(value, props.maxBytes)) {
3923
4097
  return "Text must be no longer than ".concat(props.maxLength, " bytes");
3924
4098
  }
3925
4099
  if (props.invalid) {
3926
- return props.invalid(value, data);
4100
+ return props.invalid(value, data, context);
3927
4101
  }
3928
4102
  return null;
3929
4103
  };
@@ -3931,30 +4105,30 @@ var TextInputValidator = function (props, value, data) {
3931
4105
  var GridFormTextArea = function (props) {
3932
4106
  var _a, _b;
3933
4107
  var _c = useGridPopoverContext(), field = _c.field, initialVale = _c.value, data = _c.data;
3934
- var _d = useState(initialVale != null ? "".concat(initialVale) : ""), value = _d[0], setValue = _d[1];
4108
+ var initValue = useMemo(function () { return (initialVale == null ? "" : "".concat(initialVale)); }, [initialVale]);
4109
+ var _d = useState(initValue), value = _d[0], setValue = _d[1];
3935
4110
  var helpText = (_a = props.helpText) !== null && _a !== void 0 ? _a : "Press tab to save";
3936
- var invalid = useCallback(function () { return TextInputValidator(props, value, data); }, [props, value, data]);
4111
+ var invalid = useCallback(function () { return TextInputValidator(props, value, data, {}); }, [props, value, data]);
3937
4112
  var save = useCallback(function (selectedRows) { return __awaiter(void 0, void 0, void 0, function () {
4113
+ var trimmedValue;
3938
4114
  return __generator(this, function (_a) {
3939
4115
  switch (_a.label) {
3940
4116
  case 0:
3941
- if (initialVale === (value !== null && value !== void 0 ? value : ""))
4117
+ if (invalid())
4118
+ return [2 /*return*/, false];
4119
+ trimmedValue = value.trim();
4120
+ // No change, so don't save
4121
+ if (initValue === trimmedValue)
3942
4122
  return [2 /*return*/, true];
3943
4123
  if (!props.onSave) return [3 /*break*/, 2];
3944
- return [4 /*yield*/, props.onSave(selectedRows, value)];
4124
+ return [4 /*yield*/, props.onSave(selectedRows, trimmedValue)];
3945
4125
  case 1: return [2 /*return*/, _a.sent()];
3946
4126
  case 2:
3947
- if (field == null) {
3948
- console.error("ColDef has no field set");
3949
- return [2 /*return*/, false];
3950
- }
3951
- selectedRows.forEach(function (row) {
3952
- row[field] = value;
3953
- });
4127
+ selectedRows.forEach(function (row) { return (row[field] = trimmedValue); });
3954
4128
  return [2 /*return*/, true];
3955
4129
  }
3956
4130
  });
3957
- }); }, [initialVale, value, props, field]);
4131
+ }); }, [invalid, value, initValue, props, field]);
3958
4132
  var popoverWrapper = useGridPopoverHook({
3959
4133
  className: props.className,
3960
4134
  invalid: invalid,
@@ -3971,7 +4145,7 @@ var GridFormTextInput = function (props) {
3971
4145
  var helpText = (_a = props.helpText) !== null && _a !== void 0 ? _a : "Press enter or tab to save";
3972
4146
  var initValue = useMemo(function () { return (initialVale == null ? "" : "".concat(initialVale)); }, [initialVale]);
3973
4147
  var _d = useState(initValue), value = _d[0], setValue = _d[1];
3974
- var invalid = useCallback(function () { return TextInputValidator(props, value, data); }, [data, props, value]);
4148
+ var invalid = useCallback(function () { return TextInputValidator(props, value, data, {}); }, [data, props, value]);
3975
4149
  var save = useCallback(function (selectedRows) { return __awaiter(void 0, void 0, void 0, function () {
3976
4150
  var trimmedValue;
3977
4151
  return __generator(this, function (_a) {
@@ -3980,19 +4154,14 @@ var GridFormTextInput = function (props) {
3980
4154
  if (invalid())
3981
4155
  return [2 /*return*/, false];
3982
4156
  trimmedValue = value.trim();
4157
+ // No change, so don't save
3983
4158
  if (initValue === trimmedValue)
3984
4159
  return [2 /*return*/, true];
3985
4160
  if (!props.onSave) return [3 /*break*/, 2];
3986
4161
  return [4 /*yield*/, props.onSave(selectedRows, trimmedValue)];
3987
4162
  case 1: return [2 /*return*/, _a.sent()];
3988
4163
  case 2:
3989
- if (field == null) {
3990
- console.error("ColDef has no field set");
3991
- return [2 /*return*/, false];
3992
- }
3993
- selectedRows.forEach(function (row) {
3994
- row[field] = trimmedValue;
3995
- });
4164
+ selectedRows.forEach(function (row) { return (row[field] = trimmedValue); });
3996
4165
  return [2 /*return*/, true];
3997
4166
  }
3998
4167
  });
@@ -4011,32 +4180,30 @@ var GridPopoverTextInput = function (colDef, params) {
4011
4180
 
4012
4181
  var GridFormSubComponentTextInput = function (props) {
4013
4182
  var _a;
4014
- var _b = useContext(GridSubComponentContext), value = _b.value, setValue = _b.setValue, setValid = _b.setValid, data = _b.data;
4183
+ var _b = useContext(GridSubComponentContext), value = _b.value, setValue = _b.setValue, setValid = _b.setValid, data = _b.data, context = _b.context;
4015
4184
  var helpText = (_a = props.helpText) !== null && _a !== void 0 ? _a : "Press enter or tab to save";
4016
4185
  // If is not initialised yet as it's just been created then set the default value
4017
4186
  useEffect(function () {
4018
4187
  if (value == null)
4019
4188
  setValue(props.defaultValue);
4020
4189
  }, [props.defaultValue, setValue, value]);
4021
- var invalid = useCallback(function () { return TextInputValidator(props, value, data); }, [data, props, value]);
4190
+ var invalid = useCallback(function () { return TextInputValidator(props, value, data, context); }, [context, data, props, value]);
4022
4191
  useEffect(function () {
4023
4192
  setValid(value != null && invalid() == null);
4024
4193
  }, [setValid, invalid, value]);
4025
- return (jsx(TextInputFormatted, { value: value, error: invalid(), onChange: function (e) { return setValue(e.target.value); }, helpText: helpText, autoFocus: true, placeholder: props.placeholder, style: {
4026
- width: "100%"
4027
- } }));
4194
+ return (jsx(TextInputFormatted, { value: value, error: invalid(), onChange: function (e) { return setValue(e.target.value); }, helpText: helpText, autoFocus: true, placeholder: props.placeholder, style: { width: "100%" } }));
4028
4195
  };
4029
4196
 
4030
4197
  var GridFormSubComponentTextArea = function (props) {
4031
4198
  var _a;
4032
- var _b = useContext(GridSubComponentContext), value = _b.value, data = _b.data, setValue = _b.setValue, setValid = _b.setValid;
4199
+ var _b = useContext(GridSubComponentContext), value = _b.value, data = _b.data, setValue = _b.setValue, setValid = _b.setValid, context = _b.context;
4033
4200
  var helpText = (_a = props.helpText) !== null && _a !== void 0 ? _a : "Press tab to save";
4034
4201
  // If is not initialised yet as it's just been created then set the default value
4035
4202
  useEffect(function () {
4036
4203
  if (value == null)
4037
4204
  setValue(props.defaultValue);
4038
4205
  }, [props.defaultValue, setValue, value]);
4039
- var invalid = useCallback(function () { return TextInputValidator(props, value, data); }, [data, props, value]);
4206
+ var invalid = useCallback(function () { return TextInputValidator(props, value, data, context); }, [data, props, value, context]);
4040
4207
  useEffect(function () {
4041
4208
  setValid(value != null && invalid() == null);
4042
4209
  }, [setValid, invalid, value]);
@@ -4116,16 +4283,17 @@ var useStateDeferred = function (initialValue) {
4116
4283
  var minimumInProgressTimeMs = 950;
4117
4284
  var ActionButton = function (_a) {
4118
4285
  var _b, _c, _d;
4119
- var icon = _a.icon, name = _a.name, inProgressName = _a.inProgressName, dataTestId = _a.dataTestId, className = _a.className, title = _a.title, onAction = _a.onAction, externalSetInProgress = _a.externalSetInProgress, _e = _a.size, size = _e === void 0 ? "sm" : _e, _f = _a.level, level = _f === void 0 ? "tertiary" : _f, ariaLabel = _a["aria-label"];
4120
- var _g = useState(false), inProgress = _g[0], setInProgress = _g[1];
4286
+ var icon = _a.icon, name = _a.name, inProgressName = _a.inProgressName, dataTestId = _a.dataTestId, className = _a.className, title = _a.title, onAction = _a.onAction, externalSetInProgress = _a.externalSetInProgress, _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"];
4287
+ var _h = useState(false), inProgress = _h[0], setInProgress = _h[1];
4121
4288
  var lastInProgress = usePrevious(inProgress !== null && inProgress !== void 0 ? inProgress : false);
4122
- var _h = useStateDeferred(inProgress), localInProgress = _h[0], setLocalInProgress = _h[1], setLocalInProgressDeferred = _h[2];
4289
+ var _j = useStateDeferred(inProgress), localInProgress = _j[0], setLocalInProgress = _j[1], setLocalInProgressDeferred = _j[2];
4123
4290
  useEffect(function () {
4124
4291
  if (inProgress == lastInProgress)
4125
4292
  return;
4126
4293
  inProgress ? setLocalInProgress(true) : setLocalInProgressDeferred(false, minimumInProgressTimeMs);
4127
4294
  }, [inProgress, lastInProgress, setLocalInProgress, setLocalInProgressDeferred]);
4128
- return (jsxs(LuiButton, __assign({ "data-testid": dataTestId, type: "button", level: level, title: (_b = title !== null && title !== void 0 ? title : ariaLabel) !== null && _b !== void 0 ? _b : name, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : name, className: clsx("lui-button-icon", "ActionButton", className, localInProgress && "ActionButton-inProgress"), size: "lg", style: name == null ? { padding: "8px 5px" } : {}, onClick: function () { return __awaiter(void 0, void 0, void 0, function () {
4295
+ var buttonText = (jsxs("span", __assign({ className: "ActionButton-minimalArea" }, { children: [jsx("span", __assign({ className: "ActionButton-minimalAreaDisplay" }, { children: (_b = (localInProgress ? inProgressName : name)) !== null && _b !== void 0 ? _b : name })), jsx("span", __assign({ className: "ActionButton-minimalAreaExpand" }, { children: name }))] })));
4296
+ return (jsxs(LuiButton, __assign({ "data-testid": dataTestId, type: "button", level: level, title: (_c = title !== null && title !== void 0 ? title : ariaLabel) !== null && _c !== void 0 ? _c : name, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : name, className: clsx("lui-button-icon-right", "ActionButton", className, localInProgress && "ActionButton-inProgress"), size: "lg", style: name == null ? { padding: "8px 5px" } : {}, onClick: function () { return __awaiter(void 0, void 0, void 0, function () {
4129
4297
  var promise, isPromise;
4130
4298
  return __generator(this, function (_a) {
4131
4299
  switch (_a.label) {
@@ -4147,13 +4315,19 @@ var ActionButton = function (_a) {
4147
4315
  case 3: return [2 /*return*/];
4148
4316
  }
4149
4317
  });
4150
- }); }, disabled: localInProgress }, { children: [localInProgress ? (jsx(LuiMiniSpinner, { size: 16, divProps: {
4318
+ }); }, disabled: localInProgress }, { children: [iconPosition === "right" && buttonText, localInProgress ? (jsx(LuiMiniSpinner, { size: 16, divProps: {
4151
4319
  "data-testid": "loading-spinner",
4152
- style: { margin: 0, paddingRight: 5, paddingLeft: 3, paddingBottom: 0, paddingTop: 0 },
4320
+ style: {
4321
+ margin: 0,
4322
+ paddingRight: 5,
4323
+ paddingLeft: 3,
4324
+ paddingBottom: 0,
4325
+ paddingTop: 0
4326
+ },
4153
4327
  role: "status",
4154
4328
  "aria-label": "Loading"
4155
- } })) : (jsx(LuiIcon, { name: icon, alt: (_c = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : name) !== null && _c !== void 0 ? _c : "", size: size })), jsxs("span", __assign({ className: "ActionButton-minimalArea" }, { children: [jsx("span", __assign({ className: "ActionButton-minimalAreaDisplay" }, { children: (_d = (localInProgress ? inProgressName : name)) !== null && _d !== void 0 ? _d : name })), jsx("span", __assign({ className: "ActionButton-minimalAreaExpand" }, { children: name }))] }))] })));
4329
+ } })) : (jsx(LuiIcon, { name: icon, alt: (_d = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : name) !== null && _d !== void 0 ? _d : "", size: size, spanProps: { style: iconPosition === "right" ? { transform: "scaleX(-1)" } : {} } })), iconPosition === "left" && buttonText] })));
4156
4330
  };
4157
4331
 
4158
- export { ActionButton, ComponentLoadingWrapper, ControlledMenu, FocusableItem, GenericCellEditorComponentWrapper, GenericMultiEditCellClass, Grid, GridCell, GridCellRenderer, GridContext, GridContextProvider, GridFormDropDown, GridFormMultiSelect, GridFormPopoverMenu, GridFormSubComponentTextArea, GridFormSubComponentTextInput, GridHeaderSelect, GridIcon, GridLoadableCell, GridPopoutEditMultiSelect, GridPopoverContext, GridPopoverContextProvider, GridPopoverEditBearing, GridPopoverEditBearingCorrection, GridPopoverEditDropDown, GridPopoverMenu, GridPopoverMessage, GridPopoverTextArea, GridPopoverTextInput, GridRenderPopoutMenuCell, GridRendererGenericCell, GridSubComponentContext, GridUpdatingContext, GridUpdatingContextProvider, Menu, MenuButton, MenuDivider, MenuGroup, MenuHeader, MenuHeaderItem, MenuHeaderString, MenuItem, MenuRadioGroup, MenuSeparator, MenuSeparatorString, PopoutMenuSeparator, SubMenu, TextAreaInput, TextInputFormatted, bearingCorrectionValueFormatter, bearingNumberParser, bearingStringValidator, bearingValueFormatter, convertDDToDMS, hasParentClass, isFloat, isNotEmpty, useGridPopoverContext, useGridPopoverHook, useMenuState, usePostSortRowsHook, wait };
4332
+ export { ActionButton, ComponentLoadingWrapper, ControlledMenu, FocusableItem, GenericCellEditorComponentWrapper, GenericMultiEditCellClass, Grid, GridCell, GridCellRenderer, GridContext, GridContextProvider, GridFormDropDown, GridFormMultiSelect, GridFormPopoverMenu, GridFormSubComponentTextArea, GridFormSubComponentTextInput, GridHeaderSelect, GridIcon, GridLoadableCell, GridPopoutEditMultiSelect, GridPopoverContext, GridPopoverContextProvider, GridPopoverEditBearing, GridPopoverEditBearingCorrection, GridPopoverEditDropDown, GridPopoverMenu, GridPopoverMessage, GridPopoverTextArea, GridPopoverTextInput, GridRenderPopoutMenuCell, GridRendererGenericCell, GridSubComponentContext, GridUpdatingContext, GridUpdatingContextProvider, Menu, MenuButton, MenuDivider, MenuGroup, MenuHeader, MenuHeaderItem, MenuHeaderString, MenuItem, MenuRadioGroup, MenuSeparator, MenuSeparatorString, PopoutMenuSeparator, SubMenu, TextAreaInput, TextInputFormatted, bearingCorrectionValueFormatter, bearingNumberParser, bearingStringValidator, bearingValueFormatter, convertDDToDMS, hasParentClass, isFloat, isNotEmpty, stringByteLengthIsInvalid, useGridPopoverContext, useGridPopoverHook, useMenuState, usePostSortRowsHook, wait };
4159
4333
  //# sourceMappingURL=step-ag-grid.esm.js.map