@revolist/revogrid 4.22.1 → 4.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/cjs/{cell-renderer-BQdEGQXP.js → cell-renderer-DWJ9Px9f.js} +9 -3
  2. package/dist/cjs/{column.drag.plugin-RDjQhKCH.js → column.drag.plugin-CaEBDG-Q.js} +391 -256
  3. package/dist/cjs/{column.service-DXYMehqK.js → column.service-f612L4ql.js} +1 -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-4yq9_WbM.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 +35 -15
  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 +26 -17
  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 +5 -2
  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 +6 -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/moveColumn/column.drag.plugin.js +4 -4
  34. package/dist/collection/plugins/sorting/sorting.func.js +173 -15
  35. package/dist/collection/plugins/sorting/sorting.plugin.js +167 -84
  36. package/dist/collection/plugins/sorting/sorting.sign.js +7 -1
  37. package/dist/collection/serve/controller.js +98 -37
  38. package/dist/collection/serve/data.js +273 -144
  39. package/dist/collection/services/dimension.provider.js +16 -1
  40. package/dist/collection/services/local.scroll.service.js +59 -24
  41. package/dist/collection/services/scroll.dimension.helpers.js +83 -0
  42. package/dist/collection/services/selection.store.connector.js +4 -1
  43. package/dist/collection/store/dimension/dimension.recalculate.plugin.js +22 -9
  44. package/dist/collection/store/dimension/dimension.store.js +4 -2
  45. package/dist/collection/store/vp/viewport.helpers.js +9 -0
  46. package/dist/collection/store/vp/viewport.store.js +5 -16
  47. package/dist/collection/utils/store.utils.js +3 -3
  48. package/dist/{revo-grid/cell-renderer-CALsEsnh.js → esm/cell-renderer-8UiGd-s7.js} +9 -3
  49. package/dist/esm/{column.drag.plugin-Dy5ztusn.js → column.drag.plugin-BsfhsfmB.js} +388 -255
  50. package/dist/esm/{column.service-CCvAi5l4.js → column.service-DbpulTog.js} +1 -1
  51. package/dist/{revo-grid/debounce-BfO9dz9v.js → esm/debounce-PCRWZliA.js} +1 -1
  52. package/dist/{revo-grid/dimension.helpers-DmIvjIa7.js → esm/dimension.helpers-CGKwSvw6.js} +7 -128
  53. package/dist/esm/{edit.utils-DYN6XZh8.js → edit.utils-Dnnbd0xG.js} +1 -1
  54. package/dist/{revo-grid/header-cell-renderer-DU8wKAbg.js → esm/header-cell-renderer-DGI2FAD8.js} +1 -1
  55. package/dist/esm/index-Db3qZoW5.js +127 -0
  56. package/dist/esm/index.js +11 -10
  57. package/dist/esm/revo-grid.entry.js +34 -14
  58. package/dist/esm/revogr-attribution_7.entry.js +42 -24
  59. package/dist/esm/revogr-clipboard_3.entry.js +11 -9
  60. package/dist/esm/revogr-data_4.entry.js +27 -18
  61. package/dist/esm/revogr-filter-panel.entry.js +3 -2
  62. package/dist/esm/{text-editor-DpCnd6Fq.js → text-editor-C3RUSwH5.js} +2 -2
  63. package/dist/esm/{throttle-ERvyruXb.js → throttle-CaUDyxyU.js} +60 -25
  64. package/dist/esm/viewport.helpers-CoCAvmZs.js +133 -0
  65. package/dist/{revo-grid/viewport.store-CFjDW-3l.js → esm/viewport.store-COAfzAyu.js} +15 -17
  66. package/dist/{esm/cell-renderer-CALsEsnh.js → revo-grid/cell-renderer-8UiGd-s7.js} +9 -3
  67. package/dist/revo-grid/{column.drag.plugin-Dy5ztusn.js → column.drag.plugin-BsfhsfmB.js} +388 -255
  68. package/dist/revo-grid/{column.service-CCvAi5l4.js → column.service-DbpulTog.js} +1 -1
  69. package/dist/{esm/debounce-BfO9dz9v.js → revo-grid/debounce-PCRWZliA.js} +1 -1
  70. package/dist/{esm/dimension.helpers-DmIvjIa7.js → revo-grid/dimension.helpers-CGKwSvw6.js} +7 -128
  71. package/dist/revo-grid/{edit.utils-DYN6XZh8.js → edit.utils-Dnnbd0xG.js} +1 -1
  72. package/dist/{esm/header-cell-renderer-DU8wKAbg.js → revo-grid/header-cell-renderer-DGI2FAD8.js} +1 -1
  73. package/dist/revo-grid/index-Db3qZoW5.js +127 -0
  74. package/dist/revo-grid/index.esm.js +11 -10
  75. package/dist/revo-grid/revo-grid.entry.js +34 -14
  76. package/dist/revo-grid/revogr-attribution_7.entry.js +42 -24
  77. package/dist/revo-grid/revogr-clipboard_3.entry.js +11 -9
  78. package/dist/revo-grid/revogr-data_4.entry.js +27 -18
  79. package/dist/revo-grid/revogr-filter-panel.entry.js +3 -2
  80. package/dist/revo-grid/{text-editor-DpCnd6Fq.js → text-editor-C3RUSwH5.js} +2 -2
  81. package/dist/revo-grid/{throttle-ERvyruXb.js → throttle-CaUDyxyU.js} +60 -25
  82. package/dist/revo-grid/viewport.helpers-CoCAvmZs.js +133 -0
  83. package/dist/{esm/viewport.store-CFjDW-3l.js → revo-grid/viewport.store-COAfzAyu.js} +15 -17
  84. package/dist/types/components/header/header-group-renderer.d.ts +1 -0
  85. package/dist/types/components/header/header-renderer.d.ts +1 -0
  86. package/dist/types/components/overlay/keyboard.service.d.ts +5 -0
  87. package/dist/types/plugins/groupingRow/grouping.row.plugin.d.ts +8 -0
  88. package/dist/types/plugins/sorting/sorting.func.d.ts +25 -2
  89. package/dist/types/plugins/sorting/sorting.plugin.d.ts +84 -9
  90. package/dist/types/plugins/sorting/sorting.sign.d.ts +5 -1
  91. package/dist/types/plugins/sorting/sorting.types.d.ts +46 -1
  92. package/dist/types/services/local.scroll.service.d.ts +10 -2
  93. package/dist/types/services/scroll.dimension.helpers.d.ts +20 -0
  94. package/dist/types/store/vp/viewport.helpers.d.ts +2 -0
  95. package/dist/types/types/interfaces.d.ts +11 -0
  96. package/hydrate/index.js +649 -365
  97. package/hydrate/index.mjs +649 -365
  98. package/package.json +1 -1
  99. package/standalone/column.service.js +1 -1
  100. package/standalone/data.store.js +1 -1
  101. package/standalone/debounce.js +1 -1
  102. package/standalone/dimension.helpers.js +1 -1
  103. package/standalone/index.js +1 -1
  104. package/standalone/local.scroll.timer.js +1 -1
  105. package/standalone/revo-grid.js +1 -1
  106. package/standalone/revogr-data2.js +1 -1
  107. package/standalone/revogr-filter-panel.js +1 -1
  108. package/standalone/revogr-header2.js +1 -1
  109. package/standalone/revogr-order-editor2.js +1 -1
  110. package/standalone/revogr-overlay-selection2.js +1 -1
  111. package/standalone/revogr-row-headers.js +1 -1
  112. package/standalone/revogr-row-headers2.js +1 -1
  113. package/standalone/revogr-scroll-virtual2.js +1 -1
  114. package/standalone/revogr-viewport-scroll2.js +1 -1
  115. package/standalone/selection.utils.js +1 -1
  116. package/standalone/throttle.js +1 -1
  117. package/standalone/toNumber.js +1 -1
  118. package/dist/cjs/viewport.helpers-BAovztDd.js +0 -58
  119. package/dist/esm/viewport.helpers-VXhsJZtn.js +0 -52
  120. package/dist/revo-grid/viewport.helpers-VXhsJZtn.js +0 -52
@@ -3,14 +3,30 @@
3
3
  */
4
4
  'use strict';
5
5
 
6
- var column_service = require('./column.service-DXYMehqK.js');
7
- var dimension_helpers = require('./dimension.helpers-CiiNnlLa.js');
8
- var viewport_store = require('./viewport.store-q6YdR9mg.js');
6
+ var column_service = require('./column.service-f612L4ql.js');
7
+ var dimension_helpers = require('./dimension.helpers-B9HgANnM.js');
8
+ var viewport_store = require('./viewport.store-BlKQ4x9H.js');
9
+ var index$1 = require('./index-DxaSE5uZ.js');
9
10
  var index = require('./index-Dq8Xzj5l.js');
10
11
  var filter_button = require('./filter.button-w6LWnyhi.js');
11
12
  var debounce = require('./debounce-CcpHiH2p.js');
12
- var headerCellRenderer = require('./header-cell-renderer-DGyBrK8I.js');
13
+ var headerCellRenderer = require('./header-cell-renderer-4yq9_WbM.js');
13
14
 
15
+ function calculateRealSize({ count, originItemSize, sizes, }) {
16
+ const safeCount = Math.max(0, count);
17
+ let realSize = safeCount * originItemSize;
18
+ for (let index in sizes) {
19
+ const itemIndex = Number(index);
20
+ if (!Number.isInteger(itemIndex) ||
21
+ itemIndex < 0 ||
22
+ itemIndex >= safeCount ||
23
+ String(itemIndex) !== index) {
24
+ continue;
25
+ }
26
+ realSize += sizes[index] - originItemSize;
27
+ }
28
+ return realSize;
29
+ }
14
30
  /**
15
31
  * Plugin which recalculates realSize on changes of sizes, originItemSize and count
16
32
  */
@@ -23,20 +39,18 @@ const recalculateRealSizePlugin = (storeService) => {
23
39
  * Reacts on changes of count, sizes and originItemSize
24
40
  */
25
41
  set(k) {
26
- var _a;
27
42
  switch (k) {
28
43
  case 'count':
29
44
  case 'sizes':
30
45
  case 'originItemSize': {
31
46
  // recalculate realSize
32
- let realSize = 0;
33
- const count = storeService.store.get('count');
34
- const sizes = storeService.store.get('sizes');
35
- const originItemSize = storeService.store.get('originItemSize');
36
- for (let i = 0; i < count; i++) {
37
- realSize += (_a = sizes[i]) !== null && _a !== void 0 ? _a : originItemSize;
38
- }
39
- storeService.setStore({ realSize });
47
+ storeService.setStore({
48
+ realSize: calculateRealSize({
49
+ count: storeService.store.get('count'),
50
+ sizes: storeService.store.get('sizes'),
51
+ originItemSize: storeService.store.get('originItemSize'),
52
+ }),
53
+ });
40
54
  break;
41
55
  }
42
56
  }
@@ -126,7 +140,9 @@ function initialState() {
126
140
  // size which all items can take
127
141
  realSize: 0,
128
142
  // initial item size if it wasn't changed
129
- originItemSize: 0
143
+ originItemSize: 0,
144
+ // logical-to-physical render offset used when scroll space is compressed
145
+ renderOffset: 0
130
146
  });
131
147
  }
132
148
  class DimensionStore {
@@ -158,7 +174,7 @@ class DimensionStore {
158
174
  dimension_helpers.setStore(this.store, data);
159
175
  }
160
176
  drop() {
161
- dimension_helpers.setStore(this.store, initialBase());
177
+ dimension_helpers.setStore(this.store, Object.assign(Object.assign({}, initialBase()), { renderOffset: 0 }));
162
178
  }
163
179
  /**
164
180
  * Set custom dimension sizes and overwrite old
@@ -671,7 +687,7 @@ class StretchColumn extends BasePlugin {
671
687
  this.providers = providers;
672
688
  this.stretchedColumn = null;
673
689
  // calculate scroll bar size for current user session
674
- this.scrollSize = dimension_helpers.getScrollbarSize(document);
690
+ this.scrollSize = index$1.getScrollbarSize(document);
675
691
  // subscribe to column changes
676
692
  const beforecolumnapplied = ({ detail: { columns }, }) => this.applyStretch(columns);
677
693
  this.addEventListener('beforecolumnapplied', beforecolumnapplied);
@@ -976,7 +992,7 @@ class ExportFilePlugin extends BasePlugin {
976
992
  a.dispatchEvent(new MouseEvent('click'));
977
993
  this.revogrid.removeChild(a);
978
994
  // delay for revoke, correct for some browsers
979
- await dimension_helpers.timeout(120);
995
+ await index$1.timeout(120);
980
996
  URL.revokeObjectURL(url);
981
997
  }
982
998
  /** Blob object */
@@ -1288,7 +1304,7 @@ class FilterPlugin extends BasePlugin {
1288
1304
  if (Object.keys(this.multiFilterItems).length === 0) {
1289
1305
  return;
1290
1306
  }
1291
- await dimension_helpers.timeout();
1307
+ await index$1.timeout();
1292
1308
  await this.runFiltering(this.multiFilterItems);
1293
1309
  };
1294
1310
  this.addEventListener('headerclick', e => this.headerclick(e));
@@ -1360,17 +1376,24 @@ class FilterPlugin extends BasePlugin {
1360
1376
  }
1361
1377
  }
1362
1378
  if (config.collection) {
1363
- const filtersWithFilterFunctionPresent = Object.entries(config.collection).filter(([, item]) => this.filterFunctionsIndexedByType[item.type]);
1364
- this.filterCollection = Object.fromEntries(filtersWithFilterFunctionPresent);
1379
+ const filterCollection = {};
1380
+ for (const prop of Object.keys(config.collection)) {
1381
+ const item = config.collection[prop];
1382
+ if (this.filterFunctionsIndexedByType[item.type]) {
1383
+ filterCollection[prop] = item;
1384
+ }
1385
+ }
1386
+ this.filterCollection = filterCollection;
1365
1387
  }
1366
1388
  else {
1367
1389
  this.filterCollection = {};
1368
1390
  }
1369
1391
  if (config.localization) {
1370
1392
  if (config.localization.filterNames) {
1371
- Object.entries(config.localization.filterNames).forEach(([k, v]) => {
1393
+ const filterNames = config.localization.filterNames;
1394
+ Object.keys(filterNames).forEach((k) => {
1372
1395
  if (this.filterNameIndexByType[k] != void 0) {
1373
- this.filterNameIndexByType[k] = v;
1396
+ this.filterNameIndexByType[k] = filterNames[k];
1374
1397
  }
1375
1398
  });
1376
1399
  }
@@ -1600,165 +1623,174 @@ function allAndConditionsSatisfied(pendingResults) {
1600
1623
  return !pendingResults.includes(true);
1601
1624
  }
1602
1625
 
1603
- /** `Object#toString` result references. */
1604
- var stringTag = '[object String]';
1605
-
1606
1626
  /**
1607
- * Checks if `value` is classified as a `String` primitive or object.
1608
- *
1609
- * @static
1610
- * @since 0.1.0
1611
- * @memberOf _
1612
- * @category Lang
1613
- * @param {*} value The value to check.
1614
- * @returns {boolean} Returns `true` if `value` is a string, else `false`.
1615
- * @example
1616
- *
1617
- * _.isString('abc');
1618
- * // => true
1627
+ * Checks whether a sorting map contains at least one active order.
1619
1628
  *
1620
- * _.isString(1);
1621
- * // => false
1629
+ * Empty maps and properties with `undefined` order are treated as inactive.
1622
1630
  */
1623
- function isString(value) {
1624
- return typeof value == 'string' ||
1625
- (!dimension_helpers.isArray(value) && debounce.isObjectLike(value) && debounce.baseGetTag(value) == stringTag);
1631
+ function hasActiveSorting(sorting) {
1632
+ for (const prop of Object.keys(sorting || {})) {
1633
+ if (sorting === null || sorting === void 0 ? void 0 : sorting[prop]) {
1634
+ return true;
1635
+ }
1636
+ }
1637
+ return false;
1626
1638
  }
1627
-
1628
1639
  /**
1629
- * Gets the size of an ASCII `string`.
1630
- *
1631
- * @private
1632
- * @param {string} string The string inspect.
1633
- * @returns {number} Returns the string size.
1640
+ * Compares column properties after object-key coercion.
1634
1641
  */
1635
- var asciiSize = dimension_helpers.baseProperty('length');
1636
-
1637
- /** Used to compose unicode character classes. */
1638
- var rsAstralRange$1 = '\\ud800-\\udfff',
1639
- rsComboMarksRange$1 = '\\u0300-\\u036f',
1640
- reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f',
1641
- rsComboSymbolsRange$1 = '\\u20d0-\\u20ff',
1642
- rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1,
1643
- rsVarRange$1 = '\\ufe0e\\ufe0f';
1644
-
1645
- /** Used to compose unicode capture groups. */
1646
- var rsZWJ$1 = '\\u200d';
1647
-
1648
- /** 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/). */
1649
- var reHasUnicode = RegExp('[' + rsZWJ$1 + rsAstralRange$1 + rsComboRange$1 + rsVarRange$1 + ']');
1650
-
1642
+ function isSameColumnProp(a, b) {
1643
+ return String(a) === String(b);
1644
+ }
1651
1645
  /**
1652
- * Checks if `string` contains Unicode symbols.
1653
- *
1654
- * @private
1655
- * @param {string} string The string to inspect.
1656
- * @returns {boolean} Returns `true` if a symbol is found, else `false`.
1646
+ * Returns active sorting properties in explicit priority order.
1657
1647
  */
1658
- function hasUnicode(string) {
1659
- return reHasUnicode.test(string);
1648
+ function getActiveSortingProps(sorting, sortingOrder) {
1649
+ const activeProps = [];
1650
+ const add = (prop) => {
1651
+ if ((sorting === null || sorting === void 0 ? void 0 : sorting[prop]) && !activeProps.some(active => isSameColumnProp(active, prop))) {
1652
+ activeProps.push(prop);
1653
+ }
1654
+ };
1655
+ sortingOrder === null || sortingOrder === void 0 ? void 0 : sortingOrder.forEach(add);
1656
+ Object.keys(sorting || {}).forEach(add);
1657
+ return activeProps;
1660
1658
  }
1661
-
1662
- /** Used to compose unicode character classes. */
1663
- var rsAstralRange = '\\ud800-\\udfff',
1664
- rsComboMarksRange = '\\u0300-\\u036f',
1665
- reComboHalfMarksRange = '\\ufe20-\\ufe2f',
1666
- rsComboSymbolsRange = '\\u20d0-\\u20ff',
1667
- rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
1668
- rsVarRange = '\\ufe0e\\ufe0f';
1669
-
1670
- /** Used to compose unicode capture groups. */
1671
- var rsAstral = '[' + rsAstralRange + ']',
1672
- rsCombo = '[' + rsComboRange + ']',
1673
- rsFitz = '\\ud83c[\\udffb-\\udfff]',
1674
- rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
1675
- rsNonAstral = '[^' + rsAstralRange + ']',
1676
- rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
1677
- rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
1678
- rsZWJ = '\\u200d';
1679
-
1680
- /** Used to compose unicode regexes. */
1681
- var reOptMod = rsModifier + '?',
1682
- rsOptVar = '[' + rsVarRange + ']?',
1683
- rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
1684
- rsSeq = rsOptVar + reOptMod + rsOptJoin,
1685
- rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
1686
-
1687
- /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
1688
- var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
1689
-
1690
1659
  /**
1691
- * Gets the size of a Unicode `string`.
1660
+ * Returns one-based additive sorting rank for a column.
1692
1661
  *
1693
- * @private
1694
- * @param {string} string The string inspect.
1695
- * @returns {number} Returns the string size.
1662
+ * A single active sort does not need a visible rank, so it returns undefined.
1696
1663
  */
1697
- function unicodeSize(string) {
1698
- var result = reUnicode.lastIndex = 0;
1699
- while (reUnicode.test(string)) {
1700
- ++result;
1701
- }
1702
- return result;
1664
+ function getSortingIndex(sorting, prop, sortingOrder) {
1665
+ const activeProps = getActiveSortingProps(sorting, sortingOrder);
1666
+ if (activeProps.length <= 1) {
1667
+ return undefined;
1668
+ }
1669
+ const index = activeProps.findIndex(active => isSameColumnProp(active, prop));
1670
+ return index >= 0 ? index + 1 : undefined;
1703
1671
  }
1704
-
1705
1672
  /**
1706
- * Gets the number of symbols in `string`.
1673
+ * Collects only active comparator functions from a sorting function map.
1707
1674
  *
1708
- * @private
1709
- * @param {string} string The string to inspect.
1710
- * @returns {number} Returns the string size.
1675
+ * This keeps undefined comparator entries from triggering sorting work.
1676
+ */
1677
+ function activeSortingEntries(sortingFunc = {}, sortingOrder) {
1678
+ const entries = [];
1679
+ const add = (prop) => {
1680
+ const cmp = sortingFunc[prop];
1681
+ if (typeof cmp === 'function' && !entries.some(([active]) => isSameColumnProp(active, prop))) {
1682
+ entries.push([prop, cmp]);
1683
+ }
1684
+ };
1685
+ sortingOrder === null || sortingOrder === void 0 ? void 0 : sortingOrder.forEach(add);
1686
+ Object.keys(sortingFunc).forEach(add);
1687
+ return entries;
1688
+ }
1689
+ /**
1690
+ * Reads and normalizes a value for the built-in default comparer.
1711
1691
  */
1712
- function stringSize(string) {
1713
- return hasUnicode(string)
1714
- ? unicodeSize(string)
1715
- : asciiSize(string);
1692
+ function getDefaultCompareValue(item, prop, column) {
1693
+ const aRaw = column ? column_service.getCellRaw(item, column) : item === null || item === void 0 ? void 0 : item[prop];
1694
+ return typeof aRaw === 'number' ? aRaw : aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
1695
+ }
1696
+ function isEmptyCompareValue(value) {
1697
+ return value === '' || value === null || value === undefined;
1716
1698
  }
1717
-
1718
- /** `Object#toString` result references. */
1719
- var mapTag = '[object Map]',
1720
- setTag = '[object Set]';
1721
-
1722
1699
  /**
1723
- * Gets the size of `collection` by returning its length for array-like
1724
- * values or the number of own enumerable string keyed properties for objects.
1725
- *
1726
- * @static
1727
- * @memberOf _
1728
- * @since 0.1.0
1729
- * @category Collection
1730
- * @param {Array|Object|string} collection The collection to inspect.
1731
- * @returns {number} Returns the collection size.
1732
- * @example
1733
- *
1734
- * _.size([1, 2, 3]);
1735
- * // => 3
1700
+ * Compares two already-normalized default comparer values.
1701
+ */
1702
+ function compareValues(av, bv) {
1703
+ if (av === bv) {
1704
+ return 0;
1705
+ }
1706
+ const aEmpty = isEmptyCompareValue(av);
1707
+ const bEmpty = isEmptyCompareValue(bv);
1708
+ if (aEmpty || bEmpty) {
1709
+ if (aEmpty && bEmpty) {
1710
+ return 0;
1711
+ }
1712
+ return aEmpty ? -1 : 1;
1713
+ }
1714
+ if (av > bv) {
1715
+ return 1;
1716
+ }
1717
+ return -1;
1718
+ }
1719
+ /**
1720
+ * Sorts indexes by precomputed values for default column comparers.
1736
1721
  *
1737
- * _.size({ 'a': 1, 'b': 2 });
1738
- * // => 2
1722
+ * This avoids repeatedly parsing the same cell value during large default
1723
+ * sorts while preserving normal multi-column ordering.
1724
+ */
1725
+ function sortIndexByDefaultComparers(indexes, source, entries, sorting, sortingColumns) {
1726
+ const prepared = entries.map(([prop]) => {
1727
+ const values = [];
1728
+ const column = sortingColumns[prop];
1729
+ for (const index of indexes) {
1730
+ values[index] = getDefaultCompareValue(source[index], prop, column);
1731
+ }
1732
+ return {
1733
+ order: sorting[prop],
1734
+ values,
1735
+ };
1736
+ });
1737
+ return indexes.sort((a, b) => {
1738
+ for (const { order, values } of prepared) {
1739
+ const sorted = compareValues(values[a], values[b]);
1740
+ if (sorted) {
1741
+ return order === 'desc' ? -sorted : sorted;
1742
+ }
1743
+ }
1744
+ return 0;
1745
+ });
1746
+ }
1747
+ /**
1748
+ * Detects whether the optimized default-comparer path can be used.
1739
1749
  *
1740
- * _.size('pebbles');
1741
- * // => 7
1750
+ * Grouped rows and custom `cellCompare` functions stay on the legacy
1751
+ * comparator path to preserve their exact behavior.
1742
1752
  */
1743
- function size(collection) {
1744
- if (collection == null) {
1745
- return 0;
1746
- }
1747
- if (dimension_helpers.isArrayLike(collection)) {
1748
- return isString(collection) ? stringSize(collection) : collection.length;
1749
- }
1750
- var tag = dimension_helpers.getTag(collection);
1751
- if (tag == mapTag || tag == setTag) {
1752
- return collection.size;
1753
- }
1754
- return dimension_helpers.baseKeys(collection).length;
1753
+ function canUseDefaultCompareFastPath(entries, indexes, source, sorting, sortingColumns) {
1754
+ return !indexes.some(index => column_service.isGrouping(source[index])) && !!sorting && !!sortingColumns && entries.every(([prop]) => {
1755
+ const order = sorting[prop];
1756
+ const column = sortingColumns[prop];
1757
+ return !!order && !(column === null || column === void 0 ? void 0 : column.cellCompare);
1758
+ });
1755
1759
  }
1756
-
1757
- function sortIndexByItems(indexes, source, sortingFunc = {}) {
1760
+ /**
1761
+ * Group placeholder rows are generated for their grouping column. If sorting is
1762
+ * requested for another column, the grouped source must be unwrapped first.
1763
+ */
1764
+ function hasGroupingRowsForOtherSorting(entries, indexes, source) {
1765
+ return indexes.some(index => {
1766
+ const item = source[index];
1767
+ return column_service.isGrouping(item) && !entries.some(([prop]) => isSameColumnProp(item[column_service.GROUP_COLUMN_PROP], prop));
1768
+ });
1769
+ }
1770
+ /**
1771
+ * Sorts row indexes against a source collection.
1772
+ *
1773
+ * @param indexes - Current proxy row indexes to sort.
1774
+ * @param source - Full source collection addressed by the indexes.
1775
+ * @param sortingFunc - Comparator functions by column property.
1776
+ * @param sorting - Active sorting order by column property.
1777
+ * @param sortingColumns - Column metadata by property for default-comparer optimization.
1778
+ * @param sortingOrder - Active sorting priority in click/config insertion order.
1779
+ * @returns Sorted proxy indexes. With no sorting function keys, returns source-order indexes.
1780
+ */
1781
+ function sortIndexByItems(indexes, source, sortingFunc = {}, sorting, sortingColumns, sortingOrder) {
1782
+ const hasSortingKeys = Object.keys(sortingFunc).length > 0;
1783
+ const sortingEntries = activeSortingEntries(sortingFunc, sortingOrder);
1758
1784
  // if no sorting - return unsorted indexes
1759
- if (Object.entries(sortingFunc).length === 0) {
1785
+ if (sortingEntries.length === 0) {
1760
1786
  // Unsorted indexes
1761
- return [...Array(indexes.length).keys()];
1787
+ return hasSortingKeys ? indexes : [...new Array(indexes.length).keys()];
1788
+ }
1789
+ if (hasGroupingRowsForOtherSorting(sortingEntries, indexes, source)) {
1790
+ return indexes;
1791
+ }
1792
+ if (canUseDefaultCompareFastPath(sortingEntries, indexes, source, sorting, sortingColumns)) {
1793
+ return sortIndexByDefaultComparers(indexes, source, sortingEntries, sorting, sortingColumns);
1762
1794
  }
1763
1795
  //
1764
1796
  /**
@@ -1768,15 +1800,15 @@ function sortIndexByItems(indexes, source, sortingFunc = {}) {
1768
1800
  return indexes.sort((a, b) => {
1769
1801
  const itemA = source[a];
1770
1802
  const itemB = source[b];
1771
- for (const [prop, cmp] of Object.entries(sortingFunc)) {
1803
+ for (const [prop, cmp] of sortingEntries) {
1772
1804
  if (column_service.isGrouping(itemA)) {
1773
- if (itemA['__rvgr-prop'] !== prop) {
1774
- return 0;
1805
+ if (!isSameColumnProp(itemA[column_service.GROUP_COLUMN_PROP], prop)) {
1806
+ return a - b;
1775
1807
  }
1776
1808
  }
1777
1809
  if (column_service.isGrouping(itemB)) {
1778
- if (itemB['__rvgr-prop'] !== prop) {
1779
- return 0;
1810
+ if (!isSameColumnProp(itemB[column_service.GROUP_COLUMN_PROP], prop)) {
1811
+ return a - b;
1780
1812
  }
1781
1813
  }
1782
1814
  /**
@@ -1796,13 +1828,7 @@ function defaultCellCompare(prop, a, b) {
1796
1828
  const bRaw = this.column ? column_service.getCellRaw(b, this.column) : b === null || b === void 0 ? void 0 : b[prop];
1797
1829
  const av = typeof aRaw === 'number' ? aRaw : aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
1798
1830
  const bv = typeof bRaw === 'number' ? bRaw : bRaw === null || bRaw === void 0 ? void 0 : bRaw.toString().toLowerCase();
1799
- if (av === bv) {
1800
- return 0;
1801
- }
1802
- if (av > bv) {
1803
- return 1;
1804
- }
1805
- return -1;
1831
+ return compareValues(av, bv);
1806
1832
  }
1807
1833
  function descCellCompare(cmp) {
1808
1834
  return (prop, a, b) => {
@@ -1831,6 +1857,21 @@ function getComparer(column, order) {
1831
1857
  return undefined;
1832
1858
  }
1833
1859
 
1860
+ function getSortableRowIndexes(indexes, source) {
1861
+ return indexes.filter(index => !column_service.isGrouping(source[index]));
1862
+ }
1863
+ function mergeSortedRowsWithGroups(indexes, source, sortedRows) {
1864
+ if (sortedRows.length === indexes.length) {
1865
+ return sortedRows;
1866
+ }
1867
+ let rowIndex = 0;
1868
+ return indexes.map(index => {
1869
+ if (column_service.isGrouping(source[index])) {
1870
+ return index;
1871
+ }
1872
+ return sortedRows[rowIndex++];
1873
+ });
1874
+ }
1834
1875
  /**
1835
1876
  * Lifecycle
1836
1877
  * 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.
@@ -1845,54 +1886,37 @@ class SortingPlugin extends BasePlugin {
1845
1886
  super(revogrid, providers);
1846
1887
  this.revogrid = revogrid;
1847
1888
  /**
1848
- * Delayed sorting promise
1889
+ * Delayed sorting promise registered in the grid render job queue.
1849
1890
  */
1850
1891
  this.sortingPromise = null;
1851
1892
  /**
1852
- * We need to sort only so often
1893
+ * Debounced sorting entry point.
1894
+ *
1895
+ * Sorting can be requested by column changes, source changes, and header
1896
+ * clicks in quick succession, so the actual sort is delayed and coalesced.
1853
1897
  */
1854
- this.postponeSort = debounce.debounce((order, comparison, ignoreViewportUpdate) => this.runSorting(order, comparison, ignoreViewportUpdate), 50);
1855
- const setConfig = (cfg) => {
1856
- var _a;
1857
- if (cfg) {
1858
- const sortingFunc = {};
1859
- const order = {};
1860
- (_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
1861
- sortingFunc[col.prop] = getComparer(col, col.order);
1862
- order[col.prop] = col.order;
1863
- });
1864
- if (cfg.additive) {
1865
- this.sorting = Object.assign(Object.assign({}, this.sorting), order);
1866
- this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
1867
- }
1868
- else {
1869
- // // set sorting
1870
- this.sorting = order;
1871
- this.sortingFunc = sortingFunc;
1872
- }
1873
- }
1874
- };
1875
- setConfig(config);
1898
+ this.postponeSort = debounce.debounce((order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) => this.runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate), 50);
1899
+ this.applySortingConfig(config);
1876
1900
  this.addEventListener('sortingconfigchanged', ({ detail }) => {
1877
1901
  config = detail;
1878
- setConfig(detail);
1879
- this.startSorting(this.sorting, this.sortingFunc);
1902
+ this.applySortingConfig(detail);
1903
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
1880
1904
  });
1881
1905
  this.addEventListener('beforeheaderrender', ({ detail, }) => {
1882
1906
  var _a;
1883
1907
  const { data: column } = detail;
1884
1908
  if (column.sortable) {
1885
- detail.data = Object.assign(Object.assign({}, column), { order: (_a = this.sorting) === null || _a === void 0 ? void 0 : _a[column.prop] });
1909
+ 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) });
1886
1910
  }
1887
1911
  });
1888
1912
  this.addEventListener('beforeanysource', ({ detail: { type }, }) => {
1889
1913
  // if sorting was provided - sort data
1890
- if (!!this.sorting && this.sortingFunc) {
1914
+ if (hasActiveSorting(this.sorting) && this.sortingFunc) {
1891
1915
  const event = this.emit('beforesourcesortingapply', { type, sorting: this.sorting });
1892
1916
  if (event.defaultPrevented) {
1893
1917
  return;
1894
1918
  }
1895
- this.startSorting(this.sorting, this.sortingFunc);
1919
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
1896
1920
  }
1897
1921
  });
1898
1922
  this.addEventListener('aftercolumnsset', ({ detail: { order }, }) => {
@@ -1902,13 +1926,24 @@ class SortingPlugin extends BasePlugin {
1902
1926
  }
1903
1927
  const columns = this.providers.column.getColumns();
1904
1928
  const sortingFunc = {};
1929
+ const sortingColumns = {};
1930
+ const sortingOrder = [];
1931
+ const sorting = {};
1905
1932
  for (let prop in order) {
1906
- const cmp = getComparer(column_service.getColumnByProp(columns, prop), order[prop]);
1907
- sortingFunc[prop] = cmp;
1933
+ if (order[prop]) {
1934
+ const column = column_service.getColumnByProp(columns, prop);
1935
+ const cmp = getComparer(column, order[prop]);
1936
+ sorting[prop] = order[prop];
1937
+ sortingFunc[prop] = cmp;
1938
+ sortingColumns[prop] = column;
1939
+ sortingOrder.push(prop);
1940
+ }
1908
1941
  }
1909
1942
  // set sorting
1910
- this.sorting = order;
1911
- this.sortingFunc = order && sortingFunc;
1943
+ this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
1944
+ this.sortingFunc = this.sorting ? sortingFunc : undefined;
1945
+ this.sortingColumns = this.sorting ? sortingColumns : undefined;
1946
+ this.sortingOrder = this.sorting ? sortingOrder : undefined;
1912
1947
  });
1913
1948
  this.addEventListener('beforeheaderclick', (e) => {
1914
1949
  var _a, _b, _c, _d;
@@ -1922,23 +1957,89 @@ class SortingPlugin extends BasePlugin {
1922
1957
  });
1923
1958
  }
1924
1959
  /**
1925
- * Entry point for sorting, waits for all delays, registers jobs
1960
+ * Creates mutable sorting maps from current state when additive sorting is requested.
1961
+ */
1962
+ createSortingState(additive) {
1963
+ var _a;
1964
+ return {
1965
+ sorting: additive ? Object.assign({}, this.sorting) : {},
1966
+ sortingFunc: additive ? Object.assign({}, this.sortingFunc) : {},
1967
+ sortingColumns: additive ? Object.assign({}, this.sortingColumns) : {},
1968
+ sortingOrder: additive ? [...((_a = this.sortingOrder) !== null && _a !== void 0 ? _a : [])] : [],
1969
+ };
1970
+ }
1971
+ /**
1972
+ * Stores normalized sorting state, clearing inactive empty maps.
1973
+ */
1974
+ setSortingState({ sorting, sortingFunc, sortingColumns, sortingOrder, }) {
1975
+ this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
1976
+ this.sortingFunc = this.sorting ? sortingFunc : undefined;
1977
+ this.sortingColumns = this.sorting ? sortingColumns : undefined;
1978
+ this.sortingOrder = this.sorting ? sortingOrder : undefined;
1979
+ }
1980
+ /**
1981
+ * Adds or replaces a column in a sorting state.
1926
1982
  */
1927
- startSorting(order, sortingFunc, ignoreViewportUpdate) {
1983
+ setColumnSorting(state, prop, order, cmp, column) {
1984
+ state.sorting[prop] = order;
1985
+ state.sortingFunc[prop] = cmp;
1986
+ state.sortingColumns[prop] = column;
1987
+ if (!state.sortingOrder.some(sortingProp => String(sortingProp) === String(prop))) {
1988
+ state.sortingOrder.push(prop);
1989
+ }
1990
+ }
1991
+ /**
1992
+ * Removes a column from a sorting state.
1993
+ */
1994
+ clearColumnSorting(state, prop) {
1995
+ delete state.sorting[prop];
1996
+ delete state.sortingFunc[prop];
1997
+ delete state.sortingColumns[prop];
1998
+ const index = state.sortingOrder.findIndex(sortingProp => String(sortingProp) === String(prop));
1999
+ if (index >= 0) {
2000
+ state.sortingOrder.splice(index, 1);
2001
+ }
2002
+ }
2003
+ /**
2004
+ * Normalizes external sorting configuration into internal order,
2005
+ * comparator, and column metadata maps.
2006
+ */
2007
+ applySortingConfig(cfg) {
2008
+ var _a;
2009
+ if (!cfg) {
2010
+ return;
2011
+ }
2012
+ const state = this.createSortingState(cfg.additive);
2013
+ (_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
2014
+ if (col.order) {
2015
+ this.setColumnSorting(state, col.prop, col.order, getComparer(col, col.order), col);
2016
+ return;
2017
+ }
2018
+ this.clearColumnSorting(state, col.prop);
2019
+ });
2020
+ this.setSortingState(state);
2021
+ }
2022
+ startSorting(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate) {
1928
2023
  if (!this.sortingPromise) {
1929
2024
  // add job before render
1930
2025
  this.revogrid.jobsBeforeRender.push(new Promise(resolve => {
1931
2026
  this.sortingPromise = resolve;
1932
2027
  }));
1933
2028
  }
1934
- this.postponeSort(order, sortingFunc, ignoreViewportUpdate);
2029
+ if (typeof sortingColumns === 'boolean') {
2030
+ this.postponeSort(order, sortingFunc, undefined, undefined, sortingColumns);
2031
+ return;
2032
+ }
2033
+ this.postponeSort(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate);
1935
2034
  }
1936
2035
  /**
1937
- * Apply sorting to data on header click
1938
- * If additive - add to existing sorting, multiple columns can be sorted
2036
+ * Applies sorting requested by a sortable header click.
2037
+ *
2038
+ * @param column - Column that initiated sorting.
2039
+ * @param additive - If true, add/remove this column from the current multi-sort state.
1939
2040
  */
1940
2041
  headerclick(column, additive) {
1941
- var _a, _b, _c;
2042
+ var _a;
1942
2043
  const columnProp = column.prop;
1943
2044
  let order = getNextOrder((_a = this.sorting) === null || _a === void 0 ? void 0 : _a[columnProp]);
1944
2045
  const beforeEvent = this.emit('beforesorting', { column, order, additive });
@@ -1956,52 +2057,59 @@ class SortingPlugin extends BasePlugin {
1956
2057
  return;
1957
2058
  }
1958
2059
  const cmp = getComparer(beforeApplyEvent.detail.column, beforeApplyEvent.detail.order);
1959
- if (beforeApplyEvent.detail.additive && this.sorting) {
1960
- const sorting = {};
1961
- const sortingFunc = {};
1962
- if (columnProp in sorting && size(sorting) > 1 && order === undefined) {
1963
- delete sorting[columnProp];
1964
- delete sortingFunc[columnProp];
1965
- }
1966
- else {
1967
- sorting[columnProp] = order;
1968
- sortingFunc[columnProp] = cmp;
1969
- }
1970
- this.sorting = Object.assign(Object.assign({}, this.sorting), sorting);
1971
- // extend sorting function with new sorting for multiple columns sorting
1972
- this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
2060
+ this.applyHeaderSorting(beforeApplyEvent.detail.column, beforeApplyEvent.detail.additive, order, cmp);
2061
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
2062
+ }
2063
+ /**
2064
+ * Applies sorting state produced by a header click.
2065
+ */
2066
+ applyHeaderSorting(column, additive, order, cmp) {
2067
+ if (!additive) {
2068
+ this.setSortingState(order ? {
2069
+ sorting: { [column.prop]: order },
2070
+ sortingFunc: { [column.prop]: cmp },
2071
+ sortingColumns: { [column.prop]: column },
2072
+ sortingOrder: [column.prop],
2073
+ } : this.createSortingState());
2074
+ return;
2075
+ }
2076
+ const state = this.createSortingState(true);
2077
+ if (order) {
2078
+ this.setColumnSorting(state, column.prop, order, cmp, column);
1973
2079
  }
1974
2080
  else {
1975
- if (order) {
1976
- // reset sorting
1977
- this.sorting = { [columnProp]: order };
1978
- this.sortingFunc = { [columnProp]: cmp };
1979
- }
1980
- else {
1981
- (_b = this.sorting) === null || _b === void 0 ? true : delete _b[columnProp];
1982
- (_c = this.sortingFunc) === null || _c === void 0 ? true : delete _c[columnProp];
1983
- }
2081
+ this.clearColumnSorting(state, column.prop);
1984
2082
  }
1985
- this.startSorting(this.sorting, this.sortingFunc);
2083
+ this.setSortingState(state);
1986
2084
  }
1987
- runSorting(order, comparison, ignoreViewportUpdate) {
1988
- var _a;
1989
- this.sort(order, comparison, undefined, ignoreViewportUpdate);
1990
- (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
2085
+ runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) {
2086
+ var _a, _b;
2087
+ if (typeof sortingColumns === 'boolean') {
2088
+ this.sort(order, comparison, undefined, undefined, undefined, sortingColumns);
2089
+ (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
2090
+ this.sortingPromise = null;
2091
+ return;
2092
+ }
2093
+ this.sort(order, comparison, sortingColumns, sortingOrder, undefined, ignoreViewportUpdate);
2094
+ (_b = this.sortingPromise) === null || _b === void 0 ? void 0 : _b.call(this);
1991
2095
  this.sortingPromise = null;
1992
2096
  }
1993
- /**
1994
- * Sort items by sorting function
1995
- * @requires proxyItems applied to row store
1996
- * @requires source applied to row store
1997
- *
1998
- * @param sorting - per column sorting
1999
- * @param data - this.stores['rgRow'].store.get('source')
2000
- */
2001
- sort(sorting, sortingFunc, types = column_service.rowTypes, ignoreViewportUpdate = false) {
2097
+ sort(sorting, sortingFunc, sortingColumns, sortingOrder, types = column_service.rowTypes, ignoreViewportUpdate = false) {
2098
+ let activeSortingColumns;
2099
+ let activeSortingOrder;
2100
+ let activeTypes = types;
2101
+ let activeIgnoreViewportUpdate = ignoreViewportUpdate;
2102
+ if (Array.isArray(sortingColumns)) {
2103
+ activeTypes = sortingColumns;
2104
+ activeIgnoreViewportUpdate = typeof sortingOrder === 'boolean' ? sortingOrder : false;
2105
+ }
2106
+ else {
2107
+ activeSortingColumns = sortingColumns;
2108
+ activeSortingOrder = Array.isArray(sortingOrder) ? sortingOrder : undefined;
2109
+ }
2002
2110
  // if no sorting - reset
2003
2111
  if (!Object.keys(sorting || {}).length) {
2004
- for (let type of types) {
2112
+ for (let type of activeTypes) {
2005
2113
  const storeService = this.providers.data.stores[type];
2006
2114
  // row data
2007
2115
  const source = storeService.store.get('source');
@@ -2010,26 +2118,27 @@ class SortingPlugin extends BasePlugin {
2010
2118
  // row indexes
2011
2119
  const newItemsOrder = Array.from({ length: source.length }, (_, i) => i); // recover indexes range(0, source.length)
2012
2120
  this.providers.dimension.updateSizesPositionByNewDataIndexes(type, newItemsOrder, proxyItems);
2013
- storeService.setData({ proxyItems: newItemsOrder, source: [...source], });
2121
+ storeService.setData({ proxyItems: newItemsOrder });
2014
2122
  }
2015
2123
  }
2016
2124
  else {
2017
- for (let type of types) {
2125
+ for (let type of activeTypes) {
2018
2126
  const storeService = this.providers.data.stores[type];
2019
2127
  // row data
2020
2128
  const source = storeService.store.get('source');
2021
2129
  // row indexes
2022
2130
  const proxyItems = storeService.store.get('proxyItems');
2023
- const newItemsOrder = sortIndexByItems([...proxyItems], source, sortingFunc);
2131
+ const sortItems = getSortableRowIndexes(proxyItems, source);
2132
+ const sortedItems = sortIndexByItems([...sortItems], source, sortingFunc, sorting, activeSortingColumns, activeSortingOrder);
2133
+ const newItemsOrder = mergeSortedRowsWithGroups(proxyItems, source, sortedItems);
2024
2134
  // take row indexes before trim applied and proxy items
2025
2135
  const prevItems = storeService.store.get('items');
2026
2136
  storeService.setData({
2027
2137
  proxyItems: newItemsOrder,
2028
- source: [...source],
2029
2138
  });
2030
2139
  // take currently visible row indexes
2031
2140
  const newItems = storeService.store.get('items');
2032
- if (!ignoreViewportUpdate) {
2141
+ if (!activeIgnoreViewportUpdate) {
2033
2142
  this.providers.dimension
2034
2143
  .updateSizesPositionByNewDataIndexes(type, newItems, prevItems);
2035
2144
  }
@@ -2221,6 +2330,18 @@ function filterOutEmptyGroupRows(source, filterTrimmed) {
2221
2330
  return trimmed;
2222
2331
  }
2223
2332
 
2333
+ var __rest = (undefined && undefined.__rest) || function (s, e) {
2334
+ var t = {};
2335
+ for (var p in s)
2336
+ if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
2337
+ t[p] = s[p];
2338
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
2339
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
2340
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
2341
+ t[p[i]] = s[p[i]];
2342
+ }
2343
+ return t;
2344
+ };
2224
2345
  class GroupingRowPlugin extends BasePlugin {
2225
2346
  getStore(type = column_service.GROUPING_ROW_TYPE) {
2226
2347
  return this.providers.data.stores[type].store;
@@ -2304,6 +2425,18 @@ class GroupingRowPlugin extends BasePlugin {
2304
2425
  const sortingPlugin = this.providers.plugins.getByClass(SortingPlugin);
2305
2426
  return !!(sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.sortingPromise);
2306
2427
  }
2428
+ /**
2429
+ * Returns grouping options for regrouping that must preserve current UI state.
2430
+ *
2431
+ * `expandedAll` and config `prevExpanded` are initial/config instructions.
2432
+ * Reusing them after sorting would reopen groups the user collapsed before
2433
+ * sorting instead of using the current grouped source state.
2434
+ */
2435
+ getCurrentExpandedOptions() {
2436
+ var _a;
2437
+ const _b = (_a = this.options) !== null && _a !== void 0 ? _a : {}, options = __rest(_b, ["expandedAll", "prevExpanded"]);
2438
+ return options;
2439
+ }
2307
2440
  /**
2308
2441
  * Starts global source update with group clearing and applying new one
2309
2442
  * Initiated when need to reapply grouping
@@ -2406,7 +2539,7 @@ class GroupingRowPlugin extends BasePlugin {
2406
2539
  if (!((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length)) {
2407
2540
  return;
2408
2541
  }
2409
- this.doSourceUpdate(Object.assign({}, this.options));
2542
+ this.doSourceUpdate(this.getCurrentExpandedOptions());
2410
2543
  });
2411
2544
  /**
2412
2545
  * Apply logic for focus inside of grouping
@@ -2585,7 +2718,7 @@ class ColumnMovePlugin extends BasePlugin {
2585
2718
  const cols = this.getDimension(data.pin || 'rgCol');
2586
2719
  const gridRect = this.revogrid.getBoundingClientRect();
2587
2720
  const elRect = dataEl.getBoundingClientRect();
2588
- const startItem = dimension_helpers.getItemByPosition(cols, getLeftRelative(event.x, gridRect.left, elRect.left - gridRect.left));
2721
+ const startItem = dimension_helpers.getItemByPosition(cols, getLeftRelative(event.x, gridRect.left, elRect.left - gridRect.left) + (cols.renderOffset || 0));
2589
2722
  this.staticDragData = {
2590
2723
  startPos: event.x,
2591
2724
  startItem,
@@ -2610,13 +2743,13 @@ class ColumnMovePlugin extends BasePlugin {
2610
2743
  const start = this.staticDragData.startPos;
2611
2744
  if (Math.abs(start - e.x) > 10) {
2612
2745
  const x = getLeftRelative(e.x, this.dragData.gridRect.left, this.dragData.scrollOffset);
2613
- const rgCol = dimension_helpers.getItemByPosition(this.staticDragData.cols, x);
2746
+ const rgCol = dimension_helpers.getItemByPosition(this.staticDragData.cols, x + (this.staticDragData.cols.renderOffset || 0));
2614
2747
  this.orderUi.autoscroll(x, dragData.elRect.width);
2615
2748
  // prevent position change if out of bounds
2616
2749
  if (rgCol.itemIndex >= this.staticDragData.cols.count) {
2617
2750
  return;
2618
2751
  }
2619
- this.orderUi.showHandler(rgCol.end + dragData.scrollOffset, dragData.gridRect.width);
2752
+ this.orderUi.showHandler(rgCol.end - (this.staticDragData.cols.renderOffset || 0) + dragData.scrollOffset, dragData.gridRect.width);
2620
2753
  }
2621
2754
  }
2622
2755
  move(e) {
@@ -2634,7 +2767,7 @@ class ColumnMovePlugin extends BasePlugin {
2634
2767
  if (relativePos < 0) {
2635
2768
  relativePos = 0;
2636
2769
  }
2637
- const newPosition = dimension_helpers.getItemByPosition(this.staticDragData.cols, relativePos);
2770
+ const newPosition = dimension_helpers.getItemByPosition(this.staticDragData.cols, relativePos + (this.staticDragData.cols.renderOffset || 0));
2638
2771
  const store = this.providers.column.stores[this.dragData.type].store;
2639
2772
  const source = store.get('source');
2640
2773
  const newItems = [...store.get('items')];
@@ -2717,5 +2850,7 @@ exports.filterTypes = filterTypes;
2717
2850
  exports.getComparer = getComparer;
2718
2851
  exports.getLeftRelative = getLeftRelative;
2719
2852
  exports.getNextOrder = getNextOrder;
2853
+ exports.getSortingIndex = getSortingIndex;
2854
+ exports.hasActiveSorting = hasActiveSorting;
2720
2855
  exports.isStretchPlugin = isStretchPlugin;
2721
2856
  exports.sortIndexByItems = sortIndexByItems;