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