@one-paragon/angular-utilities 2.0.0-beta.9 → 2.0.1

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.
@@ -1,11 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, Input, inject, Injector, TemplateRef, ViewContainerRef, NgModule, assertInInjectionContext, DestroyRef, computed, isSignal, Injectable, Pipe, input, signal, Renderer2, ElementRef, booleanAttribute, InjectionToken, makeEnvironmentProviders, Component, ChangeDetectionStrategy, HostListener, EventEmitter, untracked, Output, ContentChildren, ChangeDetectorRef, output, ViewChild, EnvironmentInjector, createComponent, viewChild, effect, linkedSignal, contentChild, forwardRef, contentChildren, model, runInInjectionContext, provideAppInitializer } from '@angular/core';
3
- import { shareReplay, switchAll, map, filter, tap, catchError, startWith, switchMap, mergeMap, concatMap as concatMap$1, takeUntil, distinctUntilChanged, observeOn, scan as scan$1, timestamp as timestamp$1, first as first$1 } from 'rxjs/operators';
2
+ import { Directive, Input, inject, Injector, TemplateRef, ViewContainerRef, NgModule, assertInInjectionContext, DestroyRef, computed, isSignal, Injectable, Pipe, input, signal, Renderer2, ElementRef, booleanAttribute, InjectionToken, makeEnvironmentProviders, Component, ChangeDetectionStrategy, HostListener, EventEmitter, untracked, Output, ContentChildren, ChangeDetectorRef, output, ViewChild, EnvironmentInjector, createComponent, viewChild, linkedSignal, effect, contentChild, forwardRef, contentChildren, model, runInInjectionContext, provideAppInitializer } from '@angular/core';
3
+ import { shareReplay, switchAll, map, filter, tap, catchError, startWith, switchMap, mergeMap, concatMap as concatMap$1, takeUntil, distinctUntilChanged, observeOn, debounceTime, scan as scan$1, timestamp as timestamp$1, first as first$1 } from 'rxjs/operators';
4
4
  import * as i1 from 'rxjs';
5
- import { Subject, isObservable, of, ReplaySubject, filter as filter$1, first, map as map$1, Observable, combineLatest, Subscription, startWith as startWith$1, pairwise, concatMap, merge, delay, fromEvent, takeUntil as takeUntil$1, tap as tap$1, switchMap as switchMap$1, scan, animationFrameScheduler, debounceTime, timestamp, BehaviorSubject } from 'rxjs';
5
+ import { Subject, isObservable, of, ReplaySubject, filter as filter$1, first, map as map$1, Observable, combineLatest, Subscription, startWith as startWith$1, pairwise, concatMap, merge, delay, fromEvent, takeUntil as takeUntil$1, tap as tap$1, switchMap as switchMap$1, scan, timestamp, animationFrameScheduler, debounceTime as debounceTime$1, BehaviorSubject } from 'rxjs';
6
6
  import { ComponentStore } from '@ngrx/component-store';
7
7
  import { toObservable, toSignal, outputFromObservable } from '@angular/core/rxjs-interop';
8
- import * as i1$8 from '@angular/common';
9
8
  import { DatePipe, CurrencyPipe, KeyValuePipe, NgTemplateOutlet, DecimalPipe, CommonModule, AsyncPipe } from '@angular/common';
10
9
  import * as i3$2 from '@angular/material/sort';
11
10
  import { MatSort, MatSortModule } from '@angular/material/sort';
@@ -24,7 +23,7 @@ import * as i9 from '@angular/material/core';
24
23
  import { MatOption, MatNativeDateModule } from '@angular/material/core';
25
24
  import * as i5 from '@angular/cdk/drag-drop';
26
25
  import { moveItemInArray, DragDropModule, CDK_DROP_LIST, CdkDropList, transferArrayItem } from '@angular/cdk/drag-drop';
27
- import * as i1$4 from '@angular/router';
26
+ import * as i1$5 from '@angular/router';
28
27
  import { RouterModule } from '@angular/router';
29
28
  import * as i1$1 from '@angular/material/input';
30
29
  import { MatInputModule, MatInput } from '@angular/material/input';
@@ -42,16 +41,16 @@ import * as i2 from '@angular/material/icon';
42
41
  import { MatIconModule, MatIcon } from '@angular/material/icon';
43
42
  import * as i8 from '@angular/material/select';
44
43
  import { MatSelectModule } from '@angular/material/select';
45
- import * as i4$2 from '@angular/material/menu';
46
- import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
47
- import * as i4$3 from '@angular/material/chips';
44
+ import * as i1$4 from '@angular/material/menu';
45
+ import { MatMenuModule, MatMenuTrigger, MatMenu } from '@angular/material/menu';
46
+ import * as i4$2 from '@angular/material/chips';
48
47
  import { MatChipsModule } from '@angular/material/chips';
49
- import * as i1$5 from '@angular/material/table';
48
+ import * as i1$6 from '@angular/material/table';
50
49
  import { MatTable, MatColumnDef, MatTableModule, MatHeaderRowDef, MatFooterRowDef, MatTableDataSource, MatRowDef } from '@angular/material/table';
51
50
  import { SelectionModel } from '@angular/cdk/collections';
52
- import * as i1$6 from '@angular/material/paginator';
51
+ import * as i1$7 from '@angular/material/paginator';
53
52
  import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
54
- import * as i1$7 from '@angular/cdk/scrolling';
53
+ import * as i1$8 from '@angular/cdk/scrolling';
55
54
  import { CdkVirtualScrollViewport, ScrollingModule, VIRTUAL_SCROLL_STRATEGY } from '@angular/cdk/scrolling';
56
55
  import * as i1$9 from '@ngrx/store';
57
56
  import { createFeatureSelector, createSelector, StoreModule, Store } from '@ngrx/store';
@@ -898,6 +897,22 @@ const DefaultVirtualScrollOptions = {
898
897
  rowHeight: 48,
899
898
  headerHeight: 56,
900
899
  };
900
+ function parseTbSizeToPixels(size) {
901
+ if (!size)
902
+ return undefined;
903
+ if (typeof size === 'number')
904
+ return size;
905
+ if (size.endsWith('px'))
906
+ return Number(size.replace('px', ''));
907
+ if (size.endsWith('rem')) {
908
+ const htmlElement = document.documentElement;
909
+ const remSize = window.getComputedStyle(htmlElement).getPropertyValue('font-size');
910
+ const remSizeNum = Number(remSize.replace('px', ''));
911
+ const num = Number(size.replace('rem', ''));
912
+ return num * remSizeNum;
913
+ }
914
+ return undefined;
915
+ }
901
916
 
902
917
  class KeysToDelete {
903
918
  initializationState = null;
@@ -919,7 +934,7 @@ var InitializationState;
919
934
  (function (InitializationState) {
920
935
  InitializationState[InitializationState["Created"] = 0] = "Created";
921
936
  InitializationState[InitializationState["MetaDataLoaded"] = 1] = "MetaDataLoaded";
922
- InitializationState[InitializationState["LoadedFromStore"] = 2] = "LoadedFromStore";
937
+ InitializationState[InitializationState["TableSettingsLoaded"] = 2] = "TableSettingsLoaded";
923
938
  InitializationState[InitializationState["Ready"] = 3] = "Ready";
924
939
  })(InitializationState || (InitializationState = {}));
925
940
  const defaultTableState = {
@@ -940,7 +955,8 @@ const defaultTableState = {
940
955
  };
941
956
  const defaultDataState = {
942
957
  virtualScrollOffset: 0,
943
- dataLen: 0,
958
+ sortedFilteredDataLength: 0,
959
+ sortedFilteredGroupedDataLength: 0,
944
960
  virtualEnds: {
945
961
  start: 0, end: 20
946
962
  },
@@ -1100,7 +1116,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
1100
1116
  }]
1101
1117
  }] });
1102
1118
 
1103
- const FilterTypes = {
1119
+ const FilterType = {
1104
1120
  NumberEquals: 'Equals',
1105
1121
  NumberNotEqual: 'Does Not Equal',
1106
1122
  NumberGreaterThan: 'Greater Than',
@@ -1154,7 +1170,7 @@ class TableFilterDirective {
1154
1170
  }
1155
1171
  if (this.model) {
1156
1172
  subscriber(this.model.valueChanges, val => {
1157
- if (this.filterType === FilterTypes.StringContains && val === '') {
1173
+ if (this.filterType === FilterType.StringContains && val === '') {
1158
1174
  val = undefined;
1159
1175
  }
1160
1176
  this.filterValue = val;
@@ -1238,7 +1254,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
1238
1254
  class TableFilterStringContainsDirective extends TableFilterDirective {
1239
1255
  constructor() {
1240
1256
  super();
1241
- this.filterType = FilterTypes.StringContains;
1257
+ this.filterType = FilterType.StringContains;
1242
1258
  this.fieldType = FieldType.String;
1243
1259
  }
1244
1260
  reset() {
@@ -1306,7 +1322,7 @@ class TableCustomFilterDirectiveBase extends TableCustomFilterDirective {
1306
1322
  this.savable = true;
1307
1323
  }
1308
1324
  this.filter = {
1309
- filterType: FilterTypes.Custom,
1325
+ filterType: FilterType.Custom,
1310
1326
  filterId: this.filterId,
1311
1327
  active: this._active,
1312
1328
  predicate: this._predicate,
@@ -1573,17 +1589,17 @@ const multipleStringValuesEqualsFunc = (filterInfo) => {
1573
1589
  return ((val) => filterVals.some((s) => prepareForStringCompare(val) === s));
1574
1590
  };
1575
1591
  const StringFilterFuncs = {
1576
- [FilterTypes.StringEquals]: stringEqualFunc,
1577
- [FilterTypes.StringContains]: stringContainsFunc,
1578
- [FilterTypes.StringDoesNotContain]: stringDoesNotContainFunc,
1579
- [FilterTypes.StringStartWith]: stringStartsWithFunc,
1580
- [FilterTypes.StringEndsWith]: stringEndsWithFunc,
1581
- [FilterTypes.IsNull]: isNull,
1582
- [FilterTypes.In]: multipleStringValuesEqualsFunc,
1592
+ [FilterType.StringEquals]: stringEqualFunc,
1593
+ [FilterType.StringContains]: stringContainsFunc,
1594
+ [FilterType.StringDoesNotContain]: stringDoesNotContainFunc,
1595
+ [FilterType.StringStartWith]: stringStartsWithFunc,
1596
+ [FilterType.StringEndsWith]: stringEndsWithFunc,
1597
+ [FilterType.IsNull]: isNull,
1598
+ [FilterType.In]: multipleStringValuesEqualsFunc,
1583
1599
  };
1584
1600
  const EnumFilterFuncs = {
1585
- [FilterTypes.IsNull]: isNull,
1586
- [FilterTypes.In]: multipleStringValuesEqualsFunc,
1601
+ [FilterType.IsNull]: isNull,
1602
+ [FilterType.In]: multipleStringValuesEqualsFunc,
1587
1603
  };
1588
1604
  const prepareForStringCompare = (val) => (val?.toString().trim().toLowerCase());
1589
1605
 
@@ -1608,13 +1624,13 @@ const multipleNumberValuesEqualsFunc = (filterInfo) => {
1608
1624
  return ((val) => filterInfo.filterValue.some((value) => val === value));
1609
1625
  };
1610
1626
  const NumberFilterFuncs = {
1611
- [FilterTypes.NumberEquals]: numberEqalsFunc,
1612
- [FilterTypes.NumberNotEqual]: numberNotEqualFunc,
1613
- [FilterTypes.NumberGreaterThan]: numberGreaterThanFunc,
1614
- [FilterTypes.NumberLessThan]: numberLessThanFunc,
1615
- [FilterTypes.NumberBetween]: numberBetweenFunc,
1616
- [FilterTypes.IsNull]: isNull,
1617
- [FilterTypes.In]: multipleNumberValuesEqualsFunc,
1627
+ [FilterType.NumberEquals]: numberEqalsFunc,
1628
+ [FilterType.NumberNotEqual]: numberNotEqualFunc,
1629
+ [FilterType.NumberGreaterThan]: numberGreaterThanFunc,
1630
+ [FilterType.NumberLessThan]: numberLessThanFunc,
1631
+ [FilterType.NumberBetween]: numberBetweenFunc,
1632
+ [FilterType.IsNull]: isNull,
1633
+ [FilterType.In]: multipleNumberValuesEqualsFunc,
1618
1634
  };
1619
1635
 
1620
1636
  const dateIsOnFunc = (filterInfo) => {
@@ -1655,37 +1671,37 @@ const cleanDateTime = (filterInfo, val) => {
1655
1671
  return val;
1656
1672
  };
1657
1673
  const DateFilterFuncs = {
1658
- [FilterTypes.DateIsOn]: dateIsOnFunc,
1659
- [FilterTypes.DateIsNotOn]: dateIsNotOnFunc,
1660
- [FilterTypes.DateOnOrAfter]: dateIsOnOrAfterFunc,
1661
- [FilterTypes.DateOnOrBefore]: dateIsOnOrBeforeFunc,
1662
- [FilterTypes.DateBetween]: dateBetweenFunc,
1663
- [FilterTypes.IsNull]: isNull,
1674
+ [FilterType.DateIsOn]: dateIsOnFunc,
1675
+ [FilterType.DateIsNotOn]: dateIsNotOnFunc,
1676
+ [FilterType.DateOnOrAfter]: dateIsOnOrAfterFunc,
1677
+ [FilterType.DateOnOrBefore]: dateIsOnOrBeforeFunc,
1678
+ [FilterType.DateBetween]: dateBetweenFunc,
1679
+ [FilterType.IsNull]: isNull,
1664
1680
  };
1665
1681
  const DateTimeFilterFuncs = {
1666
1682
  ...DateFilterFuncs,
1667
- [FilterTypes.DateTimeIsAt]: dateIsOnFunc,
1668
- [FilterTypes.DateTimeIsNotAt]: dateIsNotOnFunc,
1669
- [FilterTypes.DateTimeAtOrAfter]: dateIsOnOrAfterFunc,
1670
- [FilterTypes.DateTimeAtOrBefore]: dateIsOnOrBeforeFunc,
1671
- [FilterTypes.DateTimeBetween]: dateBetweenFunc,
1672
- [FilterTypes.IsNull]: isNull,
1683
+ [FilterType.DateTimeIsAt]: dateIsOnFunc,
1684
+ [FilterType.DateTimeIsNotAt]: dateIsNotOnFunc,
1685
+ [FilterType.DateTimeAtOrAfter]: dateIsOnOrAfterFunc,
1686
+ [FilterType.DateTimeAtOrBefore]: dateIsOnOrBeforeFunc,
1687
+ [FilterType.DateTimeBetween]: dateBetweenFunc,
1688
+ [FilterType.IsNull]: isNull,
1673
1689
  };
1674
1690
 
1675
1691
  const booleanEqualsFunc = (filterInfo) => (val) => {
1676
1692
  return filterInfo.filterValue === val;
1677
1693
  };
1678
1694
  const BooleanFilterFuncs = {
1679
- [FilterTypes.BooleanEquals]: booleanEqualsFunc,
1680
- [FilterTypes.IsNull]: isNull,
1695
+ [FilterType.BooleanEquals]: booleanEqualsFunc,
1696
+ [FilterType.IsNull]: isNull,
1681
1697
  };
1682
1698
 
1683
1699
  const filterFactoryMap = {
1684
- [FilterTypes.And]: (filter) => {
1700
+ [FilterType.And]: (filter) => {
1685
1701
  const filters = createFilterFuncs(filter.filterValue);
1686
1702
  return (obj) => filters.every(f => f(obj));
1687
1703
  },
1688
- [FilterTypes.In]: (filter) => {
1704
+ [FilterType.In]: (filter) => {
1689
1705
  const filters = createFilterFuncs(filter.filterValue);
1690
1706
  return (obj) => filters.some(f => f(obj));
1691
1707
  },
@@ -1705,10 +1721,10 @@ const filterTypeFuncMap = {
1705
1721
  };
1706
1722
  const filterTypeMap = Object.entries(filterTypeFuncMap).reduce((acc, [key, value]) => ({ ...acc, [key]: Object.keys(value) }), {});
1707
1723
  function isCustomFilter(filter) {
1708
- return filter && filter.filterType === FilterTypes.Custom;
1724
+ return filter && filter.filterType === FilterType.Custom;
1709
1725
  }
1710
1726
  function isFilterInfo(filter) {
1711
- return filter && typeof filter.key === 'string' && filter.filterType !== FilterTypes.Custom;
1727
+ return filter && typeof filter.key === 'string' && filter.filterType !== FilterType.Custom;
1712
1728
  }
1713
1729
  const defaultPredicate = () => true;
1714
1730
  function createFilterFuncs(filters) {
@@ -1742,10 +1758,10 @@ function createFilterFunc(filter) {
1742
1758
  };
1743
1759
  }
1744
1760
  const FalseyValueCanBeIncludedFilterTypes = [
1745
- FilterTypes.IsNull,
1746
- FilterTypes.NumberNotEqual,
1747
- FilterTypes.DateIsNotOn,
1748
- FilterTypes.StringDoesNotContain,
1761
+ FilterType.IsNull,
1762
+ FilterType.NumberNotEqual,
1763
+ FilterType.DateIsNotOn,
1764
+ FilterType.StringDoesNotContain,
1749
1765
  ];
1750
1766
 
1751
1767
  const replaceInArrayWithClone = (arr, findMeth, actionOnClone = ((t) => { })) => {
@@ -1882,13 +1898,14 @@ class TableStore extends ComponentStore {
1882
1898
  $hiddenKeys = this.selectSignal(state => state.hiddenKeys);
1883
1899
  $orderedVisibleColumns = this.selectSignal(this.$orderedCodeVisibleMetaDatas, this.$hiddenKeys, (cs, hiddenKeys) => cs.filter(m => !hiddenKeys.includes(m.key)).map(m => m.key));
1884
1900
  $getUserDefinedWidths = this.selectSignal(state => state.userDefined.widths);
1885
- $tableSettingsMinWidth = this.selectSignal(state => state.notPersistedTableSettings.minColumnWidth);
1901
+ $tableSettingsMinWidth = this.selectSignal(state => parseTbSizeToPixels(state.notPersistedTableSettings.minColumnWidth));
1886
1902
  $getUserDefinedWidth = (key) => this.selectSignal(this.$getUserDefinedWidths, widths => widths[key]);
1887
1903
  $filters = this.selectSignal(state => state.filters);
1888
1904
  filters$ = this.select(state => state.filters);
1889
1905
  $getFilter = (filterId) => {
1890
1906
  return this.selectSignal(this.$filters, filters => filters[filterId]);
1891
1907
  };
1908
+ $preSort = computed(() => createPreSort(this.$metaData()));
1892
1909
  $selectSorted = this.selectSignal(state => state.sorted, {
1893
1910
  equal: sortsAreSame
1894
1911
  });
@@ -1897,6 +1914,9 @@ class TableStore extends ComponentStore {
1897
1914
  .pipe(switchMap(() => this.selectSorted$));
1898
1915
  $getUserDefinedTableWidth = this.selectSignal(state => state.userDefined.table.width);
1899
1916
  getUserDefinedTableWidth$ = this.select(state => state.userDefined.table.width);
1917
+ $userDefinedRowHeight = this.selectSignal(state => (state.userDefined.rowHeight));
1918
+ $userDefinedHeaderHeight = this.selectSignal(state => (state.userDefined.headerHeight));
1919
+ $userDefinedPageSize = this.selectSignal(state => (state.userDefined.pageSize));
1900
1920
  $footerCollapsed = this.selectSignal(state => state.persistedTableSettings.collapseFooter);
1901
1921
  $headerCollapsed = this.selectSignal(state => state.persistedTableSettings.collapseHeader);
1902
1922
  $groupBy = this.selectSignal(state => state.groupBy);
@@ -1920,6 +1940,7 @@ class TableStore extends ComponentStore {
1920
1940
  const ts = { ...state.persistedTableSettings, ...state.notPersistedTableSettings };
1921
1941
  return ts;
1922
1942
  });
1943
+ $notPersistedTableSettings = this.selectSignal(state => state.notPersistedTableSettings);
1923
1944
  tableSettings$ = toObservable(this.$tableSettings);
1924
1945
  $props = this.selectSignal(s => s.props);
1925
1946
  $getLinkInfo = (md) => this.selectSignal(state => state.linkMaps[md.key]);
@@ -1928,7 +1949,7 @@ class TableStore extends ComponentStore {
1928
1949
  || state.userDefined?.showAll);
1929
1950
  $viewType = this.selectSignal(state => {
1930
1951
  const usePaginator = state.notPersistedTableSettings.usePaginator;
1931
- const showAll = state.showAll;
1952
+ const showAll = state.showAll || state.userDefined?.showAll;
1932
1953
  const useVirtualScroll = state.notPersistedTableSettings.useVirtualScroll;
1933
1954
  if (showAll || (useVirtualScroll && !usePaginator)) {
1934
1955
  return 'virtual all';
@@ -1944,19 +1965,56 @@ class TableStore extends ComponentStore {
1944
1965
  }
1945
1966
  });
1946
1967
  resetState = this.updater((state) => {
1947
- const sorted = createPreSort(state.metaData);
1968
+ const sorted = this.$preSort();
1948
1969
  return ({ ...state, hiddenKeys: [], sorted, filters: {}, groupBy: [], userDefined: { widths: {}, order: {}, table: {} } });
1949
1970
  });
1971
+ resetPart = this.updater((state, part) => {
1972
+ const newState = { ...state };
1973
+ switch (part) {
1974
+ case 'Sorting':
1975
+ newState.sorted = this.$preSort();
1976
+ return newState;
1977
+ case 'Filters':
1978
+ newState.filters = {};
1979
+ return newState;
1980
+ case 'Group By':
1981
+ newState.groupBy = [];
1982
+ return newState;
1983
+ case 'Hidden Columns':
1984
+ newState.hiddenKeys = [];
1985
+ return newState;
1986
+ case 'Column Widths':
1987
+ newState.userDefined.widths = {};
1988
+ newState.userDefined.table = {};
1989
+ return newState;
1990
+ case 'Column Order':
1991
+ newState.userDefined.order = {};
1992
+ return newState;
1993
+ case 'Page Size':
1994
+ delete newState.userDefined.pageSize;
1995
+ return newState;
1996
+ case 'Show All':
1997
+ delete newState.userDefined.showAll;
1998
+ return newState;
1999
+ case 'Row Height':
2000
+ delete newState.userDefined.rowHeight;
2001
+ return newState;
2002
+ case 'Header Height':
2003
+ delete newState.userDefined.headerHeight;
2004
+ return newState;
2005
+ }
2006
+ return newState;
2007
+ });
1950
2008
  updateStateFromPersistedState = this.updater((state, persistedState) => {
1951
2009
  const incomingTableState = cleanPersistedState(state, persistedState);
1952
2010
  const newState = this.updateStateFunc(state, incomingTableState);
1953
- newState.initializationState = state.initializationState === InitializationState.MetaDataLoaded ? InitializationState.LoadedFromStore : state.initializationState;
2011
+ newState.initializationState = state.initializationState <= InitializationState.MetaDataLoaded ? InitializationState.TableSettingsLoaded : state.initializationState;
1954
2012
  return newState;
1955
2013
  });
1956
2014
  updateStateFunc = (state, incomingTableState) => {
1957
2015
  const metaData = state.metaData;
1958
2016
  const sorted = incomingTableState.sorted?.length ? incomingTableState.sorted
1959
- : state.initializationState === InitializationState.Created ? createPreSort(metaData) : state.sorted;
2017
+ : state.initializationState <= InitializationState.Created ? this.$preSort() : state.sorted;
1960
2018
  return { ...state, ...incomingTableState, metaData, sorted };
1961
2019
  };
1962
2020
  setTableSettings = this.updater((state, settings) => {
@@ -1964,7 +2022,7 @@ class TableStore extends ComponentStore {
1964
2022
  ...state,
1965
2023
  persistedTableSettings: state.persistedTableSettings.merge(settings),
1966
2024
  notPersistedTableSettings: state.notPersistedTableSettings.merge(settings),
1967
- initializationState: InitializationState.Ready
2025
+ initializationState: InitializationState.TableSettingsLoaded
1968
2026
  };
1969
2027
  s.pageSize = settings.tableSettings?.paginatorSettings?.pageSize ?? s.pageSize;
1970
2028
  s.showAll = settings.tableSettings?.paginatorSettings?.defaultAll ?? s.showAll;
@@ -1982,7 +2040,7 @@ class TableStore extends ComponentStore {
1982
2040
  return prev;
1983
2041
  }, {});
1984
2042
  const sortedInitialized = state.sorted.length > 0;
1985
- const sorted = sortedInitialized ? state.sorted : createPreSort(metaData);
2043
+ const sorted = sortedInitialized ? state.sorted : this.$preSort();
1986
2044
  const order = initializeOrder(state, metaData);
1987
2045
  const initializationState = state.initializationState == InitializationState.Created ? InitializationState.MetaDataLoaded : state.initializationState;
1988
2046
  return { ...state, initializationState, metaData, sorted, userDefined: { ...state.userDefined, order: order } };
@@ -2015,6 +2073,12 @@ class TableStore extends ComponentStore {
2015
2073
  }, {});
2016
2074
  return ({ ...state, userDefined: { ...state.userDefined, order: userDefinedOrder } });
2017
2075
  });
2076
+ setUserDefinedRowHeight = this.updater((state, rowHeight) => {
2077
+ return ({ ...state, userDefined: { ...state.userDefined, rowHeight } });
2078
+ });
2079
+ setUserDefinedHeaderHeight = this.updater((state, headerHeight) => {
2080
+ return ({ ...state, userDefined: { ...state.userDefined, headerHeight } });
2081
+ });
2018
2082
  addFilter = this.updater((state, filter) => {
2019
2083
  return this.addFiltersToState(state, [filter]);
2020
2084
  });
@@ -2140,6 +2204,18 @@ class TableStore extends ComponentStore {
2140
2204
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: TableStore, decorators: [{
2141
2205
  type: Injectable
2142
2206
  }], ctorParameters: () => [] });
2207
+ const resetable = [
2208
+ 'Sorting',
2209
+ 'Filters',
2210
+ 'Group By',
2211
+ 'Hidden Columns',
2212
+ 'Column Widths',
2213
+ 'Column Order',
2214
+ 'Row Height',
2215
+ 'Header Height',
2216
+ 'Page Size',
2217
+ 'Show All',
2218
+ ];
2143
2219
 
2144
2220
  class MultiSortDirective extends MatSort {
2145
2221
  state = inject(TableStore);
@@ -2186,7 +2262,7 @@ function sortsAreSame(a, b) {
2186
2262
  }
2187
2263
 
2188
2264
  class DateFilterComponent {
2189
- FilterType = FilterTypes;
2265
+ FilterType = FilterType;
2190
2266
  info;
2191
2267
  CurrentFilterType;
2192
2268
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: DateFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -2765,7 +2841,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
2765
2841
  }], ctorParameters: () => [] });
2766
2842
 
2767
2843
  class NumberFilterComponent {
2768
- FilterType = FilterTypes;
2844
+ FilterType = FilterType;
2769
2845
  FieldType = FieldType;
2770
2846
  $currentFilterType = input.required({ alias: 'CurrentFilterType' });
2771
2847
  $info = input.required({ alias: 'info' });
@@ -2780,7 +2856,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
2780
2856
  }] });
2781
2857
 
2782
2858
  class DateTimeFilterComponent {
2783
- FilterType = FilterTypes;
2859
+ FilterType = FilterType;
2784
2860
  info;
2785
2861
  CurrentFilterType;
2786
2862
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: DateTimeFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -2887,7 +2963,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
2887
2963
  class FilterComponent {
2888
2964
  state = inject(TableStore);
2889
2965
  filterTypes = filterTypeMap;
2890
- FilterType = FilterTypes;
2966
+ FilterType = FilterType;
2891
2967
  FieldType = FieldType;
2892
2968
  $filter = input.required({
2893
2969
  alias: 'filter',
@@ -2939,7 +3015,7 @@ class GenColDisplayerComponent {
2939
3015
  this.tableState.setHiddenColumns(displayCols.map(c => ({ key: c.key, visible: c.isVisible })));
2940
3016
  }
2941
3017
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GenColDisplayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2942
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: GenColDisplayerComponent, isStandalone: true, selector: "tb-col-displayer", ngImport: i0, template: "@if($columns(); as displayCols){\r\n <span matTooltip=\"Show/hide columns\">\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\r\n <mat-icon color=\"primary\">visibility_off</mat-icon>\r\n </button>\r\n </span>\r\n <mat-menu #menu=\"matMenu\" class=\"my-mat-menu\">\r\n\r\n <button mat-menu-item>\r\n <span matTooltip=\"Close\">\r\n <button class=\"filter-button\" mat-icon-button>\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </span>\r\n </button>\r\n\r\n <button mat-menu-item stop-propagation>\r\n <span matTooltip=\"Show all columns\">\r\n <button mat-icon-button (click)=\"reset(displayCols)\">\r\n <mat-icon color=\"primary\">done_all</mat-icon>\r\n </button>\r\n </span>\r\n\r\n <span matTooltip=\"Hide all columns\">\r\n <button mat-icon-button (click)=\"unset(displayCols)\">\r\n <mat-icon color=\"primary\">cancel</mat-icon>\r\n </button>\r\n </span>\r\n </button>\r\n\r\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\" stop-propagation [cdkDropListLockAxis]=\"'y'\">\r\n @for (col of displayCols; track col.key) {\r\n <button [class.isHidden]=\"!col.isVisible\" stop-propagation mat-menu-item cdkDrag [cdkDragData]=\"col\">\r\n <div (click)=\"col.isVisible = !col.isVisible; emit(displayCols)\" style=\"display: flex; align-items: center;\">\r\n @if(col.isVisible){\r\n <button mat-icon-button matTooltip=\"Hide Column\" class=\"show-hide\">\r\n <mat-icon color=\"primary\">check_box</mat-icon>\r\n </button>\r\n } @else {\r\n <button mat-icon-button matTooltip=\"Show Column\" class=\"show-hide\">\r\n <mat-icon>indeterminate_check_box</mat-icon>\r\n </button>\r\n }\r\n \r\n <p class=\"label\">\r\n {{col.displayName || (col.key | spaceCase) }}\r\n </p>\r\n\r\n </div>\r\n </button>\r\n }\r\n\r\n </div>\r\n </mat-menu>\r\n}", styles: [".show-hide{margin-right:15px;height:24px;width:24px;padding:4px}.label{color:#6495ed;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;text-align:left;margin:0;font-size:17px;font-weight:700;display:inline-block;width:66%}.row{margin:0;padding:0}.isHidden{background-color:#d3d3d3;color:#a9a9a9;font-weight:700;font-size:17px;white-space:nowrap}.filter-button{margin-top:10px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.mdc-list-item__primary-text{display:inline-block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3018
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: GenColDisplayerComponent, isStandalone: true, selector: "tb-col-displayer", ngImport: i0, template: "@if($columns(); as displayCols){\r\n <span matTooltip=\"Show/hide columns\">\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\r\n <mat-icon color=\"primary\">visibility_off</mat-icon>\r\n </button>\r\n </span>\r\n <mat-menu #menu=\"matMenu\" class=\"my-mat-menu\">\r\n\r\n <button mat-menu-item>\r\n <span matTooltip=\"Close\">\r\n <button class=\"filter-button\" mat-icon-button>\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </span>\r\n </button>\r\n\r\n <button mat-menu-item stop-propagation>\r\n <span matTooltip=\"Show all columns\">\r\n <button mat-icon-button (click)=\"reset(displayCols)\">\r\n <mat-icon color=\"primary\">done_all</mat-icon>\r\n </button>\r\n </span>\r\n\r\n <span matTooltip=\"Hide all columns\">\r\n <button mat-icon-button (click)=\"unset(displayCols)\">\r\n <mat-icon color=\"primary\">cancel</mat-icon>\r\n </button>\r\n </span>\r\n </button>\r\n\r\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\" stop-propagation [cdkDropListLockAxis]=\"'y'\">\r\n @for (col of displayCols; track col.key) {\r\n <button [class.isHidden]=\"!col.isVisible\" stop-propagation mat-menu-item cdkDrag [cdkDragData]=\"col\">\r\n <div (click)=\"col.isVisible = !col.isVisible; emit(displayCols)\" style=\"display: flex; align-items: center;\">\r\n @if(col.isVisible){\r\n <button mat-icon-button matTooltip=\"Hide Column\" class=\"show-hide\">\r\n <mat-icon color=\"primary\">check_box</mat-icon>\r\n </button>\r\n } @else {\r\n <button mat-icon-button matTooltip=\"Show Column\" class=\"show-hide\">\r\n <mat-icon>indeterminate_check_box</mat-icon>\r\n </button>\r\n }\r\n \r\n <p class=\"label\">\r\n {{col.displayName || (col.key | spaceCase) }}\r\n </p>\r\n\r\n </div>\r\n </button>\r\n }\r\n\r\n </div>\r\n </mat-menu>\r\n}", styles: [".show-hide{margin-right:15px;height:24px;width:24px;padding:4px}.label{color:#6495ed;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;text-align:left;margin:0;font-size:17px;font-weight:700;display:inline-block;width:66%}.row{margin:0;padding:0}.isHidden{background-color:#d3d3d3;color:#a9a9a9;font-weight:700;font-size:17px;white-space:nowrap}.filter-button{margin-top:10px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.mdc-list-item__primary-text{display:inline-block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2943
3019
  }
2944
3020
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GenColDisplayerComponent, decorators: [{
2945
3021
  type: Component,
@@ -2981,7 +3057,7 @@ class GenFilterDisplayerComponent {
2981
3057
  this.filterStore.addFilter({ key: metaData.key, fieldType: metaData.fieldType });
2982
3058
  }
2983
3059
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GenFilterDisplayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2984
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: GenFilterDisplayerComponent, isStandalone: true, selector: "tb-filter-displayer", ngImport: i0, template: "<button stop-propagation class=\"filter-button\" mat-icon-button [matMenuTriggerFor]=\"menu\" [matTooltip]=\"'Add Filter'\">\r\n <mat-icon class=\"filter-icon\" color=\"primary\">filter_list</mat-icon>\r\n</button>\r\n<mat-menu #menu=\"matMenu\">\r\n @for (md of $filterCols(); track md.key) {\r\n <button (click)=\"addFilter(md)\" mat-menu-item>\r\n <span class=\"filter-labels\">{{md.displayName || (md.key | spaceCase)}}</span>\r\n </button>\r\n }\r\n</mat-menu>\r\n", styles: [".filter{margin:15px;display:inline-block}.filter-button{color:#6495ed;font-size:22px;font-weight:700}.cancel-button{margin-right:30px;font-weight:700}.filter-wrapper{margin-top:1em;margin-bottom:1em;float:right}.menu{margin-bottom:10px;width:109.1%}.filter-labels{color:#6495ed;font-size:17px;font-weight:600}.float{position:absolute;width:fit-content;z-index:101;top:10px;right:180px;max-width:90vw}.d-w{display:flex;flex-direction:row;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3060
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: GenFilterDisplayerComponent, isStandalone: true, selector: "tb-filter-displayer", ngImport: i0, template: "<button stop-propagation class=\"filter-button\" mat-icon-button [matMenuTriggerFor]=\"menu\" [matTooltip]=\"'Add Filter'\">\r\n <mat-icon class=\"filter-icon\" color=\"primary\">filter_list</mat-icon>\r\n</button>\r\n<mat-menu #menu=\"matMenu\">\r\n @for (md of $filterCols(); track md.key) {\r\n <button (click)=\"addFilter(md)\" mat-menu-item>\r\n <span class=\"filter-labels\">{{md.displayName || (md.key | spaceCase)}}</span>\r\n </button>\r\n }\r\n</mat-menu>\r\n", styles: [".filter{margin:15px;display:inline-block}.filter-button{color:#6495ed;font-size:22px;font-weight:700}.cancel-button{margin-right:30px;font-weight:700}.filter-wrapper{margin-top:1em;margin-bottom:1em;float:right}.menu{margin-bottom:10px;width:109.1%}.filter-labels{color:#6495ed;font-size:17px;font-weight:600}.float{position:absolute;width:fit-content;z-index:101;top:10px;right:180px;max-width:90vw}.d-w{display:flex;flex-direction:row;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2985
3061
  }
2986
3062
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GenFilterDisplayerComponent, decorators: [{
2987
3063
  type: Component,
@@ -3004,7 +3080,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
3004
3080
 
3005
3081
  class FormatFilterTypePipe {
3006
3082
  transform(filterType, value) {
3007
- if (filterType === FilterTypes.IsNull) {
3083
+ if (filterType === FilterType.IsNull) {
3008
3084
  return value ? filterType : 'Is Not Blank';
3009
3085
  }
3010
3086
  return filterType;
@@ -3031,16 +3107,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
3031
3107
  args: [{ name: 'formatFilterValue' }]
3032
3108
  }] });
3033
3109
  const transform = (value, meta, filterType) => {
3034
- if (filterType === FilterTypes.IsNull) {
3110
+ if (filterType === FilterType.IsNull) {
3035
3111
  return '';
3036
3112
  }
3037
- if (value && (filterType === FilterTypes.In)) {
3113
+ if (value && (filterType === FilterType.In)) {
3038
3114
  if (meta.fieldType === FieldType.Enum) {
3039
3115
  return value.map((v) => spaceCase(meta.additional.enumMap[v])).join(', ') ?? value;
3040
3116
  }
3041
3117
  return value.join(', ') ?? value;
3042
3118
  }
3043
- if (filterType === FilterTypes.NumberBetween) {
3119
+ if (filterType === FilterType.NumberBetween) {
3044
3120
  return value.Start + ' - ' + value.End;
3045
3121
  }
3046
3122
  if (meta.fieldType === FieldType.Date) {
@@ -3067,7 +3143,7 @@ class FilterChipsComponent {
3067
3143
  }
3068
3144
  $currentFilters = this.filterStore.$currentFilters;
3069
3145
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: FilterChipsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3070
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: FilterChipsComponent, isStandalone: true, selector: "lib-filter-list", ngImport: i0, template: "<div class=\"d-w\">\r\n\r\n @if ($currentFilters().length) {\r\n <button class=\"cancel-button\" mat-icon-button (click)=\"clearAll()\" matTooltip=\"Close all Filters Cards\">\r\n <mat-icon class=\"cancel-button\" color=\"primary\">close</mat-icon>\r\n </button>\r\n <div class=\"float\">\r\n @for (filter of $currentFilters(); track filter.key) {\r\n <div class=\"filter\">\r\n <tb-filter [filter]=\"filter\" (close)=\"deleteByIndex($index)\" />\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <mat-chip-set>\r\n @for (filter of $filters(); track filter.key) {\r\n <mat-chip (dblclick)=\"addFilter(filter)\" (removed)=\"tableState.removeFilter(filter.filterId!)\">\r\n {{ (filter.key | keyDisplay)() }} {{filter.filterType | formatFilterType : filter.filterValue}} {{ (filter.filterValue | formatFilterValue: filter.key : filter.filterType)() }}\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n @if ($filters().length > 1) {\r\n <mat-chip (removed)=\"tableState.clearFilters()\">\r\n Clear All\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n </mat-chip-set>\r\n\r\n</div>\r\n", styles: [".filter{margin:15px;display:inline-block}.filter-button{color:#6495ed;font-size:22px;font-weight:700}.cancel-button{margin-right:30px;font-weight:700}.filter-wrapper{margin-top:1em;margin-bottom:1em;float:right}.menu{margin-bottom:10px;width:109.1%}.filter-labels{color:#6495ed;font-size:17px;font-weight:600}.float{position:absolute;width:fit-content;z-index:101;top:10px;right:180px;max-width:90vw}.d-w{display:flex;flex-direction:row;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FilterComponent, selector: "tb-filter", inputs: ["filter"], outputs: ["close"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i4$3.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i4$3.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i4$3.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "pipe", type: KeyDisplayPipe, name: "keyDisplay" }, { kind: "pipe", type: FormatFilterTypePipe, name: "formatFilterType" }, { kind: "pipe", type: FormatFilterValuePipe, name: "formatFilterValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3146
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: FilterChipsComponent, isStandalone: true, selector: "lib-filter-list", ngImport: i0, template: "<div class=\"d-w\">\r\n\r\n @if ($currentFilters().length) {\r\n <button class=\"cancel-button\" mat-icon-button (click)=\"clearAll()\" matTooltip=\"Close all Filters Cards\">\r\n <mat-icon class=\"cancel-button\" color=\"primary\">close</mat-icon>\r\n </button>\r\n <div class=\"float\">\r\n @for (filter of $currentFilters(); track filter.key) {\r\n <div class=\"filter\">\r\n <tb-filter [filter]=\"filter\" (close)=\"deleteByIndex($index)\" />\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <mat-chip-set>\r\n @for (filter of $filters(); track filter.key) {\r\n <mat-chip (dblclick)=\"addFilter(filter)\" (removed)=\"tableState.removeFilter(filter.filterId!)\">\r\n {{ (filter.key | keyDisplay)() }} {{filter.filterType | formatFilterType : filter.filterValue}} {{ (filter.filterValue | formatFilterValue: filter.key : filter.filterType)() }}\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n @if ($filters().length > 1) {\r\n <mat-chip (removed)=\"tableState.clearFilters()\">\r\n Clear All\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n </mat-chip-set>\r\n\r\n</div>\r\n", styles: [".filter{margin:15px;display:inline-block}.filter-button{color:#6495ed;font-size:22px;font-weight:700}.cancel-button{margin-right:30px;font-weight:700}.filter-wrapper{margin-top:1em;margin-bottom:1em;float:right}.menu{margin-bottom:10px;width:109.1%}.filter-labels{color:#6495ed;font-size:17px;font-weight:600}.float{position:absolute;width:fit-content;z-index:101;top:10px;right:180px;max-width:90vw}.d-w{display:flex;flex-direction:row;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FilterComponent, selector: "tb-filter", inputs: ["filter"], outputs: ["close"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i4$2.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i4$2.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i4$2.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "pipe", type: KeyDisplayPipe, name: "keyDisplay" }, { kind: "pipe", type: FormatFilterTypePipe, name: "formatFilterType" }, { kind: "pipe", type: FormatFilterValuePipe, name: "formatFilterValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3071
3147
  }
3072
3148
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: FilterChipsComponent, decorators: [{
3073
3149
  type: Component,
@@ -3191,7 +3267,7 @@ class RouterLinkColumnComponent {
3191
3267
  >
3192
3268
  {{value()}}
3193
3269
  </a>
3194
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3270
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$5.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3195
3271
  }
3196
3272
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: RouterLinkColumnComponent, decorators: [{
3197
3273
  type: Component,
@@ -3385,23 +3461,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
3385
3461
  args: [{ providedIn: 'root' }]
3386
3462
  }], ctorParameters: () => [] });
3387
3463
 
3388
- class HeaderMenuComponent {
3464
+ class ColumnHeaderMenuComponent {
3389
3465
  tableState = inject(TableStore);
3390
3466
  FieldType = FieldType;
3391
- FilterType = FilterTypes;
3392
- myFilterType;
3467
+ FilterType = FilterType;
3393
3468
  $metaData = input.required({ alias: 'metaData' });
3394
3469
  $trigger = viewChild(MatMenuTrigger);
3395
3470
  hideField(key) {
3396
3471
  this.tableState.hideColumn(key);
3397
3472
  }
3398
- ngOnInit() {
3399
- this.resetFilterType();
3400
- }
3401
- resetFilterType() {
3473
+ $metaFilterType = computed(() => {
3402
3474
  if (this.$metaData().additional?.filterOptions?.filterableValues) {
3403
- this.myFilterType = FilterTypes.In;
3404
- return;
3475
+ return FilterType.In;
3405
3476
  }
3406
3477
  switch (this.$metaData().fieldType) {
3407
3478
  case FieldType.String:
@@ -3409,34 +3480,29 @@ class HeaderMenuComponent {
3409
3480
  case FieldType.PhoneNumber:
3410
3481
  case FieldType.Array:
3411
3482
  case FieldType.Unknown:
3412
- this.myFilterType = FilterTypes.StringContains;
3413
- break;
3483
+ return FilterType.StringContains;
3414
3484
  case FieldType.Currency:
3415
3485
  case FieldType.Number:
3416
- this.myFilterType = FilterTypes.NumberEquals;
3417
- break;
3486
+ return FilterType.NumberEquals;
3418
3487
  case FieldType.Boolean:
3419
- this.myFilterType = FilterTypes.BooleanEquals;
3420
- break;
3488
+ return FilterType.BooleanEquals;
3421
3489
  case FieldType.Date:
3422
3490
  case FieldType.DateTime:
3423
- this.myFilterType = FilterTypes.DateIsOn;
3424
- break;
3491
+ return FilterType.DateIsOn;
3425
3492
  case FieldType.Enum:
3426
- this.myFilterType = FilterTypes.In;
3427
- break;
3493
+ return FilterType.In;
3494
+ default: return FilterType.StringContains;
3428
3495
  }
3429
- }
3496
+ });
3497
+ $currentFilterType = linkedSignal(() => this.$metaFilterType());
3430
3498
  setStringFilterType() {
3431
- this.myFilterType = this.myFilterType === FilterTypes.StringContains ? FilterTypes.StringDoesNotContain : FilterTypes.StringContains;
3499
+ if (this.$currentFilterType() === FilterType.StringContains) {
3500
+ this.$currentFilterType.set(FilterType.StringDoesNotContain);
3501
+ }
3502
+ this.$currentFilterType.set(FilterType.StringContains);
3432
3503
  }
3433
3504
  setFilterType(filterType) {
3434
- if (filterType === this.myFilterType) {
3435
- this.resetFilterType();
3436
- }
3437
- else {
3438
- this.myFilterType = filterType;
3439
- }
3505
+ this.$currentFilterType.set(filterType);
3440
3506
  }
3441
3507
  onEnter(filter) {
3442
3508
  if (filter.filterValue != undefined && filter.filterType) {
@@ -3444,15 +3510,15 @@ class HeaderMenuComponent {
3444
3510
  this.$trigger().closeMenu();
3445
3511
  }
3446
3512
  }
3447
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: HeaderMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3448
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: HeaderMenuComponent, isStandalone: true, selector: "tb-header-menu", inputs: { $metaData: { classPropertyName: "$metaData", publicName: "metaData", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "$trigger", first: true, predicate: MatMenuTrigger, descendants: true, isSignal: true }], ngImport: i0, template: "@let metaData = $metaData();\r\n\r\n<button mat-icon-button class=\"open-menu-icon-button\" disableRipple [matMenuTriggerFor]=\"menu\" [matMenuTriggerRestoreFocus]=\"false\">\r\n <mat-icon class=\"menu-icon\">more_vert</mat-icon>\r\n</button>\r\n<mat-menu #menu=\"matMenu\" >\r\n @if (!(metaData.fieldType === FieldType.NotMapped))\r\n {\r\n <button mat-menu-item (click)=\"tableState.addGroupByKey(metaData.key)\">\r\n <mat-icon color=\"primary\">group</mat-icon>\r\n <span>Group By</span>\r\n </button>\r\n }\r\n <button mat-menu-item (click)=hideField(metaData.key)>\r\n <mat-icon color=\"primary\">visibility_off</mat-icon>\r\n <span>Hide Column</span>\r\n </button>\r\n @if (!(metaData.fieldType === FieldType.NotMapped))\r\n {\r\n <ng-form #myForm=\"ngForm\" (keydown.enter)=\"onEnter(myForm.value)\" class=\"tb-header-filter\">\r\n <input type=\"hidden\" name=\"filterId\" [ngModel]=\"'header-column-' + metaData.key\" />\r\n <input type=\"hidden\" name=\"filterType\" [ngModel]=\"myFilterType\" />\r\n <input type=\"hidden\" name=\"key\" [ngModel]=\"metaData.key\" />\r\n <input type=\"hidden\" name=\"fieldType\" [ngModel]=\"metaData.fieldType\" />\r\n \r\n @if(myFilterType === FilterType.Or || myFilterType === FilterType.In){\r\n <tb-in-list-filter name='filterValue' [key]='metaData.key' [ngModel]=\"undefined\"/>\r\n }\r\n @else if(metaData.fieldType === FieldType.Link || metaData.fieldType === FieldType.String || metaData.fieldType === FieldType.Array || metaData.fieldType === FieldType.Unknown || metaData.fieldType === FieldType.PhoneNumber) {\r\n <mat-form-field stop-propagation class=\"font auto-width\">\r\n <mat-icon matPrefix class=\"search-icon\">search</mat-icon>\r\n <mat-label>{{myFilterType === FilterType.StringDoesNotContain ? 'Does Not Contain...' : 'Contains...'}}</mat-label>\r\n <input matInput name=\"filterValue\" [ngModel]=\"undefined\"/>\r\n <span matSuffix [matTooltip]=\"myFilterType === FilterType.StringDoesNotContain ? 'Contains' : 'Does Not Contain'\">\r\n <button mat-icon-button color=\"primary\" (click)=\"setStringFilterType()\" class=\"header-filter-icon-button\">\r\n <mat-icon [class]=\"{'chosen-icon': myFilterType === FilterType.StringDoesNotContain }\">\r\n block\r\n </mat-icon>\r\n </button>\r\n </span>\r\n </mat-form-field>\r\n }\r\n @else if (metaData.fieldType === FieldType.Number || metaData.fieldType === FieldType.Currency) {\r\n <mat-form-field class=\"auto-width\" stop-propagation>\r\n <mat-label>{{myFilterType === FilterType.NumberEquals ? 'Equals...' : myFilterType === FilterType.NumberLessThan ? 'Less Than...' : 'More Than...'}}</mat-label>\r\n <input matInput type='number' name=\"filterValue\" [ngModel]=\"undefined\" />\r\n <span matPrefix class=\"tb-header-prefix\">\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberLessThan)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.NumberLessThan }\">\r\n <mat-icon class=\"suffix-icons\"\r\n >\r\n arrow_back_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberGreaterThan)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.NumberGreaterThan }\" >\r\n <mat-icon class=\"suffix-icons\">arrow_forward_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberEquals)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.NumberEquals }\">\r\n <span class=\"suffix-icons\">=</span>\r\n </button>\r\n </span>\r\n </mat-form-field>\r\n }\r\n @else if (metaData.fieldType === FieldType.Boolean) {\r\n <div>\r\n <label>\r\n <mat-icon class=\"search-icon\">filter_list</mat-icon>\r\n </label>\r\n <mat-radio-group stop-propagation #ctrl=\"matRadioGroup\" #boolField='ngModel' class=\"font\" name=\"filterValue\" [ngModel]=\"undefined\" >\r\n <mat-radio-button class=\"filter-radio-button\" (click)=\"boolField.control.setValue(true);\" [value]=\"true\">True</mat-radio-button><br/>\r\n <mat-radio-button class=\"filter-radio-button\" (click)=\"boolField.control.setValue(false)\" [value]=\"false\">False</mat-radio-button><br/>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n @else if (metaData.fieldType === FieldType.Date || metaData.fieldType === FieldType.DateTime) {\r\n <mat-form-field class=\"font auto-width\" stop-propagation >\r\n <span matPrefix class=\"tb-header-prefix\">\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateOnOrAfter)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.DateOnOrAfter }\">\r\n <mat-icon class=\"suffix-icons underline\">arrow_forward_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateOnOrBefore)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.DateOnOrBefore }\">\r\n <mat-icon class=\"suffix-icons underline\">arrow_back_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateIsOn)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.DateIsOn }\">\r\n <span class=\"suffix-icons underline\"> =</span>\r\n </button>\r\n </span>\r\n <mat-label>{{myFilterType === FilterType.DateIsOn ? 'On...' :\r\n myFilterType === FilterType.DateOnOrBefore ? 'On or Before...' : 'On or After...'}}</mat-label>\r\n <input matInput name=\"filterValue\" [ngModel]=\"undefined\" [matDatepicker]=\"calendar\"\r\n (click)=\"calendar.open()\"/>\r\n <mat-datepicker-toggle class=\"date-toggle header-filter-icon-button\" matSuffix [for]=\"calendar\" preventEnter></mat-datepicker-toggle>\r\n <mat-datepicker #calendar></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n <button mat-button (click)=\"onEnter(myForm.value)\" [disabled]=\"myForm.value.filterValue == undefined\" disableRipple>\r\n Apply\r\n </button>\r\n </ng-form>\r\n }\r\n</mat-menu>\r\n", styles: [":host{--mdc-text-button-container-height: 24px}:host{--mdc-filled-button-container-height: 24px}:host{--mdc-protected-button-container-height: 24px}:host{--mdc-outlined-button-container-height: 24px}:host{--mat-text-button-touch-target-display: none}:host{--mat-filled-button-touch-target-display: none}:host{--mat-protected-button-touch-target-display: none}:host{--mat-outlined-button-touch-target-display: none}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.menu-icon{font-size:16px;line-height:16px;vertical-align:top;height:16px;width:16px}.search-icon{margin-right:16px;vertical-align:middle;height:24px;color:#0000008a;font-size:21px;line-height:1.125}.font{font-size:14px}.filter-radio-button:first-of-type{padding-left:0}.filter-radio-button{padding:10px 40px;min-width:110px}.auto-width{width:260px;margin:5px;display:block;height:55px}.open-menu-icon-button{height:28px;width:28px;padding:6px}.header-filter-icon-button{height:18px;width:18px;font-size:18px;padding:0;margin:0 2px}.header-filter-icon-button ::ng-deep *{line-height:initial;font-size:initial;height:18px;width:18px;font-size:18px;bottom:initial}.header-filter-icon-button.chosen-icon,.header-filter-icon-button.chosen-icon ::ng-deep *{height:22px;width:22px;font-size:22px;color:green}mat-icon.mat-icon.suffix-icons.underline{height:20px;text-decoration:underline .1px solid}.chosen-icon mat-icon.mat-icon.suffix-icons.underline{height:24px}::ng-deep .mat-mdc-form-field-icon-prefix:has(.tb-header-prefix),.tb-header-prefix{padding:0;flex-basis:36%}.tb-header-filter ::ng-deep .mat-mdc-form-field-subscript-wrapper{line-height:0}.tb-header-filter ::ng-deep .mat-mdc-form-field-subscript-wrapper:before{height:0}.date-toggle ::ng-deep svg{position:absolute;left:0;top:0}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: InListFilterComponent, selector: "tb-in-list-filter , [tb-in-list-filter]", inputs: ["key"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i1$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i10.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i10.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i4.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i4.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i4.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3513
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ColumnHeaderMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3514
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: ColumnHeaderMenuComponent, isStandalone: true, selector: "tb-header-menu", inputs: { $metaData: { classPropertyName: "$metaData", publicName: "metaData", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "$trigger", first: true, predicate: MatMenuTrigger, descendants: true, isSignal: true }], ngImport: i0, template: "@let metaData = $metaData();\r\n@let currentFilterType = $currentFilterType();\r\n\r\n<button mat-icon-button class=\"open-menu-icon-button\" disableRipple [matMenuTriggerFor]=\"menu\" [matMenuTriggerRestoreFocus]=\"false\">\r\n <mat-icon class=\"menu-icon\">more_vert</mat-icon>\r\n</button>\r\n<mat-menu #menu=\"matMenu\" >\r\n @if (!(metaData.fieldType === FieldType.NotMapped))\r\n {\r\n <button mat-menu-item (click)=\"tableState.addGroupByKey(metaData.key)\">\r\n <mat-icon color=\"primary\">group</mat-icon>\r\n <span>Group By</span>\r\n </button>\r\n }\r\n <button mat-menu-item (click)=hideField(metaData.key)>\r\n <mat-icon color=\"primary\">visibility_off</mat-icon>\r\n <span>Hide Column</span>\r\n </button>\r\n @if (!(metaData.fieldType === FieldType.NotMapped))\r\n {\r\n <ng-form #myForm=\"ngForm\" (keydown.enter)=\"onEnter(myForm.value)\" class=\"tb-header-filter\">\r\n <input type=\"hidden\" name=\"filterId\" [ngModel]=\"'header-column-' + metaData.key\" />\r\n <input type=\"hidden\" name=\"filterType\" [ngModel]=\"currentFilterType\" />\r\n <input type=\"hidden\" name=\"key\" [ngModel]=\"metaData.key\" />\r\n <input type=\"hidden\" name=\"fieldType\" [ngModel]=\"metaData.fieldType\" />\r\n \r\n @if(currentFilterType === FilterType.Or || currentFilterType === FilterType.In){\r\n <tb-in-list-filter name='filterValue' [key]='metaData.key' [ngModel]=\"undefined\"/>\r\n }\r\n @else if(metaData.fieldType === FieldType.Link || metaData.fieldType === FieldType.String || metaData.fieldType === FieldType.Array || metaData.fieldType === FieldType.Unknown || metaData.fieldType === FieldType.PhoneNumber) {\r\n <mat-form-field stop-propagation class=\"font auto-width\">\r\n <mat-icon matPrefix class=\"search-icon\">search</mat-icon>\r\n <mat-label>{{currentFilterType === FilterType.StringDoesNotContain ? 'Does Not Contain...' : 'Contains...'}}</mat-label>\r\n <input matInput name=\"filterValue\" [ngModel]=\"undefined\"/>\r\n <span matSuffix [matTooltip]=\"currentFilterType === FilterType.StringDoesNotContain ? 'Contains' : 'Does Not Contain'\">\r\n <button mat-icon-button color=\"primary\" (click)=\"setStringFilterType()\" class=\"header-filter-icon-button\">\r\n <mat-icon [class]=\"{'chosen-icon': currentFilterType === FilterType.StringDoesNotContain }\">\r\n block\r\n </mat-icon>\r\n </button>\r\n </span>\r\n </mat-form-field>\r\n }\r\n @else if (metaData.fieldType === FieldType.Number || metaData.fieldType === FieldType.Currency) {\r\n <mat-form-field class=\"auto-width\" stop-propagation>\r\n <mat-label>{{currentFilterType === FilterType.NumberEquals ? 'Equals...' : currentFilterType === FilterType.NumberLessThan ? 'Less Than...' : 'More Than...'}}</mat-label>\r\n <input matInput type='number' name=\"filterValue\" [ngModel]=\"undefined\" />\r\n <span matPrefix class=\"tb-header-prefix\">\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberLessThan)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberLessThan }\">\r\n <mat-icon class=\"suffix-icons\"\r\n >\r\n arrow_back_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberGreaterThan)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberGreaterThan }\" >\r\n <mat-icon class=\"suffix-icons\">arrow_forward_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberEquals)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberEquals }\">\r\n <span class=\"suffix-icons\">=</span>\r\n </button>\r\n </span>\r\n </mat-form-field>\r\n }\r\n @else if (metaData.fieldType === FieldType.Boolean) {\r\n <div>\r\n <label>\r\n <mat-icon class=\"search-icon\">filter_list</mat-icon>\r\n </label>\r\n <mat-radio-group stop-propagation #ctrl=\"matRadioGroup\" #boolField='ngModel' class=\"font\" name=\"filterValue\" [ngModel]=\"undefined\" >\r\n <mat-radio-button class=\"filter-radio-button\" (click)=\"boolField.control.setValue(true);\" [value]=\"true\">True</mat-radio-button><br/>\r\n <mat-radio-button class=\"filter-radio-button\" (click)=\"boolField.control.setValue(false)\" [value]=\"false\">False</mat-radio-button><br/>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n @else if (metaData.fieldType === FieldType.Date || metaData.fieldType === FieldType.DateTime) {\r\n <mat-form-field class=\"font auto-width\" stop-propagation >\r\n <span matPrefix class=\"tb-header-prefix\">\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateOnOrAfter)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrAfter }\">\r\n <mat-icon class=\"suffix-icons underline\">arrow_forward_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateOnOrBefore)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrBefore }\">\r\n <mat-icon class=\"suffix-icons underline\">arrow_back_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateIsOn)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.DateIsOn }\">\r\n <span class=\"suffix-icons underline\"> =</span>\r\n </button>\r\n </span>\r\n <mat-label>{{currentFilterType === FilterType.DateIsOn ? 'On...' :\r\n currentFilterType === FilterType.DateOnOrBefore ? 'On or Before...' : 'On or After...'}}</mat-label>\r\n <input matInput name=\"filterValue\" [ngModel]=\"undefined\" [matDatepicker]=\"calendar\"\r\n (click)=\"calendar.open()\"/>\r\n <mat-datepicker-toggle class=\"date-toggle header-filter-icon-button\" matSuffix [for]=\"calendar\" preventEnter></mat-datepicker-toggle>\r\n <mat-datepicker #calendar></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n <button mat-button (click)=\"onEnter(myForm.value)\" [disabled]=\"myForm.value.filterValue == undefined\" disableRipple>\r\n Apply\r\n </button>\r\n </ng-form>\r\n }\r\n</mat-menu>\r\n", styles: [":host{--mdc-text-button-container-height: 24px}:host{--mdc-filled-button-container-height: 24px}:host{--mdc-protected-button-container-height: 24px}:host{--mdc-outlined-button-container-height: 24px}:host{--mat-text-button-touch-target-display: none}:host{--mat-filled-button-touch-target-display: none}:host{--mat-protected-button-touch-target-display: none}:host{--mat-outlined-button-touch-target-display: none}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.menu-icon{font-size:16px;line-height:16px;vertical-align:top;height:16px;width:16px}.search-icon{margin-right:16px;vertical-align:middle;height:24px;color:#0000008a;font-size:21px;line-height:1.125}.font{font-size:14px}.filter-radio-button:first-of-type{padding-left:0}.filter-radio-button{padding:10px 40px;min-width:110px}.auto-width{width:260px;margin:5px;display:block;height:55px}.open-menu-icon-button{height:28px;width:28px;padding:6px}.header-filter-icon-button{height:18px;width:18px;font-size:18px;padding:0;margin:0 2px}.header-filter-icon-button ::ng-deep *{line-height:initial;font-size:initial;height:18px;width:18px;font-size:18px;bottom:initial}.header-filter-icon-button.chosen-icon,.header-filter-icon-button.chosen-icon ::ng-deep *{height:22px;width:22px;font-size:22px;color:green}mat-icon.mat-icon.suffix-icons.underline{height:20px;text-decoration:underline .1px solid}.chosen-icon mat-icon.mat-icon.suffix-icons.underline{height:24px}::ng-deep .mat-mdc-form-field-icon-prefix:has(.tb-header-prefix),.tb-header-prefix{padding:0;flex-basis:36%}.tb-header-filter ::ng-deep .mat-mdc-form-field-subscript-wrapper{line-height:0}.tb-header-filter ::ng-deep .mat-mdc-form-field-subscript-wrapper:before{height:0}.date-toggle ::ng-deep svg{position:absolute;left:0;top:0}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: InListFilterComponent, selector: "tb-in-list-filter , [tb-in-list-filter]", inputs: ["key"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i1$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i10.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i10.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i4.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i4.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i4.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3449
3515
  }
3450
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: HeaderMenuComponent, decorators: [{
3516
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ColumnHeaderMenuComponent, decorators: [{
3451
3517
  type: Component,
3452
3518
  args: [{ selector: 'tb-header-menu', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
3453
3519
  MatMenuModule, MatIconModule, MatButtonModule, FormsModule, InListFilterComponent,
3454
3520
  MatInputModule, MatTooltipModule, StopPropagationDirective, MatRadioModule, MatDatepickerModule
3455
- ], template: "@let metaData = $metaData();\r\n\r\n<button mat-icon-button class=\"open-menu-icon-button\" disableRipple [matMenuTriggerFor]=\"menu\" [matMenuTriggerRestoreFocus]=\"false\">\r\n <mat-icon class=\"menu-icon\">more_vert</mat-icon>\r\n</button>\r\n<mat-menu #menu=\"matMenu\" >\r\n @if (!(metaData.fieldType === FieldType.NotMapped))\r\n {\r\n <button mat-menu-item (click)=\"tableState.addGroupByKey(metaData.key)\">\r\n <mat-icon color=\"primary\">group</mat-icon>\r\n <span>Group By</span>\r\n </button>\r\n }\r\n <button mat-menu-item (click)=hideField(metaData.key)>\r\n <mat-icon color=\"primary\">visibility_off</mat-icon>\r\n <span>Hide Column</span>\r\n </button>\r\n @if (!(metaData.fieldType === FieldType.NotMapped))\r\n {\r\n <ng-form #myForm=\"ngForm\" (keydown.enter)=\"onEnter(myForm.value)\" class=\"tb-header-filter\">\r\n <input type=\"hidden\" name=\"filterId\" [ngModel]=\"'header-column-' + metaData.key\" />\r\n <input type=\"hidden\" name=\"filterType\" [ngModel]=\"myFilterType\" />\r\n <input type=\"hidden\" name=\"key\" [ngModel]=\"metaData.key\" />\r\n <input type=\"hidden\" name=\"fieldType\" [ngModel]=\"metaData.fieldType\" />\r\n \r\n @if(myFilterType === FilterType.Or || myFilterType === FilterType.In){\r\n <tb-in-list-filter name='filterValue' [key]='metaData.key' [ngModel]=\"undefined\"/>\r\n }\r\n @else if(metaData.fieldType === FieldType.Link || metaData.fieldType === FieldType.String || metaData.fieldType === FieldType.Array || metaData.fieldType === FieldType.Unknown || metaData.fieldType === FieldType.PhoneNumber) {\r\n <mat-form-field stop-propagation class=\"font auto-width\">\r\n <mat-icon matPrefix class=\"search-icon\">search</mat-icon>\r\n <mat-label>{{myFilterType === FilterType.StringDoesNotContain ? 'Does Not Contain...' : 'Contains...'}}</mat-label>\r\n <input matInput name=\"filterValue\" [ngModel]=\"undefined\"/>\r\n <span matSuffix [matTooltip]=\"myFilterType === FilterType.StringDoesNotContain ? 'Contains' : 'Does Not Contain'\">\r\n <button mat-icon-button color=\"primary\" (click)=\"setStringFilterType()\" class=\"header-filter-icon-button\">\r\n <mat-icon [class]=\"{'chosen-icon': myFilterType === FilterType.StringDoesNotContain }\">\r\n block\r\n </mat-icon>\r\n </button>\r\n </span>\r\n </mat-form-field>\r\n }\r\n @else if (metaData.fieldType === FieldType.Number || metaData.fieldType === FieldType.Currency) {\r\n <mat-form-field class=\"auto-width\" stop-propagation>\r\n <mat-label>{{myFilterType === FilterType.NumberEquals ? 'Equals...' : myFilterType === FilterType.NumberLessThan ? 'Less Than...' : 'More Than...'}}</mat-label>\r\n <input matInput type='number' name=\"filterValue\" [ngModel]=\"undefined\" />\r\n <span matPrefix class=\"tb-header-prefix\">\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberLessThan)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.NumberLessThan }\">\r\n <mat-icon class=\"suffix-icons\"\r\n >\r\n arrow_back_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberGreaterThan)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.NumberGreaterThan }\" >\r\n <mat-icon class=\"suffix-icons\">arrow_forward_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberEquals)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.NumberEquals }\">\r\n <span class=\"suffix-icons\">=</span>\r\n </button>\r\n </span>\r\n </mat-form-field>\r\n }\r\n @else if (metaData.fieldType === FieldType.Boolean) {\r\n <div>\r\n <label>\r\n <mat-icon class=\"search-icon\">filter_list</mat-icon>\r\n </label>\r\n <mat-radio-group stop-propagation #ctrl=\"matRadioGroup\" #boolField='ngModel' class=\"font\" name=\"filterValue\" [ngModel]=\"undefined\" >\r\n <mat-radio-button class=\"filter-radio-button\" (click)=\"boolField.control.setValue(true);\" [value]=\"true\">True</mat-radio-button><br/>\r\n <mat-radio-button class=\"filter-radio-button\" (click)=\"boolField.control.setValue(false)\" [value]=\"false\">False</mat-radio-button><br/>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n @else if (metaData.fieldType === FieldType.Date || metaData.fieldType === FieldType.DateTime) {\r\n <mat-form-field class=\"font auto-width\" stop-propagation >\r\n <span matPrefix class=\"tb-header-prefix\">\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateOnOrAfter)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.DateOnOrAfter }\">\r\n <mat-icon class=\"suffix-icons underline\">arrow_forward_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateOnOrBefore)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.DateOnOrBefore }\">\r\n <mat-icon class=\"suffix-icons underline\">arrow_back_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateIsOn)\"\r\n [class]=\"{'chosen-icon': myFilterType === FilterType.DateIsOn }\">\r\n <span class=\"suffix-icons underline\"> =</span>\r\n </button>\r\n </span>\r\n <mat-label>{{myFilterType === FilterType.DateIsOn ? 'On...' :\r\n myFilterType === FilterType.DateOnOrBefore ? 'On or Before...' : 'On or After...'}}</mat-label>\r\n <input matInput name=\"filterValue\" [ngModel]=\"undefined\" [matDatepicker]=\"calendar\"\r\n (click)=\"calendar.open()\"/>\r\n <mat-datepicker-toggle class=\"date-toggle header-filter-icon-button\" matSuffix [for]=\"calendar\" preventEnter></mat-datepicker-toggle>\r\n <mat-datepicker #calendar></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n <button mat-button (click)=\"onEnter(myForm.value)\" [disabled]=\"myForm.value.filterValue == undefined\" disableRipple>\r\n Apply\r\n </button>\r\n </ng-form>\r\n }\r\n</mat-menu>\r\n", styles: [":host{--mdc-text-button-container-height: 24px}:host{--mdc-filled-button-container-height: 24px}:host{--mdc-protected-button-container-height: 24px}:host{--mdc-outlined-button-container-height: 24px}:host{--mat-text-button-touch-target-display: none}:host{--mat-filled-button-touch-target-display: none}:host{--mat-protected-button-touch-target-display: none}:host{--mat-outlined-button-touch-target-display: none}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.menu-icon{font-size:16px;line-height:16px;vertical-align:top;height:16px;width:16px}.search-icon{margin-right:16px;vertical-align:middle;height:24px;color:#0000008a;font-size:21px;line-height:1.125}.font{font-size:14px}.filter-radio-button:first-of-type{padding-left:0}.filter-radio-button{padding:10px 40px;min-width:110px}.auto-width{width:260px;margin:5px;display:block;height:55px}.open-menu-icon-button{height:28px;width:28px;padding:6px}.header-filter-icon-button{height:18px;width:18px;font-size:18px;padding:0;margin:0 2px}.header-filter-icon-button ::ng-deep *{line-height:initial;font-size:initial;height:18px;width:18px;font-size:18px;bottom:initial}.header-filter-icon-button.chosen-icon,.header-filter-icon-button.chosen-icon ::ng-deep *{height:22px;width:22px;font-size:22px;color:green}mat-icon.mat-icon.suffix-icons.underline{height:20px;text-decoration:underline .1px solid}.chosen-icon mat-icon.mat-icon.suffix-icons.underline{height:24px}::ng-deep .mat-mdc-form-field-icon-prefix:has(.tb-header-prefix),.tb-header-prefix{padding:0;flex-basis:36%}.tb-header-filter ::ng-deep .mat-mdc-form-field-subscript-wrapper{line-height:0}.tb-header-filter ::ng-deep .mat-mdc-form-field-subscript-wrapper:before{height:0}.date-toggle ::ng-deep svg{position:absolute;left:0;top:0}\n"] }]
3521
+ ], template: "@let metaData = $metaData();\r\n@let currentFilterType = $currentFilterType();\r\n\r\n<button mat-icon-button class=\"open-menu-icon-button\" disableRipple [matMenuTriggerFor]=\"menu\" [matMenuTriggerRestoreFocus]=\"false\">\r\n <mat-icon class=\"menu-icon\">more_vert</mat-icon>\r\n</button>\r\n<mat-menu #menu=\"matMenu\" >\r\n @if (!(metaData.fieldType === FieldType.NotMapped))\r\n {\r\n <button mat-menu-item (click)=\"tableState.addGroupByKey(metaData.key)\">\r\n <mat-icon color=\"primary\">group</mat-icon>\r\n <span>Group By</span>\r\n </button>\r\n }\r\n <button mat-menu-item (click)=hideField(metaData.key)>\r\n <mat-icon color=\"primary\">visibility_off</mat-icon>\r\n <span>Hide Column</span>\r\n </button>\r\n @if (!(metaData.fieldType === FieldType.NotMapped))\r\n {\r\n <ng-form #myForm=\"ngForm\" (keydown.enter)=\"onEnter(myForm.value)\" class=\"tb-header-filter\">\r\n <input type=\"hidden\" name=\"filterId\" [ngModel]=\"'header-column-' + metaData.key\" />\r\n <input type=\"hidden\" name=\"filterType\" [ngModel]=\"currentFilterType\" />\r\n <input type=\"hidden\" name=\"key\" [ngModel]=\"metaData.key\" />\r\n <input type=\"hidden\" name=\"fieldType\" [ngModel]=\"metaData.fieldType\" />\r\n \r\n @if(currentFilterType === FilterType.Or || currentFilterType === FilterType.In){\r\n <tb-in-list-filter name='filterValue' [key]='metaData.key' [ngModel]=\"undefined\"/>\r\n }\r\n @else if(metaData.fieldType === FieldType.Link || metaData.fieldType === FieldType.String || metaData.fieldType === FieldType.Array || metaData.fieldType === FieldType.Unknown || metaData.fieldType === FieldType.PhoneNumber) {\r\n <mat-form-field stop-propagation class=\"font auto-width\">\r\n <mat-icon matPrefix class=\"search-icon\">search</mat-icon>\r\n <mat-label>{{currentFilterType === FilterType.StringDoesNotContain ? 'Does Not Contain...' : 'Contains...'}}</mat-label>\r\n <input matInput name=\"filterValue\" [ngModel]=\"undefined\"/>\r\n <span matSuffix [matTooltip]=\"currentFilterType === FilterType.StringDoesNotContain ? 'Contains' : 'Does Not Contain'\">\r\n <button mat-icon-button color=\"primary\" (click)=\"setStringFilterType()\" class=\"header-filter-icon-button\">\r\n <mat-icon [class]=\"{'chosen-icon': currentFilterType === FilterType.StringDoesNotContain }\">\r\n block\r\n </mat-icon>\r\n </button>\r\n </span>\r\n </mat-form-field>\r\n }\r\n @else if (metaData.fieldType === FieldType.Number || metaData.fieldType === FieldType.Currency) {\r\n <mat-form-field class=\"auto-width\" stop-propagation>\r\n <mat-label>{{currentFilterType === FilterType.NumberEquals ? 'Equals...' : currentFilterType === FilterType.NumberLessThan ? 'Less Than...' : 'More Than...'}}</mat-label>\r\n <input matInput type='number' name=\"filterValue\" [ngModel]=\"undefined\" />\r\n <span matPrefix class=\"tb-header-prefix\">\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberLessThan)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberLessThan }\">\r\n <mat-icon class=\"suffix-icons\"\r\n >\r\n arrow_back_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberGreaterThan)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberGreaterThan }\" >\r\n <mat-icon class=\"suffix-icons\">arrow_forward_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.NumberEquals)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberEquals }\">\r\n <span class=\"suffix-icons\">=</span>\r\n </button>\r\n </span>\r\n </mat-form-field>\r\n }\r\n @else if (metaData.fieldType === FieldType.Boolean) {\r\n <div>\r\n <label>\r\n <mat-icon class=\"search-icon\">filter_list</mat-icon>\r\n </label>\r\n <mat-radio-group stop-propagation #ctrl=\"matRadioGroup\" #boolField='ngModel' class=\"font\" name=\"filterValue\" [ngModel]=\"undefined\" >\r\n <mat-radio-button class=\"filter-radio-button\" (click)=\"boolField.control.setValue(true);\" [value]=\"true\">True</mat-radio-button><br/>\r\n <mat-radio-button class=\"filter-radio-button\" (click)=\"boolField.control.setValue(false)\" [value]=\"false\">False</mat-radio-button><br/>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n @else if (metaData.fieldType === FieldType.Date || metaData.fieldType === FieldType.DateTime) {\r\n <mat-form-field class=\"font auto-width\" stop-propagation >\r\n <span matPrefix class=\"tb-header-prefix\">\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateOnOrAfter)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrAfter }\">\r\n <mat-icon class=\"suffix-icons underline\">arrow_forward_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateOnOrBefore)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrBefore }\">\r\n <mat-icon class=\"suffix-icons underline\">arrow_back_ios</mat-icon>\r\n </button>\r\n <button mat-icon-button disableRipple class=\"header-filter-icon-button\" (click)=\"setFilterType(FilterType.DateIsOn)\"\r\n [class]=\"{'chosen-icon': currentFilterType === FilterType.DateIsOn }\">\r\n <span class=\"suffix-icons underline\"> =</span>\r\n </button>\r\n </span>\r\n <mat-label>{{currentFilterType === FilterType.DateIsOn ? 'On...' :\r\n currentFilterType === FilterType.DateOnOrBefore ? 'On or Before...' : 'On or After...'}}</mat-label>\r\n <input matInput name=\"filterValue\" [ngModel]=\"undefined\" [matDatepicker]=\"calendar\"\r\n (click)=\"calendar.open()\"/>\r\n <mat-datepicker-toggle class=\"date-toggle header-filter-icon-button\" matSuffix [for]=\"calendar\" preventEnter></mat-datepicker-toggle>\r\n <mat-datepicker #calendar></mat-datepicker>\r\n </mat-form-field>\r\n }\r\n <button mat-button (click)=\"onEnter(myForm.value)\" [disabled]=\"myForm.value.filterValue == undefined\" disableRipple>\r\n Apply\r\n </button>\r\n </ng-form>\r\n }\r\n</mat-menu>\r\n", styles: [":host{--mdc-text-button-container-height: 24px}:host{--mdc-filled-button-container-height: 24px}:host{--mdc-protected-button-container-height: 24px}:host{--mdc-outlined-button-container-height: 24px}:host{--mat-text-button-touch-target-display: none}:host{--mat-filled-button-touch-target-display: none}:host{--mat-protected-button-touch-target-display: none}:host{--mat-outlined-button-touch-target-display: none}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.menu-icon{font-size:16px;line-height:16px;vertical-align:top;height:16px;width:16px}.search-icon{margin-right:16px;vertical-align:middle;height:24px;color:#0000008a;font-size:21px;line-height:1.125}.font{font-size:14px}.filter-radio-button:first-of-type{padding-left:0}.filter-radio-button{padding:10px 40px;min-width:110px}.auto-width{width:260px;margin:5px;display:block;height:55px}.open-menu-icon-button{height:28px;width:28px;padding:6px}.header-filter-icon-button{height:18px;width:18px;font-size:18px;padding:0;margin:0 2px}.header-filter-icon-button ::ng-deep *{line-height:initial;font-size:initial;height:18px;width:18px;font-size:18px;bottom:initial}.header-filter-icon-button.chosen-icon,.header-filter-icon-button.chosen-icon ::ng-deep *{height:22px;width:22px;font-size:22px;color:green}mat-icon.mat-icon.suffix-icons.underline{height:20px;text-decoration:underline .1px solid}.chosen-icon mat-icon.mat-icon.suffix-icons.underline{height:24px}::ng-deep .mat-mdc-form-field-icon-prefix:has(.tb-header-prefix),.tb-header-prefix{padding:0;flex-basis:36%}.tb-header-filter ::ng-deep .mat-mdc-form-field-subscript-wrapper{line-height:0}.tb-header-filter ::ng-deep .mat-mdc-form-field-subscript-wrapper:before{height:0}.date-toggle ::ng-deep svg{position:absolute;left:0;top:0}\n"] }]
3456
3522
  }] });
3457
3523
 
3458
3524
  class ColumnTotalPipe {
@@ -3615,7 +3681,7 @@ class ColumnBuilderComponent {
3615
3681
  return metaData.toolTip(element);
3616
3682
  };
3617
3683
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ColumnBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3618
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: ColumnBuilderComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "$columnDef", first: true, predicate: MatColumnDef, descendants: true, isSignal: true }, { propertyName: "$bodyTemplate", first: true, predicate: ["body"], descendants: true, isSignal: true }], ngImport: i0, template: "@let metaData = $metaData();\r\n@let customCell = $customCell();\r\n@let styles = $styles()!;\r\n\r\n@if(metaData)\r\n{\r\n <ng-container [matColumnDef]=\"metaData.key\">\r\n\r\n <!-- header -->\r\n <ng-template matHeaderCellDef #myHeader>\r\n <mat-header-cell cdkDrag [style]='styles?.header' resizeColumn [key]=\"metaData.key\" class=\"column-head\"\r\n [class]='metaData.additional?.columnPartClasses?.header'>\r\n <div class=\"header-container\" cdkDragHandle>\r\n @if(!customCell?.columnDef?.headerCell)\r\n {\r\n @if(metaData.fieldType !== FieldType.NotMapped){\r\n <div mat-sort-header [disabled]=\"metaData.noSort\" style=\"width: 100%\">\r\n {{ metaData.displayName ? metaData.displayName : ( metaData.key | spaceCase ) }}\r\n </div>\r\n } @else if(metaData.fieldType === FieldType.NotMapped){\r\n <div style=\"width: 100%\">\r\n {{ metaData.displayName ? metaData.displayName : ( metaData.key | spaceCase ) }}\r\n </div>\r\n }\r\n @if($showFilters()){\r\n <tb-header-menu #menu [metaData]='metaData' />\r\n }\r\n }\r\n @else\r\n {\r\n <ng-container *ngTemplateOutlet=\"customCell!.columnDef!.headerCell.template; context: {metaData: metaData, styles: styles?.header} \">\r\n </ng-container>\r\n }\r\n </div>\r\n </mat-header-cell>\r\n </ng-template>\r\n \r\n <!-- body -->\r\n <ng-container *matCellDef=\"let element;\">\r\n <ng-container *ngTemplateOutlet=\"$outerTemplate()!; context: { metaData: metaData, element: element , styles: styles?.body, $implicit: element }\"/>\r\n </ng-container>\r\n <ng-template #body let-element='element' >\r\n <mat-cell [matTooltip]=\"metaData.toolTip ? (getTooltip | func : element) : ''\" [conditionalClasses]='metaData.classes' [element]='element' [styler]='styles.body' (click)='cellClicked(element, metaData.key)' >\r\n <ng-container *ngTemplateOutlet=\"$innerTemplate()!; context: { value: ($transform()! | func : element), element: element, additional: $additional(), $implicit: element }; Injector: injector\" />\r\n </mat-cell>\r\n </ng-template>\r\n \r\n <!-- footer -->\r\n <ng-template matFooterCellDef>\r\n @if(customCell?.columnDef?.footerCell){\r\n <ng-container\r\n *ngTemplateOutlet=\"customCell!.columnDef!.footerCell.template; context: {metaData: metaData, data: $data, styles : styles.footer }\"/>\r\n } @else {\r\n @let data = $data();\r\n <mat-footer-cell [style]='styles.footer' [class]='metaData.additional?.columnPartClasses?.footer'>\r\n @if(!!data?.length && metaData.additional?.footer){\r\n <span class=\"bold\">\r\n @switch (metaData.fieldType) {\r\n @case (FieldType.Currency) { {{ data | columnTotal: metaData | currency }} }\r\n @case (FieldType.Number) { {{ data | columnTotal: metaData | number }} }\r\n }\r\n </span>\r\n }\r\n \r\n </mat-footer-cell>\r\n }\r\n </ng-template>\r\n </ng-container>\r\n}", styles: [".header-container{display:flex;flex-direction:row;width:100%;align-items:center}.negative-currency{color:red}.column-head{position:relative}.bold,.group-footer{font-weight:900}.cdk-drag-preview{background:#fff;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:33%;border-right-width:0px}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.drag-handle{color:#add8e6;cursor:move;margin-right:9px}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "directive", type: i1$5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1$5.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ResizeColumnDirective, selector: "[resizeColumn]", inputs: ["resizeColumn", "key"] }, { kind: "pipe", type: FunctionPipe, name: "func" }, { kind: "directive", type: StylerDirective, selector: "[styler]", inputs: ["element", "styler"] }, { kind: "directive", type: ConditionalClassesDirective, selector: "[conditionalClasses]", inputs: ["element", "conditionalClasses"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i5.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "component", type: i3$2.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }, { kind: "component", type: HeaderMenuComponent, selector: "tb-header-menu", inputs: ["metaData"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: ColumnTotalPipe, name: "columnTotal" }, { kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "pipe", type: DecimalPipe, name: "number" }], viewProviders: [
3684
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: ColumnBuilderComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "$columnDef", first: true, predicate: MatColumnDef, descendants: true, isSignal: true }, { propertyName: "$bodyTemplate", first: true, predicate: ["body"], descendants: true, isSignal: true }], ngImport: i0, template: "@let metaData = $metaData();\r\n@let customCell = $customCell();\r\n@let styles = $styles()!;\r\n\r\n@if(metaData)\r\n{\r\n <ng-container [matColumnDef]=\"metaData.key\">\r\n\r\n <!-- header -->\r\n <ng-template matHeaderCellDef #myHeader>\r\n <mat-header-cell cdkDrag [style]='styles?.header' resizeColumn [key]=\"metaData.key\" class=\"column-head\"\r\n [class]='metaData.additional?.columnPartClasses?.header'>\r\n <div class=\"header-container\" cdkDragHandle>\r\n @if(!customCell?.columnDef?.headerCell)\r\n {\r\n @if(metaData.fieldType !== FieldType.NotMapped){\r\n <div mat-sort-header [disabled]=\"metaData.noSort\" style=\"width: 100%\">\r\n {{ metaData.displayName ? metaData.displayName : ( metaData.key | spaceCase ) }}\r\n </div>\r\n } @else if(metaData.fieldType === FieldType.NotMapped){\r\n <div style=\"width: 100%\">\r\n {{ metaData.displayName ? metaData.displayName : ( metaData.key | spaceCase ) }}\r\n </div>\r\n }\r\n @if($showFilters()){\r\n <tb-header-menu #menu [metaData]='metaData' />\r\n }\r\n }\r\n @else\r\n {\r\n <ng-container *ngTemplateOutlet=\"customCell!.columnDef!.headerCell.template; context: {metaData: metaData, styles: styles?.header} \">\r\n </ng-container>\r\n }\r\n </div>\r\n </mat-header-cell>\r\n </ng-template>\r\n \r\n <!-- body -->\r\n <ng-container *matCellDef=\"let element;\">\r\n <ng-container *ngTemplateOutlet=\"$outerTemplate()!; context: { metaData: metaData, element: element , styles: styles?.body, $implicit: element }\"/>\r\n </ng-container>\r\n <ng-template #body let-element='element' >\r\n <mat-cell [matTooltip]=\"metaData.toolTip ? (getTooltip | func : element) : ''\" [conditionalClasses]='metaData.classes' [element]='element' [styler]='styles.body' (click)='cellClicked(element, metaData.key)' >\r\n <ng-container *ngTemplateOutlet=\"$innerTemplate()!; context: { value: ($transform()! | func : element), element: element, additional: $additional(), $implicit: element }; Injector: injector\" />\r\n </mat-cell>\r\n </ng-template>\r\n \r\n <!-- footer -->\r\n <ng-template matFooterCellDef>\r\n @if(customCell?.columnDef?.footerCell){\r\n <ng-container\r\n *ngTemplateOutlet=\"customCell!.columnDef!.footerCell.template; context: {metaData: metaData, data: $data, styles : styles.footer }\"/>\r\n } @else {\r\n @let data = $data();\r\n <mat-footer-cell [style]='styles.footer' [class]='metaData.additional?.columnPartClasses?.footer'>\r\n @if(!!data?.length && metaData.additional?.footer){\r\n <span class=\"bold\">\r\n @switch (metaData.fieldType) {\r\n @case (FieldType.Currency) { {{ data | columnTotal: metaData | currency }} }\r\n @case (FieldType.Number) { {{ data | columnTotal: metaData | number }} }\r\n }\r\n </span>\r\n }\r\n \r\n </mat-footer-cell>\r\n }\r\n </ng-template>\r\n </ng-container>\r\n}", styles: [".header-container{display:flex;flex-direction:row;width:100%;align-items:center}.negative-currency{color:red}.column-head{position:relative}.bold,.group-footer{font-weight:900}.cdk-drag-preview{background:#fff;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:33%;border-right-width:0px}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.drag-handle{color:#add8e6;cursor:move;margin-right:9px}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "directive", type: i1$6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$6.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1$6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1$6.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ResizeColumnDirective, selector: "[resizeColumn]", inputs: ["resizeColumn", "key"] }, { kind: "pipe", type: FunctionPipe, name: "func" }, { kind: "directive", type: StylerDirective, selector: "[styler]", inputs: ["element", "styler"] }, { kind: "directive", type: ConditionalClassesDirective, selector: "[conditionalClasses]", inputs: ["element", "conditionalClasses"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i5.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "component", type: i3$2.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }, { kind: "component", type: ColumnHeaderMenuComponent, selector: "tb-header-menu", inputs: ["metaData"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: ColumnTotalPipe, name: "columnTotal" }, { kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "pipe", type: DecimalPipe, name: "number" }], viewProviders: [
3619
3685
  { provide: CDK_DROP_LIST, useExisting: CdkDropList },
3620
3686
  ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3621
3687
  }
@@ -3625,7 +3691,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
3625
3691
  { provide: CDK_DROP_LIST, useExisting: CdkDropList },
3626
3692
  ], imports: [
3627
3693
  MatTableModule, NgTemplateOutlet, ResizeColumnDirective, FunctionPipe, StylerDirective,
3628
- ConditionalClassesDirective, DragDropModule, MatSortModule, SpaceCasePipe, HeaderMenuComponent,
3694
+ ConditionalClassesDirective, DragDropModule, MatSortModule, SpaceCasePipe, ColumnHeaderMenuComponent,
3629
3695
  MatTooltipModule, ColumnTotalPipe, CurrencyPipe, DecimalPipe
3630
3696
  ], template: "@let metaData = $metaData();\r\n@let customCell = $customCell();\r\n@let styles = $styles()!;\r\n\r\n@if(metaData)\r\n{\r\n <ng-container [matColumnDef]=\"metaData.key\">\r\n\r\n <!-- header -->\r\n <ng-template matHeaderCellDef #myHeader>\r\n <mat-header-cell cdkDrag [style]='styles?.header' resizeColumn [key]=\"metaData.key\" class=\"column-head\"\r\n [class]='metaData.additional?.columnPartClasses?.header'>\r\n <div class=\"header-container\" cdkDragHandle>\r\n @if(!customCell?.columnDef?.headerCell)\r\n {\r\n @if(metaData.fieldType !== FieldType.NotMapped){\r\n <div mat-sort-header [disabled]=\"metaData.noSort\" style=\"width: 100%\">\r\n {{ metaData.displayName ? metaData.displayName : ( metaData.key | spaceCase ) }}\r\n </div>\r\n } @else if(metaData.fieldType === FieldType.NotMapped){\r\n <div style=\"width: 100%\">\r\n {{ metaData.displayName ? metaData.displayName : ( metaData.key | spaceCase ) }}\r\n </div>\r\n }\r\n @if($showFilters()){\r\n <tb-header-menu #menu [metaData]='metaData' />\r\n }\r\n }\r\n @else\r\n {\r\n <ng-container *ngTemplateOutlet=\"customCell!.columnDef!.headerCell.template; context: {metaData: metaData, styles: styles?.header} \">\r\n </ng-container>\r\n }\r\n </div>\r\n </mat-header-cell>\r\n </ng-template>\r\n \r\n <!-- body -->\r\n <ng-container *matCellDef=\"let element;\">\r\n <ng-container *ngTemplateOutlet=\"$outerTemplate()!; context: { metaData: metaData, element: element , styles: styles?.body, $implicit: element }\"/>\r\n </ng-container>\r\n <ng-template #body let-element='element' >\r\n <mat-cell [matTooltip]=\"metaData.toolTip ? (getTooltip | func : element) : ''\" [conditionalClasses]='metaData.classes' [element]='element' [styler]='styles.body' (click)='cellClicked(element, metaData.key)' >\r\n <ng-container *ngTemplateOutlet=\"$innerTemplate()!; context: { value: ($transform()! | func : element), element: element, additional: $additional(), $implicit: element }; Injector: injector\" />\r\n </mat-cell>\r\n </ng-template>\r\n \r\n <!-- footer -->\r\n <ng-template matFooterCellDef>\r\n @if(customCell?.columnDef?.footerCell){\r\n <ng-container\r\n *ngTemplateOutlet=\"customCell!.columnDef!.footerCell.template; context: {metaData: metaData, data: $data, styles : styles.footer }\"/>\r\n } @else {\r\n @let data = $data();\r\n <mat-footer-cell [style]='styles.footer' [class]='metaData.additional?.columnPartClasses?.footer'>\r\n @if(!!data?.length && metaData.additional?.footer){\r\n <span class=\"bold\">\r\n @switch (metaData.fieldType) {\r\n @case (FieldType.Currency) { {{ data | columnTotal: metaData | currency }} }\r\n @case (FieldType.Number) { {{ data | columnTotal: metaData | number }} }\r\n }\r\n </span>\r\n }\r\n \r\n </mat-footer-cell>\r\n }\r\n </ng-template>\r\n </ng-container>\r\n}", styles: [".header-container{display:flex;flex-direction:row;width:100%;align-items:center}.negative-currency{color:red}.column-head{position:relative}.bold,.group-footer{font-weight:900}.cdk-drag-preview{background:#fff;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:33%;border-right-width:0px}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.drag-handle{color:#add8e6;cursor:move;margin-right:9px}\n"] }]
3631
3697
  }] });
@@ -3914,33 +3980,42 @@ class GenericTableComponent {
3914
3980
  return val;
3915
3981
  }
3916
3982
  };
3917
- $rowHeight = this.state.selectSignal(s => {
3918
- if (this.state.$isVirtual() && s.notPersistedTableSettings.virtualSettings?.enforceRowHeight) {
3919
- const height = s.notPersistedTableSettings.virtualSettings.rowHeight;
3920
- return height + 'px';
3983
+ $rowHeight = computed(() => {
3984
+ if (this.state.$userDefinedRowHeight()) {
3985
+ return this.state.$userDefinedRowHeight() + 'px';
3921
3986
  }
3922
- if (typeof s.notPersistedTableSettings.rowHeight === 'number') {
3923
- return s.notPersistedTableSettings.rowHeight + 'px';
3987
+ const notPersistedTableSettings = this.state.$notPersistedTableSettings();
3988
+ if (this.state.$isVirtual() && notPersistedTableSettings.virtualSettings?.enforceRowHeight) {
3989
+ const height = notPersistedTableSettings.virtualSettings.rowHeight;
3990
+ return parseTbSizeToPixels(height) + 'px';
3924
3991
  }
3925
- return s.notPersistedTableSettings.rowHeight;
3992
+ if (notPersistedTableSettings.rowHeight) {
3993
+ return parseTbSizeToPixels(notPersistedTableSettings.rowHeight) + 'px';
3994
+ }
3995
+ return undefined;
3926
3996
  });
3927
- $headerHeight = this.state.selectSignal(s => {
3928
- if (this.state.$isVirtual() && s.notPersistedTableSettings.virtualSettings?.enforceHeaderHeight) {
3929
- const height = s.notPersistedTableSettings.virtualSettings.headerHeight;
3930
- return height + 'px';
3997
+ $headerHeight = computed(() => {
3998
+ if (this.state.$userDefinedHeaderHeight()) {
3999
+ return this.state.$userDefinedHeaderHeight() + 'px';
3931
4000
  }
3932
- if (typeof s.notPersistedTableSettings.headerHeight === 'number') {
3933
- return s.notPersistedTableSettings.headerHeight + 'px';
4001
+ const notPersistedTableSettings = this.state.$notPersistedTableSettings();
4002
+ if (this.state.$isVirtual() && notPersistedTableSettings.virtualSettings?.enforceHeaderHeight) {
4003
+ const height = notPersistedTableSettings.virtualSettings.headerHeight;
4004
+ return parseTbSizeToPixels(height) + 'px';
3934
4005
  }
3935
- return s.notPersistedTableSettings.headerHeight;
4006
+ if (notPersistedTableSettings.headerHeight) {
4007
+ return parseTbSizeToPixels(notPersistedTableSettings.headerHeight) + 'px';
4008
+ }
4009
+ return undefined;
3936
4010
  });
3937
- $groupHeaderHeight = this.state.selectSignal(s => {
3938
- if (s.notPersistedTableSettings.groupHeaderHeight) {
3939
- return s.notPersistedTableSettings.groupHeaderHeight + 'px';
4011
+ $groupHeaderHeight = computed(() => {
4012
+ const groupHeaderHeight = this.state.$notPersistedTableSettings().groupHeaderHeight;
4013
+ if (groupHeaderHeight) {
4014
+ return parseTbSizeToPixels(groupHeaderHeight) + 'px';
3940
4015
  }
3941
4016
  return this.$rowHeight();
3942
4017
  });
3943
- $footerHeight = this.state.selectSignal(s => {
4018
+ $footerHeight = computed(() => {
3944
4019
  const footerStyle = this.$footerRowStyle();
3945
4020
  switch (footerStyle) {
3946
4021
  case 'regular-footer':
@@ -3953,7 +4028,7 @@ class GenericTableComponent {
3953
4028
  });
3954
4029
  $stickyFooter = computed(() => this.state.$props().stickyFooter || this.state.$isVirtual());
3955
4030
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GenericTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3956
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: GenericTableComponent, isStandalone: true, selector: "tb-generic-table", inputs: { $displayDataLength: { classPropertyName: "$displayDataLength", publicName: "displayDataLength", isSignal: true, isRequired: true, transformFunction: null }, $data: { classPropertyName: "$data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, $rows: { classPropertyName: "$rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, $columnInfos: { classPropertyName: "$columnInfos", publicName: "columnInfos", isSignal: true, isRequired: true, transformFunction: null }, $dataSource: { classPropertyName: "$dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, $trackBy: { classPropertyName: "$trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection$: "selection" }, viewQueries: [{ propertyName: "$headerRow", first: true, predicate: MatHeaderRowDef, descendants: true, isSignal: true }, { propertyName: "$footerRow", first: true, predicate: MatFooterRowDef, descendants: true, isSignal: true }, { propertyName: "$table", first: true, predicate: MatTable, descendants: true, isSignal: true }, { propertyName: "$dropList", first: true, predicate: CdkDropList, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-table\r\n cdkDropList\r\n cdkDropListLockAxis='x'\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n class=\"table-drag-list\"\r\n #table\r\n [dataSource]=\"$dataSource()\"\r\n [trackBy]=\"$trackByFunction()\"\r\n [style]=\"$tableWidth()\"\r\n>\r\n\r\n <!-- select column -->\r\n <ng-container matColumnDef=\"select\">\r\n @let selection = $selection();\r\n <mat-header-cell *matHeaderCellDef class=\"select-column\">\r\n <mat-checkbox (change)=\"$event ? masterToggle() : null\"\r\n [checked]=\"!!($masterToggleChecked())\"\r\n [indeterminate]=\"$masterToggleIndeterminate()\">\r\n </mat-checkbox>\r\n </mat-header-cell>\r\n\r\n <mat-cell *matCellDef=\"let row\" class=\"select-column\">\r\n <mat-checkbox\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"$event ? selection.toggle(row) : null\"\r\n [checked]=\"selection.isSelected(row)\"/>\r\n </mat-cell>\r\n\r\n <mat-footer-cell *matFooterCellDef class=\"select-column\">\r\n {{ selection.selected.length }}\r\n </mat-footer-cell>\r\n </ng-container>\r\n\r\n\r\n <!-- index column -->\r\n <ng-container matColumnDef=\"index\">\r\n <mat-header-cell *matHeaderCellDef class=\"f-mat-header-cell\" class=\"index-column\">#\r\n </mat-header-cell>\r\n <mat-cell *matCellDef=\"let i = index;\" class=\"index-column\">\r\n {{ 1 + i + $offsetIndex() }}\r\n </mat-cell>\r\n <mat-footer-cell *matFooterCellDef class=\"index-column\"></mat-footer-cell>\r\n </ng-container>\r\n\r\n <!-- Grouping -->\r\n <ng-container matColumnDef=\"groupHeader\">\r\n <mat-cell *matCellDef=\"let row\">\r\n @let expanded = (state.$getIsExpanded | func : row.key : row.groupName );\r\n <div [style.paddingLeft]=\"row.padding + 'px !important'\">\r\n <button mat-icon-button (click)=\"setExpanded(row.key, row.groupName, !expanded());\">\r\n @if (!expanded()) {\r\n <mat-icon>chevron_right</mat-icon>\r\n } @else {\r\n <mat-icon>expand_more</mat-icon>\r\n }\r\n </button>\r\n {{ getTransform | func : row.key : row.groupHeaderDisplay }} ({{ row.length }})\r\n </div>\r\n <div style=\"flex-grow: 1\">\r\n <ng-container *ngTemplateOutlet=\"state.$props().groupHeaderTemplate!; context: { element: row }\"></ng-container>\r\n </div>\r\n </mat-cell>\r\n </ng-container>\r\n\r\n <mat-row [style.height]=\"$rowHeight()\" [style.min-height]=\"$rowHeight()\"\r\n *matRowDef=\"let row; columns: $keys(); let i = index\"/>\r\n <mat-row [style.height]=\"state.$props().groupHeaderHeight ? state.$props().groupHeaderHeight + 'px' : $groupHeaderHeight()\"\r\n [style.min-height]=\"state.$props().groupHeaderHeight ? state.$props().groupHeaderHeight + 'px' : $groupHeaderHeight()\"\r\n *matRowDef=\"let row; columns: ['groupHeader']; when: isGroupHeader\" style=\"background-color: white;\"/>\r\n</mat-table>\r\n\r\n<mat-header-row [style.height]=\"$headerHeight()\" [style.min-height]=\"$headerHeight()\"\r\n *matHeaderRowDef=\"$keys(); sticky: state.$props().isSticky\" [style.top.px]=\"($offset()! * -1)\"/>\r\n<mat-footer-row [style.height]=\"$footerHeight()\" [style.min-height]=\"$footerHeight()\"\r\n *matFooterRowDef=\"$keys(); sticky: $stickyFooter() \"\r\n [style.bottom.px]=\"$stickyFooter() ? ($offset()) : undefined\"/>\r\n", styles: [":host{--mat-paginator-container-size: initial}.select-column{min-width:var(--tb-min-select-column-width, 42px)}.index-column{min-width:var(--tb-min-index-column-width, 42px)}.mat-mdc-row:nth-child(odd){background-color:var(--tb-odd-row-background-color, #cdeefe)}.page-amounts{color:#0000008a;font-family:Roboto,Helvetica Neue,sans-serif;font-size:12px;margin-right:.2rem}:host::ng-deep .table-drag-list.cdk-drop-list-dragging .drag-header:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}:host::ng-deep .mdc-data-table__cell,:host::ng-deep .mdc-data-table__header-cell{padding:var(--tb-cell-padding, 0 0 0 .2rem);line-height:var(--tb-cell-line-height, normal)}::ng-deep .op-date-time-input{line-height:3rem;font-size:.9rem;font-family:Roboto,Helvetica Neue,sans-serif;padding-left:.2rem;width:12rem}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$5.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1$5.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1$5.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i1$5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i1$5.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i1$2.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "pipe", type: FunctionPipe, name: "func" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4031
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: GenericTableComponent, isStandalone: true, selector: "tb-generic-table", inputs: { $displayDataLength: { classPropertyName: "$displayDataLength", publicName: "displayDataLength", isSignal: true, isRequired: true, transformFunction: null }, $data: { classPropertyName: "$data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, $rows: { classPropertyName: "$rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, $columnInfos: { classPropertyName: "$columnInfos", publicName: "columnInfos", isSignal: true, isRequired: true, transformFunction: null }, $dataSource: { classPropertyName: "$dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, $trackBy: { classPropertyName: "$trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection$: "selection" }, viewQueries: [{ propertyName: "$headerRow", first: true, predicate: MatHeaderRowDef, descendants: true, isSignal: true }, { propertyName: "$footerRow", first: true, predicate: MatFooterRowDef, descendants: true, isSignal: true }, { propertyName: "$table", first: true, predicate: MatTable, descendants: true, isSignal: true }, { propertyName: "$dropList", first: true, predicate: CdkDropList, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-table\r\n cdkDropList\r\n cdkDropListLockAxis='x'\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n class=\"table-drag-list\"\r\n #table\r\n [dataSource]=\"$dataSource()\"\r\n [trackBy]=\"$trackByFunction()\"\r\n [style]=\"$tableWidth()\"\r\n>\r\n\r\n <!-- select column -->\r\n <ng-container matColumnDef=\"select\">\r\n @let selection = $selection();\r\n <mat-header-cell *matHeaderCellDef class=\"select-column\">\r\n <mat-checkbox (change)=\"$event ? masterToggle() : null\"\r\n [checked]=\"!!($masterToggleChecked())\"\r\n [indeterminate]=\"$masterToggleIndeterminate()\">\r\n </mat-checkbox>\r\n </mat-header-cell>\r\n\r\n <mat-cell *matCellDef=\"let row\" class=\"select-column\">\r\n <mat-checkbox\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"$event ? selection.toggle(row) : null\"\r\n [checked]=\"selection.isSelected(row)\"/>\r\n </mat-cell>\r\n\r\n <mat-footer-cell *matFooterCellDef class=\"select-column\">\r\n {{ selection.selected.length }}\r\n </mat-footer-cell>\r\n </ng-container>\r\n\r\n\r\n <!-- index column -->\r\n <ng-container matColumnDef=\"index\">\r\n <mat-header-cell *matHeaderCellDef class=\"f-mat-header-cell\" class=\"index-column\">#\r\n </mat-header-cell>\r\n <mat-cell *matCellDef=\"let i = index;\" class=\"index-column\">\r\n {{ 1 + i + $offsetIndex() }}\r\n </mat-cell>\r\n <mat-footer-cell *matFooterCellDef class=\"index-column\"></mat-footer-cell>\r\n </ng-container>\r\n\r\n <!-- Grouping -->\r\n <ng-container matColumnDef=\"groupHeader\">\r\n <mat-cell *matCellDef=\"let row\">\r\n @let expanded = (state.$getIsExpanded | func : row.key : row.groupName );\r\n <div [style.paddingLeft]=\"row.padding + 'px !important'\">\r\n <button mat-icon-button (click)=\"setExpanded(row.key, row.groupName, !expanded());\">\r\n @if (!expanded()) {\r\n <mat-icon>chevron_right</mat-icon>\r\n } @else {\r\n <mat-icon>expand_more</mat-icon>\r\n }\r\n </button>\r\n {{ getTransform | func : row.key : row.groupHeaderDisplay }} ({{ row.length }})\r\n </div>\r\n <div style=\"flex-grow: 1\">\r\n <ng-container *ngTemplateOutlet=\"state.$props().groupHeaderTemplate!; context: { element: row }\"></ng-container>\r\n </div>\r\n </mat-cell>\r\n </ng-container>\r\n\r\n <mat-row [style.height]=\"$rowHeight()\" [style.min-height]=\"$rowHeight()\"\r\n *matRowDef=\"let row; columns: $keys(); let i = index\"/>\r\n <mat-row [style.height]=\"state.$props().groupHeaderHeight ? state.$props().groupHeaderHeight + 'px' : $groupHeaderHeight()\"\r\n [style.min-height]=\"state.$props().groupHeaderHeight ? state.$props().groupHeaderHeight + 'px' : $groupHeaderHeight()\"\r\n *matRowDef=\"let row; columns: ['groupHeader']; when: isGroupHeader\" style=\"background-color: white;\"/>\r\n</mat-table>\r\n\r\n<mat-header-row [style.height]=\"$headerHeight()\" [style.min-height]=\"$headerHeight()\"\r\n *matHeaderRowDef=\"$keys(); sticky: state.$props().isSticky\" [style.top.px]=\"($offset()! * -1)\"/>\r\n<mat-footer-row [style.height]=\"$footerHeight()\" [style.min-height]=\"$footerHeight()\"\r\n *matFooterRowDef=\"$keys(); sticky: $stickyFooter() \"\r\n [style.bottom.px]=\"$stickyFooter() ? ($offset()) : undefined\"/>\r\n", styles: [":host{--mat-paginator-container-size: initial}.select-column{min-width:var(--tb-min-select-column-width, 42px)}.index-column{min-width:var(--tb-min-index-column-width, 42px)}.mat-mdc-row:nth-child(odd){background-color:var(--tb-odd-row-background-color, #cdeefe)}.page-amounts{color:#0000008a;font-family:Roboto,Helvetica Neue,sans-serif;font-size:12px;margin-right:.2rem}:host::ng-deep .table-drag-list.cdk-drop-list-dragging .drag-header:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}:host::ng-deep .mdc-data-table__cell,:host::ng-deep .mdc-data-table__header-cell{padding:var(--tb-cell-padding, 0 0 0 .2rem);line-height:var(--tb-cell-line-height, normal)}::ng-deep .op-date-time-input{line-height:3rem;font-size:.9rem;font-family:Roboto,Helvetica Neue,sans-serif;padding-left:.2rem;width:12rem}\n"], dependencies: [{ kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$6.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1$6.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i1$6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1$6.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i1$6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i1$6.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i1$2.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "pipe", type: FunctionPipe, name: "func" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3957
4032
  }
3958
4033
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GenericTableComponent, decorators: [{
3959
4034
  type: Component,
@@ -4241,161 +4316,361 @@ const defaultStorageState = {
4241
4316
  localProfiles: {}
4242
4317
  };
4243
4318
 
4244
- class GroupByListComponent {
4245
- tableStore = inject(TableStore);
4246
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GroupByListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4247
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: GroupByListComponent, isStandalone: true, selector: "group-by-list", ngImport: i0, template: "<mat-chip-set>\r\n <span class=\"tb-group-label\">Group By:</span>\r\n @for (groupByKey of tableStore.$groupByKeys(); track groupByKey) {\r\n @if($index > 0){\r\n <mat-icon class=\"nested-arrow\">arrow_right</mat-icon>\r\n }\r\n <mat-chip (removed)=\"tableStore.removeGroupByKey(groupByKey)\">\r\n {{groupByKey | spaceCase}}\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n</mat-chip-set>\r\n", styles: [".tb-group-label{padding-right:5px}.nested-arrow{margin-right:-8px;margin-left:-8px}\n"], dependencies: [{ kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i4$3.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i4$3.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i4$3.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4248
- }
4249
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GroupByListComponent, decorators: [{
4250
- type: Component,
4251
- args: [{ selector: 'group-by-list', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
4252
- MatChipsModule, MatIconModule, SpaceCasePipe
4253
- ], template: "<mat-chip-set>\r\n <span class=\"tb-group-label\">Group By:</span>\r\n @for (groupByKey of tableStore.$groupByKeys(); track groupByKey) {\r\n @if($index > 0){\r\n <mat-icon class=\"nested-arrow\">arrow_right</mat-icon>\r\n }\r\n <mat-chip (removed)=\"tableStore.removeGroupByKey(groupByKey)\">\r\n {{groupByKey | spaceCase}}\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n</mat-chip-set>\r\n", styles: [".tb-group-label{padding-right:5px}.nested-arrow{margin-right:-8px;margin-left:-8px}\n"] }]
4254
- }] });
4255
-
4256
- class SortMenuComponentStore extends ComponentStore {
4257
- tableState = inject(TableStore);
4258
- setStoreStateEffect = effect(() => {
4259
- const metaData = this.tableState.$metaData();
4260
- if (!metaData)
4261
- return;
4262
- this.tableState.$selectSorted();
4263
- untracked(() => this.setStateFromTableStore());
4264
- });
4265
- setStateFromTableStore = () => {
4266
- const metaData = this.tableState.$metaData();
4267
- const sorted = [...this.tableState.$selectSorted()].map(s => ({
4268
- ...s,
4269
- displayName: metaData[s.active]?.displayName
4270
- }));
4271
- const notSorted = this.tableState.$metaDataArray()
4272
- .filter(md => md.fieldType !== FieldType.NotMapped && !md.noSort && !sorted.some(s => s.active === md.key))
4273
- .map(meta => ({ active: meta.key, displayName: meta.displayName }));
4274
- this.setState({ sorted, notSorted });
4319
+ //The idea of this is that if filters were only added, and none were removed or changed, then we only need to tag more rows to not be shown. We don't need to remove any 'dont show' tags.
4320
+ // So if filters were only added this method will return the added filters, if filters were removed or changed this method will return undefined.
4321
+ const updateFilterInfoState = (previousState, filterInfos) => {
4322
+ filterInfos = filterNonActiveOrNotReadyFilters(filterInfos);
4323
+ const currentState = {
4324
+ allFilters: filterInfos,
4325
+ onlyAddedFilters: filterInfoOnlyAdded(previousState.allFilters, filterInfos)
4275
4326
  };
4276
- constructor() {
4277
- super({ notSorted: [], sorted: [] });
4278
- }
4279
- setSorted = this.updater((state, sorted) => ({ ...state, sorted }));
4280
- setNotSorted = this.updater((state, notSorted) => ({ ...state, notSorted }));
4281
- $sorted = this.selectSignal(state => state.sorted);
4282
- $notSorted = this.selectSignal(state => state.notSorted);
4283
- setDirection = this.updater((state, sort) => {
4284
- const index = state.sorted.findIndex(s => s.active === sort.active);
4285
- const sorted = [...state.sorted];
4286
- sorted.splice(index, 1, sort);
4287
- return ({ ...state, sorted });
4327
+ return currentState;
4328
+ };
4329
+ const mapFilterInfoStateToPredicateState = (s) => {
4330
+ const mappedAddOnly = s.onlyAddedFilters
4331
+ ?
4332
+ Object.entries(s.onlyAddedFilters).filter(([, v]) => needsFilterCreation(v)).reduce((obj, [key, value]) => {
4333
+ obj[key] = createFilterFunc(value);
4334
+ return obj;
4335
+ }, {})
4336
+ : {};
4337
+ const mappedAll = Object.entries(s.allFilters).filter(([, v]) => needsFilterCreation(v))
4338
+ .filter(([, v]) => !isCustomFilter(v) || !!v.predicate)
4339
+ .map(([key, value]) => {
4340
+ return mappedAddOnly[key] || createFilterFunc(value);
4288
4341
  });
4289
- reset = () => {
4290
- this.setStateFromTableStore();
4342
+ return ({
4343
+ allFilters: mappedAll,
4344
+ onlyAddedFilters: s.onlyAddedFilters ? Object.values(mappedAddOnly) : undefined
4345
+ });
4346
+ };
4347
+ const updateFilterPredicateState = (previousState, filters) => {
4348
+ const currentState = {
4349
+ allFilters: filters,
4350
+ onlyAddedFilters: predicatesOnlyAdded(previousState.allFilters, filters)
4291
4351
  };
4292
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponentStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
4293
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponentStore });
4352
+ return currentState;
4353
+ };
4354
+ const updateFilterState = (filterInfos, predicates) => {
4355
+ const infos = mapFilterInfoStateToPredicateState(filterInfos.value);
4356
+ const filtersState = {
4357
+ allFilters: [...infos.allFilters, ...predicates.value.allFilters]
4358
+ };
4359
+ if (filterInfos.timestamp > predicates.timestamp && !!filterInfos.value.onlyAddedFilters) {
4360
+ filtersState.onlyAddedFilters = infos.onlyAddedFilters;
4361
+ }
4362
+ else {
4363
+ filtersState.onlyAddedFilters = predicates.value.onlyAddedFilters;
4364
+ }
4365
+ return filtersState;
4366
+ };
4367
+ const filterNonActiveOrNotReadyFilters = (filtersDict) => Object.entries(filtersDict).reduce((obj, [key, value]) => {
4368
+ if (value.active !== false && (!isCustomFilter(value) || !!value.predicate)) {
4369
+ obj[key] = value;
4370
+ }
4371
+ ;
4372
+ return obj;
4373
+ }, {});
4374
+ function filterInfoOnlyAdded(previousFilterInfos, currentFilterInfos) {
4375
+ const previousKeys = Object.keys(previousFilterInfos);
4376
+ const currentKeys = Object.keys(currentFilterInfos);
4377
+ const keysInBoth = intersection(previousKeys, currentKeys);
4378
+ const someRemoved = previousKeys.length > keysInBoth.length;
4379
+ if (someRemoved || !previousKeys.length) {
4380
+ return undefined;
4381
+ }
4382
+ if (filtersInfosUpdated(previousFilterInfos, currentFilterInfos)) {
4383
+ return undefined;
4384
+ }
4385
+ const addedFilters = difference(currentKeys, keysInBoth).reduce((dict, key) => {
4386
+ dict[key] = currentFilterInfos[key];
4387
+ return dict;
4388
+ }, {});
4389
+ return addedFilters;
4294
4390
  }
4295
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponentStore, decorators: [{
4296
- type: Injectable
4297
- }], ctorParameters: () => [] });
4298
-
4299
- class SortMenuComponent {
4300
- SortDirection = SortDirection;
4301
- tableState = inject(TableStore);
4302
- store = inject(SortMenuComponentStore);
4303
- $sorted = computed(() => [...this.store.$sorted()]);
4304
- $notSorted = computed(() => [...this.store.$notSorted()]);
4305
- $dirty = signal(false);
4306
- reset() {
4307
- this.$dirty.set(false);
4308
- this.store.reset();
4391
+ function predicatesOnlyAdded(previousPredicates, currentPredicates) {
4392
+ if (!previousPredicates.length) {
4393
+ return undefined;
4309
4394
  }
4310
- dropIntoSorted(event) {
4311
- this.$dirty.set(true);
4312
- const sorted = [...event.container.data];
4313
- if (event.previousContainer === event.container) {
4314
- moveItemInArray(sorted, event.previousIndex, event.currentIndex);
4315
- this.store.setSorted(sorted);
4316
- }
4317
- else {
4318
- const notSorted = [...event.previousContainer.data];
4319
- transferArrayItem(notSorted, sorted, event.previousIndex, event.currentIndex);
4320
- sorted[event.currentIndex] = { ...sorted[event.currentIndex], direction: SortDirection.asc };
4321
- this.store.setSorted(sorted);
4322
- this.store.setNotSorted(notSorted);
4323
- }
4395
+ const predicateFiltersRemoved = difference(previousPredicates, currentPredicates).length;
4396
+ if (predicateFiltersRemoved) {
4397
+ return undefined;
4324
4398
  }
4325
- dropIntoNotSorted(event) {
4326
- if (event.previousContainer === event.container) {
4327
- return;
4328
- }
4329
- else {
4330
- this.$dirty.set(true);
4331
- const sorted = [...event.previousContainer.data];
4332
- const notSorted = [...event.container.data];
4333
- transferArrayItem(sorted, notSorted, event.previousIndex, event.currentIndex);
4334
- notSorted[event.currentIndex] = { ...notSorted[event.currentIndex] };
4335
- this.store.setNotSorted(notSorted);
4336
- this.store.setSorted(sorted);
4337
- }
4399
+ return difference(currentPredicates, previousPredicates);
4400
+ }
4401
+ function filtersInfosUpdated(previousFilterInfos, currentFilterInfos) {
4402
+ return !Object.entries(previousFilterInfos).every(([key, val]) => {
4403
+ return currentFilterInfos[key].filterType === val.filterType && currentFilterInfos[key].filterValue === val.filterValue;
4404
+ });
4405
+ }
4406
+ function patchDirectiveFromState(directive, stateFilter) {
4407
+ if (isFilterInfo(stateFilter)) {
4408
+ const filterDirective = directive;
4409
+ filterDirective.setFilterValue(stateFilter.filterValue);
4410
+ filterDirective.update();
4338
4411
  }
4339
- apply = () => {
4340
- this.$dirty.set(false);
4341
- this.tableState.setAllSort(this.store.$sorted());
4342
- };
4343
- setDirection(sort) {
4344
- this.$dirty.set(true);
4345
- this.store.setDirection(sort);
4412
+ if (isCustomFilter(stateFilter)) {
4413
+ directive.active = stateFilter.active ?? false;
4346
4414
  }
4347
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4348
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: SortMenuComponent, isStandalone: true, selector: "tb-sort-menu", providers: [SortMenuComponentStore], ngImport: i0, template: "@let dirty = $dirty();\r\n@let sorted = $sorted();\r\n@let notSorted = $notSorted();\r\n\r\n<!-- Menu Trigger -->\r\n<span matTooltip=\"Sort\">\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\r\n <mat-icon color=\"primary\">swap_vert</mat-icon>\r\n </button>\r\n</span>\r\n\r\n<!-- Menu -->\r\n<mat-menu #menu=\"matMenu\" class=\"my-mat-menu\" (closed)=\"reset()\">\r\n <div mat-menu-item class=\"menu-button\">\r\n <div class=\"close-button-wrapper\">\r\n <span matTooltip=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </span>\r\n @if(dirty){\r\n <span matTooltip=\"Undo\" stop-propagation (click)=\"reset()\">\r\n <mat-icon>undo</mat-icon>\r\n </span>\r\n }\r\n \r\n </div>\r\n </div>\r\n\r\n <!-- Apply Button -->\r\n <div class=\"apply-button-wrapper\">\r\n <button mat-button color=\"primary\" (click)=\"apply()\"\r\n stop-propagation [class.apply-border]=\"dirty\"\r\n [disabled]=\"!dirty\">\r\n Apply @if (dirty) { Unsaved Changes }\r\n </button>\r\n </div>\r\n\r\n <!-- Default Sorting Text -->\r\n @if (!sorted.length) {\r\n <div class=\"tip\" >\r\n Sorting List\r\n </div>\r\n }\r\n\r\n <!-- Sorted Menu List -->\r\n <div class=\"list\"\r\n cdkDropList\r\n #sortedGroup=\"cdkDropList\"\r\n [cdkDropListConnectedTo]=\"[notSortedGroup]\"\r\n [cdkDropListData]=\"sorted\"\r\n (cdkDropListDropped)=\"dropIntoSorted($event)\">\r\n\r\n <!-- Menu Item Wrapper -->\r\n @for (sort of sorted; track sort.active) {\r\n <!-- Menu Item Headers -->\r\n @if (sorted.length > 1) {\r\n <span class=\"description sort-header\">{{$index === 0 ? 'First By' : 'Then By'}}</span>\r\n }\r\n\r\n <!-- Menu Item -->\r\n <div mat-menu-item cdkDrag class=\"menu-item\">\r\n <div class=\"sort-item\">\r\n <span class=\"sorted-name\">\r\n {{sort.displayName || (sort.active | spaceCase)}}\r\n <span class=\"direction-text\">{{sort.direction}}</span>\r\n </span>\r\n\r\n <!-- Sort Direction Buttons -->\r\n <div class=\"up-down-buttons-wrapper\">\r\n <button class=\"up-down-button up-button\" stop-propagation\r\n (click)=\"setDirection({active:sort.active,direction:SortDirection.asc,displayName:sort.displayName})\">\r\n <mat-icon [class]=\"sort.direction !== SortDirection.asc ? 'light-arrow' : 'dark-arrow'\" class=\"up-down-icon\">\r\n arrow_upward\r\n </mat-icon>\r\n </button>\r\n\r\n <button class=\"up-down-button\" stop-propagation\r\n (click)=\"setDirection({active:sort.active,direction:SortDirection.desc,displayName:sort.displayName})\">\r\n <mat-icon [class]=\"sort.direction === SortDirection.asc ? 'light-arrow' : 'dark-arrow'\" class=\"up-down-icon\">\r\n arrow_downward\r\n </mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n </div>\r\n\r\n <!-- Default Not Sorted Text -->\r\n @if(!notSorted.length){\r\n <div class=\"tip\" >\r\n Not Sorted List\r\n </div>\r\n }\r\n\r\n <!-- Not Sorted Menu List -->\r\n <div class=\"list\"\r\n cdkDropList\r\n #notSortedGroup=\"cdkDropList\"\r\n [cdkDropListConnectedTo]=\"[sortedGroup]\"\r\n [cdkDropListData]=\"notSorted\"\r\n (cdkDropListDropped)=\"dropIntoNotSorted($event)\">\r\n @for (sort of notSorted; track sort.active) {\r\n <div mat-menu-item class=\"menu-item\" cdkDrag>\r\n <span class=\"not-sorted-name\">{{sort.displayName || (sort.active | spaceCase)}}</span>\r\n </div>\r\n }\r\n </div>\r\n</mat-menu>\r\n", styles: [".cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.list{padding:5px 2px;border-bottom:solid 1px #ccc;color:#000000de;background:#fff}.light-arrow{color:#93b1ea78}.dark-arrow{color:#224e9c}.up-down-button{background-color:#fff;border-radius:30%;border-color:#0ff;padding:1px 1px 0;border-width:.5px;cursor:pointer;height:27px}.mat-icon.up-down-icon{margin-right:0;font-size:20px;font-weight:lighter}.sort-item{display:flex;align-items:center;justify-content:space-between}.up-down-buttons-wrapper{margin-left:2rem}.up-button{margin-right:.3rem}.mat-mdc-menu-item.menu-item,.mat-mdc-menu-item.menu-button{min-height:initial;padding:0 3px;line-height:25px;height:30px}.mat-mdc-menu-item.menu-item{cursor:move}.sorted-name{color:#224e9c;font-size:17px;font-weight:700}.not-sorted-name{color:#93b1ea;font-size:17px;font-weight:700}.apply-border{border:#224e9c solid .5px}.apply-border:hover{background-color:#faebd7}.apply-button-wrapper{display:grid;justify-content:center}.sort-header{font-size:10px;font-style:italic}.tip{padding:0 3px;color:#d3d3d3}.direction-text{font-size:small;font-weight:400}.close-button-wrapper{display:flex;flex-direction:row-reverse}\n"], dependencies: [{ kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4349
4415
  }
4350
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponent, decorators: [{
4351
- type: Component,
4352
- args: [{ selector: 'tb-sort-menu', providers: [SortMenuComponentStore], changeDetection: ChangeDetectionStrategy.OnPush, imports: [
4353
- MatTooltipModule, MatButtonModule, MatIconModule, MatMenuModule, StopPropagationDirective, DragDropModule,
4354
- SpaceCasePipe
4355
- ], template: "@let dirty = $dirty();\r\n@let sorted = $sorted();\r\n@let notSorted = $notSorted();\r\n\r\n<!-- Menu Trigger -->\r\n<span matTooltip=\"Sort\">\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\r\n <mat-icon color=\"primary\">swap_vert</mat-icon>\r\n </button>\r\n</span>\r\n\r\n<!-- Menu -->\r\n<mat-menu #menu=\"matMenu\" class=\"my-mat-menu\" (closed)=\"reset()\">\r\n <div mat-menu-item class=\"menu-button\">\r\n <div class=\"close-button-wrapper\">\r\n <span matTooltip=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </span>\r\n @if(dirty){\r\n <span matTooltip=\"Undo\" stop-propagation (click)=\"reset()\">\r\n <mat-icon>undo</mat-icon>\r\n </span>\r\n }\r\n \r\n </div>\r\n </div>\r\n\r\n <!-- Apply Button -->\r\n <div class=\"apply-button-wrapper\">\r\n <button mat-button color=\"primary\" (click)=\"apply()\"\r\n stop-propagation [class.apply-border]=\"dirty\"\r\n [disabled]=\"!dirty\">\r\n Apply @if (dirty) { Unsaved Changes }\r\n </button>\r\n </div>\r\n\r\n <!-- Default Sorting Text -->\r\n @if (!sorted.length) {\r\n <div class=\"tip\" >\r\n Sorting List\r\n </div>\r\n }\r\n\r\n <!-- Sorted Menu List -->\r\n <div class=\"list\"\r\n cdkDropList\r\n #sortedGroup=\"cdkDropList\"\r\n [cdkDropListConnectedTo]=\"[notSortedGroup]\"\r\n [cdkDropListData]=\"sorted\"\r\n (cdkDropListDropped)=\"dropIntoSorted($event)\">\r\n\r\n <!-- Menu Item Wrapper -->\r\n @for (sort of sorted; track sort.active) {\r\n <!-- Menu Item Headers -->\r\n @if (sorted.length > 1) {\r\n <span class=\"description sort-header\">{{$index === 0 ? 'First By' : 'Then By'}}</span>\r\n }\r\n\r\n <!-- Menu Item -->\r\n <div mat-menu-item cdkDrag class=\"menu-item\">\r\n <div class=\"sort-item\">\r\n <span class=\"sorted-name\">\r\n {{sort.displayName || (sort.active | spaceCase)}}\r\n <span class=\"direction-text\">{{sort.direction}}</span>\r\n </span>\r\n\r\n <!-- Sort Direction Buttons -->\r\n <div class=\"up-down-buttons-wrapper\">\r\n <button class=\"up-down-button up-button\" stop-propagation\r\n (click)=\"setDirection({active:sort.active,direction:SortDirection.asc,displayName:sort.displayName})\">\r\n <mat-icon [class]=\"sort.direction !== SortDirection.asc ? 'light-arrow' : 'dark-arrow'\" class=\"up-down-icon\">\r\n arrow_upward\r\n </mat-icon>\r\n </button>\r\n\r\n <button class=\"up-down-button\" stop-propagation\r\n (click)=\"setDirection({active:sort.active,direction:SortDirection.desc,displayName:sort.displayName})\">\r\n <mat-icon [class]=\"sort.direction === SortDirection.asc ? 'light-arrow' : 'dark-arrow'\" class=\"up-down-icon\">\r\n arrow_downward\r\n </mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n </div>\r\n\r\n <!-- Default Not Sorted Text -->\r\n @if(!notSorted.length){\r\n <div class=\"tip\" >\r\n Not Sorted List\r\n </div>\r\n }\r\n\r\n <!-- Not Sorted Menu List -->\r\n <div class=\"list\"\r\n cdkDropList\r\n #notSortedGroup=\"cdkDropList\"\r\n [cdkDropListConnectedTo]=\"[sortedGroup]\"\r\n [cdkDropListData]=\"notSorted\"\r\n (cdkDropListDropped)=\"dropIntoNotSorted($event)\">\r\n @for (sort of notSorted; track sort.active) {\r\n <div mat-menu-item class=\"menu-item\" cdkDrag>\r\n <span class=\"not-sorted-name\">{{sort.displayName || (sort.active | spaceCase)}}</span>\r\n </div>\r\n }\r\n </div>\r\n</mat-menu>\r\n", styles: [".cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.list{padding:5px 2px;border-bottom:solid 1px #ccc;color:#000000de;background:#fff}.light-arrow{color:#93b1ea78}.dark-arrow{color:#224e9c}.up-down-button{background-color:#fff;border-radius:30%;border-color:#0ff;padding:1px 1px 0;border-width:.5px;cursor:pointer;height:27px}.mat-icon.up-down-icon{margin-right:0;font-size:20px;font-weight:lighter}.sort-item{display:flex;align-items:center;justify-content:space-between}.up-down-buttons-wrapper{margin-left:2rem}.up-button{margin-right:.3rem}.mat-mdc-menu-item.menu-item,.mat-mdc-menu-item.menu-button{min-height:initial;padding:0 3px;line-height:25px;height:30px}.mat-mdc-menu-item.menu-item{cursor:move}.sorted-name{color:#224e9c;font-size:17px;font-weight:700}.not-sorted-name{color:#93b1ea;font-size:17px;font-weight:700}.apply-border{border:#224e9c solid .5px}.apply-border:hover{background-color:#faebd7}.apply-button-wrapper{display:grid;justify-content:center}.sort-header{font-size:10px;font-style:italic}.tip{padding:0 3px;color:#d3d3d3}.direction-text{font-size:small;font-weight:400}.close-button-wrapper{display:flex;flex-direction:row-reverse}\n"] }]
4356
- }] });
4357
4416
 
4358
- class PaginatorComponent {
4359
- state = inject(TableStore);
4360
- data = inject(DataStore);
4361
- $paginator = viewChild(MatPaginator);
4362
- $dataLength = this.data.selectSignal(d => d.dataLen);
4363
- pageEvent$ = toObservable(this.$paginator).pipe(notNull(), switchMap(p => p.page));
4364
- $pageEvent = toSignal(this.pageEvent$);
4365
- $pageIndexChangeEvent = computed(() => this.$pageEvent()?.pageIndex);
4366
- $pageSizeChangeEvent = computed(() => this.$pageEvent()?.pageSize);
4367
- $currentPageData = computed(() => {
4368
- const pageEvent = this.$pageEvent();
4369
- if (!pageEvent)
4370
- return;
4371
- const paginator = this.$paginator();
4372
- // Reset because initial page event does not have page length
4373
- pageEvent.pageIndex = paginator.pageIndex;
4374
- pageEvent.pageSize = paginator.pageSize;
4375
- pageEvent.length = paginator.length;
4376
- const pageDetails = mapPaginationEventToCurrentPageDetails(pageEvent);
4377
- const dataLength = this.$dataLength();
4378
- return ({ ...pageDetails, total: dataLength });
4379
- });
4380
- onPageIndexEffect = effect(() => {
4381
- const index = this.$pageIndexChangeEvent();
4382
- if (index === undefined)
4383
- return;
4384
- untracked(() => this.state.setCurrentPage(index));
4385
- });
4386
- onPageSizeEffect = effect(() => {
4387
- const size = this.$pageSizeChangeEvent();
4388
- const initialized = this.state.$initializationState() >= InitializationState.Ready;
4389
- if (!size || !initialized)
4390
- return;
4391
- untracked(() => this.state.setUserDefinedPageSize(size));
4392
- });
4393
- onMetaPageSizeEffect = effect(() => {
4394
- const paginator = this.$paginator();
4395
- if (!paginator)
4396
- return;
4417
+ function getGroupedData(data, groupByKeys) {
4418
+ return tbGroupBy(data, groupByKeys);
4419
+ }
4420
+ const tbGroupBy = (data, groupByKeys, parentGroupName) => {
4421
+ const currentKey = groupByKeys[0];
4422
+ const res = groupBy(data, currentKey);
4423
+ const remainingGroupByKeys = groupByKeys.slice(1);
4424
+ const finalGroups = !remainingGroupByKeys.length;
4425
+ if (remainingGroupByKeys.length) {
4426
+ Object.keys(res).forEach(key => res[key] = tbGroupBy(res[key], remainingGroupByKeys, key));
4427
+ }
4428
+ return Object.keys(res).map((groupName, i) => {
4429
+ const uniqName = parentGroupName ? `${parentGroupName}-${groupName}` : `${groupName}`;
4430
+ const groupHeaders = res[groupName]?.filter(row => row.isGroupHeader) ?? [];
4431
+ return {
4432
+ isGroupHeader: true,
4433
+ groupHeaderDisplay: groupName,
4434
+ hasTheData: finalGroups,
4435
+ children: finalGroups ? res[groupName] : res[groupName].map(d => { d.padding += 20; return d; }),
4436
+ groupName: `tb_group_${uniqName}`,
4437
+ padding: 1,
4438
+ key: currentKey,
4439
+ length: groupHeaders.reduce((acc, curr) => curr.length + acc, 0) + ((res[groupName] ?? []).length - groupHeaders.length),
4440
+ [initIndexSymbol]: uniqName,
4441
+ };
4442
+ });
4443
+ };
4444
+ function updateGroupByState({ groupedData }, [data, groups, expandedGroups], index) {
4445
+ if (index === 0
4446
+ || dataUpdated(data, groups, expandedGroups)
4447
+ || groupsUpdated(groups, expandedGroups)) {
4448
+ groupedData = groups.value.length ? getGroupedData(data.value, groups.value) : data.value;
4449
+ }
4450
+ const newDisplayData = expandedGroups.value.length === 0
4451
+ ? groupedData
4452
+ : groupedData.map(group => mapGroupHeader(group, expandedGroups.value)).flat();
4453
+ return ({ displayData: newDisplayData, groupedData });
4454
+ }
4455
+ function mapGroupHeader(obj, data) {
4456
+ const showChildren = data.find(a => a.expandedHeaders.includes(obj.groupName));
4457
+ const children = !showChildren ? [] :
4458
+ obj.hasTheData ? obj.children
4459
+ : obj.children.map(a => mapGroupHeader(a, data));
4460
+ return [obj, ...children].flat();
4461
+ }
4462
+ function dataUpdated(data, groups, expandedGroups) {
4463
+ return data.timestamp > groups.timestamp && data.timestamp > expandedGroups.timestamp;
4464
+ }
4465
+ function groupsUpdated(groups, expandedGroups) {
4466
+ return groups.timestamp > expandedGroups.timestamp;
4467
+ }
4468
+ ;
4469
+ const initialGroupByState = { displayData: [], groupedData: [] };
4470
+ const getAllGroupHeaderNames = (data) => {
4471
+ const groups = getGroupHeaders(data, (d) => d.isGroupHeader);
4472
+ return groupBy(groups, 'key');
4473
+ };
4474
+ const getAllGroupHeaderNamesByKeys = (data, keys) => {
4475
+ const groups = getGroupHeaders(data, (d) => d.isGroupHeader && keys.includes(d.key));
4476
+ return groupBy(groups, 'key');
4477
+ };
4478
+ const getGroupHeaders = (data, filterFunc, arr = []) => {
4479
+ const headers = data.filter(filterFunc);
4480
+ arr.push(...headers);
4481
+ headers.forEach(h => { if (!!h.children.length)
4482
+ getGroupHeaders(h.children, filterFunc, arr); });
4483
+ return arr;
4484
+ };
4485
+
4486
+ function sortData(data, sorted) {
4487
+ const ordered = orderBy(data, sorted.map(r => r.active), sorted.map(r => r.direction));
4488
+ return ordered;
4489
+ }
4490
+ function filterData(data, filters, resetAll = false) {
4491
+ for (let index = 0; index < data.length; index++) {
4492
+ const element = data[index];
4493
+ const hide = !filters.every(filter => filter(element));
4494
+ if (hide || resetAll) {
4495
+ element[tbNoShowSymbol] = hide;
4496
+ }
4497
+ }
4498
+ return data;
4499
+ }
4500
+ const tbNoShowSymbol = Symbol('tb_no_show');
4501
+
4502
+ const sortAndFilterData = (data, sortState, filterState) => combineLatest([
4503
+ data.pipe(timestamp()),
4504
+ sortState.pipe(timestamp()),
4505
+ filterState.pipe(timestamp())
4506
+ ]).pipe(scan(({ mappedData: resultData }, [data, sort, f], index) => {
4507
+ if (index === 0 || (data.timestamp > sort.timestamp && data.timestamp > f.timestamp)) {
4508
+ return ({ mappedData: filterData(sortData(data.value, sort.value.sortsToRun), f.value.allFilters) });
4509
+ }
4510
+ if (sort.timestamp > f.timestamp) {
4511
+ return ({ mappedData: sortData(resultData, sort.value.sortsToRun) });
4512
+ }
4513
+ return ({ mappedData: filterData(resultData, f.value.onlyAddedFilters || f.value.allFilters, !f.value.onlyAddedFilters) });
4514
+ }, { mappedData: [] })).pipe(map$1(({ mappedData: resultData }) => resultData.filter(item => !item[tbNoShowSymbol])), defaultShareReplay());
4515
+ const createDataCleaners = (metadatas, mutate = false) => {
4516
+ const transforms = createCleaners(metadatas);
4517
+ return (data) => {
4518
+ if (!mutate) {
4519
+ data = { ...data };
4520
+ }
4521
+ for (const transform of transforms) {
4522
+ transform(data);
4523
+ }
4524
+ return data;
4525
+ };
4526
+ };
4527
+ const createCleaners = (metadatas) => {
4528
+ return metadatas.reduce((transforms, metaData) => {
4529
+ const notNestedKey = metaData.key;
4530
+ switch (metaData.fieldType) {
4531
+ case FieldType.Currency:
4532
+ case FieldType.Number: {
4533
+ const nested = metaData.key.includes('.');
4534
+ if (nested) {
4535
+ transforms.push((t) => {
4536
+ const val = get(t, metaData.key);
4537
+ const num = Number(val);
4538
+ set(t, metaData.key, isNaN(num) || val == null ? null : num);
4539
+ });
4540
+ }
4541
+ else {
4542
+ transforms.push((t) => {
4543
+ const val = t[notNestedKey];
4544
+ const num = Number(val);
4545
+ t[notNestedKey] = (isNaN(num) || val == null ? null : num);
4546
+ });
4547
+ }
4548
+ break;
4549
+ }
4550
+ case FieldType.Date: {
4551
+ const nested = metaData.key.includes('.');
4552
+ if (nested) {
4553
+ transforms.push((t) => {
4554
+ const val = get(t, metaData.key);
4555
+ const date = Date.parse(val);
4556
+ if (isNaN(date)) {
4557
+ set(t, metaData.key, null);
4558
+ return;
4559
+ }
4560
+ const d = new Date(date);
4561
+ d.setHours(0, 0, 0, 0);
4562
+ set(t, metaData.key, d);
4563
+ });
4564
+ }
4565
+ else {
4566
+ transforms.push((t) => {
4567
+ const val = t[notNestedKey];
4568
+ const date = Date.parse(val);
4569
+ if (isNaN(date)) {
4570
+ t[notNestedKey] = null;
4571
+ return;
4572
+ }
4573
+ const d = new Date(date);
4574
+ d.setHours(0, 0, 0, 0);
4575
+ t[notNestedKey] = d;
4576
+ });
4577
+ }
4578
+ break;
4579
+ }
4580
+ case FieldType.DateTime: {
4581
+ const nested = metaData.key.includes('.');
4582
+ if (nested) {
4583
+ transforms.push((t) => {
4584
+ const val = get(t, metaData.key);
4585
+ const dateTime = Date.parse(val);
4586
+ if (isNaN(dateTime)) {
4587
+ set(t, metaData.key, null);
4588
+ return;
4589
+ }
4590
+ const dt = new Date(dateTime);
4591
+ if (metaData.additional?.dateTimeOptions?.includeMilliseconds) {
4592
+ set(t, metaData.key, dt);
4593
+ return;
4594
+ }
4595
+ if (metaData.additional?.dateTimeOptions?.includeSeconds) {
4596
+ dt.setMilliseconds(0);
4597
+ set(t, metaData.key, dt);
4598
+ return;
4599
+ }
4600
+ dt.setSeconds(0, 0);
4601
+ set(t, metaData.key, dt);
4602
+ });
4603
+ }
4604
+ else {
4605
+ transforms.push((t) => {
4606
+ const val = t[notNestedKey];
4607
+ const dateTime = Date.parse(val);
4608
+ if (isNaN(dateTime)) {
4609
+ t[notNestedKey] = null;
4610
+ return;
4611
+ }
4612
+ const dt = new Date(dateTime);
4613
+ if (metaData.additional?.dateTimeOptions?.includeMilliseconds) {
4614
+ t[notNestedKey] = dt;
4615
+ return;
4616
+ }
4617
+ if (metaData.additional?.dateTimeOptions?.includeSeconds) {
4618
+ dt.setMilliseconds(0);
4619
+ t[notNestedKey] = dt;
4620
+ return;
4621
+ }
4622
+ dt.setSeconds(0, 0);
4623
+ t[notNestedKey] = dt;
4624
+ });
4625
+ }
4626
+ }
4627
+ }
4628
+ return transforms;
4629
+ }, []);
4630
+ };
4631
+
4632
+ class PaginatorComponent {
4633
+ state = inject(TableStore);
4634
+ data = inject(DataStore);
4635
+ $paginator = viewChild(MatPaginator);
4636
+ $dataLength = this.data.selectSignal(d => d.sortedFilteredDataLength);
4637
+ pageEvent$ = toObservable(this.$paginator).pipe(notNull(), switchMap(p => p.page));
4638
+ $pageEvent = toSignal(this.pageEvent$);
4639
+ $pageIndexChangeEvent = computed(() => this.$pageEvent()?.pageIndex);
4640
+ $pageSizeChangeEvent = computed(() => this.$pageEvent()?.pageSize);
4641
+ $currentPageData = computed(() => {
4642
+ const pageEvent = this.$pageEvent();
4643
+ if (!pageEvent)
4644
+ return;
4645
+ const paginator = this.$paginator();
4646
+ // Reset because initial page event does not have page length
4647
+ pageEvent.pageIndex = paginator.pageIndex;
4648
+ pageEvent.pageSize = paginator.pageSize;
4649
+ pageEvent.length = paginator.length;
4650
+ const pageDetails = mapPaginationEventToCurrentPageDetails(pageEvent);
4651
+ const dataLength = this.$dataLength();
4652
+ return ({ ...pageDetails, total: dataLength });
4653
+ });
4654
+ onPageIndexEffect = effect(() => {
4655
+ const index = this.$pageIndexChangeEvent();
4656
+ if (index === undefined)
4657
+ return;
4658
+ untracked(() => this.state.setCurrentPage(index));
4659
+ });
4660
+ onPageSizeEffect = effect(() => {
4661
+ const size = this.$pageSizeChangeEvent();
4662
+ const initialized = this.state.$initializationState() >= InitializationState.Ready;
4663
+ if (!size || !initialized)
4664
+ return;
4665
+ untracked(() => this.state.setUserDefinedPageSize(size));
4666
+ });
4667
+ onMetaPageSizeEffect = effect(() => {
4668
+ const paginator = this.$paginator();
4669
+ if (!paginator)
4670
+ return;
4397
4671
  const metaPageSize = this.state.$pageSize();
4398
- untracked(() => paginator._changePageSize(metaPageSize));
4672
+ const initialized = this.state.$initializationState() >= InitializationState.Ready;
4673
+ untracked(() => initialized && paginator._changePageSize(metaPageSize));
4399
4674
  });
4400
4675
  onDataLengthEffect = effect(() => {
4401
4676
  const paginator = this.$paginator();
@@ -4425,7 +4700,7 @@ class PaginatorComponent {
4425
4700
  </mat-paginator>
4426
4701
  @if ($showAllOption()) {<button mat-button (click)="showAll()"><span [style.text-decoration]="$showAll() ? 'line-through' : ''" >All</span></button>}
4427
4702
  </div>
4428
- `, isInline: true, styles: [":host{--mat-paginator-container-size: initial}.select-column{min-width:var(--tb-min-select-column-width, 42px)}.index-column{min-width:var(--tb-min-index-column-width, 42px)}.mat-mdc-row:nth-child(odd){background-color:var(--tb-odd-row-background-color, #cdeefe)}.page-amounts{color:#0000008a;font-family:Roboto,Helvetica Neue,sans-serif;font-size:12px;margin-right:.2rem}:host::ng-deep .table-drag-list.cdk-drop-list-dragging .drag-header:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}:host::ng-deep .mdc-data-table__cell,:host::ng-deep .mdc-data-table__header-cell{padding:var(--tb-cell-padding, 0 0 0 .2rem);line-height:var(--tb-cell-line-height, normal)}::ng-deep .op-date-time-input{line-height:3rem;font-size:.9rem;font-family:Roboto,Helvetica Neue,sans-serif;padding-left:.2rem;width:12rem}\n", ".collapse-icon{font-size:16px;height:16px;color:#3f51b5;align-self:flex-start}.collapse-icon:hover{cursor:pointer}.hide{display:none}.paginator-row{display:flex;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i1$6.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4703
+ `, isInline: true, styles: [":host{--mat-paginator-container-size: initial}.select-column{min-width:var(--tb-min-select-column-width, 42px)}.index-column{min-width:var(--tb-min-index-column-width, 42px)}.mat-mdc-row:nth-child(odd){background-color:var(--tb-odd-row-background-color, #cdeefe)}.page-amounts{color:#0000008a;font-family:Roboto,Helvetica Neue,sans-serif;font-size:12px;margin-right:.2rem}:host::ng-deep .table-drag-list.cdk-drop-list-dragging .drag-header:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}:host::ng-deep .mdc-data-table__cell,:host::ng-deep .mdc-data-table__header-cell{padding:var(--tb-cell-padding, 0 0 0 .2rem);line-height:var(--tb-cell-line-height, normal)}::ng-deep .op-date-time-input{line-height:3rem;font-size:.9rem;font-family:Roboto,Helvetica Neue,sans-serif;padding-left:.2rem;width:12rem}\n", ".collapse-icon{font-size:16px;height:16px;color:#3f51b5;align-self:flex-start}.collapse-icon:hover{cursor:pointer}.hide{display:none}.paginator-row{display:flex;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i1$7.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4429
4704
  }
4430
4705
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: PaginatorComponent, decorators: [{
4431
4706
  type: Component,
@@ -4449,251 +4724,96 @@ const mapPaginationEventToCurrentPageDetails = (pageData) => ({
4449
4724
  total: pageData.length
4450
4725
  });
4451
4726
 
4452
- class TableVirtualScrollStrategy {
4453
- itemHeight;
4454
- headerHeight;
4455
- scrolledIndexChange;
4456
- dataLength = 0;
4457
- indexChange = new Subject();
4458
- viewport;
4459
- constructor(itemHeight, headerHeight) {
4460
- this.itemHeight = itemHeight;
4461
- this.headerHeight = headerHeight;
4462
- this.scrolledIndexChange = this.indexChange.pipe(distinctUntilChanged());
4463
- }
4464
- attach(viewport) {
4465
- this.viewport = viewport;
4466
- this.onDataLengthChanged();
4467
- }
4468
- contentScrolled$ = new Subject();
4469
- sub = subscriber(this.contentScrolled$.pipe(observeOn(animationFrameScheduler)), () => {
4470
- this.updateContent();
4727
+ class TableBuilderDataSource extends MatTableDataSource {
4728
+ subscription;
4729
+ #$dataSrc = signal([]);
4730
+ $dataSize = signal({ start: 0, end: 0 }, {
4731
+ equal: (a, b) => a.start === b.start && a.end === b.end
4471
4732
  });
4472
- onContentScrolled() {
4473
- this.contentScrolled$.next();
4474
- }
4475
- onDataLengthChanged() {
4476
- if (this.viewport) {
4477
- this.viewport.setTotalContentSize(this.dataLength * this.itemHeight);
4478
- this.updateContent();
4479
- }
4480
- }
4481
- setDataLength(length) {
4482
- this.dataLength = length;
4483
- this.onDataLengthChanged();
4484
- }
4485
- detach() { }
4486
- onContentRendered() { }
4487
- onRenderedOffsetChanged() {
4488
- }
4489
- scrollToIndex(index, behavior) {
4490
- }
4491
- updateContent() {
4492
- if (!this.viewport) {
4493
- return;
4494
- }
4495
- const amountOfRows = Math.ceil((this.viewport.getViewportSize() - this.headerHeight) / this.itemHeight);
4496
- const offset = this.viewport.measureScrollOffset();
4497
- const buffer = 35;
4498
- const skip = Math.round(offset / this.itemHeight);
4499
- // always start at an even index so we don't change the color patterns for odd and even rows.
4500
- const index = skip % 2 === 0 ? skip : skip - 1;
4501
- const start = Math.max(0, index - buffer);
4502
- const end = Math.min(this.dataLength, index + amountOfRows + buffer);
4503
- this.viewport.setRenderedContentOffset(this.itemHeight * start);
4504
- this.viewport.setRenderedRange({ start, end });
4505
- this.indexChange.next(index);
4506
- }
4507
- }
4508
-
4509
- class VirtualScrollContainer {
4510
- state = inject(TableStore);
4511
- dataStore = inject(DataStore);
4512
- viewport = viewChild(CdkVirtualScrollViewport);
4513
- genericTable = contentChild(GenericTableComponent);
4514
- tableContainer = inject(TableContainerComponent);
4515
- defaultOptions = new VirtualScrollOptions();
4516
- scrollStrategy = new TableVirtualScrollStrategy(this.computedRowHeight(), this.computedHeaderHeight());
4517
- $usePaginator = this.state.selectSignal(s => s.notPersistedTableSettings.usePaginator);
4518
- $pageSize = this.state.$pageSize;
4519
- $currentPage = this.state.$currentPage;
4520
- $showAll = this.state.selectSignal(s => s.showAll);
4521
- $stateDataLength = this.dataStore.selectSignal(s => s.dataLen);
4522
- viewPort$ = toObservable(this.viewport).pipe(notNull());
4523
- $scrolledIndexChange = toSignal(this.viewPort$.pipe(switchMap$1(v => v.scrolledIndexChange)));
4524
- $renderedRange = toSignal(this.viewPort$.pipe(switchMap$1(v => v.renderedRangeStream)));
4525
- $virtualScrollOptions = computed(() => this.state.$tableSettings().virtualSettings);
4526
- $dataLength = computed(() => {
4527
- const paginated = this.$usePaginator() && !this.$showAll();
4528
- const pageSize = this.$pageSize();
4529
- const pageNumber = this.$currentPage();
4530
- const dataLen = this.$stateDataLength();
4531
- if (paginated)
4532
- return Math.min(dataLen - (pageNumber * pageSize), pageSize);
4533
- return dataLen;
4733
+ _ = effect(() => {
4734
+ const data = this.#$dataSrc();
4735
+ const dataSize = this.$dataSize();
4736
+ untracked(() => this.data = data.slice(dataSize.start, dataSize.end));
4534
4737
  });
4535
- constructor() {
4536
- addEventListener('resize', this.resizeHandler);
4738
+ setData(data) {
4739
+ this.#$dataSrc.set(data);
4537
4740
  }
4538
- setViewportEffect = effect(() => {
4539
- const viewport = this.viewport();
4540
- untracked(() => {
4541
- if (!!viewport) {
4542
- this.setSize(this.viewport().elementRef);
4741
+ constructor(state, data) {
4742
+ super([]);
4743
+ const $currentPage = state.$currentPage;
4744
+ const $pageSize = state.$pageSize;
4745
+ const $virtualEnds = data.selectSignal(d => d.virtualEnds);
4746
+ const $dataLength = computed(() => this.#$dataSrc().length);
4747
+ const $dataSize = computed(() => {
4748
+ const viewType = state.$viewType();
4749
+ const dataLength = $dataLength();
4750
+ const currentPage = $currentPage();
4751
+ const pageSize = $pageSize();
4752
+ const virtualEnds = $virtualEnds();
4753
+ const previousPageRecords = currentPage * pageSize;
4754
+ if (viewType === 'virtual paginator') {
4755
+ return ({ start: virtualEnds.start + previousPageRecords, end: Math.min(virtualEnds.end, pageSize) + previousPageRecords });
4543
4756
  }
4544
- ;
4545
- });
4546
- });
4547
- subscriber = subscriber();
4548
- onRenderedRangeEffect = effect(() => {
4549
- const renderedRange = this.$renderedRange();
4550
- if (!renderedRange)
4551
- return;
4552
- untracked(() => {
4553
- this.dataStore.patchState({
4554
- virtualEnds: {
4555
- start: renderedRange.start,
4556
- end: renderedRange.end + 25,
4557
- }
4558
- });
4559
- this.setSize(this.viewport().elementRef);
4560
- });
4561
- });
4562
- onDataLengthEffect = effect(() => {
4563
- const dataLength = this.$dataLength();
4564
- untracked(() => {
4565
- this.scrollStrategy.setDataLength(dataLength);
4566
- });
4567
- });
4568
- onOffsetEffect = effect(() => {
4569
- const offset = this.$offset();
4570
- untracked(() => {
4571
- this.dataStore.patchState({ virtualScrollOffset: offset });
4757
+ if (viewType === 'paginator') {
4758
+ return ({ start: previousPageRecords, end: previousPageRecords + pageSize });
4759
+ }
4760
+ if (viewType === 'all') {
4761
+ return ({ start: 0, end: dataLength });
4762
+ }
4763
+ return ({ start: virtualEnds.start, end: virtualEnds.end });
4572
4764
  });
4573
- });
4574
- $offset = computed(() => {
4575
- const viewport = this.viewport();
4576
- const scrolledIndexChange = this.$scrolledIndexChange();
4577
- if (!scrolledIndexChange || !viewport)
4578
- return 0;
4579
- return viewport.getOffsetToRenderedContentStart() ?? 0;
4580
- });
4581
- ngOnDestroy() {
4582
- removeEventListener('resize', this.resizeHandler);
4583
- }
4584
- setSize(el) {
4585
- const virtualScrollOptions = this.$virtualScrollOptions();
4586
- if (virtualScrollOptions.dynamicHeight) {
4587
- this.calcDynamic(el);
4588
- return;
4589
- }
4590
- const rowHeight = this.computedRowHeight();
4591
- let amountOfVisibleItems = virtualScrollOptions?.amountOfVisibleItems || this.defaultOptions.amountOfVisibleItems;
4592
- amountOfVisibleItems = Math.min(amountOfVisibleItems, this.$dataLength());
4593
- let height = (rowHeight * amountOfVisibleItems);
4594
- const footerHeight = this.computedFooterHeight();
4595
- const headerHeight = this.computedHeaderHeight();
4596
- height += (footerHeight + headerHeight);
4597
- if (virtualScrollOptions?.maxViewPortHeight && virtualScrollOptions.maxViewPortHeight < height)
4598
- height = virtualScrollOptions.maxViewPortHeight;
4599
- this.setHeight(height, el);
4600
- }
4601
- calcDynamic$ = new Subject();
4602
- $calcDynamic = toSignal(this.calcDynamic$.pipe(debounceTime(300)));
4603
- #onCalcDynamicEffect = effect(() => {
4604
- const el = this.$calcDynamic();
4605
- if (!el)
4606
- return;
4607
- this.calcDynamic(el);
4608
- });
4609
- calcDynamic(el) {
4610
- const virtualScrollOptions = this.$virtualScrollOptions();
4611
- const t = this.tableContainer.elementRef.nativeElement.querySelector(`#${TableContainerComponent.headerId}`);
4612
- const rect = t?.getBoundingClientRect();
4613
- const viewportHeight = window.innerHeight;
4614
- const distanceFromBottom = viewportHeight - rect.bottom;
4615
- const rowHeight = this.computedRowHeight();
4616
- const footerHeight = this.computedFooterHeight();
4617
- const headerHeight = this.computedHeaderHeight();
4618
- let tableSize = distanceFromBottom;
4619
- if (virtualScrollOptions?.maxViewPortHeight && virtualScrollOptions.maxViewPortHeight < tableSize) {
4620
- tableSize = virtualScrollOptions.maxViewPortHeight;
4621
- }
4622
- const available = (distanceFromBottom - footerHeight) - headerHeight;
4623
- const amountOfRowsThatWillFit = Math.floor(available / rowHeight);
4624
- const minAmountOfRows = virtualScrollOptions?.amountOfVisibleItems || this.defaultOptions.amountOfVisibleItems;
4625
- const amountOfVisibleItems = Math.min(Math.max(amountOfRowsThatWillFit, minAmountOfRows), this.$dataLength());
4626
- let height = (rowHeight * amountOfVisibleItems);
4627
- height += (footerHeight + headerHeight) - 10;
4628
- this.setHeight(height, el);
4765
+ this.$dataSize = $dataSize;
4629
4766
  }
4630
- setHeight(height, el) {
4631
- const vsViewport = el.nativeElement;
4632
- vsViewport.setAttribute('style', `height: ${height}px !important;`);
4633
- this.viewport()?.checkViewportSize();
4634
- const virtualScrollOffset = this.viewport()?.getOffsetToRenderedContentStart() ?? 0;
4635
- this.dataStore.patchState({ virtualScrollOffset });
4767
+ connect() {
4768
+ return super.connect();
4636
4769
  }
4637
- resizeHandler = () => {
4638
- if (this.viewport() && this.$virtualScrollOptions().dynamicHeight) {
4639
- this.setSize(this.viewport().elementRef);
4770
+ disconnect() {
4771
+ if (this.subscription) {
4772
+ this.subscription.unsubscribe();
4773
+ this.subscription = undefined;
4640
4774
  }
4641
- };
4642
- computedRowHeight() {
4643
- const virtualScrollOptions = this.state.$tableSettings().virtualSettings;
4644
- const rowHeight = virtualScrollOptions?.rowHeight || (typeof this.state.$tableSettings().rowHeight === 'number' && this.state.$tableSettings().rowHeight) || this.defaultOptions.rowHeight;
4645
- return rowHeight;
4646
- }
4647
- computedHeaderHeight() {
4648
- if (this.state.$tableSettings().hideHeader)
4649
- return 0;
4650
- const virtualScrollOptions = this.state.$tableSettings().virtualSettings;
4651
- const headerHeight = virtualScrollOptions?.headerHeight || (typeof this.state.$tableSettings().headerHeight === 'number' && this.state.$tableSettings().headerHeight) || this.defaultOptions.headerHeight;
4652
- return headerHeight;
4775
+ super.disconnect();
4653
4776
  }
4654
- computedFooterHeight() {
4655
- return parseFloat(this.genericTable()?.$footerHeight()?.replace('px', '') || '0');
4777
+ }
4778
+
4779
+ function mergeCustomCellMetaData(metaData1, metaData2) {
4780
+ if (!metaData2) {
4781
+ metaData1.noExport = true;
4782
+ return metaData1;
4656
4783
  }
4657
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: VirtualScrollContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
4658
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.0.0", type: VirtualScrollContainer, isStandalone: true, selector: "tb-virtual-scroll-container", queries: [{ propertyName: "genericTable", first: true, predicate: GenericTableComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: `
4659
- <cdk-virtual-scroll-viewport>
4660
- <ng-content/>
4661
- </cdk-virtual-scroll-viewport>
4662
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: ScrollingModule }, { kind: "component", type: i1$7.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }], viewProviders: [
4663
- {
4664
- provide: VIRTUAL_SCROLL_STRATEGY,
4665
- useFactory: (c) => c.scrollStrategy,
4666
- deps: [forwardRef(() => VirtualScrollContainer)],
4667
- },
4668
- ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4784
+ if (!metaData1.displayName)
4785
+ metaData1.displayName = metaData2.displayName;
4786
+ if (!metaData1.preSort)
4787
+ metaData1.preSort = metaData2.preSort;
4788
+ if (!metaData1.order)
4789
+ metaData1.order = metaData2.order;
4790
+ if (!metaData1.width)
4791
+ metaData1.width = metaData2.width;
4792
+ if (metaData2.fieldType)
4793
+ metaData1.fieldType = metaData2.fieldType;
4794
+ metaData1.noExport = metaData2.noExport;
4795
+ return ({ ...metaData2, ...metaData1 });
4669
4796
  }
4670
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: VirtualScrollContainer, decorators: [{
4797
+
4798
+ class GroupByListComponent {
4799
+ tableStore = inject(TableStore);
4800
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GroupByListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4801
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: GroupByListComponent, isStandalone: true, selector: "group-by-list", ngImport: i0, template: "<mat-chip-set>\r\n <span class=\"tb-group-label\">Group By:</span>\r\n @for (groupByKey of tableStore.$groupByKeys(); track groupByKey) {\r\n @if($index > 0){\r\n <mat-icon class=\"nested-arrow\">arrow_right</mat-icon>\r\n }\r\n <mat-chip (removed)=\"tableStore.removeGroupByKey(groupByKey)\">\r\n {{groupByKey | spaceCase}}\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n</mat-chip-set>\r\n", styles: [".tb-group-label{padding-right:5px}.nested-arrow{margin-right:-8px;margin-left:-8px}\n"], dependencies: [{ kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i4$2.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i4$2.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i4$2.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4802
+ }
4803
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GroupByListComponent, decorators: [{
4671
4804
  type: Component,
4672
- args: [{
4673
- selector: 'tb-virtual-scroll-container',
4674
- template: `
4675
- <cdk-virtual-scroll-viewport>
4676
- <ng-content/>
4677
- </cdk-virtual-scroll-viewport>
4678
- `,
4679
- changeDetection: ChangeDetectionStrategy.OnPush,
4680
- imports: [ScrollingModule],
4681
- viewProviders: [
4682
- {
4683
- provide: VIRTUAL_SCROLL_STRATEGY,
4684
- useFactory: (c) => c.scrollStrategy,
4685
- deps: [forwardRef(() => VirtualScrollContainer)],
4686
- },
4687
- ],
4688
- }]
4689
- }], ctorParameters: () => [] });
4805
+ args: [{ selector: 'group-by-list', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
4806
+ MatChipsModule, MatIconModule, SpaceCasePipe
4807
+ ], template: "<mat-chip-set>\r\n <span class=\"tb-group-label\">Group By:</span>\r\n @for (groupByKey of tableStore.$groupByKeys(); track groupByKey) {\r\n @if($index > 0){\r\n <mat-icon class=\"nested-arrow\">arrow_right</mat-icon>\r\n }\r\n <mat-chip (removed)=\"tableStore.removeGroupByKey(groupByKey)\">\r\n {{groupByKey | spaceCase}}\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n</mat-chip-set>\r\n", styles: [".tb-group-label{padding-right:5px}.nested-arrow{margin-right:-8px;margin-left:-8px}\n"] }]
4808
+ }] });
4690
4809
 
4691
4810
  class ProfilesMenuComponent {
4692
4811
  stateService = inject(TableBuilderStateStore);
4693
4812
  tableStore = inject(TableStore);
4694
- $tableId = input.required();
4695
- onSaveState = output();
4813
+ $tableId = input.required({ alias: 'tableId' });
4814
+ $isMatMenuChild = input(false, { alias: 'isMatMenuChild' });
4696
4815
  trigger = viewChild('trigger');
4816
+ menu = viewChild.required(MatMenu);
4697
4817
  allProfilesPanelOpened = signal(false);
4698
4818
  newProfilePanelOpened = signal(false);
4699
4819
  $currentProfile = computed(() => this.stateService.$selectLocalProfileCurrentKey(this.$tableId())());
@@ -4701,7 +4821,6 @@ class ProfilesMenuComponent {
4701
4821
  $keys = computed(() => this.stateService.$selectLocalProfileKeys(this.$tableId())());
4702
4822
  saveState(key) {
4703
4823
  const tableState = this.tableStore.$savableState();
4704
- this.onSaveState.emit(null);
4705
4824
  this.stateService.saveTableSettingsToLocalAndStorage(this.$tableId(), key, tableState);
4706
4825
  }
4707
4826
  addState(key, asDefault) {
@@ -4727,411 +4846,507 @@ class ProfilesMenuComponent {
4727
4846
  return a;
4728
4847
  };
4729
4848
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ProfilesMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4730
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: ProfilesMenuComponent, isStandalone: true, selector: "tb-profiles-menu", inputs: { $tableId: { classPropertyName: "$tableId", publicName: "$tableId", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onSaveState: "onSaveState" }, viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: "<button mat-icon-button [matMenuTriggerFor]=\"menu\" #trigger=\"matMenuTrigger\" [matTooltip]=\"'Profiles'\">\r\n <mat-icon color=\"primary\">people</mat-icon>\r\n</button>\r\n<mat-menu #menu=\"matMenu\" (closed)=\"addedKey.value = null; allProfilesPanelOpened.set(false); newProfilePanelOpened.set(false)\">\r\n @if(!!$currentProfile())\r\n {\r\n <div mat-menu-item [matTooltip]=\"'Save Profile'\" mat-stroked-button (click)=\"saveState($currentProfile()!)\">\r\n <mat-icon color=\"primary\">save</mat-icon>\r\n <span>{{$currentProfile()}}</span>\r\n </div>\r\n }\r\n @else\r\n {\r\n <div class=\"profile-line\">\r\n <button class=\"first-in-line first-button\" mat-stroked-button (click)=\"addState(defaultName, m.checked);\">\r\n <mat-icon class=\"save-for-default-icon button-save-icon\" color=\"primary\">save</mat-icon>\r\n <span>Save as <span class=\"current-name\">{{defaultName}}</span> </span>\r\n </button>\r\n <button [matTooltip]=\"'Toggle Profile Being Created As Default'\" stop-propagation mat-icon-button (click)=\"m.toggle()\" >\r\n <mat-icon style=\"color: green;\">{{m.checked ? 'star' : 'star_border'}}</mat-icon>\r\n </button>\r\n <mat-checkbox class=\"display-none\" [checked]=\"true\" #m />\r\n </div>\r\n }\r\n @if (allProfilesPanelOpened()) {<hr class=\"divider\"/>}\r\n <div [class]=\"{ hide: !$keys().length, 'all-profile-row': true }\" mat-menu-item stop-propagation (click)=\"allProfilesPanelOpened.set(!allProfilesPanelOpened())\">\r\n <div class=\"all-profiles\">\r\n <span>All Profiles</span>\r\n <span [class]=\"(allProfilesPanelOpened() ? 'all-profile-arrow-close' : 'all-profile-arrow-open') + ' all-profile-arrow'\" class=\"arrow\"></span>\r\n </div>\r\n </div>\r\n <div [class]=\"{ hide: !allProfilesPanelOpened(), panel: true }\">\r\n @for (key of $keys() ; track key) {\r\n <div class=\"profile-line\" [class]=\"key === $currentProfile() ? 'current-in-list' : 'not-current-in-list'\">\r\n <button [matTooltip]=\"'Select Profile'\" class=\"menu-item first-in-line\" mat-stroked-button (click)='stateService.setLocalCurrentState({ tableId: $tableId(), currentStateKey: key})'>\r\n <span>{{key}}</span>\r\n </button>\r\n @if(key !== $defaultProfile())\r\n {\r\n <button [matTooltip]=\"'Toggle Profile Being Default'\" stop-propagation mat-icon-button (click)=\"setDefault(key)\">\r\n <mat-icon style=\"color: green;\">star_border</mat-icon>\r\n </button>\r\n }\r\n @else\r\n {\r\n <button [matTooltip]=\"'Toggle Profile Being Default'\" stop-propagation mat-icon-button (click)=\"unsetDefault()\">\r\n <mat-icon style=\"color: green;\">star</mat-icon>\r\n </button>\r\n }\r\n <button [matTooltip]=\"'Delete Profile'\" class=\"last-in-line\" stop-propagation mat-icon-button (click)='stateService.deleteProfileFromLocalAndStorage($tableId(), key)'>\r\n <mat-icon color='warn'>delete_forever</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n <hr class=\"divider\"/>\r\n </div>\r\n <div class=\"add-new-profile-row\" mat-menu-item stop-propagation (click)=\"newProfilePanelOpened.set(!newProfilePanelOpened()); addedKey.focus()\">Add New Profile</div>\r\n <div [class]=\"{ hide: !newProfilePanelOpened(), panel: true }\" >\r\n <div class=\"profile-line\" stop-propagation>\r\n <div class=\"new-name-input\">\r\n <i class=\"input-hint\">Enter New Name</i>\r\n <input matInput #addedKey=\"matInput\" [name]=\"'key'\" />\r\n </div>\r\n <button [matTooltip]=\"'Toggle Profile Being Created As Default'\" stop-propagation mat-icon-button (click)=\"m2.toggle()\" >\r\n <mat-icon style=\"color: green;\">{{m2.checked ? 'star' : 'star_border'}}</mat-icon>\r\n </button>\r\n <mat-checkbox class=\"display-none\" [ngModel]=\"!$defaultProfile()\" #m2 />\r\n </div>\r\n <button class=\"add-button\" color=\"primary\" [matTooltip]=\"'Create New Profile'\" mat-raised-button (click)=\"addState(addedKey.value, m2.checked); addedKey.value = null\" [disabled]=\"!addedKey.value\">\r\n Add\r\n </button>\r\n </div>\r\n</mat-menu>\r\n", styles: [":host ::ng-deep .mat-expansion-panel-header{padding:0}.current-name{color:#00f}.menu-item{display:inline-flex;width:initial;flex-grow:1}.profile-line{display:flex;justify-content:space-between;align-items:center}.first-in-line{--f-b: 2rem;margin-left:var(--mat-menu-item-with-icon-leading-spacing)}.first-in-line.first-button{height:var(--f-b);margin:.2rem}.first-in-line .button-save-icon{height:var(--f-b);width:var(--f-b);font-size:var(--f-b)}.main-save-button{height:4rem;width:4rem;padding:.5rem}.main-save-button mat-icon{height:3rem;width:3rem;font-size:3rem}.save-for-default-icon{margin:0}.display-none{display:none}.last-in-line{padding-right:var(--mat-menu-item-with-icon-trailing-spacing)}.default-cursor{cursor:default}.as-def{padding-left:var(--mat-menu-item-with-icon-leading-spacing)}.divider{margin:.2px 0}.add-key{max-width:8.5rem;margin-left:2px}.add-key ::ng-deep .mdc-text-field{padding:0}.panel{transition:height .1s}.hide{height:0;min-height:0;overflow:hidden}.open-panel-button{width:100%;height:2.5rem}.current-in-list{border-left:3px solid blue;background-color:#0000ff0d}.not-current-in-list{border-left:3px solid rgba(255,255,255,0)}.add-new-profile-row,.all-profile-row{border-top:rgba(128,128,128,.25) solid 1px}.all-profiles{display:flex;justify-content:space-between}.all-profiles:has(.all-profile-arrow-close){align-items:center}.all-profile-arrow{display:inline-block;height:.7rem;width:.7rem;border-color:#000;transform:rotate(-45deg)}.all-profile-arrow-open{border-left:solid 2px;border-bottom:solid 2px}.all-profile-arrow-close{border-right:solid 2px;border-top:solid 2px}.new-name-input{margin-left:3px;display:flex;flex-direction:column}.new-name-input .input-hint{font-size:smaller;font-weight:200;color:gray}.add-button{height:20px;line-height:20px;margin:3px 0 0 3px}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
4849
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: ProfilesMenuComponent, isStandalone: true, selector: "tb-profiles-menu", inputs: { $tableId: { classPropertyName: "$tableId", publicName: "tableId", isSignal: true, isRequired: true, transformFunction: null }, $isMatMenuChild: { classPropertyName: "$isMatMenuChild", publicName: "isMatMenuChild", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "menu", first: true, predicate: MatMenu, descendants: true, isSignal: true }], ngImport: i0, template: "@if(!$isMatMenuChild())\r\n{\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\" #trigger=\"matMenuTrigger\" [matTooltip]=\"'Profiles'\">\r\n <mat-icon color=\"primary\">people</mat-icon>\r\n </button>\r\n}\r\n<mat-menu #menu=\"matMenu\" (closed)=\"addedKey.value = null; allProfilesPanelOpened.set(false); newProfilePanelOpened.set(false)\">\r\n @if(!!$currentProfile())\r\n {\r\n <div mat-menu-item [matTooltip]=\"'Save Profile'\" mat-stroked-button (click)=\"saveState($currentProfile()!)\">\r\n <mat-icon color=\"primary\">save</mat-icon>\r\n <span>{{$currentProfile()}}</span>\r\n </div>\r\n }\r\n @else\r\n {\r\n <div class=\"profile-line\">\r\n <button class=\"first-in-line first-button\" mat-stroked-button (click)=\"addState(defaultName, m.checked);\">\r\n <mat-icon class=\"save-for-default-icon button-save-icon\" color=\"primary\">save</mat-icon>\r\n <span>Save as <span class=\"current-name\">{{defaultName}}</span> </span>\r\n </button>\r\n <button [matTooltip]=\"'Toggle Profile Being Created As Default'\" stop-propagation mat-icon-button (click)=\"m.toggle()\" >\r\n <mat-icon style=\"color: green;\">{{m.checked ? 'star' : 'star_border'}}</mat-icon>\r\n </button>\r\n <mat-checkbox class=\"display-none\" [checked]=\"true\" #m />\r\n </div>\r\n }\r\n @if (allProfilesPanelOpened()) {<hr class=\"divider\"/>}\r\n <div [class]=\"{ hide: !$keys().length, 'all-profile-row': true }\" mat-menu-item stop-propagation (click)=\"allProfilesPanelOpened.set(!allProfilesPanelOpened())\">\r\n <div class=\"all-profiles\">\r\n <span>All Profiles</span>\r\n <span [class]=\"(allProfilesPanelOpened() ? 'all-profile-arrow-close' : 'all-profile-arrow-open') + ' all-profile-arrow'\" class=\"arrow\"></span>\r\n </div>\r\n </div>\r\n <div [class]=\"{ hide: !allProfilesPanelOpened(), panel: true }\">\r\n @for (key of $keys() ; track key) {\r\n <div class=\"profile-line\" [class]=\"key === $currentProfile() ? 'current-in-list' : 'not-current-in-list'\">\r\n <button [matTooltip]=\"'Select Profile'\" class=\"menu-item first-in-line\" mat-stroked-button (click)='stateService.setLocalCurrentState({ tableId: $tableId(), currentStateKey: key})'>\r\n <span>{{key}}</span>\r\n </button>\r\n @if(key !== $defaultProfile())\r\n {\r\n <button [matTooltip]=\"'Toggle Profile Being Default'\" stop-propagation mat-icon-button (click)=\"setDefault(key)\">\r\n <mat-icon style=\"color: green;\">star_border</mat-icon>\r\n </button>\r\n }\r\n @else\r\n {\r\n <button [matTooltip]=\"'Toggle Profile Being Default'\" stop-propagation mat-icon-button (click)=\"unsetDefault()\">\r\n <mat-icon style=\"color: green;\">star</mat-icon>\r\n </button>\r\n }\r\n <button [matTooltip]=\"'Delete Profile'\" class=\"last-in-line\" stop-propagation mat-icon-button (click)='stateService.deleteProfileFromLocalAndStorage($tableId(), key)'>\r\n <mat-icon color='warn'>delete_forever</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n <hr class=\"divider\"/>\r\n </div>\r\n <div class=\"add-new-profile-row\" mat-menu-item stop-propagation (click)=\"newProfilePanelOpened.set(!newProfilePanelOpened()); addedKey.focus()\">Add New Profile</div>\r\n <div [class]=\"{ hide: !newProfilePanelOpened(), panel: true }\" >\r\n <div class=\"profile-line\" stop-propagation>\r\n <div class=\"new-name-input\">\r\n <i class=\"input-hint\">Enter New Name</i>\r\n <input matInput #addedKey=\"matInput\" [name]=\"'key'\" />\r\n </div>\r\n <button [matTooltip]=\"'Toggle Profile Being Created As Default'\" stop-propagation mat-icon-button (click)=\"m2.toggle()\" >\r\n <mat-icon style=\"color: green;\">{{m2.checked ? 'star' : 'star_border'}}</mat-icon>\r\n </button>\r\n <mat-checkbox class=\"display-none\" [ngModel]=\"!$defaultProfile()\" #m2 />\r\n </div>\r\n <button class=\"add-button\" color=\"primary\" [matTooltip]=\"'Create New Profile'\" mat-raised-button (click)=\"addState(addedKey.value, m2.checked); addedKey.value = null\" [disabled]=\"!addedKey.value\">\r\n Add\r\n </button>\r\n </div>\r\n</mat-menu>\r\n", styles: [":host ::ng-deep .mat-expansion-panel-header{padding:0}.current-name{color:#00f}.menu-item{display:inline-flex;width:initial;flex-grow:1}.profile-line{display:flex;justify-content:space-between;align-items:center}.first-in-line{--f-b: 2rem;margin-left:var(--mat-menu-item-with-icon-leading-spacing)}.first-in-line.first-button{height:var(--f-b);margin:.2rem}.first-in-line .button-save-icon{height:var(--f-b);width:var(--f-b);font-size:var(--f-b)}.main-save-button{height:4rem;width:4rem;padding:.5rem}.main-save-button mat-icon{height:3rem;width:3rem;font-size:3rem}.save-for-default-icon{margin:0}.display-none{display:none}.last-in-line{padding-right:var(--mat-menu-item-with-icon-trailing-spacing)}.default-cursor{cursor:default}.as-def{padding-left:var(--mat-menu-item-with-icon-leading-spacing)}.divider{margin:.2px 0}.add-key{max-width:8.5rem;margin-left:2px}.add-key ::ng-deep .mdc-text-field{padding:0}.panel{transition:height .1s}.hide{height:0;min-height:0;overflow:hidden}.open-panel-button{width:100%;height:2.5rem}.current-in-list{border-left:3px solid blue;background-color:#0000ff0d}.not-current-in-list{border-left:3px solid rgba(255,255,255,0)}.add-new-profile-row,.all-profile-row{border-top:rgba(128,128,128,.25) solid 1px}.all-profiles{display:flex;justify-content:space-between}.all-profiles:has(.all-profile-arrow-close){align-items:center}.all-profile-arrow{display:inline-block;height:.7rem;width:.7rem;border-color:#000;transform:rotate(-45deg)}.all-profile-arrow-open{border-left:solid 2px;border-bottom:solid 2px}.all-profile-arrow-close{border-right:solid 2px;border-top:solid 2px}.new-name-input{margin-left:3px;display:flex;flex-direction:column}.new-name-input .input-hint{font-size:smaller;font-weight:200;color:gray}.add-button{height:20px;line-height:20px;margin:3px 0 0 3px}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
4731
4850
  }
4732
4851
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ProfilesMenuComponent, decorators: [{
4733
4852
  type: Component,
4734
4853
  args: [{ selector: 'tb-profiles-menu', imports: [MatIcon, MatTooltip, MatIconButton, MatMenuModule, MatButton, MatInput,
4735
4854
  MatCheckbox, StopPropagationDirective, MatInputModule, FormsModule
4736
- ], template: "<button mat-icon-button [matMenuTriggerFor]=\"menu\" #trigger=\"matMenuTrigger\" [matTooltip]=\"'Profiles'\">\r\n <mat-icon color=\"primary\">people</mat-icon>\r\n</button>\r\n<mat-menu #menu=\"matMenu\" (closed)=\"addedKey.value = null; allProfilesPanelOpened.set(false); newProfilePanelOpened.set(false)\">\r\n @if(!!$currentProfile())\r\n {\r\n <div mat-menu-item [matTooltip]=\"'Save Profile'\" mat-stroked-button (click)=\"saveState($currentProfile()!)\">\r\n <mat-icon color=\"primary\">save</mat-icon>\r\n <span>{{$currentProfile()}}</span>\r\n </div>\r\n }\r\n @else\r\n {\r\n <div class=\"profile-line\">\r\n <button class=\"first-in-line first-button\" mat-stroked-button (click)=\"addState(defaultName, m.checked);\">\r\n <mat-icon class=\"save-for-default-icon button-save-icon\" color=\"primary\">save</mat-icon>\r\n <span>Save as <span class=\"current-name\">{{defaultName}}</span> </span>\r\n </button>\r\n <button [matTooltip]=\"'Toggle Profile Being Created As Default'\" stop-propagation mat-icon-button (click)=\"m.toggle()\" >\r\n <mat-icon style=\"color: green;\">{{m.checked ? 'star' : 'star_border'}}</mat-icon>\r\n </button>\r\n <mat-checkbox class=\"display-none\" [checked]=\"true\" #m />\r\n </div>\r\n }\r\n @if (allProfilesPanelOpened()) {<hr class=\"divider\"/>}\r\n <div [class]=\"{ hide: !$keys().length, 'all-profile-row': true }\" mat-menu-item stop-propagation (click)=\"allProfilesPanelOpened.set(!allProfilesPanelOpened())\">\r\n <div class=\"all-profiles\">\r\n <span>All Profiles</span>\r\n <span [class]=\"(allProfilesPanelOpened() ? 'all-profile-arrow-close' : 'all-profile-arrow-open') + ' all-profile-arrow'\" class=\"arrow\"></span>\r\n </div>\r\n </div>\r\n <div [class]=\"{ hide: !allProfilesPanelOpened(), panel: true }\">\r\n @for (key of $keys() ; track key) {\r\n <div class=\"profile-line\" [class]=\"key === $currentProfile() ? 'current-in-list' : 'not-current-in-list'\">\r\n <button [matTooltip]=\"'Select Profile'\" class=\"menu-item first-in-line\" mat-stroked-button (click)='stateService.setLocalCurrentState({ tableId: $tableId(), currentStateKey: key})'>\r\n <span>{{key}}</span>\r\n </button>\r\n @if(key !== $defaultProfile())\r\n {\r\n <button [matTooltip]=\"'Toggle Profile Being Default'\" stop-propagation mat-icon-button (click)=\"setDefault(key)\">\r\n <mat-icon style=\"color: green;\">star_border</mat-icon>\r\n </button>\r\n }\r\n @else\r\n {\r\n <button [matTooltip]=\"'Toggle Profile Being Default'\" stop-propagation mat-icon-button (click)=\"unsetDefault()\">\r\n <mat-icon style=\"color: green;\">star</mat-icon>\r\n </button>\r\n }\r\n <button [matTooltip]=\"'Delete Profile'\" class=\"last-in-line\" stop-propagation mat-icon-button (click)='stateService.deleteProfileFromLocalAndStorage($tableId(), key)'>\r\n <mat-icon color='warn'>delete_forever</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n <hr class=\"divider\"/>\r\n </div>\r\n <div class=\"add-new-profile-row\" mat-menu-item stop-propagation (click)=\"newProfilePanelOpened.set(!newProfilePanelOpened()); addedKey.focus()\">Add New Profile</div>\r\n <div [class]=\"{ hide: !newProfilePanelOpened(), panel: true }\" >\r\n <div class=\"profile-line\" stop-propagation>\r\n <div class=\"new-name-input\">\r\n <i class=\"input-hint\">Enter New Name</i>\r\n <input matInput #addedKey=\"matInput\" [name]=\"'key'\" />\r\n </div>\r\n <button [matTooltip]=\"'Toggle Profile Being Created As Default'\" stop-propagation mat-icon-button (click)=\"m2.toggle()\" >\r\n <mat-icon style=\"color: green;\">{{m2.checked ? 'star' : 'star_border'}}</mat-icon>\r\n </button>\r\n <mat-checkbox class=\"display-none\" [ngModel]=\"!$defaultProfile()\" #m2 />\r\n </div>\r\n <button class=\"add-button\" color=\"primary\" [matTooltip]=\"'Create New Profile'\" mat-raised-button (click)=\"addState(addedKey.value, m2.checked); addedKey.value = null\" [disabled]=\"!addedKey.value\">\r\n Add\r\n </button>\r\n </div>\r\n</mat-menu>\r\n", styles: [":host ::ng-deep .mat-expansion-panel-header{padding:0}.current-name{color:#00f}.menu-item{display:inline-flex;width:initial;flex-grow:1}.profile-line{display:flex;justify-content:space-between;align-items:center}.first-in-line{--f-b: 2rem;margin-left:var(--mat-menu-item-with-icon-leading-spacing)}.first-in-line.first-button{height:var(--f-b);margin:.2rem}.first-in-line .button-save-icon{height:var(--f-b);width:var(--f-b);font-size:var(--f-b)}.main-save-button{height:4rem;width:4rem;padding:.5rem}.main-save-button mat-icon{height:3rem;width:3rem;font-size:3rem}.save-for-default-icon{margin:0}.display-none{display:none}.last-in-line{padding-right:var(--mat-menu-item-with-icon-trailing-spacing)}.default-cursor{cursor:default}.as-def{padding-left:var(--mat-menu-item-with-icon-leading-spacing)}.divider{margin:.2px 0}.add-key{max-width:8.5rem;margin-left:2px}.add-key ::ng-deep .mdc-text-field{padding:0}.panel{transition:height .1s}.hide{height:0;min-height:0;overflow:hidden}.open-panel-button{width:100%;height:2.5rem}.current-in-list{border-left:3px solid blue;background-color:#0000ff0d}.not-current-in-list{border-left:3px solid rgba(255,255,255,0)}.add-new-profile-row,.all-profile-row{border-top:rgba(128,128,128,.25) solid 1px}.all-profiles{display:flex;justify-content:space-between}.all-profiles:has(.all-profile-arrow-close){align-items:center}.all-profile-arrow{display:inline-block;height:.7rem;width:.7rem;border-color:#000;transform:rotate(-45deg)}.all-profile-arrow-open{border-left:solid 2px;border-bottom:solid 2px}.all-profile-arrow-close{border-right:solid 2px;border-top:solid 2px}.new-name-input{margin-left:3px;display:flex;flex-direction:column}.new-name-input .input-hint{font-size:smaller;font-weight:200;color:gray}.add-button{height:20px;line-height:20px;margin:3px 0 0 3px}\n"] }]
4855
+ ], template: "@if(!$isMatMenuChild())\r\n{\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\" #trigger=\"matMenuTrigger\" [matTooltip]=\"'Profiles'\">\r\n <mat-icon color=\"primary\">people</mat-icon>\r\n </button>\r\n}\r\n<mat-menu #menu=\"matMenu\" (closed)=\"addedKey.value = null; allProfilesPanelOpened.set(false); newProfilePanelOpened.set(false)\">\r\n @if(!!$currentProfile())\r\n {\r\n <div mat-menu-item [matTooltip]=\"'Save Profile'\" mat-stroked-button (click)=\"saveState($currentProfile()!)\">\r\n <mat-icon color=\"primary\">save</mat-icon>\r\n <span>{{$currentProfile()}}</span>\r\n </div>\r\n }\r\n @else\r\n {\r\n <div class=\"profile-line\">\r\n <button class=\"first-in-line first-button\" mat-stroked-button (click)=\"addState(defaultName, m.checked);\">\r\n <mat-icon class=\"save-for-default-icon button-save-icon\" color=\"primary\">save</mat-icon>\r\n <span>Save as <span class=\"current-name\">{{defaultName}}</span> </span>\r\n </button>\r\n <button [matTooltip]=\"'Toggle Profile Being Created As Default'\" stop-propagation mat-icon-button (click)=\"m.toggle()\" >\r\n <mat-icon style=\"color: green;\">{{m.checked ? 'star' : 'star_border'}}</mat-icon>\r\n </button>\r\n <mat-checkbox class=\"display-none\" [checked]=\"true\" #m />\r\n </div>\r\n }\r\n @if (allProfilesPanelOpened()) {<hr class=\"divider\"/>}\r\n <div [class]=\"{ hide: !$keys().length, 'all-profile-row': true }\" mat-menu-item stop-propagation (click)=\"allProfilesPanelOpened.set(!allProfilesPanelOpened())\">\r\n <div class=\"all-profiles\">\r\n <span>All Profiles</span>\r\n <span [class]=\"(allProfilesPanelOpened() ? 'all-profile-arrow-close' : 'all-profile-arrow-open') + ' all-profile-arrow'\" class=\"arrow\"></span>\r\n </div>\r\n </div>\r\n <div [class]=\"{ hide: !allProfilesPanelOpened(), panel: true }\">\r\n @for (key of $keys() ; track key) {\r\n <div class=\"profile-line\" [class]=\"key === $currentProfile() ? 'current-in-list' : 'not-current-in-list'\">\r\n <button [matTooltip]=\"'Select Profile'\" class=\"menu-item first-in-line\" mat-stroked-button (click)='stateService.setLocalCurrentState({ tableId: $tableId(), currentStateKey: key})'>\r\n <span>{{key}}</span>\r\n </button>\r\n @if(key !== $defaultProfile())\r\n {\r\n <button [matTooltip]=\"'Toggle Profile Being Default'\" stop-propagation mat-icon-button (click)=\"setDefault(key)\">\r\n <mat-icon style=\"color: green;\">star_border</mat-icon>\r\n </button>\r\n }\r\n @else\r\n {\r\n <button [matTooltip]=\"'Toggle Profile Being Default'\" stop-propagation mat-icon-button (click)=\"unsetDefault()\">\r\n <mat-icon style=\"color: green;\">star</mat-icon>\r\n </button>\r\n }\r\n <button [matTooltip]=\"'Delete Profile'\" class=\"last-in-line\" stop-propagation mat-icon-button (click)='stateService.deleteProfileFromLocalAndStorage($tableId(), key)'>\r\n <mat-icon color='warn'>delete_forever</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n <hr class=\"divider\"/>\r\n </div>\r\n <div class=\"add-new-profile-row\" mat-menu-item stop-propagation (click)=\"newProfilePanelOpened.set(!newProfilePanelOpened()); addedKey.focus()\">Add New Profile</div>\r\n <div [class]=\"{ hide: !newProfilePanelOpened(), panel: true }\" >\r\n <div class=\"profile-line\" stop-propagation>\r\n <div class=\"new-name-input\">\r\n <i class=\"input-hint\">Enter New Name</i>\r\n <input matInput #addedKey=\"matInput\" [name]=\"'key'\" />\r\n </div>\r\n <button [matTooltip]=\"'Toggle Profile Being Created As Default'\" stop-propagation mat-icon-button (click)=\"m2.toggle()\" >\r\n <mat-icon style=\"color: green;\">{{m2.checked ? 'star' : 'star_border'}}</mat-icon>\r\n </button>\r\n <mat-checkbox class=\"display-none\" [ngModel]=\"!$defaultProfile()\" #m2 />\r\n </div>\r\n <button class=\"add-button\" color=\"primary\" [matTooltip]=\"'Create New Profile'\" mat-raised-button (click)=\"addState(addedKey.value, m2.checked); addedKey.value = null\" [disabled]=\"!addedKey.value\">\r\n Add\r\n </button>\r\n </div>\r\n</mat-menu>\r\n", styles: [":host ::ng-deep .mat-expansion-panel-header{padding:0}.current-name{color:#00f}.menu-item{display:inline-flex;width:initial;flex-grow:1}.profile-line{display:flex;justify-content:space-between;align-items:center}.first-in-line{--f-b: 2rem;margin-left:var(--mat-menu-item-with-icon-leading-spacing)}.first-in-line.first-button{height:var(--f-b);margin:.2rem}.first-in-line .button-save-icon{height:var(--f-b);width:var(--f-b);font-size:var(--f-b)}.main-save-button{height:4rem;width:4rem;padding:.5rem}.main-save-button mat-icon{height:3rem;width:3rem;font-size:3rem}.save-for-default-icon{margin:0}.display-none{display:none}.last-in-line{padding-right:var(--mat-menu-item-with-icon-trailing-spacing)}.default-cursor{cursor:default}.as-def{padding-left:var(--mat-menu-item-with-icon-leading-spacing)}.divider{margin:.2px 0}.add-key{max-width:8.5rem;margin-left:2px}.add-key ::ng-deep .mdc-text-field{padding:0}.panel{transition:height .1s}.hide{height:0;min-height:0;overflow:hidden}.open-panel-button{width:100%;height:2.5rem}.current-in-list{border-left:3px solid blue;background-color:#0000ff0d}.not-current-in-list{border-left:3px solid rgba(255,255,255,0)}.add-new-profile-row,.all-profile-row{border-top:rgba(128,128,128,.25) solid 1px}.all-profiles{display:flex;justify-content:space-between}.all-profiles:has(.all-profile-arrow-close){align-items:center}.all-profile-arrow{display:inline-block;height:.7rem;width:.7rem;border-color:#000;transform:rotate(-45deg)}.all-profile-arrow-open{border-left:solid 2px;border-bottom:solid 2px}.all-profile-arrow-close{border-right:solid 2px;border-top:solid 2px}.new-name-input{margin-left:3px;display:flex;flex-direction:column}.new-name-input .input-hint{font-size:smaller;font-weight:200;color:gray}.add-button{height:20px;line-height:20px;margin:3px 0 0 3px}\n"] }]
4737
4856
  }] });
4738
4857
 
4739
- const containerImports = [
4740
- NgTemplateOutlet,
4741
- PaginatorComponent,
4742
- MultiSortDirective, GroupByListComponent, FilterChipsComponent, GenFilterDisplayerComponent, GenColDisplayerComponent,
4743
- SortMenuComponent, GenericTableComponent, StopPropagationDirective, ProfilesMenuComponent,
4744
- MatButtonModule, MatMenuModule, MatIconModule, MatTooltipModule, VirtualScrollContainer
4745
- ];
4746
-
4747
- //The idea of this is that if filters were only added, and none were removed or changed, then we only need to tag more rows to not be shown. We don't need to remove any 'dont show' tags.
4748
- // So if filters were only added this method will return the added filters, if filters were removed or changed this method will return undefined.
4749
- const updateFilterInfoState = (previousState, filterInfos) => {
4750
- filterInfos = filterNonActiveOrNotReadyFilters(filterInfos);
4751
- const currentState = {
4752
- allFilters: filterInfos,
4753
- onlyAddedFilters: filterInfoOnlyAdded(previousState.allFilters, filterInfos)
4754
- };
4755
- return currentState;
4756
- };
4757
- const mapFilterInfoStateToPredicateState = (s) => {
4758
- const mappedAddOnly = s.onlyAddedFilters
4759
- ?
4760
- Object.entries(s.onlyAddedFilters).filter(([, v]) => needsFilterCreation(v)).reduce((obj, [key, value]) => {
4761
- obj[key] = createFilterFunc(value);
4762
- return obj;
4763
- }, {})
4764
- : {};
4765
- const mappedAll = Object.entries(s.allFilters).filter(([, v]) => needsFilterCreation(v))
4766
- .filter(([, v]) => !isCustomFilter(v) || !!v.predicate)
4767
- .map(([key, value]) => {
4768
- return mappedAddOnly[key] || createFilterFunc(value);
4769
- });
4770
- return ({
4771
- allFilters: mappedAll,
4772
- onlyAddedFilters: s.onlyAddedFilters ? Object.values(mappedAddOnly) : undefined
4858
+ class SortMenuComponentStore extends ComponentStore {
4859
+ tableState = inject(TableStore);
4860
+ setStoreStateEffect = effect(() => {
4861
+ const metaData = this.tableState.$metaData();
4862
+ if (!metaData)
4863
+ return;
4864
+ this.tableState.$selectSorted();
4865
+ untracked(() => this.setStateFromTableStore());
4773
4866
  });
4774
- };
4775
- const updateFilterPredicateState = (previousState, filters) => {
4776
- const currentState = {
4777
- allFilters: filters,
4778
- onlyAddedFilters: predicatesOnlyAdded(previousState.allFilters, filters)
4779
- };
4780
- return currentState;
4781
- };
4782
- const updateFilterState = (filterInfos, predicates) => {
4783
- const infos = mapFilterInfoStateToPredicateState(filterInfos.value);
4784
- const filtersState = {
4785
- allFilters: [...infos.allFilters, ...predicates.value.allFilters]
4867
+ setStateFromTableStore = () => {
4868
+ const metaData = this.tableState.$metaData();
4869
+ const sorted = [...this.tableState.$selectSorted()].map(s => ({
4870
+ ...s,
4871
+ displayName: metaData[s.active]?.displayName
4872
+ }));
4873
+ const notSorted = this.tableState.$metaDataArray()
4874
+ .filter(md => md.fieldType !== FieldType.NotMapped && !md.noSort && !sorted.some(s => s.active === md.key))
4875
+ .map(meta => ({ active: meta.key, displayName: meta.displayName }));
4876
+ this.setState({ sorted, notSorted });
4786
4877
  };
4787
- if (filterInfos.timestamp > predicates.timestamp && !!filterInfos.value.onlyAddedFilters) {
4788
- filtersState.onlyAddedFilters = infos.onlyAddedFilters;
4789
- }
4790
- else {
4791
- filtersState.onlyAddedFilters = predicates.value.onlyAddedFilters;
4792
- }
4793
- return filtersState;
4794
- };
4795
- const filterNonActiveOrNotReadyFilters = (filtersDict) => Object.entries(filtersDict).reduce((obj, [key, value]) => {
4796
- if (value.active !== false && (!isCustomFilter(value) || !!value.predicate)) {
4797
- obj[key] = value;
4798
- }
4799
- ;
4800
- return obj;
4801
- }, {});
4802
- function filterInfoOnlyAdded(previousFilterInfos, currentFilterInfos) {
4803
- const previousKeys = Object.keys(previousFilterInfos);
4804
- const currentKeys = Object.keys(currentFilterInfos);
4805
- const keysInBoth = intersection(previousKeys, currentKeys);
4806
- const someRemoved = previousKeys.length > keysInBoth.length;
4807
- if (someRemoved || !previousKeys.length) {
4808
- return undefined;
4809
- }
4810
- if (filtersInfosUpdated(previousFilterInfos, currentFilterInfos)) {
4811
- return undefined;
4878
+ constructor() {
4879
+ super({ notSorted: [], sorted: [] });
4812
4880
  }
4813
- const addedFilters = difference(currentKeys, keysInBoth).reduce((dict, key) => {
4814
- dict[key] = currentFilterInfos[key];
4815
- return dict;
4816
- }, {});
4817
- return addedFilters;
4881
+ setSorted = this.updater((state, sorted) => ({ ...state, sorted }));
4882
+ setNotSorted = this.updater((state, notSorted) => ({ ...state, notSorted }));
4883
+ $sorted = this.selectSignal(state => state.sorted);
4884
+ $notSorted = this.selectSignal(state => state.notSorted);
4885
+ setDirection = this.updater((state, sort) => {
4886
+ const index = state.sorted.findIndex(s => s.active === sort.active);
4887
+ const sorted = [...state.sorted];
4888
+ sorted.splice(index, 1, sort);
4889
+ return ({ ...state, sorted });
4890
+ });
4891
+ reset = () => {
4892
+ this.setStateFromTableStore();
4893
+ };
4894
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponentStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
4895
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponentStore });
4818
4896
  }
4819
- function predicatesOnlyAdded(previousPredicates, currentPredicates) {
4820
- if (!previousPredicates.length) {
4821
- return undefined;
4897
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponentStore, decorators: [{
4898
+ type: Injectable
4899
+ }], ctorParameters: () => [] });
4900
+
4901
+ class SortMenuComponent {
4902
+ SortDirection = SortDirection;
4903
+ tableState = inject(TableStore);
4904
+ store = inject(SortMenuComponentStore);
4905
+ $sorted = computed(() => [...this.store.$sorted()]);
4906
+ $notSorted = computed(() => [...this.store.$notSorted()]);
4907
+ $dirty = signal(false);
4908
+ reset() {
4909
+ this.$dirty.set(false);
4910
+ this.store.reset();
4822
4911
  }
4823
- const predicateFiltersRemoved = difference(previousPredicates, currentPredicates).length;
4824
- if (predicateFiltersRemoved) {
4825
- return undefined;
4912
+ dropIntoSorted(event) {
4913
+ this.$dirty.set(true);
4914
+ const sorted = [...event.container.data];
4915
+ if (event.previousContainer === event.container) {
4916
+ moveItemInArray(sorted, event.previousIndex, event.currentIndex);
4917
+ this.store.setSorted(sorted);
4918
+ }
4919
+ else {
4920
+ const notSorted = [...event.previousContainer.data];
4921
+ transferArrayItem(notSorted, sorted, event.previousIndex, event.currentIndex);
4922
+ sorted[event.currentIndex] = { ...sorted[event.currentIndex], direction: SortDirection.asc };
4923
+ this.store.setSorted(sorted);
4924
+ this.store.setNotSorted(notSorted);
4925
+ }
4826
4926
  }
4827
- return difference(currentPredicates, previousPredicates);
4828
- }
4829
- function filtersInfosUpdated(previousFilterInfos, currentFilterInfos) {
4830
- return !Object.entries(previousFilterInfos).every(([key, val]) => {
4831
- return currentFilterInfos[key].filterType === val.filterType && currentFilterInfos[key].filterValue === val.filterValue;
4832
- });
4833
- }
4834
- function patchDirectiveFromState(directive, stateFilter) {
4835
- if (isFilterInfo(stateFilter)) {
4836
- const filterDirective = directive;
4837
- filterDirective.setFilterValue(stateFilter.filterValue);
4838
- filterDirective.update();
4927
+ dropIntoNotSorted(event) {
4928
+ if (event.previousContainer === event.container) {
4929
+ return;
4930
+ }
4931
+ else {
4932
+ this.$dirty.set(true);
4933
+ const sorted = [...event.previousContainer.data];
4934
+ const notSorted = [...event.container.data];
4935
+ transferArrayItem(sorted, notSorted, event.previousIndex, event.currentIndex);
4936
+ notSorted[event.currentIndex] = { ...notSorted[event.currentIndex] };
4937
+ this.store.setNotSorted(notSorted);
4938
+ this.store.setSorted(sorted);
4939
+ }
4839
4940
  }
4840
- if (isCustomFilter(stateFilter)) {
4841
- directive.active = stateFilter.active ?? false;
4941
+ apply = () => {
4942
+ this.$dirty.set(false);
4943
+ this.tableState.setAllSort(this.store.$sorted());
4944
+ };
4945
+ setDirection(sort) {
4946
+ this.$dirty.set(true);
4947
+ this.store.setDirection(sort);
4842
4948
  }
4949
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4950
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: SortMenuComponent, isStandalone: true, selector: "tb-sort-menu", providers: [SortMenuComponentStore], ngImport: i0, template: "@let dirty = $dirty();\r\n@let sorted = $sorted();\r\n@let notSorted = $notSorted();\r\n\r\n<!-- Menu Trigger -->\r\n<span matTooltip=\"Sort\">\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\r\n <mat-icon color=\"primary\">swap_vert</mat-icon>\r\n </button>\r\n</span>\r\n\r\n<!-- Menu -->\r\n<mat-menu #menu=\"matMenu\" class=\"my-mat-menu\" (closed)=\"reset()\">\r\n <div mat-menu-item class=\"menu-button\">\r\n <div class=\"close-button-wrapper\">\r\n <span matTooltip=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </span>\r\n @if(dirty){\r\n <span matTooltip=\"Undo\" stop-propagation (click)=\"reset()\">\r\n <mat-icon>undo</mat-icon>\r\n </span>\r\n }\r\n \r\n </div>\r\n </div>\r\n\r\n <!-- Apply Button -->\r\n <div class=\"apply-button-wrapper\">\r\n <button mat-button color=\"primary\" (click)=\"apply()\"\r\n stop-propagation [class.apply-border]=\"dirty\"\r\n [disabled]=\"!dirty\">\r\n Apply @if (dirty) { Unsaved Changes }\r\n </button>\r\n </div>\r\n\r\n <!-- Default Sorting Text -->\r\n @if (!sorted.length) {\r\n <div class=\"tip\" >\r\n Sorting List\r\n </div>\r\n }\r\n\r\n <!-- Sorted Menu List -->\r\n <div class=\"list\"\r\n cdkDropList\r\n #sortedGroup=\"cdkDropList\"\r\n [cdkDropListConnectedTo]=\"[notSortedGroup]\"\r\n [cdkDropListData]=\"sorted\"\r\n (cdkDropListDropped)=\"dropIntoSorted($event)\">\r\n\r\n <!-- Menu Item Wrapper -->\r\n @for (sort of sorted; track sort.active) {\r\n <!-- Menu Item Headers -->\r\n @if (sorted.length > 1) {\r\n <span class=\"description sort-header\">{{$index === 0 ? 'First By' : 'Then By'}}</span>\r\n }\r\n\r\n <!-- Menu Item -->\r\n <div mat-menu-item cdkDrag class=\"menu-item\">\r\n <div class=\"sort-item\">\r\n <span class=\"sorted-name\">\r\n {{sort.displayName || (sort.active | spaceCase)}}\r\n <span class=\"direction-text\">{{sort.direction}}</span>\r\n </span>\r\n\r\n <!-- Sort Direction Buttons -->\r\n <div class=\"up-down-buttons-wrapper\">\r\n <button class=\"up-down-button up-button\" stop-propagation\r\n (click)=\"setDirection({active:sort.active,direction:SortDirection.asc,displayName:sort.displayName})\">\r\n <mat-icon [class]=\"sort.direction !== SortDirection.asc ? 'light-arrow' : 'dark-arrow'\" class=\"up-down-icon\">\r\n arrow_upward\r\n </mat-icon>\r\n </button>\r\n\r\n <button class=\"up-down-button\" stop-propagation\r\n (click)=\"setDirection({active:sort.active,direction:SortDirection.desc,displayName:sort.displayName})\">\r\n <mat-icon [class]=\"sort.direction === SortDirection.asc ? 'light-arrow' : 'dark-arrow'\" class=\"up-down-icon\">\r\n arrow_downward\r\n </mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n </div>\r\n\r\n <!-- Default Not Sorted Text -->\r\n @if(!notSorted.length){\r\n <div class=\"tip\" >\r\n Not Sorted List\r\n </div>\r\n }\r\n\r\n <!-- Not Sorted Menu List -->\r\n <div class=\"list\"\r\n cdkDropList\r\n #notSortedGroup=\"cdkDropList\"\r\n [cdkDropListConnectedTo]=\"[sortedGroup]\"\r\n [cdkDropListData]=\"notSorted\"\r\n (cdkDropListDropped)=\"dropIntoNotSorted($event)\">\r\n @for (sort of notSorted; track sort.active) {\r\n <div mat-menu-item class=\"menu-item\" cdkDrag>\r\n <span class=\"not-sorted-name\">{{sort.displayName || (sort.active | spaceCase)}}</span>\r\n </div>\r\n }\r\n </div>\r\n</mat-menu>\r\n", styles: [".cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.list{padding:5px 2px;border-bottom:solid 1px #ccc;color:#000000de;background:#fff}.light-arrow{color:#93b1ea78}.dark-arrow{color:#224e9c}.up-down-button{background-color:#fff;border-radius:30%;border-color:#0ff;padding:1px 1px 0;border-width:.5px;cursor:pointer;height:27px}.mat-icon.up-down-icon{margin-right:0;font-size:20px;font-weight:lighter}.sort-item{display:flex;align-items:center;justify-content:space-between}.up-down-buttons-wrapper{margin-left:2rem}.up-button{margin-right:.3rem}.mat-mdc-menu-item.menu-item,.mat-mdc-menu-item.menu-button{min-height:initial;padding:0 3px;line-height:25px;height:30px}.mat-mdc-menu-item.menu-item{cursor:move}.sorted-name{color:#224e9c;font-size:17px;font-weight:700}.not-sorted-name{color:#93b1ea;font-size:17px;font-weight:700}.apply-border{border:#224e9c solid .5px}.apply-border:hover{background-color:#faebd7}.apply-button-wrapper{display:grid;justify-content:center}.sort-header{font-size:10px;font-style:italic}.tip{padding:0 3px;color:#d3d3d3}.direction-text{font-size:small;font-weight:400}.close-button-wrapper{display:flex;flex-direction:row-reverse}\n"], dependencies: [{ kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4843
4951
  }
4952
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: SortMenuComponent, decorators: [{
4953
+ type: Component,
4954
+ args: [{ selector: 'tb-sort-menu', providers: [SortMenuComponentStore], changeDetection: ChangeDetectionStrategy.OnPush, imports: [
4955
+ MatTooltipModule, MatButtonModule, MatIconModule, MatMenuModule, StopPropagationDirective, DragDropModule,
4956
+ SpaceCasePipe
4957
+ ], template: "@let dirty = $dirty();\r\n@let sorted = $sorted();\r\n@let notSorted = $notSorted();\r\n\r\n<!-- Menu Trigger -->\r\n<span matTooltip=\"Sort\">\r\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\r\n <mat-icon color=\"primary\">swap_vert</mat-icon>\r\n </button>\r\n</span>\r\n\r\n<!-- Menu -->\r\n<mat-menu #menu=\"matMenu\" class=\"my-mat-menu\" (closed)=\"reset()\">\r\n <div mat-menu-item class=\"menu-button\">\r\n <div class=\"close-button-wrapper\">\r\n <span matTooltip=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </span>\r\n @if(dirty){\r\n <span matTooltip=\"Undo\" stop-propagation (click)=\"reset()\">\r\n <mat-icon>undo</mat-icon>\r\n </span>\r\n }\r\n \r\n </div>\r\n </div>\r\n\r\n <!-- Apply Button -->\r\n <div class=\"apply-button-wrapper\">\r\n <button mat-button color=\"primary\" (click)=\"apply()\"\r\n stop-propagation [class.apply-border]=\"dirty\"\r\n [disabled]=\"!dirty\">\r\n Apply @if (dirty) { Unsaved Changes }\r\n </button>\r\n </div>\r\n\r\n <!-- Default Sorting Text -->\r\n @if (!sorted.length) {\r\n <div class=\"tip\" >\r\n Sorting List\r\n </div>\r\n }\r\n\r\n <!-- Sorted Menu List -->\r\n <div class=\"list\"\r\n cdkDropList\r\n #sortedGroup=\"cdkDropList\"\r\n [cdkDropListConnectedTo]=\"[notSortedGroup]\"\r\n [cdkDropListData]=\"sorted\"\r\n (cdkDropListDropped)=\"dropIntoSorted($event)\">\r\n\r\n <!-- Menu Item Wrapper -->\r\n @for (sort of sorted; track sort.active) {\r\n <!-- Menu Item Headers -->\r\n @if (sorted.length > 1) {\r\n <span class=\"description sort-header\">{{$index === 0 ? 'First By' : 'Then By'}}</span>\r\n }\r\n\r\n <!-- Menu Item -->\r\n <div mat-menu-item cdkDrag class=\"menu-item\">\r\n <div class=\"sort-item\">\r\n <span class=\"sorted-name\">\r\n {{sort.displayName || (sort.active | spaceCase)}}\r\n <span class=\"direction-text\">{{sort.direction}}</span>\r\n </span>\r\n\r\n <!-- Sort Direction Buttons -->\r\n <div class=\"up-down-buttons-wrapper\">\r\n <button class=\"up-down-button up-button\" stop-propagation\r\n (click)=\"setDirection({active:sort.active,direction:SortDirection.asc,displayName:sort.displayName})\">\r\n <mat-icon [class]=\"sort.direction !== SortDirection.asc ? 'light-arrow' : 'dark-arrow'\" class=\"up-down-icon\">\r\n arrow_upward\r\n </mat-icon>\r\n </button>\r\n\r\n <button class=\"up-down-button\" stop-propagation\r\n (click)=\"setDirection({active:sort.active,direction:SortDirection.desc,displayName:sort.displayName})\">\r\n <mat-icon [class]=\"sort.direction === SortDirection.asc ? 'light-arrow' : 'dark-arrow'\" class=\"up-down-icon\">\r\n arrow_downward\r\n </mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n </div>\r\n\r\n <!-- Default Not Sorted Text -->\r\n @if(!notSorted.length){\r\n <div class=\"tip\" >\r\n Not Sorted List\r\n </div>\r\n }\r\n\r\n <!-- Not Sorted Menu List -->\r\n <div class=\"list\"\r\n cdkDropList\r\n #notSortedGroup=\"cdkDropList\"\r\n [cdkDropListConnectedTo]=\"[sortedGroup]\"\r\n [cdkDropListData]=\"notSorted\"\r\n (cdkDropListDropped)=\"dropIntoNotSorted($event)\">\r\n @for (sort of notSorted; track sort.active) {\r\n <div mat-menu-item class=\"menu-item\" cdkDrag>\r\n <span class=\"not-sorted-name\">{{sort.displayName || (sort.active | spaceCase)}}</span>\r\n </div>\r\n }\r\n </div>\r\n</mat-menu>\r\n", styles: [".cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.list{padding:5px 2px;border-bottom:solid 1px #ccc;color:#000000de;background:#fff}.light-arrow{color:#93b1ea78}.dark-arrow{color:#224e9c}.up-down-button{background-color:#fff;border-radius:30%;border-color:#0ff;padding:1px 1px 0;border-width:.5px;cursor:pointer;height:27px}.mat-icon.up-down-icon{margin-right:0;font-size:20px;font-weight:lighter}.sort-item{display:flex;align-items:center;justify-content:space-between}.up-down-buttons-wrapper{margin-left:2rem}.up-button{margin-right:.3rem}.mat-mdc-menu-item.menu-item,.mat-mdc-menu-item.menu-button{min-height:initial;padding:0 3px;line-height:25px;height:30px}.mat-mdc-menu-item.menu-item{cursor:move}.sorted-name{color:#224e9c;font-size:17px;font-weight:700}.not-sorted-name{color:#93b1ea;font-size:17px;font-weight:700}.apply-border{border:#224e9c solid .5px}.apply-border:hover{background-color:#faebd7}.apply-button-wrapper{display:grid;justify-content:center}.sort-header{font-size:10px;font-style:italic}.tip{padding:0 3px;color:#d3d3d3}.direction-text{font-size:small;font-weight:400}.close-button-wrapper{display:flex;flex-direction:row-reverse}\n"] }]
4958
+ }] });
4844
4959
 
4845
- function getGroupedData(data, groupByKeys) {
4846
- return tbGroupBy(data, groupByKeys);
4847
- }
4848
- const tbGroupBy = (data, groupByKeys, parentGroupName) => {
4849
- const currentKey = groupByKeys[0];
4850
- const res = groupBy(data, currentKey);
4851
- const remainingGroupByKeys = groupByKeys.slice(1);
4852
- const finalGroups = !remainingGroupByKeys.length;
4853
- if (remainingGroupByKeys.length) {
4854
- Object.keys(res).forEach(key => res[key] = tbGroupBy(res[key], remainingGroupByKeys, key));
4960
+ class ResetMenuComponent {
4961
+ menu = viewChild.required(MatMenu);
4962
+ tableContainer = inject(TableContainerComponent);
4963
+ state = this.tableContainer.state;
4964
+ onStateReset$ = output({ alias: 'onStateReset' });
4965
+ resetState() {
4966
+ this.tableContainer.$customFilterDirectives().forEach(cf => cf.reset());
4967
+ this.tableContainer.$filterDirectives().forEach(cf => cf.reset());
4968
+ this.state.resetState();
4969
+ this.onStateReset$.emit(null);
4855
4970
  }
4856
- return Object.keys(res).map((groupName, i) => {
4857
- const uniqName = parentGroupName ? `${parentGroupName}-${groupName}` : `${groupName}`;
4858
- const groupHeaders = res[groupName]?.filter(row => row.isGroupHeader) ?? [];
4859
- return {
4860
- isGroupHeader: true,
4861
- groupHeaderDisplay: groupName,
4862
- hasTheData: finalGroups,
4863
- children: finalGroups ? res[groupName] : res[groupName].map(d => { d.padding += 20; return d; }),
4864
- groupName: `tb_group_${uniqName}`,
4865
- padding: 1,
4866
- key: currentKey,
4867
- length: groupHeaders.reduce((acc, curr) => curr.length + acc, 0) + ((res[groupName] ?? []).length - groupHeaders.length),
4868
- [initIndexSymbol]: uniqName,
4869
- };
4971
+ $filtersSet = computed(() => {
4972
+ return Object.values(this.state.$filters())
4973
+ .filter(f => (isCustomFilter(f) && f.active) || f.filterValue != undefined)
4974
+ .length;
4870
4975
  });
4871
- };
4872
- function updateGroupByState({ groupedData }, [data, groups, expandedGroups], index) {
4873
- if (index === 0
4874
- || dataUpdated(data, groups, expandedGroups)
4875
- || groupsUpdated(groups, expandedGroups)) {
4876
- groupedData = groups.value.length ? getGroupedData(data.value, groups.value) : data.value;
4877
- }
4878
- const newDisplayData = expandedGroups.value.length === 0
4879
- ? groupedData
4880
- : groupedData.map(group => mapGroupHeader(group, expandedGroups.value)).flat();
4881
- return ({ displayData: newDisplayData, groupedData });
4882
- }
4883
- function mapGroupHeader(obj, data) {
4884
- const showChildren = data.find(a => a.expandedHeaders.includes(obj.groupName));
4885
- const children = !showChildren ? [] :
4886
- obj.hasTheData ? obj.children
4887
- : obj.children.map(a => mapGroupHeader(a, data));
4888
- return [obj, ...children].flat();
4889
- }
4890
- function dataUpdated(data, groups, expandedGroups) {
4891
- return data.timestamp > groups.timestamp && data.timestamp > expandedGroups.timestamp;
4892
- }
4893
- function groupsUpdated(groups, expandedGroups) {
4894
- return groups.timestamp > expandedGroups.timestamp;
4895
- }
4896
- ;
4897
- const initialGroupByState = { displayData: [], groupedData: [] };
4898
- const getAllGroupHeaderNames = (data) => {
4899
- const groups = getGroupHeaders(data, (d) => d.isGroupHeader);
4900
- return groupBy(groups, 'key');
4901
- };
4902
- const getAllGroupHeaderNamesByKeys = (data, keys) => {
4903
- const groups = getGroupHeaders(data, (d) => d.isGroupHeader && keys.includes(d.key));
4904
- return groupBy(groups, 'key');
4905
- };
4906
- const getGroupHeaders = (data, filterFunc, arr = []) => {
4907
- const headers = data.filter(filterFunc);
4908
- arr.push(...headers);
4909
- headers.forEach(h => { if (!!h.children.length)
4910
- getGroupHeaders(h.children, filterFunc, arr); });
4911
- return arr;
4912
- };
4913
-
4914
- function sortData(data, sorted) {
4915
- const ordered = orderBy(data, sorted.map(r => r.active), sorted.map(r => r.direction));
4916
- return ordered;
4917
- }
4918
- function filterData(data, filters, resetAll = false) {
4919
- for (let index = 0; index < data.length; index++) {
4920
- const element = data[index];
4921
- const hide = !filters.every(filter => filter(element));
4922
- if (hide || resetAll) {
4923
- element[tbNoShowSymbol] = hide;
4976
+ $sortSet = computed(() => {
4977
+ const sorts = this.state.$selectSorted();
4978
+ if (!sorts.length)
4979
+ return false;
4980
+ const preSorts = this.state.$preSort();
4981
+ if (!preSorts.length)
4982
+ return true;
4983
+ return !sortsAreSame(preSorts, sorts);
4984
+ });
4985
+ $groupBySet = computed(() => this.state.$groupByKeys().length);
4986
+ $hiddenSet = computed(() => this.state.$hiddenKeys().length);
4987
+ $orderSet = computed(() => Object.keys(this.state.$userDefinedOrder()).length);
4988
+ $widthsSet = computed(() => Object.keys(this.state.$getUserDefinedWidths()).length);
4989
+ $rowHeightSet = this.state.$userDefinedRowHeight;
4990
+ headerHeightSet = this.state.$userDefinedHeaderHeight;
4991
+ pageSizeSet = this.state.$userDefinedPageSize;
4992
+ showAllSet = this.state.selectSignal(s => s.userDefined.showAll);
4993
+ $set = computed(() => {
4994
+ const arr = [];
4995
+ if (this.$filtersSet()) {
4996
+ arr.push('Filters');
4997
+ }
4998
+ if (this.$sortSet()) {
4999
+ arr.push('Sorting');
5000
+ }
5001
+ if (this.$groupBySet()) {
5002
+ arr.push('Group By');
5003
+ }
5004
+ if (this.$hiddenSet()) {
5005
+ arr.push('Hidden Columns');
5006
+ }
5007
+ if (this.$orderSet()) {
5008
+ arr.push('Column Order');
4924
5009
  }
5010
+ if (this.$widthsSet()) {
5011
+ arr.push('Column Widths');
5012
+ }
5013
+ if (this.$rowHeightSet()) {
5014
+ arr.push('Row Height');
5015
+ }
5016
+ if (this.headerHeightSet()) {
5017
+ arr.push('Header Height');
5018
+ }
5019
+ if (this.pageSizeSet()) {
5020
+ arr.push('Page Size');
5021
+ }
5022
+ if (this.showAllSet()) {
5023
+ arr.push('Show All');
5024
+ }
5025
+ return arr;
5026
+ });
5027
+ resetable = resetable;
5028
+ reset(s) {
5029
+ this.state.resetPart(s);
4925
5030
  }
4926
- return data;
5031
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ResetMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5032
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: ResetMenuComponent, isStandalone: true, selector: "lib-reset-menu", outputs: { onStateReset$: "onStateReset" }, viewQueries: [{ propertyName: "menu", first: true, predicate: MatMenu, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-menu #menu2=\"matMenu\">\r\n @if($set().length > 1)\r\n {\r\n <button mat-menu-item (click)=\"state.resetState()\">All</button>\r\n }\r\n @for (item of $set(); track $index)\r\n {\r\n <button mat-menu-item (click)=\"state.resetPart(item)\">Reset {{item}}</button>\r\n }\r\n</mat-menu>", styles: [":host{display:contents}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "ngmodule", type: MatButtonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4927
5033
  }
4928
- const tbNoShowSymbol = Symbol('tb_no_show');
5034
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ResetMenuComponent, decorators: [{
5035
+ type: Component,
5036
+ args: [{ selector: 'lib-reset-menu', imports: [MatMenuModule, MatButtonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mat-menu #menu2=\"matMenu\">\r\n @if($set().length > 1)\r\n {\r\n <button mat-menu-item (click)=\"state.resetState()\">All</button>\r\n }\r\n @for (item of $set(); track $index)\r\n {\r\n <button mat-menu-item (click)=\"state.resetPart(item)\">Reset {{item}}</button>\r\n }\r\n</mat-menu>", styles: [":host{display:contents}\n"] }]
5037
+ }] });
4929
5038
 
4930
- const sortAndFilterData = (data, sortState, filterState) => combineLatest([
4931
- data.pipe(timestamp()),
4932
- sortState.pipe(timestamp()),
4933
- filterState.pipe(timestamp())
4934
- ]).pipe(scan(({ mappedData: resultData }, [data, sort, f], index) => {
4935
- if (index === 0 || (data.timestamp > sort.timestamp && data.timestamp > f.timestamp)) {
4936
- return ({ mappedData: filterData(sortData(data.value, sort.value.sortsToRun), f.value.allFilters) });
5039
+ class TableHeaderMenuComponent {
5040
+ menu = viewChild.required(MatMenu);
5041
+ exportToCsvService = inject(ExportToCsvService);
5042
+ tableContainer = inject(TableContainerComponent);
5043
+ state = this.tableContainer.state;
5044
+ $rowHeightNum = computed(() => +(this.tableContainer.$genericTable()?.$rowHeight()?.replace('px', '') || 0));
5045
+ $headerHeightNum = computed(() => +(this.tableContainer.$genericTable()?.$headerHeight()?.replace('px', '') || 0));
5046
+ exportToCsv() {
5047
+ this.exportToCsvService.exportToCsv(this.tableContainer.$data());
5048
+ }
5049
+ updateHeight(v, element) {
5050
+ if (+element.value < 10)
5051
+ element.value = '10';
5052
+ if (+element.value > 100)
5053
+ element.value = '100';
5054
+ if (v === 'row')
5055
+ this.state.setUserDefinedRowHeight(+element.value);
5056
+ if (v === 'header')
5057
+ this.state.setUserDefinedHeaderHeight(+element.value);
5058
+ }
5059
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: TableHeaderMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5060
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: TableHeaderMenuComponent, isStandalone: true, selector: "lib-table-header-menu", viewQueries: [{ propertyName: "menu", first: true, predicate: MatMenu, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-menu #mainMenu='matMenu' [xPosition]=\"'before'\">\r\n <span [matTooltip]=\"!r.$set().length ? 'Nothing To Reset' : ''\">\r\n <button mat-menu-item [matMenuTriggerFor]=\"r.menu()\" #d=\"matMenuItem\" [disabled]=\"!r.$set().length\">\r\n <mat-icon color=\"primary\">autorenew</mat-icon>\r\n <span>Reset</span>\r\n </button>\r\n </span>\r\n @if (!tableContainer.state.$tableSettings().hideExport) {\r\n <button mat-menu-item (click)=\"exportToCsv()\">\r\n <mat-icon color=\"primary\">file_download</mat-icon>\r\n <span>Export Table</span>\r\n </button>\r\n }\r\n @if (tableContainer.$tableId(); as tableId) {\r\n <button stop-propagation mat-menu-item [matMenuTriggerFor]=\"pm.menu()\">\r\n <mat-icon color=\"primary\">people</mat-icon>\r\n <span>Profiles</span>\r\n </button>\r\n <tb-profiles-menu class=\"profiles-menu\" #pm [tableId]=\"tableId\" [isMatMenuChild]=\"true\" />\r\n }\r\n\r\n\r\n <div mat-menu-item>\r\n <div class=\"height-input-wrapper\">\r\n <span>Row Height</span>\r\n <input #i class=\"input\" stop-propagation type=\"number\" [value]=\"$rowHeightNum()\" (change)=\"updateHeight('row', i)\" [min]=\"10\" [max]=\"100\" />\r\n </div>\r\n </div>\r\n @if(!state.$tableSettings().hideHeader)\r\n {\r\n <div mat-menu-item>\r\n <div class=\"height-input-wrapper\">\r\n <span>Header Height</span>\r\n <input #i2 class=\"input\" stop-propagation type=\"number\" [value]=\"$headerHeightNum()\" (change)=\"updateHeight('header', i2)\" [min]=\"10\" [max]=\"100\"/>\r\n </div>\r\n </div>\r\n }\r\n</mat-menu>\r\n<lib-reset-menu #r/>\r\n\r\n", styles: [".input{appearance:none;border:none;outline:none;background:none;box-shadow:none;margin:0;font:inherit;color:inherit;border:1px solid black;border-radius:4px;width:50px;padding:0 0 0 4px}.height-input-wrapper{display:flex;gap:4px}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ProfilesMenuComponent, selector: "tb-profiles-menu", inputs: ["tableId", "isMatMenuChild"] }, { kind: "component", type: ResetMenuComponent, selector: "lib-reset-menu", outputs: ["onStateReset"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }] });
5061
+ }
5062
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: TableHeaderMenuComponent, decorators: [{
5063
+ type: Component,
5064
+ args: [{ selector: 'lib-table-header-menu', imports: [MatMenuModule, MatIcon, ProfilesMenuComponent, ResetMenuComponent, MatTooltip, StopPropagationDirective], template: "<mat-menu #mainMenu='matMenu' [xPosition]=\"'before'\">\r\n <span [matTooltip]=\"!r.$set().length ? 'Nothing To Reset' : ''\">\r\n <button mat-menu-item [matMenuTriggerFor]=\"r.menu()\" #d=\"matMenuItem\" [disabled]=\"!r.$set().length\">\r\n <mat-icon color=\"primary\">autorenew</mat-icon>\r\n <span>Reset</span>\r\n </button>\r\n </span>\r\n @if (!tableContainer.state.$tableSettings().hideExport) {\r\n <button mat-menu-item (click)=\"exportToCsv()\">\r\n <mat-icon color=\"primary\">file_download</mat-icon>\r\n <span>Export Table</span>\r\n </button>\r\n }\r\n @if (tableContainer.$tableId(); as tableId) {\r\n <button stop-propagation mat-menu-item [matMenuTriggerFor]=\"pm.menu()\">\r\n <mat-icon color=\"primary\">people</mat-icon>\r\n <span>Profiles</span>\r\n </button>\r\n <tb-profiles-menu class=\"profiles-menu\" #pm [tableId]=\"tableId\" [isMatMenuChild]=\"true\" />\r\n }\r\n\r\n\r\n <div mat-menu-item>\r\n <div class=\"height-input-wrapper\">\r\n <span>Row Height</span>\r\n <input #i class=\"input\" stop-propagation type=\"number\" [value]=\"$rowHeightNum()\" (change)=\"updateHeight('row', i)\" [min]=\"10\" [max]=\"100\" />\r\n </div>\r\n </div>\r\n @if(!state.$tableSettings().hideHeader)\r\n {\r\n <div mat-menu-item>\r\n <div class=\"height-input-wrapper\">\r\n <span>Header Height</span>\r\n <input #i2 class=\"input\" stop-propagation type=\"number\" [value]=\"$headerHeightNum()\" (change)=\"updateHeight('header', i2)\" [min]=\"10\" [max]=\"100\"/>\r\n </div>\r\n </div>\r\n }\r\n</mat-menu>\r\n<lib-reset-menu #r/>\r\n\r\n", styles: [".input{appearance:none;border:none;outline:none;background:none;box-shadow:none;margin:0;font:inherit;color:inherit;border:1px solid black;border-radius:4px;width:50px;padding:0 0 0 4px}.height-input-wrapper{display:flex;gap:4px}\n"] }]
5065
+ }] });
5066
+
5067
+ class TableVirtualScrollStrategy {
5068
+ scrolledIndexChange;
5069
+ dataLength = 0;
5070
+ indexChange = new Subject();
5071
+ viewport;
5072
+ $rowHeight;
5073
+ $rowHeightChange = linkedSignal({
5074
+ source: () => this.$rowHeight(),
5075
+ computation: (curr, previous) => ({ curr, previous: previous?.source || curr })
5076
+ });
5077
+ $headerHeight;
5078
+ constructor(scrollContainer) {
5079
+ this.scrolledIndexChange = this.indexChange.pipe(distinctUntilChanged());
5080
+ this.$rowHeight = scrollContainer.computedRowHeight;
5081
+ this.$headerHeight = scrollContainer.computedHeaderHeight;
4937
5082
  }
4938
- if (sort.timestamp > f.timestamp) {
4939
- return ({ mappedData: sortData(resultData, sort.value.sortsToRun) });
5083
+ attach(viewport) {
5084
+ this.viewport = viewport;
5085
+ this.onDataLengthChanged();
4940
5086
  }
4941
- return ({ mappedData: filterData(resultData, f.value.onlyAddedFilters || f.value.allFilters, !f.value.onlyAddedFilters) });
4942
- }, { mappedData: [] })).pipe(map$1(({ mappedData: resultData }) => resultData.filter(item => !item[tbNoShowSymbol])), defaultShareReplay());
4943
- const createDataCleaners = (metadatas, mutate = false) => {
4944
- const transforms = createCleaners(metadatas);
4945
- return (data) => {
4946
- if (!mutate) {
4947
- data = { ...data };
4948
- }
4949
- for (const transform of transforms) {
4950
- transform(data);
4951
- }
4952
- return data;
4953
- };
4954
- };
4955
- const createCleaners = (metadatas) => {
4956
- return metadatas.reduce((transforms, metaData) => {
4957
- const notNestedKey = metaData.key;
4958
- switch (metaData.fieldType) {
4959
- case FieldType.Currency:
4960
- case FieldType.Number: {
4961
- const nested = metaData.key.includes('.');
4962
- if (nested) {
4963
- transforms.push((t) => {
4964
- const val = get(t, metaData.key);
4965
- const num = Number(val);
4966
- set(t, metaData.key, isNaN(num) || val == null ? null : num);
4967
- });
4968
- }
4969
- else {
4970
- transforms.push((t) => {
4971
- const val = t[notNestedKey];
4972
- const num = Number(val);
4973
- t[notNestedKey] = (isNaN(num) || val == null ? null : num);
4974
- });
4975
- }
4976
- break;
4977
- }
4978
- case FieldType.Date: {
4979
- const nested = metaData.key.includes('.');
4980
- if (nested) {
4981
- transforms.push((t) => {
4982
- const val = get(t, metaData.key);
4983
- const date = Date.parse(val);
4984
- if (isNaN(date)) {
4985
- set(t, metaData.key, null);
4986
- return;
4987
- }
4988
- const d = new Date(date);
4989
- d.setHours(0, 0, 0, 0);
4990
- set(t, metaData.key, d);
4991
- });
4992
- }
4993
- else {
4994
- transforms.push((t) => {
4995
- const val = t[notNestedKey];
4996
- const date = Date.parse(val);
4997
- if (isNaN(date)) {
4998
- t[notNestedKey] = null;
4999
- return;
5000
- }
5001
- const d = new Date(date);
5002
- d.setHours(0, 0, 0, 0);
5003
- t[notNestedKey] = d;
5004
- });
5005
- }
5006
- break;
5007
- }
5008
- case FieldType.DateTime: {
5009
- const nested = metaData.key.includes('.');
5010
- if (nested) {
5011
- transforms.push((t) => {
5012
- const val = get(t, metaData.key);
5013
- const dateTime = Date.parse(val);
5014
- if (isNaN(dateTime)) {
5015
- set(t, metaData.key, null);
5016
- return;
5017
- }
5018
- const dt = new Date(dateTime);
5019
- if (metaData.additional?.dateTimeOptions?.includeMilliseconds) {
5020
- set(t, metaData.key, dt);
5021
- return;
5022
- }
5023
- if (metaData.additional?.dateTimeOptions?.includeSeconds) {
5024
- dt.setMilliseconds(0);
5025
- set(t, metaData.key, dt);
5026
- return;
5027
- }
5028
- dt.setSeconds(0, 0);
5029
- set(t, metaData.key, dt);
5030
- });
5031
- }
5032
- else {
5033
- transforms.push((t) => {
5034
- const val = t[notNestedKey];
5035
- const dateTime = Date.parse(val);
5036
- if (isNaN(dateTime)) {
5037
- t[notNestedKey] = null;
5038
- return;
5039
- }
5040
- const dt = new Date(dateTime);
5041
- if (metaData.additional?.dateTimeOptions?.includeMilliseconds) {
5042
- t[notNestedKey] = dt;
5043
- return;
5044
- }
5045
- if (metaData.additional?.dateTimeOptions?.includeSeconds) {
5046
- dt.setMilliseconds(0);
5047
- t[notNestedKey] = dt;
5048
- return;
5049
- }
5050
- dt.setSeconds(0, 0);
5051
- t[notNestedKey] = dt;
5052
- });
5053
- }
5054
- }
5087
+ contentScrolled$ = new Subject();
5088
+ sub = subscriber(this.contentScrolled$.pipe(observeOn(animationFrameScheduler), debounceTime(20)), () => {
5089
+ this.updateContent('scroll');
5090
+ });
5091
+ onContentScrolled() {
5092
+ this.contentScrolled$.next();
5093
+ }
5094
+ onDataLengthChanged() {
5095
+ }
5096
+ setDataLength(length) {
5097
+ this.dataLength = length;
5098
+ if (this.viewport && this.$rowHeight) {
5099
+ this.viewport.setTotalContentSize(this.dataLength * this.$rowHeight());
5100
+ // this.updateContent('data ' + dataTrigger);
5055
5101
  }
5056
- return transforms;
5057
- }, []);
5058
- };
5059
-
5060
- class TableBuilderDataSource extends MatTableDataSource {
5061
- subscription;
5062
- #$dataSrc = signal([]);
5063
- $dataSize = signal({ start: 0, end: 0 }, {
5064
- equal: (a, b) => a.start === b.start && a.end === b.end
5102
+ this.updateContent('data ');
5103
+ }
5104
+ detach() { }
5105
+ onContentRendered() { }
5106
+ onRenderedOffsetChanged() {
5107
+ }
5108
+ scrollToIndex(index, behavior) {
5109
+ }
5110
+ #onHeaderChange = effect(() => {
5111
+ this.$headerHeight && this.$headerHeight();
5112
+ this.updateContent('header height');
5065
5113
  });
5066
- _ = effect(() => {
5067
- const data = this.#$dataSrc();
5068
- const dataSize = this.$dataSize();
5069
- untracked(() => this.data = data.slice(dataSize.start, dataSize.end));
5114
+ #onRowChange = effect(() => {
5115
+ this.$rowHeight && this.$rowHeight();
5116
+ this.updateContent('row height');
5070
5117
  });
5071
- setData(data) {
5072
- this.#$dataSrc.set(data);
5118
+ updateContent(trigger) {
5119
+ if (!this.viewport || !this.$rowHeight) {
5120
+ return;
5121
+ }
5122
+ const currentContentHeight = +this.viewport._totalContentHeight.replace('px', '');
5123
+ const newContentHeight = this.dataLength * this.$rowHeight();
5124
+ if (currentContentHeight !== newContentHeight) {
5125
+ this.viewport.setTotalContentSize(newContentHeight);
5126
+ setTimeout(() => {
5127
+ this.update(trigger);
5128
+ }, 0);
5129
+ return;
5130
+ }
5131
+ this.update(trigger);
5073
5132
  }
5074
- constructor(state, data) {
5075
- super([]);
5076
- const $currentPage = state.$currentPage;
5077
- const $pageSize = state.$pageSize;
5078
- const $virtualEnds = data.selectSignal(d => d.virtualEnds);
5079
- const $dataLength = computed(() => this.#$dataSrc().length);
5080
- const $dataSize = computed(() => {
5081
- const viewType = state.$viewType();
5082
- const dataLength = $dataLength();
5083
- const currentPage = $currentPage();
5084
- const pageSize = $pageSize();
5085
- const virtualEnds = $virtualEnds();
5086
- const previousPageRecords = currentPage * pageSize;
5087
- if (viewType === 'virtual paginator') {
5088
- return ({ start: virtualEnds.start + previousPageRecords, end: Math.min(virtualEnds.end, pageSize) + previousPageRecords });
5089
- }
5090
- if (viewType === 'paginator') {
5091
- return ({ start: previousPageRecords, end: previousPageRecords + pageSize });
5133
+ update(trigger) {
5134
+ if (!this.viewport || !this.$rowHeight) {
5135
+ return;
5136
+ }
5137
+ const rowHeightChangeEvent = this.$rowHeightChange();
5138
+ const rowHeight = rowHeightChangeEvent.curr;
5139
+ const rowHeightAdjustment = trigger === 'row height' ? rowHeightChangeEvent.curr / rowHeightChangeEvent.previous : 1;
5140
+ const amountOfRows = Math.ceil((this.viewport.getViewportSize() - this.$headerHeight()) / rowHeight);
5141
+ const f = this.viewport.measureScrollOffset();
5142
+ const offset = this.viewport.measureScrollOffset() * rowHeightAdjustment;
5143
+ if (offset !== f) {
5144
+ this.viewport.scrollToOffset(offset);
5145
+ }
5146
+ const buffer = 35;
5147
+ const skip = Math.round(offset / rowHeight);
5148
+ const index = skip % 2 === 0 ? skip : skip - 1;
5149
+ const start = Math.max(0, index - buffer);
5150
+ const end = Math.min(this.dataLength, index + amountOfRows + buffer);
5151
+ this.viewport.setRenderedContentOffset(rowHeight * start);
5152
+ this.viewport.setRenderedRange({ start, end });
5153
+ this.indexChange.next(index);
5154
+ }
5155
+ }
5156
+
5157
+ class VirtualScrollContainer {
5158
+ state = inject(TableStore);
5159
+ dataStore = inject(DataStore);
5160
+ viewport = viewChild.required(CdkVirtualScrollViewport);
5161
+ genericTable = contentChild(GenericTableComponent);
5162
+ tableContainer = inject(TableContainerComponent);
5163
+ defaultOptions = new VirtualScrollOptions();
5164
+ $usePaginator = this.state.selectSignal(s => s.notPersistedTableSettings.usePaginator);
5165
+ $pageSize = this.state.$pageSize;
5166
+ $currentPage = this.state.$currentPage;
5167
+ $showAll = this.state.$showAll;
5168
+ $stateDataLength = this.dataStore.selectSignal(s => s.sortedFilteredGroupedDataLength);
5169
+ viewPort$ = toObservable(this.viewport).pipe(notNull());
5170
+ $scrolledIndexChange = toSignal(this.viewPort$.pipe(switchMap$1(v => v.scrolledIndexChange)));
5171
+ $renderedRange = toSignal(this.viewPort$.pipe(switchMap$1(v => v.renderedRangeStream)));
5172
+ $virtualScrollOptions = computed(() => this.state.$tableSettings().virtualSettings);
5173
+ $dataLength = computed(() => {
5174
+ const paginated = this.$usePaginator() && !this.$showAll();
5175
+ const pageSize = this.$pageSize();
5176
+ const pageNumber = this.$currentPage();
5177
+ const dataLen = this.$stateDataLength();
5178
+ if (paginated)
5179
+ return Math.min(dataLen - (pageNumber * pageSize), pageSize);
5180
+ return dataLen;
5181
+ });
5182
+ constructor() {
5183
+ addEventListener('resize', this.resizeHandler);
5184
+ }
5185
+ setViewportEffect = effect(() => {
5186
+ const viewport = this.viewport();
5187
+ untracked(() => {
5188
+ if (!!viewport) {
5189
+ this.setSize(this.viewport().elementRef);
5092
5190
  }
5093
- if (viewType === 'all') {
5094
- return ({ start: 0, end: dataLength });
5191
+ ;
5192
+ });
5193
+ });
5194
+ subscriber = subscriber();
5195
+ #onRenderedRangeEffect = effect(() => {
5196
+ const renderedRange = this.$renderedRange();
5197
+ if (!renderedRange)
5198
+ return;
5199
+ untracked(() => {
5200
+ this.dataStore.patchState({
5201
+ virtualEnds: {
5202
+ start: renderedRange.start,
5203
+ end: renderedRange.end + 25,
5204
+ }
5205
+ });
5206
+ this.setSize(this.viewport().elementRef);
5207
+ });
5208
+ });
5209
+ #onDataLengthEffect = effect(() => {
5210
+ const dataLength = this.$dataLength();
5211
+ untracked(() => {
5212
+ const renderedRange = this.$renderedRange();
5213
+ this.scrollStrategy.setDataLength(dataLength);
5214
+ if ((renderedRange?.start || 0) > dataLength) {
5215
+ this.viewport().scrollToOffset(0);
5095
5216
  }
5096
- return ({ start: virtualEnds.start, end: virtualEnds.end });
5097
5217
  });
5098
- this.$dataSize = $dataSize;
5218
+ });
5219
+ #onOffsetEffect = effect(() => {
5220
+ const offset = this.$offset();
5221
+ untracked(() => {
5222
+ this.dataStore.patchState({ virtualScrollOffset: offset });
5223
+ });
5224
+ });
5225
+ $offset = computed(() => {
5226
+ const viewport = this.viewport();
5227
+ const scrolledIndexChange = this.$scrolledIndexChange();
5228
+ if (!scrolledIndexChange || !viewport)
5229
+ return 0;
5230
+ return viewport.getOffsetToRenderedContentStart() ?? 0;
5231
+ });
5232
+ ngOnDestroy() {
5233
+ removeEventListener('resize', this.resizeHandler);
5099
5234
  }
5100
- connect() {
5101
- return super.connect();
5235
+ setSize(el) {
5236
+ const virtualScrollOptions = this.$virtualScrollOptions();
5237
+ if (virtualScrollOptions.dynamicHeight) {
5238
+ this.calcDynamic(el);
5239
+ return;
5240
+ }
5241
+ const rowHeight = this.computedRowHeight();
5242
+ let amountOfVisibleItems = virtualScrollOptions?.amountOfVisibleItems || this.defaultOptions.amountOfVisibleItems;
5243
+ amountOfVisibleItems = Math.min(amountOfVisibleItems, this.$dataLength());
5244
+ let height = (rowHeight * amountOfVisibleItems);
5245
+ const footerHeight = this.computedFooterHeight();
5246
+ const headerHeight = this.computedHeaderHeight();
5247
+ height += (footerHeight + headerHeight);
5248
+ const maxViewPortHeightPx = parseTbSizeToPixels(virtualScrollOptions.maxViewPortHeight) || 0;
5249
+ if (virtualScrollOptions?.maxViewPortHeight && maxViewPortHeightPx)
5250
+ height = maxViewPortHeightPx;
5251
+ this.setHeight(height, el);
5102
5252
  }
5103
- disconnect() {
5104
- if (this.subscription) {
5105
- this.subscription.unsubscribe();
5106
- this.subscription = undefined;
5253
+ calcDynamic$ = new Subject();
5254
+ $calcDynamic = toSignal(this.calcDynamic$.pipe(debounceTime$1(300)));
5255
+ #onCalcDynamicEffect = effect(() => {
5256
+ const el = this.$calcDynamic();
5257
+ if (!el)
5258
+ return;
5259
+ untracked(() => {
5260
+ this.calcDynamic(el);
5261
+ });
5262
+ });
5263
+ calcDynamic(el) {
5264
+ const virtualScrollOptions = this.$virtualScrollOptions();
5265
+ const t = this.tableContainer.elementRef.nativeElement.querySelector(`#${TableContainerComponent.headerId}`);
5266
+ const rect = t?.getBoundingClientRect();
5267
+ const viewportHeight = window.innerHeight;
5268
+ const distanceFromBottom = viewportHeight - rect.bottom;
5269
+ const rowHeight = this.computedRowHeight();
5270
+ const footerHeight = this.computedFooterHeight();
5271
+ const headerHeight = this.computedHeaderHeight();
5272
+ const maxViewPortHeightPx = parseTbSizeToPixels(virtualScrollOptions.maxViewPortHeight) || 0;
5273
+ let tableSize = distanceFromBottom;
5274
+ if (virtualScrollOptions?.maxViewPortHeight && maxViewPortHeightPx < tableSize) {
5275
+ tableSize = maxViewPortHeightPx;
5107
5276
  }
5108
- super.disconnect();
5277
+ const available = (distanceFromBottom - footerHeight) - headerHeight - (this.$usePaginator() ? 20 : 0);
5278
+ const amountOfRowsThatWillFit = Math.floor(available / rowHeight);
5279
+ const minAmountOfRows = virtualScrollOptions?.amountOfVisibleItems || this.defaultOptions.amountOfVisibleItems;
5280
+ const amountOfVisibleItems = Math.min(Math.max(amountOfRowsThatWillFit, minAmountOfRows), this.$dataLength());
5281
+ let height = (rowHeight * amountOfVisibleItems);
5282
+ height += (footerHeight + headerHeight) - 10;
5283
+ this.setHeight(height, el);
5109
5284
  }
5110
- }
5111
-
5112
- function mergeCustomCellMetaData(metaData1, metaData2) {
5113
- if (!metaData2) {
5114
- metaData1.noExport = true;
5115
- return metaData1;
5285
+ setHeight(height, el) {
5286
+ const vsViewport = el.nativeElement;
5287
+ vsViewport.setAttribute('style', `height: ${height}px !important;`);
5288
+ this.viewport()?.checkViewportSize();
5289
+ const virtualScrollOffset = this.viewport()?.getOffsetToRenderedContentStart() ?? 0;
5290
+ this.dataStore.patchState({ virtualScrollOffset });
5116
5291
  }
5117
- if (!metaData1.displayName)
5118
- metaData1.displayName = metaData2.displayName;
5119
- if (!metaData1.preSort)
5120
- metaData1.preSort = metaData2.preSort;
5121
- if (!metaData1.order)
5122
- metaData1.order = metaData2.order;
5123
- if (!metaData1.width)
5124
- metaData1.width = metaData2.width;
5125
- if (metaData2.fieldType)
5126
- metaData1.fieldType = metaData2.fieldType;
5127
- metaData1.noExport = metaData2.noExport;
5128
- return metaData1;
5292
+ resizeHandler = () => {
5293
+ if (this.viewport() && this.$virtualScrollOptions().dynamicHeight) {
5294
+ this.setSize(this.viewport().elementRef);
5295
+ }
5296
+ };
5297
+ computedRowHeight = computed(() => {
5298
+ const virtualScrollOptions = this.state.$tableSettings().virtualSettings;
5299
+ const rowHeight = this.state.$userDefinedRowHeight() || virtualScrollOptions?.rowHeight || this.state.$tableSettings().rowHeight || this.defaultOptions.rowHeight;
5300
+ return parseTbSizeToPixels(rowHeight) || 0;
5301
+ });
5302
+ computedHeaderHeight = computed(() => {
5303
+ if (this.state.$tableSettings().hideHeader)
5304
+ return 0;
5305
+ const virtualScrollOptions = this.state.$tableSettings().virtualSettings;
5306
+ const headerHeight = this.state.$userDefinedHeaderHeight() || virtualScrollOptions?.headerHeight || this.state.$tableSettings().headerHeight || this.defaultOptions.headerHeight;
5307
+ return parseTbSizeToPixels(headerHeight) || 0;
5308
+ });
5309
+ computedFooterHeight = computed(() => {
5310
+ return parseFloat(this.genericTable()?.$footerHeight()?.replace('px', '') || '0');
5311
+ });
5312
+ scrollStrategy = new TableVirtualScrollStrategy(this);
5313
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: VirtualScrollContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
5314
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.0.0", type: VirtualScrollContainer, isStandalone: true, selector: "tb-virtual-scroll-container", queries: [{ propertyName: "genericTable", first: true, predicate: GenericTableComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: `
5315
+ <cdk-virtual-scroll-viewport>
5316
+ <ng-content/>
5317
+ </cdk-virtual-scroll-viewport>
5318
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ScrollingModule }, { kind: "component", type: i1$8.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }], viewProviders: [
5319
+ {
5320
+ provide: VIRTUAL_SCROLL_STRATEGY,
5321
+ useFactory: (c) => c.scrollStrategy,
5322
+ deps: [forwardRef(() => VirtualScrollContainer)],
5323
+ },
5324
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5129
5325
  }
5326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: VirtualScrollContainer, decorators: [{
5327
+ type: Component,
5328
+ args: [{
5329
+ selector: 'tb-virtual-scroll-container',
5330
+ template: `
5331
+ <cdk-virtual-scroll-viewport>
5332
+ <ng-content/>
5333
+ </cdk-virtual-scroll-viewport>
5334
+ `,
5335
+ changeDetection: ChangeDetectionStrategy.OnPush,
5336
+ imports: [ScrollingModule],
5337
+ viewProviders: [
5338
+ {
5339
+ provide: VIRTUAL_SCROLL_STRATEGY,
5340
+ useFactory: (c) => c.scrollStrategy,
5341
+ deps: [forwardRef(() => VirtualScrollContainer)],
5342
+ },
5343
+ ],
5344
+ }]
5345
+ }], ctorParameters: () => [] });
5130
5346
 
5131
5347
  class TableContainerComponent {
5132
5348
  state = inject(TableStore);
5133
5349
  dataStore = inject(DataStore);
5134
- exportToCsvService = inject((ExportToCsvService));
5135
5350
  wrapper = inject(TableWrapperDirective, { optional: true });
5136
5351
  stateService = inject(TableBuilderStateStore);
5137
5352
  injector = inject(Injector);
@@ -5144,6 +5359,11 @@ class TableContainerComponent {
5144
5359
  _$customRows = contentChildren((MatRowDef));
5145
5360
  $customRows = computed(() => [...this._$customRows()]);
5146
5361
  $customCells = contentChildren(CustomCellDirective);
5362
+ $menu = viewChild.required(MatMenu);
5363
+ menuInjector = Injector.create({
5364
+ providers: [{ provide: MatMenu, useFactory: () => this.$menu() }],
5365
+ parent: this.injector
5366
+ });
5147
5367
  $tableBuilder = input.required({ alias: 'tableBuilder' });
5148
5368
  $tableId = input(undefined, { alias: 'tableId' });
5149
5369
  $trackBy = input(undefined, { alias: 'trackBy' });
@@ -5198,15 +5418,6 @@ class TableContainerComponent {
5198
5418
  $collapsedFooter = this.state.$footerCollapsed;
5199
5419
  $collapsedHeader = this.state.$headerCollapsed;
5200
5420
  $displayDataLength = computed(() => this.$displayData().length);
5201
- resetState() {
5202
- this.$customFilterDirectives().forEach(cf => cf.reset());
5203
- this.$filterDirectives().forEach(cf => cf.reset());
5204
- this.state.resetState();
5205
- this.onStateReset$.emit(null);
5206
- }
5207
- exportToCsv() {
5208
- this.exportToCsvService.exportToCsv(this.$data());
5209
- }
5210
5421
  #initializeTableSettingsFromTableBuilderAndPersistedStateEffect = effect(() => {
5211
5422
  const metaLoaded = this.$isInitializationState(InitializationState.MetaDataLoaded)();
5212
5423
  if (!metaLoaded)
@@ -5218,18 +5429,19 @@ class TableContainerComponent {
5218
5429
  persistedState.persistedTableSettings = new PersistedTableSettings(persistedState.persistedTableSettings);
5219
5430
  this.state.updateStateFromPersistedState(persistedState);
5220
5431
  }
5221
- this.state.setInitializationState(InitializationState.LoadedFromStore);
5432
+ this.state.setInitializationState(InitializationState.Ready);
5222
5433
  });
5223
5434
  });
5224
5435
  #setPageSizeFromInputEffect = effect(() => {
5225
5436
  const pageSize = this.$pageSize();
5226
- if (pageSize) {
5437
+ const userDefinedPageSize = this.state.$userDefinedPageSize();
5438
+ if (pageSize && !userDefinedPageSize) {
5227
5439
  untracked(() => this.state.setPageSize(pageSize));
5228
5440
  }
5229
5441
  });
5230
5442
  #patchedFilters = [];
5231
5443
  #patchSavableFilterDirectivesFromPersistedStateEffect = effect(() => {
5232
- const loaded = this.$isInitializationState(InitializationState.LoadedFromStore)();
5444
+ const loaded = this.$isInitializationState(InitializationState.TableSettingsLoaded)();
5233
5445
  const filterDirectives = this.$allFilterDirectives();
5234
5446
  if (!loaded || !filterDirectives.length)
5235
5447
  return;
@@ -5244,7 +5456,7 @@ class TableContainerComponent {
5244
5456
  });
5245
5457
  });
5246
5458
  #patchSavableFilterInputsFromPersistedStateEffect = effect(() => {
5247
- const loaded = this.$isInitializationState(InitializationState.LoadedFromStore)();
5459
+ const loaded = this.$isInitializationState(InitializationState.TableSettingsLoaded)();
5248
5460
  const inputFilters = this.$filterInfoInputs();
5249
5461
  if (!loaded || !inputFilters.length)
5250
5462
  return;
@@ -5332,22 +5544,27 @@ class TableContainerComponent {
5332
5544
  const flatGrouped$ = combineLatest([sortedAndFilteredData$.pipe(timestamp$1()), this.state.groupByKeys$.pipe(timestamp$1()), this.state.expandedGroups$.pipe(timestamp$1())]).pipe(scan$1(updateGroupByState, initialGroupByState), map(({ displayData }) => displayData), defaultShareReplay());
5333
5545
  this.state.on(sortedAndFilteredData$, (data) => {
5334
5546
  this._data$.next(data);
5335
- this.dataStore.patchState({ dataLen: data.length });
5547
+ this.dataStore.patchState({ sortedFilteredDataLength: data.length });
5336
5548
  });
5337
5549
  this.state.on(flatGrouped$, (data) => {
5338
5550
  this.dataSource.setData(data);
5339
5551
  this.$displayData.set(data);
5552
+ this.dataStore.patchState({ sortedFilteredGroupedDataLength: data.length });
5340
5553
  });
5341
5554
  }
5342
5555
  $isInitializationState = (state) => computed(() => this.state.selectSignal(s => s.initializationState >= state)());
5343
5556
  static headerId = 'tb-header-wrapper';
5344
5557
  headerId = TableContainerComponent.headerId;
5345
5558
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: TableContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5346
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: TableContainerComponent, isStandalone: true, selector: "tb-table-container", inputs: { $tableBuilder: { classPropertyName: "$tableBuilder", publicName: "tableBuilder", isSignal: true, isRequired: true, transformFunction: null }, $tableId: { classPropertyName: "$tableId", publicName: "tableId", isSignal: true, isRequired: false, transformFunction: null }, $trackBy: { classPropertyName: "$trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, $inputFilters: { classPropertyName: "$inputFilters", publicName: "inputFilters", isSignal: true, isRequired: false, transformFunction: null }, $indexColumn: { classPropertyName: "$indexColumn", publicName: "indexColumn", isSignal: true, isRequired: false, transformFunction: null }, $selectionColumn: { classPropertyName: "$selectionColumn", publicName: "selectionColumn", isSignal: true, isRequired: false, transformFunction: null }, $isSticky: { classPropertyName: "$isSticky", publicName: "isSticky", isSignal: true, isRequired: false, transformFunction: null }, $stickyFooter: { classPropertyName: "$stickyFooter", publicName: "stickyFooter", isSignal: true, isRequired: false, transformFunction: null }, $groupHeaderTemplate: { classPropertyName: "$groupHeaderTemplate", publicName: "groupHeaderTemplate", isSignal: true, isRequired: false, transformFunction: null }, $groupHeaderHeight: { classPropertyName: "$groupHeaderHeight", publicName: "groupHeaderHeight", isSignal: true, isRequired: false, transformFunction: null }, $pageSize: { classPropertyName: "$pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { $inputFilters: "inputFiltersChange", selection$: "selection", onStateReset$: "onStateReset", onSaveState$: "onSaveState", state$: "state", data$: "data" }, providers: [TableStore, ExportToCsvService, WrapperFilterStore, DataStore], queries: [{ propertyName: "$filterDirectives", predicate: TableFilterDirective, descendants: true, isSignal: true }, { propertyName: "$customFilterDirectives", predicate: TableCustomFilterDirective, descendants: true, isSignal: true }, { propertyName: "_$customRows", predicate: (MatRowDef), isSignal: true }, { propertyName: "$customCells", predicate: CustomCellDirective, isSignal: true }], viewQueries: [{ propertyName: "$paginatorComponent", first: true, predicate: PaginatorComponent, descendants: true, isSignal: true }, { propertyName: "$genericTable", first: true, predicate: GenericTableComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@let tableId = $tableId();\r\n@let tableSettings = state.$tableSettings();\r\n\r\n<ng-content select=\"[before]\" />\r\n<ng-container multiSort>\r\n <div class=\"tb-header-wrapper\" [id]=\"headerId\">\r\n <div class=\"title\">\r\n @if ((!$collapsedHeader()) || tableSettings.showTitleWhenHeaderCollapsed) {\r\n <ng-content select=\".tb-header-title\"/>\r\n }\r\n @if(state.$groupByKeys().length){\r\n <group-by-list />\r\n }\r\n </div>\r\n <div class=\"flx-row-end\">\r\n <lib-filter-list />\r\n @if (!tableSettings.hideHeader) {\r\n @if (!$collapsedHeader()) {\r\n <ng-container *ngTemplateOutlet=\"headerMenu\"/>\r\n <button mat-icon-button color='primary' [matMenuTriggerFor]=\"mainMenu\">\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n <mat-menu #mainMenu='matMenu'>\r\n <ng-container *ngTemplateOutlet=\"headerMenuExtra\"/>\r\n </mat-menu>\r\n }\r\n @else {\r\n <mat-icon color=\"primary\" [matMenuTriggerFor]=\"mainMenu\" class=\"flat-menu-button pointer\">more_horiz</mat-icon>\r\n <mat-menu #mainMenu='matMenu'>\r\n <div class=\"flex-column\">\r\n <ng-container *ngTemplateOutlet=\"headerMenu\"/>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"headerMenuExtra\"/>\r\n </mat-menu>\r\n }\r\n <mat-icon [matTooltip]=\"$collapsedHeader() ? 'expand' : 'collapse'\" class=\"collapse-icon header\"\r\n (click)=\"state.toggleCollapseHeader()\">\r\n {{$collapsedHeader() ? 'expand_less' : 'expand_more'}}\r\n </mat-icon>\r\n }\r\n\r\n </div>\r\n </div>\r\n\r\n @if($useVirtual())\r\n {\r\n <tb-virtual-scroll-container class=\"scrollable\">\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayDataLength]=\"$displayDataLength()\"\r\n (selection)='selection$.emit($event)' [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" />\r\n </tb-virtual-scroll-container>\r\n }\r\n @else\r\n {\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayDataLength]=\"$displayDataLength()\"\r\n (selection)='selection$.emit($event)' [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" />\r\n }\r\n @if(tableSettings.usePaginator)\r\n {\r\n <div class=\"paginator\">\r\n <tb-paginator #tbPaginator />\r\n\r\n <mat-icon [matTooltip]=\"$collapsedFooter() ? 'expand' : 'collapse'\" class=\"collapse-icon footer\"\r\n (click)=\"state.toggleCollapseFooter()\">\r\n {{$collapsedFooter() ? 'expand_more' : 'expand_less'}}\r\n </mat-icon>\r\n </div>\r\n }\r\n\r\n <ng-template #headerMenu>\r\n @if (!tableSettings.hideFilter) {<tb-filter-displayer/>}\r\n @if (!tableSettings.hideColumnSettings) {<tb-col-displayer/>}\r\n @if (!tableSettings.hideSort) {<tb-sort-menu/>}\r\n @if (!!tableId) {<tb-profiles-menu [$tableId]=\"tableId\" (onSaveState)=\"onSaveState$.emit($event)\"/>}\r\n </ng-template>\r\n\r\n <ng-template #headerMenuExtra>\r\n <button mat-menu-item (click)=\"resetState()\">\r\n <mat-icon color=\"primary\">autorenew</mat-icon>\r\n <span>Reset table</span>\r\n </button>\r\n @if (!tableSettings.hideExport) {\r\n <button mat-menu-item (click)=\"exportToCsv()\">\r\n <mat-icon color=\"primary\">file_download</mat-icon>\r\n <span>Export Table</span>\r\n </button>\r\n }\r\n @if (tableId) {\r\n <button stop-propagation mat-menu-item (click)=\"pm.trigger()?.toggleMenu()\">\r\n <mat-icon color=\"primary\">people</mat-icon>\r\n <span>Profiles</span>\r\n </button>\r\n <tb-profiles-menu class=\"profiles-menu\" #pm [$tableId]=\"tableId\" (onSaveState)=\"onSaveState$.emit($event)\"/>\r\n }\r\n </ng-template>\r\n</ng-container>\r\n", styles: [".tb-header-wrapper{display:flex;flex-direction:row;justify-content:space-between;width:100%}.flx-row-end{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.flat-menu{line-height:initial;height:initial}.pointer{cursor:pointer}.add-key{width:90%}.paginator{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;background-color:#fff;bottom:0;position:sticky;border-top:.5px solid rgba(0,0,0,.12)}.profiles-menu{visibility:hidden;width:0px;height:0px;display:block;overflow:hidden;position:absolute;top:50px}\n", ".collapse-icon{font-size:16px;height:16px;color:#3f51b5;align-self:flex-start}.collapse-icon:hover{cursor:pointer}.hide{display:none}.paginator-row{display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: i1$8.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PaginatorComponent, selector: "tb-paginator" }, { kind: "directive", type: MultiSortDirective, selector: "[multiSort]", inputs: ["matSortDisabled"], exportAs: ["multiSort"] }, { kind: "component", type: GroupByListComponent, selector: "group-by-list" }, { kind: "component", type: FilterChipsComponent, selector: "lib-filter-list" }, { kind: "component", type: GenFilterDisplayerComponent, selector: "tb-filter-displayer" }, { kind: "component", type: GenColDisplayerComponent, selector: "tb-col-displayer" }, { kind: "component", type: SortMenuComponent, selector: "tb-sort-menu" }, { kind: "component", type: GenericTableComponent, selector: "tb-generic-table", inputs: ["displayDataLength", "data", "rows", "columnInfos", "dataSource", "trackBy"], outputs: ["selection"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }, { kind: "component", type: ProfilesMenuComponent, selector: "tb-profiles-menu", inputs: ["$tableId"], outputs: ["onSaveState"] }, { kind: "ngmodule", type: i3$1.MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: i4$2.MatMenuModule }, { kind: "component", type: i4$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: i2.MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: i4$1.MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: VirtualScrollContainer, selector: "tb-virtual-scroll-container" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5559
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: TableContainerComponent, isStandalone: true, selector: "tb-table-container", inputs: { $tableBuilder: { classPropertyName: "$tableBuilder", publicName: "tableBuilder", isSignal: true, isRequired: true, transformFunction: null }, $tableId: { classPropertyName: "$tableId", publicName: "tableId", isSignal: true, isRequired: false, transformFunction: null }, $trackBy: { classPropertyName: "$trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, $inputFilters: { classPropertyName: "$inputFilters", publicName: "inputFilters", isSignal: true, isRequired: false, transformFunction: null }, $indexColumn: { classPropertyName: "$indexColumn", publicName: "indexColumn", isSignal: true, isRequired: false, transformFunction: null }, $selectionColumn: { classPropertyName: "$selectionColumn", publicName: "selectionColumn", isSignal: true, isRequired: false, transformFunction: null }, $isSticky: { classPropertyName: "$isSticky", publicName: "isSticky", isSignal: true, isRequired: false, transformFunction: null }, $stickyFooter: { classPropertyName: "$stickyFooter", publicName: "stickyFooter", isSignal: true, isRequired: false, transformFunction: null }, $groupHeaderTemplate: { classPropertyName: "$groupHeaderTemplate", publicName: "groupHeaderTemplate", isSignal: true, isRequired: false, transformFunction: null }, $groupHeaderHeight: { classPropertyName: "$groupHeaderHeight", publicName: "groupHeaderHeight", isSignal: true, isRequired: false, transformFunction: null }, $pageSize: { classPropertyName: "$pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { $inputFilters: "inputFiltersChange", selection$: "selection", onStateReset$: "onStateReset", onSaveState$: "onSaveState", state$: "state", data$: "data" }, providers: [TableStore, ExportToCsvService, WrapperFilterStore, DataStore], queries: [{ propertyName: "$filterDirectives", predicate: TableFilterDirective, descendants: true, isSignal: true }, { propertyName: "$customFilterDirectives", predicate: TableCustomFilterDirective, descendants: true, isSignal: true }, { propertyName: "_$customRows", predicate: (MatRowDef), isSignal: true }, { propertyName: "$customCells", predicate: CustomCellDirective, isSignal: true }], viewQueries: [{ propertyName: "$paginatorComponent", first: true, predicate: PaginatorComponent, descendants: true, isSignal: true }, { propertyName: "$genericTable", first: true, predicate: GenericTableComponent, descendants: true, isSignal: true }, { propertyName: "$menu", first: true, predicate: MatMenu, descendants: true, isSignal: true }], ngImport: i0, template: "@let tableId = $tableId();\r\n@let tableSettings = state.$tableSettings();\r\n\r\n<ng-content select=\"[before]\" />\r\n<ng-container multiSort>\r\n <div class=\"tb-header-wrapper\" [id]=\"headerId\">\r\n <div class=\"title\">\r\n @if ((!$collapsedHeader()) || tableSettings.showTitleWhenHeaderCollapsed) {\r\n <ng-content select=\".tb-header-title\"/>\r\n }\r\n @if(state.$groupByKeys().length){\r\n <group-by-list />\r\n }\r\n </div>\r\n <div class=\"flx-row-end\">\r\n <lib-filter-list />\r\n @if (!tableSettings.hideHeader) {\r\n @if (!$collapsedHeader()) {\r\n <ng-container *ngTemplateOutlet=\"headerMenu\"/>\r\n <button mat-icon-button color='primary' [matMenuTriggerFor]=\"l.menu()\">\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n\r\n <lib-table-header-menu #l/>\r\n\r\n }\r\n @else {\r\n <mat-icon color=\"primary\" [matMenuTriggerFor]=\"mainMenu\" class=\"flat-menu-button pointer\">more_horiz</mat-icon>\r\n <mat-menu #mainMenu='matMenu'>\r\n <div class=\"flex-column\">\r\n <ng-container *ngTemplateOutlet=\"headerMenu; injector menuInjector\"/>\r\n </div>\r\n <lib-table-header-menu />\r\n </mat-menu>\r\n }\r\n <mat-icon [matTooltip]=\"$collapsedHeader() ? 'expand' : 'collapse'\" class=\"collapse-icon header\"\r\n (click)=\"state.toggleCollapseHeader()\">\r\n {{$collapsedHeader() ? 'expand_less' : 'expand_more'}}\r\n </mat-icon>\r\n }\r\n\r\n </div>\r\n </div>\r\n\r\n @if($useVirtual())\r\n {\r\n <tb-virtual-scroll-container class=\"scrollable\">\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayDataLength]=\"$displayDataLength()\"\r\n (selection)='selection$.emit($event)' [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" />\r\n </tb-virtual-scroll-container>\r\n }\r\n @else\r\n {\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayDataLength]=\"$displayDataLength()\"\r\n (selection)='selection$.emit($event)' [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" />\r\n }\r\n @if(tableSettings.usePaginator)\r\n {\r\n <div class=\"paginator\">\r\n <tb-paginator #tbPaginator />\r\n\r\n <mat-icon [matTooltip]=\"$collapsedFooter() ? 'expand' : 'collapse'\" class=\"collapse-icon footer\"\r\n (click)=\"state.toggleCollapseFooter()\">\r\n {{$collapsedFooter() ? 'expand_more' : 'expand_less'}}\r\n </mat-icon>\r\n </div>\r\n }\r\n\r\n <ng-template #headerMenu>\r\n @if (!tableSettings.hideFilter) {<tb-filter-displayer/>}\r\n @if (!tableSettings.hideColumnSettings) {<tb-col-displayer/>}\r\n @if (!tableSettings.hideSort) {<tb-sort-menu/>}\r\n @if (!!tableId) {<tb-profiles-menu [tableId]=\"tableId\"/>}\r\n </ng-template>\r\n\r\n</ng-container>\r\n", styles: [".tb-header-wrapper{display:flex;flex-direction:row;justify-content:space-between;width:100%}.flx-row-end{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.flat-menu{line-height:initial;height:initial}.pointer{cursor:pointer}.add-key{width:90%}.paginator{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;background-color:#fff;bottom:0;position:sticky;border-top:.5px solid rgba(0,0,0,.12)}.profiles-menu{visibility:hidden;width:0px;height:0px;display:block;overflow:hidden;position:absolute;top:50px}\n", ".collapse-icon{font-size:16px;height:16px;color:#3f51b5;align-self:flex-start}.collapse-icon:hover{cursor:pointer}.hide{display:none}.paginator-row{display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PaginatorComponent, selector: "tb-paginator" }, { kind: "directive", type: MultiSortDirective, selector: "[multiSort]", inputs: ["matSortDisabled"], exportAs: ["multiSort"] }, { kind: "component", type: GroupByListComponent, selector: "group-by-list" }, { kind: "component", type: FilterChipsComponent, selector: "lib-filter-list" }, { kind: "component", type: GenFilterDisplayerComponent, selector: "tb-filter-displayer" }, { kind: "component", type: GenColDisplayerComponent, selector: "tb-col-displayer" }, { kind: "component", type: SortMenuComponent, selector: "tb-sort-menu" }, { kind: "component", type: GenericTableComponent, selector: "tb-generic-table", inputs: ["displayDataLength", "data", "rows", "columnInfos", "dataSource", "trackBy"], outputs: ["selection"] }, { kind: "component", type: ProfilesMenuComponent, selector: "tb-profiles-menu", inputs: ["tableId", "isMatMenuChild"] }, { kind: "component", type: TableHeaderMenuComponent, selector: "lib-table-header-menu" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: VirtualScrollContainer, selector: "tb-virtual-scroll-container" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5347
5560
  }
5348
5561
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: TableContainerComponent, decorators: [{
5349
5562
  type: Component,
5350
- args: [{ selector: 'tb-table-container', changeDetection: ChangeDetectionStrategy.OnPush, providers: [TableStore, ExportToCsvService, WrapperFilterStore, DataStore], imports: containerImports, template: "@let tableId = $tableId();\r\n@let tableSettings = state.$tableSettings();\r\n\r\n<ng-content select=\"[before]\" />\r\n<ng-container multiSort>\r\n <div class=\"tb-header-wrapper\" [id]=\"headerId\">\r\n <div class=\"title\">\r\n @if ((!$collapsedHeader()) || tableSettings.showTitleWhenHeaderCollapsed) {\r\n <ng-content select=\".tb-header-title\"/>\r\n }\r\n @if(state.$groupByKeys().length){\r\n <group-by-list />\r\n }\r\n </div>\r\n <div class=\"flx-row-end\">\r\n <lib-filter-list />\r\n @if (!tableSettings.hideHeader) {\r\n @if (!$collapsedHeader()) {\r\n <ng-container *ngTemplateOutlet=\"headerMenu\"/>\r\n <button mat-icon-button color='primary' [matMenuTriggerFor]=\"mainMenu\">\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n <mat-menu #mainMenu='matMenu'>\r\n <ng-container *ngTemplateOutlet=\"headerMenuExtra\"/>\r\n </mat-menu>\r\n }\r\n @else {\r\n <mat-icon color=\"primary\" [matMenuTriggerFor]=\"mainMenu\" class=\"flat-menu-button pointer\">more_horiz</mat-icon>\r\n <mat-menu #mainMenu='matMenu'>\r\n <div class=\"flex-column\">\r\n <ng-container *ngTemplateOutlet=\"headerMenu\"/>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"headerMenuExtra\"/>\r\n </mat-menu>\r\n }\r\n <mat-icon [matTooltip]=\"$collapsedHeader() ? 'expand' : 'collapse'\" class=\"collapse-icon header\"\r\n (click)=\"state.toggleCollapseHeader()\">\r\n {{$collapsedHeader() ? 'expand_less' : 'expand_more'}}\r\n </mat-icon>\r\n }\r\n\r\n </div>\r\n </div>\r\n\r\n @if($useVirtual())\r\n {\r\n <tb-virtual-scroll-container class=\"scrollable\">\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayDataLength]=\"$displayDataLength()\"\r\n (selection)='selection$.emit($event)' [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" />\r\n </tb-virtual-scroll-container>\r\n }\r\n @else\r\n {\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayDataLength]=\"$displayDataLength()\"\r\n (selection)='selection$.emit($event)' [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" />\r\n }\r\n @if(tableSettings.usePaginator)\r\n {\r\n <div class=\"paginator\">\r\n <tb-paginator #tbPaginator />\r\n\r\n <mat-icon [matTooltip]=\"$collapsedFooter() ? 'expand' : 'collapse'\" class=\"collapse-icon footer\"\r\n (click)=\"state.toggleCollapseFooter()\">\r\n {{$collapsedFooter() ? 'expand_more' : 'expand_less'}}\r\n </mat-icon>\r\n </div>\r\n }\r\n\r\n <ng-template #headerMenu>\r\n @if (!tableSettings.hideFilter) {<tb-filter-displayer/>}\r\n @if (!tableSettings.hideColumnSettings) {<tb-col-displayer/>}\r\n @if (!tableSettings.hideSort) {<tb-sort-menu/>}\r\n @if (!!tableId) {<tb-profiles-menu [$tableId]=\"tableId\" (onSaveState)=\"onSaveState$.emit($event)\"/>}\r\n </ng-template>\r\n\r\n <ng-template #headerMenuExtra>\r\n <button mat-menu-item (click)=\"resetState()\">\r\n <mat-icon color=\"primary\">autorenew</mat-icon>\r\n <span>Reset table</span>\r\n </button>\r\n @if (!tableSettings.hideExport) {\r\n <button mat-menu-item (click)=\"exportToCsv()\">\r\n <mat-icon color=\"primary\">file_download</mat-icon>\r\n <span>Export Table</span>\r\n </button>\r\n }\r\n @if (tableId) {\r\n <button stop-propagation mat-menu-item (click)=\"pm.trigger()?.toggleMenu()\">\r\n <mat-icon color=\"primary\">people</mat-icon>\r\n <span>Profiles</span>\r\n </button>\r\n <tb-profiles-menu class=\"profiles-menu\" #pm [$tableId]=\"tableId\" (onSaveState)=\"onSaveState$.emit($event)\"/>\r\n }\r\n </ng-template>\r\n</ng-container>\r\n", styles: [".tb-header-wrapper{display:flex;flex-direction:row;justify-content:space-between;width:100%}.flx-row-end{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.flat-menu{line-height:initial;height:initial}.pointer{cursor:pointer}.add-key{width:90%}.paginator{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;background-color:#fff;bottom:0;position:sticky;border-top:.5px solid rgba(0,0,0,.12)}.profiles-menu{visibility:hidden;width:0px;height:0px;display:block;overflow:hidden;position:absolute;top:50px}\n", ".collapse-icon{font-size:16px;height:16px;color:#3f51b5;align-self:flex-start}.collapse-icon:hover{cursor:pointer}.hide{display:none}.paginator-row{display:flex;align-items:center}\n"] }]
5563
+ args: [{ selector: 'tb-table-container', changeDetection: ChangeDetectionStrategy.OnPush, providers: [TableStore, ExportToCsvService, WrapperFilterStore, DataStore], imports: [NgTemplateOutlet,
5564
+ PaginatorComponent,
5565
+ MultiSortDirective, GroupByListComponent, FilterChipsComponent, GenFilterDisplayerComponent, GenColDisplayerComponent,
5566
+ SortMenuComponent, GenericTableComponent, ProfilesMenuComponent, TableHeaderMenuComponent,
5567
+ MatButtonModule, MatMenuModule, MatIconModule, MatTooltipModule, VirtualScrollContainer], template: "@let tableId = $tableId();\r\n@let tableSettings = state.$tableSettings();\r\n\r\n<ng-content select=\"[before]\" />\r\n<ng-container multiSort>\r\n <div class=\"tb-header-wrapper\" [id]=\"headerId\">\r\n <div class=\"title\">\r\n @if ((!$collapsedHeader()) || tableSettings.showTitleWhenHeaderCollapsed) {\r\n <ng-content select=\".tb-header-title\"/>\r\n }\r\n @if(state.$groupByKeys().length){\r\n <group-by-list />\r\n }\r\n </div>\r\n <div class=\"flx-row-end\">\r\n <lib-filter-list />\r\n @if (!tableSettings.hideHeader) {\r\n @if (!$collapsedHeader()) {\r\n <ng-container *ngTemplateOutlet=\"headerMenu\"/>\r\n <button mat-icon-button color='primary' [matMenuTriggerFor]=\"l.menu()\">\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n\r\n <lib-table-header-menu #l/>\r\n\r\n }\r\n @else {\r\n <mat-icon color=\"primary\" [matMenuTriggerFor]=\"mainMenu\" class=\"flat-menu-button pointer\">more_horiz</mat-icon>\r\n <mat-menu #mainMenu='matMenu'>\r\n <div class=\"flex-column\">\r\n <ng-container *ngTemplateOutlet=\"headerMenu; injector menuInjector\"/>\r\n </div>\r\n <lib-table-header-menu />\r\n </mat-menu>\r\n }\r\n <mat-icon [matTooltip]=\"$collapsedHeader() ? 'expand' : 'collapse'\" class=\"collapse-icon header\"\r\n (click)=\"state.toggleCollapseHeader()\">\r\n {{$collapsedHeader() ? 'expand_less' : 'expand_more'}}\r\n </mat-icon>\r\n }\r\n\r\n </div>\r\n </div>\r\n\r\n @if($useVirtual())\r\n {\r\n <tb-virtual-scroll-container class=\"scrollable\">\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayDataLength]=\"$displayDataLength()\"\r\n (selection)='selection$.emit($event)' [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" />\r\n </tb-virtual-scroll-container>\r\n }\r\n @else\r\n {\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayDataLength]=\"$displayDataLength()\"\r\n (selection)='selection$.emit($event)' [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" />\r\n }\r\n @if(tableSettings.usePaginator)\r\n {\r\n <div class=\"paginator\">\r\n <tb-paginator #tbPaginator />\r\n\r\n <mat-icon [matTooltip]=\"$collapsedFooter() ? 'expand' : 'collapse'\" class=\"collapse-icon footer\"\r\n (click)=\"state.toggleCollapseFooter()\">\r\n {{$collapsedFooter() ? 'expand_more' : 'expand_less'}}\r\n </mat-icon>\r\n </div>\r\n }\r\n\r\n <ng-template #headerMenu>\r\n @if (!tableSettings.hideFilter) {<tb-filter-displayer/>}\r\n @if (!tableSettings.hideColumnSettings) {<tb-col-displayer/>}\r\n @if (!tableSettings.hideSort) {<tb-sort-menu/>}\r\n @if (!!tableId) {<tb-profiles-menu [tableId]=\"tableId\"/>}\r\n </ng-template>\r\n\r\n</ng-container>\r\n", styles: [".tb-header-wrapper{display:flex;flex-direction:row;justify-content:space-between;width:100%}.flx-row-end{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.flat-menu{line-height:initial;height:initial}.pointer{cursor:pointer}.add-key{width:90%}.paginator{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;background-color:#fff;bottom:0;position:sticky;border-top:.5px solid rgba(0,0,0,.12)}.profiles-menu{visibility:hidden;width:0px;height:0px;display:block;overflow:hidden;position:absolute;top:50px}\n", ".collapse-icon{font-size:16px;height:16px;color:#3f51b5;align-self:flex-start}.collapse-icon:hover{cursor:pointer}.hide{display:none}.paginator-row{display:flex;align-items:center}\n"] }]
5351
5568
  }] });
5352
5569
 
5353
5570
  class TableBuilderModule {
@@ -5760,5 +5977,5 @@ const setUpStoreFactory = () => {
5760
5977
  * Generated bundle index. Do not edit.
5761
5978
  */
5762
5979
 
5763
- export { ActionStateSpinnerComponent, ActionStateUiModule, ActionStatus, AppStatusState, ArrayStyle, AutoFocusDirective, CancellationToken, ClickEmitterDirective, ClickSubjectDirective, ConditionalClassesDirective, CreateTableBuilder, CustomCellDirective, DateFilterComponent, DefaultVirtualScrollOptions, DialogDirective, DialogService, DialogWrapper, FieldType, FilterChipsComponent, FilterComponent, FilterTypes, FunctionPipe, GenColDisplayerComponent, GenFilterDisplayerComponent, GeneralTableSettings, GenericTableComponent, GroupByListComponent, HttpErrorStateDirective, HttpInProgressStateDirective, HttpNotStartedStateDirective, HttpRequestModule, HttpRequestStateDirective, HttpRequestStateFactory, HttpRequestStateStore, HttpRequestStatus, HttpRequestStrategy, HttpSuccessStateDirective, MatButtonToggleFilterDirective, MatCheckboxTbFilterDirective, MatOptionTbFilterDirective, MatRadioButtonTbFilterDirective, MatSlideToggleGroupDirective, MatSlideToggleTbFilterDirective, MatTableObservableDataSource, MultiSortDirective, NgrxExtModule, NotPersistedTableSettings, PaginatorComponent, PaginatorOptions, PersistedTableSettings, PhoneNumberPipe, PreventEnterDirective, ResizeColumnDirective, SortDirection, SpaceCasePipe, StopPropagationDirective, StylerDirective, Subjectifier, Subscriber, TableBuilder, TableBuilderConfigToken, TableBuilderModule, TableColumnHeaderSettings, TableContainerComponent, TableCustomFilterDirective, TableCustomFilterDirectiveBase, TableFilterDirective, TableFilterStringContainsDirective, TableSettings, TableWrapperDirective, TableWrapperFooterSettings, TableWrapperHeaderSettings, Target, TbSelectedFilterDirective, TrimWhitespaceDirective, UtilitiesModule, VirtualScrollOptions, actionStatusReducer, chainRequest, clearActionableSelectorRequestCache, combineArrays, createActionResultSelector, createActionSelector, createActionableResultSelector, createActionableSelector, createFailure, createRequestor, createSuccess, defaultFilter, defaultShareReplay, delayOn, filterArray, getRequestorBody, getRequestorStatus, getStatusState, httpRequest, httpRequestor, inProgress, initialState, isErrorState, isSuccessOrErrorState, isSuccessState, mapArray, mapError, metaDataArrToDict, notNull, notStarted, onWait, onceWhen, previousAndCurrent, provideActionableSelector, provideTableBuilder, selectAll, selectEntities, selectEntity, selectIds, selectTotal, serverStatusTypes, setUpStoreFactory, skipOneWhen, sortsAreSame, spaceCase, startWithIfEmpty, statusAdapter, statusIsSuccessOrInProgress, subscriber, switchOff, tapError, tapSuccess, wrapInArr };
5980
+ export { ActionStateSpinnerComponent, ActionStateUiModule, ActionStatus, AppStatusState, ArrayStyle, AutoFocusDirective, CancellationToken, ClickEmitterDirective, ClickSubjectDirective, ConditionalClassesDirective, CreateTableBuilder, CustomCellDirective, DateFilterComponent, DefaultVirtualScrollOptions, DialogDirective, DialogService, DialogWrapper, FieldType, FilterChipsComponent, FilterComponent, FilterType, FunctionPipe, GenColDisplayerComponent, GenFilterDisplayerComponent, GeneralTableSettings, GenericTableComponent, GroupByListComponent, HttpErrorStateDirective, HttpInProgressStateDirective, HttpNotStartedStateDirective, HttpRequestModule, HttpRequestStateDirective, HttpRequestStateFactory, HttpRequestStateStore, HttpRequestStatus, HttpRequestStrategy, HttpSuccessStateDirective, MatButtonToggleFilterDirective, MatCheckboxTbFilterDirective, MatOptionTbFilterDirective, MatRadioButtonTbFilterDirective, MatSlideToggleGroupDirective, MatSlideToggleTbFilterDirective, MatTableObservableDataSource, MultiSortDirective, NgrxExtModule, NotPersistedTableSettings, PaginatorComponent, PaginatorOptions, PersistedTableSettings, PhoneNumberPipe, PreventEnterDirective, ResizeColumnDirective, SortDirection, SpaceCasePipe, StopPropagationDirective, StylerDirective, Subjectifier, Subscriber, TableBuilder, TableBuilderConfigToken, TableBuilderModule, TableColumnHeaderSettings, TableContainerComponent, TableCustomFilterDirective, TableCustomFilterDirectiveBase, TableFilterDirective, TableFilterStringContainsDirective, TableSettings, TableWrapperDirective, TableWrapperFooterSettings, TableWrapperHeaderSettings, Target, TbSelectedFilterDirective, TrimWhitespaceDirective, UtilitiesModule, VirtualScrollOptions, actionStatusReducer, chainRequest, clearActionableSelectorRequestCache, combineArrays, createActionResultSelector, createActionSelector, createActionableResultSelector, createActionableSelector, createFailure, createRequestor, createSuccess, defaultFilter, defaultShareReplay, delayOn, filterArray, getRequestorBody, getRequestorStatus, getStatusState, httpRequest, httpRequestor, inProgress, initialState, isErrorState, isSuccessOrErrorState, isSuccessState, mapArray, mapError, metaDataArrToDict, notNull, notStarted, onWait, onceWhen, parseTbSizeToPixels, previousAndCurrent, provideActionableSelector, provideTableBuilder, selectAll, selectEntities, selectEntity, selectIds, selectTotal, serverStatusTypes, setUpStoreFactory, skipOneWhen, sortsAreSame, spaceCase, startWithIfEmpty, statusAdapter, statusIsSuccessOrInProgress, subscriber, switchOff, tapError, tapSuccess, wrapInArr };
5764
5981
  //# sourceMappingURL=one-paragon-angular-utilities.mjs.map