@revolist/revogrid 4.22.0 → 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 (130) hide show
  1. package/dist/cjs/{cell-renderer-uZmDBXz7.js → cell-renderer-DWJ9Px9f.js} +9 -3
  2. package/dist/cjs/{column.drag.plugin-CM_5mKV3.js → column.drag.plugin-CaEBDG-Q.js} +409 -267
  3. package/dist/cjs/{column.service-DvQDqxxx.js → column.service-f612L4ql.js} +1 -1
  4. package/dist/cjs/{dimension.helpers-CaIsYC99.js → dimension.helpers-B9HgANnM.js} +14 -146
  5. package/dist/cjs/{edit.utils-CwMzSIVF.js → edit.utils-pKeiYFLJ.js} +22 -1
  6. package/dist/cjs/{header-cell-renderer-B1dJwgTO.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 +45 -31
  9. package/dist/cjs/revo-grid.cjs.entry.js +35 -15
  10. package/dist/cjs/revogr-attribution_7.cjs.entry.js +44 -26
  11. package/dist/cjs/revogr-clipboard_3.cjs.entry.js +11 -9
  12. package/dist/cjs/revogr-data_4.cjs.entry.js +132 -178
  13. package/dist/cjs/revogr-filter-panel.cjs.entry.js +2 -1
  14. package/dist/cjs/{text-editor-BTnGaIl3.js → text-editor-B4W-m-r-.js} +3 -3
  15. package/dist/cjs/{throttle-CI4MsAqs.js → throttle-BCwEuJJq.js} +59 -24
  16. package/dist/cjs/viewport.helpers-BND76K2j.js +140 -0
  17. package/dist/cjs/{viewport.store-Dcjud-a-.js → viewport.store-BlKQ4x9H.js} +16 -16
  18. package/dist/collection/components/clipboard/revogr-clipboard.js +1 -1
  19. package/dist/collection/components/data/revogr-data.js +5 -3
  20. package/dist/collection/components/header/header-group-renderer.js +2 -1
  21. package/dist/collection/components/header/header-renderer.js +6 -5
  22. package/dist/collection/components/header/revogr-header-style.css +13 -3
  23. package/dist/collection/components/header/revogr-header.js +105 -42
  24. package/dist/collection/components/order/order-row.service.js +6 -5
  25. package/dist/collection/components/overlay/keyboard.service.js +25 -3
  26. package/dist/collection/components/overlay/selection.utils.js +8 -6
  27. package/dist/collection/components/revoGrid/revo-grid.js +6 -5
  28. package/dist/collection/components/revoGrid/viewport.service.js +2 -1
  29. package/dist/collection/components/scroll/revogr-viewport-scroll.js +10 -6
  30. package/dist/collection/components/scrollable/revogr-scroll-virtual.js +4 -10
  31. package/dist/collection/plugins/filter/filter.panel.js +2 -1
  32. package/dist/collection/plugins/filter/filter.plugin.js +11 -4
  33. package/dist/collection/plugins/groupingRow/grouping.row.plugin.js +25 -1
  34. package/dist/collection/plugins/moveColumn/column.drag.plugin.js +18 -15
  35. package/dist/collection/plugins/sorting/sorting.func.js +173 -15
  36. package/dist/collection/plugins/sorting/sorting.plugin.js +167 -84
  37. package/dist/collection/plugins/sorting/sorting.sign.js +7 -1
  38. package/dist/collection/serve/controller.js +98 -37
  39. package/dist/collection/serve/data.js +273 -144
  40. package/dist/collection/services/dimension.provider.js +16 -1
  41. package/dist/collection/services/local.scroll.service.js +59 -24
  42. package/dist/collection/services/scroll.dimension.helpers.js +83 -0
  43. package/dist/collection/services/selection.store.connector.js +4 -1
  44. package/dist/collection/store/dimension/dimension.recalculate.plugin.js +22 -9
  45. package/dist/collection/store/dimension/dimension.store.js +4 -2
  46. package/dist/collection/store/vp/viewport.helpers.js +9 -0
  47. package/dist/collection/store/vp/viewport.store.js +5 -16
  48. package/dist/collection/types/events.js +4 -0
  49. package/dist/collection/utils/key.utils.js +20 -0
  50. package/dist/collection/utils/store.utils.js +3 -3
  51. package/dist/{revo-grid/cell-renderer-K_BKH7Kx.js → esm/cell-renderer-8UiGd-s7.js} +9 -3
  52. package/dist/esm/{column.drag.plugin-DEqZ2qXJ.js → column.drag.plugin-BsfhsfmB.js} +402 -266
  53. package/dist/esm/{column.service-Cdz3dYqZ.js → column.service-DbpulTog.js} +1 -1
  54. package/dist/{revo-grid/debounce-BfO9dz9v.js → esm/debounce-PCRWZliA.js} +1 -1
  55. package/dist/{revo-grid/dimension.helpers-DzxqJQqN.js → esm/dimension.helpers-CGKwSvw6.js} +7 -128
  56. package/dist/esm/{edit.utils-CzfeG98N.js → edit.utils-Dnnbd0xG.js} +22 -2
  57. package/dist/{revo-grid/header-cell-renderer-DXhxZMly.js → esm/header-cell-renderer-DGI2FAD8.js} +1 -1
  58. package/dist/esm/index-Db3qZoW5.js +127 -0
  59. package/dist/esm/index.js +15 -10
  60. package/dist/esm/revo-grid.entry.js +34 -14
  61. package/dist/esm/revogr-attribution_7.entry.js +43 -25
  62. package/dist/esm/revogr-clipboard_3.entry.js +12 -10
  63. package/dist/esm/revogr-data_4.entry.js +133 -179
  64. package/dist/esm/revogr-filter-panel.entry.js +3 -2
  65. package/dist/esm/{text-editor-C1ks5eQ4.js → text-editor-C3RUSwH5.js} +2 -2
  66. package/dist/esm/{throttle-BEjFQa2l.js → throttle-CaUDyxyU.js} +60 -25
  67. package/dist/esm/viewport.helpers-CoCAvmZs.js +133 -0
  68. package/dist/{revo-grid/viewport.store-saAZJHRo.js → esm/viewport.store-COAfzAyu.js} +15 -17
  69. package/dist/{esm/cell-renderer-K_BKH7Kx.js → revo-grid/cell-renderer-8UiGd-s7.js} +9 -3
  70. package/dist/revo-grid/{column.drag.plugin-DEqZ2qXJ.js → column.drag.plugin-BsfhsfmB.js} +402 -266
  71. package/dist/revo-grid/{column.service-Cdz3dYqZ.js → column.service-DbpulTog.js} +1 -1
  72. package/dist/{esm/debounce-BfO9dz9v.js → revo-grid/debounce-PCRWZliA.js} +1 -1
  73. package/dist/{esm/dimension.helpers-DzxqJQqN.js → revo-grid/dimension.helpers-CGKwSvw6.js} +7 -128
  74. package/dist/revo-grid/{edit.utils-CzfeG98N.js → edit.utils-Dnnbd0xG.js} +22 -2
  75. package/dist/{esm/header-cell-renderer-DXhxZMly.js → revo-grid/header-cell-renderer-DGI2FAD8.js} +1 -1
  76. package/dist/revo-grid/index-Db3qZoW5.js +127 -0
  77. package/dist/revo-grid/index.esm.js +15 -10
  78. package/dist/revo-grid/revo-grid.entry.js +34 -14
  79. package/dist/revo-grid/revogr-attribution_7.entry.js +43 -25
  80. package/dist/revo-grid/revogr-clipboard_3.entry.js +12 -10
  81. package/dist/revo-grid/revogr-data_4.entry.js +133 -179
  82. package/dist/revo-grid/revogr-filter-panel.entry.js +3 -2
  83. package/dist/revo-grid/{text-editor-C1ks5eQ4.js → text-editor-C3RUSwH5.js} +2 -2
  84. package/dist/revo-grid/{throttle-BEjFQa2l.js → throttle-CaUDyxyU.js} +60 -25
  85. package/dist/revo-grid/viewport.helpers-CoCAvmZs.js +133 -0
  86. package/dist/{esm/viewport.store-saAZJHRo.js → revo-grid/viewport.store-COAfzAyu.js} +15 -17
  87. package/dist/types/components/header/header-group-renderer.d.ts +1 -0
  88. package/dist/types/components/header/header-renderer.d.ts +1 -0
  89. package/dist/types/components/header/revogr-header.d.ts +6 -0
  90. package/dist/types/components/overlay/keyboard.service.d.ts +5 -0
  91. package/dist/types/plugins/groupingRow/grouping.row.plugin.d.ts +8 -0
  92. package/dist/types/plugins/moveColumn/column.drag.plugin.d.ts +29 -3
  93. package/dist/types/plugins/sorting/sorting.func.d.ts +25 -2
  94. package/dist/types/plugins/sorting/sorting.plugin.d.ts +84 -9
  95. package/dist/types/plugins/sorting/sorting.sign.d.ts +5 -1
  96. package/dist/types/plugins/sorting/sorting.types.d.ts +46 -1
  97. package/dist/types/services/local.scroll.service.d.ts +10 -2
  98. package/dist/types/services/scroll.dimension.helpers.d.ts +20 -0
  99. package/dist/types/store/vp/viewport.helpers.d.ts +2 -0
  100. package/dist/types/types/events.d.ts +1 -1
  101. package/dist/types/types/interfaces.d.ts +11 -0
  102. package/dist/types/utils/key.utils.d.ts +8 -0
  103. package/hydrate/index.js +791 -539
  104. package/hydrate/index.mjs +791 -539
  105. package/package.json +1 -1
  106. package/standalone/column.service.js +1 -1
  107. package/standalone/data.store.js +1 -1
  108. package/standalone/debounce.js +1 -1
  109. package/standalone/dimension.helpers.js +1 -1
  110. package/standalone/index.js +1 -1
  111. package/standalone/local.scroll.timer.js +1 -1
  112. package/standalone/revo-grid.js +1 -1
  113. package/standalone/revogr-clipboard2.js +1 -1
  114. package/standalone/revogr-data2.js +1 -1
  115. package/standalone/revogr-edit.js +1 -1
  116. package/standalone/revogr-edit2.js +1 -1
  117. package/standalone/revogr-filter-panel.js +1 -1
  118. package/standalone/revogr-header2.js +1 -1
  119. package/standalone/revogr-order-editor2.js +1 -1
  120. package/standalone/revogr-overlay-selection2.js +1 -1
  121. package/standalone/revogr-row-headers.js +1 -1
  122. package/standalone/revogr-row-headers2.js +1 -1
  123. package/standalone/revogr-scroll-virtual2.js +1 -1
  124. package/standalone/revogr-viewport-scroll2.js +1 -1
  125. package/standalone/selection.utils.js +1 -1
  126. package/standalone/throttle.js +1 -1
  127. package/standalone/toNumber.js +1 -1
  128. package/dist/cjs/viewport.helpers-BAovztDd.js +0 -58
  129. package/dist/esm/viewport.helpers-VXhsJZtn.js +0 -52
  130. package/dist/revo-grid/viewport.helpers-VXhsJZtn.js +0 -52
@@ -1,15 +1,30 @@
1
1
  /*!
2
2
  * Built by Revolist OU ❤️
3
3
  */
4
- import size from "lodash/size";
5
4
  import debounce from "lodash/debounce";
6
5
  import { BasePlugin } from "../base.plugin";
7
6
  import { getColumnByProp } from "../../utils/column.utils";
8
7
  import { columnTypes, rowTypes } from "../../store/index";
9
- import { getComparer, getNextOrder, sortIndexByItems } from "./sorting.func";
8
+ import { isGrouping } from "../groupingRow/grouping.service";
9
+ import { getComparer, getNextOrder, getSortingIndex, hasActiveSorting, sortIndexByItems, } from "./sorting.func";
10
10
  export * from './sorting.types';
11
11
  export * from './sorting.func';
12
12
  export * from './sorting.sign';
13
+ function getSortableRowIndexes(indexes, source) {
14
+ return indexes.filter(index => !isGrouping(source[index]));
15
+ }
16
+ function mergeSortedRowsWithGroups(indexes, source, sortedRows) {
17
+ if (sortedRows.length === indexes.length) {
18
+ return sortedRows;
19
+ }
20
+ let rowIndex = 0;
21
+ return indexes.map(index => {
22
+ if (isGrouping(source[index])) {
23
+ return index;
24
+ }
25
+ return sortedRows[rowIndex++];
26
+ });
27
+ }
13
28
  /**
14
29
  * Lifecycle
15
30
  * 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.
@@ -24,54 +39,37 @@ export class SortingPlugin extends BasePlugin {
24
39
  super(revogrid, providers);
25
40
  this.revogrid = revogrid;
26
41
  /**
27
- * Delayed sorting promise
42
+ * Delayed sorting promise registered in the grid render job queue.
28
43
  */
29
44
  this.sortingPromise = null;
30
45
  /**
31
- * We need to sort only so often
46
+ * Debounced sorting entry point.
47
+ *
48
+ * Sorting can be requested by column changes, source changes, and header
49
+ * clicks in quick succession, so the actual sort is delayed and coalesced.
32
50
  */
33
- this.postponeSort = debounce((order, comparison, ignoreViewportUpdate) => this.runSorting(order, comparison, ignoreViewportUpdate), 50);
34
- const setConfig = (cfg) => {
35
- var _a;
36
- if (cfg) {
37
- const sortingFunc = {};
38
- const order = {};
39
- (_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
40
- sortingFunc[col.prop] = getComparer(col, col.order);
41
- order[col.prop] = col.order;
42
- });
43
- if (cfg.additive) {
44
- this.sorting = Object.assign(Object.assign({}, this.sorting), order);
45
- this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
46
- }
47
- else {
48
- // // set sorting
49
- this.sorting = order;
50
- this.sortingFunc = sortingFunc;
51
- }
52
- }
53
- };
54
- setConfig(config);
51
+ this.postponeSort = debounce((order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) => this.runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate), 50);
52
+ this.applySortingConfig(config);
55
53
  this.addEventListener('sortingconfigchanged', ({ detail }) => {
56
54
  config = detail;
57
- setConfig(detail);
58
- this.startSorting(this.sorting, this.sortingFunc);
55
+ this.applySortingConfig(detail);
56
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
59
57
  });
60
58
  this.addEventListener('beforeheaderrender', ({ detail, }) => {
61
59
  var _a;
62
60
  const { data: column } = detail;
63
61
  if (column.sortable) {
64
- detail.data = Object.assign(Object.assign({}, column), { order: (_a = this.sorting) === null || _a === void 0 ? void 0 : _a[column.prop] });
62
+ 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) });
65
63
  }
66
64
  });
67
65
  this.addEventListener('beforeanysource', ({ detail: { type }, }) => {
68
66
  // if sorting was provided - sort data
69
- if (!!this.sorting && this.sortingFunc) {
67
+ if (hasActiveSorting(this.sorting) && this.sortingFunc) {
70
68
  const event = this.emit('beforesourcesortingapply', { type, sorting: this.sorting });
71
69
  if (event.defaultPrevented) {
72
70
  return;
73
71
  }
74
- this.startSorting(this.sorting, this.sortingFunc);
72
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
75
73
  }
76
74
  });
77
75
  this.addEventListener('aftercolumnsset', ({ detail: { order }, }) => {
@@ -81,13 +79,24 @@ export class SortingPlugin extends BasePlugin {
81
79
  }
82
80
  const columns = this.providers.column.getColumns();
83
81
  const sortingFunc = {};
82
+ const sortingColumns = {};
83
+ const sortingOrder = [];
84
+ const sorting = {};
84
85
  for (let prop in order) {
85
- const cmp = getComparer(getColumnByProp(columns, prop), order[prop]);
86
- sortingFunc[prop] = cmp;
86
+ if (order[prop]) {
87
+ const column = getColumnByProp(columns, prop);
88
+ const cmp = getComparer(column, order[prop]);
89
+ sorting[prop] = order[prop];
90
+ sortingFunc[prop] = cmp;
91
+ sortingColumns[prop] = column;
92
+ sortingOrder.push(prop);
93
+ }
87
94
  }
88
95
  // set sorting
89
- this.sorting = order;
90
- this.sortingFunc = order && sortingFunc;
96
+ this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
97
+ this.sortingFunc = this.sorting ? sortingFunc : undefined;
98
+ this.sortingColumns = this.sorting ? sortingColumns : undefined;
99
+ this.sortingOrder = this.sorting ? sortingOrder : undefined;
91
100
  });
92
101
  this.addEventListener('beforeheaderclick', (e) => {
93
102
  var _a, _b, _c, _d;
@@ -101,23 +110,89 @@ export class SortingPlugin extends BasePlugin {
101
110
  });
102
111
  }
103
112
  /**
104
- * Entry point for sorting, waits for all delays, registers jobs
113
+ * Creates mutable sorting maps from current state when additive sorting is requested.
114
+ */
115
+ createSortingState(additive) {
116
+ var _a;
117
+ return {
118
+ sorting: additive ? Object.assign({}, this.sorting) : {},
119
+ sortingFunc: additive ? Object.assign({}, this.sortingFunc) : {},
120
+ sortingColumns: additive ? Object.assign({}, this.sortingColumns) : {},
121
+ sortingOrder: additive ? [...((_a = this.sortingOrder) !== null && _a !== void 0 ? _a : [])] : [],
122
+ };
123
+ }
124
+ /**
125
+ * Stores normalized sorting state, clearing inactive empty maps.
126
+ */
127
+ setSortingState({ sorting, sortingFunc, sortingColumns, sortingOrder, }) {
128
+ this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
129
+ this.sortingFunc = this.sorting ? sortingFunc : undefined;
130
+ this.sortingColumns = this.sorting ? sortingColumns : undefined;
131
+ this.sortingOrder = this.sorting ? sortingOrder : undefined;
132
+ }
133
+ /**
134
+ * Adds or replaces a column in a sorting state.
105
135
  */
106
- startSorting(order, sortingFunc, ignoreViewportUpdate) {
136
+ setColumnSorting(state, prop, order, cmp, column) {
137
+ state.sorting[prop] = order;
138
+ state.sortingFunc[prop] = cmp;
139
+ state.sortingColumns[prop] = column;
140
+ if (!state.sortingOrder.some(sortingProp => String(sortingProp) === String(prop))) {
141
+ state.sortingOrder.push(prop);
142
+ }
143
+ }
144
+ /**
145
+ * Removes a column from a sorting state.
146
+ */
147
+ clearColumnSorting(state, prop) {
148
+ delete state.sorting[prop];
149
+ delete state.sortingFunc[prop];
150
+ delete state.sortingColumns[prop];
151
+ const index = state.sortingOrder.findIndex(sortingProp => String(sortingProp) === String(prop));
152
+ if (index >= 0) {
153
+ state.sortingOrder.splice(index, 1);
154
+ }
155
+ }
156
+ /**
157
+ * Normalizes external sorting configuration into internal order,
158
+ * comparator, and column metadata maps.
159
+ */
160
+ applySortingConfig(cfg) {
161
+ var _a;
162
+ if (!cfg) {
163
+ return;
164
+ }
165
+ const state = this.createSortingState(cfg.additive);
166
+ (_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
167
+ if (col.order) {
168
+ this.setColumnSorting(state, col.prop, col.order, getComparer(col, col.order), col);
169
+ return;
170
+ }
171
+ this.clearColumnSorting(state, col.prop);
172
+ });
173
+ this.setSortingState(state);
174
+ }
175
+ startSorting(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate) {
107
176
  if (!this.sortingPromise) {
108
177
  // add job before render
109
178
  this.revogrid.jobsBeforeRender.push(new Promise(resolve => {
110
179
  this.sortingPromise = resolve;
111
180
  }));
112
181
  }
113
- this.postponeSort(order, sortingFunc, ignoreViewportUpdate);
182
+ if (typeof sortingColumns === 'boolean') {
183
+ this.postponeSort(order, sortingFunc, undefined, undefined, sortingColumns);
184
+ return;
185
+ }
186
+ this.postponeSort(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate);
114
187
  }
115
188
  /**
116
- * Apply sorting to data on header click
117
- * If additive - add to existing sorting, multiple columns can be sorted
189
+ * Applies sorting requested by a sortable header click.
190
+ *
191
+ * @param column - Column that initiated sorting.
192
+ * @param additive - If true, add/remove this column from the current multi-sort state.
118
193
  */
119
194
  headerclick(column, additive) {
120
- var _a, _b, _c;
195
+ var _a;
121
196
  const columnProp = column.prop;
122
197
  let order = getNextOrder((_a = this.sorting) === null || _a === void 0 ? void 0 : _a[columnProp]);
123
198
  const beforeEvent = this.emit('beforesorting', { column, order, additive });
@@ -135,52 +210,59 @@ export class SortingPlugin extends BasePlugin {
135
210
  return;
136
211
  }
137
212
  const cmp = getComparer(beforeApplyEvent.detail.column, beforeApplyEvent.detail.order);
138
- if (beforeApplyEvent.detail.additive && this.sorting) {
139
- const sorting = {};
140
- const sortingFunc = {};
141
- if (columnProp in sorting && size(sorting) > 1 && order === undefined) {
142
- delete sorting[columnProp];
143
- delete sortingFunc[columnProp];
144
- }
145
- else {
146
- sorting[columnProp] = order;
147
- sortingFunc[columnProp] = cmp;
148
- }
149
- this.sorting = Object.assign(Object.assign({}, this.sorting), sorting);
150
- // extend sorting function with new sorting for multiple columns sorting
151
- this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
213
+ this.applyHeaderSorting(beforeApplyEvent.detail.column, beforeApplyEvent.detail.additive, order, cmp);
214
+ this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
215
+ }
216
+ /**
217
+ * Applies sorting state produced by a header click.
218
+ */
219
+ applyHeaderSorting(column, additive, order, cmp) {
220
+ if (!additive) {
221
+ this.setSortingState(order ? {
222
+ sorting: { [column.prop]: order },
223
+ sortingFunc: { [column.prop]: cmp },
224
+ sortingColumns: { [column.prop]: column },
225
+ sortingOrder: [column.prop],
226
+ } : this.createSortingState());
227
+ return;
228
+ }
229
+ const state = this.createSortingState(true);
230
+ if (order) {
231
+ this.setColumnSorting(state, column.prop, order, cmp, column);
152
232
  }
153
233
  else {
154
- if (order) {
155
- // reset sorting
156
- this.sorting = { [columnProp]: order };
157
- this.sortingFunc = { [columnProp]: cmp };
158
- }
159
- else {
160
- (_b = this.sorting) === null || _b === void 0 ? true : delete _b[columnProp];
161
- (_c = this.sortingFunc) === null || _c === void 0 ? true : delete _c[columnProp];
162
- }
234
+ this.clearColumnSorting(state, column.prop);
163
235
  }
164
- this.startSorting(this.sorting, this.sortingFunc);
236
+ this.setSortingState(state);
165
237
  }
166
- runSorting(order, comparison, ignoreViewportUpdate) {
167
- var _a;
168
- this.sort(order, comparison, undefined, ignoreViewportUpdate);
169
- (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
238
+ runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) {
239
+ var _a, _b;
240
+ if (typeof sortingColumns === 'boolean') {
241
+ this.sort(order, comparison, undefined, undefined, undefined, sortingColumns);
242
+ (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
243
+ this.sortingPromise = null;
244
+ return;
245
+ }
246
+ this.sort(order, comparison, sortingColumns, sortingOrder, undefined, ignoreViewportUpdate);
247
+ (_b = this.sortingPromise) === null || _b === void 0 ? void 0 : _b.call(this);
170
248
  this.sortingPromise = null;
171
249
  }
172
- /**
173
- * Sort items by sorting function
174
- * @requires proxyItems applied to row store
175
- * @requires source applied to row store
176
- *
177
- * @param sorting - per column sorting
178
- * @param data - this.stores['rgRow'].store.get('source')
179
- */
180
- sort(sorting, sortingFunc, types = rowTypes, ignoreViewportUpdate = false) {
250
+ sort(sorting, sortingFunc, sortingColumns, sortingOrder, types = rowTypes, ignoreViewportUpdate = false) {
251
+ let activeSortingColumns;
252
+ let activeSortingOrder;
253
+ let activeTypes = types;
254
+ let activeIgnoreViewportUpdate = ignoreViewportUpdate;
255
+ if (Array.isArray(sortingColumns)) {
256
+ activeTypes = sortingColumns;
257
+ activeIgnoreViewportUpdate = typeof sortingOrder === 'boolean' ? sortingOrder : false;
258
+ }
259
+ else {
260
+ activeSortingColumns = sortingColumns;
261
+ activeSortingOrder = Array.isArray(sortingOrder) ? sortingOrder : undefined;
262
+ }
181
263
  // if no sorting - reset
182
264
  if (!Object.keys(sorting || {}).length) {
183
- for (let type of types) {
265
+ for (let type of activeTypes) {
184
266
  const storeService = this.providers.data.stores[type];
185
267
  // row data
186
268
  const source = storeService.store.get('source');
@@ -189,26 +271,27 @@ export class SortingPlugin extends BasePlugin {
189
271
  // row indexes
190
272
  const newItemsOrder = Array.from({ length: source.length }, (_, i) => i); // recover indexes range(0, source.length)
191
273
  this.providers.dimension.updateSizesPositionByNewDataIndexes(type, newItemsOrder, proxyItems);
192
- storeService.setData({ proxyItems: newItemsOrder, source: [...source], });
274
+ storeService.setData({ proxyItems: newItemsOrder });
193
275
  }
194
276
  }
195
277
  else {
196
- for (let type of types) {
278
+ for (let type of activeTypes) {
197
279
  const storeService = this.providers.data.stores[type];
198
280
  // row data
199
281
  const source = storeService.store.get('source');
200
282
  // row indexes
201
283
  const proxyItems = storeService.store.get('proxyItems');
202
- const newItemsOrder = sortIndexByItems([...proxyItems], source, sortingFunc);
284
+ const sortItems = getSortableRowIndexes(proxyItems, source);
285
+ const sortedItems = sortIndexByItems([...sortItems], source, sortingFunc, sorting, activeSortingColumns, activeSortingOrder);
286
+ const newItemsOrder = mergeSortedRowsWithGroups(proxyItems, source, sortedItems);
203
287
  // take row indexes before trim applied and proxy items
204
288
  const prevItems = storeService.store.get('items');
205
289
  storeService.setData({
206
290
  proxyItems: newItemsOrder,
207
- source: [...source],
208
291
  });
209
292
  // take currently visible row indexes
210
293
  const newItems = storeService.store.get('items');
211
- if (!ignoreViewportUpdate) {
294
+ if (!activeIgnoreViewportUpdate) {
212
295
  this.providers.dimension
213
296
  .updateSizesPositionByNewDataIndexes(type, newItems, prevItems);
214
297
  }
@@ -2,7 +2,13 @@
2
2
  * Built by Revolist OU ❤️
3
3
  */
4
4
  import { h } from "@stencil/core";
5
+ /**
6
+ * Renders sorting direction and optional additive sorting rank.
7
+ */
5
8
  export const SortingSign = ({ column }) => {
6
9
  var _a;
7
- return h("i", { class: (_a = column === null || column === void 0 ? void 0 : column.order) !== null && _a !== void 0 ? _a : 'sort-off' });
10
+ const indicatorAttrs = { class: 'sort-indicator' };
11
+ const iconAttrs = { class: (_a = column === null || column === void 0 ? void 0 : column.order) !== null && _a !== void 0 ? _a : 'sort-off' };
12
+ const orderIndexAttrs = { class: 'sort-order-index' };
13
+ return (h("span", Object.assign({}, indicatorAttrs), h("i", Object.assign({}, iconAttrs)), (column === null || column === void 0 ? void 0 : column.sortIndex) ? (h("sup", Object.assign({}, orderIndexAttrs), column.sortIndex)) : null));
8
14
  };
@@ -1,15 +1,15 @@
1
- import { generateFakeDataObject } from './data.js';
1
+ import { generateFakeDataObjectAsync } from './data.js';
2
2
 
3
3
  /**
4
4
  * Map of prevented events
5
5
  */
6
- window.eventsPrevented = {};
6
+ globalThis.eventsPrevented = {};
7
7
 
8
8
  /**
9
9
  * Toggle row headers visibility
10
10
  * @param {boolean} isShow - Show row headers if true, hide otherwise
11
11
  */
12
- window.showRowHeaders = function (isShow) {
12
+ globalThis.showRowHeaders = function (isShow) {
13
13
  const grid = document.querySelector('revo-grid');
14
14
  grid.rowHeaders = isShow;
15
15
  };
@@ -18,8 +18,8 @@ window.showRowHeaders = function (isShow) {
18
18
  * Toggle column grouping visibility
19
19
  * @param {boolean} isShow - Show column grouping if true, hide otherwise
20
20
  */
21
- window.showColGrouping = function (isShow) {
22
- setData({
21
+ globalThis.showColGrouping = function (isShow) {
22
+ globalThis.setData({
23
23
  groupedHeader: isShow,
24
24
  });
25
25
  };
@@ -28,17 +28,30 @@ window.showColGrouping = function (isShow) {
28
28
  * Set row size
29
29
  * @param {number} s - Row size
30
30
  */
31
- window.setRowSize = function (s) {
31
+ globalThis.setRowSize = function (s) {
32
32
  const grid = document.querySelector('revo-grid');
33
33
  grid.rowSize = s;
34
34
  };
35
35
 
36
+ /**
37
+ * Apply several custom row sizes.
38
+ */
39
+ globalThis.setCustomRowSizes = function () {
40
+ const grid = document.querySelector('revo-grid');
41
+ grid.rowDefinitions = [
42
+ { type: 'rgRow', index: 1, size: 64 },
43
+ { type: 'rgRow', index: 3, size: 96 },
44
+ { type: 'rgRow', index: 6, size: 48 },
45
+ { type: 'rgRow', index: 10, size: 120 },
46
+ ];
47
+ };
48
+
36
49
  /**
37
50
  * Start editing cell
38
51
  * @param {number} rgRow - Row index
39
52
  * @param {string} prop - Column property
40
53
  */
41
- window.setEdit = function (rgRow, prop) {
54
+ globalThis.setEdit = function (rgRow, prop) {
42
55
  const grid = document.querySelector('revo-grid');
43
56
  grid.setCellEdit(rgRow, prop);
44
57
  };
@@ -47,7 +60,7 @@ window.setEdit = function (rgRow, prop) {
47
60
  * Scroll to column
48
61
  * @param {number} [x=30] - Column index
49
62
  */
50
- window.scrollToCol = function (x = 30) {
63
+ globalThis.scrollToCol = function (x = 30) {
51
64
  const grid = document.querySelector('revo-grid');
52
65
  grid.scrollToColumnProp(x);
53
66
  };
@@ -55,7 +68,7 @@ window.scrollToCol = function (x = 30) {
55
68
  /**
56
69
  * Clear grouping
57
70
  */
58
- window.clearGrouping = function () {
71
+ globalThis.clearGrouping = function () {
59
72
  const grid = document.querySelector('revo-grid');
60
73
  grid.grouping = {};
61
74
  };
@@ -65,7 +78,7 @@ window.clearGrouping = function () {
65
78
  * @param {Array} props - Array of properties to group by
66
79
  * @param {boolean} expandedAll - Expand all groups if true, collapse otherwise
67
80
  */
68
- window.setGrouping = function (props = [], expandedAll = false) {
81
+ globalThis.setGrouping = function (props = [], expandedAll = false) {
69
82
  const grid = document.querySelector('revo-grid');
70
83
  grid.grouping = {
71
84
  props,
@@ -82,7 +95,7 @@ window.setGrouping = function (props = [], expandedAll = false) {
82
95
  * Set trimmed rows
83
96
  * @param {Array} rows - Array of row indexes to trim
84
97
  */
85
- window.setTrimmed = function (rows = []) {
98
+ globalThis.setTrimmed = function (rows = []) {
86
99
  const grid = document.querySelector('revo-grid');
87
100
  grid.trimmedRows = rows.reduce((r, v) => {
88
101
  r[v] = true;
@@ -94,7 +107,7 @@ window.setTrimmed = function (rows = []) {
94
107
  * Export grid
95
108
  * @param {string} [filename='new file'] - File name
96
109
  */
97
- window.exportGrid = function (filename = 'new file') {
110
+ globalThis.exportGrid = function (filename = 'new file') {
98
111
  const grid = document.querySelector('revo-grid');
99
112
  grid.getPlugins().then(plugins => {
100
113
  plugins.forEach(p => {
@@ -116,31 +129,78 @@ let defaultData = {
116
129
  colPinStart: [],
117
130
  };
118
131
 
132
+ let dataGenerationId = 0;
133
+
134
+ function formatNumber(value) {
135
+ return new Intl.NumberFormat('en').format(value);
136
+ }
137
+
138
+ function setLoader(text, visible = true) {
139
+ const $loader = document.querySelector('.loader');
140
+ if (!$loader) {
141
+ return;
142
+ }
143
+ $loader.textContent = text;
144
+ $loader.style.display = visible ? 'block' : 'none';
145
+ }
146
+
147
+ function cancelDataGeneration() {
148
+ dataGenerationId++;
149
+ setLoader('', false);
150
+ }
151
+
119
152
  /**
120
153
  * Set data
121
154
  * @param {Object} [config={}] - Data configuration
122
155
  */
123
- window.setData = function (config = {}) {
156
+ globalThis.setData = async function (config = {}) {
124
157
  defaultData = { ...defaultData, ...config };
125
- const $loader = document.querySelector('.loader');
126
- $loader.style.display = 'block';
127
- setTimeout(() => {
158
+ const generationId = ++dataGenerationId;
159
+ const totalCells = defaultData.rows * defaultData.cols;
160
+ setLoader(`Preparing ${formatNumber(defaultData.rows)} rows x ${formatNumber(defaultData.cols)} columns...`);
161
+
162
+ try {
163
+ // Let the loader paint before data generation starts.
164
+ await new Promise(resolve => setTimeout(resolve, 0));
165
+ const data = await generateFakeDataObjectAsync(defaultData, {
166
+ isCanceled: () => generationId !== dataGenerationId,
167
+ onProgress: ({ rows, totalRows }) => {
168
+ if (generationId !== dataGenerationId) {
169
+ return;
170
+ }
171
+ setLoader(
172
+ `Generated ${formatNumber(rows)} / ${formatNumber(totalRows)} rows (${formatNumber(totalCells)} cells)...`,
173
+ );
174
+ },
175
+ });
176
+
177
+ if (generationId !== dataGenerationId || !data) {
178
+ return;
179
+ }
180
+
128
181
  const grid = document.querySelector('revo-grid');
129
- const data = generateFakeDataObject(defaultData);
182
+ if (!grid) {
183
+ return;
184
+ }
130
185
 
131
186
  grid.columns = data.headers;
132
187
  grid.source = data.rows;
133
188
 
134
189
  grid.pinnedTopSource = data.pinnedTopRows;
135
190
  grid.pinnedBottomSource = data.pinnedBottomRows;
136
- $loader.style.display = 'none';
137
- }, 0);
191
+ setLoader('', false);
192
+ } catch (error) {
193
+ if (generationId === dataGenerationId) {
194
+ setLoader(`Data generation failed: ${error?.message || error}`);
195
+ throw error;
196
+ }
197
+ }
138
198
  };
139
199
 
140
- window.setRtl = function (checked) {
200
+ globalThis.setRtl = function (checked) {
141
201
  const grid = document.querySelector('revo-grid');
142
202
  grid.rtl = checked;
143
- window.document.dir = checked ? 'rtl' : 'ltr';
203
+ globalThis.document.dir = checked ? 'rtl' : 'ltr';
144
204
  };
145
205
 
146
206
  /**
@@ -148,7 +208,7 @@ window.setRtl = function (checked) {
148
208
  * @param {string} type - Type of pinned rows/columns
149
209
  * @param {boolean} checked - True if rows/columns are pinned, false otherwise
150
210
  */
151
- window.setPinned = function (type, checked) {
211
+ globalThis.setPinned = function (type, checked) {
152
212
  const val = [];
153
213
  if (checked) {
154
214
  switch (type) {
@@ -166,7 +226,7 @@ window.setPinned = function (type, checked) {
166
226
  break;
167
227
  }
168
228
  }
169
- setData({
229
+ globalThis.setData({
170
230
  [type]: val,
171
231
  });
172
232
  };
@@ -176,8 +236,8 @@ window.setPinned = function (type, checked) {
176
236
  * @param {string} name - Event name
177
237
  * @param {boolean} checked - True if event should be prevented, false otherwise
178
238
  */
179
- window.preventEvent = function (name, checked) {
180
- eventsPrevented[name] = checked;
239
+ globalThis.preventEvent = function (name, checked) {
240
+ globalThis.eventsPrevented[name] = checked;
181
241
  };
182
242
 
183
243
  let keys = 2;
@@ -187,7 +247,7 @@ let attrs = {};
187
247
  * Toggle visibility of grid
188
248
  * @param {boolean} checked - True if grid is visible, false otherwise
189
249
  */
190
- window.toggleVisibility = function (checked) {
250
+ globalThis.toggleVisibility = function (checked) {
191
251
  if (!checked) {
192
252
  const grid = document.querySelector('revo-grid');
193
253
  attrs = {};
@@ -209,7 +269,7 @@ window.toggleVisibility = function (checked) {
209
269
  });
210
270
  grid.setAttribute('key', keys++);
211
271
  holder.appendChild(grid);
212
- setData();
272
+ globalThis.setData();
213
273
  }
214
274
  };
215
275
 
@@ -220,7 +280,7 @@ let timerUpdateInterval;
220
280
  * @param {boolean} checked - True if timer should be updated, false otherwise
221
281
  * @param {number} [inteval=3] - Update interval in seconds
222
282
  */
223
- window.timerUpdate = function (checked, inteval = 3) {
283
+ globalThis.timerUpdate = function (checked, inteval = 3) {
224
284
  clearInterval(timerUpdateInterval);
225
285
  if (checked) {
226
286
  timerUpdateInterval = setInterval(() => {
@@ -234,9 +294,9 @@ window.timerUpdate = function (checked, inteval = 3) {
234
294
  * Set theme
235
295
  * @param {string} theme - Theme name
236
296
  */
237
- window.theme = function (theme) {
297
+ globalThis.theme = function (theme) {
238
298
  const grid = document.querySelector('revo-grid');
239
- if (theme && theme.indexOf('dark') > -1) {
299
+ if (theme?.includes('dark')) {
240
300
  document.documentElement.setAttribute('data-bs-theme', 'dark');
241
301
  } else {
242
302
  document.documentElement.removeAttribute('data-bs-theme');
@@ -244,26 +304,26 @@ window.theme = function (theme) {
244
304
  grid.theme = theme || 'default';
245
305
  };
246
306
 
247
- window.onload = onLoad;
307
+ globalThis.onload = onLoad;
248
308
 
249
- window.clearFilter = () => {
309
+ globalThis.clearFilter = () => {
250
310
  const grid = document.querySelector('revo-grid');
251
311
  grid.filter = {};
252
312
  };
253
313
 
254
- window.sortColumn = (columnProp= 0, additive = false) => {
314
+ globalThis.sortColumn = (columnProp= 0, additive = false) => {
255
315
  const grid = document.querySelector('revo-grid');
256
316
  grid.updateColumnSorting({
257
317
  prop: columnProp,
258
318
  }, 'asc', additive);
259
319
  };
260
320
 
261
- window.clearSorting = () => {
321
+ globalThis.clearSorting = () => {
262
322
  const grid = document.querySelector('revo-grid');
263
323
  grid.clearSorting();
264
324
  };
265
325
 
266
- window.setFilter = () => {
326
+ globalThis.setFilter = () => {
267
327
  const grid = document.querySelector('revo-grid');
268
328
  const filterFunc = (cellValue, extraValue) => {
269
329
  if (!cellValue) {
@@ -304,7 +364,8 @@ window.setFilter = () => {
304
364
  * Deep groups should align with a1/a2/a3/b1/b2/b3.
305
365
  * https://github.com/revolist/revogrid/issues/828
306
366
  */
307
- window.setColumnGroupOffsetBugDemo = () => {
367
+ globalThis.setColumnGroupOffsetBugDemo = () => {
368
+ cancelDataGeneration();
308
369
  const grid = document.querySelector('revo-grid');
309
370
 
310
371
  grid.columns = [
@@ -390,7 +451,7 @@ function onLoad() {
390
451
  const events = ['aftercolumnresize'];
391
452
  events.forEach(e => {
392
453
  grid.addEventListener(e, $e => {
393
- if (window.eventsPrevented[e]) {
454
+ if (globalThis.eventsPrevented[e]) {
394
455
  $e.preventDefault();
395
456
  }
396
457
  console.log(