@economic/taco 2.45.0-alpha.0 → 2.45.0-alpha.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. package/dist/components/Layout/components/Top.d.ts +3 -3
  2. package/dist/components/Popover/Popover.d.ts +1 -1
  3. package/dist/components/Provider/Localization.d.ts +2 -0
  4. package/dist/components/Report/Report.d.ts +1 -1
  5. package/dist/components/Select2/components/Search.d.ts +0 -6
  6. package/dist/components/Select2/utilities.d.ts +2 -0
  7. package/dist/components/Table3/Table3.d.ts +2 -14
  8. package/dist/components/Table3/components/Columns/Internal/EditingActionsMenu.d.ts +1 -2
  9. package/dist/components/Table3/components/Editing/DiscardChangesConfirmationDialog.d.ts +7 -0
  10. package/dist/components/Table3/components/Row/Editing/CreateNewRow.d.ts +14 -0
  11. package/dist/components/Table3/components/Row/Editing/TemporaryRow.d.ts +11 -0
  12. package/dist/components/Table3/features/useEditingState.d.ts +29 -0
  13. package/dist/components/Table3/features/useTableEditing.d.ts +26 -36
  14. package/dist/components/Table3/listeners/useTableEditingListener.d.ts +1 -1
  15. package/dist/components/Table3/types.d.ts +24 -8
  16. package/dist/components/Table3/useTable3.d.ts +6 -0
  17. package/dist/components/Table3/util/editing.d.ts +7 -1
  18. package/dist/esm/index.css +35 -4
  19. package/dist/esm/packages/taco/src/components/Layout/components/Top.js +2 -2
  20. package/dist/esm/packages/taco/src/components/Layout/components/Top.js.map +1 -1
  21. package/dist/esm/packages/taco/src/components/ModeSwitch/ModeSwitch.js +2 -2
  22. package/dist/esm/packages/taco/src/components/ModeSwitch/ModeSwitch.js.map +1 -1
  23. package/dist/esm/packages/taco/src/components/Popover/Popover.js.map +1 -1
  24. package/dist/esm/packages/taco/src/components/Provider/Localization.js +5 -3
  25. package/dist/esm/packages/taco/src/components/Provider/Localization.js.map +1 -1
  26. package/dist/esm/packages/taco/src/components/Select2/Select2.js +50 -45
  27. package/dist/esm/packages/taco/src/components/Select2/Select2.js.map +1 -1
  28. package/dist/esm/packages/taco/src/components/Select2/components/Option.js +1 -1
  29. package/dist/esm/packages/taco/src/components/Select2/components/Option.js.map +1 -1
  30. package/dist/esm/packages/taco/src/components/Select2/components/Search.js +3 -13
  31. package/dist/esm/packages/taco/src/components/Select2/components/Search.js.map +1 -1
  32. package/dist/esm/packages/taco/src/components/Select2/components/Trigger.js +19 -1
  33. package/dist/esm/packages/taco/src/components/Select2/components/Trigger.js.map +1 -1
  34. package/dist/esm/packages/taco/src/components/Select2/hooks/useChildren.js +1 -10
  35. package/dist/esm/packages/taco/src/components/Select2/hooks/useChildren.js.map +1 -1
  36. package/dist/esm/packages/taco/src/components/Select2/utilities.js +11 -1
  37. package/dist/esm/packages/taco/src/components/Select2/utilities.js.map +1 -1
  38. package/dist/esm/packages/taco/src/components/Switch/Switch.js +1 -1
  39. package/dist/esm/packages/taco/src/components/Switch/Switch.js.map +1 -1
  40. package/dist/esm/packages/taco/src/components/Table3/Table3.js +14 -6
  41. package/dist/esm/packages/taco/src/components/Table3/Table3.js.map +1 -1
  42. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/Editing/RowMoveIndicator.js +1 -2
  43. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/Editing/RowMoveIndicator.js.map +1 -1
  44. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/EditingControlCell.js +33 -11
  45. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/EditingControlCell.js.map +1 -1
  46. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Internal/EditingActionsMenu.js +5 -37
  47. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Internal/EditingActionsMenu.js.map +1 -1
  48. package/dist/esm/packages/taco/src/components/Table3/components/Editing/Alert.js +17 -12
  49. package/dist/esm/packages/taco/src/components/Table3/components/Editing/Alert.js.map +1 -1
  50. package/dist/esm/packages/taco/src/components/Table3/components/Editing/DiscardChangesConfirmationDialog.js +34 -0
  51. package/dist/esm/packages/taco/src/components/Table3/components/Editing/DiscardChangesConfirmationDialog.js.map +1 -0
  52. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateNewRow.js +103 -0
  53. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateNewRow.js.map +1 -0
  54. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/SaveStatus.js +2 -14
  55. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/SaveStatus.js.map +1 -1
  56. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/TemporaryRow.js +96 -0
  57. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/TemporaryRow.js.map +1 -0
  58. package/dist/esm/packages/taco/src/components/Table3/components/Row/Row.js +39 -6
  59. package/dist/esm/packages/taco/src/components/Table3/components/Row/Row.js.map +1 -1
  60. package/dist/esm/packages/taco/src/components/Table3/components/Toolbar/Editing/Editing.js +4 -17
  61. package/dist/esm/packages/taco/src/components/Table3/components/Toolbar/Editing/Editing.js.map +1 -1
  62. package/dist/esm/packages/taco/src/components/Table3/features/useEditingState.js +519 -0
  63. package/dist/esm/packages/taco/src/components/Table3/features/useEditingState.js.map +1 -0
  64. package/dist/esm/packages/taco/src/components/Table3/features/useTableEditing.js +29 -406
  65. package/dist/esm/packages/taco/src/components/Table3/features/useTableEditing.js.map +1 -1
  66. package/dist/esm/packages/taco/src/components/Table3/listeners/useTableEditingListener.js +44 -33
  67. package/dist/esm/packages/taco/src/components/Table3/listeners/useTableEditingListener.js.map +1 -1
  68. package/dist/esm/packages/taco/src/components/Table3/useTable3.js +34 -13
  69. package/dist/esm/packages/taco/src/components/Table3/useTable3.js.map +1 -1
  70. package/dist/esm/packages/taco/src/components/Table3/util/editing.js +11 -23
  71. package/dist/esm/packages/taco/src/components/Table3/util/editing.js.map +1 -1
  72. package/dist/esm/packages/taco/src/primitives/Collection/components/Root.js +20 -4
  73. package/dist/esm/packages/taco/src/primitives/Collection/components/Root.js.map +1 -1
  74. package/dist/esm/packages/taco/src/primitives/Listbox2/components/Option.js +0 -4
  75. package/dist/esm/packages/taco/src/primitives/Listbox2/components/Option.js.map +1 -1
  76. package/dist/esm/packages/taco/src/primitives/Listbox2/components/Root.js +1 -0
  77. package/dist/esm/packages/taco/src/primitives/Listbox2/components/Root.js.map +1 -1
  78. package/dist/esm/packages/taco/src/primitives/Table/Core/Table.js +1 -3
  79. package/dist/esm/packages/taco/src/primitives/Table/Core/Table.js.map +1 -1
  80. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.js +9 -3
  81. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.js.map +1 -1
  82. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Internal/Actions.js +9 -7
  83. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Internal/Actions.js.map +1 -1
  84. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Footer/Footer.js.map +1 -1
  85. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/BuiltIns/DisplayRow.js +2 -2
  86. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/BuiltIns/DisplayRow.js.map +1 -1
  87. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/Row.js +4 -2
  88. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/Row.js.map +1 -1
  89. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/RowContext.js +2 -1
  90. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/RowContext.js.map +1 -1
  91. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Toolbar/components/Filters/components/FilterValue.js +8 -1
  92. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Toolbar/components/Filters/components/FilterValue.js.map +1 -1
  93. package/dist/esm/packages/taco/src/primitives/Table/Core/features/useTableRenderer.js +29 -7
  94. package/dist/esm/packages/taco/src/primitives/Table/Core/features/useTableRenderer.js.map +1 -1
  95. package/dist/esm/packages/taco/src/primitives/Table/Core/useTable.js +2 -2
  96. package/dist/esm/packages/taco/src/primitives/Table/Core/useTable.js.map +1 -1
  97. package/dist/esm/packages/taco/src/primitives/Table/types.js.map +1 -1
  98. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/features/useTableRowSelection.js +2 -1
  99. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/features/useTableRowSelection.js.map +1 -1
  100. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/features/useTableSearch.js +3 -3
  101. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/features/useTableSearch.js.map +1 -1
  102. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/useTableManager.js +1 -1
  103. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/useTableManager.js.map +1 -1
  104. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/util/setup.js +11 -0
  105. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/util/setup.js.map +1 -1
  106. package/dist/esm/packages/taco/src/utils/dom.js +23 -12
  107. package/dist/esm/packages/taco/src/utils/dom.js.map +1 -1
  108. package/dist/index.css +35 -4
  109. package/dist/primitives/Collection/components/Root.d.ts +3 -1
  110. package/dist/primitives/Table/Core/components/Columns/Internal/Actions.d.ts +3 -1
  111. package/dist/primitives/Table/Core/components/Footer/Footer.d.ts +1 -1
  112. package/dist/primitives/Table/Core/components/Row/RowContext.d.ts +1 -0
  113. package/dist/primitives/Table/Core/features/useTableRenderer.d.ts +2 -2
  114. package/dist/primitives/Table/Core/features/useTableStyle.d.ts +3 -3
  115. package/dist/primitives/Table/Core/types.d.ts +4 -0
  116. package/dist/primitives/Table/Core/useTable.d.ts +2 -2
  117. package/dist/primitives/Table/types.d.ts +2 -2
  118. package/dist/primitives/Table/useTableManager/useTableManager.d.ts +1 -1
  119. package/dist/taco.cjs.development.js +1130 -756
  120. package/dist/taco.cjs.development.js.map +1 -1
  121. package/dist/taco.cjs.production.min.js +1 -1
  122. package/dist/taco.cjs.production.min.js.map +1 -1
  123. package/dist/utils/dom.d.ts +2 -1
  124. package/package.json +16 -16
  125. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateRowButton.js +0 -90
  126. 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,21 +4221,25 @@ 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) {
4220
- if (container !== null && container !== void 0 && container.querySelector(selector)) {
4228
+ const escapedSelector = CSS.escape(selector);
4229
+ if (container !== null && container !== void 0 && container.querySelector(escapedSelector)) {
4221
4230
  return true;
4222
4231
  }
4223
- const elementInDocument = document.querySelector(selector);
4232
+ const elementInDocument = document.querySelector(escapedSelector);
4224
4233
  // if the element does exist, see if it is itself connected to somethng that was triggered from the container
4225
4234
  if (elementInDocument) {
4226
- return isElementInsideOrTriggeredFromContainer(elementInDocument, container);
4235
+ return isElementTriggeredFromContainer(elementInDocument, container);
4227
4236
  }
4228
4237
  return false;
4229
4238
  }
4230
- 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));
4231
4243
  }
4232
4244
  function isElementInsideOverlay(element) {
4233
4245
  return !!(element !== null && element !== void 0 && element.closest('[role=dialog],[role=menu]'));
@@ -4721,7 +4733,9 @@ const defaultLocalisationTexts = {
4721
4733
  tooltip: 'Edit table'
4722
4734
  },
4723
4735
  create: {
4724
- label: 'New'
4736
+ label: 'New',
4737
+ disabled: 'Existing new row must be saved',
4738
+ saving: 'Saving...'
4725
4739
  }
4726
4740
  },
4727
4741
  clearChangesConfirmationDialog: {
@@ -4743,8 +4757,8 @@ const defaultLocalisationTexts = {
4743
4757
  },
4744
4758
  validation: {
4745
4759
  alert: {
4746
- titleOne: '[COUNT] unsaved entry:',
4747
- titlePlural: '[COUNT] unsaved entries:',
4760
+ titleOne: '[COUNT] unsaved row:',
4761
+ titlePlural: '[COUNT] unsaved rows:',
4748
4762
  messageOne: "[COLUMN] [ROW] is incomplete and hasn't been saved.",
4749
4763
  messagePlural: "[COLUMN] [ROW] are incomplete and haven't been saved.",
4750
4764
  messageRow: 'Row',
@@ -7646,7 +7660,7 @@ const Switch = /*#__PURE__*/React.forwardRef(function Switch(props, ref) {
7646
7660
  onCheckedChange: onChange,
7647
7661
  ref: ref
7648
7662
  }), /*#__PURE__*/React.createElement(PrimitiveSwitch.Thumb, {
7649
- 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]"
7650
7664
  }));
7651
7665
  if (label) {
7652
7666
  const labelContainerClassName = cn('flex self-start cursor-pointer', {
@@ -8706,10 +8720,10 @@ const ModeSwitch = /*#__PURE__*/React.forwardRef(function ModeSwitch(props, ref)
8706
8720
  onCheckedChange: onChange,
8707
8721
  ref: ref
8708
8722
  }), /*#__PURE__*/React.createElement(PrimitiveSwitch.Thumb, {
8709
- 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%]"
8710
8724
  }, /*#__PURE__*/React.createElement(Icon, {
8711
8725
  name: "edit-simple",
8712
- className: "!h-5 !w-5"
8726
+ className: "pointer-events-none !h-5 !w-5"
8713
8727
  })));
8714
8728
  });
8715
8729
  ModeSwitch.displayName = 'ModeSwitch';
@@ -10412,6 +10426,15 @@ function configureReactTableOptions(options, props, localization) {
10412
10426
  // We don't want to expose internal Tanstack Table row, so we need to wrap enableRowSelection callback into additional function,
10413
10427
  // which receives the React Table Row object and passes row.original to a callback.
10414
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
+ }
10415
10438
  const tableOptions = {
10416
10439
  defaultColumn: {
10417
10440
  enableColumnFilter: options.enableFiltering || true,
@@ -10430,11 +10453,13 @@ function configureReactTableOptions(options, props, localization) {
10430
10453
  enableGrouping: true,
10431
10454
  enableHiding: (_options$enableColumn2 = options.enableColumnHiding) !== null && _options$enableColumn2 !== void 0 ? _options$enableColumn2 : false,
10432
10455
  enablePinning: (_options$enableColumn3 = options.enableColumnFreezing) !== null && _options$enableColumn3 !== void 0 ? _options$enableColumn3 : false,
10456
+ enableRowPinning: true,
10433
10457
  enableRowSelection: reactTableEnableRowSelection !== null && reactTableEnableRowSelection !== void 0 ? reactTableEnableRowSelection : false,
10434
10458
  enableSorting: (_options$enableSortin = options.enableSorting) !== null && _options$enableSortin !== void 0 ? _options$enableSortin : false,
10435
10459
  // models for default features
10436
10460
  getExpandedRowModel: reactTable.getExpandedRowModel(),
10437
10461
  getGroupedRowModel: reactTable.getGroupedRowModel(),
10462
+ getRowId,
10438
10463
  groupedColumnMode: false
10439
10464
  };
10440
10465
  if (tableOptions.enableColumnResizing) {
@@ -10916,6 +10941,7 @@ function useTableRowHeight(isEnabled = false, defaultRowHeight = 'medium') {
10916
10941
  function useTableRowSelection(isEnabled = false) {
10917
10942
  const lastSelectedRowIndex = React__default.useRef();
10918
10943
  const onKeyDown = React__default.useCallback((event, table) => {
10944
+ var _event$target;
10919
10945
  if (!isEnabled || !table.options.enableRowSelection || event.defaultPrevented) {
10920
10946
  return;
10921
10947
  }
@@ -10930,7 +10956,7 @@ function useTableRowSelection(isEnabled = false) {
10930
10956
  (_rows$rowActiveIndex2 = rows[rowActiveIndex]) === null || _rows$rowActiveIndex2 === void 0 ? void 0 : _rows$rowActiveIndex2.toggleSelected();
10931
10957
  }
10932
10958
  return;
10933
- } 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)) {
10934
10960
  event.preventDefault();
10935
10961
  table.toggleAllRowsSelected();
10936
10962
  return;
@@ -10955,10 +10981,10 @@ function useTableSearch(isEnabled = false, defaultEnableGlobalFilter = false) {
10955
10981
  // react-table doesn't re-render when options.enableGlobalFilter changes, so for now we force it
10956
10982
  const currentFilter = instance.getState().globalFilter;
10957
10983
  if (currentFilter) {
10958
- setTimeout(() => {
10959
- instance.setGlobalFilter('');
10984
+ instance.resetGlobalFilter(true);
10985
+ window.requestAnimationFrame(() => {
10960
10986
  instance.setGlobalFilter(currentFilter);
10961
- }, 1);
10987
+ });
10962
10988
  }
10963
10989
  }
10964
10990
  // highlighting
@@ -11767,7 +11793,7 @@ function useTableManager(props, meta, internalColumns) {
11767
11793
  rowDrag,
11768
11794
  rowDrop: rowDrop,
11769
11795
  rowExpansion: rowExpansion,
11770
- rowIdentityColumnId: props.rowIdentityColumnId,
11796
+ rowIdentityAccessor: props.rowIdentityAccessor,
11771
11797
  rowGoto,
11772
11798
  rowGroups: rowGroups,
11773
11799
  rowHeight,
@@ -12105,7 +12131,8 @@ const Skeleton = /*#__PURE__*/React__default.forwardRef(function Skeleton(props,
12105
12131
 
12106
12132
  const RowContext = /*#__PURE__*/React__default.createContext({
12107
12133
  isHovered: false,
12108
- rowIndex: -1
12134
+ rowIndex: -1,
12135
+ hideRowActions: false
12109
12136
  });
12110
12137
 
12111
12138
  /* anonymous functions will break the memoisation on each render, wrap handlers in callbacks */
@@ -12113,6 +12140,7 @@ function Row(props) {
12113
12140
  const {
12114
12141
  renderer: RowRenderer,
12115
12142
  cellRenderer: CellRenderer,
12143
+ hideRowActions = false,
12116
12144
  ...displayRowProps
12117
12145
  } = props;
12118
12146
  const tableMeta = props.table.options.meta;
@@ -12120,8 +12148,9 @@ function Row(props) {
12120
12148
  // context - it must be here for cells to read it, since they render alongside the row inside DisplayRow
12121
12149
  const contextValue = React__default.useMemo(() => ({
12122
12150
  isHovered,
12123
- rowIndex: props.index
12124
- }), [isHovered, props.index]);
12151
+ rowIndex: props.index,
12152
+ hideRowActions
12153
+ }), [isHovered, props.index, hideRowActions]);
12125
12154
  if (props.row.original === undefined) {
12126
12155
  return /*#__PURE__*/React__default.createElement(SkeletonRow, Object.assign({}, props));
12127
12156
  }
@@ -12132,11 +12161,35 @@ function Row(props) {
12132
12161
  })));
12133
12162
  }
12134
12163
 
12135
- function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12136
- 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;
12137
12190
  const tableMeta = table.options.meta;
12138
- const rows = table.getRowModel().rows;
12139
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 : [];
12140
12193
  // expanded rows
12141
12194
  const {
12142
12195
  createRowMeasurer,
@@ -12146,9 +12199,6 @@ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12146
12199
  const rangeExtractor = useRowGroupVirtualisation(table);
12147
12200
  // account for thead and tfoot in the scroll area - both are always medium row height
12148
12201
  const scrollPaddingStart = ROW_HEIGHT_ESTIMATES.medium;
12149
- // column groups offset the bottom padding :shrug:, multiplying by 1.5 ensures the bottom padding remains
12150
- // consistent when there are groups and when there aren't. 1.5 is relatively arbitrary, but it gives alignment
12151
- const scrollPaddingEnd = ROW_HEIGHT_ESTIMATES.medium * (table.getHeaderGroups().length > 1 ? 1.5 : 1);
12152
12202
  const virtualiser = reactVirtual.useVirtualizer({
12153
12203
  count: rows.length,
12154
12204
  estimateSize,
@@ -12157,7 +12207,8 @@ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12157
12207
  rangeExtractor,
12158
12208
  // correctly sets the scroll padding offset, e.g. when keyboard navigating rows in the list
12159
12209
  scrollPaddingStart,
12160
- scrollPaddingEnd: tableMeta.footer.isEnabled ? scrollPaddingEnd * 2 : scrollPaddingEnd
12210
+ scrollPaddingEnd: getScrollPaddingEndOffset(table),
12211
+ paddingEnd: getPaddingEndOffset(table, options)
12161
12212
  });
12162
12213
  const totalSize = virtualiser.getTotalSize();
12163
12214
  const virtualItems = virtualiser.getVirtualItems();
@@ -12314,12 +12365,14 @@ function Actions$1(props) {
12314
12365
  actionsLength,
12315
12366
  data,
12316
12367
  isActiveRow,
12317
- rowId
12368
+ rowId,
12369
+ table
12318
12370
  } = props;
12319
12371
  const {
12320
12372
  texts
12321
12373
  } = useLocalization();
12322
- 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);
12323
12376
  const actionsOnRow = visibleActions.length === actionsLength ? visibleActions : visibleActions.slice(0, actionsLength - 1);
12324
12377
  const actionsInMenu = visibleActions.slice(visibleActions.length === actionsLength ? actionsLength : actionsLength - 1);
12325
12378
  const className = cn('flex justify-end text-right bg-[inherit] shadow-[-6px_0px_6px_var(--table-row-actions-shadow)] print:hidden');
@@ -12359,7 +12412,8 @@ const Cell = /*#__PURE__*/React__default.memo(function MemoedCell(context) {
12359
12412
  } = context;
12360
12413
  const {
12361
12414
  isHovered,
12362
- rowIndex
12415
+ rowIndex,
12416
+ hideRowActions
12363
12417
  } = React__default.useContext(RowContext);
12364
12418
  const tableMeta = table.options.meta;
12365
12419
  const actions = tableMeta.rowActions.rowActions;
@@ -12367,15 +12421,14 @@ const Cell = /*#__PURE__*/React__default.memo(function MemoedCell(context) {
12367
12421
  const isActiveRow = tableMeta.rowActive.rowActiveIndex === rowIndex;
12368
12422
  const isResizingColumn = !!table.getState().columnSizingInfo.isResizingColumn;
12369
12423
  const isHoverStatePaused = tableMeta.rowActive.isHoverStatePaused;
12370
- // We don't want to show actions in edit mode, since we have editing actions,
12371
- // which is shown in edit mode instead.
12372
- if (actions !== null && actions !== void 0 && actions.length && (isActiveRow || isHovered && !isHoverStatePaused && !isResizingColumn)) {
12424
+ if (!hideRowActions && actions !== null && actions !== void 0 && actions.length && (isActiveRow || isHovered && !isHoverStatePaused && !isResizingColumn)) {
12373
12425
  return /*#__PURE__*/React__default.createElement(Actions$1, {
12374
12426
  actions: actions,
12375
12427
  actionsLength: actionsLength,
12376
12428
  data: row.original,
12377
12429
  isActiveRow: isActiveRow,
12378
- rowId: row.id
12430
+ rowId: row.id,
12431
+ table: table
12379
12432
  });
12380
12433
  }
12381
12434
  return null;
@@ -12625,13 +12678,13 @@ const INTERNAL_RENDERERS = {
12625
12678
  rowExpansion: renderer$2,
12626
12679
  rowSelection: renderer$3
12627
12680
  };
12628
- function useTable(props, externalRef, renderers, meta) {
12681
+ function useTable(props, externalRef, renderers, meta, options) {
12629
12682
  // create a ref and merge with the consumer's ref
12630
12683
  const ref = useMergedRef(externalRef);
12631
12684
  // configure the table
12632
12685
  const manager = useTableManager(props, meta, INTERNAL_RENDERERS);
12633
12686
  // configure the virtualised renderer
12634
- const renderer = useTableRenderer(renderers, manager.instance, ref, props.defaultRowActiveIndex);
12687
+ const renderer = useTableRenderer(renderers, manager.instance, ref, props.defaultRowActiveIndex, options);
12635
12688
  // configure dynamic styling
12636
12689
  const {
12637
12690
  style,
@@ -12732,7 +12785,10 @@ function GroupedCell(props) {
12732
12785
  index,
12733
12786
  isHighlighted
12734
12787
  } = props;
12735
- const tableMeta = cell.getContext().table.options.meta;
12788
+ const {
12789
+ table
12790
+ } = cell.getContext();
12791
+ const tableMeta = table.options.meta;
12736
12792
  const columnMeta = cell.column.columnDef.meta;
12737
12793
  const attributes = getCellAttributes(cell, index, isHighlighted);
12738
12794
  const {
@@ -12750,7 +12806,8 @@ function GroupedCell(props) {
12750
12806
  colSpan: colSpan,
12751
12807
  rowActions: tableMeta.rowGroups.rowActionsForGroup,
12752
12808
  rowId: cell.row.id,
12753
- subRows: subRows
12809
+ subRows: subRows,
12810
+ table: table
12754
12811
  }), content);
12755
12812
  }
12756
12813
  const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupedCell(props) {
@@ -12762,6 +12819,7 @@ const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupe
12762
12819
  rowActions,
12763
12820
  rowId,
12764
12821
  subRows,
12822
+ table,
12765
12823
  ...attributes
12766
12824
  } = props;
12767
12825
  return /*#__PURE__*/React__default.createElement("td", Object.assign({}, attributes, {
@@ -12776,7 +12834,8 @@ const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupe
12776
12834
  actionsLength: 4,
12777
12835
  data: subRows,
12778
12836
  isActiveRow: true,
12779
- rowId: rowId
12837
+ rowId: rowId,
12838
+ table: table
12780
12839
  })) : null);
12781
12840
  });
12782
12841
 
@@ -12838,7 +12897,7 @@ const DisplayRow = /*#__PURE__*/React__default.memo(function DisplayRow(props) {
12838
12897
  if (tableMeta.rowActive.isEnabled) {
12839
12898
  attributes['data-row-active'] = tableMeta.rowActive.rowActiveIndex === index ? true : undefined;
12840
12899
  // we use capture because it let's us picks up clicks on components inside the row, e.g. checkboxes
12841
- attributes.onClickCapture = handleClickCapture;
12900
+ attributes.onPointerDown = handleClickCapture;
12842
12901
  }
12843
12902
  // row click
12844
12903
  if (tableMeta.rowClick.isEnabled(row.original)) {
@@ -12916,7 +12975,7 @@ const DisplayRow = /*#__PURE__*/React__default.memo(function DisplayRow(props) {
12916
12975
  const expansionRef = React__default.useRef(null);
12917
12976
  const isExpanded = !!attributes['data-row-expanded'];
12918
12977
  useSetVirtualisedRowHeight(measureRow, ref.current, expansionRef.current, isExpanded);
12919
- const className = cn('group/row', {
12978
+ const className = cn('group/row', otherAttributes.className, {
12920
12979
  'hover:cursor-grab': tableMeta.rowDrag.isEnabled && typeof attributes.onClick !== 'function',
12921
12980
  'hover:cursor-pointer': typeof attributes.onClick === 'function'
12922
12981
  });
@@ -14400,12 +14459,12 @@ const getOptionsFromCollection = (collection, selector) => collection.querySelec
14400
14459
  const Root = /*#__PURE__*/React__default.forwardRef(function CollectionRoot(props, ref) {
14401
14460
  const {
14402
14461
  querySelector,
14462
+ resetOnChange,
14403
14463
  tabIndex = 0,
14404
14464
  ...otherProps
14405
14465
  } = props;
14406
14466
  const internalRef = useMergedRef(ref);
14407
14467
  const [activeIndex, setActiveIndex] = React__default.useState();
14408
- const lastLengthRef = React__default.useRef(0);
14409
14468
  const setActiveOption = (index, collection, option) => {
14410
14469
  var _collection$querySele;
14411
14470
  (_collection$querySele = collection.querySelector(`[aria-current]`)) === null || _collection$querySele === void 0 ? void 0 : _collection$querySele.removeAttribute('aria-current');
@@ -14428,17 +14487,34 @@ const Root = /*#__PURE__*/React__default.forwardRef(function CollectionRoot(prop
14428
14487
  }, [internalRef.current, querySelector]);
14429
14488
  React__default.useEffect(() => {
14430
14489
  if (internalRef.current) {
14431
- internalRef.current.setActiveIndex = setActiveIndexByElement;
14490
+ internalRef.current.setActiveIndexByElement = setActiveIndexByElement;
14432
14491
  }
14433
14492
  }, [internalRef.current]);
14493
+ React__default.useEffect(() => {
14494
+ if (internalRef.current) {
14495
+ const selected = internalRef.current.querySelectorAll(`[aria-current="true"]`);
14496
+ const options = getOptionsFromCollection(internalRef.current, querySelector);
14497
+ if (options.length && selected.length === 1) {
14498
+ const firstSelected = internalRef.current.querySelector(`[aria-selected]`);
14499
+ if (firstSelected) {
14500
+ const selectedIndex = Array.from(options).indexOf(firstSelected);
14501
+ if (selectedIndex > -1) {
14502
+ setActiveOption(selectedIndex, internalRef.current, firstSelected);
14503
+ }
14504
+ }
14505
+ }
14506
+ }
14507
+ }, [resetOnChange]);
14434
14508
  React__default.useEffect(() => {
14435
14509
  if (internalRef.current) {
14436
14510
  const options = getOptionsFromCollection(internalRef.current, querySelector);
14437
- if (options.length && options.length !== lastLengthRef.current) {
14511
+ if (options.length) {
14438
14512
  let selected = internalRef.current.querySelectorAll(`[aria-current="true"]`);
14513
+ // if nothing is current (keyboard visible), look for selected items
14439
14514
  if (selected.length === 0) {
14440
14515
  selected = internalRef.current.querySelectorAll(`[aria-selected]`);
14441
14516
  }
14517
+ // if one item is selected, make sure it's current
14442
14518
  if (selected.length === 1) {
14443
14519
  if (options) {
14444
14520
  const firstSelected = selected.item(0);
@@ -14452,7 +14528,6 @@ const Root = /*#__PURE__*/React__default.forwardRef(function CollectionRoot(prop
14452
14528
  setActiveOption(0, internalRef.current, options.item(0));
14453
14529
  }
14454
14530
  }
14455
- lastLengthRef.current = options.length;
14456
14531
  }
14457
14532
  }, [props.children]);
14458
14533
  const handleClick = event => {
@@ -14585,6 +14660,7 @@ const Root$1 = /*#__PURE__*/React__default.forwardRef(function Listbox2(props, r
14585
14660
  id: id,
14586
14661
  querySelector: customSelector ? `${DEFAULT_SELECTOR}, ${customSelector}` : DEFAULT_SELECTOR,
14587
14662
  ref: ref,
14663
+ resetOnChange: value,
14588
14664
  role: "listbox"
14589
14665
  }), children)));
14590
14666
  });
@@ -14643,10 +14719,6 @@ const Option = /*#__PURE__*/React__default.forwardRef(function Listbox2Option(pr
14643
14719
  if (disabled || listboxDisabled || listboxReadOnly) {
14644
14720
  event.stopPropagation();
14645
14721
  return;
14646
- }
14647
- // UX requirement: if tab key is pressed and the current option is selected then keydown event is ignored
14648
- else if (event.key === 'Tab' && selected) {
14649
- return;
14650
14722
  } else if (isAriaSelectionKey(event)) {
14651
14723
  setValue(value);
14652
14724
  }
@@ -14750,6 +14822,16 @@ const getFontSize = fontSize => {
14750
14822
  return 'text-sm';
14751
14823
  }
14752
14824
  };
14825
+ const filterOption = (child, searchQuery) => {
14826
+ var _child$props$textValu, _child$props$descript;
14827
+ if ((_child$props$textValu = child.props.textValue) !== null && _child$props$textValu !== void 0 && _child$props$textValu.toLowerCase().includes(searchQuery.toLowerCase())) {
14828
+ return true;
14829
+ }
14830
+ if ((_child$props$descript = child.props.description) !== null && _child$props$descript !== void 0 && _child$props$descript.toLowerCase().includes(searchQuery.toLowerCase())) {
14831
+ return true;
14832
+ }
14833
+ return String(child.props.children).toLowerCase().includes(searchQuery.toLowerCase());
14834
+ };
14753
14835
 
14754
14836
  const Select2Context = /*#__PURE__*/React__default.createContext({});
14755
14837
  const useSelect2Context = () => React__default.useContext(Select2Context);
@@ -15020,7 +15102,7 @@ const Option$1 = /*#__PURE__*/React__default.forwardRef(function Select2Option(p
15020
15102
  onClick: event => {
15021
15103
  var _listboxRef$current;
15022
15104
  event.stopPropagation();
15023
- listboxRef === null || listboxRef === void 0 ? void 0 : (_listboxRef$current = listboxRef.current) === null || _listboxRef$current === void 0 ? void 0 : _listboxRef$current.setActiveIndex(event.currentTarget.parentElement);
15105
+ listboxRef === null || listboxRef === void 0 ? void 0 : (_listboxRef$current = listboxRef.current) === null || _listboxRef$current === void 0 ? void 0 : _listboxRef$current.setActiveIndexByElement(event.currentTarget.parentElement);
15024
15106
  },
15025
15107
  popover: popover,
15026
15108
  tabIndex: -1
@@ -15089,7 +15171,9 @@ const Button$3 = /*#__PURE__*/React__default.forwardRef(function Select2TriggerB
15089
15171
  var _props$className;
15090
15172
  const {
15091
15173
  children,
15174
+ onBlur,
15092
15175
  onClick,
15176
+ onFocus,
15093
15177
  tabIndex = 0,
15094
15178
  ...otherProps
15095
15179
  } = props;
@@ -15120,6 +15204,18 @@ const Button$3 = /*#__PURE__*/React__default.forwardRef(function Select2TriggerB
15120
15204
  onClick(event);
15121
15205
  }
15122
15206
  };
15207
+ let handleBlur;
15208
+ if (typeof onBlur === 'function') {
15209
+ // we might be focusing on an input or something inside the dropdown that was triggered by the select
15210
+ // so see if the element gaining focus is inside a portal and look up its controller
15211
+ // if we don't do this, things like validate on blur occur while simply opening the select
15212
+ handleBlur = event => {
15213
+ if (isElementInsideOrTriggeredFromContainer(event.relatedTarget, event.currentTarget)) {
15214
+ return;
15215
+ }
15216
+ onBlur(event);
15217
+ };
15218
+ }
15123
15219
  // select the value text if the select is readonly
15124
15220
  const handleFocus = event => {
15125
15221
  if (readOnly) {
@@ -15129,6 +15225,9 @@ const Button$3 = /*#__PURE__*/React__default.forwardRef(function Select2TriggerB
15129
15225
  (_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);
15130
15226
  }
15131
15227
  }
15228
+ if (typeof onFocus === 'function') {
15229
+ onFocus(event);
15230
+ }
15132
15231
  };
15133
15232
  return /*#__PURE__*/React__default.createElement("button", Object.assign({}, otherProps, {
15134
15233
  "aria-invalid": invalid ? true : undefined,
@@ -15136,6 +15235,7 @@ const Button$3 = /*#__PURE__*/React__default.forwardRef(function Select2TriggerB
15136
15235
  className: className,
15137
15236
  disabled: disabled,
15138
15237
  onClick: handleClick,
15238
+ onBlur: handleBlur,
15139
15239
  onFocus: handleFocus,
15140
15240
  ref: ref,
15141
15241
  role: "combobox",
@@ -15398,17 +15498,12 @@ const BubbleSelect = props => {
15398
15498
  };
15399
15499
 
15400
15500
  const Search$2 = /*#__PURE__*/React__default.forwardRef(function ListboxSearch(props, ref) {
15401
- const {
15402
- onTabKeyPress,
15403
- ...otherProps
15404
- } = props;
15405
15501
  const {
15406
15502
  listboxRef,
15407
15503
  searchQuery,
15408
15504
  setSearchQuery,
15409
15505
  setValidationError,
15410
- validationError,
15411
- setOpen
15506
+ validationError
15412
15507
  } = useSelect2Context();
15413
15508
  const handleChange = event => {
15414
15509
  if (validationError) {
@@ -15421,11 +15516,6 @@ const Search$2 = /*#__PURE__*/React__default.forwardRef(function ListboxSearch(p
15421
15516
  if (event.key === ' ') {
15422
15517
  return;
15423
15518
  }
15424
- // Select2 should close dropdown and receive focus, when user press Tab while searching (UX requirement to support better keyboard navigation)
15425
- if (event.key === 'Tab') {
15426
- setOpen(false);
15427
- onTabKeyPress();
15428
- }
15429
15519
  if (isAriaSelectionKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {
15430
15520
  var _listboxRef$current;
15431
15521
  event.preventDefault();
@@ -15435,12 +15525,12 @@ const Search$2 = /*#__PURE__*/React__default.forwardRef(function ListboxSearch(p
15435
15525
  }
15436
15526
  };
15437
15527
  return /*#__PURE__*/React__default.createElement(Field, {
15438
- className: cn('mx-1.5 mb-1.5 !min-h-fit ', {
15528
+ className: cn('mx-1.5 mb-1.5 !min-h-fit', {
15439
15529
  '!pb-0': !validationError
15440
15530
  }),
15441
15531
  invalid: !!validationError,
15442
15532
  message: validationError === null || validationError === void 0 ? void 0 : validationError.message
15443
- }, /*#__PURE__*/React__default.createElement(Input, Object.assign({}, otherProps, {
15533
+ }, /*#__PURE__*/React__default.createElement(Input, Object.assign({}, props, {
15444
15534
  autoFocus: true,
15445
15535
  invalid: !!validationError,
15446
15536
  onChange: handleChange,
@@ -15501,16 +15591,6 @@ const useChildren = ({
15501
15591
  setSearchQuery
15502
15592
  };
15503
15593
  };
15504
- const filterOption = (child, searchQuery) => {
15505
- var _child$props$textValu, _child$props$descript;
15506
- if ((_child$props$textValu = child.props.textValue) !== null && _child$props$textValu !== void 0 && _child$props$textValu.toLowerCase().includes(searchQuery.toLowerCase())) {
15507
- return true;
15508
- }
15509
- if ((_child$props$descript = child.props.description) !== null && _child$props$descript !== void 0 && _child$props$descript.toLowerCase().includes(searchQuery.toLowerCase())) {
15510
- return true;
15511
- }
15512
- return String(child.props.children).toLowerCase().includes(searchQuery.toLowerCase());
15513
- };
15514
15594
 
15515
15595
  const getNextColor = options => {
15516
15596
  const occurrences = AVAILABLE_COLORS.reduce((prev, color) => {
@@ -15674,7 +15754,6 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15674
15754
  // align the listbox min width with the width of the input - it should never be smaller
15675
15755
  const dimensions = useBoundingClientRectListener(internalRef);
15676
15756
  // state
15677
- const [tabTriggeredClose, setTabTriggeredClose] = React__default.useState(false);
15678
15757
  const [open, setOpen] = React__default.useState(false);
15679
15758
  const [value, _setValue] = reactUseControllableState.useControllableState({
15680
15759
  // uncontrolled
@@ -15727,58 +15806,69 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15727
15806
  createDialog,
15728
15807
  createTriggerText
15729
15808
  };
15809
+ const hasInlineCreation = onCreate && !createDialog;
15810
+ const hasSearch = flattenedChildren.length > 5 || hasInlineCreation;
15811
+ const visibleChildren = searchQuery === '' ? initialChildren : filteredChildren;
15812
+ const selectOptions = searchQuery === '' ? flattenedChildren.map(child => child.props.value) : filteredChildren.map(child => isGroup(child) ? Array.isArray(child.props.children) && child.props.children.map(subChild => subChild.props.value) : child.props.value).flatMap(c => c) || [];
15813
+ // support typeahead functionality when search isn't available
15814
+ const queryTimeoutRef = React__default.useRef('');
15815
+ const typeahead = debounce(function () {
15816
+ if (!queryTimeoutRef.current) {
15817
+ return;
15818
+ }
15819
+ const matchedValueIndex = visibleChildren.findIndex(child => filterOption(child, queryTimeoutRef.current));
15820
+ if (matchedValueIndex > -1) {
15821
+ setValue(selectOptions[matchedValueIndex]);
15822
+ }
15823
+ queryTimeoutRef.current = '';
15824
+ }, 200);
15825
+ const setValueIfMatched = query => {
15826
+ queryTimeoutRef.current = queryTimeoutRef.current + query;
15827
+ typeahead();
15828
+ };
15730
15829
  const handleKeyDown = event => {
15731
15830
  var _listboxRef$current;
15732
15831
  if (open) {
15733
15832
  event.preventDefault();
15734
- } else if (isElementInsideTable3OrReport(event.currentTarget)) {
15833
+ } else if (isElementInsideTable3OrReport(event.currentTarget) && isAriaDirectionKey(event)) {
15735
15834
  return;
15736
15835
  } else if (!event.ctrlKey && !event.metaKey && (event.key === 'ArrowDown' || /^[a-z0-9]$/i.test(event.key))) {
15737
15836
  setOpen(true);
15837
+ if (!hasSearch) {
15838
+ setValueIfMatched(event.key);
15839
+ }
15738
15840
  }
15739
15841
  // the focus should always remain on the input, so we forward events on to the listbox
15740
15842
  (_listboxRef$current = listboxRef.current) === null || _listboxRef$current === void 0 ? void 0 : _listboxRef$current.dispatchEvent(createCustomKeyboardEvent(event));
15741
15843
  };
15742
- let handleBlur;
15743
- if (otherProps.onBlur) {
15744
- // we might be focusing on an input or something inside the dropdown that was triggered by the select
15745
- // so see if the element gaining focus is inside a portal and look up its controller
15746
- // if we don't do this, things like validate on blur occur while simply opening the select
15747
- handleBlur = event => {
15748
- var _elementGainingFocus$;
15749
- const elementGainingFocus = event.relatedTarget;
15750
- if (elementGainingFocus === undefined) {
15751
- return;
15752
- }
15753
- 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;
15754
- if (!portalId || event.currentTarget.getAttribute(`aria-controls`) !== portalId) {
15755
- var _otherProps$onBlur;
15756
- (_otherProps$onBlur = otherProps.onBlur) === null || _otherProps$onBlur === void 0 ? void 0 : _otherProps$onBlur.call(otherProps, event);
15757
- }
15758
- };
15759
- }
15844
+ const shouldFocusNextRef = React__default.useRef(false);
15760
15845
  const handleListboxKeyDown = event => {
15761
15846
  if (isAriaDirectionKey(event)) {
15762
15847
  setShouldPauseHoverState(true);
15848
+ return;
15849
+ }
15850
+ if (event.key === 'Tab') {
15851
+ shouldFocusNextRef.current = true;
15852
+ setOpen(false);
15853
+ return;
15854
+ }
15855
+ // support typeahead to set the value by typing its text
15856
+ if (!hasSearch && /^[a-z0-9]$/i.test(event.key)) {
15857
+ setValueIfMatched(event.key);
15858
+ return;
15763
15859
  }
15764
15860
  };
15861
+ // popover closes and unmounts before any event can be used to focus next, so prevent focusing the trigger and focus next
15765
15862
  const handleCloseAutoFocus = event => {
15766
- event.preventDefault();
15767
- event.stopPropagation();
15768
- if (tabTriggeredClose) {
15769
- const nextFocussableElement = getNextFocussableElement(internalRef.current);
15770
- if (nextFocussableElement) {
15771
- // UX requirement: move focus to the next focussable element when tab key is pressed to select the value
15772
- nextFocussableElement.focus();
15773
- // Reset the tabTriggeredClose state
15774
- setTabTriggeredClose(false);
15775
- }
15776
- } else {
15777
- var _internalRef$current;
15778
- (_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 ? void 0 : _internalRef$current.focus();
15863
+ if (shouldFocusNextRef.current) {
15864
+ var _otherProps$onBlur, _getNextFocussableEle;
15865
+ event.preventDefault();
15866
+ shouldFocusNextRef.current = false;
15867
+ (_otherProps$onBlur = otherProps.onBlur) === null || _otherProps$onBlur === void 0 ? void 0 : _otherProps$onBlur.call(otherProps, event);
15868
+ (_getNextFocussableEle = getNextFocussableElement(internalRef.current)) === null || _getNextFocussableEle === void 0 ? void 0 : _getNextFocussableEle.focus();
15869
+ return;
15779
15870
  }
15780
15871
  };
15781
- const selectOptions = searchQuery === '' ? flattenedChildren.map(child => child.props.value) : filteredChildren.map(child => isGroup(child) ? Array.isArray(child.props.children) && child.props.children.map(subChild => subChild.props.value) : child.props.value).flatMap(c => c) || [];
15782
15872
  const areAllSelected = Array.isArray(value) && selectOptions.every(option => value.includes(option));
15783
15873
  const selectAllText = React__default.useMemo(() => {
15784
15874
  if (searchQuery === '') {
@@ -15810,8 +15900,6 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15810
15900
  setValue(nextValue);
15811
15901
  }
15812
15902
  };
15813
- const hasInlineCreation = onCreate && !createDialog;
15814
- const hasSearch = flattenedChildren.length > 5 || hasInlineCreation;
15815
15903
  const className = cn('border-grey-300 rounded border bg-white py-1.5 shadow-md ', {
15816
15904
  'focus-within:yt-focus': !hasSearch,
15817
15905
  'outline-none': hasSearch
@@ -15827,18 +15915,14 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15827
15915
  }, /*#__PURE__*/React__default.createElement(Trigger$7, Object.assign({}, otherProps, {
15828
15916
  "aria-haspopup": "listbox",
15829
15917
  emptyValue: emptyValue,
15830
- onBlur: handleBlur,
15831
15918
  onKeyDown: handleKeyDown,
15832
15919
  placeholder: placeholder,
15833
15920
  ref: internalRef
15834
15921
  }), flattenedChildren)), /*#__PURE__*/React__default.createElement(PopoverPrimitive.Portal, null, /*#__PURE__*/React__default.createElement(PopoverPrimitive.Content, {
15835
15922
  asChild: true,
15836
15923
  align: "start",
15837
- onOpenAutoFocus: () => {
15838
- var _internalRef$current2;
15839
- (_internalRef$current2 = internalRef.current) === null || _internalRef$current2 === void 0 ? void 0 : _internalRef$current2.focus();
15840
- },
15841
15924
  onCloseAutoFocus: handleCloseAutoFocus,
15925
+ onPointerDownOutside: otherProps.onBlur,
15842
15926
  sideOffset: 4,
15843
15927
  tabIndex: -1
15844
15928
  }, /*#__PURE__*/React__default.createElement("div", {
@@ -15848,8 +15932,7 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15848
15932
  }
15849
15933
  }, hasSearch ? (/*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Search$2, {
15850
15934
  placeholder: hasInlineCreation ? texts.select2.searchOrCreate : texts.select2.search,
15851
- ref: searchRef,
15852
- onTabKeyPress: () => setTabTriggeredClose(true)
15935
+ ref: searchRef
15853
15936
  }), multiple && selectOptions.length > 1 && (/*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Button$1, {
15854
15937
  className: "!justify-start",
15855
15938
  appearance: "discrete",
@@ -15878,7 +15961,7 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15878
15961
  ref: listboxRef,
15879
15962
  setValue: setValue,
15880
15963
  value: value
15881
- }, searchQuery === '' ? (/*#__PURE__*/React__default.createElement(Collection$1, null, initialChildren)) : (/*#__PURE__*/React__default.createElement(Collection$1, null, filteredChildren)), onCreate ? /*#__PURE__*/React__default.createElement(Create, {
15964
+ }, /*#__PURE__*/React__default.createElement(Collection$1, null, visibleChildren), onCreate ? /*#__PURE__*/React__default.createElement(Create, {
15882
15965
  onCreate: onCreate,
15883
15966
  options: flattenedChildren
15884
15967
  }) : null))))), /*#__PURE__*/React__default.createElement(ControlledHiddenField, {
@@ -15919,6 +16002,7 @@ const ControlledHiddenField = props => {
15919
16002
  key: String(bubbleValue),
15920
16003
  multiple: multiple,
15921
16004
  name: name,
16005
+ tabIndex: -1,
15922
16006
  value: bubbleValue
15923
16007
  }, emptyValue !== undefined ? /*#__PURE__*/React__default.createElement("option", {
15924
16008
  value: emptyValue
@@ -16370,7 +16454,7 @@ function Control(props) {
16370
16454
  const ref = React__default.useRef(null);
16371
16455
  React.useEffect(() => {
16372
16456
  // 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
16373
- if (controlRenderer === 'switch' && value === undefined) {
16457
+ if ((controlRenderer === 'switch' || controlRenderer === 'checkbox') && value === undefined) {
16374
16458
  onChange(false);
16375
16459
  }
16376
16460
  }, [controlRenderer]);
@@ -16395,6 +16479,12 @@ function Control(props) {
16395
16479
  checked: Boolean(value),
16396
16480
  onChange: onChange
16397
16481
  }));
16482
+ } else if (controlRenderer === 'checkbox') {
16483
+ return /*#__PURE__*/React__default.createElement(Checkbox, Object.assign({}, attributes, {
16484
+ className: "!m-1.5",
16485
+ checked: Boolean(value),
16486
+ onChange: onChange
16487
+ }));
16398
16488
  } else if ((controlRenderer === 'input' || controlRenderer === undefined) && dataType === 'number') {
16399
16489
  return /*#__PURE__*/React__default.createElement(Input, Object.assign({}, attributes, {
16400
16490
  className: "flex-grow",
@@ -16754,8 +16844,6 @@ function TableGrid(props) {
16754
16844
  table.meta.rowActive.handleFocus(event, table.meta.length, table.renderer.scrollToIndex);
16755
16845
  } : undefined;
16756
16846
  const filterReason = getFilterReason(table);
16757
- const searchNotApplied = !table.state.globalFilter || table.state.globalFilter === '';
16758
- const filtersNotApplied = !table.state.columnFilters || table.state.columnFilters.length === 0;
16759
16847
  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, {
16760
16848
  id: table.id,
16761
16849
  "data-table-font-size": table.meta.fontSize.size,
@@ -16788,7 +16876,7 @@ function TableGrid(props) {
16788
16876
  ...table.renderer.style,
16789
16877
  height: table.renderer.style.height + ROW_HEIGHT_ESTIMATES[table.meta.rowHeight.height]
16790
16878
  } : table.renderer.style
16791
- }, table.renderer.rows, searchNotApplied && filtersNotApplied && props.children), table.meta.footer.isEnabled ? /*#__PURE__*/React__default.createElement(Foot, {
16879
+ }, table.renderer.rows, props.children), table.meta.footer.isEnabled ? /*#__PURE__*/React__default.createElement(Foot, {
16792
16880
  table: table.instance
16793
16881
  }) : null)))));
16794
16882
  }
@@ -18291,71 +18379,6 @@ const useTableRowCreation = (data, tableRef) => {
18291
18379
  };
18292
18380
  };
18293
18381
 
18294
- function useTableEditingListener(table, tableRef) {
18295
- const tableMeta = table.options.meta;
18296
- const completedRowsCount = tableMeta.editing.getCompletedRowsCount();
18297
- const localization = useLocalization();
18298
- const saveChanges = () => {
18299
- requestAnimationFrame(() => {
18300
- tableMeta.editing.saveChanges();
18301
- });
18302
- };
18303
- // save when the row changes
18304
- useLazyEffect(() => {
18305
- if (tableMeta.editing.isEditing) {
18306
- saveChanges();
18307
- }
18308
- }, [tableMeta.rowActive.rowActiveIndex]);
18309
- useLazyEffect(() => {
18310
- if (tableMeta.editing.isEditing) {
18311
- if (tableMeta.rowActive.rowActiveIndex === undefined) {
18312
- tableMeta.rowActive.setRowActiveIndex(0);
18313
- }
18314
- } else {
18315
- // save
18316
- saveChanges();
18317
- // reset detailed mode
18318
- tableMeta.editing.toggleDetailedMode(false);
18319
- // reset the last index back to the first focusable element, when editing gets turned off
18320
- tableMeta.editing.setLastFocusedCellIndex(undefined);
18321
- }
18322
- }, [tableMeta.editing.isEditing]);
18323
- // show a warning if the user navigates away without triggering save, such as using the browser back/forward button
18324
- const hasChanges = tableMeta.editing.hasChanges();
18325
- React__default.useEffect(() => {
18326
- function showUnsavedChangesWarning(event) {
18327
- if (tableMeta.editing.isEditing && hasChanges) {
18328
- event.returnValue = true;
18329
- return true;
18330
- }
18331
- return false;
18332
- }
18333
- window.addEventListener('beforeunload', showUnsavedChangesWarning);
18334
- return () => {
18335
- window.removeEventListener('beforeunload', showUnsavedChangesWarning);
18336
- };
18337
- }, [tableMeta.editing.isEditing, hasChanges]);
18338
- React__default.useEffect(() => {
18339
- if (completedRowsCount > 0) {
18340
- resetHighlightedColumnIndexes(table.getState().globalFilter, table, localization);
18341
- }
18342
- }, [completedRowsCount]);
18343
- React__default.useEffect(() => {
18344
- const onClickOutside = event => {
18345
- if (tableMeta.editing.isEditing) {
18346
- var _event$target$getAttr, _event$target;
18347
- 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 : '';
18348
- const insideTable = isElementInsideOrTriggeredFromContainer(event.target, tableRef.current) || element === 'backdrop';
18349
- if (!insideTable) {
18350
- saveChanges();
18351
- }
18352
- }
18353
- };
18354
- document.addEventListener('click', onClickOutside);
18355
- return () => document.removeEventListener('click', onClickOutside);
18356
- }, [saveChanges, tableMeta.editing.isEditing]);
18357
- }
18358
-
18359
18382
  function willRowMove(cell, change, rowIndex, localization) {
18360
18383
  const {
18361
18384
  table
@@ -18436,444 +18459,642 @@ function willRowMoveAfterSorting(cell, change, rowIndex) {
18436
18459
  }
18437
18460
  return ((_resortedRows$index = resortedRows[index]) === null || _resortedRows$index === void 0 ? void 0 : _resortedRows$index.id) !== cell.row.id;
18438
18461
  }
18439
- function animateCreateRow(id) {
18440
- const templateRow = document.querySelector(`[data-row-id="${id}"]`);
18441
- if (templateRow) {
18442
- const firstCell = templateRow.querySelector(':first-child');
18443
- const checkbox = firstCell === null || firstCell === void 0 ? void 0 : firstCell.querySelector('[data-taco="checkbox"]');
18444
- firstCell === null || firstCell === void 0 ? void 0 : firstCell.focus();
18445
- if (checkbox) {
18446
- setDataFocusAttribute(checkbox);
18447
- }
18448
- templateRow.scrollIntoView();
18449
- const keyframes = [{
18450
- background: '#b2c7ef'
18451
- }, {
18452
- background: '#ebebeb'
18453
- }];
18454
- for (const child of templateRow.children) {
18455
- child.animate(keyframes, {
18456
- duration: 1000,
18457
- easing: 'ease-out'
18458
- });
18459
- }
18462
+ const TEMPORARY_ROW_ID_PREFIX = 'temp-';
18463
+ function isTemporaryRow(rowId) {
18464
+ if (rowId === undefined) {
18465
+ return false;
18460
18466
  }
18467
+ return String(rowId).startsWith(TEMPORARY_ROW_ID_PREFIX);
18461
18468
  }
18469
+ const shortcut = {
18470
+ key: 'e',
18471
+ meta: true,
18472
+ shift: false
18473
+ };
18462
18474
 
18463
- function useTableEditing(isEnabled = false, handleSave, handleChange, validator) {
18464
- // used to switch the table into editing mode
18465
- const [isEditing, toggleEditing] = React__default.useState(false);
18466
- // used to switch the editing between "detailed" mode
18467
- const [isDetailedMode, toggleDetailedMode] = React__default.useState(false);
18468
- // store the last focused cell, so that up/down arrow key navigation remains in the same column
18469
- const [lastFocusedCellIndex, setLastFocusedCellIndex] = useLastFocusedCellIndex();
18470
- // store pending changes for each row
18471
- // changes are saved as soon as the active row changes, so in most cases this will only contain the active row's changes
18472
- // but not always - if validation or server requests fail when saving, those rows remain until the failure is resolved
18473
- const pendingChangesFns = usePendingChanges(isEnabled, handleSave, handleChange, validator);
18474
- useGlobalKeyDown(isEnabled && isEditing ? {
18475
+ function useTableEditingListener(table, tableRef, scrollToIndex) {
18476
+ const tableMeta = table.options.meta;
18477
+ const localization = useLocalization();
18478
+ // save when the row changes
18479
+ // store the last row active index, otherwise everytime tableMeta.editing.saveChanges changes the hook runs again
18480
+ const lastRowActiveIndexRef = React__default.useRef(tableMeta.rowActive.rowActiveIndex);
18481
+ useLazyEffect(() => {
18482
+ if (tableMeta.editing.isEditing && lastRowActiveIndexRef.current !== undefined && tableMeta.rowActive.rowActiveIndex !== lastRowActiveIndexRef.current) {
18483
+ lastRowActiveIndexRef.current = tableMeta.rowActive.rowActiveIndex;
18484
+ tableMeta.editing.saveChanges(table);
18485
+ }
18486
+ }, [tableMeta.rowActive.rowActiveIndex, tableMeta.editing.saveChanges]);
18487
+ // show a warning if the user navigates away without triggering save, such as using the browser back/forward button
18488
+ const hasChanges = tableMeta.editing.hasChanges();
18489
+ React__default.useEffect(() => {
18490
+ function showUnsavedChangesWarning(event) {
18491
+ if (tableMeta.editing.isEditing && hasChanges) {
18492
+ event.returnValue = true;
18493
+ return true;
18494
+ }
18495
+ return false;
18496
+ }
18497
+ window.addEventListener('beforeunload', showUnsavedChangesWarning);
18498
+ return () => {
18499
+ window.removeEventListener('beforeunload', showUnsavedChangesWarning);
18500
+ };
18501
+ }, [tableMeta.editing.isEditing, hasChanges]);
18502
+ const hasSavedChanges = tableMeta.editing.hasSaved();
18503
+ useLazyEffect(() => {
18504
+ if (hasSavedChanges) {
18505
+ resetHighlightedColumnIndexes(table.getState().globalFilter, table, localization);
18506
+ }
18507
+ }, [hasSavedChanges]);
18508
+ React__default.useEffect(() => {
18509
+ const onClickOutside = event => {
18510
+ if (tableMeta.editing.isEditing) {
18511
+ const element = event.target;
18512
+ const insideTable = element.getAttribute('data-taco') === 'backdrop' || element.getAttribute('data-table') === 'editing-toggle' || isElementInsideOrTriggeredFromContainer(element, tableRef.current);
18513
+ // users can click the white space below rows which could be inside the table, but a valid scenario to save
18514
+ if (!insideTable || element.tagName === 'TABLE' || element.tagName === 'TBODY') {
18515
+ tableMeta.editing.saveChanges(table);
18516
+ }
18517
+ }
18518
+ };
18519
+ document.addEventListener('click', onClickOutside);
18520
+ return () => document.removeEventListener('click', onClickOutside);
18521
+ }, [tableMeta.editing.isEditing, tableMeta.editing.saveChanges]);
18522
+ const rows = table.getRowModel().rows;
18523
+ // make sure pending changes are removed for rows that no longer exist
18524
+ useLazyEffect(() => {
18525
+ const pendingChanges = tableMeta.editing.getErrorsShownInAlert();
18526
+ pendingChanges.forEach(pendingChange => {
18527
+ try {
18528
+ table.getRow(pendingChange.rowId);
18529
+ } catch {
18530
+ tableMeta.editing.discardChanges(pendingChange.rowId, table);
18531
+ }
18532
+ });
18533
+ }, [rows.length]);
18534
+ // shortcuts
18535
+ useGlobalKeyDown(tableMeta.editing.isEnabled ? shortcut : undefined, event => {
18536
+ event.preventDefault();
18537
+ tableMeta.editing.toggleEditing(!tableMeta.editing.isEditing, table, scrollToIndex);
18538
+ });
18539
+ useGlobalKeyDown(tableMeta.editing.isEditing ? {
18475
18540
  key: 's',
18476
18541
  meta: true,
18477
18542
  shift: false
18478
18543
  } : undefined, event => {
18479
18544
  event.preventDefault();
18480
- pendingChangesFns.saveChanges();
18545
+ tableMeta.editing.saveChanges(table);
18481
18546
  });
18482
- return {
18483
- isEnabled,
18484
- isEditing,
18485
- isDetailedMode,
18486
- toggleDetailedMode: isEnabled ? toggleDetailedMode : () => undefined,
18487
- toggleEditing: isEnabled ? toggleEditing : () => undefined,
18488
- lastFocusedCellIndex,
18489
- setLastFocusedCellIndex,
18490
- ...pendingChangesFns
18491
- };
18492
18547
  }
18493
- function usePendingChanges(isEnabled, handleSave, handleChange, validator) {
18494
- const saveChanges = function (rowId = undefined) {
18495
- try {
18496
- let _exit = false;
18497
- if (!handleSave) {
18498
- console.warn('Tried to save, but Table has no onEditingSave handler');
18499
- return Promise.resolve();
18548
+
18549
+ const DELAY_BEFORE_REMOVING_SAVE_STATUS = 3000;
18550
+ function reducer$2(state, action) {
18551
+ const {
18552
+ type,
18553
+ rowId,
18554
+ payload
18555
+ } = action;
18556
+ switch (type) {
18557
+ case 'setCellValue':
18558
+ {
18559
+ const {
18560
+ columnId,
18561
+ row,
18562
+ value
18563
+ } = payload;
18564
+ return {
18565
+ ...state,
18566
+ changes: {
18567
+ ...state.changes,
18568
+ rows: setWith(state.changes.rows, `${rowId}.${columnId}`, value, Object),
18569
+ originals: setWith(state.changes.originals, rowId, row, Object)
18570
+ }
18571
+ };
18500
18572
  }
18501
- // we save back to pendingChanges, so make a copy of it's state when save was triggered
18502
- const changesToSave = rowId ? {
18503
- [rowId]: pendingChanges[rowId]
18504
- } : {
18505
- ...pendingChanges
18506
- };
18507
- const changes = Object.keys(changesToSave);
18508
- return Promise.resolve(function () {
18509
- if (changes.length) {
18510
- return _forOf(changes, function (rowId) {
18511
- const pendingChange = changesToSave[rowId];
18512
- const changeSet = getChangesetFromChanges(pendingChange);
18513
- return _catch(function () {
18514
- function _temp3(_result) {
18515
- return _exit ? _result : Promise.resolve(handleSave(changeSet)).then(function () {
18516
- // cleanup changes, we don't need them after saving
18517
- resetChanges(rowId);
18518
- setRowSaveStatus(rowId, 'complete');
18519
- });
18520
- }
18521
- if (getRowSaveStatus(rowId) === 'pending') {
18522
- _exit = true;
18523
- return;
18524
- }
18525
- // set saving = true
18526
- setRowSaveStatus(rowId, 'pending');
18527
- // re-run validation, maybe a cell is already invalid but has never been blurred
18528
- const _temp2 = function () {
18529
- if (validator) {
18530
- return Promise.resolve(validator(changeSet)).then(function (errors) {
18531
- if (errors && Object.keys(errors).length) {
18532
- throw errors;
18533
- }
18534
- });
18535
- }
18536
- }();
18537
- return _temp2 && _temp2.then ? _temp2.then(_temp3) : _temp3(_temp2); // send new data to the server
18538
- }, function (error) {
18539
- // the onEditingSave handler should throw errors when something fails, e.g. validation, network errors etc
18540
- // this code handles those errors and maps them either to row errors or cell specific errors
18541
- let rowError;
18542
- let cellErrors;
18543
- if (typeof error === 'string') {
18544
- rowError = error;
18545
- } else if (error instanceof Error) {
18546
- var _error$response;
18547
- rowError = error.message;
18548
- // most of our apis return error objects within this shape
18549
- if (typeof ((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.data) === 'object') {
18550
- var _error$response2;
18551
- cellErrors = (_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.data;
18552
- }
18553
- } else if (typeof error === 'object') {
18554
- cellErrors = error;
18555
- }
18556
- if (rowError || cellErrors) {
18557
- setPendingChanges(currentChanges => {
18558
- const nextChanges = {
18559
- ...currentChanges
18560
- };
18561
- nextChanges[rowId]._meta.errors = {
18562
- row: rowError,
18563
- cells: cellErrors,
18564
- shouldShowErrorAlert: true
18565
- };
18566
- return nextChanges;
18567
- });
18568
- }
18569
- setRowSaveStatus(rowId, undefined);
18570
- });
18571
- }, function () {
18572
- return _exit;
18573
+ case 'removeCellValue':
18574
+ {
18575
+ const {
18576
+ columnId,
18577
+ rowIdentityAccessor
18578
+ } = payload;
18579
+ const changes = omit(state.changes.rows, `${rowId}.${columnId}`);
18580
+ // if there are no changes left, remove the row
18581
+ if (!Object.keys(changes[rowId]).length) {
18582
+ return reducer$2(state, {
18583
+ type: 'removeRow',
18584
+ rowId,
18585
+ payload: {
18586
+ rowIdentityAccessor
18587
+ }
18573
18588
  });
18574
18589
  }
18575
- }());
18590
+ return {
18591
+ ...state,
18592
+ changes: {
18593
+ ...state.changes,
18594
+ rows: omit(state.changes.rows, `${rowId}.${columnId}`),
18595
+ errors: omit(state.changes.errors, `${rowId}.cells.${columnId}`),
18596
+ moveReasons: omit(state.changes.moveReasons, `${rowId}.${columnId}`)
18597
+ }
18598
+ };
18599
+ }
18600
+ case 'updateRow':
18601
+ {
18602
+ const {
18603
+ cellErrors,
18604
+ moveReasons,
18605
+ original,
18606
+ value
18607
+ } = payload;
18608
+ return {
18609
+ ...state,
18610
+ changes: {
18611
+ ...state.changes,
18612
+ rows: setWith(state.changes.rows, rowId, value, Object),
18613
+ errors: setWith(state.changes.errors, `${rowId}.cells`, cellErrors !== null && cellErrors !== void 0 ? cellErrors : state.changes.errors.cells[rowId], Object),
18614
+ originals: setWith(state.changes.originals, rowId, original !== null && original !== void 0 ? original : state.changes.originals[rowId], Object),
18615
+ moveReasons: setWith(state.changes.moveReasons, rowId, moveReasons !== null && moveReasons !== void 0 ? moveReasons : state.changes.moveReasons[rowId], Object),
18616
+ // status can be undefined, so don't use ??
18617
+ status: setWith(state.changes.status, rowId, undefined, Object)
18618
+ }
18619
+ };
18620
+ }
18621
+ case 'removeRow':
18622
+ {
18623
+ const {
18624
+ rowIdentityAccessor
18625
+ } = payload;
18626
+ return {
18627
+ ...state,
18628
+ changes: {
18629
+ ...state.changes,
18630
+ rows: omit(state.changes.rows, rowId),
18631
+ errors: omit(state.changes.errors, rowId),
18632
+ moveReasons: omit(state.changes.moveReasons, rowId),
18633
+ originals: omit(state.changes.originals, rowId),
18634
+ status: omit(state.changes.status, rowId)
18635
+ },
18636
+ temporaryRows: state.temporaryRows.filter(row => row[rowIdentityAccessor] !== rowId)
18637
+ };
18638
+ }
18639
+ case 'setRowStatus':
18640
+ {
18641
+ const {
18642
+ status
18643
+ } = payload;
18644
+ return {
18645
+ ...state,
18646
+ changes: {
18647
+ ...state.changes,
18648
+ status: status ? setWith(state.changes.status, rowId, status, Object) : omit(state.changes.status, rowId)
18649
+ }
18650
+ };
18651
+ }
18652
+ case 'setRowErrors':
18653
+ {
18654
+ const {
18655
+ ...errors
18656
+ } = payload;
18657
+ return {
18658
+ ...state,
18659
+ changes: {
18660
+ ...state.changes,
18661
+ errors: setWith(state.changes.errors, rowId, errors, Object)
18662
+ }
18663
+ };
18664
+ }
18665
+ case 'createRow':
18666
+ {
18667
+ const {
18668
+ value
18669
+ } = payload;
18670
+ return {
18671
+ ...state,
18672
+ temporaryRows: state.temporaryRows.concat(value),
18673
+ changes: {
18674
+ ...state.changes,
18675
+ rows: setWith(state.changes.rows, rowId, value, Object),
18676
+ originals: setWith(state.changes.originals, rowId, value, Object)
18677
+ }
18678
+ };
18679
+ }
18680
+ default:
18681
+ return state;
18682
+ }
18683
+ }
18684
+ function usePendingChangesState(handleSave, handleChange, rowIdentityAccessor, validator) {
18685
+ const saveChanges = function (table, rowId = undefined) {
18686
+ try {
18687
+ let _exit = false;
18688
+ if (!handleSave) {
18689
+ console.warn('Tried to save, but Table has no onEditingSave handler');
18690
+ return Promise.resolve(false);
18691
+ }
18692
+ // sometimes we only want to save one row
18693
+ const changes = rowId ? {
18694
+ [rowId]: state.changes.rows[rowId]
18695
+ } : state.changes.rows;
18696
+ let completed = true;
18697
+ const _temp9 = _forOf(Object.keys(changes), function (rowId) {
18698
+ const status = getRowStatus(rowId);
18699
+ return _catch(function () {
18700
+ function _temp8(_result) {
18701
+ return _exit ? _result : Promise.resolve(handleSave(changeSet)).then(function () {
18702
+ // cleanup changes, we don't need them after saving
18703
+ discardChanges(rowId, table);
18704
+ // show the saved status, then remove it after a delay
18705
+ setRowStatus(rowId, 'saved');
18706
+ setTimeout(() => {
18707
+ setRowStatus(rowId, undefined);
18708
+ }, DELAY_BEFORE_REMOVING_SAVE_STATUS);
18709
+ });
18710
+ }
18711
+ // don't try to save if - already saving, or there are known errors
18712
+ if (status === 'saving' || status === 'errored') {
18713
+ return;
18714
+ }
18715
+ setRowStatus(rowId, 'saving');
18716
+ const changeSet = {
18717
+ ...state.changes.originals[rowId],
18718
+ ...changes[rowId]
18719
+ };
18720
+ // if we had to create a temporary id, delete it first - it's our data, not theirs
18721
+ if (isTemporaryRow(changeSet[rowIdentityAccessor])) {
18722
+ delete changeSet[rowIdentityAccessor];
18723
+ }
18724
+ // re-run validation, maybe a cell is already invalid but has never been blurred
18725
+ const _temp7 = function () {
18726
+ if (validator) {
18727
+ return Promise.resolve(validator(changeSet)).then(function (errors) {
18728
+ if (errors && Object.keys(errors).length) {
18729
+ throw errors;
18730
+ }
18731
+ });
18732
+ }
18733
+ }();
18734
+ return _temp7 && _temp7.then ? _temp7.then(_temp8) : _temp8(_temp7); // send new data to the server
18735
+ }, function (error) {
18736
+ var _error$response;
18737
+ 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) {
18738
+ console.error(error);
18739
+ }
18740
+ // the onEditingSave handler should throw errors when something fails, e.g. validation, network errors etc
18741
+ // this code handles those errors and maps them either to row errors or cell specific errors
18742
+ let rowError;
18743
+ let cellErrors;
18744
+ if (typeof error === 'string') {
18745
+ rowError = error;
18746
+ } else if (error instanceof Error) {
18747
+ var _error$response2;
18748
+ rowError = error.message;
18749
+ // most of our apis return error objects within this shape
18750
+ if (typeof ((_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.data) === 'object') {
18751
+ var _error$response3;
18752
+ cellErrors = (_error$response3 = error.response) === null || _error$response3 === void 0 ? void 0 : _error$response3.data;
18753
+ }
18754
+ } else if (typeof error === 'object') {
18755
+ cellErrors = error;
18756
+ }
18757
+ if (rowError || cellErrors) {
18758
+ dispatch({
18759
+ type: 'setRowErrors',
18760
+ rowId,
18761
+ payload: {
18762
+ row: rowError,
18763
+ cells: cellErrors,
18764
+ shouldShowErrorAlert: true
18765
+ }
18766
+ });
18767
+ }
18768
+ setRowStatus(rowId, 'errored');
18769
+ completed = false;
18770
+ });
18771
+ }, function () {
18772
+ return _exit;
18773
+ });
18774
+ return Promise.resolve(_temp9 && _temp9.then ? _temp9.then(function (_result3) {
18775
+ return _exit ? _result3 : completed;
18776
+ }) : _exit ? _temp9 : completed);
18576
18777
  } catch (e) {
18577
18778
  return Promise.reject(e);
18578
18779
  }
18579
18780
  };
18580
- const validateCell = function (cell) {
18781
+ const onCellChanged = function (cell, rowIndex, shouldRunUpdaters = true) {
18581
18782
  try {
18582
- if (!validator || !isEnabled) {
18583
- return Promise.resolve();
18584
- }
18585
- const changeSet = getChangesetFromChanges(pendingChanges[cell.row.id]);
18586
- // only validate if the cell being blurred actually has any changes
18587
- const _temp = function () {
18588
- if (cell.column.id in changeSet) {
18589
- return Promise.resolve(validator(changeSet)).then(function (errors) {
18590
- setPendingChanges(currentChanges => {
18591
- const nextChanges = {
18592
- ...currentChanges
18593
- };
18594
- nextChanges[cell.row.id]._meta = {
18595
- ...nextChanges[cell.row.id]._meta,
18596
- errors: {
18597
- ...nextChanges[cell.row.id]._meta.errors,
18598
- cells: errors,
18599
- shouldShowErrorAlert: !Object.keys(errors).length ? false : nextChanges[cell.row.id]._meta.errors.shouldShowErrorAlert
18783
+ function _temp6() {
18784
+ var _state$changes$errors11;
18785
+ function _temp4() {
18786
+ // only set errors and move reasons for the cells we're currently acting on
18787
+ // why? because the UX is not good if we set them for cells the user hasn't touched yet
18788
+ const cellsToActOn = [cell.column.id, ...Object.keys(updatesForOtherCells)];
18789
+ const allCells = cell.row._getAllCellsByColumnId();
18790
+ cellsToActOn.forEach(accessor => {
18791
+ if (validationErrors[accessor]) {
18792
+ nextCellErrors[accessor] = validationErrors[accessor];
18793
+ // don't show move indicator for cells with errors, they aren't valid and can't be saved
18794
+ delete nextMoveReasons[accessor];
18795
+ } else {
18796
+ var _allCells$accessor;
18797
+ // there isn't any error in this run, remove any error set in state
18798
+ delete nextCellErrors[accessor];
18799
+ if ((_allCells$accessor = allCells[accessor]) !== null && _allCells$accessor !== void 0 && _allCells$accessor.column.getIsSorted()) {
18800
+ // run row move determination
18801
+ const reason = willRowMove(cell, nextChanges[accessor], rowIndex, localization);
18802
+ // if the row will move based on this change save why, otherwise delete any existing state
18803
+ if (reason) {
18804
+ nextMoveReasons[accessor] = reason;
18805
+ } else {
18806
+ delete nextMoveReasons[accessor];
18600
18807
  }
18601
- };
18602
- return nextChanges;
18808
+ }
18809
+ }
18810
+ });
18811
+ dispatch({
18812
+ type: 'updateRow',
18813
+ rowId: cell.row.id,
18814
+ payload: {
18815
+ cellErrors: nextCellErrors,
18816
+ moveReasons: nextMoveReasons,
18817
+ value: nextChanges
18818
+ }
18819
+ });
18820
+ }
18821
+ // create a projection of the next state, so we can act against it
18822
+ const nextChanges = {
18823
+ ...state.changes.rows[cell.row.id],
18824
+ ...updatesForOtherCells
18825
+ };
18826
+ const nextMoveReasons = {
18827
+ ...state.changes.moveReasons[cell.row.id]
18828
+ };
18829
+ const nextCellErrors = {
18830
+ ...((_state$changes$errors11 = state.changes.errors[cell.row.id]) === null || _state$changes$errors11 === void 0 ? void 0 : _state$changes$errors11.cells)
18831
+ };
18832
+ // run validation
18833
+ let validationErrors = {};
18834
+ const _temp3 = function () {
18835
+ if (validator) {
18836
+ const nextRowValue = {
18837
+ ...state.changes.originals[cell.row.id],
18838
+ ...changes,
18839
+ ...updatesForOtherCells
18840
+ };
18841
+ return Promise.resolve(validator(nextRowValue)).then(function (_validator2) {
18842
+ validationErrors = _validator2 !== null && _validator2 !== void 0 ? _validator2 : {};
18603
18843
  });
18844
+ }
18845
+ }();
18846
+ return _temp3 && _temp3.then ? _temp3.then(_temp4) : _temp4(_temp3);
18847
+ }
18848
+ const changes = state.changes.rows[cell.row.id];
18849
+ if (!changes) {
18850
+ return Promise.resolve();
18851
+ }
18852
+ let updatesForOtherCells = {};
18853
+ // run the updater handler if there is one, to see if there are any other cells to update
18854
+ const _temp5 = function () {
18855
+ if (typeof handleChange === 'function' && shouldRunUpdaters) {
18856
+ const previousRowValue = {
18857
+ ...state.changes.originals[cell.row.id]
18858
+ };
18859
+ const nextRowValue = {
18860
+ ...state.changes.originals[cell.row.id],
18861
+ ...changes
18862
+ };
18863
+ return Promise.resolve(handleChange(cell.column.id, changes[cell.column.id], nextRowValue, previousRowValue)).then(function (_handleChange) {
18864
+ updatesForOtherCells = _handleChange !== null && _handleChange !== void 0 ? _handleChange : {};
18604
18865
  });
18605
18866
  }
18606
18867
  }();
18607
- return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
18608
- } catch (e) {
18609
- return Promise.reject(e);
18610
- }
18611
- };
18612
- const setCellValue = function (cell, change, rowIndex) {
18613
- try {
18614
- const changes = {
18615
- [cell.column.id]: change
18616
- };
18617
- setPendingChanges(currentChanges => {
18618
- const nextChanges = createPendingChangesSetter(currentChanges, cell.row, rowIndex, changes, localization);
18619
- pendingChangesUpdater.syncCellChanges(nextChanges);
18620
- return nextChanges;
18621
- });
18622
- pendingChangesUpdater.runCellUpdates(changes, cell, rowIndex);
18623
- return Promise.resolve();
18868
+ return Promise.resolve(_temp5 && _temp5.then ? _temp5.then(_temp6) : _temp6(_temp5));
18624
18869
  } catch (e) {
18625
18870
  return Promise.reject(e);
18626
18871
  }
18627
- };
18628
- const addCreatedRowChangeset = function (row) {
18872
+ }; // general
18873
+ // rows
18874
+ const setRowValue = function (rowId, original, value) {
18629
18875
  try {
18630
- const cells = row.getAllCells();
18631
- setPendingChanges(currentChanges => {
18632
- return cells.reduce((changes, cell) => {
18633
- if (cell.getValue()) {
18634
- var _currentChanges$cell$, _currentChanges$cell$2, _currentChanges$cell$3;
18635
- return {
18636
- ...changes,
18637
- [cell.row.id]: {
18638
- ...changes[cell.row.id],
18639
- [cell.column.id]: cell.getValue(),
18640
- _meta: {
18641
- ...((_currentChanges$cell$ = currentChanges[cell.row.id]) === null || _currentChanges$cell$ === void 0 ? void 0 : _currentChanges$cell$._meta),
18642
- original: cell.row.original,
18643
- moveReason: {
18644
- ...((_currentChanges$cell$2 = currentChanges[cell.row.id]) === null || _currentChanges$cell$2 === void 0 ? void 0 : _currentChanges$cell$2._meta.moveReason)
18645
- },
18646
- errors: {
18647
- ...((_currentChanges$cell$3 = currentChanges[cell.row.id]) === null || _currentChanges$cell$3 === void 0 ? void 0 : _currentChanges$cell$3._meta.errors)
18648
- }
18649
- }
18650
- }
18651
- };
18652
- } else {
18653
- return changes;
18876
+ function _temp2() {
18877
+ dispatch({
18878
+ type: 'updateRow',
18879
+ rowId,
18880
+ payload: {
18881
+ cellErrors,
18882
+ original,
18883
+ value
18654
18884
  }
18655
- }, currentChanges);
18656
- });
18657
- return Promise.resolve();
18885
+ });
18886
+ }
18887
+ let cellErrors;
18888
+ const _temp = function () {
18889
+ if (validator) {
18890
+ const row = {
18891
+ ...original,
18892
+ ...value
18893
+ };
18894
+ return Promise.resolve(validator(row)).then(function (_validator) {
18895
+ cellErrors = _validator !== null && _validator !== void 0 ? _validator : {};
18896
+ });
18897
+ }
18898
+ }();
18899
+ return Promise.resolve(_temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp));
18658
18900
  } catch (e) {
18659
18901
  return Promise.reject(e);
18660
18902
  }
18661
18903
  };
18662
18904
  const localization = useLocalization();
18663
- const [pendingChanges, setPendingChanges] = React__default.useState({});
18664
- // we maintain save status as separate state because 'complete' needs to briefly show after pendingChanges are deleted
18665
- const [saveStates, setSaveState] = React__default.useState({});
18666
- function getCellValue(cell) {
18667
- var _pendingChanges$cell$;
18668
- return (_pendingChanges$cell$ = pendingChanges[cell.row.id]) === null || _pendingChanges$cell$ === void 0 ? void 0 : _pendingChanges$cell$[cell.column.id];
18905
+ const [state, dispatch] = React__default.useReducer(reducer$2, {
18906
+ changes: {
18907
+ rows: {},
18908
+ errors: {},
18909
+ moveReasons: {},
18910
+ originals: {},
18911
+ status: {}
18912
+ },
18913
+ temporaryRows: []
18914
+ });
18915
+ function getRowValue(rowId) {
18916
+ var _state$changes$rows$r, _state$changes$rows;
18917
+ 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;
18669
18918
  }
18670
- function getCellError(cell) {
18671
- var _pendingChanges$cell$2, _pendingChanges$cell$3, _pendingChanges$cell$4;
18672
- 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];
18919
+ function getRowMoveReason(rowId) {
18920
+ var _Object$values$, _state$changes$moveRe, _state$changes$moveRe2;
18921
+ 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;
18673
18922
  }
18674
- const pendingChangesUpdater = usePendingChangesUpdater(handleChange, setPendingChanges);
18675
18923
  function hasRowErrors(rowId) {
18676
- var _pendingChanges$rowId, _pendingChanges$rowId2, _pendingChanges$rowId3, _pendingChanges$rowId4, _pendingChanges$rowId5;
18677
- if (!isEnabled) {
18678
- return false;
18679
- }
18680
- 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;
18924
+ var _state$changes$errors, _state$changes$errors2, _state$changes$errors3;
18925
+ 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;
18926
+ }
18927
+ function hasRowErrorsShownInAlert(rowId) {
18928
+ var _state$changes$errors4;
18929
+ return hasRowErrors(rowId) && !!((_state$changes$errors4 = state.changes.errors[rowId]) !== null && _state$changes$errors4 !== void 0 && _state$changes$errors4.shouldShowErrorAlert);
18681
18930
  }
18682
- function hasRowErrorsSeen(rowId) {
18683
- var _pendingChanges$rowId6;
18684
- if (!isEnabled) {
18931
+ function hasTemporaryRowErrors() {
18932
+ var _state$temporaryRows, _state$changes$errors5, _state$changes$errors6, _state$changes$errors7;
18933
+ const newRow = (_state$temporaryRows = state.temporaryRows) === null || _state$temporaryRows === void 0 ? void 0 : _state$temporaryRows[0];
18934
+ if (!newRow) {
18685
18935
  return false;
18686
18936
  }
18687
- return hasRowErrors(rowId) && !!((_pendingChanges$rowId6 = pendingChanges[rowId]._meta.errors) !== null && _pendingChanges$rowId6 !== void 0 && _pendingChanges$rowId6.shouldShowErrorAlert);
18937
+ const rowId = newRow[rowIdentityAccessor];
18938
+ 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;
18688
18939
  }
18689
- function getRowPendingChange(rowId) {
18690
- const rowPendingChanges = pendingChanges[rowId];
18691
- if (rowPendingChanges) {
18692
- const {
18693
- _meta,
18694
- ...pendingChange
18695
- } = rowPendingChanges;
18696
- return pendingChange;
18697
- }
18698
- return undefined;
18940
+ function getRowStatus(rowId) {
18941
+ return state.changes.status[rowId];
18699
18942
  }
18700
- function getRowSaveStatus(rowId) {
18701
- if (!isEnabled) {
18702
- return false;
18703
- }
18704
- return saveStates[rowId];
18943
+ function setRowStatus(rowId, status) {
18944
+ dispatch({
18945
+ type: 'setRowStatus',
18946
+ rowId,
18947
+ payload: {
18948
+ status
18949
+ }
18950
+ });
18705
18951
  }
18706
- function setRowSaveStatus(rowId, status) {
18707
- setSaveState(currentStates => {
18708
- const nextStates = {
18709
- ...currentStates
18710
- };
18711
- if (status) {
18712
- nextStates[rowId] = status;
18713
- } else {
18714
- delete nextStates[rowId];
18952
+ function createRow(data) {
18953
+ const newRowId = `${TEMPORARY_ROW_ID_PREFIX}${uuid.v4()}`;
18954
+ const value = {
18955
+ ...data,
18956
+ [rowIdentityAccessor]: newRowId
18957
+ };
18958
+ dispatch({
18959
+ type: 'createRow',
18960
+ rowId: newRowId,
18961
+ payload: {
18962
+ value
18715
18963
  }
18716
- return nextStates;
18717
18964
  });
18965
+ return newRowId;
18966
+ }
18967
+ // cells
18968
+ function setCellValue(cell, value) {
18969
+ const rowId = cell.row.id;
18970
+ const columnId = cell.column.id;
18971
+ // update if the change is different to the original value
18972
+ if (value !== cell.row.original[columnId]) {
18973
+ dispatch({
18974
+ type: 'setCellValue',
18975
+ rowId,
18976
+ payload: {
18977
+ columnId,
18978
+ row: cell.row.original,
18979
+ value
18980
+ }
18981
+ });
18982
+ }
18983
+ // otherwise remove any previous change - no point saving the same value
18984
+ else if (cell.row.id in state.changes.rows) {
18985
+ dispatch({
18986
+ type: 'removeCellValue',
18987
+ rowId,
18988
+ payload: {
18989
+ columnId,
18990
+ rowIdentityAccessor
18991
+ }
18992
+ });
18993
+ }
18718
18994
  }
18719
- function getRowMoveReason(rowId) {
18720
- var _pendingChanges$rowId7;
18721
- return (_pendingChanges$rowId7 = pendingChanges[rowId]) !== null && _pendingChanges$rowId7 !== void 0 && _pendingChanges$rowId7._meta.moveReason ? Object.values(pendingChanges[rowId]._meta.moveReason)[0] : undefined;
18995
+ function getCellValue(cell) {
18996
+ var _state$changes$rows2, _state$changes$rows2$;
18997
+ 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];
18722
18998
  }
18723
- function hasChanges(rowId) {
18724
- if (!isEnabled) {
18725
- return false;
18726
- }
18727
- return rowId ? !!pendingChanges[rowId] : !!Object.keys(pendingChanges).length;
18999
+ function getCellError(cell) {
19000
+ var _state$changes$errors8, _state$changes$errors9, _state$changes$errors10;
19001
+ 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];
18728
19002
  }
18729
- function hasAlertErrors() {
18730
- if (!isEnabled) {
18731
- return false;
19003
+ function getErrorsShownInAlert() {
19004
+ const rowsWithErrors = Object.keys(state.changes.errors);
19005
+ if (!rowsWithErrors.length) {
19006
+ return [];
18732
19007
  }
18733
- return !!getAlertErrors().length;
18734
- }
18735
- function getAlertErrors() {
18736
- return Object.keys(pendingChanges).filter(hasRowErrorsSeen).map(rowId => ({
19008
+ return rowsWithErrors.filter(hasRowErrorsShownInAlert).map(rowId => ({
18737
19009
  rowId,
18738
- pendingChange: pendingChanges[rowId]
19010
+ changes: state.changes.rows[rowId],
19011
+ errors: state.changes.errors[rowId]
18739
19012
  }));
18740
19013
  }
18741
- function resetChanges(rowId) {
18742
- setPendingChanges(currentChanges => {
18743
- const nextChanges = {
18744
- ...currentChanges
18745
- };
18746
- delete nextChanges[rowId];
18747
- return nextChanges;
18748
- });
19014
+ function hasSaved() {
19015
+ return !!Object.values(state.changes.status).filter(value => value === 'saved').length;
18749
19016
  }
18750
- function getCompletedRowsCount() {
18751
- return Object.values(saveStates).filter(value => value === 'complete').length;
19017
+ function hasChanges(rowId) {
19018
+ return rowId ? !!state.changes.rows[rowId] : !!Object.keys(state.changes.rows).length;
19019
+ }
19020
+ function discardChanges(rowId, table) {
19021
+ // remove any new rows from pinned state before discarding them
19022
+ table.resetRowPinning(true);
19023
+ dispatch({
19024
+ type: 'removeRow',
19025
+ rowId,
19026
+ payload: {
19027
+ rowIdentityAccessor
19028
+ }
19029
+ });
18752
19030
  }
18753
19031
  return {
19032
+ // row
19033
+ setRowValue,
19034
+ getRowValue,
19035
+ getRowMoveReason,
19036
+ hasRowErrors,
19037
+ hasRowErrorsShownInAlert,
19038
+ hasTemporaryRowErrors,
19039
+ getRowStatus,
19040
+ setRowStatus,
19041
+ // cells
19042
+ setCellValue,
18754
19043
  getCellValue,
18755
19044
  getCellError,
18756
- setCellValue,
18757
- validateCell,
18758
- addCreatedRowChangeset,
19045
+ onCellChanged,
19046
+ // general
19047
+ getErrorsShownInAlert,
18759
19048
  hasChanges,
18760
- hasAlertErrors,
18761
- getAlertErrors,
18762
19049
  saveChanges,
18763
- resetChanges,
18764
- hasRowErrors,
18765
- hasRowErrorsSeen,
18766
- getRowPendingChange,
18767
- getRowSaveStatus,
18768
- setRowSaveStatus,
18769
- getRowMoveReason,
18770
- getCompletedRowsCount
19050
+ discardChanges,
19051
+ hasSaved,
19052
+ // new rows
19053
+ createRow,
19054
+ temporaryRows: state.temporaryRows
18771
19055
  };
18772
19056
  }
18773
- function useLastFocusedCellIndex() {
19057
+
19058
+ function useTableEditing(isEnabled = false, handleSave, handleChange, rowIdentityAccessor, validator) {
19059
+ // used to switch the table into editing mode
19060
+ const [isEditing, setEditing] = React__default.useState(false);
19061
+ // used to switch the editing between "detailed" mode
19062
+ const [isDetailedMode, toggleDetailedMode] = React__default.useState(false);
19063
+ // used to contain ref to the create button
19064
+ const createRowButtonRef = React__default.useRef(null);
18774
19065
  // store the last focused cell, so that up/down arrow key navigation remains in the same column
18775
- const lastFocusedCellIndexRef = React__default.useRef(undefined);
18776
- const setLastFocusedCellIndex = React__default.useCallback(index => {
18777
- lastFocusedCellIndexRef.current = index;
18778
- }, []);
18779
- return [lastFocusedCellIndexRef.current, setLastFocusedCellIndex];
18780
- }
18781
- function usePendingChangesUpdater(handleChange, setPendingChanges) {
18782
- const localization = useLocalization();
18783
- const updatersRef = React__default.useRef({});
18784
- const runCellUpdates = React__default.useCallback(lodash.debounce(function (changes, cell, rowIndex) {
18785
- try {
18786
- const _temp4 = function () {
18787
- if (typeof handleChange === 'function') {
18788
- const previousValues = {
18789
- ...cell.row.original,
18790
- ...getChangesetFromChanges(updatersRef.current[cell.row.id])
18791
- };
18792
- const nextValues = {
18793
- ...previousValues,
18794
- ...changes
18795
- };
18796
- return Promise.resolve(handleChange(cell.column.id, changes[cell.column.id], nextValues, previousValues)).then(function (updates) {
18797
- if (updates && Object.keys(updates).length) {
18798
- setPendingChanges(currentChanges => createPendingChangesSetter(currentChanges, cell.row, rowIndex, updates, localization));
18799
- }
18800
- });
18801
- }
18802
- }();
18803
- return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(function () {}) : void 0);
18804
- } catch (e) {
18805
- return Promise.reject(e);
19066
+ const [lastFocusedCellIndex, setLastFocusedCellIndex] = React__default.useState(undefined);
19067
+ const pendingChangesFns = usePendingChangesState(handleSave, handleChange, rowIdentityAccessor, validator);
19068
+ function toggleEditing(enabled, table, scrollToIndex) {
19069
+ var _tableMeta$rowActive$, _table$getRowModel$ro;
19070
+ if (!enabled) {
19071
+ // save
19072
+ pendingChangesFns.saveChanges(table);
19073
+ // reset detailed mode
19074
+ toggleDetailedMode(false);
19075
+ // reset the last index back to the first focusable element, when editing gets turned off
19076
+ setLastFocusedCellIndex(undefined);
18806
19077
  }
18807
- }, 250), []);
18808
- function syncCellChanges(changes) {
18809
- updatersRef.current = changes;
18810
- }
18811
- return {
18812
- syncCellChanges,
18813
- runCellUpdates
18814
- };
18815
- }
18816
- function createPendingChangesSetter(currentChanges, row, rowIndex, changes, localization) {
18817
- var _currentChanges$row$i, _currentChanges$row$i2, _currentChanges$row$i3;
18818
- // prepare
18819
- const nextChanges = {
18820
- ...currentChanges
18821
- };
18822
- const rowChanges = {
18823
- ...currentChanges[row.id],
18824
- _meta: {
18825
- ...((_currentChanges$row$i = currentChanges[row.id]) === null || _currentChanges$row$i === void 0 ? void 0 : _currentChanges$row$i._meta),
18826
- original: row.original,
18827
- moveReason: {
18828
- ...((_currentChanges$row$i2 = currentChanges[row.id]) === null || _currentChanges$row$i2 === void 0 ? void 0 : _currentChanges$row$i2._meta.moveReason)
18829
- },
18830
- errors: {
18831
- ...((_currentChanges$row$i3 = currentChanges[row.id]) === null || _currentChanges$row$i3 === void 0 ? void 0 : _currentChanges$row$i3._meta.errors)
18832
- }
19078
+ const tableMeta = table.options.meta;
19079
+ const index = (_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0;
19080
+ if (tableMeta.rowActive.rowActiveIndex === undefined) {
19081
+ tableMeta.rowActive.setRowActiveIndex(index);
18833
19082
  }
18834
- };
18835
- // run changes
18836
- const cells = row._getAllCellsByColumnId();
18837
- for (const [accessor, change] of Object.entries(changes)) {
18838
- // update if the change is different to the original (saved) value,
18839
- // otherwise remove any change - no point saving the same value
18840
- if (change !== row.original[accessor]) {
18841
- rowChanges[accessor] = change;
18842
- // consumers sometimes include properties in onEditingChange that aren't rendered as columns, we need to guard against that.
18843
- // eslint-disable-next-line no-prototype-builtins
18844
- if (cells.hasOwnProperty(accessor)) {
18845
- // determine if the row will move position based on this change, and save why it will move
18846
- const reason = willRowMove(cells[accessor], change, rowIndex, localization);
18847
- if (reason) {
18848
- rowChanges._meta.moveReason[accessor] = reason;
18849
- } else {
18850
- delete rowChanges._meta.moveReason[accessor];
18851
- }
18852
- }
18853
- } else {
18854
- delete rowChanges[accessor];
18855
- delete rowChanges._meta.moveReason[accessor];
19083
+ setEditing(enabled);
19084
+ if (!isTemporaryRow((_table$getRowModel$ro = table.getRowModel().rows[index]) === null || _table$getRowModel$ro === void 0 ? void 0 : _table$getRowModel$ro.id)) {
19085
+ scrollToIndex(index);
18856
19086
  }
18857
19087
  }
18858
- // set changes
18859
- // or delete if there are no changes left, so that we don't store changes with unchanged data
18860
- if (Object.keys(rowChanges).filter(k => k !== '_meta').length) {
18861
- nextChanges[row.id] = rowChanges;
18862
- } else {
18863
- delete nextChanges[row.id];
18864
- }
18865
- return nextChanges;
18866
- }
18867
- function getChangesetFromChanges(changes) {
18868
- // extract the original data from the row changes
18869
- const {
18870
- _meta,
18871
- ...changeset
18872
- } = changes !== null && changes !== void 0 ? changes : {};
18873
- // and mix them in with the changes, ready to send to the server
18874
19088
  return {
18875
- ...(_meta === null || _meta === void 0 ? void 0 : _meta.original),
18876
- ...changeset
19089
+ isEnabled,
19090
+ isEditing,
19091
+ isDetailedMode,
19092
+ toggleDetailedMode: isEnabled ? toggleDetailedMode : () => undefined,
19093
+ toggleEditing: isEnabled ? toggleEditing : () => undefined,
19094
+ lastFocusedCellIndex,
19095
+ setLastFocusedCellIndex,
19096
+ createRowButtonRef,
19097
+ ...pendingChangesFns
18877
19098
  };
18878
19099
  }
18879
19100
 
@@ -18917,7 +19138,6 @@ function RowMoveIndicator(props) {
18917
19138
  if (!show) {
18918
19139
  return null;
18919
19140
  }
18920
- 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';
18921
19141
  const {
18922
19142
  title,
18923
19143
  description
@@ -18926,7 +19146,7 @@ function RowMoveIndicator(props) {
18926
19146
  placement: "bottom",
18927
19147
  title: description.replace('[COLUMN]', columnMeta.header)
18928
19148
  }, /*#__PURE__*/React__default.createElement("span", {
18929
- className: className
19149
+ "data-row-move-indicator": true
18930
19150
  }, /*#__PURE__*/React__default.createElement(Icon, {
18931
19151
  name: "info",
18932
19152
  className: "-mt-0.5 mr-1 !h-4 !w-4 rounded-full bg-white !p-0 text-blue-500"
@@ -19115,13 +19335,31 @@ function EditingControlCell(props) {
19115
19335
  const {
19116
19336
  rowIndex
19117
19337
  } = React__default.useContext(RowContext);
19118
- const tableMeta = cell.getContext().table.options.meta;
19338
+ const {
19339
+ table
19340
+ } = cell.getContext();
19341
+ const tableMeta = table.options.meta;
19119
19342
  const columnMeta = cell.column.columnDef.meta;
19120
19343
  const isActiveRow = tableMeta.rowActive.rowActiveIndex === rowIndex;
19344
+ const type = (_columnMeta$control = columnMeta.control) !== null && _columnMeta$control !== void 0 ? _columnMeta$control : 'input';
19121
19345
  const handleFocus = useEditingCellAutofocus(props);
19346
+ const value = cell.getValue();
19347
+ // some controls, like select2, should trigger cell changed (validation, updates) as the value changes
19348
+ const hasNonTextControl = React__default.useMemo(() => {
19349
+ var _cellRef$current;
19350
+ 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"]'));
19351
+ }, [cellRef.current]);
19352
+ const handleChange = nextValue => {
19353
+ if (nextValue !== value) {
19354
+ tableMeta.editing.setCellValue(cell, nextValue);
19355
+ if (hasNonTextControl) {
19356
+ tableMeta.editing.onCellChanged(cell, rowIndex);
19357
+ }
19358
+ }
19359
+ };
19122
19360
  const handleBlur = () => {
19123
19361
  tableMeta.editing.toggleDetailedMode(false);
19124
- tableMeta.editing.validateCell(cell);
19362
+ tableMeta.editing.onCellChanged(cell, rowIndex, !hasNonTextControl);
19125
19363
  };
19126
19364
  // ensure that blur runs when the cell gets unmounted (when vertically arrow key navigating)
19127
19365
  React__default.useEffect(() => {
@@ -19141,14 +19379,13 @@ function EditingControlCell(props) {
19141
19379
  isDetailedMode: tableMeta.editing.isDetailedMode,
19142
19380
  isTruncated: !!columnMeta.enableTruncate,
19143
19381
  onBlur: handleBlur,
19144
- onChange: value => tableMeta.editing.setCellValue(cell, value, rowIndex),
19382
+ onChange: handleChange,
19145
19383
  row: cell.row.original,
19146
- rowPendingChanges: tableMeta.editing.getRowPendingChange(cell.row.id),
19384
+ rowPendingChanges: tableMeta.editing.getRowValue(cell.row.id),
19147
19385
  tabIndex: isActiveRow ? 0 : -1,
19148
- toggleEditing: tableMeta.editing.toggleEditing,
19149
19386
  toggleDetailedMode: tableMeta.editing.toggleDetailedMode,
19150
- type: (_columnMeta$control = columnMeta.control) !== null && _columnMeta$control !== void 0 ? _columnMeta$control : 'input',
19151
- value: cell.getValue()
19387
+ type,
19388
+ value
19152
19389
  };
19153
19390
  const cellAttributes = {
19154
19391
  ...getCellAttributes(cell, index, isHighlighted),
@@ -19180,7 +19417,6 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19180
19417
  row,
19181
19418
  rowPendingChanges,
19182
19419
  tabIndex = -1,
19183
- toggleEditing,
19184
19420
  toggleDetailedMode,
19185
19421
  type = 'input',
19186
19422
  value
@@ -19211,6 +19447,13 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19211
19447
  ref: controlRef
19212
19448
  }));
19213
19449
  }
19450
+ if (type === 'checkbox') {
19451
+ return /*#__PURE__*/React__default.createElement(Checkbox, Object.assign({}, commonProps, {
19452
+ checked: Boolean(value),
19453
+ onChange: onChange,
19454
+ ref: controlRef
19455
+ }));
19456
+ }
19214
19457
  const handleInputKeyDown = event => {
19215
19458
  const target = event.target;
19216
19459
  if (target.readOnly) {
@@ -19239,8 +19482,8 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19239
19482
  }
19240
19483
  // reset the value, or exit edit mode when pressing escape
19241
19484
  if (event.key === 'Escape') {
19242
- event.preventDefault();
19243
19485
  if (isDetailedMode) {
19486
+ event.preventDefault();
19244
19487
  toggleDetailedMode(false);
19245
19488
  if (value !== currentValue) {
19246
19489
  props.onChange(currentValue);
@@ -19250,8 +19493,6 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19250
19493
  var _target$select2;
19251
19494
  return (_target$select2 = target.select) === null || _target$select2 === void 0 ? void 0 : _target$select2.call(target);
19252
19495
  });
19253
- } else {
19254
- toggleEditing(false);
19255
19496
  }
19256
19497
  return;
19257
19498
  }
@@ -19350,12 +19591,37 @@ function Cell$5(props) {
19350
19591
  return /*#__PURE__*/React__default.createElement(DisplayCell, Object.assign({}, props));
19351
19592
  }
19352
19593
 
19594
+ function DiscardChangesConfirmationDialog(props) {
19595
+ const {
19596
+ onDiscard: handleDiscard,
19597
+ ...dialogProps
19598
+ } = props;
19599
+ const {
19600
+ texts
19601
+ } = useLocalization();
19602
+ const handleClickInsideDialogContent = event => {
19603
+ // Prevents the click event from propagating to the table, ensuring the row isn't saved when a click occurs
19604
+ // inside the dialog
19605
+ event.stopPropagation();
19606
+ };
19607
+ return /*#__PURE__*/React__default.createElement(Dialog, Object.assign({}, dialogProps), /*#__PURE__*/React__default.createElement(Dialog.Content, {
19608
+ "aria-label": texts.table3.editing.clearChangesConfirmationDialog.title,
19609
+ onClick: handleClickInsideDialogContent
19610
+ }, /*#__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, {
19611
+ tabIndex: 0
19612
+ }, texts.table3.editing.clearChangesConfirmationDialog.cancel)), /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19613
+ autoFocus: true,
19614
+ tabIndex: 0,
19615
+ appearance: "primary",
19616
+ onClick: handleDiscard
19617
+ }, texts.table3.editing.clearChangesConfirmationDialog.confirm))))));
19618
+ }
19619
+
19353
19620
  function EditingActionMenu(props) {
19354
19621
  const {
19355
19622
  hasChanges,
19356
19623
  hasErrors,
19357
- onClear: handleClear,
19358
- onExit: handleExit,
19624
+ onDiscard: handleDiscard,
19359
19625
  onEditingSave: handleSave,
19360
19626
  isLastRow
19361
19627
  } = props;
@@ -19377,7 +19643,6 @@ function EditingActionMenu(props) {
19377
19643
  return /*#__PURE__*/React__default.createElement(IconButton, {
19378
19644
  appearance: "transparent",
19379
19645
  "aria-label": texts.table3.editing.actions.tooltip,
19380
- className: "group-[[data-row-editing-status]]/row:hidden",
19381
19646
  icon: "more",
19382
19647
  onKeyDown: handleKeyDown,
19383
19648
  menu: menuProps => (/*#__PURE__*/React__default.createElement(Menu$1, Object.assign({}, menuProps), /*#__PURE__*/React__default.createElement(Menu$1.Content, {
@@ -19389,42 +19654,13 @@ function EditingActionMenu(props) {
19389
19654
  }, texts.table3.editing.actions.save), /*#__PURE__*/React__default.createElement(Menu$1.Item, {
19390
19655
  icon: "close",
19391
19656
  disabled: !hasChanges,
19392
- dialog: props => /*#__PURE__*/React__default.createElement(ConfirmClearChangesDialog, Object.assign({}, props, {
19393
- onClear: handleClear
19657
+ dialog: props => /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, Object.assign({}, props, {
19658
+ onDiscard: handleDiscard
19394
19659
  }))
19395
- }, texts.table3.editing.actions.clear), /*#__PURE__*/React__default.createElement(Menu$1.Item, {
19396
- icon: "undo",
19397
- onClick: handleExit
19398
- }, texts.table3.editing.actions.exit))))
19660
+ }, texts.table3.editing.actions.clear))))
19399
19661
  });
19400
19662
  }
19401
- function ConfirmClearChangesDialog(props) {
19402
- const {
19403
- onClear: handleClear,
19404
- ...dialogProps
19405
- } = props;
19406
- const {
19407
- texts
19408
- } = useLocalization();
19409
- const handleClickInsideDialogContent = event => {
19410
- // Prevents the click event from propagating to the table, ensuring the row isn't saved when a click occurs
19411
- // inside the dialog
19412
- event.stopPropagation();
19413
- };
19414
- return /*#__PURE__*/React__default.createElement(Dialog, Object.assign({}, dialogProps), /*#__PURE__*/React__default.createElement(Dialog.Content, {
19415
- "aria-label": texts.table3.editing.clearChangesConfirmationDialog.title,
19416
- onClick: handleClickInsideDialogContent
19417
- }, /*#__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, {
19418
- tabIndex: 0
19419
- }, texts.table3.editing.clearChangesConfirmationDialog.cancel)), /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19420
- autoFocus: true,
19421
- tabIndex: 0,
19422
- appearance: "primary",
19423
- onClick: handleClear
19424
- }, texts.table3.editing.clearChangesConfirmationDialog.confirm))))));
19425
- }
19426
19663
 
19427
- const COMPLETE_INDICATOR_DELAY = 3000;
19428
19664
  function SaveStatus(props) {
19429
19665
  const {
19430
19666
  rowId,
@@ -19434,18 +19670,7 @@ function SaveStatus(props) {
19434
19670
  texts
19435
19671
  } = useLocalization();
19436
19672
  const tableMeta = table.options.meta;
19437
- const status = tableMeta.editing.getRowSaveStatus(rowId);
19438
- React__default.useEffect(() => {
19439
- let timeout;
19440
- if (status === 'complete') {
19441
- timeout = setTimeout(() => {
19442
- tableMeta.editing.setRowSaveStatus(rowId, undefined);
19443
- }, COMPLETE_INDICATOR_DELAY);
19444
- }
19445
- return () => {
19446
- clearTimeout(timeout);
19447
- };
19448
- }, [status]);
19673
+ const status = tableMeta.editing.getRowStatus(rowId);
19449
19674
  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)]', {
19450
19675
  'mt-0.5': tableMeta.rowHeight.height === 'short',
19451
19676
  'mt-1': tableMeta.rowHeight.height === 'medium',
@@ -19456,7 +19681,7 @@ function SaveStatus(props) {
19456
19681
  className: "!contents"
19457
19682
  }, /*#__PURE__*/React__default.createElement("span", {
19458
19683
  className: className
19459
- }, status === 'pending' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19684
+ }, status === 'saving' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19460
19685
  title: texts.table3.editing.saving.progress
19461
19686
  }, /*#__PURE__*/React__default.createElement(Spinner, {
19462
19687
  delay: 0,
@@ -19497,15 +19722,46 @@ function Row$2(props) {
19497
19722
  }
19498
19723
  }
19499
19724
  }, [tableMeta.editing.isEditing, isActiveRow]);
19725
+ const rowStatus = tableMeta.editing.getRowStatus(row.id);
19726
+ // discard new row
19727
+ const [showDiscardDialog, setShowDiscardDialog] = React__default.useState(false);
19728
+ function handleDiscard() {
19729
+ tableMeta.editing.discardChanges(row.id, table);
19730
+ requestAnimationFrame(() => {
19731
+ if (isTemporaryRow(row.id)) {
19732
+ var _tableMeta$editing$cr;
19733
+ (_tableMeta$editing$cr = tableMeta.editing.createRowButtonRef.current) === null || _tableMeta$editing$cr === void 0 ? void 0 : _tableMeta$editing$cr.focus();
19734
+ } else {
19735
+ focusManager.focusFirst();
19736
+ }
19737
+ });
19738
+ }
19739
+ function handleKeyDown(event) {
19740
+ if (props.onKeyDown) {
19741
+ props.onKeyDown(event);
19742
+ }
19743
+ if (event.isDefaultPrevented() || event.isPropagationStopped()) {
19744
+ return;
19745
+ }
19746
+ if (event.key === 'Escape' && tableMeta.editing.hasChanges(row.id) && !isElementTriggeredFromContainer(event.target, event.currentTarget)) {
19747
+ event.preventDefault();
19748
+ setShowDiscardDialog(true);
19749
+ }
19750
+ }
19500
19751
  const attributes = {
19501
- 'data-row-editing-invalid': tableMeta.editing.isEnabled && tableMeta.editing.hasRowErrors(row.id) ? !tableMeta.editing.hasRowErrorsSeen(row.id) ? 'unseen' : true : undefined,
19502
- 'data-row-editing-status': tableMeta.editing.isEnabled && tableMeta.editing.getRowSaveStatus(row.id) ? tableMeta.editing.getRowSaveStatus(row.id) : undefined,
19503
- onFocus: handleFocus
19752
+ 'data-row-editing-invalid': tableMeta.editing.hasRowErrors(row.id) ? !tableMeta.editing.hasRowErrorsShownInAlert(row.id) ? 'unseen' : true : undefined,
19753
+ 'data-row-editing-status': rowStatus,
19754
+ onFocus: handleFocus,
19755
+ onKeyDown: handleKeyDown
19504
19756
  };
19505
- return /*#__PURE__*/React__default.createElement(DisplayRow, Object.assign({}, props, attributes), tableMeta.editing.getRowSaveStatus(row.id) ? /*#__PURE__*/React__default.createElement(SaveStatus, {
19757
+ 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, {
19506
19758
  rowId: row.id,
19507
19759
  table: table
19508
- }) : null);
19760
+ }) : null), /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, {
19761
+ open: showDiscardDialog,
19762
+ onChange: setShowDiscardDialog,
19763
+ onDiscard: handleDiscard
19764
+ }));
19509
19765
  }
19510
19766
 
19511
19767
  const RENDERERS$1 = {
@@ -19513,29 +19769,50 @@ const RENDERERS$1 = {
19513
19769
  cell: Cell$5
19514
19770
  };
19515
19771
  function useTable3(props, ref) {
19516
- const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.validator);
19772
+ const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.rowIdentityAccessor, props.validator);
19517
19773
  const creationEnabled = editing.isEnabled && !!props.onEditingCreate;
19774
+ // this gives me the performance heeby jeebies, but can't think of a better way to internalise the state
19775
+ const data = React__default.useMemo(() => {
19776
+ if (editing.temporaryRows.length) {
19777
+ var _props$data;
19778
+ return ((_props$data = props.data) !== null && _props$data !== void 0 ? _props$data : []).concat(editing.temporaryRows);
19779
+ }
19780
+ return props.data;
19781
+ }, [JSON.stringify(props.data), editing.temporaryRows.length]);
19518
19782
  const extendedProps = {
19519
19783
  ...props,
19784
+ data,
19520
19785
  enableRowActions: editing.isEditing ? true : props.enableRowActions,
19521
- rowActions: editing.isEditing ? [(_, rowId) => (/*#__PURE__*/React__default.createElement(EditingActionMenu, {
19522
- hasChanges: editing.hasChanges(rowId),
19523
- hasErrors: editing.hasRowErrors(rowId),
19524
- onClear: () => editing.resetChanges(rowId),
19525
- onEditingSave: () => editing.saveChanges(rowId),
19526
- onExit: () => editing.toggleEditing(false),
19527
- isLastRow: !creationEnabled && table.meta.rowActive.rowActiveIndex === table.meta.length - 1
19528
- }))] : props.rowActions
19786
+ // Display EditingActionMenu instead of row actions while editing
19787
+ rowActions: editing.isEditing ? [(_, rowId, table) => {
19788
+ const tableMeta = table.options.meta;
19789
+ return /*#__PURE__*/React__default.createElement(EditingActionMenu, {
19790
+ hasChanges: editing.hasChanges(rowId),
19791
+ hasErrors: editing.hasRowErrors(rowId),
19792
+ onDiscard: () => editing.discardChanges(rowId, table),
19793
+ onEditingSave: function () {
19794
+ try {
19795
+ return Promise.resolve(editing.saveChanges(table, rowId)).then(function () {});
19796
+ } catch (e) {
19797
+ return Promise.reject(e);
19798
+ }
19799
+ },
19800
+ isLastRow: !creationEnabled && tableMeta.rowActive.rowActiveIndex === tableMeta.length - 1
19801
+ });
19802
+ }] : props.rowActions
19529
19803
  };
19530
19804
  const meta = {
19531
19805
  editing
19532
19806
  };
19533
- const table = useTable(extendedProps, ref, RENDERERS$1, meta);
19807
+ const options = {
19808
+ virtualiserPaddingEndOffset: props.enableEditing && props.onEditingCreate ? editing.hasTemporaryRowErrors() ? 1.4 : 1 : 0
19809
+ };
19810
+ const table = useTable(extendedProps, ref, RENDERERS$1, meta, options);
19534
19811
  // listeners
19535
- useTableEditingListener(table.instance, table.ref);
19812
+ useTableEditingListener(table.instance, table.ref, table.renderer.scrollToIndex);
19536
19813
  React__default.useEffect(() => {
19537
19814
  if (table.ref.current) {
19538
- table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing);
19815
+ table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing, table.instance, table.renderer.scrollToIndex);
19539
19816
  }
19540
19817
  }, [table.ref.current]);
19541
19818
  return table;
@@ -19554,7 +19831,7 @@ function Alert$1(props) {
19554
19831
  const validationTexts = texts.table3.editing.validation;
19555
19832
  const tableMeta = table.options.meta;
19556
19833
  const [showFilterResetDialog, setShowFilterResetDialog] = React__default.useState(false);
19557
- const pendingChangesWithErrors = tableMeta.editing.getAlertErrors();
19834
+ const pendingChangesWithErrors = tableMeta.editing.getErrorsShownInAlert();
19558
19835
  function scrollToRow(rowIndex) {
19559
19836
  tableMeta.rowActive.setRowActiveIndex(rowIndex);
19560
19837
  scrollToIndex(rowIndex, {
@@ -19573,38 +19850,43 @@ function Alert$1(props) {
19573
19850
  const title = (pendingChangesWithErrors.length === 1 ? validationTexts.alert.titleOne : validationTexts.alert.titlePlural).replace('[COUNT]', String(pendingChangesWithErrors.length));
19574
19851
  // generate links to each invalid row, to go into the error message
19575
19852
  const links = [];
19576
- const rowIdentityColumn = tableMeta.rowIdentityColumnId ? table.getColumn(tableMeta.rowIdentityColumnId) : undefined;
19577
- pendingChangesWithErrors.forEach((error, index) => {
19853
+ const visibleColumns = table.getVisibleFlatColumns().map(c => c.id);
19854
+ const rowIdentityColumn = tableMeta.rowIdentityAccessor && visibleColumns.includes(String(tableMeta.rowIdentityAccessor)) ? table.getColumn(String(tableMeta.rowIdentityAccessor)) : undefined;
19855
+ pendingChangesWithErrors.forEach((pendingChangeWithError, index) => {
19578
19856
  // if appropriate, concatenate the item with the text "and"
19579
19857
  if (pendingChangesWithErrors.length > 1 && index === pendingChangesWithErrors.length - 1) {
19580
19858
  // Add space before and after `messageAnd` text
19581
19859
  links.push(` ${validationTexts.alert.messageAnd} `);
19582
19860
  }
19583
- const rowIndex = table.getRowModel().rows.findIndex(row => row.id === error.rowId);
19861
+ const rowIndex = table.getRowModel().rows.findIndex(row => row.id === pendingChangeWithError.rowId);
19584
19862
  const handleClick = () => {
19863
+ // if row is visible
19585
19864
  if (rowIndex > -1) {
19586
19865
  scrollToRow(rowIndex);
19587
- } else {
19588
- setShowFilterResetDialog(error.rowId);
19866
+ }
19867
+ // if row is filtered out
19868
+ else {
19869
+ setShowFilterResetDialog(pendingChangeWithError.rowId);
19589
19870
  }
19590
19871
  };
19591
19872
  let tooltip;
19592
- if (error.pendingChange._meta.errors.row) {
19593
- tooltip = error.pendingChange._meta.errors.row;
19873
+ if (pendingChangeWithError.errors.row) {
19874
+ tooltip = pendingChangeWithError.errors.row;
19594
19875
  } else {
19595
19876
  var _table$getAllColumns$, _table$getAllColumns$2;
19596
- const firstCellErrorColumnId = Object.keys(error.pendingChange._meta.errors.cells)[0];
19877
+ const firstCellErrorColumnId = Object.keys(pendingChangeWithError.errors.cells)[0];
19597
19878
  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;
19598
- tooltip = `${columnName}: ${error.pendingChange._meta.errors.cells[firstCellErrorColumnId]}`;
19879
+ tooltip = `${columnName}: ${pendingChangeWithError.errors.cells[firstCellErrorColumnId]}`;
19599
19880
  }
19881
+ const row = table.getRow(pendingChangeWithError.rowId).original;
19600
19882
  links.push(/*#__PURE__*/React__default.createElement(Tooltip, {
19601
- key: error.rowId,
19883
+ key: pendingChangeWithError.rowId,
19602
19884
  title: tooltip
19603
19885
  }, /*#__PURE__*/React__default.createElement("span", {
19604
19886
  className: "text-blue",
19605
19887
  onClick: handleClick,
19606
19888
  role: "button"
19607
- }, rowIdentityColumn ? error.pendingChange._meta.original[rowIdentityColumn.id] : rowIndex + 1)));
19889
+ }, rowIdentityColumn ? row[rowIdentityColumn.id] : rowIndex + 1)));
19608
19890
  // if appropriate, concatenate the item with the text ","
19609
19891
  if (pendingChangesWithErrors.length > 2 && index < pendingChangesWithErrors.length - 2) {
19610
19892
  links.push(', ');
@@ -19660,127 +19942,212 @@ function FilterResetDialog(props) {
19660
19942
  }, texts.table3.editing.validation.resetFiltersDialog.confirm)))));
19661
19943
  }
19662
19944
 
19663
- function CreateNewRowButton(props) {
19945
+ function Editing(props) {
19664
19946
  const {
19665
- onEditingCreate,
19666
19947
  scrollToIndex,
19667
- table,
19668
- tableMeta
19948
+ table
19669
19949
  } = props;
19670
19950
  const {
19671
19951
  texts
19672
19952
  } = useLocalization();
19673
- const rows = table.getCoreRowModel().rows.filter(row => row.original !== undefined);
19674
- const [rowCreated, setRowCreated] = React__default.useState({
19675
- rowFinder: undefined
19676
- });
19677
- const handleKeyDown = event => {
19678
- if (!tableMeta.editing.hasChanges() && event.key === 'Tab') {
19679
- tableMeta.editing.saveChanges();
19680
- }
19953
+ const ref = React__default.useRef(null);
19954
+ const tableMeta = table.options.meta;
19955
+ const handleChange = enabled => {
19956
+ tableMeta.editing.toggleEditing(enabled, table, scrollToIndex);
19681
19957
  };
19682
- const handleCreate = function () {
19958
+ const tooltip = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, texts.table3.editing.buttons.edit.tooltip, /*#__PURE__*/React__default.createElement(Shortcut, {
19959
+ className: "ml-2",
19960
+ keys: shortcut
19961
+ }));
19962
+ return /*#__PURE__*/React__default.createElement(Tooltip, {
19963
+ title: tooltip
19964
+ }, /*#__PURE__*/React__default.createElement(ModeSwitch, {
19965
+ "data-table": "editing-toggle",
19966
+ checked: tableMeta.editing.isEditing,
19967
+ onChange: handleChange,
19968
+ ref: ref
19969
+ }));
19970
+ }
19971
+
19972
+ function CreateNewRow(props) {
19973
+ var _temporaryRows$0$tabl, _temporaryRows$, _table$getState$colum;
19974
+ const {
19975
+ buttonRef,
19976
+ onEditingCreate: handleEditingCreate,
19977
+ scrollToIndex,
19978
+ table,
19979
+ tableMeta,
19980
+ tableRef
19981
+ } = props;
19982
+ const {
19983
+ texts
19984
+ } = useLocalization();
19985
+ const temporaryRows = tableMeta.editing.temporaryRows;
19986
+ 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 : '';
19987
+ 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);
19988
+ const isSaving = !!temporaryRowId && tableMeta.editing.getRowStatus(temporaryRowId) === 'saving';
19989
+ const createRow = function (row) {
19683
19990
  try {
19684
- if (!onEditingCreate) {
19991
+ if (!handleEditingCreate || isDisabled) {
19685
19992
  return Promise.resolve();
19686
19993
  }
19687
- const createdRow = rows.find(row => {
19688
- var _rowCreated$rowFinder;
19689
- 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);
19690
- });
19691
- const _temp = function () {
19692
- if (createdRow) {
19693
- return Promise.resolve(tableMeta.editing.saveChanges()).then(function () {
19694
- if (!tableMeta.editing.hasRowErrors(createdRow.id)) {
19695
- const rowFinder = onEditingCreate();
19696
- setRowCreated({
19697
- rowFinder
19698
- });
19699
- }
19700
- });
19701
- } else {
19702
- const rowFinder = onEditingCreate();
19703
- setRowCreated({
19704
- rowFinder
19705
- });
19994
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
19995
+ if (!saved) {
19996
+ return;
19706
19997
  }
19707
- }();
19708
- return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
19998
+ const changeset = row !== null && row !== void 0 ? row : handleEditingCreate();
19999
+ try {
20000
+ if (changeset) {
20001
+ const rowId = tableMeta.editing.createRow(changeset);
20002
+ table.getRow(rowId).pin('bottom');
20003
+ // set the active row to the new row before toggling editing on
20004
+ const nextRowIndex = temporaryRows.length ? tableMeta.length + 1 : tableMeta.length;
20005
+ tableMeta.rowActive.setRowActiveIndex(nextRowIndex);
20006
+ tableMeta.editing.toggleEditing(true, table, scrollToIndex);
20007
+ tableMeta.editing.setLastFocusedCellIndex(0);
20008
+ }
20009
+ } catch (error) {
20010
+ console.error(error);
20011
+ }
20012
+ });
19709
20013
  } catch (e) {
19710
20014
  return Promise.reject(e);
19711
20015
  }
19712
20016
  };
20017
+ // allow programmatic access to creating rows from outside the table
19713
20018
  React__default.useEffect(() => {
19714
- if (typeof (rowCreated === null || rowCreated === void 0 ? void 0 : rowCreated.rowFinder) === 'function') {
19715
- const createdRow = rows.find(row => {
19716
- var _rowCreated$rowFinder2;
19717
- 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);
19718
- });
19719
- if (createdRow) {
19720
- const rowInTable = table.getRowModel().rows.filter(row => row.original !== undefined).find(row => {
19721
- var _rowCreated$rowFinder3;
19722
- 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);
19723
- });
19724
- if (rowInTable) {
19725
- tableMeta.editing.toggleEditing(true);
19726
- tableMeta.rowActive.setRowActiveIndex(createdRow.index);
19727
- scrollToIndex(createdRow.index);
19728
- requestAnimationFrame(() => animateCreateRow(createdRow.id));
19729
- }
19730
- requestAnimationFrame(() => tableMeta.editing.addCreatedRowChangeset(createdRow));
19731
- }
20019
+ if (tableRef.current) {
20020
+ tableRef.current.instance.createRow = createRow;
19732
20021
  }
19733
- }, [rowCreated]);
20022
+ }, [tableRef.current, createRow]);
20023
+ const handleCreate = function () {
20024
+ return createRow();
20025
+ };
20026
+ const shortcut = {
20027
+ key: 'Enter',
20028
+ shift: true
20029
+ };
20030
+ let tooltip;
20031
+ if (isSaving) {
20032
+ tooltip = texts.table3.editing.buttons.create.saving;
20033
+ } else if (isDisabled) {
20034
+ tooltip = texts.table3.editing.buttons.create.disabled;
20035
+ } else {
20036
+ tooltip = /*#__PURE__*/React__default.createElement(Shortcut, {
20037
+ keys: shortcut
20038
+ });
20039
+ }
20040
+ const isScrolled = tableRef.current ? tableRef.current.scrollHeight > tableRef.current.clientHeight : false;
20041
+ const className = cn('group/row border-grey-300 !sticky z-[21]', {
20042
+ 'bottom-10': tableMeta.footer.isEnabled,
20043
+ 'bottom-0': !tableMeta.footer.isEnabled,
20044
+ 'border-t-2': isScrolled,
20045
+ 'border-b': !isScrolled
20046
+ });
19734
20047
  return /*#__PURE__*/React__default.createElement("tr", {
19735
- onClick: handleCreate,
19736
- className: "border-grey-300 hover:bg-grey-100 group !sticky bottom-10 left-0 z-[21] !block cursor-pointer border-t"
20048
+ "data-row-create": true,
20049
+ className: className,
20050
+ tabIndex: -1
19737
20051
  }, /*#__PURE__*/React__default.createElement("td", {
19738
- className: "!border-t-0 !bg-transparent"
20052
+ className: "!bg-grey-50 col-span-full !border-b-0 !px-1"
19739
20053
  }, /*#__PURE__*/React__default.createElement(Button$1, {
19740
- onKeyDown: handleKeyDown,
19741
- className: "group-hover:bg-grey-200 sticky left-0",
19742
- appearance: "transparent"
19743
- }, "+ ", texts.table3.editing.buttons.create.label)));
20054
+ appearance: "transparent",
20055
+ className: "group-hover:bg-grey-200 sticky left-[4px]",
20056
+ disabled: isDisabled,
20057
+ onClick: handleCreate,
20058
+ ref: buttonRef,
20059
+ shortcut: shortcut,
20060
+ tooltip: tooltip
20061
+ }, /*#__PURE__*/React__default.createElement(Icon, {
20062
+ name: "circle-plus"
20063
+ }), texts.table3.editing.buttons.create.label)));
19744
20064
  }
19745
20065
 
19746
- function Editing(props) {
20066
+ function TemporaryRow(props) {
19747
20067
  const {
19748
- scrollToIndex,
19749
- table
20068
+ createRowButtonRef,
20069
+ table,
20070
+ tableMeta,
20071
+ tableRef
19750
20072
  } = props;
19751
- const {
19752
- texts
19753
- } = useLocalization();
19754
- const ref = React__default.useRef(null);
19755
- const tableMeta = table.options.meta;
19756
- const shortcut = {
19757
- key: 'e',
19758
- meta: true,
19759
- shift: false
20073
+ const handleKeyDown = function (event) {
20074
+ try {
20075
+ const _temp2 = function () {
20076
+ if (event.key === 'ArrowDown') {
20077
+ event.preventDefault();
20078
+ const _temp = function () {
20079
+ if (!isElementTriggeredFromContainer(event.target, event.currentTarget)) {
20080
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
20081
+ if (saved) {
20082
+ var _createRowButtonRef$c;
20083
+ (_createRowButtonRef$c = createRowButtonRef.current) === null || _createRowButtonRef$c === void 0 ? void 0 : _createRowButtonRef$c.focus();
20084
+ }
20085
+ });
20086
+ }
20087
+ }();
20088
+ if (_temp && _temp.then) return _temp.then(function () {});
20089
+ } else if (event.key === 'ArrowUp') {
20090
+ event.preventDefault();
20091
+ event.stopPropagation();
20092
+ if (tableRef.current) {
20093
+ var _tableRef$current$que, _tableRef$current$que2, _tableRef$current$que3;
20094
+ 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 : []);
20095
+ 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;
20096
+ const newRowHeight = event.currentTarget.getBoundingClientRect().height;
20097
+ const visibleHeight = tableRef.current.clientHeight - footerHeight - newRowHeight;
20098
+ const tableTopOffset = tableRef.current.getBoundingClientRect().top;
20099
+ let nextRowIndex;
20100
+ // iterate available rows in reverse order, since we're working at the bottom
20101
+ for (let index = availableRows.length - 1; index >= 0; index--) {
20102
+ const rowRect = availableRows[index].getBoundingClientRect();
20103
+ const topPlusHalfRow = rowRect.top + rowRect.height / 2;
20104
+ if (topPlusHalfRow - tableTopOffset <= visibleHeight) {
20105
+ nextRowIndex = index;
20106
+ break;
20107
+ }
20108
+ }
20109
+ if (nextRowIndex) {
20110
+ tableMeta.rowActive.setRowActiveIndex(Number(availableRows[nextRowIndex < 0 ? 0 : nextRowIndex].getAttribute('data-row-index')));
20111
+ }
20112
+ }
20113
+ }
20114
+ }();
20115
+ return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {}) : void 0);
20116
+ } catch (e) {
20117
+ return Promise.reject(e);
20118
+ }
19760
20119
  };
19761
- const tooltip = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, texts.table3.editing.buttons.edit.tooltip, /*#__PURE__*/React__default.createElement(Shortcut, {
19762
- className: "ml-2",
19763
- keys: shortcut
19764
- }));
19765
- useGlobalKeyDown(shortcut, event => {
19766
- var _ref$current;
19767
- event.preventDefault();
19768
- (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.click();
19769
- });
19770
- const handleChange = enabled => {
19771
- tableMeta.editing.toggleEditing(enabled);
19772
- requestAnimationFrame(() => {
19773
- var _tableMeta$rowActive$;
19774
- return scrollToIndex((_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0);
19775
- });
20120
+ const handleKeyDownCapture = event => {
20121
+ if (event.key === 'ArrowLeft' && tableMeta.editing.lastFocusedCellIndex === 0) {
20122
+ event.preventDefault();
20123
+ event.stopPropagation();
20124
+ } else if (event.key === 'ArrowRight' && tableMeta.editing.lastFocusedCellIndex) {
20125
+ if (tableMeta.editing.lastFocusedCellIndex === table.getVisibleFlatColumns().length - 1) {
20126
+ event.preventDefault();
20127
+ event.stopPropagation();
20128
+ }
20129
+ }
19776
20130
  };
19777
- return /*#__PURE__*/React__default.createElement(Tooltip, {
19778
- title: tooltip
19779
- }, /*#__PURE__*/React__default.createElement(ModeSwitch, {
19780
- checked: tableMeta.editing.isEditing,
19781
- onChange: handleChange,
19782
- ref: ref
19783
- }));
20131
+ const isScrolled = tableRef.current ? tableRef.current.scrollHeight > tableRef.current.clientHeight : false;
20132
+ const className = cn('group/row border-grey-300 !sticky z-[22]', {
20133
+ 'bottom-[calc(5rem_+_3px)] data-[row-editing-move]:bottom-[calc(5rem_+_2px)]': tableMeta.footer.isEnabled,
20134
+ 'bottom-[calc(2.5rem_+_3px)] data-[row-editing-move]:bottom-[calc(2.5rem_+_2px)]': !tableMeta.footer.isEnabled,
20135
+ 'border-t-2 shadow-[0px_-5px_20px_0px_rgba(0,0,0,0.1)] [&>td]:!border-b-0': isScrolled
20136
+ });
20137
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, table.getBottomRows().map(row => (/*#__PURE__*/React__default.createElement(Row, {
20138
+ key: row.id,
20139
+ cellRenderer: RENDERERS$1.cell,
20140
+ index: tableMeta.length,
20141
+ measureRow: () => null,
20142
+ renderer: RENDERERS$1.row,
20143
+ row: row,
20144
+ table: table,
20145
+ className: className,
20146
+ onKeyDown: handleKeyDown,
20147
+ onKeyDownCapture: handleKeyDownCapture,
20148
+ // Row actions should only be hidden on temporary rows when editing is turned off
20149
+ hideRowActions: !tableMeta.editing.isEditing
20150
+ }))));
19784
20151
  }
19785
20152
 
19786
20153
  function Column$3(_) {
@@ -19798,8 +20165,8 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19798
20165
  '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,
19799
20166
  enableHorizontalArrowKeyNavigation: table3.meta.editing.isEditing
19800
20167
  };
19801
- const hasAlertErrors = table3.meta.editing.hasAlertErrors();
19802
- const showCreateRowButton = table3.meta.editing.isEnabled && props.onEditingCreate;
20168
+ const hasAlertErrors = table3.meta.editing.getErrorsShownInAlert().length;
20169
+ const hasCreateWorkflow = table3.meta.editing.isEnabled && props.onEditingCreate;
19803
20170
  return /*#__PURE__*/React__default.createElement(Table, null, /*#__PURE__*/React__default.createElement(Table.Toolbar, {
19804
20171
  table: table3
19805
20172
  }, table3.meta.editing.isEnabled ? (/*#__PURE__*/React__default.createElement(Editing, {
@@ -19813,12 +20180,19 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19813
20180
  })) : null, /*#__PURE__*/React__default.createElement(Table.Grid, Object.assign({}, gridAttributes, {
19814
20181
  "data-taco": "table3",
19815
20182
  table: table3
19816
- }), showCreateRowButton && (/*#__PURE__*/React__default.createElement(CreateNewRowButton, {
20183
+ }), hasCreateWorkflow ? (/*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(TemporaryRow, {
20184
+ createRowButtonRef: table3.meta.editing.createRowButtonRef,
19817
20185
  table: table3.instance,
19818
20186
  tableMeta: table3.meta,
20187
+ tableRef: table3.ref
20188
+ }), /*#__PURE__*/React__default.createElement(CreateNewRow, {
20189
+ buttonRef: table3.meta.editing.createRowButtonRef,
19819
20190
  onEditingCreate: props.onEditingCreate,
19820
- scrollToIndex: table3.renderer.scrollToIndex
19821
- }))));
20191
+ scrollToIndex: table3.renderer.scrollToIndex,
20192
+ table: table3.instance,
20193
+ tableMeta: table3.meta,
20194
+ tableRef: table3.ref
20195
+ }))) : null));
19822
20196
  });
19823
20197
  const Table3 = /*#__PURE__*/fixedForwardRef(function Table3(props, ref) {
19824
20198
  const stringifiedChildren = String(props.children);
@@ -20572,9 +20946,9 @@ const Top = props => {
20572
20946
  setSidebarOpen
20573
20947
  } = React__default.useContext(LayoutContext);
20574
20948
  const toggleSidebar = () => setSidebarOpen(open => !open);
20575
- return typeof props.children === 'function' ? props.children({
20949
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, typeof props.children === 'function' ? props.children({
20576
20950
  toggleSidebar
20577
- }) : props.children;
20951
+ }) : props.children);
20578
20952
  };
20579
20953
 
20580
20954
  const Page = /*#__PURE__*/React__default.forwardRef(function LayoutPage(props, ref) {