@revolist/revogrid 4.22.1 → 4.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/dist/cjs/{cell-renderer-BQdEGQXP.js → cell-renderer-Dcz022q7.js} +9 -3
  2. package/dist/cjs/{column.drag.plugin-RDjQhKCH.js → column.drag.plugin-DJueWxN_.js} +391 -256
  3. package/dist/cjs/{column.service-DXYMehqK.js → column.service-C1Qvcf5l.js} +10 -1
  4. package/dist/cjs/{dimension.helpers-CiiNnlLa.js → dimension.helpers-B9HgANnM.js} +14 -145
  5. package/dist/cjs/{edit.utils-CecCfA4E.js → edit.utils-pKeiYFLJ.js} +1 -1
  6. package/dist/cjs/{header-cell-renderer-DGyBrK8I.js → header-cell-renderer-QrcXXSkF.js} +1 -1
  7. package/dist/cjs/index-DxaSE5uZ.js +136 -0
  8. package/dist/cjs/index.cjs.js +37 -32
  9. package/dist/cjs/revo-grid.cjs.entry.js +124 -18
  10. package/dist/cjs/revogr-attribution_7.cjs.entry.js +43 -25
  11. package/dist/cjs/revogr-clipboard_3.cjs.entry.js +10 -8
  12. package/dist/cjs/revogr-data_4.cjs.entry.js +74 -32
  13. package/dist/cjs/revogr-filter-panel.cjs.entry.js +2 -1
  14. package/dist/cjs/{text-editor-DnLZW1a-.js → text-editor-B4W-m-r-.js} +3 -3
  15. package/dist/cjs/{throttle-CfgQFkfR.js → throttle-BCwEuJJq.js} +59 -24
  16. package/dist/cjs/viewport.helpers-BND76K2j.js +140 -0
  17. package/dist/cjs/{viewport.store-q6YdR9mg.js → viewport.store-BlKQ4x9H.js} +16 -16
  18. package/dist/collection/components/data/revogr-data.js +5 -3
  19. package/dist/collection/components/header/header-group-renderer.js +1 -1
  20. package/dist/collection/components/header/header-renderer.js +1 -1
  21. package/dist/collection/components/header/revogr-header-style.css +13 -3
  22. package/dist/collection/components/header/revogr-header.js +53 -17
  23. package/dist/collection/components/order/order-row.service.js +6 -5
  24. package/dist/collection/components/overlay/keyboard.service.js +23 -1
  25. package/dist/collection/components/overlay/selection.utils.js +8 -6
  26. package/dist/collection/components/revoGrid/revo-grid.js +69 -5
  27. package/dist/collection/components/revoGrid/viewport.service.js +2 -1
  28. package/dist/collection/components/scroll/revogr-viewport-scroll.js +10 -6
  29. package/dist/collection/components/scrollable/revogr-scroll-virtual.js +4 -10
  30. package/dist/collection/plugins/filter/filter.panel.js +2 -1
  31. package/dist/collection/plugins/filter/filter.plugin.js +11 -4
  32. package/dist/collection/plugins/groupingRow/grouping.row.plugin.js +25 -1
  33. package/dist/collection/plugins/groupingRow/grouping.service.js +9 -0
  34. package/dist/collection/plugins/moveColumn/column.drag.plugin.js +4 -4
  35. package/dist/collection/plugins/sorting/sorting.func.js +173 -15
  36. package/dist/collection/plugins/sorting/sorting.plugin.js +167 -84
  37. package/dist/collection/plugins/sorting/sorting.sign.js +7 -1
  38. package/dist/collection/serve/controller.js +98 -37
  39. package/dist/collection/serve/data.js +273 -144
  40. package/dist/collection/services/dimension.provider.js +16 -1
  41. package/dist/collection/services/local.scroll.service.js +59 -24
  42. package/dist/collection/services/scroll.dimension.helpers.js +83 -0
  43. package/dist/collection/services/selection.store.connector.js +30 -4
  44. package/dist/collection/store/dimension/dimension.recalculate.plugin.js +22 -9
  45. package/dist/collection/store/dimension/dimension.store.js +4 -2
  46. package/dist/collection/store/vp/viewport.helpers.js +9 -0
  47. package/dist/collection/store/vp/viewport.store.js +5 -16
  48. package/dist/collection/utils/store.utils.js +3 -3
  49. package/dist/{revo-grid/cell-renderer-CALsEsnh.js → esm/cell-renderer-BtN-NGCk.js} +9 -3
  50. package/dist/esm/{column.drag.plugin-Dy5ztusn.js → column.drag.plugin-DCZW62Uc.js} +388 -255
  51. package/dist/esm/{column.service-CCvAi5l4.js → column.service-CC_SD8W3.js} +10 -1
  52. package/dist/{revo-grid/debounce-BfO9dz9v.js → esm/debounce-PCRWZliA.js} +1 -1
  53. package/dist/{revo-grid/dimension.helpers-DmIvjIa7.js → esm/dimension.helpers-CGKwSvw6.js} +7 -128
  54. package/dist/esm/{edit.utils-DYN6XZh8.js → edit.utils-Dnnbd0xG.js} +1 -1
  55. package/dist/{revo-grid/header-cell-renderer-DU8wKAbg.js → esm/header-cell-renderer-BsvUQ8GS.js} +1 -1
  56. package/dist/esm/index-Db3qZoW5.js +127 -0
  57. package/dist/esm/index.js +11 -10
  58. package/dist/esm/revo-grid.entry.js +123 -17
  59. package/dist/esm/revogr-attribution_7.entry.js +42 -24
  60. package/dist/esm/revogr-clipboard_3.entry.js +11 -9
  61. package/dist/esm/revogr-data_4.entry.js +75 -33
  62. package/dist/esm/revogr-filter-panel.entry.js +3 -2
  63. package/dist/esm/{text-editor-DpCnd6Fq.js → text-editor-C3RUSwH5.js} +2 -2
  64. package/dist/esm/{throttle-ERvyruXb.js → throttle-CaUDyxyU.js} +60 -25
  65. package/dist/esm/viewport.helpers-CoCAvmZs.js +133 -0
  66. package/dist/{revo-grid/viewport.store-CFjDW-3l.js → esm/viewport.store-COAfzAyu.js} +15 -17
  67. package/dist/{esm/cell-renderer-CALsEsnh.js → revo-grid/cell-renderer-BtN-NGCk.js} +9 -3
  68. package/dist/revo-grid/{column.drag.plugin-Dy5ztusn.js → column.drag.plugin-DCZW62Uc.js} +388 -255
  69. package/dist/revo-grid/{column.service-CCvAi5l4.js → column.service-CC_SD8W3.js} +10 -1
  70. package/dist/{esm/debounce-BfO9dz9v.js → revo-grid/debounce-PCRWZliA.js} +1 -1
  71. package/dist/{esm/dimension.helpers-DmIvjIa7.js → revo-grid/dimension.helpers-CGKwSvw6.js} +7 -128
  72. package/dist/revo-grid/{edit.utils-DYN6XZh8.js → edit.utils-Dnnbd0xG.js} +1 -1
  73. package/dist/{esm/header-cell-renderer-DU8wKAbg.js → revo-grid/header-cell-renderer-BsvUQ8GS.js} +1 -1
  74. package/dist/revo-grid/index-Db3qZoW5.js +127 -0
  75. package/dist/revo-grid/index.esm.js +11 -10
  76. package/dist/revo-grid/revo-grid.entry.js +123 -17
  77. package/dist/revo-grid/revogr-attribution_7.entry.js +42 -24
  78. package/dist/revo-grid/revogr-clipboard_3.entry.js +11 -9
  79. package/dist/revo-grid/revogr-data_4.entry.js +75 -33
  80. package/dist/revo-grid/revogr-filter-panel.entry.js +3 -2
  81. package/dist/revo-grid/{text-editor-DpCnd6Fq.js → text-editor-C3RUSwH5.js} +2 -2
  82. package/dist/revo-grid/{throttle-ERvyruXb.js → throttle-CaUDyxyU.js} +60 -25
  83. package/dist/revo-grid/viewport.helpers-CoCAvmZs.js +133 -0
  84. package/dist/{esm/viewport.store-CFjDW-3l.js → revo-grid/viewport.store-COAfzAyu.js} +15 -17
  85. package/dist/types/components/header/header-group-renderer.d.ts +2 -0
  86. package/dist/types/components/header/header-renderer.d.ts +1 -0
  87. package/dist/types/components/header/revogr-header.d.ts +2 -0
  88. package/dist/types/components/overlay/keyboard.service.d.ts +5 -0
  89. package/dist/types/components/revoGrid/revo-grid.d.ts +12 -0
  90. package/dist/types/plugins/groupingRow/grouping.row.plugin.d.ts +8 -0
  91. package/dist/types/plugins/sorting/sorting.func.d.ts +25 -2
  92. package/dist/types/plugins/sorting/sorting.plugin.d.ts +84 -9
  93. package/dist/types/plugins/sorting/sorting.sign.d.ts +5 -1
  94. package/dist/types/plugins/sorting/sorting.types.d.ts +46 -1
  95. package/dist/types/services/local.scroll.service.d.ts +10 -2
  96. package/dist/types/services/scroll.dimension.helpers.d.ts +20 -0
  97. package/dist/types/services/selection.store.connector.d.ts +6 -0
  98. package/dist/types/store/vp/viewport.helpers.d.ts +2 -0
  99. package/dist/types/types/interfaces.d.ts +11 -0
  100. package/dist/types/types/selection.d.ts +13 -0
  101. package/hydrate/index.js +795 -383
  102. package/hydrate/index.mjs +795 -383
  103. package/package.json +1 -1
  104. package/standalone/column.service.js +1 -1
  105. package/standalone/data.store.js +1 -1
  106. package/standalone/debounce.js +1 -1
  107. package/standalone/dimension.helpers.js +1 -1
  108. package/standalone/index.js +1 -1
  109. package/standalone/local.scroll.timer.js +1 -1
  110. package/standalone/revo-grid.js +1 -1
  111. package/standalone/revogr-data2.js +1 -1
  112. package/standalone/revogr-filter-panel.js +1 -1
  113. package/standalone/revogr-header2.js +1 -1
  114. package/standalone/revogr-order-editor2.js +1 -1
  115. package/standalone/revogr-overlay-selection2.js +1 -1
  116. package/standalone/revogr-row-headers.js +1 -1
  117. package/standalone/revogr-row-headers2.js +1 -1
  118. package/standalone/revogr-scroll-virtual2.js +1 -1
  119. package/standalone/revogr-viewport-scroll2.js +1 -1
  120. package/standalone/selection.utils.js +1 -1
  121. package/standalone/throttle.js +1 -1
  122. package/standalone/toNumber.js +1 -1
  123. package/dist/cjs/viewport.helpers-BAovztDd.js +0 -58
  124. package/dist/esm/viewport.helpers-VXhsJZtn.js +0 -52
  125. package/dist/revo-grid/viewport.helpers-VXhsJZtn.js +0 -52
package/hydrate/index.js CHANGED
@@ -7646,7 +7646,8 @@ class FilterPanel {
7646
7646
  const options = [];
7647
7647
  const prop = this.changes.prop;
7648
7648
  const hidden = new Set();
7649
- Object.entries(this.filterItems).forEach(([_, values]) => {
7649
+ Object.keys(this.filterItems).forEach((prop) => {
7650
+ const values = this.filterItems[prop];
7650
7651
  values.forEach((filter) => {
7651
7652
  if (filter.hidden) {
7652
7653
  hidden.add(filter.type);
@@ -8729,11 +8730,11 @@ var COMPARE_PARTIAL_FLAG$4 = 1,
8729
8730
  var boolTag$1 = '[object Boolean]',
8730
8731
  dateTag$1 = '[object Date]',
8731
8732
  errorTag$1 = '[object Error]',
8732
- mapTag$3 = '[object Map]',
8733
+ mapTag$2 = '[object Map]',
8733
8734
  numberTag$1 = '[object Number]',
8734
8735
  regexpTag$1 = '[object RegExp]',
8735
- setTag$3 = '[object Set]',
8736
- stringTag$2 = '[object String]',
8736
+ setTag$2 = '[object Set]',
8737
+ stringTag$1 = '[object String]',
8737
8738
  symbolTag = '[object Symbol]';
8738
8739
 
8739
8740
  var arrayBufferTag$1 = '[object ArrayBuffer]',
@@ -8788,16 +8789,16 @@ function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
8788
8789
  return object.name == other.name && object.message == other.message;
8789
8790
 
8790
8791
  case regexpTag$1:
8791
- case stringTag$2:
8792
+ case stringTag$1:
8792
8793
  // Coerce regexes to strings and treat strings, primitives and objects,
8793
8794
  // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
8794
8795
  // for more details.
8795
8796
  return object == (other + '');
8796
8797
 
8797
- case mapTag$3:
8798
+ case mapTag$2:
8798
8799
  var convert = mapToArray;
8799
8800
 
8800
- case setTag$3:
8801
+ case setTag$2:
8801
8802
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG$4;
8802
8803
  convert || (convert = setToArray);
8803
8804
 
@@ -9138,12 +9139,12 @@ var argsTag$1 = '[object Arguments]',
9138
9139
  dateTag = '[object Date]',
9139
9140
  errorTag = '[object Error]',
9140
9141
  funcTag = '[object Function]',
9141
- mapTag$2 = '[object Map]',
9142
+ mapTag$1 = '[object Map]',
9142
9143
  numberTag = '[object Number]',
9143
9144
  objectTag$2 = '[object Object]',
9144
9145
  regexpTag = '[object RegExp]',
9145
- setTag$2 = '[object Set]',
9146
- stringTag$1 = '[object String]',
9146
+ setTag$1 = '[object Set]',
9147
+ stringTag = '[object String]',
9147
9148
  weakMapTag$1 = '[object WeakMap]';
9148
9149
 
9149
9150
  var arrayBufferTag = '[object ArrayBuffer]',
@@ -9169,9 +9170,9 @@ typedArrayTags[argsTag$1] = typedArrayTags[arrayTag$1] =
9169
9170
  typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
9170
9171
  typedArrayTags[dataViewTag$1] = typedArrayTags[dateTag] =
9171
9172
  typedArrayTags[errorTag] = typedArrayTags[funcTag] =
9172
- typedArrayTags[mapTag$2] = typedArrayTags[numberTag] =
9173
+ typedArrayTags[mapTag$1] = typedArrayTags[numberTag] =
9173
9174
  typedArrayTags[objectTag$2] = typedArrayTags[regexpTag] =
9174
- typedArrayTags[setTag$2] = typedArrayTags[stringTag$1] =
9175
+ typedArrayTags[setTag$1] = typedArrayTags[stringTag] =
9175
9176
  typedArrayTags[weakMapTag$1] = false;
9176
9177
 
9177
9178
  /**
@@ -9521,10 +9522,10 @@ var Set$1 = getNative(root, 'Set');
9521
9522
  var WeakMap$1 = getNative(root, 'WeakMap');
9522
9523
 
9523
9524
  /** `Object#toString` result references. */
9524
- var mapTag$1 = '[object Map]',
9525
+ var mapTag = '[object Map]',
9525
9526
  objectTag$1 = '[object Object]',
9526
9527
  promiseTag = '[object Promise]',
9527
- setTag$1 = '[object Set]',
9528
+ setTag = '[object Set]',
9528
9529
  weakMapTag = '[object WeakMap]';
9529
9530
 
9530
9531
  var dataViewTag = '[object DataView]';
@@ -9547,9 +9548,9 @@ var getTag = baseGetTag;
9547
9548
 
9548
9549
  // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
9549
9550
  if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
9550
- (Map$1 && getTag(new Map$1) != mapTag$1) ||
9551
+ (Map$1 && getTag(new Map$1) != mapTag) ||
9551
9552
  (Promise$1 && getTag(Promise$1.resolve()) != promiseTag) ||
9552
- (Set$1 && getTag(new Set$1) != setTag$1) ||
9553
+ (Set$1 && getTag(new Set$1) != setTag) ||
9553
9554
  (WeakMap$1 && getTag(new WeakMap$1) != weakMapTag)) {
9554
9555
  getTag = function(value) {
9555
9556
  var result = baseGetTag(value),
@@ -9559,9 +9560,9 @@ if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
9559
9560
  if (ctorString) {
9560
9561
  switch (ctorString) {
9561
9562
  case dataViewCtorString: return dataViewTag;
9562
- case mapCtorString: return mapTag$1;
9563
+ case mapCtorString: return mapTag;
9563
9564
  case promiseCtorString: return promiseTag;
9564
- case setCtorString: return setTag$1;
9565
+ case setCtorString: return setTag;
9565
9566
  case weakMapCtorString: return weakMapTag;
9566
9567
  }
9567
9568
  }
@@ -10825,9 +10826,9 @@ function gatherTrimmedItems(trimmedItems) {
10825
10826
  * @param data - The data to set on the store.
10826
10827
  */
10827
10828
  function setStore(store, data) {
10828
- Object.entries(data).forEach(([key, value]) => {
10829
- store.set(key, value);
10830
- });
10829
+ for (const key of Object.keys(data)) {
10830
+ store.set(key, data[key]);
10831
+ }
10831
10832
  }
10832
10833
 
10833
10834
  /**
@@ -11338,21 +11339,6 @@ function getScrollbarSize(document) {
11338
11339
  // Return the calculated width of the scrollbar
11339
11340
  return scrollbarWidth;
11340
11341
  }
11341
- /* Scale a value between 2 ranges
11342
- *
11343
- * Sample:
11344
- * // 55 from a 0-100 range to a 0-1000 range (Ranges don't have to be positive)
11345
- * const n = scaleValue(55, [0,100], [0,1000]);
11346
- *
11347
- * Ranges of two values
11348
- * @from
11349
- * @to
11350
- *
11351
- * ~~ return value does the equivalent of Math.floor but faster.
11352
- */
11353
- function scaleValue(value, from, to) {
11354
- return ((to[1] - to[0]) * (value - from[0])) / (from[1] - from[0]) + to[0];
11355
- }
11356
11342
  /**
11357
11343
  * Async timeout
11358
11344
  */
@@ -11726,6 +11712,21 @@ function getItemByIndex(dimension, index) {
11726
11712
  return item;
11727
11713
  }
11728
11714
 
11715
+ function calculateRealSize({ count, originItemSize, sizes, }) {
11716
+ const safeCount = Math.max(0, count);
11717
+ let realSize = safeCount * originItemSize;
11718
+ for (let index in sizes) {
11719
+ const itemIndex = Number(index);
11720
+ if (!Number.isInteger(itemIndex) ||
11721
+ itemIndex < 0 ||
11722
+ itemIndex >= safeCount ||
11723
+ String(itemIndex) !== index) {
11724
+ continue;
11725
+ }
11726
+ realSize += sizes[index] - originItemSize;
11727
+ }
11728
+ return realSize;
11729
+ }
11729
11730
  /**
11730
11731
  * Plugin which recalculates realSize on changes of sizes, originItemSize and count
11731
11732
  */
@@ -11738,20 +11739,18 @@ const recalculateRealSizePlugin = (storeService) => {
11738
11739
  * Reacts on changes of count, sizes and originItemSize
11739
11740
  */
11740
11741
  set(k) {
11741
- var _a;
11742
11742
  switch (k) {
11743
11743
  case 'count':
11744
11744
  case 'sizes':
11745
11745
  case 'originItemSize': {
11746
11746
  // recalculate realSize
11747
- let realSize = 0;
11748
- const count = storeService.store.get('count');
11749
- const sizes = storeService.store.get('sizes');
11750
- const originItemSize = storeService.store.get('originItemSize');
11751
- for (let i = 0; i < count; i++) {
11752
- realSize += (_a = sizes[i]) !== null && _a !== void 0 ? _a : originItemSize;
11753
- }
11754
- storeService.setStore({ realSize });
11747
+ storeService.setStore({
11748
+ realSize: calculateRealSize({
11749
+ count: storeService.store.get('count'),
11750
+ sizes: storeService.store.get('sizes'),
11751
+ originItemSize: storeService.store.get('originItemSize'),
11752
+ }),
11753
+ });
11755
11754
  break;
11756
11755
  }
11757
11756
  }
@@ -11841,7 +11840,9 @@ function initialState$1() {
11841
11840
  // size which all items can take
11842
11841
  realSize: 0,
11843
11842
  // initial item size if it wasn't changed
11844
- originItemSize: 0
11843
+ originItemSize: 0,
11844
+ // logical-to-physical render offset used when scroll space is compressed
11845
+ renderOffset: 0
11845
11846
  });
11846
11847
  }
11847
11848
  class DimensionStore {
@@ -11873,7 +11874,7 @@ class DimensionStore {
11873
11874
  setStore(this.store, data);
11874
11875
  }
11875
11876
  drop() {
11876
- setStore(this.store, initialBase());
11877
+ setStore(this.store, Object.assign(Object.assign({}, initialBase()), { renderOffset: 0 }));
11877
11878
  }
11878
11879
  /**
11879
11880
  * Set custom dimension sizes and overwrite old
@@ -12044,6 +12045,15 @@ function isRangeSingleCell(a) {
12044
12045
  return a.x === a.x1 && a.y === a.y1;
12045
12046
  }
12046
12047
 
12048
+ function getViewportMaxCoordinate(dimension, viewportSize, frameOffset = 1) {
12049
+ if (!viewportSize || dimension.realSize <= viewportSize) {
12050
+ return 0;
12051
+ }
12052
+ return Math.max(0, dimension.realSize - viewportSize - dimension.originItemSize * frameOffset);
12053
+ }
12054
+ function clampViewportCoordinate(coordinate, dimension, viewportSize, frameOffset = 1) {
12055
+ return Math.min(Math.max(0, coordinate), getViewportMaxCoordinate(dimension, viewportSize, frameOffset));
12056
+ }
12047
12057
  /**
12048
12058
  * Update items based on new scroll position
12049
12059
  * If viewport wasn't changed fully simple recombination of positions
@@ -12309,6 +12319,8 @@ function initialState() {
12309
12319
  realCount: 0,
12310
12320
  // size of viewport in px
12311
12321
  clientSize: 0,
12322
+ // logical-to-physical render offset used when scroll space is compressed
12323
+ renderOffset: 0,
12312
12324
  };
12313
12325
  }
12314
12326
  /**
@@ -12344,21 +12356,8 @@ class ViewportStore {
12344
12356
  const outsize = singleOffsetInPx * 2;
12345
12357
  // math virtual size is based on visible area + 2 items outside of visible area
12346
12358
  const virtualSize = viewportSize + outsize;
12347
- // expected no scroll if real size less than virtual size, position is 0
12348
- let maxCoordinate = 0;
12349
- // if there is nodes outside of viewport, max coordinate has to be adjusted
12350
- if (dimension.realSize > viewportSize) {
12351
- // max coordinate is real size minus virtual/rendered space
12352
- maxCoordinate = dimension.realSize - viewportSize - singleOffsetInPx;
12353
- }
12354
- let pos = position;
12355
- // limit position to max and min coordinates
12356
- if (pos < 0) {
12357
- pos = 0;
12358
- }
12359
- else if (pos > maxCoordinate) {
12360
- pos = maxCoordinate;
12361
- }
12359
+ const maxCoordinate = getViewportMaxCoordinate(dimension, viewportSize, frameOffset);
12360
+ let pos = clampViewportCoordinate(position, dimension, viewportSize, frameOffset);
12362
12361
  // store last coordinate for further restore on redraw
12363
12362
  this.lastCoordinate = pos;
12364
12363
  // actual position is less than first item start based on offset
@@ -12495,11 +12494,12 @@ class RowOrderService {
12495
12494
  getRow(y, { el, rows }) {
12496
12495
  const { top } = el.getBoundingClientRect();
12497
12496
  const topRelative = y - top;
12498
- const rgRow = getItemByPosition(rows, topRelative);
12497
+ const rowOffset = rows.renderOffset || 0;
12498
+ const rgRow = getItemByPosition(rows, topRelative + rowOffset);
12499
12499
  const absolutePosition = {
12500
12500
  itemIndex: rgRow.itemIndex,
12501
- start: rgRow.start + top,
12502
- end: rgRow.end + top,
12501
+ start: rgRow.start - rowOffset + top,
12502
+ end: rgRow.end - rowOffset + top,
12503
12503
  };
12504
12504
  return absolutePosition;
12505
12505
  }
@@ -12508,8 +12508,8 @@ class RowOrderService {
12508
12508
  const { top, left } = el.getBoundingClientRect();
12509
12509
  const topRelative = y - top;
12510
12510
  const leftRelative = x - left;
12511
- const rgRow = getItemByPosition(rows, topRelative);
12512
- const rgCol = getItemByPosition(cols, leftRelative);
12511
+ const rgRow = getItemByPosition(rows, topRelative + (rows.renderOffset || 0));
12512
+ const rgCol = getItemByPosition(cols, leftRelative + (cols.renderOffset || 0));
12513
12513
  return { x: rgCol.itemIndex, y: rgRow.itemIndex };
12514
12514
  }
12515
12515
  }
@@ -12645,6 +12645,9 @@ const GROUPING_ROW_TYPE = 'rgRow';
12645
12645
  function getGroupValueDefault(item, prop) {
12646
12646
  return item[prop] || null;
12647
12647
  }
12648
+ function isDataRow(item) {
12649
+ return item != null;
12650
+ }
12648
12651
  // get source based on proxy item collection to preserve rgRow order
12649
12652
  function getSource(source, items, withoutGrouping = false) {
12650
12653
  let index = 0;
@@ -12666,6 +12669,9 @@ function getSource(source, items, withoutGrouping = false) {
12666
12669
  result.prevExpanded[model[PSEUDO_GROUP_ITEM_VALUE]] = true;
12667
12670
  }
12668
12671
  }
12672
+ else if (!isDataRow(model)) {
12673
+ return;
12674
+ }
12669
12675
  else {
12670
12676
  result.source.push(model);
12671
12677
  result.oldNewIndexes[i] = index;
@@ -12746,6 +12752,9 @@ function flattenGroupMaps({ groupedValues, parentIds, isExpanded, itemIndex, exp
12746
12752
  function gatherGrouping(array, columnProps, { prevExpanded = {}, expandedAll = false, getGroupValue = getGroupValueDefault, }) {
12747
12753
  const groupedItems = new Map();
12748
12754
  array.forEach((item, originalIndex) => {
12755
+ if (!isDataRow(item)) {
12756
+ return;
12757
+ }
12749
12758
  const groupLevelValues = columnProps.map(groupId => getGroupValue(item, groupId));
12750
12759
  const lastLevelValue = groupLevelValues.pop();
12751
12760
  let currentGroupLevel = groupedItems;
@@ -13245,8 +13254,8 @@ function getCurrentCell({ x, y }, { el, rows, cols }) {
13245
13254
  cellX = width - 1;
13246
13255
  }
13247
13256
  // Get the row and column items based on the cell position
13248
- const rgRow = getItemByPosition(rows, cellY);
13249
- const rgCol = getItemByPosition(cols, cellX);
13257
+ const rgRow = getItemByPosition(rows, cellY + (rows.renderOffset || 0));
13258
+ const rgCol = getItemByPosition(cols, cellX + (cols.renderOffset || 0));
13250
13259
  // Set the row and column index to 0 if they are before the first item
13251
13260
  if (rgCol.itemIndex < 0) {
13252
13261
  rgCol.itemIndex = 0;
@@ -13316,10 +13325,12 @@ function styleByCellProps(styles) {
13316
13325
  };
13317
13326
  }
13318
13327
  function getCell({ x, y, x1, y1 }, dimensionRow, dimensionCol) {
13319
- const top = getItemByIndex(dimensionRow, y).start;
13320
- const left = getItemByIndex(dimensionCol, x).start;
13321
- const bottom = getItemByIndex(dimensionRow, y1).end;
13322
- const right = getItemByIndex(dimensionCol, x1).end;
13328
+ const rowOffset = dimensionRow.renderOffset || 0;
13329
+ const colOffset = dimensionCol.renderOffset || 0;
13330
+ const top = getItemByIndex(dimensionRow, y).start - rowOffset;
13331
+ const left = getItemByIndex(dimensionCol, x).start - colOffset;
13332
+ const bottom = getItemByIndex(dimensionRow, y1).end - rowOffset;
13333
+ const right = getItemByIndex(dimensionCol, x1).end - colOffset;
13323
13334
  return {
13324
13335
  left,
13325
13336
  right,
@@ -13350,9 +13361,29 @@ class KeyboardService {
13350
13361
  constructor(sv) {
13351
13362
  this.sv = sv;
13352
13363
  }
13364
+ /**
13365
+ * Appends printable key input that arrives after edit mode was requested
13366
+ * but before the editor input has mounted or received focus.
13367
+ */
13368
+ appendPendingEditValue(e) {
13369
+ if (isShortcutModifier(e) ||
13370
+ e.key.length !== 1 ||
13371
+ (e.target instanceof HTMLElement && isEditInput(e.target))) {
13372
+ return false;
13373
+ }
13374
+ const editCell = this.sv.selectionStore.get('edit');
13375
+ if (typeof (editCell === null || editCell === void 0 ? void 0 : editCell.val) !== 'string') {
13376
+ return false;
13377
+ }
13378
+ this.sv.selectionStore.set('edit', Object.assign(Object.assign({}, editCell), { val: `${editCell.val}${e.key}` }));
13379
+ return true;
13380
+ }
13353
13381
  async keyDown(e, canRange, isEditMode, { range, focus }) {
13354
13382
  // IF EDIT MODE
13355
13383
  if (isEditMode) {
13384
+ if (this.appendPendingEditValue(e)) {
13385
+ return;
13386
+ }
13356
13387
  switch (e.code) {
13357
13388
  case codesLetter.ESCAPE:
13358
13389
  this.sv.cancel();
@@ -13446,7 +13477,8 @@ class KeyboardService {
13446
13477
  }
13447
13478
  const eData = this.sv.getData();
13448
13479
  if (isMulti) {
13449
- if (isAfterLast(data.end, eData.lastCell) || isBeforeFirst(data.start)) {
13480
+ const isOutOfBounds = [data.start, data.end].some(cell => isAfterLast(cell, eData.lastCell) || isBeforeFirst(cell));
13481
+ if (isOutOfBounds) {
13450
13482
  return false;
13451
13483
  }
13452
13484
  const range = getRange(data.start, data.end);
@@ -14688,6 +14720,87 @@ class DataProvider {
14688
14720
  }
14689
14721
  }
14690
14722
 
14723
+ const FALLBACK_MAX_SCROLL_SIZE = 16000000;
14724
+ const SCROLL_SIZE_GUARD = 1000000;
14725
+ let detectedMaxScrollSize;
14726
+ function getMaxScrollSize(doc = typeof document === 'undefined' ? undefined : document) {
14727
+ if (typeof detectedMaxScrollSize === 'number') {
14728
+ return detectedMaxScrollSize;
14729
+ }
14730
+ const body = doc === null || doc === void 0 ? void 0 : doc.body;
14731
+ if (body) {
14732
+ const ownerDocument = body.ownerDocument;
14733
+ const element = ownerDocument.createElement('div');
14734
+ element.style.cssText = [
14735
+ 'height:1px',
14736
+ 'left:-10000px',
14737
+ 'overflow:scroll',
14738
+ 'position:absolute',
14739
+ 'top:-10000px',
14740
+ 'visibility:hidden',
14741
+ 'width:1px',
14742
+ ].join(';');
14743
+ const content = ownerDocument.createElement('div');
14744
+ content.style.height = `${FALLBACK_MAX_SCROLL_SIZE * 4}px`;
14745
+ element.appendChild(content);
14746
+ body.appendChild(element);
14747
+ detectedMaxScrollSize = Math.max(0, Math.min(element.scrollHeight, FALLBACK_MAX_SCROLL_SIZE * 4) - SCROLL_SIZE_GUARD);
14748
+ element.remove();
14749
+ if (detectedMaxScrollSize > SCROLL_SIZE_GUARD) {
14750
+ return detectedMaxScrollSize;
14751
+ }
14752
+ detectedMaxScrollSize = FALLBACK_MAX_SCROLL_SIZE;
14753
+ return detectedMaxScrollSize;
14754
+ }
14755
+ return FALLBACK_MAX_SCROLL_SIZE;
14756
+ }
14757
+ function getScrollDimension({ contentSize, clientSize, virtualSize = 0, maxScrollSize = getMaxScrollSize(), }) {
14758
+ const safeContentSize = Math.max(0, maxScrollSize - SCROLL_SIZE_GUARD);
14759
+ const size = Math.max(0, contentSize);
14760
+ const client = Math.max(0, clientSize);
14761
+ const viewport = Math.max(0, virtualSize || client);
14762
+ const logicalScrollSize = Math.max(0, size - viewport);
14763
+ const maxPhysicalScrollSize = Math.max(0, safeContentSize - client);
14764
+ const physicalScrollSize = Math.min(logicalScrollSize, maxPhysicalScrollSize);
14765
+ const physicalContentSize = client + physicalScrollSize;
14766
+ const isCompressed = logicalScrollSize > physicalScrollSize && physicalScrollSize > 0;
14767
+ const clampLogical = (coordinate) => Math.min(Math.max(0, coordinate || 0), logicalScrollSize);
14768
+ const clampPhysical = (coordinate) => Math.min(Math.max(0, coordinate || 0), physicalScrollSize);
14769
+ const toLogicalCoordinate = (coordinate) => {
14770
+ if (!logicalScrollSize || !physicalScrollSize) {
14771
+ return 0;
14772
+ }
14773
+ if (!isCompressed) {
14774
+ return clampLogical(coordinate);
14775
+ }
14776
+ return clampLogical((clampPhysical(coordinate) / physicalScrollSize) * logicalScrollSize);
14777
+ };
14778
+ const toPhysicalCoordinate = (coordinate) => {
14779
+ if (!logicalScrollSize || !physicalScrollSize) {
14780
+ return 0;
14781
+ }
14782
+ if (!isCompressed) {
14783
+ return clampPhysical(coordinate);
14784
+ }
14785
+ return clampPhysical((clampLogical(coordinate) / logicalScrollSize) * physicalScrollSize);
14786
+ };
14787
+ return {
14788
+ contentSize: size,
14789
+ clientSize: client,
14790
+ viewportSize: viewport,
14791
+ physicalContentSize,
14792
+ logicalScrollSize,
14793
+ physicalScrollSize,
14794
+ isCompressed,
14795
+ toLogicalCoordinate,
14796
+ toPhysicalCoordinate,
14797
+ getRenderOffset(coordinate) {
14798
+ const logical = clampLogical(coordinate);
14799
+ return logical - toPhysicalCoordinate(logical);
14800
+ },
14801
+ };
14802
+ }
14803
+
14691
14804
  /**
14692
14805
  * Dimension provider
14693
14806
  * Stores dimension information and custom sizes
@@ -14825,6 +14938,20 @@ class DimensionProvider {
14825
14938
  }
14826
14939
  setViewPortCoordinate({ type, coordinate = this.viewports.stores[type].lastCoordinate, force = false, }) {
14827
14940
  const dimension = this.stores[type].getCurrentState();
14941
+ const viewport = this.viewports.stores[type].store;
14942
+ const clientSize = viewport.get('clientSize');
14943
+ const viewportSize = viewport.get('virtualSize');
14944
+ const scrollDimension = getScrollDimension({
14945
+ contentSize: dimension.realSize,
14946
+ clientSize,
14947
+ virtualSize: viewportSize,
14948
+ });
14949
+ const renderCoordinate = clampViewportCoordinate(coordinate, dimension, viewportSize);
14950
+ const renderOffset = clientSize && viewportSize
14951
+ ? scrollDimension.getRenderOffset(renderCoordinate)
14952
+ : 0;
14953
+ this.stores[type].setStore({ renderOffset });
14954
+ this.viewports.stores[type].setViewport({ renderOffset });
14828
14955
  this.viewports.stores[type].setViewPortCoordinate(coordinate, dimension, force);
14829
14956
  }
14830
14957
  getViewPortPos(e) {
@@ -15521,17 +15648,24 @@ class FilterPlugin extends BasePlugin {
15521
15648
  }
15522
15649
  }
15523
15650
  if (config.collection) {
15524
- const filtersWithFilterFunctionPresent = Object.entries(config.collection).filter(([, item]) => this.filterFunctionsIndexedByType[item.type]);
15525
- this.filterCollection = Object.fromEntries(filtersWithFilterFunctionPresent);
15651
+ const filterCollection = {};
15652
+ for (const prop of Object.keys(config.collection)) {
15653
+ const item = config.collection[prop];
15654
+ if (this.filterFunctionsIndexedByType[item.type]) {
15655
+ filterCollection[prop] = item;
15656
+ }
15657
+ }
15658
+ this.filterCollection = filterCollection;
15526
15659
  }
15527
15660
  else {
15528
15661
  this.filterCollection = {};
15529
15662
  }
15530
15663
  if (config.localization) {
15531
15664
  if (config.localization.filterNames) {
15532
- Object.entries(config.localization.filterNames).forEach(([k, v]) => {
15665
+ const filterNames = config.localization.filterNames;
15666
+ Object.keys(filterNames).forEach((k) => {
15533
15667
  if (this.filterNameIndexByType[k] != void 0) {
15534
- this.filterNameIndexByType[k] = v;
15668
+ this.filterNameIndexByType[k] = filterNames[k];
15535
15669
  }
15536
15670
  });
15537
15671
  }
@@ -15761,165 +15895,174 @@ function allAndConditionsSatisfied(pendingResults) {
15761
15895
  return !pendingResults.includes(true);
15762
15896
  }
15763
15897
 
15764
- /** `Object#toString` result references. */
15765
- var stringTag = '[object String]';
15766
-
15767
15898
  /**
15768
- * Checks if `value` is classified as a `String` primitive or object.
15899
+ * Checks whether a sorting map contains at least one active order.
15769
15900
  *
15770
- * @static
15771
- * @since 0.1.0
15772
- * @memberOf _
15773
- * @category Lang
15774
- * @param {*} value The value to check.
15775
- * @returns {boolean} Returns `true` if `value` is a string, else `false`.
15776
- * @example
15777
- *
15778
- * _.isString('abc');
15779
- * // => true
15780
- *
15781
- * _.isString(1);
15782
- * // => false
15901
+ * Empty maps and properties with `undefined` order are treated as inactive.
15783
15902
  */
15784
- function isString(value) {
15785
- return typeof value == 'string' ||
15786
- (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
15903
+ function hasActiveSorting(sorting) {
15904
+ for (const prop of Object.keys(sorting || {})) {
15905
+ if (sorting === null || sorting === void 0 ? void 0 : sorting[prop]) {
15906
+ return true;
15907
+ }
15908
+ }
15909
+ return false;
15787
15910
  }
15788
-
15789
15911
  /**
15790
- * Gets the size of an ASCII `string`.
15791
- *
15792
- * @private
15793
- * @param {string} string The string inspect.
15794
- * @returns {number} Returns the string size.
15912
+ * Compares column properties after object-key coercion.
15795
15913
  */
15796
- var asciiSize = baseProperty('length');
15797
-
15798
- /** Used to compose unicode character classes. */
15799
- var rsAstralRange$1 = '\\ud800-\\udfff',
15800
- rsComboMarksRange$1 = '\\u0300-\\u036f',
15801
- reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f',
15802
- rsComboSymbolsRange$1 = '\\u20d0-\\u20ff',
15803
- rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1,
15804
- rsVarRange$1 = '\\ufe0e\\ufe0f';
15805
-
15806
- /** Used to compose unicode capture groups. */
15807
- var rsZWJ$1 = '\\u200d';
15808
-
15809
- /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
15810
- var reHasUnicode = RegExp('[' + rsZWJ$1 + rsAstralRange$1 + rsComboRange$1 + rsVarRange$1 + ']');
15811
-
15914
+ function isSameColumnProp(a, b) {
15915
+ return String(a) === String(b);
15916
+ }
15812
15917
  /**
15813
- * Checks if `string` contains Unicode symbols.
15814
- *
15815
- * @private
15816
- * @param {string} string The string to inspect.
15817
- * @returns {boolean} Returns `true` if a symbol is found, else `false`.
15918
+ * Returns active sorting properties in explicit priority order.
15818
15919
  */
15819
- function hasUnicode(string) {
15820
- return reHasUnicode.test(string);
15821
- }
15822
-
15823
- /** Used to compose unicode character classes. */
15824
- var rsAstralRange = '\\ud800-\\udfff',
15825
- rsComboMarksRange = '\\u0300-\\u036f',
15826
- reComboHalfMarksRange = '\\ufe20-\\ufe2f',
15827
- rsComboSymbolsRange = '\\u20d0-\\u20ff',
15828
- rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
15829
- rsVarRange = '\\ufe0e\\ufe0f';
15830
-
15831
- /** Used to compose unicode capture groups. */
15832
- var rsAstral = '[' + rsAstralRange + ']',
15833
- rsCombo = '[' + rsComboRange + ']',
15834
- rsFitz = '\\ud83c[\\udffb-\\udfff]',
15835
- rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
15836
- rsNonAstral = '[^' + rsAstralRange + ']',
15837
- rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
15838
- rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
15839
- rsZWJ = '\\u200d';
15840
-
15841
- /** Used to compose unicode regexes. */
15842
- var reOptMod = rsModifier + '?',
15843
- rsOptVar = '[' + rsVarRange + ']?',
15844
- rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
15845
- rsSeq = rsOptVar + reOptMod + rsOptJoin,
15846
- rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
15847
-
15848
- /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
15849
- var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
15850
-
15920
+ function getActiveSortingProps(sorting, sortingOrder) {
15921
+ const activeProps = [];
15922
+ const add = (prop) => {
15923
+ if ((sorting === null || sorting === void 0 ? void 0 : sorting[prop]) && !activeProps.some(active => isSameColumnProp(active, prop))) {
15924
+ activeProps.push(prop);
15925
+ }
15926
+ };
15927
+ sortingOrder === null || sortingOrder === void 0 ? void 0 : sortingOrder.forEach(add);
15928
+ Object.keys(sorting || {}).forEach(add);
15929
+ return activeProps;
15930
+ }
15851
15931
  /**
15852
- * Gets the size of a Unicode `string`.
15932
+ * Returns one-based additive sorting rank for a column.
15853
15933
  *
15854
- * @private
15855
- * @param {string} string The string inspect.
15856
- * @returns {number} Returns the string size.
15934
+ * A single active sort does not need a visible rank, so it returns undefined.
15857
15935
  */
15858
- function unicodeSize(string) {
15859
- var result = reUnicode.lastIndex = 0;
15860
- while (reUnicode.test(string)) {
15861
- ++result;
15862
- }
15863
- return result;
15936
+ function getSortingIndex(sorting, prop, sortingOrder) {
15937
+ const activeProps = getActiveSortingProps(sorting, sortingOrder);
15938
+ if (activeProps.length <= 1) {
15939
+ return undefined;
15940
+ }
15941
+ const index = activeProps.findIndex(active => isSameColumnProp(active, prop));
15942
+ return index >= 0 ? index + 1 : undefined;
15864
15943
  }
15865
-
15866
15944
  /**
15867
- * Gets the number of symbols in `string`.
15945
+ * Collects only active comparator functions from a sorting function map.
15868
15946
  *
15869
- * @private
15870
- * @param {string} string The string to inspect.
15871
- * @returns {number} Returns the string size.
15947
+ * This keeps undefined comparator entries from triggering sorting work.
15872
15948
  */
15873
- function stringSize(string) {
15874
- return hasUnicode(string)
15875
- ? unicodeSize(string)
15876
- : asciiSize(string);
15949
+ function activeSortingEntries(sortingFunc = {}, sortingOrder) {
15950
+ const entries = [];
15951
+ const add = (prop) => {
15952
+ const cmp = sortingFunc[prop];
15953
+ if (typeof cmp === 'function' && !entries.some(([active]) => isSameColumnProp(active, prop))) {
15954
+ entries.push([prop, cmp]);
15955
+ }
15956
+ };
15957
+ sortingOrder === null || sortingOrder === void 0 ? void 0 : sortingOrder.forEach(add);
15958
+ Object.keys(sortingFunc).forEach(add);
15959
+ return entries;
15877
15960
  }
15878
-
15879
- /** `Object#toString` result references. */
15880
- var mapTag = '[object Map]',
15881
- setTag = '[object Set]';
15882
-
15883
15961
  /**
15884
- * Gets the size of `collection` by returning its length for array-like
15885
- * values or the number of own enumerable string keyed properties for objects.
15886
- *
15887
- * @static
15888
- * @memberOf _
15889
- * @since 0.1.0
15890
- * @category Collection
15891
- * @param {Array|Object|string} collection The collection to inspect.
15892
- * @returns {number} Returns the collection size.
15893
- * @example
15894
- *
15895
- * _.size([1, 2, 3]);
15896
- * // => 3
15962
+ * Reads and normalizes a value for the built-in default comparer.
15963
+ */
15964
+ function getDefaultCompareValue(item, prop, column) {
15965
+ const aRaw = column ? getCellRaw(item, column) : item === null || item === void 0 ? void 0 : item[prop];
15966
+ return typeof aRaw === 'number' ? aRaw : aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
15967
+ }
15968
+ function isEmptyCompareValue(value) {
15969
+ return value === '' || value === null || value === undefined;
15970
+ }
15971
+ /**
15972
+ * Compares two already-normalized default comparer values.
15973
+ */
15974
+ function compareValues(av, bv) {
15975
+ if (av === bv) {
15976
+ return 0;
15977
+ }
15978
+ const aEmpty = isEmptyCompareValue(av);
15979
+ const bEmpty = isEmptyCompareValue(bv);
15980
+ if (aEmpty || bEmpty) {
15981
+ if (aEmpty && bEmpty) {
15982
+ return 0;
15983
+ }
15984
+ return aEmpty ? -1 : 1;
15985
+ }
15986
+ if (av > bv) {
15987
+ return 1;
15988
+ }
15989
+ return -1;
15990
+ }
15991
+ /**
15992
+ * Sorts indexes by precomputed values for default column comparers.
15897
15993
  *
15898
- * _.size({ 'a': 1, 'b': 2 });
15899
- * // => 2
15994
+ * This avoids repeatedly parsing the same cell value during large default
15995
+ * sorts while preserving normal multi-column ordering.
15996
+ */
15997
+ function sortIndexByDefaultComparers(indexes, source, entries, sorting, sortingColumns) {
15998
+ const prepared = entries.map(([prop]) => {
15999
+ const values = [];
16000
+ const column = sortingColumns[prop];
16001
+ for (const index of indexes) {
16002
+ values[index] = getDefaultCompareValue(source[index], prop, column);
16003
+ }
16004
+ return {
16005
+ order: sorting[prop],
16006
+ values,
16007
+ };
16008
+ });
16009
+ return indexes.sort((a, b) => {
16010
+ for (const { order, values } of prepared) {
16011
+ const sorted = compareValues(values[a], values[b]);
16012
+ if (sorted) {
16013
+ return order === 'desc' ? -sorted : sorted;
16014
+ }
16015
+ }
16016
+ return 0;
16017
+ });
16018
+ }
16019
+ /**
16020
+ * Detects whether the optimized default-comparer path can be used.
15900
16021
  *
15901
- * _.size('pebbles');
15902
- * // => 7
16022
+ * Grouped rows and custom `cellCompare` functions stay on the legacy
16023
+ * comparator path to preserve their exact behavior.
15903
16024
  */
15904
- function size(collection) {
15905
- if (collection == null) {
15906
- return 0;
15907
- }
15908
- if (isArrayLike(collection)) {
15909
- return isString(collection) ? stringSize(collection) : collection.length;
15910
- }
15911
- var tag = getTag(collection);
15912
- if (tag == mapTag || tag == setTag) {
15913
- return collection.size;
15914
- }
15915
- return baseKeys(collection).length;
16025
+ function canUseDefaultCompareFastPath(entries, indexes, source, sorting, sortingColumns) {
16026
+ return !indexes.some(index => isGrouping(source[index])) && !!sorting && !!sortingColumns && entries.every(([prop]) => {
16027
+ const order = sorting[prop];
16028
+ const column = sortingColumns[prop];
16029
+ return !!order && !(column === null || column === void 0 ? void 0 : column.cellCompare);
16030
+ });
15916
16031
  }
15917
-
15918
- function sortIndexByItems(indexes, source, sortingFunc = {}) {
16032
+ /**
16033
+ * Group placeholder rows are generated for their grouping column. If sorting is
16034
+ * requested for another column, the grouped source must be unwrapped first.
16035
+ */
16036
+ function hasGroupingRowsForOtherSorting(entries, indexes, source) {
16037
+ return indexes.some(index => {
16038
+ const item = source[index];
16039
+ return isGrouping(item) && !entries.some(([prop]) => isSameColumnProp(item[GROUP_COLUMN_PROP], prop));
16040
+ });
16041
+ }
16042
+ /**
16043
+ * Sorts row indexes against a source collection.
16044
+ *
16045
+ * @param indexes - Current proxy row indexes to sort.
16046
+ * @param source - Full source collection addressed by the indexes.
16047
+ * @param sortingFunc - Comparator functions by column property.
16048
+ * @param sorting - Active sorting order by column property.
16049
+ * @param sortingColumns - Column metadata by property for default-comparer optimization.
16050
+ * @param sortingOrder - Active sorting priority in click/config insertion order.
16051
+ * @returns Sorted proxy indexes. With no sorting function keys, returns source-order indexes.
16052
+ */
16053
+ function sortIndexByItems(indexes, source, sortingFunc = {}, sorting, sortingColumns, sortingOrder) {
16054
+ const hasSortingKeys = Object.keys(sortingFunc).length > 0;
16055
+ const sortingEntries = activeSortingEntries(sortingFunc, sortingOrder);
15919
16056
  // if no sorting - return unsorted indexes
15920
- if (Object.entries(sortingFunc).length === 0) {
16057
+ if (sortingEntries.length === 0) {
15921
16058
  // Unsorted indexes
15922
- return [...Array(indexes.length).keys()];
16059
+ return hasSortingKeys ? indexes : [...new Array(indexes.length).keys()];
16060
+ }
16061
+ if (hasGroupingRowsForOtherSorting(sortingEntries, indexes, source)) {
16062
+ return indexes;
16063
+ }
16064
+ if (canUseDefaultCompareFastPath(sortingEntries, indexes, source, sorting, sortingColumns)) {
16065
+ return sortIndexByDefaultComparers(indexes, source, sortingEntries, sorting, sortingColumns);
15923
16066
  }
15924
16067
  //
15925
16068
  /**
@@ -15929,15 +16072,15 @@ function sortIndexByItems(indexes, source, sortingFunc = {}) {
15929
16072
  return indexes.sort((a, b) => {
15930
16073
  const itemA = source[a];
15931
16074
  const itemB = source[b];
15932
- for (const [prop, cmp] of Object.entries(sortingFunc)) {
16075
+ for (const [prop, cmp] of sortingEntries) {
15933
16076
  if (isGrouping(itemA)) {
15934
- if (itemA['__rvgr-prop'] !== prop) {
15935
- return 0;
16077
+ if (!isSameColumnProp(itemA[GROUP_COLUMN_PROP], prop)) {
16078
+ return a - b;
15936
16079
  }
15937
16080
  }
15938
16081
  if (isGrouping(itemB)) {
15939
- if (itemB['__rvgr-prop'] !== prop) {
15940
- return 0;
16082
+ if (!isSameColumnProp(itemB[GROUP_COLUMN_PROP], prop)) {
16083
+ return a - b;
15941
16084
  }
15942
16085
  }
15943
16086
  /**
@@ -15957,13 +16100,7 @@ function defaultCellCompare(prop, a, b) {
15957
16100
  const bRaw = this.column ? getCellRaw(b, this.column) : b === null || b === void 0 ? void 0 : b[prop];
15958
16101
  const av = typeof aRaw === 'number' ? aRaw : aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
15959
16102
  const bv = typeof bRaw === 'number' ? bRaw : bRaw === null || bRaw === void 0 ? void 0 : bRaw.toString().toLowerCase();
15960
- if (av === bv) {
15961
- return 0;
15962
- }
15963
- if (av > bv) {
15964
- return 1;
15965
- }
15966
- return -1;
16103
+ return compareValues(av, bv);
15967
16104
  }
15968
16105
  function descCellCompare(cmp) {
15969
16106
  return (prop, a, b) => {
@@ -15992,11 +16129,32 @@ function getComparer(column, order) {
15992
16129
  return undefined;
15993
16130
  }
15994
16131
 
16132
+ /**
16133
+ * Renders sorting direction and optional additive sorting rank.
16134
+ */
15995
16135
  const SortingSign = ({ column }) => {
15996
16136
  var _a;
15997
- return hAsync("i", { class: (_a = column === null || column === void 0 ? void 0 : column.order) !== null && _a !== void 0 ? _a : 'sort-off' });
16137
+ const indicatorAttrs = { class: 'sort-indicator' };
16138
+ const iconAttrs = { class: (_a = column === null || column === void 0 ? void 0 : column.order) !== null && _a !== void 0 ? _a : 'sort-off' };
16139
+ const orderIndexAttrs = { class: 'sort-order-index' };
16140
+ return (hAsync("span", Object.assign({}, indicatorAttrs), hAsync("i", Object.assign({}, iconAttrs)), (column === null || column === void 0 ? void 0 : column.sortIndex) ? (hAsync("sup", Object.assign({}, orderIndexAttrs), column.sortIndex)) : null));
15998
16141
  };
15999
16142
 
16143
+ function getSortableRowIndexes(indexes, source) {
16144
+ return indexes.filter(index => !isGrouping(source[index]));
16145
+ }
16146
+ function mergeSortedRowsWithGroups(indexes, source, sortedRows) {
16147
+ if (sortedRows.length === indexes.length) {
16148
+ return sortedRows;
16149
+ }
16150
+ let rowIndex = 0;
16151
+ return indexes.map(index => {
16152
+ if (isGrouping(source[index])) {
16153
+ return index;
16154
+ }
16155
+ return sortedRows[rowIndex++];
16156
+ });
16157
+ }
16000
16158
  /**
16001
16159
  * Lifecycle
16002
16160
  * 1. @event `beforesorting` - Triggered when sorting just starts. Nothing has happened yet. This can be triggered from a column or from the source. If the type is from rows, the column will be undefined.
@@ -16011,54 +16169,37 @@ class SortingPlugin extends BasePlugin {
16011
16169
  super(revogrid, providers);
16012
16170
  this.revogrid = revogrid;
16013
16171
  /**
16014
- * Delayed sorting promise
16172
+ * Delayed sorting promise registered in the grid render job queue.
16015
16173
  */
16016
16174
  this.sortingPromise = null;
16017
16175
  /**
16018
- * We need to sort only so often
16176
+ * Debounced sorting entry point.
16177
+ *
16178
+ * Sorting can be requested by column changes, source changes, and header
16179
+ * clicks in quick succession, so the actual sort is delayed and coalesced.
16019
16180
  */
16020
- this.postponeSort = debounce$1((order, comparison, ignoreViewportUpdate) => this.runSorting(order, comparison, ignoreViewportUpdate), 50);
16021
- const setConfig = (cfg) => {
16022
- var _a;
16023
- if (cfg) {
16024
- const sortingFunc = {};
16025
- const order = {};
16026
- (_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
16027
- sortingFunc[col.prop] = getComparer(col, col.order);
16028
- order[col.prop] = col.order;
16029
- });
16030
- if (cfg.additive) {
16031
- this.sorting = Object.assign(Object.assign({}, this.sorting), order);
16032
- this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
16033
- }
16034
- else {
16035
- // // set sorting
16036
- this.sorting = order;
16037
- this.sortingFunc = sortingFunc;
16038
- }
16039
- }
16040
- };
16041
- setConfig(config);
16181
+ this.postponeSort = debounce$1((order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) => this.runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate), 50);
16182
+ this.applySortingConfig(config);
16042
16183
  this.addEventListener('sortingconfigchanged', ({ detail }) => {
16043
16184
  config = detail;
16044
- setConfig(detail);
16045
- this.startSorting(this.sorting, this.sortingFunc);
16185
+ this.applySortingConfig(detail);
16186
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
16046
16187
  });
16047
16188
  this.addEventListener('beforeheaderrender', ({ detail, }) => {
16048
16189
  var _a;
16049
16190
  const { data: column } = detail;
16050
16191
  if (column.sortable) {
16051
- detail.data = Object.assign(Object.assign({}, column), { order: (_a = this.sorting) === null || _a === void 0 ? void 0 : _a[column.prop] });
16192
+ detail.data = Object.assign(Object.assign({}, column), { order: (_a = this.sorting) === null || _a === void 0 ? void 0 : _a[column.prop], sortIndex: getSortingIndex(this.sorting, column.prop, this.sortingOrder) });
16052
16193
  }
16053
16194
  });
16054
16195
  this.addEventListener('beforeanysource', ({ detail: { type }, }) => {
16055
16196
  // if sorting was provided - sort data
16056
- if (!!this.sorting && this.sortingFunc) {
16197
+ if (hasActiveSorting(this.sorting) && this.sortingFunc) {
16057
16198
  const event = this.emit('beforesourcesortingapply', { type, sorting: this.sorting });
16058
16199
  if (event.defaultPrevented) {
16059
16200
  return;
16060
16201
  }
16061
- this.startSorting(this.sorting, this.sortingFunc);
16202
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
16062
16203
  }
16063
16204
  });
16064
16205
  this.addEventListener('aftercolumnsset', ({ detail: { order }, }) => {
@@ -16068,13 +16209,24 @@ class SortingPlugin extends BasePlugin {
16068
16209
  }
16069
16210
  const columns = this.providers.column.getColumns();
16070
16211
  const sortingFunc = {};
16212
+ const sortingColumns = {};
16213
+ const sortingOrder = [];
16214
+ const sorting = {};
16071
16215
  for (let prop in order) {
16072
- const cmp = getComparer(getColumnByProp(columns, prop), order[prop]);
16073
- sortingFunc[prop] = cmp;
16216
+ if (order[prop]) {
16217
+ const column = getColumnByProp(columns, prop);
16218
+ const cmp = getComparer(column, order[prop]);
16219
+ sorting[prop] = order[prop];
16220
+ sortingFunc[prop] = cmp;
16221
+ sortingColumns[prop] = column;
16222
+ sortingOrder.push(prop);
16223
+ }
16074
16224
  }
16075
16225
  // set sorting
16076
- this.sorting = order;
16077
- this.sortingFunc = order && sortingFunc;
16226
+ this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
16227
+ this.sortingFunc = this.sorting ? sortingFunc : undefined;
16228
+ this.sortingColumns = this.sorting ? sortingColumns : undefined;
16229
+ this.sortingOrder = this.sorting ? sortingOrder : undefined;
16078
16230
  });
16079
16231
  this.addEventListener('beforeheaderclick', (e) => {
16080
16232
  var _a, _b, _c, _d;
@@ -16088,23 +16240,89 @@ class SortingPlugin extends BasePlugin {
16088
16240
  });
16089
16241
  }
16090
16242
  /**
16091
- * Entry point for sorting, waits for all delays, registers jobs
16243
+ * Creates mutable sorting maps from current state when additive sorting is requested.
16244
+ */
16245
+ createSortingState(additive) {
16246
+ var _a;
16247
+ return {
16248
+ sorting: additive ? Object.assign({}, this.sorting) : {},
16249
+ sortingFunc: additive ? Object.assign({}, this.sortingFunc) : {},
16250
+ sortingColumns: additive ? Object.assign({}, this.sortingColumns) : {},
16251
+ sortingOrder: additive ? [...((_a = this.sortingOrder) !== null && _a !== void 0 ? _a : [])] : [],
16252
+ };
16253
+ }
16254
+ /**
16255
+ * Stores normalized sorting state, clearing inactive empty maps.
16256
+ */
16257
+ setSortingState({ sorting, sortingFunc, sortingColumns, sortingOrder, }) {
16258
+ this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
16259
+ this.sortingFunc = this.sorting ? sortingFunc : undefined;
16260
+ this.sortingColumns = this.sorting ? sortingColumns : undefined;
16261
+ this.sortingOrder = this.sorting ? sortingOrder : undefined;
16262
+ }
16263
+ /**
16264
+ * Adds or replaces a column in a sorting state.
16092
16265
  */
16093
- startSorting(order, sortingFunc, ignoreViewportUpdate) {
16266
+ setColumnSorting(state, prop, order, cmp, column) {
16267
+ state.sorting[prop] = order;
16268
+ state.sortingFunc[prop] = cmp;
16269
+ state.sortingColumns[prop] = column;
16270
+ if (!state.sortingOrder.some(sortingProp => String(sortingProp) === String(prop))) {
16271
+ state.sortingOrder.push(prop);
16272
+ }
16273
+ }
16274
+ /**
16275
+ * Removes a column from a sorting state.
16276
+ */
16277
+ clearColumnSorting(state, prop) {
16278
+ delete state.sorting[prop];
16279
+ delete state.sortingFunc[prop];
16280
+ delete state.sortingColumns[prop];
16281
+ const index = state.sortingOrder.findIndex(sortingProp => String(sortingProp) === String(prop));
16282
+ if (index >= 0) {
16283
+ state.sortingOrder.splice(index, 1);
16284
+ }
16285
+ }
16286
+ /**
16287
+ * Normalizes external sorting configuration into internal order,
16288
+ * comparator, and column metadata maps.
16289
+ */
16290
+ applySortingConfig(cfg) {
16291
+ var _a;
16292
+ if (!cfg) {
16293
+ return;
16294
+ }
16295
+ const state = this.createSortingState(cfg.additive);
16296
+ (_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
16297
+ if (col.order) {
16298
+ this.setColumnSorting(state, col.prop, col.order, getComparer(col, col.order), col);
16299
+ return;
16300
+ }
16301
+ this.clearColumnSorting(state, col.prop);
16302
+ });
16303
+ this.setSortingState(state);
16304
+ }
16305
+ startSorting(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate) {
16094
16306
  if (!this.sortingPromise) {
16095
16307
  // add job before render
16096
16308
  this.revogrid.jobsBeforeRender.push(new Promise(resolve => {
16097
16309
  this.sortingPromise = resolve;
16098
16310
  }));
16099
16311
  }
16100
- this.postponeSort(order, sortingFunc, ignoreViewportUpdate);
16312
+ if (typeof sortingColumns === 'boolean') {
16313
+ this.postponeSort(order, sortingFunc, undefined, undefined, sortingColumns);
16314
+ return;
16315
+ }
16316
+ this.postponeSort(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate);
16101
16317
  }
16102
16318
  /**
16103
- * Apply sorting to data on header click
16104
- * If additive - add to existing sorting, multiple columns can be sorted
16319
+ * Applies sorting requested by a sortable header click.
16320
+ *
16321
+ * @param column - Column that initiated sorting.
16322
+ * @param additive - If true, add/remove this column from the current multi-sort state.
16105
16323
  */
16106
16324
  headerclick(column, additive) {
16107
- var _a, _b, _c;
16325
+ var _a;
16108
16326
  const columnProp = column.prop;
16109
16327
  let order = getNextOrder((_a = this.sorting) === null || _a === void 0 ? void 0 : _a[columnProp]);
16110
16328
  const beforeEvent = this.emit('beforesorting', { column, order, additive });
@@ -16122,52 +16340,59 @@ class SortingPlugin extends BasePlugin {
16122
16340
  return;
16123
16341
  }
16124
16342
  const cmp = getComparer(beforeApplyEvent.detail.column, beforeApplyEvent.detail.order);
16125
- if (beforeApplyEvent.detail.additive && this.sorting) {
16126
- const sorting = {};
16127
- const sortingFunc = {};
16128
- if (columnProp in sorting && size(sorting) > 1 && order === undefined) {
16129
- delete sorting[columnProp];
16130
- delete sortingFunc[columnProp];
16131
- }
16132
- else {
16133
- sorting[columnProp] = order;
16134
- sortingFunc[columnProp] = cmp;
16135
- }
16136
- this.sorting = Object.assign(Object.assign({}, this.sorting), sorting);
16137
- // extend sorting function with new sorting for multiple columns sorting
16138
- this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
16343
+ this.applyHeaderSorting(beforeApplyEvent.detail.column, beforeApplyEvent.detail.additive, order, cmp);
16344
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
16345
+ }
16346
+ /**
16347
+ * Applies sorting state produced by a header click.
16348
+ */
16349
+ applyHeaderSorting(column, additive, order, cmp) {
16350
+ if (!additive) {
16351
+ this.setSortingState(order ? {
16352
+ sorting: { [column.prop]: order },
16353
+ sortingFunc: { [column.prop]: cmp },
16354
+ sortingColumns: { [column.prop]: column },
16355
+ sortingOrder: [column.prop],
16356
+ } : this.createSortingState());
16357
+ return;
16358
+ }
16359
+ const state = this.createSortingState(true);
16360
+ if (order) {
16361
+ this.setColumnSorting(state, column.prop, order, cmp, column);
16139
16362
  }
16140
16363
  else {
16141
- if (order) {
16142
- // reset sorting
16143
- this.sorting = { [columnProp]: order };
16144
- this.sortingFunc = { [columnProp]: cmp };
16145
- }
16146
- else {
16147
- (_b = this.sorting) === null || _b === void 0 ? true : delete _b[columnProp];
16148
- (_c = this.sortingFunc) === null || _c === void 0 ? true : delete _c[columnProp];
16149
- }
16364
+ this.clearColumnSorting(state, column.prop);
16150
16365
  }
16151
- this.startSorting(this.sorting, this.sortingFunc);
16366
+ this.setSortingState(state);
16152
16367
  }
16153
- runSorting(order, comparison, ignoreViewportUpdate) {
16154
- var _a;
16155
- this.sort(order, comparison, undefined, ignoreViewportUpdate);
16156
- (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
16368
+ runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) {
16369
+ var _a, _b;
16370
+ if (typeof sortingColumns === 'boolean') {
16371
+ this.sort(order, comparison, undefined, undefined, undefined, sortingColumns);
16372
+ (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
16373
+ this.sortingPromise = null;
16374
+ return;
16375
+ }
16376
+ this.sort(order, comparison, sortingColumns, sortingOrder, undefined, ignoreViewportUpdate);
16377
+ (_b = this.sortingPromise) === null || _b === void 0 ? void 0 : _b.call(this);
16157
16378
  this.sortingPromise = null;
16158
16379
  }
16159
- /**
16160
- * Sort items by sorting function
16161
- * @requires proxyItems applied to row store
16162
- * @requires source applied to row store
16163
- *
16164
- * @param sorting - per column sorting
16165
- * @param data - this.stores['rgRow'].store.get('source')
16166
- */
16167
- sort(sorting, sortingFunc, types = rowTypes, ignoreViewportUpdate = false) {
16380
+ sort(sorting, sortingFunc, sortingColumns, sortingOrder, types = rowTypes, ignoreViewportUpdate = false) {
16381
+ let activeSortingColumns;
16382
+ let activeSortingOrder;
16383
+ let activeTypes = types;
16384
+ let activeIgnoreViewportUpdate = ignoreViewportUpdate;
16385
+ if (Array.isArray(sortingColumns)) {
16386
+ activeTypes = sortingColumns;
16387
+ activeIgnoreViewportUpdate = typeof sortingOrder === 'boolean' ? sortingOrder : false;
16388
+ }
16389
+ else {
16390
+ activeSortingColumns = sortingColumns;
16391
+ activeSortingOrder = Array.isArray(sortingOrder) ? sortingOrder : undefined;
16392
+ }
16168
16393
  // if no sorting - reset
16169
16394
  if (!Object.keys(sorting || {}).length) {
16170
- for (let type of types) {
16395
+ for (let type of activeTypes) {
16171
16396
  const storeService = this.providers.data.stores[type];
16172
16397
  // row data
16173
16398
  const source = storeService.store.get('source');
@@ -16176,26 +16401,27 @@ class SortingPlugin extends BasePlugin {
16176
16401
  // row indexes
16177
16402
  const newItemsOrder = Array.from({ length: source.length }, (_, i) => i); // recover indexes range(0, source.length)
16178
16403
  this.providers.dimension.updateSizesPositionByNewDataIndexes(type, newItemsOrder, proxyItems);
16179
- storeService.setData({ proxyItems: newItemsOrder, source: [...source], });
16404
+ storeService.setData({ proxyItems: newItemsOrder });
16180
16405
  }
16181
16406
  }
16182
16407
  else {
16183
- for (let type of types) {
16408
+ for (let type of activeTypes) {
16184
16409
  const storeService = this.providers.data.stores[type];
16185
16410
  // row data
16186
16411
  const source = storeService.store.get('source');
16187
16412
  // row indexes
16188
16413
  const proxyItems = storeService.store.get('proxyItems');
16189
- const newItemsOrder = sortIndexByItems([...proxyItems], source, sortingFunc);
16414
+ const sortItems = getSortableRowIndexes(proxyItems, source);
16415
+ const sortedItems = sortIndexByItems([...sortItems], source, sortingFunc, sorting, activeSortingColumns, activeSortingOrder);
16416
+ const newItemsOrder = mergeSortedRowsWithGroups(proxyItems, source, sortedItems);
16190
16417
  // take row indexes before trim applied and proxy items
16191
16418
  const prevItems = storeService.store.get('items');
16192
16419
  storeService.setData({
16193
16420
  proxyItems: newItemsOrder,
16194
- source: [...source],
16195
16421
  });
16196
16422
  // take currently visible row indexes
16197
16423
  const newItems = storeService.store.get('items');
16198
- if (!ignoreViewportUpdate) {
16424
+ if (!activeIgnoreViewportUpdate) {
16199
16425
  this.providers.dimension
16200
16426
  .updateSizesPositionByNewDataIndexes(type, newItems, prevItems);
16201
16427
  }
@@ -16765,6 +16991,18 @@ const expandSvgIconVNode = (expanded = false) => {
16765
16991
  return (hAsync("svg", { "aria-hidden": "true", style: { transform: `rotate(${!expanded ? -90 : 0}deg)` }, focusable: "false", viewBox: "0 0 448 512" }, hAsync("path", { fill: "currentColor", d: "M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z" })));
16766
16992
  };
16767
16993
 
16994
+ var __rest = (undefined && undefined.__rest) || function (s, e) {
16995
+ var t = {};
16996
+ for (var p in s)
16997
+ if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16998
+ t[p] = s[p];
16999
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
17000
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17001
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17002
+ t[p[i]] = s[p[i]];
17003
+ }
17004
+ return t;
17005
+ };
16768
17006
  class GroupingRowPlugin extends BasePlugin {
16769
17007
  getStore(type = GROUPING_ROW_TYPE) {
16770
17008
  return this.providers.data.stores[type].store;
@@ -16848,6 +17086,18 @@ class GroupingRowPlugin extends BasePlugin {
16848
17086
  const sortingPlugin = this.providers.plugins.getByClass(SortingPlugin);
16849
17087
  return !!(sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.sortingPromise);
16850
17088
  }
17089
+ /**
17090
+ * Returns grouping options for regrouping that must preserve current UI state.
17091
+ *
17092
+ * `expandedAll` and config `prevExpanded` are initial/config instructions.
17093
+ * Reusing them after sorting would reopen groups the user collapsed before
17094
+ * sorting instead of using the current grouped source state.
17095
+ */
17096
+ getCurrentExpandedOptions() {
17097
+ var _a;
17098
+ const _b = (_a = this.options) !== null && _a !== void 0 ? _a : {}, options = __rest(_b, ["expandedAll", "prevExpanded"]);
17099
+ return options;
17100
+ }
16851
17101
  /**
16852
17102
  * Starts global source update with group clearing and applying new one
16853
17103
  * Initiated when need to reapply grouping
@@ -16950,7 +17200,7 @@ class GroupingRowPlugin extends BasePlugin {
16950
17200
  if (!((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length)) {
16951
17201
  return;
16952
17202
  }
16953
- this.doSourceUpdate(Object.assign({}, this.options));
17203
+ this.doSourceUpdate(this.getCurrentExpandedOptions());
16954
17204
  });
16955
17205
  /**
16956
17206
  * Apply logic for focus inside of grouping
@@ -17157,7 +17407,8 @@ class ViewportService {
17157
17407
  (_a = this.config.dimensionProvider) === null || _a === void 0 ? void 0 : _a.setCustomSizes(type, detail, true);
17158
17408
  // set resize event
17159
17409
  const changedItems = {};
17160
- for (const [i, size] of Object.entries(detail || {})) {
17410
+ for (const i of Object.keys(detail || {})) {
17411
+ const size = detail[i];
17161
17412
  const virtualIndex = parseInt(i, 10);
17162
17413
  const item = getSourceItem(store, virtualIndex);
17163
17414
  if (item) {
@@ -17412,13 +17663,11 @@ class SelectionStoreConnector {
17412
17663
  return (_a = this.focusedStore) === null || _a === void 0 ? void 0 : _a.entity.store.get('range');
17413
17664
  }
17414
17665
  registerColumn(x, type) {
17666
+ this.updateColumnTypeMapping(x, type);
17415
17667
  if (this.columnStores[x]) {
17416
17668
  return this.columnStores[x];
17417
17669
  }
17418
17670
  this.columnStores[x] = new SelectionStore();
17419
- // build cross-linking type to position
17420
- this.storesByType[type] = x;
17421
- this.storesXToType[x] = type;
17422
17671
  return this.columnStores[x];
17423
17672
  }
17424
17673
  registerRow(y, type) {
@@ -17560,7 +17809,10 @@ class SelectionStoreConnector {
17560
17809
  const nextItem = nextCell(focus, lastCell);
17561
17810
  let nextStore;
17562
17811
  if (nextItem) {
17563
- Object.entries(nextItem).forEach(([type, nextItemCoord]) => {
17812
+ Object.keys(nextItem).forEach((t) => {
17813
+ var _a;
17814
+ const type = t;
17815
+ const nextItemCoord = (_a = nextItem[type]) !== null && _a !== void 0 ? _a : 0;
17564
17816
  let stores;
17565
17817
  switch (type) {
17566
17818
  case 'x':
@@ -17636,6 +17888,31 @@ class SelectionStoreConnector {
17636
17888
  }
17637
17889
  return stores;
17638
17890
  }
17891
+ /**
17892
+ * Keep column viewport positions and types in sync across pin/unpin rerenders.
17893
+ * Regression case: when a selected rgCol cell was pinned left, colPinStart
17894
+ * could take over x=0 and render the stale rgCol focus store in the pinned area.
17895
+ */
17896
+ updateColumnTypeMapping(x, type) {
17897
+ const previousType = this.storesXToType[x];
17898
+ const previousX = this.storesByType[type];
17899
+ let shouldClearFocus = false;
17900
+ this.storesByType[type] = x;
17901
+ this.storesXToType[x] = type;
17902
+ if (previousType && previousType !== type) {
17903
+ shouldClearFocus = true;
17904
+ if (this.storesByType[previousType] === x) {
17905
+ delete this.storesByType[previousType];
17906
+ }
17907
+ }
17908
+ if (typeof previousX === 'number' && previousX !== x && this.storesXToType[previousX] === type) {
17909
+ delete this.storesXToType[previousX];
17910
+ shouldClearFocus = true;
17911
+ }
17912
+ if (shouldClearFocus) {
17913
+ this.clearAll();
17914
+ }
17915
+ }
17639
17916
  }
17640
17917
 
17641
17918
  /**
@@ -18235,7 +18512,7 @@ class ColumnMovePlugin extends BasePlugin {
18235
18512
  const cols = this.getDimension(data.pin || 'rgCol');
18236
18513
  const gridRect = this.revogrid.getBoundingClientRect();
18237
18514
  const elRect = dataEl.getBoundingClientRect();
18238
- const startItem = getItemByPosition(cols, getLeftRelative(event.x, gridRect.left, elRect.left - gridRect.left));
18515
+ const startItem = getItemByPosition(cols, getLeftRelative(event.x, gridRect.left, elRect.left - gridRect.left) + (cols.renderOffset || 0));
18239
18516
  this.staticDragData = {
18240
18517
  startPos: event.x,
18241
18518
  startItem,
@@ -18260,13 +18537,13 @@ class ColumnMovePlugin extends BasePlugin {
18260
18537
  const start = this.staticDragData.startPos;
18261
18538
  if (Math.abs(start - e.x) > 10) {
18262
18539
  const x = getLeftRelative(e.x, this.dragData.gridRect.left, this.dragData.scrollOffset);
18263
- const rgCol = getItemByPosition(this.staticDragData.cols, x);
18540
+ const rgCol = getItemByPosition(this.staticDragData.cols, x + (this.staticDragData.cols.renderOffset || 0));
18264
18541
  this.orderUi.autoscroll(x, dragData.elRect.width);
18265
18542
  // prevent position change if out of bounds
18266
18543
  if (rgCol.itemIndex >= this.staticDragData.cols.count) {
18267
18544
  return;
18268
18545
  }
18269
- this.orderUi.showHandler(rgCol.end + dragData.scrollOffset, dragData.gridRect.width);
18546
+ this.orderUi.showHandler(rgCol.end - (this.staticDragData.cols.renderOffset || 0) + dragData.scrollOffset, dragData.gridRect.width);
18270
18547
  }
18271
18548
  }
18272
18549
  move(e) {
@@ -18284,7 +18561,7 @@ class ColumnMovePlugin extends BasePlugin {
18284
18561
  if (relativePos < 0) {
18285
18562
  relativePos = 0;
18286
18563
  }
18287
- const newPosition = getItemByPosition(this.staticDragData.cols, relativePos);
18564
+ const newPosition = getItemByPosition(this.staticDragData.cols, relativePos + (this.staticDragData.cols.renderOffset || 0));
18288
18565
  const store = this.providers.column.stores[this.dragData.type].store;
18289
18566
  const source = store.get('source');
18290
18567
  const newItems = [...store.get('items')];
@@ -19232,6 +19509,7 @@ class RevoGridComponent {
19232
19509
  if (!this.dimensionProvider || !this.columnProvider) {
19233
19510
  return;
19234
19511
  }
19512
+ const focusToRestore = init ? undefined : this.getColumnFocusRestore();
19235
19513
  const beforeGatherEvent = this.beforecolumnsgather.emit({
19236
19514
  columns: [...newVal],
19237
19515
  });
@@ -19249,14 +19527,76 @@ class RevoGridComponent {
19249
19527
  return;
19250
19528
  }
19251
19529
  const columns = this.columnProvider.setColumns(beforeApplyEvent.detail);
19530
+ if (focusToRestore) {
19531
+ this.pendingColumnFocusRestore = focusToRestore;
19532
+ }
19533
+ const order = {};
19534
+ for (const prop of Object.keys(beforeApplyEvent.detail.sort)) {
19535
+ order[prop] = beforeApplyEvent.detail.sort[prop].order;
19536
+ }
19252
19537
  this.aftercolumnsset.emit({
19253
19538
  columns,
19254
- order: Object.entries(beforeApplyEvent.detail.sort).reduce((acc, [prop, column]) => {
19255
- acc[prop] = column.order;
19256
- return acc;
19257
- }, {}),
19539
+ order,
19258
19540
  });
19259
19541
  }
19542
+ /**
19543
+ * Capture logical focus before columns are repartitioned by pin state.
19544
+ * Regression case: selecting a regular cell, then pinning that column left,
19545
+ * used to let the new pinned viewport reuse the old rgCol selection store.
19546
+ */
19547
+ getColumnFocusRestore() {
19548
+ var _a, _b, _c, _d;
19549
+ const focused = (_a = this.viewport) === null || _a === void 0 ? void 0 : _a.getFocused();
19550
+ const prevStoreX = (_c = (_b = this.selectionStoreConnector) === null || _b === void 0 ? void 0 : _b.focusedStore) === null || _c === void 0 ? void 0 : _c.position.x;
19551
+ const prop = (_d = focused === null || focused === void 0 ? void 0 : focused.column) === null || _d === void 0 ? void 0 : _d.prop;
19552
+ if (!focused || prop === undefined || prevStoreX === undefined) {
19553
+ return;
19554
+ }
19555
+ return {
19556
+ prop,
19557
+ colType: focused.colType,
19558
+ colIndex: focused.cell.x,
19559
+ prevStoreX,
19560
+ rowType: focused.rowType,
19561
+ rowIndex: focused.cell.y,
19562
+ };
19563
+ }
19564
+ /**
19565
+ * Reapply focus by column prop after render, once pinning has moved the
19566
+ * column to its new viewport and virtual index.
19567
+ */
19568
+ restoreColumnFocusAfterRender() {
19569
+ var _a, _b, _c, _d;
19570
+ const pending = this.pendingColumnFocusRestore;
19571
+ if (!pending) {
19572
+ return;
19573
+ }
19574
+ this.pendingColumnFocusRestore = undefined;
19575
+ if (!this.viewport || !this.columnProvider) {
19576
+ return;
19577
+ }
19578
+ const column = (_b = (_a = this.columnProvider.getColumnByProp(pending.prop)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : getColumnByProp(this.columns, pending.prop);
19579
+ if (!column) {
19580
+ return;
19581
+ }
19582
+ const colType = column.pin || 'rgCol';
19583
+ const columnIndex = this.columnProvider.getColumnIndexByProp(pending.prop, colType);
19584
+ if (columnIndex < 0) {
19585
+ return;
19586
+ }
19587
+ // Header-only column refreshes should not collapse an existing range.
19588
+ // Replay focus only when pin/unpin or repartitioning moved the logical column.
19589
+ if (colType === pending.colType &&
19590
+ columnIndex === pending.colIndex &&
19591
+ pending.prevStoreX === ((_d = (_c = this.selectionStoreConnector) === null || _c === void 0 ? void 0 : _c.focusedStore) === null || _d === void 0 ? void 0 : _d.position.x)) {
19592
+ return;
19593
+ }
19594
+ const cell = {
19595
+ x: columnIndex,
19596
+ y: pending.rowIndex,
19597
+ };
19598
+ this.viewport.setFocus(colType, pending.rowType, cell, cell);
19599
+ }
19260
19600
  disableVirtualXChanged(newVal = false, prevVal = false) {
19261
19601
  if (newVal === prevVal) {
19262
19602
  return;
@@ -19543,7 +19883,7 @@ class RevoGridComponent {
19543
19883
  if (Object.keys((_a = this.trimmedRows) !== null && _a !== void 0 ? _a : {}).length > 0) {
19544
19884
  this.trimmedRowsChanged(this.trimmedRows);
19545
19885
  }
19546
- this.rowDefChanged(this.rowDefinitions);
19886
+ this.rowDefChanged(this.rowDefinitions, undefined, undefined, false);
19547
19887
  // init grouping
19548
19888
  if (this.grouping && Object.keys(this.grouping).length > 0) {
19549
19889
  this.groupingChanged(this.grouping);
@@ -19569,6 +19909,7 @@ class RevoGridComponent {
19569
19909
  return Promise.all(this.jobsBeforeRender);
19570
19910
  }
19571
19911
  componentDidRender() {
19912
+ this.restoreColumnFocusAfterRender();
19572
19913
  this.aftergridrender.emit();
19573
19914
  }
19574
19915
  render() {
@@ -20060,11 +20401,13 @@ class RevogrData {
20060
20401
  const depth = this.dataStore.get('groupingDepth');
20061
20402
  const groupingCustomRenderer = this.dataStore.get('groupingCustomRenderer');
20062
20403
  const groupDepth = this.columnService.hasGrouping ? depth : 0;
20404
+ const rowRenderOffset = this.viewportRow.get('renderOffset') || 0;
20405
+ const colRenderOffset = this.viewportCol.get('renderOffset') || 0;
20063
20406
  for (let rgRow of rows) {
20064
20407
  const dataItem = getSourceItem(this.dataStore, rgRow.itemIndex);
20065
20408
  // #region Grouping
20066
20409
  if (isGrouping(dataItem)) {
20067
- const gmodel = Object.assign(Object.assign({}, rgRow), { index: rgRow.itemIndex, model: dataItem, groupingCustomRenderer,
20410
+ const gmodel = Object.assign(Object.assign({}, rgRow), { start: rgRow.start - rowRenderOffset, index: rgRow.itemIndex, model: dataItem, groupingCustomRenderer,
20068
20411
  // Only show expand button if grouping is enabled and not in row headers
20069
20412
  hasExpand: this.columnService.hasGrouping && this.colType !== 'rowHeaders', columnItems: cols, providers: this.providers });
20070
20413
  rowsEls.push(hAsync(GroupingRowRenderer, Object.assign({}, gmodel)));
@@ -20087,7 +20430,7 @@ class RevogrData {
20087
20430
  [DATA_ROW]: rowProps.itemIndex,
20088
20431
  style: {
20089
20432
  width: `${columnProps.size}px`,
20090
- transform: `translateX(${columnProps.start}px)`,
20433
+ transform: `translateX(${columnProps.start - colRenderOffset}px)`,
20091
20434
  height: rowProps.size ? `${rowProps.size}px` : undefined,
20092
20435
  },
20093
20436
  };
@@ -20115,7 +20458,7 @@ class RevogrData {
20115
20458
  if (this.rowHighlightPlugin.isRowFocused(rgRow.itemIndex)) {
20116
20459
  rowClass += ` ${ROW_FOCUSED_CLASS}`;
20117
20460
  }
20118
- const row = (hAsync(RowRenderer, { index: rgRow.itemIndex, rowClass: rowClass, size: rgRow.size, start: rgRow.start, groupingLevel: groupDepth || undefined }, cells));
20461
+ const row = (hAsync(RowRenderer, { index: rgRow.itemIndex, rowClass: rowClass, size: rgRow.size, start: rgRow.start - rowRenderOffset, groupingLevel: groupDepth || undefined }, cells));
20119
20462
  this.beforerowrender.emit({
20120
20463
  node: row,
20121
20464
  item: rgRow,
@@ -20434,7 +20777,7 @@ const HeaderRenderer = (p) => {
20434
20777
  class: cellClass,
20435
20778
  style: {
20436
20779
  width: `${p.column.size}px`,
20437
- transform: `translateX(${p.column.start}px)`,
20780
+ transform: `translateX(${p.column.start - (p.renderOffset || 0)}px)`,
20438
20781
  },
20439
20782
  onResize: p.onResize,
20440
20783
  onDblClick(originalEvent) {
@@ -20479,7 +20822,7 @@ const HeaderGroupRenderer = (p) => {
20479
20822
  [HEADER_CLASS]: true,
20480
20823
  },
20481
20824
  style: {
20482
- transform: `translateX(${p.start}px)`,
20825
+ transform: `translateX(${p.start - (p.renderOffset || 0)}px)`,
20483
20826
  width: `${p.end - p.start}px`,
20484
20827
  },
20485
20828
  onResize: p.onResize,
@@ -20487,7 +20830,7 @@ const HeaderGroupRenderer = (p) => {
20487
20830
  return (hAsync(HeaderCellRenderer, { data: Object.assign(Object.assign({}, p.group), { prop: '', providers: p.providers, index: p.start }), props: groupProps, additionalData: p.additionalData }));
20488
20831
  };
20489
20832
 
20490
- const revogrHeaderStyleCss = () => `@charset "UTF-8";revogr-header{position:relative;z-index:5;display:block}revogr-header .header-rgRow{display:block;position:relative}revogr-header .header-rgRow.group{z-index:0}revogr-header .group-rgRow{position:relative;overflow:hidden}revogr-header .rgHeaderCell{position:absolute;box-sizing:border-box;height:100%;z-index:1;display:flex}revogr-header .rgHeaderCell.align-center{text-align:center}revogr-header .rgHeaderCell.align-left{text-align:left}revogr-header .rgHeaderCell.align-right{text-align:right}revogr-header .rgHeaderCell.sortable{cursor:pointer}revogr-header .rgHeaderCell i.asc:after,revogr-header .rgHeaderCell i.desc:after{font-size:13px}revogr-header .rgHeaderCell i.asc:after{content:"↑"}revogr-header .rgHeaderCell i.desc:after{content:"↓"}revogr-header .rgHeaderCell.active{z-index:10}revogr-header .rgHeaderCell.active .resizable{background-color:deepskyblue}revogr-header .rgHeaderCell .header-content{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-grow:1}revogr-header .rgHeaderCell .resizable{display:block;position:absolute;z-index:90;touch-action:none;user-select:none}revogr-header .rgHeaderCell .resizable:hover{background-color:deepskyblue}revogr-header .rgHeaderCell>.resizable-r{cursor:ew-resize;width:6px;right:0;top:0;height:100%}revogr-header .rgHeaderCell>.resizable-rb{cursor:se-resize;width:6px;height:6px;right:0;bottom:0}revogr-header .rgHeaderCell>.resizable-b{cursor:s-resize;height:6px;bottom:0;width:100%;left:0}revogr-header .rgHeaderCell>.resizable-lb{cursor:sw-resize;width:6px;height:6px;left:0;bottom:0}revogr-header .rgHeaderCell>.resizable-l{cursor:w-resize;width:6px;left:0;height:100%;top:0}revogr-header .rgHeaderCell>.resizable-lt{cursor:nw-resize;width:6px;height:6px;left:0;top:0}revogr-header .rgHeaderCell>.resizable-t{cursor:n-resize;height:6px;top:0;width:100%;left:0}revogr-header .rgHeaderCell>.resizable-rt{cursor:ne-resize;width:6px;height:6px;right:0;top:0}revogr-header .rv-filter{visibility:hidden}`;
20833
+ const revogrHeaderStyleCss = () => `@charset "UTF-8";revogr-header{position:relative;z-index:5;display:block}revogr-header .header-rgRow{display:block;position:relative}revogr-header .header-rgRow.group{z-index:0}revogr-header .group-rgRow{position:relative;overflow:hidden}revogr-header .rgHeaderCell{position:absolute;box-sizing:border-box;height:100%;z-index:1;display:flex}revogr-header .rgHeaderCell.align-center{text-align:center}revogr-header .rgHeaderCell.align-left{text-align:left}revogr-header .rgHeaderCell.align-right{text-align:right}revogr-header .rgHeaderCell.sortable{cursor:pointer}revogr-header .rgHeaderCell .sort-indicator{display:inline-flex;align-items:flex-start;gap:1px}revogr-header .rgHeaderCell .sort-indicator i.asc:after,revogr-header .rgHeaderCell .sort-indicator i.desc:after{font-size:13px}revogr-header .rgHeaderCell .sort-indicator i.asc:after{content:"↑"}revogr-header .rgHeaderCell .sort-indicator i.desc:after{content:"↓"}revogr-header .rgHeaderCell .sort-indicator .sort-order-index{font-size:10px;line-height:1;top:0}revogr-header .rgHeaderCell.active{z-index:10}revogr-header .rgHeaderCell.active .resizable{background-color:deepskyblue}revogr-header .rgHeaderCell .header-content{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-grow:1}revogr-header .rgHeaderCell .resizable{display:block;position:absolute;z-index:90;touch-action:none;user-select:none}revogr-header .rgHeaderCell .resizable:hover{background-color:deepskyblue}revogr-header .rgHeaderCell>.resizable-r{cursor:ew-resize;width:6px;right:0;top:0;height:100%}revogr-header .rgHeaderCell>.resizable-rb{cursor:se-resize;width:6px;height:6px;right:0;bottom:0}revogr-header .rgHeaderCell>.resizable-b{cursor:s-resize;height:6px;bottom:0;width:100%;left:0}revogr-header .rgHeaderCell>.resizable-lb{cursor:sw-resize;width:6px;height:6px;left:0;bottom:0}revogr-header .rgHeaderCell>.resizable-l{cursor:w-resize;width:6px;left:0;height:100%;top:0}revogr-header .rgHeaderCell>.resizable-lt{cursor:nw-resize;width:6px;height:6px;left:0;top:0}revogr-header .rgHeaderCell>.resizable-t{cursor:n-resize;height:6px;top:0;width:100%;left:0}revogr-header .rgHeaderCell>.resizable-rt{cursor:ne-resize;width:6px;height:6px;right:0;top:0}revogr-header .rv-filter{visibility:hidden}`;
20491
20834
 
20492
20835
  class RevogrHeaderComponent {
20493
20836
  constructor(hostRef) {
@@ -20543,6 +20886,7 @@ class RevogrHeaderComponent {
20543
20886
  }
20544
20887
  renderHeaderColumns(cols, range) {
20545
20888
  const columnsToRender = [];
20889
+ const renderOffset = this.viewportCol.get('renderOffset') || 0;
20546
20890
  for (let rgCol of cols) {
20547
20891
  const colData = this.colData[rgCol.itemIndex];
20548
20892
  const props = {
@@ -20551,6 +20895,7 @@ class RevogrHeaderComponent {
20551
20895
  data: Object.assign(Object.assign({}, colData), { index: rgCol.itemIndex, providers: this.providers }),
20552
20896
  canFilter: !!this.columnFilter,
20553
20897
  canResize: this.canResize,
20898
+ renderOffset,
20554
20899
  active: this.resizeHandler,
20555
20900
  additionalData: this.additionalData,
20556
20901
  onResize: e => this.onResize(e, rgCol.itemIndex),
@@ -20586,37 +20931,71 @@ class RevogrHeaderComponent {
20586
20931
  ];
20587
20932
  }
20588
20933
  renderGroupColumn(group, level, visibleGroupRange) {
20589
- var _a;
20590
- const groupStartIndex = (_a = group.indexes[0]) !== null && _a !== void 0 ? _a : -1;
20591
- if (groupStartIndex < 0) {
20592
- return;
20593
- }
20594
- const groupEndIndex = groupStartIndex + group.indexes.length - 1;
20595
- if (!visibleGroupRange ||
20596
- !isGroupInVisibleRange(groupStartIndex, groupEndIndex, visibleGroupRange)) {
20597
- return;
20598
- }
20599
- const groupStart = getItemByIndex(this.dimensionCol.state, groupStartIndex).start;
20600
- const groupEnd = getItemByIndex(this.dimensionCol.state, groupEndIndex).end;
20934
+ const groupRange = this.getGroupIndexRange(group);
20935
+ const groupBounds = this.getGroupBounds(groupRange);
20601
20936
  const props = {
20937
+ level,
20602
20938
  providers: this.providers,
20603
- start: groupStart,
20604
- end: groupEnd,
20939
+ start: groupBounds.start,
20940
+ end: groupBounds.end,
20605
20941
  group,
20942
+ renderOffset: this.viewportCol.get('renderOffset') || 0,
20606
20943
  active: this.resizeHandler,
20607
20944
  canResize: this.canResize,
20608
20945
  additionalData: this.additionalData,
20609
20946
  onResize: e => {
20610
20947
  var _a;
20611
- return this.onResizeGroup((_a = e.changedX) !== null && _a !== void 0 ? _a : 0, groupStartIndex, groupEndIndex);
20948
+ return groupRange
20949
+ ? this.onResizeGroup((_a = e.changedX) !== null && _a !== void 0 ? _a : 0, groupRange.startIndex, groupRange.endIndex)
20950
+ : undefined;
20612
20951
  },
20613
20952
  };
20614
20953
  const event = this.beforeGroupHeaderRender.emit(props);
20615
20954
  if (event.defaultPrevented) {
20616
20955
  return;
20617
20956
  }
20957
+ const renderRange = this.getGroupIndexRange(event.detail.group);
20958
+ if (!renderRange ||
20959
+ !visibleGroupRange ||
20960
+ !isGroupInVisibleRange(renderRange.startIndex, renderRange.endIndex, visibleGroupRange)) {
20961
+ return;
20962
+ }
20963
+ if (event.detail.onResize === props.onResize) {
20964
+ event.detail.onResize = e => {
20965
+ var _a;
20966
+ return this.onResizeGroup((_a = e.changedX) !== null && _a !== void 0 ? _a : 0, renderRange.startIndex, renderRange.endIndex);
20967
+ };
20968
+ }
20969
+ const renderBounds = this.getGroupBounds(renderRange);
20970
+ if (event.detail.start === props.start) {
20971
+ event.detail.start = renderBounds.start;
20972
+ }
20973
+ if (event.detail.end === props.end) {
20974
+ event.detail.end = renderBounds.end;
20975
+ }
20618
20976
  return hAsync(HeaderGroupRenderer, Object.assign({ key: this.getGroupHeaderCellKey(event.detail.group, level) }, event.detail));
20619
20977
  }
20978
+ getGroupIndexRange(group) {
20979
+ var _a;
20980
+ const startIndex = (_a = group.indexes[0]) !== null && _a !== void 0 ? _a : -1;
20981
+ if (startIndex < 0) {
20982
+ return;
20983
+ }
20984
+ const endIndex = group.indexes[group.indexes.length - 1];
20985
+ return {
20986
+ startIndex,
20987
+ endIndex,
20988
+ };
20989
+ }
20990
+ getGroupBounds(range) {
20991
+ if (!range) {
20992
+ return { start: 0, end: 0 };
20993
+ }
20994
+ return {
20995
+ start: getItemByIndex(this.dimensionCol.state, range.startIndex).start,
20996
+ end: getItemByIndex(this.dimensionCol.state, range.endIndex).end,
20997
+ };
20998
+ }
20620
20999
  getVisibleGroupRange() {
20621
21000
  const visibleColumns = this.viewportCol.get('items');
20622
21001
  if (!visibleColumns.length) {
@@ -20793,10 +21172,11 @@ const NO_COORDINATE = -1;
20793
21172
  * return full size
20794
21173
  */
20795
21174
  function getContentSize(contentSize, clientSize, virtualSize = 0) {
20796
- if (virtualSize > contentSize) {
20797
- return 0;
20798
- }
20799
- return contentSize + (virtualSize ? clientSize - virtualSize : 0);
21175
+ return getScrollDimension({
21176
+ contentSize,
21177
+ clientSize,
21178
+ virtualSize,
21179
+ }).physicalContentSize;
20800
21180
  }
20801
21181
  class LocalScrollService {
20802
21182
  constructor(cfg) {
@@ -20810,14 +21190,20 @@ class LocalScrollService {
20810
21190
  rgRow: NO_COORDINATE,
20811
21191
  rgCol: NO_COORDINATE,
20812
21192
  };
21193
+ this.previousLogicalScroll = {
21194
+ rgRow: 0,
21195
+ rgCol: 0,
21196
+ };
20813
21197
  this.params = {
20814
21198
  rgRow: Object.assign({}, initialParams),
20815
21199
  rgCol: Object.assign({}, initialParams),
20816
21200
  };
20817
21201
  }
20818
21202
  setParams(params, dimension) {
20819
- const virtualContentSize = getContentSize(params.contentSize, params.clientSize, params.virtualSize);
20820
- this.params[dimension] = Object.assign(Object.assign({}, params), { maxSize: virtualContentSize - params.clientSize, virtualContentSize });
21203
+ const scrollDimension = getScrollDimension(params);
21204
+ const virtualContentSize = scrollDimension.physicalContentSize;
21205
+ this.params[dimension] = Object.assign(Object.assign({}, params), { maxSize: virtualContentSize - params.clientSize, virtualContentSize,
21206
+ scrollDimension });
20821
21207
  }
20822
21208
  // apply scroll values after scroll done
20823
21209
  async setScroll(e) {
@@ -20837,16 +21223,27 @@ class LocalScrollService {
20837
21223
  await frameAnimation;
20838
21224
  const params = this.getParams(e.dimension);
20839
21225
  e.coordinate = Math.ceil(e.coordinate);
20840
- this.previousScroll[e.dimension] = this.wrapCoordinate(e.coordinate, params);
21226
+ this.previousLogicalScroll[e.dimension] = this.wrapLogicalCoordinate(e.coordinate, params);
21227
+ const physicalCoordinate = this.toPhysicalCoordinate(e.coordinate, params);
21228
+ this.previousScroll[e.dimension] = this.wrapPhysicalCoordinate(physicalCoordinate, params);
20841
21229
  this.preventArtificialScroll[e.dimension] = null;
20842
- this.cfg.applyScroll(Object.assign(Object.assign({}, e), { coordinate: params.virtualSize
20843
- ? this.convert(e.coordinate, params, false)
20844
- : e.coordinate }));
21230
+ this.cfg.applyScroll(Object.assign(Object.assign({}, e), { coordinate: physicalCoordinate }));
20845
21231
  }
20846
21232
  catch (id) {
20847
21233
  window.cancelAnimationFrame(id);
20848
21234
  }
20849
21235
  }
21236
+ async setScrollByDelta(e, currentPhysicalCoordinate) {
21237
+ var _a;
21238
+ const params = this.getParams(e.dimension);
21239
+ const baseCoordinate = this.previousScroll[e.dimension] === NO_COORDINATE
21240
+ ? this.toLogicalCoordinate(currentPhysicalCoordinate, params)
21241
+ : this.previousLogicalScroll[e.dimension];
21242
+ const coordinate = this.wrapLogicalCoordinate(baseCoordinate + ((_a = e.delta) !== null && _a !== void 0 ? _a : 0), params);
21243
+ const nextEvent = Object.assign(Object.assign({}, e), { coordinate });
21244
+ await this.setScroll(nextEvent);
21245
+ return nextEvent;
21246
+ }
20850
21247
  /**
20851
21248
  * On scroll event started
20852
21249
  */
@@ -20859,21 +21256,21 @@ class LocalScrollService {
20859
21256
  return;
20860
21257
  }
20861
21258
  const param = this.getParams(dimension);
21259
+ const logicalCoordinate = this.toLogicalScrollCoordinate(coordinate, dimension, param, delta);
20862
21260
  // let component know about scroll event started
20863
21261
  this.cfg.runScroll({
20864
21262
  dimension: dimension,
20865
- coordinate: param.virtualSize
20866
- ? this.convert(coordinate, param)
20867
- : coordinate,
21263
+ coordinate: logicalCoordinate,
20868
21264
  delta,
20869
21265
  outside,
20870
21266
  });
21267
+ this.previousLogicalScroll[dimension] = logicalCoordinate;
20871
21268
  }
20872
21269
  getParams(dimension) {
20873
21270
  return this.params[dimension];
20874
21271
  }
20875
21272
  // check if scroll outside of region to avoid looping
20876
- wrapCoordinate(c, param) {
21273
+ wrapPhysicalCoordinate(c, param) {
20877
21274
  if (c < 0) {
20878
21275
  return NO_COORDINATE;
20879
21276
  }
@@ -20882,22 +21279,39 @@ class LocalScrollService {
20882
21279
  }
20883
21280
  return c;
20884
21281
  }
21282
+ wrapLogicalCoordinate(c, param) {
21283
+ var _a, _b;
21284
+ if (c < 0) {
21285
+ return 0;
21286
+ }
21287
+ return Math.min(c, (_b = (_a = param.scrollDimension) === null || _a === void 0 ? void 0 : _a.logicalScrollSize) !== null && _b !== void 0 ? _b : c);
21288
+ }
20885
21289
  // prevent already started scroll, performance optimization
20886
21290
  cancelScroll(dimension) {
20887
21291
  var _a, _b;
20888
21292
  (_b = (_a = this.preventArtificialScroll)[dimension]) === null || _b === void 0 ? void 0 : _b.call(_a);
20889
21293
  this.preventArtificialScroll[dimension] = null;
20890
21294
  }
20891
- /* convert virtual to real and back, scale range */
20892
- convert(pos, param, toReal = true) {
20893
- var _a;
20894
- const minRange = param.clientSize;
20895
- const from = [0, ((_a = param.virtualContentSize) !== null && _a !== void 0 ? _a : minRange) - minRange];
20896
- const to = [0, param.contentSize - param.virtualSize];
20897
- if (toReal) {
20898
- return scaleValue(pos, from, to);
21295
+ toLogicalScrollCoordinate(coordinate, dimension, param, delta) {
21296
+ const scrollDimension = param.scrollDimension;
21297
+ if (!scrollDimension) {
21298
+ return coordinate;
21299
+ }
21300
+ if (typeof delta === 'number' && scrollDimension.isCompressed) {
21301
+ const base = this.previousScroll[dimension] === NO_COORDINATE
21302
+ ? scrollDimension.toLogicalCoordinate(coordinate - delta)
21303
+ : this.previousLogicalScroll[dimension];
21304
+ return scrollDimension.toLogicalCoordinate(scrollDimension.toPhysicalCoordinate(base + delta));
20899
21305
  }
20900
- return scaleValue(pos, to, from);
21306
+ return scrollDimension.toLogicalCoordinate(coordinate);
21307
+ }
21308
+ toPhysicalCoordinate(coordinate, param) {
21309
+ var _a, _b;
21310
+ return (_b = (_a = param.scrollDimension) === null || _a === void 0 ? void 0 : _a.toPhysicalCoordinate(coordinate)) !== null && _b !== void 0 ? _b : coordinate;
21311
+ }
21312
+ toLogicalCoordinate(coordinate, param) {
21313
+ var _a, _b;
21314
+ return (_b = (_a = param.scrollDimension) === null || _a === void 0 ? void 0 : _a.toLogicalCoordinate(coordinate)) !== null && _b !== void 0 ? _b : coordinate;
20901
21315
  }
20902
21316
  }
20903
21317
 
@@ -21055,15 +21469,9 @@ class RevogrScrollVirtual {
21055
21469
  */
21056
21470
  async changeScroll(e) {
21057
21471
  if (e.delta) {
21058
- switch (e.dimension) {
21059
- case 'rgCol':
21060
- e.coordinate = this.element.scrollLeft + e.delta;
21061
- break;
21062
- case 'rgRow':
21063
- e.coordinate = this.element.scrollTop + e.delta;
21064
- break;
21065
- }
21066
- this.setScroll(e);
21472
+ const scrollProperty = e.dimension === 'rgRow' ? 'scrollTop' : 'scrollLeft';
21473
+ const currentPhysicalCoordinate = this.element[scrollProperty];
21474
+ return this.localScrollService.setScrollByDelta(e, currentPhysicalCoordinate);
21067
21475
  }
21068
21476
  return e;
21069
21477
  }
@@ -21126,7 +21534,7 @@ class RevogrScrollVirtual {
21126
21534
  }
21127
21535
  render() {
21128
21536
  const size = getContentSize(this.realSize, this.dimension === 'rgRow' ? this.element.clientHeight : this.element.clientWidth, this.clientSize);
21129
- return (hAsync(Host, { key: '57f81ec9deb2395e96b283338c03b9ad44f1e929', onScroll: (e) => this.onScroll(e) }, hAsync("div", { key: '1a8c869adab53b362c351dae8d53664f33c4212c', style: {
21537
+ return (hAsync(Host, { key: '7213817ef941eee4050b714266598ec0c2961ee9', onScroll: (e) => this.onScroll(e) }, hAsync("div", { key: '501da49c63253ab943172494b9dbf5399be56cee', style: {
21130
21538
  [this.dimension === 'rgRow' ? 'height' : 'width']: `${size}px`,
21131
21539
  } })));
21132
21540
  }
@@ -21235,7 +21643,7 @@ class RevogrViewportScroll {
21235
21643
  * @param e
21236
21644
  */
21237
21645
  async changeScroll(e, silent = false) {
21238
- var _a, _b;
21646
+ var _a, _b, _c, _d;
21239
21647
  if (silent) {
21240
21648
  if (e.coordinate && this.verticalScroll) {
21241
21649
  switch (e.dimension) {
@@ -21248,15 +21656,16 @@ class RevogrViewportScroll {
21248
21656
  return;
21249
21657
  }
21250
21658
  if (e.delta) {
21659
+ let currentPhysicalCoordinate = 0;
21251
21660
  switch (e.dimension) {
21252
21661
  case 'rgCol':
21253
- e.coordinate = this.horizontalScroll.scrollLeft + e.delta;
21662
+ currentPhysicalCoordinate = this.horizontalScroll.scrollLeft;
21254
21663
  break;
21255
21664
  case 'rgRow':
21256
- e.coordinate = ((_b = (_a = this.verticalScroll) === null || _a === void 0 ? void 0 : _a.scrollTop) !== null && _b !== void 0 ? _b : 0) + e.delta;
21665
+ currentPhysicalCoordinate = (_b = (_a = this.verticalScroll) === null || _a === void 0 ? void 0 : _a.scrollTop) !== null && _b !== void 0 ? _b : 0;
21257
21666
  break;
21258
21667
  }
21259
- this.setScroll(e);
21668
+ return (_d = (_c = this.localScrollService) === null || _c === void 0 ? void 0 : _c.setScrollByDelta(e, currentPhysicalCoordinate)) !== null && _d !== void 0 ? _d : e;
21260
21669
  }
21261
21670
  return e;
21262
21671
  }
@@ -21408,7 +21817,10 @@ class RevogrViewportScroll {
21408
21817
  this.setScrollVisibility('rgCol', this.horizontalScroll.clientWidth, this.contentWidth);
21409
21818
  }
21410
21819
  render() {
21411
- return (hAsync(Host, { key: 'adc7378dba1794ca2ec263d52b09abefe50bcbfd', onWheel: this.horizontalMouseWheel, onScroll: (e) => this.applyScroll('rgCol', e) }, hAsync("div", { key: '7b57a8a0ea44629fefcfe4d2cd77bf0f048d8e06', class: "inner-content-table", style: { width: `${this.contentWidth}px` } }, hAsync("div", { key: 'cca3de158bc2a7f0651f578a281819be5698b257', class: "header-wrapper", ref: e => (this.header = e) }, hAsync("slot", { key: '1d170147dabe034f2c35481a8e2fedd6de2b6aed', name: HEADER_SLOT })), hAsync("div", { key: 'b6dd29a91bb1f380a83a035dfdb749ca669936f2', class: "vertical-inner", ref: el => (this.verticalScroll = el), onWheel: this.verticalMouseWheel, onScroll: (e) => this.applyScroll('rgRow', e) }, hAsync("div", { key: '9bce27bf8ec4d3b679aa9a34eb6379a8c2d46cac', class: "content-wrapper", style: { height: `${this.contentHeight}px` } }, hAsync("slot", { key: 'b44a082c9fbb948fd87bd235b4cd4356fd4a3536', name: CONTENT_SLOT }))), hAsync("div", { key: '28c305ff6bc664f1d1bbb117e8b8565c8d4bb6b2', class: "footer-wrapper", ref: e => (this.footer = e) }, hAsync("slot", { key: '96312fb7f18198fd1feb9dcc00c79cde74ba9c9f', name: FOOTER_SLOT })))));
21820
+ var _a, _b, _c, _d;
21821
+ const physicalContentHeight = getContentSize(this.contentHeight, (_b = (_a = this.verticalScroll) === null || _a === void 0 ? void 0 : _a.clientHeight) !== null && _b !== void 0 ? _b : 0);
21822
+ const physicalContentWidth = getContentSize(this.contentWidth, (_d = (_c = this.horizontalScroll) === null || _c === void 0 ? void 0 : _c.clientWidth) !== null && _d !== void 0 ? _d : 0);
21823
+ return (hAsync(Host, { key: 'a0c47dede9d131dea8c8ca449e8a323f24d9b113', onWheel: this.horizontalMouseWheel, onScroll: (e) => this.applyScroll('rgCol', e) }, hAsync("div", { key: '6c960e753ffe522ba4afb1c379264873b6c617f3', class: "inner-content-table", style: { width: `${physicalContentWidth}px` } }, hAsync("div", { key: '1a6cbcbd3634e84756b54c8150aebd25c824e14a', class: "header-wrapper", ref: e => (this.header = e) }, hAsync("slot", { key: 'e4202c687bc39b4f78f3ed9840e979b032f06af8', name: HEADER_SLOT })), hAsync("div", { key: '651415b5b32e72735065b183317386a34042bb85', class: "vertical-inner", ref: el => (this.verticalScroll = el), onWheel: this.verticalMouseWheel, onScroll: (e) => this.applyScroll('rgRow', e) }, hAsync("div", { key: 'e65623b78d80957d8676adb019618953ef267ec3', class: "content-wrapper", style: { height: `${physicalContentHeight}px` } }, hAsync("slot", { key: '5af47b12ef1226587cf774233447b5252d65e836', name: CONTENT_SLOT }))), hAsync("div", { key: 'cbc0fd64fbfb53d3b18e547bbe34e32b7bb9c043', class: "footer-wrapper", ref: e => (this.footer = e) }, hAsync("slot", { key: 'a8e4bfaef400973121090bac3069eb85469a95f3', name: FOOTER_SLOT })))));
21412
21824
  }
21413
21825
  /**
21414
21826
  * Extra layer for scroll event monitoring, where MouseWheel event is not passing