@linzjs/step-ag-grid 29.12.0 → 29.14.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 (103) hide show
  1. package/dist/index.css +26 -2
  2. package/dist/src/components/Grid.d.ts +37 -67
  3. package/dist/src/components/GridCell.d.ts +2 -19
  4. package/dist/src/components/GridCellFiller.d.ts +1 -1
  5. package/dist/src/components/GridCellMultiEditor.d.ts +1 -2
  6. package/dist/src/components/GridPopoverHook.d.ts +1 -1
  7. package/dist/src/components/GridRangeSelectContextMenu.d.ts +10 -0
  8. package/dist/src/components/gridFilter/GridFilterButtons.d.ts +1 -1
  9. package/dist/src/components/gridFilter/useGridFilter.d.ts +1 -1
  10. package/dist/src/components/gridForm/GridFormDropDown.d.ts +2 -2
  11. package/dist/src/components/gridForm/GridFormEditBearing.d.ts +1 -1
  12. package/dist/src/components/gridForm/GridFormMessage.d.ts +1 -1
  13. package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +1 -1
  14. package/dist/src/components/gridForm/GridFormMultiSelectGrid.d.ts +1 -1
  15. package/dist/src/components/gridForm/GridFormPopoverMenu.d.ts +3 -2
  16. package/dist/src/components/gridForm/GridFormSubComponentTextArea.d.ts +1 -1
  17. package/dist/src/components/gridForm/GridFormSubComponentTextInput.d.ts +1 -1
  18. package/dist/src/components/gridForm/GridFormTextArea.d.ts +1 -1
  19. package/dist/src/components/gridForm/GridFormTextInput.d.ts +1 -1
  20. package/dist/src/components/gridHook/useGridContextMenu.d.ts +13 -8
  21. package/dist/src/components/gridHook/useGridCopy.d.ts +15 -0
  22. package/dist/src/components/gridHook/useGridCopySettings.d.ts +11 -0
  23. package/dist/src/components/gridHook/useGridRangeSelection.d.ts +25 -0
  24. package/dist/src/components/gridPopoverEdit/GridButton.d.ts +1 -2
  25. package/dist/src/components/gridPopoverEdit/GridEditBoolean.d.ts +2 -2
  26. package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.d.ts +2 -2
  27. package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelectGrid.d.ts +2 -2
  28. package/dist/src/components/gridPopoverEdit/GridPopoverEditBearing.d.ts +4 -2
  29. package/dist/src/components/gridPopoverEdit/GridPopoverEditDropDown.d.ts +2 -2
  30. package/dist/src/components/gridPopoverEdit/GridPopoverMenu.d.ts +2 -2
  31. package/dist/src/components/gridPopoverEdit/GridPopoverMessage.d.ts +2 -2
  32. package/dist/src/components/gridPopoverEdit/GridPopoverTextArea.d.ts +2 -2
  33. package/dist/src/components/gridPopoverEdit/GridPopoverTextInput.d.ts +2 -2
  34. package/dist/src/components/gridRender/GridRenderGenericCell.d.ts +1 -2
  35. package/dist/src/components/index.d.ts +1 -0
  36. package/dist/src/components/types.d.ts +27 -0
  37. package/dist/src/contexts/GridContext.d.ts +13 -12
  38. package/dist/src/contexts/GridPopoverContext.d.ts +1 -1
  39. package/dist/src/lui/timeoutHook.d.ts +0 -6
  40. package/dist/src/lui/tsUtils.d.ts +5 -0
  41. package/dist/src/utils/__tests__/random.ts +19 -0
  42. package/dist/src/utils/textValidator.d.ts +1 -1
  43. package/dist/src/utils/util.d.ts +1 -0
  44. package/dist/step-ag-grid.cjs +650 -242
  45. package/dist/step-ag-grid.cjs.map +1 -1
  46. package/dist/step-ag-grid.esm.js +651 -245
  47. package/dist/step-ag-grid.esm.js.map +1 -1
  48. package/package.json +4 -2
  49. package/src/components/Grid.tsx +312 -221
  50. package/src/components/GridCell.tsx +1 -25
  51. package/src/components/GridCellFiller.tsx +1 -1
  52. package/src/components/GridCellMultiEditor.tsx +2 -2
  53. package/src/components/GridPopoverHook.tsx +1 -1
  54. package/src/components/GridRangeSelectContextMenu.tsx +73 -0
  55. package/src/components/gridFilter/GridFilterButtons.tsx +1 -1
  56. package/src/components/gridFilter/useGridFilter.ts +1 -1
  57. package/src/components/gridForm/GridFormDropDown.tsx +2 -4
  58. package/src/components/gridForm/GridFormEditBearing.tsx +1 -1
  59. package/src/components/gridForm/GridFormMessage.tsx +1 -1
  60. package/src/components/gridForm/GridFormMultiSelect.tsx +1 -1
  61. package/src/components/gridForm/GridFormMultiSelectGrid.tsx +1 -1
  62. package/src/components/gridForm/GridFormPopoverMenu.tsx +3 -2
  63. package/src/components/gridForm/GridFormSubComponentTextArea.tsx +1 -1
  64. package/src/components/gridForm/GridFormSubComponentTextInput.tsx +1 -1
  65. package/src/components/gridForm/GridFormTextArea.tsx +1 -1
  66. package/src/components/gridForm/GridFormTextInput.tsx +1 -1
  67. package/src/components/gridHook/useGridContextMenu.tsx +23 -10
  68. package/src/components/gridHook/useGridCopy.ts +279 -0
  69. package/src/components/gridHook/useGridCopySettings.ts +28 -0
  70. package/src/components/gridHook/useGridRangeSelection.ts +235 -0
  71. package/src/components/gridPopoverEdit/GridButton.tsx +2 -2
  72. package/src/components/gridPopoverEdit/GridEditBoolean.tsx +2 -2
  73. package/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.ts +2 -2
  74. package/src/components/gridPopoverEdit/GridPopoutEditMultiSelectGrid.ts +2 -2
  75. package/src/components/gridPopoverEdit/GridPopoverEditBearing.ts +5 -2
  76. package/src/components/gridPopoverEdit/GridPopoverEditDropDown.ts +2 -2
  77. package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +2 -2
  78. package/src/components/gridPopoverEdit/GridPopoverMessage.ts +2 -2
  79. package/src/components/gridPopoverEdit/GridPopoverTextArea.ts +2 -2
  80. package/src/components/gridPopoverEdit/GridPopoverTextInput.ts +2 -2
  81. package/src/components/gridRender/GridRenderGenericCell.tsx +1 -2
  82. package/src/components/index.ts +1 -0
  83. package/src/components/types.ts +34 -0
  84. package/src/contexts/GridContext.tsx +57 -148
  85. package/src/contexts/GridContextProvider.tsx +16 -13
  86. package/src/contexts/GridPopoverContext.tsx +1 -1
  87. package/src/contexts/GridPopoverContextProvider.tsx +1 -1
  88. package/src/lui/timeoutHook.tsx +0 -19
  89. package/src/lui/tsUtils.ts +8 -0
  90. package/src/react-menu3/components/MenuButton.tsx +2 -2
  91. package/src/react-menu3/hooks/useItemState.ts +1 -1
  92. package/src/stories/grid/GridCopy.stories.tsx +175 -0
  93. package/src/stories/grid/GridPopoverEditBearing.stories.tsx +4 -4
  94. package/src/stories/grid/GridPopoverEditDropDown.stories.tsx +3 -3
  95. package/src/stories/grid/GridReadOnly.stories.tsx +4 -3
  96. package/src/stories/grid/interactions/GridKeyboardInteractions.stories.tsx +2 -2
  97. package/src/styles/ContextMenu.scss +61 -0
  98. package/src/styles/Grid.scss +26 -2
  99. package/src/utils/__tests__/random.ts +19 -0
  100. package/src/utils/bearing.ts +2 -2
  101. package/src/utils/textValidator.test.ts +1 -1
  102. package/src/utils/textValidator.ts +1 -1
  103. package/src/utils/util.ts +2 -0
@@ -419,6 +419,9 @@ function useInterval(callback, delay) {
419
419
  savedCallback.current = callback;
420
420
  }, [callback]);
421
421
  React.useEffect(() => {
422
+ if (delay === null) {
423
+ return;
424
+ }
422
425
  const id = setInterval(() => {
423
426
  savedCallback.current();
424
427
  }, delay);
@@ -428,147 +431,54 @@ function useInterval(callback, delay) {
428
431
  }, [delay]);
429
432
  }
430
433
 
434
+ const NoContext = () => {
435
+ console.error('Missing GridContextProvider');
436
+ return null;
437
+ };
431
438
  const GridContext = React.createContext({
432
439
  gridReady: false,
433
440
  gridRenderState: () => null,
434
- getColDef: () => {
435
- console.error('no context provider for getColDef');
436
- return undefined;
437
- },
438
- getColumns: () => {
439
- console.error('no context provider for getColumns');
440
- return [];
441
- },
442
- getColumnIds: () => {
443
- console.error('no context provider for getColumnIds');
444
- return [];
445
- },
441
+ getCellValue: NoContext,
442
+ getColDef: NoContext,
443
+ getColumns: NoContext,
444
+ getColumnIds: NoContext,
446
445
  invisibleColumnIds: undefined,
447
- setInvisibleColumnIds: () => {
448
- console.error('no context provider for setInvisibleColumnIds');
449
- },
450
- prePopupOps: () => {
451
- console.error('no context provider for prePopupOps');
452
- },
446
+ setInvisibleColumnIds: NoContext,
447
+ prePopupOps: NoContext,
453
448
  externallySelectedItemsAreInSync: false,
454
- setApis: () => {
455
- console.error('no context provider for setApis');
456
- },
457
- setQuickFilter: () => {
458
- console.error('no context provider for setQuickFilter');
459
- },
460
- selectRowsById: () => {
461
- console.error('no context provider for selectRows');
462
- },
463
- getSelectedRows: () => {
464
- console.error('no context provider for getSelectedRows');
465
- return [];
466
- },
467
- getFilteredSelectedRows: () => {
468
- console.error('no context provider for getFilteredSelectedRows');
469
- return [];
470
- },
471
- getSelectedRowIds: () => {
472
- console.error('no context provider for getSelectedRowIds');
473
- return [];
474
- },
475
- getFilteredSelectedRowIds: () => {
476
- console.error('no context provider for getFilteredSelectedRowIds');
477
- return [];
478
- },
479
- // eslint-disable-next-line @typescript-eslint/require-await
480
- selectRowsDiff: async () => {
481
- console.error('no context provider for selectRowsDiff');
482
- },
483
- selectRowsByIdWithFlash: () => {
484
- console.error('no context provider for selectRowsWithFlash');
485
- },
486
- // eslint-disable-next-line @typescript-eslint/require-await
487
- selectRowsWithFlashDiff: async () => {
488
- console.error('no context provider for selectRowsWithFlashDiff');
489
- },
490
- flashRows: () => {
491
- console.error('no context provider for flashRows');
492
- },
493
- // eslint-disable-next-line @typescript-eslint/require-await
494
- flashRowsDiff: async () => {
495
- console.error('no context provider for flashRows');
496
- },
497
- // eslint-disable-next-line @typescript-eslint/require-await,@typescript-eslint/no-misused-promises
498
- focusByRowById: async () => {
499
- console.error('no context provider for focusByRowById');
500
- },
501
- ensureRowVisible: () => {
502
- console.error('no context provider for ensureRowVisible');
503
- return true;
504
- },
505
- ensureSelectedRowIsVisible: () => {
506
- console.error('no context provider for ensureSelectedRowIsVisible');
507
- },
508
- getFirstRowId: () => {
509
- console.error('no context provider for getFirstRowId');
510
- return -1;
511
- },
512
- autoSizeColumns: async () => {
513
- console.error('no context provider for autoSizeColumns');
514
- return Promise.resolve(null);
515
- },
516
- sizeColumnsToFit: () => {
517
- console.error('no context provider for autoSizeAllColumns');
518
- return null;
519
- },
520
- editingCells: () => {
521
- console.error('no context provider for editingCells');
522
- return false;
523
- },
524
- // eslint-disable-next-line @typescript-eslint/require-await
525
- startCellEditing: async () => {
526
- console.error('no context provider for startCellEditing');
527
- },
528
- resetFocusedCellAfterCellEditing: () => {
529
- console.error('no context provider for resetFocusedCellAfterCellEditing');
530
- },
531
- // eslint-disable-next-line @typescript-eslint/require-await
532
- updatingCells: async () => {
533
- console.error('no context provider for modifyUpdating');
534
- return false;
535
- },
536
- redrawRows: () => {
537
- console.error('no context provider for redrawRows');
538
- },
539
- setExternallySelectedItemsAreInSync: () => {
540
- console.error('no context provider for setExternallySelectedItemsAreInSync');
541
- },
542
- // eslint-disable-next-line @typescript-eslint/require-await
543
- waitForExternallySelectedItemsToBeInSync: async () => {
544
- console.error('no context provider for waitForExternallySelectedItemsToBeInSync');
545
- },
546
- addExternalFilter: () => {
547
- console.error('no context provider for addExternalFilter');
548
- },
549
- removeExternalFilter: () => {
550
- console.error('no context provider for removeExternalFilter');
551
- },
552
- isExternalFilterPresent: () => {
553
- console.error('no context provider for isExternalFilterPresent');
554
- return false;
555
- },
556
- doesExternalFilterPass: () => {
557
- console.error('no context provider for doesExternalFilterPass');
558
- return true;
559
- },
560
- downloadCsv: () => {
561
- console.error('no context provider for downloadCsv');
562
- },
563
- onBulkEditingComplete: () => {
564
- console.error('no context provider for onBulkEditingComplete');
565
- },
566
- setOnBulkEditingComplete: () => {
567
- console.error('no context provider for setOnBulkEditingComplete');
568
- },
569
- showNoRowsOverlay: () => {
570
- console.error('no context provider for showLoadingOverlay');
571
- },
449
+ setApis: NoContext,
450
+ setQuickFilter: NoContext,
451
+ selectRowsById: NoContext,
452
+ getSelectedRows: NoContext,
453
+ getFilteredSelectedRows: NoContext,
454
+ getSelectedRowIds: NoContext,
455
+ getFilteredSelectedRowIds: NoContext,
456
+ selectRowsDiff: NoContext,
457
+ selectRowsByIdWithFlash: NoContext,
458
+ selectRowsWithFlashDiff: NoContext,
459
+ flashRows: NoContext,
460
+ flashRowsDiff: NoContext,
461
+ focusByRowById: NoContext,
462
+ ensureRowVisible: NoContext,
463
+ ensureSelectedRowIsVisible: NoContext,
464
+ getFirstRowId: NoContext,
465
+ autoSizeColumns: NoContext,
466
+ sizeColumnsToFit: NoContext,
467
+ editingCells: NoContext,
468
+ startCellEditing: NoContext,
469
+ resetFocusedCellAfterCellEditing: NoContext,
470
+ updatingCells: NoContext,
471
+ redrawRows: NoContext,
472
+ setExternallySelectedItemsAreInSync: NoContext,
473
+ waitForExternallySelectedItemsToBeInSync: NoContext,
474
+ addExternalFilter: NoContext,
475
+ removeExternalFilter: NoContext,
476
+ isExternalFilterPresent: NoContext,
477
+ doesExternalFilterPass: NoContext,
478
+ downloadCsv: NoContext,
479
+ onBulkEditingComplete: NoContext,
480
+ setOnBulkEditingComplete: NoContext,
481
+ showNoRowsOverlay: NoContext,
572
482
  });
573
483
  const useGridContext = () => React.useContext(GridContext);
574
484
 
@@ -850,6 +760,36 @@ const GridHeaderSelect = ({ api }) => {
850
760
  } }) }));
851
761
  };
852
762
 
763
+ function styleInject(css, ref) {
764
+ if ( ref === void 0 ) ref = {};
765
+ var insertAt = ref.insertAt;
766
+
767
+ if (!css || typeof document === 'undefined') { return; }
768
+
769
+ var head = document.head || document.getElementsByTagName('head')[0];
770
+ var style = document.createElement('style');
771
+ style.type = 'text/css';
772
+
773
+ if (insertAt === 'top') {
774
+ if (head.firstChild) {
775
+ head.insertBefore(style, head.firstChild);
776
+ } else {
777
+ head.appendChild(style);
778
+ }
779
+ } else {
780
+ head.appendChild(style);
781
+ }
782
+
783
+ if (style.styleSheet) {
784
+ style.styleSheet.cssText = css;
785
+ } else {
786
+ style.appendChild(document.createTextNode(css));
787
+ }
788
+ }
789
+
790
+ var css_248z$4 = ".GridContextMenu li.szh-menu__header{color:#6b6966;font-size:14px;font-weight:600;padding-left:16px;padding-right:16px;text-transform:none}.GridContextMenu li.szh-menu__item{padding-left:16px;padding-right:16px}.GridContextMenu li.szh-menu__item .copyMenuMenuItem{align-items:center;display:flex;gap:8px}.GridContextMenu li.szh-menu__item .copyMenuMenuItem__text{color:#2a292c;font-size:16px;font-weight:400;width:80px}.GridContextMenu li.szh-menu__item .copyMenuMenuItem__buttonDefault{background:none;border:2px solid #0000;display:flex;padding:6px}.GridContextMenu li.szh-menu__item .copyMenuMenuItem__buttonDefault.copyMenuMenuItem__buttonDefault--hidden:hover{border:2px solid #2a292c}.GridContextMenu li.szh-menu__item .copyMenuMenuItem__buttonDefault--hidden .LuiIcon{fill:#0000}.GridContextMenu li.szh-menu__item .LuiIcon,.GridContextMenu li.szh-menu__item .copyMenuMenuItem__buttonDefault--hidden:hover .LuiIcon{fill:#6b6966}.GridContextMenu li.szh-menu__item .LuiIcon[data-icon=ic_tick]{padding-left:4px;padding-right:4px}.GridContextMenu li.szh-menu__item--hover{background-color:#e2f3f7}";
791
+ styleInject(css_248z$4);
792
+
853
793
  const EventHandlersContext = React.createContext({
854
794
  handleClick: () => { },
855
795
  });
@@ -2684,7 +2624,7 @@ const SubMenuFr = ({ 'aria-label': ariaLabel, className, disabled, direction, la
2684
2624
  };
2685
2625
  const SubMenu = withHovering('SubMenu', SubMenuFr);
2686
2626
 
2687
- const useGridContextMenu = ({ contextMenuSelectRow, contextMenu: ContextMenu, }) => {
2627
+ const useGridContextMenu = ({ contextMenuSelectRow, contextMenu: ContextMenu, context, }) => {
2688
2628
  const { redrawRows, prePopupOps, resetFocusedCellAfterCellEditing, getSelectedRows } = React.useContext(GridContext);
2689
2629
  const [isOpen, setOpen] = React.useState(false);
2690
2630
  const [anchorPoint, setAnchorPoint] = React.useState({ x: 0, y: 0 });
@@ -2692,6 +2632,7 @@ const useGridContextMenu = ({ contextMenuSelectRow, contextMenu: ContextMenu, })
2692
2632
  const clickedColDefRef = React.useRef(null);
2693
2633
  const selectedRowsRef = React.useRef([]);
2694
2634
  const clickedRowRef = React.useRef(null);
2635
+ const eventRef = React.useRef(undefined);
2695
2636
  const openMenu = React.useCallback((e) => {
2696
2637
  if (!e)
2697
2638
  return;
@@ -2711,16 +2652,424 @@ const useGridContextMenu = ({ contextMenuSelectRow, contextMenu: ContextMenu, })
2711
2652
  clickedColDefRef.current = event.colDef;
2712
2653
  selectedRowsRef.current = getSelectedRows();
2713
2654
  clickedRowRef.current = event.data;
2655
+ eventRef.current = event;
2714
2656
  // This is actually a pointer event
2715
2657
  openMenu(event.event);
2716
2658
  }, [contextMenuSelectRow, getSelectedRows, openMenu]);
2717
2659
  return {
2718
2660
  openMenu,
2719
2661
  cellContextMenu,
2720
- 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,
2662
+ contextMenuComponent: ContextMenu ? (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(ControlledMenu, { className: 'GridContextMenu', anchorPoint: anchorPoint, state: isOpen ? 'open' : 'closed', direction: "right", onClose: closeMenu, children: isOpen && (jsxRuntime.jsx(ContextMenu, { selectedRows: selectedRowsRef.current, clickedRow: clickedRowRef.current, colDef: clickedColDefRef.current, event: eventRef.current, close: closeMenu, context: context })) }) })) : null,
2663
+ };
2664
+ };
2665
+
2666
+ const typedEntries = (obj) => Object.entries(obj);
2667
+
2668
+ const gridCopyOptions = {
2669
+ html: { text: 'Text\xa0/\xa0HTML', icon: 'ic_product_list' },
2670
+ csv: { text: 'CSV', icon: 'ic_csv_file' },
2671
+ json: { text: 'Json', icon: 'ic_file_attached_outline', developer: true },
2672
+ };
2673
+ const CopyOptionsStorageKey = 'stepAgGrid_defaultCopy';
2674
+ const useGridCopySettings = () => {
2675
+ const [copyType, _setCopyType] = React.useState(() => {
2676
+ const defaultCopy = window.localStorage.getItem(CopyOptionsStorageKey) ?? '';
2677
+ return Object.keys(gridCopyOptions).includes(defaultCopy) ? defaultCopy : 'html';
2678
+ });
2679
+ const setCopyType = React.useCallback((key) => {
2680
+ window.localStorage.setItem(CopyOptionsStorageKey, key);
2681
+ _setCopyType(key);
2682
+ }, []);
2683
+ return {
2684
+ copyType,
2685
+ setCopyType,
2721
2686
  };
2722
2687
  };
2723
2688
 
2689
+ const GridRangeSelectContextMenu = ({ event, context, }) => {
2690
+ const developerContextMenu = !!event?.event?.ctrlKey && !!event?.event?.shiftKey;
2691
+ const onCopy = React.useMemo(() => context?.onCopy, [context?.onCopy]);
2692
+ const onClick = React.useCallback((type) => {
2693
+ onCopy?.(type);
2694
+ }, [onCopy]);
2695
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MenuHeader, { children: "Copy as" }), typedEntries(gridCopyOptions).map(([key, { icon, text, developer }]) => {
2696
+ return ((!developer || developerContextMenu) && (jsxRuntime.jsx(MenuItem, { onClick: () => void onClick(key), children: jsxRuntime.jsxs("div", { className: 'copyMenuMenuItem', children: [jsxRuntime.jsx(lui.LuiIcon, { name: icon, alt: text, size: 'md' }), jsxRuntime.jsx("div", { className: 'copyMenuMenuItem__text', children: text })] }) }, key)));
2697
+ }), jsxRuntime.jsx(MenuDivider, {}), jsxRuntime.jsx(MenuHeader, { children: "Set copy default" }), typedEntries(gridCopyOptions).map(([key, { text, developer }]) => {
2698
+ return (!developer && (jsxRuntime.jsx(MenuItem, { onClick: (e) => {
2699
+ context?.setCopyType(key);
2700
+ e.keepOpen = true;
2701
+ }, children: jsxRuntime.jsxs("div", { className: clsx('copyMenuMenuItem', context?.copyType === key ? '' : 'copyMenuMenuItem__buttonDefault--hidden'), children: [jsxRuntime.jsx(lui.LuiIcon, { name: 'ic_tick', alt: 'CSV', size: 'sm' }), jsxRuntime.jsx("div", { className: 'copyMenuMenuItem__text', children: text })] }) }, 'default_' + key)));
2702
+ })] }));
2703
+ };
2704
+
2705
+ const agGridSelectRowColId = 'ag-Grid-SelectionColumn';
2706
+
2707
+ const useGridCopy = ({ ranges, rangeStartRef, rangeEndRef, hasSelectedMoreThanOneCellRef, cellContextMenu, }) => {
2708
+ const showToast = lui.useShowLUIMessage();
2709
+ const { getSelectedRowIds } = useGridContext();
2710
+ const { getColDef, getCellValue } = useGridContext();
2711
+ const { copyType, setCopyType } = useGridCopySettings();
2712
+ const onCopy = React.useCallback((type = copyType) => {
2713
+ const rangeStart = rangeStartRef.current;
2714
+ const rangeEnd = rangeEndRef.current;
2715
+ if (rangeStart === null || rangeEnd === null || !hasSelectedMoreThanOneCellRef.current) {
2716
+ return;
2717
+ }
2718
+ if (rangeStart.rowId === rangeEnd.rowId && rangeStart.colId === rangeEnd.colId) {
2719
+ type = 'html';
2720
+ }
2721
+ const json = type === 'json';
2722
+ const { selectedColIds, selectedNodes } = ranges();
2723
+ const filteredSelectedColIds = selectedColIds.filter((colId) => colId === agGridSelectRowColId ||
2724
+ (colId !== 'gridCellFiller' && getColDef(colId)?.headerComponentParams?.exportable !== false));
2725
+ const selectedRowIds = getSelectedRowIds();
2726
+ const formatters = lodashEs.compact(filteredSelectedColIds.map((colKey) => {
2727
+ return (rowNode) => {
2728
+ if (colKey === agGridSelectRowColId) {
2729
+ return selectedRowIds.includes(rowNode.data.id);
2730
+ }
2731
+ else {
2732
+ const v = getCellValue({ rowNode, colKey });
2733
+ if (json && v !== undefined) {
2734
+ return v;
2735
+ }
2736
+ const f = getCellValue({ rowNode, colKey, useFormatter: true });
2737
+ // If it's a number, and it matches value return the original type
2738
+ return v == f ? v : f;
2739
+ }
2740
+ };
2741
+ }));
2742
+ // Get and apply headers
2743
+ const headers = filteredSelectedColIds.map((colId) => {
2744
+ if (colId === agGridSelectRowColId)
2745
+ return type === 'json' ? 'selected' : 'Selected';
2746
+ if (json) {
2747
+ return colId;
2748
+ }
2749
+ return getColDef(colId)?.headerName ?? '?';
2750
+ });
2751
+ const maxCellLength = {};
2752
+ headers.forEach((headerName, i) => {
2753
+ const colId = filteredSelectedColIds[i];
2754
+ maxCellLength[colId] = headerName.length;
2755
+ });
2756
+ const rows = [];
2757
+ if (type === 'csv' || type === 'html') {
2758
+ rows.push(headers);
2759
+ }
2760
+ selectedNodes.forEach((node) => {
2761
+ const row = [];
2762
+ rows.push(row);
2763
+ formatters.forEach((formatter, i) => {
2764
+ const colId = filteredSelectedColIds[i];
2765
+ let value = formatter(node);
2766
+ if (typeof value === 'string') {
2767
+ value = value.replaceAll('\xa0', ' ');
2768
+ }
2769
+ if (!json) {
2770
+ if (value === '-' || value === '–' || value == null) {
2771
+ value = '';
2772
+ }
2773
+ value = String(value);
2774
+ if (value === '-' || value === '–') {
2775
+ value = '';
2776
+ }
2777
+ maxCellLength[colId] = Math.max(maxCellLength[colId], value.length);
2778
+ }
2779
+ switch (type) {
2780
+ case 'json':
2781
+ value =
2782
+ value === 'undefined' || (value !== null && typeof value === 'object') || typeof value === 'string'
2783
+ ? JSON.stringify(value)
2784
+ : value;
2785
+ break;
2786
+ case 'markdown':
2787
+ value = encodeMarkdownValue(value);
2788
+ break;
2789
+ case 'csv':
2790
+ value = encodeCSVValue(value);
2791
+ break;
2792
+ }
2793
+ row.push(String(value));
2794
+ });
2795
+ });
2796
+ let result = '';
2797
+ let html = `<table style="
2798
+ font-family: 'Open Sans', system-ui, sans-serif;
2799
+ font-size: 10px;
2800
+ line-height: 10px;
2801
+ border: 1px solid #d1d9e0;
2802
+ border-collapse: collapse;
2803
+ ">`;
2804
+ if (json) {
2805
+ result += '[\n';
2806
+ }
2807
+ rows.forEach((row, rowIndex) => {
2808
+ if (json) {
2809
+ result += ' { ';
2810
+ }
2811
+ if (rowIndex == 1) {
2812
+ html += '<tbody style="font-weight: 400;">';
2813
+ }
2814
+ if (rowIndex == 0) {
2815
+ html += '<thead style="font-weight: 600;">';
2816
+ }
2817
+ if (rowIndex === 0 || (rowIndex & 1) === 1) {
2818
+ html += '<tr>';
2819
+ }
2820
+ else {
2821
+ html += '<tr style="background-color: #f6f8fa;">';
2822
+ }
2823
+ if (rowIndex === 1 && type === 'html') {
2824
+ Object.values(maxCellLength).forEach((maxLength) => {
2825
+ result += '|' + '-'.repeat(maxLength + 2);
2826
+ });
2827
+ result += '|\n';
2828
+ }
2829
+ row.forEach((cell, i) => {
2830
+ switch (type) {
2831
+ case 'csv':
2832
+ if (i !== 0) {
2833
+ result += ', ';
2834
+ }
2835
+ result += cell;
2836
+ break;
2837
+ case 'html':
2838
+ if (i === 0) {
2839
+ result += '|';
2840
+ }
2841
+ const colId = filteredSelectedColIds[i];
2842
+ result += ' ' + cell.padEnd(maxCellLength[colId], ' ') + ' ';
2843
+ result += '|';
2844
+ html +=
2845
+ rowIndex === 0
2846
+ ? '<th style="border: 1px solid #d1d9e0; padding:6px 13px; text-align: left;">'
2847
+ : '<td style="border: 1px solid #d1d9e0; padding:6px 13px;">';
2848
+ html += cell;
2849
+ html += rowIndex === 0 ? '</th>' : '</td>';
2850
+ break;
2851
+ case 'json':
2852
+ if (i !== 0) {
2853
+ result += ', ';
2854
+ }
2855
+ result += JSON.stringify(headers[i]) + ': ' + cell;
2856
+ break;
2857
+ }
2858
+ });
2859
+ html += '</tr>';
2860
+ if (rowIndex == 0) {
2861
+ html += '</thead>';
2862
+ }
2863
+ if (rowIndex == rows.length - 1) {
2864
+ html += '</tbody>';
2865
+ }
2866
+ if (json) {
2867
+ result += ' }';
2868
+ }
2869
+ result += '\n';
2870
+ });
2871
+ if (json) {
2872
+ result += ']\n';
2873
+ }
2874
+ html += '</table>';
2875
+ showToast({
2876
+ message: `${gridCopyOptions[type].text} copied`,
2877
+ messageType: 'toast',
2878
+ messageLevel: 'info',
2879
+ });
2880
+ if (type === 'html') {
2881
+ const clipboardItem = new ClipboardItem({
2882
+ 'text/html': new Blob([html], { type: 'text/html' }),
2883
+ 'text/plain': new Blob([result], { type: 'text/plain' }), // fallback
2884
+ });
2885
+ void navigator.clipboard.write([clipboardItem]).catch((err) => console.error('Failed to copy: ', err));
2886
+ }
2887
+ else {
2888
+ void navigator.clipboard.writeText(result).catch((err) => console.error('Failed to copy: ', err));
2889
+ }
2890
+ }, [getCellValue, ranges, copyType]);
2891
+ const onCopyEvent = React.useCallback((e) => {
2892
+ const rangeStart = rangeStartRef.current;
2893
+ const rangeEnd = rangeEndRef.current;
2894
+ if (rangeStart === null ||
2895
+ rangeEnd === null ||
2896
+ (rangeStart.colId === rangeEnd.colId &&
2897
+ rangeStart.rowId === rangeEnd.rowId &&
2898
+ !hasSelectedMoreThanOneCellRef.current)) {
2899
+ return;
2900
+ }
2901
+ e.preventDefault();
2902
+ onCopy();
2903
+ }, [onCopy]);
2904
+ const { cellContextMenu: rangeSelectContextMenu, contextMenuComponent: rangeSelectContextMenuComponent } = useGridContextMenu({
2905
+ contextMenu: (GridRangeSelectContextMenu),
2906
+ context: { onCopy, copyType, setCopyType },
2907
+ });
2908
+ const rangeSelectInterceptContextMenu = React.useCallback((event) => rangeStartRef.current == null ? cellContextMenu(event) : rangeSelectContextMenu(event), [cellContextMenu, rangeSelectContextMenu]);
2909
+ return {
2910
+ onCopyEvent,
2911
+ rangeSelectInterceptContextMenu,
2912
+ rangeSelectContextMenuComponent,
2913
+ };
2914
+ };
2915
+ const encodeMarkdownValue = (value) => {
2916
+ return value.replaceAll('|', '\\|');
2917
+ };
2918
+ const encodeCSVValue = (value) => {
2919
+ let str = String(value);
2920
+ // Check if it needs quoting
2921
+ if (/[",\n]/.test(str)) {
2922
+ // Escape double quotes by doubling them
2923
+ str = '"' + str.replace(/"/g, '""') + '"';
2924
+ }
2925
+ return str;
2926
+ };
2927
+
2928
+ const useGridRangeSelection = ({ enableRangeSelection, gridDivRef, rangeStartRef, rangeEndRef, hasSelectedMoreThanOneCellRef, rangeSortedNodesRef, }) => {
2929
+ const [refreshIntervalEnabled, setRefreshIntervalEnabled] = React.useState(false);
2930
+ const ranges = React.useCallback(() => {
2931
+ const gridElement = gridDivRef.current;
2932
+ const rangeStart = rangeStartRef.current;
2933
+ const rangeEnd = rangeEndRef.current;
2934
+ const rangeSortedNodes = rangeSortedNodesRef.current;
2935
+ if (!gridElement || !rangeStart || !rangeEnd || !rangeSortedNodes) {
2936
+ return {
2937
+ selectedColIds: [],
2938
+ selectedNodes: [],
2939
+ };
2940
+ }
2941
+ const elStyleLeftComparator = (el1, el2) => elStyleLeft(el1) - elStyleLeft(el2);
2942
+ const elStyleLeft = (el) => parseFloat(el.style.left) ?? 0;
2943
+ const getSortedColIds = () => {
2944
+ //
2945
+ const leftHeaders = [...gridElement.querySelectorAll('.ag-pinned-left-header .ag-header-cell')].sort(elStyleLeftComparator);
2946
+ const centerHeaders = [...gridElement.querySelectorAll('.ag-header-viewport .ag-header-cell')].sort(elStyleLeftComparator);
2947
+ const rightHeaders = [...gridElement.querySelectorAll('.ag-pinned-right-header .ag-header-cell')].sort(elStyleLeftComparator);
2948
+ return [...leftHeaders, ...centerHeaders, ...rightHeaders].map((el, i) => el.getAttribute('col-id') ?? String(i));
2949
+ };
2950
+ const sortedColIds = getSortedColIds();
2951
+ const startColIndex = sortedColIds.indexOf(rangeStart.colId);
2952
+ const endColIndex = sortedColIds.indexOf(rangeEnd.colId);
2953
+ const selectedColIds = sortedColIds.slice(Math.min(startColIndex, endColIndex), Math.max(startColIndex, endColIndex) + 1);
2954
+ const startRowIndex = rangeSortedNodes.findIndex((node) => node.data.id === rangeStart.rowId);
2955
+ const endRowIndex = rangeSortedNodes.findIndex((node) => node.data.id === rangeEnd.rowId);
2956
+ const selectedNodes = rangeSortedNodes.slice(Math.min(startRowIndex, endRowIndex), Math.max(startRowIndex, endRowIndex) + 1);
2957
+ return { selectedColIds, selectedNodes };
2958
+ }, []);
2959
+ const redrawSelectedRanges = React.useCallback(() => {
2960
+ const gridElement = gridDivRef.current;
2961
+ const { selectedColIds, selectedNodes } = ranges();
2962
+ selectedColIds.forEach((colId, colIndex) => {
2963
+ selectedNodes.forEach((node, rowIndex) => {
2964
+ const rowId = node.data.id;
2965
+ const cell = gridElement.querySelector(`.ag-row[row-id=${JSON.stringify(String(rowId))}] .ag-cell[col-id=${JSON.stringify(colId)}`);
2966
+ cell?.classList.add('rangeSelect');
2967
+ if (colIndex === 0) {
2968
+ cell?.classList.add('rangeSelectLeft');
2969
+ }
2970
+ if (colIndex === selectedColIds.length - 1) {
2971
+ cell?.classList.add('rangeSelectRight');
2972
+ }
2973
+ if (rowIndex === 0) {
2974
+ cell?.classList.add('rangeSelectTop');
2975
+ }
2976
+ if (rowIndex === selectedNodes.length - 1) {
2977
+ cell?.classList.add('rangeSelectBottom');
2978
+ }
2979
+ });
2980
+ });
2981
+ }, []);
2982
+ const updateRangeSelectionCellClasses = React.useCallback((justRefresh) => {
2983
+ //
2984
+ // Get all grid cols, sort by pinned, then style: left
2985
+ const gridElement = gridDivRef.current;
2986
+ if (!gridElement) {
2987
+ return;
2988
+ }
2989
+ // Clear all selections
2990
+ if (!justRefresh) {
2991
+ gridElement
2992
+ .querySelectorAll('.rangeSelect,.rangeSelectLeft,.rangeSelectTop,.rangeSelectRight,.rangeSelectBottom')
2993
+ .forEach((el) => {
2994
+ el.classList.remove('rangeSelect', 'rangeSelectLeft', 'rangeSelectTop', 'rangeSelectRight', 'rangeSelectBottom');
2995
+ });
2996
+ }
2997
+ // if range selection multiple add .Grid-container.rangeSelectingMultiple
2998
+ const rangeStart = rangeStartRef.current;
2999
+ const rangeEnd = rangeEndRef.current;
3000
+ if (rangeStart !== null &&
3001
+ rangeEnd !== null &&
3002
+ (hasSelectedMoreThanOneCellRef.current ||
3003
+ rangeStart.colId !== rangeEnd.colId ||
3004
+ rangeStart.rowId !== rangeEnd.rowId)) {
3005
+ gridElement.classList.add('rangeSelectingMultiple');
3006
+ gridElement.querySelectorAll('.ag-cell-focus').forEach((el) => {
3007
+ el.classList.remove('ag-cell-focus');
3008
+ });
3009
+ }
3010
+ else {
3011
+ gridElement.classList.remove('rangeSelectingMultiple');
3012
+ return;
3013
+ }
3014
+ const rangeSortedNodes = rangeSortedNodesRef.current;
3015
+ if (!rangeSortedNodes) {
3016
+ return;
3017
+ }
3018
+ redrawSelectedRanges();
3019
+ }, [ranges, redrawSelectedRanges]);
3020
+ // Handle updates after scroll / grid refresh
3021
+ useInterval(() => {
3022
+ updateRangeSelectionCellClasses(true);
3023
+ }, refreshIntervalEnabled ? 150 : null);
3024
+ const clearRangeSelection = React.useCallback(() => {
3025
+ hasSelectedMoreThanOneCellRef.current = false;
3026
+ setRefreshIntervalEnabled(false);
3027
+ hasSelectedMoreThanOneCellRef.current = false;
3028
+ rangeStartRef.current = null;
3029
+ rangeEndRef.current = null;
3030
+ updateRangeSelectionCellClasses();
3031
+ }, [updateRangeSelectionCellClasses]);
3032
+ const onCellMouseOver = React.useCallback((e, mouseDown) => {
3033
+ if (!enableRangeSelection) {
3034
+ return;
3035
+ }
3036
+ const button = e.event.buttons;
3037
+ if (button !== 1) {
3038
+ // TODO fix this?
3039
+ //rangeSortedNodesRef.current = null;
3040
+ return;
3041
+ }
3042
+ rangeEndRef.current = {
3043
+ rowId: e.node.data.id,
3044
+ colId: e.column.getColId(),
3045
+ timestamp: Date.now(),
3046
+ };
3047
+ if (mouseDown) {
3048
+ const sortedNodes = [];
3049
+ e.api.forEachNodeAfterFilterAndSort((node) => sortedNodes.push(node));
3050
+ rangeSortedNodesRef.current = sortedNodes;
3051
+ setRefreshIntervalEnabled(true);
3052
+ rangeStartRef.current = { ...rangeEndRef.current };
3053
+ }
3054
+ if (rangeStartRef.current &&
3055
+ rangeEndRef.current &&
3056
+ (rangeStartRef.current.rowId !== rangeEndRef.current.rowId ||
3057
+ rangeStartRef.current.colId !== rangeEndRef.current.colId)) {
3058
+ hasSelectedMoreThanOneCellRef.current = true;
3059
+ window.getSelection()?.removeAllRanges();
3060
+ }
3061
+ updateRangeSelectionCellClasses();
3062
+ }, [enableRangeSelection, updateRangeSelectionCellClasses]);
3063
+ const onCellMouseDown = React.useCallback((e) => {
3064
+ const button = e.event.buttons;
3065
+ if (button === 1) {
3066
+ clearRangeSelection();
3067
+ }
3068
+ onCellMouseOver(e, true);
3069
+ }, [onCellMouseOver]);
3070
+ return { clearRangeSelection, ranges, onCellMouseDown, onCellMouseOver };
3071
+ };
3072
+
2724
3073
  const GridLoadingOverlayComponentFr = (props, externalRef) => (jsxRuntime.jsx("div", { ref: externalRef, style: {
2725
3074
  left: 0,
2726
3075
  top: 0,
@@ -2902,8 +3251,26 @@ agGridCommunity.ModuleRegistry.registerModules([agGridCommunity.AllCommunityModu
2902
3251
  /**
2903
3252
  * Wrapper for AgGrid to add commonly used functionality.
2904
3253
  */
2905
- const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection = 'multiple', suppressColumnVirtualization = true, theme = 'ag-theme-step-default', sizeColumns = 'auto', selectColumnPinned = 'left', contextMenuSelectRow = false, singleClickEdit = false, rowData, rowHeight = theme === 'ag-theme-step-default' ? 40 : theme === 'ag-theme-step-compact' ? 36 : 40, selectable, onCellFocused: paramsOnCellFocused, maxInitialWidth, suppressReadOnlyStyle = false, ...params }) => {
2906
- const { gridReady, gridRenderState, setApis, ensureRowVisible, getFirstRowId, selectRowsById, focusByRowById, ensureSelectedRowIsVisible, autoSizeColumns, sizeColumnsToFit, externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync, isExternalFilterPresent, doesExternalFilterPass, setOnBulkEditingComplete, getColDef, showNoRowsOverlay, prePopupOps, startCellEditing: propStartCellEditing, } = useGridContext();
3254
+ const Grid = ({ theme = 'ag-theme-step-default', 'data-testid': dataTestId,
3255
+ // ─── Grid State ───────────────────────────────
3256
+ suppressReadOnlyStyle = false,
3257
+ // ─── Data & Columns ───────────────────────────
3258
+ defaultPostSort = true, rowData, rowHeight = theme === 'ag-theme-step-default' ? 40 : theme === 'ag-theme-step-compact' ? 36 : 40, rowSelection = 'multiple', sizeColumns = 'auto',
3259
+ // ─── Selection ────────────────────────────────
3260
+ autoSelectFirstRow, enableRangeSelection = true, externalSelectedIds, externalSelectedItems, selectColumnPinned = 'left', selectable, setExternalSelectedIds, setExternalSelectedItems,
3261
+ // ─── Editing ──────────────────────────────────
3262
+ singleClickEdit = false,
3263
+ // ─── Context Menu ─────────────────────────────
3264
+ contextMenuSelectRow = false, contextMenu,
3265
+ // ─── Callbacks / Events ───────────────────────
3266
+ onCellFocused: paramsOnCellFocused, onColumnMoved,
3267
+ // ─── Row Behavior ─────────────────────────────
3268
+ suppressColumnVirtualization = true,
3269
+ // ─── Miscellaneous ────────────────────────────
3270
+ maxInitialWidth,
3271
+ // ─── Spread Remaining Params ──────────────────
3272
+ ...params }) => {
3273
+ const { setApis, setExternallySelectedItemsAreInSync, setOnBulkEditingComplete, gridReady, gridRenderState, externallySelectedItemsAreInSync, showNoRowsOverlay, autoSizeColumns, sizeColumnsToFit, doesExternalFilterPass, ensureRowVisible, ensureSelectedRowIsVisible, focusByRowById, getColDef, getFirstRowId, isExternalFilterPresent, prePopupOps, selectRowsById, startCellEditing: propStartCellEditing, } = useGridContext();
2907
3274
  // CellEditingStop event happens too much for one edit
2908
3275
  const startedEditRef = React.useRef(false);
2909
3276
  const startCellEditing = React.useCallback((props) => {
@@ -2912,7 +3279,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2912
3279
  }, [propStartCellEditing]);
2913
3280
  const { updatedDep, anyUpdating, updatingCols } = React.useContext(GridUpdatingContext);
2914
3281
  const gridDivRef = React.useRef(null);
2915
- const lastSelectedIds = React.useRef([]);
3282
+ const lastSelectedIds = React.useRef();
2916
3283
  const [staleGrid, setStaleGrid] = React.useState(false);
2917
3284
  const [autoSized, setAutoSized] = React.useState(false);
2918
3285
  const postSortRows = usePostSortRowsHook({ setStaleGrid });
@@ -3038,12 +3405,13 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3038
3405
  */
3039
3406
  const hasSelectedFirstItem = React.useRef(false);
3040
3407
  React.useEffect(() => {
3041
- if (!gridReady || hasSelectedFirstItem.current || !rowData || !externallySelectedItemsAreInSync)
3408
+ if (!gridReady || hasSelectedFirstItem.current || !rowData || !externallySelectedItemsAreInSync) {
3042
3409
  return;
3410
+ }
3043
3411
  hasSelectedFirstItem.current = true;
3044
- if (isNotEmpty(rowData) && lodashEs.isEmpty(params.externalSelectedItems)) {
3412
+ if (isNotEmpty(rowData) && lodashEs.isEmpty(externalSelectedItems) && lodashEs.isEmpty(externalSelectedIds)) {
3045
3413
  const firstRowId = getFirstRowId();
3046
- if (params.autoSelectFirstRow) {
3414
+ if (autoSelectFirstRow && selectable) {
3047
3415
  selectRowsById([firstRowId]);
3048
3416
  }
3049
3417
  else {
@@ -3054,31 +3422,52 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3054
3422
  externallySelectedItemsAreInSync,
3055
3423
  focusByRowById,
3056
3424
  gridReady,
3057
- params.externalSelectedItems,
3058
- params.autoSelectFirstRow,
3425
+ externalSelectedItems,
3426
+ autoSelectFirstRow,
3059
3427
  rowData,
3060
3428
  selectRowsById,
3061
3429
  getFirstRowId,
3430
+ selectable,
3431
+ externalSelectedIds,
3062
3432
  ]);
3063
3433
  /**
3064
3434
  * Ensure external selected items list is in sync with panel.
3065
3435
  */
3066
3436
  const synchroniseExternalStateToGridSelection = React.useCallback(({ api }) => {
3067
- if (!params.externalSelectedItems || !params.setExternalSelectedItems) {
3068
- setExternallySelectedItemsAreInSync(true);
3069
- return;
3437
+ if (externalSelectedIds && setExternalSelectedIds) {
3438
+ const selectedRowsIds = api.getSelectedRows().map((row) => row.id);
3439
+ // We don't want to update selected Items if it hasn't changed to prevent excess renders
3440
+ if (externalSelectedIds.length !== selectedRowsIds.length ||
3441
+ isNotEmpty(lodashEs.xorBy(selectedRowsIds, externalSelectedIds))) {
3442
+ setExternallySelectedItemsAreInSync(false);
3443
+ setExternalSelectedIds([...selectedRowsIds]);
3444
+ }
3445
+ else {
3446
+ setExternallySelectedItemsAreInSync(true);
3447
+ }
3070
3448
  }
3071
- const selectedRows = api.getSelectedRows();
3072
- // We don't want to update selected Items if it hasn't changed to prevent excess renders
3073
- if (params.externalSelectedItems.length !== selectedRows.length ||
3074
- isNotEmpty(lodashEs.xorBy(selectedRows, params.externalSelectedItems, (row) => row.id))) {
3075
- setExternallySelectedItemsAreInSync(false);
3076
- params.setExternalSelectedItems([...selectedRows]);
3449
+ else if (externalSelectedItems && setExternalSelectedItems) {
3450
+ const selectedRows = api.getSelectedRows();
3451
+ // We don't want to update selected Items if it hasn't changed to prevent excess renders
3452
+ if (externalSelectedItems.length !== selectedRows.length ||
3453
+ isNotEmpty(lodashEs.xorBy(selectedRows, externalSelectedItems, (row) => row.id))) {
3454
+ setExternallySelectedItemsAreInSync(false);
3455
+ setExternalSelectedItems([...selectedRows]);
3456
+ }
3457
+ else {
3458
+ setExternallySelectedItemsAreInSync(true);
3459
+ }
3077
3460
  }
3078
3461
  else {
3079
3462
  setExternallySelectedItemsAreInSync(true);
3080
3463
  }
3081
- }, [params, setExternallySelectedItemsAreInSync]);
3464
+ }, [
3465
+ externalSelectedIds,
3466
+ externalSelectedItems,
3467
+ setExternalSelectedIds,
3468
+ setExternalSelectedItems,
3469
+ setExternallySelectedItemsAreInSync,
3470
+ ]);
3082
3471
  /**
3083
3472
  * Synchronise externally selected items to grid.
3084
3473
  * If new ids are selected scroll them into view.
@@ -3086,19 +3475,26 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3086
3475
  const synchroniseExternallySelectedItemsToGrid = React.useCallback(() => {
3087
3476
  if (!gridReady)
3088
3477
  return;
3089
- if (!params.externalSelectedItems) {
3478
+ if (!externalSelectedItems && !externalSelectedIds) {
3090
3479
  setExternallySelectedItemsAreInSync(true);
3091
3480
  return;
3092
3481
  }
3093
- const selectedIds = params.externalSelectedItems.map((row) => row.id);
3094
- const lastNewId = lodashEs.last(lodashEs.difference(selectedIds, lastSelectedIds.current));
3482
+ const selectedIds = externalSelectedIds ?? externalSelectedItems?.map((row) => row.id);
3483
+ const lastNewId = lodashEs.last(lodashEs.difference(selectedIds, lastSelectedIds.current ?? []));
3095
3484
  if (lastNewId != null) {
3096
3485
  ensureRowVisible(lastNewId);
3097
3486
  }
3098
3487
  lastSelectedIds.current = selectedIds;
3099
3488
  selectRowsById(selectedIds);
3100
3489
  setExternallySelectedItemsAreInSync(true);
3101
- }, [gridReady, params.externalSelectedItems, ensureRowVisible, selectRowsById, setExternallySelectedItemsAreInSync]);
3490
+ }, [
3491
+ gridReady,
3492
+ externalSelectedItems,
3493
+ externalSelectedIds,
3494
+ selectRowsById,
3495
+ setExternallySelectedItemsAreInSync,
3496
+ ensureRowVisible,
3497
+ ]);
3102
3498
  /**
3103
3499
  * Combine grid and cell editable into one function
3104
3500
  */
@@ -3140,7 +3536,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3140
3536
  const columnDefs = React.useMemo(() => {
3141
3537
  return params.columnDefs.map(mapColDef);
3142
3538
  }, [params.columnDefs, mapColDef]);
3143
- const hasExternallySelectedItems = !!params.setExternalSelectedItems;
3539
+ const hasExternallySelectedItems = !!setExternalSelectedItems || !!setExternalSelectedIds;
3144
3540
  /**
3145
3541
  * When grid is ready set the apis to the grid context and sync selected items to grid.
3146
3542
  */
@@ -3196,15 +3592,6 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3196
3592
  void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
3197
3593
  }
3198
3594
  }, [startCellEditing]);
3199
- /**
3200
- * Handle single click edits
3201
- */
3202
- const onCellClicked = React.useCallback((event) => {
3203
- const editable = fnOrVar(event.colDef?.editable, event);
3204
- if ((editable && event.colDef.singleClickEdit) ?? singleClickEdit) {
3205
- void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
3206
- }
3207
- }, [singleClickEdit, startCellEditing]);
3208
3595
  const onCellEditingStopped = React.useCallback((event) => {
3209
3596
  if (!startedEditRef.current) {
3210
3597
  return;
@@ -3253,6 +3640,78 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3253
3640
  prePopupOps();
3254
3641
  }
3255
3642
  }, [prePopupOps, startCellEditing]);
3643
+ const { cellContextMenu, contextMenuComponent } = useGridContextMenu({
3644
+ contextMenu,
3645
+ contextMenuSelectRow,
3646
+ });
3647
+ const hasSelectedMoreThanOneCellRef = React.useRef(false);
3648
+ const rangeStartRef = React.useRef(null);
3649
+ const rangeEndRef = React.useRef(null);
3650
+ const rangeSortedNodesRef = React.useRef(null);
3651
+ const { clearRangeSelection, ranges, onCellMouseDown, onCellMouseOver } = useGridRangeSelection({
3652
+ enableRangeSelection,
3653
+ gridDivRef,
3654
+ rangeStartRef,
3655
+ rangeEndRef,
3656
+ hasSelectedMoreThanOneCellRef,
3657
+ rangeSortedNodesRef,
3658
+ });
3659
+ const { onCopyEvent, rangeSelectInterceptContextMenu, rangeSelectContextMenuComponent } = useGridCopy({
3660
+ ranges,
3661
+ rangeStartRef,
3662
+ rangeEndRef,
3663
+ hasSelectedMoreThanOneCellRef,
3664
+ cellContextMenu,
3665
+ });
3666
+ const onSortChanged = React.useCallback(() => {
3667
+ clearRangeSelection();
3668
+ ensureSelectedRowIsVisible();
3669
+ }, [clearRangeSelection, ensureSelectedRowIsVisible]);
3670
+ /**
3671
+ * Handle single click edits
3672
+ */
3673
+ const onCellClicked = React.useCallback((event) => {
3674
+ if (rangeStartRef.current && rangeEndRef.current) {
3675
+ // This is to detect difference between a single click and a click drag return to cell.
3676
+ if (rangeEndRef.current.timestamp - rangeStartRef.current.timestamp < 100) {
3677
+ clearRangeSelection();
3678
+ }
3679
+ return;
3680
+ }
3681
+ const editable = fnOrVar(event.colDef?.editable, event);
3682
+ if ((editable && event.colDef.singleClickEdit) ?? singleClickEdit) {
3683
+ void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
3684
+ }
3685
+ }, [clearRangeSelection, singleClickEdit, startCellEditing]);
3686
+ /**
3687
+ * Set of column I'd's that are prevented from auto-sizing as they are user set
3688
+ */
3689
+ const userSizedColIds = React.useRef(new Map());
3690
+ /**
3691
+ * Lock/unlock column width on user edit/reset.
3692
+ */
3693
+ const onColumnResized = React.useCallback((e) => {
3694
+ const colId = e.column?.getColId();
3695
+ if (colId == null) {
3696
+ return;
3697
+ }
3698
+ const width = e.column?.getActualWidth();
3699
+ if (width == null) {
3700
+ return;
3701
+ }
3702
+ switch (e.source) {
3703
+ case 'uiColumnResized':
3704
+ userSizedColIds.current.set(colId, width);
3705
+ break;
3706
+ case 'autosizeColumns':
3707
+ userSizedColIds.current.delete(colId);
3708
+ break;
3709
+ }
3710
+ }, []);
3711
+ const columnMoved = React.useCallback((e) => {
3712
+ clearRangeSelection();
3713
+ onColumnMoved?.(e);
3714
+ }, [clearRangeSelection, onColumnMoved]);
3256
3715
  /**
3257
3716
  * Once the grid has auto-sized we want to run fit to fit the grid in its container,
3258
3717
  * but we don't want the non-flex auto-sized columns to "fit" size, so suppressSizeToFit is set to true.
@@ -3270,7 +3729,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3270
3729
  let comparator = colDef.comparator;
3271
3730
  if (sortable && !comparator) {
3272
3731
  comparator = (value1, value2, node1, node2) => {
3273
- let r = 0;
3732
+ let r;
3274
3733
  if (typeof valueFormatter === 'function') {
3275
3734
  r = compareNaturalInsensitive(valueFormatter({
3276
3735
  data: node1.data,
@@ -3360,37 +3819,6 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3360
3819
  }
3361
3820
  prevLoading.current = newLoading;
3362
3821
  }, [params.loading, rowData, showNoRowsOverlay]);
3363
- /**
3364
- * Set of column I'd's that are prevented from auto-sizing as they are user set
3365
- */
3366
- const userSizedColIds = React.useRef(new Map());
3367
- /**
3368
- * Lock/unlock column width on user edit/reset.
3369
- */
3370
- const onColumnResized = React.useCallback((e) => {
3371
- const colId = e.column?.getColId();
3372
- if (colId == null) {
3373
- return;
3374
- }
3375
- const width = e.column?.getActualWidth();
3376
- if (width == null) {
3377
- return;
3378
- }
3379
- switch (e.source) {
3380
- case 'uiColumnResized':
3381
- userSizedColIds.current.set(colId, width);
3382
- /*const colDef = e.column?.getColDef();
3383
- if (!colDef?.flex) {
3384
- onGridResize(e);
3385
- }*/
3386
- break;
3387
- case 'autosizeColumns':
3388
- userSizedColIds.current.delete(colId);
3389
- //onGridResize(e);
3390
- break;
3391
- }
3392
- }, []);
3393
- const gridContextMenu = useGridContextMenu({ contextMenu: params.contextMenu, contextMenuSelectRow });
3394
3822
  const startDragYRef = React.useRef(null);
3395
3823
  const clearHighlightRowClasses = React.useCallback(() => {
3396
3824
  document.querySelectorAll(`.ag-row-highlight-above`)?.forEach((el) => {
@@ -3467,11 +3895,14 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3467
3895
  }
3468
3896
  }, [params, clearHighlightRowClasses]);
3469
3897
  React.useEffect(() => {
3470
- if (params.setExternalSelectedItems && selectable == null) {
3471
- console.warn('<Grid/> has setExternalSelectedItems parameter, but is missing selectable parameter,' +
3898
+ if ((setExternalSelectedItems || setExternalSelectedIds) && selectable == null) {
3899
+ console.warn('<Grid/> has setExternalSelectedItems/setExternalSelectedIds parameter, but is missing selectable parameter,' +
3472
3900
  'this will cause weird delays in editing.\nIf you need to hide selection column use hideSelectColumn=true');
3473
3901
  }
3474
- }, [params.setExternalSelectedItems, selectable]);
3902
+ },
3903
+ // Only needs to run on startup
3904
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3905
+ [selectable]);
3475
3906
  // This is setting a ref in the GridContext so won't be triggering an update loop
3476
3907
  setOnBulkEditingComplete(params.onBulkEditingComplete);
3477
3908
  const getRowId = React.useCallback((params) => `${params.data.id}`, []);
@@ -3515,25 +3946,24 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3515
3946
  }
3516
3947
  return false;
3517
3948
  },
3518
- onCellClicked: params.enableSelectionWithoutKeys || params.enableClickSelection
3519
- ? undefined
3520
- : clickInputWhenContainingCellClicked,
3949
+ // enableClickSelection = true means ag-grid auto selects row if you click outside the checkbox
3950
+ // if it's false we have to do it.
3951
+ onCellClicked: params.enableClickSelection ? undefined : clickInputWhenContainingCellClicked,
3521
3952
  };
3522
3953
  }, [
3523
- params.enableClickSelection,
3524
- params.enableSelectionWithoutKeys,
3525
3954
  params.hideSelectColumn,
3526
3955
  params.onRowDragEnd,
3527
3956
  rowSelection,
3528
3957
  selectColumnPinned,
3529
3958
  selectable,
3959
+ params.enableClickSelection,
3530
3960
  ]);
3531
3961
  const onGridSizeChanged = React.useCallback((event) => {
3532
3962
  if (sizeColumns === 'fit' || (['auto', 'auto-skip-headers'].includes(sizeColumns) && hasSetContentSize.current)) {
3533
3963
  event.api.sizeColumnsToFit();
3534
3964
  }
3535
3965
  }, [sizeColumns]);
3536
- 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, { theme: 'legacy', rowSelection: selectable
3966
+ return (jsxRuntime.jsxs("div", { "data-testid": dataTestId, className: clsx('Grid-container', theme, 'theme-specific', staleGrid && 'Grid-sortIsStale', gridReady && rowData && autoSized && 'Grid-ready'), children: [contextMenuComponent, rangeSelectContextMenuComponent, jsxRuntime.jsx("div", { style: { flex: 1 }, ref: gridDivRef, onCopy: onCopyEvent, children: jsxRuntime.jsx(agGridReact.AgGridReact, { theme: 'legacy', domLayout: params.domLayout, defaultColDef: defaultColDef, columnDefs: columnDefsAdjusted, getRowId: getRowId, rowData: rowData, alwaysShowVerticalScroll: params.alwaysShowVerticalScroll, animateRows: params.animateRows ?? false, doesExternalFilterPass: doesExternalFilterPass, isExternalFilterPresent: isExternalFilterPresent, maintainColumnOrder: true, noRowsOverlayComponent: noRowsOverlayComponent, onCellClicked: onCellClicked, onCellContextMenu: rangeSelectInterceptContextMenu, onCellDoubleClicked: onCellDoubleClick, onCellEditingStopped: onCellEditingStopped, onCellFocused: onCellFocused, onCellKeyDown: onCellKeyPress, onCellMouseDown: onCellMouseDown, onCellMouseOver: onCellMouseOver, onColumnMoved: columnMoved, onColumnResized: onColumnResized, onColumnVisible: () => void setInitialContentSize(), onGridReady: onGridReady, onGridSizeChanged: onGridSizeChanged, onModelUpdated: onModelUpdated, onRowClicked: params.onRowClicked, onRowDataUpdated: onRowDataUpdated, onRowDoubleClicked: params.onRowDoubleClicked, onRowDragCancel: clearHighlightRowClasses, onRowDragEnd: onRowDragEnd, onRowDragMove: onRowDragMove, onSelectionChanged: synchroniseExternalStateToGridSelection, onSortChanged: onSortChanged, pinnedBottomRowData: params.pinnedBottomRowData, pinnedTopRowData: params.pinnedTopRowData, postSortRows: params.onRowDragEnd || !defaultPostSort ? undefined : postSortRows, preventDefaultOnContextMenu: true, quickFilterParser: quickFilterParser, rowClassRules: params.rowClassRules, rowDragText: params.rowDragText, rowHeight: rowHeight, rowSelection: selectable
3537
3967
  ? {
3538
3968
  enableSelectionWithoutKeys: params.enableSelectionWithoutKeys ?? false,
3539
3969
  enableClickSelection: params.enableClickSelection ?? false,
@@ -3543,7 +3973,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3543
3973
  headerCheckbox: false,
3544
3974
  }),
3545
3975
  }
3546
- : undefined, selectionColumnDef: selectionColumnDef, rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: getRowId, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onGridSizeChanged: onGridSizeChanged, onColumnVisible: () => void setInitialContentSize(), onRowDataUpdated: onRowDataUpdated, onCellFocused: onCellFocused, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStopped: onCellEditingStopped, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: defaultColDef, columnDefs: columnDefsAdjusted, rowData: rowData, postSortRows: params.onRowDragEnd || !defaultPostSort ? undefined : postSortRows, onModelUpdated: onModelUpdated, onGridReady: onGridReady, onSortChanged: ensureSelectedRowIsVisible, quickFilterParser: quickFilterParser, onSelectionChanged: synchroniseExternalStateToGridSelection, onColumnMoved: params.onColumnMoved, noRowsOverlayComponent: noRowsOverlayComponent, alwaysShowVerticalScroll: params.alwaysShowVerticalScroll, isExternalFilterPresent: isExternalFilterPresent, doesExternalFilterPass: doesExternalFilterPass, maintainColumnOrder: true, preventDefaultOnContextMenu: true, onCellContextMenu: gridContextMenu.cellContextMenu, rowDragText: params.rowDragText, onRowDragCancel: clearHighlightRowClasses, onRowDragMove: onRowDragMove, onRowDragEnd: onRowDragEnd, suppressCellFocus: params.suppressCellFocus, pinnedTopRowData: params.pinnedTopRowData, pinnedBottomRowData: params.pinnedBottomRowData, onRowClicked: params.onRowClicked, onRowDoubleClicked: params.onRowDoubleClicked, suppressStartEditOnTab: true }) })] }));
3976
+ : undefined, selectionColumnDef: selectionColumnDef, suppressCellFocus: params.suppressCellFocus, suppressClickEdit: true, suppressColumnVirtualisation: suppressColumnVirtualization, suppressStartEditOnTab: true }) })] }));
3547
3977
  };
3548
3978
  const quickFilterParser = (filterStr) => {
3549
3979
  // filter is exact matches exactly groups separated by commas
@@ -3784,33 +4214,6 @@ const GridFilterButtons = ({ className, luiButtonProps, options, }) => {
3784
4214
  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}`))) }) }));
3785
4215
  };
3786
4216
 
3787
- function styleInject(css, ref) {
3788
- if ( ref === void 0 ) ref = {};
3789
- var insertAt = ref.insertAt;
3790
-
3791
- if (!css || typeof document === 'undefined') { return; }
3792
-
3793
- var head = document.head || document.getElementsByTagName('head')[0];
3794
- var style = document.createElement('style');
3795
- style.type = 'text/css';
3796
-
3797
- if (insertAt === 'top') {
3798
- if (head.firstChild) {
3799
- head.insertBefore(style, head.firstChild);
3800
- } else {
3801
- head.appendChild(style);
3802
- }
3803
- } else {
3804
- head.appendChild(style);
3805
- }
3806
-
3807
- if (style.styleSheet) {
3808
- style.styleSheet.cssText = css;
3809
- } else {
3810
- style.appendChild(document.createTextNode(css));
3811
- }
3812
- }
3813
-
3814
4217
  var css_248z$3 = ".GridFilterColsMultiSelect{background:#fff;font-family:Open Sans,system-ui,sans-serif;font-style:normal;font-weight:600;padding:8px}.GridFilterColsMultiSelect .LuiSelect-label-text{color:#6b6966;display:inline-block}.GridFilterColsMultiSelect .LuiCheckboxInput-item,.GridFilterColsMultiSelect .LuiCheckboxInput-selectAll{color:#2a292c;font-size:16px;font-weight:600;letter-spacing:0;line-height:20px;line-height:24px;margin-bottom:0}";
3815
4218
  styleInject(css_248z$3);
3816
4219
 
@@ -4618,14 +5021,14 @@ const TextInputFormatted = (props) => {
4618
5021
 
4619
5022
  const bearingValueFormatter = (value) => {
4620
5023
  const safeValue = typeof value === 'string' ? parseFloat(value) : value;
4621
- if (safeValue == null) {
5024
+ if (safeValue == null || Number.isNaN(safeValue)) {
4622
5025
  return '–';
4623
5026
  }
4624
5027
  return convertDDToDMS(safeValue, false);
4625
5028
  };
4626
5029
  const bearingCorrectionValueFormatter = (value) => {
4627
5030
  const safeValue = value;
4628
- if (safeValue == null) {
5031
+ if (safeValue == null || Number.isNaN(safeValue)) {
4629
5032
  return '–';
4630
5033
  }
4631
5034
  if (typeof safeValue === 'string') {
@@ -5421,6 +5824,7 @@ const GridPopoutEditMultiSelectGrid = (colDef, props) => GridCell(colDef, {
5421
5824
  },
5422
5825
  });
5423
5826
 
5827
+ const GridCellBearingValueFormatter = (params) => bearingValueFormatter(params.value) ?? '';
5424
5828
  const GridPopoverEditBearingLike = (colDef, props) => GridCell({
5425
5829
  valueFormatter: (params) => props.editorParams?.formatValue(params.value) ?? '',
5426
5830
  ...colDef,
@@ -5573,6 +5977,7 @@ const GridContextProvider = (props) => {
5573
5977
  }
5574
5978
  return gridApi && !gridApi.isDestroyed() ? hasApiFn(gridApi) : noApiFn();
5575
5979
  }, [gridApi]);
5980
+ const getCellValue = React.useCallback((...props) => gridApi?.getCellValue(...props), [gridApi]);
5576
5981
  /**
5577
5982
  * Scroll row into view by Id.
5578
5983
  *
@@ -5732,7 +6137,7 @@ const GridContextProvider = (props) => {
5732
6137
  // It may be that the first cell is the selection cell, this doesn't exist as a colDef
5733
6138
  // so instead, I just try and select it. If it doesn't exist selection will stay on the
5734
6139
  // previously focused cell
5735
- gridApi.setFocusedCell(rowIndex, 'ag-Grid-SelectionColumn');
6140
+ gridApi.setFocusedCell(rowIndex, agGridSelectRowColId);
5736
6141
  }
5737
6142
  }, 100);
5738
6143
  }
@@ -6171,6 +6576,7 @@ const GridContextProvider = (props) => {
6171
6576
  getSelectedRowIds,
6172
6577
  getFilteredSelectedRowIds,
6173
6578
  getFirstRowId,
6579
+ getCellValue,
6174
6580
  editingCells,
6175
6581
  ensureRowVisible,
6176
6582
  ensureSelectedRowIsVisible,
@@ -6361,6 +6767,7 @@ exports.GenericCellEditorComponentWrapper = GenericCellEditorComponentWrapper;
6361
6767
  exports.Grid = Grid;
6362
6768
  exports.GridButton = GridButton;
6363
6769
  exports.GridCell = GridCell;
6770
+ exports.GridCellBearingValueFormatter = GridCellBearingValueFormatter;
6364
6771
  exports.GridCellFiller = GridCellFiller;
6365
6772
  exports.GridCellFillerColId = GridCellFillerColId;
6366
6773
  exports.GridCellMultiEditor = GridCellMultiEditor;
@@ -6424,6 +6831,7 @@ exports.SubMenu = SubMenu;
6424
6831
  exports.TextAreaInput = TextAreaInput;
6425
6832
  exports.TextInputFormatted = TextInputFormatted;
6426
6833
  exports.TextInputValidator = TextInputValidator;
6834
+ exports.agGridSelectRowColId = agGridSelectRowColId;
6427
6835
  exports.bearingCorrectionRangeValidator = bearingCorrectionRangeValidator;
6428
6836
  exports.bearingCorrectionValueFormatter = bearingCorrectionValueFormatter;
6429
6837
  exports.bearingNumberParser = bearingNumberParser;