@revolist/revogrid 4.27.0 → 4.27.2

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 (76) hide show
  1. package/dist/cjs/{cell-renderer-C7rdgaov.js → cell-renderer-BDIx0xys.js} +1 -1
  2. package/dist/cjs/{column.service-Bbml5C2j.js → column.service-D-ENzqyb.js} +2 -0
  3. package/dist/cjs/{filter.button-F2Bw3UAd.js → filter.button-C6ixuMmr.js} +3 -2
  4. package/dist/cjs/{header-cell-renderer-BljFI6wj.js → header-cell-renderer-B5Y4fdZC.js} +1 -1
  5. package/dist/cjs/index.cjs.js +7 -5
  6. package/dist/cjs/loader.cjs.js +1 -1
  7. package/dist/cjs/revo-grid.cjs.entry.js +63 -43
  8. package/dist/cjs/revo-grid.cjs.js +1 -1
  9. package/dist/cjs/revogr-attribution_7.cjs.entry.js +1 -1
  10. package/dist/cjs/revogr-data_4.cjs.entry.js +12 -11
  11. package/dist/cjs/revogr-filter-panel.cjs.entry.js +139 -33
  12. package/dist/cjs/{row-resize.plugin-BRQy_qNn.js → row-resize.plugin-C4YOF1lN.js} +353 -185
  13. package/dist/collection/components/header/header-renderer.js +7 -6
  14. package/dist/collection/components/header/revogr-header-style.css +8 -3
  15. package/dist/collection/components/revoGrid/revo-grid-style.css +12 -2
  16. package/dist/collection/components/revoGrid/revo-grid.js +37 -21
  17. package/dist/collection/plugins/filter/filter.button.js +3 -2
  18. package/dist/collection/plugins/filter/filter.indexed.js +5 -0
  19. package/dist/collection/plugins/filter/filter.panel.js +138 -31
  20. package/dist/collection/plugins/filter/filter.plugin.js +48 -5
  21. package/dist/collection/plugins/filter/filter.style.css +25 -3
  22. package/dist/collection/plugins/groupingRow/grouping.const.js +1 -0
  23. package/dist/collection/plugins/groupingRow/grouping.row.plugin.js +84 -54
  24. package/dist/collection/plugins/groupingRow/grouping.sorting.service.js +58 -0
  25. package/dist/collection/plugins/groupingRow/grouping.trimmed.service.js +5 -3
  26. package/dist/collection/plugins/row-resize/row-resize.plugin.js +144 -113
  27. package/dist/collection/plugins/sorting/sorting.plugin.js +16 -13
  28. package/dist/collection/plugins/wcag/index.js +5 -4
  29. package/dist/collection/services/dimension.provider.js +17 -1
  30. package/dist/esm/{cell-renderer-BFpmdV8H.js → cell-renderer-D9ze8OJw.js} +1 -1
  31. package/dist/esm/{column.service-CM-wgGs8.js → column.service-pu_fdQ0S.js} +2 -1
  32. package/dist/esm/{filter.button-DMhpuAiw.js → filter.button-CEPUxLUo.js} +3 -2
  33. package/dist/{revo-grid/header-cell-renderer-Bqh1PrgH.js → esm/header-cell-renderer-YCiVIQ2E.js} +1 -1
  34. package/dist/esm/index.js +6 -6
  35. package/dist/esm/loader.js +1 -1
  36. package/dist/esm/revo-grid.entry.js +63 -43
  37. package/dist/esm/revo-grid.js +1 -1
  38. package/dist/esm/revogr-attribution_7.entry.js +1 -1
  39. package/dist/esm/revogr-data_4.entry.js +12 -11
  40. package/dist/esm/revogr-filter-panel.entry.js +139 -33
  41. package/dist/esm/{row-resize.plugin-BRiaHlHA.js → row-resize.plugin-Beu0pMds.js} +354 -187
  42. package/dist/revo-grid/{cell-renderer-BFpmdV8H.js → cell-renderer-D9ze8OJw.js} +1 -1
  43. package/dist/revo-grid/{column.service-CM-wgGs8.js → column.service-pu_fdQ0S.js} +2 -1
  44. package/dist/revo-grid/{filter.button-DMhpuAiw.js → filter.button-CEPUxLUo.js} +3 -2
  45. package/dist/{esm/header-cell-renderer-Bqh1PrgH.js → revo-grid/header-cell-renderer-YCiVIQ2E.js} +1 -1
  46. package/dist/revo-grid/index.esm.js +6 -6
  47. package/dist/revo-grid/revo-grid.entry.js +63 -43
  48. package/dist/revo-grid/revo-grid.esm.js +1 -1
  49. package/dist/revo-grid/revogr-attribution_7.entry.js +1 -1
  50. package/dist/revo-grid/revogr-data_4.entry.js +12 -11
  51. package/dist/revo-grid/revogr-filter-panel.entry.js +139 -33
  52. package/dist/revo-grid/{row-resize.plugin-BRiaHlHA.js → row-resize.plugin-Beu0pMds.js} +354 -187
  53. package/dist/types/components/revoGrid/revo-grid.d.ts +2 -0
  54. package/dist/types/plugins/filter/filter.indexed.d.ts +2 -0
  55. package/dist/types/plugins/filter/filter.panel.d.ts +9 -2
  56. package/dist/types/plugins/filter/filter.plugin.d.ts +8 -1
  57. package/dist/types/plugins/filter/filter.types.d.ts +8 -0
  58. package/dist/types/plugins/groupingRow/grouping.const.d.ts +1 -0
  59. package/dist/types/plugins/groupingRow/grouping.row.plugin.d.ts +5 -7
  60. package/dist/types/plugins/groupingRow/grouping.sorting.service.d.ts +7 -0
  61. package/dist/types/plugins/groupingRow/grouping.trimmed.service.d.ts +9 -0
  62. package/dist/types/plugins/row-resize/row-resize.plugin.d.ts +14 -12
  63. package/dist/types/plugins/sorting/sorting.plugin.d.ts +5 -0
  64. package/dist/types/services/dimension.provider.d.ts +7 -1
  65. package/dist/types/types/interfaces.d.ts +13 -1
  66. package/hydrate/index.js +561 -264
  67. package/hydrate/index.mjs +561 -264
  68. package/package.json +1 -1
  69. package/standalone/column.service.js +1 -1
  70. package/standalone/filter.button.js +1 -1
  71. package/standalone/index.js +1 -1
  72. package/standalone/revo-grid.js +1 -1
  73. package/standalone/revogr-data2.js +1 -1
  74. package/standalone/revogr-filter-panel.js +1 -1
  75. package/standalone/revogr-header2.js +1 -1
  76. package/standalone/revogr-overlay-selection2.js +1 -1
@@ -5,7 +5,7 @@
5
5
  import { h } from "@stencil/core";
6
6
  import { BasePlugin } from "../base.plugin";
7
7
  import { FILTER_PROP, isFilterBtn } from "./filter.button";
8
- import { filterCoreFunctionsIndexedByType, filterNames, filterTypes, } from "./filter.indexed";
8
+ import { filterCoreFunctionsIndexedByType, filterNames, filterTypeDefaults, filterTypes, } from "./filter.indexed";
9
9
  import { resolveBlankSemantics } from "./filter.blank";
10
10
  import { timeout } from "../../utils";
11
11
  import { ASYNC_FILTER_ROW_THRESHOLD, FILTER_CHUNK_SIZE, FILTER_TIME_BUDGET_MS, } from "./filter.constants";
@@ -30,6 +30,8 @@ export const FILTE_PANEL = 'revogr-filter-panel';
30
30
  *
31
31
  * @property {FilterLocalization|undefined} localization - translation for filter popup captions.
32
32
  *
33
+ * @property {boolean|undefined} defaultFilter - creates a draft condition when an empty filter panel opens. Defaults to true.
34
+ *
33
35
  * @property {boolean|undefined} disableDynamicFiltering - disables dynamic filtering. A way to apply filters on Save only.
34
36
  */
35
37
  /**
@@ -51,7 +53,7 @@ export class FilterPlugin extends BasePlugin {
51
53
  * number: ['eqN', 'neqN', 'gt']
52
54
  * }
53
55
  */
54
- this.filterByType = Object.assign({}, filterTypes);
56
+ this.filterByType = Object.fromEntries(Object.entries(filterTypes).map(([type, filters]) => [type, [...filters]]));
55
57
  this.filterNameIndexByType = Object.assign({}, filterNames);
56
58
  this.filterFunctionsIndexedByType = Object.assign({}, filterCoreFunctionsIndexedByType);
57
59
  this.filterProp = FILTER_PROP;
@@ -135,11 +137,16 @@ export class FilterPlugin extends BasePlugin {
135
137
  return null;
136
138
  }
137
139
  initConfig(config) {
138
- var _a;
140
+ var _a, _b, _c, _d;
139
141
  this.config = config;
140
142
  this.allowDuplicateOperators = (_a = config.allowDuplicateOperators) !== null && _a !== void 0 ? _a : true;
141
143
  if (this.pop) {
142
144
  this.pop.allowDuplicateOperators = this.allowDuplicateOperators;
145
+ this.pop.disableDynamicFiltering =
146
+ (_b = config.disableDynamicFiltering) !== null && _b !== void 0 ? _b : false;
147
+ this.pop.closeOnOutsideClick =
148
+ (_c = config.closeFilterPanelOnOutsideClick) !== null && _c !== void 0 ? _c : true;
149
+ this.pop.filterCaptions = (_d = config.localization) === null || _d === void 0 ? void 0 : _d.captions;
143
150
  }
144
151
  if (config.multiFilterItems) {
145
152
  this.multiFilterItems = Object.assign({}, config.multiFilterItems);
@@ -228,11 +235,12 @@ export class FilterPlugin extends BasePlugin {
228
235
  }
229
236
  // filter button clicked, open filter dialog
230
237
  const buttonPos = (filterButton instanceof HTMLElement ? filterButton : el).getBoundingClientRect();
231
- const data = Object.assign(Object.assign(Object.assign({}, e.detail), this.filterCollection[prop]), { x: buttonPos.x, y: buttonPos.y + buttonPos.height, anchorY: buttonPos.y, autoCorrect: true, filterTypes: this.getColumnFilter(e.detail.filter), filterItems: this.multiFilterItems, extraContent: this.extraHyperContent, extraBottomContent: this.extraBottomHyperContent });
238
+ const data = Object.assign(Object.assign(Object.assign({}, e.detail), this.filterCollection[prop]), { x: buttonPos.x, y: buttonPos.y + buttonPos.height, anchorY: buttonPos.y, autoCorrect: true, filterTypes: this.getColumnFilter(e.detail.filter), defaultFilterType: this.getDefaultFilter(e.detail.filter), showDefaultFilter: this.shouldShowDefaultFilter(e.detail.filter), filterItems: this.multiFilterItems, extraContent: this.extraHyperContent, extraBottomContent: this.extraBottomHyperContent });
232
239
  (_b = this.beforeshow) === null || _b === void 0 ? void 0 : _b.call(this, data);
233
240
  this.pop.show(data);
234
241
  }
235
- getColumnFilter(type) {
242
+ getColumnFilter(config) {
243
+ const type = this.isColumnFilterOption(config) ? config.type : config;
236
244
  let filterType = 'string';
237
245
  if (!type) {
238
246
  return { [filterType]: this.filterByType[filterType] };
@@ -252,6 +260,41 @@ export class FilterPlugin extends BasePlugin {
252
260
  }
253
261
  return { [filterType]: this.filterByType[filterType] };
254
262
  }
263
+ /** Resolve the preferred operator against the column's available filters. */
264
+ getDefaultFilter(config) {
265
+ var _a;
266
+ const filters = this.getColumnFilter(config);
267
+ const availableFilters = Object.values(filters).flat();
268
+ const columnDefault = this.isColumnFilterOption(config)
269
+ ? config.default
270
+ : undefined;
271
+ if (typeof columnDefault === 'string' &&
272
+ availableFilters.includes(columnDefault)) {
273
+ return columnDefault;
274
+ }
275
+ const firstFamily = Object.keys(filters)[0];
276
+ const familyDefault = filterTypeDefaults[firstFamily];
277
+ if (familyDefault && ((_a = filters[firstFamily]) === null || _a === void 0 ? void 0 : _a.includes(familyDefault))) {
278
+ return familyDefault;
279
+ }
280
+ return availableFilters[0];
281
+ }
282
+ /** Resolve grid and column-level draft opt-outs. */
283
+ shouldShowDefaultFilter(config) {
284
+ var _a;
285
+ if (this.isColumnFilterOption(config)) {
286
+ if (config.default === false) {
287
+ return false;
288
+ }
289
+ if (typeof config.default === 'string') {
290
+ return true;
291
+ }
292
+ }
293
+ return ((_a = this.config) === null || _a === void 0 ? void 0 : _a.defaultFilter) !== false;
294
+ }
295
+ isColumnFilterOption(value) {
296
+ return !!value && typeof value === 'object' && !Array.isArray(value);
297
+ }
255
298
  isValidType(type) {
256
299
  return !!(typeof type === 'string' && this.filterByType[type]);
257
300
  }
@@ -112,15 +112,36 @@ revogr-filter-panel .filter-panel-dialog .filter-actions button {
112
112
  }
113
113
  }
114
114
  .rgHeaderCell:hover .rv-filter {
115
- transition: opacity 267ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, transform 178ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
115
+ transition: opacity 267ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, width 267ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, transform 178ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
116
116
  }
117
- .rgHeaderCell:hover .rv-filter,
117
+ .rgHeaderCell:hover:has(.rv-filter) .header-content, .rgHeaderCell:focus-within:has(.rv-filter) .header-content, .rgHeaderCell:has(.rv-filter.active) .header-content {
118
+ margin-right: 24px;
119
+ }
120
+ .rgHeaderCell:hover:has(.rv-filter):has(.desc) .header-content, .rgHeaderCell:hover:has(.rv-filter):has(.asc) .header-content, .rgHeaderCell:focus-within:has(.rv-filter):has(.desc) .header-content, .rgHeaderCell:focus-within:has(.rv-filter):has(.asc) .header-content, .rgHeaderCell:has(.rv-filter.active):has(.desc) .header-content, .rgHeaderCell:has(.rv-filter.active):has(.asc) .header-content {
121
+ margin-right: 8px;
122
+ padding-right: 24px;
123
+ }
124
+ .rgHeaderCell:hover .rv-filter, .rgHeaderCell:focus-within .rv-filter,
118
125
  .rgHeaderCell .rv-filter.active {
119
126
  opacity: 1;
127
+ width: 24px;
128
+ }
129
+ @media (hover: none), (pointer: coarse) {
130
+ .rgHeaderCell:has(.rv-filter) .header-content {
131
+ margin-right: 24px;
132
+ }
133
+ .rgHeaderCell:has(.rv-filter):has(.desc) .header-content, .rgHeaderCell:has(.rv-filter):has(.asc) .header-content {
134
+ margin-right: 8px;
135
+ padding-right: 24px;
136
+ }
137
+ .rgHeaderCell .rv-filter {
138
+ opacity: 1;
139
+ width: 24px;
140
+ }
120
141
  }
121
142
  .rgHeaderCell .rv-filter {
122
143
  height: 24px;
123
- width: 24px;
144
+ width: 0;
124
145
  background: none;
125
146
  border: 0;
126
147
  opacity: 0;
@@ -129,6 +150,7 @@ revogr-filter-panel .filter-panel-dialog .filter-actions button {
129
150
  border-radius: 4px;
130
151
  position: relative;
131
152
  z-index: 1;
153
+ padding: 0;
132
154
  }
133
155
  .rgHeaderCell .rv-filter.active {
134
156
  color: var(--rg-theme-filter-panel-icon-active);
@@ -12,4 +12,5 @@ export const GROUP_COLUMN_PROP = `${GRID_INTERNALS}-prop`;
12
12
  export const GROUP_ORIGINAL_INDEX = `${GRID_INTERNALS}-original-index`;
13
13
  export const GROUP_EXPAND_BTN = `group-expand`;
14
14
  export const GROUP_EXPAND_EVENT = `groupexpandclick`;
15
+ export const BEFORE_GROUPING_APPLY_EVENT = `beforegroupingapply`;
15
16
  export const GROUPING_ROW_TYPE = 'rgRow';
@@ -1,26 +1,14 @@
1
1
  /*!
2
2
  * Built by Revolist OU ❤️
3
3
  */
4
- var __rest = (this && this.__rest) || function (s, e) {
5
- var t = {};
6
- for (var p in s)
7
- if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
8
- t[p] = s[p];
9
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
10
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
11
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
12
- t[p[i]] = s[p[i]];
13
- }
14
- return t;
15
- };
16
4
  import { getPhysical, setItems, columnTypes, } from "../../store/index";
17
5
  import { BasePlugin } from "../base.plugin";
18
6
  import { FILTER_TRIMMED_TYPE } from "../filter/filter.plugin";
19
- import { SortingPlugin } from "../sorting/sorting.plugin";
20
- import { GROUP_EXPAND_EVENT, GROUPING_ROW_TYPE, PSEUDO_GROUP_COLUMN, } from "./grouping.const";
7
+ import { SortingPlugin, hasActiveSorting } from "../sorting/sorting.plugin";
8
+ import { BEFORE_GROUPING_APPLY_EVENT, GROUP_EXPAND_EVENT, GROUPING_ROW_TYPE, PSEUDO_GROUP_COLUMN, PSEUDO_GROUP_ITEM_ID, } from "./grouping.const";
21
9
  import { doExpand, doCollapse } from "./grouping.row.expand.service";
22
10
  import { gatherGrouping, getExpanded, getSource, isGrouping, isGroupingColumn, } from "./grouping.service";
23
- import { filterOutEmptyGroupRows, processDoubleConversionTrimmed, TRIMMED_GROUPING, } from "./grouping.trimmed.service";
11
+ import { convertGroupingIndex, filterOutEmptyGroupRows, processDoubleConversionTrimmed, TRIMMED_GROUPING, } from "./grouping.trimmed.service";
24
12
  export * from './grouping.const';
25
13
  export * from './grouping.row.expand.service';
26
14
  export * from './grouping.row.types';
@@ -41,15 +29,16 @@ export class GroupingRowPlugin extends BasePlugin {
41
29
  }
42
30
  // expand event triggered
43
31
  onExpand({ virtualIndex }) {
44
- const { source } = getSource(this.getStore().get('source'), this.getStore().get('proxyItems'));
45
- let newTrimmed = this.getStore().get('trimmed')[TRIMMED_GROUPING];
46
- let i = getPhysical(this.getStore(), virtualIndex);
32
+ const store = this.getStore();
33
+ const source = store.get('source');
34
+ let newTrimmed = store.get('trimmed')[TRIMMED_GROUPING];
35
+ const i = getPhysical(store, virtualIndex);
47
36
  const isExpanded = getExpanded(source[i]);
48
37
  if (!isExpanded) {
49
- const { trimmed, items } = doExpand(virtualIndex, source, this.getStore().get('items'));
38
+ const { trimmed, items: expandedItems } = doExpand(virtualIndex, source, store.get('items'));
50
39
  newTrimmed = Object.assign(Object.assign({}, newTrimmed), trimmed);
51
- if (items) {
52
- setItems(this.getStore(), items);
40
+ if (expandedItems) {
41
+ setItems(store, expandedItems);
53
42
  }
54
43
  }
55
44
  else {
@@ -57,7 +46,7 @@ export class GroupingRowPlugin extends BasePlugin {
57
46
  newTrimmed = Object.assign(Object.assign({}, newTrimmed), trimmed);
58
47
  this.revogrid.clearFocus();
59
48
  }
60
- this.getStore().set('source', source);
49
+ store.set('source', source);
61
50
  this.revogrid.addTrimmed(newTrimmed, TRIMMED_GROUPING);
62
51
  }
63
52
  setColumnGrouping(cols) {
@@ -79,7 +68,7 @@ export class GroupingRowPlugin extends BasePlugin {
79
68
  onDrag(e) {
80
69
  const { from, to } = e.detail;
81
70
  const isDown = to - from >= 0;
82
- const { source } = getSource(this.getStore().get('source'), this.getStore().get('proxyItems'));
71
+ const source = this.getStore().get('source');
83
72
  const items = this.getStore().get('items');
84
73
  let i = isDown ? from : to;
85
74
  const end = isDown ? to : from;
@@ -105,21 +94,13 @@ export class GroupingRowPlugin extends BasePlugin {
105
94
  const source = this.getStore().get('source');
106
95
  return filterOutEmptyGroupRows(source, trimmed);
107
96
  }
108
- isSortingRunning() {
109
- const sortingPlugin = this.providers.plugins.getByClass(SortingPlugin);
110
- return !!(sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.sortingPromise);
111
- }
112
97
  /**
113
- * Returns grouping options for regrouping that must preserve current UI state.
114
- *
115
- * `expandedAll` and config `prevExpanded` are initial/config instructions.
116
- * Reusing them after sorting would reopen groups the user collapsed before
117
- * sorting instead of using the current grouped source state.
98
+ * Sorting changes proxy order without changing the physical source baseline.
99
+ * Other proxy changes, such as row dragging, are user-authored source order
100
+ * and must be retained when grouping is rebuilt.
118
101
  */
119
- getCurrentExpandedOptions() {
120
- var _a;
121
- const _b = (_a = this.options) !== null && _a !== void 0 ? _a : {}, { expandedAll: _expandedAll, prevExpanded: _prevExpanded } = _b, options = __rest(_b, ["expandedAll", "prevExpanded"]);
122
- return options;
102
+ isSortingActiveOrPending(sortingPlugin) {
103
+ return !!(sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.sortingPromise) || hasActiveSorting(sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.sorting);
123
104
  }
124
105
  /**
125
106
  * Starts global source update with group clearing and applying new one
@@ -132,7 +113,12 @@ export class GroupingRowPlugin extends BasePlugin {
132
113
  * @param newOldIndexMap - provides us mapping with new indexes vs old indexes, we would use it for trimmed mapping
133
114
  */
134
115
  const store = this.getStore();
135
- const { source, prevExpanded, oldNewIndexes } = getSource(store.get('source'), store.get('proxyItems'), true);
116
+ const sortingPlugin = this.providers.plugins.getByClass(SortingPlugin);
117
+ const currentSource = store.get('source');
118
+ const sourceItems = this.isSortingActiveOrPending(sortingPlugin)
119
+ ? currentSource.map((_, index) => index)
120
+ : store.get('proxyItems');
121
+ const { source, prevExpanded, oldNewIndexes } = getSource(currentSource, sourceItems, true);
136
122
  const expanded = Object.assign({ prevExpanded }, options);
137
123
  /**
138
124
  * Group again
@@ -142,8 +128,13 @@ export class GroupingRowPlugin extends BasePlugin {
142
128
  const customRenderer = options === null || options === void 0 ? void 0 : options.groupLabelTemplate;
143
129
  const cellRenderer = options === null || options === void 0 ? void 0 : options.groupCellTemplate;
144
130
  // setup source
131
+ this.revogrid.dispatchEvent(new CustomEvent(BEFORE_GROUPING_APPLY_EVENT));
145
132
  this.providers.data.setData(sourceWithGroups, GROUPING_ROW_TYPE, this.revogrid.disableVirtualY, { depth, customRenderer, cellRenderer }, true);
133
+ this.remapRowDefinitions(oldNewIndexes !== null && oldNewIndexes !== void 0 ? oldNewIndexes : {}, oldNewIndexMap, currentSource, sourceWithGroups);
146
134
  this.updateTrimmed(trimmed, oldNewIndexes !== null && oldNewIndexes !== void 0 ? oldNewIndexes : {}, oldNewIndexMap, sourceWithGroups);
135
+ if (hasActiveSorting(sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.sorting)) {
136
+ sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.reapplySorting();
137
+ }
147
138
  }
148
139
  /**
149
140
  * Apply grouping on data set
@@ -152,9 +143,14 @@ export class GroupingRowPlugin extends BasePlugin {
152
143
  */
153
144
  onDataSet(data) {
154
145
  var _a, _b, _c;
146
+ const currentSource = this.getStore().get('source');
147
+ const sortingPlugin = this.providers.plugins.getByClass(SortingPlugin);
148
+ const currentItems = this.isSortingActiveOrPending(sortingPlugin)
149
+ ? currentSource.map((_, index) => index)
150
+ : this.getStore().get('proxyItems');
151
+ const { prevExpanded, oldNewIndexes } = getSource(currentSource, currentItems, true);
155
152
  let preservedExpanded = {};
156
153
  if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.preserveGroupingOnUpdate) !== false) {
157
- let { prevExpanded } = getSource(this.getStore().get('source'), this.getStore().get('proxyItems'), true);
158
154
  preservedExpanded = prevExpanded;
159
155
  }
160
156
  const source = data.source.filter(s => !isGrouping(s));
@@ -166,6 +162,7 @@ export class GroupingRowPlugin extends BasePlugin {
166
162
  customRenderer: options.groupLabelTemplate,
167
163
  cellRenderer: options.groupCellTemplate,
168
164
  });
165
+ queueMicrotask(() => this.remapRowDefinitions(oldNewIndexes !== null && oldNewIndexes !== void 0 ? oldNewIndexes : {}, oldNewIndexMap, currentSource, sourceWithGroups));
169
166
  this.updateTrimmed(trimmed, oldNewIndexMap, undefined, sourceWithGroups, { filterTrimmedMode: 'recompute-after-source-set' });
170
167
  }
171
168
  /**
@@ -201,10 +198,6 @@ export class GroupingRowPlugin extends BasePlugin {
201
198
  if (!(((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length) && ((_c = detail === null || detail === void 0 ? void 0 : detail.source) === null || _c === void 0 ? void 0 : _c.length))) {
202
199
  return;
203
200
  }
204
- // if sorting is running don't apply grouping, wait for sorting, then it'll apply in @aftersortingapply
205
- if (this.isSortingRunning()) {
206
- return;
207
- }
208
201
  this.onDataSet(detail);
209
202
  });
210
203
  this.addEventListener('beforecolumnsset', ({ detail }) => {
@@ -219,17 +212,6 @@ export class GroupingRowPlugin extends BasePlugin {
219
212
  this.addEventListener('beforefiltertrimmed', ({ detail }) => {
220
213
  detail.itemsToFilter = this.beforeFilterTrimmed(detail.itemsToFilter);
221
214
  });
222
- /**
223
- * sorting applied need to clear grouping and apply again
224
- * based on new results whole grouping order will changed
225
- */
226
- this.addEventListener('aftersortingapply', () => {
227
- var _a, _b;
228
- if (!((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length)) {
229
- return;
230
- }
231
- this.doSourceUpdate(this.getCurrentExpandedOptions());
232
- });
233
215
  /**
234
216
  * Apply logic for focus inside of grouping
235
217
  * We can't focus on grouping rows, navigation only inside of groups for now
@@ -262,9 +244,57 @@ export class GroupingRowPlugin extends BasePlugin {
262
244
  }
263
245
  });
264
246
  // clear rows
265
- const { source, oldNewIndexes } = getSource(this.getStore().get('source'), this.getStore().get('proxyItems'), true);
247
+ const store = this.getStore();
248
+ const sortingPlugin = this.providers.plugins.getByClass(SortingPlugin);
249
+ const currentSource = store.get('source');
250
+ const sourceItems = this.isSortingActiveOrPending(sortingPlugin)
251
+ ? currentSource.map((_, index) => index)
252
+ : store.get('proxyItems');
253
+ const { source, oldNewIndexes } = getSource(currentSource, sourceItems, true);
254
+ this.revogrid.dispatchEvent(new CustomEvent(BEFORE_GROUPING_APPLY_EVENT));
266
255
  this.providers.data.setData(source, GROUPING_ROW_TYPE, this.revogrid.disableVirtualY, undefined, true);
256
+ this.remapRowDefinitions(oldNewIndexes !== null && oldNewIndexes !== void 0 ? oldNewIndexes : {}, undefined, currentSource, source);
267
257
  this.updateTrimmed(undefined, undefined, oldNewIndexes, source);
258
+ if (hasActiveSorting(sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.sorting)) {
259
+ sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.reapplySorting();
260
+ }
261
+ }
262
+ remapRowDefinitions(firstLevelMap, secondLevelMap, previousSource, nextSource) {
263
+ const definitions = this.providers.dimension.getRowDefinitions();
264
+ const nextGroupIndexes = new Map();
265
+ nextSource === null || nextSource === void 0 ? void 0 : nextSource.forEach((row, index) => {
266
+ const groupId = row[PSEUDO_GROUP_ITEM_ID];
267
+ if (groupId && !nextGroupIndexes.has(groupId)) {
268
+ nextGroupIndexes.set(groupId, index);
269
+ }
270
+ });
271
+ let changed = false;
272
+ const remapped = definitions.flatMap(definition => {
273
+ if (definition.type !== GROUPING_ROW_TYPE) {
274
+ return [definition];
275
+ }
276
+ const previousRow = previousSource === null || previousSource === void 0 ? void 0 : previousSource[definition.index];
277
+ const groupId = previousRow === null || previousRow === void 0 ? void 0 : previousRow[PSEUDO_GROUP_ITEM_ID];
278
+ const index = groupId
279
+ ? nextGroupIndexes.get(groupId)
280
+ : convertGroupingIndex(definition.index, firstLevelMap, secondLevelMap);
281
+ if (typeof index !== 'number') {
282
+ changed = true;
283
+ return [];
284
+ }
285
+ if (index < 0) {
286
+ changed = true;
287
+ return [];
288
+ }
289
+ if (index === definition.index) {
290
+ return [definition];
291
+ }
292
+ changed = true;
293
+ return [Object.assign(Object.assign({}, definition), { index })];
294
+ });
295
+ if (changed) {
296
+ this.providers.dimension.setRowDefinitions(remapped);
297
+ }
268
298
  }
269
299
  updateTrimmed(trimmedGroup = {}, firstLevelMap = {}, secondLevelMap, source = this.getStore().get('source'), { filterTrimmedMode = 'remap', } = {}) {
270
300
  // map previously trimmed data
@@ -0,0 +1,58 @@
1
+ /*!
2
+ * Built by Revolist OU ❤️
3
+ */
4
+ import { GROUP_DEPTH } from "./grouping.const";
5
+ import { isGrouping } from "./grouping.service";
6
+ /**
7
+ * Restores group headers around already-sorted data indexes without rebuilding
8
+ * the physical source. Group insertion order follows the first sorted member,
9
+ * matching the order produced by regrouping a sorted source.
10
+ */
11
+ export function gatherGroupedRowIndexes(source, sortedDataIndexes) {
12
+ const groupPathByDataIndex = new Map();
13
+ const currentGroupPath = [];
14
+ source.forEach((model, physicalIndex) => {
15
+ if (isGrouping(model)) {
16
+ const depth = model[GROUP_DEPTH];
17
+ if (typeof depth !== 'number') {
18
+ return;
19
+ }
20
+ currentGroupPath.length = depth;
21
+ currentGroupPath[depth] = physicalIndex;
22
+ return;
23
+ }
24
+ if (model != null) {
25
+ groupPathByDataIndex.set(physicalIndex, [...currentGroupPath]);
26
+ }
27
+ });
28
+ const root = {
29
+ children: new Map(),
30
+ items: [],
31
+ };
32
+ for (const physicalIndex of sortedDataIndexes) {
33
+ const groupPath = groupPathByDataIndex.get(physicalIndex);
34
+ if (!(groupPath === null || groupPath === void 0 ? void 0 : groupPath.length)) {
35
+ return undefined;
36
+ }
37
+ let node = root;
38
+ for (const groupIndex of groupPath) {
39
+ let child = node.children.get(groupIndex);
40
+ if (!child) {
41
+ child = { children: new Map(), items: [] };
42
+ node.children.set(groupIndex, child);
43
+ }
44
+ node = child;
45
+ }
46
+ node.items.push(physicalIndex);
47
+ }
48
+ const groupedIndexes = [];
49
+ const appendNode = (node) => {
50
+ node.children.forEach((child, groupIndex) => {
51
+ groupedIndexes.push(groupIndex);
52
+ appendNode(child);
53
+ });
54
+ groupedIndexes.push(...node.items);
55
+ };
56
+ appendNode(root);
57
+ return groupedIndexes;
58
+ }
@@ -13,8 +13,10 @@ export const TRIMMED_GROUPING = 'grouping';
13
13
  * against the grouped physical source can still be remapped. If neither path
14
14
  * resolves to a number, the caller drops the stale trim entry.
15
15
  */
16
- function convertTrimmedIndex(initialIndex, firstLevelMap, secondLevelMap) {
17
- const sourceIndex = Number.parseInt(initialIndex, 10);
16
+ export function convertGroupingIndex(initialIndex, firstLevelMap, secondLevelMap) {
17
+ const sourceIndex = typeof initialIndex === 'number'
18
+ ? initialIndex
19
+ : Number.parseInt(initialIndex, 10);
18
20
  const firstConversionIndex = firstLevelMap[sourceIndex];
19
21
  if (!secondLevelMap) {
20
22
  return firstConversionIndex;
@@ -47,7 +49,7 @@ export function processDoubleConversionTrimmed(initiallyTrimed, firstLevelMap, s
47
49
  * if item exists we find it in collection
48
50
  * we support 2 level of conversions
49
51
  */
50
- const newConversionIndex = convertTrimmedIndex(initialIndex, firstLevelMap, secondLevelMap);
52
+ const newConversionIndex = convertGroupingIndex(initialIndex, firstLevelMap, secondLevelMap);
51
53
  // Group rows do not exist in the ungrouped index map and must not leak into new trims.
52
54
  if (typeof newConversionIndex !== 'number') {
53
55
  continue;