@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
@@ -1,14 +1,30 @@
1
1
  /*!
2
2
  * Built by Revolist OU ❤️
3
3
  */
4
- import { J as reduce, g as getRange, K as baseEach, C as getColumnType, c as columnTypes, L as toInteger, u as isGrouping, t as getGroupingName, r as rowTypes, B as getCellDataParsed, A as getCellRaw, I as getColumnByProp, h as GROUP_EXPANDED, x as getParsedGroup, y as isSameGroup, G as GROUP_DEPTH, e as PSEUDO_GROUP_ITEM_VALUE, d as PSEUDO_GROUP_ITEM_ID, o as GROUPING_ROW_TYPE, p as getSource, f as PSEUDO_GROUP_COLUMN, s as gatherGrouping, m as GROUP_EXPAND_EVENT, v as isGroupingColumn, q as getExpanded, E as isColGrouping } from './column.service-CCvAi5l4.js';
5
- import { W as createStore, w as setStore, i as calculateDimensionData, X as identity, Y as isArray, b as getSourceItem, o as getScrollbarSize, u as timeout, Z as baseProperty, _ as isArrayLike, $ as getTag, a0 as baseKeys, g as getPhysical, e as setItems, j as getItemByPosition } from './dimension.helpers-DmIvjIa7.js';
6
- import { f as calculateRowHeaderSize } from './viewport.store-CFjDW-3l.js';
4
+ import { J as reduce, g as getRange, K as baseEach, C as getColumnType, c as columnTypes, L as toInteger, u as isGrouping, t as getGroupingName, r as rowTypes, B as getCellDataParsed, A as getCellRaw, j as GROUP_COLUMN_PROP, I as getColumnByProp, h as GROUP_EXPANDED, x as getParsedGroup, y as isSameGroup, G as GROUP_DEPTH, e as PSEUDO_GROUP_ITEM_VALUE, d as PSEUDO_GROUP_ITEM_ID, o as GROUPING_ROW_TYPE, p as getSource, f as PSEUDO_GROUP_COLUMN, s as gatherGrouping, m as GROUP_EXPAND_EVENT, v as isGroupingColumn, q as getExpanded, E as isColGrouping } from './column.service-DbpulTog.js';
5
+ import { K as createStore, l as setStore, i as calculateDimensionData, L as identity, N as isArray, b as getSourceItem, g as getPhysical, e as setItems, j as getItemByPosition } from './dimension.helpers-CGKwSvw6.js';
6
+ import { j as calculateRowHeaderSize } from './viewport.store-COAfzAyu.js';
7
+ import { g as getScrollbarSize, t as timeout } from './index-Db3qZoW5.js';
7
8
  import { h } from './index-Chp_81rd.js';
8
9
  import { b as FILTER_PROP, i as isFilterBtn } from './filter.button-C8XTWPU2.js';
9
- import { i as isObjectLike, b as baseGetTag, d as debounce } from './debounce-BfO9dz9v.js';
10
- import { O as ON_COLUMN_CLICK, d as dispatch } from './header-cell-renderer-DU8wKAbg.js';
10
+ import { d as debounce } from './debounce-PCRWZliA.js';
11
+ import { O as ON_COLUMN_CLICK, d as dispatch } from './header-cell-renderer-DGI2FAD8.js';
11
12
 
13
+ function calculateRealSize({ count, originItemSize, sizes, }) {
14
+ const safeCount = Math.max(0, count);
15
+ let realSize = safeCount * originItemSize;
16
+ for (let index in sizes) {
17
+ const itemIndex = Number(index);
18
+ if (!Number.isInteger(itemIndex) ||
19
+ itemIndex < 0 ||
20
+ itemIndex >= safeCount ||
21
+ String(itemIndex) !== index) {
22
+ continue;
23
+ }
24
+ realSize += sizes[index] - originItemSize;
25
+ }
26
+ return realSize;
27
+ }
12
28
  /**
13
29
  * Plugin which recalculates realSize on changes of sizes, originItemSize and count
14
30
  */
@@ -21,20 +37,18 @@ const recalculateRealSizePlugin = (storeService) => {
21
37
  * Reacts on changes of count, sizes and originItemSize
22
38
  */
23
39
  set(k) {
24
- var _a;
25
40
  switch (k) {
26
41
  case 'count':
27
42
  case 'sizes':
28
43
  case 'originItemSize': {
29
44
  // recalculate realSize
30
- let realSize = 0;
31
- const count = storeService.store.get('count');
32
- const sizes = storeService.store.get('sizes');
33
- const originItemSize = storeService.store.get('originItemSize');
34
- for (let i = 0; i < count; i++) {
35
- realSize += (_a = sizes[i]) !== null && _a !== void 0 ? _a : originItemSize;
36
- }
37
- storeService.setStore({ realSize });
45
+ storeService.setStore({
46
+ realSize: calculateRealSize({
47
+ count: storeService.store.get('count'),
48
+ sizes: storeService.store.get('sizes'),
49
+ originItemSize: storeService.store.get('originItemSize'),
50
+ }),
51
+ });
38
52
  break;
39
53
  }
40
54
  }
@@ -124,7 +138,9 @@ function initialState() {
124
138
  // size which all items can take
125
139
  realSize: 0,
126
140
  // initial item size if it wasn't changed
127
- originItemSize: 0
141
+ originItemSize: 0,
142
+ // logical-to-physical render offset used when scroll space is compressed
143
+ renderOffset: 0
128
144
  });
129
145
  }
130
146
  class DimensionStore {
@@ -156,7 +172,7 @@ class DimensionStore {
156
172
  setStore(this.store, data);
157
173
  }
158
174
  drop() {
159
- setStore(this.store, initialBase());
175
+ setStore(this.store, Object.assign(Object.assign({}, initialBase()), { renderOffset: 0 }));
160
176
  }
161
177
  /**
162
178
  * Set custom dimension sizes and overwrite old
@@ -1358,17 +1374,24 @@ class FilterPlugin extends BasePlugin {
1358
1374
  }
1359
1375
  }
1360
1376
  if (config.collection) {
1361
- const filtersWithFilterFunctionPresent = Object.entries(config.collection).filter(([, item]) => this.filterFunctionsIndexedByType[item.type]);
1362
- this.filterCollection = Object.fromEntries(filtersWithFilterFunctionPresent);
1377
+ const filterCollection = {};
1378
+ for (const prop of Object.keys(config.collection)) {
1379
+ const item = config.collection[prop];
1380
+ if (this.filterFunctionsIndexedByType[item.type]) {
1381
+ filterCollection[prop] = item;
1382
+ }
1383
+ }
1384
+ this.filterCollection = filterCollection;
1363
1385
  }
1364
1386
  else {
1365
1387
  this.filterCollection = {};
1366
1388
  }
1367
1389
  if (config.localization) {
1368
1390
  if (config.localization.filterNames) {
1369
- Object.entries(config.localization.filterNames).forEach(([k, v]) => {
1391
+ const filterNames = config.localization.filterNames;
1392
+ Object.keys(filterNames).forEach((k) => {
1370
1393
  if (this.filterNameIndexByType[k] != void 0) {
1371
- this.filterNameIndexByType[k] = v;
1394
+ this.filterNameIndexByType[k] = filterNames[k];
1372
1395
  }
1373
1396
  });
1374
1397
  }
@@ -1598,165 +1621,174 @@ function allAndConditionsSatisfied(pendingResults) {
1598
1621
  return !pendingResults.includes(true);
1599
1622
  }
1600
1623
 
1601
- /** `Object#toString` result references. */
1602
- var stringTag = '[object String]';
1603
-
1604
1624
  /**
1605
- * Checks if `value` is classified as a `String` primitive or object.
1606
- *
1607
- * @static
1608
- * @since 0.1.0
1609
- * @memberOf _
1610
- * @category Lang
1611
- * @param {*} value The value to check.
1612
- * @returns {boolean} Returns `true` if `value` is a string, else `false`.
1613
- * @example
1614
- *
1615
- * _.isString('abc');
1616
- * // => true
1625
+ * Checks whether a sorting map contains at least one active order.
1617
1626
  *
1618
- * _.isString(1);
1619
- * // => false
1627
+ * Empty maps and properties with `undefined` order are treated as inactive.
1620
1628
  */
1621
- function isString(value) {
1622
- return typeof value == 'string' ||
1623
- (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
1629
+ function hasActiveSorting(sorting) {
1630
+ for (const prop of Object.keys(sorting || {})) {
1631
+ if (sorting === null || sorting === void 0 ? void 0 : sorting[prop]) {
1632
+ return true;
1633
+ }
1634
+ }
1635
+ return false;
1624
1636
  }
1625
-
1626
1637
  /**
1627
- * Gets the size of an ASCII `string`.
1628
- *
1629
- * @private
1630
- * @param {string} string The string inspect.
1631
- * @returns {number} Returns the string size.
1638
+ * Compares column properties after object-key coercion.
1632
1639
  */
1633
- var asciiSize = baseProperty('length');
1634
-
1635
- /** Used to compose unicode character classes. */
1636
- var rsAstralRange$1 = '\\ud800-\\udfff',
1637
- rsComboMarksRange$1 = '\\u0300-\\u036f',
1638
- reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f',
1639
- rsComboSymbolsRange$1 = '\\u20d0-\\u20ff',
1640
- rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1,
1641
- rsVarRange$1 = '\\ufe0e\\ufe0f';
1642
-
1643
- /** Used to compose unicode capture groups. */
1644
- var rsZWJ$1 = '\\u200d';
1645
-
1646
- /** 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/). */
1647
- var reHasUnicode = RegExp('[' + rsZWJ$1 + rsAstralRange$1 + rsComboRange$1 + rsVarRange$1 + ']');
1648
-
1640
+ function isSameColumnProp(a, b) {
1641
+ return String(a) === String(b);
1642
+ }
1649
1643
  /**
1650
- * Checks if `string` contains Unicode symbols.
1651
- *
1652
- * @private
1653
- * @param {string} string The string to inspect.
1654
- * @returns {boolean} Returns `true` if a symbol is found, else `false`.
1644
+ * Returns active sorting properties in explicit priority order.
1655
1645
  */
1656
- function hasUnicode(string) {
1657
- return reHasUnicode.test(string);
1646
+ function getActiveSortingProps(sorting, sortingOrder) {
1647
+ const activeProps = [];
1648
+ const add = (prop) => {
1649
+ if ((sorting === null || sorting === void 0 ? void 0 : sorting[prop]) && !activeProps.some(active => isSameColumnProp(active, prop))) {
1650
+ activeProps.push(prop);
1651
+ }
1652
+ };
1653
+ sortingOrder === null || sortingOrder === void 0 ? void 0 : sortingOrder.forEach(add);
1654
+ Object.keys(sorting || {}).forEach(add);
1655
+ return activeProps;
1658
1656
  }
1659
-
1660
- /** Used to compose unicode character classes. */
1661
- var rsAstralRange = '\\ud800-\\udfff',
1662
- rsComboMarksRange = '\\u0300-\\u036f',
1663
- reComboHalfMarksRange = '\\ufe20-\\ufe2f',
1664
- rsComboSymbolsRange = '\\u20d0-\\u20ff',
1665
- rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
1666
- rsVarRange = '\\ufe0e\\ufe0f';
1667
-
1668
- /** Used to compose unicode capture groups. */
1669
- var rsAstral = '[' + rsAstralRange + ']',
1670
- rsCombo = '[' + rsComboRange + ']',
1671
- rsFitz = '\\ud83c[\\udffb-\\udfff]',
1672
- rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
1673
- rsNonAstral = '[^' + rsAstralRange + ']',
1674
- rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
1675
- rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
1676
- rsZWJ = '\\u200d';
1677
-
1678
- /** Used to compose unicode regexes. */
1679
- var reOptMod = rsModifier + '?',
1680
- rsOptVar = '[' + rsVarRange + ']?',
1681
- rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
1682
- rsSeq = rsOptVar + reOptMod + rsOptJoin,
1683
- rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
1684
-
1685
- /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
1686
- var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
1687
-
1688
1657
  /**
1689
- * Gets the size of a Unicode `string`.
1658
+ * Returns one-based additive sorting rank for a column.
1690
1659
  *
1691
- * @private
1692
- * @param {string} string The string inspect.
1693
- * @returns {number} Returns the string size.
1660
+ * A single active sort does not need a visible rank, so it returns undefined.
1694
1661
  */
1695
- function unicodeSize(string) {
1696
- var result = reUnicode.lastIndex = 0;
1697
- while (reUnicode.test(string)) {
1698
- ++result;
1699
- }
1700
- return result;
1662
+ function getSortingIndex(sorting, prop, sortingOrder) {
1663
+ const activeProps = getActiveSortingProps(sorting, sortingOrder);
1664
+ if (activeProps.length <= 1) {
1665
+ return undefined;
1666
+ }
1667
+ const index = activeProps.findIndex(active => isSameColumnProp(active, prop));
1668
+ return index >= 0 ? index + 1 : undefined;
1701
1669
  }
1702
-
1703
1670
  /**
1704
- * Gets the number of symbols in `string`.
1671
+ * Collects only active comparator functions from a sorting function map.
1705
1672
  *
1706
- * @private
1707
- * @param {string} string The string to inspect.
1708
- * @returns {number} Returns the string size.
1673
+ * This keeps undefined comparator entries from triggering sorting work.
1674
+ */
1675
+ function activeSortingEntries(sortingFunc = {}, sortingOrder) {
1676
+ const entries = [];
1677
+ const add = (prop) => {
1678
+ const cmp = sortingFunc[prop];
1679
+ if (typeof cmp === 'function' && !entries.some(([active]) => isSameColumnProp(active, prop))) {
1680
+ entries.push([prop, cmp]);
1681
+ }
1682
+ };
1683
+ sortingOrder === null || sortingOrder === void 0 ? void 0 : sortingOrder.forEach(add);
1684
+ Object.keys(sortingFunc).forEach(add);
1685
+ return entries;
1686
+ }
1687
+ /**
1688
+ * Reads and normalizes a value for the built-in default comparer.
1709
1689
  */
1710
- function stringSize(string) {
1711
- return hasUnicode(string)
1712
- ? unicodeSize(string)
1713
- : asciiSize(string);
1690
+ function getDefaultCompareValue(item, prop, column) {
1691
+ const aRaw = column ? getCellRaw(item, column) : item === null || item === void 0 ? void 0 : item[prop];
1692
+ return typeof aRaw === 'number' ? aRaw : aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
1693
+ }
1694
+ function isEmptyCompareValue(value) {
1695
+ return value === '' || value === null || value === undefined;
1714
1696
  }
1715
-
1716
- /** `Object#toString` result references. */
1717
- var mapTag = '[object Map]',
1718
- setTag = '[object Set]';
1719
-
1720
1697
  /**
1721
- * Gets the size of `collection` by returning its length for array-like
1722
- * values or the number of own enumerable string keyed properties for objects.
1723
- *
1724
- * @static
1725
- * @memberOf _
1726
- * @since 0.1.0
1727
- * @category Collection
1728
- * @param {Array|Object|string} collection The collection to inspect.
1729
- * @returns {number} Returns the collection size.
1730
- * @example
1731
- *
1732
- * _.size([1, 2, 3]);
1733
- * // => 3
1698
+ * Compares two already-normalized default comparer values.
1699
+ */
1700
+ function compareValues(av, bv) {
1701
+ if (av === bv) {
1702
+ return 0;
1703
+ }
1704
+ const aEmpty = isEmptyCompareValue(av);
1705
+ const bEmpty = isEmptyCompareValue(bv);
1706
+ if (aEmpty || bEmpty) {
1707
+ if (aEmpty && bEmpty) {
1708
+ return 0;
1709
+ }
1710
+ return aEmpty ? -1 : 1;
1711
+ }
1712
+ if (av > bv) {
1713
+ return 1;
1714
+ }
1715
+ return -1;
1716
+ }
1717
+ /**
1718
+ * Sorts indexes by precomputed values for default column comparers.
1734
1719
  *
1735
- * _.size({ 'a': 1, 'b': 2 });
1736
- * // => 2
1720
+ * This avoids repeatedly parsing the same cell value during large default
1721
+ * sorts while preserving normal multi-column ordering.
1722
+ */
1723
+ function sortIndexByDefaultComparers(indexes, source, entries, sorting, sortingColumns) {
1724
+ const prepared = entries.map(([prop]) => {
1725
+ const values = [];
1726
+ const column = sortingColumns[prop];
1727
+ for (const index of indexes) {
1728
+ values[index] = getDefaultCompareValue(source[index], prop, column);
1729
+ }
1730
+ return {
1731
+ order: sorting[prop],
1732
+ values,
1733
+ };
1734
+ });
1735
+ return indexes.sort((a, b) => {
1736
+ for (const { order, values } of prepared) {
1737
+ const sorted = compareValues(values[a], values[b]);
1738
+ if (sorted) {
1739
+ return order === 'desc' ? -sorted : sorted;
1740
+ }
1741
+ }
1742
+ return 0;
1743
+ });
1744
+ }
1745
+ /**
1746
+ * Detects whether the optimized default-comparer path can be used.
1737
1747
  *
1738
- * _.size('pebbles');
1739
- * // => 7
1748
+ * Grouped rows and custom `cellCompare` functions stay on the legacy
1749
+ * comparator path to preserve their exact behavior.
1740
1750
  */
1741
- function size(collection) {
1742
- if (collection == null) {
1743
- return 0;
1744
- }
1745
- if (isArrayLike(collection)) {
1746
- return isString(collection) ? stringSize(collection) : collection.length;
1747
- }
1748
- var tag = getTag(collection);
1749
- if (tag == mapTag || tag == setTag) {
1750
- return collection.size;
1751
- }
1752
- return baseKeys(collection).length;
1751
+ function canUseDefaultCompareFastPath(entries, indexes, source, sorting, sortingColumns) {
1752
+ return !indexes.some(index => isGrouping(source[index])) && !!sorting && !!sortingColumns && entries.every(([prop]) => {
1753
+ const order = sorting[prop];
1754
+ const column = sortingColumns[prop];
1755
+ return !!order && !(column === null || column === void 0 ? void 0 : column.cellCompare);
1756
+ });
1753
1757
  }
1754
-
1755
- function sortIndexByItems(indexes, source, sortingFunc = {}) {
1758
+ /**
1759
+ * Group placeholder rows are generated for their grouping column. If sorting is
1760
+ * requested for another column, the grouped source must be unwrapped first.
1761
+ */
1762
+ function hasGroupingRowsForOtherSorting(entries, indexes, source) {
1763
+ return indexes.some(index => {
1764
+ const item = source[index];
1765
+ return isGrouping(item) && !entries.some(([prop]) => isSameColumnProp(item[GROUP_COLUMN_PROP], prop));
1766
+ });
1767
+ }
1768
+ /**
1769
+ * Sorts row indexes against a source collection.
1770
+ *
1771
+ * @param indexes - Current proxy row indexes to sort.
1772
+ * @param source - Full source collection addressed by the indexes.
1773
+ * @param sortingFunc - Comparator functions by column property.
1774
+ * @param sorting - Active sorting order by column property.
1775
+ * @param sortingColumns - Column metadata by property for default-comparer optimization.
1776
+ * @param sortingOrder - Active sorting priority in click/config insertion order.
1777
+ * @returns Sorted proxy indexes. With no sorting function keys, returns source-order indexes.
1778
+ */
1779
+ function sortIndexByItems(indexes, source, sortingFunc = {}, sorting, sortingColumns, sortingOrder) {
1780
+ const hasSortingKeys = Object.keys(sortingFunc).length > 0;
1781
+ const sortingEntries = activeSortingEntries(sortingFunc, sortingOrder);
1756
1782
  // if no sorting - return unsorted indexes
1757
- if (Object.entries(sortingFunc).length === 0) {
1783
+ if (sortingEntries.length === 0) {
1758
1784
  // Unsorted indexes
1759
- return [...Array(indexes.length).keys()];
1785
+ return hasSortingKeys ? indexes : [...new Array(indexes.length).keys()];
1786
+ }
1787
+ if (hasGroupingRowsForOtherSorting(sortingEntries, indexes, source)) {
1788
+ return indexes;
1789
+ }
1790
+ if (canUseDefaultCompareFastPath(sortingEntries, indexes, source, sorting, sortingColumns)) {
1791
+ return sortIndexByDefaultComparers(indexes, source, sortingEntries, sorting, sortingColumns);
1760
1792
  }
1761
1793
  //
1762
1794
  /**
@@ -1766,15 +1798,15 @@ function sortIndexByItems(indexes, source, sortingFunc = {}) {
1766
1798
  return indexes.sort((a, b) => {
1767
1799
  const itemA = source[a];
1768
1800
  const itemB = source[b];
1769
- for (const [prop, cmp] of Object.entries(sortingFunc)) {
1801
+ for (const [prop, cmp] of sortingEntries) {
1770
1802
  if (isGrouping(itemA)) {
1771
- if (itemA['__rvgr-prop'] !== prop) {
1772
- return 0;
1803
+ if (!isSameColumnProp(itemA[GROUP_COLUMN_PROP], prop)) {
1804
+ return a - b;
1773
1805
  }
1774
1806
  }
1775
1807
  if (isGrouping(itemB)) {
1776
- if (itemB['__rvgr-prop'] !== prop) {
1777
- return 0;
1808
+ if (!isSameColumnProp(itemB[GROUP_COLUMN_PROP], prop)) {
1809
+ return a - b;
1778
1810
  }
1779
1811
  }
1780
1812
  /**
@@ -1794,13 +1826,7 @@ function defaultCellCompare(prop, a, b) {
1794
1826
  const bRaw = this.column ? getCellRaw(b, this.column) : b === null || b === void 0 ? void 0 : b[prop];
1795
1827
  const av = typeof aRaw === 'number' ? aRaw : aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
1796
1828
  const bv = typeof bRaw === 'number' ? bRaw : bRaw === null || bRaw === void 0 ? void 0 : bRaw.toString().toLowerCase();
1797
- if (av === bv) {
1798
- return 0;
1799
- }
1800
- if (av > bv) {
1801
- return 1;
1802
- }
1803
- return -1;
1829
+ return compareValues(av, bv);
1804
1830
  }
1805
1831
  function descCellCompare(cmp) {
1806
1832
  return (prop, a, b) => {
@@ -1829,6 +1855,21 @@ function getComparer(column, order) {
1829
1855
  return undefined;
1830
1856
  }
1831
1857
 
1858
+ function getSortableRowIndexes(indexes, source) {
1859
+ return indexes.filter(index => !isGrouping(source[index]));
1860
+ }
1861
+ function mergeSortedRowsWithGroups(indexes, source, sortedRows) {
1862
+ if (sortedRows.length === indexes.length) {
1863
+ return sortedRows;
1864
+ }
1865
+ let rowIndex = 0;
1866
+ return indexes.map(index => {
1867
+ if (isGrouping(source[index])) {
1868
+ return index;
1869
+ }
1870
+ return sortedRows[rowIndex++];
1871
+ });
1872
+ }
1832
1873
  /**
1833
1874
  * Lifecycle
1834
1875
  * 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.
@@ -1843,54 +1884,37 @@ class SortingPlugin extends BasePlugin {
1843
1884
  super(revogrid, providers);
1844
1885
  this.revogrid = revogrid;
1845
1886
  /**
1846
- * Delayed sorting promise
1887
+ * Delayed sorting promise registered in the grid render job queue.
1847
1888
  */
1848
1889
  this.sortingPromise = null;
1849
1890
  /**
1850
- * We need to sort only so often
1891
+ * Debounced sorting entry point.
1892
+ *
1893
+ * Sorting can be requested by column changes, source changes, and header
1894
+ * clicks in quick succession, so the actual sort is delayed and coalesced.
1851
1895
  */
1852
- this.postponeSort = debounce((order, comparison, ignoreViewportUpdate) => this.runSorting(order, comparison, ignoreViewportUpdate), 50);
1853
- const setConfig = (cfg) => {
1854
- var _a;
1855
- if (cfg) {
1856
- const sortingFunc = {};
1857
- const order = {};
1858
- (_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
1859
- sortingFunc[col.prop] = getComparer(col, col.order);
1860
- order[col.prop] = col.order;
1861
- });
1862
- if (cfg.additive) {
1863
- this.sorting = Object.assign(Object.assign({}, this.sorting), order);
1864
- this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
1865
- }
1866
- else {
1867
- // // set sorting
1868
- this.sorting = order;
1869
- this.sortingFunc = sortingFunc;
1870
- }
1871
- }
1872
- };
1873
- setConfig(config);
1896
+ this.postponeSort = debounce((order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) => this.runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate), 50);
1897
+ this.applySortingConfig(config);
1874
1898
  this.addEventListener('sortingconfigchanged', ({ detail }) => {
1875
1899
  config = detail;
1876
- setConfig(detail);
1877
- this.startSorting(this.sorting, this.sortingFunc);
1900
+ this.applySortingConfig(detail);
1901
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
1878
1902
  });
1879
1903
  this.addEventListener('beforeheaderrender', ({ detail, }) => {
1880
1904
  var _a;
1881
1905
  const { data: column } = detail;
1882
1906
  if (column.sortable) {
1883
- detail.data = Object.assign(Object.assign({}, column), { order: (_a = this.sorting) === null || _a === void 0 ? void 0 : _a[column.prop] });
1907
+ 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) });
1884
1908
  }
1885
1909
  });
1886
1910
  this.addEventListener('beforeanysource', ({ detail: { type }, }) => {
1887
1911
  // if sorting was provided - sort data
1888
- if (!!this.sorting && this.sortingFunc) {
1912
+ if (hasActiveSorting(this.sorting) && this.sortingFunc) {
1889
1913
  const event = this.emit('beforesourcesortingapply', { type, sorting: this.sorting });
1890
1914
  if (event.defaultPrevented) {
1891
1915
  return;
1892
1916
  }
1893
- this.startSorting(this.sorting, this.sortingFunc);
1917
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
1894
1918
  }
1895
1919
  });
1896
1920
  this.addEventListener('aftercolumnsset', ({ detail: { order }, }) => {
@@ -1900,13 +1924,24 @@ class SortingPlugin extends BasePlugin {
1900
1924
  }
1901
1925
  const columns = this.providers.column.getColumns();
1902
1926
  const sortingFunc = {};
1927
+ const sortingColumns = {};
1928
+ const sortingOrder = [];
1929
+ const sorting = {};
1903
1930
  for (let prop in order) {
1904
- const cmp = getComparer(getColumnByProp(columns, prop), order[prop]);
1905
- sortingFunc[prop] = cmp;
1931
+ if (order[prop]) {
1932
+ const column = getColumnByProp(columns, prop);
1933
+ const cmp = getComparer(column, order[prop]);
1934
+ sorting[prop] = order[prop];
1935
+ sortingFunc[prop] = cmp;
1936
+ sortingColumns[prop] = column;
1937
+ sortingOrder.push(prop);
1938
+ }
1906
1939
  }
1907
1940
  // set sorting
1908
- this.sorting = order;
1909
- this.sortingFunc = order && sortingFunc;
1941
+ this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
1942
+ this.sortingFunc = this.sorting ? sortingFunc : undefined;
1943
+ this.sortingColumns = this.sorting ? sortingColumns : undefined;
1944
+ this.sortingOrder = this.sorting ? sortingOrder : undefined;
1910
1945
  });
1911
1946
  this.addEventListener('beforeheaderclick', (e) => {
1912
1947
  var _a, _b, _c, _d;
@@ -1920,23 +1955,89 @@ class SortingPlugin extends BasePlugin {
1920
1955
  });
1921
1956
  }
1922
1957
  /**
1923
- * Entry point for sorting, waits for all delays, registers jobs
1958
+ * Creates mutable sorting maps from current state when additive sorting is requested.
1959
+ */
1960
+ createSortingState(additive) {
1961
+ var _a;
1962
+ return {
1963
+ sorting: additive ? Object.assign({}, this.sorting) : {},
1964
+ sortingFunc: additive ? Object.assign({}, this.sortingFunc) : {},
1965
+ sortingColumns: additive ? Object.assign({}, this.sortingColumns) : {},
1966
+ sortingOrder: additive ? [...((_a = this.sortingOrder) !== null && _a !== void 0 ? _a : [])] : [],
1967
+ };
1968
+ }
1969
+ /**
1970
+ * Stores normalized sorting state, clearing inactive empty maps.
1971
+ */
1972
+ setSortingState({ sorting, sortingFunc, sortingColumns, sortingOrder, }) {
1973
+ this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
1974
+ this.sortingFunc = this.sorting ? sortingFunc : undefined;
1975
+ this.sortingColumns = this.sorting ? sortingColumns : undefined;
1976
+ this.sortingOrder = this.sorting ? sortingOrder : undefined;
1977
+ }
1978
+ /**
1979
+ * Adds or replaces a column in a sorting state.
1924
1980
  */
1925
- startSorting(order, sortingFunc, ignoreViewportUpdate) {
1981
+ setColumnSorting(state, prop, order, cmp, column) {
1982
+ state.sorting[prop] = order;
1983
+ state.sortingFunc[prop] = cmp;
1984
+ state.sortingColumns[prop] = column;
1985
+ if (!state.sortingOrder.some(sortingProp => String(sortingProp) === String(prop))) {
1986
+ state.sortingOrder.push(prop);
1987
+ }
1988
+ }
1989
+ /**
1990
+ * Removes a column from a sorting state.
1991
+ */
1992
+ clearColumnSorting(state, prop) {
1993
+ delete state.sorting[prop];
1994
+ delete state.sortingFunc[prop];
1995
+ delete state.sortingColumns[prop];
1996
+ const index = state.sortingOrder.findIndex(sortingProp => String(sortingProp) === String(prop));
1997
+ if (index >= 0) {
1998
+ state.sortingOrder.splice(index, 1);
1999
+ }
2000
+ }
2001
+ /**
2002
+ * Normalizes external sorting configuration into internal order,
2003
+ * comparator, and column metadata maps.
2004
+ */
2005
+ applySortingConfig(cfg) {
2006
+ var _a;
2007
+ if (!cfg) {
2008
+ return;
2009
+ }
2010
+ const state = this.createSortingState(cfg.additive);
2011
+ (_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
2012
+ if (col.order) {
2013
+ this.setColumnSorting(state, col.prop, col.order, getComparer(col, col.order), col);
2014
+ return;
2015
+ }
2016
+ this.clearColumnSorting(state, col.prop);
2017
+ });
2018
+ this.setSortingState(state);
2019
+ }
2020
+ startSorting(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate) {
1926
2021
  if (!this.sortingPromise) {
1927
2022
  // add job before render
1928
2023
  this.revogrid.jobsBeforeRender.push(new Promise(resolve => {
1929
2024
  this.sortingPromise = resolve;
1930
2025
  }));
1931
2026
  }
1932
- this.postponeSort(order, sortingFunc, ignoreViewportUpdate);
2027
+ if (typeof sortingColumns === 'boolean') {
2028
+ this.postponeSort(order, sortingFunc, undefined, undefined, sortingColumns);
2029
+ return;
2030
+ }
2031
+ this.postponeSort(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate);
1933
2032
  }
1934
2033
  /**
1935
- * Apply sorting to data on header click
1936
- * If additive - add to existing sorting, multiple columns can be sorted
2034
+ * Applies sorting requested by a sortable header click.
2035
+ *
2036
+ * @param column - Column that initiated sorting.
2037
+ * @param additive - If true, add/remove this column from the current multi-sort state.
1937
2038
  */
1938
2039
  headerclick(column, additive) {
1939
- var _a, _b, _c;
2040
+ var _a;
1940
2041
  const columnProp = column.prop;
1941
2042
  let order = getNextOrder((_a = this.sorting) === null || _a === void 0 ? void 0 : _a[columnProp]);
1942
2043
  const beforeEvent = this.emit('beforesorting', { column, order, additive });
@@ -1954,52 +2055,59 @@ class SortingPlugin extends BasePlugin {
1954
2055
  return;
1955
2056
  }
1956
2057
  const cmp = getComparer(beforeApplyEvent.detail.column, beforeApplyEvent.detail.order);
1957
- if (beforeApplyEvent.detail.additive && this.sorting) {
1958
- const sorting = {};
1959
- const sortingFunc = {};
1960
- if (columnProp in sorting && size(sorting) > 1 && order === undefined) {
1961
- delete sorting[columnProp];
1962
- delete sortingFunc[columnProp];
1963
- }
1964
- else {
1965
- sorting[columnProp] = order;
1966
- sortingFunc[columnProp] = cmp;
1967
- }
1968
- this.sorting = Object.assign(Object.assign({}, this.sorting), sorting);
1969
- // extend sorting function with new sorting for multiple columns sorting
1970
- this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
2058
+ this.applyHeaderSorting(beforeApplyEvent.detail.column, beforeApplyEvent.detail.additive, order, cmp);
2059
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
2060
+ }
2061
+ /**
2062
+ * Applies sorting state produced by a header click.
2063
+ */
2064
+ applyHeaderSorting(column, additive, order, cmp) {
2065
+ if (!additive) {
2066
+ this.setSortingState(order ? {
2067
+ sorting: { [column.prop]: order },
2068
+ sortingFunc: { [column.prop]: cmp },
2069
+ sortingColumns: { [column.prop]: column },
2070
+ sortingOrder: [column.prop],
2071
+ } : this.createSortingState());
2072
+ return;
2073
+ }
2074
+ const state = this.createSortingState(true);
2075
+ if (order) {
2076
+ this.setColumnSorting(state, column.prop, order, cmp, column);
1971
2077
  }
1972
2078
  else {
1973
- if (order) {
1974
- // reset sorting
1975
- this.sorting = { [columnProp]: order };
1976
- this.sortingFunc = { [columnProp]: cmp };
1977
- }
1978
- else {
1979
- (_b = this.sorting) === null || _b === void 0 ? true : delete _b[columnProp];
1980
- (_c = this.sortingFunc) === null || _c === void 0 ? true : delete _c[columnProp];
1981
- }
2079
+ this.clearColumnSorting(state, column.prop);
1982
2080
  }
1983
- this.startSorting(this.sorting, this.sortingFunc);
2081
+ this.setSortingState(state);
1984
2082
  }
1985
- runSorting(order, comparison, ignoreViewportUpdate) {
1986
- var _a;
1987
- this.sort(order, comparison, undefined, ignoreViewportUpdate);
1988
- (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
2083
+ runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) {
2084
+ var _a, _b;
2085
+ if (typeof sortingColumns === 'boolean') {
2086
+ this.sort(order, comparison, undefined, undefined, undefined, sortingColumns);
2087
+ (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
2088
+ this.sortingPromise = null;
2089
+ return;
2090
+ }
2091
+ this.sort(order, comparison, sortingColumns, sortingOrder, undefined, ignoreViewportUpdate);
2092
+ (_b = this.sortingPromise) === null || _b === void 0 ? void 0 : _b.call(this);
1989
2093
  this.sortingPromise = null;
1990
2094
  }
1991
- /**
1992
- * Sort items by sorting function
1993
- * @requires proxyItems applied to row store
1994
- * @requires source applied to row store
1995
- *
1996
- * @param sorting - per column sorting
1997
- * @param data - this.stores['rgRow'].store.get('source')
1998
- */
1999
- sort(sorting, sortingFunc, types = rowTypes, ignoreViewportUpdate = false) {
2095
+ sort(sorting, sortingFunc, sortingColumns, sortingOrder, types = rowTypes, ignoreViewportUpdate = false) {
2096
+ let activeSortingColumns;
2097
+ let activeSortingOrder;
2098
+ let activeTypes = types;
2099
+ let activeIgnoreViewportUpdate = ignoreViewportUpdate;
2100
+ if (Array.isArray(sortingColumns)) {
2101
+ activeTypes = sortingColumns;
2102
+ activeIgnoreViewportUpdate = typeof sortingOrder === 'boolean' ? sortingOrder : false;
2103
+ }
2104
+ else {
2105
+ activeSortingColumns = sortingColumns;
2106
+ activeSortingOrder = Array.isArray(sortingOrder) ? sortingOrder : undefined;
2107
+ }
2000
2108
  // if no sorting - reset
2001
2109
  if (!Object.keys(sorting || {}).length) {
2002
- for (let type of types) {
2110
+ for (let type of activeTypes) {
2003
2111
  const storeService = this.providers.data.stores[type];
2004
2112
  // row data
2005
2113
  const source = storeService.store.get('source');
@@ -2008,26 +2116,27 @@ class SortingPlugin extends BasePlugin {
2008
2116
  // row indexes
2009
2117
  const newItemsOrder = Array.from({ length: source.length }, (_, i) => i); // recover indexes range(0, source.length)
2010
2118
  this.providers.dimension.updateSizesPositionByNewDataIndexes(type, newItemsOrder, proxyItems);
2011
- storeService.setData({ proxyItems: newItemsOrder, source: [...source], });
2119
+ storeService.setData({ proxyItems: newItemsOrder });
2012
2120
  }
2013
2121
  }
2014
2122
  else {
2015
- for (let type of types) {
2123
+ for (let type of activeTypes) {
2016
2124
  const storeService = this.providers.data.stores[type];
2017
2125
  // row data
2018
2126
  const source = storeService.store.get('source');
2019
2127
  // row indexes
2020
2128
  const proxyItems = storeService.store.get('proxyItems');
2021
- const newItemsOrder = sortIndexByItems([...proxyItems], source, sortingFunc);
2129
+ const sortItems = getSortableRowIndexes(proxyItems, source);
2130
+ const sortedItems = sortIndexByItems([...sortItems], source, sortingFunc, sorting, activeSortingColumns, activeSortingOrder);
2131
+ const newItemsOrder = mergeSortedRowsWithGroups(proxyItems, source, sortedItems);
2022
2132
  // take row indexes before trim applied and proxy items
2023
2133
  const prevItems = storeService.store.get('items');
2024
2134
  storeService.setData({
2025
2135
  proxyItems: newItemsOrder,
2026
- source: [...source],
2027
2136
  });
2028
2137
  // take currently visible row indexes
2029
2138
  const newItems = storeService.store.get('items');
2030
- if (!ignoreViewportUpdate) {
2139
+ if (!activeIgnoreViewportUpdate) {
2031
2140
  this.providers.dimension
2032
2141
  .updateSizesPositionByNewDataIndexes(type, newItems, prevItems);
2033
2142
  }
@@ -2219,6 +2328,18 @@ function filterOutEmptyGroupRows(source, filterTrimmed) {
2219
2328
  return trimmed;
2220
2329
  }
2221
2330
 
2331
+ var __rest = (undefined && undefined.__rest) || function (s, e) {
2332
+ var t = {};
2333
+ for (var p in s)
2334
+ if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
2335
+ t[p] = s[p];
2336
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
2337
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
2338
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
2339
+ t[p[i]] = s[p[i]];
2340
+ }
2341
+ return t;
2342
+ };
2222
2343
  class GroupingRowPlugin extends BasePlugin {
2223
2344
  getStore(type = GROUPING_ROW_TYPE) {
2224
2345
  return this.providers.data.stores[type].store;
@@ -2302,6 +2423,18 @@ class GroupingRowPlugin extends BasePlugin {
2302
2423
  const sortingPlugin = this.providers.plugins.getByClass(SortingPlugin);
2303
2424
  return !!(sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.sortingPromise);
2304
2425
  }
2426
+ /**
2427
+ * Returns grouping options for regrouping that must preserve current UI state.
2428
+ *
2429
+ * `expandedAll` and config `prevExpanded` are initial/config instructions.
2430
+ * Reusing them after sorting would reopen groups the user collapsed before
2431
+ * sorting instead of using the current grouped source state.
2432
+ */
2433
+ getCurrentExpandedOptions() {
2434
+ var _a;
2435
+ const _b = (_a = this.options) !== null && _a !== void 0 ? _a : {}, options = __rest(_b, ["expandedAll", "prevExpanded"]);
2436
+ return options;
2437
+ }
2305
2438
  /**
2306
2439
  * Starts global source update with group clearing and applying new one
2307
2440
  * Initiated when need to reapply grouping
@@ -2404,7 +2537,7 @@ class GroupingRowPlugin extends BasePlugin {
2404
2537
  if (!((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length)) {
2405
2538
  return;
2406
2539
  }
2407
- this.doSourceUpdate(Object.assign({}, this.options));
2540
+ this.doSourceUpdate(this.getCurrentExpandedOptions());
2408
2541
  });
2409
2542
  /**
2410
2543
  * Apply logic for focus inside of grouping
@@ -2583,7 +2716,7 @@ class ColumnMovePlugin extends BasePlugin {
2583
2716
  const cols = this.getDimension(data.pin || 'rgCol');
2584
2717
  const gridRect = this.revogrid.getBoundingClientRect();
2585
2718
  const elRect = dataEl.getBoundingClientRect();
2586
- const startItem = getItemByPosition(cols, getLeftRelative(event.x, gridRect.left, elRect.left - gridRect.left));
2719
+ const startItem = getItemByPosition(cols, getLeftRelative(event.x, gridRect.left, elRect.left - gridRect.left) + (cols.renderOffset || 0));
2587
2720
  this.staticDragData = {
2588
2721
  startPos: event.x,
2589
2722
  startItem,
@@ -2608,13 +2741,13 @@ class ColumnMovePlugin extends BasePlugin {
2608
2741
  const start = this.staticDragData.startPos;
2609
2742
  if (Math.abs(start - e.x) > 10) {
2610
2743
  const x = getLeftRelative(e.x, this.dragData.gridRect.left, this.dragData.scrollOffset);
2611
- const rgCol = getItemByPosition(this.staticDragData.cols, x);
2744
+ const rgCol = getItemByPosition(this.staticDragData.cols, x + (this.staticDragData.cols.renderOffset || 0));
2612
2745
  this.orderUi.autoscroll(x, dragData.elRect.width);
2613
2746
  // prevent position change if out of bounds
2614
2747
  if (rgCol.itemIndex >= this.staticDragData.cols.count) {
2615
2748
  return;
2616
2749
  }
2617
- this.orderUi.showHandler(rgCol.end + dragData.scrollOffset, dragData.gridRect.width);
2750
+ this.orderUi.showHandler(rgCol.end - (this.staticDragData.cols.renderOffset || 0) + dragData.scrollOffset, dragData.gridRect.width);
2618
2751
  }
2619
2752
  }
2620
2753
  move(e) {
@@ -2632,7 +2765,7 @@ class ColumnMovePlugin extends BasePlugin {
2632
2765
  if (relativePos < 0) {
2633
2766
  relativePos = 0;
2634
2767
  }
2635
- const newPosition = getItemByPosition(this.staticDragData.cols, relativePos);
2768
+ const newPosition = getItemByPosition(this.staticDragData.cols, relativePos + (this.staticDragData.cols.renderOffset || 0));
2636
2769
  const store = this.providers.column.stores[this.dragData.type].store;
2637
2770
  const source = store.get('source');
2638
2771
  const newItems = [...store.get('items')];
@@ -2687,4 +2820,4 @@ function getLeftRelative(absoluteX, gridPos, offset) {
2687
2820
  return absoluteX - gridPos - offset;
2688
2821
  }
2689
2822
 
2690
- export { AutoSizeColumnPlugin as A, BasePlugin as B, ColumnAutoSizeMode as C, DimensionStore as D, ExportFilePlugin as E, FILTER_TRIMMED_TYPE as F, GroupingRowPlugin as G, SelectionStore as S, StretchColumn as a, ExportCsv as b, FILTER_CONFIG_CHANGED_EVENT as c, FILTE_PANEL as d, FilterPlugin as e, filterCoreFunctionsIndexedByType as f, filterTypes as g, filterNames as h, isStretchPlugin as i, doCollapse as j, doExpand as k, COLUMN_DRAG_MOVE_EVENT as l, COLUMN_DRAG_END_EVENT as m, BEFORE_COLUMN_DRAG_END_EVENT as n, COLUMN_DRAG_START_EVENT as o, ColumnMovePlugin as p, getLeftRelative as q, SortingPlugin as r, sortIndexByItems as s, defaultCellCompare as t, descCellCompare as u, getNextOrder as v, getComparer as w };
2823
+ export { AutoSizeColumnPlugin as A, BasePlugin as B, ColumnAutoSizeMode as C, DimensionStore as D, ExportFilePlugin as E, FILTER_TRIMMED_TYPE as F, GroupingRowPlugin as G, SelectionStore as S, StretchColumn as a, ExportCsv as b, FILTER_CONFIG_CHANGED_EVENT as c, FILTE_PANEL as d, FilterPlugin as e, filterCoreFunctionsIndexedByType as f, filterTypes as g, filterNames as h, isStretchPlugin as i, doCollapse as j, doExpand as k, COLUMN_DRAG_MOVE_EVENT as l, COLUMN_DRAG_END_EVENT as m, BEFORE_COLUMN_DRAG_END_EVENT as n, COLUMN_DRAG_START_EVENT as o, ColumnMovePlugin as p, getLeftRelative as q, SortingPlugin as r, hasActiveSorting as s, getSortingIndex as t, sortIndexByItems as u, defaultCellCompare as v, descCellCompare as w, getNextOrder as x, getComparer as y };