@economic/taco 2.45.0-alpha.1 → 2.45.0-alpha.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. package/dist/components/Popover/Popover.d.ts +1 -1
  2. package/dist/components/Provider/Localization.d.ts +2 -0
  3. package/dist/components/Report/Report.d.ts +1 -1
  4. package/dist/components/Select2/components/Search.d.ts +0 -6
  5. package/dist/components/Table3/Table3.d.ts +2 -14
  6. package/dist/components/Table3/components/Columns/Internal/EditingActionsMenu.d.ts +3 -4
  7. package/dist/components/Table3/components/Editing/DiscardChangesConfirmationDialog.d.ts +7 -0
  8. package/dist/components/Table3/components/Row/Editing/CreateNewRow.d.ts +14 -0
  9. package/dist/components/Table3/components/Row/Editing/TemporaryRow.d.ts +11 -0
  10. package/dist/components/Table3/features/useEditingState.d.ts +29 -0
  11. package/dist/components/Table3/features/useTableEditing.d.ts +26 -36
  12. package/dist/components/Table3/listeners/useTableEditingListener.d.ts +1 -1
  13. package/dist/components/Table3/types.d.ts +24 -8
  14. package/dist/components/Table3/useTable3.d.ts +6 -0
  15. package/dist/components/Table3/util/editing.d.ts +7 -1
  16. package/dist/esm/index.css +35 -4
  17. package/dist/esm/packages/taco/src/components/Button/util.js +1 -1
  18. package/dist/esm/packages/taco/src/components/Button/util.js.map +1 -1
  19. package/dist/esm/packages/taco/src/components/ModeSwitch/ModeSwitch.js +2 -2
  20. package/dist/esm/packages/taco/src/components/ModeSwitch/ModeSwitch.js.map +1 -1
  21. package/dist/esm/packages/taco/src/components/Popover/Popover.js.map +1 -1
  22. package/dist/esm/packages/taco/src/components/Provider/Localization.js +5 -3
  23. package/dist/esm/packages/taco/src/components/Provider/Localization.js.map +1 -1
  24. package/dist/esm/packages/taco/src/components/Select2/Select2.js +21 -40
  25. package/dist/esm/packages/taco/src/components/Select2/Select2.js.map +1 -1
  26. package/dist/esm/packages/taco/src/components/Select2/components/Search.js +2 -12
  27. package/dist/esm/packages/taco/src/components/Select2/components/Search.js.map +1 -1
  28. package/dist/esm/packages/taco/src/components/Select2/components/Trigger.js +19 -1
  29. package/dist/esm/packages/taco/src/components/Select2/components/Trigger.js.map +1 -1
  30. package/dist/esm/packages/taco/src/components/Switch/Switch.js +1 -1
  31. package/dist/esm/packages/taco/src/components/Switch/Switch.js.map +1 -1
  32. package/dist/esm/packages/taco/src/components/Table3/Table3.js +14 -6
  33. package/dist/esm/packages/taco/src/components/Table3/Table3.js.map +1 -1
  34. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/Editing/RowMoveIndicator.js +1 -2
  35. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/Editing/RowMoveIndicator.js.map +1 -1
  36. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/EditingControlCell.js +33 -11
  37. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/EditingControlCell.js.map +1 -1
  38. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Internal/EditingActionsMenu.js +7 -39
  39. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Internal/EditingActionsMenu.js.map +1 -1
  40. package/dist/esm/packages/taco/src/components/Table3/components/Editing/Alert.js +17 -12
  41. package/dist/esm/packages/taco/src/components/Table3/components/Editing/Alert.js.map +1 -1
  42. package/dist/esm/packages/taco/src/components/Table3/components/Editing/DiscardChangesConfirmationDialog.js +34 -0
  43. package/dist/esm/packages/taco/src/components/Table3/components/Editing/DiscardChangesConfirmationDialog.js.map +1 -0
  44. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateNewRow.js +104 -0
  45. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateNewRow.js.map +1 -0
  46. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/SaveStatus.js +2 -14
  47. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/SaveStatus.js.map +1 -1
  48. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/TemporaryRow.js +96 -0
  49. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/TemporaryRow.js.map +1 -0
  50. package/dist/esm/packages/taco/src/components/Table3/components/Row/Row.js +39 -6
  51. package/dist/esm/packages/taco/src/components/Table3/components/Row/Row.js.map +1 -1
  52. package/dist/esm/packages/taco/src/components/Table3/components/Toolbar/Editing/Editing.js +4 -17
  53. package/dist/esm/packages/taco/src/components/Table3/components/Toolbar/Editing/Editing.js.map +1 -1
  54. package/dist/esm/packages/taco/src/components/Table3/features/useEditingState.js +519 -0
  55. package/dist/esm/packages/taco/src/components/Table3/features/useEditingState.js.map +1 -0
  56. package/dist/esm/packages/taco/src/components/Table3/features/useTableEditing.js +29 -406
  57. package/dist/esm/packages/taco/src/components/Table3/features/useTableEditing.js.map +1 -1
  58. package/dist/esm/packages/taco/src/components/Table3/listeners/useTableEditingListener.js +44 -33
  59. package/dist/esm/packages/taco/src/components/Table3/listeners/useTableEditingListener.js.map +1 -1
  60. package/dist/esm/packages/taco/src/components/Table3/useTable3.js +44 -14
  61. package/dist/esm/packages/taco/src/components/Table3/useTable3.js.map +1 -1
  62. package/dist/esm/packages/taco/src/components/Table3/util/editing.js +11 -23
  63. package/dist/esm/packages/taco/src/components/Table3/util/editing.js.map +1 -1
  64. package/dist/esm/packages/taco/src/primitives/Collection/components/Root.js +18 -0
  65. package/dist/esm/packages/taco/src/primitives/Collection/components/Root.js.map +1 -1
  66. package/dist/esm/packages/taco/src/primitives/Listbox2/components/Option.js +0 -5
  67. package/dist/esm/packages/taco/src/primitives/Listbox2/components/Option.js.map +1 -1
  68. package/dist/esm/packages/taco/src/primitives/Listbox2/components/Root.js +1 -0
  69. package/dist/esm/packages/taco/src/primitives/Listbox2/components/Root.js.map +1 -1
  70. package/dist/esm/packages/taco/src/primitives/Table/Core/Table.js +6 -4
  71. package/dist/esm/packages/taco/src/primitives/Table/Core/Table.js.map +1 -1
  72. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.js +30 -17
  73. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.js.map +1 -1
  74. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Internal/Actions.js +10 -7
  75. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Internal/Actions.js.map +1 -1
  76. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Footer/Footer.js.map +1 -1
  77. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/BuiltIns/DisplayRow.js +6 -3
  78. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/BuiltIns/DisplayRow.js.map +1 -1
  79. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/Row.js +4 -2
  80. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/Row.js.map +1 -1
  81. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/RowContext.js +2 -1
  82. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/RowContext.js.map +1 -1
  83. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Toolbar/components/Filters/components/FilterValue.js +8 -1
  84. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Toolbar/components/Filters/components/FilterValue.js.map +1 -1
  85. package/dist/esm/packages/taco/src/primitives/Table/Core/features/useTableRenderer.js +29 -7
  86. package/dist/esm/packages/taco/src/primitives/Table/Core/features/useTableRenderer.js.map +1 -1
  87. package/dist/esm/packages/taco/src/primitives/Table/Core/useTable.js +2 -2
  88. package/dist/esm/packages/taco/src/primitives/Table/Core/useTable.js.map +1 -1
  89. package/dist/esm/packages/taco/src/primitives/Table/types.js.map +1 -1
  90. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/features/useTableRowSelection.js +2 -1
  91. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/features/useTableRowSelection.js.map +1 -1
  92. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/useTableManager.js +1 -1
  93. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/useTableManager.js.map +1 -1
  94. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/util/setup.js +11 -0
  95. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/util/setup.js.map +1 -1
  96. package/dist/esm/packages/taco/src/utils/dom.js +20 -10
  97. package/dist/esm/packages/taco/src/utils/dom.js.map +1 -1
  98. package/dist/index.css +35 -4
  99. package/dist/primitives/Collection/components/Root.d.ts +2 -0
  100. package/dist/primitives/Table/Core/components/Body/util.d.ts +4 -4
  101. package/dist/primitives/Table/Core/components/Columns/Internal/Actions.d.ts +3 -1
  102. package/dist/primitives/Table/Core/components/Footer/Footer.d.ts +1 -1
  103. package/dist/primitives/Table/Core/components/Row/RowContext.d.ts +1 -0
  104. package/dist/primitives/Table/Core/features/useTableRenderer.d.ts +2 -2
  105. package/dist/primitives/Table/Core/features/useTableStyle.d.ts +3 -3
  106. package/dist/primitives/Table/Core/types.d.ts +4 -0
  107. package/dist/primitives/Table/Core/useTable.d.ts +2 -2
  108. package/dist/primitives/Table/types.d.ts +2 -2
  109. package/dist/primitives/Table/useTableManager/useTableManager.d.ts +1 -1
  110. package/dist/taco.cjs.development.js +1119 -743
  111. package/dist/taco.cjs.development.js.map +1 -1
  112. package/dist/taco.cjs.production.min.js +1 -1
  113. package/dist/taco.cjs.production.min.js.map +1 -1
  114. package/dist/utils/dom.d.ts +2 -1
  115. package/package.json +17 -17
  116. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateRowButton.js +0 -90
  117. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateRowButton.js.map +0 -1
@@ -43,7 +43,8 @@ var set = _interopDefault(require('lodash/set'));
43
43
  var unset = _interopDefault(require('lodash/unset'));
44
44
  var compact = _interopDefault(require('lodash/compact'));
45
45
  var pullAt = _interopDefault(require('lodash/pullAt'));
46
- var lodash = require('lodash');
46
+ var omit = _interopDefault(require('lodash/omit'));
47
+ var setWith = _interopDefault(require('lodash/setWith'));
47
48
  var TabsPrimitive = require('@radix-ui/react-tabs');
48
49
  var Joyride = require('react-joyride');
49
50
  var Joyride__default = _interopDefault(Joyride);
@@ -4169,7 +4170,7 @@ const useMergedRef = ref => {
4169
4170
  };
4170
4171
 
4171
4172
  // taken from react-aria
4172
- const FOCUSABLE_ELEMENTS = ['input:not([disabled]):not([type=hidden])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'a[href]', 'area[href]', 'summary', 'iframe', 'object', 'embed', 'audio[controls]', 'video[controls]', '[contenteditable]', '[tabindex]:not([tabindex="-1"]):not([disabled])', 'details:not([disabled])', 'summary:not(:disabled)'];
4173
+ const FOCUSABLE_ELEMENTS = ['[tabindex]:not([disabled])', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'a[href]', 'area[href]', 'summary', 'iframe', 'object', 'embed', 'audio[controls]', 'video[controls]', '[contenteditable]', 'details:not([disabled])', 'summary:not(:disabled)'];
4173
4174
  const hasFocusableElement = element => {
4174
4175
  if (!element) {
4175
4176
  return null;
@@ -4195,13 +4196,20 @@ const getNextFocussableElement = currentElement => {
4195
4196
  if (!currentElement) {
4196
4197
  return null;
4197
4198
  }
4198
- const focussableElements = [...document.querySelectorAll(FOCUSABLE_ELEMENTS.join(','))];
4199
+ let focussableElements = [...document.querySelectorAll(FOCUSABLE_ELEMENTS.join(','))];
4199
4200
  const currentElementIndex = focussableElements.indexOf(currentElement);
4200
- // If the currentElement is not in the focussable elements list or it is the last element
4201
- if (currentElementIndex !== -1 && currentElementIndex === focussableElements.length - 1) {
4202
- return null;
4201
+ if (currentElementIndex > -1) {
4202
+ focussableElements = focussableElements.slice(currentElementIndex + 1).filter(element => element.getAttribute('tabindex') !== '-1');
4203
+ if (focussableElements.length) {
4204
+ var _focussableElements$;
4205
+ focussableElements = focussableElements.filter(element => {
4206
+ var _element$checkVisibil, _element$checkVisibil2;
4207
+ return (_element$checkVisibil = (_element$checkVisibil2 = element.checkVisibility) === null || _element$checkVisibil2 === void 0 ? void 0 : _element$checkVisibil2.call(element)) !== null && _element$checkVisibil !== void 0 ? _element$checkVisibil : true;
4208
+ });
4209
+ return (_focussableElements$ = focussableElements[0]) !== null && _focussableElements$ !== void 0 ? _focussableElements$ : null;
4210
+ }
4203
4211
  }
4204
- return focussableElements[currentElementIndex + 1];
4212
+ return null;
4205
4213
  };
4206
4214
  const getOverlaySelector = element => {
4207
4215
  switch (element === null || element === void 0 ? void 0 : element.getAttribute('role')) {
@@ -4213,7 +4221,7 @@ const getOverlaySelector = element => {
4213
4221
  return undefined;
4214
4222
  }
4215
4223
  };
4216
- function isElementInsideOrTriggeredFromContainer(element, container) {
4224
+ function isElementTriggeredFromContainer(element, container) {
4217
4225
  var _getOverlaySelector, _element$closest;
4218
4226
  const selector = (_getOverlaySelector = getOverlaySelector(element)) !== null && _getOverlaySelector !== void 0 ? _getOverlaySelector : getOverlaySelector((_element$closest = element === null || element === void 0 ? void 0 : element.closest('[role=dialog],[role=menu]')) !== null && _element$closest !== void 0 ? _element$closest : null);
4219
4227
  if (selector) {
@@ -4224,11 +4232,14 @@ function isElementInsideOrTriggeredFromContainer(element, container) {
4224
4232
  const elementInDocument = document.querySelector(escapedSelector);
4225
4233
  // if the element does exist, see if it is itself connected to somethng that was triggered from the container
4226
4234
  if (elementInDocument) {
4227
- return isElementInsideOrTriggeredFromContainer(elementInDocument, container);
4235
+ return isElementTriggeredFromContainer(elementInDocument, container);
4228
4236
  }
4229
4237
  return false;
4230
4238
  }
4231
- return !!(container !== null && container !== void 0 && container.contains(element));
4239
+ return false;
4240
+ }
4241
+ function isElementInsideOrTriggeredFromContainer(element, container) {
4242
+ return isElementTriggeredFromContainer(element, container) || !!(container !== null && container !== void 0 && container.contains(element));
4232
4243
  }
4233
4244
  function isElementInsideOverlay(element) {
4234
4245
  return !!(element !== null && element !== void 0 && element.closest('[role=dialog],[role=menu]'));
@@ -4374,7 +4385,7 @@ const Tooltip = /*#__PURE__*/React.forwardRef(function Tooltip(props, ref) {
4374
4385
  });
4375
4386
 
4376
4387
  const getButtonClasses = () => {
4377
- return 'flex-shrink-0 min-h-[theme(spacing.8)] min-w-[theme(spacing.8)] gap-1 h-max leading-5 inline-flex items-center justify-center focus-visible:yt-focus aria-disabled:cursor-not-allowed';
4388
+ return 'flex-shrink-0 min-h-[theme(spacing.8)] min-w-[theme(spacing.8)] gap-1 h-max leading-5 inline-flex items-center justify-center focus-visible:yt-focus data-[state=instant-open]:yt-focus aria-disabled:cursor-not-allowed';
4378
4389
  };
4379
4390
  const getAppearanceClasses = (value, icon = false) => {
4380
4391
  switch (value) {
@@ -4722,7 +4733,9 @@ const defaultLocalisationTexts = {
4722
4733
  tooltip: 'Edit table'
4723
4734
  },
4724
4735
  create: {
4725
- label: 'New'
4736
+ label: 'New',
4737
+ disabled: 'Existing new row must be saved',
4738
+ saving: 'Saving...'
4726
4739
  }
4727
4740
  },
4728
4741
  clearChangesConfirmationDialog: {
@@ -4744,8 +4757,8 @@ const defaultLocalisationTexts = {
4744
4757
  },
4745
4758
  validation: {
4746
4759
  alert: {
4747
- titleOne: '[COUNT] unsaved entry:',
4748
- titlePlural: '[COUNT] unsaved entries:',
4760
+ titleOne: '[COUNT] unsaved row:',
4761
+ titlePlural: '[COUNT] unsaved rows:',
4749
4762
  messageOne: "[COLUMN] [ROW] is incomplete and hasn't been saved.",
4750
4763
  messagePlural: "[COLUMN] [ROW] are incomplete and haven't been saved.",
4751
4764
  messageRow: 'Row',
@@ -7647,7 +7660,7 @@ const Switch = /*#__PURE__*/React.forwardRef(function Switch(props, ref) {
7647
7660
  onCheckedChange: onChange,
7648
7661
  ref: ref
7649
7662
  }), /*#__PURE__*/React.createElement(PrimitiveSwitch.Thumb, {
7650
- className: "'will-change-transform mt-0.5 h-4 w-4 translate-x-[0.15rem] rounded-full bg-white transition-transform group-disabled:opacity-50 group-aria-checked:translate-x-[1.1rem]"
7663
+ className: "pointer-events-none mt-0.5 h-4 w-4 translate-x-[0.15rem] rounded-full bg-white transition-transform will-change-transform group-disabled:opacity-50 group-aria-checked:translate-x-[1.1rem]"
7651
7664
  }));
7652
7665
  if (label) {
7653
7666
  const labelContainerClassName = cn('flex self-start cursor-pointer', {
@@ -8707,10 +8720,10 @@ const ModeSwitch = /*#__PURE__*/React.forwardRef(function ModeSwitch(props, ref)
8707
8720
  onCheckedChange: onChange,
8708
8721
  ref: ref
8709
8722
  }), /*#__PURE__*/React.createElement(PrimitiveSwitch.Thumb, {
8710
- className: "'will-change-transform flex h-6 w-6 items-center justify-center rounded-full bg-white transition-transform group-disabled:opacity-50 group-aria-checked:translate-x-[100%]"
8723
+ className: "pointer-events-none flex h-6 w-6 items-center justify-center rounded-full bg-white transition-transform will-change-transform group-disabled:opacity-50 group-aria-checked:translate-x-[100%]"
8711
8724
  }, /*#__PURE__*/React.createElement(Icon, {
8712
8725
  name: "edit-simple",
8713
- className: "!h-5 !w-5"
8726
+ className: "pointer-events-none !h-5 !w-5"
8714
8727
  })));
8715
8728
  });
8716
8729
  ModeSwitch.displayName = 'ModeSwitch';
@@ -10413,6 +10426,15 @@ function configureReactTableOptions(options, props, localization) {
10413
10426
  // We don't want to expose internal Tanstack Table row, so we need to wrap enableRowSelection callback into additional function,
10414
10427
  // which receives the React Table Row object and passes row.original to a callback.
10415
10428
  const reactTableEnableRowSelection = typeof options.enableRowSelection === 'function' ? row => options.enableRowSelection(row.original) : options.enableRowSelection;
10429
+ let getRowId;
10430
+ if (props.rowIdentityAccessor) {
10431
+ getRowId = (originalRow, index) => {
10432
+ if (originalRow) {
10433
+ return String(originalRow[props.rowIdentityAccessor]);
10434
+ }
10435
+ return String(index);
10436
+ };
10437
+ }
10416
10438
  const tableOptions = {
10417
10439
  defaultColumn: {
10418
10440
  enableColumnFilter: options.enableFiltering || true,
@@ -10431,11 +10453,13 @@ function configureReactTableOptions(options, props, localization) {
10431
10453
  enableGrouping: true,
10432
10454
  enableHiding: (_options$enableColumn2 = options.enableColumnHiding) !== null && _options$enableColumn2 !== void 0 ? _options$enableColumn2 : false,
10433
10455
  enablePinning: (_options$enableColumn3 = options.enableColumnFreezing) !== null && _options$enableColumn3 !== void 0 ? _options$enableColumn3 : false,
10456
+ enableRowPinning: true,
10434
10457
  enableRowSelection: reactTableEnableRowSelection !== null && reactTableEnableRowSelection !== void 0 ? reactTableEnableRowSelection : false,
10435
10458
  enableSorting: (_options$enableSortin = options.enableSorting) !== null && _options$enableSortin !== void 0 ? _options$enableSortin : false,
10436
10459
  // models for default features
10437
10460
  getExpandedRowModel: reactTable.getExpandedRowModel(),
10438
10461
  getGroupedRowModel: reactTable.getGroupedRowModel(),
10462
+ getRowId,
10439
10463
  groupedColumnMode: false
10440
10464
  };
10441
10465
  if (tableOptions.enableColumnResizing) {
@@ -10917,6 +10941,7 @@ function useTableRowHeight(isEnabled = false, defaultRowHeight = 'medium') {
10917
10941
  function useTableRowSelection(isEnabled = false) {
10918
10942
  const lastSelectedRowIndex = React__default.useRef();
10919
10943
  const onKeyDown = React__default.useCallback((event, table) => {
10944
+ var _event$target;
10920
10945
  if (!isEnabled || !table.options.enableRowSelection || event.defaultPrevented) {
10921
10946
  return;
10922
10947
  }
@@ -10931,7 +10956,7 @@ function useTableRowSelection(isEnabled = false) {
10931
10956
  (_rows$rowActiveIndex2 = rows[rowActiveIndex]) === null || _rows$rowActiveIndex2 === void 0 ? void 0 : _rows$rowActiveIndex2.toggleSelected();
10932
10957
  }
10933
10958
  return;
10934
- } else if ((event.ctrlKey || event.metaKey) && event.key === 'a') {
10959
+ } else if ((event.ctrlKey || event.metaKey) && event.key === 'a' && !['INPUT', 'TEXTAREA'].includes((_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.tagName)) {
10935
10960
  event.preventDefault();
10936
10961
  table.toggleAllRowsSelected();
10937
10962
  return;
@@ -11768,7 +11793,7 @@ function useTableManager(props, meta, internalColumns) {
11768
11793
  rowDrag,
11769
11794
  rowDrop: rowDrop,
11770
11795
  rowExpansion: rowExpansion,
11771
- rowIdentityColumnId: props.rowIdentityColumnId,
11796
+ rowIdentityAccessor: props.rowIdentityAccessor,
11772
11797
  rowGoto,
11773
11798
  rowGroups: rowGroups,
11774
11799
  rowHeight,
@@ -12106,7 +12131,8 @@ const Skeleton = /*#__PURE__*/React__default.forwardRef(function Skeleton(props,
12106
12131
 
12107
12132
  const RowContext = /*#__PURE__*/React__default.createContext({
12108
12133
  isHovered: false,
12109
- rowIndex: -1
12134
+ rowIndex: -1,
12135
+ hideRowActions: false
12110
12136
  });
12111
12137
 
12112
12138
  /* anonymous functions will break the memoisation on each render, wrap handlers in callbacks */
@@ -12114,6 +12140,7 @@ function Row(props) {
12114
12140
  const {
12115
12141
  renderer: RowRenderer,
12116
12142
  cellRenderer: CellRenderer,
12143
+ hideRowActions = false,
12117
12144
  ...displayRowProps
12118
12145
  } = props;
12119
12146
  const tableMeta = props.table.options.meta;
@@ -12121,8 +12148,9 @@ function Row(props) {
12121
12148
  // context - it must be here for cells to read it, since they render alongside the row inside DisplayRow
12122
12149
  const contextValue = React__default.useMemo(() => ({
12123
12150
  isHovered,
12124
- rowIndex: props.index
12125
- }), [isHovered, props.index]);
12151
+ rowIndex: props.index,
12152
+ hideRowActions
12153
+ }), [isHovered, props.index, hideRowActions]);
12126
12154
  if (props.row.original === undefined) {
12127
12155
  return /*#__PURE__*/React__default.createElement(SkeletonRow, Object.assign({}, props));
12128
12156
  }
@@ -12133,11 +12161,35 @@ function Row(props) {
12133
12161
  })));
12134
12162
  }
12135
12163
 
12136
- function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12137
- var _table$getState$group, _virtualItems$padding, _virtualItems$padding2, _virtualItems$padding3, _ref, _virtualItems;
12164
+ // scroll padding end is designed to always show half of the next row
12165
+ function getScrollPaddingEndOffset(table) {
12166
+ const tableMeta = table.options.meta;
12167
+ let offset = 2;
12168
+ if (tableMeta.footer.isEnabled) {
12169
+ offset += 1;
12170
+ }
12171
+ if (table.getHeaderGroups().length > 1) {
12172
+ offset += table.getHeaderGroups().length - 1;
12173
+ }
12174
+ let height = ROW_HEIGHT_ESTIMATES.medium * offset;
12175
+ const bottomRows = table.getBottomRows();
12176
+ if (bottomRows.length) {
12177
+ // 1.4 offsets for half rows and also accounts for increased row heights (which is likely in pinned rows)
12178
+ height += ROW_HEIGHT_ESTIMATES[tableMeta.rowHeight.height] * 1.4 * bottomRows.length;
12179
+ }
12180
+ return height;
12181
+ }
12182
+ // scroll padding end is designed to always show half of the next row
12183
+ function getPaddingEndOffset(table, options) {
12184
+ var _table$getBottomRows, _options$virtualiserP;
12185
+ const bottomRows = (_table$getBottomRows = table.getBottomRows()) !== null && _table$getBottomRows !== void 0 ? _table$getBottomRows : [];
12186
+ return ROW_HEIGHT_ESTIMATES.medium * ((_options$virtualiserP = options === null || options === void 0 ? void 0 : options.virtualiserPaddingEndOffset) !== null && _options$virtualiserP !== void 0 ? _options$virtualiserP : 1) * bottomRows.length;
12187
+ }
12188
+ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex, options) {
12189
+ var _table$getState$group, _table$getCenterRows, _virtualItems$padding, _virtualItems$padding2, _virtualItems$padding3, _ref, _virtualItems;
12138
12190
  const tableMeta = table.options.meta;
12139
- const rows = table.getRowModel().rows;
12140
12191
  const isTableRowGrouped = !!((_table$getState$group = table.getState().grouping) !== null && _table$getState$group !== void 0 && _table$getState$group.length);
12192
+ const rows = (_table$getCenterRows = table.getCenterRows()) !== null && _table$getCenterRows !== void 0 ? _table$getCenterRows : [];
12141
12193
  // expanded rows
12142
12194
  const {
12143
12195
  createRowMeasurer,
@@ -12147,9 +12199,6 @@ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12147
12199
  const rangeExtractor = useRowGroupVirtualisation(table);
12148
12200
  // account for thead and tfoot in the scroll area - both are always medium row height
12149
12201
  const scrollPaddingStart = ROW_HEIGHT_ESTIMATES.medium;
12150
- // column groups offset the bottom padding :shrug:, multiplying by 1.5 ensures the bottom padding remains
12151
- // consistent when there are groups and when there aren't. 1.5 is relatively arbitrary, but it gives alignment
12152
- const scrollPaddingEnd = ROW_HEIGHT_ESTIMATES.medium * (table.getHeaderGroups().length > 1 ? 1.5 : 1);
12153
12202
  const virtualiser = reactVirtual.useVirtualizer({
12154
12203
  count: rows.length,
12155
12204
  estimateSize,
@@ -12158,7 +12207,8 @@ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12158
12207
  rangeExtractor,
12159
12208
  // correctly sets the scroll padding offset, e.g. when keyboard navigating rows in the list
12160
12209
  scrollPaddingStart,
12161
- scrollPaddingEnd: tableMeta.footer.isEnabled ? scrollPaddingEnd * 2 : scrollPaddingEnd
12210
+ scrollPaddingEnd: getScrollPaddingEndOffset(table),
12211
+ paddingEnd: getPaddingEndOffset(table, options)
12162
12212
  });
12163
12213
  const totalSize = virtualiser.getTotalSize();
12164
12214
  const virtualItems = virtualiser.getVirtualItems();
@@ -12315,12 +12365,14 @@ function Actions$1(props) {
12315
12365
  actionsLength,
12316
12366
  data,
12317
12367
  isActiveRow,
12318
- rowId
12368
+ rowId,
12369
+ table
12319
12370
  } = props;
12320
12371
  const {
12321
12372
  texts
12322
12373
  } = useLocalization();
12323
- const visibleActions = actions.map(action => action(data, rowId)).filter(action => !!action);
12374
+ // we don't want to document passing table, so it isn't on the type
12375
+ const visibleActions = actions.map(action => action(data, rowId, table)).filter(action => !!action);
12324
12376
  const actionsOnRow = visibleActions.length === actionsLength ? visibleActions : visibleActions.slice(0, actionsLength - 1);
12325
12377
  const actionsInMenu = visibleActions.slice(visibleActions.length === actionsLength ? actionsLength : actionsLength - 1);
12326
12378
  const className = cn('flex justify-end text-right bg-[inherit] shadow-[-6px_0px_6px_var(--table-row-actions-shadow)] print:hidden');
@@ -12360,7 +12412,8 @@ const Cell = /*#__PURE__*/React__default.memo(function MemoedCell(context) {
12360
12412
  } = context;
12361
12413
  const {
12362
12414
  isHovered,
12363
- rowIndex
12415
+ rowIndex,
12416
+ hideRowActions
12364
12417
  } = React__default.useContext(RowContext);
12365
12418
  const tableMeta = table.options.meta;
12366
12419
  const actions = tableMeta.rowActions.rowActions;
@@ -12368,15 +12421,15 @@ const Cell = /*#__PURE__*/React__default.memo(function MemoedCell(context) {
12368
12421
  const isActiveRow = tableMeta.rowActive.rowActiveIndex === rowIndex;
12369
12422
  const isResizingColumn = !!table.getState().columnSizingInfo.isResizingColumn;
12370
12423
  const isHoverStatePaused = tableMeta.rowActive.isHoverStatePaused;
12371
- // We don't want to show actions in edit mode, since we have editing actions,
12372
- // which is shown in edit mode instead.
12373
- if (actions !== null && actions !== void 0 && actions.length && (isActiveRow || isHovered && !isHoverStatePaused && !isResizingColumn)) {
12424
+ const isRowGrouped = row.getIsGrouped();
12425
+ if (!hideRowActions && !isRowGrouped && actions !== null && actions !== void 0 && actions.length && (isActiveRow || isHovered && !isHoverStatePaused && !isResizingColumn)) {
12374
12426
  return /*#__PURE__*/React__default.createElement(Actions$1, {
12375
12427
  actions: actions,
12376
12428
  actionsLength: actionsLength,
12377
12429
  data: row.original,
12378
12430
  isActiveRow: isActiveRow,
12379
- rowId: row.id
12431
+ rowId: row.id,
12432
+ table: table
12380
12433
  });
12381
12434
  }
12382
12435
  return null;
@@ -12626,13 +12679,13 @@ const INTERNAL_RENDERERS = {
12626
12679
  rowExpansion: renderer$2,
12627
12680
  rowSelection: renderer$3
12628
12681
  };
12629
- function useTable(props, externalRef, renderers, meta) {
12682
+ function useTable(props, externalRef, renderers, meta, options) {
12630
12683
  // create a ref and merge with the consumer's ref
12631
12684
  const ref = useMergedRef(externalRef);
12632
12685
  // configure the table
12633
12686
  const manager = useTableManager(props, meta, INTERNAL_RENDERERS);
12634
12687
  // configure the virtualised renderer
12635
- const renderer = useTableRenderer(renderers, manager.instance, ref, props.defaultRowActiveIndex);
12688
+ const renderer = useTableRenderer(renderers, manager.instance, ref, props.defaultRowActiveIndex, options);
12636
12689
  // configure dynamic styling
12637
12690
  const {
12638
12691
  style,
@@ -12733,7 +12786,10 @@ function GroupedCell(props) {
12733
12786
  index,
12734
12787
  isHighlighted
12735
12788
  } = props;
12736
- const tableMeta = cell.getContext().table.options.meta;
12789
+ const {
12790
+ table
12791
+ } = cell.getContext();
12792
+ const tableMeta = table.options.meta;
12737
12793
  const columnMeta = cell.column.columnDef.meta;
12738
12794
  const attributes = getCellAttributes(cell, index, isHighlighted);
12739
12795
  const {
@@ -12742,7 +12798,9 @@ function GroupedCell(props) {
12742
12798
  } = React__default.useContext(RowContext);
12743
12799
  const isActiveRow = tableMeta.rowActive.rowActiveIndex === rowIndex;
12744
12800
  const canShowActions = isActiveRow || isHovered && !tableMeta.rowActive.isHoverStatePaused;
12745
- const colSpan = cell.row.getVisibleCells().filter(c => !isInternalColumn(c.column.id)).length - 1;
12801
+ // Set colSpan based on the count of visible cells, including '__actions' and non-internal columns, so that
12802
+ // rowGroupActions aligns with rowActions.
12803
+ const colSpan = cell.row.getVisibleCells().filter(c => c.column.id === '__actions' || !isInternalColumn(c.column.id)).length - 1;
12746
12804
  const content = (_ref = (_columnMeta$renderer = (_columnMeta$renderer2 = columnMeta.renderer) === null || _columnMeta$renderer2 === void 0 ? void 0 : _columnMeta$renderer2.call(columnMeta, cell.getValue(), cell.row.original)) !== null && _columnMeta$renderer !== void 0 ? _columnMeta$renderer : cell.getValue()) !== null && _ref !== void 0 ? _ref : null;
12747
12805
  const subRows = cell.getContext().row.subRows.map(row => row.original);
12748
12806
  return /*#__PURE__*/React__default.createElement(MemoedGroupedCell, Object.assign({}, attributes, {
@@ -12751,7 +12809,8 @@ function GroupedCell(props) {
12751
12809
  colSpan: colSpan,
12752
12810
  rowActions: tableMeta.rowGroups.rowActionsForGroup,
12753
12811
  rowId: cell.row.id,
12754
- subRows: subRows
12812
+ subRows: subRows,
12813
+ table: table
12755
12814
  }), content);
12756
12815
  }
12757
12816
  const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupedCell(props) {
@@ -12763,22 +12822,29 @@ const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupe
12763
12822
  rowActions,
12764
12823
  rowId,
12765
12824
  subRows,
12825
+ table,
12766
12826
  ...attributes
12767
12827
  } = props;
12768
- return /*#__PURE__*/React__default.createElement("td", Object.assign({}, attributes, {
12769
- ref: cellRef,
12770
- style: {
12771
- gridColumn: `span ${colSpan} / span ${colSpan}`
12772
- }
12773
- }), /*#__PURE__*/React__default.createElement("span", {
12774
- className: "grow"
12775
- }, children), rowActions !== null && rowActions !== void 0 && rowActions.length && canShowActions ? (/*#__PURE__*/React__default.createElement(Actions$1, {
12776
- actions: rowActions,
12777
- actionsLength: 4,
12778
- data: subRows,
12779
- isActiveRow: true,
12780
- rowId: rowId
12781
- })) : null);
12828
+ return (
12829
+ /*#__PURE__*/
12830
+ // pr-1 is needed to align group row actions with row actions in sibling rows, if present
12831
+ React__default.createElement("td", Object.assign({}, attributes, {
12832
+ className: "!pr-1",
12833
+ ref: cellRef,
12834
+ style: {
12835
+ gridColumn: `span ${colSpan} / span ${colSpan}`
12836
+ }
12837
+ }), /*#__PURE__*/React__default.createElement("span", {
12838
+ className: "grow"
12839
+ }, children), rowActions !== null && rowActions !== void 0 && rowActions.length && canShowActions ? (/*#__PURE__*/React__default.createElement(Actions$1, {
12840
+ actions: rowActions,
12841
+ actionsLength: 4,
12842
+ data: subRows,
12843
+ isActiveRow: true,
12844
+ rowId: rowId,
12845
+ table: table
12846
+ })) : null)
12847
+ );
12782
12848
  });
12783
12849
 
12784
12850
  function Cell$4(props) {
@@ -12839,7 +12905,7 @@ const DisplayRow = /*#__PURE__*/React__default.memo(function DisplayRow(props) {
12839
12905
  if (tableMeta.rowActive.isEnabled) {
12840
12906
  attributes['data-row-active'] = tableMeta.rowActive.rowActiveIndex === index ? true : undefined;
12841
12907
  // we use capture because it let's us picks up clicks on components inside the row, e.g. checkboxes
12842
- attributes.onClickCapture = handleClickCapture;
12908
+ attributes.onPointerDown = handleClickCapture;
12843
12909
  }
12844
12910
  // row click
12845
12911
  if (tableMeta.rowClick.isEnabled(row.original)) {
@@ -12917,14 +12983,17 @@ const DisplayRow = /*#__PURE__*/React__default.memo(function DisplayRow(props) {
12917
12983
  const expansionRef = React__default.useRef(null);
12918
12984
  const isExpanded = !!attributes['data-row-expanded'];
12919
12985
  useSetVirtualisedRowHeight(measureRow, ref.current, expansionRef.current, isExpanded);
12920
- const className = cn('group/row', {
12986
+ const className = cn('group/row', otherAttributes.className, {
12921
12987
  'hover:cursor-grab': tableMeta.rowDrag.isEnabled && typeof attributes.onClick !== 'function',
12922
12988
  'hover:cursor-pointer': typeof attributes.onClick === 'function'
12923
12989
  });
12990
+ const isGrouped = row.getIsGrouped();
12924
12991
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("tr", Object.assign({}, attributes, {
12925
12992
  className: className,
12926
12993
  ref: ref
12927
- }), children, row.getVisibleCells().map((cell, cellIndex) => (/*#__PURE__*/React__default.createElement(Cell$4, {
12994
+ }), children, row.getVisibleCells()
12995
+ // Filter out the row actions cell from rendering in Grouped Row
12996
+ .filter(cell => !(isGrouped && cell.column.id === '__actions')).map((cell, cellIndex) => (/*#__PURE__*/React__default.createElement(Cell$4, {
12928
12997
  key: cell.id,
12929
12998
  cell: cell,
12930
12999
  index: cellIndex,
@@ -14401,6 +14470,7 @@ const getOptionsFromCollection = (collection, selector) => collection.querySelec
14401
14470
  const Root = /*#__PURE__*/React__default.forwardRef(function CollectionRoot(props, ref) {
14402
14471
  const {
14403
14472
  querySelector,
14473
+ resetOnChange,
14404
14474
  tabIndex = 0,
14405
14475
  ...otherProps
14406
14476
  } = props;
@@ -14431,14 +14501,31 @@ const Root = /*#__PURE__*/React__default.forwardRef(function CollectionRoot(prop
14431
14501
  internalRef.current.setActiveIndexByElement = setActiveIndexByElement;
14432
14502
  }
14433
14503
  }, [internalRef.current]);
14504
+ React__default.useEffect(() => {
14505
+ if (internalRef.current) {
14506
+ const selected = internalRef.current.querySelectorAll(`[aria-current="true"]`);
14507
+ const options = getOptionsFromCollection(internalRef.current, querySelector);
14508
+ if (options.length && selected.length === 1) {
14509
+ const firstSelected = internalRef.current.querySelector(`[aria-selected]`);
14510
+ if (firstSelected) {
14511
+ const selectedIndex = Array.from(options).indexOf(firstSelected);
14512
+ if (selectedIndex > -1) {
14513
+ setActiveOption(selectedIndex, internalRef.current, firstSelected);
14514
+ }
14515
+ }
14516
+ }
14517
+ }
14518
+ }, [resetOnChange]);
14434
14519
  React__default.useEffect(() => {
14435
14520
  if (internalRef.current) {
14436
14521
  const options = getOptionsFromCollection(internalRef.current, querySelector);
14437
14522
  if (options.length) {
14438
14523
  let selected = internalRef.current.querySelectorAll(`[aria-current="true"]`);
14524
+ // if nothing is current (keyboard visible), look for selected items
14439
14525
  if (selected.length === 0) {
14440
14526
  selected = internalRef.current.querySelectorAll(`[aria-selected]`);
14441
14527
  }
14528
+ // if one item is selected, make sure it's current
14442
14529
  if (selected.length === 1) {
14443
14530
  if (options) {
14444
14531
  const firstSelected = selected.item(0);
@@ -14584,6 +14671,7 @@ const Root$1 = /*#__PURE__*/React__default.forwardRef(function Listbox2(props, r
14584
14671
  id: id,
14585
14672
  querySelector: customSelector ? `${DEFAULT_SELECTOR}, ${customSelector}` : DEFAULT_SELECTOR,
14586
14673
  ref: ref,
14674
+ resetOnChange: value,
14587
14675
  role: "listbox"
14588
14676
  }), children)));
14589
14677
  });
@@ -14642,10 +14730,6 @@ const Option = /*#__PURE__*/React__default.forwardRef(function Listbox2Option(pr
14642
14730
  if (disabled || listboxDisabled || listboxReadOnly) {
14643
14731
  event.stopPropagation();
14644
14732
  return;
14645
- }
14646
- // UX requirement: if tab key is pressed and the current option is selected then keydown event is ignored
14647
- else if (event.key === 'Tab' && selected) {
14648
- return;
14649
14733
  } else if (isAriaSelectionKey(event)) {
14650
14734
  setValue(value);
14651
14735
  }
@@ -14656,7 +14740,6 @@ const Option = /*#__PURE__*/React__default.forwardRef(function Listbox2Option(pr
14656
14740
  return /*#__PURE__*/React__default.createElement("div", Object.assign({}, otherProps, {
14657
14741
  "aria-disabled": listboxDisabled || disabled ? 'true' : undefined,
14658
14742
  "aria-selected": selected ? 'true' : undefined,
14659
- key: `${value}_${String(selected)}`,
14660
14743
  id: id,
14661
14744
  onClick: handleClick,
14662
14745
  onKeyDown: handleKeyDown,
@@ -15099,7 +15182,9 @@ const Button$3 = /*#__PURE__*/React__default.forwardRef(function Select2TriggerB
15099
15182
  var _props$className;
15100
15183
  const {
15101
15184
  children,
15185
+ onBlur,
15102
15186
  onClick,
15187
+ onFocus,
15103
15188
  tabIndex = 0,
15104
15189
  ...otherProps
15105
15190
  } = props;
@@ -15130,6 +15215,18 @@ const Button$3 = /*#__PURE__*/React__default.forwardRef(function Select2TriggerB
15130
15215
  onClick(event);
15131
15216
  }
15132
15217
  };
15218
+ let handleBlur;
15219
+ if (typeof onBlur === 'function') {
15220
+ // we might be focusing on an input or something inside the dropdown that was triggered by the select
15221
+ // so see if the element gaining focus is inside a portal and look up its controller
15222
+ // if we don't do this, things like validate on blur occur while simply opening the select
15223
+ handleBlur = event => {
15224
+ if (isElementInsideOrTriggeredFromContainer(event.relatedTarget, event.currentTarget)) {
15225
+ return;
15226
+ }
15227
+ onBlur(event);
15228
+ };
15229
+ }
15133
15230
  // select the value text if the select is readonly
15134
15231
  const handleFocus = event => {
15135
15232
  if (readOnly) {
@@ -15139,6 +15236,9 @@ const Button$3 = /*#__PURE__*/React__default.forwardRef(function Select2TriggerB
15139
15236
  (_window$getSelection = window.getSelection()) === null || _window$getSelection === void 0 ? void 0 : (_window$getSelection$ = _window$getSelection.selectAllChildren) === null || _window$getSelection$ === void 0 ? void 0 : _window$getSelection$.call(_window$getSelection, value);
15140
15237
  }
15141
15238
  }
15239
+ if (typeof onFocus === 'function') {
15240
+ onFocus(event);
15241
+ }
15142
15242
  };
15143
15243
  return /*#__PURE__*/React__default.createElement("button", Object.assign({}, otherProps, {
15144
15244
  "aria-invalid": invalid ? true : undefined,
@@ -15146,6 +15246,7 @@ const Button$3 = /*#__PURE__*/React__default.forwardRef(function Select2TriggerB
15146
15246
  className: className,
15147
15247
  disabled: disabled,
15148
15248
  onClick: handleClick,
15249
+ onBlur: handleBlur,
15149
15250
  onFocus: handleFocus,
15150
15251
  ref: ref,
15151
15252
  role: "combobox",
@@ -15408,17 +15509,12 @@ const BubbleSelect = props => {
15408
15509
  };
15409
15510
 
15410
15511
  const Search$2 = /*#__PURE__*/React__default.forwardRef(function ListboxSearch(props, ref) {
15411
- const {
15412
- onTabKeyPress,
15413
- ...otherProps
15414
- } = props;
15415
15512
  const {
15416
15513
  listboxRef,
15417
15514
  searchQuery,
15418
15515
  setSearchQuery,
15419
15516
  setValidationError,
15420
- validationError,
15421
- setOpen
15517
+ validationError
15422
15518
  } = useSelect2Context();
15423
15519
  const handleChange = event => {
15424
15520
  if (validationError) {
@@ -15431,11 +15527,6 @@ const Search$2 = /*#__PURE__*/React__default.forwardRef(function ListboxSearch(p
15431
15527
  if (event.key === ' ') {
15432
15528
  return;
15433
15529
  }
15434
- // Select2 should close dropdown and receive focus, when user press Tab while searching (UX requirement to support better keyboard navigation)
15435
- if (event.key === 'Tab') {
15436
- setOpen(false);
15437
- onTabKeyPress();
15438
- }
15439
15530
  if (isAriaSelectionKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {
15440
15531
  var _listboxRef$current;
15441
15532
  event.preventDefault();
@@ -15450,7 +15541,7 @@ const Search$2 = /*#__PURE__*/React__default.forwardRef(function ListboxSearch(p
15450
15541
  }),
15451
15542
  invalid: !!validationError,
15452
15543
  message: validationError === null || validationError === void 0 ? void 0 : validationError.message
15453
- }, /*#__PURE__*/React__default.createElement(Input, Object.assign({}, otherProps, {
15544
+ }, /*#__PURE__*/React__default.createElement(Input, Object.assign({}, props, {
15454
15545
  autoFocus: true,
15455
15546
  invalid: !!validationError,
15456
15547
  onChange: handleChange,
@@ -15674,7 +15765,6 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15674
15765
  // align the listbox min width with the width of the input - it should never be smaller
15675
15766
  const dimensions = useBoundingClientRectListener(internalRef);
15676
15767
  // state
15677
- const [tabTriggeredClose, setTabTriggeredClose] = React__default.useState(false);
15678
15768
  const [open, setOpen] = React__default.useState(false);
15679
15769
  const [value, _setValue] = reactUseControllableState.useControllableState({
15680
15770
  // uncontrolled
@@ -15751,7 +15841,7 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15751
15841
  var _listboxRef$current;
15752
15842
  if (open) {
15753
15843
  event.preventDefault();
15754
- } else if (isElementInsideTable3OrReport(event.currentTarget)) {
15844
+ } else if (isElementInsideTable3OrReport(event.currentTarget) && isAriaDirectionKey(event)) {
15755
15845
  return;
15756
15846
  } else if (!event.ctrlKey && !event.metaKey && (event.key === 'ArrowDown' || /^[a-z0-9]$/i.test(event.key))) {
15757
15847
  setOpen(true);
@@ -15762,46 +15852,32 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15762
15852
  // the focus should always remain on the input, so we forward events on to the listbox
15763
15853
  (_listboxRef$current = listboxRef.current) === null || _listboxRef$current === void 0 ? void 0 : _listboxRef$current.dispatchEvent(createCustomKeyboardEvent(event));
15764
15854
  };
15765
- let handleBlur;
15766
- if (otherProps.onBlur) {
15767
- // we might be focusing on an input or something inside the dropdown that was triggered by the select
15768
- // so see if the element gaining focus is inside a portal and look up its controller
15769
- // if we don't do this, things like validate on blur occur while simply opening the select
15770
- handleBlur = event => {
15771
- var _elementGainingFocus$;
15772
- const elementGainingFocus = event.relatedTarget;
15773
- if (elementGainingFocus === undefined) {
15774
- return;
15775
- }
15776
- const portalId = elementGainingFocus === null || elementGainingFocus === void 0 ? void 0 : (_elementGainingFocus$ = elementGainingFocus.closest('[data-radix-popper-content-wrapper] > :first-child')) === null || _elementGainingFocus$ === void 0 ? void 0 : _elementGainingFocus$.id;
15777
- if (!portalId || event.currentTarget.getAttribute(`aria-controls`) !== portalId) {
15778
- var _otherProps$onBlur;
15779
- (_otherProps$onBlur = otherProps.onBlur) === null || _otherProps$onBlur === void 0 ? void 0 : _otherProps$onBlur.call(otherProps, event);
15780
- }
15781
- };
15782
- }
15855
+ const shouldFocusNextRef = React__default.useRef(false);
15783
15856
  const handleListboxKeyDown = event => {
15784
15857
  if (isAriaDirectionKey(event)) {
15785
15858
  setShouldPauseHoverState(true);
15859
+ return;
15860
+ }
15861
+ if (event.key === 'Tab') {
15862
+ shouldFocusNextRef.current = true;
15863
+ setOpen(false);
15864
+ return;
15786
15865
  }
15866
+ // support typeahead to set the value by typing its text
15787
15867
  if (!hasSearch && /^[a-z0-9]$/i.test(event.key)) {
15788
15868
  setValueIfMatched(event.key);
15869
+ return;
15789
15870
  }
15790
15871
  };
15872
+ // popover closes and unmounts before any event can be used to focus next, so prevent focusing the trigger and focus next
15791
15873
  const handleCloseAutoFocus = event => {
15792
- event.preventDefault();
15793
- event.stopPropagation();
15794
- if (tabTriggeredClose) {
15795
- const nextFocussableElement = getNextFocussableElement(internalRef.current);
15796
- if (nextFocussableElement) {
15797
- // UX requirement: move focus to the next focussable element when tab key is pressed to select the value
15798
- nextFocussableElement.focus();
15799
- // Reset the tabTriggeredClose state
15800
- setTabTriggeredClose(false);
15801
- }
15802
- } else {
15803
- var _internalRef$current;
15804
- (_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 ? void 0 : _internalRef$current.focus();
15874
+ if (shouldFocusNextRef.current) {
15875
+ var _otherProps$onBlur, _getNextFocussableEle;
15876
+ event.preventDefault();
15877
+ shouldFocusNextRef.current = false;
15878
+ (_otherProps$onBlur = otherProps.onBlur) === null || _otherProps$onBlur === void 0 ? void 0 : _otherProps$onBlur.call(otherProps, event);
15879
+ (_getNextFocussableEle = getNextFocussableElement(internalRef.current)) === null || _getNextFocussableEle === void 0 ? void 0 : _getNextFocussableEle.focus();
15880
+ return;
15805
15881
  }
15806
15882
  };
15807
15883
  const areAllSelected = Array.isArray(value) && selectOptions.every(option => value.includes(option));
@@ -15850,18 +15926,14 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15850
15926
  }, /*#__PURE__*/React__default.createElement(Trigger$7, Object.assign({}, otherProps, {
15851
15927
  "aria-haspopup": "listbox",
15852
15928
  emptyValue: emptyValue,
15853
- onBlur: handleBlur,
15854
15929
  onKeyDown: handleKeyDown,
15855
15930
  placeholder: placeholder,
15856
15931
  ref: internalRef
15857
15932
  }), flattenedChildren)), /*#__PURE__*/React__default.createElement(PopoverPrimitive.Portal, null, /*#__PURE__*/React__default.createElement(PopoverPrimitive.Content, {
15858
15933
  asChild: true,
15859
15934
  align: "start",
15860
- onOpenAutoFocus: () => {
15861
- var _internalRef$current2;
15862
- (_internalRef$current2 = internalRef.current) === null || _internalRef$current2 === void 0 ? void 0 : _internalRef$current2.focus();
15863
- },
15864
15935
  onCloseAutoFocus: handleCloseAutoFocus,
15936
+ onPointerDownOutside: otherProps.onBlur,
15865
15937
  sideOffset: 4,
15866
15938
  tabIndex: -1
15867
15939
  }, /*#__PURE__*/React__default.createElement("div", {
@@ -15871,8 +15943,7 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15871
15943
  }
15872
15944
  }, hasSearch ? (/*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Search$2, {
15873
15945
  placeholder: hasInlineCreation ? texts.select2.searchOrCreate : texts.select2.search,
15874
- ref: searchRef,
15875
- onTabKeyPress: () => setTabTriggeredClose(true)
15946
+ ref: searchRef
15876
15947
  }), multiple && selectOptions.length > 1 && (/*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Button$1, {
15877
15948
  className: "!justify-start",
15878
15949
  appearance: "discrete",
@@ -15942,6 +16013,7 @@ const ControlledHiddenField = props => {
15942
16013
  key: String(bubbleValue),
15943
16014
  multiple: multiple,
15944
16015
  name: name,
16016
+ tabIndex: -1,
15945
16017
  value: bubbleValue
15946
16018
  }, emptyValue !== undefined ? /*#__PURE__*/React__default.createElement("option", {
15947
16019
  value: emptyValue
@@ -16393,7 +16465,7 @@ function Control(props) {
16393
16465
  const ref = React__default.useRef(null);
16394
16466
  React.useEffect(() => {
16395
16467
  // Set value to false only after first render of the control (when it's undefined) after setting the FilterColumn value, because we don't want to change then the value every time filter is opened
16396
- if (controlRenderer === 'switch' && value === undefined) {
16468
+ if ((controlRenderer === 'switch' || controlRenderer === 'checkbox') && value === undefined) {
16397
16469
  onChange(false);
16398
16470
  }
16399
16471
  }, [controlRenderer]);
@@ -16418,6 +16490,12 @@ function Control(props) {
16418
16490
  checked: Boolean(value),
16419
16491
  onChange: onChange
16420
16492
  }));
16493
+ } else if (controlRenderer === 'checkbox') {
16494
+ return /*#__PURE__*/React__default.createElement(Checkbox, Object.assign({}, attributes, {
16495
+ className: "!m-1.5",
16496
+ checked: Boolean(value),
16497
+ onChange: onChange
16498
+ }));
16421
16499
  } else if ((controlRenderer === 'input' || controlRenderer === undefined) && dataType === 'number') {
16422
16500
  return /*#__PURE__*/React__default.createElement(Input, Object.assign({}, attributes, {
16423
16501
  className: "flex-grow",
@@ -16777,8 +16855,6 @@ function TableGrid(props) {
16777
16855
  table.meta.rowActive.handleFocus(event, table.meta.length, table.renderer.scrollToIndex);
16778
16856
  } : undefined;
16779
16857
  const filterReason = getFilterReason(table);
16780
- const searchNotApplied = !table.state.globalFilter || table.state.globalFilter === '';
16781
- const filtersNotApplied = !table.state.columnFilters || table.state.columnFilters.length === 0;
16782
16858
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("style", null, table.stylesheet), /*#__PURE__*/React__default.createElement(focus.FocusScope, null, /*#__PURE__*/React__default.createElement("table", Object.assign({}, attributes, {
16783
16859
  id: table.id,
16784
16860
  "data-table-font-size": table.meta.fontSize.size,
@@ -16794,7 +16870,11 @@ function TableGrid(props) {
16794
16870
  style: table.style,
16795
16871
  tabIndex: -1
16796
16872
  }), /*#__PURE__*/React__default.createElement("thead", null, table.instance.getHeaderGroups().map(headerGroup => (/*#__PURE__*/React__default.createElement("tr", {
16797
- key: headerGroup.id
16873
+ key: headerGroup.id,
16874
+ onFocus: event => {
16875
+ // prevents rowActive.handleFocus from running when clicking on column-header menus.
16876
+ event.stopPropagation();
16877
+ }
16798
16878
  }, headerGroup.headers.map(props => (/*#__PURE__*/React__default.createElement(Header$5, {
16799
16879
  key: props.id,
16800
16880
  header: props,
@@ -16811,7 +16891,7 @@ function TableGrid(props) {
16811
16891
  ...table.renderer.style,
16812
16892
  height: table.renderer.style.height + ROW_HEIGHT_ESTIMATES[table.meta.rowHeight.height]
16813
16893
  } : table.renderer.style
16814
- }, table.renderer.rows, searchNotApplied && filtersNotApplied && props.children), table.meta.footer.isEnabled ? /*#__PURE__*/React__default.createElement(Foot, {
16894
+ }, table.renderer.rows, props.children), table.meta.footer.isEnabled ? /*#__PURE__*/React__default.createElement(Foot, {
16815
16895
  table: table.instance
16816
16896
  }) : null)))));
16817
16897
  }
@@ -18314,71 +18394,6 @@ const useTableRowCreation = (data, tableRef) => {
18314
18394
  };
18315
18395
  };
18316
18396
 
18317
- function useTableEditingListener(table, tableRef) {
18318
- const tableMeta = table.options.meta;
18319
- const completedRowsCount = tableMeta.editing.getCompletedRowsCount();
18320
- const localization = useLocalization();
18321
- const saveChanges = () => {
18322
- requestAnimationFrame(() => {
18323
- tableMeta.editing.saveChanges();
18324
- });
18325
- };
18326
- // save when the row changes
18327
- useLazyEffect(() => {
18328
- if (tableMeta.editing.isEditing) {
18329
- saveChanges();
18330
- }
18331
- }, [tableMeta.rowActive.rowActiveIndex]);
18332
- useLazyEffect(() => {
18333
- if (tableMeta.editing.isEditing) {
18334
- if (tableMeta.rowActive.rowActiveIndex === undefined) {
18335
- tableMeta.rowActive.setRowActiveIndex(0);
18336
- }
18337
- } else {
18338
- // save
18339
- saveChanges();
18340
- // reset detailed mode
18341
- tableMeta.editing.toggleDetailedMode(false);
18342
- // reset the last index back to the first focusable element, when editing gets turned off
18343
- tableMeta.editing.setLastFocusedCellIndex(undefined);
18344
- }
18345
- }, [tableMeta.editing.isEditing]);
18346
- // show a warning if the user navigates away without triggering save, such as using the browser back/forward button
18347
- const hasChanges = tableMeta.editing.hasChanges();
18348
- React__default.useEffect(() => {
18349
- function showUnsavedChangesWarning(event) {
18350
- if (tableMeta.editing.isEditing && hasChanges) {
18351
- event.returnValue = true;
18352
- return true;
18353
- }
18354
- return false;
18355
- }
18356
- window.addEventListener('beforeunload', showUnsavedChangesWarning);
18357
- return () => {
18358
- window.removeEventListener('beforeunload', showUnsavedChangesWarning);
18359
- };
18360
- }, [tableMeta.editing.isEditing, hasChanges]);
18361
- React__default.useEffect(() => {
18362
- if (completedRowsCount > 0) {
18363
- resetHighlightedColumnIndexes(table.getState().globalFilter, table, localization);
18364
- }
18365
- }, [completedRowsCount]);
18366
- React__default.useEffect(() => {
18367
- const onClickOutside = event => {
18368
- if (tableMeta.editing.isEditing) {
18369
- var _event$target$getAttr, _event$target;
18370
- const element = (_event$target$getAttr = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.getAttribute('data-taco')) !== null && _event$target$getAttr !== void 0 ? _event$target$getAttr : '';
18371
- const insideTable = isElementInsideOrTriggeredFromContainer(event.target, tableRef.current) || element === 'backdrop';
18372
- if (!insideTable) {
18373
- saveChanges();
18374
- }
18375
- }
18376
- };
18377
- document.addEventListener('click', onClickOutside);
18378
- return () => document.removeEventListener('click', onClickOutside);
18379
- }, [saveChanges, tableMeta.editing.isEditing]);
18380
- }
18381
-
18382
18397
  function willRowMove(cell, change, rowIndex, localization) {
18383
18398
  const {
18384
18399
  table
@@ -18459,444 +18474,642 @@ function willRowMoveAfterSorting(cell, change, rowIndex) {
18459
18474
  }
18460
18475
  return ((_resortedRows$index = resortedRows[index]) === null || _resortedRows$index === void 0 ? void 0 : _resortedRows$index.id) !== cell.row.id;
18461
18476
  }
18462
- function animateCreateRow(id) {
18463
- const templateRow = document.querySelector(`[data-row-id="${id}"]`);
18464
- if (templateRow) {
18465
- const firstCell = templateRow.querySelector(':first-child');
18466
- const checkbox = firstCell === null || firstCell === void 0 ? void 0 : firstCell.querySelector('[data-taco="checkbox"]');
18467
- firstCell === null || firstCell === void 0 ? void 0 : firstCell.focus();
18468
- if (checkbox) {
18469
- setDataFocusAttribute(checkbox);
18470
- }
18471
- templateRow.scrollIntoView();
18472
- const keyframes = [{
18473
- background: '#b2c7ef'
18474
- }, {
18475
- background: '#ebebeb'
18476
- }];
18477
- for (const child of templateRow.children) {
18478
- child.animate(keyframes, {
18479
- duration: 1000,
18480
- easing: 'ease-out'
18481
- });
18482
- }
18477
+ const TEMPORARY_ROW_ID_PREFIX = 'temp-';
18478
+ function isTemporaryRow(rowId) {
18479
+ if (rowId === undefined) {
18480
+ return false;
18483
18481
  }
18482
+ return String(rowId).startsWith(TEMPORARY_ROW_ID_PREFIX);
18484
18483
  }
18484
+ const shortcut = {
18485
+ key: 'e',
18486
+ meta: true,
18487
+ shift: false
18488
+ };
18485
18489
 
18486
- function useTableEditing(isEnabled = false, handleSave, handleChange, validator) {
18487
- // used to switch the table into editing mode
18488
- const [isEditing, toggleEditing] = React__default.useState(false);
18489
- // used to switch the editing between "detailed" mode
18490
- const [isDetailedMode, toggleDetailedMode] = React__default.useState(false);
18491
- // store the last focused cell, so that up/down arrow key navigation remains in the same column
18492
- const [lastFocusedCellIndex, setLastFocusedCellIndex] = useLastFocusedCellIndex();
18493
- // store pending changes for each row
18494
- // changes are saved as soon as the active row changes, so in most cases this will only contain the active row's changes
18495
- // but not always - if validation or server requests fail when saving, those rows remain until the failure is resolved
18496
- const pendingChangesFns = usePendingChanges(isEnabled, handleSave, handleChange, validator);
18497
- useGlobalKeyDown(isEnabled && isEditing ? {
18490
+ function useTableEditingListener(table, tableRef, scrollToIndex) {
18491
+ const tableMeta = table.options.meta;
18492
+ const localization = useLocalization();
18493
+ // save when the row changes
18494
+ // store the last row active index, otherwise everytime tableMeta.editing.saveChanges changes the hook runs again
18495
+ const lastRowActiveIndexRef = React__default.useRef(tableMeta.rowActive.rowActiveIndex);
18496
+ useLazyEffect(() => {
18497
+ if (tableMeta.editing.isEditing && lastRowActiveIndexRef.current !== undefined && tableMeta.rowActive.rowActiveIndex !== lastRowActiveIndexRef.current) {
18498
+ lastRowActiveIndexRef.current = tableMeta.rowActive.rowActiveIndex;
18499
+ tableMeta.editing.saveChanges(table);
18500
+ }
18501
+ }, [tableMeta.rowActive.rowActiveIndex, tableMeta.editing.saveChanges]);
18502
+ // show a warning if the user navigates away without triggering save, such as using the browser back/forward button
18503
+ const hasChanges = tableMeta.editing.hasChanges();
18504
+ React__default.useEffect(() => {
18505
+ function showUnsavedChangesWarning(event) {
18506
+ if (tableMeta.editing.isEditing && hasChanges) {
18507
+ event.returnValue = true;
18508
+ return true;
18509
+ }
18510
+ return false;
18511
+ }
18512
+ window.addEventListener('beforeunload', showUnsavedChangesWarning);
18513
+ return () => {
18514
+ window.removeEventListener('beforeunload', showUnsavedChangesWarning);
18515
+ };
18516
+ }, [tableMeta.editing.isEditing, hasChanges]);
18517
+ const hasSavedChanges = tableMeta.editing.hasSaved();
18518
+ useLazyEffect(() => {
18519
+ if (hasSavedChanges) {
18520
+ resetHighlightedColumnIndexes(table.getState().globalFilter, table, localization);
18521
+ }
18522
+ }, [hasSavedChanges]);
18523
+ React__default.useEffect(() => {
18524
+ const onClickOutside = event => {
18525
+ if (tableMeta.editing.isEditing) {
18526
+ const element = event.target;
18527
+ const insideTable = element.getAttribute('data-taco') === 'backdrop' || element.getAttribute('data-table') === 'editing-toggle' || isElementInsideOrTriggeredFromContainer(element, tableRef.current);
18528
+ // users can click the white space below rows which could be inside the table, but a valid scenario to save
18529
+ if (!insideTable || element.tagName === 'TABLE' || element.tagName === 'TBODY') {
18530
+ tableMeta.editing.saveChanges(table);
18531
+ }
18532
+ }
18533
+ };
18534
+ document.addEventListener('click', onClickOutside);
18535
+ return () => document.removeEventListener('click', onClickOutside);
18536
+ }, [tableMeta.editing.isEditing, tableMeta.editing.saveChanges]);
18537
+ const rows = table.getRowModel().rows;
18538
+ // make sure pending changes are removed for rows that no longer exist
18539
+ useLazyEffect(() => {
18540
+ const pendingChanges = tableMeta.editing.getErrorsShownInAlert();
18541
+ pendingChanges.forEach(pendingChange => {
18542
+ try {
18543
+ table.getRow(pendingChange.rowId);
18544
+ } catch {
18545
+ tableMeta.editing.discardChanges(pendingChange.rowId, table);
18546
+ }
18547
+ });
18548
+ }, [rows.length]);
18549
+ // shortcuts
18550
+ useGlobalKeyDown(tableMeta.editing.isEnabled ? shortcut : undefined, event => {
18551
+ event.preventDefault();
18552
+ tableMeta.editing.toggleEditing(!tableMeta.editing.isEditing, table, scrollToIndex);
18553
+ });
18554
+ useGlobalKeyDown(tableMeta.editing.isEditing ? {
18498
18555
  key: 's',
18499
18556
  meta: true,
18500
18557
  shift: false
18501
18558
  } : undefined, event => {
18502
18559
  event.preventDefault();
18503
- pendingChangesFns.saveChanges();
18560
+ tableMeta.editing.saveChanges(table);
18504
18561
  });
18505
- return {
18506
- isEnabled,
18507
- isEditing,
18508
- isDetailedMode,
18509
- toggleDetailedMode: isEnabled ? toggleDetailedMode : () => undefined,
18510
- toggleEditing: isEnabled ? toggleEditing : () => undefined,
18511
- lastFocusedCellIndex,
18512
- setLastFocusedCellIndex,
18513
- ...pendingChangesFns
18514
- };
18515
18562
  }
18516
- function usePendingChanges(isEnabled, handleSave, handleChange, validator) {
18517
- const saveChanges = function (rowId = undefined) {
18563
+
18564
+ const DELAY_BEFORE_REMOVING_SAVE_STATUS = 3000;
18565
+ function reducer$2(state, action) {
18566
+ const {
18567
+ type,
18568
+ rowId,
18569
+ payload
18570
+ } = action;
18571
+ switch (type) {
18572
+ case 'setCellValue':
18573
+ {
18574
+ const {
18575
+ columnId,
18576
+ row,
18577
+ value
18578
+ } = payload;
18579
+ return {
18580
+ ...state,
18581
+ changes: {
18582
+ ...state.changes,
18583
+ rows: setWith(state.changes.rows, `${rowId}.${columnId}`, value, Object),
18584
+ originals: setWith(state.changes.originals, rowId, row, Object)
18585
+ }
18586
+ };
18587
+ }
18588
+ case 'removeCellValue':
18589
+ {
18590
+ const {
18591
+ columnId,
18592
+ rowIdentityAccessor
18593
+ } = payload;
18594
+ const changes = omit(state.changes.rows, `${rowId}.${columnId}`);
18595
+ // if there are no changes left, remove the row
18596
+ if (!Object.keys(changes[rowId]).length) {
18597
+ return reducer$2(state, {
18598
+ type: 'removeRow',
18599
+ rowId,
18600
+ payload: {
18601
+ rowIdentityAccessor
18602
+ }
18603
+ });
18604
+ }
18605
+ return {
18606
+ ...state,
18607
+ changes: {
18608
+ ...state.changes,
18609
+ rows: omit(state.changes.rows, `${rowId}.${columnId}`),
18610
+ errors: omit(state.changes.errors, `${rowId}.cells.${columnId}`),
18611
+ moveReasons: omit(state.changes.moveReasons, `${rowId}.${columnId}`)
18612
+ }
18613
+ };
18614
+ }
18615
+ case 'updateRow':
18616
+ {
18617
+ const {
18618
+ cellErrors,
18619
+ moveReasons,
18620
+ original,
18621
+ value
18622
+ } = payload;
18623
+ return {
18624
+ ...state,
18625
+ changes: {
18626
+ ...state.changes,
18627
+ rows: setWith(state.changes.rows, rowId, value, Object),
18628
+ errors: setWith(state.changes.errors, `${rowId}.cells`, cellErrors !== null && cellErrors !== void 0 ? cellErrors : state.changes.errors.cells[rowId], Object),
18629
+ originals: setWith(state.changes.originals, rowId, original !== null && original !== void 0 ? original : state.changes.originals[rowId], Object),
18630
+ moveReasons: setWith(state.changes.moveReasons, rowId, moveReasons !== null && moveReasons !== void 0 ? moveReasons : state.changes.moveReasons[rowId], Object),
18631
+ // status can be undefined, so don't use ??
18632
+ status: setWith(state.changes.status, rowId, undefined, Object)
18633
+ }
18634
+ };
18635
+ }
18636
+ case 'removeRow':
18637
+ {
18638
+ const {
18639
+ rowIdentityAccessor
18640
+ } = payload;
18641
+ return {
18642
+ ...state,
18643
+ changes: {
18644
+ ...state.changes,
18645
+ rows: omit(state.changes.rows, rowId),
18646
+ errors: omit(state.changes.errors, rowId),
18647
+ moveReasons: omit(state.changes.moveReasons, rowId),
18648
+ originals: omit(state.changes.originals, rowId),
18649
+ status: omit(state.changes.status, rowId)
18650
+ },
18651
+ temporaryRows: state.temporaryRows.filter(row => row[rowIdentityAccessor] !== rowId)
18652
+ };
18653
+ }
18654
+ case 'setRowStatus':
18655
+ {
18656
+ const {
18657
+ status
18658
+ } = payload;
18659
+ return {
18660
+ ...state,
18661
+ changes: {
18662
+ ...state.changes,
18663
+ status: status ? setWith(state.changes.status, rowId, status, Object) : omit(state.changes.status, rowId)
18664
+ }
18665
+ };
18666
+ }
18667
+ case 'setRowErrors':
18668
+ {
18669
+ const {
18670
+ ...errors
18671
+ } = payload;
18672
+ return {
18673
+ ...state,
18674
+ changes: {
18675
+ ...state.changes,
18676
+ errors: setWith(state.changes.errors, rowId, errors, Object)
18677
+ }
18678
+ };
18679
+ }
18680
+ case 'createRow':
18681
+ {
18682
+ const {
18683
+ value
18684
+ } = payload;
18685
+ return {
18686
+ ...state,
18687
+ temporaryRows: state.temporaryRows.concat(value),
18688
+ changes: {
18689
+ ...state.changes,
18690
+ rows: setWith(state.changes.rows, rowId, value, Object),
18691
+ originals: setWith(state.changes.originals, rowId, value, Object)
18692
+ }
18693
+ };
18694
+ }
18695
+ default:
18696
+ return state;
18697
+ }
18698
+ }
18699
+ function usePendingChangesState(handleSave, handleChange, rowIdentityAccessor, validator) {
18700
+ const saveChanges = function (table, rowId = undefined) {
18518
18701
  try {
18519
18702
  let _exit = false;
18520
18703
  if (!handleSave) {
18521
18704
  console.warn('Tried to save, but Table has no onEditingSave handler');
18522
- return Promise.resolve();
18705
+ return Promise.resolve(false);
18523
18706
  }
18524
- // we save back to pendingChanges, so make a copy of it's state when save was triggered
18525
- const changesToSave = rowId ? {
18526
- [rowId]: pendingChanges[rowId]
18527
- } : {
18528
- ...pendingChanges
18529
- };
18530
- const changes = Object.keys(changesToSave);
18531
- return Promise.resolve(function () {
18532
- if (changes.length) {
18533
- return _forOf(changes, function (rowId) {
18534
- const pendingChange = changesToSave[rowId];
18535
- const changeSet = getChangesetFromChanges(pendingChange);
18536
- return _catch(function () {
18537
- function _temp3(_result) {
18538
- return _exit ? _result : Promise.resolve(handleSave(changeSet)).then(function () {
18539
- // cleanup changes, we don't need them after saving
18540
- resetChanges(rowId);
18541
- setRowSaveStatus(rowId, 'complete');
18542
- });
18543
- }
18544
- if (getRowSaveStatus(rowId) === 'pending') {
18545
- _exit = true;
18546
- return;
18547
- }
18548
- // set saving = true
18549
- setRowSaveStatus(rowId, 'pending');
18550
- // re-run validation, maybe a cell is already invalid but has never been blurred
18551
- const _temp2 = function () {
18552
- if (validator) {
18553
- return Promise.resolve(validator(changeSet)).then(function (errors) {
18554
- if (errors && Object.keys(errors).length) {
18555
- throw errors;
18556
- }
18557
- });
18558
- }
18559
- }();
18560
- return _temp2 && _temp2.then ? _temp2.then(_temp3) : _temp3(_temp2); // send new data to the server
18561
- }, function (error) {
18562
- // the onEditingSave handler should throw errors when something fails, e.g. validation, network errors etc
18563
- // this code handles those errors and maps them either to row errors or cell specific errors
18564
- let rowError;
18565
- let cellErrors;
18566
- if (typeof error === 'string') {
18567
- rowError = error;
18568
- } else if (error instanceof Error) {
18569
- var _error$response;
18570
- rowError = error.message;
18571
- // most of our apis return error objects within this shape
18572
- if (typeof ((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.data) === 'object') {
18573
- var _error$response2;
18574
- cellErrors = (_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.data;
18707
+ // sometimes we only want to save one row
18708
+ const changes = rowId ? {
18709
+ [rowId]: state.changes.rows[rowId]
18710
+ } : state.changes.rows;
18711
+ let completed = true;
18712
+ const _temp9 = _forOf(Object.keys(changes), function (rowId) {
18713
+ const status = getRowStatus(rowId);
18714
+ return _catch(function () {
18715
+ function _temp8(_result) {
18716
+ return _exit ? _result : Promise.resolve(handleSave(changeSet)).then(function () {
18717
+ // cleanup changes, we don't need them after saving
18718
+ discardChanges(rowId, table);
18719
+ // show the saved status, then remove it after a delay
18720
+ setRowStatus(rowId, 'saved');
18721
+ setTimeout(() => {
18722
+ setRowStatus(rowId, undefined);
18723
+ }, DELAY_BEFORE_REMOVING_SAVE_STATUS);
18724
+ });
18725
+ }
18726
+ // don't try to save if - already saving, or there are known errors
18727
+ if (status === 'saving' || status === 'errored') {
18728
+ return;
18729
+ }
18730
+ setRowStatus(rowId, 'saving');
18731
+ const changeSet = {
18732
+ ...state.changes.originals[rowId],
18733
+ ...changes[rowId]
18734
+ };
18735
+ // if we had to create a temporary id, delete it first - it's our data, not theirs
18736
+ if (isTemporaryRow(changeSet[rowIdentityAccessor])) {
18737
+ delete changeSet[rowIdentityAccessor];
18738
+ }
18739
+ // re-run validation, maybe a cell is already invalid but has never been blurred
18740
+ const _temp7 = function () {
18741
+ if (validator) {
18742
+ return Promise.resolve(validator(changeSet)).then(function (errors) {
18743
+ if (errors && Object.keys(errors).length) {
18744
+ throw errors;
18575
18745
  }
18576
- } else if (typeof error === 'object') {
18577
- cellErrors = error;
18578
- }
18579
- if (rowError || cellErrors) {
18580
- setPendingChanges(currentChanges => {
18581
- const nextChanges = {
18582
- ...currentChanges
18583
- };
18584
- nextChanges[rowId]._meta.errors = {
18585
- row: rowError,
18586
- cells: cellErrors,
18587
- shouldShowErrorAlert: true
18588
- };
18589
- return nextChanges;
18590
- });
18746
+ });
18747
+ }
18748
+ }();
18749
+ return _temp7 && _temp7.then ? _temp7.then(_temp8) : _temp8(_temp7); // send new data to the server
18750
+ }, function (error) {
18751
+ var _error$response;
18752
+ if (error instanceof ReferenceError || error instanceof TypeError || (error === null || error === void 0 ? void 0 : (_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.status) >= 500) {
18753
+ console.error(error);
18754
+ }
18755
+ // the onEditingSave handler should throw errors when something fails, e.g. validation, network errors etc
18756
+ // this code handles those errors and maps them either to row errors or cell specific errors
18757
+ let rowError;
18758
+ let cellErrors;
18759
+ if (typeof error === 'string') {
18760
+ rowError = error;
18761
+ } else if (error instanceof Error) {
18762
+ var _error$response2;
18763
+ rowError = error.message;
18764
+ // most of our apis return error objects within this shape
18765
+ if (typeof ((_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.data) === 'object') {
18766
+ var _error$response3;
18767
+ cellErrors = (_error$response3 = error.response) === null || _error$response3 === void 0 ? void 0 : _error$response3.data;
18768
+ }
18769
+ } else if (typeof error === 'object') {
18770
+ cellErrors = error;
18771
+ }
18772
+ if (rowError || cellErrors) {
18773
+ dispatch({
18774
+ type: 'setRowErrors',
18775
+ rowId,
18776
+ payload: {
18777
+ row: rowError,
18778
+ cells: cellErrors,
18779
+ shouldShowErrorAlert: true
18591
18780
  }
18592
- setRowSaveStatus(rowId, undefined);
18593
18781
  });
18594
- }, function () {
18595
- return _exit;
18596
- });
18597
- }
18598
- }());
18782
+ }
18783
+ setRowStatus(rowId, 'errored');
18784
+ completed = false;
18785
+ });
18786
+ }, function () {
18787
+ return _exit;
18788
+ });
18789
+ return Promise.resolve(_temp9 && _temp9.then ? _temp9.then(function (_result3) {
18790
+ return _exit ? _result3 : completed;
18791
+ }) : _exit ? _temp9 : completed);
18599
18792
  } catch (e) {
18600
18793
  return Promise.reject(e);
18601
18794
  }
18602
18795
  };
18603
- const validateCell = function (cell) {
18796
+ const onCellChanged = function (cell, rowIndex, shouldRunUpdaters = true) {
18604
18797
  try {
18605
- if (!validator || !isEnabled) {
18606
- return Promise.resolve();
18607
- }
18608
- const changeSet = getChangesetFromChanges(pendingChanges[cell.row.id]);
18609
- // only validate if the cell being blurred actually has any changes
18610
- const _temp = function () {
18611
- if (cell.column.id in changeSet) {
18612
- return Promise.resolve(validator(changeSet)).then(function (errors) {
18613
- setPendingChanges(currentChanges => {
18614
- const nextChanges = {
18615
- ...currentChanges
18616
- };
18617
- nextChanges[cell.row.id]._meta = {
18618
- ...nextChanges[cell.row.id]._meta,
18619
- errors: {
18620
- ...nextChanges[cell.row.id]._meta.errors,
18621
- cells: errors,
18622
- shouldShowErrorAlert: !Object.keys(errors).length ? false : nextChanges[cell.row.id]._meta.errors.shouldShowErrorAlert
18798
+ function _temp6() {
18799
+ var _state$changes$errors11;
18800
+ function _temp4() {
18801
+ // only set errors and move reasons for the cells we're currently acting on
18802
+ // why? because the UX is not good if we set them for cells the user hasn't touched yet
18803
+ const cellsToActOn = [cell.column.id, ...Object.keys(updatesForOtherCells)];
18804
+ const allCells = cell.row._getAllCellsByColumnId();
18805
+ cellsToActOn.forEach(accessor => {
18806
+ if (validationErrors[accessor]) {
18807
+ nextCellErrors[accessor] = validationErrors[accessor];
18808
+ // don't show move indicator for cells with errors, they aren't valid and can't be saved
18809
+ delete nextMoveReasons[accessor];
18810
+ } else {
18811
+ var _allCells$accessor;
18812
+ // there isn't any error in this run, remove any error set in state
18813
+ delete nextCellErrors[accessor];
18814
+ if ((_allCells$accessor = allCells[accessor]) !== null && _allCells$accessor !== void 0 && _allCells$accessor.column.getIsSorted()) {
18815
+ // run row move determination
18816
+ const reason = willRowMove(cell, nextChanges[accessor], rowIndex, localization);
18817
+ // if the row will move based on this change save why, otherwise delete any existing state
18818
+ if (reason) {
18819
+ nextMoveReasons[accessor] = reason;
18820
+ } else {
18821
+ delete nextMoveReasons[accessor];
18623
18822
  }
18624
- };
18625
- return nextChanges;
18823
+ }
18824
+ }
18825
+ });
18826
+ dispatch({
18827
+ type: 'updateRow',
18828
+ rowId: cell.row.id,
18829
+ payload: {
18830
+ cellErrors: nextCellErrors,
18831
+ moveReasons: nextMoveReasons,
18832
+ value: nextChanges
18833
+ }
18834
+ });
18835
+ }
18836
+ // create a projection of the next state, so we can act against it
18837
+ const nextChanges = {
18838
+ ...state.changes.rows[cell.row.id],
18839
+ ...updatesForOtherCells
18840
+ };
18841
+ const nextMoveReasons = {
18842
+ ...state.changes.moveReasons[cell.row.id]
18843
+ };
18844
+ const nextCellErrors = {
18845
+ ...((_state$changes$errors11 = state.changes.errors[cell.row.id]) === null || _state$changes$errors11 === void 0 ? void 0 : _state$changes$errors11.cells)
18846
+ };
18847
+ // run validation
18848
+ let validationErrors = {};
18849
+ const _temp3 = function () {
18850
+ if (validator) {
18851
+ const nextRowValue = {
18852
+ ...state.changes.originals[cell.row.id],
18853
+ ...changes,
18854
+ ...updatesForOtherCells
18855
+ };
18856
+ return Promise.resolve(validator(nextRowValue)).then(function (_validator2) {
18857
+ validationErrors = _validator2 !== null && _validator2 !== void 0 ? _validator2 : {};
18626
18858
  });
18859
+ }
18860
+ }();
18861
+ return _temp3 && _temp3.then ? _temp3.then(_temp4) : _temp4(_temp3);
18862
+ }
18863
+ const changes = state.changes.rows[cell.row.id];
18864
+ if (!changes) {
18865
+ return Promise.resolve();
18866
+ }
18867
+ let updatesForOtherCells = {};
18868
+ // run the updater handler if there is one, to see if there are any other cells to update
18869
+ const _temp5 = function () {
18870
+ if (typeof handleChange === 'function' && shouldRunUpdaters) {
18871
+ const previousRowValue = {
18872
+ ...state.changes.originals[cell.row.id]
18873
+ };
18874
+ const nextRowValue = {
18875
+ ...state.changes.originals[cell.row.id],
18876
+ ...changes
18877
+ };
18878
+ return Promise.resolve(handleChange(cell.column.id, changes[cell.column.id], nextRowValue, previousRowValue)).then(function (_handleChange) {
18879
+ updatesForOtherCells = _handleChange !== null && _handleChange !== void 0 ? _handleChange : {};
18627
18880
  });
18628
18881
  }
18629
18882
  }();
18630
- return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
18631
- } catch (e) {
18632
- return Promise.reject(e);
18633
- }
18634
- };
18635
- const setCellValue = function (cell, change, rowIndex) {
18636
- try {
18637
- const changes = {
18638
- [cell.column.id]: change
18639
- };
18640
- setPendingChanges(currentChanges => {
18641
- const nextChanges = createPendingChangesSetter(currentChanges, cell.row, rowIndex, changes, localization);
18642
- pendingChangesUpdater.syncCellChanges(nextChanges);
18643
- return nextChanges;
18644
- });
18645
- pendingChangesUpdater.runCellUpdates(changes, cell, rowIndex);
18646
- return Promise.resolve();
18883
+ return Promise.resolve(_temp5 && _temp5.then ? _temp5.then(_temp6) : _temp6(_temp5));
18647
18884
  } catch (e) {
18648
18885
  return Promise.reject(e);
18649
18886
  }
18650
- };
18651
- const addCreatedRowChangeset = function (row) {
18887
+ }; // general
18888
+ // rows
18889
+ const setRowValue = function (rowId, original, value) {
18652
18890
  try {
18653
- const cells = row.getAllCells();
18654
- setPendingChanges(currentChanges => {
18655
- return cells.reduce((changes, cell) => {
18656
- if (cell.getValue()) {
18657
- var _currentChanges$cell$, _currentChanges$cell$2, _currentChanges$cell$3;
18658
- return {
18659
- ...changes,
18660
- [cell.row.id]: {
18661
- ...changes[cell.row.id],
18662
- [cell.column.id]: cell.getValue(),
18663
- _meta: {
18664
- ...((_currentChanges$cell$ = currentChanges[cell.row.id]) === null || _currentChanges$cell$ === void 0 ? void 0 : _currentChanges$cell$._meta),
18665
- original: cell.row.original,
18666
- moveReason: {
18667
- ...((_currentChanges$cell$2 = currentChanges[cell.row.id]) === null || _currentChanges$cell$2 === void 0 ? void 0 : _currentChanges$cell$2._meta.moveReason)
18668
- },
18669
- errors: {
18670
- ...((_currentChanges$cell$3 = currentChanges[cell.row.id]) === null || _currentChanges$cell$3 === void 0 ? void 0 : _currentChanges$cell$3._meta.errors)
18671
- }
18672
- }
18673
- }
18674
- };
18675
- } else {
18676
- return changes;
18891
+ function _temp2() {
18892
+ dispatch({
18893
+ type: 'updateRow',
18894
+ rowId,
18895
+ payload: {
18896
+ cellErrors,
18897
+ original,
18898
+ value
18677
18899
  }
18678
- }, currentChanges);
18679
- });
18680
- return Promise.resolve();
18900
+ });
18901
+ }
18902
+ let cellErrors;
18903
+ const _temp = function () {
18904
+ if (validator) {
18905
+ const row = {
18906
+ ...original,
18907
+ ...value
18908
+ };
18909
+ return Promise.resolve(validator(row)).then(function (_validator) {
18910
+ cellErrors = _validator !== null && _validator !== void 0 ? _validator : {};
18911
+ });
18912
+ }
18913
+ }();
18914
+ return Promise.resolve(_temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp));
18681
18915
  } catch (e) {
18682
18916
  return Promise.reject(e);
18683
18917
  }
18684
18918
  };
18685
18919
  const localization = useLocalization();
18686
- const [pendingChanges, setPendingChanges] = React__default.useState({});
18687
- // we maintain save status as separate state because 'complete' needs to briefly show after pendingChanges are deleted
18688
- const [saveStates, setSaveState] = React__default.useState({});
18689
- function getCellValue(cell) {
18690
- var _pendingChanges$cell$;
18691
- return (_pendingChanges$cell$ = pendingChanges[cell.row.id]) === null || _pendingChanges$cell$ === void 0 ? void 0 : _pendingChanges$cell$[cell.column.id];
18920
+ const [state, dispatch] = React__default.useReducer(reducer$2, {
18921
+ changes: {
18922
+ rows: {},
18923
+ errors: {},
18924
+ moveReasons: {},
18925
+ originals: {},
18926
+ status: {}
18927
+ },
18928
+ temporaryRows: []
18929
+ });
18930
+ function getRowValue(rowId) {
18931
+ var _state$changes$rows$r, _state$changes$rows;
18932
+ return (_state$changes$rows$r = (_state$changes$rows = state.changes.rows) === null || _state$changes$rows === void 0 ? void 0 : _state$changes$rows[rowId]) !== null && _state$changes$rows$r !== void 0 ? _state$changes$rows$r : undefined;
18692
18933
  }
18693
- function getCellError(cell) {
18694
- var _pendingChanges$cell$2, _pendingChanges$cell$3, _pendingChanges$cell$4;
18695
- return (_pendingChanges$cell$2 = pendingChanges[cell.row.id]) === null || _pendingChanges$cell$2 === void 0 ? void 0 : (_pendingChanges$cell$3 = _pendingChanges$cell$2._meta.errors) === null || _pendingChanges$cell$3 === void 0 ? void 0 : (_pendingChanges$cell$4 = _pendingChanges$cell$3.cells) === null || _pendingChanges$cell$4 === void 0 ? void 0 : _pendingChanges$cell$4[cell.column.id];
18934
+ function getRowMoveReason(rowId) {
18935
+ var _Object$values$, _state$changes$moveRe, _state$changes$moveRe2;
18936
+ return (_Object$values$ = Object.values((_state$changes$moveRe = (_state$changes$moveRe2 = state.changes.moveReasons) === null || _state$changes$moveRe2 === void 0 ? void 0 : _state$changes$moveRe2[rowId]) !== null && _state$changes$moveRe !== void 0 ? _state$changes$moveRe : {})[0]) !== null && _Object$values$ !== void 0 ? _Object$values$ : undefined;
18696
18937
  }
18697
- const pendingChangesUpdater = usePendingChangesUpdater(handleChange, setPendingChanges);
18698
18938
  function hasRowErrors(rowId) {
18699
- var _pendingChanges$rowId, _pendingChanges$rowId2, _pendingChanges$rowId3, _pendingChanges$rowId4, _pendingChanges$rowId5;
18700
- if (!isEnabled) {
18701
- return false;
18702
- }
18703
- return !!((_pendingChanges$rowId = pendingChanges[rowId]) !== null && _pendingChanges$rowId !== void 0 && (_pendingChanges$rowId2 = _pendingChanges$rowId._meta.errors) !== null && _pendingChanges$rowId2 !== void 0 && _pendingChanges$rowId2.row) || !!Object.keys((_pendingChanges$rowId3 = (_pendingChanges$rowId4 = pendingChanges[rowId]) === null || _pendingChanges$rowId4 === void 0 ? void 0 : (_pendingChanges$rowId5 = _pendingChanges$rowId4._meta.errors) === null || _pendingChanges$rowId5 === void 0 ? void 0 : _pendingChanges$rowId5.cells) !== null && _pendingChanges$rowId3 !== void 0 ? _pendingChanges$rowId3 : {}).length;
18939
+ var _state$changes$errors, _state$changes$errors2, _state$changes$errors3;
18940
+ return !!((_state$changes$errors = state.changes.errors[rowId]) !== null && _state$changes$errors !== void 0 && _state$changes$errors.row) || !!Object.keys((_state$changes$errors2 = (_state$changes$errors3 = state.changes.errors[rowId]) === null || _state$changes$errors3 === void 0 ? void 0 : _state$changes$errors3.cells) !== null && _state$changes$errors2 !== void 0 ? _state$changes$errors2 : {}).length;
18941
+ }
18942
+ function hasRowErrorsShownInAlert(rowId) {
18943
+ var _state$changes$errors4;
18944
+ return hasRowErrors(rowId) && !!((_state$changes$errors4 = state.changes.errors[rowId]) !== null && _state$changes$errors4 !== void 0 && _state$changes$errors4.shouldShowErrorAlert);
18704
18945
  }
18705
- function hasRowErrorsSeen(rowId) {
18706
- var _pendingChanges$rowId6;
18707
- if (!isEnabled) {
18946
+ function hasTemporaryRowErrors() {
18947
+ var _state$temporaryRows, _state$changes$errors5, _state$changes$errors6, _state$changes$errors7;
18948
+ const newRow = (_state$temporaryRows = state.temporaryRows) === null || _state$temporaryRows === void 0 ? void 0 : _state$temporaryRows[0];
18949
+ if (!newRow) {
18708
18950
  return false;
18709
18951
  }
18710
- return hasRowErrors(rowId) && !!((_pendingChanges$rowId6 = pendingChanges[rowId]._meta.errors) !== null && _pendingChanges$rowId6 !== void 0 && _pendingChanges$rowId6.shouldShowErrorAlert);
18952
+ const rowId = newRow[rowIdentityAccessor];
18953
+ return !!((_state$changes$errors5 = state.changes.errors[rowId]) !== null && _state$changes$errors5 !== void 0 && _state$changes$errors5.row) || !!Object.keys((_state$changes$errors6 = (_state$changes$errors7 = state.changes.errors[rowId]) === null || _state$changes$errors7 === void 0 ? void 0 : _state$changes$errors7.cells) !== null && _state$changes$errors6 !== void 0 ? _state$changes$errors6 : {}).length;
18711
18954
  }
18712
- function getRowPendingChange(rowId) {
18713
- const rowPendingChanges = pendingChanges[rowId];
18714
- if (rowPendingChanges) {
18715
- const {
18716
- _meta,
18717
- ...pendingChange
18718
- } = rowPendingChanges;
18719
- return pendingChange;
18720
- }
18721
- return undefined;
18955
+ function getRowStatus(rowId) {
18956
+ return state.changes.status[rowId];
18722
18957
  }
18723
- function getRowSaveStatus(rowId) {
18724
- if (!isEnabled) {
18725
- return false;
18726
- }
18727
- return saveStates[rowId];
18958
+ function setRowStatus(rowId, status) {
18959
+ dispatch({
18960
+ type: 'setRowStatus',
18961
+ rowId,
18962
+ payload: {
18963
+ status
18964
+ }
18965
+ });
18728
18966
  }
18729
- function setRowSaveStatus(rowId, status) {
18730
- setSaveState(currentStates => {
18731
- const nextStates = {
18732
- ...currentStates
18733
- };
18734
- if (status) {
18735
- nextStates[rowId] = status;
18736
- } else {
18737
- delete nextStates[rowId];
18967
+ function createRow(data) {
18968
+ const newRowId = `${TEMPORARY_ROW_ID_PREFIX}${uuid.v4()}`;
18969
+ const value = {
18970
+ ...data,
18971
+ [rowIdentityAccessor]: newRowId
18972
+ };
18973
+ dispatch({
18974
+ type: 'createRow',
18975
+ rowId: newRowId,
18976
+ payload: {
18977
+ value
18738
18978
  }
18739
- return nextStates;
18740
18979
  });
18980
+ return newRowId;
18981
+ }
18982
+ // cells
18983
+ function setCellValue(cell, value) {
18984
+ const rowId = cell.row.id;
18985
+ const columnId = cell.column.id;
18986
+ // update if the change is different to the original value
18987
+ if (value !== cell.row.original[columnId]) {
18988
+ dispatch({
18989
+ type: 'setCellValue',
18990
+ rowId,
18991
+ payload: {
18992
+ columnId,
18993
+ row: cell.row.original,
18994
+ value
18995
+ }
18996
+ });
18997
+ }
18998
+ // otherwise remove any previous change - no point saving the same value
18999
+ else if (cell.row.id in state.changes.rows) {
19000
+ dispatch({
19001
+ type: 'removeCellValue',
19002
+ rowId,
19003
+ payload: {
19004
+ columnId,
19005
+ rowIdentityAccessor
19006
+ }
19007
+ });
19008
+ }
18741
19009
  }
18742
- function getRowMoveReason(rowId) {
18743
- var _pendingChanges$rowId7;
18744
- return (_pendingChanges$rowId7 = pendingChanges[rowId]) !== null && _pendingChanges$rowId7 !== void 0 && _pendingChanges$rowId7._meta.moveReason ? Object.values(pendingChanges[rowId]._meta.moveReason)[0] : undefined;
19010
+ function getCellValue(cell) {
19011
+ var _state$changes$rows2, _state$changes$rows2$;
19012
+ return (_state$changes$rows2 = state.changes.rows) === null || _state$changes$rows2 === void 0 ? void 0 : (_state$changes$rows2$ = _state$changes$rows2[cell.row.id]) === null || _state$changes$rows2$ === void 0 ? void 0 : _state$changes$rows2$[cell.column.id];
18745
19013
  }
18746
- function hasChanges(rowId) {
18747
- if (!isEnabled) {
18748
- return false;
18749
- }
18750
- return rowId ? !!pendingChanges[rowId] : !!Object.keys(pendingChanges).length;
19014
+ function getCellError(cell) {
19015
+ var _state$changes$errors8, _state$changes$errors9, _state$changes$errors10;
19016
+ return (_state$changes$errors8 = state.changes.errors) === null || _state$changes$errors8 === void 0 ? void 0 : (_state$changes$errors9 = _state$changes$errors8[cell.row.id]) === null || _state$changes$errors9 === void 0 ? void 0 : (_state$changes$errors10 = _state$changes$errors9.cells) === null || _state$changes$errors10 === void 0 ? void 0 : _state$changes$errors10[cell.column.id];
18751
19017
  }
18752
- function hasAlertErrors() {
18753
- if (!isEnabled) {
18754
- return false;
19018
+ function getErrorsShownInAlert() {
19019
+ const rowsWithErrors = Object.keys(state.changes.errors);
19020
+ if (!rowsWithErrors.length) {
19021
+ return [];
18755
19022
  }
18756
- return !!getAlertErrors().length;
18757
- }
18758
- function getAlertErrors() {
18759
- return Object.keys(pendingChanges).filter(hasRowErrorsSeen).map(rowId => ({
19023
+ return rowsWithErrors.filter(hasRowErrorsShownInAlert).map(rowId => ({
18760
19024
  rowId,
18761
- pendingChange: pendingChanges[rowId]
19025
+ changes: state.changes.rows[rowId],
19026
+ errors: state.changes.errors[rowId]
18762
19027
  }));
18763
19028
  }
18764
- function resetChanges(rowId) {
18765
- setPendingChanges(currentChanges => {
18766
- const nextChanges = {
18767
- ...currentChanges
18768
- };
18769
- delete nextChanges[rowId];
18770
- return nextChanges;
18771
- });
19029
+ function hasSaved() {
19030
+ return !!Object.values(state.changes.status).filter(value => value === 'saved').length;
18772
19031
  }
18773
- function getCompletedRowsCount() {
18774
- return Object.values(saveStates).filter(value => value === 'complete').length;
19032
+ function hasChanges(rowId) {
19033
+ return rowId ? !!state.changes.rows[rowId] : !!Object.keys(state.changes.rows).length;
19034
+ }
19035
+ function discardChanges(rowId, table) {
19036
+ // remove any new rows from pinned state before discarding them
19037
+ table.resetRowPinning(true);
19038
+ dispatch({
19039
+ type: 'removeRow',
19040
+ rowId,
19041
+ payload: {
19042
+ rowIdentityAccessor
19043
+ }
19044
+ });
18775
19045
  }
18776
19046
  return {
19047
+ // row
19048
+ setRowValue,
19049
+ getRowValue,
19050
+ getRowMoveReason,
19051
+ hasRowErrors,
19052
+ hasRowErrorsShownInAlert,
19053
+ hasTemporaryRowErrors,
19054
+ getRowStatus,
19055
+ setRowStatus,
19056
+ // cells
19057
+ setCellValue,
18777
19058
  getCellValue,
18778
19059
  getCellError,
18779
- setCellValue,
18780
- validateCell,
18781
- addCreatedRowChangeset,
19060
+ onCellChanged,
19061
+ // general
19062
+ getErrorsShownInAlert,
18782
19063
  hasChanges,
18783
- hasAlertErrors,
18784
- getAlertErrors,
18785
19064
  saveChanges,
18786
- resetChanges,
18787
- hasRowErrors,
18788
- hasRowErrorsSeen,
18789
- getRowPendingChange,
18790
- getRowSaveStatus,
18791
- setRowSaveStatus,
18792
- getRowMoveReason,
18793
- getCompletedRowsCount
19065
+ discardChanges,
19066
+ hasSaved,
19067
+ // new rows
19068
+ createRow,
19069
+ temporaryRows: state.temporaryRows
18794
19070
  };
18795
19071
  }
18796
- function useLastFocusedCellIndex() {
19072
+
19073
+ function useTableEditing(isEnabled = false, handleSave, handleChange, rowIdentityAccessor, validator) {
19074
+ // used to switch the table into editing mode
19075
+ const [isEditing, setEditing] = React__default.useState(false);
19076
+ // used to switch the editing between "detailed" mode
19077
+ const [isDetailedMode, toggleDetailedMode] = React__default.useState(false);
19078
+ // used to contain ref to the create button
19079
+ const createRowButtonRef = React__default.useRef(null);
18797
19080
  // store the last focused cell, so that up/down arrow key navigation remains in the same column
18798
- const lastFocusedCellIndexRef = React__default.useRef(undefined);
18799
- const setLastFocusedCellIndex = React__default.useCallback(index => {
18800
- lastFocusedCellIndexRef.current = index;
18801
- }, []);
18802
- return [lastFocusedCellIndexRef.current, setLastFocusedCellIndex];
18803
- }
18804
- function usePendingChangesUpdater(handleChange, setPendingChanges) {
18805
- const localization = useLocalization();
18806
- const updatersRef = React__default.useRef({});
18807
- const runCellUpdates = React__default.useCallback(lodash.debounce(function (changes, cell, rowIndex) {
18808
- try {
18809
- const _temp4 = function () {
18810
- if (typeof handleChange === 'function') {
18811
- const previousValues = {
18812
- ...cell.row.original,
18813
- ...getChangesetFromChanges(updatersRef.current[cell.row.id])
18814
- };
18815
- const nextValues = {
18816
- ...previousValues,
18817
- ...changes
18818
- };
18819
- return Promise.resolve(handleChange(cell.column.id, changes[cell.column.id], nextValues, previousValues)).then(function (updates) {
18820
- if (updates && Object.keys(updates).length) {
18821
- setPendingChanges(currentChanges => createPendingChangesSetter(currentChanges, cell.row, rowIndex, updates, localization));
18822
- }
18823
- });
18824
- }
18825
- }();
18826
- return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(function () {}) : void 0);
18827
- } catch (e) {
18828
- return Promise.reject(e);
19081
+ const [lastFocusedCellIndex, setLastFocusedCellIndex] = React__default.useState(undefined);
19082
+ const pendingChangesFns = usePendingChangesState(handleSave, handleChange, rowIdentityAccessor, validator);
19083
+ function toggleEditing(enabled, table, scrollToIndex) {
19084
+ var _tableMeta$rowActive$, _table$getRowModel$ro;
19085
+ if (!enabled) {
19086
+ // save
19087
+ pendingChangesFns.saveChanges(table);
19088
+ // reset detailed mode
19089
+ toggleDetailedMode(false);
19090
+ // reset the last index back to the first focusable element, when editing gets turned off
19091
+ setLastFocusedCellIndex(undefined);
18829
19092
  }
18830
- }, 250), []);
18831
- function syncCellChanges(changes) {
18832
- updatersRef.current = changes;
18833
- }
18834
- return {
18835
- syncCellChanges,
18836
- runCellUpdates
18837
- };
18838
- }
18839
- function createPendingChangesSetter(currentChanges, row, rowIndex, changes, localization) {
18840
- var _currentChanges$row$i, _currentChanges$row$i2, _currentChanges$row$i3;
18841
- // prepare
18842
- const nextChanges = {
18843
- ...currentChanges
18844
- };
18845
- const rowChanges = {
18846
- ...currentChanges[row.id],
18847
- _meta: {
18848
- ...((_currentChanges$row$i = currentChanges[row.id]) === null || _currentChanges$row$i === void 0 ? void 0 : _currentChanges$row$i._meta),
18849
- original: row.original,
18850
- moveReason: {
18851
- ...((_currentChanges$row$i2 = currentChanges[row.id]) === null || _currentChanges$row$i2 === void 0 ? void 0 : _currentChanges$row$i2._meta.moveReason)
18852
- },
18853
- errors: {
18854
- ...((_currentChanges$row$i3 = currentChanges[row.id]) === null || _currentChanges$row$i3 === void 0 ? void 0 : _currentChanges$row$i3._meta.errors)
18855
- }
19093
+ const tableMeta = table.options.meta;
19094
+ const index = (_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0;
19095
+ if (tableMeta.rowActive.rowActiveIndex === undefined) {
19096
+ tableMeta.rowActive.setRowActiveIndex(index);
18856
19097
  }
18857
- };
18858
- // run changes
18859
- const cells = row._getAllCellsByColumnId();
18860
- for (const [accessor, change] of Object.entries(changes)) {
18861
- // update if the change is different to the original (saved) value,
18862
- // otherwise remove any change - no point saving the same value
18863
- if (change !== row.original[accessor]) {
18864
- rowChanges[accessor] = change;
18865
- // consumers sometimes include properties in onEditingChange that aren't rendered as columns, we need to guard against that.
18866
- // eslint-disable-next-line no-prototype-builtins
18867
- if (cells.hasOwnProperty(accessor)) {
18868
- // determine if the row will move position based on this change, and save why it will move
18869
- const reason = willRowMove(cells[accessor], change, rowIndex, localization);
18870
- if (reason) {
18871
- rowChanges._meta.moveReason[accessor] = reason;
18872
- } else {
18873
- delete rowChanges._meta.moveReason[accessor];
18874
- }
18875
- }
18876
- } else {
18877
- delete rowChanges[accessor];
18878
- delete rowChanges._meta.moveReason[accessor];
19098
+ setEditing(enabled);
19099
+ if (!isTemporaryRow((_table$getRowModel$ro = table.getRowModel().rows[index]) === null || _table$getRowModel$ro === void 0 ? void 0 : _table$getRowModel$ro.id)) {
19100
+ scrollToIndex(index);
18879
19101
  }
18880
19102
  }
18881
- // set changes
18882
- // or delete if there are no changes left, so that we don't store changes with unchanged data
18883
- if (Object.keys(rowChanges).filter(k => k !== '_meta').length) {
18884
- nextChanges[row.id] = rowChanges;
18885
- } else {
18886
- delete nextChanges[row.id];
18887
- }
18888
- return nextChanges;
18889
- }
18890
- function getChangesetFromChanges(changes) {
18891
- // extract the original data from the row changes
18892
- const {
18893
- _meta,
18894
- ...changeset
18895
- } = changes !== null && changes !== void 0 ? changes : {};
18896
- // and mix them in with the changes, ready to send to the server
18897
19103
  return {
18898
- ...(_meta === null || _meta === void 0 ? void 0 : _meta.original),
18899
- ...changeset
19104
+ isEnabled,
19105
+ isEditing,
19106
+ isDetailedMode,
19107
+ toggleDetailedMode: isEnabled ? toggleDetailedMode : () => undefined,
19108
+ toggleEditing: isEnabled ? toggleEditing : () => undefined,
19109
+ lastFocusedCellIndex,
19110
+ setLastFocusedCellIndex,
19111
+ createRowButtonRef,
19112
+ ...pendingChangesFns
18900
19113
  };
18901
19114
  }
18902
19115
 
@@ -18940,7 +19153,6 @@ function RowMoveIndicator(props) {
18940
19153
  if (!show) {
18941
19154
  return null;
18942
19155
  }
18943
- const className = 'wcag-blue-500 absolute left-0 top-full ml-1 whitespace-nowrap rounded-b-md px-1 py-1 text-xs font-bold z-10';
18944
19156
  const {
18945
19157
  title,
18946
19158
  description
@@ -18949,7 +19161,7 @@ function RowMoveIndicator(props) {
18949
19161
  placement: "bottom",
18950
19162
  title: description.replace('[COLUMN]', columnMeta.header)
18951
19163
  }, /*#__PURE__*/React__default.createElement("span", {
18952
- className: className
19164
+ "data-row-move-indicator": true
18953
19165
  }, /*#__PURE__*/React__default.createElement(Icon, {
18954
19166
  name: "info",
18955
19167
  className: "-mt-0.5 mr-1 !h-4 !w-4 rounded-full bg-white !p-0 text-blue-500"
@@ -19138,13 +19350,31 @@ function EditingControlCell(props) {
19138
19350
  const {
19139
19351
  rowIndex
19140
19352
  } = React__default.useContext(RowContext);
19141
- const tableMeta = cell.getContext().table.options.meta;
19353
+ const {
19354
+ table
19355
+ } = cell.getContext();
19356
+ const tableMeta = table.options.meta;
19142
19357
  const columnMeta = cell.column.columnDef.meta;
19143
19358
  const isActiveRow = tableMeta.rowActive.rowActiveIndex === rowIndex;
19359
+ const type = (_columnMeta$control = columnMeta.control) !== null && _columnMeta$control !== void 0 ? _columnMeta$control : 'input';
19144
19360
  const handleFocus = useEditingCellAutofocus(props);
19361
+ const value = cell.getValue();
19362
+ // some controls, like select2, should trigger cell changed (validation, updates) as the value changes
19363
+ const hasNonTextControl = React__default.useMemo(() => {
19364
+ var _cellRef$current;
19365
+ return typeof type === 'function' && !!((_cellRef$current = cellRef.current) !== null && _cellRef$current !== void 0 && _cellRef$current.querySelector('[data-taco="Select2"],[data-taco="switch"],[data-taco="checkbox"]'));
19366
+ }, [cellRef.current]);
19367
+ const handleChange = nextValue => {
19368
+ if (nextValue !== value) {
19369
+ tableMeta.editing.setCellValue(cell, nextValue);
19370
+ if (hasNonTextControl) {
19371
+ tableMeta.editing.onCellChanged(cell, rowIndex);
19372
+ }
19373
+ }
19374
+ };
19145
19375
  const handleBlur = () => {
19146
19376
  tableMeta.editing.toggleDetailedMode(false);
19147
- tableMeta.editing.validateCell(cell);
19377
+ tableMeta.editing.onCellChanged(cell, rowIndex, !hasNonTextControl);
19148
19378
  };
19149
19379
  // ensure that blur runs when the cell gets unmounted (when vertically arrow key navigating)
19150
19380
  React__default.useEffect(() => {
@@ -19164,14 +19394,13 @@ function EditingControlCell(props) {
19164
19394
  isDetailedMode: tableMeta.editing.isDetailedMode,
19165
19395
  isTruncated: !!columnMeta.enableTruncate,
19166
19396
  onBlur: handleBlur,
19167
- onChange: value => tableMeta.editing.setCellValue(cell, value, rowIndex),
19397
+ onChange: handleChange,
19168
19398
  row: cell.row.original,
19169
- rowPendingChanges: tableMeta.editing.getRowPendingChange(cell.row.id),
19399
+ rowPendingChanges: tableMeta.editing.getRowValue(cell.row.id),
19170
19400
  tabIndex: isActiveRow ? 0 : -1,
19171
- toggleEditing: tableMeta.editing.toggleEditing,
19172
19401
  toggleDetailedMode: tableMeta.editing.toggleDetailedMode,
19173
- type: (_columnMeta$control = columnMeta.control) !== null && _columnMeta$control !== void 0 ? _columnMeta$control : 'input',
19174
- value: cell.getValue()
19402
+ type,
19403
+ value
19175
19404
  };
19176
19405
  const cellAttributes = {
19177
19406
  ...getCellAttributes(cell, index, isHighlighted),
@@ -19203,7 +19432,6 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19203
19432
  row,
19204
19433
  rowPendingChanges,
19205
19434
  tabIndex = -1,
19206
- toggleEditing,
19207
19435
  toggleDetailedMode,
19208
19436
  type = 'input',
19209
19437
  value
@@ -19234,6 +19462,13 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19234
19462
  ref: controlRef
19235
19463
  }));
19236
19464
  }
19465
+ if (type === 'checkbox') {
19466
+ return /*#__PURE__*/React__default.createElement(Checkbox, Object.assign({}, commonProps, {
19467
+ checked: Boolean(value),
19468
+ onChange: onChange,
19469
+ ref: controlRef
19470
+ }));
19471
+ }
19237
19472
  const handleInputKeyDown = event => {
19238
19473
  const target = event.target;
19239
19474
  if (target.readOnly) {
@@ -19262,8 +19497,8 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19262
19497
  }
19263
19498
  // reset the value, or exit edit mode when pressing escape
19264
19499
  if (event.key === 'Escape') {
19265
- event.preventDefault();
19266
19500
  if (isDetailedMode) {
19501
+ event.preventDefault();
19267
19502
  toggleDetailedMode(false);
19268
19503
  if (value !== currentValue) {
19269
19504
  props.onChange(currentValue);
@@ -19273,8 +19508,6 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19273
19508
  var _target$select2;
19274
19509
  return (_target$select2 = target.select) === null || _target$select2 === void 0 ? void 0 : _target$select2.call(target);
19275
19510
  });
19276
- } else {
19277
- toggleEditing(false);
19278
19511
  }
19279
19512
  return;
19280
19513
  }
@@ -19373,12 +19606,37 @@ function Cell$5(props) {
19373
19606
  return /*#__PURE__*/React__default.createElement(DisplayCell, Object.assign({}, props));
19374
19607
  }
19375
19608
 
19376
- function EditingActionMenu(props) {
19609
+ function DiscardChangesConfirmationDialog(props) {
19610
+ const {
19611
+ onDiscard: handleDiscard,
19612
+ ...dialogProps
19613
+ } = props;
19614
+ const {
19615
+ texts
19616
+ } = useLocalization();
19617
+ const handleClickInsideDialogContent = event => {
19618
+ // Prevents the click event from propagating to the table, ensuring the row isn't saved when a click occurs
19619
+ // inside the dialog
19620
+ event.stopPropagation();
19621
+ };
19622
+ return /*#__PURE__*/React__default.createElement(Dialog, Object.assign({}, dialogProps), /*#__PURE__*/React__default.createElement(Dialog.Content, {
19623
+ "aria-label": texts.table3.editing.clearChangesConfirmationDialog.title,
19624
+ onClick: handleClickInsideDialogContent
19625
+ }, /*#__PURE__*/React__default.createElement(Dialog.Title, null, texts.table3.editing.clearChangesConfirmationDialog.title), /*#__PURE__*/React__default.createElement("p", null, texts.table3.editing.clearChangesConfirmationDialog.description), /*#__PURE__*/React__default.createElement(Dialog.Footer, null, /*#__PURE__*/React__default.createElement(Group, null, /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19626
+ tabIndex: 0
19627
+ }, texts.table3.editing.clearChangesConfirmationDialog.cancel)), /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19628
+ autoFocus: true,
19629
+ tabIndex: 0,
19630
+ appearance: "primary",
19631
+ onClick: handleDiscard
19632
+ }, texts.table3.editing.clearChangesConfirmationDialog.confirm))))));
19633
+ }
19634
+
19635
+ function EditingActionsMenu(props) {
19377
19636
  const {
19378
19637
  hasChanges,
19379
19638
  hasErrors,
19380
- onClear: handleClear,
19381
- onExit: handleExit,
19639
+ onDiscard: handleDiscard,
19382
19640
  onEditingSave: handleSave,
19383
19641
  isLastRow
19384
19642
  } = props;
@@ -19400,7 +19658,6 @@ function EditingActionMenu(props) {
19400
19658
  return /*#__PURE__*/React__default.createElement(IconButton, {
19401
19659
  appearance: "transparent",
19402
19660
  "aria-label": texts.table3.editing.actions.tooltip,
19403
- className: "group-[[data-row-editing-status]]/row:hidden",
19404
19661
  icon: "more",
19405
19662
  onKeyDown: handleKeyDown,
19406
19663
  menu: menuProps => (/*#__PURE__*/React__default.createElement(Menu$1, Object.assign({}, menuProps), /*#__PURE__*/React__default.createElement(Menu$1.Content, {
@@ -19412,42 +19669,13 @@ function EditingActionMenu(props) {
19412
19669
  }, texts.table3.editing.actions.save), /*#__PURE__*/React__default.createElement(Menu$1.Item, {
19413
19670
  icon: "close",
19414
19671
  disabled: !hasChanges,
19415
- dialog: props => /*#__PURE__*/React__default.createElement(ConfirmClearChangesDialog, Object.assign({}, props, {
19416
- onClear: handleClear
19672
+ dialog: props => /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, Object.assign({}, props, {
19673
+ onDiscard: handleDiscard
19417
19674
  }))
19418
- }, texts.table3.editing.actions.clear), /*#__PURE__*/React__default.createElement(Menu$1.Item, {
19419
- icon: "undo",
19420
- onClick: handleExit
19421
- }, texts.table3.editing.actions.exit))))
19675
+ }, texts.table3.editing.actions.clear))))
19422
19676
  });
19423
19677
  }
19424
- function ConfirmClearChangesDialog(props) {
19425
- const {
19426
- onClear: handleClear,
19427
- ...dialogProps
19428
- } = props;
19429
- const {
19430
- texts
19431
- } = useLocalization();
19432
- const handleClickInsideDialogContent = event => {
19433
- // Prevents the click event from propagating to the table, ensuring the row isn't saved when a click occurs
19434
- // inside the dialog
19435
- event.stopPropagation();
19436
- };
19437
- return /*#__PURE__*/React__default.createElement(Dialog, Object.assign({}, dialogProps), /*#__PURE__*/React__default.createElement(Dialog.Content, {
19438
- "aria-label": texts.table3.editing.clearChangesConfirmationDialog.title,
19439
- onClick: handleClickInsideDialogContent
19440
- }, /*#__PURE__*/React__default.createElement(Dialog.Title, null, texts.table3.editing.clearChangesConfirmationDialog.title), /*#__PURE__*/React__default.createElement("p", null, texts.table3.editing.clearChangesConfirmationDialog.description), /*#__PURE__*/React__default.createElement(Dialog.Footer, null, /*#__PURE__*/React__default.createElement(Group, null, /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19441
- tabIndex: 0
19442
- }, texts.table3.editing.clearChangesConfirmationDialog.cancel)), /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19443
- autoFocus: true,
19444
- tabIndex: 0,
19445
- appearance: "primary",
19446
- onClick: handleClear
19447
- }, texts.table3.editing.clearChangesConfirmationDialog.confirm))))));
19448
- }
19449
19678
 
19450
- const COMPLETE_INDICATOR_DELAY = 3000;
19451
19679
  function SaveStatus(props) {
19452
19680
  const {
19453
19681
  rowId,
@@ -19457,18 +19685,7 @@ function SaveStatus(props) {
19457
19685
  texts
19458
19686
  } = useLocalization();
19459
19687
  const tableMeta = table.options.meta;
19460
- const status = tableMeta.editing.getRowSaveStatus(rowId);
19461
- React__default.useEffect(() => {
19462
- let timeout;
19463
- if (status === 'complete') {
19464
- timeout = window.setTimeout(() => {
19465
- tableMeta.editing.setRowSaveStatus(rowId, undefined);
19466
- }, COMPLETE_INDICATOR_DELAY);
19467
- }
19468
- return () => {
19469
- clearTimeout(timeout);
19470
- };
19471
- }, [status]);
19688
+ const status = tableMeta.editing.getRowStatus(rowId);
19472
19689
  const className = cn('col-span-full sticky ml-auto right-0 top-0 -mb-[100%] z-10 h-8 bg-[inherit] flex items-center px-1.5 shadow-[-6px_0px_6px_var(--table-row-actions-shadow)]', {
19473
19690
  'mt-0.5': tableMeta.rowHeight.height === 'short',
19474
19691
  'mt-1': tableMeta.rowHeight.height === 'medium',
@@ -19479,7 +19696,7 @@ function SaveStatus(props) {
19479
19696
  className: "!contents"
19480
19697
  }, /*#__PURE__*/React__default.createElement("span", {
19481
19698
  className: className
19482
- }, status === 'pending' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19699
+ }, status === 'saving' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19483
19700
  title: texts.table3.editing.saving.progress
19484
19701
  }, /*#__PURE__*/React__default.createElement(Spinner, {
19485
19702
  delay: 0,
@@ -19520,15 +19737,46 @@ function Row$2(props) {
19520
19737
  }
19521
19738
  }
19522
19739
  }, [tableMeta.editing.isEditing, isActiveRow]);
19740
+ const rowStatus = tableMeta.editing.getRowStatus(row.id);
19741
+ // discard new row
19742
+ const [showDiscardDialog, setShowDiscardDialog] = React__default.useState(false);
19743
+ function handleDiscard() {
19744
+ tableMeta.editing.discardChanges(row.id, table);
19745
+ requestAnimationFrame(() => {
19746
+ if (isTemporaryRow(row.id)) {
19747
+ var _tableMeta$editing$cr;
19748
+ (_tableMeta$editing$cr = tableMeta.editing.createRowButtonRef.current) === null || _tableMeta$editing$cr === void 0 ? void 0 : _tableMeta$editing$cr.focus();
19749
+ } else {
19750
+ focusManager.focusFirst();
19751
+ }
19752
+ });
19753
+ }
19754
+ function handleKeyDown(event) {
19755
+ if (props.onKeyDown) {
19756
+ props.onKeyDown(event);
19757
+ }
19758
+ if (event.isDefaultPrevented() || event.isPropagationStopped()) {
19759
+ return;
19760
+ }
19761
+ if (event.key === 'Escape' && tableMeta.editing.hasChanges(row.id) && !isElementTriggeredFromContainer(event.target, event.currentTarget)) {
19762
+ event.preventDefault();
19763
+ setShowDiscardDialog(true);
19764
+ }
19765
+ }
19523
19766
  const attributes = {
19524
- 'data-row-editing-invalid': tableMeta.editing.isEnabled && tableMeta.editing.hasRowErrors(row.id) ? !tableMeta.editing.hasRowErrorsSeen(row.id) ? 'unseen' : true : undefined,
19525
- 'data-row-editing-status': tableMeta.editing.isEnabled && tableMeta.editing.getRowSaveStatus(row.id) ? tableMeta.editing.getRowSaveStatus(row.id) : undefined,
19526
- onFocus: handleFocus
19767
+ 'data-row-editing-invalid': tableMeta.editing.hasRowErrors(row.id) ? !tableMeta.editing.hasRowErrorsShownInAlert(row.id) ? 'unseen' : true : undefined,
19768
+ 'data-row-editing-status': rowStatus,
19769
+ onFocus: handleFocus,
19770
+ onKeyDown: handleKeyDown
19527
19771
  };
19528
- return /*#__PURE__*/React__default.createElement(DisplayRow, Object.assign({}, props, attributes), tableMeta.editing.getRowSaveStatus(row.id) ? /*#__PURE__*/React__default.createElement(SaveStatus, {
19772
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(DisplayRow, Object.assign({}, props, attributes), rowStatus === 'saving' || rowStatus === 'saved' ? /*#__PURE__*/React__default.createElement(SaveStatus, {
19529
19773
  rowId: row.id,
19530
19774
  table: table
19531
- }) : null);
19775
+ }) : null), /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, {
19776
+ open: showDiscardDialog,
19777
+ onChange: setShowDiscardDialog,
19778
+ onDiscard: handleDiscard
19779
+ }));
19532
19780
  }
19533
19781
 
19534
19782
  const RENDERERS$1 = {
@@ -19536,29 +19784,59 @@ const RENDERERS$1 = {
19536
19784
  cell: Cell$5
19537
19785
  };
19538
19786
  function useTable3(props, ref) {
19539
- const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.validator);
19787
+ const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.rowIdentityAccessor, props.validator);
19540
19788
  const creationEnabled = editing.isEnabled && !!props.onEditingCreate;
19789
+ // this gives me the performance heeby jeebies, but can't think of a better way to internalise the state
19790
+ const data = React__default.useMemo(() => {
19791
+ if (editing.temporaryRows.length) {
19792
+ var _props$data;
19793
+ return ((_props$data = props.data) !== null && _props$data !== void 0 ? _props$data : []).concat(editing.temporaryRows);
19794
+ }
19795
+ return props.data;
19796
+ }, [JSON.stringify(props.data), editing.temporaryRows.length]);
19541
19797
  const extendedProps = {
19542
19798
  ...props,
19799
+ data,
19543
19800
  enableRowActions: editing.isEditing ? true : props.enableRowActions,
19544
- rowActions: editing.isEditing ? [(_, rowId) => (/*#__PURE__*/React__default.createElement(EditingActionMenu, {
19545
- hasChanges: editing.hasChanges(rowId),
19546
- hasErrors: editing.hasRowErrors(rowId),
19547
- onClear: () => editing.resetChanges(rowId),
19548
- onEditingSave: () => editing.saveChanges(rowId),
19549
- onExit: () => editing.toggleEditing(false),
19550
- isLastRow: !creationEnabled && table.meta.rowActive.rowActiveIndex === table.meta.length - 1
19551
- }))] : props.rowActions
19801
+ // Display EditingActionMenu instead of row actions while editing
19802
+ rowActions: editing.isEditing ? [(_, rowId, table) => {
19803
+ const tableMeta = table.options.meta;
19804
+ return /*#__PURE__*/React__default.createElement(EditingActionsMenu, {
19805
+ hasChanges: editing.hasChanges(rowId),
19806
+ hasErrors: editing.hasRowErrors(rowId),
19807
+ onDiscard: () => {
19808
+ if (editing.temporaryRows.length) {
19809
+ tableMeta.rowActive.setRowActiveIndex(undefined);
19810
+ setTimeout(() => {
19811
+ var _editing$createRowBut;
19812
+ return (_editing$createRowBut = editing.createRowButtonRef.current) === null || _editing$createRowBut === void 0 ? void 0 : _editing$createRowBut.focus();
19813
+ }, 50);
19814
+ }
19815
+ editing.discardChanges(rowId, table);
19816
+ },
19817
+ onEditingSave: function () {
19818
+ try {
19819
+ return Promise.resolve(editing.saveChanges(table, rowId)).then(function () {});
19820
+ } catch (e) {
19821
+ return Promise.reject(e);
19822
+ }
19823
+ },
19824
+ isLastRow: !creationEnabled && tableMeta.rowActive.rowActiveIndex === tableMeta.length - 1
19825
+ });
19826
+ }] : props.rowActions
19552
19827
  };
19553
19828
  const meta = {
19554
19829
  editing
19555
19830
  };
19556
- const table = useTable(extendedProps, ref, RENDERERS$1, meta);
19831
+ const options = {
19832
+ virtualiserPaddingEndOffset: props.enableEditing && props.onEditingCreate ? editing.hasTemporaryRowErrors() ? 1.4 : 1 : 0
19833
+ };
19834
+ const table = useTable(extendedProps, ref, RENDERERS$1, meta, options);
19557
19835
  // listeners
19558
- useTableEditingListener(table.instance, table.ref);
19836
+ useTableEditingListener(table.instance, table.ref, table.renderer.scrollToIndex);
19559
19837
  React__default.useEffect(() => {
19560
19838
  if (table.ref.current) {
19561
- table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing);
19839
+ table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing, table.instance, table.renderer.scrollToIndex);
19562
19840
  }
19563
19841
  }, [table.ref.current]);
19564
19842
  return table;
@@ -19577,7 +19855,7 @@ function Alert$1(props) {
19577
19855
  const validationTexts = texts.table3.editing.validation;
19578
19856
  const tableMeta = table.options.meta;
19579
19857
  const [showFilterResetDialog, setShowFilterResetDialog] = React__default.useState(false);
19580
- const pendingChangesWithErrors = tableMeta.editing.getAlertErrors();
19858
+ const pendingChangesWithErrors = tableMeta.editing.getErrorsShownInAlert();
19581
19859
  function scrollToRow(rowIndex) {
19582
19860
  tableMeta.rowActive.setRowActiveIndex(rowIndex);
19583
19861
  scrollToIndex(rowIndex, {
@@ -19596,38 +19874,43 @@ function Alert$1(props) {
19596
19874
  const title = (pendingChangesWithErrors.length === 1 ? validationTexts.alert.titleOne : validationTexts.alert.titlePlural).replace('[COUNT]', String(pendingChangesWithErrors.length));
19597
19875
  // generate links to each invalid row, to go into the error message
19598
19876
  const links = [];
19599
- const rowIdentityColumn = tableMeta.rowIdentityColumnId ? table.getColumn(tableMeta.rowIdentityColumnId) : undefined;
19600
- pendingChangesWithErrors.forEach((error, index) => {
19877
+ const visibleColumns = table.getVisibleFlatColumns().map(c => c.id);
19878
+ const rowIdentityColumn = tableMeta.rowIdentityAccessor && visibleColumns.includes(String(tableMeta.rowIdentityAccessor)) ? table.getColumn(String(tableMeta.rowIdentityAccessor)) : undefined;
19879
+ pendingChangesWithErrors.forEach((pendingChangeWithError, index) => {
19601
19880
  // if appropriate, concatenate the item with the text "and"
19602
19881
  if (pendingChangesWithErrors.length > 1 && index === pendingChangesWithErrors.length - 1) {
19603
19882
  // Add space before and after `messageAnd` text
19604
19883
  links.push(` ${validationTexts.alert.messageAnd} `);
19605
19884
  }
19606
- const rowIndex = table.getRowModel().rows.findIndex(row => row.id === error.rowId);
19885
+ const rowIndex = table.getRowModel().rows.findIndex(row => row.id === pendingChangeWithError.rowId);
19607
19886
  const handleClick = () => {
19887
+ // if row is visible
19608
19888
  if (rowIndex > -1) {
19609
19889
  scrollToRow(rowIndex);
19610
- } else {
19611
- setShowFilterResetDialog(error.rowId);
19890
+ }
19891
+ // if row is filtered out
19892
+ else {
19893
+ setShowFilterResetDialog(pendingChangeWithError.rowId);
19612
19894
  }
19613
19895
  };
19614
19896
  let tooltip;
19615
- if (error.pendingChange._meta.errors.row) {
19616
- tooltip = error.pendingChange._meta.errors.row;
19897
+ if (pendingChangeWithError.errors.row) {
19898
+ tooltip = pendingChangeWithError.errors.row;
19617
19899
  } else {
19618
19900
  var _table$getAllColumns$, _table$getAllColumns$2;
19619
- const firstCellErrorColumnId = Object.keys(error.pendingChange._meta.errors.cells)[0];
19901
+ const firstCellErrorColumnId = Object.keys(pendingChangeWithError.errors.cells)[0];
19620
19902
  const columnName = (_table$getAllColumns$ = table.getAllColumns().find(column => column.id === firstCellErrorColumnId)) === null || _table$getAllColumns$ === void 0 ? void 0 : (_table$getAllColumns$2 = _table$getAllColumns$.columnDef.meta) === null || _table$getAllColumns$2 === void 0 ? void 0 : _table$getAllColumns$2.header;
19621
- tooltip = `${columnName}: ${error.pendingChange._meta.errors.cells[firstCellErrorColumnId]}`;
19903
+ tooltip = `${columnName}: ${pendingChangeWithError.errors.cells[firstCellErrorColumnId]}`;
19622
19904
  }
19905
+ const row = table.getRow(pendingChangeWithError.rowId).original;
19623
19906
  links.push(/*#__PURE__*/React__default.createElement(Tooltip, {
19624
- key: error.rowId,
19907
+ key: pendingChangeWithError.rowId,
19625
19908
  title: tooltip
19626
19909
  }, /*#__PURE__*/React__default.createElement("span", {
19627
19910
  className: "text-blue",
19628
19911
  onClick: handleClick,
19629
19912
  role: "button"
19630
- }, rowIdentityColumn ? error.pendingChange._meta.original[rowIdentityColumn.id] : rowIndex + 1)));
19913
+ }, rowIdentityColumn ? row[rowIdentityColumn.id] : rowIndex + 1)));
19631
19914
  // if appropriate, concatenate the item with the text ","
19632
19915
  if (pendingChangesWithErrors.length > 2 && index < pendingChangesWithErrors.length - 2) {
19633
19916
  links.push(', ');
@@ -19683,127 +19966,213 @@ function FilterResetDialog(props) {
19683
19966
  }, texts.table3.editing.validation.resetFiltersDialog.confirm)))));
19684
19967
  }
19685
19968
 
19686
- function CreateNewRowButton(props) {
19969
+ function Editing(props) {
19687
19970
  const {
19688
- onEditingCreate,
19689
19971
  scrollToIndex,
19690
- table,
19691
- tableMeta
19972
+ table
19692
19973
  } = props;
19693
19974
  const {
19694
19975
  texts
19695
19976
  } = useLocalization();
19696
- const rows = table.getCoreRowModel().rows.filter(row => row.original !== undefined);
19697
- const [rowCreated, setRowCreated] = React__default.useState({
19698
- rowFinder: undefined
19699
- });
19700
- const handleKeyDown = event => {
19701
- if (!tableMeta.editing.hasChanges() && event.key === 'Tab') {
19702
- tableMeta.editing.saveChanges();
19703
- }
19977
+ const ref = React__default.useRef(null);
19978
+ const tableMeta = table.options.meta;
19979
+ const handleChange = enabled => {
19980
+ tableMeta.editing.toggleEditing(enabled, table, scrollToIndex);
19704
19981
  };
19705
- const handleCreate = function () {
19982
+ const tooltip = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, texts.table3.editing.buttons.edit.tooltip, /*#__PURE__*/React__default.createElement(Shortcut, {
19983
+ className: "ml-2",
19984
+ keys: shortcut
19985
+ }));
19986
+ return /*#__PURE__*/React__default.createElement(Tooltip, {
19987
+ title: tooltip
19988
+ }, /*#__PURE__*/React__default.createElement(ModeSwitch, {
19989
+ "data-table": "editing-toggle",
19990
+ checked: tableMeta.editing.isEditing,
19991
+ onChange: handleChange,
19992
+ ref: ref
19993
+ }));
19994
+ }
19995
+
19996
+ function CreateNewRow(props) {
19997
+ var _temporaryRows$0$tabl, _temporaryRows$, _table$getState$colum, _tableRef$current2;
19998
+ const {
19999
+ buttonRef,
20000
+ onEditingCreate: handleEditingCreate,
20001
+ scrollToIndex,
20002
+ table,
20003
+ tableMeta,
20004
+ tableRef
20005
+ } = props;
20006
+ const {
20007
+ texts
20008
+ } = useLocalization();
20009
+ const temporaryRows = tableMeta.editing.temporaryRows;
20010
+ const temporaryRowId = (_temporaryRows$0$tabl = (_temporaryRows$ = temporaryRows[0]) === null || _temporaryRows$ === void 0 ? void 0 : _temporaryRows$[tableMeta.rowIdentityAccessor]) !== null && _temporaryRows$0$tabl !== void 0 ? _temporaryRows$0$tabl : '';
20011
+ const isDisabled = !!table.getState().globalFilter || !!((_table$getState$colum = table.getState().columnFilters) !== null && _table$getState$colum !== void 0 && _table$getState$colum.length) || !!temporaryRowId && !!tableMeta.editing.hasRowErrors(temporaryRowId);
20012
+ const isSaving = !!temporaryRowId && tableMeta.editing.getRowStatus(temporaryRowId) === 'saving';
20013
+ const createRow = function (row) {
19706
20014
  try {
19707
- if (!onEditingCreate) {
20015
+ if (!handleEditingCreate || isDisabled) {
19708
20016
  return Promise.resolve();
19709
20017
  }
19710
- const createdRow = rows.find(row => {
19711
- var _rowCreated$rowFinder;
19712
- return rowCreated === null || rowCreated === void 0 ? void 0 : (_rowCreated$rowFinder = rowCreated.rowFinder) === null || _rowCreated$rowFinder === void 0 ? void 0 : _rowCreated$rowFinder.call(rowCreated, row.original);
19713
- });
19714
- const _temp = function () {
19715
- if (createdRow) {
19716
- return Promise.resolve(tableMeta.editing.saveChanges()).then(function () {
19717
- if (!tableMeta.editing.hasRowErrors(createdRow.id)) {
19718
- const rowFinder = onEditingCreate();
19719
- setRowCreated({
19720
- rowFinder
19721
- });
19722
- }
19723
- });
19724
- } else {
19725
- const rowFinder = onEditingCreate();
19726
- setRowCreated({
19727
- rowFinder
19728
- });
20018
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
20019
+ if (!saved) {
20020
+ return;
19729
20021
  }
19730
- }();
19731
- return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
20022
+ const changeset = row !== null && row !== void 0 ? row : handleEditingCreate();
20023
+ try {
20024
+ if (changeset) {
20025
+ const rowId = tableMeta.editing.createRow(changeset);
20026
+ table.getRow(rowId).pin('bottom');
20027
+ // set the active row to the new row before toggling editing on
20028
+ const nextRowIndex = temporaryRows.length ? tableMeta.length + 1 : tableMeta.length;
20029
+ tableMeta.rowActive.setRowActiveIndex(nextRowIndex);
20030
+ tableMeta.editing.toggleEditing(true, table, scrollToIndex);
20031
+ tableMeta.editing.setLastFocusedCellIndex(0);
20032
+ }
20033
+ } catch (error) {
20034
+ console.error(error);
20035
+ }
20036
+ });
19732
20037
  } catch (e) {
19733
20038
  return Promise.reject(e);
19734
20039
  }
19735
20040
  };
20041
+ // allow programmatic access to creating rows from outside the table
19736
20042
  React__default.useEffect(() => {
19737
- if (typeof (rowCreated === null || rowCreated === void 0 ? void 0 : rowCreated.rowFinder) === 'function') {
19738
- const createdRow = rows.find(row => {
19739
- var _rowCreated$rowFinder2;
19740
- return rowCreated === null || rowCreated === void 0 ? void 0 : (_rowCreated$rowFinder2 = rowCreated.rowFinder) === null || _rowCreated$rowFinder2 === void 0 ? void 0 : _rowCreated$rowFinder2.call(rowCreated, row.original);
19741
- });
19742
- if (createdRow) {
19743
- const rowInTable = table.getRowModel().rows.filter(row => row.original !== undefined).find(row => {
19744
- var _rowCreated$rowFinder3;
19745
- return rowCreated === null || rowCreated === void 0 ? void 0 : (_rowCreated$rowFinder3 = rowCreated.rowFinder) === null || _rowCreated$rowFinder3 === void 0 ? void 0 : _rowCreated$rowFinder3.call(rowCreated, row.original);
19746
- });
19747
- if (rowInTable) {
19748
- tableMeta.editing.toggleEditing(true);
19749
- tableMeta.rowActive.setRowActiveIndex(createdRow.index);
19750
- scrollToIndex(createdRow.index);
19751
- requestAnimationFrame(() => animateCreateRow(createdRow.id));
19752
- }
19753
- requestAnimationFrame(() => tableMeta.editing.addCreatedRowChangeset(createdRow));
19754
- }
20043
+ var _tableRef$current;
20044
+ if (tableRef !== null && tableRef !== void 0 && (_tableRef$current = tableRef.current) !== null && _tableRef$current !== void 0 && _tableRef$current.instance) {
20045
+ tableRef.current.instance.createRow = createRow;
19755
20046
  }
19756
- }, [rowCreated]);
20047
+ }, [tableRef === null || tableRef === void 0 ? void 0 : (_tableRef$current2 = tableRef.current) === null || _tableRef$current2 === void 0 ? void 0 : _tableRef$current2.instance, createRow]);
20048
+ const handleCreate = function () {
20049
+ return createRow();
20050
+ };
20051
+ const shortcut = {
20052
+ key: 'Enter',
20053
+ meta: true
20054
+ };
20055
+ let tooltip;
20056
+ if (isSaving) {
20057
+ tooltip = texts.table3.editing.buttons.create.saving;
20058
+ } else if (isDisabled) {
20059
+ tooltip = texts.table3.editing.buttons.create.disabled;
20060
+ } else {
20061
+ tooltip = /*#__PURE__*/React__default.createElement(Shortcut, {
20062
+ keys: shortcut
20063
+ });
20064
+ }
20065
+ const isScrolled = tableRef.current ? tableRef.current.scrollHeight > tableRef.current.clientHeight : false;
20066
+ const className = cn('group/row border-grey-300 !sticky z-[21]', {
20067
+ 'bottom-10': tableMeta.footer.isEnabled,
20068
+ 'bottom-0': !tableMeta.footer.isEnabled,
20069
+ 'border-t-2': isScrolled,
20070
+ 'border-b': !isScrolled
20071
+ });
19757
20072
  return /*#__PURE__*/React__default.createElement("tr", {
19758
- onClick: handleCreate,
19759
- className: "border-grey-300 hover:bg-grey-100 group !sticky bottom-10 left-0 z-[21] !block cursor-pointer border-t"
20073
+ "data-row-create": true,
20074
+ className: className,
20075
+ tabIndex: -1
19760
20076
  }, /*#__PURE__*/React__default.createElement("td", {
19761
- className: "!border-t-0 !bg-transparent"
20077
+ className: "!bg-grey-50 col-span-full !border-b-0 !px-1"
19762
20078
  }, /*#__PURE__*/React__default.createElement(Button$1, {
19763
- onKeyDown: handleKeyDown,
19764
- className: "group-hover:bg-grey-200 sticky left-0",
19765
- appearance: "transparent"
19766
- }, "+ ", texts.table3.editing.buttons.create.label)));
20079
+ appearance: "transparent",
20080
+ className: "group-hover:bg-grey-200 sticky left-[4px]",
20081
+ disabled: isDisabled,
20082
+ onClick: handleCreate,
20083
+ ref: buttonRef,
20084
+ shortcut: shortcut,
20085
+ tooltip: tooltip
20086
+ }, /*#__PURE__*/React__default.createElement(Icon, {
20087
+ name: "circle-plus"
20088
+ }), texts.table3.editing.buttons.create.label)));
19767
20089
  }
19768
20090
 
19769
- function Editing(props) {
20091
+ function TemporaryRow(props) {
19770
20092
  const {
19771
- scrollToIndex,
19772
- table
20093
+ createRowButtonRef,
20094
+ table,
20095
+ tableMeta,
20096
+ tableRef
19773
20097
  } = props;
19774
- const {
19775
- texts
19776
- } = useLocalization();
19777
- const ref = React__default.useRef(null);
19778
- const tableMeta = table.options.meta;
19779
- const shortcut = {
19780
- key: 'e',
19781
- meta: true,
19782
- shift: false
20098
+ const handleKeyDown = function (event) {
20099
+ try {
20100
+ const _temp2 = function () {
20101
+ if (event.key === 'ArrowDown') {
20102
+ event.preventDefault();
20103
+ const _temp = function () {
20104
+ if (!isElementTriggeredFromContainer(event.target, event.currentTarget)) {
20105
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
20106
+ if (saved) {
20107
+ var _createRowButtonRef$c;
20108
+ (_createRowButtonRef$c = createRowButtonRef.current) === null || _createRowButtonRef$c === void 0 ? void 0 : _createRowButtonRef$c.focus();
20109
+ }
20110
+ });
20111
+ }
20112
+ }();
20113
+ if (_temp && _temp.then) return _temp.then(function () {});
20114
+ } else if (event.key === 'ArrowUp') {
20115
+ event.preventDefault();
20116
+ event.stopPropagation();
20117
+ if (tableRef.current) {
20118
+ var _tableRef$current$que, _tableRef$current$que2, _tableRef$current$que3;
20119
+ const availableRows = Array.from((_tableRef$current$que = tableRef.current.querySelectorAll(`tbody tr:not([data-row-id^='${TEMPORARY_ROW_ID_PREFIX}'])`)) !== null && _tableRef$current$que !== void 0 ? _tableRef$current$que : []);
20120
+ const footerHeight = (_tableRef$current$que2 = (_tableRef$current$que3 = tableRef.current.querySelector('tfoot')) === null || _tableRef$current$que3 === void 0 ? void 0 : _tableRef$current$que3.getBoundingClientRect().height) !== null && _tableRef$current$que2 !== void 0 ? _tableRef$current$que2 : 0;
20121
+ const newRowHeight = event.currentTarget.getBoundingClientRect().height;
20122
+ const visibleHeight = tableRef.current.clientHeight - footerHeight - newRowHeight;
20123
+ const tableTopOffset = tableRef.current.getBoundingClientRect().top;
20124
+ let nextRowIndex;
20125
+ // iterate available rows in reverse order, since we're working at the bottom
20126
+ for (let index = availableRows.length - 1; index >= 0; index--) {
20127
+ const rowRect = availableRows[index].getBoundingClientRect();
20128
+ const topPlusHalfRow = rowRect.top + rowRect.height / 2;
20129
+ if (topPlusHalfRow - tableTopOffset <= visibleHeight) {
20130
+ nextRowIndex = index;
20131
+ break;
20132
+ }
20133
+ }
20134
+ if (nextRowIndex) {
20135
+ tableMeta.rowActive.setRowActiveIndex(Number(availableRows[nextRowIndex < 0 ? 0 : nextRowIndex].getAttribute('data-row-index')));
20136
+ }
20137
+ }
20138
+ }
20139
+ }();
20140
+ return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {}) : void 0);
20141
+ } catch (e) {
20142
+ return Promise.reject(e);
20143
+ }
19783
20144
  };
19784
- const tooltip = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, texts.table3.editing.buttons.edit.tooltip, /*#__PURE__*/React__default.createElement(Shortcut, {
19785
- className: "ml-2",
19786
- keys: shortcut
19787
- }));
19788
- useGlobalKeyDown(shortcut, event => {
19789
- var _ref$current;
19790
- event.preventDefault();
19791
- (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.click();
19792
- });
19793
- const handleChange = enabled => {
19794
- tableMeta.editing.toggleEditing(enabled);
19795
- requestAnimationFrame(() => {
19796
- var _tableMeta$rowActive$;
19797
- return scrollToIndex((_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0);
19798
- });
20145
+ const handleKeyDownCapture = event => {
20146
+ if (event.key === 'ArrowLeft' && tableMeta.editing.lastFocusedCellIndex === 0) {
20147
+ event.preventDefault();
20148
+ event.stopPropagation();
20149
+ } else if (event.key === 'ArrowRight' && tableMeta.editing.lastFocusedCellIndex) {
20150
+ if (tableMeta.editing.lastFocusedCellIndex === table.getVisibleFlatColumns().length - 1) {
20151
+ event.preventDefault();
20152
+ event.stopPropagation();
20153
+ }
20154
+ }
19799
20155
  };
19800
- return /*#__PURE__*/React__default.createElement(Tooltip, {
19801
- title: tooltip
19802
- }, /*#__PURE__*/React__default.createElement(ModeSwitch, {
19803
- checked: tableMeta.editing.isEditing,
19804
- onChange: handleChange,
19805
- ref: ref
19806
- }));
20156
+ const isScrolled = tableRef.current ? tableRef.current.scrollHeight > tableRef.current.clientHeight : false;
20157
+ const className = cn('group/row border-grey-300 !sticky z-[22]', {
20158
+ 'bottom-[calc(5rem_+_3px)] data-[row-editing-move]:bottom-[calc(5rem_+_2px)]': tableMeta.footer.isEnabled,
20159
+ 'bottom-[calc(2.5rem_+_3px)] data-[row-editing-move]:bottom-[calc(2.5rem_+_2px)]': !tableMeta.footer.isEnabled,
20160
+ 'border-t-2 shadow-[0px_-5px_20px_0px_rgba(0,0,0,0.1)] [&>td]:!border-b-0': isScrolled
20161
+ });
20162
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, table.getBottomRows().map(row => (/*#__PURE__*/React__default.createElement(Row, {
20163
+ key: row.id,
20164
+ cellRenderer: RENDERERS$1.cell,
20165
+ index: tableMeta.length,
20166
+ measureRow: () => null,
20167
+ renderer: RENDERERS$1.row,
20168
+ row: row,
20169
+ table: table,
20170
+ className: className,
20171
+ onKeyDown: handleKeyDown,
20172
+ onKeyDownCapture: handleKeyDownCapture,
20173
+ // Row actions should only be hidden on temporary rows when editing is turned off
20174
+ hideRowActions: !tableMeta.editing.isEditing
20175
+ }))));
19807
20176
  }
19808
20177
 
19809
20178
  function Column$3(_) {
@@ -19821,8 +20190,8 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19821
20190
  'data-table-editing-mode': (_table3$meta$editing = table3.meta.editing) !== null && _table3$meta$editing !== void 0 && _table3$meta$editing.isEditing ? (_table3$meta$editing2 = table3.meta.editing) !== null && _table3$meta$editing2 !== void 0 && _table3$meta$editing2.isDetailedMode ? 'detailed' : 'normal' : undefined,
19822
20191
  enableHorizontalArrowKeyNavigation: table3.meta.editing.isEditing
19823
20192
  };
19824
- const hasAlertErrors = table3.meta.editing.hasAlertErrors();
19825
- const showCreateRowButton = table3.meta.editing.isEnabled && props.onEditingCreate;
20193
+ const hasAlertErrors = table3.meta.editing.getErrorsShownInAlert().length;
20194
+ const hasCreateWorkflow = table3.meta.editing.isEnabled && props.onEditingCreate;
19826
20195
  return /*#__PURE__*/React__default.createElement(Table, null, /*#__PURE__*/React__default.createElement(Table.Toolbar, {
19827
20196
  table: table3
19828
20197
  }, table3.meta.editing.isEnabled ? (/*#__PURE__*/React__default.createElement(Editing, {
@@ -19836,12 +20205,19 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19836
20205
  })) : null, /*#__PURE__*/React__default.createElement(Table.Grid, Object.assign({}, gridAttributes, {
19837
20206
  "data-taco": "table3",
19838
20207
  table: table3
19839
- }), showCreateRowButton && (/*#__PURE__*/React__default.createElement(CreateNewRowButton, {
20208
+ }), hasCreateWorkflow ? (/*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(TemporaryRow, {
20209
+ createRowButtonRef: table3.meta.editing.createRowButtonRef,
19840
20210
  table: table3.instance,
19841
20211
  tableMeta: table3.meta,
20212
+ tableRef: table3.ref
20213
+ }), /*#__PURE__*/React__default.createElement(CreateNewRow, {
20214
+ buttonRef: table3.meta.editing.createRowButtonRef,
19842
20215
  onEditingCreate: props.onEditingCreate,
19843
- scrollToIndex: table3.renderer.scrollToIndex
19844
- }))));
20216
+ scrollToIndex: table3.renderer.scrollToIndex,
20217
+ table: table3.instance,
20218
+ tableMeta: table3.meta,
20219
+ tableRef: table3.ref
20220
+ }))) : null));
19845
20221
  });
19846
20222
  const Table3 = /*#__PURE__*/fixedForwardRef(function Table3(props, ref) {
19847
20223
  const stringifiedChildren = String(props.children);