@linzjs/step-ag-grid 23.0.0 → 24.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 (274) hide show
  1. package/dist/src/components/ComponentLoadingWrapper.d.ts +1 -1
  2. package/dist/src/components/Grid.d.ts +17 -17
  3. package/dist/src/components/GridCell.d.ts +9 -9
  4. package/dist/src/components/GridCellFiller.d.ts +2 -2
  5. package/dist/src/components/GridCellMultiEditor.d.ts +6 -6
  6. package/dist/src/components/GridCellMultiSelectClassRules.d.ts +1 -1
  7. package/dist/src/components/GridIcon.d.ts +2 -2
  8. package/dist/src/components/GridNoRowsOverlay.d.ts +1 -1
  9. package/dist/src/components/GridPopoverHook.d.ts +2 -2
  10. package/dist/src/components/GridWrapper.d.ts +1 -1
  11. package/dist/src/components/PostSortRowsHook.d.ts +1 -1
  12. package/dist/src/components/clickInputWhenContainingCellClicked.d.ts +1 -1
  13. package/dist/src/components/gridFilter/GridFilterButtons.d.ts +5 -5
  14. package/dist/src/components/gridFilter/GridFilterColumnsToggle.d.ts +1 -1
  15. package/dist/src/components/gridFilter/GridFilterDownloadCsvButton.d.ts +1 -1
  16. package/dist/src/components/gridFilter/GridFilterHeaderIconButton.d.ts +2 -2
  17. package/dist/src/components/gridFilter/GridFilters.d.ts +1 -1
  18. package/dist/src/components/gridFilter/index.d.ts +7 -7
  19. package/dist/src/components/gridFilter/useGridFilter.d.ts +2 -2
  20. package/dist/src/components/gridForm/GridFormDropDown.d.ts +8 -8
  21. package/dist/src/components/gridForm/GridFormEditBearing.d.ts +2 -2
  22. package/dist/src/components/gridForm/GridFormMessage.d.ts +3 -3
  23. package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +4 -4
  24. package/dist/src/components/gridForm/GridFormMultiSelectGrid.d.ts +4 -4
  25. package/dist/src/components/gridForm/GridFormPopoverMenu.d.ts +5 -5
  26. package/dist/src/components/gridForm/GridFormSubComponentTextArea.d.ts +4 -4
  27. package/dist/src/components/gridForm/GridFormSubComponentTextInput.d.ts +4 -4
  28. package/dist/src/components/gridForm/GridFormTextArea.d.ts +4 -4
  29. package/dist/src/components/gridForm/GridFormTextInput.d.ts +3 -3
  30. package/dist/src/components/gridForm/index.d.ts +10 -10
  31. package/dist/src/components/gridHeader/GridHeaderSelect.d.ts +1 -1
  32. package/dist/src/components/gridHeader/index.d.ts +1 -1
  33. package/dist/src/components/gridHook/index.d.ts +1 -1
  34. package/dist/src/components/gridHook/useGridContextMenu.d.ts +4 -4
  35. package/dist/src/components/gridPopoverEdit/GridButton.d.ts +5 -5
  36. package/dist/src/components/gridPopoverEdit/GridEditBoolean.d.ts +4 -4
  37. package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.d.ts +4 -4
  38. package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelectGrid.d.ts +4 -4
  39. package/dist/src/components/gridPopoverEdit/GridPopoverEditBearing.d.ts +4 -4
  40. package/dist/src/components/gridPopoverEdit/GridPopoverEditDropDown.d.ts +4 -4
  41. package/dist/src/components/gridPopoverEdit/GridPopoverMenu.d.ts +4 -4
  42. package/dist/src/components/gridPopoverEdit/GridPopoverMessage.d.ts +4 -4
  43. package/dist/src/components/gridPopoverEdit/GridPopoverTextArea.d.ts +4 -4
  44. package/dist/src/components/gridPopoverEdit/GridPopoverTextInput.d.ts +4 -4
  45. package/dist/src/components/gridPopoverEdit/index.d.ts +11 -11
  46. package/dist/src/components/gridRender/GridRenderGenericCell.d.ts +5 -5
  47. package/dist/src/components/gridRender/GridRenderPopoutMenuCell.d.ts +1 -1
  48. package/dist/src/components/gridRender/index.d.ts +2 -2
  49. package/dist/src/components/gridUtil.d.ts +1 -1
  50. package/dist/src/components/index.d.ts +19 -19
  51. package/dist/src/contexts/GridContext.d.ts +4 -4
  52. package/dist/src/contexts/GridContextProvider.d.ts +3 -3
  53. package/dist/src/contexts/GridPopoverContext.d.ts +3 -3
  54. package/dist/src/contexts/GridPopoverContextProvider.d.ts +4 -4
  55. package/dist/src/contexts/GridUpdatingContextProvider.d.ts +1 -1
  56. package/dist/src/index.d.ts +17 -17
  57. package/dist/src/lui/ActionButton.d.ts +9 -9
  58. package/dist/src/lui/FormError.d.ts +2 -2
  59. package/dist/src/lui/TextAreaInput.d.ts +1 -1
  60. package/dist/src/lui/TextInputFormatted.d.ts +2 -2
  61. package/dist/src/lui/reactUtils.d.ts +1 -1
  62. package/dist/src/lui/stateDeferredHook.d.ts +1 -1
  63. package/dist/src/react-menu3/components/ControlledMenu.d.ts +2 -2
  64. package/dist/src/react-menu3/components/FocusableItem.d.ts +3 -3
  65. package/dist/src/react-menu3/components/Menu.d.ts +3 -3
  66. package/dist/src/react-menu3/components/MenuButton.d.ts +2 -2
  67. package/dist/src/react-menu3/components/MenuDivider.d.ts +1 -1
  68. package/dist/src/react-menu3/components/MenuGroup.d.ts +2 -2
  69. package/dist/src/react-menu3/components/MenuHeader.d.ts +2 -2
  70. package/dist/src/react-menu3/components/MenuItem.d.ts +3 -3
  71. package/dist/src/react-menu3/components/MenuList.d.ts +1 -1
  72. package/dist/src/react-menu3/components/MenuRadioGroup.d.ts +2 -2
  73. package/dist/src/react-menu3/components/SubMenu.d.ts +5 -5
  74. package/dist/src/react-menu3/contexts/EventHandlersContext.d.ts +1 -1
  75. package/dist/src/react-menu3/contexts/MenuListContext.d.ts +2 -2
  76. package/dist/src/react-menu3/contexts/MenuListItemContext.d.ts +1 -1
  77. package/dist/src/react-menu3/contexts/RadioGroupContext.d.ts +1 -1
  78. package/dist/src/react-menu3/contexts/SettingsContext.d.ts +2 -2
  79. package/dist/src/react-menu3/hooks/index.d.ts +9 -9
  80. package/dist/src/react-menu3/hooks/useBEM.d.ts +1 -1
  81. package/dist/src/react-menu3/hooks/useCombinedRef.d.ts +1 -1
  82. package/dist/src/react-menu3/hooks/useIsomorphicLayoutEffect.d.ts +1 -1
  83. package/dist/src/react-menu3/hooks/useItemEffect.d.ts +1 -1
  84. package/dist/src/react-menu3/hooks/useItemState.d.ts +1 -1
  85. package/dist/src/react-menu3/hooks/useItems.d.ts +2 -2
  86. package/dist/src/react-menu3/hooks/useMenuChange.d.ts +1 -1
  87. package/dist/src/react-menu3/hooks/useMenuState.d.ts +1 -1
  88. package/dist/src/react-menu3/hooks/useMenuStateAndFocus.d.ts +1 -1
  89. package/dist/src/react-menu3/index.d.ts +11 -11
  90. package/dist/src/react-menu3/positionUtils/getPositionHelpers.d.ts +1 -1
  91. package/dist/src/react-menu3/positionUtils/index.d.ts +3 -3
  92. package/dist/src/react-menu3/positionUtils/placeArrowHorizontal.d.ts +1 -1
  93. package/dist/src/react-menu3/positionUtils/placeArrowVertical.d.ts +1 -1
  94. package/dist/src/react-menu3/positionUtils/placeLeftorRight.d.ts +4 -4
  95. package/dist/src/react-menu3/positionUtils/placeToporBottom.d.ts +5 -5
  96. package/dist/src/react-menu3/positionUtils/positionContextMenu.d.ts +2 -2
  97. package/dist/src/react-menu3/positionUtils/positionMenu.d.ts +5 -5
  98. package/dist/src/react-menu3/style-utils/index.d.ts +1 -1
  99. package/dist/src/react-menu3/types.d.ts +15 -15
  100. package/dist/src/react-menu3/utils/constants.d.ts +1 -1
  101. package/dist/src/react-menu3/utils/index.d.ts +3 -3
  102. package/dist/src/react-menu3/utils/utils.d.ts +5 -5
  103. package/dist/src/react-menu3/utils/withHovering.d.ts +1 -1
  104. package/dist/src/utils/testQuick.d.ts +2 -2
  105. package/dist/src/utils/testUtil.d.ts +2 -2
  106. package/dist/src/utils/textValidator.d.ts +2 -2
  107. package/dist/step-ag-grid.cjs.js +966 -952
  108. package/dist/step-ag-grid.cjs.js.map +1 -1
  109. package/dist/step-ag-grid.esm.js +968 -954
  110. package/dist/step-ag-grid.esm.js.map +1 -1
  111. package/package.json +26 -41
  112. package/src/components/ComponentLoadingWrapper.tsx +5 -6
  113. package/src/components/Grid.tsx +85 -83
  114. package/src/components/GridCell.test.tsx +15 -15
  115. package/src/components/GridCell.tsx +46 -44
  116. package/src/components/GridCellFiller.tsx +5 -4
  117. package/src/components/GridCellMultiEditor.tsx +7 -7
  118. package/src/components/GridCellMultiSelectClassRules.tsx +3 -3
  119. package/src/components/GridIcon.tsx +6 -7
  120. package/src/components/GridLoadableCell.tsx +2 -2
  121. package/src/components/GridNoRowsOverlay.tsx +8 -8
  122. package/src/components/GridPopoverHook.tsx +16 -16
  123. package/src/components/GridWrapper.tsx +2 -2
  124. package/src/components/PostSortRowsHook.ts +11 -11
  125. package/src/components/clickInputWhenContainingCellClicked.tsx +5 -5
  126. package/src/components/gridFilter/GridFilterButtons.tsx +8 -9
  127. package/src/components/gridFilter/GridFilterColumnsToggle.tsx +25 -26
  128. package/src/components/gridFilter/GridFilterDownloadCsvButton.tsx +12 -13
  129. package/src/components/gridFilter/GridFilterHeaderIconButton.tsx +9 -10
  130. package/src/components/gridFilter/GridFilterQuick.tsx +6 -6
  131. package/src/components/gridFilter/GridFilters.tsx +1 -1
  132. package/src/components/gridFilter/index.ts +7 -7
  133. package/src/components/gridFilter/useGridFilter.ts +3 -3
  134. package/src/components/gridForm/GridFormDropDown.tsx +56 -52
  135. package/src/components/gridForm/GridFormEditBearing.tsx +12 -12
  136. package/src/components/gridForm/GridFormMessage.tsx +10 -10
  137. package/src/components/gridForm/GridFormMultiSelect.tsx +53 -51
  138. package/src/components/gridForm/GridFormMultiSelectGrid.tsx +25 -26
  139. package/src/components/gridForm/GridFormPopoverMenu.tsx +32 -29
  140. package/src/components/gridForm/GridFormSubComponentTextArea.tsx +10 -10
  141. package/src/components/gridForm/GridFormSubComponentTextInput.tsx +8 -8
  142. package/src/components/gridForm/GridFormTextArea.tsx +11 -11
  143. package/src/components/gridForm/GridFormTextInput.tsx +11 -11
  144. package/src/components/gridForm/index.ts +10 -10
  145. package/src/components/gridHeader/GridHeaderSelect.tsx +9 -9
  146. package/src/components/gridHeader/index.ts +1 -1
  147. package/src/components/gridHook/index.ts +1 -1
  148. package/src/components/gridHook/useGridContextMenu.tsx +7 -7
  149. package/src/components/gridPopoverEdit/GridButton.tsx +13 -12
  150. package/src/components/gridPopoverEdit/GridEditBoolean.tsx +19 -18
  151. package/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.ts +7 -6
  152. package/src/components/gridPopoverEdit/GridPopoutEditMultiSelectGrid.ts +7 -6
  153. package/src/components/gridPopoverEdit/GridPopoverEditBearing.ts +9 -9
  154. package/src/components/gridPopoverEdit/GridPopoverEditDropDown.ts +8 -7
  155. package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +6 -6
  156. package/src/components/gridPopoverEdit/GridPopoverMessage.ts +4 -4
  157. package/src/components/gridPopoverEdit/GridPopoverTextArea.ts +4 -4
  158. package/src/components/gridPopoverEdit/GridPopoverTextInput.ts +4 -4
  159. package/src/components/gridPopoverEdit/index.ts +11 -11
  160. package/src/components/gridRender/GridRenderGenericCell.tsx +5 -5
  161. package/src/components/gridRender/GridRenderPopoutMenuCell.tsx +8 -9
  162. package/src/components/gridRender/index.ts +2 -2
  163. package/src/components/gridUtil.ts +3 -3
  164. package/src/components/index.ts +19 -19
  165. package/src/contexts/GridContext.tsx +52 -46
  166. package/src/contexts/GridContextProvider.test.tsx +14 -14
  167. package/src/contexts/GridContextProvider.tsx +42 -41
  168. package/src/contexts/GridPopoverContext.tsx +10 -7
  169. package/src/contexts/GridPopoverContextProvider.tsx +12 -10
  170. package/src/contexts/GridSubComponentContext.ts +6 -5
  171. package/src/contexts/GridUpdatingContext.tsx +5 -4
  172. package/src/contexts/GridUpdatingContextProvider.tsx +3 -3
  173. package/src/index.ts +17 -21
  174. package/src/lui/ActionButton.tsx +42 -41
  175. package/src/lui/FormError.tsx +4 -4
  176. package/src/lui/TextAreaInput.tsx +9 -9
  177. package/src/lui/TextInputFormatted.tsx +11 -11
  178. package/src/lui/reactUtils.test.tsx +8 -8
  179. package/src/lui/reactUtils.tsx +2 -2
  180. package/src/lui/stateDeferredHook.tsx +3 -5
  181. package/src/lui/timeoutHook.test.tsx +5 -5
  182. package/src/lui/timeoutHook.tsx +1 -1
  183. package/src/react-app-env.d.ts +1 -1
  184. package/src/react-menu3/components/ControlledMenu.tsx +48 -48
  185. package/src/react-menu3/components/FocusableItem.tsx +7 -7
  186. package/src/react-menu3/components/Menu.tsx +11 -11
  187. package/src/react-menu3/components/MenuButton.tsx +4 -4
  188. package/src/react-menu3/components/MenuDivider.tsx +4 -4
  189. package/src/react-menu3/components/MenuGroup.tsx +5 -5
  190. package/src/react-menu3/components/MenuHeader.tsx +4 -4
  191. package/src/react-menu3/components/MenuItem.tsx +14 -14
  192. package/src/react-menu3/components/MenuList.tsx +55 -55
  193. package/src/react-menu3/components/MenuRadioGroup.tsx +7 -7
  194. package/src/react-menu3/components/SubMenu.tsx +24 -24
  195. package/src/react-menu3/contexts/EventHandlersContext.ts +2 -2
  196. package/src/react-menu3/contexts/HoverItemContext.ts +1 -1
  197. package/src/react-menu3/contexts/ItemSettingsContext.ts +1 -1
  198. package/src/react-menu3/contexts/MenuListContext.ts +2 -2
  199. package/src/react-menu3/contexts/MenuListItemContext.ts +2 -2
  200. package/src/react-menu3/contexts/RadioGroupContext.ts +2 -2
  201. package/src/react-menu3/contexts/SettingsContext.ts +2 -2
  202. package/src/react-menu3/hooks/index.ts +9 -9
  203. package/src/react-menu3/hooks/useBEM.ts +4 -4
  204. package/src/react-menu3/hooks/useCombinedRef.ts +2 -2
  205. package/src/react-menu3/hooks/useIsomorphicLayoutEffect.ts +4 -4
  206. package/src/react-menu3/hooks/useItemEffect.ts +3 -3
  207. package/src/react-menu3/hooks/useItemState.ts +5 -5
  208. package/src/react-menu3/hooks/useItems.ts +8 -8
  209. package/src/react-menu3/hooks/useMenuChange.ts +3 -3
  210. package/src/react-menu3/hooks/useMenuState.ts +5 -5
  211. package/src/react-menu3/hooks/useMenuStateAndFocus.ts +4 -4
  212. package/src/react-menu3/index.ts +11 -11
  213. package/src/react-menu3/positionUtils/getPositionHelpers.ts +2 -2
  214. package/src/react-menu3/positionUtils/index.ts +3 -3
  215. package/src/react-menu3/positionUtils/placeArrowHorizontal.ts +1 -1
  216. package/src/react-menu3/positionUtils/placeArrowVertical.ts +1 -1
  217. package/src/react-menu3/positionUtils/placeLeftorRight.ts +13 -13
  218. package/src/react-menu3/positionUtils/placeToporBottom.ts +15 -15
  219. package/src/react-menu3/positionUtils/positionContextMenu.ts +4 -4
  220. package/src/react-menu3/positionUtils/positionMenu.ts +14 -14
  221. package/src/react-menu3/style-utils/index.ts +24 -24
  222. package/src/react-menu3/types.ts +15 -15
  223. package/src/react-menu3/utils/constants.ts +33 -33
  224. package/src/react-menu3/utils/index.ts +3 -4
  225. package/src/react-menu3/utils/propTypes2.ts +10 -10
  226. package/src/react-menu3/utils/utils.ts +14 -14
  227. package/src/react-menu3/utils/withHovering.tsx +3 -3
  228. package/src/stories/components/ActionButton.stories.tsx +23 -24
  229. package/src/stories/grid/FormTest.tsx +15 -16
  230. package/src/stories/grid/GridDragRow.stories.tsx +33 -34
  231. package/src/stories/grid/GridFilterButtons.stories.tsx +32 -33
  232. package/src/stories/grid/GridNoRowsOverlay.stories.tsx +9 -10
  233. package/src/stories/grid/GridNonEditableRow.stories.tsx +40 -41
  234. package/src/stories/grid/GridPinnedRow.stories.tsx +25 -26
  235. package/src/stories/grid/GridPopoutContextMenu.stories.tsx +33 -32
  236. package/src/stories/grid/GridPopoutEditBoolean.stories.tsx +21 -22
  237. package/src/stories/grid/GridPopoutEditGeneric.stories.tsx +18 -19
  238. package/src/stories/grid/GridPopoutEditGenericTextArea.stories.tsx +50 -49
  239. package/src/stories/grid/GridPopoverEditBearing.stories.tsx +25 -26
  240. package/src/stories/grid/GridPopoverEditDropDown.stories.tsx +93 -94
  241. package/src/stories/grid/GridPopoverEditMultiSelect.stories.tsx +62 -63
  242. package/src/stories/grid/GridPopoverEditMultiSelectGrid.stories.tsx +28 -28
  243. package/src/stories/grid/GridReadOnly.stories.tsx +66 -67
  244. package/src/stories/grid/GridViewList.stories.tsx +37 -38
  245. package/src/stories/grid/gridFormInteraction/GridFormDropDownInteraction.stories.tsx +37 -38
  246. package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx +25 -26
  247. package/src/stories/grid/gridFormInteraction/GridFormEditBearingInteraction.stories.tsx +25 -26
  248. package/src/stories/grid/gridFormInteraction/GridFormMultiSelectGridInteraction.stories.tsx +31 -31
  249. package/src/stories/grid/gridFormInteraction/GridFormMultiSelectInteraction.stories.tsx +47 -48
  250. package/src/stories/grid/gridFormInteraction/GridFormPopoverMenuInteraction.stories.tsx +44 -45
  251. package/src/stories/grid/gridFormInteraction/GridFormTextAreaInteraction.stories.tsx +19 -20
  252. package/src/stories/grid/gridFormInteraction/GridFormTextInputInteraction.stories.tsx +21 -22
  253. package/src/stories/grid/gridFormStatic/GridFormDropDown.stories.tsx +40 -41
  254. package/src/stories/grid/gridFormStatic/GridFormEditBearing.stories.tsx +14 -15
  255. package/src/stories/grid/gridFormStatic/GridFormEditBearingCorrection.stories.tsx +14 -15
  256. package/src/stories/grid/gridFormStatic/GridFormMessage.stories.tsx +10 -11
  257. package/src/stories/grid/gridFormStatic/GridFormMultiSelect.stories.tsx +20 -21
  258. package/src/stories/grid/gridFormStatic/GridFormPopoverMenu.stories.tsx +16 -17
  259. package/src/stories/grid/gridFormStatic/GridFormTextArea.stories.tsx +13 -14
  260. package/src/stories/grid/gridFormStatic/GridFormTextInput.stories.tsx +13 -14
  261. package/src/stories/grid/interactions/GridKeyboardInteractions.stories.tsx +68 -71
  262. package/src/stories/react-menu/ReactMenu.stories.tsx +26 -26
  263. package/src/utils/bearing.test.ts +44 -44
  264. package/src/utils/bearing.ts +20 -20
  265. package/src/utils/deferredPromise.ts +1 -1
  266. package/src/utils/storybookTestUtil.ts +2 -2
  267. package/src/utils/testQuick.ts +15 -14
  268. package/src/utils/testUtil.ts +31 -36
  269. package/src/utils/textMatcher.test.ts +9 -9
  270. package/src/utils/textMatcher.ts +8 -8
  271. package/src/utils/textValidator.test.ts +56 -56
  272. package/src/utils/textValidator.ts +11 -11
  273. package/src/utils/util.test.ts +20 -20
  274. package/src/utils/util.ts +7 -7
@@ -8,11 +8,43 @@ var lodashEs = require('lodash-es');
8
8
  var React = require('react');
9
9
  var reactDom = require('react-dom');
10
10
 
11
+ /**
12
+ * AgGrid checkbox select does not pass clicks within cell but not on the checkbox to checkbox.
13
+ * This passes the event to the checkbox when you click anywhere in the cell.
14
+ */
15
+ const clickInputWhenContainingCellClicked = (params) => {
16
+ const { data, event, colDef } = params;
17
+ if (!data || !event)
18
+ return;
19
+ const element = event.target;
20
+ // Already handled
21
+ if (element.closest('.GridCell-readonly') ||
22
+ (['BUTTON', 'INPUT'].includes(element?.tagName) && element.closest('.ag-cell-inline-editing'))) {
23
+ return;
24
+ }
25
+ const row = element.closest('[row-id]');
26
+ if (!row)
27
+ return;
28
+ const colId = colDef.colId;
29
+ if (!colId)
30
+ return;
31
+ const clickInput = () => {
32
+ const cell = row.querySelector(`[col-id='${colId}']`);
33
+ if (!cell)
34
+ return;
35
+ const input = cell.querySelector('input, button');
36
+ if (!input)
37
+ return;
38
+ input?.dispatchEvent(event);
39
+ };
40
+ setTimeout(clickInput, 20);
41
+ };
42
+
11
43
  /**
12
44
  * If loading is true this returns a loading spinner, otherwise it returns its children.
13
45
  */
14
46
  const ComponentLoadingWrapper = (props) => {
15
- return props.loading ? (jsxRuntime.jsx(lui.LuiMiniSpinner, { size: 22, divProps: { role: "status", ["aria-label"]: "Loading", style: { padding: 16 } } })) : (jsxRuntime.jsxs("div", { style: { pointerEvents: props.saving ? "none" : "inherit" }, className: props.className, children: [props.saving && jsxRuntime.jsx("div", { className: "ComponentLoadingWrapper-saveOverlay" }), props.children] }));
47
+ return props.loading ? (jsxRuntime.jsx(lui.LuiMiniSpinner, { size: 22, divProps: { role: 'status', ['aria-label']: 'Loading', style: { padding: 16 } } })) : (jsxRuntime.jsxs("div", { style: { pointerEvents: props.saving ? 'none' : 'inherit' }, className: props.className, children: [props.saving && jsxRuntime.jsx("div", { className: 'ComponentLoadingWrapper-saveOverlay' }), props.children] }));
16
48
  };
17
49
 
18
50
  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)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
@@ -61,153 +93,160 @@ const GridContext = React.createContext({
61
93
  gridReady: false,
62
94
  gridRenderState: () => null,
63
95
  getColDef: () => {
64
- console.error("no context provider for getColDef");
96
+ console.error('no context provider for getColDef');
65
97
  return undefined;
66
98
  },
67
99
  getColumns: () => {
68
- console.error("no context provider for getColumns");
100
+ console.error('no context provider for getColumns');
69
101
  return [];
70
102
  },
71
103
  getColumnIds: () => {
72
- console.error("no context provider for getColumnIds");
104
+ console.error('no context provider for getColumnIds');
73
105
  return [];
74
106
  },
75
107
  invisibleColumnIds: undefined,
76
108
  setInvisibleColumnIds: () => {
77
- console.error("no context provider for setInvisibleColumnIds");
109
+ console.error('no context provider for setInvisibleColumnIds');
78
110
  },
79
111
  prePopupOps: () => {
80
- console.error("no context provider for prePopupOps");
112
+ console.error('no context provider for prePopupOps');
81
113
  },
82
114
  postPopupOps: () => {
83
- console.error("no context provider for prePopupOps");
115
+ console.error('no context provider for prePopupOps');
84
116
  },
85
117
  externallySelectedItemsAreInSync: false,
86
118
  setApis: () => {
87
- console.error("no context provider for setApis");
119
+ console.error('no context provider for setApis');
88
120
  },
89
121
  setQuickFilter: () => {
90
- console.error("no context provider for setQuickFilter");
122
+ console.error('no context provider for setQuickFilter');
91
123
  },
92
124
  selectRowsById: () => {
93
- console.error("no context provider for selectRows");
125
+ console.error('no context provider for selectRows');
94
126
  },
95
127
  getSelectedRows: () => {
96
- console.error("no context provider for getSelectedRows");
128
+ console.error('no context provider for getSelectedRows');
97
129
  return [];
98
130
  },
99
131
  getFilteredSelectedRows: () => {
100
- console.error("no context provider for getFilteredSelectedRows");
132
+ console.error('no context provider for getFilteredSelectedRows');
101
133
  return [];
102
134
  },
103
135
  getSelectedRowIds: () => {
104
- console.error("no context provider for getSelectedRowIds");
136
+ console.error('no context provider for getSelectedRowIds');
105
137
  return [];
106
138
  },
107
139
  getFilteredSelectedRowIds: () => {
108
- console.error("no context provider for getFilteredSelectedRowIds");
140
+ console.error('no context provider for getFilteredSelectedRowIds');
109
141
  return [];
110
142
  },
143
+ // eslint-disable-next-line @typescript-eslint/require-await
111
144
  selectRowsDiff: async () => {
112
- console.error("no context provider for selectRowsDiff");
145
+ console.error('no context provider for selectRowsDiff');
113
146
  },
114
147
  selectRowsByIdWithFlash: () => {
115
- console.error("no context provider for selectRowsWithFlash");
148
+ console.error('no context provider for selectRowsWithFlash');
116
149
  },
150
+ // eslint-disable-next-line @typescript-eslint/require-await
117
151
  selectRowsWithFlashDiff: async () => {
118
- console.error("no context provider for selectRowsWithFlashDiff");
152
+ console.error('no context provider for selectRowsWithFlashDiff');
119
153
  },
120
154
  flashRows: () => {
121
- console.error("no context provider for flashRows");
155
+ console.error('no context provider for flashRows');
122
156
  },
157
+ // eslint-disable-next-line @typescript-eslint/require-await
123
158
  flashRowsDiff: async () => {
124
- console.error("no context provider for flashRows");
159
+ console.error('no context provider for flashRows');
125
160
  },
161
+ // eslint-disable-next-line @typescript-eslint/require-await,@typescript-eslint/no-misused-promises
126
162
  focusByRowById: async () => {
127
- console.error("no context provider for focusByRowById");
163
+ console.error('no context provider for focusByRowById');
128
164
  },
129
165
  ensureRowVisible: () => {
130
- console.error("no context provider for ensureRowVisible");
166
+ console.error('no context provider for ensureRowVisible');
131
167
  return true;
132
168
  },
133
169
  ensureSelectedRowIsVisible: () => {
134
- console.error("no context provider for ensureSelectedRowIsVisible");
170
+ console.error('no context provider for ensureSelectedRowIsVisible');
135
171
  },
136
172
  getFirstRowId: () => {
137
- console.error("no context provider for getFirstRowId");
173
+ console.error('no context provider for getFirstRowId');
138
174
  return -1;
139
175
  },
140
176
  autoSizeColumns: () => {
141
- console.error("no context provider for autoSizeColumns");
177
+ console.error('no context provider for autoSizeColumns');
142
178
  return null;
143
179
  },
144
180
  sizeColumnsToFit: () => {
145
- console.error("no context provider for autoSizeAllColumns");
181
+ console.error('no context provider for autoSizeAllColumns');
146
182
  return null;
147
183
  },
148
184
  editingCells: () => {
149
- console.error("no context provider for editingCells");
185
+ console.error('no context provider for editingCells');
150
186
  return false;
151
187
  },
152
188
  cancelEdit: () => {
153
- console.error("no context provider for cancelEdit");
189
+ console.error('no context provider for cancelEdit');
154
190
  },
155
191
  startCellEditing: () => {
156
- console.error("no context provider for startCellEditing");
192
+ console.error('no context provider for startCellEditing');
157
193
  },
158
194
  stopEditing: () => {
159
- console.error("no context provider for stopEditing");
195
+ console.error('no context provider for stopEditing');
160
196
  },
197
+ // eslint-disable-next-line @typescript-eslint/require-await
161
198
  updatingCells: async () => {
162
- console.error("no context provider for modifyUpdating");
199
+ console.error('no context provider for modifyUpdating');
163
200
  return false;
164
201
  },
165
202
  redrawRows: () => {
166
- console.error("no context provider for redrawRows");
203
+ console.error('no context provider for redrawRows');
167
204
  },
168
205
  setExternallySelectedItemsAreInSync: () => {
169
- console.error("no context provider for setExternallySelectedItemsAreInSync");
206
+ console.error('no context provider for setExternallySelectedItemsAreInSync');
170
207
  },
208
+ // eslint-disable-next-line @typescript-eslint/require-await
171
209
  waitForExternallySelectedItemsToBeInSync: async () => {
172
- console.error("no context provider for waitForExternallySelectedItemsToBeInSync");
210
+ console.error('no context provider for waitForExternallySelectedItemsToBeInSync');
173
211
  },
174
212
  addExternalFilter: () => {
175
- console.error("no context provider for addExternalFilter");
213
+ console.error('no context provider for addExternalFilter');
176
214
  },
177
215
  removeExternalFilter: () => {
178
- console.error("no context provider for removeExternalFilter");
216
+ console.error('no context provider for removeExternalFilter');
179
217
  },
180
218
  isExternalFilterPresent: () => {
181
- console.error("no context provider for isExternalFilterPresent");
219
+ console.error('no context provider for isExternalFilterPresent');
182
220
  return false;
183
221
  },
184
222
  doesExternalFilterPass: () => {
185
- console.error("no context provider for doesExternalFilterPass");
223
+ console.error('no context provider for doesExternalFilterPass');
186
224
  return true;
187
225
  },
188
226
  downloadCsv: () => {
189
- console.error("no context provider for downloadCsv");
227
+ console.error('no context provider for downloadCsv');
190
228
  },
191
229
  setOnCellEditingComplete: () => {
192
- console.error("no context provider for setOnCellEditingComplete");
230
+ console.error('no context provider for setOnCellEditingComplete');
193
231
  },
194
232
  showNoRowsOverlay: () => {
195
- console.error("no context provider for showLoadingOverlay");
233
+ console.error('no context provider for showLoadingOverlay');
196
234
  },
197
235
  });
198
236
  const useGridContext = () => React.useContext(GridContext);
199
237
 
200
238
  const GridUpdatingContext = React.createContext({
201
239
  checkUpdating: () => {
202
- console.error("Missing GridUpdatingContext");
240
+ console.error('Missing GridUpdatingContext');
203
241
  return false;
204
242
  },
205
243
  updatingCols: () => {
206
- console.error("Missing GridUpdatingContext");
244
+ console.error('Missing GridUpdatingContext');
207
245
  return [];
208
246
  },
247
+ // eslint-disable-next-line @typescript-eslint/require-await
209
248
  modifyUpdating: async () => {
210
- console.error("Missing GridUpdatingContext");
249
+ console.error('Missing GridUpdatingContext');
211
250
  },
212
251
  updatedDep: 0,
213
252
  });
@@ -249,196 +288,19 @@ const hasParentClass = function (className, child) {
249
288
  return false;
250
289
  };
251
290
  const stringByteLengthIsInvalid = (str, maxBytes) => new TextEncoder().encode(str).length > maxBytes;
252
- const fnOrVar = (fn, param) => (typeof fn === "function" ? fn(param) : fn);
291
+ const fnOrVar = (fn, param) => (typeof fn === 'function' ? fn(param) : fn);
253
292
  const sanitiseFileName = (filename) => {
254
293
  const valid = filename
255
294
  .trim()
256
- .replaceAll(/(\/|\\)+/g, "-")
257
- .replaceAll(/\s+/g, "_")
258
- .replaceAll(/[^\w\-āēīōūĀĒĪŌŪ.]/g, "");
259
- const parts = valid.split(".");
295
+ .replaceAll(/(\/|\\)+/g, '-')
296
+ .replaceAll(/\s+/g, '_')
297
+ .replaceAll(/[^\w\-āēīōūĀĒĪŌŪ.]/g, '');
298
+ const parts = valid.split('.');
260
299
  const fileExt = parts.length > 1 ? parts.pop() : undefined;
261
300
  // Arbitrary max filename length of 64 chars + extension
262
301
  if (!fileExt)
263
302
  return valid.slice().slice(0, 64);
264
- return valid.slice(0, -fileExt.length - 1).slice(0, 64) + "." + fileExt;
265
- };
266
-
267
- const GridLoadingOverlayComponentFr = (props, externalRef) => (jsxRuntime.jsx("div", { ref: externalRef, style: {
268
- left: 0,
269
- top: 0,
270
- bottom: 0,
271
- right: 0,
272
- position: "absolute",
273
- backgroundColor: "rgba(255,255,255,0.5)",
274
- }, children: jsxRuntime.jsx("div", { style: { height: "100%", position: "relative" }, children: jsxRuntime.jsx("div", { style: { position: "absolute", left: 0, top: props.headerRowHeight, right: 0, bottom: 0 }, children: jsxRuntime.jsx(lui.LuiStatusSpinner, {}) }) }) }));
275
- const GridLoadingOverlayComponent = React.forwardRef(GridLoadingOverlayComponentFr);
276
- const GridNoRowsOverlayFr = (props, externalRef) => {
277
- if (props.loading) {
278
- return jsxRuntime.jsx(GridLoadingOverlayComponent, { ref: externalRef, headerRowHeight: props.headerRowHeight });
279
- }
280
- if (props.rowCount === 0) {
281
- return jsxRuntime.jsx("div", { ref: externalRef, children: props.noRowsOverlayText ?? "There are currently no rows" });
282
- }
283
- if (props.filteredRowCount === 0) {
284
- return jsxRuntime.jsx("div", { ref: externalRef, children: props.noRowsMatchingOverlayText ?? "All rows have been filtered" });
285
- }
286
- return jsxRuntime.jsx("div", { ref: externalRef });
287
- };
288
- const GridNoRowsOverlay = React.forwardRef(GridNoRowsOverlayFr);
289
-
290
- /**
291
- * Retains last sort order from via <AgGrid postRowSort>.
292
- * Then applies this sort until next sort column change.
293
- * Handles stale sort, when you edit a row but don't want to re-sort.
294
- */
295
- const usePostSortRowsHook = ({ setStaleGrid }) => {
296
- const { redrawRows } = React.useContext(GridContext);
297
- // On first run we need to init the first backed up sort order
298
- const initialised = React.useRef(false);
299
- // Used to detect sort order has changed since last run
300
- const lastSortOrderHash = React.useRef("");
301
- // Used to detect if sort order was the same, has the direction changed
302
- const previousRowSortIndexRef = React.useRef({});
303
- // stale sort is when there's a sort and user edits a row
304
- // this applies a class to the div wrapping the grid which in turn adds a * beside the sort arrow
305
- const sortWasStale = React.useRef(false);
306
- // Previous col sort is stored and reapplied if the sort direction changes on the same column and the sort was stale
307
- // As a sort on a stale row should just resort, not change sort direction
308
- const previousColSort = React.useRef([]);
309
- const previousQuickFilter = React.useRef("");
310
- return React.useCallback(({ api, nodes }) => {
311
- // Grid is destroyed
312
- if (!api)
313
- return;
314
- const previousRowSortIndex = previousRowSortIndexRef.current;
315
- const hashNode = (node) => {
316
- return node ? JSON.stringify(node.data) : "";
317
- };
318
- const copyCurrentSortSettings = () => api.getColumnState().map((row) => ({ colId: row.colId, sort: row.sort, sortIndex: row.sortIndex }));
319
- const backupSortOrder = () => {
320
- for (const x in previousRowSortIndex)
321
- delete previousRowSortIndex[x];
322
- nodes.forEach((node, index) => (previousRowSortIndex[`${node.data.id}`] = { index, hash: hashNode(node) }));
323
- };
324
- // Check if column is the first sorted column. Note: column is preconfigured to sort its sortIndex is null not 1
325
- const isFirstSortColumn = (row) => row.sort && [0, null].includes(row.sortIndex ?? null);
326
- const isSameColumnAndDifferentSort = (col1, col2) => col1 && col2 && col1.colId === col2.colId && col1.sort != col2.sort;
327
- const restorePreviousSortColumnState = () => api.applyColumnState({ state: previousColSort.current });
328
- const sortNodesByPreviousSort = () => {
329
- nodes.sort((a, b) => (previousRowSortIndex[`${a.data.id}`]?.index ?? Number.MAX_SAFE_INTEGER) -
330
- (previousRowSortIndex[`${b.data.id}`]?.index ?? Number.MAX_SAFE_INTEGER));
331
- };
332
- // On first load copy the current sort
333
- if (!initialised.current) {
334
- initialised.current = true;
335
- previousColSort.current = copyCurrentSortSettings();
336
- }
337
- const newSortOrder = JSON.stringify(copyCurrentSortSettings());
338
- let sortOrderChanged = newSortOrder != lastSortOrderHash.current;
339
- const quickFilter = api.getQuickFilter();
340
- if (previousQuickFilter.current != quickFilter) {
341
- previousQuickFilter.current = quickFilter ?? "";
342
- sortOrderChanged = true;
343
- }
344
- if (lodashEs.isEmpty(previousRowSortIndex)) {
345
- backupSortOrder();
346
- }
347
- if (sortOrderChanged) {
348
- const thisFirstCol = copyCurrentSortSettings().find(isFirstSortColumn);
349
- const previousFirstCol = previousColSort.current.find(isFirstSortColumn);
350
- // Change to sort can be: (in the context of stale sort do...)
351
- // - no sort to sorted (do nothing)
352
- // - asc to desc (resort as asc, and remove stale sort)
353
- // - desc to no sort (resort as desc, and remove stale sort)
354
- const wasSortChangedOnSameColumn = previousFirstCol && (!thisFirstCol || isSameColumnAndDifferentSort(previousFirstCol, thisFirstCol));
355
- // if sort was stale, and we're here, someone has clicked a stale sort order (^*) in the column header
356
- if (sortWasStale.current && wasSortChangedOnSameColumn) {
357
- // Sort was an existing priority 1 column
358
- // We want to re-sort with the old sort direction and clear stale sort
359
- sortWasStale.current = false;
360
- setStaleGrid(false);
361
- // trigger a recapture of sort order
362
- lastSortOrderHash.current = "";
363
- restorePreviousSortColumnState();
364
- }
365
- else {
366
- // Sort was on a different column so clear sort and sort like normal
367
- if (sortWasStale.current) {
368
- sortWasStale.current = false;
369
- setStaleGrid(false);
370
- }
371
- // Columns were sorted so retain the sort
372
- backupSortOrder();
373
- lastSortOrderHash.current = newSortOrder;
374
- }
375
- }
376
- else {
377
- let firstChangedNodeIndex = -1;
378
- let lastNewNode = undefined;
379
- let changedRowCount = 0;
380
- let newRowCount = 0;
381
- let index = 0;
382
- for (const node of nodes) {
383
- const psr = previousRowSortIndex[`${node.data.id}`];
384
- if (psr) {
385
- if (psr.hash != hashNode(node)) {
386
- if (firstChangedNodeIndex === -1)
387
- firstChangedNodeIndex = index;
388
- changedRowCount++;
389
- }
390
- }
391
- else {
392
- lastNewNode = node;
393
- newRowCount++;
394
- }
395
- index++;
396
- }
397
- let wasStale = false;
398
- if (changedRowCount === 0 && newRowCount === 1) {
399
- // insert new row at end
400
- const newIndex = index - 1;
401
- previousRowSortIndex[`${lastNewNode?.data.id}`] = { index: newIndex, hash: hashNode(lastNewNode) };
402
- wasStale = true;
403
- }
404
- else if (changedRowCount === 2 && newRowCount === 0) {
405
- // This must be a swap rows (sometimes it's not, needs further attention)
406
- backupSortOrder();
407
- wasStale = false;
408
- }
409
- else if (changedRowCount > 1 && newRowCount === 1) {
410
- // This must be a insert so, insert new row near the row that changed
411
- previousRowSortIndex[`${lastNewNode?.data.id}`] = {
412
- index: firstChangedNodeIndex + 0.5,
413
- hash: hashNode(lastNewNode),
414
- };
415
- wasStale = true;
416
- // For some reason AgGrid mis-positions the inserted row.
417
- lastNewNode && redrawRows();
418
- }
419
- else if (changedRowCount == 1 && newRowCount === 0) {
420
- // User edited one row so, do nothing, retain sort
421
- wasStale = true;
422
- }
423
- else if (changedRowCount !== 0 || newRowCount != 0) {
424
- // too many rows changed, resort
425
- backupSortOrder();
426
- }
427
- if (wasStale) {
428
- // Check if the sort order the aggrid passed matches our stale sort order
429
- const stillStale = Object.keys(previousRowSortIndex).length != nodes.length ||
430
- nodes.some((node, index) => previousRowSortIndex[`${node.data.id}`]?.index !== index);
431
- // If we haven't already processed a stale sort then...
432
- if (stillStale && !sortWasStale.current) {
433
- // backup sort state, so we can restore it when sort is clicked on a stale column
434
- previousColSort.current = copyCurrentSortSettings();
435
- sortWasStale.current = true;
436
- setStaleGrid(true);
437
- }
438
- }
439
- sortNodesByPreviousSort();
440
- }
441
- }, [redrawRows, setStaleGrid]);
303
+ return valid.slice(0, -fileExt.length - 1).slice(0, 64) + '.' + fileExt;
442
304
  };
443
305
 
444
306
  /**
@@ -454,9 +316,9 @@ const GridHeaderSelect = ({ api }) => {
454
316
  const clickHandler = () => {
455
317
  setUpdateCounter(updateCounter + 1);
456
318
  };
457
- api.addEventListener("selectionChanged", clickHandler);
319
+ api.addEventListener('selectionChanged', clickHandler);
458
320
  return () => {
459
- !api.isDestroyed() && api.removeEventListener("selectionChanged", clickHandler);
321
+ !api.isDestroyed() && api.removeEventListener('selectionChanged', clickHandler);
460
322
  };
461
323
  }, [api, updateCounter]);
462
324
  const handleMultiSelect = () => {
@@ -470,11 +332,23 @@ const GridHeaderSelect = ({ api }) => {
470
332
  const totalNodeCount = api.getDisplayedRowCount();
471
333
  const partialSelect = selectedNodeCount != 0 && selectedNodeCount != totalNodeCount;
472
334
  const allSelected = selectedNodeCount != 0 && selectedNodeCount == totalNodeCount;
473
- return (jsxRuntime.jsx("div", { className: clsx("ag-wrapper ag-input-wrapper ag-checkbox-input-wrapper", partialSelect && "ag-indeterminate", allSelected && "ag-checked"), onClick: handleMultiSelect, children: jsxRuntime.jsx("input", { type: "checkbox", className: "ag-checkbox-input-wrapper", onChange: () => {
335
+ return (jsxRuntime.jsx("div", { className: clsx('ag-wrapper ag-input-wrapper ag-checkbox-input-wrapper', partialSelect && 'ag-indeterminate', allSelected && 'ag-checked'), onClick: handleMultiSelect, children: jsxRuntime.jsx("input", { type: "checkbox", className: 'ag-checkbox-input-wrapper', onChange: () => {
474
336
  /* do nothing */
475
337
  } }) }));
476
338
  };
477
339
 
340
+ const EventHandlersContext = React.createContext({
341
+ handleClick: () => { },
342
+ });
343
+
344
+ const ItemSettingsContext = React.createContext({
345
+ submenuOpenDelay: 0,
346
+ submenuCloseDelay: 0,
347
+ });
348
+
349
+ // FIXME hacking a default context in here is probably bad, but the context is mess
350
+ const SettingsContext = React.createContext({});
351
+
478
352
  // Generate className following BEM methodology: http://getbem.com/naming/
479
353
  // Modifier value can be one of the following types: boolean, string, undefined
480
354
  const useBEM = ({ block, element, modifiers, className }) => React.useMemo(() => {
@@ -486,8 +360,8 @@ const useBEM = ({ block, element, modifiers, className }) => React.useMemo(() =>
486
360
  if (value)
487
361
  classString += ` ${blockElement}--${value === true ? name : `${name}-${value}`}`;
488
362
  });
489
- let expandedClassName = typeof className === "function" ? className(modifiers) : className;
490
- if (typeof expandedClassName === "string") {
363
+ let expandedClassName = typeof className === 'function' ? className(modifiers) : className;
364
+ if (typeof expandedClassName === 'string') {
491
365
  expandedClassName = expandedClassName.trim();
492
366
  if (expandedClassName)
493
367
  classString += ` ${expandedClassName}`;
@@ -498,7 +372,7 @@ const useBEM = ({ block, element, modifiers, className }) => React.useMemo(() =>
498
372
  // Adapted from material-ui
499
373
  // https://github.com/mui-org/material-ui/blob/f996027d00e7e4bff3fc040786c1706f9c6c3f82/packages/material-ui-utils/src/useForkRef.ts
500
374
  const setRef = (ref, instance) => {
501
- if (typeof ref === "function") {
375
+ if (typeof ref === 'function') {
502
376
  ref(instance);
503
377
  }
504
378
  else if (ref) {
@@ -518,33 +392,50 @@ const useCombinedRef = (refA, refB) => {
518
392
  // https://github.com/reduxjs/react-redux/blob/b48d087d76f666e1c6c5a9713bbec112a1631841/src/utils/useIsomorphicLayoutEffect.js#L12
519
393
  // https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85
520
394
  // https://github.com/facebook/react/issues/14927#issuecomment-549457471
521
- const useIsomorphicLayoutEffect = typeof window !== "undefined" &&
522
- typeof window.document !== "undefined" &&
523
- typeof window.document.createElement !== "undefined"
395
+ const useIsomorphicLayoutEffect = typeof window !== 'undefined' &&
396
+ typeof window.document !== 'undefined' &&
397
+ typeof window.document.createElement !== 'undefined'
524
398
  ? React.useLayoutEffect
525
399
  : React.useEffect;
526
400
 
527
- const menuContainerClass = "szh-menu-container";
528
- const menuClass = "szh-menu";
529
- const menuButtonClass = "szh-menu-button";
530
- const menuArrowClass = "arrow";
531
- const menuItemClass = "item";
532
- const menuDividerClass = "divider";
533
- const menuHeaderClass = "header";
534
- const menuGroupClass = "group";
535
- const subMenuClass = "submenu";
536
- const radioGroupClass = "radio-group";
401
+ const useItemEffect = (isDisabled, menuItemRef, updateItems) => {
402
+ useIsomorphicLayoutEffect(() => {
403
+ if (!menuItemRef)
404
+ return;
405
+ if (process.env.NODE_ENV !== 'production' && !updateItems) {
406
+ throw new Error(`[React-Menu] This menu item or submenu should be rendered under a menu: ${menuItemRef.current.outerHTML}`);
407
+ }
408
+ if (isDisabled)
409
+ return;
410
+ const item = menuItemRef.current;
411
+ updateItems(item, true);
412
+ return () => {
413
+ updateItems(item);
414
+ };
415
+ }, [isDisabled, menuItemRef, updateItems]);
416
+ };
417
+
418
+ const menuContainerClass = 'szh-menu-container';
419
+ const menuClass = 'szh-menu';
420
+ const menuButtonClass = 'szh-menu-button';
421
+ const menuArrowClass = 'arrow';
422
+ const menuItemClass = 'item';
423
+ const menuDividerClass = 'divider';
424
+ const menuHeaderClass = 'header';
425
+ const menuGroupClass = 'group';
426
+ const subMenuClass = 'submenu';
427
+ const radioGroupClass = 'radio-group';
537
428
  const Keys = Object.freeze({
538
- ENTER: "Enter",
539
- TAB: "Tab",
540
- ESC: "Escape",
541
- SPACE: " ",
542
- HOME: "Home",
543
- END: "End",
544
- LEFT: "ArrowLeft",
545
- RIGHT: "ArrowRight",
546
- UP: "ArrowUp",
547
- DOWN: "ArrowDown",
429
+ ENTER: 'Enter',
430
+ TAB: 'Tab',
431
+ ESC: 'Escape',
432
+ SPACE: ' ',
433
+ HOME: 'Home',
434
+ END: 'End',
435
+ LEFT: 'ArrowLeft',
436
+ RIGHT: 'ArrowRight',
437
+ UP: 'ArrowUp',
438
+ DOWN: 'ArrowDown',
548
439
  });
549
440
  const HoverActionTypes = Object.freeze({
550
441
  RESET: 0,
@@ -557,39 +448,39 @@ const HoverActionTypes = Object.freeze({
557
448
  SET_INDEX: 7,
558
449
  });
559
450
  const CloseReason = Object.freeze({
560
- CLICK: "click",
561
- CANCEL: "cancel",
562
- BLUR: "blur",
563
- SCROLL: "scroll",
564
- TAB_FORWARD: "tab_forward",
565
- TAB_BACKWARD: "tab_backward",
451
+ CLICK: 'click',
452
+ CANCEL: 'cancel',
453
+ BLUR: 'blur',
454
+ SCROLL: 'scroll',
455
+ TAB_FORWARD: 'tab_forward',
456
+ TAB_BACKWARD: 'tab_backward',
566
457
  });
567
458
  const FocusPositions = Object.freeze({
568
- FIRST: "first",
569
- LAST: "last",
459
+ FIRST: 'first',
460
+ LAST: 'last',
570
461
  });
571
462
  const MenuStateMap = Object.freeze({
572
- entering: "opening",
573
- entered: "open",
574
- exiting: "closing",
575
- exited: "closed",
463
+ entering: 'opening',
464
+ entered: 'open',
465
+ exiting: 'closing',
466
+ exited: 'closed',
576
467
  });
577
468
 
578
- const isMenuOpen = (state) => !!state && state[0] === "o";
469
+ const isMenuOpen = (state) => !!state && state[0] === 'o';
579
470
  const batchedUpdates = reactDom.unstable_batchedUpdates || ((callback) => callback());
580
471
  const floatEqual = (a, b, diff = 0.0001) => Math.abs(a - b) < diff;
581
472
  const getTransition = (transition, name) => transition === true || !!(transition && transition[name]);
582
473
  function safeCall(fn, arg) {
583
- return typeof fn === "function" ? fn(arg) : fn;
474
+ return typeof fn === 'function' ? fn(arg) : fn;
584
475
  }
585
- const internalKey = "_szhsinMenu";
476
+ const internalKey = '_szhsinMenu';
586
477
  const getName = (component) => component[internalKey];
587
478
  const mergeProps = (target, source) => {
588
479
  source &&
589
480
  Object.keys(source).forEach((key) => {
590
481
  const targetProp = target[key];
591
482
  const sourceProp = source[key];
592
- if (typeof sourceProp === "function" && targetProp) {
483
+ if (typeof sourceProp === 'function' && targetProp) {
593
484
  target[key] = (...arg) => {
594
485
  sourceProp(...arg);
595
486
  targetProp(...arg);
@@ -631,24 +522,24 @@ const getScrollAncestor = (node) => {
631
522
  };
632
523
  function commonProps(isDisabled, isHovering) {
633
524
  return {
634
- "aria-disabled": isDisabled || undefined,
525
+ 'aria-disabled': isDisabled || undefined,
635
526
  tabIndex: isHovering ? 0 : -1,
636
527
  };
637
528
  }
638
529
  const indexOfNode = (nodeList, node) => lodashEs.findIndex(nodeList, node);
639
530
  const focusFirstInput = (container) => {
640
531
  // We can't use instanceof Element in portals, so I use querySelectorAll as a proxy here
641
- if (!container || !("querySelectorAll" in container))
532
+ if (!container || !('querySelectorAll' in container))
642
533
  return false;
643
534
  const inputs = container.querySelectorAll("input[type='text'],input:not([type]),textarea");
644
535
  const input = inputs[0];
645
536
  // Using focus as proxy for HTMLElement
646
- if (!input || !("focus" in input))
537
+ if (!input || !('focus' in input))
647
538
  return false;
648
539
  input.focus();
649
540
  // Text areas should start at end
650
541
  // this is a proxy for instanceof HTMLTextAreaElement
651
- if (["textarea", "text"].includes(input.type)) {
542
+ if (['textarea', 'text'].includes(input.type)) {
652
543
  input.setSelectionRange(0, input.value.length);
653
544
  }
654
545
  return true;
@@ -700,7 +591,7 @@ const useItems = (menuRef, focusRef) => {
700
591
  const sortItems = () => {
701
592
  if (mutableState.sorted)
702
593
  return;
703
- const orderedNodes = menuRef.current.querySelectorAll(".szh-menu__item");
594
+ const orderedNodes = menuRef.current.querySelectorAll('.szh-menu__item');
704
595
  items.sort((a, b) => indexOfNode(orderedNodes, a) - indexOfNode(orderedNodes, b));
705
596
  mutableState.sorted = true;
706
597
  };
@@ -727,12 +618,12 @@ const useItems = (menuRef, focusRef) => {
727
618
  newItem = items[index];
728
619
  break;
729
620
  case HoverActionTypes.SET_INDEX:
730
- if (typeof nextIndex !== "number")
621
+ if (typeof nextIndex !== 'number')
731
622
  break;
732
623
  sortItems();
733
624
  index = nextIndex;
734
625
  newItem = items[index];
735
- lodashEs.defer(() => newItem.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" }));
626
+ lodashEs.defer(() => newItem.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }));
736
627
  break;
737
628
  case HoverActionTypes.INCREASE:
738
629
  sortItems();
@@ -758,7 +649,7 @@ const useItems = (menuRef, focusRef) => {
758
649
  break;
759
650
  }
760
651
  default:
761
- if (process.env.NODE_ENV !== "production")
652
+ if (process.env.NODE_ENV !== 'production')
762
653
  throw new Error(`[React-Menu] Unknown hover action type: ${actionType}`);
763
654
  }
764
655
  if (!newItem && !newItemFn)
@@ -769,28 +660,6 @@ const useItems = (menuRef, focusRef) => {
769
660
  return { hoverItem, dispatch, updateItems };
770
661
  };
771
662
 
772
- const useItemEffect = (isDisabled, menuItemRef, updateItems) => {
773
- useIsomorphicLayoutEffect(() => {
774
- if (!menuItemRef)
775
- return;
776
- if (process.env.NODE_ENV !== "production" && !updateItems) {
777
- throw new Error(`[React-Menu] This menu item or submenu should be rendered under a menu: ${menuItemRef.current.outerHTML}`);
778
- }
779
- if (isDisabled)
780
- return;
781
- const item = menuItemRef.current;
782
- updateItems(item, true);
783
- return () => {
784
- updateItems(item);
785
- };
786
- }, [isDisabled, menuItemRef, updateItems]);
787
- };
788
-
789
- const ItemSettingsContext = React.createContext({
790
- submenuOpenDelay: 0,
791
- submenuCloseDelay: 0,
792
- });
793
-
794
663
  const MenuListItemContext = React.createContext({
795
664
  dispatch: () => { },
796
665
  updateItems: () => { },
@@ -958,8 +827,8 @@ const useMenuState = (props) => {
958
827
  mountOnEnter: !initialMounted,
959
828
  unmountOnExit: unmountOnClose,
960
829
  timeout: transitionTimeout ?? 500,
961
- enter: getTransition(transition, "open"),
962
- exit: getTransition(transition, "close"),
830
+ enter: getTransition(transition, 'open'),
831
+ exit: getTransition(transition, 'close'),
963
832
  });
964
833
  return [{ state: MenuStateMap[state.status], endTransition }, toggleMenu];
965
834
  };
@@ -974,18 +843,6 @@ const useMenuStateAndFocus = (options) => {
974
843
  return [{ menuItemFocus, ...menuProps }, toggleMenu, openMenu];
975
844
  };
976
845
 
977
- const MenuButton = React.forwardRef(function MenuButton({ className, isOpen, disabled, children, ...restProps }, ref) {
978
- const modifiers = React.useMemo(() => ({ open: isOpen }), [isOpen]);
979
- return (jsxRuntime.jsx("button", { "aria-haspopup": true, "aria-expanded": isOpen, "aria-disabled": disabled || undefined, type: "button", disabled: disabled, ...restProps, ref: ref, className: useBEM({ block: menuButtonClass, modifiers, className }), children: children }));
980
- });
981
-
982
- const EventHandlersContext = React.createContext({
983
- handleClick: () => { },
984
- });
985
-
986
- // FIXME hacking a default context in here is probably bad, but the context is mess
987
- const SettingsContext = React.createContext({});
988
-
989
846
  const MenuListContext = React.createContext({});
990
847
 
991
848
  const getPositionHelpers = (containerRef, menuRef, menuScroll, boundingBoxPadding) => {
@@ -1080,14 +937,14 @@ const positionContextMenu = ({ positionHelpers, anchorPoint, }) => {
1080
937
  x = confineHorizontally(x);
1081
938
  }
1082
939
  // Similar logic to the left and right side above.
1083
- let computedDirection = "bottom";
940
+ let computedDirection = 'bottom';
1084
941
  const bottomOverflow = getBottomOverflow(y);
1085
942
  if (bottomOverflow > 0) {
1086
943
  const adjustedY = y - menuRect.height;
1087
944
  const topOverflow = getTopOverflow(adjustedY);
1088
945
  if (topOverflow >= 0 || -topOverflow < bottomOverflow) {
1089
946
  y = adjustedY;
1090
- computedDirection = "top";
947
+ computedDirection = 'top';
1091
948
  }
1092
949
  y = confineVertically(y);
1093
950
  }
@@ -1106,18 +963,18 @@ const placeLeftorRight = (props) => {
1106
963
  const { anchorRect, containerRect, menuRect, placeLeftorRightY, placeLeftX, placeRightX, getLeftOverflow, getRightOverflow, confineHorizontally, confineVertically, arrowRef, arrow, direction, position, } = props;
1107
964
  let computedDirection = direction;
1108
965
  let y = placeLeftorRightY;
1109
- if (position !== "initial") {
966
+ if (position !== 'initial') {
1110
967
  y = confineVertically(y);
1111
- if (position === "anchor") {
968
+ if (position === 'anchor') {
1112
969
  // restrict menu to the edge of anchor element
1113
970
  y = Math.min(y, anchorRect.bottom - containerRect.top);
1114
971
  y = Math.max(y, anchorRect.top - containerRect.top - menuRect.height);
1115
972
  }
1116
973
  }
1117
974
  let x, leftOverflow, rightOverflow;
1118
- if (computedDirection === "left") {
975
+ if (computedDirection === 'left') {
1119
976
  x = placeLeftX;
1120
- if (position !== "initial") {
977
+ if (position !== 'initial') {
1121
978
  // if menu overflows to the left,
1122
979
  // try to reposition it to the right of the anchor.
1123
980
  leftOverflow = getLeftOverflow(x);
@@ -1127,7 +984,7 @@ const placeLeftorRight = (props) => {
1127
984
  rightOverflow = getRightOverflow(placeRightX);
1128
985
  if (rightOverflow <= 0 || -leftOverflow > rightOverflow) {
1129
986
  x = placeRightX;
1130
- computedDirection = "right";
987
+ computedDirection = 'right';
1131
988
  }
1132
989
  }
1133
990
  }
@@ -1135,18 +992,18 @@ const placeLeftorRight = (props) => {
1135
992
  else {
1136
993
  // Opposite logic to the 'left' direction above
1137
994
  x = placeRightX;
1138
- if (position !== "initial") {
995
+ if (position !== 'initial') {
1139
996
  rightOverflow = getRightOverflow(x);
1140
997
  if (rightOverflow > 0) {
1141
998
  leftOverflow = getLeftOverflow(placeLeftX);
1142
999
  if (leftOverflow >= 0 || -leftOverflow < rightOverflow) {
1143
1000
  x = placeLeftX;
1144
- computedDirection = "left";
1001
+ computedDirection = 'left';
1145
1002
  }
1146
1003
  }
1147
1004
  }
1148
1005
  }
1149
- if (position === "auto")
1006
+ if (position === 'auto')
1150
1007
  x = confineHorizontally(x);
1151
1008
  const arrowY = arrow
1152
1009
  ? placeArrowVertical({
@@ -1171,20 +1028,20 @@ const placeArrowHorizontal = (p) => {
1171
1028
  const placeToporBottom = (props) => {
1172
1029
  const { anchorRect, containerRect, menuRect, placeToporBottomX, placeTopY, placeBottomY, getTopOverflow, getBottomOverflow, confineHorizontally, confineVertically, arrowRef, arrow, direction, position, } = props;
1173
1030
  // make sure invalid direction is treated as 'bottom'
1174
- let computedDirection = direction === "top" ? "top" : "bottom";
1031
+ let computedDirection = direction === 'top' ? 'top' : 'bottom';
1175
1032
  let x = placeToporBottomX;
1176
- if (position !== "initial") {
1033
+ if (position !== 'initial') {
1177
1034
  x = confineHorizontally(x);
1178
- if (position === "anchor") {
1035
+ if (position === 'anchor') {
1179
1036
  // restrict menu to the edge of anchor element
1180
1037
  x = Math.min(x, anchorRect.right - containerRect.left);
1181
1038
  x = Math.max(x, anchorRect.left - containerRect.left - menuRect.width);
1182
1039
  }
1183
1040
  }
1184
1041
  let y, topOverflow, bottomOverflow;
1185
- if (computedDirection === "top") {
1042
+ if (computedDirection === 'top') {
1186
1043
  y = placeTopY;
1187
- if (position !== "initial") {
1044
+ if (position !== 'initial') {
1188
1045
  // if menu overflows to the top,
1189
1046
  // try to reposition it to the bottom of the anchor.
1190
1047
  topOverflow = getTopOverflow(y);
@@ -1194,7 +1051,7 @@ const placeToporBottom = (props) => {
1194
1051
  bottomOverflow = getBottomOverflow(placeBottomY);
1195
1052
  if (bottomOverflow <= 0 || -topOverflow > bottomOverflow) {
1196
1053
  y = placeBottomY;
1197
- computedDirection = "bottom";
1054
+ computedDirection = 'bottom';
1198
1055
  }
1199
1056
  }
1200
1057
  }
@@ -1202,18 +1059,18 @@ const placeToporBottom = (props) => {
1202
1059
  else {
1203
1060
  // Opposite logic to the 'top' direction above
1204
1061
  y = placeBottomY;
1205
- if (position !== "initial") {
1062
+ if (position !== 'initial') {
1206
1063
  bottomOverflow = getBottomOverflow(y);
1207
1064
  if (bottomOverflow > 0) {
1208
1065
  topOverflow = getTopOverflow(placeTopY);
1209
1066
  if (topOverflow >= 0 || -topOverflow < bottomOverflow) {
1210
1067
  y = placeTopY;
1211
- computedDirection = "top";
1068
+ computedDirection = 'top';
1212
1069
  }
1213
1070
  }
1214
1071
  }
1215
1072
  }
1216
- if (position === "auto")
1073
+ if (position === 'auto')
1217
1074
  y = confineVertically(y);
1218
1075
  const arrowX = arrow
1219
1076
  ? placeArrowHorizontal({
@@ -1233,7 +1090,7 @@ const positionMenu = (props) => {
1233
1090
  let horizontalOffset = offsetX;
1234
1091
  let verticalOffset = offsetY;
1235
1092
  if (arrow && arrowRef.current) {
1236
- if (direction === "left" || direction === "right") {
1093
+ if (direction === 'left' || direction === 'right') {
1237
1094
  horizontalOffset += arrowRef.current.offsetWidth;
1238
1095
  }
1239
1096
  else {
@@ -1248,11 +1105,11 @@ const positionMenu = (props) => {
1248
1105
  const placeTopY = anchorRect.top - containerRect.top - menuRect.height - verticalOffset;
1249
1106
  const placeBottomY = anchorRect.bottom - containerRect.top + verticalOffset;
1250
1107
  let placeToporBottomX, placeLeftorRightY;
1251
- if (align === "end") {
1108
+ if (align === 'end') {
1252
1109
  placeToporBottomX = anchorRect.right - containerRect.left - menuRect.width;
1253
1110
  placeLeftorRightY = anchorRect.bottom - containerRect.top - menuRect.height;
1254
1111
  }
1255
- else if (align === "center") {
1112
+ else if (align === 'center') {
1256
1113
  placeToporBottomX = anchorRect.left - containerRect.left - (menuRect.width - anchorRect.width) / 2;
1257
1114
  placeLeftorRightY = anchorRect.top - containerRect.top - (menuRect.height - anchorRect.height) / 2;
1258
1115
  }
@@ -1277,17 +1134,17 @@ const positionMenu = (props) => {
1277
1134
  position,
1278
1135
  };
1279
1136
  switch (direction) {
1280
- case "left":
1281
- case "right":
1137
+ case 'left':
1138
+ case 'right':
1282
1139
  return placeLeftorRight(options);
1283
- case "top":
1284
- case "bottom":
1140
+ case 'top':
1141
+ case 'bottom':
1285
1142
  default:
1286
1143
  return placeToporBottom(options);
1287
1144
  }
1288
1145
  };
1289
1146
 
1290
- const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowStyle, anchorPoint, anchorRef, containerRef, externalRef, parentScrollingRef, arrow, align = "start", direction = "bottom", position = "auto", overflow = "visible", setDownOverflow, repositionFlag, captureFocus = true, state, endTransition, isDisabled, menuItemFocus, dontShrinkIfDirectionIsTop, offsetX = 0, offsetY = 0, children, onClose, ...restProps }) => {
1147
+ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowStyle, anchorPoint, anchorRef, containerRef, externalRef, parentScrollingRef, arrow, align = 'start', direction = 'bottom', position = 'auto', overflow = 'visible', setDownOverflow, repositionFlag, captureFocus = true, state, endTransition, isDisabled, menuItemFocus, dontShrinkIfDirectionIsTop, offsetX = 0, offsetY = 0, children, onClose, ...restProps }) => {
1291
1148
  const [menuPosition, setMenuPosition] = React.useState({ x: 0, y: 0 });
1292
1149
  const [arrowPosition, setArrowPosition] = React.useState({ x: 0, y: 0 });
1293
1150
  const [overflowData, setOverflowData] = React.useState();
@@ -1305,8 +1162,8 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1305
1162
  const latestHandlePosition = React.useRef(() => { });
1306
1163
  const { hoverItem, dispatch, updateItems } = useItems(menuRef, focusRef);
1307
1164
  const isOpen = isMenuOpen(state);
1308
- const openTransition = getTransition(transition, "open");
1309
- const closeTransition = getTransition(transition, "close");
1165
+ const openTransition = getTransition(transition, 'open');
1166
+ const closeTransition = getTransition(transition, 'close');
1310
1167
  const scrollNodes = scrollNodesRef.current;
1311
1168
  /**
1312
1169
  * Given the menu-item we are on, find the closest or furthest next menu-item horizontally and focus it.
@@ -1316,8 +1173,8 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1316
1173
  if (!menuItemEl)
1317
1174
  return false;
1318
1175
  let [best, worst] = [];
1319
- findParentWithClass("szh-menu", menuItemEl)
1320
- ?.querySelectorAll(".szh-menu__item")
1176
+ findParentWithClass('szh-menu', menuItemEl)
1177
+ ?.querySelectorAll('.szh-menu__item')
1321
1178
  ?.forEach((item, i) => {
1322
1179
  // Must be at same height as currently focused menu-item
1323
1180
  if (item.offsetTop === menuItemEl.offsetTop) {
@@ -1332,14 +1189,14 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1332
1189
  const r = best ?? worst;
1333
1190
  if (!r)
1334
1191
  return false;
1335
- dispatch(HoverActionTypes.SET_INDEX, undefined, r["i"]);
1192
+ dispatch(HoverActionTypes.SET_INDEX, undefined, r['i']);
1336
1193
  return true;
1337
1194
  };
1338
1195
  const onKeyDown = (e) => {
1339
1196
  const elementTarget = e.target instanceof HTMLElement ? e.target : null;
1340
1197
  const isTextInputTarget = elementTarget &&
1341
- (elementTarget.nodeName === "TEXTAREA" ||
1342
- (elementTarget.nodeName === "INPUT" && elementTarget.getAttribute("type") === "text"));
1198
+ (elementTarget.nodeName === 'TEXTAREA' ||
1199
+ (elementTarget.nodeName === 'INPUT' && elementTarget.getAttribute('type') === 'text'));
1343
1200
  switch (e.key) {
1344
1201
  case Keys.HOME:
1345
1202
  // Don't eat home/end events on inputs
@@ -1383,14 +1240,14 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1383
1240
  e.stopPropagation();
1384
1241
  };
1385
1242
  const onAnimationEnd = () => {
1386
- if (state === "closing") {
1243
+ if (state === 'closing') {
1387
1244
  setOverflowData(undefined); // reset overflowData after closing
1388
1245
  }
1389
1246
  endTransition && safeCall(endTransition);
1390
1247
  };
1391
1248
  const handlePosition = React.useCallback((noOverflowCheck) => {
1392
1249
  if (!containerRef?.current) {
1393
- if (process.env.NODE_ENV !== "production") {
1250
+ if (process.env.NODE_ENV !== 'production') {
1394
1251
  console.error('[React-Menu] Menu cannot be positioned properly as container ref is null. If you need to initialise `state` prop to "open" for ControlledMenu, please see this solution: https://codesandbox.io/s/initial-open-sp10wn');
1395
1252
  }
1396
1253
  return;
@@ -1404,7 +1261,7 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1404
1261
  const positionHelpers = getPositionHelpers(containerRef, menuRef, scrollNodes.menu, boundingBoxPadding);
1405
1262
  const { menuRect } = positionHelpers;
1406
1263
  let results = {
1407
- computedDirection: "bottom",
1264
+ computedDirection: 'bottom',
1408
1265
  x: 0,
1409
1266
  y: 0,
1410
1267
  };
@@ -1427,7 +1284,7 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1427
1284
  let { y } = results;
1428
1285
  const { x, arrowX, arrowY, computedDirection } = results;
1429
1286
  let menuHeight = menuRect.height;
1430
- if (!noOverflowCheck && overflow !== "visible") {
1287
+ if (!noOverflowCheck && overflow !== 'visible') {
1431
1288
  const { getTopOverflow, getBottomOverflow } = positionHelpers;
1432
1289
  let height, overflowAmt;
1433
1290
  const prevHeight = latestMenuSize.current.height;
@@ -1508,21 +1365,21 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1508
1365
  }
1509
1366
  }
1510
1367
  let scroll = viewScroll;
1511
- if (scrollNodes.anchors.length && scroll === "initial")
1512
- scroll = "auto";
1513
- if (scroll === "initial")
1368
+ if (scrollNodes.anchors.length && scroll === 'initial')
1369
+ scroll = 'auto';
1370
+ if (scroll === 'initial')
1514
1371
  return;
1515
1372
  const handleScroll = () => {
1516
- if (scroll === "auto") {
1373
+ if (scroll === 'auto') {
1517
1374
  batchedUpdates(() => handlePosition(true));
1518
1375
  }
1519
1376
  else {
1520
1377
  safeCall(onClose, { reason: CloseReason.SCROLL });
1521
1378
  }
1522
1379
  };
1523
- const scrollObservers = scrollNodes.anchors.concat(viewScroll !== "initial" ? menuScroll : []);
1524
- scrollObservers.forEach((o) => o.addEventListener("scroll", handleScroll));
1525
- return () => scrollObservers.forEach((o) => o.removeEventListener("scroll", handleScroll));
1380
+ const scrollObservers = scrollNodes.anchors.concat(viewScroll !== 'initial' ? menuScroll : []);
1381
+ scrollObservers.forEach((o) => o.addEventListener('scroll', handleScroll));
1382
+ return () => scrollObservers.forEach((o) => o.removeEventListener('scroll', handleScroll));
1526
1383
  }, [rootAnchorRef, scrollNodes, isOpen, onClose, viewScroll, handlePosition]);
1527
1384
  const hasOverflow = !!overflowData && overflowData.overflowAmt != null && overflowData.overflowAmt > 0;
1528
1385
  React.useEffect(() => {
@@ -1530,11 +1387,11 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1530
1387
  return;
1531
1388
  const handleScroll = () => batchedUpdates(handlePosition);
1532
1389
  const parentScroll = parentScrollingRef.current;
1533
- parentScroll.addEventListener("scroll", handleScroll);
1534
- return () => parentScroll.removeEventListener("scroll", handleScroll);
1390
+ parentScroll.addEventListener('scroll', handleScroll);
1391
+ return () => parentScroll.removeEventListener('scroll', handleScroll);
1535
1392
  }, [isOpen, hasOverflow, parentScrollingRef, handlePosition]);
1536
1393
  React.useEffect(() => {
1537
- if (typeof ResizeObserver !== "function" || reposition === "initial")
1394
+ if (typeof ResizeObserver !== 'function' || reposition === 'initial')
1538
1395
  return;
1539
1396
  const resizeObserver = new ResizeObserver(([entry]) => {
1540
1397
  const { borderBoxSize, target } = entry;
@@ -1559,12 +1416,12 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1559
1416
  });
1560
1417
  });
1561
1418
  const observeTarget = menuRef.current;
1562
- resizeObserver.observe(observeTarget, { box: "border-box" });
1419
+ resizeObserver.observe(observeTarget, { box: 'border-box' });
1563
1420
  return () => resizeObserver.unobserve(observeTarget);
1564
1421
  }, [reposition]);
1565
1422
  // Matt added window resize observer
1566
1423
  React.useEffect(() => {
1567
- if (typeof ResizeObserver !== "function" || reposition === "initial")
1424
+ if (typeof ResizeObserver !== 'function' || reposition === 'initial')
1568
1425
  return;
1569
1426
  const callback = lodashEs.debounce(() => {
1570
1427
  const { width, height } = menuRef.current.ownerDocument.body.getBoundingClientRect();
@@ -1582,7 +1439,7 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1582
1439
  }, 250);
1583
1440
  const resizeObserver = new ResizeObserver(callback);
1584
1441
  const observeTarget = menuRef.current.ownerDocument.body;
1585
- resizeObserver.observe(observeTarget, { box: "border-box" });
1442
+ resizeObserver.observe(observeTarget, { box: 'border-box' });
1586
1443
  return () => {
1587
1444
  callback.cancel();
1588
1445
  resizeObserver.unobserve(observeTarget);
@@ -1603,7 +1460,7 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1603
1460
  else if (position === FocusPositions.LAST) {
1604
1461
  dispatch(HoverActionTypes.LAST, undefined, 0);
1605
1462
  }
1606
- else if (typeof position === "number" && position >= -1) {
1463
+ else if (typeof position === 'number' && position >= -1) {
1607
1464
  dispatch(HoverActionTypes.SET_INDEX, undefined, position);
1608
1465
  }
1609
1466
  };
@@ -1665,10 +1522,10 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1665
1522
  if (minHeight.current < h)
1666
1523
  minHeight.current = h;
1667
1524
  }
1668
- const dontShrinkOps = React.useMemo(() => expandedDirection === "top" && dontShrinkIfDirectionIsTop
1525
+ const dontShrinkOps = React.useMemo(() => expandedDirection === 'top' && dontShrinkIfDirectionIsTop
1669
1526
  ? {
1670
- overflowY: isSubmenuOpen ? "" : "auto",
1671
- minHeight: (isSubmenuOpen ? 0 : minHeight.current) + "px",
1527
+ overflowY: isSubmenuOpen ? '' : 'auto',
1528
+ minHeight: (isSubmenuOpen ? 0 : minHeight.current) + 'px',
1672
1529
  }
1673
1530
  : undefined, [dontShrinkIfDirectionIsTop, expandedDirection, isSubmenuOpen]);
1674
1531
  return (jsxRuntime.jsxs("ul", { role: "menu", "aria-label": ariaLabel, ...mergeProps({ onKeyDown, onAnimationEnd }, restProps), ...commonProps(isDisabled), ref: useCombinedRef(externalRef, menuRef), className: useBEM({ block: menuClass, modifiers, className: menuClassName }), style: {
@@ -1676,18 +1533,18 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1676
1533
  ...overflowStyle,
1677
1534
  ...dontShrinkOps,
1678
1535
  margin: 0,
1679
- display: state === "closed" ? "none" : undefined,
1680
- position: "absolute",
1536
+ display: state === 'closed' ? 'none' : undefined,
1537
+ position: 'absolute',
1681
1538
  left: menuPosition.x,
1682
1539
  top: menuPosition.y,
1683
- }, children: [jsxRuntime.jsx("div", { ref: focusRef, tabIndex: -1, style: { position: "absolute", left: 0, top: 0 }, onKeyDown: (event) => {
1684
- if (event.key == "Tab") {
1540
+ }, children: [jsxRuntime.jsx("div", { ref: focusRef, tabIndex: -1, style: { position: 'absolute', left: 0, top: 0 }, onKeyDown: (event) => {
1541
+ if (event.key == 'Tab') {
1685
1542
  event.preventDefault();
1686
1543
  event.stopPropagation();
1687
1544
  safeCall(onClose, {
1688
1545
  key: event.key,
1689
1546
  shiftKey: event.shiftKey,
1690
- reason: event.key === "Tab"
1547
+ reason: event.key === 'Tab'
1691
1548
  ? event.shiftKey
1692
1549
  ? CloseReason.TAB_BACKWARD
1693
1550
  : CloseReason.TAB_FORWARD
@@ -1696,13 +1553,13 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
1696
1553
  }
1697
1554
  } }), arrow && (jsxRuntime.jsx("div", { className: _arrowClass, style: {
1698
1555
  ...arrowStyle,
1699
- position: "absolute",
1556
+ position: 'absolute',
1700
1557
  left: arrowPosition.x,
1701
1558
  top: arrowPosition.y,
1702
1559
  }, ref: arrowRef })), jsxRuntime.jsx(MenuListContext.Provider, { value: listContext, children: jsxRuntime.jsx(MenuListItemContext.Provider, { value: itemContext, children: jsxRuntime.jsx(HoverItemContext.Provider, { value: hoverItem, children: children }) }) })] }));
1703
1560
  };
1704
1561
 
1705
- const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps, initialMounted, unmountOnClose, transition, transitionTimeout, boundingBoxRef, boundingBoxPadding, reposition = "auto", submenuOpenDelay = 300, submenuCloseDelay = 150, skipOpen, viewScroll = "initial", portal, theming, onItemClick, onClose, saveButtonRef, ...restProps }, externalRef) => {
1562
+ const ControlledMenuFr = ({ 'aria-label': ariaLabel, className, containerProps, initialMounted, unmountOnClose, transition, transitionTimeout, boundingBoxRef, boundingBoxPadding, reposition = 'auto', submenuOpenDelay = 300, submenuCloseDelay = 150, skipOpen, viewScroll = 'initial', portal, theming, onItemClick, onClose, saveButtonRef, ...restProps }, externalRef) => {
1706
1563
  const containerRef = React.useRef();
1707
1564
  const scrollNodesRef = React.useRef({});
1708
1565
  const { anchorRef, state } = restProps;
@@ -1729,10 +1586,10 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1729
1586
  reposition,
1730
1587
  viewScroll,
1731
1588
  ]);
1732
- const isWithinMenu = React.useCallback((target) => hasParentClass("szh-menu--state-open", target) ||
1589
+ const isWithinMenu = React.useCallback((target) => hasParentClass('szh-menu--state-open', target) ||
1733
1590
  // This is temporary, it will be removed when the overlay click is fixed
1734
- hasParentClass("LuiModalPrefab", target) ||
1735
- hasParentClass("prefab-modal", target), []);
1591
+ hasParentClass('LuiModalPrefab', target) ||
1592
+ hasParentClass('prefab-modal', target), []);
1736
1593
  const handleScreenEventForSave = React.useCallback((ev) => {
1737
1594
  if (!isWithinMenu(ev.target)) {
1738
1595
  ev.preventDefault();
@@ -1742,7 +1599,7 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1742
1599
  // This doesn't happen in React18
1743
1600
  // To work around it, I invoke the save by clicking on a passed in invisible button ref
1744
1601
  if (saveButtonRef?.current) {
1745
- saveButtonRef.current.setAttribute("data-reason", CloseReason.BLUR);
1602
+ saveButtonRef.current.setAttribute('data-reason', CloseReason.BLUR);
1746
1603
  saveButtonRef.current.click();
1747
1604
  }
1748
1605
  else
@@ -1772,7 +1629,7 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1772
1629
  const activeElement = thisDocument.activeElement;
1773
1630
  if (!anchorRef?.current || !activeElement)
1774
1631
  return;
1775
- if (ev.key !== "Tab" && ev.key !== "Enter")
1632
+ if (ev.key !== 'Tab' && ev.key !== 'Enter')
1776
1633
  return;
1777
1634
  if (ev.repeat) {
1778
1635
  ev.preventDefault();
@@ -1782,12 +1639,12 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1782
1639
  const invokeSave = (reason) => {
1783
1640
  if (!saveButtonRef?.current)
1784
1641
  return;
1785
- saveButtonRef.current?.setAttribute("data-reason", reason);
1642
+ saveButtonRef.current?.setAttribute('data-reason', reason);
1786
1643
  saveButtonRef?.current?.click();
1787
1644
  };
1788
1645
  // data-allowtabtosave is used such that list filter inputs can use tab to save
1789
- const allowTabToSave = activeElement.getAttribute("data-allowtabtosave") == "true";
1790
- const inputElsIterator = thisDocument.querySelectorAll(".szh-menu--state-open input,textarea");
1646
+ const allowTabToSave = activeElement.getAttribute('data-allowtabtosave') == 'true';
1647
+ const inputElsIterator = thisDocument.querySelectorAll('.szh-menu--state-open input,textarea');
1791
1648
  let inputEls = [];
1792
1649
  inputElsIterator.forEach((el) => inputEls.push(el));
1793
1650
  inputEls = inputEls.filter((el) => !el.disabled);
@@ -1795,9 +1652,9 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1795
1652
  return;
1796
1653
  const firstInputEl = inputEls[0];
1797
1654
  const lastInputEl = inputEls[inputEls.length - 1];
1798
- const isTextArea = activeElement.nodeName === "TEXTAREA";
1799
- const suppressEnterAutoSave = activeElement.getAttribute("data-disableenterautosave") == "true" || isTextArea;
1800
- if (ev.key === "Tab") {
1655
+ const isTextArea = activeElement.nodeName === 'TEXTAREA';
1656
+ const suppressEnterAutoSave = activeElement.getAttribute('data-disableenterautosave') == 'true' || isTextArea;
1657
+ if (ev.key === 'Tab') {
1801
1658
  const tabDirection = ev.shiftKey ? CloseReason.TAB_BACKWARD : CloseReason.TAB_FORWARD;
1802
1659
  if ((activeElement === lastInputEl && !ev.shiftKey) ||
1803
1660
  (activeElement === firstInputEl && ev.shiftKey) ||
@@ -1812,13 +1669,13 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1812
1669
  }
1813
1670
  }
1814
1671
  }
1815
- const type = activeElement.getAttribute("type");
1816
- const isTextInput = type === "text" || type == null || type === "textarea";
1672
+ const type = activeElement.getAttribute('type');
1673
+ const isTextInput = type === 'text' || type == null || type === 'textarea';
1817
1674
  switch (activeElement.nodeName) {
1818
- case "INPUT":
1675
+ case 'INPUT':
1819
1676
  {
1820
1677
  // If there's only one input element, we support tab and enter
1821
- if (isTextInput && ev.key === "Enter" && !suppressEnterAutoSave) {
1678
+ if (isTextInput && ev.key === 'Enter' && !suppressEnterAutoSave) {
1822
1679
  ev.preventDefault();
1823
1680
  ev.stopPropagation();
1824
1681
  if (isDown) {
@@ -1837,19 +1694,19 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1837
1694
  React.useEffect(() => {
1838
1695
  if (isMenuOpen(state)) {
1839
1696
  const thisDocument = anchorRef?.current ? anchorRef?.current.ownerDocument : document;
1840
- thisDocument.addEventListener("keydown", handleKeydownTabAndEnter, true);
1841
- thisDocument.addEventListener("keyup", handleKeyupTabAndEnter, true);
1842
- thisDocument.addEventListener("mousedown", handleScreenEventForSave, true);
1843
- thisDocument.addEventListener("mouseup", handleScreenEventForCancel, true);
1844
- thisDocument.addEventListener("click", handleScreenEventForCancel, true);
1845
- thisDocument.addEventListener("dblclick", handleScreenEventForCancel, true);
1697
+ thisDocument.addEventListener('keydown', handleKeydownTabAndEnter, true);
1698
+ thisDocument.addEventListener('keyup', handleKeyupTabAndEnter, true);
1699
+ thisDocument.addEventListener('mousedown', handleScreenEventForSave, true);
1700
+ thisDocument.addEventListener('mouseup', handleScreenEventForCancel, true);
1701
+ thisDocument.addEventListener('click', handleScreenEventForCancel, true);
1702
+ thisDocument.addEventListener('dblclick', handleScreenEventForCancel, true);
1846
1703
  return () => {
1847
- thisDocument.removeEventListener("keydown", handleKeydownTabAndEnter, true);
1848
- thisDocument.removeEventListener("keyup", handleKeyupTabAndEnter, true);
1849
- thisDocument.removeEventListener("mousedown", handleScreenEventForSave, true);
1850
- thisDocument.removeEventListener("mouseup", handleScreenEventForCancel, true);
1851
- thisDocument.removeEventListener("click", handleScreenEventForCancel, true);
1852
- thisDocument.removeEventListener("dblclick", handleScreenEventForCancel, true);
1704
+ thisDocument.removeEventListener('keydown', handleKeydownTabAndEnter, true);
1705
+ thisDocument.removeEventListener('keyup', handleKeyupTabAndEnter, true);
1706
+ thisDocument.removeEventListener('mousedown', handleScreenEventForSave, true);
1707
+ thisDocument.removeEventListener('mouseup', handleScreenEventForCancel, true);
1708
+ thisDocument.removeEventListener('click', handleScreenEventForCancel, true);
1709
+ thisDocument.removeEventListener('dblclick', handleScreenEventForCancel, true);
1853
1710
  };
1854
1711
  }
1855
1712
  return () => { };
@@ -1881,7 +1738,7 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1881
1738
  value: event.value,
1882
1739
  key: event.key,
1883
1740
  shiftKey: event.shiftKey,
1884
- reason: event.key === "Tab"
1741
+ reason: event.key === 'Tab'
1885
1742
  ? event.shiftKey
1886
1743
  ? CloseReason.TAB_BACKWARD
1887
1744
  : CloseReason.TAB_FORWARD
@@ -1919,15 +1776,15 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1919
1776
  }
1920
1777
  }
1921
1778
  };
1922
- const itemTransition = getTransition(transition, "item");
1779
+ const itemTransition = getTransition(transition, 'item');
1923
1780
  const modifiers = React.useMemo(() => ({ theme: theming, itemTransition }), [theming, itemTransition]);
1924
1781
  const menuList = (jsxRuntime.jsx("div", { ...mergeProps({ onKeyUp, onBlur }, containerProps), className: useBEM({
1925
1782
  block: menuContainerClass,
1926
1783
  modifiers,
1927
1784
  className,
1928
- }), style: { ...containerProps?.style, position: "relative" }, ref: containerRef, children: state && (jsxRuntime.jsx(SettingsContext.Provider, { value: settings, children: jsxRuntime.jsx(ItemSettingsContext.Provider, { value: itemSettings, children: jsxRuntime.jsx(EventHandlersContext.Provider, { value: eventHandlers, children: jsxRuntime.jsx(MenuList, { ...restProps, ariaLabel: ariaLabel || "Menu", externalRef: externalRef, containerRef: containerRef, onClose: onClose }) }) }) })) }));
1785
+ }), style: { ...containerProps?.style, position: 'relative' }, ref: containerRef, children: state && (jsxRuntime.jsx(SettingsContext.Provider, { value: settings, children: jsxRuntime.jsx(ItemSettingsContext.Provider, { value: itemSettings, children: jsxRuntime.jsx(EventHandlersContext.Provider, { value: eventHandlers, children: jsxRuntime.jsx(MenuList, { ...restProps, ariaLabel: ariaLabel || 'Menu', externalRef: externalRef, containerRef: containerRef, onClose: onClose }) }) }) })) }));
1929
1786
  if (portal === true && anchorRef?.current != null) {
1930
- if (hasParentClass("react-menu-inline-test", anchorRef.current)) {
1787
+ if (hasParentClass('react-menu-inline-test', anchorRef.current)) {
1931
1788
  portal = false;
1932
1789
  }
1933
1790
  else {
@@ -1935,8 +1792,8 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1935
1792
  }
1936
1793
  }
1937
1794
  if (portal) {
1938
- if (typeof portal === "boolean") {
1939
- if (portal && typeof document !== "undefined") {
1795
+ if (typeof portal === 'boolean') {
1796
+ if (portal && typeof document !== 'undefined') {
1940
1797
  return reactDom.createPortal(menuList, document.body);
1941
1798
  }
1942
1799
  }
@@ -1948,7 +1805,31 @@ const ControlledMenuFr = ({ "aria-label": ariaLabel, className, containerProps,
1948
1805
  };
1949
1806
  const ControlledMenu = React.forwardRef(ControlledMenuFr);
1950
1807
 
1951
- function MenuFr({ "aria-label": ariaLabel, menuButton, instanceRef, onMenuChange, ...restProps }, externalRef) {
1808
+ const FocusableItemFr = ({ className, disabled, children, isHovering, menuItemRef, externalRef, ...restProps }) => {
1809
+ const isDisabled = !!disabled;
1810
+ const ref = React.useRef(null);
1811
+ const { setHover, onPointerLeave, ...restStateProps } = useItemState(menuItemRef, ref, isHovering, isDisabled);
1812
+ const { handleClose } = React.useContext(EventHandlersContext);
1813
+ const modifiers = React.useMemo(() => ({
1814
+ disabled: isDisabled,
1815
+ hover: isHovering,
1816
+ focusable: true,
1817
+ }), [isDisabled, isHovering]);
1818
+ const renderChildren = React.useMemo(() => safeCall(children, {
1819
+ ...modifiers,
1820
+ ref,
1821
+ closeMenu: handleClose,
1822
+ }), [children, modifiers, handleClose]);
1823
+ const mergedProps = mergeProps({
1824
+ ...restStateProps,
1825
+ onPointerLeave: (e) => onPointerLeave(e, true),
1826
+ onFocus: setHover,
1827
+ }, restProps);
1828
+ return (jsxRuntime.jsx("li", { role: "menuitem", ...mergedProps, ...commonProps(isDisabled), ref: useCombinedRef(externalRef, menuItemRef), className: useBEM({ block: menuClass, element: menuItemClass, modifiers, className }), children: renderChildren }));
1829
+ };
1830
+ const FocusableItem = withHovering('FocusableItem', FocusableItemFr);
1831
+
1832
+ function MenuFr({ 'aria-label': ariaLabel, menuButton, instanceRef, onMenuChange, ...restProps }, externalRef) {
1952
1833
  const [stateProps, toggleMenu, openMenu] = useMenuStateAndFocus(restProps);
1953
1834
  const isOpen = isMenuOpen(stateProps.state);
1954
1835
  const skipOpen = React.useRef(false);
@@ -1980,13 +1861,13 @@ function MenuFr({ "aria-label": ariaLabel, menuButton, instanceRef, onMenuChange
1980
1861
  // Too many mixed types here to figure out what to pick for button. Bad code.
1981
1862
  const button = safeCall(menuButton, { open: isOpen });
1982
1863
  if (!button || !button.type)
1983
- throw new Error("Menu requires a menuButton prop.");
1864
+ throw new Error('Menu requires a menuButton prop.');
1984
1865
  const buttonProps = {
1985
1866
  ref: useCombinedRef(button.ref, buttonRef),
1986
1867
  ...mergeProps({ onClick, onKeyDown }, button.props),
1987
1868
  isOpen: false,
1988
1869
  };
1989
- if (getName(button.type) === "MenuButton") {
1870
+ if (getName(button.type) === 'MenuButton') {
1990
1871
  buttonProps.isOpen = isOpen;
1991
1872
  }
1992
1873
  const renderButton = React.cloneElement(button, buttonProps);
@@ -1995,17 +1876,165 @@ function MenuFr({ "aria-label": ariaLabel, menuButton, instanceRef, onMenuChange
1995
1876
  openMenu,
1996
1877
  closeMenu: () => toggleMenu(false),
1997
1878
  }));
1998
- return (jsxRuntime.jsxs(React.Fragment, { children: [renderButton, jsxRuntime.jsx(ControlledMenu, { ...restProps, ...stateProps, "aria-label": ariaLabel || (typeof button.props.children === "string" ? button.props.children : "Menu"), anchorRef: buttonRef, ref: externalRef, onClose: handleClose, skipOpen: skipOpen })] }));
1879
+ return (jsxRuntime.jsxs(React.Fragment, { children: [renderButton, jsxRuntime.jsx(ControlledMenu, { ...restProps, ...stateProps, "aria-label": ariaLabel || (typeof button.props.children === 'string' ? button.props.children : 'Menu'), anchorRef: buttonRef, ref: externalRef, onClose: handleClose, skipOpen: skipOpen })] }));
1999
1880
  }
2000
1881
  const Menu = React.forwardRef(MenuFr);
2001
1882
 
2002
- const SubMenuFr = ({ "aria-label": ariaLabel, className, disabled, direction, label, openTrigger, onMenuChange, isHovering, instanceRef, menuItemRef, itemProps = {}, ...restProps }) => {
1883
+ const MenuButton = React.forwardRef(function MenuButton({ className, isOpen, disabled, children, ...restProps }, ref) {
1884
+ const modifiers = React.useMemo(() => ({ open: isOpen }), [isOpen]);
1885
+ return (jsxRuntime.jsx("button", { "aria-haspopup": true, "aria-expanded": isOpen, "aria-disabled": disabled || undefined, type: "button", disabled: disabled, ...restProps, ref: ref, className: useBEM({ block: menuButtonClass, modifiers, className }), children: children }));
1886
+ });
1887
+
1888
+ const MenuDividerFr = ({ className, ...restProps }, externalRef) => {
1889
+ return (jsxRuntime.jsx("li", { role: "separator", ...restProps, ref: externalRef, className: useBEM({ block: menuClass, element: menuDividerClass, className }) }));
1890
+ };
1891
+ const MenuDivider = React.memo(React.forwardRef(MenuDividerFr));
1892
+
1893
+ const MenuGroupFr = ({ className, style, takeOverflow, ...restProps }, externalRef) => {
1894
+ const ref = React.useRef(null);
1895
+ const [overflowStyle, setOverflowStyle] = React.useState();
1896
+ const { overflow, overflowAmt } = React.useContext(MenuListContext);
1897
+ useIsomorphicLayoutEffect(() => {
1898
+ let maxHeight;
1899
+ if (takeOverflow && overflowAmt != null && overflowAmt >= 0 && ref.current) {
1900
+ maxHeight = ref.current.getBoundingClientRect().height - overflowAmt;
1901
+ if (maxHeight < 0)
1902
+ maxHeight = 0;
1903
+ }
1904
+ setOverflowStyle(maxHeight != null && maxHeight >= 0 ? { maxHeight, overflow } : undefined);
1905
+ }, [takeOverflow, overflow, overflowAmt]);
1906
+ useIsomorphicLayoutEffect(() => {
1907
+ if (overflowStyle && ref.current)
1908
+ ref.current.scrollTop = 0;
1909
+ }, [overflowStyle]);
1910
+ return (jsxRuntime.jsx("div", { ...restProps, ref: useCombinedRef(externalRef, ref), className: useBEM({ block: menuClass, element: menuGroupClass, className }), style: { ...style, ...overflowStyle } }));
1911
+ };
1912
+ const MenuGroup = React.forwardRef(MenuGroupFr);
1913
+
1914
+ const MenuHeaderFr = ({ className, ...restProps }, externalRef) => {
1915
+ return (jsxRuntime.jsx("li", { role: "presentation", ...restProps, ref: externalRef, className: useBEM({ block: menuClass, element: menuHeaderClass, className }) }));
1916
+ };
1917
+ const MenuHeader = React.memo(React.forwardRef(MenuHeaderFr));
1918
+
1919
+ const RadioGroupContext = React.createContext({});
1920
+
1921
+ const MenuItemFr = ({ className, value, href, type, checked, disabled, children, onClick, isHovering, menuItemRef, externalRef, ...restProps }) => {
1922
+ const isDisabled = !!disabled;
1923
+ const { setHover, ...restStateProps } = useItemState(menuItemRef, menuItemRef, isHovering, isDisabled);
1924
+ const eventHandlers = React.useContext(EventHandlersContext);
1925
+ const radioGroup = React.useContext(RadioGroupContext);
1926
+ const isRadio = type === 'radio';
1927
+ const isCheckBox = type === 'checkbox';
1928
+ const isAnchor = !!href && !isDisabled && !isRadio && !isCheckBox;
1929
+ const isChecked = isRadio ? radioGroup.value === value : isCheckBox ? !!checked : false;
1930
+ // handle click seems to be a combination of multiple event types, bad code.
1931
+ const handleClick = (e) => {
1932
+ if (isDisabled) {
1933
+ if (e.syntheticEvent) {
1934
+ e.syntheticEvent.stopPropagation();
1935
+ e.syntheticEvent.preventDefault();
1936
+ }
1937
+ else {
1938
+ e.stopPropagation();
1939
+ e.preventDefault();
1940
+ }
1941
+ return;
1942
+ }
1943
+ const event = {
1944
+ value,
1945
+ syntheticEvent: e,
1946
+ };
1947
+ if (e.key !== undefined) {
1948
+ const ke = e;
1949
+ event.key = ke.key;
1950
+ event.shiftKey = ke.shiftKey;
1951
+ }
1952
+ if (isCheckBox)
1953
+ event.checked = !isChecked;
1954
+ if (isRadio)
1955
+ event.name = radioGroup.name;
1956
+ safeCall(onClick, event);
1957
+ if (isRadio)
1958
+ safeCall(radioGroup.onRadioChange, event);
1959
+ eventHandlers.handleClick(event, isCheckBox || isRadio);
1960
+ };
1961
+ const handleKeyDown = (e) => {
1962
+ // if tab is allowed the handleKeyUp event can't process the tab
1963
+ if (e.key === 'Tab') {
1964
+ e.preventDefault();
1965
+ e.stopPropagation();
1966
+ }
1967
+ };
1968
+ /**
1969
+ * Keyboard events are triggered on up, otherwise subcomponents get spaces and enters typed in them
1970
+ */
1971
+ const handleKeyUp = (e) => {
1972
+ if (!isHovering)
1973
+ return;
1974
+ switch (e.key) {
1975
+ case Keys.ENTER:
1976
+ case Keys.TAB:
1977
+ case Keys.SPACE:
1978
+ e.preventDefault();
1979
+ e.stopPropagation();
1980
+ if (isAnchor) {
1981
+ menuItemRef?.current && menuItemRef.current.click();
1982
+ }
1983
+ else {
1984
+ handleClick(e);
1985
+ }
1986
+ break;
1987
+ }
1988
+ };
1989
+ const modifiers = React.useMemo(() => ({
1990
+ type,
1991
+ disabled: isDisabled,
1992
+ hover: isHovering,
1993
+ checked: isChecked,
1994
+ anchor: isAnchor,
1995
+ }), [type, isDisabled, isHovering, isChecked, isAnchor]);
1996
+ const mergedProps = mergeProps({
1997
+ ...restStateProps,
1998
+ onPointerDown: setHover,
1999
+ onKeyDown: handleKeyDown,
2000
+ onKeyUp: handleKeyUp,
2001
+ onClick: handleClick,
2002
+ }, restProps);
2003
+ // Order of props overriding (same in all components):
2004
+ // 1. Preset props adhering to WAI-ARIA Authoring Practices.
2005
+ // 2. Merged outer and local props
2006
+ // 3. ref, className
2007
+ const menuItemProps = {
2008
+ role: isRadio ? 'menuitemradio' : isCheckBox ? 'menuitemcheckbox' : 'menuitem',
2009
+ 'aria-checked': isRadio || isCheckBox ? isChecked : undefined,
2010
+ ...mergedProps,
2011
+ ...commonProps(isDisabled, isHovering),
2012
+ ref: useCombinedRef(externalRef, menuItemRef),
2013
+ className: useBEM({ block: menuClass, element: menuItemClass, modifiers, className }),
2014
+ children: React.useMemo(() => safeCall(children, modifiers), [children, modifiers]),
2015
+ };
2016
+ if (isAnchor) {
2017
+ return (jsxRuntime.jsx("li", { role: "presentation", children: jsxRuntime.jsx("a", { href: href, ...menuItemProps }) }));
2018
+ }
2019
+ else {
2020
+ return jsxRuntime.jsx("li", { ...menuItemProps });
2021
+ }
2022
+ };
2023
+ const MenuItem = withHovering('MenuItem', MenuItemFr);
2024
+
2025
+ const MenuRadioGroupFr = ({ 'aria-label': ariaLabel, className, name, value, onRadioChange, ...restProps }, externalRef) => {
2026
+ const contextValue = React.useMemo(() => ({ name, value, onRadioChange }), [name, value, onRadioChange]);
2027
+ return (jsxRuntime.jsx(RadioGroupContext.Provider, { value: contextValue, children: jsxRuntime.jsx("li", { role: "presentation", children: jsxRuntime.jsx("ul", { role: "group", "aria-label": ariaLabel || name || 'Radio group', ...restProps, ref: externalRef, className: useBEM({ block: menuClass, element: radioGroupClass, className }) }) }) }));
2028
+ };
2029
+ const MenuRadioGroup = React.forwardRef(MenuRadioGroupFr);
2030
+
2031
+ const SubMenuFr = ({ 'aria-label': ariaLabel, className, disabled, direction, label, openTrigger, onMenuChange, isHovering, instanceRef, menuItemRef, itemProps = {}, ...restProps }) => {
2003
2032
  const settings = React.useContext(SettingsContext);
2004
2033
  const { rootMenuRef } = settings;
2005
2034
  const { submenuOpenDelay, submenuCloseDelay } = React.useContext(ItemSettingsContext);
2006
2035
  const { parentMenuRef, parentDir, overflow: parentOverflow } = React.useContext(MenuListContext);
2007
2036
  const { isParentOpen, isSubmenuOpen, setOpenSubmenuCount, dispatch, updateItems } = React.useContext(MenuListItemContext);
2008
- const isPortal = parentOverflow !== "visible";
2037
+ const isPortal = parentOverflow !== 'visible';
2009
2038
  const [stateProps, toggleMenu, _openMenu] = useMenuStateAndFocus(settings);
2010
2039
  const { state } = stateProps;
2011
2040
  const isDisabled = !!disabled;
@@ -2073,7 +2102,7 @@ const SubMenuFr = ({ "aria-label": ariaLabel, className, disabled, direction, la
2073
2102
  case Keys.ENTER:
2074
2103
  case Keys.SPACE:
2075
2104
  case Keys.RIGHT:
2076
- openTrigger !== "none" && openMenu(FocusPositions.FIRST);
2105
+ openTrigger !== 'none' && openMenu(FocusPositions.FIRST);
2077
2106
  break;
2078
2107
  }
2079
2108
  };
@@ -2115,188 +2144,21 @@ const SubMenuFr = ({ "aria-label": ariaLabel, className, disabled, direction, la
2115
2144
  onPointerMove: handlePointerMove,
2116
2145
  onPointerLeave: handlePointerLeave,
2117
2146
  onKeyDown: handleItemKeyDown,
2118
- onClick: () => openTrigger !== "none" && openMenu(),
2147
+ onClick: () => openTrigger !== 'none' && openMenu(),
2119
2148
  }, restItemProps);
2120
2149
  const getMenuList = () => {
2121
- const menuList = (jsxRuntime.jsx(MenuList, { ...restProps, ...stateProps, ariaLabel: ariaLabel || (typeof label === "string" ? label : "Submenu"), anchorRef: menuItemRef, containerRef: isPortal ? rootMenuRef : containerRef, direction: direction || (parentDir === "right" || parentDir === "left" ? parentDir : "right"), parentScrollingRef: isPortal && parentMenuRef, isDisabled: isDisabled }));
2150
+ const menuList = (jsxRuntime.jsx(MenuList, { ...restProps, ...stateProps, ariaLabel: ariaLabel || (typeof label === 'string' ? label : 'Submenu'), anchorRef: menuItemRef, containerRef: isPortal ? rootMenuRef : containerRef, direction: direction || (parentDir === 'right' || parentDir === 'left' ? parentDir : 'right'), parentScrollingRef: isPortal && parentMenuRef, isDisabled: isDisabled }));
2122
2151
  const container = rootMenuRef?.current;
2123
2152
  return isPortal && container ? reactDom.createPortal(menuList, container) : menuList;
2124
2153
  };
2125
- return (jsxRuntime.jsxs("li", { className: useBEM({ block: menuClass, element: subMenuClass, className }), style: { position: "relative" }, role: "presentation", ref: containerRef, onKeyDown: handleKeyDown, children: [jsxRuntime.jsx("div", { role: "menuitem", "aria-haspopup": true, "aria-expanded": isOpen, ...mergedItemProps, ...commonProps(isDisabled, isHovering), ref: useCombinedRef(externalItemRef, menuItemRef), className: useBEM({
2154
+ return (jsxRuntime.jsxs("li", { className: useBEM({ block: menuClass, element: subMenuClass, className }), style: { position: 'relative' }, role: "presentation", ref: containerRef, onKeyDown: handleKeyDown, children: [jsxRuntime.jsx("div", { role: "menuitem", "aria-haspopup": true, "aria-expanded": isOpen, ...mergedItemProps, ...commonProps(isDisabled, isHovering), ref: useCombinedRef(externalItemRef, menuItemRef), className: useBEM({
2126
2155
  block: menuClass,
2127
2156
  element: menuItemClass,
2128
2157
  modifiers,
2129
2158
  className: itemClassName,
2130
2159
  }), children: React.useMemo(() => safeCall(label, modifiers), [label, modifiers]) }), state && getMenuList()] }));
2131
2160
  };
2132
- const SubMenu = withHovering("SubMenu", SubMenuFr);
2133
-
2134
- const RadioGroupContext = React.createContext({});
2135
-
2136
- const MenuItemFr = ({ className, value, href, type, checked, disabled, children, onClick, isHovering, menuItemRef, externalRef, ...restProps }) => {
2137
- const isDisabled = !!disabled;
2138
- const { setHover, ...restStateProps } = useItemState(menuItemRef, menuItemRef, isHovering, isDisabled);
2139
- const eventHandlers = React.useContext(EventHandlersContext);
2140
- const radioGroup = React.useContext(RadioGroupContext);
2141
- const isRadio = type === "radio";
2142
- const isCheckBox = type === "checkbox";
2143
- const isAnchor = !!href && !isDisabled && !isRadio && !isCheckBox;
2144
- const isChecked = isRadio ? radioGroup.value === value : isCheckBox ? !!checked : false;
2145
- // handle click seems to be a combination of multiple event types, bad code.
2146
- const handleClick = (e) => {
2147
- if (isDisabled) {
2148
- if (e.syntheticEvent) {
2149
- e.syntheticEvent.stopPropagation();
2150
- e.syntheticEvent.preventDefault();
2151
- }
2152
- else {
2153
- e.stopPropagation();
2154
- e.preventDefault();
2155
- }
2156
- return;
2157
- }
2158
- const event = {
2159
- value,
2160
- syntheticEvent: e,
2161
- };
2162
- if (e.key !== undefined) {
2163
- const ke = e;
2164
- event.key = ke.key;
2165
- event.shiftKey = ke.shiftKey;
2166
- }
2167
- if (isCheckBox)
2168
- event.checked = !isChecked;
2169
- if (isRadio)
2170
- event.name = radioGroup.name;
2171
- safeCall(onClick, event);
2172
- if (isRadio)
2173
- safeCall(radioGroup.onRadioChange, event);
2174
- eventHandlers.handleClick(event, isCheckBox || isRadio);
2175
- };
2176
- const handleKeyDown = (e) => {
2177
- // if tab is allowed the handleKeyUp event can't process the tab
2178
- if (e.key === "Tab") {
2179
- e.preventDefault();
2180
- e.stopPropagation();
2181
- }
2182
- };
2183
- /**
2184
- * Keyboard events are triggered on up, otherwise subcomponents get spaces and enters typed in them
2185
- */
2186
- const handleKeyUp = (e) => {
2187
- if (!isHovering)
2188
- return;
2189
- switch (e.key) {
2190
- case Keys.ENTER:
2191
- case Keys.TAB:
2192
- case Keys.SPACE:
2193
- e.preventDefault();
2194
- e.stopPropagation();
2195
- if (isAnchor) {
2196
- menuItemRef?.current && menuItemRef.current.click();
2197
- }
2198
- else {
2199
- handleClick(e);
2200
- }
2201
- break;
2202
- }
2203
- };
2204
- const modifiers = React.useMemo(() => ({
2205
- type,
2206
- disabled: isDisabled,
2207
- hover: isHovering,
2208
- checked: isChecked,
2209
- anchor: isAnchor,
2210
- }), [type, isDisabled, isHovering, isChecked, isAnchor]);
2211
- const mergedProps = mergeProps({
2212
- ...restStateProps,
2213
- onPointerDown: setHover,
2214
- onKeyDown: handleKeyDown,
2215
- onKeyUp: handleKeyUp,
2216
- onClick: handleClick,
2217
- }, restProps);
2218
- // Order of props overriding (same in all components):
2219
- // 1. Preset props adhering to WAI-ARIA Authoring Practices.
2220
- // 2. Merged outer and local props
2221
- // 3. ref, className
2222
- const menuItemProps = {
2223
- role: isRadio ? "menuitemradio" : isCheckBox ? "menuitemcheckbox" : "menuitem",
2224
- "aria-checked": isRadio || isCheckBox ? isChecked : undefined,
2225
- ...mergedProps,
2226
- ...commonProps(isDisabled, isHovering),
2227
- ref: useCombinedRef(externalRef, menuItemRef),
2228
- className: useBEM({ block: menuClass, element: menuItemClass, modifiers, className }),
2229
- children: React.useMemo(() => safeCall(children, modifiers), [children, modifiers]),
2230
- };
2231
- if (isAnchor) {
2232
- return (jsxRuntime.jsx("li", { role: "presentation", children: jsxRuntime.jsx("a", { href: href, ...menuItemProps }) }));
2233
- }
2234
- else {
2235
- return jsxRuntime.jsx("li", { ...menuItemProps });
2236
- }
2237
- };
2238
- const MenuItem = withHovering("MenuItem", MenuItemFr);
2239
-
2240
- const FocusableItemFr = ({ className, disabled, children, isHovering, menuItemRef, externalRef, ...restProps }) => {
2241
- const isDisabled = !!disabled;
2242
- const ref = React.useRef(null);
2243
- const { setHover, onPointerLeave, ...restStateProps } = useItemState(menuItemRef, ref, isHovering, isDisabled);
2244
- const { handleClose } = React.useContext(EventHandlersContext);
2245
- const modifiers = React.useMemo(() => ({
2246
- disabled: isDisabled,
2247
- hover: isHovering,
2248
- focusable: true,
2249
- }), [isDisabled, isHovering]);
2250
- const renderChildren = React.useMemo(() => safeCall(children, {
2251
- ...modifiers,
2252
- ref,
2253
- closeMenu: handleClose,
2254
- }), [children, modifiers, handleClose]);
2255
- const mergedProps = mergeProps({
2256
- ...restStateProps,
2257
- onPointerLeave: (e) => onPointerLeave(e, true),
2258
- onFocus: setHover,
2259
- }, restProps);
2260
- return (jsxRuntime.jsx("li", { role: "menuitem", ...mergedProps, ...commonProps(isDisabled), ref: useCombinedRef(externalRef, menuItemRef), className: useBEM({ block: menuClass, element: menuItemClass, modifiers, className }), children: renderChildren }));
2261
- };
2262
- const FocusableItem = withHovering("FocusableItem", FocusableItemFr);
2263
-
2264
- const MenuDividerFr = ({ className, ...restProps }, externalRef) => {
2265
- return (jsxRuntime.jsx("li", { role: "separator", ...restProps, ref: externalRef, className: useBEM({ block: menuClass, element: menuDividerClass, className }) }));
2266
- };
2267
- const MenuDivider = React.memo(React.forwardRef(MenuDividerFr));
2268
-
2269
- const MenuHeaderFr = ({ className, ...restProps }, externalRef) => {
2270
- return (jsxRuntime.jsx("li", { role: "presentation", ...restProps, ref: externalRef, className: useBEM({ block: menuClass, element: menuHeaderClass, className }) }));
2271
- };
2272
- const MenuHeader = React.memo(React.forwardRef(MenuHeaderFr));
2273
-
2274
- const MenuGroupFr = ({ className, style, takeOverflow, ...restProps }, externalRef) => {
2275
- const ref = React.useRef(null);
2276
- const [overflowStyle, setOverflowStyle] = React.useState();
2277
- const { overflow, overflowAmt } = React.useContext(MenuListContext);
2278
- useIsomorphicLayoutEffect(() => {
2279
- let maxHeight;
2280
- if (takeOverflow && overflowAmt != null && overflowAmt >= 0 && ref.current) {
2281
- maxHeight = ref.current.getBoundingClientRect().height - overflowAmt;
2282
- if (maxHeight < 0)
2283
- maxHeight = 0;
2284
- }
2285
- setOverflowStyle(maxHeight != null && maxHeight >= 0 ? { maxHeight, overflow } : undefined);
2286
- }, [takeOverflow, overflow, overflowAmt]);
2287
- useIsomorphicLayoutEffect(() => {
2288
- if (overflowStyle && ref.current)
2289
- ref.current.scrollTop = 0;
2290
- }, [overflowStyle]);
2291
- return (jsxRuntime.jsx("div", { ...restProps, ref: useCombinedRef(externalRef, ref), className: useBEM({ block: menuClass, element: menuGroupClass, className }), style: { ...style, ...overflowStyle } }));
2292
- };
2293
- const MenuGroup = React.forwardRef(MenuGroupFr);
2294
-
2295
- const MenuRadioGroupFr = ({ "aria-label": ariaLabel, className, name, value, onRadioChange, ...restProps }, externalRef) => {
2296
- const contextValue = React.useMemo(() => ({ name, value, onRadioChange }), [name, value, onRadioChange]);
2297
- return (jsxRuntime.jsx(RadioGroupContext.Provider, { value: contextValue, children: jsxRuntime.jsx("li", { role: "presentation", children: jsxRuntime.jsx("ul", { role: "group", "aria-label": ariaLabel || name || "Radio group", ...restProps, ref: externalRef, className: useBEM({ block: menuClass, element: radioGroupClass, className }) }) }) }));
2298
- };
2299
- const MenuRadioGroup = React.forwardRef(MenuRadioGroupFr);
2161
+ const SubMenu = withHovering('SubMenu', SubMenuFr);
2300
2162
 
2301
2163
  const useGridContextMenu = ({ contextMenuSelectRow, contextMenu: ContextMenu, }) => {
2302
2164
  const { redrawRows, prePopupOps, postPopupOps, getSelectedRows } = React.useContext(GridContext);
@@ -2331,46 +2193,191 @@ const useGridContextMenu = ({ contextMenuSelectRow, contextMenu: ContextMenu, })
2331
2193
  return {
2332
2194
  openMenu,
2333
2195
  cellContextMenu,
2334
- component: ContextMenu ? (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(ControlledMenu, { anchorPoint: anchorPoint, state: isOpen ? "open" : "closed", direction: "right", onClose: closeMenu, children: isOpen && (jsxRuntime.jsx(ContextMenu, { selectedRows: selectedRowsRef.current, clickedRow: clickedRowRef.current, colDef: clickedColDefRef.current, close: closeMenu })) }) })) : null,
2196
+ component: ContextMenu ? (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(ControlledMenu, { anchorPoint: anchorPoint, state: isOpen ? 'open' : 'closed', direction: "right", onClose: closeMenu, children: isOpen && (jsxRuntime.jsx(ContextMenu, { selectedRows: selectedRowsRef.current, clickedRow: clickedRowRef.current, colDef: clickedColDefRef.current, close: closeMenu })) }) })) : null,
2335
2197
  };
2336
2198
  };
2337
2199
 
2200
+ const GridLoadingOverlayComponentFr = (props, externalRef) => (jsxRuntime.jsx("div", { ref: externalRef, style: {
2201
+ left: 0,
2202
+ top: 0,
2203
+ bottom: 0,
2204
+ right: 0,
2205
+ position: 'absolute',
2206
+ backgroundColor: 'rgba(255,255,255,0.5)',
2207
+ }, children: jsxRuntime.jsx("div", { style: { height: '100%', position: 'relative' }, children: jsxRuntime.jsx("div", { style: { position: 'absolute', left: 0, top: props.headerRowHeight, right: 0, bottom: 0 }, children: jsxRuntime.jsx(lui.LuiStatusSpinner, {}) }) }) }));
2208
+ const GridLoadingOverlayComponent = React.forwardRef(GridLoadingOverlayComponentFr);
2209
+ const GridNoRowsOverlayFr = (props, externalRef) => {
2210
+ if (props.loading) {
2211
+ return jsxRuntime.jsx(GridLoadingOverlayComponent, { ref: externalRef, headerRowHeight: props.headerRowHeight });
2212
+ }
2213
+ if (props.rowCount === 0) {
2214
+ return jsxRuntime.jsx("div", { ref: externalRef, children: props.noRowsOverlayText ?? 'There are currently no rows' });
2215
+ }
2216
+ if (props.filteredRowCount === 0) {
2217
+ return jsxRuntime.jsx("div", { ref: externalRef, children: props.noRowsMatchingOverlayText ?? 'All rows have been filtered' });
2218
+ }
2219
+ return jsxRuntime.jsx("div", { ref: externalRef });
2220
+ };
2221
+ const GridNoRowsOverlay = React.forwardRef(GridNoRowsOverlayFr);
2222
+
2338
2223
  /**
2339
- * AgGrid checkbox select does not pass clicks within cell but not on the checkbox to checkbox.
2340
- * This passes the event to the checkbox when you click anywhere in the cell.
2224
+ * Retains last sort order from via <AgGrid postRowSort>.
2225
+ * Then applies this sort until next sort column change.
2226
+ * Handles stale sort, when you edit a row but don't want to re-sort.
2341
2227
  */
2342
- const clickInputWhenContainingCellClicked = (params) => {
2343
- const { data, event, colDef } = params;
2344
- if (!data || !event)
2345
- return;
2346
- const element = event.target;
2347
- // Already handled
2348
- if (element.closest(".GridCell-readonly") ||
2349
- (["BUTTON", "INPUT"].includes(element?.tagName) && element.closest(".ag-cell-inline-editing"))) {
2350
- return;
2351
- }
2352
- const row = element.closest("[row-id]");
2353
- if (!row)
2354
- return;
2355
- const colId = colDef.colId;
2356
- if (!colId)
2357
- return;
2358
- const clickInput = () => {
2359
- const cell = row.querySelector(`[col-id='${colId}']`);
2360
- if (!cell)
2361
- return;
2362
- const input = cell.querySelector("input, button");
2363
- if (!input)
2228
+ const usePostSortRowsHook = ({ setStaleGrid }) => {
2229
+ const { redrawRows } = React.useContext(GridContext);
2230
+ // On first run we need to init the first backed up sort order
2231
+ const initialised = React.useRef(false);
2232
+ // Used to detect sort order has changed since last run
2233
+ const lastSortOrderHash = React.useRef('');
2234
+ // Used to detect if sort order was the same, has the direction changed
2235
+ const previousRowSortIndexRef = React.useRef({});
2236
+ // stale sort is when there's a sort and user edits a row
2237
+ // this applies a class to the div wrapping the grid which in turn adds a * beside the sort arrow
2238
+ const sortWasStale = React.useRef(false);
2239
+ // Previous col sort is stored and reapplied if the sort direction changes on the same column and the sort was stale
2240
+ // As a sort on a stale row should just resort, not change sort direction
2241
+ const previousColSort = React.useRef([]);
2242
+ const previousQuickFilter = React.useRef('');
2243
+ return React.useCallback(({ api, nodes }) => {
2244
+ // Grid is destroyed
2245
+ if (!api)
2364
2246
  return;
2365
- input?.dispatchEvent(event);
2366
- };
2367
- setTimeout(clickInput, 20);
2247
+ const previousRowSortIndex = previousRowSortIndexRef.current;
2248
+ const hashNode = (node) => {
2249
+ return node ? JSON.stringify(node.data) : '';
2250
+ };
2251
+ const copyCurrentSortSettings = () => api.getColumnState().map((row) => ({ colId: row.colId, sort: row.sort, sortIndex: row.sortIndex }));
2252
+ const backupSortOrder = () => {
2253
+ for (const x in previousRowSortIndex)
2254
+ delete previousRowSortIndex[x];
2255
+ nodes.forEach((node, index) => (previousRowSortIndex[`${node.data.id}`] = { index, hash: hashNode(node) }));
2256
+ };
2257
+ // Check if column is the first sorted column. Note: column is preconfigured to sort its sortIndex is null not 1
2258
+ const isFirstSortColumn = (row) => row.sort && [0, null].includes(row.sortIndex ?? null);
2259
+ const isSameColumnAndDifferentSort = (col1, col2) => col1 && col2 && col1.colId === col2.colId && col1.sort != col2.sort;
2260
+ const restorePreviousSortColumnState = () => api.applyColumnState({ state: previousColSort.current });
2261
+ const sortNodesByPreviousSort = () => {
2262
+ nodes.sort((a, b) => (previousRowSortIndex[`${a.data.id}`]?.index ?? Number.MAX_SAFE_INTEGER) -
2263
+ (previousRowSortIndex[`${b.data.id}`]?.index ?? Number.MAX_SAFE_INTEGER));
2264
+ };
2265
+ // On first load copy the current sort
2266
+ if (!initialised.current) {
2267
+ initialised.current = true;
2268
+ previousColSort.current = copyCurrentSortSettings();
2269
+ }
2270
+ const newSortOrder = JSON.stringify(copyCurrentSortSettings());
2271
+ let sortOrderChanged = newSortOrder != lastSortOrderHash.current;
2272
+ const quickFilter = api.getQuickFilter();
2273
+ if (previousQuickFilter.current != quickFilter) {
2274
+ previousQuickFilter.current = quickFilter ?? '';
2275
+ sortOrderChanged = true;
2276
+ }
2277
+ if (lodashEs.isEmpty(previousRowSortIndex)) {
2278
+ backupSortOrder();
2279
+ }
2280
+ if (sortOrderChanged) {
2281
+ const thisFirstCol = copyCurrentSortSettings().find(isFirstSortColumn);
2282
+ const previousFirstCol = previousColSort.current.find(isFirstSortColumn);
2283
+ // Change to sort can be: (in the context of stale sort do...)
2284
+ // - no sort to sorted (do nothing)
2285
+ // - asc to desc (resort as asc, and remove stale sort)
2286
+ // - desc to no sort (resort as desc, and remove stale sort)
2287
+ const wasSortChangedOnSameColumn = previousFirstCol && (!thisFirstCol || isSameColumnAndDifferentSort(previousFirstCol, thisFirstCol));
2288
+ // if sort was stale, and we're here, someone has clicked a stale sort order (^*) in the column header
2289
+ if (sortWasStale.current && wasSortChangedOnSameColumn) {
2290
+ // Sort was an existing priority 1 column
2291
+ // We want to re-sort with the old sort direction and clear stale sort
2292
+ sortWasStale.current = false;
2293
+ setStaleGrid(false);
2294
+ // trigger a recapture of sort order
2295
+ lastSortOrderHash.current = '';
2296
+ restorePreviousSortColumnState();
2297
+ }
2298
+ else {
2299
+ // Sort was on a different column so clear sort and sort like normal
2300
+ if (sortWasStale.current) {
2301
+ sortWasStale.current = false;
2302
+ setStaleGrid(false);
2303
+ }
2304
+ // Columns were sorted so retain the sort
2305
+ backupSortOrder();
2306
+ lastSortOrderHash.current = newSortOrder;
2307
+ }
2308
+ }
2309
+ else {
2310
+ let firstChangedNodeIndex = -1;
2311
+ let lastNewNode = undefined;
2312
+ let changedRowCount = 0;
2313
+ let newRowCount = 0;
2314
+ let index = 0;
2315
+ for (const node of nodes) {
2316
+ const psr = previousRowSortIndex[`${node.data.id}`];
2317
+ if (psr) {
2318
+ if (psr.hash != hashNode(node)) {
2319
+ if (firstChangedNodeIndex === -1)
2320
+ firstChangedNodeIndex = index;
2321
+ changedRowCount++;
2322
+ }
2323
+ }
2324
+ else {
2325
+ lastNewNode = node;
2326
+ newRowCount++;
2327
+ }
2328
+ index++;
2329
+ }
2330
+ let wasStale = false;
2331
+ if (changedRowCount === 0 && newRowCount === 1) {
2332
+ // insert new row at end
2333
+ const newIndex = index - 1;
2334
+ previousRowSortIndex[`${lastNewNode?.data.id}`] = { index: newIndex, hash: hashNode(lastNewNode) };
2335
+ wasStale = true;
2336
+ }
2337
+ else if (changedRowCount === 2 && newRowCount === 0) {
2338
+ // This must be a swap rows (sometimes it's not, needs further attention)
2339
+ backupSortOrder();
2340
+ wasStale = false;
2341
+ }
2342
+ else if (changedRowCount > 1 && newRowCount === 1) {
2343
+ // This must be a insert so, insert new row near the row that changed
2344
+ previousRowSortIndex[`${lastNewNode?.data.id}`] = {
2345
+ index: firstChangedNodeIndex + 0.5,
2346
+ hash: hashNode(lastNewNode),
2347
+ };
2348
+ wasStale = true;
2349
+ // For some reason AgGrid mis-positions the inserted row.
2350
+ lastNewNode && redrawRows();
2351
+ }
2352
+ else if (changedRowCount == 1 && newRowCount === 0) {
2353
+ // User edited one row so, do nothing, retain sort
2354
+ wasStale = true;
2355
+ }
2356
+ else if (changedRowCount !== 0 || newRowCount != 0) {
2357
+ // too many rows changed, resort
2358
+ backupSortOrder();
2359
+ }
2360
+ if (wasStale) {
2361
+ // Check if the sort order the aggrid passed matches our stale sort order
2362
+ const stillStale = Object.keys(previousRowSortIndex).length != nodes.length ||
2363
+ nodes.some((node, index) => previousRowSortIndex[`${node.data.id}`]?.index !== index);
2364
+ // If we haven't already processed a stale sort then...
2365
+ if (stillStale && !sortWasStale.current) {
2366
+ // backup sort state, so we can restore it when sort is clicked on a stale column
2367
+ previousColSort.current = copyCurrentSortSettings();
2368
+ sortWasStale.current = true;
2369
+ setStaleGrid(true);
2370
+ }
2371
+ }
2372
+ sortNodesByPreviousSort();
2373
+ }
2374
+ }, [redrawRows, setStaleGrid]);
2368
2375
  };
2369
2376
 
2370
2377
  /**
2371
2378
  * Wrapper for AgGrid to add commonly used functionality.
2372
2379
  */
2373
- const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection = "multiple", suppressColumnVirtualization = true, theme = "ag-theme-step-default", sizeColumns = "auto", selectColumnPinned = null, contextMenuSelectRow = false, singleClickEdit = false, rowData, rowHeight = theme === "ag-theme-step-default" ? 40 : theme === "ag-theme-step-compact" ? 36 : 40, ...params }) => {
2380
+ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection = 'multiple', suppressColumnVirtualization = true, theme = 'ag-theme-step-default', sizeColumns = 'auto', selectColumnPinned = null, contextMenuSelectRow = false, singleClickEdit = false, rowData, rowHeight = theme === 'ag-theme-step-default' ? 40 : theme === 'ag-theme-step-compact' ? 36 : 40, ...params }) => {
2374
2381
  const { gridReady, gridRenderState, setApis, ensureRowVisible, getFirstRowId, selectRowsById, focusByRowById, ensureSelectedRowIsVisible, autoSizeColumns, sizeColumnsToFit, externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync, isExternalFilterPresent, doesExternalFilterPass, setOnCellEditingComplete, getColDef, showNoRowsOverlay, prePopupOps, stopEditing, } = React.useContext(GridContext);
2375
2382
  const { checkUpdating, updatedDep, updatingCols } = React.useContext(GridUpdatingContext);
2376
2383
  const gridDivRef = React.useRef(null);
@@ -2399,20 +2406,20 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2399
2406
  needsAutoSize.current = true;
2400
2407
  return;
2401
2408
  }
2402
- const skipHeader = sizeColumns === "auto-skip-headers" && gridRendered === "rows-visible";
2403
- if (sizeColumns === "auto" || skipHeader) {
2409
+ const skipHeader = sizeColumns === 'auto-skip-headers' && gridRendered === 'rows-visible';
2410
+ if (sizeColumns === 'auto' || skipHeader) {
2404
2411
  const result = autoSizeColumns({ skipHeader, userSizedColIds: userSizedColIds.current, includeFlex: true });
2405
2412
  if (!result) {
2406
2413
  needsAutoSize.current = true;
2407
2414
  return;
2408
2415
  }
2409
- if (gridRendered === "empty") {
2416
+ if (gridRendered === 'empty') {
2410
2417
  if (!hasSetContentSizeEmpty.current && !hasSetContentSize.current) {
2411
2418
  hasSetContentSizeEmpty.current = true;
2412
2419
  params.onContentSize?.(result);
2413
2420
  }
2414
2421
  }
2415
- else if (gridRendered === "rows-visible") {
2422
+ else if (gridRendered === 'rows-visible') {
2416
2423
  if (!hasSetContentSize.current) {
2417
2424
  if (lastFullResize.current === result.width) {
2418
2425
  hasSetContentSize.current = true;
@@ -2426,10 +2433,10 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2426
2433
  }
2427
2434
  else {
2428
2435
  // It should be impossible to get here
2429
- console.error("Unknown value returned from hasGridRendered");
2436
+ console.error('Unknown value returned from hasGridRendered');
2430
2437
  }
2431
2438
  }
2432
- if (sizeColumns !== "none") {
2439
+ if (sizeColumns !== 'none') {
2433
2440
  sizeColumnsToFit();
2434
2441
  }
2435
2442
  setAutoSized(true);
@@ -2448,7 +2455,7 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2448
2455
  needsAutoSize.current = true;
2449
2456
  }
2450
2457
  }
2451
- if (needsAutoSize.current || (!hasSetContentSize.current && sizeColumns === "auto")) {
2458
+ if (needsAutoSize.current || (!hasSetContentSize.current && sizeColumns === 'auto')) {
2452
2459
  needsAutoSize.current = false;
2453
2460
  setInitialContentSize();
2454
2461
  }
@@ -2490,7 +2497,7 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2490
2497
  }
2491
2498
  const selectedRows = api.getSelectedRows();
2492
2499
  // We don't want to update selected Items if it hasn't changed to prevent excess renders
2493
- if (params.externalSelectedItems.length != selectedRows.length ||
2500
+ if (params.externalSelectedItems.length !== selectedRows.length ||
2494
2501
  isNotEmpty(lodashEs.xorBy(selectedRows, params.externalSelectedItems, (row) => row.id))) {
2495
2502
  setExternallySelectedItemsAreInSync(false);
2496
2503
  params.setExternalSelectedItems([...selectedRows]);
@@ -2546,14 +2553,14 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2546
2553
  editable,
2547
2554
  cellClassRules: {
2548
2555
  ...colDef.cellClassRules,
2549
- "GridCell-readonly": (ccp) => !editable(ccp),
2556
+ 'GridCell-readonly': (ccp) => !editable(ccp),
2550
2557
  },
2551
2558
  };
2552
2559
  });
2553
2560
  return params.selectable || params.onRowDragEnd
2554
2561
  ? [
2555
2562
  {
2556
- colId: "selection",
2563
+ colId: 'selection',
2557
2564
  editable: false,
2558
2565
  rowDrag: !!params.onRowDragEnd,
2559
2566
  minWidth: params.selectable && params.onRowDragEnd ? 76 : 48,
@@ -2563,12 +2570,12 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2563
2570
  exportable: false,
2564
2571
  },
2565
2572
  checkboxSelection: params.selectable,
2566
- headerClass: params.onRowDragEnd ? "ag-header-select-draggable" : undefined,
2567
- headerComponent: rowSelection === "multiple" ? GridHeaderSelect : null,
2573
+ headerClass: params.onRowDragEnd ? 'ag-header-select-draggable' : undefined,
2574
+ headerComponent: rowSelection === 'multiple' ? GridHeaderSelect : null,
2568
2575
  suppressHeaderKeyboardEvent: (e) => {
2569
2576
  if (!params.selectable)
2570
2577
  return false;
2571
- if ((e.event.key === "Enter" || e.event.key === " ") && !e.event.repeat) {
2578
+ if ((e.event.key === 'Enter' || e.event.key === ' ') && !e.event.repeat) {
2572
2579
  if (lodashEs.isEmpty(e.api.getSelectedRows())) {
2573
2580
  e.api.selectAllFiltered();
2574
2581
  }
@@ -2619,7 +2626,7 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2619
2626
  // Don't update while there are spinners
2620
2627
  if (!lodashEs.isEmpty(updatingCols()))
2621
2628
  return;
2622
- const skipHeader = sizeColumns === "auto-skip-headers";
2629
+ const skipHeader = sizeColumns === 'auto-skip-headers';
2623
2630
  if (hasSetContentSize.current) {
2624
2631
  autoSizeColumns({ skipHeader, userSizedColIds: userSizedColIds.current, colIds: colIdsEdited.current });
2625
2632
  }
@@ -2649,7 +2656,7 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2649
2656
  event.node.setSelected(true, true);
2650
2657
  }
2651
2658
  // Cell already being edited, so don't re-edit until finished
2652
- if (checkUpdating([event.colDef.field ?? ""], event.data.id)) {
2659
+ if (checkUpdating([event.colDef.field ?? ''], event.data.id)) {
2653
2660
  return;
2654
2661
  }
2655
2662
  if (event.rowIndex !== null) {
@@ -2695,11 +2702,11 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2695
2702
  */
2696
2703
  const onCellKeyPress = React.useCallback((e) => {
2697
2704
  const kbe = e.event;
2698
- if (kbe.key === "Enter") {
2705
+ if (kbe.key === 'Enter') {
2699
2706
  if (!invokeEditAction(e))
2700
2707
  startCellEditing(e);
2701
2708
  }
2702
- if (kbe.key === "Tab") {
2709
+ if (kbe.key === 'Tab') {
2703
2710
  // eslint-disable-next-line
2704
2711
  prePopupOps();
2705
2712
  }
@@ -2709,14 +2716,14 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2709
2716
  * but we don't want the non-flex auto-sized columns to "fit" size, so suppressSizeToFit is set to true.
2710
2717
  */
2711
2718
  const columnDefsAdjusted = React.useMemo(() => {
2712
- const adjustColDefOrGroup = (colDef) => "children" in colDef ? adjustGroupColDef(colDef) : adjustColDef(colDef);
2719
+ const adjustColDefOrGroup = (colDef) => 'children' in colDef ? adjustGroupColDef(colDef) : adjustColDef(colDef);
2713
2720
  const adjustGroupColDef = (colDef) => ({
2714
2721
  ...colDef,
2715
2722
  children: colDef.children.map((colDef) => adjustColDefOrGroup(colDef)),
2716
2723
  });
2717
2724
  const adjustColDef = (colDef) => ({
2718
2725
  ...colDef,
2719
- suppressSizeToFit: (sizeColumns === "auto" || sizeColumns === "auto-skip-headers") && !colDef.flex,
2726
+ suppressSizeToFit: (sizeColumns === 'auto' || sizeColumns === 'auto-skip-headers') && !colDef.flex,
2720
2727
  sortable: colDef.sortable && params.defaultColDef?.sortable !== false,
2721
2728
  });
2722
2729
  return columnDefs.map((colDef) => adjustColDefOrGroup(colDef));
@@ -2738,8 +2745,8 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2738
2745
  if (lodashEs.isEmpty(colIds)) {
2739
2746
  // Columns to resize?
2740
2747
  if (!lodashEs.isEmpty(colIdsEdited.current)) {
2741
- const skipHeader = sizeColumns === "auto-skip-headers";
2742
- if (sizeColumns === "auto" || skipHeader) {
2748
+ const skipHeader = sizeColumns === 'auto-skip-headers';
2749
+ if (sizeColumns === 'auto' || skipHeader) {
2743
2750
  lodashEs.defer(() => {
2744
2751
  if (hasSetContentSize.current) {
2745
2752
  autoSizeColumns({
@@ -2775,7 +2782,7 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2775
2782
  * Resize columns to fit if required on window/container resize
2776
2783
  */
2777
2784
  const onGridSizeChanged = React.useCallback(() => {
2778
- if (sizeColumns !== "none") {
2785
+ if (sizeColumns !== 'none') {
2779
2786
  sizeColumnsToFit();
2780
2787
  }
2781
2788
  }, [sizeColumns, sizeColumnsToFit]);
@@ -2791,10 +2798,10 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2791
2798
  if (colId == null)
2792
2799
  return;
2793
2800
  switch (e.source) {
2794
- case "uiColumnDragged":
2801
+ case 'uiColumnDragged':
2795
2802
  userSizedColIds.current.add(colId);
2796
2803
  break;
2797
- case "autosizeColumns":
2804
+ case 'autosizeColumns':
2798
2805
  userSizedColIds.current.delete(colId);
2799
2806
  break;
2800
2807
  }
@@ -2816,33 +2823,35 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2816
2823
  }
2817
2824
  }
2818
2825
  }, []);
2819
- const onRowDragEnd = React.useCallback(async (event) => {
2820
- const clientSideRowModel = event.api.getModel();
2821
- if (event.node.rowIndex != null) {
2822
- const lastHighlightedRowNode = clientSideRowModel.getLastHighlightedRowNode();
2823
- const isBelow = lastHighlightedRowNode && lastHighlightedRowNode.highlighted === agGridCommunity.RowHighlightPosition.Below;
2824
- let targetIndex = event.overIndex;
2825
- if (event.node.rowIndex > event.overIndex) {
2826
- targetIndex += isBelow ? 1 : 0;
2827
- }
2828
- else {
2829
- targetIndex += isBelow ? 0 : -1;
2826
+ const onRowDragEnd = React.useCallback((event) => {
2827
+ void (async () => {
2828
+ const clientSideRowModel = event.api.getModel();
2829
+ if (event.node.rowIndex != null) {
2830
+ const lastHighlightedRowNode = clientSideRowModel.getLastHighlightedRowNode();
2831
+ const isBelow = lastHighlightedRowNode && lastHighlightedRowNode.highlighted === agGridCommunity.RowHighlightPosition.Below;
2832
+ let targetIndex = event.overIndex;
2833
+ if (event.node.rowIndex > event.overIndex) {
2834
+ targetIndex += isBelow ? 1 : 0;
2835
+ }
2836
+ else {
2837
+ targetIndex += isBelow ? 0 : -1;
2838
+ }
2839
+ const moved = event.node.data;
2840
+ const target = event.overNode?.data;
2841
+ moved.id !== target?.id && //moved over a different row
2842
+ event.node.rowIndex != targetIndex && //moved to a different index
2843
+ params.onRowDragEnd &&
2844
+ (await params.onRowDragEnd(moved, target, targetIndex));
2830
2845
  }
2831
- const moved = event.node.data;
2832
- const target = event.overNode?.data;
2833
- moved.id !== target?.id && //moved over a different row
2834
- event.node.rowIndex != targetIndex && //moved to a different index
2835
- params.onRowDragEnd &&
2836
- (await params.onRowDragEnd(moved, target, targetIndex));
2837
- }
2838
- clientSideRowModel.highlightRowAtPixel(null);
2846
+ clientSideRowModel.highlightRowAtPixel(null);
2847
+ })();
2839
2848
  }, [params]);
2840
2849
  // This is setting a ref in the GridContext so won't be triggering an update loop
2841
2850
  setOnCellEditingComplete(params.onCellEditingComplete);
2842
2851
  const headerRowCount = columnDefs.some((c) => c.children) ? 2 : 1;
2843
- return (jsxRuntime.jsxs("div", { "data-testid": dataTestId, className: clsx("Grid-container", theme, "theme-specific", staleGrid && "Grid-sortIsStale", gridReady && rowData && autoSized && "Grid-ready"), children: [gridContextMenu.component, jsxRuntime.jsx("div", { style: { flex: 1 }, ref: gridDivRef, children: jsxRuntime.jsx(agGridReact.AgGridReact, { rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: (params) => `${params.data.id}`, suppressRowClickSelection: true, rowSelection: rowSelection, suppressBrowserResizeObserver: true, onGridSizeChanged: onGridSizeChanged, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onColumnVisible: () => {
2852
+ return (jsxRuntime.jsxs("div", { "data-testid": dataTestId, className: clsx('Grid-container', theme, 'theme-specific', staleGrid && 'Grid-sortIsStale', gridReady && rowData && autoSized && 'Grid-ready'), children: [gridContextMenu.component, jsxRuntime.jsx("div", { style: { flex: 1 }, ref: gridDivRef, children: jsxRuntime.jsx(agGridReact.AgGridReact, { rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: (params) => `${params.data.id}`, suppressRowClickSelection: true, rowSelection: rowSelection, suppressBrowserResizeObserver: true, onGridSizeChanged: onGridSizeChanged, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onColumnVisible: () => {
2844
2853
  setInitialContentSize();
2845
- }, onRowDataUpdated: onRowDataChanged, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStarted: refreshSelectedRows, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: { minWidth: 48, ...lodashEs.omit(params.defaultColDef, ["editable"]) }, columnDefs: columnDefsAdjusted, rowData: rowData, noRowsOverlayComponent: (event) => {
2854
+ }, onRowDataUpdated: onRowDataChanged, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStarted: refreshSelectedRows, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: { minWidth: 48, ...lodashEs.omit(params.defaultColDef, ['editable']) }, columnDefs: columnDefsAdjusted, rowData: rowData, noRowsOverlayComponent: (event) => {
2846
2855
  let rowCount = 0;
2847
2856
  event.api.forEachNode(() => rowCount++);
2848
2857
  return (jsxRuntime.jsx(GridNoRowsOverlay, { loading: !rowData || params.loading === true, rowCount: rowCount, headerRowHeight: headerRowCount * rowHeight, filteredRowCount: event.api.getDisplayedRowCount(), noRowsOverlayText: params.noRowsOverlayText, noRowsMatchingOverlayText: params.noRowsMatchingOverlayText }));
@@ -2853,18 +2862,20 @@ const GridPopoverContext = React.createContext({
2853
2862
  anchorRef: { current: null },
2854
2863
  saving: false,
2855
2864
  setSaving: () => { },
2856
- colId: "",
2857
- field: "",
2865
+ colId: '',
2866
+ field: '',
2858
2867
  value: null,
2859
2868
  data: {},
2860
2869
  selectedRows: [],
2861
- updateValue: async () => false,
2862
- formatValue: () => "! No gridPopoverContextProvider !",
2870
+ updateValue: () => false,
2871
+ formatValue: () => '! No gridPopoverContextProvider !',
2863
2872
  });
2864
2873
  const useGridPopoverContext = () => React.useContext(GridPopoverContext);
2865
2874
 
2866
- const GridPopoverContextProvider = ({ props, children }) => {
2875
+ const GridPopoverContextProvider = (props2) => {
2867
2876
  const { getFilteredSelectedRows, updatingCells } = React.useContext(GridContext);
2877
+ const children = props2.children;
2878
+ const props = props2.props;
2868
2879
  const anchorRef = React.useRef(props.eGridCell);
2869
2880
  const hasSaved = React.useRef(false);
2870
2881
  const [saving, setSaving] = React.useState(false);
@@ -2873,8 +2884,8 @@ const GridPopoverContextProvider = ({ props, children }) => {
2873
2884
  const multiEdit = cellEditorParams?.multiEdit ?? false;
2874
2885
  // Then item that is clicked on will always be first in the list
2875
2886
  const selectedRows = React.useMemo(() => multiEdit ? lodashEs.sortBy(getFilteredSelectedRows(), (row) => row.id !== props.data.id) : [props.data], [getFilteredSelectedRows, multiEdit, props.data]);
2876
- const field = props.colDef?.field ?? "";
2877
- const colId = props.colDef?.colId ?? field ?? "";
2887
+ const field = props.colDef?.field ?? '';
2888
+ const colId = props.colDef?.colId ?? field ?? '';
2878
2889
  const updateValue = React.useCallback(async (saveFn, tabDirection) => {
2879
2890
  if (hasSaved.current)
2880
2891
  return true;
@@ -2896,7 +2907,7 @@ const GridPopoverContextProvider = ({ props, children }) => {
2896
2907
  };
2897
2908
 
2898
2909
  const GridCellMultiSelectClassRules = {
2899
- "ag-selected-for-edit": (params) => {
2910
+ 'ag-selected-for-edit': (params) => {
2900
2911
  const { api, node, colDef } = params;
2901
2912
  const cep = colDef.cellEditorSelector
2902
2913
  ? colDef.cellEditorSelector(params)?.params
@@ -2910,9 +2921,9 @@ const GridCellMultiSelectClassRules = {
2910
2921
  },
2911
2922
  };
2912
2923
 
2913
- const GridIcon = (props) => (jsxRuntime.jsx(lui.LuiIcon, { name: props.icon, title: props.title, alt: props.title, size: props.size ?? "md", className: clsx(`AgGridGenericCellRenderer-${props.icon}Icon`, props.className, props.disabled && "GridIcon-disabled") }));
2924
+ const GridIcon = (props) => (jsxRuntime.jsx(lui.LuiIcon, { name: props.icon, title: props.title, alt: props.title, size: props.size ?? 'md', className: clsx(`AgGridGenericCellRenderer-${props.icon}Icon`, props.className, props.disabled && 'GridIcon-disabled') }));
2914
2925
 
2915
- const GridLoadableCell = () => (jsxRuntime.jsx(lui.LuiMiniSpinner, { size: 22, divProps: { className: "GridLoadableCell-container", role: "status", "aria-label": "Loading" } }));
2926
+ const GridLoadableCell = () => (jsxRuntime.jsx(lui.LuiMiniSpinner, { size: 22, divProps: { className: 'GridLoadableCell-container', role: 'status', 'aria-label': 'Loading' } }));
2916
2927
 
2917
2928
  const GridCellRenderer = (props) => {
2918
2929
  const { checkUpdating } = React.useContext(GridUpdatingContext);
@@ -2923,38 +2934,38 @@ const GridCellRenderer = (props) => {
2923
2934
  const infoFn = rendererParams?.info;
2924
2935
  let infoText = props.data !== undefined && infoFn ? infoFn(props) : undefined;
2925
2936
  if (Array.isArray(warningText))
2926
- warningText = warningText.join("\n");
2937
+ warningText = warningText.join('\n');
2927
2938
  if (Array.isArray(infoText))
2928
- infoText = infoText.join("\n");
2929
- return checkUpdating(colDef.field ?? colDef.colId ?? "", props.data.id) ? (jsxRuntime.jsx(GridLoadableCell, {})) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [!!warningText && (jsxRuntime.jsx(GridIcon, { icon: "ic_warning_outline", title: typeof warningText === "string" ? warningText : "Warning" })), !!infoText && jsxRuntime.jsx(GridIcon, { icon: "ic_info_outline", title: typeof infoText === "string" ? infoText : "Info" }), jsxRuntime.jsx("div", { className: "GridCell-container", children: colDef.cellRendererParams?.originalCellRenderer ? (jsxRuntime.jsx(colDef.cellRendererParams.originalCellRenderer, { ...props })) : (jsxRuntime.jsx("span", { title: props.valueFormatted ?? undefined, children: props.valueFormatted })) }), fnOrVar(colDef.editable, props) && rendererParams?.rightHoverElement && (jsxRuntime.jsx("div", { className: "GridCell-hoverRight", children: rendererParams?.rightHoverElement }))] }));
2939
+ infoText = infoText.join('\n');
2940
+ return checkUpdating(colDef.field ?? colDef.colId ?? '', props.data.id) ? (jsxRuntime.jsx(GridLoadableCell, {})) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [!!warningText && (jsxRuntime.jsx(GridIcon, { icon: 'ic_warning_outline', title: typeof warningText === 'string' ? warningText : 'Warning' })), !!infoText && jsxRuntime.jsx(GridIcon, { icon: 'ic_info_outline', title: typeof infoText === 'string' ? infoText : 'Info' }), jsxRuntime.jsx("div", { className: 'GridCell-container', children: colDef.cellRendererParams?.originalCellRenderer ? (jsxRuntime.jsx(colDef.cellRendererParams.originalCellRenderer, { ...props })) : (jsxRuntime.jsx("span", { title: props.valueFormatted ?? undefined, children: props.valueFormatted })) }), fnOrVar(colDef.editable, props) && rendererParams?.rightHoverElement && (jsxRuntime.jsx("div", { className: 'GridCell-hoverRight', children: rendererParams?.rightHoverElement }))] }));
2930
2941
  };
2931
2942
  const suppressCellKeyboardEvents = (e) => {
2932
2943
  const shortcutKeys = e.colDef.cellRendererParams?.shortcutKeys ?? {};
2933
2944
  const exec = shortcutKeys[e.event.key];
2934
- if (exec && !e.editing && !e.event.repeat && e.event.type === "keydown") {
2945
+ if (exec && !e.editing && !e.event.repeat && e.event.type === 'keydown') {
2935
2946
  const editable = fnOrVar(e.colDef?.editable, e);
2936
2947
  return editable ? (exec(e) ?? true) : true;
2937
2948
  }
2938
2949
  // It's important that aggrid doesn't trigger edit on enter
2939
2950
  // as the incorrect selected rows will be returned
2940
- return !["ArrowLeft", "ArrowRight", "ArrowDown", "ArrowUp", "Tab", " ", "Home", "End", "PageUp", "PageDown"].includes(e.event.key);
2951
+ return !['ArrowLeft', 'ArrowRight', 'ArrowDown', 'ArrowUp', 'Tab', ' ', 'Home', 'End', 'PageUp', 'PageDown'].includes(e.event.key);
2941
2952
  };
2942
2953
  const generateFilterGetter = (field, filterValueGetter, valueFormatter) => {
2943
2954
  if (filterValueGetter)
2944
2955
  return filterValueGetter;
2945
2956
  // aggrid will default to valueGetter
2946
- if (typeof valueFormatter !== "function" || !field)
2957
+ if (typeof valueFormatter !== 'function' || !field)
2947
2958
  return undefined;
2948
2959
  return (params) => {
2949
2960
  const value = params.getValue(field);
2950
2961
  let formattedValue = valueFormatter({ ...params, value });
2951
2962
  // Search for null values using standard dash
2952
- if (formattedValue === "")
2953
- formattedValue += " -";
2963
+ if (formattedValue === '')
2964
+ formattedValue += ' -';
2954
2965
  // Search by raw value as well as formatted
2955
- const gotValue = ["string", "number"].includes(typeof value) ? value : undefined;
2956
- return (formattedValue + (gotValue != null && formattedValue != gotValue ? " " + gotValue : "")) //
2957
- .replace(/\s+/g, " ")
2966
+ const gotValue = ['string', 'number'].includes(typeof value) ? value : undefined;
2967
+ return (formattedValue + (gotValue != null && formattedValue != gotValue ? ' ' + gotValue : '')) //
2968
+ .replace(/\s+/g, ' ')
2958
2969
  .trim();
2959
2970
  };
2960
2971
  };
@@ -2997,15 +3008,15 @@ const GridCell = (props, custom) => {
2997
3008
  // Default value formatter, otherwise react freaks out on objects
2998
3009
  valueFormatter: (params) => {
2999
3010
  if (params.value == null)
3000
- return "";
3001
- const types = ["number", "boolean", "string"];
3011
+ return '';
3012
+ const types = ['number', 'boolean', 'string'];
3002
3013
  if (types.includes(typeof params.value))
3003
3014
  return `${params.value}`;
3004
3015
  else
3005
3016
  return JSON.stringify(params.value);
3006
3017
  },
3007
3018
  ...props,
3008
- cellRenderer: typeof props.cellRenderer === "string" ? props.cellRenderer : GridCellRenderer,
3019
+ cellRenderer: typeof props.cellRenderer === 'string' ? props.cellRenderer : GridCellRenderer,
3009
3020
  cellRendererParams: {
3010
3021
  originalCellRenderer: props.cellRenderer,
3011
3022
  ...props.cellRendererParams,
@@ -3021,16 +3032,16 @@ const GenericCellEditorComponentWrapper = (editor) => {
3021
3032
  return React.forwardRef(function GenericCellEditorComponentFr(cellEditorParams, _) {
3022
3033
  const valueFormatted = cellEditorParams.formatValue
3023
3034
  ? cellEditorParams.formatValue(cellEditorParams.value)
3024
- : "Missing formatter";
3025
- return (jsxRuntime.jsxs(GridPopoverContextProvider, { props: cellEditorParams, children: [jsxRuntime.jsx(cellEditorParams.colDef.cellRenderer, { ...cellEditorParams, valueFormatted: valueFormatted, ...cellEditorParams.colDef.cellRendererParams }), obj.editor && jsxRuntime.jsx(obj.editor, { ...cellEditorParams })] }));
3035
+ : 'Missing formatter';
3036
+ return (jsxRuntime.jsx(GridPopoverContextProvider, { props: cellEditorParams, children: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(cellEditorParams.colDef.cellRenderer, { ...cellEditorParams, valueFormatted: valueFormatted, ...cellEditorParams.colDef.cellRendererParams }), obj.editor && jsxRuntime.jsx(obj.editor, { ...cellEditorParams })] }) }));
3026
3037
  });
3027
3038
  };
3028
3039
 
3029
- const GridCellFillerColId = "gridCellFiller";
3040
+ const GridCellFillerColId = 'gridCellFiller';
3030
3041
  const isGridCellFiller = (col) => col.colId === GridCellFillerColId;
3031
3042
  const GridCellFiller = () => ({
3032
3043
  colId: GridCellFillerColId,
3033
- headerName: "",
3044
+ headerName: '',
3034
3045
  flex: 1,
3035
3046
  });
3036
3047
 
@@ -3048,8 +3059,27 @@ const GridCellMultiEditor = (props, cellEditorSelector) => GridCell({
3048
3059
  ...props,
3049
3060
  });
3050
3061
 
3051
- const GridFilterHeaderIconButton = React.forwardRef(function columnsButton({ icon, title, onClick, buttonProps, disabled = false, size = "md" }, ref) {
3052
- return (jsxRuntime.jsx(lui.LuiButton, { ...buttonProps, type: "button", level: "tertiary", className: "lui-button-icon-only", ref: ref, "aria-label": title, title: title, onClick: onClick, disabled: disabled, children: jsxRuntime.jsx(lui.LuiIcon, { name: icon, alt: "Menu", size: size }) }));
3062
+ const useGridFilter = (filter) => {
3063
+ const { addExternalFilter, removeExternalFilter } = React.useContext(GridContext);
3064
+ React.useEffect(() => {
3065
+ const thisFilter = filter;
3066
+ thisFilter && addExternalFilter(thisFilter);
3067
+ return () => {
3068
+ thisFilter && removeExternalFilter(thisFilter);
3069
+ };
3070
+ }, [addExternalFilter, filter, removeExternalFilter]);
3071
+ };
3072
+
3073
+ const GridFilterButtons = ({ className, luiButtonProps, options, }) => {
3074
+ // Select defaultSelected option, otherwise first option. If no options select none.
3075
+ const [selectedOption, setSelectedOption] = React.useState(options.find((option) => option.defaultSelected) ?? options[0]);
3076
+ const filter = React.useMemo(() => selectedOption?.filter, [selectedOption]);
3077
+ useGridFilter(filter);
3078
+ return (jsxRuntime.jsx("div", { className: clsx(className, 'flex-col-center'), children: jsxRuntime.jsx(lui.LuiButtonGroup, { children: options.map((option, index) => (jsxRuntime.jsx(lui.LuiButton, { ...luiButtonProps, className: clsx(`lui-button lui-button-secondary`, selectedOption?.label === option.label && `lui-button-active`, luiButtonProps?.className), onClick: () => setSelectedOption(option), children: option.label }, `${index}`))) }) }));
3079
+ };
3080
+
3081
+ const GridFilterHeaderIconButton = React.forwardRef(function columnsButton({ icon, title, onClick, buttonProps, disabled = false, size = 'md' }, ref) {
3082
+ return (jsxRuntime.jsx(lui.LuiButton, { ...buttonProps, type: 'button', level: 'tertiary', className: 'lui-button-icon-only', ref: ref, buttonProps: { 'aria-label': title }, title: title, onClick: onClick, disabled: disabled, children: jsxRuntime.jsx(lui.LuiIcon, { name: icon, alt: 'Menu', size: size }) }));
3053
3083
  });
3054
3084
 
3055
3085
  const GridFilterColumnsToggle = ({ saveState = true }) => {
@@ -3057,9 +3087,9 @@ const GridFilterColumnsToggle = ({ saveState = true }) => {
3057
3087
  const { getColumns, getColumnIds, invisibleColumnIds, setInvisibleColumnIds } = React.useContext(GridContext);
3058
3088
  const columnStorageKey = React.useMemo(() => lodashEs.isEmpty(getColumnIds())
3059
3089
  ? null // Grid hasn't been initialised yet
3060
- : "stepAgGrid_invisibleColumnIds_" + getColumnIds().join("_"), [getColumnIds]);
3090
+ : 'stepAgGrid_invisibleColumnIds_' + getColumnIds().join('_'), [getColumnIds]);
3061
3091
  // infer the invisible ids from colDefs
3062
- const resetColumns = React.useCallback(() => setInvisibleColumnIds(getColumnIds("initialHide")), [getColumnIds, setInvisibleColumnIds]);
3092
+ const resetColumns = React.useCallback(() => setInvisibleColumnIds(getColumnIds('initialHide')), [getColumnIds, setInvisibleColumnIds]);
3063
3093
  // Load state on start
3064
3094
  React.useEffect(() => {
3065
3095
  if (!columnStorageKey || loaded)
@@ -3071,11 +3101,11 @@ const GridFilterColumnsToggle = ({ saveState = true }) => {
3071
3101
  resetColumns();
3072
3102
  }
3073
3103
  else {
3074
- const invisibleIds = JSON.parse(stored ?? "[]");
3104
+ const invisibleIds = JSON.parse(stored ?? '[]');
3075
3105
  if (!Array.isArray(invisibleIds)) {
3076
3106
  console.error(`stored invisible ids not an array: ${stored}`);
3077
3107
  }
3078
- else if (!invisibleIds.every((id) => typeof id === "string")) {
3108
+ else if (!invisibleIds.every((id) => typeof id === 'string')) {
3079
3109
  console.error(`stored invisible ids not strings: ${stored}`);
3080
3110
  }
3081
3111
  else {
@@ -3105,15 +3135,15 @@ const GridFilterColumnsToggle = ({ saveState = true }) => {
3105
3135
  }, [invisibleColumnIds, setInvisibleColumnIds]);
3106
3136
  const numericRegExp = /^\d+$/;
3107
3137
  const isNonManageableColumn = (col) => col.lockVisible || col.colId == null || numericRegExp.test(col.colId);
3108
- return (jsxRuntime.jsxs(Menu, { menuButton: jsxRuntime.jsx(GridFilterHeaderIconButton, { icon: "ic_columns", title: "Column visibility" }), menuClassName: "step-ag-grid-react-menu", portal: true, unmountOnClose: true, children: [jsxRuntime.jsx("div", { className: "GridFilterColumnsToggle-container", children: getColumns("headerName").map((col) => (jsxRuntime.jsx(MenuItem, { disabled: isNonManageableColumn(col), onClick: (e) => {
3138
+ return (jsxRuntime.jsxs(Menu, { menuButton: jsxRuntime.jsx(GridFilterHeaderIconButton, { icon: 'ic_columns', title: 'Column visibility' }), menuClassName: 'step-ag-grid-react-menu', portal: true, unmountOnClose: true, children: [jsxRuntime.jsx("div", { className: 'GridFilterColumnsToggle-container', children: getColumns('headerName').map((col) => (jsxRuntime.jsx(MenuItem, { disabled: isNonManageableColumn(col), onClick: (e) => {
3109
3139
  // Global react-menu MenuItem handler handles tabs
3110
- if (e.key !== "Tab") {
3140
+ if (e.key !== 'Tab') {
3111
3141
  e.keepOpen = true;
3112
- if (e.key !== "Enter") {
3142
+ if (e.key !== 'Enter') {
3113
3143
  toggleColumn(col.colId);
3114
3144
  }
3115
3145
  }
3116
- }, children: jsxRuntime.jsx(lui.LuiCheckboxInput, { isChecked: !!invisibleColumnIds && !invisibleColumnIds.includes(col.colId ?? ""), value: `${col.colId}`, label: col.headerName ?? "", isDisabled: isNonManageableColumn(col), inputProps: {
3146
+ }, children: jsxRuntime.jsx(lui.LuiCheckboxInput, { isChecked: !!invisibleColumnIds && !invisibleColumnIds.includes(col.colId ?? ''), value: `${col.colId}`, label: col.headerName ?? '', isDisabled: isNonManageableColumn(col), inputProps: {
3117
3147
  onClick: (e) => {
3118
3148
  // Click is handled by MenuItem onClick so keyboard events work
3119
3149
  e.preventDefault();
@@ -3121,47 +3151,15 @@ const GridFilterColumnsToggle = ({ saveState = true }) => {
3121
3151
  },
3122
3152
  }, onChange: () => {
3123
3153
  /*Do nothing, change handled by menuItem*/
3124
- } }) }, col.colId ?? "no_col_id"))) }), jsxRuntime.jsx(MenuDivider, {}, `$$divider_reset_columns`), jsxRuntime.jsxs(MenuItem, { onClick: (e) => {
3154
+ } }) }, col.colId ?? 'no_col_id'))) }), jsxRuntime.jsx(MenuDivider, {}, `$$divider_reset_columns`), jsxRuntime.jsxs(MenuItem, { onClick: (e) => {
3125
3155
  // Global react-menu MenuItem handler handles tabs
3126
- if (e.key !== "Tab") {
3127
- e.keepOpen = e.key !== "Enter";
3156
+ if (e.key !== 'Tab') {
3157
+ e.keepOpen = e.key !== 'Enter';
3128
3158
  resetColumns();
3129
3159
  }
3130
- }, children: [jsxRuntime.jsx(lui.LuiIcon, { name: "ic_regenerate", alt: "Reset columns", size: "md", className: "MenuItem-icon" }), "Reset columns"] }, "$$reset_columns")] }));
3131
- };
3132
-
3133
- const useGridFilter = (filter) => {
3134
- const { addExternalFilter, removeExternalFilter } = React.useContext(GridContext);
3135
- React.useEffect(() => {
3136
- const thisFilter = filter;
3137
- thisFilter && addExternalFilter(thisFilter);
3138
- return () => {
3139
- thisFilter && removeExternalFilter(thisFilter);
3140
- };
3141
- }, [addExternalFilter, filter, removeExternalFilter]);
3142
- };
3143
-
3144
- const GridFilterButtons = ({ className, luiButtonProps, options, }) => {
3145
- // Select defaultSelected option, otherwise first option. If no options select none.
3146
- const [selectedOption, setSelectedOption] = React.useState(options.find((option) => option.defaultSelected) ?? options[0]);
3147
- const filter = React.useMemo(() => selectedOption?.filter, [selectedOption]);
3148
- useGridFilter(filter);
3149
- return (jsxRuntime.jsx("div", { className: clsx(className, "flex-col-center"), children: jsxRuntime.jsx(lui.LuiButtonGroup, { children: options.map((option, index) => (jsxRuntime.jsx(lui.LuiButton, { ...luiButtonProps, className: clsx(`lui-button lui-button-secondary`, selectedOption?.label === option.label && `lui-button-active`, luiButtonProps?.className), onClick: () => setSelectedOption(option), children: option.label }, `${index}`))) }) }));
3150
- };
3151
-
3152
- const GridFilterQuick = ({ quickFilterPlaceholder, defaultValue }) => {
3153
- const { setQuickFilter } = React.useContext(GridContext);
3154
- const [quickFilterValue, setQuickFilterValue] = React.useState(defaultValue ?? "");
3155
- React.useEffect(() => {
3156
- setQuickFilter(quickFilterValue);
3157
- }, [quickFilterValue, setQuickFilter]);
3158
- return (jsxRuntime.jsxs("div", { className: "GridFilterQuick-container", children: [jsxRuntime.jsx("div", { className: "GridFilterQuick-icon", children: jsxRuntime.jsx(lui.LuiIcon, { name: "ic_search", alt: "Search", size: "md" }) }), jsxRuntime.jsx("input", { "aria-label": "Search", className: "GridFilterQuick-input", type: "text", placeholder: quickFilterPlaceholder ?? "Search", value: quickFilterValue, onChange: (event) => {
3159
- setQuickFilterValue(event.target.value);
3160
- } })] }));
3160
+ }, children: [jsxRuntime.jsx(lui.LuiIcon, { name: 'ic_regenerate', alt: 'Reset columns', size: 'md', className: 'MenuItem-icon' }), "Reset columns"] }, '$$reset_columns')] }));
3161
3161
  };
3162
3162
 
3163
- const GridFilters = ({ children }) => (jsxRuntime.jsx("div", { className: "Grid-container-filters", children: children }));
3164
-
3165
3163
  /**
3166
3164
  * Cancels timeouts on scope being destroyed.
3167
3165
  *
@@ -3228,12 +3226,25 @@ const GridFilterDownloadCsvButton = (csvExportParams) => {
3228
3226
  }, 100);
3229
3227
  };
3230
3228
  return downloading ? (jsxRuntime.jsx(lui.LuiMiniSpinner, { size: 22, divProps: {
3231
- role: "status",
3232
- ["aria-label"]: "Downloading...",
3233
- style: { width: 42, display: "flex", justifyContent: "center" },
3234
- } })) : (jsxRuntime.jsx(GridFilterHeaderIconButton, { icon: "ic_csv_file", title: "Download CSV", onClick: handleDownloadClick, disabled: downloading }));
3229
+ role: 'status',
3230
+ ['aria-label']: 'Downloading...',
3231
+ style: { width: 42, display: 'flex', justifyContent: 'center' },
3232
+ } })) : (jsxRuntime.jsx(GridFilterHeaderIconButton, { icon: 'ic_csv_file', title: 'Download CSV', onClick: handleDownloadClick, disabled: downloading }));
3233
+ };
3234
+
3235
+ const GridFilterQuick = ({ quickFilterPlaceholder, defaultValue }) => {
3236
+ const { setQuickFilter } = React.useContext(GridContext);
3237
+ const [quickFilterValue, setQuickFilterValue] = React.useState(defaultValue ?? '');
3238
+ React.useEffect(() => {
3239
+ setQuickFilter(quickFilterValue);
3240
+ }, [quickFilterValue, setQuickFilter]);
3241
+ return (jsxRuntime.jsxs("div", { className: "GridFilterQuick-container", children: [jsxRuntime.jsx("div", { className: "GridFilterQuick-icon", children: jsxRuntime.jsx(lui.LuiIcon, { name: 'ic_search', alt: 'Search', size: 'md' }) }), jsxRuntime.jsx("input", { "aria-label": "Search", className: "GridFilterQuick-input", type: "text", placeholder: quickFilterPlaceholder ?? 'Search', value: quickFilterValue, onChange: (event) => {
3242
+ setQuickFilterValue(event.target.value);
3243
+ } })] }));
3235
3244
  };
3236
3245
 
3246
+ const GridFilters = ({ children }) => (jsxRuntime.jsx("div", { className: "Grid-container-filters", children: children }));
3247
+
3237
3248
  /* global setTimeout, clearTimeout */
3238
3249
 
3239
3250
  var dist = function debounce(fn) {
@@ -3309,16 +3320,17 @@ function defer() {
3309
3320
  var debounce = /*@__PURE__*/getDefaultExportFromCjs(dist);
3310
3321
 
3311
3322
  const GridSubComponentContext = React.createContext({
3312
- value: "GridSubComponentContext value no context",
3323
+ value: 'GridSubComponentContext value no context',
3313
3324
  data: {},
3314
3325
  setValue: () => {
3315
- console.error("GridSubComponentContext setValue no context");
3326
+ console.error('GridSubComponentContext setValue no context');
3316
3327
  },
3317
3328
  setValid: () => {
3318
- console.error("GridSubComponentContext setValid no context");
3329
+ console.error('GridSubComponentContext setValid no context');
3319
3330
  },
3331
+ // eslint-disable-next-line @typescript-eslint/require-await
3320
3332
  triggerSave: async () => {
3321
- console.error("GridSubComponentContext triggerSave no context");
3333
+ console.error('GridSubComponentContext triggerSave no context');
3322
3334
  },
3323
3335
  context: null,
3324
3336
  });
@@ -3354,7 +3366,7 @@ var css_248z$2 = ".FormError{display:flex}.FormError-helpText{color:#6b6966;font
3354
3366
  styleInject(css_248z$2);
3355
3367
 
3356
3368
  const FormError = (props) => {
3357
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [props.error && (jsxRuntime.jsxs("div", { className: "FormError", children: [jsxRuntime.jsx(lui.LuiIcon, { alt: "error", name: "ic_error", className: "FormError-text-icon", size: "sm", status: "error" }), jsxRuntime.jsx("span", { className: "FormError-error", children: props.error })] })), props.helpText && !props.error && jsxRuntime.jsx("span", { className: "FormError-helpText", children: props.helpText })] }));
3369
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [props.error && (jsxRuntime.jsxs("div", { className: "FormError", children: [jsxRuntime.jsx(lui.LuiIcon, { alt: "error", name: "ic_error", className: "FormError-text-icon", size: "sm", status: "error" }), jsxRuntime.jsx("span", { className: "FormError-error", children: props.error })] })), props.helpText && !props.error && jsxRuntime.jsx("span", { className: 'FormError-helpText', children: props.helpText })] }));
3358
3370
  };
3359
3371
 
3360
3372
  function escapeStringRegexp(string) {
@@ -3494,18 +3506,18 @@ const textMatch = (text, filter) => {
3494
3506
  if (text == null)
3495
3507
  return true;
3496
3508
  const superFilters = filter
3497
- .split(",")
3509
+ .split(',')
3498
3510
  .map((sf) => sf.trim())
3499
3511
  .filter((sf) => sf)
3500
3512
  .map((r) => r
3501
3513
  .split(/\s+/)
3502
- .map((f) => (f.startsWith("=") ? f.slice(1) : f + "*"))
3503
- .join(" "));
3504
- const [negativeFilters, positiveFilters] = lodashEs.partition(superFilters, (superFilters) => superFilters.startsWith("!"));
3505
- const values = text.replaceAll(",", " ").trim().split(/\s+/);
3514
+ .map((f) => (f.startsWith('=') ? f.slice(1) : f + '*'))
3515
+ .join(' '));
3516
+ const [negativeFilters, positiveFilters] = lodashEs.partition(superFilters, (superFilters) => superFilters.startsWith('!'));
3517
+ const values = text.replaceAll(',', ' ').trim().split(/\s+/);
3506
3518
  return ((lodashEs.isEmpty(positiveFilters) || // Not filtered
3507
3519
  positiveFilters.some((superFilter) => {
3508
- const subFilters = superFilter.split(/\s+/).map((s) => s.replaceAll(/([!?])/g, "\\$1"));
3520
+ const subFilters = superFilter.split(/\s+/).map((s) => s.replaceAll(/([!?])/g, '\\$1'));
3509
3521
  return subFilters.every((subFilter) => values.some((value) => isMatch(value, subFilter)));
3510
3522
  })) &&
3511
3523
  (lodashEs.isEmpty(negativeFilters) ||
@@ -3542,19 +3554,19 @@ const useGridPopoverHook = (props) => {
3542
3554
  }
3543
3555
  }, [cancelEdit, props, stopEditing, updateValue]);
3544
3556
  const popoverWrapper = React.useCallback((children) => {
3545
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: anchorRef.current && (jsxRuntime.jsxs(ControlledMenu, { state: isOpen ? "open" : "closed", portal: true, unmountOnClose: true, anchorRef: anchorRef, saveButtonRef: saveButtonRef, menuClassName: "step-ag-grid-react-menu", onClose: (event) => {
3557
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: anchorRef.current && (jsxRuntime.jsxs(ControlledMenu, { state: isOpen ? 'open' : 'closed', portal: true, unmountOnClose: true, anchorRef: anchorRef, saveButtonRef: saveButtonRef, menuClassName: 'step-ag-grid-react-menu', onClose: (event) => {
3546
3558
  // Prevent menu from closing when modals are invoked
3547
3559
  if (event.reason === CloseReason.BLUR)
3548
3560
  return;
3549
- triggerSave(event.reason).then();
3550
- }, viewScroll: "auto", dontShrinkIfDirectionIsTop: true, className: props.className, children: [saving && ( // This is the overlay that prevents editing when the editor is saving
3551
- jsxRuntime.jsx("div", { className: "ComponentLoadingWrapper-saveOverlay" })), children, jsxRuntime.jsx("button", { ref: saveButtonRef, "data-reason": "", onClick: (e) => {
3552
- let reason = e.currentTarget.getAttribute("data-reason") ?? undefined;
3561
+ void triggerSave(event.reason);
3562
+ }, viewScroll: 'auto', dontShrinkIfDirectionIsTop: true, className: props.className, children: [saving && ( // This is the overlay that prevents editing when the editor is saving
3563
+ jsxRuntime.jsx("div", { className: 'ComponentLoadingWrapper-saveOverlay' })), children, jsxRuntime.jsx("button", { ref: saveButtonRef, "data-reason": '', onClick: (e) => {
3564
+ let reason = e.currentTarget.getAttribute('data-reason') ?? undefined;
3553
3565
  if (props.dontSaveOnExternalClick && reason === CloseReason.BLUR) {
3554
3566
  reason = CloseReason.CANCEL;
3555
3567
  }
3556
- triggerSave(reason).then();
3557
- }, style: { display: "none" } })] })) }));
3568
+ void triggerSave(reason);
3569
+ }, style: { display: 'none' } })] })) }));
3558
3570
  }, [anchorRef, isOpen, props.className, props.dontSaveOnExternalClick, saving, triggerSave]);
3559
3571
  return {
3560
3572
  popoverWrapper,
@@ -3562,19 +3574,19 @@ const useGridPopoverHook = (props) => {
3562
3574
  };
3563
3575
  };
3564
3576
 
3565
- const MenuSeparatorString = "_____MENU_SEPARATOR_____";
3577
+ const MenuSeparatorString = '_____MENU_SEPARATOR_____';
3566
3578
  const MenuSeparator = Object.freeze({ value: MenuSeparatorString });
3567
- const MenuHeaderString = "_____MENU_HEADER_____";
3579
+ const MenuHeaderString = '_____MENU_HEADER_____';
3568
3580
  const MenuHeaderItem = (title) => {
3569
3581
  return { label: title, value: MenuHeaderString };
3570
3582
  };
3571
3583
  const fieldToString = (field) => {
3572
- return typeof field == "symbol" ? field.toString() : `${field}`;
3584
+ return typeof field === 'symbol' ? field.toString() : `${field}`;
3573
3585
  };
3574
3586
  const GridFormDropDown = (props) => {
3575
3587
  const { selectedRows, field, data } = useGridPopoverContext();
3576
3588
  // Save triggers during async action processing which triggers another selectItem(), this ref blocks that
3577
- const [filter, setFilter] = React.useState(props.filterDefaultValue ?? "");
3589
+ const [filter, setFilter] = React.useState(props.filterDefaultValue ?? '');
3578
3590
  const [filteredValues, setFilteredValues] = React.useState();
3579
3591
  const [options, setOptions] = React.useState(null);
3580
3592
  const subComponentIsValid = React.useRef(false);
@@ -3605,12 +3617,12 @@ const GridFormDropDown = (props) => {
3605
3617
  if (options)
3606
3618
  return;
3607
3619
  let optionsConf = props.options;
3608
- (async () => {
3609
- if (typeof optionsConf == "function") {
3620
+ void (async () => {
3621
+ if (typeof optionsConf === 'function') {
3610
3622
  optionsConf = await optionsConf(selectedRows, filter);
3611
3623
  }
3612
3624
  if (optionsConf !== undefined) {
3613
- const optionsList = optionsConf?.map((item) => item == null || typeof item == "string"
3625
+ const optionsList = optionsConf?.map((item) => item == null || typeof item === 'string'
3614
3626
  ? {
3615
3627
  value: item,
3616
3628
  label: item,
@@ -3623,16 +3635,16 @@ const GridFormDropDown = (props) => {
3623
3635
  }, [filter, options, props, selectedRows]);
3624
3636
  // Local filtering.
3625
3637
  React.useEffect(() => {
3626
- if (props.filtered == "local") {
3638
+ if (props.filtered == 'local') {
3627
3639
  if (options == null)
3628
3640
  return;
3629
3641
  setFilteredValues(options
3630
3642
  .map((option) => {
3631
- if (option.label != null && typeof option.label !== "string") {
3632
- console.error("Cannot filter non-string labels", option);
3643
+ if (option.label != null && typeof option.label !== 'string') {
3644
+ console.error('Cannot filter non-string labels', option);
3633
3645
  return undefined;
3634
3646
  }
3635
- return textMatch(option.label || "", filter) ? option : undefined;
3647
+ return textMatch(option.label || '', filter) ? option : undefined;
3636
3648
  })
3637
3649
  .filter((r) => r !== undefined));
3638
3650
  }
@@ -3643,9 +3655,9 @@ const GridFormDropDown = (props) => {
3643
3655
  const previousFilter = React.useRef(filter);
3644
3656
  // Reload filtering.
3645
3657
  React.useEffect(() => {
3646
- if (previousFilter.current != filter && props.filtered == "reload") {
3658
+ if (previousFilter.current != filter && props.filtered == 'reload') {
3647
3659
  previousFilter.current = filter;
3648
- reSearchOnFilterChange().then();
3660
+ void reSearchOnFilterChange();
3649
3661
  }
3650
3662
  }, [filter, props, reSearchOnFilterChange]);
3651
3663
  /**
@@ -3683,12 +3695,12 @@ const GridFormDropDown = (props) => {
3683
3695
  });
3684
3696
  let lastHeader = null;
3685
3697
  let showHeader = null;
3686
- return popoverWrapper(jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [props.filtered && (jsxRuntime.jsxs("div", { className: "GridFormDropDown-filter", children: [jsxRuntime.jsx(FocusableItem, { className: "filter-item", onFocus: () => {
3698
+ return popoverWrapper(jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [props.filtered && (jsxRuntime.jsxs("div", { className: 'GridFormDropDown-filter', children: [jsxRuntime.jsx(FocusableItem, { className: 'filter-item', onFocus: () => {
3687
3699
  setSelectedItem(null);
3688
3700
  setSubSelectedValue(null);
3689
3701
  subComponentIsValid.current = true;
3690
- }, children: ({ ref }) => (jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", width: "100%" }, children: [jsxRuntime.jsx("input", { className: "LuiTextInput-input", ref: ref, type: "text", placeholder: props.filterPlaceholder ?? "Filter...", "data-testid": "filteredMenu-free-text-input", defaultValue: filter, "data-allowtabtosave": true, "data-disableenterautosave": !props.onSelectFilter &&
3691
- !(filteredValues && filteredValues.length === 1 && !filteredValues[0].subComponent), onChange: (e) => setFilter(e.target.value) }), props.filterHelpText && isNotEmpty(filter) && (jsxRuntime.jsx(FormError, { error: null, helpText: props.filterHelpText }))] })) }), jsxRuntime.jsx(MenuDivider, {}, `$$divider_filter`)] })), jsxRuntime.jsx(ComponentLoadingWrapper, { loading: !options, className: "GridFormDropDown-options", children: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [options && (lodashEs.isEmpty(options) || (filteredValues && lodashEs.isEmpty(filteredValues))) && (jsxRuntime.jsx(MenuItem, { className: "GridPopoverEditDropDown-noOptions", disabled: true, children: props.noOptionsMessage ?? "No Options" }, `${fieldToString(field)}-empty`)), options?.map((item, index) => {
3702
+ }, children: ({ ref }) => (jsxRuntime.jsxs("div", { style: { display: 'flex', flexDirection: 'column', width: '100%' }, children: [jsxRuntime.jsx("input", { className: 'LuiTextInput-input', ref: ref, type: "text", placeholder: props.filterPlaceholder ?? 'Filter...', "data-testid": 'filteredMenu-free-text-input', defaultValue: filter, "data-allowtabtosave": true, "data-disableenterautosave": !props.onSelectFilter &&
3703
+ !(filteredValues && filteredValues.length === 1 && !filteredValues[0].subComponent), onChange: (e) => setFilter(e.target.value) }), props.filterHelpText && isNotEmpty(filter) && (jsxRuntime.jsx(FormError, { error: null, helpText: props.filterHelpText }))] })) }), jsxRuntime.jsx(MenuDivider, {}, `$$divider_filter`)] })), jsxRuntime.jsx(ComponentLoadingWrapper, { loading: !options, className: 'GridFormDropDown-options', children: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [options && (lodashEs.isEmpty(options) || (filteredValues && lodashEs.isEmpty(filteredValues))) && (jsxRuntime.jsx(MenuItem, { className: 'GridPopoverEditDropDown-noOptions', disabled: true, children: props.noOptionsMessage ?? 'No Options' }, `${fieldToString(field)}-empty`)), options?.map((item, index) => {
3692
3704
  showHeader = null;
3693
3705
  if (item.value === MenuSeparatorString) {
3694
3706
  return jsxRuntime.jsx(MenuDivider, {}, `$$divider_${index}`);
@@ -3703,7 +3715,7 @@ const GridFormDropDown = (props) => {
3703
3715
  lastHeader = null;
3704
3716
  }
3705
3717
  }
3706
- return ((!filteredValues || filteredValues.includes(item)) && (jsxRuntime.jsxs(React.Fragment, { children: [showHeader, jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs(MenuItem, { disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "", value: item.value, onFocus: () => {
3718
+ return ((!filteredValues || filteredValues.includes(item)) && (jsxRuntime.jsxs(React.Fragment, { children: [showHeader, jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs(MenuItem, { disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== 'boolean' ? item.disabled : '', value: item.value, onFocus: () => {
3707
3719
  if (selectedItem !== item) {
3708
3720
  setSelectedItem(item);
3709
3721
  setSubSelectedValue(null);
@@ -3714,7 +3726,7 @@ const GridFormDropDown = (props) => {
3714
3726
  }
3715
3727
  }, onClick: (e) => {
3716
3728
  e.keepOpen = !!item.subComponent;
3717
- }, children: [item.label ?? (item.value == null ? `<${item.value}>` : `${item.value}`), item.subComponent ? "..." : ""] }, `${fieldToString(field)}-${index}`), item.subComponent && selectedItem === item && (jsxRuntime.jsx(FocusableItem, { className: "LuiDeprecatedForms", children: () => (jsxRuntime.jsx(GridSubComponentContext.Provider, { value: {
3729
+ }, children: [item.label ?? (item.value == null ? `<${item.value}>` : `${item.value}`), item.subComponent ? '...' : ''] }, `${fieldToString(field)}-${index}`), item.subComponent && selectedItem === item && (jsxRuntime.jsx(FocusableItem, { className: 'LuiDeprecatedForms', children: () => (jsxRuntime.jsx(GridSubComponentContext.Provider, { value: {
3718
3730
  context: { options },
3719
3731
  data,
3720
3732
  value: subSelectedValue,
@@ -3731,7 +3743,7 @@ const GridFormDropDown = (props) => {
3731
3743
  triggerSave: async () => {
3732
3744
  // empty
3733
3745
  },
3734
- }, children: item.subComponent && (jsxRuntime.jsx("div", { className: "subComponent", children: jsxRuntime.jsx(item.subComponent, {}) })) })) }, `${item.label}_subcomponent`))] }, `menu-wrapper-${index}`)] }, `${index}`)));
3746
+ }, children: item.subComponent && (jsxRuntime.jsx("div", { className: 'subComponent', children: jsxRuntime.jsx(item.subComponent, {}) })) })) }, `${String(item.label)}_subcomponent`))] }, `menu-wrapper-${index}`)] }, `${index}`)));
3735
3747
  })] }) })] }));
3736
3748
  };
3737
3749
 
@@ -3739,45 +3751,45 @@ var css_248z$1 = ".LuiTextInput.GridLuiTextInput{margin-bottom:0}.LuiTextInput-f
3739
3751
  styleInject(css_248z$1);
3740
3752
 
3741
3753
  const TextInputFormatted = (props) => {
3742
- return (jsxRuntime.jsxs("div", { className: clsx("LuiTextInput GridLuiTextInput Grid-popoverContainer", props.error && "hasError", props.className), children: [jsxRuntime.jsxs("span", { className: "LuiTextInput-inputWrapper", children: [jsxRuntime.jsx("input", { type: "text", spellCheck: true, defaultValue: props.value, ...lodashEs.omit(props, ["error", "value", "helpText", "formatted", "className", "allowTabToSave"]), className: "LuiTextInput-input", onMouseEnter: (e) => {
3754
+ return (jsxRuntime.jsxs("div", { className: clsx('LuiTextInput GridLuiTextInput Grid-popoverContainer', props.error && 'hasError', props.className), children: [jsxRuntime.jsxs("span", { className: "LuiTextInput-inputWrapper", children: [jsxRuntime.jsx("input", { type: 'text', spellCheck: true, defaultValue: props.value, ...lodashEs.omit(props, ['error', 'value', 'helpText', 'formatted', 'className', 'allowTabToSave']), className: 'LuiTextInput-input', onMouseEnter: (e) => {
3743
3755
  e.currentTarget.focus();
3744
3756
  props.onMouseEnter && props.onMouseEnter(e);
3745
- }, "data-allowtabtosave": props.allowTabToSave }), jsxRuntime.jsx("span", { className: "LuiTextInput-formatted", children: props.formatted })] }), jsxRuntime.jsx(FormError, { error: props.error, helpText: props.helpText })] }));
3757
+ }, "data-allowtabtosave": props.allowTabToSave }), jsxRuntime.jsx("span", { className: 'LuiTextInput-formatted', children: props.formatted })] }), jsxRuntime.jsx(FormError, { error: props.error, helpText: props.helpText })] }));
3746
3758
  };
3747
3759
 
3748
3760
  const bearingValueFormatter = (value) => {
3749
- const safeValue = typeof value == "string" ? parseFloat(value) : value;
3761
+ const safeValue = typeof value === 'string' ? parseFloat(value) : value;
3750
3762
  if (safeValue == null) {
3751
- return "";
3763
+ return '';
3752
3764
  }
3753
3765
  return convertDDToDMS(safeValue, false);
3754
3766
  };
3755
3767
  const bearingCorrectionValueFormatter = (value) => {
3756
3768
  const safeValue = value;
3757
3769
  if (safeValue == null) {
3758
- return "";
3770
+ return '';
3759
3771
  }
3760
- if (typeof safeValue === "string") {
3772
+ if (typeof safeValue === 'string') {
3761
3773
  return convertDDToDMS(bearingNumberParser(safeValue), true, 4);
3762
3774
  }
3763
3775
  return convertDDToDMS(safeValue, true, 4);
3764
3776
  };
3765
3777
  const bearingNumberParser = (value) => {
3766
- if (value === "")
3778
+ if (value === '')
3767
3779
  return null;
3768
3780
  return parseFloat(value);
3769
3781
  };
3770
3782
  const validMaskForDmsBearing = /^((-)?\d+)?(\.([0-5](\d([0-5](\d(\d+)?)?)?)?)?)?$/;
3771
3783
  const bearingStringValidator = (value, customInvalid) => {
3772
3784
  value = value.trim();
3773
- if (value === "")
3785
+ if (value === '')
3774
3786
  return null;
3775
3787
  const match = value.match(validMaskForDmsBearing);
3776
3788
  if (!match)
3777
- return "Bearing must be a number in D.MMSSS format";
3789
+ return 'Bearing must be a number in D.MMSSS format';
3778
3790
  const decimalPart = match[4];
3779
3791
  if (decimalPart != null && decimalPart.length > 5) {
3780
- return "Bearing has a maximum of 5 decimal places";
3792
+ return 'Bearing has a maximum of 5 decimal places';
3781
3793
  }
3782
3794
  const bearing = parseFloat(value);
3783
3795
  return customInvalid ? customInvalid(bearing) : null;
@@ -3796,9 +3808,9 @@ const bearingStringValidator = (value, customInvalid) => {
3796
3808
  */
3797
3809
  const convertDDToDMS = (dd, showPositiveSymbol = true, trailingZeroDp = 2) => {
3798
3810
  if (dd == null)
3799
- return "";
3811
+ return '';
3800
3812
  // toFixed rounds parts up greater than 60, which has to be corrected below
3801
- const [bearingWholeString, bearingDecimalString] = dd.toFixed(5).split(".");
3813
+ const [bearingWholeString, bearingDecimalString] = dd.toFixed(5).split('.');
3802
3814
  let bearingWhole = Math.abs(parseInt(bearingWholeString));
3803
3815
  let minNumeric = parseInt(bearingDecimalString?.substring(0, 2));
3804
3816
  let secNumeric = parseInt(bearingDecimalString?.substring(2, 4));
@@ -3814,11 +3826,11 @@ const convertDDToDMS = (dd, showPositiveSymbol = true, trailingZeroDp = 2) => {
3814
3826
  if (bearingWhole >= 360) {
3815
3827
  bearingWhole -= 360;
3816
3828
  }
3817
- const minString = minNumeric.toString().padStart(2, "0");
3818
- const secString = secNumeric.toString().padStart(2, "0");
3829
+ const minString = minNumeric.toString().padStart(2, '0');
3830
+ const secString = secNumeric.toString().padStart(2, '0');
3819
3831
  const deciSecString = bearingDecimalString?.substring(4, 5);
3820
- let dmsString = `${showPositiveSymbol && dd > 0 ? "+" : ""}${dd < 0 ? "-" : ""}${bearingWhole}°`;
3821
- if (trailingZeroDp === 5 || deciSecString != "0") {
3832
+ let dmsString = `${showPositiveSymbol && dd > 0 ? '+' : ''}${dd < 0 ? '-' : ''}${bearingWhole}°`;
3833
+ if (trailingZeroDp === 5 || deciSecString != '0') {
3822
3834
  dmsString += `\xa0${minString}'\xa0${secString}.${deciSecString}"`; // "\xa0" is here for non-breaking space
3823
3835
  }
3824
3836
  else if (trailingZeroDp === 4 || secNumeric != 0) {
@@ -3831,27 +3843,27 @@ const convertDDToDMS = (dd, showPositiveSymbol = true, trailingZeroDp = 2) => {
3831
3843
  };
3832
3844
  const bearingRangeValidator = (value) => {
3833
3845
  if (value === null)
3834
- return "Bearing is required";
3846
+ return 'Bearing is required';
3835
3847
  if (value >= 360)
3836
- return "Bearing must be less than 360 degrees";
3848
+ return 'Bearing must be less than 360 degrees';
3837
3849
  if (value < 0)
3838
- return "Bearing must not be negative";
3850
+ return 'Bearing must not be negative';
3839
3851
  return null;
3840
3852
  };
3841
3853
  const bearingCorrectionRangeValidator = (value) => {
3842
3854
  if (value === null)
3843
- return "Bearing correction is required";
3855
+ return 'Bearing correction is required';
3844
3856
  if (value >= 360)
3845
- return "Bearing correction must be less than 360 degrees";
3857
+ return 'Bearing correction must be less than 360 degrees';
3846
3858
  if (value <= -180)
3847
- return "Bearing correction must be greater then -180 degrees";
3859
+ return 'Bearing correction must be greater then -180 degrees';
3848
3860
  return null;
3849
3861
  };
3850
3862
 
3851
3863
  const GridFormEditBearing = (props) => {
3852
3864
  const { field, value: initialValue } = useGridPopoverContext();
3853
3865
  // This clears out any scientific precision
3854
- const defaultValue = React.useMemo(() => (initialValue == null ? "" : parseFloat(parseFloat(initialValue).toFixed(10)).toString()), [initialValue]);
3866
+ const defaultValue = React.useMemo(() => (initialValue == null ? '' : parseFloat(parseFloat(initialValue).toFixed(10)).toString()), [initialValue]);
3855
3867
  const [value, setValue] = React.useState(defaultValue);
3856
3868
  const invalid = React.useCallback(() => bearingStringValidator(value, props.range), [props.range, value]);
3857
3869
  const save = React.useCallback(async (selectedRows) => {
@@ -3865,7 +3877,7 @@ const GridFormEditBearing = (props) => {
3865
3877
  }
3866
3878
  else {
3867
3879
  if (field == null) {
3868
- console.error("field is not defined in ColDef");
3880
+ console.error('field is not defined in ColDef');
3869
3881
  }
3870
3882
  else {
3871
3883
  selectedRows.forEach((row) => {
@@ -3880,11 +3892,11 @@ const GridFormEditBearing = (props) => {
3880
3892
  invalid,
3881
3893
  save,
3882
3894
  });
3883
- return popoverWrapper(jsxRuntime.jsx("div", { className: "GridFormEditBearing-input", children: jsxRuntime.jsx(TextInputFormatted, { value: defaultValue, onChange: (e) => {
3895
+ return popoverWrapper(jsxRuntime.jsx("div", { className: 'GridFormEditBearing-input', children: jsxRuntime.jsx(TextInputFormatted, { value: defaultValue, onChange: (e) => {
3884
3896
  setValue(e.target.value.trim());
3885
3897
  }, autoFocus: true, placeholder: props.placeHolder, formatted: bearingStringValidator(value, props.range) || !props.formatValue
3886
- ? "?"
3887
- : props.formatValue(bearingNumberParser(value)), error: bearingStringValidator(value, props.range), helpText: "Press enter or tab to save" }) }));
3898
+ ? '?'
3899
+ : props.formatValue(bearingNumberParser(value)), error: bearingStringValidator(value, props.range), helpText: 'Press enter or tab to save' }) }));
3888
3900
  };
3889
3901
 
3890
3902
  const GridFormMessage = (props) => {
@@ -3892,11 +3904,11 @@ const GridFormMessage = (props) => {
3892
3904
  const [message, setMessage] = React.useState(null);
3893
3905
  const { popoverWrapper } = useGridPopoverHook({ className: props.className });
3894
3906
  React.useEffect(() => {
3895
- (async () => {
3907
+ void (async () => {
3896
3908
  setMessage(await props.message(selectedRows));
3897
- })().then();
3909
+ })();
3898
3910
  }, [props, selectedRows]);
3899
- return popoverWrapper(jsxRuntime.jsx(ComponentLoadingWrapper, { loading: message === null, className: clsx("GridFormMessage-container", props.className), children: jsxRuntime.jsx(jsxRuntime.Fragment, { children: message }) }));
3911
+ return popoverWrapper(jsxRuntime.jsx(ComponentLoadingWrapper, { loading: message === null, className: clsx('GridFormMessage-container', props.className), children: jsxRuntime.jsx(jsxRuntime.Fragment, { children: message }) }));
3900
3912
  };
3901
3913
 
3902
3914
  const GridFormMultiSelect = (props) => {
@@ -3904,8 +3916,8 @@ const GridFormMultiSelect = (props) => {
3904
3916
  const subComponentIsValidRef = React.useRef({});
3905
3917
  const optionsInitialising = React.useRef(false);
3906
3918
  const firstInputSubComponent = React.useRef(null);
3907
- const [filter, setFilter] = React.useState("");
3908
- const [initialValues, setInitialValues] = React.useState("");
3919
+ const [filter, setFilter] = React.useState('');
3920
+ const [initialValues, setInitialValues] = React.useState('');
3909
3921
  const [options, setOptions] = React.useState();
3910
3922
  const invalid = React.useCallback(() => {
3911
3923
  if (!options)
@@ -3933,8 +3945,8 @@ const GridFormMultiSelect = (props) => {
3933
3945
  if (options || optionsInitialising.current)
3934
3946
  return;
3935
3947
  optionsInitialising.current = true;
3936
- (async () => {
3937
- const optionsList = typeof props.options === "function" ? await props.options(selectedRows) : props.options;
3948
+ void (async () => {
3949
+ const optionsList = typeof props.options === 'function' ? await props.options(selectedRows) : props.options;
3938
3950
  setInitialValues(JSON.stringify(optionsList));
3939
3951
  setOptions(optionsList);
3940
3952
  optionsInitialising.current = false;
@@ -3946,7 +3958,7 @@ const GridFormMultiSelect = (props) => {
3946
3958
  const headerGroups = React.useMemo(() => {
3947
3959
  if (!options)
3948
3960
  return undefined;
3949
- const result = lodashEs.groupBy(options.filter((o) => textMatch(o.label, filter) && o.value != null), "filter");
3961
+ const result = lodashEs.groupBy(options.filter((o) => textMatch(o.label, filter) && o.value != null), 'filter');
3950
3962
  // remove leading/trailing/duplicate dividers
3951
3963
  return lodashEs.fromPairs(lodashEs.toPairs(result).map(([key, arr]) => {
3952
3964
  let lastWasDivider = true;
@@ -3970,14 +3982,14 @@ const GridFormMultiSelect = (props) => {
3970
3982
  ];
3971
3983
  }));
3972
3984
  }, [filter, options]);
3973
- const headers = React.useMemo(() => props.headers ?? [{ header: "" }], [props.headers]);
3985
+ const headers = React.useMemo(() => props.headers ?? [{ header: '' }], [props.headers]);
3974
3986
  const { popoverWrapper, triggerSave } = useGridPopoverHook({
3975
3987
  className: props.className,
3976
3988
  invalid,
3977
3989
  save,
3978
3990
  });
3979
- return popoverWrapper(jsxRuntime.jsx(ComponentLoadingWrapper, { loading: !options, className: "GridFormMultiSelect-container", children: options && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [props.filtered && (jsxRuntime.jsx(FilterInput, { headerGroups, options, setOptions, filter, setFilter, triggerSave, filterHelpText: props.filterHelpText, onSelectFilter: props.onSelectFilter, filterPlaceholder: props.filterPlaceholder })), headerGroups &&
3980
- (lodashEs.isEmpty(headerGroups) || !lodashEs.toPairs(headerGroups).some(([_, options]) => !lodashEs.isEmpty(options))) && (jsxRuntime.jsx(MenuItem, { className: "GridMultiSelect-noOptions", disabled: true, children: props.noOptionsMessage ?? "No Options" }, "noOptions")), headerGroups && !lodashEs.isEmpty(headerGroups) && (jsxRuntime.jsx("div", { className: "GridFormMultiSelect-options", children: headers.map((header, index) => {
3991
+ return popoverWrapper(jsxRuntime.jsx(ComponentLoadingWrapper, { loading: !options, className: 'GridFormMultiSelect-container', children: options && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [props.filtered && (jsxRuntime.jsx(FilterInput, { headerGroups, options, setOptions, filter, setFilter, triggerSave, filterHelpText: props.filterHelpText, onSelectFilter: props.onSelectFilter, filterPlaceholder: props.filterPlaceholder })), headerGroups &&
3992
+ (lodashEs.isEmpty(headerGroups) || !lodashEs.toPairs(headerGroups).some(([_, options]) => !lodashEs.isEmpty(options))) && (jsxRuntime.jsx(MenuItem, { className: 'GridMultiSelect-noOptions', disabled: true, children: props.noOptionsMessage ?? 'No Options' }, 'noOptions')), headerGroups && !lodashEs.isEmpty(headerGroups) && (jsxRuntime.jsx("div", { className: 'GridFormMultiSelect-options', children: headers.map((header, index) => {
3981
3993
  const subOptions = headerGroups[`${header.filter}`];
3982
3994
  return (!lodashEs.isEmpty(subOptions) && (jsxRuntime.jsxs(React.Fragment, { children: [header.header && jsxRuntime.jsx(MenuHeader, { children: header.header }), subOptions.map((item, index) => item.value === MenuSeparatorString ? (jsxRuntime.jsx(MenuDivider, {}, `div_${index}`)) : (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(MenuRadioItem, { item: item, options: options, setOptions: setOptions, onChecked: () => {
3983
3995
  // Default to focus on first input in subComponent
@@ -4019,7 +4031,7 @@ const FilterInput = (props) => {
4019
4031
  return;
4020
4032
  const filterTrimmed = filter.trim();
4021
4033
  if (lodashEs.isEmpty(filterTrimmed)) {
4022
- triggerSave().then();
4034
+ void triggerSave();
4023
4035
  return;
4024
4036
  }
4025
4037
  const preFilterOptions = JSON.stringify(options);
@@ -4028,15 +4040,15 @@ const FilterInput = (props) => {
4028
4040
  if (preFilterOptions === JSON.stringify(options))
4029
4041
  return;
4030
4042
  setOptions([...options]);
4031
- setFilter("");
4043
+ setFilter('');
4032
4044
  }, [filter, onSelectFilter, options, setFilter, setOptions, triggerSave]);
4033
4045
  const handleKeyDown = React.useCallback((e) => {
4034
- if (e.key === "Enter") {
4046
+ if (e.key === 'Enter') {
4035
4047
  enterHasBeenPressed.current = true;
4036
4048
  }
4037
4049
  }, []);
4038
4050
  const handleKeyUp = React.useCallback((e) => {
4039
- if (e.key === "Enter") {
4051
+ if (e.key === 'Enter') {
4040
4052
  e.stopPropagation();
4041
4053
  e.preventDefault();
4042
4054
  if (e.ctrlKey)
@@ -4044,22 +4056,22 @@ const FilterInput = (props) => {
4044
4056
  else if (enterHasBeenPressed.current) {
4045
4057
  const filterTrimmed = filter.trim();
4046
4058
  if (lodashEs.isEmpty(filterTrimmed)) {
4047
- triggerSave().then();
4059
+ void triggerSave();
4048
4060
  return;
4049
4061
  }
4050
4062
  onSelectFilter && addCustomFilterValue();
4051
4063
  }
4052
4064
  lastKeyWasEnter.current = true;
4053
4065
  }
4054
- else if (e.key === "Control") {
4055
- lastKeyWasEnter.current && setFilter("");
4066
+ else if (e.key === 'Control') {
4067
+ lastKeyWasEnter.current && setFilter('');
4056
4068
  lastKeyWasEnter.current = false;
4057
4069
  }
4058
4070
  else {
4059
4071
  lastKeyWasEnter.current = false;
4060
4072
  }
4061
4073
  }, [addCustomFilterValue, filter, onSelectFilter, setFilter, toggleSelectAllVisible, triggerSave]);
4062
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(FocusableItem, { className: "filter-item", children: (_) => (jsxRuntime.jsxs("div", { style: { width: "100%" }, className: "GridFormMultiSelect-filter", children: [jsxRuntime.jsx("input", { className: "LuiTextInput-input", type: "text", placeholder: filterPlaceholder ?? "Filter...", "data-testid": "filteredMenu-free-text-input", value: filter, "data-disableenterautosave": true, "data-allowtabtosave": true, onChange: (e) => setFilter(e.target.value), onKeyDown: handleKeyDown, onKeyUp: handleKeyUp }), filterHelpText && (jsxRuntime.jsx(FormError, { error: null, helpText: typeof filterHelpText === "function" ? filterHelpText(filter.trim(), options) : filterHelpText }))] })) }, "filter"), jsxRuntime.jsx(MenuDivider, {}, `$$divider_filter`)] }));
4074
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(FocusableItem, { className: 'filter-item', children: (_) => (jsxRuntime.jsxs("div", { style: { width: '100%' }, className: 'GridFormMultiSelect-filter', children: [jsxRuntime.jsx("input", { className: 'LuiTextInput-input', type: "text", placeholder: filterPlaceholder ?? 'Filter...', "data-testid": 'filteredMenu-free-text-input', value: filter, "data-disableenterautosave": true, "data-allowtabtosave": true, onChange: (e) => setFilter(e.target.value), onKeyDown: handleKeyDown, onKeyUp: handleKeyUp }), filterHelpText && (jsxRuntime.jsx(FormError, { error: null, helpText: typeof filterHelpText === 'function' ? filterHelpText(filter.trim(), options) : filterHelpText }))] })) }, 'filter'), jsxRuntime.jsx(MenuDivider, {}, `$$divider_filter`)] }));
4063
4075
  };
4064
4076
  const MenuRadioItem = (props) => {
4065
4077
  const { item, options, setOptions } = props;
@@ -4069,12 +4081,12 @@ const MenuRadioItem = (props) => {
4069
4081
  }, [options, setOptions]);
4070
4082
  return (jsxRuntime.jsx(MenuItem, { onClick: (e) => {
4071
4083
  // Global react-menu MenuItem handler handles tabs
4072
- if (e.key !== "Tab" && e.key !== "Enter") {
4084
+ if (e.key !== 'Tab' && e.key !== 'Enter') {
4073
4085
  e.keepOpen = true;
4074
4086
  toggleValue(item);
4075
4087
  }
4076
4088
  item.checked && props.onChecked && props.onChecked();
4077
- }, children: jsxRuntime.jsx(lui.LuiCheckboxInput, { isChecked: item.checked ?? false, value: `${item.value}`, label: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [item.warning && jsxRuntime.jsx(GridIcon, { icon: "ic_warning_outline", title: item.warning }), item.label ?? (item.value == null ? `<${item.value}>` : `${item.value}`)] }), inputProps: {
4089
+ }, children: jsxRuntime.jsx(lui.LuiCheckboxInput, { isChecked: item.checked ?? false, value: `${item.value}`, label: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [item.warning && jsxRuntime.jsx(GridIcon, { icon: 'ic_warning_outline', title: item.warning }), item.label ?? (item.value == null ? `<${item.value}>` : `${item.value}`)] }), inputProps: {
4078
4090
  onClick: (e) => {
4079
4091
  // Click is handled by MenuItem onClick
4080
4092
  e.preventDefault();
@@ -4090,8 +4102,8 @@ function MenuSubComponentFr(props, ref) {
4090
4102
  const focusableRef = React.useRef(null);
4091
4103
  React.useEffect(() => {
4092
4104
  if (focusableRef.current) {
4093
- const firstInputElement = focusableRef.current.querySelectorAll("input")[0] ?? null;
4094
- if (typeof ref === "function") {
4105
+ const firstInputElement = focusableRef.current.querySelectorAll('input')[0] ?? null;
4106
+ if (typeof ref === 'function') {
4095
4107
  ref(firstInputElement);
4096
4108
  }
4097
4109
  else if (ref) {
@@ -4099,7 +4111,7 @@ function MenuSubComponentFr(props, ref) {
4099
4111
  }
4100
4112
  }
4101
4113
  }, [ref]);
4102
- return (jsxRuntime.jsx(FocusableItem, { className: "LuiDeprecatedForms", ref: focusableRef, children: () => (jsxRuntime.jsx(GridSubComponentContext.Provider, { value: {
4114
+ return (jsxRuntime.jsx(FocusableItem, { className: 'LuiDeprecatedForms', ref: focusableRef, children: () => (jsxRuntime.jsx(GridSubComponentContext.Provider, { value: {
4103
4115
  context: { options },
4104
4116
  data,
4105
4117
  value: item.subValue,
@@ -4111,7 +4123,7 @@ function MenuSubComponentFr(props, ref) {
4111
4123
  subComponentIsValid[`${item.value}`] = valid;
4112
4124
  },
4113
4125
  triggerSave,
4114
- }, children: jsxRuntime.jsx("div", { className: "subComponent", children: item.subComponent && jsxRuntime.jsx(item.subComponent, {}) }) })) }, `${item.value}_subcomponent`));
4126
+ }, children: jsxRuntime.jsx("div", { className: 'subComponent', children: item.subComponent && jsxRuntime.jsx(item.subComponent, {}) }) })) }, `${item.value}_subcomponent`));
4115
4127
  }
4116
4128
 
4117
4129
  const GridFormMultiSelectGrid = (props) => {
@@ -4156,33 +4168,33 @@ const GridFormMultiSelectGrid = (props) => {
4156
4168
  if (options || optionsInitialising.current)
4157
4169
  return;
4158
4170
  optionsInitialising.current = true;
4159
- (async () => {
4160
- const optionsList = typeof props.options === "function" ? await props.options(selectedRows) : props.options;
4161
- setInitialValues(optionsList.map((o) => ({ ...o, label: "" })));
4171
+ void (async () => {
4172
+ const optionsList = typeof props.options === 'function' ? await props.options(selectedRows) : props.options;
4173
+ setInitialValues(optionsList.map((o) => ({ ...o, label: '' })));
4162
4174
  setOptions(optionsList);
4163
4175
  optionsInitialising.current = false;
4164
4176
  })();
4165
4177
  }, [options, props, selectedRows]);
4166
4178
  const toggleValue = React.useCallback((item) => {
4167
4179
  if (options) {
4168
- item.checked = item.checked === true && item.canSelectPartial ? "partial" : !item.checked;
4180
+ item.checked = item.checked === true && item.canSelectPartial ? 'partial' : !item.checked;
4169
4181
  setOptions([...options]);
4170
4182
  }
4171
4183
  }, [options, setOptions]);
4172
- return popoverWrapper(jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx("div", { className: "Grid-popoverContainer", children: jsxRuntime.jsx("div", { style: {
4173
- display: "grid",
4174
- gridAutoFlow: "column",
4184
+ return popoverWrapper(jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx("div", { className: 'Grid-popoverContainer', children: jsxRuntime.jsx("div", { style: {
4185
+ display: 'grid',
4186
+ gridAutoFlow: 'column',
4175
4187
  gridTemplateRows: `repeat(${props.maxRowCount ?? 10}, auto)`,
4176
- maxWidth: "calc(min(100vw,500px))",
4177
- overflowX: "auto",
4188
+ maxWidth: 'calc(min(100vw,500px))',
4189
+ overflowX: 'auto',
4178
4190
  }, children: options &&
4179
4191
  options.map((o) => (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(MenuItem, { onClick: (e) => {
4180
4192
  // Global react-menu MenuItem handler handles tabs
4181
- if (e.key !== "Tab" && e.key !== "Enter") {
4193
+ if (e.key !== 'Tab' && e.key !== 'Enter') {
4182
4194
  e.keepOpen = true;
4183
4195
  toggleValue(o);
4184
4196
  }
4185
- }, children: jsxRuntime.jsx(lui.LuiCheckboxInput, { isChecked: !!o.checked, isIndeterminate: o.checked === "partial", value: `${o.value}`, label: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [o.warning && jsxRuntime.jsx(GridIcon, { icon: "ic_warning_outline", title: o.warning }, "$$icon$$"), jsxRuntime.jsx("span", { className: "GridMultiSelectGrid-Label", children: o.label ?? (o.value == null ? `<${o.value}>` : `${o.value}`) }, "$$label$$")] }), inputProps: {
4197
+ }, children: jsxRuntime.jsx(lui.LuiCheckboxInput, { isChecked: !!o.checked, isIndeterminate: o.checked === 'partial', value: `${o.value}`, label: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [o.warning && jsxRuntime.jsx(GridIcon, { icon: 'ic_warning_outline', title: o.warning }, '$$icon$$'), jsxRuntime.jsx("span", { className: 'GridMultiSelectGrid-Label', children: o.label ?? (o.value == null ? `<${o.value}>` : `${o.value}`) }, '$$label$$')] }), inputProps: {
4186
4198
  onClick: (e) => {
4187
4199
  // Click is handled by MenuItem onClick
4188
4200
  e.preventDefault();
@@ -4194,7 +4206,7 @@ const GridFormMultiSelectGrid = (props) => {
4194
4206
  };
4195
4207
 
4196
4208
  /** Menu configuration types **/
4197
- const __isMenuSeparator__ = "__isMenuSeparator__";
4209
+ const __isMenuSeparator__ = '__isMenuSeparator__';
4198
4210
  const PopoutMenuSeparator = Object.freeze({ label: __isMenuSeparator__ });
4199
4211
  /**
4200
4212
  * NOTE: If the popout menu doesn't appear on single click when also selecting row it's because
@@ -4211,7 +4223,7 @@ const GridFormPopoverMenu = (props) => {
4211
4223
  if (props.defaultAction)
4212
4224
  await props.defaultAction(params);
4213
4225
  else
4214
- console.error(`No action specified for ${params.menuOption.label} menu options`);
4226
+ console.error(`No action specified for ${String(params.menuOption.label)} menu options`);
4215
4227
  }, [props]);
4216
4228
  // Load up options list if it's async function
4217
4229
  React.useEffect(() => {
@@ -4219,8 +4231,8 @@ const GridFormPopoverMenu = (props) => {
4219
4231
  return;
4220
4232
  optionsInitialising.current = true;
4221
4233
  const optionsConf = props.options ?? [];
4222
- (async () => {
4223
- const newOptions = typeof optionsConf == "function" ? await optionsConf(selectedRows) : optionsConf;
4234
+ void (async () => {
4235
+ const newOptions = typeof optionsConf === 'function' ? await optionsConf(selectedRows) : optionsConf;
4224
4236
  setOptions(newOptions);
4225
4237
  if (!props.defaultAction) {
4226
4238
  const anyOptionsAreMissingAction = newOptions.some((option) => !option.action);
@@ -4250,7 +4262,7 @@ const GridFormPopoverMenu = (props) => {
4250
4262
  else {
4251
4263
  subComponentIsValid.current = true;
4252
4264
  setSubSelectedValue(null);
4253
- await updateValue(async () => actionClick(item), e.key === "Tab" ? (e.shiftKey ? -1 : 1) : 0);
4265
+ await updateValue(async () => actionClick(item), e.key === 'Tab' ? (e.shiftKey ? -1 : 1) : 0);
4254
4266
  }
4255
4267
  }, [actionClick, subComponentSelected, updateValue]);
4256
4268
  const save = React.useCallback(async () => {
@@ -4268,7 +4280,7 @@ const GridFormPopoverMenu = (props) => {
4268
4280
  invalid: () => subComponentSelected && !subComponentIsValid.current,
4269
4281
  save,
4270
4282
  });
4271
- return popoverWrapper(jsxRuntime.jsx(ComponentLoadingWrapper, { loading: !options, className: "GridFormPopupMenu", children: jsxRuntime.jsx(jsxRuntime.Fragment, { children: lodashEs.isEmpty(options) ? (jsxRuntime.jsx(MenuItem, { className: "GridPopoverMenu-noOptions", disabled: true, children: "No actions" }, `GridPopoverMenu-empty`)) : (options?.map((item, index) => item.label === "__isMenuSeparator__" ? (jsxRuntime.jsx(MenuDivider, {}, `$$divider_${index}`)) : (!item.hidden && (jsxRuntime.jsxs(React.Fragment, { children: [item.subMenu ? (jsxRuntime.jsx(SubMenu, { disabled: !!item.disabled, label: item.label, title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "", children: jsxRuntime.jsx(item.subMenu, {}) }, `${item.label}`)) : (jsxRuntime.jsx(MenuItem, { onClick: (e) => onMenuItemClick(e, item), disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== "boolean" ? item.disabled : "", children: item.label }, `${item.label}`)), item.subComponent && subComponentSelected === item && (jsxRuntime.jsx(FocusableItem, { className: "LuiDeprecatedForms", children: () => (jsxRuntime.jsx(GridSubComponentContext.Provider, { value: {
4283
+ return popoverWrapper(jsxRuntime.jsx(ComponentLoadingWrapper, { loading: !options, className: 'GridFormPopupMenu', children: jsxRuntime.jsx(jsxRuntime.Fragment, { children: lodashEs.isEmpty(options) ? (jsxRuntime.jsx(MenuItem, { className: 'GridPopoverMenu-noOptions', disabled: true, children: "No actions" }, `GridPopoverMenu-empty`)) : (options?.map((item, index) => item.label === '__isMenuSeparator__' ? (jsxRuntime.jsx(MenuDivider, {}, `$$divider_${index}`)) : (!item.hidden && (jsxRuntime.jsxs(React.Fragment, { children: [item.subMenu ? (jsxRuntime.jsx(SubMenu, { disabled: !!item.disabled, label: item.label, title: item.disabled && typeof item.disabled !== 'boolean' ? item.disabled : '', children: jsxRuntime.jsx(item.subMenu, {}) }, `${String(item.label)}`)) : (jsxRuntime.jsx(MenuItem, { onClick: (e) => void onMenuItemClick(e, item), disabled: !!item.disabled, title: item.disabled && typeof item.disabled !== 'boolean' ? item.disabled : '', children: item.label }, `${String(item.label)}`)), item.subComponent && subComponentSelected === item && (jsxRuntime.jsx(FocusableItem, { className: 'LuiDeprecatedForms', children: () => (jsxRuntime.jsx(GridSubComponentContext.Provider, { value: {
4272
4284
  context: {},
4273
4285
  data,
4274
4286
  value: subSelectedValue,
@@ -4279,13 +4291,13 @@ const GridFormPopoverMenu = (props) => {
4279
4291
  subComponentIsValid.current = valid;
4280
4292
  },
4281
4293
  triggerSave,
4282
- }, children: jsxRuntime.jsx("div", { className: "subComponent", children: item.subComponent && jsxRuntime.jsx(item.subComponent, {}) }) })) }, `${item.label}_subcomponent`))] }, `${item.label}`))))) }) }));
4294
+ }, children: jsxRuntime.jsx("div", { className: 'subComponent', children: item.subComponent && jsxRuntime.jsx(item.subComponent, {}) }) })) }, `${String(item.label)}_subcomponent`))] }, `${String(item.label)}`))))) }) }));
4283
4295
  };
4284
4296
 
4285
4297
  const TextAreaInput = (props) => {
4286
4298
  const reactId = React.useId();
4287
4299
  const id = props?.id ?? reactId;
4288
- return (jsxRuntime.jsxs("div", { className: clsx("LuiTextAreaInput Grid-popoverContainer", props.disabled ? "isDisabled" : "", props.error ? "hasError" : "", props.className), children: [jsxRuntime.jsxs("label", { htmlFor: id, children: [props.mandatory != null && jsxRuntime.jsx("span", { className: "LuiTextAreaInput-mandatory", children: "*" }), props.label != null && jsxRuntime.jsx("span", { className: "LuiTextAreaInput-label", children: props.label }), jsxRuntime.jsx("div", { className: "LuiTextAreaInput-wrapper", children: jsxRuntime.jsx("textarea", { rows: 5, ...lodashEs.omit(props, ["error", "value", "helpText", "formatted", "className", "allowTabToSave"]), id: id, value: props.value ?? "", spellCheck: true, onMouseEnter: (e) => {
4300
+ return (jsxRuntime.jsxs("div", { className: clsx('LuiTextAreaInput Grid-popoverContainer', props.disabled ? 'isDisabled' : '', props.error ? 'hasError' : '', props.className), children: [jsxRuntime.jsxs("label", { htmlFor: id, children: [props.mandatory != null && jsxRuntime.jsx("span", { className: "LuiTextAreaInput-mandatory", children: "*" }), props.label != null && jsxRuntime.jsx("span", { className: "LuiTextAreaInput-label", children: props.label }), jsxRuntime.jsx("div", { className: "LuiTextAreaInput-wrapper", children: jsxRuntime.jsx("textarea", { rows: 5, ...lodashEs.omit(props, ['error', 'value', 'helpText', 'formatted', 'className', 'allowTabToSave']), id: id, value: props.value ?? '', spellCheck: true, onMouseEnter: (e) => {
4289
4301
  if (document.activeElement != e.currentTarget) {
4290
4302
  e.currentTarget.focus();
4291
4303
  e.currentTarget.selectionStart = e.currentTarget.value.length;
@@ -4298,11 +4310,11 @@ const TextInputValidator = (props, value, data, context) => {
4298
4310
  if (value == null)
4299
4311
  return null;
4300
4312
  // This can happen because subcomponent is invoked without type safety
4301
- if (typeof value !== "string") {
4302
- return "Value is not a string";
4313
+ if (typeof value !== 'string') {
4314
+ return 'Value is not a string';
4303
4315
  }
4304
- if (props.required && value.trim() == "") {
4305
- return "Must not be empty";
4316
+ if (props.required && value.trim() == '') {
4317
+ return 'Must not be empty';
4306
4318
  }
4307
4319
  if (props.maxLength && value.length > props.maxLength) {
4308
4320
  return `Must be no longer than ${props.maxLength} characters`;
@@ -4312,10 +4324,10 @@ const TextInputValidator = (props, value, data, context) => {
4312
4324
  }
4313
4325
  const nf = props.numberFormat;
4314
4326
  if (nf) {
4315
- if (value != "" && !isFloat(value)) {
4327
+ if (value != '' && !isFloat(value)) {
4316
4328
  return `Must be a valid number`;
4317
4329
  }
4318
- if (value != "") {
4330
+ if (value != '') {
4319
4331
  const number = parseFloat(value);
4320
4332
  if (nf.notZero && number === 0) {
4321
4333
  return `Must not be 0`;
@@ -4332,12 +4344,12 @@ const TextInputValidator = (props, value, data, context) => {
4332
4344
  if (nf.leMax != null && number > nf.leMax) {
4333
4345
  return `Must not be greater than ${nf.leMax.toLocaleString()}`;
4334
4346
  }
4335
- if (nf.precision != null && value != "") {
4347
+ if (nf.precision != null && value != '') {
4336
4348
  if (parseFloat(number.toPrecision(nf.precision)) != number) {
4337
4349
  return `Must have no more than ${nf.precision} digits precision`;
4338
4350
  }
4339
4351
  }
4340
- if (nf.scale != null && value != "") {
4352
+ if (nf.scale != null && value != '') {
4341
4353
  if (parseFloat(number.toFixed(nf.scale)) != number) {
4342
4354
  return nf.scale == 0 ? `Must be a whole number` : `Must have no more than ${nf.scale} decimal places`;
4343
4355
  }
@@ -4352,7 +4364,7 @@ const TextInputValidator = (props, value, data, context) => {
4352
4364
 
4353
4365
  const GridFormSubComponentTextArea = (props) => {
4354
4366
  const { value, data, setValue, setValid, context } = React.useContext(GridSubComponentContext);
4355
- const helpText = props.helpText ?? "Press tab to save";
4367
+ const helpText = props.helpText ?? 'Press tab to save';
4356
4368
  // If is not initialised yet as it's just been created then set the default value
4357
4369
  React.useEffect(() => {
4358
4370
  if (value == null)
@@ -4362,12 +4374,12 @@ const GridFormSubComponentTextArea = (props) => {
4362
4374
  React.useEffect(() => {
4363
4375
  setValid(value != null && invalid() == null);
4364
4376
  }, [setValid, invalid, value]);
4365
- return (jsxRuntime.jsx("div", { className: clsx("FreeTextInput", props.className), children: jsxRuntime.jsx(TextAreaInput, { className: "free-text-input", value: value, onChange: (e) => setValue(e.target.value), error: invalid(), helpText: helpText, placeholder: props.placeholder, allowTabToSave: true }) }));
4377
+ return (jsxRuntime.jsx("div", { className: clsx('FreeTextInput', props.className), children: jsxRuntime.jsx(TextAreaInput, { className: 'free-text-input', value: value, onChange: (e) => setValue(e.target.value), error: invalid(), helpText: helpText, placeholder: props.placeholder, allowTabToSave: true }) }));
4366
4378
  };
4367
4379
 
4368
4380
  const GridFormSubComponentTextInput = (props) => {
4369
4381
  const { value, setValue, setValid, data, context } = React.useContext(GridSubComponentContext);
4370
- const helpText = props.helpText ?? "Press enter or tab to save";
4382
+ const helpText = props.helpText ?? 'Press enter or tab to save';
4371
4383
  // If is not initialised yet as it's just been created then set the default value
4372
4384
  React.useEffect(() => {
4373
4385
  if (value == null)
@@ -4377,14 +4389,14 @@ const GridFormSubComponentTextInput = (props) => {
4377
4389
  React.useEffect(() => {
4378
4390
  setValid(value != null && invalid() == null);
4379
4391
  }, [setValid, invalid, value]);
4380
- return (jsxRuntime.jsx(TextInputFormatted, { value: value, error: invalid(), onChange: (e) => setValue(e.target.value), helpText: helpText, placeholder: props.placeholder, style: { width: "100%" }, allowTabToSave: true }));
4392
+ return (jsxRuntime.jsx(TextInputFormatted, { value: value, error: invalid(), onChange: (e) => setValue(e.target.value), helpText: helpText, placeholder: props.placeholder, style: { width: '100%' }, allowTabToSave: true }));
4381
4393
  };
4382
4394
 
4383
4395
  const GridFormTextArea = (props) => {
4384
4396
  const { field, value: initialVale, data } = useGridPopoverContext();
4385
- const initValue = React.useMemo(() => (initialVale == null ? "" : `${initialVale}`), [initialVale]);
4397
+ const initValue = React.useMemo(() => (initialVale == null ? '' : `${initialVale}`), [initialVale]);
4386
4398
  const [value, setValue] = React.useState(initValue);
4387
- const helpText = props.helpText ?? "Press tab to save";
4399
+ const helpText = props.helpText ?? 'Press tab to save';
4388
4400
  const invalid = React.useCallback(() => TextInputValidator(props, value, data, {}), [props, value, data]);
4389
4401
  const save = React.useCallback(async (selectedRows) => {
4390
4402
  if (invalid())
@@ -4404,13 +4416,13 @@ const GridFormTextArea = (props) => {
4404
4416
  invalid,
4405
4417
  save,
4406
4418
  });
4407
- return popoverWrapper(jsxRuntime.jsx("div", { className: "subComponent", style: { display: "flex", flexDirection: "row", width: props.width ?? 240 }, children: jsxRuntime.jsx(TextAreaInput, { value: value, onChange: (e) => setValue(e.target.value), error: invalid(), placeholder: props.placeholder ?? "Type here", helpText: helpText }) }));
4419
+ return popoverWrapper(jsxRuntime.jsx("div", { className: 'subComponent', style: { display: 'flex', flexDirection: 'row', width: props.width ?? 240 }, children: jsxRuntime.jsx(TextAreaInput, { value: value, onChange: (e) => setValue(e.target.value), error: invalid(), placeholder: props.placeholder ?? 'Type here', helpText: helpText }) }));
4408
4420
  };
4409
4421
 
4410
4422
  const GridFormTextInput = (props) => {
4411
4423
  const { field, value: initialVale, data } = useGridPopoverContext();
4412
- const helpText = props.helpText ?? "Press enter or tab to save";
4413
- const initValue = React.useMemo(() => (initialVale == null ? "" : `${initialVale}`), [initialVale]);
4424
+ const helpText = props.helpText ?? 'Press enter or tab to save';
4425
+ const initValue = React.useMemo(() => (initialVale == null ? '' : `${initialVale}`), [initialVale]);
4414
4426
  const [value, setValue] = React.useState(initValue);
4415
4427
  const invalid = React.useCallback(() => TextInputValidator(props, value, data, {}), [data, props, value]);
4416
4428
  const save = React.useCallback(async (selectedRows) => {
@@ -4431,7 +4443,7 @@ const GridFormTextInput = (props) => {
4431
4443
  invalid,
4432
4444
  save,
4433
4445
  });
4434
- return popoverWrapper(jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "row" }, className: "FormTest subComponent", children: jsxRuntime.jsx(TextInputFormatted, { value: value, onChange: (e) => setValue(e.target.value), error: invalid(), formatted: props.units, style: { width: props.width ?? 240 }, placeholder: props.placeholder ?? "Type here", helpText: helpText }) }));
4446
+ return popoverWrapper(jsxRuntime.jsx("div", { style: { display: 'flex', flexDirection: 'row' }, className: 'FormTest subComponent', children: jsxRuntime.jsx(TextInputFormatted, { value: value, onChange: (e) => setValue(e.target.value), error: invalid(), formatted: props.units, style: { width: props.width ?? 240 }, placeholder: props.placeholder ?? 'Type here', helpText: helpText }) }));
4435
4447
  };
4436
4448
 
4437
4449
  const ButtonCellRenderer = (props) => {
@@ -4443,24 +4455,24 @@ const ButtonCellRenderer = (props) => {
4443
4455
  inputRef.current?.focus();
4444
4456
  }
4445
4457
  };
4446
- api.addEventListener("cellFocused", checkFocus);
4458
+ api.addEventListener('cellFocused', checkFocus);
4447
4459
  return () => {
4448
- api.removeEventListener("cellFocused", checkFocus);
4460
+ api.removeEventListener('cellFocused', checkFocus);
4449
4461
  };
4450
4462
  }, [api, column, node.rowIndex]);
4451
4463
  return (jsxRuntime.jsx(lui.LuiButton, { ref: inputRef, className: "lui-button-icon-only", size: "sm", level: "text", onClick: () => {
4452
4464
  const selectedRows = [data];
4453
4465
  const selectedRowIds = selectedRows.map((r) => r.id);
4454
4466
  colDef?.cellEditorParams.onClick?.({ selectedRows, selectedRowIds });
4455
- }, style: { display: colDef?.cellEditorParams?.visible?.(props) !== false ? "" : "none" }, children: jsxRuntime.jsx(lui.LuiIcon, { name: "ic_redo", alt: "revert", size: "md" }) }));
4467
+ }, style: { display: colDef?.cellEditorParams?.visible?.(props) !== false ? '' : 'none' }, children: jsxRuntime.jsx(lui.LuiIcon, { name: "ic_redo", alt: "revert", size: "md" }) }));
4456
4468
  };
4457
4469
  const GridButton = (colDef, editor) => {
4458
4470
  return GridCell({
4459
4471
  minWidth: 72,
4460
4472
  maxWidth: 72,
4461
4473
  resizable: false,
4462
- headerClass: "GridHeaderAlignCenter",
4463
- cellClass: "GridCellAlignCenter",
4474
+ headerClass: 'GridHeaderAlignCenter',
4475
+ cellClass: 'GridCellAlignCenter',
4464
4476
  cellRenderer: ButtonCellRenderer,
4465
4477
  cellEditorParams: {
4466
4478
  ...editor,
@@ -4478,15 +4490,15 @@ const BooleanCellRenderer = (props) => {
4478
4490
  inputRef.current?.focus();
4479
4491
  }
4480
4492
  };
4481
- api.addEventListener("cellFocused", checkFocus);
4493
+ api.addEventListener('cellFocused', checkFocus);
4482
4494
  return () => {
4483
- api.removeEventListener("cellFocused", checkFocus);
4495
+ api.removeEventListener('cellFocused', checkFocus);
4484
4496
  };
4485
4497
  }, [api, column, node.rowIndex]);
4486
4498
  const isDisabled = !fnOrVar(colDef?.editable, props);
4487
- return (jsxRuntime.jsx("div", { className: clsx("ag-wrapper ag-input-wrapper ag-checkbox-input-wrapper", {
4488
- "ag-checked": props.value,
4489
- "ag-disabled": isDisabled,
4499
+ return (jsxRuntime.jsx("div", { className: clsx('ag-wrapper ag-input-wrapper ag-checkbox-input-wrapper', {
4500
+ 'ag-checked': props.value,
4501
+ 'ag-disabled': isDisabled,
4490
4502
  }), children: jsxRuntime.jsx("input", { type: "checkbox", className: "ag-input-field-input ag-checkbox-input", disabled: isDisabled, ref: inputRef, checked: value, onChange: () => { }, onClick: (e) => {
4491
4503
  e.stopPropagation();
4492
4504
  // cell has to be in edit mode
@@ -4506,7 +4518,7 @@ const BooleanCellRenderer = (props) => {
4506
4518
  });
4507
4519
  const checked = !value;
4508
4520
  onValueChange(checked);
4509
- params.onClick({ selectedRows, selectedRowIds: selectedRows.map((r) => r.id), checked }).then();
4521
+ void params.onClick({ selectedRows, selectedRowIds: selectedRows.map((r) => r.id), checked });
4510
4522
  } }) }));
4511
4523
  };
4512
4524
  const GridEditBoolean = (colDef, editorProps) => {
@@ -4520,8 +4532,8 @@ const GridEditBoolean = (colDef, editorProps) => {
4520
4532
  singleClickEdit: true,
4521
4533
  resizable: false,
4522
4534
  editable: true,
4523
- cellClass: "GridCellAlignCenter",
4524
- headerClass: "GridHeaderAlignCenter",
4535
+ cellClass: 'GridCellAlignCenter',
4536
+ headerClass: 'GridHeaderAlignCenter',
4525
4537
  ...colDef,
4526
4538
  });
4527
4539
  };
@@ -4531,7 +4543,7 @@ const GridPopoutEditMultiSelect = (colDef, props) => GridCell(colDef, {
4531
4543
  ...props,
4532
4544
  editorParams: {
4533
4545
  ...props.editorParams,
4534
- className: clsx("GridMultiSelect-containerMedium", props.editorParams?.className),
4546
+ className: clsx('GridMultiSelect-containerMedium', props.editorParams?.className),
4535
4547
  },
4536
4548
  });
4537
4549
 
@@ -4540,47 +4552,19 @@ const GridPopoutEditMultiSelectGrid = (colDef, props) => GridCell(colDef, {
4540
4552
  ...props,
4541
4553
  editorParams: {
4542
4554
  ...props.editorParams,
4543
- className: clsx("GridMultiSelect-containerMedium", props.editorParams?.className),
4544
- },
4545
- });
4546
-
4547
- const GridRenderPopoutMenuCell = (props) => {
4548
- const disabled = !fnOrVar(props.colDef?.editable, props);
4549
- return (jsxRuntime.jsx(lui.LuiIcon, { name: "ic_more_vert", alt: "More actions", size: "md", className: clsx("GridPopoutMenu-burger", disabled && "GridPopoutMenu-burgerDisabled") }));
4550
- };
4551
-
4552
- /**
4553
- * Popout burger menu
4554
- */
4555
- const GridPopoverMenu = (colDef, custom) => GridCell({
4556
- minWidth: 48,
4557
- maxWidth: 48,
4558
- width: 40,
4559
- sortable: false,
4560
- editable: colDef.editable != null ? colDef.editable : true,
4561
- exportable: false,
4562
- cellStyle: { flex: 1, justifyContent: "center" },
4563
- cellRenderer: GridRenderPopoutMenuCell,
4564
- ...colDef,
4565
- cellRendererParams: {
4566
- // Menus open on single click, this parameter is picked up in Grid.tsx
4567
- singleClickEdit: true,
4555
+ className: clsx('GridMultiSelect-containerMedium', props.editorParams?.className),
4568
4556
  },
4569
- }, {
4570
- editor: GridFormPopoverMenu,
4571
- preventAutoEdit: true,
4572
- ...custom,
4573
4557
  });
4574
4558
 
4575
4559
  const GridPopoverEditBearingLike = (colDef, props) => GridCell({
4576
- valueFormatter: (params) => props.editorParams?.formatValue(params.value) ?? "",
4560
+ valueFormatter: (params) => props.editorParams?.formatValue(params.value) ?? '',
4577
4561
  ...colDef,
4578
4562
  }, {
4579
4563
  editor: GridFormEditBearing,
4580
4564
  ...props,
4581
4565
  });
4582
4566
  const GridPopoverEditBearingEditorParams = {
4583
- placeHolder: "Enter bearing",
4567
+ placeHolder: 'Enter bearing',
4584
4568
  formatValue: bearingValueFormatter,
4585
4569
  range: bearingRangeValidator,
4586
4570
  };
@@ -4592,7 +4576,7 @@ const GridPopoverEditBearing = (colDef, props) => GridPopoverEditBearingLike(col
4592
4576
  },
4593
4577
  });
4594
4578
  const GridPopoverEditBearingCorrectionEditorParams = {
4595
- placeHolder: "Enter bearing correction",
4579
+ placeHolder: 'Enter bearing correction',
4596
4580
  formatValue: bearingCorrectionValueFormatter,
4597
4581
  range: bearingCorrectionRangeValidator,
4598
4582
  };
@@ -4610,11 +4594,39 @@ const GridPopoverEditDropDown = (colDef, props) => GridCell(colDef, {
4610
4594
  editorParams: {
4611
4595
  ...props.editorParams,
4612
4596
  className: clsx({
4613
- "GridPopoverEditDropDown-containerLarge": !props.editorParams?.className?.includes("GridPopoverEditDropDown-container"),
4597
+ 'GridPopoverEditDropDown-containerLarge': !props.editorParams?.className?.includes('GridPopoverEditDropDown-container'),
4614
4598
  }, props.editorParams?.className),
4615
4599
  },
4616
4600
  });
4617
4601
 
4602
+ const GridRenderPopoutMenuCell = (props) => {
4603
+ const disabled = !fnOrVar(props.colDef?.editable, props);
4604
+ return (jsxRuntime.jsx(lui.LuiIcon, { name: 'ic_more_vert', alt: 'More actions', size: 'md', className: clsx('GridPopoutMenu-burger', disabled && 'GridPopoutMenu-burgerDisabled') }));
4605
+ };
4606
+
4607
+ /**
4608
+ * Popout burger menu
4609
+ */
4610
+ const GridPopoverMenu = (colDef, custom) => GridCell({
4611
+ minWidth: 48,
4612
+ maxWidth: 48,
4613
+ width: 40,
4614
+ sortable: false,
4615
+ editable: colDef.editable != null ? colDef.editable : true,
4616
+ exportable: false,
4617
+ cellStyle: { flex: 1, justifyContent: 'center' },
4618
+ cellRenderer: GridRenderPopoutMenuCell,
4619
+ ...colDef,
4620
+ cellRendererParams: {
4621
+ // Menus open on single click, this parameter is picked up in Grid.tsx
4622
+ singleClickEdit: true,
4623
+ },
4624
+ }, {
4625
+ editor: GridFormPopoverMenu,
4626
+ preventAutoEdit: true,
4627
+ ...custom,
4628
+ });
4629
+
4618
4630
  const GridPopoverMessage = (colDef, props) => GridCell({
4619
4631
  resizable: true,
4620
4632
  ...colDef,
@@ -4634,9 +4646,9 @@ const GridPopoverTextInput = (colDef, params) => GridCell(colDef, {
4634
4646
  ...params,
4635
4647
  });
4636
4648
 
4637
- const GridWrapper = ({ children, maxHeight }) => (jsxRuntime.jsx("div", { className: "Grid-wrapper", style: { maxHeight }, children: children }));
4649
+ const GridWrapper = ({ children, maxHeight }) => (jsxRuntime.jsx("div", { className: 'Grid-wrapper', style: { maxHeight }, children: children }));
4638
4650
 
4639
- const getColId = (colDef) => colDef.colId ?? "";
4651
+ const getColId = (colDef) => colDef.colId ?? '';
4640
4652
  const isFlexColumn = (colDef) => !!colDef.flex && !isGridCellFiller(colDef);
4641
4653
 
4642
4654
  /**
@@ -4648,7 +4660,7 @@ const GridContextProvider = (props) => {
4648
4660
  const { modifyUpdating, checkUpdating } = React.useContext(GridUpdatingContext);
4649
4661
  const [gridApi, setGridApi] = React.useState();
4650
4662
  const [gridReady, setGridReady] = React.useState(false);
4651
- const [quickFilter, _setQuickFilter] = React.useState("");
4663
+ const [quickFilter, _setQuickFilter] = React.useState('');
4652
4664
  const [invisibleColumnIds, _setInvisibleColumnIds] = React.useState();
4653
4665
  const testId = React.useRef();
4654
4666
  const idsBeforeUpdate = React.useRef([]);
@@ -4668,7 +4680,7 @@ const GridContextProvider = (props) => {
4668
4680
  * Set quick filter directly on grid, based on previously save quickFilter state.
4669
4681
  */
4670
4682
  React.useEffect(() => {
4671
- gridApi?.setGridOption("quickFilterText", quickFilter);
4683
+ gridApi?.setGridOption('quickFilterText', quickFilter);
4672
4684
  }, [gridApi, quickFilter]);
4673
4685
  /**
4674
4686
  * Wraps things that require gridApi in common handling, for when gridApi not present.
@@ -4701,9 +4713,9 @@ const GridContextProvider = (props) => {
4701
4713
  let id = 0;
4702
4714
  try {
4703
4715
  gridApi?.forEachNodeAfterFilterAndSort((rowNode) => {
4704
- id = parseInt(rowNode.id ?? "0");
4716
+ id = parseInt(rowNode.id ?? '0');
4705
4717
  // this is the only way to get out of the loop
4706
- throw "expected exception - exit_loop";
4718
+ throw 'expected exception - exit_loop';
4707
4719
  });
4708
4720
  }
4709
4721
  catch (ex) {
@@ -4717,7 +4729,7 @@ const GridContextProvider = (props) => {
4717
4729
  const setApis = React.useCallback((gridApi, dataTestId) => {
4718
4730
  testId.current = dataTestId;
4719
4731
  setGridApi(gridApi);
4720
- gridApi?.setGridOption("quickFilterText", quickFilter);
4732
+ gridApi?.setGridOption('quickFilterText', quickFilter);
4721
4733
  setGridReady(!!gridApi);
4722
4734
  }, [quickFilter]);
4723
4735
  /**
@@ -4727,9 +4739,9 @@ const GridContextProvider = (props) => {
4727
4739
  if (!gridApi)
4728
4740
  return null;
4729
4741
  if (!gridApi.getDisplayedRowCount())
4730
- return "empty";
4742
+ return 'empty';
4731
4743
  if (!lodashEs.isEmpty(gridApi.getRenderedNodes()))
4732
- return "rows-visible";
4744
+ return 'rows-visible';
4733
4745
  // If there are rows to render, but there are no rendered nodes then we should wait
4734
4746
  return null;
4735
4747
  }, [gridApi]);
@@ -4785,7 +4797,7 @@ const GridContextProvider = (props) => {
4785
4797
  * Uses beforeUpdate ids to find new nodes.
4786
4798
  */
4787
4799
  const _getNewNodes = React.useCallback(() => {
4788
- return gridApiOp((gridApi) => lodashEs.compact(lodashEs.difference(_getAllRowIds(), idsBeforeUpdate.current).map((rowId) => gridApi.getRowNode("" + rowId))), () => []);
4800
+ return gridApiOp((gridApi) => lodashEs.compact(lodashEs.difference(_getAllRowIds(), idsBeforeUpdate.current).map((rowId) => gridApi.getRowNode('' + rowId))), () => []);
4789
4801
  }, [_getAllRowIds, gridApiOp]);
4790
4802
  /**
4791
4803
  * Get grid nodes via rowIds. If rowIds has no matching node the result may be smaller than expected.
@@ -4794,7 +4806,7 @@ const GridContextProvider = (props) => {
4794
4806
  * @param rowIds Row ids to get from grid.
4795
4807
  */
4796
4808
  const _rowIdsToNodes = React.useCallback((rowIds) => {
4797
- return gridApiOp((gridApi) => lodashEs.compact(rowIds.map((rowId) => gridApi.getRowNode("" + rowId))), () => []);
4809
+ return gridApiOp((gridApi) => lodashEs.compact(rowIds.map((rowId) => gridApi.getRowNode('' + rowId))), () => []);
4798
4810
  }, [gridApiOp]);
4799
4811
  /**
4800
4812
  * Get ColDefs, with flattened ColGroupDefs
@@ -4935,7 +4947,7 @@ const GridContextProvider = (props) => {
4935
4947
  gridApi.autoSizeColumns(colsToResize.map((colState) => colState.colId), skipHeader);
4936
4948
  }
4937
4949
  return {
4938
- width: lodashEs.sumBy(gridApi.getColumnState().filter((col) => !col.hide), "width"),
4950
+ width: lodashEs.sumBy(gridApi.getColumnState().filter((col) => !col.hide), 'width'),
4939
4951
  };
4940
4952
  }, [gridApi]);
4941
4953
  /**
@@ -4952,7 +4964,9 @@ const GridContextProvider = (props) => {
4952
4964
  }
4953
4965
  gridApi.stopEditing();
4954
4966
  }, [gridApi]);
4955
- const startCellEditing = React.useCallback(async ({ rowId, colId }) => {
4967
+ const startCellEditing = React.useCallback(
4968
+ // eslint-disable-next-line @typescript-eslint/require-await
4969
+ ({ rowId, colId }) => {
4956
4970
  if (!gridApi)
4957
4971
  return;
4958
4972
  const colDef = gridApi.getColumnDef(colId);
@@ -4967,7 +4981,7 @@ const GridContextProvider = (props) => {
4967
4981
  rowNode.setSelected(true, true);
4968
4982
  }
4969
4983
  // Cell already being edited, so don't re-edit until finished
4970
- if (checkUpdating([colDef.field ?? ""], rowId)) {
4984
+ if (checkUpdating([colDef.field ?? ''], rowId)) {
4971
4985
  return;
4972
4986
  }
4973
4987
  const rowIndex = rowNode.rowIndex;
@@ -5038,11 +5052,11 @@ const GridContextProvider = (props) => {
5038
5052
  return await gridApiOp(async (gridApi) => {
5039
5053
  const selectedRows = props.selectedRows;
5040
5054
  let ok = false;
5041
- await modifyUpdating(props.field ?? "", selectedRows.map((data) => data.id), async () => {
5055
+ await modifyUpdating(props.field ?? '', selectedRows.map((data) => data.id), async () => {
5042
5056
  // Need to refresh to get spinners to work on all rows
5043
5057
  gridApi.refreshCells({ rowNodes: props.selectedRows, force: true });
5044
5058
  ok = await fnUpdate(selectedRows).catch((ex) => {
5045
- console.error("Exception during modifyUpdating", ex);
5059
+ console.error('Exception during modifyUpdating', ex);
5046
5060
  return false;
5047
5061
  });
5048
5062
  });
@@ -5079,7 +5093,7 @@ const GridContextProvider = (props) => {
5079
5093
  }
5080
5094
  catch (ex) {
5081
5095
  // Hide errors in jest, but log them in browser
5082
- if (typeof jest === "undefined")
5096
+ if (typeof jest === 'undefined')
5083
5097
  console.error(ex);
5084
5098
  }
5085
5099
  }, 50), [gridApi]);
@@ -5101,7 +5115,7 @@ const GridContextProvider = (props) => {
5101
5115
  gridApi?.forEachNodeAfterFilter((rowNode) => {
5102
5116
  arr.push(rowNode.id);
5103
5117
  });
5104
- return arr.join("|");
5118
+ return arr.join('|');
5105
5119
  };
5106
5120
  if (gridApi) {
5107
5121
  const hasFocusedCell = gridApi.getFocusedCell();
@@ -5115,11 +5129,11 @@ const GridContextProvider = (props) => {
5115
5129
  }, 200), [gridApi]);
5116
5130
  const addExternalFilter = (filter) => {
5117
5131
  externalFilters.current.push(filter);
5118
- onFilterChanged().then();
5132
+ void onFilterChanged();
5119
5133
  };
5120
5134
  const removeExternalFilter = (filter) => {
5121
5135
  lodashEs.remove(externalFilters.current, (v) => v === filter);
5122
- onFilterChanged().then();
5136
+ void onFilterChanged();
5123
5137
  };
5124
5138
  const isExternalFilterPresent = () => !lodashEs.isEmpty(externalFilters.current);
5125
5139
  const doesExternalFilterPass = (node) => externalFilters.current.every((filter) => filter(node.data, node));
@@ -5223,10 +5237,10 @@ const GridContextProvider = (props) => {
5223
5237
  const downloadCsvUseValueFormattersProcessCellCallback = (params) => {
5224
5238
  const encodeToString = (value) => {
5225
5239
  // Convert nullish values to blank
5226
- if (value === "-" || value === "" || value == null) {
5227
- return "";
5240
+ if (value === '-' || value === '' || value == null) {
5241
+ return '';
5228
5242
  }
5229
- if (typeof value === "string") {
5243
+ if (typeof value === 'string') {
5230
5244
  return value;
5231
5245
  }
5232
5246
  return JSON.stringify(value);
@@ -5240,19 +5254,19 @@ const downloadCsvUseValueFormattersProcessCellCallback = (params) => {
5240
5254
  const valueFormatter = colDef.valueFormatter;
5241
5255
  // If no valueFormatter then value _must_ be a string
5242
5256
  if (valueFormatter == null) {
5243
- if (params.value != null && typeof params.value !== "string") {
5257
+ if (params.value != null && typeof params.value !== 'string') {
5244
5258
  console.error(`downloadCsv: valueFormatter missing and getValue is not a string, colId: ${colDef.colId}`);
5245
5259
  }
5246
5260
  return encodeToString(params.value);
5247
5261
  }
5248
5262
  // We don't have access to registered functions, so we can't call them
5249
- if (typeof valueFormatter !== "function") {
5263
+ if (typeof valueFormatter !== 'function') {
5250
5264
  console.error(`downloadCsv: String type (registered) value formatters are unsupported in downloadCsv, colId: ${colDef.colId}`);
5251
5265
  return encodeToString(params.value);
5252
5266
  }
5253
5267
  const result = valueFormatter({ ...params, data: params.node?.data, colDef, node: null });
5254
5268
  // type may not be string due to casting, leave the type check in
5255
- if (params.value != null && typeof result !== "string") {
5269
+ if (params.value != null && typeof result !== 'string') {
5256
5270
  console.error(`downloadCsv: valueFormatter is returning non string values, colDef:", colId: ${colDef.colId}`);
5257
5271
  }
5258
5272
  // We add an extra encodeToString here just in case valueFormatter is returning non string values
@@ -5311,7 +5325,7 @@ const usePrevious = (value) => {
5311
5325
 
5312
5326
  // Kept this less than one second, so I don't have issues with waitFor as it defaults to 1s
5313
5327
  const minimumInProgressTimeMs = 950;
5314
- const ActionButton = ({ icon, name, inProgressName, disabled, dataTestId, style, className, title, onClick, size = "sm", iconPosition = "left", level = "tertiary", "aria-label": ariaLabel, }) => {
5328
+ const ActionButton = ({ icon, name, inProgressName, disabled, dataTestId, style, className, title, onClick, size = 'sm', iconPosition = 'left', level = 'tertiary', 'aria-label': ariaLabel, }) => {
5315
5329
  const [inProgress, setInProgress] = React.useState(false);
5316
5330
  const lastInProgress = usePrevious(inProgress ?? false);
5317
5331
  const [localInProgress, setLocalInProgress, setLocalInProgressDeferred] = useStateDeferred(inProgress);
@@ -5320,28 +5334,28 @@ const ActionButton = ({ icon, name, inProgressName, disabled, dataTestId, style,
5320
5334
  return;
5321
5335
  inProgress ? setLocalInProgress(true) : setLocalInProgressDeferred(false, minimumInProgressTimeMs);
5322
5336
  }, [inProgress, lastInProgress, setLocalInProgress, setLocalInProgressDeferred]);
5323
- const buttonText = (jsxRuntime.jsxs("span", { className: "ActionButton-minimalArea", children: [jsxRuntime.jsx("span", { className: "ActionButton-minimalAreaDisplay", children: (localInProgress ? inProgressName : name) ?? name }), jsxRuntime.jsx("span", { className: "ActionButton-minimalAreaExpand", children: name })] }));
5324
- return (jsxRuntime.jsxs(lui.LuiButton, { "data-testid": dataTestId, type: "button", level: level, title: title ?? ariaLabel ?? name, "aria-label": ariaLabel ?? name, className: clsx("lui-button-icon-right", "ActionButton", className, localInProgress && "ActionButton-inProgress", name != null && !className?.includes("ActionButton-fill") && "ActionButton-minimal", name == null && "ActionButton-iconOnly"), size: "lg", style: style, onClick: async () => {
5337
+ const buttonText = (jsxRuntime.jsxs("span", { className: 'ActionButton-minimalArea', children: [jsxRuntime.jsx("span", { className: 'ActionButton-minimalAreaDisplay', children: (localInProgress ? inProgressName : name) ?? name }), jsxRuntime.jsx("span", { className: 'ActionButton-minimalAreaExpand', children: name })] }));
5338
+ return (jsxRuntime.jsxs(lui.LuiButton, { "data-testid": dataTestId, type: 'button', level: level, title: title ?? ariaLabel ?? name, buttonProps: { 'aria-label': ariaLabel ?? name }, className: clsx('lui-button-icon-right', 'ActionButton', className, localInProgress && 'ActionButton-inProgress', name != null && !className?.includes('ActionButton-fill') && 'ActionButton-minimal', name == null && 'ActionButton-iconOnly'), size: 'lg', style: style, onClick: () => {
5325
5339
  const promise = onClick();
5326
- const isPromise = typeof promise !== "undefined";
5340
+ const isPromise = typeof promise !== 'undefined';
5327
5341
  if (isPromise) {
5328
5342
  setInProgress(true);
5329
- if (isPromise)
5330
- await promise;
5331
- setInProgress(false);
5343
+ void promise.finally(() => {
5344
+ setInProgress(false);
5345
+ });
5332
5346
  }
5333
- }, disabled: localInProgress || disabled, children: [iconPosition === "right" && buttonText, localInProgress && (jsxRuntime.jsx("div", { style: { position: "relative" }, children: jsxRuntime.jsx(lui.LuiMiniSpinner, { size: 14, divProps: {
5334
- "data-testid": "loading-spinner",
5347
+ }, disabled: localInProgress || disabled, children: [iconPosition === 'right' && buttonText, localInProgress && (jsxRuntime.jsx("div", { style: { position: 'relative' }, children: jsxRuntime.jsx(lui.LuiMiniSpinner, { size: 14, divProps: {
5348
+ 'data-testid': 'loading-spinner',
5335
5349
  style: {
5336
- position: "absolute",
5350
+ position: 'absolute',
5337
5351
  left: 4,
5338
5352
  top: -10,
5339
5353
  bottom: 10,
5340
5354
  right: -4,
5341
5355
  },
5342
- role: "status",
5343
- "aria-label": "Loading",
5344
- } }) })), jsxRuntime.jsx(lui.LuiIcon, { name: icon, alt: ariaLabel ?? name ?? "", size: size }), iconPosition === "left" && buttonText] }));
5356
+ role: 'status',
5357
+ 'aria-label': 'Loading',
5358
+ } }) })), jsxRuntime.jsx(lui.LuiIcon, { name: icon, alt: ariaLabel ?? name ?? '', size: size }), iconPosition === 'left' && buttonText] }));
5345
5359
  };
5346
5360
 
5347
5361
  const useDeferredPromise = () => {