@lumeer/pivot 0.0.5 → 0.0.7

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 (32) hide show
  1. package/esm2022/lib/lmr-pivot-table.component.mjs +70 -10
  2. package/esm2022/lib/lmr-pivot-table.module.mjs +16 -4
  3. package/esm2022/lib/lmr-simple-pivot-table.component.mjs +6 -3
  4. package/esm2022/lib/pipes/cell-has-value.pipe.mjs +35 -0
  5. package/esm2022/lib/pipes/filter-visible-cells.pipe.mjs +35 -0
  6. package/esm2022/lib/pipes/is-cell-expandable.pipe.mjs +35 -0
  7. package/esm2022/lib/pipes/is-cell-expanded.pipe.mjs +37 -0
  8. package/esm2022/lib/pipes/is-cell-rows-expandable.pipe.mjs +35 -0
  9. package/esm2022/lib/util/lmr-pivot-state.mjs +150 -0
  10. package/esm2022/lib/util/lmr-pivot-table.mjs +1 -1
  11. package/esm2022/lib/util/pivot-table-converter.mjs +62 -40
  12. package/esm2022/lib/util/pivot-util.mjs +7 -4
  13. package/esm2022/public-api.mjs +2 -2
  14. package/fesm2022/lumeer-pivot.mjs +428 -58
  15. package/fesm2022/lumeer-pivot.mjs.map +1 -1
  16. package/lib/lmr-pivot-table.component.d.ts +20 -4
  17. package/lib/lmr-pivot-table.module.d.ts +10 -6
  18. package/lib/lmr-simple-pivot-table.component.d.ts +8 -2
  19. package/lib/pipes/cell-has-value.pipe.d.ts +8 -0
  20. package/lib/pipes/filter-visible-cells.pipe.d.ts +9 -0
  21. package/lib/pipes/is-cell-expandable.pipe.d.ts +8 -0
  22. package/lib/pipes/is-cell-expanded.pipe.d.ts +9 -0
  23. package/lib/pipes/is-cell-rows-expandable.pipe.d.ts +8 -0
  24. package/lib/util/lmr-pivot-state.d.ts +14 -0
  25. package/lib/util/lmr-pivot-table.d.ts +7 -1
  26. package/lib/util/pivot-table-converter.d.ts +1 -0
  27. package/lumeer-pivot-0.0.7.tgz +0 -0
  28. package/package.json +1 -1
  29. package/public-api.d.ts +1 -1
  30. package/esm2022/lib/pipes/pivot-table-value.pipe.mjs +0 -35
  31. package/lib/pipes/pivot-table-value.pipe.d.ts +0 -8
  32. package/lumeer-pivot-0.0.5.tgz +0 -0
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Directive, Pipe, Injectable, EventEmitter, TemplateRef, Component, ChangeDetectionStrategy, Input, Output, ContentChild, NgModule } from '@angular/core';
3
3
  import { cleanQueryAttribute, DataAggregator, UnknownConstraint, ConstraintType, attributesResourcesAttributesMap, aggregateDataResources, AttributesResourceType, dataAggregationConstraint, DataAggregationType, PercentageConstraint, aggregateDataValues, isValueAggregation, NumberConstraint, generateId, LanguageTag } from '@lumeer/data-filters';
4
- import { deepObjectsEquals, hex2rgba, isArray, isNotNullOrUndefined, flattenMatrix, uniqueValues, flattenValues, shadeColor, deepObjectCopy, isNullOrUndefined, isNumeric, toNumber } from '@lumeer/utils';
4
+ import { deepObjectsEquals, hex2rgba, isArray, isNotNullOrUndefined, flattenMatrix, uniqueValues, flattenValues, createRange, shadeColor, deepObjectCopy, isNullOrUndefined, isNumeric, toNumber } from '@lumeer/utils';
5
5
  import { BehaviorSubject, filter, throttleTime, asyncScheduler, map, tap } from 'rxjs';
6
6
  import * as i1 from '@angular/common';
7
7
  import { CommonModule } from '@angular/common';
@@ -53,10 +53,10 @@ function pivotAttributesAreSame(a1, a2) {
53
53
  return deepObjectsEquals(cleanQueryAttribute(a1), cleanQueryAttribute(a2));
54
54
  }
55
55
  function isPivotConfigChanged(viewConfig, currentConfig) {
56
- if (!!viewConfig.mergeTables !== !!currentConfig.mergeTables && (currentConfig.stemsConfigs || []).length > 1) {
56
+ if (!!viewConfig?.mergeTables !== !!currentConfig?.mergeTables && (currentConfig?.stemsConfigs || []).length > 1) {
57
57
  return true;
58
58
  }
59
- return pivotStemConfigsHasChanged(viewConfig.stemsConfigs || [], currentConfig.stemsConfigs || []);
59
+ return pivotStemConfigsHasChanged(viewConfig?.stemsConfigs || [], currentConfig?.stemsConfigs || []);
60
60
  }
61
61
  function pivotStemConfigsHasChanged(s1, s2) {
62
62
  if (s1.length !== s2.length) {
@@ -65,10 +65,13 @@ function pivotStemConfigsHasChanged(s1, s2) {
65
65
  return s1.some((stemConfig, index) => pivotStemConfigHasChanged(stemConfig, s2[index]));
66
66
  }
67
67
  function pivotStemConfigHasChanged(s1, s2) {
68
- return (!deepObjectsEquals(s1.rowAttributes || [], s2.rowAttributes || []) ||
68
+ return (!deepObjectsEquals(cleanRowAttributes(s1.rowAttributes), cleanRowAttributes(s2.rowAttributes)) ||
69
69
  !deepObjectsEquals(s1.columnAttributes || [], s2.columnAttributes || []) ||
70
70
  !deepObjectsEquals(s1.valueAttributes || [], s2.valueAttributes || []));
71
71
  }
72
+ function cleanRowAttributes(attrs) {
73
+ return (attrs || []).map(attr => ({ ...attr, showHeader: undefined }));
74
+ }
72
75
  function createDefaultPivotConfig(query) {
73
76
  const stems = (query && query.stems) || [];
74
77
  const stemsConfigs = stems.map(stem => createDefaultPivotStemConfig(stem));
@@ -719,6 +722,7 @@ class PivotTableConverter {
719
722
  background: this.getHeaderBackground(header, level),
720
723
  constraint: header.constraint,
721
724
  label: header.attributeName,
725
+ childIndexes: createRange(currentIndex, currentIndex + (header.children?.length || 1))
722
726
  };
723
727
  if (header.children) {
724
728
  this.iterateAndFillCellsByRows(cells, rowGroupsInfo, header.children, currentIndex, showSums, level + 1, header);
@@ -731,24 +735,23 @@ class PivotTableConverter {
731
735
  for (let i = 0; i < expressions.length; i++) {
732
736
  const expressionIndex = currentIndex - (expressions.length - i);
733
737
  const background = this.getSummaryBackground(level);
734
- this.splitRowGroupHeader(cells, level, expressionIndex, background, expressions[i].title);
735
- this.fillCellsForExpressionRow(cells, expressions[i], expressionIndex, background);
738
+ const { indexes } = this.fillCellsForExpressionRow(cells, expressions[i], expressionIndex, background);
739
+ this.splitRowGroupHeader(cells, level, expressionIndex, background, expressions[i].title, indexes);
740
+ rowGroupsInfo[expressionIndex] = { background, indexes: [], expression: expressions[i], level };
736
741
  }
737
742
  }
738
743
  if (showSums[level]) {
739
744
  const { title, summary } = this.formatSummaryHeader(parentHeader, level);
740
745
  const background = this.getSummaryBackground(level);
741
746
  const columnIndex = Math.max(level - 1, 0);
742
- this.splitRowGroupHeader(cells, columnIndex, currentIndex, background, summary, title, parentHeader?.constraint, parentHeader?.attributeName);
747
+ this.splitRowGroupHeader(cells, columnIndex, currentIndex, background, summary, [], title, parentHeader?.constraint, parentHeader?.attributeName);
743
748
  const rowIndexes = getTargetIndexesForHeaders(headers);
744
- const transformedRowIndexes = rowIndexes
745
- .map(v => this.rowsTransformationArray[v])
746
- .filter(v => isNotNullOrUndefined(v));
749
+ const transformedRowIndexes = this.transformRowIndexes(rowIndexes);
747
750
  rowGroupsInfo[currentIndex] = { background, indexes: transformedRowIndexes, level };
748
751
  this.fillCellsForGroupedRow(cells, rowIndexes, currentIndex, background);
749
752
  }
750
753
  }
751
- splitRowGroupHeader(cells, columnIndex, currentIndex, background, summary, title, constraint, label) {
754
+ splitRowGroupHeader(cells, columnIndex, currentIndex, background, summary, rowIndexes, title, constraint, label) {
752
755
  let colSpan = this.rowLevels - columnIndex;
753
756
  const stickyStart = this.isRowLevelSticky(columnIndex);
754
757
  // split row group header cell because of correct sticky scroll
@@ -759,7 +762,7 @@ class PivotTableConverter {
759
762
  constraint: undefined,
760
763
  label: undefined,
761
764
  cssClass: PivotTableConverter.rowGroupHeaderClass,
762
- isHeader: true,
765
+ isSummary: true,
763
766
  rowSpan: 1,
764
767
  colSpan: colSpan - newColspan,
765
768
  background,
@@ -772,12 +775,13 @@ class PivotTableConverter {
772
775
  constraint,
773
776
  label,
774
777
  cssClass: PivotTableConverter.rowGroupHeaderClass,
775
- isHeader: true,
778
+ isSummary: true,
776
779
  stickyStart,
777
780
  rowSpan: 1,
778
781
  colSpan,
779
782
  background,
780
783
  summary,
784
+ rowIndexes,
781
785
  };
782
786
  }
783
787
  formatSummaryHeader(header, level) {
@@ -828,7 +832,7 @@ class PivotTableConverter {
828
832
  rowSpan: 1,
829
833
  colSpan: 1,
830
834
  cssClass: PivotTableConverter.dataClass,
831
- isHeader: false,
835
+ isValue: true,
832
836
  };
833
837
  }
834
838
  }
@@ -897,17 +901,19 @@ class PivotTableConverter {
897
901
  colSpan: 1,
898
902
  rowSpan: 1,
899
903
  cssClass: PivotTableConverter.groupDataClass,
900
- isHeader: false,
901
904
  background,
905
+ isValue: true,
902
906
  };
903
907
  }
904
908
  }
905
909
  }
906
910
  fillCellsForExpressionRow(cells, expression, rowIndexInCells, background) {
911
+ let rowIndexes = [];
907
912
  for (let column = 0; column < this.columnsTransformationArray.length; column++) {
908
913
  const columnIndexInCells = this.columnsTransformationArray[column];
909
914
  if (isNotNullOrUndefined(columnIndexInCells)) {
910
- const { value, dataResources } = this.evaluateExpression(expression, column);
915
+ const { value, dataResources, indexes } = this.evaluateExpression(expression, [column]);
916
+ rowIndexes = indexes;
911
917
  const valueIndex = column % this.data.valueTitles.length;
912
918
  const formattedValue = this.formatValueByConstraint(value, valueIndex);
913
919
  cells[rowIndexInCells][columnIndexInCells] = {
@@ -916,21 +922,23 @@ class PivotTableConverter {
916
922
  colSpan: 1,
917
923
  rowSpan: 1,
918
924
  cssClass: PivotTableConverter.groupDataClass,
919
- isHeader: false,
920
925
  background,
926
+ isValue: true,
921
927
  };
922
928
  }
923
929
  }
930
+ return { indexes: uniqueValues([...rowIndexes, rowIndexInCells]) };
924
931
  }
925
- evaluateExpression(expression, column) {
932
+ evaluateExpression(expression, columns) {
926
933
  return (expression.operands || []).reduce((result, operand, index) => {
927
- const { value, dataResources } = this.evaluateOperand(operand, column);
934
+ const { value, dataResources, indexes } = this.evaluateOperand(operand, columns);
928
935
  result.dataResources.push(...dataResources);
936
+ result.indexes.push(...indexes);
929
937
  switch (expression.operation) {
930
- case "add":
938
+ case 'add':
931
939
  result.value += value;
932
940
  break;
933
- case "subtract":
941
+ case 'subtract':
934
942
  result.value = (index === 0 ? value : result.value - value);
935
943
  break;
936
944
  case 'multiply':
@@ -941,20 +949,25 @@ class PivotTableConverter {
941
949
  break;
942
950
  }
943
951
  return result;
944
- }, { value: 0, dataResources: [] });
952
+ }, { value: 0, dataResources: [], indexes: [] });
945
953
  }
946
- evaluateOperand(operand, column) {
954
+ evaluateOperand(operand, columns) {
947
955
  switch (operand.type) {
948
- case "expression": return this.evaluateExpression(operand, column);
949
- case "value": return { value: operand.value, dataResources: [] };
950
- case "header": {
956
+ case 'expression': return this.evaluateExpression(operand, columns);
957
+ case 'value': return { value: operand.value, dataResources: [], indexes: [] };
958
+ case 'header': {
951
959
  const rows = getTargetIndexesForHeaders(operand.headers);
952
- const { values, dataResources } = this.getGroupedValuesForRowsAndCols(rows, [column]);
953
- const { value } = this.aggregateDataValues(values, [column]);
954
- return { value, dataResources };
960
+ const { values, dataResources } = this.getGroupedValuesForRowsAndCols(rows, columns);
961
+ const { value } = this.aggregateDataValues(values, columns);
962
+ return { value, dataResources, indexes: this.transformRowIndexes(rows) };
955
963
  }
956
964
  }
957
965
  }
966
+ transformRowIndexes(rows) {
967
+ return rows
968
+ .map(v => this.rowsTransformationArray[v])
969
+ .filter(v => isNotNullOrUndefined(v));
970
+ }
958
971
  getGroupedValuesForRowsAndCols(rows, columns) {
959
972
  const values = [];
960
973
  const dataResources = [];
@@ -1012,7 +1025,7 @@ class PivotTableConverter {
1012
1025
  constraint: parentHeader?.constraint,
1013
1026
  label: parentHeader?.attributeName,
1014
1027
  cssClass: PivotTableConverter.columnGroupHeaderClass,
1015
- isHeader: true,
1028
+ isSummary: true,
1016
1029
  stickyTop: this.isColumnLevelSticky(level),
1017
1030
  rowSpan: this.columnLevels - rowIndex - (shouldAddValueHeaders ? 1 : 0),
1018
1031
  colSpan: numberOfSums,
@@ -1027,7 +1040,7 @@ class PivotTableConverter {
1027
1040
  cells[this.columnLevels - 1][columnIndexInCells] = {
1028
1041
  value: valueTitle,
1029
1042
  cssClass: PivotTableConverter.columnGroupHeaderClass,
1030
- isHeader: true,
1043
+ isSummary: true,
1031
1044
  stickyTop: this.isColumnLevelSticky(level),
1032
1045
  rowSpan: 1,
1033
1046
  colSpan: 1,
@@ -1060,8 +1073,8 @@ class PivotTableConverter {
1060
1073
  colSpan: 1,
1061
1074
  rowSpan: 1,
1062
1075
  cssClass: PivotTableConverter.groupDataClass,
1063
- isHeader: false,
1064
1076
  background,
1077
+ isValue: true,
1065
1078
  };
1066
1079
  }
1067
1080
  }
@@ -1100,7 +1113,7 @@ class PivotTableConverter {
1100
1113
  rowSpan: 1,
1101
1114
  colSpan: 1,
1102
1115
  cssClass: PivotTableConverter.dataClass,
1103
- isHeader: false,
1116
+ isValue: true,
1104
1117
  };
1105
1118
  }
1106
1119
  }
@@ -1117,23 +1130,35 @@ class PivotTableConverter {
1117
1130
  }
1118
1131
  fillCellsByGroupIntersection(cells, rowGroupsInfo, columnGroupsInfo) {
1119
1132
  const rowsCount = cells.length;
1120
- const columnsCount = (cells[0] && cells[0].length) || 0;
1133
+ const columnsCount = cells[0]?.length || 0;
1121
1134
  for (let i = 0; i < rowGroupsInfo.length; i++) {
1122
1135
  const rowGroupInfo = rowGroupsInfo[i];
1123
1136
  if (rowGroupInfo) {
1124
1137
  for (let j = 0; j < columnGroupsInfo.length; j++) {
1125
1138
  if (columnGroupsInfo[j]) {
1126
- // it's enough to fill group values only from row side
1127
- const { rowsIndexes, columnsIndexes } = this.getValuesIndexesFromCellsIndexes(rowGroupInfo.indexes, columnGroupsInfo[j].indexes);
1128
- const { values, dataResources } = this.getGroupedValuesForRowsAndCols(rowsIndexes, columnsIndexes);
1129
- const formattedValue = this.aggregateAndFormatDataValues(values, rowsIndexes, columnsIndexes);
1139
+ const columns = columnGroupsInfo[j].indexes;
1140
+ let formattedValue;
1141
+ let dataResources;
1142
+ if (rowGroupInfo.expression) {
1143
+ const result = this.evaluateExpression(rowGroupInfo.expression, columns);
1144
+ const valueIndex = columns[0] % this.data.valueTitles.length;
1145
+ formattedValue = this.formatValueByConstraint(result.value, valueIndex);
1146
+ dataResources = result.dataResources;
1147
+ }
1148
+ else {
1149
+ // it's enough to fill group values only from row side
1150
+ const { rowsIndexes, columnsIndexes } = this.getValuesIndexesFromCellsIndexes(rowGroupInfo.indexes, columns);
1151
+ const result = this.getGroupedValuesForRowsAndCols(rowsIndexes, columnsIndexes);
1152
+ formattedValue = this.aggregateAndFormatDataValues(result.values, rowsIndexes, columnsIndexes);
1153
+ dataResources = result.dataResources;
1154
+ }
1130
1155
  cells[i][j] = {
1131
1156
  value: String(formattedValue),
1132
1157
  dataResources,
1133
1158
  colSpan: 1,
1134
1159
  rowSpan: 1,
1135
1160
  cssClass: PivotTableConverter.groupDataClass,
1136
- isHeader: false,
1161
+ isValue: true,
1137
1162
  };
1138
1163
  }
1139
1164
  }
@@ -1183,7 +1208,7 @@ class PivotTableConverter {
1183
1208
  cssClass: isDataClass ? PivotTableConverter.dataClass : PivotTableConverter.groupDataClass,
1184
1209
  rowSpan: 1,
1185
1210
  colSpan: 1,
1186
- isHeader: false,
1211
+ isValue: true,
1187
1212
  };
1188
1213
  }
1189
1214
  else {
@@ -1199,7 +1224,7 @@ class PivotTableConverter {
1199
1224
  matrix[0][j] = {
1200
1225
  value: rowHeaderAttribute.title,
1201
1226
  cssClass: PivotTableConverter.rowAttributeHeaderClass,
1202
- isHeader: true,
1227
+ isAttributeHeader: true,
1203
1228
  rowSpan: 1,
1204
1229
  colSpan: titleColSpan,
1205
1230
  stickyTop: this.isColumnLevelSticky(0),
@@ -1210,7 +1235,7 @@ class PivotTableConverter {
1210
1235
  matrix[this.nonStickyColumnIndex][j] = {
1211
1236
  value: '',
1212
1237
  cssClass: PivotTableConverter.rowAttributeHeaderClass,
1213
- isHeader: true,
1238
+ isAttributeHeader: true,
1214
1239
  rowSpan: 1,
1215
1240
  colSpan: this.columnLevels - titleColSpan,
1216
1241
  background: rowHeaderAttribute.color,
@@ -1599,6 +1624,155 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
1599
1624
  args: [{ selector: '[lmr-table-cell-tmp]' }]
1600
1625
  }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
1601
1626
 
1627
+ function isCellExpandable(cell) {
1628
+ return isCellColumnsExpandable(cell) || isCellRowsExpandable(cell);
1629
+ }
1630
+ function isCellColumnsExpandable(cell) {
1631
+ return cell?.childIndexes?.length > 1;
1632
+ }
1633
+ function isCellRowsExpandable(cell) {
1634
+ return cell?.rowIndexes?.length > 1;
1635
+ }
1636
+ function toggleExpanded(cell, columnIndex, state) {
1637
+ if (cell.originalRowIndex) {
1638
+ return toggleExpandedState(state, cell.originalRowIndex, columnIndex);
1639
+ }
1640
+ return state;
1641
+ }
1642
+ function areCellsSame(c1, c2) {
1643
+ return c1?.summary === c2?.summary && c1?.value === c2?.value;
1644
+ }
1645
+ function toggleExpandedState(state, rowIndex, columnIndex) {
1646
+ if (isNullOrUndefined(rowIndex) || isNullOrUndefined(columnIndex) || rowIndex < 0 || columnIndex < 0) {
1647
+ return state;
1648
+ }
1649
+ const cellsCopy = [...(state?.cells || [])];
1650
+ const rowCopy = [...(cellsCopy[rowIndex] || [])];
1651
+ rowCopy[columnIndex] = { ...rowCopy[columnIndex], collapsed: !rowCopy[columnIndex]?.collapsed };
1652
+ cellsCopy[rowIndex] = rowCopy;
1653
+ return { ...state, cells: cellsCopy };
1654
+ }
1655
+ function filterVisibleCells(cells, state, parentIndex = 0) {
1656
+ const cellsChildIndexesMap = createCellsChildIndexesMap(cells);
1657
+ return cells.reduce((currentRows, row, index) => {
1658
+ const firstCell = row[0];
1659
+ if (!firstCell) {
1660
+ return currentRows;
1661
+ }
1662
+ const originalRowIndex = parentIndex + index;
1663
+ if (firstCell.isAttributeHeader || firstCell.isSummary || firstCell.isValue) {
1664
+ currentRows.push(setOriginalRowIndexForHeaders(row, originalRowIndex));
1665
+ return currentRows;
1666
+ }
1667
+ if (isRowVisible(index, cellsChildIndexesMap, 0, state)) {
1668
+ if (row.some(cell => isCellColumnsExpandable(cell))) {
1669
+ const isCollapsed = state?.[index]?.[0]?.collapsed;
1670
+ if (isCollapsed) {
1671
+ const firstDataHeaderIndex = takeIf(row.findIndex(cell => cell.isValue), result => result >= 0) ?? 1;
1672
+ const rowCopy = [...row];
1673
+ rowCopy[0] = {
1674
+ ...row[0],
1675
+ colSpan: firstDataHeaderIndex,
1676
+ rowSpan: 1,
1677
+ originalRowIndex,
1678
+ };
1679
+ for (let i = 1; i < firstDataHeaderIndex; i++) {
1680
+ rowCopy[i] = undefined;
1681
+ }
1682
+ currentRows.push(rowCopy);
1683
+ }
1684
+ else {
1685
+ const nestedCells = sliceMatrix(cells, index, index + firstCell.rowSpan - 1, 1, cells[0].length - 1);
1686
+ const nestedState = sliceMatrix(state, index, index + firstCell.rowSpan - 1, 1, cells[0].length - 1);
1687
+ const nestedFilteredRows = filterVisibleCells(nestedCells, nestedState, originalRowIndex);
1688
+ const changedCell = {
1689
+ ...row[0],
1690
+ rowSpan: nestedFilteredRows.length,
1691
+ originalRowIndex,
1692
+ };
1693
+ const newRows = appendCellToMatrix(changedCell, nestedFilteredRows);
1694
+ currentRows.push(...newRows);
1695
+ }
1696
+ }
1697
+ else {
1698
+ currentRows.push(setOriginalRowIndexForHeaders(row, originalRowIndex));
1699
+ for (let i = 1; i < firstCell.rowSpan; i++) {
1700
+ currentRows.push(setOriginalRowIndexForHeaders(cells[index + i], originalRowIndex + i));
1701
+ }
1702
+ }
1703
+ }
1704
+ return currentRows;
1705
+ }, []);
1706
+ }
1707
+ function setOriginalRowIndexForHeaders(row, originalRowIndex) {
1708
+ const newRow = [];
1709
+ for (let i = 0; i < row.length; i++) {
1710
+ const cell = row[i];
1711
+ if (!cell) {
1712
+ newRow.push(cell);
1713
+ }
1714
+ else if (cell.isValue) {
1715
+ return [...newRow, ...row.slice(i)];
1716
+ }
1717
+ else {
1718
+ newRow.push({ ...cell, originalRowIndex });
1719
+ }
1720
+ }
1721
+ return newRow;
1722
+ }
1723
+ function appendCellToMatrix(cell, rows) {
1724
+ return rows.map((row, index) => index > 0 ? [undefined, ...row] : [cell, ...row]);
1725
+ }
1726
+ function takeIf(value, predicate) {
1727
+ return predicate(value) ? value : undefined;
1728
+ }
1729
+ function sliceMatrix(cells, fromRow, toRow, fromColumn, toColumn) {
1730
+ const slicedMatrix = [];
1731
+ for (let i = fromRow; i <= toRow; i++) {
1732
+ const row = (cells?.[i] || []).slice(fromColumn, toColumn + 1);
1733
+ slicedMatrix.push(row);
1734
+ }
1735
+ return slicedMatrix;
1736
+ }
1737
+ function createCellsChildIndexesMap(rowCells) {
1738
+ const firstCells = rowCells.map(rowCells => rowCells[0]);
1739
+ return createRowsChildIndexesMap(firstCells);
1740
+ }
1741
+ function createRowsChildIndexesMap(rowCells) {
1742
+ return (rowCells || []).reduce((map, cell, index) => {
1743
+ for (const childIndex of (cell?.rowIndexes || [])) {
1744
+ if (!map[childIndex])
1745
+ map[childIndex] = [];
1746
+ map[childIndex].push(index);
1747
+ }
1748
+ return map;
1749
+ }, []);
1750
+ }
1751
+ function isRowVisible(index, childIndexesMap, columnIndex, state) {
1752
+ const childIndexes = childIndexesMap?.[index] || [];
1753
+ return !childIndexes.length || childIndexes.some(childIndex => !state?.[childIndex]?.[columnIndex]?.collapsed);
1754
+ }
1755
+ function collapseAllCells(table) {
1756
+ const cells = [];
1757
+ const tableCells = table?.cells || [];
1758
+ for (let i = 0; i < tableCells.length; i++) {
1759
+ const row = tableCells[i];
1760
+ for (let j = 0; j < row.length; j++) {
1761
+ const cell = row[j];
1762
+ if (cell?.isValue || cell?.isAttributeHeader || cell?.isHeader) {
1763
+ break;
1764
+ }
1765
+ if (isCellExpandable(cell)) {
1766
+ if (!cells[i]) {
1767
+ cells[i] = [];
1768
+ }
1769
+ cells[i][j] = { collapsed: true };
1770
+ }
1771
+ }
1772
+ }
1773
+ return { cells };
1774
+ }
1775
+
1602
1776
  /*
1603
1777
  * Lumeer: Modern Data Definition and Processing Platform
1604
1778
  *
@@ -1653,17 +1827,148 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
1653
1827
  * You should have received a copy of the GNU General Public License
1654
1828
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
1655
1829
  */
1656
- class PivotTableCellHasValuePipe {
1830
+ class CellHasValuePipe {
1657
1831
  transform(cell) {
1658
1832
  return isNotNullOrUndefined(cell.value) && String(cell.value).trim() !== '';
1659
1833
  }
1660
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PivotTableCellHasValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1661
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: PivotTableCellHasValuePipe, name: "pivotTableCellHasValue" });
1834
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellHasValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1835
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: CellHasValuePipe, name: "cellHasValue" });
1836
+ }
1837
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellHasValuePipe, decorators: [{
1838
+ type: Pipe,
1839
+ args: [{
1840
+ name: 'cellHasValue',
1841
+ }]
1842
+ }] });
1843
+
1844
+ /*
1845
+ * Lumeer: Modern Data Definition and Processing Platform
1846
+ *
1847
+ * Copyright (C) since 2017 Lumeer.io, s.r.o. and/or its affiliates.
1848
+ *
1849
+ * This program is free software: you can redistribute it and/or modify
1850
+ * it under the terms of the GNU General Public License as published by
1851
+ * the Free Software Foundation, either version 3 of the License, or
1852
+ * (at your option) any later version.
1853
+ *
1854
+ * This program is distributed in the hope that it will be useful,
1855
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1856
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1857
+ * GNU General Public License for more details.
1858
+ *
1859
+ * You should have received a copy of the GNU General Public License
1860
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1861
+ */
1862
+ class IsCellExpandablePipe {
1863
+ transform(cell) {
1864
+ return isCellExpandable(cell);
1865
+ }
1866
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: IsCellExpandablePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1867
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: IsCellExpandablePipe, name: "isCellExpandable" });
1868
+ }
1869
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: IsCellExpandablePipe, decorators: [{
1870
+ type: Pipe,
1871
+ args: [{
1872
+ name: 'isCellExpandable',
1873
+ }]
1874
+ }] });
1875
+
1876
+ /*
1877
+ * Lumeer: Modern Data Definition and Processing Platform
1878
+ *
1879
+ * Copyright (C) since 2017 Lumeer.io, s.r.o. and/or its affiliates.
1880
+ *
1881
+ * This program is free software: you can redistribute it and/or modify
1882
+ * it under the terms of the GNU General Public License as published by
1883
+ * the Free Software Foundation, either version 3 of the License, or
1884
+ * (at your option) any later version.
1885
+ *
1886
+ * This program is distributed in the hope that it will be useful,
1887
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1888
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1889
+ * GNU General Public License for more details.
1890
+ *
1891
+ * You should have received a copy of the GNU General Public License
1892
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1893
+ */
1894
+ class IsCellExpandedPipe {
1895
+ transform(cell, columnIndex, state) {
1896
+ if (cell.originalRowIndex) {
1897
+ return !state?.cells?.[cell.originalRowIndex]?.[columnIndex]?.collapsed;
1898
+ }
1899
+ return false;
1900
+ }
1901
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: IsCellExpandedPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1902
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: IsCellExpandedPipe, name: "isCellExpanded" });
1903
+ }
1904
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: IsCellExpandedPipe, decorators: [{
1905
+ type: Pipe,
1906
+ args: [{
1907
+ name: 'isCellExpanded',
1908
+ }]
1909
+ }] });
1910
+
1911
+ /*
1912
+ * Lumeer: Modern Data Definition and Processing Platform
1913
+ *
1914
+ * Copyright (C) since 2017 Lumeer.io, s.r.o. and/or its affiliates.
1915
+ *
1916
+ * This program is free software: you can redistribute it and/or modify
1917
+ * it under the terms of the GNU General Public License as published by
1918
+ * the Free Software Foundation, either version 3 of the License, or
1919
+ * (at your option) any later version.
1920
+ *
1921
+ * This program is distributed in the hope that it will be useful,
1922
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1923
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1924
+ * GNU General Public License for more details.
1925
+ *
1926
+ * You should have received a copy of the GNU General Public License
1927
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1928
+ */
1929
+ class IsCellRowsExpandablePipe {
1930
+ transform(cell) {
1931
+ return isCellRowsExpandable(cell);
1932
+ }
1933
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: IsCellRowsExpandablePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1934
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: IsCellRowsExpandablePipe, name: "isCellRowsExpandable" });
1662
1935
  }
1663
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PivotTableCellHasValuePipe, decorators: [{
1936
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: IsCellRowsExpandablePipe, decorators: [{
1664
1937
  type: Pipe,
1665
1938
  args: [{
1666
- name: 'pivotTableCellHasValue',
1939
+ name: 'isCellRowsExpandable',
1940
+ }]
1941
+ }] });
1942
+
1943
+ /*
1944
+ * Lumeer: Modern Data Definition and Processing Platform
1945
+ *
1946
+ * Copyright (C) since 2017 Lumeer.io, s.r.o. and/or its affiliates.
1947
+ *
1948
+ * This program is free software: you can redistribute it and/or modify
1949
+ * it under the terms of the GNU General Public License as published by
1950
+ * the Free Software Foundation, either version 3 of the License, or
1951
+ * (at your option) any later version.
1952
+ *
1953
+ * This program is distributed in the hope that it will be useful,
1954
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1955
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1956
+ * GNU General Public License for more details.
1957
+ *
1958
+ * You should have received a copy of the GNU General Public License
1959
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1960
+ */
1961
+ class FilterVisibleCellsPipe {
1962
+ transform(table, state) {
1963
+ return filterVisibleCells(table.cells, state?.cells);
1964
+ }
1965
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterVisibleCellsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1966
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: FilterVisibleCellsPipe, name: "filterVisibleCells" });
1967
+ }
1968
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterVisibleCellsPipe, decorators: [{
1969
+ type: Pipe,
1970
+ args: [{
1971
+ name: 'filterVisibleCells',
1667
1972
  }]
1668
1973
  }] });
1669
1974
 
@@ -1715,6 +2020,7 @@ class LmrPivotTableComponent {
1715
2020
  transform;
1716
2021
  emptyTablesTemplateInput;
1717
2022
  tableCellTemplateInput;
2023
+ initiallyCollapsed;
1718
2024
  cellClick = new EventEmitter();
1719
2025
  pivotDataChange = new EventEmitter();
1720
2026
  pivotTablesChange = new EventEmitter();
@@ -1722,19 +2028,36 @@ class LmrPivotTableComponent {
1722
2028
  tableCellTemplate;
1723
2029
  pivotTransformer = new PivotDataConverter();
1724
2030
  pivotTableConverter = new PivotTableConverter();
1725
- dataSubject = new BehaviorSubject(null);
2031
+ stickyColumnWidth = 150;
2032
+ stickyColumnHeight = 150;
2033
+ dataSubject$ = new BehaviorSubject(null);
2034
+ currentTables;
1726
2035
  pivotData$;
1727
2036
  pivotTables$;
2037
+ pivotStates$ = new BehaviorSubject([]);
1728
2038
  ngOnInit() {
1729
- const observable = this.dataSubject.pipe(filter(data => !!data));
1730
- this.pivotData$ = observable.pipe(throttleTime(200, asyncScheduler, { trailing: true, leading: true }), map(data => this.handleData(data)), tap(data => this.pivotDataChange.emit(data)));
1731
- this.pivotTables$ = this.pivotData$.pipe(map(data => this.pivotTableConverter.createTables(data, this.transform)), tap(tables => this.pivotTablesChange.emit(tables)));
2039
+ const observable = this.dataSubject$.pipe(filter(data => !!data));
2040
+ this.pivotData$ = observable.pipe(throttleTime(200, asyncScheduler, { trailing: true, leading: true }), map(data => this.handleData(data)), tap(data => this.onPivotDataChange(data)));
2041
+ this.pivotTables$ = this.pivotData$.pipe(map(data => this.pivotTableConverter.createTables(data, this.transform)), tap(tables => this.onPivotTablesChange(tables)));
2042
+ }
2043
+ onPivotDataChange(data) {
2044
+ this.pivotDataChange.emit(data);
2045
+ }
2046
+ onPivotTablesChange(tables) {
2047
+ if (this.initiallyCollapsed && tablesAreVeryDifferent(this.currentTables, tables)) {
2048
+ this.pivotStates$.next(tables.map(table => collapseAllCells(table)));
2049
+ }
2050
+ this.currentTables = tables;
2051
+ this.pivotTablesChange.emit(tables);
1732
2052
  }
1733
2053
  handleData(data) {
1734
2054
  return this.pivotTransformer.createData(data.config, data.transform, data.collections, data.linkTypes, data.data, data.query, data.constraintData);
1735
2055
  }
1736
2056
  ngOnChanges(changes) {
1737
- this.dataSubject.next({
2057
+ if (shouldResetState(changes)) {
2058
+ this.resetState();
2059
+ }
2060
+ this.dataSubject$.next({
1738
2061
  config: this.config,
1739
2062
  transform: this.transform,
1740
2063
  collections: this.collections,
@@ -1744,12 +2067,31 @@ class LmrPivotTableComponent {
1744
2067
  constraintData: this.constraintData,
1745
2068
  });
1746
2069
  }
2070
+ resetState() {
2071
+ // this.pivotStates$.next([]);
2072
+ }
2073
+ onCellClick(cell, row, tableIndex, rowIndex, columnIndex) {
2074
+ if (isCellExpandable(cell)) {
2075
+ const oldState = this.pivotStates$.value[tableIndex];
2076
+ const newState = toggleExpanded(cell, columnIndex, oldState);
2077
+ this.setState(tableIndex, newState);
2078
+ }
2079
+ else if (cell?.isHeader || cell?.isValue) {
2080
+ const headerCell = cell.isHeader ? cell : row.find(c => c.isHeader);
2081
+ this.cellClick.emit({ cell, tableIndex, rowIndex: headerCell?.originalRowIndex || rowIndex, columnIndex });
2082
+ }
2083
+ }
2084
+ setState(index, state) {
2085
+ const statesCopy = [...(this.pivotStates$.value || [])];
2086
+ statesCopy.splice(index, 1, state);
2087
+ this.pivotStates$.next(statesCopy);
2088
+ }
1747
2089
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LmrPivotTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1748
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: LmrPivotTableComponent, selector: "lmr-pivot-table", inputs: { collections: "collections", data: "data", linkTypes: "linkTypes", query: "query", constraintData: "constraintData", config: "config", transform: "transform", emptyTablesTemplateInput: "emptyTablesTemplateInput", tableCellTemplateInput: "tableCellTemplateInput" }, outputs: { cellClick: "cellClick", pivotDataChange: "pivotDataChange", pivotTablesChange: "pivotTablesChange" }, queries: [{ propertyName: "emptyTablesTemplate", first: true, predicate: LmrEmptyTablesTemplateDirective, descendants: true, read: TemplateRef }, { propertyName: "tableCellTemplate", first: true, predicate: LmrTableCellTemplateDirective, descendants: true, read: TemplateRef }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"{pivotTables: pivotTables$ | async, pivotData: pivotData$ | async} as data\">\n <ng-container *ngIf=\"data.pivotTables?.length && !(data.pivotData | pivotDataEmpty)\">\n <table *ngFor=\"let pivotTable of data.pivotTables; let first\"\n class=\"table table-without-padding table-borderless table-md\"\n [class.mt-4]=\"!first\">\n <tr *ngFor=\"let rowCells of pivotTable.cells; let rowIndex = index\">\n\n <ng-container *ngFor=\"let cell of rowCells; let cellIndex = index\">\n <td *ngIf=\"cell && {hasValue: cell | pivotTableCellHasValue} as cellData\"\n class=\"cell {{cell.constraint ? (cell.constraint.type | lowercase) : ''}} text-truncate\"\n [style.max-width.px]=\"300\"\n [class.sticky-start]=\"cell.stickyStart\"\n [class.sticky-top]=\"cell.stickyTop\"\n [rowSpan]=\"cell.rowSpan\"\n [colSpan]=\"cell.colSpan\"\n [style.top.px]=\"cell.stickyTop ? (rowIndex * 40) : undefined\"\n [style.left.px]=\"cell.stickyStart ? (cellIndex * 150) : undefined\"\n [ngClass]=\"cell.cssClass\"\n [style.background]=\"cell.background\"\n [style.color]=\"cell.background && (cell.background | contrastColor)\">\n <ng-container *ngIf=\"cell.summary\">\n <ng-container *ngIf=\"cellData.hasValue\">\n <div class=\"d-flex align-items-center h-100\">\n <span class=\"summary me-2\">{{cell.summary}}</span>\n <ng-template #defaultTableCellTemplate>\n <span class=\"flex-grow-1 h-100 text-truncate d-inline-block\">\n {{ cell.value }}\n </span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"tableCellTemplate || tableCellTemplateInput || defaultTableCellTemplate\"\n [ngTemplateOutletContext]=\"{ value: cell.value, cell: cell }\">\n </ng-template>\n </div>\n </ng-container>\n <ng-container *ngIf=\"!cellData.hasValue\">\n <span class=\"d-inline-block summary\">{{cell.summary}}</span>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!cell.summary\">\n <ng-container *ngIf=\"cellData.hasValue\">\n <ng-template #defaultTableCellTemplate>\n <span class=\"d-inline-block\">\n {{ cell.value }}\n </span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"tableCellTemplate || tableCellTemplateInput || defaultTableCellTemplate\"\n [ngTemplateOutletContext]=\"{ value: cell.value, cell: cell }\">\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!cellData.hasValue\">&nbsp;</ng-container>\n </ng-container>\n </td>\n </ng-container>\n </tr>\n </table>\n </ng-container>\n\n <ng-container *ngIf=\"!data.pivotTables?.length || (data.pivotData | pivotDataEmpty)\">\n <ng-template #defaultEmptyTablesTemplate>\n <div>&nbsp;</div>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"emptyTablesTemplate || emptyTablesTemplateInput || defaultEmptyTablesTemplate\"\n [ngTemplateOutletContext]=\"{ }\">\n </ng-template>\n </ng-container>\n</ng-container>\n", styles: [".table{border-spacing:0;border-collapse:separate}.pivot-data-cell,.pivot-data-group-cell,.pivot-column-header-cell,.pivot-column-group-header-cell{text-align:right}.pivot-column-header-cell,.pivot-row-attribute-header-cell,.pivot-row-header-cell,.pivot-data-group-cell,.pivot-row-group-header-cell,.pivot-column-group-header-cell{font-weight:700;border:1px #f8f9fa solid}.pivot-row-header-cell.sticky-start,.pivot-row-group-header-cell.sticky-start,.pivot-empty-cell.sticky-start{position:sticky;width:150px;min-width:150px;max-width:150px!important;z-index:9}.pivot-column-header-cell.sticky-top,.pivot-row-attribute-header-cell.sticky-top,.pivot-column-group-header-cell.sticky-top,.pivot-empty-cell.sticky-top{position:sticky;z-index:10}.pivot-row-attribute-header-cell.sticky-top,.pivot-row-attribute-header-cell.sticky-start{position:sticky;z-index:11}.pivot-empty-cell{background:white;border:1px white solid}.pivot-empty-cell.sticky-top{z-index:11}.cell.color{padding:0!important;height:30px}.cell.color .summary{padding-left:.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.LowerCasePipe, name: "lowercase" }, { kind: "pipe", type: PivotDataEmptyPipe, name: "pivotDataEmpty" }, { kind: "pipe", type: PivotTableCellHasValuePipe, name: "pivotTableCellHasValue" }, { kind: "pipe", type: ContrastColorPipe, name: "contrastColor" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2090
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: LmrPivotTableComponent, selector: "lmr-pivot-table", inputs: { collections: "collections", data: "data", linkTypes: "linkTypes", query: "query", constraintData: "constraintData", config: "config", transform: "transform", emptyTablesTemplateInput: "emptyTablesTemplateInput", tableCellTemplateInput: "tableCellTemplateInput", initiallyCollapsed: "initiallyCollapsed" }, outputs: { cellClick: "cellClick", pivotDataChange: "pivotDataChange", pivotTablesChange: "pivotTablesChange" }, queries: [{ propertyName: "emptyTablesTemplate", first: true, predicate: LmrEmptyTablesTemplateDirective, descendants: true, read: TemplateRef }, { propertyName: "tableCellTemplate", first: true, predicate: LmrTableCellTemplateDirective, descendants: true, read: TemplateRef }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"{pivotTables: pivotTables$ | async, pivotStates: pivotStates$ | async, pivotData: pivotData$ | async} as data\">\n <ng-container *ngIf=\"data.pivotTables?.length && !(data.pivotData | pivotDataEmpty)\">\n <table *ngFor=\"let pivotTable of data.pivotTables; let first; let tableIndex = index\"\n class=\"table table-without-padding table-borderless table-md\"\n [class.mt-4]=\"!first\">\n <tr *ngFor=\"let rowCells of pivotTable | filterVisibleCells:data.pivotStates[tableIndex]; let rowIndex = index\">\n\n <ng-container *ngFor=\"let cell of rowCells; let cellIndex = index\">\n <td *ngIf=\"cell && {hasValue: cell | cellHasValue} as cellData\"\n class=\"cell position-relative {{cell.constraint ? (cell.constraint.type | lowercase) : ''}} text-truncate\"\n [class.expandable]=\"cell | isCellExpandable\"\n [class.expandable-rows]=\"cell | isCellRowsExpandable\"\n [class.expanded]=\"cell | isCellExpanded:cellIndex:data.pivotStates[tableIndex]\"\n [class.sticky-start]=\"cell.stickyStart\"\n [class.sticky-top]=\"cell.stickyTop\"\n [rowSpan]=\"cell.rowSpan\"\n [colSpan]=\"cell.colSpan\"\n [style.top.px]=\"cell.stickyTop ? (rowIndex * stickyColumnHeight) : undefined\"\n [style.left.px]=\"cell.stickyStart ? (cellIndex * stickyColumnWidth) : undefined\"\n [style.width.px]=\"cell.stickyStart ? (cell.colSpan * stickyColumnWidth) : undefined\"\n [style.max-width.px]=\"cell.stickyStart ? (cell.colSpan * stickyColumnWidth) : 300\"\n [style.min-width.px]=\"cell.stickyStart ? (cell.colSpan * stickyColumnWidth) : undefined\"\n [ngClass]=\"cell.cssClass\"\n [style.background]=\"cell.background\"\n [style.color]=\"cell.background && (cell.background | contrastColor)\"\n (click)=\"onCellClick(cell, rowCells, tableIndex, rowIndex, cellIndex)\">\n <ng-container *ngIf=\"cell.summary\">\n <ng-container *ngIf=\"cellData.hasValue\">\n <div class=\"d-flex align-items-center h-100\">\n <span class=\"summary me-2\">{{cell.summary}}</span>\n <ng-template #defaultTableCellTemplate>\n <span class=\"flex-grow-1 h-100 text-truncate d-inline-block\">\n {{ cell.value }}\n </span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"tableCellTemplate || tableCellTemplateInput || defaultTableCellTemplate\"\n [ngTemplateOutletContext]=\"{ value: cell.value, cell: cell }\">\n </ng-template>\n </div>\n </ng-container>\n <ng-container *ngIf=\"!cellData.hasValue\">\n <span class=\"d-block\" style=\"overflow: hidden; white-space: normal\">{{cell.summary}}</span>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!cell.summary\">\n <ng-container *ngIf=\"cellData.hasValue\">\n <ng-template #defaultTableCellTemplate>\n <span class=\"d-block\" style=\"overflow: hidden; white-space: normal; cursor: pointer\">\n {{ cell.value }}\n </span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"tableCellTemplate || tableCellTemplateInput || defaultTableCellTemplate\"\n [ngTemplateOutletContext]=\"{ value: cell.value, cell: cell }\">\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!cellData.hasValue\">&nbsp;</ng-container>\n </ng-container>\n </td>\n </ng-container>\n </tr>\n </table>\n </ng-container>\n\n <ng-container *ngIf=\"!data.pivotTables?.length || (data.pivotData | pivotDataEmpty)\">\n <ng-template #defaultEmptyTablesTemplate>\n <div>&nbsp;</div>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"emptyTablesTemplate || emptyTablesTemplateInput || defaultEmptyTablesTemplate\"\n [ngTemplateOutletContext]=\"{ }\">\n </ng-template>\n </ng-container>\n</ng-container>\n", styles: [".table{border-spacing:0;border-collapse:separate}.pivot-data-cell,.pivot-data-group-cell,.pivot-column-header-cell,.pivot-column-group-header-cell{text-align:right}.pivot-column-header-cell,.pivot-row-attribute-header-cell,.pivot-row-header-cell,.pivot-data-group-cell,.pivot-row-group-header-cell,.pivot-column-group-header-cell{font-weight:700;border:1px #f8f9fa solid}.pivot-row-header-cell.sticky-start,.pivot-row-group-header-cell.sticky-start,.pivot-empty-cell.sticky-start{position:sticky!important;width:150px;min-width:150px;max-width:150px!important;z-index:9}.pivot-row-header-cell.expandable,.pivot-row-group-header-cell.expandable{position:absolute;cursor:pointer;padding-right:15px}.pivot-row-header-cell.expandable:after,.pivot-row-group-header-cell.expandable:after{content:\"\";position:absolute;top:50%;right:5px;width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #253746;transform:translateY(-50%)}.pivot-row-header-cell.expandable.expanded:after,.pivot-row-group-header-cell.expandable.expanded:after{border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #253746;border-bottom:0}.pivot-row-header-cell.expandable.expanded.expandable-rows:after,.pivot-row-group-header-cell.expandable.expanded.expandable-rows:after{border-left:5px solid transparent;border-right:5px solid transparent;border-top:0;border-bottom:5px solid #253746}.pivot-column-header-cell.sticky-top,.pivot-row-attribute-header-cell.sticky-top,.pivot-column-group-header-cell.sticky-top,.pivot-empty-cell.sticky-top{position:sticky!important;z-index:10}.pivot-row-attribute-header-cell.sticky-top,.pivot-row-attribute-header-cell.sticky-start{position:sticky!important;z-index:11}.pivot-empty-cell{background:white;border:1px white solid}.pivot-empty-cell.sticky-top{z-index:11}.cell.color{padding:0!important;height:30px}.cell.color .summary{padding-left:.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.LowerCasePipe, name: "lowercase" }, { kind: "pipe", type: PivotDataEmptyPipe, name: "pivotDataEmpty" }, { kind: "pipe", type: CellHasValuePipe, name: "cellHasValue" }, { kind: "pipe", type: IsCellExpandablePipe, name: "isCellExpandable" }, { kind: "pipe", type: IsCellExpandedPipe, name: "isCellExpanded" }, { kind: "pipe", type: IsCellRowsExpandablePipe, name: "isCellRowsExpandable" }, { kind: "pipe", type: FilterVisibleCellsPipe, name: "filterVisibleCells" }, { kind: "pipe", type: ContrastColorPipe, name: "contrastColor" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1749
2091
  }
1750
2092
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LmrPivotTableComponent, decorators: [{
1751
2093
  type: Component,
1752
- args: [{ selector: 'lmr-pivot-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{pivotTables: pivotTables$ | async, pivotData: pivotData$ | async} as data\">\n <ng-container *ngIf=\"data.pivotTables?.length && !(data.pivotData | pivotDataEmpty)\">\n <table *ngFor=\"let pivotTable of data.pivotTables; let first\"\n class=\"table table-without-padding table-borderless table-md\"\n [class.mt-4]=\"!first\">\n <tr *ngFor=\"let rowCells of pivotTable.cells; let rowIndex = index\">\n\n <ng-container *ngFor=\"let cell of rowCells; let cellIndex = index\">\n <td *ngIf=\"cell && {hasValue: cell | pivotTableCellHasValue} as cellData\"\n class=\"cell {{cell.constraint ? (cell.constraint.type | lowercase) : ''}} text-truncate\"\n [style.max-width.px]=\"300\"\n [class.sticky-start]=\"cell.stickyStart\"\n [class.sticky-top]=\"cell.stickyTop\"\n [rowSpan]=\"cell.rowSpan\"\n [colSpan]=\"cell.colSpan\"\n [style.top.px]=\"cell.stickyTop ? (rowIndex * 40) : undefined\"\n [style.left.px]=\"cell.stickyStart ? (cellIndex * 150) : undefined\"\n [ngClass]=\"cell.cssClass\"\n [style.background]=\"cell.background\"\n [style.color]=\"cell.background && (cell.background | contrastColor)\">\n <ng-container *ngIf=\"cell.summary\">\n <ng-container *ngIf=\"cellData.hasValue\">\n <div class=\"d-flex align-items-center h-100\">\n <span class=\"summary me-2\">{{cell.summary}}</span>\n <ng-template #defaultTableCellTemplate>\n <span class=\"flex-grow-1 h-100 text-truncate d-inline-block\">\n {{ cell.value }}\n </span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"tableCellTemplate || tableCellTemplateInput || defaultTableCellTemplate\"\n [ngTemplateOutletContext]=\"{ value: cell.value, cell: cell }\">\n </ng-template>\n </div>\n </ng-container>\n <ng-container *ngIf=\"!cellData.hasValue\">\n <span class=\"d-inline-block summary\">{{cell.summary}}</span>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!cell.summary\">\n <ng-container *ngIf=\"cellData.hasValue\">\n <ng-template #defaultTableCellTemplate>\n <span class=\"d-inline-block\">\n {{ cell.value }}\n </span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"tableCellTemplate || tableCellTemplateInput || defaultTableCellTemplate\"\n [ngTemplateOutletContext]=\"{ value: cell.value, cell: cell }\">\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!cellData.hasValue\">&nbsp;</ng-container>\n </ng-container>\n </td>\n </ng-container>\n </tr>\n </table>\n </ng-container>\n\n <ng-container *ngIf=\"!data.pivotTables?.length || (data.pivotData | pivotDataEmpty)\">\n <ng-template #defaultEmptyTablesTemplate>\n <div>&nbsp;</div>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"emptyTablesTemplate || emptyTablesTemplateInput || defaultEmptyTablesTemplate\"\n [ngTemplateOutletContext]=\"{ }\">\n </ng-template>\n </ng-container>\n</ng-container>\n", styles: [".table{border-spacing:0;border-collapse:separate}.pivot-data-cell,.pivot-data-group-cell,.pivot-column-header-cell,.pivot-column-group-header-cell{text-align:right}.pivot-column-header-cell,.pivot-row-attribute-header-cell,.pivot-row-header-cell,.pivot-data-group-cell,.pivot-row-group-header-cell,.pivot-column-group-header-cell{font-weight:700;border:1px #f8f9fa solid}.pivot-row-header-cell.sticky-start,.pivot-row-group-header-cell.sticky-start,.pivot-empty-cell.sticky-start{position:sticky;width:150px;min-width:150px;max-width:150px!important;z-index:9}.pivot-column-header-cell.sticky-top,.pivot-row-attribute-header-cell.sticky-top,.pivot-column-group-header-cell.sticky-top,.pivot-empty-cell.sticky-top{position:sticky;z-index:10}.pivot-row-attribute-header-cell.sticky-top,.pivot-row-attribute-header-cell.sticky-start{position:sticky;z-index:11}.pivot-empty-cell{background:white;border:1px white solid}.pivot-empty-cell.sticky-top{z-index:11}.cell.color{padding:0!important;height:30px}.cell.color .summary{padding-left:.5rem}\n"] }]
2094
+ args: [{ selector: 'lmr-pivot-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{pivotTables: pivotTables$ | async, pivotStates: pivotStates$ | async, pivotData: pivotData$ | async} as data\">\n <ng-container *ngIf=\"data.pivotTables?.length && !(data.pivotData | pivotDataEmpty)\">\n <table *ngFor=\"let pivotTable of data.pivotTables; let first; let tableIndex = index\"\n class=\"table table-without-padding table-borderless table-md\"\n [class.mt-4]=\"!first\">\n <tr *ngFor=\"let rowCells of pivotTable | filterVisibleCells:data.pivotStates[tableIndex]; let rowIndex = index\">\n\n <ng-container *ngFor=\"let cell of rowCells; let cellIndex = index\">\n <td *ngIf=\"cell && {hasValue: cell | cellHasValue} as cellData\"\n class=\"cell position-relative {{cell.constraint ? (cell.constraint.type | lowercase) : ''}} text-truncate\"\n [class.expandable]=\"cell | isCellExpandable\"\n [class.expandable-rows]=\"cell | isCellRowsExpandable\"\n [class.expanded]=\"cell | isCellExpanded:cellIndex:data.pivotStates[tableIndex]\"\n [class.sticky-start]=\"cell.stickyStart\"\n [class.sticky-top]=\"cell.stickyTop\"\n [rowSpan]=\"cell.rowSpan\"\n [colSpan]=\"cell.colSpan\"\n [style.top.px]=\"cell.stickyTop ? (rowIndex * stickyColumnHeight) : undefined\"\n [style.left.px]=\"cell.stickyStart ? (cellIndex * stickyColumnWidth) : undefined\"\n [style.width.px]=\"cell.stickyStart ? (cell.colSpan * stickyColumnWidth) : undefined\"\n [style.max-width.px]=\"cell.stickyStart ? (cell.colSpan * stickyColumnWidth) : 300\"\n [style.min-width.px]=\"cell.stickyStart ? (cell.colSpan * stickyColumnWidth) : undefined\"\n [ngClass]=\"cell.cssClass\"\n [style.background]=\"cell.background\"\n [style.color]=\"cell.background && (cell.background | contrastColor)\"\n (click)=\"onCellClick(cell, rowCells, tableIndex, rowIndex, cellIndex)\">\n <ng-container *ngIf=\"cell.summary\">\n <ng-container *ngIf=\"cellData.hasValue\">\n <div class=\"d-flex align-items-center h-100\">\n <span class=\"summary me-2\">{{cell.summary}}</span>\n <ng-template #defaultTableCellTemplate>\n <span class=\"flex-grow-1 h-100 text-truncate d-inline-block\">\n {{ cell.value }}\n </span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"tableCellTemplate || tableCellTemplateInput || defaultTableCellTemplate\"\n [ngTemplateOutletContext]=\"{ value: cell.value, cell: cell }\">\n </ng-template>\n </div>\n </ng-container>\n <ng-container *ngIf=\"!cellData.hasValue\">\n <span class=\"d-block\" style=\"overflow: hidden; white-space: normal\">{{cell.summary}}</span>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!cell.summary\">\n <ng-container *ngIf=\"cellData.hasValue\">\n <ng-template #defaultTableCellTemplate>\n <span class=\"d-block\" style=\"overflow: hidden; white-space: normal; cursor: pointer\">\n {{ cell.value }}\n </span>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"tableCellTemplate || tableCellTemplateInput || defaultTableCellTemplate\"\n [ngTemplateOutletContext]=\"{ value: cell.value, cell: cell }\">\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!cellData.hasValue\">&nbsp;</ng-container>\n </ng-container>\n </td>\n </ng-container>\n </tr>\n </table>\n </ng-container>\n\n <ng-container *ngIf=\"!data.pivotTables?.length || (data.pivotData | pivotDataEmpty)\">\n <ng-template #defaultEmptyTablesTemplate>\n <div>&nbsp;</div>\n </ng-template>\n\n <ng-template\n [ngTemplateOutlet]=\"emptyTablesTemplate || emptyTablesTemplateInput || defaultEmptyTablesTemplate\"\n [ngTemplateOutletContext]=\"{ }\">\n </ng-template>\n </ng-container>\n</ng-container>\n", styles: [".table{border-spacing:0;border-collapse:separate}.pivot-data-cell,.pivot-data-group-cell,.pivot-column-header-cell,.pivot-column-group-header-cell{text-align:right}.pivot-column-header-cell,.pivot-row-attribute-header-cell,.pivot-row-header-cell,.pivot-data-group-cell,.pivot-row-group-header-cell,.pivot-column-group-header-cell{font-weight:700;border:1px #f8f9fa solid}.pivot-row-header-cell.sticky-start,.pivot-row-group-header-cell.sticky-start,.pivot-empty-cell.sticky-start{position:sticky!important;width:150px;min-width:150px;max-width:150px!important;z-index:9}.pivot-row-header-cell.expandable,.pivot-row-group-header-cell.expandable{position:absolute;cursor:pointer;padding-right:15px}.pivot-row-header-cell.expandable:after,.pivot-row-group-header-cell.expandable:after{content:\"\";position:absolute;top:50%;right:5px;width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #253746;transform:translateY(-50%)}.pivot-row-header-cell.expandable.expanded:after,.pivot-row-group-header-cell.expandable.expanded:after{border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #253746;border-bottom:0}.pivot-row-header-cell.expandable.expanded.expandable-rows:after,.pivot-row-group-header-cell.expandable.expanded.expandable-rows:after{border-left:5px solid transparent;border-right:5px solid transparent;border-top:0;border-bottom:5px solid #253746}.pivot-column-header-cell.sticky-top,.pivot-row-attribute-header-cell.sticky-top,.pivot-column-group-header-cell.sticky-top,.pivot-empty-cell.sticky-top{position:sticky!important;z-index:10}.pivot-row-attribute-header-cell.sticky-top,.pivot-row-attribute-header-cell.sticky-start{position:sticky!important;z-index:11}.pivot-empty-cell{background:white;border:1px white solid}.pivot-empty-cell.sticky-top{z-index:11}.cell.color{padding:0!important;height:30px}.cell.color .summary{padding-left:.5rem}\n"] }]
1753
2095
  }], propDecorators: { collections: [{
1754
2096
  type: Input
1755
2097
  }], data: [{
@@ -1768,6 +2110,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
1768
2110
  type: Input
1769
2111
  }], tableCellTemplateInput: [{
1770
2112
  type: Input
2113
+ }], initiallyCollapsed: [{
2114
+ type: Input
1771
2115
  }], cellClick: [{
1772
2116
  type: Output
1773
2117
  }], pivotDataChange: [{
@@ -1781,6 +2125,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
1781
2125
  type: ContentChild,
1782
2126
  args: [LmrTableCellTemplateDirective, { read: TemplateRef }]
1783
2127
  }] } });
2128
+ function shouldResetState(changes) {
2129
+ if (changes['config']) {
2130
+ const previousValue = changes['config'].previousValue;
2131
+ const currentValue = changes['config'].currentValue;
2132
+ return isPivotConfigChanged(previousValue, currentValue);
2133
+ }
2134
+ return false;
2135
+ }
2136
+ function tablesAreVeryDifferent(t1, t2) {
2137
+ if ((t1 || []).length !== (t2 || []).length) {
2138
+ return true;
2139
+ }
2140
+ // row numbers are different
2141
+ return (t1 || []).some((t, index) => t.cells?.length !== t2[index].cells?.length);
2142
+ }
1784
2143
 
1785
2144
  class LmrSimplePivotTableComponent {
1786
2145
  rows;
@@ -1789,6 +2148,7 @@ class LmrSimplePivotTableComponent {
1789
2148
  config;
1790
2149
  transform;
1791
2150
  locale;
2151
+ initiallyCollapsed;
1792
2152
  cellClick = new EventEmitter();
1793
2153
  pivotDataChange = new EventEmitter();
1794
2154
  pivotTablesChange = new EventEmitter();
@@ -1844,11 +2204,11 @@ class LmrSimplePivotTableComponent {
1844
2204
  });
1845
2205
  }
1846
2206
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LmrSimplePivotTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1847
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: LmrSimplePivotTableComponent, selector: "lmr-simple-pivot-table", inputs: { rows: "rows", attributes: "attributes", color: "color", config: "config", transform: "transform", locale: "locale" }, outputs: { cellClick: "cellClick", pivotDataChange: "pivotDataChange", pivotTablesChange: "pivotTablesChange" }, queries: [{ propertyName: "emptyTablesTemplate", first: true, predicate: LmrEmptyTablesTemplateDirective, descendants: true, read: TemplateRef }, { propertyName: "tableCellTemplate", first: true, predicate: LmrTableCellTemplateDirective, descendants: true, read: TemplateRef }], usesOnChanges: true, ngImport: i0, template: "<lmr-pivot-table [transform]=\"transform\"\n [data]=\"data\"\n [config]=\"pivotConfig\"\n [query]=\"query\"\n [constraintData]=\"constraintData\"\n [collections]=\"[collection]\"\n [emptyTablesTemplateInput]=\"emptyTablesTemplate\"\n [tableCellTemplateInput]=\"tableCellTemplate\"\n (pivotDataChange)=\"pivotDataChange.emit($event)\"\n (pivotTablesChange)=\"pivotTablesChange.emit($event)\">\n</lmr-pivot-table>\n", dependencies: [{ kind: "component", type: LmrPivotTableComponent, selector: "lmr-pivot-table", inputs: ["collections", "data", "linkTypes", "query", "constraintData", "config", "transform", "emptyTablesTemplateInput", "tableCellTemplateInput"], outputs: ["cellClick", "pivotDataChange", "pivotTablesChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2207
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: LmrSimplePivotTableComponent, selector: "lmr-simple-pivot-table", inputs: { rows: "rows", attributes: "attributes", color: "color", config: "config", transform: "transform", locale: "locale", initiallyCollapsed: "initiallyCollapsed" }, outputs: { cellClick: "cellClick", pivotDataChange: "pivotDataChange", pivotTablesChange: "pivotTablesChange" }, queries: [{ propertyName: "emptyTablesTemplate", first: true, predicate: LmrEmptyTablesTemplateDirective, descendants: true, read: TemplateRef }, { propertyName: "tableCellTemplate", first: true, predicate: LmrTableCellTemplateDirective, descendants: true, read: TemplateRef }], usesOnChanges: true, ngImport: i0, template: "<lmr-pivot-table [transform]=\"transform\"\n [data]=\"data\"\n [config]=\"pivotConfig\"\n [query]=\"query\"\n [constraintData]=\"constraintData\"\n [collections]=\"[collection]\"\n [emptyTablesTemplateInput]=\"emptyTablesTemplate\"\n [tableCellTemplateInput]=\"tableCellTemplate\"\n [initiallyCollapsed]=\"initiallyCollapsed\"\n (cellClick)=\"cellClick.emit($event)\"\n (pivotDataChange)=\"pivotDataChange.emit($event)\"\n (pivotTablesChange)=\"pivotTablesChange.emit($event)\">\n</lmr-pivot-table>\n", dependencies: [{ kind: "component", type: LmrPivotTableComponent, selector: "lmr-pivot-table", inputs: ["collections", "data", "linkTypes", "query", "constraintData", "config", "transform", "emptyTablesTemplateInput", "tableCellTemplateInput", "initiallyCollapsed"], outputs: ["cellClick", "pivotDataChange", "pivotTablesChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1848
2208
  }
1849
2209
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LmrSimplePivotTableComponent, decorators: [{
1850
2210
  type: Component,
1851
- args: [{ selector: 'lmr-simple-pivot-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<lmr-pivot-table [transform]=\"transform\"\n [data]=\"data\"\n [config]=\"pivotConfig\"\n [query]=\"query\"\n [constraintData]=\"constraintData\"\n [collections]=\"[collection]\"\n [emptyTablesTemplateInput]=\"emptyTablesTemplate\"\n [tableCellTemplateInput]=\"tableCellTemplate\"\n (pivotDataChange)=\"pivotDataChange.emit($event)\"\n (pivotTablesChange)=\"pivotTablesChange.emit($event)\">\n</lmr-pivot-table>\n" }]
2211
+ args: [{ selector: 'lmr-simple-pivot-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<lmr-pivot-table [transform]=\"transform\"\n [data]=\"data\"\n [config]=\"pivotConfig\"\n [query]=\"query\"\n [constraintData]=\"constraintData\"\n [collections]=\"[collection]\"\n [emptyTablesTemplateInput]=\"emptyTablesTemplate\"\n [tableCellTemplateInput]=\"tableCellTemplate\"\n [initiallyCollapsed]=\"initiallyCollapsed\"\n (cellClick)=\"cellClick.emit($event)\"\n (pivotDataChange)=\"pivotDataChange.emit($event)\"\n (pivotTablesChange)=\"pivotTablesChange.emit($event)\">\n</lmr-pivot-table>\n" }]
1852
2212
  }], propDecorators: { rows: [{
1853
2213
  type: Input
1854
2214
  }], attributes: [{
@@ -1861,6 +2221,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
1861
2221
  type: Input
1862
2222
  }], locale: [{
1863
2223
  type: Input
2224
+ }], initiallyCollapsed: [{
2225
+ type: Input
1864
2226
  }], cellClick: [{
1865
2227
  type: Output
1866
2228
  }], pivotDataChange: [{
@@ -1880,7 +2242,11 @@ class LmrPivotTableModule {
1880
2242
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: LmrPivotTableModule, declarations: [LmrPivotTableComponent,
1881
2243
  LmrSimplePivotTableComponent,
1882
2244
  PivotDataEmptyPipe,
1883
- PivotTableCellHasValuePipe,
2245
+ CellHasValuePipe,
2246
+ IsCellExpandablePipe,
2247
+ IsCellExpandedPipe,
2248
+ IsCellRowsExpandablePipe,
2249
+ FilterVisibleCellsPipe,
1884
2250
  ContrastColorPipe,
1885
2251
  LmrEmptyTablesTemplateDirective,
1886
2252
  LmrTableCellTemplateDirective], imports: [CommonModule,
@@ -1898,7 +2264,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
1898
2264
  LmrPivotTableComponent,
1899
2265
  LmrSimplePivotTableComponent,
1900
2266
  PivotDataEmptyPipe,
1901
- PivotTableCellHasValuePipe,
2267
+ CellHasValuePipe,
2268
+ IsCellExpandablePipe,
2269
+ IsCellExpandedPipe,
2270
+ IsCellRowsExpandablePipe,
2271
+ FilterVisibleCellsPipe,
1902
2272
  ContrastColorPipe,
1903
2273
  LmrEmptyTablesTemplateDirective,
1904
2274
  LmrTableCellTemplateDirective,