@linzjs/step-ag-grid 4.0.2 → 5.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 (49) hide show
  1. package/dist/index.js +325 -265
  2. package/dist/index.js.map +1 -1
  3. package/dist/src/components/GridPopoverHook.d.ts +2 -13
  4. package/dist/src/components/gridForm/GridFormDropDown.d.ts +1 -1
  5. package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +1 -1
  6. package/dist/src/components/gridForm/GridFormPopoverMenu.d.ts +0 -1
  7. package/dist/src/contexts/GridContext.d.ts +1 -0
  8. package/dist/src/contexts/GridPopoverContext.d.ts +1 -1
  9. package/dist/src/contexts/GridUpdatingContext.d.ts +3 -2
  10. package/dist/src/contexts/GridUpdatingContextProvider.d.ts +1 -1
  11. package/dist/src/lui/FormError.d.ts +6 -0
  12. package/dist/src/react-menu3/components/MenuItem.d.ts +1 -1
  13. package/dist/src/react-menu3/components/SubMenu.d.ts +1 -1
  14. package/dist/src/react-menu3/hooks/useBEM.d.ts +1 -1
  15. package/dist/src/react-menu3/types.d.ts +18 -17
  16. package/dist/src/react-menu3/utils/constants.d.ts +4 -0
  17. package/dist/src/react-menu3/utils/utils.d.ts +1 -1
  18. package/dist/step-ag-grid.esm.js +326 -266
  19. package/dist/step-ag-grid.esm.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/GridPopoverHook.tsx +30 -79
  22. package/src/components/gridForm/GridFormDropDown.tsx +62 -46
  23. package/src/components/gridForm/GridFormEditBearing.tsx +16 -8
  24. package/src/components/gridForm/GridFormMultiSelect.tsx +12 -4
  25. package/src/components/gridForm/GridFormPopoverMenu.tsx +25 -22
  26. package/src/components/gridForm/GridFormSubComponentTextArea.tsx +1 -14
  27. package/src/components/gridForm/GridFormSubComponentTextInput.tsx +1 -18
  28. package/src/components/gridForm/GridFormTextArea.tsx +8 -5
  29. package/src/components/gridForm/GridFormTextInput.tsx +8 -4
  30. package/src/contexts/GridContext.tsx +4 -0
  31. package/src/contexts/GridContextProvider.tsx +8 -0
  32. package/src/contexts/GridPopoverContext.tsx +1 -1
  33. package/src/contexts/GridPopoverContextProvider.tsx +7 -4
  34. package/src/contexts/GridUpdatingContext.tsx +7 -1
  35. package/src/contexts/GridUpdatingContextProvider.tsx +17 -6
  36. package/src/lui/FormError.tsx +29 -0
  37. package/src/lui/TextAreaInput.tsx +2 -18
  38. package/src/lui/TextInputFormatted.tsx +2 -17
  39. package/src/react-menu3/components/ControlledMenu.tsx +114 -12
  40. package/src/react-menu3/components/MenuItem.tsx +19 -2
  41. package/src/react-menu3/types.ts +2 -0
  42. package/src/react-menu3/utils/constants.ts +4 -0
  43. package/src/stories/grid/FormTest.tsx +24 -21
  44. package/src/stories/grid/GridPopoutBearing.stories.tsx +3 -2
  45. package/src/stories/grid/GridPopoutEditDropDown.stories.tsx +10 -0
  46. package/src/stories/grid/GridPopoutEditMultiSelect.stories.tsx +1 -1
  47. package/src/stories/grid/GridReadOnly.stories.tsx +11 -11
  48. package/src/styles/GridFormDropDown.scss +1 -1
  49. package/src/utils/bearing.ts +1 -1
package/dist/index.js CHANGED
@@ -71,6 +71,7 @@ var subMenuClass = "submenu";
71
71
  var radioGroupClass = "radio-group";
72
72
  var Keys = Object.freeze({
73
73
  ENTER: "Enter",
74
+ TAB: "Tab",
74
75
  ESC: "Escape",
75
76
  SPACE: " ",
76
77
  HOME: "Home",
@@ -94,7 +95,9 @@ var CloseReason = Object.freeze({
94
95
  CLICK: "click",
95
96
  CANCEL: "cancel",
96
97
  BLUR: "blur",
97
- SCROLL: "scroll"
98
+ SCROLL: "scroll",
99
+ TAB_FORWARD: "tab_forward",
100
+ TAB_BACKWARD: "tab_backward"
98
101
  });
99
102
  var FocusPositions = Object.freeze({
100
103
  FIRST: "first",
@@ -1366,14 +1369,120 @@ var ControlledMenuFr = function (_a, externalRef) {
1366
1369
  ev.stopPropagation();
1367
1370
  }
1368
1371
  }, [isWithinMenu]);
1372
+ var lastTabDownEl = react.useRef();
1373
+ var lastEnterDownEl = react.useRef();
1374
+ var handleKeyboardTabAndEnter = react.useCallback(function (isDown) { return function (ev) {
1375
+ var thisDocument = (anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) ? anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current.ownerDocument : document;
1376
+ var activeElement = thisDocument.activeElement;
1377
+ if (!(anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) || !activeElement)
1378
+ return;
1379
+ if (ev.key !== "Tab" && ev.key !== "Enter")
1380
+ return;
1381
+ if (ev.repeat) {
1382
+ ev.preventDefault();
1383
+ ev.stopPropagation();
1384
+ return;
1385
+ }
1386
+ var inputElsIterator = thisDocument.querySelectorAll(".szh-menu--state-open input,textarea");
1387
+ var inputEls = [];
1388
+ inputElsIterator.forEach(function (el) { return inputEls.push(el); });
1389
+ inputEls = inputEls.filter(function (el) { return !el.disabled; });
1390
+ if (inputEls.length === 0)
1391
+ return;
1392
+ var firstInputEl = inputEls[0];
1393
+ var lastInputEl = inputEls[inputEls.length - 1];
1394
+ if (activeElement !== firstInputEl && activeElement !== lastInputEl)
1395
+ return;
1396
+ var suppressAutoSaveEvents = activeElement.getAttribute("data-suppressAutoSaveEvents");
1397
+ var invokeSave = function (reason) {
1398
+ var _a, _b;
1399
+ if (!(saveButtonRef === null || saveButtonRef === void 0 ? void 0 : saveButtonRef.current) || suppressAutoSaveEvents)
1400
+ return;
1401
+ (_a = saveButtonRef.current) === null || _a === void 0 ? void 0 : _a.setAttribute("data-reason", reason);
1402
+ (_b = saveButtonRef === null || saveButtonRef === void 0 ? void 0 : saveButtonRef.current) === null || _b === void 0 ? void 0 : _b.click();
1403
+ };
1404
+ var isTextArea = activeElement.nodeName === "TEXTAREA";
1405
+ switch (activeElement.nodeName) {
1406
+ case "TEXTAREA":
1407
+ case "INPUT": {
1408
+ if (activeElement === lastInputEl && activeElement === firstInputEl) {
1409
+ if (ev.key === "Tab") {
1410
+ // Can't forward/backwards tab out of popup
1411
+ ev.preventDefault();
1412
+ ev.stopPropagation();
1413
+ if (isDown) {
1414
+ lastTabDownEl.current = activeElement;
1415
+ }
1416
+ else {
1417
+ lastTabDownEl.current == activeElement &&
1418
+ invokeSave(ev.shiftKey ? CloseReason.TAB_BACKWARD : CloseReason.TAB_FORWARD);
1419
+ }
1420
+ }
1421
+ if (ev.key === "Enter" && !isTextArea) {
1422
+ ev.preventDefault();
1423
+ ev.stopPropagation();
1424
+ if (isDown) {
1425
+ lastEnterDownEl.current = activeElement;
1426
+ }
1427
+ else {
1428
+ lastEnterDownEl.current == activeElement && invokeSave(CloseReason.CLICK);
1429
+ }
1430
+ }
1431
+ }
1432
+ else if (activeElement === lastInputEl) {
1433
+ if (ev.key === "Tab" && !ev.shiftKey) {
1434
+ // Can't backward tab out of popup
1435
+ ev.preventDefault();
1436
+ ev.stopPropagation();
1437
+ if (isDown) {
1438
+ lastTabDownEl.current = activeElement;
1439
+ }
1440
+ else {
1441
+ lastTabDownEl.current == activeElement && invokeSave(CloseReason.TAB_FORWARD);
1442
+ }
1443
+ }
1444
+ if (ev.key === "Enter" && !isTextArea) {
1445
+ ev.preventDefault();
1446
+ ev.stopPropagation();
1447
+ if (isDown) {
1448
+ lastEnterDownEl.current = activeElement;
1449
+ }
1450
+ else {
1451
+ lastEnterDownEl.current == activeElement && invokeSave(CloseReason.CLICK);
1452
+ }
1453
+ }
1454
+ }
1455
+ else if (activeElement === firstInputEl) {
1456
+ if (ev.key === "Tab" && ev.shiftKey) {
1457
+ // Can't backward tab out of popup
1458
+ ev.preventDefault();
1459
+ ev.stopPropagation();
1460
+ if (isDown) {
1461
+ lastTabDownEl.current = activeElement;
1462
+ }
1463
+ else {
1464
+ lastTabDownEl.current == activeElement && invokeSave(CloseReason.TAB_BACKWARD);
1465
+ }
1466
+ }
1467
+ }
1468
+ break;
1469
+ }
1470
+ }
1471
+ }; }, [anchorRef, saveButtonRef]);
1472
+ var handleKeydownTabAndEnter = react.useMemo(function () { return handleKeyboardTabAndEnter(true); }, [handleKeyboardTabAndEnter]);
1473
+ var handleKeyupTabAndEnter = react.useMemo(function () { return handleKeyboardTabAndEnter(false); }, [handleKeyboardTabAndEnter]);
1369
1474
  react.useEffect(function () {
1370
1475
  if (isMenuOpen(state)) {
1371
1476
  var thisDocument_1 = (anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) ? anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current.ownerDocument : document;
1477
+ thisDocument_1.addEventListener("keydown", handleKeydownTabAndEnter, true);
1478
+ thisDocument_1.addEventListener("keyup", handleKeyupTabAndEnter, true);
1372
1479
  thisDocument_1.addEventListener("mousedown", handleScreenEventForSave, true);
1373
1480
  thisDocument_1.addEventListener("mouseup", handleScreenEventForCancel, true);
1374
1481
  thisDocument_1.addEventListener("click", handleScreenEventForCancel, true);
1375
1482
  thisDocument_1.addEventListener("dblclick", handleScreenEventForCancel, true);
1376
1483
  return function () {
1484
+ thisDocument_1.addEventListener("keydown", handleKeydownTabAndEnter, true);
1485
+ thisDocument_1.addEventListener("keyup", handleKeyupTabAndEnter, true);
1377
1486
  thisDocument_1.removeEventListener("mousedown", handleScreenEventForSave, true);
1378
1487
  thisDocument_1.removeEventListener("mouseup", handleScreenEventForCancel, true);
1379
1488
  thisDocument_1.removeEventListener("click", handleScreenEventForCancel, true);
@@ -1381,7 +1490,14 @@ var ControlledMenuFr = function (_a, externalRef) {
1381
1490
  };
1382
1491
  }
1383
1492
  return function () { };
1384
- }, [handleScreenEventForSave, handleScreenEventForCancel, state, anchorRef]);
1493
+ }, [
1494
+ handleScreenEventForSave,
1495
+ handleScreenEventForCancel,
1496
+ state,
1497
+ anchorRef,
1498
+ handleKeydownTabAndEnter,
1499
+ handleKeyupTabAndEnter,
1500
+ ]);
1385
1501
  var itemSettings = react.useMemo(function () { return ({
1386
1502
  submenuOpenDelay: submenuOpenDelay,
1387
1503
  submenuCloseDelay: submenuCloseDelay
@@ -1676,8 +1792,11 @@ var MenuItemFr = function (_a) {
1676
1792
  value: value,
1677
1793
  syntheticEvent: e
1678
1794
  };
1679
- if (e.key !== undefined)
1680
- event.key = e.key;
1795
+ if (e.key !== undefined) {
1796
+ var ke = e;
1797
+ event.key = ke.key;
1798
+ event.shiftKey = ke.shiftKey;
1799
+ }
1681
1800
  if (isCheckBox)
1682
1801
  event.checked = !isChecked;
1683
1802
  if (isRadio)
@@ -1687,6 +1806,13 @@ var MenuItemFr = function (_a) {
1687
1806
  safeCall(radioGroup.onRadioChange, event);
1688
1807
  eventHandlers.handleClick(event, isCheckBox || isRadio);
1689
1808
  };
1809
+ var handleKeyDown = function (e) {
1810
+ // if tab is allowed the handleKeyUp event can't process the tab
1811
+ if (e.key === "Tab") {
1812
+ e.preventDefault();
1813
+ e.stopPropagation();
1814
+ }
1815
+ };
1690
1816
  /**
1691
1817
  * Keyboard events are triggered on up, otherwise sub-components get spaces and enters typed in them
1692
1818
  */
@@ -1695,7 +1821,10 @@ var MenuItemFr = function (_a) {
1695
1821
  return;
1696
1822
  switch (e.key) {
1697
1823
  case Keys.ENTER:
1824
+ case Keys.TAB:
1698
1825
  case Keys.SPACE:
1826
+ e.preventDefault();
1827
+ e.stopPropagation();
1699
1828
  if (isAnchor) {
1700
1829
  (menuItemRef === null || menuItemRef === void 0 ? void 0 : menuItemRef.current) && menuItemRef.current.click();
1701
1830
  }
@@ -1712,7 +1841,7 @@ var MenuItemFr = function (_a) {
1712
1841
  checked: isChecked,
1713
1842
  anchor: isAnchor
1714
1843
  }); }, [type, isDisabled, isHovering, isChecked, isAnchor]);
1715
- var mergedProps = mergeProps(__assign(__assign({}, restStateProps), { onPointerDown: setHover, onKeyUp: handleKeyUp, onClick: handleClick }), restProps);
1844
+ var mergedProps = mergeProps(__assign(__assign({}, restStateProps), { onPointerDown: setHover, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp, onClick: handleClick }), restProps);
1716
1845
  // Order of props overriding (same in all components):
1717
1846
  // 1. Preset props adhering to WAI-ARIA Authoring Practices.
1718
1847
  // 2. Merged outer and local props
@@ -1857,6 +1986,9 @@ var GridContext = react.createContext({
1857
1986
  }); },
1858
1987
  redrawRows: function () {
1859
1988
  console.error("no context provider for redrawRows");
1989
+ },
1990
+ selectNextCell: function () {
1991
+ console.error("no context provider for selectNextCell");
1860
1992
  }
1861
1993
  });
1862
1994
 
@@ -1870,7 +2002,8 @@ var GridUpdatingContext = react.createContext({
1870
2002
  console.error("Missing GridUpdatingContext");
1871
2003
  return [2 /*return*/];
1872
2004
  });
1873
- }); }
2005
+ }); },
2006
+ updatedDep: 0
1874
2007
  });
1875
2008
 
1876
2009
  /**
@@ -2130,6 +2263,15 @@ var GridContextProvider = function (props) {
2130
2263
  gridApi.redrawRows(rowNodes ? { rowNodes: rowNodes } : undefined);
2131
2264
  });
2132
2265
  };
2266
+ var selectNextCell = function (tabDirection) {
2267
+ if (tabDirection === void 0) { tabDirection = 0; }
2268
+ gridApiOp(function (gridApi) {
2269
+ if (tabDirection == 1)
2270
+ gridApi.tabToNextCell();
2271
+ if (tabDirection == -1)
2272
+ gridApi.tabToPreviousCell();
2273
+ });
2274
+ };
2133
2275
  return (jsxRuntime.jsx(GridContext.Provider, __assign({ value: {
2134
2276
  gridReady: gridReady,
2135
2277
  setGridApi: setGridApi,
@@ -2148,34 +2290,42 @@ var GridContextProvider = function (props) {
2148
2290
  sizeColumnsToFit: sizeColumnsToFit,
2149
2291
  stopEditing: stopEditing,
2150
2292
  updatingCells: updatingCells,
2151
- redrawRows: redrawRows
2293
+ redrawRows: redrawRows,
2294
+ selectNextCell: selectNextCell
2152
2295
  } }, { children: props.children })));
2153
2296
  };
2154
2297
 
2155
2298
  var GridUpdatingContextProvider = function (props) {
2156
2299
  var updatingBlocks = react.useRef({});
2157
2300
  var updating = react.useRef({});
2301
+ var _a = react.useState(0), updatedDep = _a[0], setUpdatedDep = _a[1];
2158
2302
  var resetUpdating = function () {
2159
2303
  var mergedUpdatingBlocks = {};
2160
2304
  for (var key in updatingBlocks.current) {
2161
2305
  mergedUpdatingBlocks[key] = lodashEs.flatten(updatingBlocks.current[key]);
2162
2306
  }
2163
2307
  updating.current = mergedUpdatingBlocks;
2308
+ setUpdatedDep(function (updatedDep) { return updatedDep + 1; });
2164
2309
  };
2165
- var modifyUpdating = function (field, ids, fn) { return __awaiter(void 0, void 0, void 0, function () {
2166
- var fieldUpdatingIds, idRef;
2167
- var _a;
2168
- return __generator(this, function (_b) {
2169
- switch (_b.label) {
2310
+ var modifyUpdating = function (fields, ids, fn) { return __awaiter(void 0, void 0, void 0, function () {
2311
+ var idRef;
2312
+ return __generator(this, function (_a) {
2313
+ switch (_a.label) {
2170
2314
  case 0:
2171
- fieldUpdatingIds = (_a = updatingBlocks.current[field]) !== null && _a !== void 0 ? _a : (updatingBlocks.current[field] = []);
2172
2315
  idRef = __spreadArray([], ids, true);
2173
- fieldUpdatingIds.push(idRef);
2316
+ lodashEs.castArray(fields).forEach(function (field) {
2317
+ var _a;
2318
+ var fieldUpdatingIds = (_a = updatingBlocks.current[field]) !== null && _a !== void 0 ? _a : (updatingBlocks.current[field] = []);
2319
+ fieldUpdatingIds.push(idRef);
2320
+ });
2174
2321
  resetUpdating();
2175
2322
  return [4 /*yield*/, fn()];
2176
2323
  case 1:
2177
- _b.sent();
2178
- lodashEs.remove(fieldUpdatingIds, function (idList) { return idList === idRef; });
2324
+ _a.sent();
2325
+ lodashEs.castArray(fields).forEach(function (field) {
2326
+ var fieldUpdatingIds = updatingBlocks.current[field];
2327
+ lodashEs.remove(fieldUpdatingIds, function (idList) { return idList === idRef; });
2328
+ });
2179
2329
  resetUpdating();
2180
2330
  return [2 /*return*/];
2181
2331
  }
@@ -2184,7 +2334,7 @@ var GridUpdatingContextProvider = function (props) {
2184
2334
  var checkUpdating = function (fields, id) {
2185
2335
  return lodashEs.castArray(fields).some(function (f) { var _a; return (_a = updating.current[f]) === null || _a === void 0 ? void 0 : _a.includes(id); });
2186
2336
  };
2187
- return (jsxRuntime.jsx(GridUpdatingContext.Provider, __assign({ value: { modifyUpdating: modifyUpdating, checkUpdating: checkUpdating } }, { children: props.children })));
2337
+ return (jsxRuntime.jsx(GridUpdatingContext.Provider, __assign({ value: { modifyUpdating: modifyUpdating, checkUpdating: checkUpdating, updatedDep: updatedDep } }, { children: props.children })));
2188
2338
  };
2189
2339
 
2190
2340
  var GridPopoverContext = react.createContext({
@@ -2206,7 +2356,7 @@ var useGridPopoverContext = function () {
2206
2356
  var GridPopoverContextProvider = function (_a) {
2207
2357
  var _b, _c, _d;
2208
2358
  var props = _a.props, children = _a.children;
2209
- var _e = react.useContext(GridContext), getSelectedRows = _e.getSelectedRows, updatingCells = _e.updatingCells, stopEditing = _e.stopEditing;
2359
+ var _e = react.useContext(GridContext), getSelectedRows = _e.getSelectedRows, updatingCells = _e.updatingCells, stopEditing = _e.stopEditing, selectNextCell = _e.selectNextCell;
2210
2360
  var anchorRef = react.useRef(props.eGridCell);
2211
2361
  var _f = react.useState(false), saving = _f[0], setSaving = _f[1];
2212
2362
  var colDef = props.colDef;
@@ -2215,7 +2365,7 @@ var GridPopoverContextProvider = function (_a) {
2215
2365
  // Then item that is clicked on will always be first in the list
2216
2366
  var selectedRows = react.useMemo(function () { return (multiEdit ? lodashEs.sortBy(getSelectedRows(), function (row) { return row.id !== props.data.id; }) : [props.data]); }, [getSelectedRows, multiEdit, props.data]);
2217
2367
  var field = (_d = (_c = props.colDef) === null || _c === void 0 ? void 0 : _c.field) !== null && _d !== void 0 ? _d : "";
2218
- var updateValue = react.useCallback(function (saveFn) { return __awaiter(void 0, void 0, void 0, function () {
2368
+ var updateValue = react.useCallback(function (saveFn, tabDirection) { return __awaiter(void 0, void 0, void 0, function () {
2219
2369
  var result;
2220
2370
  return __generator(this, function (_a) {
2221
2371
  switch (_a.label) {
@@ -2225,13 +2375,15 @@ var GridPopoverContextProvider = function (_a) {
2225
2375
  return [4 /*yield*/, updatingCells({ selectedRows: selectedRows, field: field }, saveFn, setSaving)];
2226
2376
  case 1:
2227
2377
  result = _a.sent();
2228
- if (result)
2378
+ if (result) {
2229
2379
  stopEditing();
2380
+ tabDirection && selectNextCell(tabDirection);
2381
+ }
2230
2382
  _a.label = 2;
2231
2383
  case 2: return [2 /*return*/, result];
2232
2384
  }
2233
2385
  });
2234
- }); }, [field, saving, selectedRows, stopEditing, updatingCells]);
2386
+ }); }, [field, saving, selectNextCell, selectedRows, stopEditing, updatingCells]);
2235
2387
  return (jsxRuntime.jsx(GridPopoverContext.Provider, __assign({ value: {
2236
2388
  anchorRef: anchorRef,
2237
2389
  saving: saving,
@@ -2261,43 +2413,7 @@ var GridSubComponentContext = react.createContext({
2261
2413
  }); }
2262
2414
  });
2263
2415
 
2264
- function toVal(mix) {
2265
- var k, y, str='';
2266
- if (mix) {
2267
- if (typeof mix === 'object') {
2268
- if (Array.isArray(mix)) {
2269
- for (k=0; k < mix.length; k++) {
2270
- if (mix[k] && (y = toVal(mix[k]))) {
2271
- str && (str += ' ');
2272
- str += y;
2273
- }
2274
- }
2275
- } else {
2276
- for (k in mix) {
2277
- if (mix[k] && (y = toVal(k))) {
2278
- str && (str += ' ');
2279
- str += y;
2280
- }
2281
- }
2282
- }
2283
- } else if (typeof mix !== 'boolean' && !mix.call) {
2284
- str && (str += ' ');
2285
- str += mix;
2286
- }
2287
- }
2288
- return str;
2289
- }
2290
-
2291
- function clsx () {
2292
- var i=0, x, str='';
2293
- while (i < arguments.length) {
2294
- if (x = toVal(arguments[i++])) {
2295
- str && (str += ' ');
2296
- str += x;
2297
- }
2298
- }
2299
- return str;
2300
- }
2416
+ 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}
2301
2417
 
2302
2418
  /**
2303
2419
  * Retains last sort order from via <AgGrid postRowSort>.
@@ -2796,96 +2912,35 @@ var useGridPopoverHook = function (props) {
2796
2912
  setOpen(true);
2797
2913
  }, []);
2798
2914
  var triggerSave = react.useCallback(function (reason) { return __awaiter(void 0, void 0, void 0, function () {
2799
- var _a, _b;
2800
- return __generator(this, function (_c) {
2801
- switch (_c.label) {
2915
+ return __generator(this, function (_a) {
2916
+ switch (_a.label) {
2802
2917
  case 0:
2803
- _a = reason == "cancel" || !props.save;
2804
- if (_a) return [3 /*break*/, 3];
2805
- _b = updateValue;
2806
- if (!_b) return [3 /*break*/, 2];
2807
- return [4 /*yield*/, updateValue(props.save)];
2918
+ if (reason == "cancel") {
2919
+ stopEditing();
2920
+ return [2 /*return*/];
2921
+ }
2922
+ if (props.invalid && props.invalid()) {
2923
+ return [2 /*return*/];
2924
+ }
2925
+ if (!!props.save) return [3 /*break*/, 1];
2926
+ stopEditing();
2927
+ return [3 /*break*/, 3];
2808
2928
  case 1:
2809
- _b = (_c.sent());
2810
- _c.label = 2;
2811
- case 2:
2812
- _a = (_b);
2813
- _c.label = 3;
2814
- case 3:
2815
- if (_a) {
2816
- setOpen(false);
2929
+ if (!props.save) return [3 /*break*/, 3];
2930
+ // forms that don't provide an invalid fn must wait until they have saved to close
2931
+ if (props.invalid)
2817
2932
  stopEditing();
2933
+ return [4 /*yield*/, updateValue(props.save, reason === CloseReason.TAB_FORWARD ? 1 : reason === CloseReason.TAB_BACKWARD ? -1 : 0)];
2934
+ case 2:
2935
+ if (_a.sent()) {
2936
+ if (!props.invalid)
2937
+ stopEditing();
2818
2938
  }
2819
- return [2 /*return*/];
2939
+ _a.label = 3;
2940
+ case 3: return [2 /*return*/];
2820
2941
  }
2821
2942
  });
2822
- }); }, [props.save, stopEditing, updateValue]);
2823
- var onlyInputKeyboardEventHandlers = {
2824
- onKeyUp: function (e) {
2825
- var isTextArea = e.currentTarget.type === "textarea";
2826
- if (e.key === "Enter" && !isTextArea) {
2827
- e.preventDefault();
2828
- e.stopPropagation();
2829
- triggerSave().then();
2830
- }
2831
- else if (e.key === "Tab") {
2832
- e.preventDefault();
2833
- e.stopPropagation();
2834
- }
2835
- },
2836
- onKeyDown: function (e) {
2837
- var isTextArea = e.currentTarget.type === "textarea";
2838
- if (e.key === "Enter" && !isTextArea) {
2839
- e.preventDefault();
2840
- e.stopPropagation();
2841
- }
2842
- else if (e.key === "Tab") {
2843
- e.preventDefault();
2844
- e.stopPropagation();
2845
- !e.shiftKey && triggerSave().then();
2846
- }
2847
- }
2848
- };
2849
- var firstInputKeyboardEventHandlers = {
2850
- onKeyUp: function (e) {
2851
- if (e.key === "Tab" && e.shiftKey) {
2852
- e.preventDefault();
2853
- e.stopPropagation();
2854
- }
2855
- },
2856
- onKeyDown: function (e) {
2857
- if (e.key === "Tab" && e.shiftKey) {
2858
- e.preventDefault();
2859
- e.stopPropagation();
2860
- }
2861
- }
2862
- };
2863
- var lastInputKeyboardEventHandlers = {
2864
- onKeyUp: function (e) {
2865
- var isTextArea = e.currentTarget.type === "textarea";
2866
- if (e.key === "Enter" && !isTextArea) {
2867
- e.preventDefault();
2868
- e.stopPropagation();
2869
- triggerSave().then();
2870
- }
2871
- else if (e.key === "Tab" && !e.shiftKey) {
2872
- e.preventDefault();
2873
- e.stopPropagation();
2874
- }
2875
- },
2876
- onKeyDown: function (e) {
2877
- var isTextArea = e.currentTarget.type === "textarea";
2878
- if (e.key === "Enter" && !isTextArea) {
2879
- e.preventDefault();
2880
- e.stopPropagation();
2881
- }
2882
- else if (e.key === "Tab" && !e.shiftKey) {
2883
- e.preventDefault();
2884
- e.stopPropagation();
2885
- triggerSave().then();
2886
- }
2887
- }
2888
- };
2943
+ }); }, [props, stopEditing, updateValue]);
2889
2944
  var popoverWrapper = react.useCallback(function (children) {
2890
2945
  return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: anchorRef.current && (jsxRuntime.jsxs(ControlledMenu, __assign({ state: isOpen ? "open" : "closed", portal: true, unmountOnClose: true, anchorRef: anchorRef, saveButtonRef: saveButtonRef, menuClassName: "step-ag-grid-react-menu", onClose: function (event) {
2891
2946
  // Prevent menu from closing when modals are invoked
@@ -2901,14 +2956,14 @@ var useGridPopoverHook = function (props) {
2901
2956
  right: 0,
2902
2957
  backgroundColor: "rgba(64,64,64,0.1)",
2903
2958
  zIndex: 1000
2904
- } })), children, jsxRuntime.jsx("button", { ref: saveButtonRef, onClick: function () { return triggerSave().then(); }, style: { display: "none" } })] }))) }));
2959
+ } })), children, jsxRuntime.jsx("button", { ref: saveButtonRef, "data-reason": "", onClick: function (e) {
2960
+ var _a;
2961
+ triggerSave((_a = e.currentTarget.getAttribute("data-reason")) !== null && _a !== void 0 ? _a : undefined).then();
2962
+ }, style: { display: "none" } })] }))) }));
2905
2963
  }, [anchorRef, isOpen, props.className, saving, triggerSave]);
2906
2964
  return {
2907
2965
  popoverWrapper: popoverWrapper,
2908
- triggerSave: triggerSave,
2909
- onlyInputKeyboardEventHandlers: onlyInputKeyboardEventHandlers,
2910
- firstInputKeyboardEventHandlers: firstInputKeyboardEventHandlers,
2911
- lastInputKeyboardEventHandlers: lastInputKeyboardEventHandlers
2966
+ triggerSave: triggerSave
2912
2967
  };
2913
2968
  };
2914
2969
 
@@ -2934,7 +2989,7 @@ var GridRenderPopoutMenuCell = function (props) {
2934
2989
  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}";
2935
2990
  styleInject(css_248z$5);
2936
2991
 
2937
- var css_248z$4 = ".GridPopoverEditDropDown-containerSmall .GridFormDropDown-options{max-height:120px;overflow-y:auto}.GridPopoverEditDropDown-containerMedium .GridFormDropDown-options{max-height:200px;overflow-y:auto}.GridPopoverEditDropDown-containerLarge .GridFormDropDown-options{max-height:400px;overflow-y:auto}.GridPopoverEditDropDown-containerUnlimited .GridFormDropDown-options{overflow-y:auto}";
2992
+ 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}";
2938
2993
  styleInject(css_248z$4);
2939
2994
 
2940
2995
  /* global setTimeout, clearTimeout */
@@ -3019,18 +3074,20 @@ var fieldToString = function (field) {
3019
3074
  };
3020
3075
  var GridFormDropDown = function (props) {
3021
3076
  var _a = useGridPopoverContext(), selectedRows = _a.selectedRows, field = _a.field, updateValue = _a.updateValue, data = _a.data;
3022
- var stopEditing = react.useContext(GridContext).stopEditing;
3077
+ // Save triggers during async action processing which triggers another selectItem(), this ref blocks that
3078
+ var hasSubmitted = react.useRef(false);
3023
3079
  var _b = react.useState(""), filter = _b[0], setFilter = _b[1];
3024
3080
  var _c = react.useState([]), filteredValues = _c[0], setFilteredValues = _c[1];
3025
3081
  var optionsInitialising = react.useRef(false);
3026
3082
  var _d = react.useState(null), options = _d[0], setOptions = _d[1];
3027
3083
  var subComponentIsValid = react.useRef(false);
3028
3084
  var _e = react.useState(), subSelectedValue = _e[0], setSubSelectedValue = _e[1];
3029
- var _f = react.useState(), selectedSubComponent = _f[0], setSelectedSubComponent = _f[1];
3030
- var selectItemHandler = react.useCallback(function (value, subComponentValue) { return __awaiter(void 0, void 0, void 0, function () {
3085
+ var _f = react.useState(null), selectedSubComponent = _f[0], setSelectedSubComponent = _f[1];
3086
+ var selectItemHandler = react.useCallback(function (value, subComponentValue, reason) { return __awaiter(void 0, void 0, void 0, function () {
3031
3087
  return __generator(this, function (_a) {
3032
- if (subComponentValue !== undefined && !subComponentIsValid.current)
3088
+ if (hasSubmitted.current || (subComponentValue !== undefined && !subComponentIsValid.current))
3033
3089
  return [2 /*return*/, false];
3090
+ hasSubmitted.current = true;
3034
3091
  return [2 /*return*/, updateValue(function (selectedRows) { return __awaiter(void 0, void 0, void 0, function () {
3035
3092
  var hasChanged;
3036
3093
  return __generator(this, function (_a) {
@@ -3049,7 +3106,7 @@ var GridFormDropDown = function (props) {
3049
3106
  case 3: return [2 /*return*/, true];
3050
3107
  }
3051
3108
  });
3052
- }); })];
3109
+ }); }, reason === CloseReason.TAB_FORWARD ? 1 : reason === CloseReason.TAB_BACKWARD ? -1 : 0)];
3053
3110
  });
3054
3111
  }); }, [field, props, updateValue]);
3055
3112
  var selectFilterHandler = react.useCallback(function (value) { return __awaiter(void 0, void 0, void 0, function () {
@@ -3069,7 +3126,7 @@ var GridFormDropDown = function (props) {
3069
3126
  return [2 /*return*/, true];
3070
3127
  }
3071
3128
  });
3072
- }); })];
3129
+ }); }, 0)];
3073
3130
  });
3074
3131
  }); }, [props, updateValue]);
3075
3132
  // Load up options list if it's async function
@@ -3143,74 +3200,80 @@ var GridFormDropDown = function (props) {
3143
3200
  researchOnFilterChange().then();
3144
3201
  }
3145
3202
  }, [filter, props, researchOnFilterChange]);
3146
- var onFilterKeyDown = react.useCallback(function (e) { return __awaiter(void 0, void 0, void 0, function () {
3203
+ var save = react.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
3147
3204
  var activeOptions;
3148
3205
  return __generator(this, function (_a) {
3149
3206
  switch (_a.label) {
3150
3207
  case 0:
3151
3208
  if (!options)
3152
- return [2 /*return*/];
3153
- if (!(e.key == "Enter" || e.key == "Tab")) return [3 /*break*/, 5];
3209
+ return [2 /*return*/, true];
3154
3210
  activeOptions = options.filter(function (option) { return !filteredValues.includes(option.value); });
3155
- if (!(activeOptions.length == 1)) return [3 /*break*/, 2];
3211
+ if (!(activeOptions.length === 1)) return [3 /*break*/, 2];
3156
3212
  return [4 /*yield*/, selectItemHandler(activeOptions[0].value)];
3157
3213
  case 1:
3158
3214
  _a.sent();
3159
- stopEditing();
3160
- return [3 /*break*/, 5];
3215
+ return [3 /*break*/, 6];
3161
3216
  case 2:
3162
- if (!props.onSelectFilter) return [3 /*break*/, 4];
3217
+ if (!(activeOptions.length === 0 && props.onSelectFilter)) return [3 /*break*/, 4];
3163
3218
  return [4 /*yield*/, selectFilterHandler(filter)];
3164
3219
  case 3:
3165
3220
  _a.sent();
3166
- stopEditing();
3167
- return [3 /*break*/, 5];
3221
+ return [3 /*break*/, 6];
3168
3222
  case 4:
3169
- e.preventDefault();
3170
- e.stopPropagation();
3171
- _a.label = 5;
3172
- case 5: return [2 /*return*/];
3173
- }
3174
- });
3175
- }); }, [filteredValues, options, selectItemHandler, selectFilterHandler, stopEditing, filter, props]);
3176
- var save = react.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
3177
- return __generator(this, function (_a) {
3178
- switch (_a.label) {
3179
- case 0:
3180
3223
  // Handler for sub-selected value
3181
3224
  if (!selectedSubComponent)
3182
3225
  return [2 /*return*/, true];
3183
- if (!subComponentIsValid.current)
3226
+ if (selectedSubComponent.subComponent && !subComponentIsValid.current)
3184
3227
  return [2 /*return*/, false];
3185
3228
  return [4 /*yield*/, selectItemHandler(selectedSubComponent.value, subSelectedValue)];
3186
- case 1:
3229
+ case 5:
3187
3230
  _a.sent();
3188
- return [2 /*return*/, true];
3231
+ _a.label = 6;
3232
+ case 6: return [2 /*return*/, true];
3189
3233
  }
3190
3234
  });
3191
- }); }, [selectItemHandler, selectedSubComponent, subSelectedValue]);
3192
- var popoverWrapper = useGridPopoverHook({ className: props.className, save: save }).popoverWrapper;
3235
+ }); }, [
3236
+ filter,
3237
+ filteredValues,
3238
+ options,
3239
+ props.onSelectFilter,
3240
+ selectFilterHandler,
3241
+ selectItemHandler,
3242
+ selectedSubComponent,
3243
+ subSelectedValue,
3244
+ ]);
3245
+ var popoverWrapper = useGridPopoverHook({
3246
+ className: props.className,
3247
+ invalid: function () { return !!(selectedSubComponent && !subComponentIsValid.current); },
3248
+ save: save
3249
+ }).popoverWrapper;
3193
3250
  return popoverWrapper(jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [props.filtered && (jsxRuntime.jsxs("div", __assign({ className: "GridFormDropDown-filter" }, { children: [jsxRuntime.jsx(FocusableItem, __assign({ className: "filter-item" }, { children: function (_a) {
3194
3251
  var _b;
3195
3252
  var ref = _a.ref;
3196
- return (jsxRuntime.jsx("div", __assign({ style: { display: "flex", width: "100%" } }, { children: jsxRuntime.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: filter, onChange: function (e) { return setFilter(e.target.value.toLowerCase()); }, onKeyDown: function (e) { return onFilterKeyDown(e); } }) })));
3253
+ return (jsxRuntime.jsx("div", __assign({ style: { display: "flex", width: "100%" } }, { children: jsxRuntime.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: filter, onChange: function (e) { return setFilter(e.target.value.toLowerCase()); } }) })));
3197
3254
  } })), jsxRuntime.jsx(MenuDivider, {}, "$$divider_filter")] }))), jsxRuntime.jsx(ComponentLoadingWrapper, __assign({ loading: !options, className: "GridFormDropDown-options" }, { children: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [options && options.length == (filteredValues === null || filteredValues === void 0 ? void 0 : filteredValues.length) && (jsxRuntime.jsx(MenuItem, { children: "[Empty]" }, "".concat(fieldToString(field), "-empty"))), options === null || options === void 0 ? void 0 : options.map(function (item, index) {
3198
3255
  var _a;
3199
- return item.value === MenuSeparatorString ? (jsxRuntime.jsx(MenuDivider, {}, "$$divider_".concat(index))) : item.value === MenuHeaderString ? (jsxRuntime.jsx(MenuHeader, { children: item.label }, "$$header_".concat(index))) : filteredValues.includes(item.value) ? null : (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(MenuItem, __assign({ disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "", value: item.value, onClick: function (e) {
3256
+ return item.value === MenuSeparatorString ? (jsxRuntime.jsx(MenuDivider, {}, "$$divider_".concat(index))) : item.value === MenuHeaderString ? (jsxRuntime.jsx(MenuHeader, { children: item.label }, "$$header_".concat(index))) : filteredValues.includes(item.value) ? null : (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs(MenuItem, __assign({ disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "", value: item.value, onClick: function (e) {
3200
3257
  if (item.subComponent) {
3201
3258
  if (selectedSubComponent === item) {
3259
+ // toggle selection off
3202
3260
  setSelectedSubComponent(null);
3203
3261
  subComponentIsValid.current = true;
3204
3262
  }
3205
3263
  else {
3264
+ // toggle selection on
3206
3265
  setSelectedSubComponent(item);
3207
3266
  }
3208
3267
  e.keepOpen = true;
3209
3268
  }
3210
3269
  else {
3211
- selectItemHandler(item.value).then();
3270
+ selectItemHandler(item.value, undefined, e.key === "Tab"
3271
+ ? e.shiftKey
3272
+ ? CloseReason.TAB_BACKWARD
3273
+ : CloseReason.TAB_FORWARD
3274
+ : CloseReason.CLICK).then();
3212
3275
  }
3213
- } }, { children: (_a = item.label) !== null && _a !== void 0 ? _a : (item.value == null ? "<".concat(item.value, ">") : "".concat(item.value)) }), "".concat(fieldToString(field), "-").concat(index)), item.subComponent && selectedSubComponent === item && (jsxRuntime.jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (ref) { return (jsxRuntime.jsx(GridSubComponentContext.Provider, __assign({ value: {
3276
+ } }, { 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 && (jsxRuntime.jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (ref) { return (jsxRuntime.jsx(GridSubComponentContext.Provider, __assign({ value: {
3214
3277
  data: data,
3215
3278
  value: subSelectedValue,
3216
3279
  setValue: function (value) {
@@ -3242,6 +3305,10 @@ var GridFormMultiSelect = function (props) {
3242
3305
  var _d = react.useState([]), filteredValues = _d[0], setFilteredValues = _d[1];
3243
3306
  var optionsInitialising = react.useRef(false);
3244
3307
  var _e = react.useState(), options = _e[0], setOptions = _e[1];
3308
+ var invalid = react.useCallback(function () {
3309
+ var validations = lodashEs.pick(subComponentIsValid.current, Object.keys(selectedValues));
3310
+ return Object.values(validations).some(function (v) { return !v; });
3311
+ }, [selectedValues]);
3245
3312
  var save = react.useCallback(function (selectedRows) { return __awaiter(void 0, void 0, void 0, function () {
3246
3313
  var validations, notValid, menuOptionSubValueResult;
3247
3314
  return __generator(this, function (_a) {
@@ -3335,8 +3402,9 @@ var GridFormMultiSelect = function (props) {
3335
3402
  }, [selectedValues]);
3336
3403
  var _f = useGridPopoverHook({
3337
3404
  className: props.className,
3405
+ invalid: invalid,
3338
3406
  save: save
3339
- }), popoverWrapper = _f.popoverWrapper, lastInputKeyboardEventHandlers = _f.lastInputKeyboardEventHandlers, triggerSave = _f.triggerSave;
3407
+ }), popoverWrapper = _f.popoverWrapper, triggerSave = _f.triggerSave;
3340
3408
  return popoverWrapper(jsxRuntime.jsx(ComponentLoadingWrapper, __assign({ loading: !options, className: "GridFormMultiSelect-container" }, { children: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [options && props.filtered && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(FocusableItem, __assign({ className: "filter-item" }, { children: function (_a) {
3341
3409
  var _b;
3342
3410
  var ref = _a.ref;
@@ -3344,9 +3412,12 @@ var GridFormMultiSelect = function (props) {
3344
3412
  } }), "filter"), jsxRuntime.jsx(MenuDivider, {}, "$$divider_filter")] })), jsxRuntime.jsx("div", __assign({ className: "GridFormMultiSelect-options" }, { children: options === null || options === void 0 ? void 0 : options.map(function (item, index) {
3345
3413
  var _a;
3346
3414
  return item.value === MenuSeparatorString ? (jsxRuntime.jsx(MenuDivider, {}, "$$divider_".concat(index))) : filteredValues.includes(item.value) ? null : (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(MenuItem, __assign({ onClick: function (e) {
3347
- e.keepOpen = true;
3348
- toggleValue(item);
3349
- } }, lastInputKeyboardEventHandlers, { children: jsxRuntime.jsx(lui.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: {
3415
+ // Global react-menu MenuItem handler handles tabs
3416
+ if (e.key !== "Tab") {
3417
+ e.keepOpen = true;
3418
+ toggleValue(item);
3419
+ }
3420
+ } }, { children: jsxRuntime.jsx(lui.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: {
3350
3421
  onClick: function (e) {
3351
3422
  e.preventDefault();
3352
3423
  e.stopPropagation();
@@ -3446,7 +3517,7 @@ var GridFormPopoverMenu = function (props) {
3446
3517
  });
3447
3518
  }); })();
3448
3519
  }, [options, props.defaultAction, props.options, selectedRows]);
3449
- var actionClick = react.useCallback(function (menuOption) { return __awaiter(void 0, void 0, void 0, function () {
3520
+ var actionClick = react.useCallback(function (menuOption, reason) { return __awaiter(void 0, void 0, void 0, function () {
3450
3521
  return __generator(this, function (_a) {
3451
3522
  actionProcessing.current = true;
3452
3523
  return [2 /*return*/, updateValue(function () { return __awaiter(void 0, void 0, void 0, function () {
@@ -3463,25 +3534,27 @@ var GridFormPopoverMenu = function (props) {
3463
3534
  return [2 /*return*/, true];
3464
3535
  }
3465
3536
  });
3466
- }); })];
3537
+ }); }, reason === CloseReason.TAB_FORWARD ? 1 : reason === CloseReason.TAB_BACKWARD ? -1 : 0)];
3467
3538
  });
3468
3539
  }); }, [defaultAction, selectedRows, subSelectedValue, updateValue]);
3469
- var onMenuItemClick = react.useCallback(function (e, item) {
3470
- if (item.subComponent) {
3471
- subComponentIsValid.current = false;
3472
- setSubSelectedValue(null);
3473
- setSubComponentSelected(subComponentSelected === item ? null : item);
3474
- e.keepOpen = true;
3475
- }
3476
- else {
3477
- actionClick(item).then();
3478
- e.keepOpen = true;
3479
- }
3480
- }, [actionClick, subComponentSelected]);
3481
- var selectedRowCount = selectedRows.length;
3482
- var filteredOptions = options === null || options === void 0 ? void 0 : options.filter(function (menuOption) {
3483
- return menuOption.label === PopoutMenuSeparator || selectedRowCount === 1 || menuOption.supportsMultiEdit;
3484
- });
3540
+ var onMenuItemClick = react.useCallback(function (e, item) { return __awaiter(void 0, void 0, void 0, function () {
3541
+ return __generator(this, function (_a) {
3542
+ switch (_a.label) {
3543
+ case 0:
3544
+ if (!item.subComponent) return [3 /*break*/, 1];
3545
+ subComponentIsValid.current = false;
3546
+ setSubSelectedValue(null);
3547
+ setSubComponentSelected(subComponentSelected === item ? null : item);
3548
+ e.keepOpen = true;
3549
+ return [3 /*break*/, 3];
3550
+ case 1: return [4 /*yield*/, actionClick(item, e.key === "Tab" ? (e.shiftKey ? CloseReason.TAB_BACKWARD : CloseReason.TAB_FORWARD) : CloseReason.CLICK).then()];
3551
+ case 2:
3552
+ _a.sent();
3553
+ _a.label = 3;
3554
+ case 3: return [2 /*return*/];
3555
+ }
3556
+ });
3557
+ }); }, [actionClick, subComponentSelected]);
3485
3558
  var save = react.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
3486
3559
  return __generator(this, function (_a) {
3487
3560
  switch (_a.label) {
@@ -3489,19 +3562,23 @@ var GridFormPopoverMenu = function (props) {
3489
3562
  if (!(!actionProcessing.current && subComponentSelected)) return [3 /*break*/, 2];
3490
3563
  if (!subComponentIsValid.current)
3491
3564
  return [2 /*return*/, false];
3492
- return [4 /*yield*/, actionClick(subComponentSelected)];
3565
+ return [4 /*yield*/, actionClick(subComponentSelected, "click")];
3493
3566
  case 1:
3494
3567
  _a.sent();
3495
- return [2 /*return*/, false];
3568
+ return [2 /*return*/, true];
3496
3569
  case 2:
3497
3570
  // Otherwise assume it's a cancel, either way we close the menu
3498
3571
  return [2 /*return*/, true];
3499
3572
  }
3500
3573
  });
3501
3574
  }); }, [actionClick, subComponentSelected]);
3502
- var _e = useGridPopoverHook({ className: props.className, save: save }), popoverWrapper = _e.popoverWrapper, triggerSave = _e.triggerSave;
3503
- return popoverWrapper(jsxRuntime.jsx(ComponentLoadingWrapper, __assign({ loading: !filteredOptions, className: "GridFormPopupMenu" }, { children: jsxRuntime.jsx(jsxRuntime.Fragment, { children: options === null || options === void 0 ? void 0 : options.map(function (item, index) {
3504
- return item.label === PopoutMenuSeparator ? (jsxRuntime.jsx(MenuDivider, {}, "$$divider_".concat(index))) : (!item.hidden && (jsxRuntime.jsxs(react.Fragment, { children: [jsxRuntime.jsx(MenuItem, __assign({ onClick: function (e) { return onMenuItemClick(e, item); }, disabled: !!item.disabled || !(filteredOptions === null || filteredOptions === void 0 ? void 0 : filteredOptions.includes(item)), title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "" }, { children: item.label }), "".concat(item.label)), item.subComponent && subComponentSelected === item && (jsxRuntime.jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (_) {
3575
+ var _e = useGridPopoverHook({
3576
+ className: props.className,
3577
+ invalid: function () { return subComponentSelected && !subComponentIsValid.current; },
3578
+ save: save
3579
+ }), popoverWrapper = _e.popoverWrapper, triggerSave = _e.triggerSave;
3580
+ return popoverWrapper(jsxRuntime.jsx(ComponentLoadingWrapper, __assign({ loading: !options, className: "GridFormPopupMenu" }, { children: jsxRuntime.jsx(jsxRuntime.Fragment, { children: options === null || options === void 0 ? void 0 : options.map(function (item, index) {
3581
+ return item.label === PopoutMenuSeparator ? (jsxRuntime.jsx(MenuDivider, {}, "$$divider_".concat(index))) : (!item.hidden && (jsxRuntime.jsxs(react.Fragment, { children: [jsxRuntime.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 && (jsxRuntime.jsx(FocusableItem, __assign({ className: "LuiDeprecatedForms" }, { children: function (_) {
3505
3582
  return item.subComponent && (jsxRuntime.jsx(GridSubComponentContext.Provider, __assign({ value: {
3506
3583
  data: data,
3507
3584
  value: subSelectedValue,
@@ -3528,7 +3605,7 @@ var GridPopoverMenu = function (colDef, custom) {
3528
3605
  };
3529
3606
 
3530
3607
  var bearingValueFormatter = function (params) {
3531
- var value = params.value;
3608
+ var value = typeof params.value == "string" ? parseFloat(params.value) : params.value;
3532
3609
  if (value == null) {
3533
3610
  return "-";
3534
3611
  }
@@ -3611,28 +3688,33 @@ styleInject(css_248z$2);
3611
3688
  var css_248z$1 = ".LuiTextInput{margin-bottom:0}.LuiTextInput-formatted{color:#beb9b4;line-height:48px;position:absolute;right:14px;top:0}";
3612
3689
  styleInject(css_248z$1);
3613
3690
 
3691
+ var FormError = function (props) {
3692
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [props.error && (jsxRuntime.jsxs("span", __assign({ className: "LuiTextInput-error" }, { children: [jsxRuntime.jsx(lui.LuiIcon, { alt: "error", name: "ic_error", className: "LuiTextInput-error-icon", size: "sm", status: "error" }), props.error] }))), props.helpText && !props.error && (jsxRuntime.jsx("span", __assign({ style: {
3693
+ fontSize: "0.7rem"
3694
+ } }, { children: props.helpText })))] }));
3695
+ };
3696
+
3614
3697
  var TextInputFormatted = function (props) {
3615
3698
  return (jsxRuntime.jsxs("div", __assign({ className: clsx("LuiTextInput Grid-popoverContainer", props.error && "hasError", props.className) }, { children: [jsxRuntime.jsxs("span", __assign({ className: "LuiTextInput-inputWrapper" }, { children: [jsxRuntime.jsx("input", __assign({ type: "text", spellCheck: true, defaultValue: props.value }, lodashEs.omit(props, ["error", "value", "helpText", "formatted", "className"]), { className: "LuiTextInput-input", onMouseEnter: function (e) {
3616
3699
  e.currentTarget.focus();
3617
3700
  props.onMouseEnter && props.onMouseEnter(e);
3618
- } })), jsxRuntime.jsx("span", __assign({ className: "LuiTextInput-formatted" }, { children: props.formatted }))] })), props.error && (jsxRuntime.jsxs("span", __assign({ className: "LuiTextInput-error" }, { children: [jsxRuntime.jsx(lui.LuiIcon, { alt: "error", name: "ic_error", className: "LuiTextInput-error-icon", size: "sm", status: "error" }), props.error] }))), props.helpText && !props.error && (jsxRuntime.jsx("span", __assign({ style: {
3619
- fontSize: "0.7rem"
3620
- } }, { children: props.helpText })))] })));
3701
+ } })), jsxRuntime.jsx("span", __assign({ className: "LuiTextInput-formatted" }, { children: props.formatted }))] })), jsxRuntime.jsx(FormError, { error: props.error, helpText: props.helpText })] })));
3621
3702
  };
3622
3703
 
3623
3704
  var GridFormEditBearing = function (props) {
3624
3705
  var _a = useGridPopoverContext(), field = _a.field, initialValue = _a.value;
3625
- var _b = react.useState("".concat(initialValue !== null && initialValue !== void 0 ? initialValue : "")), value = _b[0], setValue = _b[1];
3706
+ // This clears out any scientific precision
3707
+ var defaultValue = react.useMemo(function () { return (initialValue == null ? "" : parseFloat(parseFloat(initialValue).toFixed(10)).toString()); }, [initialValue]);
3708
+ var _b = react.useState(defaultValue), value = _b[0], setValue = _b[1];
3709
+ var invalid = react.useCallback(function () { return bearingStringValidator(value, props.range); }, [props.range, value]);
3626
3710
  var save = react.useCallback(function (selectedRows) { return __awaiter(void 0, void 0, void 0, function () {
3627
3711
  var parsedValue;
3628
3712
  return __generator(this, function (_a) {
3629
3713
  switch (_a.label) {
3630
3714
  case 0:
3631
- if (bearingStringValidator(value))
3632
- return [2 /*return*/, false];
3633
3715
  parsedValue = bearingNumberParser(value);
3634
3716
  // Value didn't change so don't save just cancel
3635
- if (parsedValue === initialValue) {
3717
+ if (parsedValue === bearingNumberParser(defaultValue)) {
3636
3718
  return [2 /*return*/, true];
3637
3719
  }
3638
3720
  if (!props.onSave) return [3 /*break*/, 2];
@@ -3651,14 +3733,15 @@ var GridFormEditBearing = function (props) {
3651
3733
  case 3: return [2 /*return*/, true];
3652
3734
  }
3653
3735
  });
3654
- }); }, [field, initialValue, props, value]);
3655
- var _c = useGridPopoverHook({
3736
+ }); }, [defaultValue, field, props, value]);
3737
+ var popoverWrapper = useGridPopoverHook({
3656
3738
  className: props.className,
3739
+ invalid: invalid,
3657
3740
  save: save
3658
- }), popoverWrapper = _c.popoverWrapper, onlyInputKeyboardEventHandlers = _c.onlyInputKeyboardEventHandlers;
3659
- return popoverWrapper(jsxRuntime.jsx("div", __assign({ className: "GridFormEditBearing-input Grid-popoverContainer" }, { children: jsxRuntime.jsx(TextInputFormatted, __assign({ value: value !== null && value !== void 0 ? value : "", onChange: function (e) {
3741
+ }).popoverWrapper;
3742
+ return popoverWrapper(jsxRuntime.jsx("div", __assign({ className: "GridFormEditBearing-input Grid-popoverContainer" }, { children: jsxRuntime.jsx(TextInputFormatted, { value: defaultValue, onChange: function (e) {
3660
3743
  setValue(e.target.value.trim());
3661
- }, autoFocus: true, placeholder: props.placeHolder }, onlyInputKeyboardEventHandlers, { formatted: bearingStringValidator(value, props.range) ? "?" : convertDDToDMS(bearingNumberParser(value)), error: bearingStringValidator(value, props.range) })) })));
3744
+ }, autoFocus: true, placeholder: props.placeHolder, formatted: bearingStringValidator(value, props.range) ? "?" : convertDDToDMS(bearingNumberParser(value)), error: bearingStringValidator(value, props.range), helpText: "Press enter or tab to save" }) })));
3662
3745
  };
3663
3746
 
3664
3747
  var GridPopoverEditBearingLike = function (colDef, props) {
@@ -3803,9 +3886,7 @@ var TextAreaInput = function (props) {
3803
3886
  e.currentTarget.selectionStart = e.currentTarget.value.length;
3804
3887
  }
3805
3888
  props.onMouseEnter && props.onMouseEnter(e);
3806
- } }, { children: props.value })) }))] })), props.error && (jsxRuntime.jsxs("span", __assign({ className: "LuiTextAreaInput-error" }, { children: [jsxRuntime.jsx(lui.LuiIcon, { alt: "error", name: "ic_error", className: "LuiTextAreaInput-error-icon", size: "sm", status: "error" }), props.error] }))), props.helpText && !props.error && (jsxRuntime.jsx("span", __assign({ style: {
3807
- fontSize: "0.7rem"
3808
- } }, { children: props.helpText })))] })));
3889
+ } }, { children: props.value })) }))] })), jsxRuntime.jsx(FormError, { error: props.error, helpText: props.helpText })] })));
3809
3890
  };
3810
3891
 
3811
3892
  var TextInputValidator = function (props, value, data) {
@@ -3837,8 +3918,6 @@ var GridFormTextArea = function (props) {
3837
3918
  return __generator(this, function (_a) {
3838
3919
  switch (_a.label) {
3839
3920
  case 0:
3840
- if (invalid())
3841
- return [2 /*return*/, false];
3842
3921
  if (initialVale === (value !== null && value !== void 0 ? value : ""))
3843
3922
  return [2 /*return*/, true];
3844
3923
  if (!props.onSave) return [3 /*break*/, 2];
@@ -3855,9 +3934,13 @@ var GridFormTextArea = function (props) {
3855
3934
  return [2 /*return*/, true];
3856
3935
  }
3857
3936
  });
3858
- }); }, [invalid, initialVale, value, props, field]);
3859
- var _e = useGridPopoverHook({ className: props.className, save: save }), popoverWrapper = _e.popoverWrapper, onlyInputKeyboardEventHandlers = _e.onlyInputKeyboardEventHandlers;
3860
- return popoverWrapper(jsxRuntime.jsx("div", __assign({ style: { display: "flex", flexDirection: "row", width: (_b = props.width) !== null && _b !== void 0 ? _b : 240 } }, { children: jsxRuntime.jsx(TextAreaInput, __assign({ value: value, onChange: function (e) { return setValue(e.target.value); }, error: invalid(), placeholder: props.placeholder, helpText: helpText }, onlyInputKeyboardEventHandlers)) })));
3937
+ }); }, [initialVale, value, props, field]);
3938
+ var popoverWrapper = useGridPopoverHook({
3939
+ className: props.className,
3940
+ invalid: invalid,
3941
+ save: save
3942
+ }).popoverWrapper;
3943
+ return popoverWrapper(jsxRuntime.jsx("div", __assign({ style: { display: "flex", flexDirection: "row", width: (_b = props.width) !== null && _b !== void 0 ? _b : 240 } }, { children: jsxRuntime.jsx(TextAreaInput, { value: value, onChange: function (e) { return setValue(e.target.value); }, error: invalid(), placeholder: props.placeholder, helpText: helpText }) })));
3861
3944
  };
3862
3945
 
3863
3946
  var GridPopoverTextArea = function (colDef, params) { return GridCell(colDef, __assign({ editor: GridFormTextArea }, params)); };
@@ -3866,7 +3949,7 @@ var GridFormTextInput = function (props) {
3866
3949
  var _a, _b;
3867
3950
  var _c = useGridPopoverContext(), field = _c.field, initialVale = _c.value, data = _c.data;
3868
3951
  var helpText = (_a = props.helpText) !== null && _a !== void 0 ? _a : "Press enter or tab to save";
3869
- var initValue = initialVale == null ? "" : "".concat(initialVale);
3952
+ var initValue = react.useMemo(function () { return (initialVale == null ? "" : "".concat(initialVale)); }, [initialVale]);
3870
3953
  var _d = react.useState(initValue), value = _d[0], setValue = _d[1];
3871
3954
  var invalid = react.useCallback(function () { return TextInputValidator(props, value, data); }, [data, props, value]);
3872
3955
  var save = react.useCallback(function (selectedRows) { return __awaiter(void 0, void 0, void 0, function () {
@@ -3894,8 +3977,12 @@ var GridFormTextInput = function (props) {
3894
3977
  }
3895
3978
  });
3896
3979
  }); }, [invalid, value, initValue, props, field]);
3897
- var _e = useGridPopoverHook({ className: props.className, save: save }), popoverWrapper = _e.popoverWrapper, onlyInputKeyboardEventHandlers = _e.onlyInputKeyboardEventHandlers;
3898
- return popoverWrapper(jsxRuntime.jsx("div", __assign({ style: { display: "flex", flexDirection: "row", width: (_b = props.width) !== null && _b !== void 0 ? _b : 240 }, className: "FormTest" }, { children: jsxRuntime.jsx(TextInputFormatted, __assign({ value: value, onChange: function (e) { return setValue(e.target.value); }, error: invalid(), formatted: props.units, style: { width: "100%" }, placeholder: props.placeholder }, onlyInputKeyboardEventHandlers, { helpText: helpText })) })));
3980
+ var popoverWrapper = useGridPopoverHook({
3981
+ className: props.className,
3982
+ invalid: invalid,
3983
+ save: save
3984
+ }).popoverWrapper;
3985
+ return popoverWrapper(jsxRuntime.jsx("div", __assign({ style: { display: "flex", flexDirection: "row", width: (_b = props.width) !== null && _b !== void 0 ? _b : 240 }, className: "FormTest" }, { children: jsxRuntime.jsx(TextInputFormatted, { value: value, onChange: function (e) { return setValue(e.target.value); }, error: invalid(), formatted: props.units, style: { width: "100%" }, placeholder: props.placeholder, helpText: helpText }) })));
3899
3986
  };
3900
3987
 
3901
3988
  var GridPopoverTextInput = function (colDef, params) {
@@ -3904,7 +3991,7 @@ var GridPopoverTextInput = function (colDef, params) {
3904
3991
 
3905
3992
  var GridFormSubComponentTextInput = function (props) {
3906
3993
  var _a;
3907
- var _b = react.useContext(GridSubComponentContext), value = _b.value, setValue = _b.setValue, setValid = _b.setValid, triggerSave = _b.triggerSave, data = _b.data;
3994
+ var _b = react.useContext(GridSubComponentContext), value = _b.value, setValue = _b.setValue, setValid = _b.setValid, data = _b.data;
3908
3995
  var helpText = (_a = props.helpText) !== null && _a !== void 0 ? _a : "Press enter or tab to save";
3909
3996
  // If is not initialised yet as it's just been created then set the default value
3910
3997
  react.useEffect(function () {
@@ -3915,30 +4002,14 @@ var GridFormSubComponentTextInput = function (props) {
3915
4002
  react.useEffect(function () {
3916
4003
  setValid(value != null && invalid() == null);
3917
4004
  }, [setValid, invalid, value]);
3918
- return (jsxRuntime.jsx(TextInputFormatted, { value: value, error: invalid(), onChange: function (e) { return setValue(e.target.value); }, helpText: helpText, autoFocus: true, onKeyDown: function (e) {
3919
- if (e.key === "Tab" || e.key === "Enter") {
3920
- e.preventDefault();
3921
- e.stopPropagation();
3922
- }
3923
- }, onKeyUp: function (e) {
3924
- if (e.key === "Tab") {
3925
- e.preventDefault();
3926
- e.stopPropagation();
3927
- !e.shiftKey && triggerSave().then();
3928
- }
3929
- else if (e.key === "Enter") {
3930
- triggerSave().then();
3931
- e.preventDefault();
3932
- e.stopPropagation();
3933
- }
3934
- }, placeholder: props.placeholder, style: {
4005
+ return (jsxRuntime.jsx(TextInputFormatted, { value: value, error: invalid(), onChange: function (e) { return setValue(e.target.value); }, helpText: helpText, autoFocus: true, placeholder: props.placeholder, style: {
3935
4006
  width: "100%"
3936
4007
  } }));
3937
4008
  };
3938
4009
 
3939
4010
  var GridFormSubComponentTextArea = function (props) {
3940
4011
  var _a;
3941
- var _b = react.useContext(GridSubComponentContext), value = _b.value, data = _b.data, setValue = _b.setValue, setValid = _b.setValid, triggerSave = _b.triggerSave;
4012
+ var _b = react.useContext(GridSubComponentContext), value = _b.value, data = _b.data, setValue = _b.setValue, setValid = _b.setValid;
3942
4013
  var helpText = (_a = props.helpText) !== null && _a !== void 0 ? _a : "Press tab to save";
3943
4014
  // If is not initialised yet as it's just been created then set the default value
3944
4015
  react.useEffect(function () {
@@ -3949,18 +4020,7 @@ var GridFormSubComponentTextArea = function (props) {
3949
4020
  react.useEffect(function () {
3950
4021
  setValid(value != null && invalid() == null);
3951
4022
  }, [setValid, invalid, value]);
3952
- return (jsxRuntime.jsx("div", __assign({ className: clsx("FreeTextInput LuiDeprecatedForms", props.className) }, { children: jsxRuntime.jsx(TextAreaInput, { className: "free-text-input", value: value, onChange: function (e) { return setValue(e.target.value); }, error: invalid(), helpText: helpText, autoFocus: true, placeholder: props.placeholder, onKeyDown: function (e) {
3953
- if (e.key === "Tab") {
3954
- e.preventDefault();
3955
- e.stopPropagation();
3956
- }
3957
- }, onKeyUp: function (e) {
3958
- if (e.key === "Tab") {
3959
- e.preventDefault();
3960
- e.stopPropagation();
3961
- !e.shiftKey && triggerSave().then();
3962
- }
3963
- } }) })));
4023
+ return (jsxRuntime.jsx("div", __assign({ className: clsx("FreeTextInput LuiDeprecatedForms", props.className) }, { children: jsxRuntime.jsx(TextAreaInput, { className: "free-text-input", value: value, onChange: function (e) { return setValue(e.target.value); }, error: invalid(), helpText: helpText, autoFocus: true, placeholder: props.placeholder }) })));
3964
4024
  };
3965
4025
 
3966
4026
  var css_248z = ".ActionButton{align-items:center;display:flex}.ActionButton .LuiIcon{margin:0 4px!important}.ActionButton-minimalArea{position:relative}.ActionButton-minimalAreaDisplay{position:absolute}.ActionButton-minimalAreaExpand{visibility:hidden}.ActionButton-inProgress{background-color:#e2f3f7!important;color:#007198!important;cursor:progress}.ActionButton-inProgress svg *{fill:#0000!important}";