@revolist/revogrid 3.2.17 → 3.3.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.
@@ -11,123 +11,91 @@ const PSEUDO_GROUP_ITEM_ID = `${GRID_INTERNALS}-id`;
11
11
  const PSEUDO_GROUP_ITEM_VALUE = `${GRID_INTERNALS}-value`;
12
12
  const PSEUDO_GROUP_COLUMN = `${GRID_INTERNALS}-column`;
13
13
  const GROUP_EXPANDED = `${GRID_INTERNALS}-expanded`;
14
+ const GROUP_ORIGINAL_INDEX = `${GRID_INTERNALS}-original-index`;
14
15
  const GROUP_EXPAND_BTN = `group-expand`;
15
16
  const GROUP_EXPAND_EVENT = `groupExpandClick`;
16
17
  const GROUPING_ROW_TYPE = 'rgRow';
17
18
 
18
- /**
19
- * Do actual grouping
20
- * @param array - items to group
21
- * @param f - function responsible for grouping, returns property to group by
22
- */
23
- function groupBy(array, f) {
24
- const groupsOrder = [];
25
- const itemsByGroup = {};
26
- array.forEach((item, i) => {
27
- // get grouping values
28
- const groupKeys = JSON.stringify(f(item));
29
- // new group identification
30
- if (!itemsByGroup[groupKeys]) {
31
- itemsByGroup[groupKeys] = new Map();
32
- // create group parents
33
- groupsOrder.push({
34
- children: itemsByGroup[groupKeys],
35
- id: groupKeys,
36
- });
37
- }
38
- // save to group with previous index
39
- itemsByGroup[groupKeys].set(i, item);
40
- });
41
- return groupsOrder;
42
- }
43
19
  /**
44
20
  * Gather data for grouping
45
21
  * @param array - flat data array
46
- * @param mapFunc - mapping function for stringify
22
+ * @param groupIds - ids of groups
47
23
  * @param expanded - potentially expanded items if present
48
24
  */
49
- function gatherGrouping(array, mapFunc, { prevExpanded, expandedAll }) {
50
- // build groups
51
- const groupsOrder = groupBy(array, mapFunc);
52
- const itemsMirror = []; // grouped source
53
- const pseudoGroupTest = {}; // check if group header exists
54
- // item index in source
55
- let itemIndex = 0;
56
- // to save max group depth
57
- let groupingDepth = 0;
25
+ function gatherGrouping(array, groupIds, { prevExpanded, expandedAll }) {
26
+ const groupedItems = new Map();
27
+ array.forEach((item, originalIndex) => {
28
+ const groupLevelValues = groupIds.map((groupId) => item[groupId] || null);
29
+ const lastLevelValue = groupLevelValues.pop();
30
+ let currentGroupLevel = groupedItems;
31
+ groupLevelValues.forEach((value) => {
32
+ if (!currentGroupLevel.has(value)) {
33
+ currentGroupLevel.set(value, new Map());
34
+ }
35
+ currentGroupLevel = currentGroupLevel.get(value);
36
+ });
37
+ if (!currentGroupLevel.has(lastLevelValue)) {
38
+ currentGroupLevel.set(lastLevelValue, []);
39
+ }
40
+ item[GROUP_ORIGINAL_INDEX] = originalIndex;
41
+ const lastLevelItems = currentGroupLevel.get(lastLevelValue);
42
+ lastLevelItems.push(item);
43
+ });
44
+ let itemIndex = -1;
45
+ const groupingDepth = groupIds.length;
58
46
  // collapse all groups in the beginning
59
47
  const trimmed = {};
60
48
  // index mapping
61
49
  const oldNewIndexMap = {};
62
- // go through groups
63
- groupsOrder.forEach(group => {
64
- const parseGroup = getParsedGroup(group.id);
65
- // extra precaution and type safe guard
66
- if (!parseGroup) {
67
- return;
68
- }
69
- let depth = 0;
70
- let skipTrim = !!expandedAll;
71
- let isExpanded = skipTrim;
72
- const children = [];
73
- // add group headers
74
- parseGroup.reduce((prevVal, groupValue) => {
75
- prevVal.push(groupValue);
76
- const newVal = prevVal.join(',');
77
- // if header not added, add new header
78
- if (!pseudoGroupTest[newVal]) {
79
- isExpanded = expandedAll || (prevExpanded && prevExpanded[newVal]);
80
- itemsMirror.push(getPseudoGroup(groupValue, newVal, depth, group.id, isExpanded));
81
- // if not first level auto collapse
82
- if (depth && !isExpanded && !skipTrim) {
83
- // check if parent expanded, expand this layer too
84
- const parent = prevVal.slice(0, prevVal.length - 1);
85
- if (!(prevExpanded && parent.length && prevExpanded[parent.join(',')])) {
50
+ // check if group header exists
51
+ const pseudoGroupTest = {};
52
+ const sourceWithGroups = [];
53
+ function flattenGroupMaps(groupedValues, parentIds, isExpanded) {
54
+ const depth = parentIds.length;
55
+ groupedValues.forEach((innerGroupedValues, groupId) => {
56
+ const levelIds = [...parentIds, groupId];
57
+ const mergedIds = levelIds.join(',');
58
+ const isGroupExpanded = isExpanded && (!!expandedAll || !!(prevExpanded === null || prevExpanded === void 0 ? void 0 : prevExpanded[mergedIds]));
59
+ sourceWithGroups.push({
60
+ [PSEUDO_GROUP_ITEM]: groupId,
61
+ [GROUP_DEPTH]: depth,
62
+ [PSEUDO_GROUP_ITEM_ID]: JSON.stringify(levelIds),
63
+ [PSEUDO_GROUP_ITEM_VALUE]: mergedIds,
64
+ [GROUP_EXPANDED]: isGroupExpanded,
65
+ });
66
+ itemIndex += 1;
67
+ if (!isGroupExpanded && depth) {
68
+ trimmed[itemIndex] = true;
69
+ }
70
+ if (Array.isArray(innerGroupedValues)) {
71
+ innerGroupedValues.forEach((value) => {
72
+ itemIndex += 1;
73
+ if (!isGroupExpanded) {
86
74
  trimmed[itemIndex] = true;
87
75
  }
88
- }
89
- itemIndex++;
90
- pseudoGroupTest[newVal] = children;
76
+ oldNewIndexMap[value[GROUP_ORIGINAL_INDEX]] = itemIndex;
77
+ const pseudoGroupTestIds = levelIds.map((_value, index) => levelIds.slice(0, index + 1).join(','));
78
+ pseudoGroupTestIds.forEach((pseudoGroupTestId) => {
79
+ if (!pseudoGroupTest[pseudoGroupTestId]) {
80
+ pseudoGroupTest[pseudoGroupTestId] = [];
81
+ }
82
+ pseudoGroupTest[pseudoGroupTestId].push(itemIndex);
83
+ });
84
+ });
85
+ sourceWithGroups.push(...innerGroupedValues);
91
86
  }
92
- // calculate depth
93
- depth++;
94
- groupingDepth = depth;
95
- return prevVal;
96
- }, []);
97
- // add regular items
98
- group.children.forEach((item, oldIndex) => {
99
- // hide items if group colapsed
100
- if (!isExpanded && !skipTrim) {
101
- // collapse rgRow
102
- trimmed[itemIndex] = true;
87
+ else {
88
+ flattenGroupMaps(innerGroupedValues, levelIds, isGroupExpanded);
103
89
  }
104
- // add items to new source
105
- itemsMirror.push(item);
106
- oldNewIndexMap[oldIndex] = itemIndex;
107
- children.push(itemIndex);
108
- itemIndex++;
109
90
  });
110
- });
91
+ }
92
+ flattenGroupMaps(groupedItems, [], true);
111
93
  return {
112
- // updates source mirror
113
- sourceWithGroups: itemsMirror,
114
- // largest depth for grouping
94
+ sourceWithGroups,
115
95
  depth: groupingDepth,
116
- // used for expand/collapse grouping values
117
96
  trimmed,
118
- // used for mapping old values to new
119
97
  oldNewIndexMap,
120
- // used to get child items in group
121
- childrenByGroup: pseudoGroupTest,
122
- };
123
- }
124
- function getPseudoGroup(groupValue, value, depth, id, isExpanded = false) {
125
- return {
126
- [PSEUDO_GROUP_ITEM]: groupValue,
127
- [GROUP_DEPTH]: depth,
128
- [PSEUDO_GROUP_ITEM_ID]: id,
129
- [PSEUDO_GROUP_ITEM_VALUE]: value,
130
- [GROUP_EXPANDED]: isExpanded,
98
+ childrenByGroup: pseudoGroupTest, // used to get child items in group
131
99
  };
132
100
  }
133
101
  function getGroupingName(rgRow) {
@@ -139,9 +107,6 @@ function isGrouping(rgRow) {
139
107
  function isGroupingColumn(column) {
140
108
  return column && typeof column[PSEUDO_GROUP_COLUMN] !== 'undefined';
141
109
  }
142
- function isArray(data) {
143
- return typeof data.push !== 'undefined';
144
- }
145
110
  function measureEqualDepth(groupA, groupB) {
146
111
  const ln = groupA.length;
147
112
  let i = 0;
@@ -155,7 +120,7 @@ function measureEqualDepth(groupA, groupB) {
155
120
  function getParsedGroup(id) {
156
121
  const parseGroup = JSON.parse(id);
157
122
  // extra precaution and type safe guard
158
- if (!isArray(parseGroup)) {
123
+ if (!Array.isArray(parseGroup)) {
159
124
  return null;
160
125
  }
161
126
  return parseGroup;
@@ -740,4 +705,4 @@ class ColumnService {
740
705
  }
741
706
  }
742
707
 
743
- export { ColumnService as C, EMPTY_INDEX as E, GROUP_EXPANDED as G, PSEUDO_GROUP_ITEM_ID as P, SelectionStoreConnector as S, getParsedGroup as a, isSameGroup as b, GROUP_DEPTH as c, GROUPING_ROW_TYPE as d, PSEUDO_GROUP_ITEM_VALUE as e, PSEUDO_GROUP_COLUMN as f, getGroupingName as g, GROUP_EXPAND_EVENT as h, isGrouping as i, gatherGrouping as j, isGroupingColumn as k, GROUP_EXPAND_BTN as l, PSEUDO_GROUP_ITEM as m, getRange as n, isRangeSingleCell as o };
708
+ export { ColumnService as C, EMPTY_INDEX as E, GROUP_EXPANDED as G, PSEUDO_GROUP_ITEM_VALUE as P, SelectionStoreConnector as S, getParsedGroup as a, isSameGroup as b, GROUP_DEPTH as c, PSEUDO_GROUP_ITEM_ID as d, GROUPING_ROW_TYPE as e, PSEUDO_GROUP_COLUMN as f, getGroupingName as g, GROUP_EXPAND_EVENT as h, isGrouping as i, gatherGrouping as j, isGroupingColumn as k, GROUP_EXPAND_BTN as l, PSEUDO_GROUP_ITEM as m, getRange as n, isRangeSingleCell as o };
@@ -474,6 +474,7 @@ class DataStore {
474
474
  setStore(this.store, {
475
475
  groupingDepth: grouping.depth,
476
476
  groups: grouping.groups,
477
+ groupingCustomRenderer: grouping.customRenderer,
477
478
  });
478
479
  }
479
480
  }
@@ -13,7 +13,7 @@ import { t as timeout, g as getScrollbarWidth } from './utils.js';
13
13
  import { i as isFilterBtn, F as FILTER_PROP } from './filter.button.js';
14
14
  import { i as isString_1, d as defineCustomElement$a } from './revogr-edit2.js';
15
15
  import { t as toInteger_1 } from './toInteger.js';
16
- import { i as isGrouping, g as getGroupingName, P as PSEUDO_GROUP_ITEM_ID, G as GROUP_EXPANDED, a as getParsedGroup, b as isSameGroup, c as GROUP_DEPTH, d as GROUPING_ROW_TYPE, e as PSEUDO_GROUP_ITEM_VALUE, f as PSEUDO_GROUP_COLUMN, h as GROUP_EXPAND_EVENT, j as gatherGrouping, k as isGroupingColumn, E as EMPTY_INDEX, S as SelectionStoreConnector } from './columnService.js';
16
+ import { i as isGrouping, g as getGroupingName, G as GROUP_EXPANDED, a as getParsedGroup, b as isSameGroup, c as GROUP_DEPTH, P as PSEUDO_GROUP_ITEM_VALUE, d as PSEUDO_GROUP_ITEM_ID, e as GROUPING_ROW_TYPE, f as PSEUDO_GROUP_COLUMN, h as GROUP_EXPAND_EVENT, j as gatherGrouping, k as isGroupingColumn, E as EMPTY_INDEX, S as SelectionStoreConnector } from './columnService.js';
17
17
  import { g as getLastCell, H as HEADER_SLOT, C as CONTENT_SLOT, F as FOOTER_SLOT, D as DATA_SLOT, d as defineCustomElement$2 } from './revogr-viewport-scroll2.js';
18
18
  import { l as lodash, d as defineCustomElement$3 } from './revogr-temp-range2.js';
19
19
  import { d as debounce_1 } from './debounce.js';
@@ -1936,19 +1936,18 @@ class ExportFilePlugin extends BasePlugin {
1936
1936
  // provide collapse data
1937
1937
  function doCollapse(pIndex, source) {
1938
1938
  const model = source[pIndex];
1939
- const currentId = model[PSEUDO_GROUP_ITEM_ID];
1939
+ const collapseValue = model[PSEUDO_GROUP_ITEM_VALUE];
1940
1940
  const trimmed = {};
1941
1941
  let i = pIndex + 1;
1942
1942
  const total = source.length;
1943
1943
  while (i < total) {
1944
1944
  const currentModel = source[i];
1945
1945
  if (isGrouping(currentModel)) {
1946
- if (currentId !== currentModel[PSEUDO_GROUP_ITEM_ID]) {
1946
+ const currentValue = currentModel[PSEUDO_GROUP_ITEM_VALUE];
1947
+ if (!currentValue.length || !currentValue.startsWith(collapseValue + ',')) {
1947
1948
  break;
1948
1949
  }
1949
- else {
1950
- currentModel[GROUP_EXPANDED] = false;
1951
- }
1950
+ currentModel[GROUP_EXPANDED] = false;
1952
1951
  }
1953
1952
  trimmed[i++] = true;
1954
1953
  }
@@ -2188,7 +2187,7 @@ class GroupingRowPlugin extends BasePlugin {
2188
2187
  * sorting applied need to clear grouping and apply again
2189
2188
  * based on new results whole grouping order will changed
2190
2189
  */
2191
- this.addEventListener('afterSortingApply', () => this.doSourceUpdate());
2190
+ this.addEventListener('afterSortingApply', () => this.doSourceUpdate(Object.assign({}, this.options)));
2192
2191
  /**
2193
2192
  * Apply logic for focus inside of grouping
2194
2193
  * We can't focus on grouping rows, navigation only inside of groups for now
@@ -2208,6 +2207,7 @@ class GroupingRowPlugin extends BasePlugin {
2208
2207
  * Initiated when need to reapply grouping
2209
2208
  */
2210
2209
  doSourceUpdate(options) {
2210
+ var _a;
2211
2211
  if (!this.hasProps) {
2212
2212
  return;
2213
2213
  }
@@ -2220,11 +2220,9 @@ class GroupingRowPlugin extends BasePlugin {
2220
2220
  * Group again
2221
2221
  * @param oldNewIndexMap - provides us mapping with new indexes vs old indexes
2222
2222
  */
2223
- const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup } = gatherGrouping(source,
2224
- // filter
2225
- item => { var _a; return (_a = this.options) === null || _a === void 0 ? void 0 : _a.props.map(key => item[key]); }, Object.assign({ prevExpanded }, options));
2223
+ const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup } = gatherGrouping(source, ((_a = this.options) === null || _a === void 0 ? void 0 : _a.props) || [], Object.assign({ prevExpanded }, options));
2226
2224
  // setup source
2227
- this.providers.dataProvider.setData(sourceWithGroups, GROUPING_ROW_TYPE, { depth }, true);
2225
+ this.providers.dataProvider.setData(sourceWithGroups, GROUPING_ROW_TYPE, { depth, customRenderer: options === null || options === void 0 ? void 0 : options.groupLabelTemplate }, true);
2228
2226
  this.updateTrimmed(trimmed, childrenByGroup, oldNewIndexes, oldNewIndexMap);
2229
2227
  }
2230
2228
  /**
@@ -2233,14 +2231,13 @@ class GroupingRowPlugin extends BasePlugin {
2233
2231
  * If source came from other plugin
2234
2232
  */
2235
2233
  onDataSet(data) {
2234
+ var _a;
2236
2235
  if (!this.hasProps || !(data === null || data === void 0 ? void 0 : data.source) || !data.source.length) {
2237
2236
  return;
2238
2237
  }
2239
2238
  const source = data.source.filter(s => !isGrouping(s));
2240
2239
  const expanded = this.revogrid.grouping || {};
2241
- const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup } = gatherGrouping(source,
2242
- // filter
2243
- item => { var _a; return (_a = this.options) === null || _a === void 0 ? void 0 : _a.props.map(key => item[key]); }, Object.assign({}, (expanded || {})));
2240
+ const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup } = gatherGrouping(source, ((_a = this.options) === null || _a === void 0 ? void 0 : _a.props) || [], Object.assign({}, (expanded || {})));
2244
2241
  data.source = sourceWithGroups;
2245
2242
  this.providers.dataProvider.setGrouping({ depth });
2246
2243
  this.updateTrimmed(trimmed, childrenByGroup, oldNewIndexMap);
@@ -44,13 +44,17 @@ function expandEvent(e, model, virtualIndex) {
44
44
  e.target.dispatchEvent(event);
45
45
  }
46
46
  const GroupingRowRenderer = (props) => {
47
- const { model, itemIndex, hasExpand } = props;
47
+ const { model, itemIndex, hasExpand, groupingCustomRenderer } = props;
48
48
  const name = model[PSEUDO_GROUP_ITEM];
49
49
  const expanded = model[GROUP_EXPANDED];
50
50
  const depth = parseInt(model[GROUP_DEPTH], 10) || 0;
51
51
  if (!hasExpand) {
52
52
  return h(RowRenderer, Object.assign({}, props, { rowClass: "groupingRow", depth: depth }));
53
53
  }
54
+ if (groupingCustomRenderer) {
55
+ return (h(RowRenderer, Object.assign({}, props, { rowClass: "groupingRow", depth: depth }),
56
+ h("div", { onClick: e => expandEvent(e, model, itemIndex) }, groupingCustomRenderer(h, { name, itemIndex, expanded, depth }))));
57
+ }
54
58
  return (h(RowRenderer, Object.assign({}, props, { rowClass: "groupingRow", depth: depth }),
55
59
  h("button", { class: { [GROUP_EXPAND_BTN]: true }, onClick: e => expandEvent(e, model, itemIndex) },
56
60
  h("svg", { "aria-hidden": "true", style: { transform: `rotate(${!expanded ? -90 : 0}deg)` }, focusable: "false", viewBox: "0 0 448 512" },
@@ -88,11 +92,12 @@ const RevogrData = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
88
92
  const range = (_a = this.rowSelectionStore) === null || _a === void 0 ? void 0 : _a.get('range');
89
93
  const rowsEls = [];
90
94
  const depth = this.dataStore.get('groupingDepth');
95
+ const groupingCustomRenderer = this.dataStore.get('groupingCustomRenderer');
91
96
  for (let rgRow of rows) {
92
97
  const dataRow = getSourceItem(this.dataStore, rgRow.itemIndex);
93
98
  /** grouping */
94
99
  if (isGrouping(dataRow)) {
95
- rowsEls.push(h(GroupingRowRenderer, Object.assign({}, rgRow, { model: dataRow, hasExpand: this.columnService.hasGrouping })));
100
+ rowsEls.push(h(GroupingRowRenderer, Object.assign({}, rgRow, { model: dataRow, groupingCustomRenderer: groupingCustomRenderer, hasExpand: this.columnService.hasGrouping })));
96
101
  continue;
97
102
  }
98
103
  /** grouping end */
@@ -229,9 +229,9 @@ var isArguments_1 = isArguments;
229
229
  * _.isArray(_.noop);
230
230
  * // => false
231
231
  */
232
- var isArray$1 = Array.isArray;
232
+ var isArray = Array.isArray;
233
233
 
234
- var isArray_1 = isArray$1;
234
+ var isArray_1 = isArray;
235
235
 
236
236
  /**
237
237
  * This method returns `false`.
@@ -3627,6 +3627,7 @@ class DataStore {
3627
3627
  setStore(this.store, {
3628
3628
  groupingDepth: grouping.depth,
3629
3629
  groups: grouping.groups,
3630
+ groupingCustomRenderer: grouping.customRenderer,
3630
3631
  });
3631
3632
  }
3632
3633
  }
@@ -5903,123 +5904,91 @@ const PSEUDO_GROUP_ITEM_ID = `${GRID_INTERNALS}-id`;
5903
5904
  const PSEUDO_GROUP_ITEM_VALUE = `${GRID_INTERNALS}-value`;
5904
5905
  const PSEUDO_GROUP_COLUMN = `${GRID_INTERNALS}-column`;
5905
5906
  const GROUP_EXPANDED = `${GRID_INTERNALS}-expanded`;
5907
+ const GROUP_ORIGINAL_INDEX = `${GRID_INTERNALS}-original-index`;
5906
5908
  const GROUP_EXPAND_BTN = `group-expand`;
5907
5909
  const GROUP_EXPAND_EVENT = `groupExpandClick`;
5908
5910
  const GROUPING_ROW_TYPE = 'rgRow';
5909
5911
 
5910
- /**
5911
- * Do actual grouping
5912
- * @param array - items to group
5913
- * @param f - function responsible for grouping, returns property to group by
5914
- */
5915
- function groupBy(array, f) {
5916
- const groupsOrder = [];
5917
- const itemsByGroup = {};
5918
- array.forEach((item, i) => {
5919
- // get grouping values
5920
- const groupKeys = JSON.stringify(f(item));
5921
- // new group identification
5922
- if (!itemsByGroup[groupKeys]) {
5923
- itemsByGroup[groupKeys] = new Map();
5924
- // create group parents
5925
- groupsOrder.push({
5926
- children: itemsByGroup[groupKeys],
5927
- id: groupKeys,
5928
- });
5929
- }
5930
- // save to group with previous index
5931
- itemsByGroup[groupKeys].set(i, item);
5932
- });
5933
- return groupsOrder;
5934
- }
5935
5912
  /**
5936
5913
  * Gather data for grouping
5937
5914
  * @param array - flat data array
5938
- * @param mapFunc - mapping function for stringify
5915
+ * @param groupIds - ids of groups
5939
5916
  * @param expanded - potentially expanded items if present
5940
5917
  */
5941
- function gatherGrouping(array, mapFunc, { prevExpanded, expandedAll }) {
5942
- // build groups
5943
- const groupsOrder = groupBy(array, mapFunc);
5944
- const itemsMirror = []; // grouped source
5945
- const pseudoGroupTest = {}; // check if group header exists
5946
- // item index in source
5947
- let itemIndex = 0;
5948
- // to save max group depth
5949
- let groupingDepth = 0;
5918
+ function gatherGrouping(array, groupIds, { prevExpanded, expandedAll }) {
5919
+ const groupedItems = new Map();
5920
+ array.forEach((item, originalIndex) => {
5921
+ const groupLevelValues = groupIds.map((groupId) => item[groupId] || null);
5922
+ const lastLevelValue = groupLevelValues.pop();
5923
+ let currentGroupLevel = groupedItems;
5924
+ groupLevelValues.forEach((value) => {
5925
+ if (!currentGroupLevel.has(value)) {
5926
+ currentGroupLevel.set(value, new Map());
5927
+ }
5928
+ currentGroupLevel = currentGroupLevel.get(value);
5929
+ });
5930
+ if (!currentGroupLevel.has(lastLevelValue)) {
5931
+ currentGroupLevel.set(lastLevelValue, []);
5932
+ }
5933
+ item[GROUP_ORIGINAL_INDEX] = originalIndex;
5934
+ const lastLevelItems = currentGroupLevel.get(lastLevelValue);
5935
+ lastLevelItems.push(item);
5936
+ });
5937
+ let itemIndex = -1;
5938
+ const groupingDepth = groupIds.length;
5950
5939
  // collapse all groups in the beginning
5951
5940
  const trimmed = {};
5952
5941
  // index mapping
5953
5942
  const oldNewIndexMap = {};
5954
- // go through groups
5955
- groupsOrder.forEach(group => {
5956
- const parseGroup = getParsedGroup(group.id);
5957
- // extra precaution and type safe guard
5958
- if (!parseGroup) {
5959
- return;
5960
- }
5961
- let depth = 0;
5962
- let skipTrim = !!expandedAll;
5963
- let isExpanded = skipTrim;
5964
- const children = [];
5965
- // add group headers
5966
- parseGroup.reduce((prevVal, groupValue) => {
5967
- prevVal.push(groupValue);
5968
- const newVal = prevVal.join(',');
5969
- // if header not added, add new header
5970
- if (!pseudoGroupTest[newVal]) {
5971
- isExpanded = expandedAll || (prevExpanded && prevExpanded[newVal]);
5972
- itemsMirror.push(getPseudoGroup(groupValue, newVal, depth, group.id, isExpanded));
5973
- // if not first level auto collapse
5974
- if (depth && !isExpanded && !skipTrim) {
5975
- // check if parent expanded, expand this layer too
5976
- const parent = prevVal.slice(0, prevVal.length - 1);
5977
- if (!(prevExpanded && parent.length && prevExpanded[parent.join(',')])) {
5943
+ // check if group header exists
5944
+ const pseudoGroupTest = {};
5945
+ const sourceWithGroups = [];
5946
+ function flattenGroupMaps(groupedValues, parentIds, isExpanded) {
5947
+ const depth = parentIds.length;
5948
+ groupedValues.forEach((innerGroupedValues, groupId) => {
5949
+ const levelIds = [...parentIds, groupId];
5950
+ const mergedIds = levelIds.join(',');
5951
+ const isGroupExpanded = isExpanded && (!!expandedAll || !!(prevExpanded === null || prevExpanded === void 0 ? void 0 : prevExpanded[mergedIds]));
5952
+ sourceWithGroups.push({
5953
+ [PSEUDO_GROUP_ITEM]: groupId,
5954
+ [GROUP_DEPTH]: depth,
5955
+ [PSEUDO_GROUP_ITEM_ID]: JSON.stringify(levelIds),
5956
+ [PSEUDO_GROUP_ITEM_VALUE]: mergedIds,
5957
+ [GROUP_EXPANDED]: isGroupExpanded,
5958
+ });
5959
+ itemIndex += 1;
5960
+ if (!isGroupExpanded && depth) {
5961
+ trimmed[itemIndex] = true;
5962
+ }
5963
+ if (Array.isArray(innerGroupedValues)) {
5964
+ innerGroupedValues.forEach((value) => {
5965
+ itemIndex += 1;
5966
+ if (!isGroupExpanded) {
5978
5967
  trimmed[itemIndex] = true;
5979
5968
  }
5980
- }
5981
- itemIndex++;
5982
- pseudoGroupTest[newVal] = children;
5969
+ oldNewIndexMap[value[GROUP_ORIGINAL_INDEX]] = itemIndex;
5970
+ const pseudoGroupTestIds = levelIds.map((_value, index) => levelIds.slice(0, index + 1).join(','));
5971
+ pseudoGroupTestIds.forEach((pseudoGroupTestId) => {
5972
+ if (!pseudoGroupTest[pseudoGroupTestId]) {
5973
+ pseudoGroupTest[pseudoGroupTestId] = [];
5974
+ }
5975
+ pseudoGroupTest[pseudoGroupTestId].push(itemIndex);
5976
+ });
5977
+ });
5978
+ sourceWithGroups.push(...innerGroupedValues);
5983
5979
  }
5984
- // calculate depth
5985
- depth++;
5986
- groupingDepth = depth;
5987
- return prevVal;
5988
- }, []);
5989
- // add regular items
5990
- group.children.forEach((item, oldIndex) => {
5991
- // hide items if group colapsed
5992
- if (!isExpanded && !skipTrim) {
5993
- // collapse rgRow
5994
- trimmed[itemIndex] = true;
5980
+ else {
5981
+ flattenGroupMaps(innerGroupedValues, levelIds, isGroupExpanded);
5995
5982
  }
5996
- // add items to new source
5997
- itemsMirror.push(item);
5998
- oldNewIndexMap[oldIndex] = itemIndex;
5999
- children.push(itemIndex);
6000
- itemIndex++;
6001
5983
  });
6002
- });
5984
+ }
5985
+ flattenGroupMaps(groupedItems, [], true);
6003
5986
  return {
6004
- // updates source mirror
6005
- sourceWithGroups: itemsMirror,
6006
- // largest depth for grouping
5987
+ sourceWithGroups,
6007
5988
  depth: groupingDepth,
6008
- // used for expand/collapse grouping values
6009
5989
  trimmed,
6010
- // used for mapping old values to new
6011
5990
  oldNewIndexMap,
6012
- // used to get child items in group
6013
- childrenByGroup: pseudoGroupTest,
6014
- };
6015
- }
6016
- function getPseudoGroup(groupValue, value, depth, id, isExpanded = false) {
6017
- return {
6018
- [PSEUDO_GROUP_ITEM]: groupValue,
6019
- [GROUP_DEPTH]: depth,
6020
- [PSEUDO_GROUP_ITEM_ID]: id,
6021
- [PSEUDO_GROUP_ITEM_VALUE]: value,
6022
- [GROUP_EXPANDED]: isExpanded,
5991
+ childrenByGroup: pseudoGroupTest, // used to get child items in group
6023
5992
  };
6024
5993
  }
6025
5994
  function getGroupingName(rgRow) {
@@ -6031,9 +6000,6 @@ function isGrouping(rgRow) {
6031
6000
  function isGroupingColumn(column) {
6032
6001
  return column && typeof column[PSEUDO_GROUP_COLUMN] !== 'undefined';
6033
6002
  }
6034
- function isArray(data) {
6035
- return typeof data.push !== 'undefined';
6036
- }
6037
6003
  function measureEqualDepth(groupA, groupB) {
6038
6004
  const ln = groupA.length;
6039
6005
  let i = 0;
@@ -6047,7 +6013,7 @@ function measureEqualDepth(groupA, groupB) {
6047
6013
  function getParsedGroup(id) {
6048
6014
  const parseGroup = JSON.parse(id);
6049
6015
  // extra precaution and type safe guard
6050
- if (!isArray(parseGroup)) {
6016
+ if (!Array.isArray(parseGroup)) {
6051
6017
  return null;
6052
6018
  }
6053
6019
  return parseGroup;
@@ -6294,19 +6260,18 @@ class ExportFilePlugin extends BasePlugin {
6294
6260
  // provide collapse data
6295
6261
  function doCollapse(pIndex, source) {
6296
6262
  const model = source[pIndex];
6297
- const currentId = model[PSEUDO_GROUP_ITEM_ID];
6263
+ const collapseValue = model[PSEUDO_GROUP_ITEM_VALUE];
6298
6264
  const trimmed = {};
6299
6265
  let i = pIndex + 1;
6300
6266
  const total = source.length;
6301
6267
  while (i < total) {
6302
6268
  const currentModel = source[i];
6303
6269
  if (isGrouping(currentModel)) {
6304
- if (currentId !== currentModel[PSEUDO_GROUP_ITEM_ID]) {
6270
+ const currentValue = currentModel[PSEUDO_GROUP_ITEM_VALUE];
6271
+ if (!currentValue.length || !currentValue.startsWith(collapseValue + ',')) {
6305
6272
  break;
6306
6273
  }
6307
- else {
6308
- currentModel[GROUP_EXPANDED] = false;
6309
- }
6274
+ currentModel[GROUP_EXPANDED] = false;
6310
6275
  }
6311
6276
  trimmed[i++] = true;
6312
6277
  }
@@ -6546,7 +6511,7 @@ class GroupingRowPlugin extends BasePlugin {
6546
6511
  * sorting applied need to clear grouping and apply again
6547
6512
  * based on new results whole grouping order will changed
6548
6513
  */
6549
- this.addEventListener('afterSortingApply', () => this.doSourceUpdate());
6514
+ this.addEventListener('afterSortingApply', () => this.doSourceUpdate(Object.assign({}, this.options)));
6550
6515
  /**
6551
6516
  * Apply logic for focus inside of grouping
6552
6517
  * We can't focus on grouping rows, navigation only inside of groups for now
@@ -6566,6 +6531,7 @@ class GroupingRowPlugin extends BasePlugin {
6566
6531
  * Initiated when need to reapply grouping
6567
6532
  */
6568
6533
  doSourceUpdate(options) {
6534
+ var _a;
6569
6535
  if (!this.hasProps) {
6570
6536
  return;
6571
6537
  }
@@ -6578,11 +6544,9 @@ class GroupingRowPlugin extends BasePlugin {
6578
6544
  * Group again
6579
6545
  * @param oldNewIndexMap - provides us mapping with new indexes vs old indexes
6580
6546
  */
6581
- const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup } = gatherGrouping(source,
6582
- // filter
6583
- item => { var _a; return (_a = this.options) === null || _a === void 0 ? void 0 : _a.props.map(key => item[key]); }, Object.assign({ prevExpanded }, options));
6547
+ const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup } = gatherGrouping(source, ((_a = this.options) === null || _a === void 0 ? void 0 : _a.props) || [], Object.assign({ prevExpanded }, options));
6584
6548
  // setup source
6585
- this.providers.dataProvider.setData(sourceWithGroups, GROUPING_ROW_TYPE, { depth }, true);
6549
+ this.providers.dataProvider.setData(sourceWithGroups, GROUPING_ROW_TYPE, { depth, customRenderer: options === null || options === void 0 ? void 0 : options.groupLabelTemplate }, true);
6586
6550
  this.updateTrimmed(trimmed, childrenByGroup, oldNewIndexes, oldNewIndexMap);
6587
6551
  }
6588
6552
  /**
@@ -6591,14 +6555,13 @@ class GroupingRowPlugin extends BasePlugin {
6591
6555
  * If source came from other plugin
6592
6556
  */
6593
6557
  onDataSet(data) {
6558
+ var _a;
6594
6559
  if (!this.hasProps || !(data === null || data === void 0 ? void 0 : data.source) || !data.source.length) {
6595
6560
  return;
6596
6561
  }
6597
6562
  const source = data.source.filter(s => !isGrouping(s));
6598
6563
  const expanded = this.revogrid.grouping || {};
6599
- const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup } = gatherGrouping(source,
6600
- // filter
6601
- item => { var _a; return (_a = this.options) === null || _a === void 0 ? void 0 : _a.props.map(key => item[key]); }, Object.assign({}, (expanded || {})));
6564
+ const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup } = gatherGrouping(source, ((_a = this.options) === null || _a === void 0 ? void 0 : _a.props) || [], Object.assign({}, (expanded || {})));
6602
6565
  data.source = sourceWithGroups;
6603
6566
  this.providers.dataProvider.setGrouping({ depth });
6604
6567
  this.updateTrimmed(trimmed, childrenByGroup, oldNewIndexMap);
@@ -25724,13 +25687,17 @@ function expandEvent(e, model, virtualIndex) {
25724
25687
  e.target.dispatchEvent(event);
25725
25688
  }
25726
25689
  const GroupingRowRenderer = (props) => {
25727
- const { model, itemIndex, hasExpand } = props;
25690
+ const { model, itemIndex, hasExpand, groupingCustomRenderer } = props;
25728
25691
  const name = model[PSEUDO_GROUP_ITEM];
25729
25692
  const expanded = model[GROUP_EXPANDED];
25730
25693
  const depth = parseInt(model[GROUP_DEPTH], 10) || 0;
25731
25694
  if (!hasExpand) {
25732
25695
  return index.h(RowRenderer, Object.assign({}, props, { rowClass: "groupingRow", depth: depth }));
25733
25696
  }
25697
+ if (groupingCustomRenderer) {
25698
+ return (index.h(RowRenderer, Object.assign({}, props, { rowClass: "groupingRow", depth: depth }),
25699
+ index.h("div", { onClick: e => expandEvent(e, model, itemIndex) }, groupingCustomRenderer(index.h, { name, itemIndex, expanded, depth }))));
25700
+ }
25734
25701
  return (index.h(RowRenderer, Object.assign({}, props, { rowClass: "groupingRow", depth: depth }),
25735
25702
  index.h("button", { class: { [GROUP_EXPAND_BTN]: true }, onClick: e => expandEvent(e, model, itemIndex) },
25736
25703
  index.h("svg", { "aria-hidden": "true", style: { transform: `rotate(${!expanded ? -90 : 0}deg)` }, focusable: "false", viewBox: "0 0 448 512" },
@@ -25767,11 +25734,12 @@ const RevogrData = class {
25767
25734
  const range = (_a = this.rowSelectionStore) === null || _a === void 0 ? void 0 : _a.get('range');
25768
25735
  const rowsEls = [];
25769
25736
  const depth = this.dataStore.get('groupingDepth');
25737
+ const groupingCustomRenderer = this.dataStore.get('groupingCustomRenderer');
25770
25738
  for (let rgRow of rows) {
25771
25739
  const dataRow = getSourceItem(this.dataStore, rgRow.itemIndex);
25772
25740
  /** grouping */
25773
25741
  if (isGrouping(dataRow)) {
25774
- rowsEls.push(index.h(GroupingRowRenderer, Object.assign({}, rgRow, { model: dataRow, hasExpand: this.columnService.hasGrouping })));
25742
+ rowsEls.push(index.h(GroupingRowRenderer, Object.assign({}, rgRow, { model: dataRow, groupingCustomRenderer: groupingCustomRenderer, hasExpand: this.columnService.hasGrouping })));
25775
25743
  continue;
25776
25744
  }
25777
25745
  /** grouping end */