@one-paragon/angular-utilities 2.5.2 → 2.5.4-beta.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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Input, Directive, inject, Injector, TemplateRef, ViewContainerRef, NgModule, assertInInjectionContext, DestroyRef, signal, computed, isSignal, effect, untracked, InjectionToken, Injectable, runInInjectionContext, input, Renderer2, ElementRef, booleanAttribute, Pipe, makeEnvironmentProviders, HostListener, ChangeDetectionStrategy, Component, EventEmitter, Output, ContentChildren, ChangeDetectorRef, output, viewChild, EnvironmentInjector, createComponent, linkedSignal, contentChild, forwardRef, contentChildren, provideAppInitializer } from '@angular/core';
2
+ import { Input, Directive, inject, Injector, TemplateRef, ViewContainerRef, NgModule, assertInInjectionContext, DestroyRef, signal, computed, isSignal, effect, untracked, InjectionToken, Injectable, runInInjectionContext, input, Renderer2, ElementRef, booleanAttribute, Pipe, makeEnvironmentProviders, HostListener, ChangeDetectionStrategy, Component, EventEmitter, Output, ContentChildren, ChangeDetectorRef, viewChild, EnvironmentInjector, createComponent, linkedSignal, output, contentChild, forwardRef, contentChildren, provideAppInitializer } from '@angular/core';
3
3
  import { shareReplay, map, switchAll, filter, tap, catchError, startWith, switchMap, mergeMap, concatMap as concatMap$1, takeUntil, distinctUntilChanged, debounceTime } from 'rxjs/operators';
4
4
  import * as i1 from 'rxjs';
5
5
  import { isObservable, Subject, of, ReplaySubject, filter as filter$1, first, map as map$1, Observable, combineLatest, Subscription, startWith as startWith$1, pairwise, pipe, concatMap, merge, delay, fromEvent, takeUntil as takeUntil$1, tap as tap$1, switchMap as switchMap$1, scan, timestamp, BehaviorSubject } from 'rxjs';
@@ -920,6 +920,7 @@ class TableSettings {
920
920
  this.groupHeaderHeight = undefined;
921
921
  this.rowClick = undefined;
922
922
  this.exportSettings = undefined;
923
+ this.groupBySettings = [];
923
924
  }
924
925
  }
925
926
  class PersistedTableSettings {
@@ -959,6 +960,7 @@ class NotPersistedTableSettings {
959
960
  this.headerHeight = undefined;
960
961
  this.rowClick = undefined;
961
962
  this.exportSettings = undefined;
963
+ this.groupBySettings = [];
962
964
  }
963
965
  merge(tableSettings) {
964
966
  const newNpts = merge$1(this, new NotPersistedTableSettings());
@@ -984,6 +986,7 @@ class NotPersistedTableSettings {
984
986
  newNpts.rowStyles = tableSettings.tableSettings?.rowStyles ?? newNpts.rowStyles;
985
987
  newNpts.rowClick = tableSettings.tableSettings?.rowClick ?? newNpts.rowClick;
986
988
  newNpts.exportSettings = tableSettings.tableSettings?.exportSettings ?? newNpts.exportSettings;
989
+ newNpts.groupBySettings = tableSettings.tableSettings?.groupBySettings ?? newNpts.groupBySettings ?? [];
987
990
  if (tableSettings.tableSettings?.virtualScrollSettings) {
988
991
  const currVirt = tableSettings.tableSettings?.virtualScrollSettings || newNpts.virtualSettings;
989
992
  if (!currVirt.headerHeight) {
@@ -1974,6 +1977,13 @@ class DialogDirective {
1974
1977
  this.opDialogAddDialogClass = true;
1975
1978
  this.injector = inject(Injector);
1976
1979
  this.subscriber = subscriber(this.injector);
1980
+ /**
1981
+ * For use with origin element to keep dialog on screen.
1982
+ * If true, will position based on width and height provided IF it was provide as a number.
1983
+ * If no width provided or/and height, provide a default in number (of pixels) of the not provided values.
1984
+ * If no width/height provided at all, will default to 600x400.
1985
+ */
1986
+ this.$positionOnScreen = input(false, { alias: 'opDialogPositionOnScreen' });
1977
1987
  this._data = new Subject();
1978
1988
  this.setDataAndState = (data) => {
1979
1989
  if (data) {
@@ -2009,7 +2019,28 @@ class DialogDirective {
2009
2019
  initDialog() {
2010
2020
  if (this.nativeElement) {
2011
2021
  const rect = this.nativeElement.getBoundingClientRect();
2012
- const position = { left: `${rect.left}px`, top: `${rect.bottom - 50}px` };
2022
+ const position = {};
2023
+ if (this.$positionOnScreen()) {
2024
+ const viewportWidth = window.innerWidth;
2025
+ const viewportHeight = window.innerHeight;
2026
+ const p = this.$positionOnScreen();
2027
+ const width = typeof p === 'object' && p.width ? p.width : typeof this.dialogConfig.width === 'number' ? this.dialogConfig.width : 600;
2028
+ const height = typeof p === 'object' && p.height ? p.height : typeof this.dialogConfig.height === 'number' ? this.dialogConfig.height : 400;
2029
+ // Check horizontal positioning
2030
+ if (rect.left + width > viewportWidth) {
2031
+ position.right = `${viewportWidth - rect.right}px`;
2032
+ }
2033
+ else {
2034
+ position.left = `${rect.left}px`;
2035
+ }
2036
+ // Check vertical positioning
2037
+ if (rect.bottom + height > viewportHeight) {
2038
+ position.bottom = `${viewportHeight - rect.top}px`;
2039
+ }
2040
+ else {
2041
+ position.top = `${rect.bottom - 20}px`;
2042
+ }
2043
+ }
2013
2044
  this.opDialogConfig = { ...this.opDialogConfig, position };
2014
2045
  }
2015
2046
  if (this.opDialogAddDialogClass) {
@@ -2047,7 +2078,7 @@ class DialogDirective {
2047
2078
  return true;
2048
2079
  }
2049
2080
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: DialogDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2050
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.3", type: DialogDirective, isStandalone: true, selector: "[opDialog]", inputs: { opDialogAddDialogClass: "opDialogAddDialogClass", opDialogConfig: "opDialogConfig", setControl: ["opDialog", "setControl"], nativeElement: ["opDialogOrigin", "nativeElement"] }, outputs: { opDialogClosed: "opDialogClosed" }, ngImport: i0 }); }
2081
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: DialogDirective, isStandalone: true, selector: "[opDialog]", inputs: { opDialogAddDialogClass: { classPropertyName: "opDialogAddDialogClass", publicName: "opDialogAddDialogClass", isSignal: false, isRequired: false, transformFunction: null }, opDialogConfig: { classPropertyName: "opDialogConfig", publicName: "opDialogConfig", isSignal: false, isRequired: false, transformFunction: null }, setControl: { classPropertyName: "setControl", publicName: "opDialog", isSignal: false, isRequired: false, transformFunction: null }, nativeElement: { classPropertyName: "nativeElement", publicName: "opDialogOrigin", isSignal: false, isRequired: false, transformFunction: null }, $positionOnScreen: { classPropertyName: "$positionOnScreen", publicName: "opDialogPositionOnScreen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opDialogClosed: "opDialogClosed" }, ngImport: i0 }); }
2051
2082
  }
2052
2083
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: DialogDirective, decorators: [{
2053
2084
  type: Directive,
@@ -2912,6 +2943,28 @@ class TableStore extends ComponentStore {
2912
2943
  const state = this.state();
2913
2944
  return mapSaveableState(state);
2914
2945
  });
2946
+ //#region meta order and hidden
2947
+ this.showColumn = this.updater((state, key) => ({
2948
+ ...state,
2949
+ hiddenKeys: state.hiddenKeys.filter(k => k !== key),
2950
+ }));
2951
+ this.hideColumn = this.updater((state, key) => ({
2952
+ ...state,
2953
+ hiddenKeys: [...state.hiddenKeys.filter(k => k !== key), key],
2954
+ }));
2955
+ this.setHiddenColumns = this.updater((state, displayCols) => {
2956
+ return ({ ...state, hiddenKeys: displayCols.filter(d => !d.visible).map(d => d.key) });
2957
+ });
2958
+ this.setUserDefinedOrder = this.updater((state, moved) => {
2959
+ const { newOrder, oldOrder } = moved;
2960
+ const mdsArr = orderedStateVisibleMetaData(state);
2961
+ moveItemInArray(mdsArr, oldOrder, newOrder);
2962
+ const userDefinedOrder = mdsArr.reduce((aggregate, current, index) => {
2963
+ aggregate[current.key] = index;
2964
+ return aggregate;
2965
+ }, {});
2966
+ return ({ ...state, userDefined: { ...state.userDefined, order: userDefinedOrder } });
2967
+ });
2915
2968
  this.$userDefinedOrder = this.selectSignal(state => state.userDefined.order);
2916
2969
  this.metaData$ = this.select(state => state.metaData);
2917
2970
  this.$metaData = this.selectSignal(state => state.metaData);
@@ -2925,15 +2978,87 @@ class TableStore extends ComponentStore {
2925
2978
  });
2926
2979
  this.$hiddenKeys = this.selectSignal(state => state.hiddenKeys);
2927
2980
  this.$orderedVisibleColumns = this.selectSignal(this.$orderedCodeVisibleMetaDatas, this.$hiddenKeys, (cs, hiddenKeys) => cs.filter(m => !hiddenKeys.includes(m.key)).map(m => m.key));
2981
+ //#endregion meta order and hidden
2982
+ //#region widths
2983
+ this.setUserDefinedWidth = this.updater((state, colWidths) => {
2984
+ const userDefinedWidths = { ...state.userDefined.widths };
2985
+ colWidths.forEach(cw => {
2986
+ userDefinedWidths[cw.key] = cw.widthInPixel;
2987
+ });
2988
+ return { ...state, userDefined: { ...state.userDefined, widths: userDefinedWidths } };
2989
+ });
2990
+ this.setTableWidth = this.updater((state, widthInPixels) => ({ ...state, userDefined: { ...state.userDefined, table: { width: widthInPixels } } }));
2928
2991
  this.$getUserDefinedWidths = this.selectSignal(state => state.userDefined.widths);
2929
2992
  this.$tableSettingsMinWidth = this.selectSignal(state => parseTbSizeToPixels(state.notPersistedTableSettings.minColumnWidth));
2930
2993
  this.$getUserDefinedWidth = (key) => this.selectSignal(this.$getUserDefinedWidths, widths => widths[key]);
2994
+ this.$getUserDefinedTableWidth = this.selectSignal(state => state.userDefined.table.width);
2995
+ this.getUserDefinedTableWidth$ = this.select(state => state.userDefined.table.width);
2996
+ //#endregion widths
2997
+ //#region filter
2998
+ this.addFilter = this.updater((state, filter) => {
2999
+ return this.addFiltersToState(state, [filter]);
3000
+ });
3001
+ this.addFilters = this.updater((state, filters) => {
3002
+ return this.addFiltersToState(state, filters);
3003
+ });
3004
+ this.removeFilter = this.updater((state, filterId) => {
3005
+ const filtersCopy = { ...state.filters };
3006
+ delete filtersCopy[filterId];
3007
+ return ({ ...state, filters: filtersCopy });
3008
+ });
3009
+ this.removeFilters = this.updater((state, filterIds) => {
3010
+ const filtersCopy = { ...state.filters };
3011
+ filterIds.forEach(id => { delete filtersCopy[id]; });
3012
+ return ({ ...state, filters: filtersCopy });
3013
+ });
3014
+ this.clearFilters = this.updater((state) => ({ ...state, filters: {} }));
3015
+ this.addFiltersToState = (state, filters) => {
3016
+ var customFilters = filters.filter(isCustomFilter);
3017
+ var filterInfos = filters.filter(isFilterInfo);
3018
+ const filtersObj = filterInfos
3019
+ .filter(fltr => Object.keys(state.metaData).some(key => key === fltr.key) || console.warn(`Meta data with key ${fltr.key} not found`))
3020
+ .reduce((filtersObj, filter) => {
3021
+ if (!filter.filterId) {
3022
+ filter.filterId = crypto.randomUUID();
3023
+ }
3024
+ filtersObj[filter.filterId] = filter;
3025
+ return filtersObj;
3026
+ }, {});
3027
+ customFilters.forEach(fltr => {
3028
+ if (!fltr.filterId) {
3029
+ fltr.filterId = crypto.randomUUID();
3030
+ }
3031
+ filtersObj[fltr.filterId] = fltr;
3032
+ });
3033
+ return {
3034
+ ...state,
3035
+ filters: { ...state.filters, ...filtersObj }
3036
+ };
3037
+ };
2931
3038
  this.$filters = this.selectSignal(state => state.filters);
2932
3039
  this.$filtersArray = computed(() => Object.values(this.state().filters) || []);
2933
3040
  this.filters$ = this.select(state => state.filters);
2934
3041
  this.$getFilter = (filterId) => {
2935
3042
  return this.selectSignal(this.$filters, filters => filters[filterId]);
2936
3043
  };
3044
+ //#endregion filter
3045
+ //#region sort
3046
+ this.setSort = this.updater((state, { key, direction }) => {
3047
+ const sortArray = state.sorted.filter(s => s.active !== key);
3048
+ if (direction) {
3049
+ sortArray.unshift({ active: key, direction });
3050
+ }
3051
+ return {
3052
+ ...state,
3053
+ sorted: sortArray,
3054
+ };
3055
+ });
3056
+ this.setAllSort = this.updater((state, sortArray) => {
3057
+ return {
3058
+ ...state,
3059
+ sorted: sortArray,
3060
+ };
3061
+ });
2937
3062
  this.$preSort = computed(() => createPreSort(this.$metaData()));
2938
3063
  this._$selectSorted = this.selectSignal(state => state.sorted, {
2939
3064
  equal: sortsAreSame
@@ -2950,15 +3075,90 @@ class TableStore extends ComponentStore {
2950
3075
  this.selectSorted$ = this.select(state => state.sorted).pipe(distinctUntilChanged(sortsAreSame));
2951
3076
  this.$getSorts = this.selectSignal(() => this.$initializationState() !== InitializationState.Ready ? [] : this.$selectSorted());
2952
3077
  this.sort$ = toObservable(this.$getSorts);
2953
- this.$getUserDefinedTableWidth = this.selectSignal(state => state.userDefined.table.width);
2954
- this.getUserDefinedTableWidth$ = this.select(state => state.userDefined.table.width);
2955
- this.$userDefinedRowHeight = this.selectSignal(state => (state.userDefined.rowHeight));
2956
- this.$userDefinedHeaderHeight = this.selectSignal(state => (state.userDefined.headerHeight));
2957
- this.$userDefinedPageSize = this.selectSignal(state => (state.userDefined.pageSize));
2958
- this.$footerCollapsed = this.selectSignal(state => state.persistedTableSettings.collapseFooter);
2959
- this.$headerCollapsed = this.selectSignal(state => state.persistedTableSettings.collapseHeader);
2960
- this.$groupBy = this.selectSignal(state => state.groupBy);
2961
- this.$groupByData = this.selectSignal(this.$groupBy, this.$metaDataArray, (gb, mds) => gb.filter(bg => mds.some(md => md.key === bg.key)), {
3078
+ //#endregion sort
3079
+ //#region groupBy
3080
+ this.addGroupByKey = this.updater((state, metaDataKey) => ({
3081
+ ...state,
3082
+ groupBy: [...state.groupBy, { key: metaDataKey, expandedHeaders: [], sort: '' }]
3083
+ }));
3084
+ this.removeGroupByKey = this.updater((state, groupByKey) => ({
3085
+ ...state,
3086
+ groupBy: state.groupBy.filter(key => groupByKey !== key.key)
3087
+ }));
3088
+ this.updateExpandedGroups = this.updater((state, data) => {
3089
+ const gbk = replaceInArrayWithClone(state.groupBy, k => k.key === data.key, gk => {
3090
+ if (data.isExpanded) {
3091
+ if (gk.expandedHeaders === 'all' || gk.expandedHeaders.includes(data.groupUniqueName))
3092
+ return;
3093
+ gk.expandedHeaders = [...gk.expandedHeaders, data.groupUniqueName];
3094
+ }
3095
+ else {
3096
+ //we need to make sure it will not = all at this point. See generic table setExpanded
3097
+ if (gk.expandedHeaders !== 'all') {
3098
+ gk.expandedHeaders = gk.expandedHeaders.filter(g => g !== data.groupUniqueName);
3099
+ }
3100
+ }
3101
+ });
3102
+ return ({
3103
+ ...state,
3104
+ groupBy: gbk
3105
+ });
3106
+ });
3107
+ this.expandAllOfGroup = this.updater((state, data) => {
3108
+ const newGroupedData = state.groupBy.map(gb => ({
3109
+ key: gb.key,
3110
+ expandedHeaders: data.groupHeadersByKey[gb.key]?.map(g => g.uniqueName) ?? gb.expandedHeaders,
3111
+ sort: gb.sort,
3112
+ }));
3113
+ return ({ ...state, groupBy: newGroupedData });
3114
+ });
3115
+ this.collapseAll = this.updater((state) => ({
3116
+ ...state,
3117
+ groupBy: state.groupBy.map(gb => ({ key: gb.key, expandedHeaders: [], sort: gb.sort }))
3118
+ }));
3119
+ this.collapseAllOfKey = this.updater((state, data) => ({
3120
+ ...state,
3121
+ groupBy: state.groupBy.map(gb => ({
3122
+ key: gb.key,
3123
+ expandedHeaders: data.keys.includes(gb.key) ? [] : gb.expandedHeaders,
3124
+ sort: gb.sort,
3125
+ }))
3126
+ }));
3127
+ this.updateGroupBySort = this.updater((state, data) => {
3128
+ const newGroupedData = replaceInArrayWithClone(state.groupBy, gb => gb.key === data.key, gb => {
3129
+ gb.sort = data.sort;
3130
+ });
3131
+ return ({ ...state, groupBy: newGroupedData });
3132
+ });
3133
+ this.getGroupBySortDirection = (key) => computed(() => {
3134
+ const groupBy = this.state().groupBy.find(gb => gb.key === key);
3135
+ return groupBy ? groupBy.sort : '';
3136
+ });
3137
+ this.cycleGroupBySortDirection = this.updater((state, key) => {
3138
+ const currentGroupBy = state.groupBy.find(gb => gb.key === key);
3139
+ console.log(currentGroupBy);
3140
+ if (!currentGroupBy)
3141
+ return state;
3142
+ let nextSort;
3143
+ switch (currentGroupBy.sort) {
3144
+ case '':
3145
+ case undefined:
3146
+ nextSort = 'desc';
3147
+ break;
3148
+ case 'desc':
3149
+ nextSort = 'asc';
3150
+ break;
3151
+ case 'asc':
3152
+ nextSort = '';
3153
+ break;
3154
+ }
3155
+ const newGroupedData = replaceInArrayWithClone(state.groupBy, gb => gb.key === key, gb => {
3156
+ gb.sort = nextSort;
3157
+ });
3158
+ return ({ ...state, groupBy: newGroupedData });
3159
+ });
3160
+ this.#$groupBy = this.selectSignal(state => state.groupBy);
3161
+ this.$groupByData = this.selectSignal(this.#$groupBy, this.$metaDataArray, (gb, mds) => gb.filter(bg => mds.some(md => md.key === bg.key)), {
2962
3162
  equal: (prev, curr) => prev.length === curr.length && curr.every((k, i) => prev[i].key === k.key)
2963
3163
  });
2964
3164
  this.groupByKeys$ = this.select(state => state.groupBy.map(gbk => gbk.key))
@@ -2969,28 +3169,25 @@ class TableStore extends ComponentStore {
2969
3169
  return aa.length === bb.length && aa.every((k) => bb.includes(k));
2970
3170
  }));
2971
3171
  this.$expandGroups = this.selectSignal(state => state.groupBy, { equal: (a, b) => {
2972
- const aa = a.flatMap(g => g.expandedHeaders);
2973
- const bb = b.flatMap(g => g.expandedHeaders);
3172
+ const aa = a.flatMap(g => g.expandedHeaders === 'all' ? ['all'] : g.expandedHeaders);
3173
+ const bb = b.flatMap(g => g.expandedHeaders === 'all' ? ['all'] : g.expandedHeaders);
2974
3174
  return aa.length === bb.length && aa.every((k) => bb.includes(k));
2975
3175
  } });
2976
3176
  this.$getIsExpanded = (columnKey, groupUniqueName) => {
2977
- return this.selectSignal(state => !!state.groupBy.filter(g => g.key === columnKey && g.expandedHeaders.includes(groupUniqueName)).length);
3177
+ return this.selectSignal(state => !!state.groupBy.filter(g => g.key === columnKey && (g.expandedHeaders.includes(groupUniqueName) || g.expandedHeaders === 'all')).length);
2978
3178
  };
3179
+ this.$expandAllGroupsOfKey = (columnKey) => this.selectSignal(state => state.groupBy.find(g => g.key === columnKey)?.expandedHeaders === 'all');
2979
3180
  this.$sortedGroupsUpdates = this.selectSignal(state => state.groupBy, { equal: (a, b) => sortsAreSame(a.map(g => ({ active: g.key, direction: g.sort })), b.map(g => ({ active: g.key, direction: g.sort }))) });
2980
- this.$currentPage = this.selectSignal(state => state.currentPage);
2981
- this.$pageSize = this.selectSignal(s => s.userDefined?.pageSize || s.pageSize);
2982
- this.$showAll = this.selectSignal(s => s.userDefined?.showAll ?? s.showAll);
2983
- this.$tableSettings = this.selectSignal(state => {
2984
- const ts = { ...state.persistedTableSettings, ...state.notPersistedTableSettings };
2985
- return ts;
2986
- });
2987
- this.$notPersistedTableSettings = this.selectSignal(state => state.notPersistedTableSettings);
2988
- this.tableSettings$ = toObservable(this.$tableSettings);
2989
- this.$props = this.selectSignal(s => s.props);
2990
- this.$getLinkInfo = (md) => this.selectSignal(state => state.linkMaps[md.key]);
3181
+ //#endregion groupBy
3182
+ //#region page paginator and show all
3183
+ this.setCurrentPage = this.updater((state, currentPage) => ({ ...state, currentPage }));
3184
+ this.setPageSize = this.updater((state, pageSize) => ({ ...state, pageSize }));
3185
+ this.setUserDefinedPageSize = this.updater((state, pageSize) => ({ ...state, userDefined: { ...state.userDefined, pageSize } }));
3186
+ this.setUserDefinedShowAll = this.updater((state, showAll) => ({ ...state, showAll, userDefined: { ...state.userDefined, showAll } }));
2991
3187
  this.$isVirtual = this.selectSignal(state => state.notPersistedTableSettings.useVirtualScroll
2992
3188
  || state.showAll
2993
3189
  || state.userDefined?.showAll);
3190
+ this.$showAll = this.selectSignal(s => s.userDefined?.showAll ?? s.showAll);
2994
3191
  this.$viewType = this.selectSignal(state => {
2995
3192
  const usePaginator = state.notPersistedTableSettings.usePaginator;
2996
3193
  const showAll = state.showAll || state.userDefined?.showAll;
@@ -3008,6 +3205,30 @@ class TableStore extends ComponentStore {
3008
3205
  return 'all';
3009
3206
  }
3010
3207
  });
3208
+ this.$userDefinedPageSize = this.selectSignal(state => (state.userDefined.pageSize));
3209
+ this.$currentPage = this.selectSignal(state => state.currentPage);
3210
+ this.$pageSize = this.selectSignal(s => s.userDefined?.pageSize || s.pageSize);
3211
+ //#endregion page paginator and show all
3212
+ //#region table settings and props
3213
+ this.$tableSettings = this.selectSignal(state => {
3214
+ const ts = { ...state.persistedTableSettings, ...state.notPersistedTableSettings };
3215
+ return ts;
3216
+ });
3217
+ this.$notPersistedTableSettings = this.selectSignal(state => state.notPersistedTableSettings);
3218
+ this.tableSettings$ = toObservable(this.$tableSettings);
3219
+ this.$props = this.selectSignal(s => s.props);
3220
+ //#endregion table settings and props
3221
+ this.setUserDefinedRowHeight = this.updater((state, rowHeight) => {
3222
+ return ({ ...state, userDefined: { ...state.userDefined, rowHeight } });
3223
+ });
3224
+ this.setUserDefinedHeaderHeight = this.updater((state, headerHeight) => {
3225
+ return ({ ...state, userDefined: { ...state.userDefined, headerHeight } });
3226
+ });
3227
+ this.$userDefinedRowHeight = this.selectSignal(state => (state.userDefined.rowHeight));
3228
+ this.$userDefinedHeaderHeight = this.selectSignal(state => (state.userDefined.headerHeight));
3229
+ this.$footerCollapsed = this.selectSignal(state => state.persistedTableSettings.collapseFooter);
3230
+ this.$headerCollapsed = this.selectSignal(state => state.persistedTableSettings.collapseHeader);
3231
+ this.$getLinkInfo = (md) => this.selectSignal(state => state.linkMaps[md.key]);
3011
3232
  this.resetState = this.updater((state) => {
3012
3233
  const sorted = this.$preSort();
3013
3234
  return ({ ...state, hiddenKeys: [], sorted, filters: {}, groupBy: [], userDefined: { widths: {}, order: {}, table: {} } });
@@ -3069,6 +3290,11 @@ class TableStore extends ComponentStore {
3069
3290
  };
3070
3291
  s.pageSize = settings.tableSettings?.paginatorSettings?.pageSize ?? s.pageSize;
3071
3292
  s.showAll = settings.tableSettings?.paginatorSettings?.defaultAll ?? s.showAll;
3293
+ s.groupBy = (settings.tableSettings?.groupBySettings || []).map(g => ({
3294
+ expandedHeaders: g.expanded ? 'all' : [],
3295
+ key: g.key,
3296
+ sort: ''
3297
+ }));
3072
3298
  return s;
3073
3299
  });
3074
3300
  this.setMetaData = this.updater((state, md) => {
@@ -3088,104 +3314,9 @@ class TableStore extends ComponentStore {
3088
3314
  const initializationState = state.initializationState == InitializationState.Created ? InitializationState.MetaDataLoaded : state.initializationState;
3089
3315
  return { ...state, initializationState, metaData, sorted, userDefined: { ...state.userDefined, order: order } };
3090
3316
  });
3091
- this.showColumn = this.updater((state, key) => ({
3092
- ...state,
3093
- hiddenKeys: state.hiddenKeys.filter(k => k !== key),
3094
- }));
3095
- this.hideColumn = this.updater((state, key) => ({
3096
- ...state,
3097
- hiddenKeys: [...state.hiddenKeys.filter(k => k !== key), key],
3098
- }));
3099
- this.setHiddenColumns = this.updater((state, displayCols) => {
3100
- return ({ ...state, hiddenKeys: displayCols.filter(d => !d.visible).map(d => d.key) });
3101
- });
3102
- this.setUserDefinedWidth = this.updater((state, colWidths) => {
3103
- const userDefinedWidths = { ...state.userDefined.widths };
3104
- colWidths.forEach(cw => {
3105
- userDefinedWidths[cw.key] = cw.widthInPixel;
3106
- });
3107
- return { ...state, userDefined: { ...state.userDefined, widths: userDefinedWidths } };
3108
- });
3109
- this.setUserDefinedOrder = this.updater((state, moved) => {
3110
- const { newOrder, oldOrder } = moved;
3111
- const mdsArr = orderedStateVisibleMetaData(state);
3112
- moveItemInArray(mdsArr, oldOrder, newOrder);
3113
- const userDefinedOrder = mdsArr.reduce((aggregate, current, index) => {
3114
- aggregate[current.key] = index;
3115
- return aggregate;
3116
- }, {});
3117
- return ({ ...state, userDefined: { ...state.userDefined, order: userDefinedOrder } });
3118
- });
3119
- this.setUserDefinedRowHeight = this.updater((state, rowHeight) => {
3120
- return ({ ...state, userDefined: { ...state.userDefined, rowHeight } });
3121
- });
3122
- this.setUserDefinedHeaderHeight = this.updater((state, headerHeight) => {
3123
- return ({ ...state, userDefined: { ...state.userDefined, headerHeight } });
3124
- });
3125
- this.addFilter = this.updater((state, filter) => {
3126
- return this.addFiltersToState(state, [filter]);
3127
- });
3128
- this.addFilters = this.updater((state, filters) => {
3129
- return this.addFiltersToState(state, filters);
3130
- });
3131
- this.removeFilter = this.updater((state, filterId) => {
3132
- const filtersCopy = { ...state.filters };
3133
- delete filtersCopy[filterId];
3134
- return ({ ...state, filters: filtersCopy });
3135
- });
3136
- this.removeFilters = this.updater((state, filterIds) => {
3137
- const filtersCopy = { ...state.filters };
3138
- filterIds.forEach(id => { delete filtersCopy[id]; });
3139
- return ({ ...state, filters: filtersCopy });
3140
- });
3141
- this.clearFilters = this.updater((state) => ({ ...state, filters: {} }));
3142
- this.addFiltersToState = (state, filters) => {
3143
- var customFilters = filters.filter(isCustomFilter);
3144
- var filterInfos = filters.filter(isFilterInfo);
3145
- const filtersObj = filterInfos
3146
- .filter(fltr => Object.keys(state.metaData).some(key => key === fltr.key) || console.warn(`Meta data with key ${fltr.key} not found`))
3147
- .reduce((filtersObj, filter) => {
3148
- if (!filter.filterId) {
3149
- filter.filterId = crypto.randomUUID();
3150
- }
3151
- filtersObj[filter.filterId] = filter;
3152
- return filtersObj;
3153
- }, {});
3154
- customFilters.forEach(fltr => {
3155
- if (!fltr.filterId) {
3156
- fltr.filterId = crypto.randomUUID();
3157
- }
3158
- filtersObj[fltr.filterId] = fltr;
3159
- });
3160
- return {
3161
- ...state,
3162
- filters: { ...state.filters, ...filtersObj }
3163
- };
3164
- };
3165
- this.setSort = this.updater((state, { key, direction }) => {
3166
- const sortArray = state.sorted.filter(s => s.active !== key);
3167
- if (direction) {
3168
- sortArray.unshift({ active: key, direction });
3169
- }
3170
- return {
3171
- ...state,
3172
- sorted: sortArray,
3173
- };
3174
- });
3175
- this.setAllSort = this.updater((state, sortArray) => {
3176
- return {
3177
- ...state,
3178
- sorted: sortArray,
3179
- };
3180
- });
3181
- this.setCurrentPage = this.updater((state, currentPage) => ({ ...state, currentPage }));
3182
- this.setPageSize = this.updater((state, pageSize) => ({ ...state, pageSize }));
3183
- this.setUserDefinedPageSize = this.updater((state, pageSize) => ({ ...state, userDefined: { ...state.userDefined, pageSize } }));
3184
- this.setUserDefinedShowAll = this.updater((state, showAll) => ({ ...state, showAll, userDefined: { ...state.userDefined, showAll } }));
3185
3317
  this.setProps = this.updater((state, props) => {
3186
3318
  return ({ ...state, props });
3187
3319
  });
3188
- this.setTableWidth = this.updater((state, widthInPixels) => ({ ...state, userDefined: { ...state.userDefined, table: { width: widthInPixels } } }));
3189
3320
  this.setInitializationState = this.updater((state, initializationState) => {
3190
3321
  return { ...state, initializationState };
3191
3322
  });
@@ -3199,73 +3330,6 @@ class TableStore extends ComponentStore {
3199
3330
  tableSettings.collapseFooter = options?.collapseFooter ?? !tableSettings.collapseFooter;
3200
3331
  return ({ ...state, persistedTableSettings: new PersistedTableSettings(tableSettings) });
3201
3332
  });
3202
- this.addGroupByKey = this.updater((state, metaDataKey) => ({
3203
- ...state,
3204
- groupBy: [...state.groupBy, { key: metaDataKey, expandedHeaders: [], sort: '' }]
3205
- }));
3206
- this.removeGroupByKey = this.updater((state, groupByKey) => ({
3207
- ...state,
3208
- groupBy: state.groupBy.filter(key => groupByKey !== key.key)
3209
- }));
3210
- this.updateExpandedGroups = this.updater((state, data) => {
3211
- const gbk = replaceInArrayWithClone(state.groupBy, k => k.key === data.key, gk => {
3212
- gk.expandedHeaders = data.isExpanded ? [...gk.expandedHeaders, data.groupUniqueName] : gk.expandedHeaders.filter(g => g !== data.groupUniqueName);
3213
- });
3214
- return ({
3215
- ...state,
3216
- groupBy: gbk
3217
- });
3218
- });
3219
- this.expandAllOfGroup = this.updater((state, data) => {
3220
- const newGroupedData = state.groupBy.map(gb => ({
3221
- key: gb.key,
3222
- expandedHeaders: data.groupHeadersByKey[gb.key]?.map(g => g.uniqueName) ?? gb.expandedHeaders
3223
- }));
3224
- return ({ ...state, groupBy: newGroupedData });
3225
- });
3226
- this.collapseAll = this.updater((state) => ({
3227
- ...state,
3228
- groupBy: state.groupBy.map(gb => ({ key: gb.key, expandedHeaders: [], sort: gb.sort }))
3229
- }));
3230
- this.collapseAllOfKey = this.updater((state, data) => ({
3231
- ...state,
3232
- groupBy: state.groupBy.map(gb => ({
3233
- key: gb.key,
3234
- expandedHeaders: data.keys.includes(gb.key) ? [] : gb.expandedHeaders,
3235
- sort: gb.sort,
3236
- }))
3237
- }));
3238
- this.updateGroupBySort = this.updater((state, data) => {
3239
- const newGroupedData = replaceInArrayWithClone(state.groupBy, gb => gb.key === data.key, gb => {
3240
- gb.sort = data.sort;
3241
- });
3242
- return ({ ...state, groupBy: newGroupedData });
3243
- });
3244
- this.getGroupBySortDirection = (key) => computed(() => {
3245
- const groupBy = this.state().groupBy.find(gb => gb.key === key);
3246
- return groupBy ? groupBy.sort : '';
3247
- });
3248
- this.cycleGroupBySortDirection = this.updater((state, key) => {
3249
- const currentGroupBy = state.groupBy.find(gb => gb.key === key);
3250
- if (!currentGroupBy)
3251
- return state;
3252
- let nextSort;
3253
- switch (currentGroupBy.sort) {
3254
- case '':
3255
- nextSort = 'desc';
3256
- break;
3257
- case 'desc':
3258
- nextSort = 'asc';
3259
- break;
3260
- case 'asc':
3261
- nextSort = '';
3262
- break;
3263
- }
3264
- const newGroupedData = replaceInArrayWithClone(state.groupBy, gb => gb.key === key, gb => {
3265
- gb.sort = nextSort;
3266
- });
3267
- return ({ ...state, groupBy: newGroupedData });
3268
- });
3269
3333
  this.setLinkMaps = this.updater((state, maps) => {
3270
3334
  return ({ ...state, linkMaps: maps });
3271
3335
  });
@@ -3284,6 +3348,7 @@ class TableStore extends ComponentStore {
3284
3348
  return this;
3285
3349
  };
3286
3350
  }
3351
+ #$groupBy;
3287
3352
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: TableStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3288
3353
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: TableStore }); }
3289
3354
  }
@@ -3304,19 +3369,36 @@ const resetable = [
3304
3369
  ];
3305
3370
 
3306
3371
  class MultiSortDirective extends MatSort {
3372
+ #onSortChange;
3373
+ #onStateSortUpdate;
3307
3374
  constructor() {
3308
3375
  super();
3309
3376
  this.state = inject(TableStore);
3310
- this.state.setSort(this.sortChange.pipe(distinctUntilChanged((f, s) => f.active === s.active && f.direction === s.direction), map(sc => ({ key: sc.active, direction: sc.direction }))));
3311
- this.state.on(this.state.sort$, (rules) => {
3312
- const topRule = { active: rules[0]?.active || '', direction: rules[0]?.direction || '' };
3313
- const topActiveChanged = topRule.active !== this.active || '';
3314
- const topDirectionChanged = topRule.direction !== this.direction || '';
3315
- if (topActiveChanged || topDirectionChanged) {
3316
- this.active = topRule.active;
3317
- this.direction = topRule.direction;
3318
- this.sortChange.emit(topRule);
3319
- }
3377
+ this.$sortChange = toSignal(this.sortChange, {
3378
+ equal: (f, s) => f?.active === s?.active && f?.direction === s?.direction
3379
+ });
3380
+ this.#onSortChange = effect(() => {
3381
+ const sortChange = this.$sortChange();
3382
+ if (!sortChange)
3383
+ return;
3384
+ untracked(() => {
3385
+ this.state.setSort({ key: sortChange.active, direction: sortChange.direction });
3386
+ });
3387
+ });
3388
+ this.#onStateSortUpdate = effect(() => {
3389
+ const rules = this.state.$getSorts();
3390
+ if (!rules)
3391
+ return;
3392
+ untracked(() => {
3393
+ const topRule = { active: rules[0]?.active || '', direction: rules[0]?.direction || '' };
3394
+ const topActiveChanged = topRule.active !== this.active || '';
3395
+ const topDirectionChanged = topRule.direction !== this.direction || '';
3396
+ if (topActiveChanged || topDirectionChanged) {
3397
+ this.active = topRule.active;
3398
+ this.direction = topRule.direction;
3399
+ this.sortChange.emit(topRule);
3400
+ }
3401
+ });
3320
3402
  });
3321
3403
  }
3322
3404
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MultiSortDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
@@ -3712,7 +3794,10 @@ class FilterComponent {
3712
3794
  const filterable = this.$metaData()?.additional?.filterOptions?.filterableValues;
3713
3795
  return filterable === 'all values' || filterable?.allValues === true;
3714
3796
  });
3715
- this.close = output();
3797
+ this.close$ = new Subject();
3798
+ this.done$ = new Subject();
3799
+ this.close = outputFromObservable(this.close$);
3800
+ this.done = outputFromObservable(merge(this.done$, this.close$));
3716
3801
  this.$enteredFilterType = signal(undefined);
3717
3802
  this.$currentFilterType = computed(() => this.$enteredFilterType() || this.$filter()?.filterType);
3718
3803
  this.$availableFilterTypes = computed(() => this.filterTypes[this.$filter()?.fieldType]);
@@ -3722,14 +3807,15 @@ class FilterComponent {
3722
3807
  event.preventDefault();
3723
3808
  if (filter.filterValue != null && filter.filterType) {
3724
3809
  this.addFilter(filter);
3725
- this.close.emit();
3810
+ this.close$.next();
3726
3811
  }
3727
3812
  }
3728
3813
  addFilter(filter) {
3729
3814
  this.state.addFilter({ ...filter, filterBy: this.$filterBy() });
3815
+ this.done$.next();
3730
3816
  }
3731
3817
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: FilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3732
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", type: FilterComponent, isStandalone: true, selector: "tb-filter", inputs: { $filter: { classPropertyName: "$filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { close: "close" }, ngImport: i0, template: "@let filter = $filter();\r\n@let currentFilterType = $currentFilterType();\r\n\r\n@if (filter)\r\n{\r\n <mat-card appearance=\"outlined\" class=\"filter-card\">\r\n <mat-card-content>\r\n <form #form=\"ngForm\" (keydown.enter)=\"onEnter(form.value,$event)\" (keydown.escape)=\"close.emit()\">\r\n <input type=\"hidden\" name=\"filterId\" [ngModel]=\"filter.filterId\" />\r\n <input type=\"hidden\" name=\"key\" [ngModel]=\"filter.key\" />\r\n <input type=\"hidden\" name=\"fieldType\" [ngModel]=\"filter.fieldType\" />\r\n <div class=\"head-row\" >\r\n <h4 class=\"filter-name\">{{(filter.key | spaceCase)}} Filter</h4>\r\n <button class=\"cancel-button small-button\" color=\"primary\" mat-icon-button type=\"button\" [matTooltip]=\"'Close'\"\r\n (click)=\"close.emit();\">\r\n <mat-icon class=\"cancel-button\" color=\"primary\">close</mat-icon>\r\n </button>\r\n </div>\r\n <div class=\"filter-row\">\r\n <div class=\"inline\">\r\n <mat-form-field class=\"my-filter\" >\r\n <mat-select placeholder=\"Select Filter Type\" name=\"filterType\" [ngModel]=\"$currentFilterType()\" [panelWidth]=\"null\" (ngModelChange)=\"$enteredFilterType.set($event)\">\r\n @for (kvp of filterTypes[filter.fieldType]; track kvp)\r\n {\r\n <mat-option [value]=\"kvp\">\r\n {{ kvp }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n @if(\r\n filter.fieldType === FieldType.String\r\n || filter.fieldType === FieldType.Array\r\n || filter.fieldType === FieldType.Link\r\n || filter.fieldType === FieldType.Unknown\r\n || filter.fieldType === FieldType.PhoneNumber)\r\n {\r\n <ng-container *ngTemplateOutlet=\"String\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Number || filter.fieldType === FieldType.Currency)\r\n {\r\n <tb-number-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Boolean)\r\n {\r\n <ng-container *ngTemplateOutlet=\"Boolean\" />\r\n }\r\n @else if(\r\n filter.fieldType === FieldType.Date\r\n || (\r\n filter.fieldType === FieldType.DateTime\r\n && (currentFilterType === FilterType.DateIsOn || currentFilterType === FilterType.DateIsNotOn || currentFilterType === FilterType.DateTimeAtOrAfter || currentFilterType === FilterType.DateTimeAtOrBefore)\r\n ))\r\n {\r\n <tb-date-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.DateTime)\r\n {\r\n <tb-date-time-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Enum)\r\n {\r\n <ng-container *ngTemplateOutlet=\"Enum\" />\r\n }\r\n\r\n @if(currentFilterType === FilterType.IsNull)\r\n {\r\n <mat-radio-group name=\"filterValue\" [ngModel]=\"filter.filterValue\">\r\n <mat-radio-button [value]=\"true\">True</mat-radio-button>\r\n <mat-radio-button [value]=\"false\">False</mat-radio-button>\r\n </mat-radio-group>\r\n }\r\n </div>\r\n <button mat-button disableRipple [disabled]=\"form.value.filterValue==undefined || !form.value.filterType\" (click)=\"addFilter(form.value)\">\r\n Apply\r\n </button>\r\n \r\n \r\n <ng-template #String>\r\n @if(currentFilterType !== FilterType.IsNull && currentFilterType !== FilterType.In)\r\n {\r\n <mat-form-field class=\"my-filter\">\r\n <input matInput name=\"filterValue\" [ngModel]=\"filter.filterValue\" />\r\n </mat-form-field>\r\n }\r\n @else if(currentFilterType === FilterType.In)\r\n {\r\n @if($allValuesInMeta())\r\n {\r\n <tb-in-list-filter name=\"filterValue\" [key]=\"filter.key\" [values]=\"filter.filterValue\" [(ngModel)]=\"filter.filterValue\" />\r\n }\r\n @else\r\n {\r\n <lib-in-filter name=\"filterValue\" [type]=\"FieldType.String\" [(ngModel)]=\"filter.filterValue\" />\r\n }\r\n }\r\n </ng-template>\r\n \r\n <ng-template #Boolean >\r\n @if(currentFilterType === FilterType.BooleanEquals)\r\n {\r\n <div class=\"switch\">\r\n <mat-radio-group name=\"filterValue\" [ngModel]=\"filter.filterValue\" >\r\n <mat-radio-button preventEnter [value]=\"true\">True</mat-radio-button>\r\n <mat-radio-button preventEnter [value]=\"false\">False</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n </ng-template>\r\n <ng-template #Enum>\r\n @if(currentFilterType === FilterType.In)\r\n {\r\n <tb-in-list-filter name='filterValue' [key]=\"filter.key\" [values]=\"filter.filterValue\" [(ngModel)]=\"filter.filterValue\" />\r\n\r\n }\r\n </ng-template>\r\n </form>\r\n </mat-card-content>\r\n </mat-card>\r\n}\r\n", styles: [".filter-name{color:var(tb-filter-name);margin:10px 0;font-weight:600;display:inline-block}.switch{display:inline-block}.head-row{display:flex;width:100%;align-items:center;justify-content:space-between}.filter-row{display:flex;align-items:center;gap:1rem}mat-card.filter-card::ng-deep mat-form-field{width:150px}mat-card.filter-card::ng-deep .mat-mdc-form-field-subscript-wrapper{line-height:0}mat-card.filter-card::ng-deep .mat-mdc-form-field-subscript-wrapper:before{height:0}.inline{display:inline-block}.small-button{height:18px;width:18px;font-size:18px;padding:0;margin:0}.small-button ::ng-deep *{line-height:initial;font-size:initial;height:18px;width:18px;font-size:18px;bottom:initial}.cancel-button{font-weight:700}.date-toggle ::ng-deep svg{position:absolute;left:0;top:0}\n"], dependencies: [{ kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$3.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i1$2.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: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: NumberFilterComponent, selector: "tb-number-filter", inputs: ["currentFilterType", "info"] }, { kind: "component", type: DateFilterComponent, selector: "tb-date-filter", inputs: ["info", "currentFilterType"] }, { kind: "component", type: DateTimeFilterComponent, selector: "tb-date-time-filter", inputs: ["info", "currentFilterType"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i8.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i8.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: "component", type: InFilterComponent, selector: "lib-in-filter", inputs: ["type"] }, { kind: "component", type: InListFilterComponent, selector: "tb-in-list-filter", inputs: ["values", "key"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3818
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", type: FilterComponent, isStandalone: true, selector: "tb-filter", inputs: { $filter: { classPropertyName: "$filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { close: "close", done: "done" }, ngImport: i0, template: "@let filter = $filter();\r\n@let currentFilterType = $currentFilterType();\r\n\r\n@if (filter)\r\n{\r\n <mat-card appearance=\"outlined\" class=\"filter-card\">\r\n <mat-card-content>\r\n <form #form=\"ngForm\" (keydown.enter)=\"onEnter(form.value,$event)\" (keydown.escape)=\"close$.next()\">\r\n <input type=\"hidden\" name=\"filterId\" [ngModel]=\"filter.filterId\" />\r\n <input type=\"hidden\" name=\"key\" [ngModel]=\"filter.key\" />\r\n <input type=\"hidden\" name=\"fieldType\" [ngModel]=\"filter.fieldType\" />\r\n <div class=\"head-row\" >\r\n <h4 class=\"filter-name\">{{(filter.key | spaceCase)}} Filter</h4>\r\n <button class=\"cancel-button small-button\" color=\"primary\" mat-icon-button type=\"button\" [matTooltip]=\"'Close'\"\r\n (click)=\"close$.next();\">\r\n <mat-icon class=\"cancel-button\" color=\"primary\">close</mat-icon>\r\n </button>\r\n </div>\r\n <div class=\"filter-row\">\r\n <div class=\"inline\">\r\n <mat-form-field class=\"my-filter\" >\r\n <mat-select placeholder=\"Select Filter Type\" name=\"filterType\" [ngModel]=\"$currentFilterType()\" [panelWidth]=\"null\" (ngModelChange)=\"$enteredFilterType.set($event)\">\r\n @for (kvp of filterTypes[filter.fieldType]; track kvp)\r\n {\r\n <mat-option [value]=\"kvp\">\r\n {{ kvp }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n @if(\r\n filter.fieldType === FieldType.String\r\n || filter.fieldType === FieldType.Array\r\n || filter.fieldType === FieldType.Link\r\n || filter.fieldType === FieldType.Unknown\r\n || filter.fieldType === FieldType.PhoneNumber)\r\n {\r\n <ng-container *ngTemplateOutlet=\"String\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Number || filter.fieldType === FieldType.Currency)\r\n {\r\n <tb-number-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Boolean)\r\n {\r\n <ng-container *ngTemplateOutlet=\"Boolean\" />\r\n }\r\n @else if(\r\n filter.fieldType === FieldType.Date\r\n || (\r\n filter.fieldType === FieldType.DateTime\r\n && (currentFilterType === FilterType.DateIsOn || currentFilterType === FilterType.DateIsNotOn || currentFilterType === FilterType.DateTimeAtOrAfter || currentFilterType === FilterType.DateTimeAtOrBefore)\r\n ))\r\n {\r\n <tb-date-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.DateTime)\r\n {\r\n <tb-date-time-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Enum)\r\n {\r\n <ng-container *ngTemplateOutlet=\"Enum\" />\r\n }\r\n\r\n @if(currentFilterType === FilterType.IsNull)\r\n {\r\n <mat-radio-group name=\"filterValue\" [ngModel]=\"filter.filterValue\">\r\n <mat-radio-button [value]=\"true\">True</mat-radio-button>\r\n <mat-radio-button [value]=\"false\">False</mat-radio-button>\r\n </mat-radio-group>\r\n }\r\n </div>\r\n <button mat-button disableRipple [disabled]=\"form.value.filterValue==undefined || !form.value.filterType\" (click)=\"addFilter(form.value)\">\r\n Apply\r\n </button>\r\n \r\n \r\n <ng-template #String>\r\n @if(currentFilterType !== FilterType.IsNull && currentFilterType !== FilterType.In)\r\n {\r\n <mat-form-field class=\"my-filter\">\r\n <input matInput name=\"filterValue\" [ngModel]=\"filter.filterValue\" />\r\n </mat-form-field>\r\n }\r\n @else if(currentFilterType === FilterType.In)\r\n {\r\n @if($allValuesInMeta())\r\n {\r\n <tb-in-list-filter name=\"filterValue\" [key]=\"filter.key\" [values]=\"filter.filterValue\" [(ngModel)]=\"filter.filterValue\" />\r\n }\r\n @else\r\n {\r\n <lib-in-filter name=\"filterValue\" [type]=\"FieldType.String\" [(ngModel)]=\"filter.filterValue\" />\r\n }\r\n }\r\n </ng-template>\r\n \r\n <ng-template #Boolean >\r\n @if(currentFilterType === FilterType.BooleanEquals)\r\n {\r\n <div class=\"switch\">\r\n <mat-radio-group name=\"filterValue\" [ngModel]=\"filter.filterValue\" >\r\n <mat-radio-button preventEnter [value]=\"true\">True</mat-radio-button>\r\n <mat-radio-button preventEnter [value]=\"false\">False</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n </ng-template>\r\n <ng-template #Enum>\r\n @if(currentFilterType === FilterType.In)\r\n {\r\n <tb-in-list-filter name='filterValue' [key]=\"filter.key\" [values]=\"filter.filterValue\" [(ngModel)]=\"filter.filterValue\" />\r\n\r\n }\r\n </ng-template>\r\n </form>\r\n </mat-card-content>\r\n </mat-card>\r\n}\r\n", styles: [".filter-name{color:var(tb-filter-name);margin:10px 0;font-weight:600;display:inline-block}.switch{display:inline-block}.head-row{display:flex;width:100%;align-items:center;justify-content:space-between}.filter-row{display:flex;align-items:center;gap:1rem}mat-card.filter-card::ng-deep mat-form-field{width:150px}mat-card.filter-card::ng-deep .mat-mdc-form-field-subscript-wrapper{line-height:0}mat-card.filter-card::ng-deep .mat-mdc-form-field-subscript-wrapper:before{height:0}.inline{display:inline-block}.small-button{height:18px;width:18px;font-size:18px;padding:0;margin:0}.small-button ::ng-deep *{line-height:initial;font-size:initial;height:18px;width:18px;font-size:18px;bottom:initial}.cancel-button{font-weight:700}.date-toggle ::ng-deep svg{position:absolute;left:0;top:0}\n"], dependencies: [{ kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$3.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: SpaceCasePipe, name: "spaceCase" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i1$2.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: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: NumberFilterComponent, selector: "tb-number-filter", inputs: ["currentFilterType", "info"] }, { kind: "component", type: DateFilterComponent, selector: "tb-date-filter", inputs: ["info", "currentFilterType"] }, { kind: "component", type: DateTimeFilterComponent, selector: "tb-date-time-filter", inputs: ["info", "currentFilterType"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i8.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i8.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: "component", type: InFilterComponent, selector: "lib-in-filter", inputs: ["type"] }, { kind: "component", type: InListFilterComponent, selector: "tb-in-list-filter", inputs: ["values", "key"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3733
3819
  }
3734
3820
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: FilterComponent, decorators: [{
3735
3821
  type: Component,
@@ -3738,7 +3824,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImpor
3738
3824
  MatInputModule, MatSelectModule, NumberFilterComponent,
3739
3825
  DateFilterComponent, DateTimeFilterComponent, MatRadioModule, InFilterComponent, InListFilterComponent,
3740
3826
  NgTemplateOutlet
3741
- ], template: "@let filter = $filter();\r\n@let currentFilterType = $currentFilterType();\r\n\r\n@if (filter)\r\n{\r\n <mat-card appearance=\"outlined\" class=\"filter-card\">\r\n <mat-card-content>\r\n <form #form=\"ngForm\" (keydown.enter)=\"onEnter(form.value,$event)\" (keydown.escape)=\"close.emit()\">\r\n <input type=\"hidden\" name=\"filterId\" [ngModel]=\"filter.filterId\" />\r\n <input type=\"hidden\" name=\"key\" [ngModel]=\"filter.key\" />\r\n <input type=\"hidden\" name=\"fieldType\" [ngModel]=\"filter.fieldType\" />\r\n <div class=\"head-row\" >\r\n <h4 class=\"filter-name\">{{(filter.key | spaceCase)}} Filter</h4>\r\n <button class=\"cancel-button small-button\" color=\"primary\" mat-icon-button type=\"button\" [matTooltip]=\"'Close'\"\r\n (click)=\"close.emit();\">\r\n <mat-icon class=\"cancel-button\" color=\"primary\">close</mat-icon>\r\n </button>\r\n </div>\r\n <div class=\"filter-row\">\r\n <div class=\"inline\">\r\n <mat-form-field class=\"my-filter\" >\r\n <mat-select placeholder=\"Select Filter Type\" name=\"filterType\" [ngModel]=\"$currentFilterType()\" [panelWidth]=\"null\" (ngModelChange)=\"$enteredFilterType.set($event)\">\r\n @for (kvp of filterTypes[filter.fieldType]; track kvp)\r\n {\r\n <mat-option [value]=\"kvp\">\r\n {{ kvp }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n @if(\r\n filter.fieldType === FieldType.String\r\n || filter.fieldType === FieldType.Array\r\n || filter.fieldType === FieldType.Link\r\n || filter.fieldType === FieldType.Unknown\r\n || filter.fieldType === FieldType.PhoneNumber)\r\n {\r\n <ng-container *ngTemplateOutlet=\"String\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Number || filter.fieldType === FieldType.Currency)\r\n {\r\n <tb-number-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Boolean)\r\n {\r\n <ng-container *ngTemplateOutlet=\"Boolean\" />\r\n }\r\n @else if(\r\n filter.fieldType === FieldType.Date\r\n || (\r\n filter.fieldType === FieldType.DateTime\r\n && (currentFilterType === FilterType.DateIsOn || currentFilterType === FilterType.DateIsNotOn || currentFilterType === FilterType.DateTimeAtOrAfter || currentFilterType === FilterType.DateTimeAtOrBefore)\r\n ))\r\n {\r\n <tb-date-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.DateTime)\r\n {\r\n <tb-date-time-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Enum)\r\n {\r\n <ng-container *ngTemplateOutlet=\"Enum\" />\r\n }\r\n\r\n @if(currentFilterType === FilterType.IsNull)\r\n {\r\n <mat-radio-group name=\"filterValue\" [ngModel]=\"filter.filterValue\">\r\n <mat-radio-button [value]=\"true\">True</mat-radio-button>\r\n <mat-radio-button [value]=\"false\">False</mat-radio-button>\r\n </mat-radio-group>\r\n }\r\n </div>\r\n <button mat-button disableRipple [disabled]=\"form.value.filterValue==undefined || !form.value.filterType\" (click)=\"addFilter(form.value)\">\r\n Apply\r\n </button>\r\n \r\n \r\n <ng-template #String>\r\n @if(currentFilterType !== FilterType.IsNull && currentFilterType !== FilterType.In)\r\n {\r\n <mat-form-field class=\"my-filter\">\r\n <input matInput name=\"filterValue\" [ngModel]=\"filter.filterValue\" />\r\n </mat-form-field>\r\n }\r\n @else if(currentFilterType === FilterType.In)\r\n {\r\n @if($allValuesInMeta())\r\n {\r\n <tb-in-list-filter name=\"filterValue\" [key]=\"filter.key\" [values]=\"filter.filterValue\" [(ngModel)]=\"filter.filterValue\" />\r\n }\r\n @else\r\n {\r\n <lib-in-filter name=\"filterValue\" [type]=\"FieldType.String\" [(ngModel)]=\"filter.filterValue\" />\r\n }\r\n }\r\n </ng-template>\r\n \r\n <ng-template #Boolean >\r\n @if(currentFilterType === FilterType.BooleanEquals)\r\n {\r\n <div class=\"switch\">\r\n <mat-radio-group name=\"filterValue\" [ngModel]=\"filter.filterValue\" >\r\n <mat-radio-button preventEnter [value]=\"true\">True</mat-radio-button>\r\n <mat-radio-button preventEnter [value]=\"false\">False</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n </ng-template>\r\n <ng-template #Enum>\r\n @if(currentFilterType === FilterType.In)\r\n {\r\n <tb-in-list-filter name='filterValue' [key]=\"filter.key\" [values]=\"filter.filterValue\" [(ngModel)]=\"filter.filterValue\" />\r\n\r\n }\r\n </ng-template>\r\n </form>\r\n </mat-card-content>\r\n </mat-card>\r\n}\r\n", styles: [".filter-name{color:var(tb-filter-name);margin:10px 0;font-weight:600;display:inline-block}.switch{display:inline-block}.head-row{display:flex;width:100%;align-items:center;justify-content:space-between}.filter-row{display:flex;align-items:center;gap:1rem}mat-card.filter-card::ng-deep mat-form-field{width:150px}mat-card.filter-card::ng-deep .mat-mdc-form-field-subscript-wrapper{line-height:0}mat-card.filter-card::ng-deep .mat-mdc-form-field-subscript-wrapper:before{height:0}.inline{display:inline-block}.small-button{height:18px;width:18px;font-size:18px;padding:0;margin:0}.small-button ::ng-deep *{line-height:initial;font-size:initial;height:18px;width:18px;font-size:18px;bottom:initial}.cancel-button{font-weight:700}.date-toggle ::ng-deep svg{position:absolute;left:0;top:0}\n"] }]
3827
+ ], template: "@let filter = $filter();\r\n@let currentFilterType = $currentFilterType();\r\n\r\n@if (filter)\r\n{\r\n <mat-card appearance=\"outlined\" class=\"filter-card\">\r\n <mat-card-content>\r\n <form #form=\"ngForm\" (keydown.enter)=\"onEnter(form.value,$event)\" (keydown.escape)=\"close$.next()\">\r\n <input type=\"hidden\" name=\"filterId\" [ngModel]=\"filter.filterId\" />\r\n <input type=\"hidden\" name=\"key\" [ngModel]=\"filter.key\" />\r\n <input type=\"hidden\" name=\"fieldType\" [ngModel]=\"filter.fieldType\" />\r\n <div class=\"head-row\" >\r\n <h4 class=\"filter-name\">{{(filter.key | spaceCase)}} Filter</h4>\r\n <button class=\"cancel-button small-button\" color=\"primary\" mat-icon-button type=\"button\" [matTooltip]=\"'Close'\"\r\n (click)=\"close$.next();\">\r\n <mat-icon class=\"cancel-button\" color=\"primary\">close</mat-icon>\r\n </button>\r\n </div>\r\n <div class=\"filter-row\">\r\n <div class=\"inline\">\r\n <mat-form-field class=\"my-filter\" >\r\n <mat-select placeholder=\"Select Filter Type\" name=\"filterType\" [ngModel]=\"$currentFilterType()\" [panelWidth]=\"null\" (ngModelChange)=\"$enteredFilterType.set($event)\">\r\n @for (kvp of filterTypes[filter.fieldType]; track kvp)\r\n {\r\n <mat-option [value]=\"kvp\">\r\n {{ kvp }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n @if(\r\n filter.fieldType === FieldType.String\r\n || filter.fieldType === FieldType.Array\r\n || filter.fieldType === FieldType.Link\r\n || filter.fieldType === FieldType.Unknown\r\n || filter.fieldType === FieldType.PhoneNumber)\r\n {\r\n <ng-container *ngTemplateOutlet=\"String\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Number || filter.fieldType === FieldType.Currency)\r\n {\r\n <tb-number-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Boolean)\r\n {\r\n <ng-container *ngTemplateOutlet=\"Boolean\" />\r\n }\r\n @else if(\r\n filter.fieldType === FieldType.Date\r\n || (\r\n filter.fieldType === FieldType.DateTime\r\n && (currentFilterType === FilterType.DateIsOn || currentFilterType === FilterType.DateIsNotOn || currentFilterType === FilterType.DateTimeAtOrAfter || currentFilterType === FilterType.DateTimeAtOrBefore)\r\n ))\r\n {\r\n <tb-date-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.DateTime)\r\n {\r\n <tb-date-time-filter [info]=\"filter\" [currentFilterType]=\"currentFilterType!\" />\r\n }\r\n @else if(filter.fieldType === FieldType.Enum)\r\n {\r\n <ng-container *ngTemplateOutlet=\"Enum\" />\r\n }\r\n\r\n @if(currentFilterType === FilterType.IsNull)\r\n {\r\n <mat-radio-group name=\"filterValue\" [ngModel]=\"filter.filterValue\">\r\n <mat-radio-button [value]=\"true\">True</mat-radio-button>\r\n <mat-radio-button [value]=\"false\">False</mat-radio-button>\r\n </mat-radio-group>\r\n }\r\n </div>\r\n <button mat-button disableRipple [disabled]=\"form.value.filterValue==undefined || !form.value.filterType\" (click)=\"addFilter(form.value)\">\r\n Apply\r\n </button>\r\n \r\n \r\n <ng-template #String>\r\n @if(currentFilterType !== FilterType.IsNull && currentFilterType !== FilterType.In)\r\n {\r\n <mat-form-field class=\"my-filter\">\r\n <input matInput name=\"filterValue\" [ngModel]=\"filter.filterValue\" />\r\n </mat-form-field>\r\n }\r\n @else if(currentFilterType === FilterType.In)\r\n {\r\n @if($allValuesInMeta())\r\n {\r\n <tb-in-list-filter name=\"filterValue\" [key]=\"filter.key\" [values]=\"filter.filterValue\" [(ngModel)]=\"filter.filterValue\" />\r\n }\r\n @else\r\n {\r\n <lib-in-filter name=\"filterValue\" [type]=\"FieldType.String\" [(ngModel)]=\"filter.filterValue\" />\r\n }\r\n }\r\n </ng-template>\r\n \r\n <ng-template #Boolean >\r\n @if(currentFilterType === FilterType.BooleanEquals)\r\n {\r\n <div class=\"switch\">\r\n <mat-radio-group name=\"filterValue\" [ngModel]=\"filter.filterValue\" >\r\n <mat-radio-button preventEnter [value]=\"true\">True</mat-radio-button>\r\n <mat-radio-button preventEnter [value]=\"false\">False</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n </ng-template>\r\n <ng-template #Enum>\r\n @if(currentFilterType === FilterType.In)\r\n {\r\n <tb-in-list-filter name='filterValue' [key]=\"filter.key\" [values]=\"filter.filterValue\" [(ngModel)]=\"filter.filterValue\" />\r\n\r\n }\r\n </ng-template>\r\n </form>\r\n </mat-card-content>\r\n </mat-card>\r\n}\r\n", styles: [".filter-name{color:var(tb-filter-name);margin:10px 0;font-weight:600;display:inline-block}.switch{display:inline-block}.head-row{display:flex;width:100%;align-items:center;justify-content:space-between}.filter-row{display:flex;align-items:center;gap:1rem}mat-card.filter-card::ng-deep mat-form-field{width:150px}mat-card.filter-card::ng-deep .mat-mdc-form-field-subscript-wrapper{line-height:0}mat-card.filter-card::ng-deep .mat-mdc-form-field-subscript-wrapper:before{height:0}.inline{display:inline-block}.small-button{height:18px;width:18px;font-size:18px;padding:0;margin:0}.small-button ::ng-deep *{line-height:initial;font-size:initial;height:18px;width:18px;font-size:18px;bottom:initial}.cancel-button{font-weight:700}.date-toggle ::ng-deep svg{position:absolute;left:0;top:0}\n"] }]
3742
3828
  }] });
3743
3829
 
3744
3830
  class GenColDisplayerComponent {
@@ -3929,7 +4015,7 @@ class FilterChipsComponent {
3929
4015
  this.filterStore.clearAll();
3930
4016
  }
3931
4017
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: FilterChipsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3932
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", type: FilterChipsComponent, isStandalone: true, selector: "lib-filter-list", ngImport: i0, template: "<div class=\"d-w\">\r\n\r\n @if ($currentFilters().length)\r\n {\r\n <button class=\"cancel-button\" mat-icon-button matTooltip=\"Close all Filters Cards\" (click)=\"clearAll()\">\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 {\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 {\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 @for (filter of $certainCustomFilters(); track filter.filterId)\r\n {\r\n <mat-chip (removed)=\"tableState.removeFilter(filter.filterId!)\">\r\n {{filter.chipLabel}}\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n @if (($filters().length + $certainCustomFilters().length) > 1)\r\n {\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{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{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.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.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$1.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$1.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i4$1.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 }); }
4018
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", type: FilterChipsComponent, isStandalone: true, selector: "lib-filter-list", ngImport: i0, template: "<div class=\"d-w\">\r\n\r\n @if ($currentFilters().length)\r\n {\r\n <button class=\"cancel-button\" mat-icon-button matTooltip=\"Close all Filters Cards\" (click)=\"clearAll()\">\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 {\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 {\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 @for (filter of $certainCustomFilters(); track filter.filterId)\r\n {\r\n <mat-chip (removed)=\"tableState.removeFilter(filter.filterId!)\">\r\n {{filter.chipLabel}}\r\n <mat-icon matChipRemove>cancel</mat-icon>\r\n </mat-chip>\r\n }\r\n @if (($filters().length + $certainCustomFilters().length) > 1)\r\n {\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{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{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.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FilterComponent, selector: "tb-filter", inputs: ["filter"], outputs: ["close", "done"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i4$1.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$1.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i4$1.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 }); }
3933
4019
  }
3934
4020
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: FilterChipsComponent, decorators: [{
3935
4021
  type: Component,
@@ -4166,6 +4252,7 @@ class ColumnHeaderMenuComponent {
4166
4252
  });
4167
4253
  this.$currentFilterType = linkedSignal(() => this.$metaFilterType());
4168
4254
  this.$key = computed(() => this.$metaData().key || crypto.randomUUID());
4255
+ this.addFilter$ = new Subject();
4169
4256
  }
4170
4257
  hideField(key) {
4171
4258
  this.tableState.hideColumn(key);
@@ -4200,21 +4287,22 @@ class ColumnHeaderMenuComponent {
4200
4287
  addFilter(metaData) {
4201
4288
  if (!this.filterStore)
4202
4289
  return;
4203
- this.filterStore.addFilter({
4290
+ this.addFilter$.next({
4204
4291
  key: metaData.key,
4205
4292
  fieldType: metaData.filterLogic?.filterType || metaData.fieldType,
4206
4293
  filterBy: metaData.filterLogic?.filterBy === 'use map' ? metaData.map : metaData.filterLogic?.filterBy
4207
4294
  });
4208
4295
  }
4209
4296
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ColumnHeaderMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4210
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", 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 filterFieldType = $filterFieldType();\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 ($fieldType() !== FieldType.NotMapped || !!$metaData().groupByLogic?.groupBy)\r\n {\r\n <button color=\"primary\" 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 color=\"primary\" 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 <div (keydown)=\"$event.stopImmediatePropagation()\">\r\n @let filterValue = $filterValue();\r\n <ng-template matMenuContent>\r\n @if (filterFieldType !== FieldType.NotMapped)\r\n {\r\n <button color=\"primary\" mat-menu-item (click)=\"addFilter(metaData)\">\r\n <mat-icon color=\"primary\">filter_list</mat-icon>\r\n <span>Choose Other Filter</span>\r\n </button>\r\n <ng-form #myForm=\"ngForm\" class=\"tb-header-filter\" (keydown.enter)=\"onEnter(myForm.value, metaData)\">\r\n @if(currentFilterType === FilterType.In)\r\n {\r\n <tb-in-list-filter name=\"filterValue\" [key]=\"metaData.key\" [ngModel]=\"filterValue\" [values]=\"filterValue\" />\r\n }\r\n @else if(filterFieldType === FieldType.Link || filterFieldType === FieldType.String || filterFieldType === FieldType.Array || filterFieldType === FieldType.Unknown || filterFieldType === FieldType.PhoneNumber)\r\n {\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\" class=\"header-filter-icon-button\" (click)=\"setStringFilterType()\">\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 (filterFieldType === FieldType.Number || filterFieldType === FieldType.Currency)\r\n {\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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberLessThan }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberGreaterThan }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberEquals }\"\r\n (click)=\"setFilterType(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 (filterFieldType === FieldType.Boolean)\r\n {\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 #ctrl=\"matRadioGroup\" #boolField='ngModel' stop-propagation class=\"font\" name=\"filterValue\" [ngModel]=\"undefined\" >\r\n <mat-radio-button class=\"filter-radio-button\" [value]=\"true\" (click)=\"boolField.control.setValue(true);\">True</mat-radio-button><br/>\r\n <mat-radio-button class=\"filter-radio-button\" [value]=\"false\" (click)=\"boolField.control.setValue(false)\">False</mat-radio-button><br/>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n @else if (filterFieldType === FieldType.Date || filterFieldType === FieldType.DateTime)\r\n {\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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrAfter }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrBefore }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateIsOn }\"\r\n (click)=\"setFilterType(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 preventEnter [for]=\"calendar\" />\r\n <mat-datepicker #calendar />\r\n </mat-form-field>\r\n }\r\n <button mat-button disableRipple [disabled]=\"myForm.value.filterValue == undefined\" (click)=\"onEnter(myForm.value, metaData)\">\r\n Apply\r\n </button>\r\n </ng-form>\r\n }\r\n </ng-template>\r\n </div>\r\n\r\n</mat-menu>\r\n", styles: [":host{--mat-button-filled-container-height: 24px;--mat-button-filled-touch-target-display: none;--mat-button-outlined-container-height: 24px;--mat-button-outlined-touch-target-display: none;--mat-button-protected-container-height: 24px;--mat-button-protected-touch-target-display: none;--mat-button-text-container-height: 24px;--mat-button-text-touch-target-display: none;--mat-button-tonal-container-height: 24px;--mat-button-tonal-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;width: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.MatMenuContent, selector: "ng-template[matMenuContent]" }, { 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$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.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: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.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", inputs: ["values", "key"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i1$2.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: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i1$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.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: i8.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i8.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: i2$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i2$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i2$1.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4297
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", 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 filterFieldType = $filterFieldType();\r\n@let currentFilterType = $currentFilterType();\r\n\r\n<button #b 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 ($fieldType() !== FieldType.NotMapped || !!$metaData().groupByLogic?.groupBy)\r\n {\r\n <button color=\"primary\" 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 color=\"primary\" 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 <div (keydown)=\"$event.stopImmediatePropagation()\">\r\n @let filterValue = $filterValue();\r\n <ng-template matMenuContent>\r\n @if (filterFieldType !== FieldType.NotMapped)\r\n {\r\n <button color=\"primary\" mat-menu-item (click)=\"addFilter(metaData)\">\r\n <mat-icon color=\"primary\">filter_list</mat-icon>\r\n <span>Choose Other Filter</span>\r\n </button>\r\n <ng-form #myForm=\"ngForm\" class=\"tb-header-filter\" (keydown.enter)=\"onEnter(myForm.value, metaData)\">\r\n @if(currentFilterType === FilterType.In)\r\n {\r\n <tb-in-list-filter name=\"filterValue\" [key]=\"metaData.key\" [ngModel]=\"filterValue\" [values]=\"filterValue\" />\r\n }\r\n @else if(filterFieldType === FieldType.Link || filterFieldType === FieldType.String || filterFieldType === FieldType.Array || filterFieldType === FieldType.Unknown || filterFieldType === FieldType.PhoneNumber)\r\n {\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\" class=\"header-filter-icon-button\" (click)=\"setStringFilterType()\">\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 (filterFieldType === FieldType.Number || filterFieldType === FieldType.Currency)\r\n {\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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberLessThan }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberGreaterThan }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberEquals }\"\r\n (click)=\"setFilterType(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 (filterFieldType === FieldType.Boolean)\r\n {\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 #ctrl=\"matRadioGroup\" #boolField='ngModel' stop-propagation class=\"font\" name=\"filterValue\" [ngModel]=\"undefined\" >\r\n <mat-radio-button class=\"filter-radio-button\" [value]=\"true\" (click)=\"boolField.control.setValue(true);\">True</mat-radio-button><br/>\r\n <mat-radio-button class=\"filter-radio-button\" [value]=\"false\" (click)=\"boolField.control.setValue(false)\">False</mat-radio-button><br/>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n @else if (filterFieldType === FieldType.Date || filterFieldType === FieldType.DateTime)\r\n {\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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrAfter }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrBefore }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateIsOn }\"\r\n (click)=\"setFilterType(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 preventEnter [for]=\"calendar\" />\r\n <mat-datepicker #calendar />\r\n </mat-form-field>\r\n }\r\n <button mat-button disableRipple [disabled]=\"myForm.value.filterValue == undefined\" (click)=\"onEnter(myForm.value, metaData)\">\r\n Apply\r\n </button>\r\n </ng-form>\r\n }\r\n </ng-template>\r\n </div>\r\n\r\n</mat-menu>\r\n\r\n<tb-filter\r\n *opDialog=\"addFilter$; let filter; origin b._elementRef.nativeElement; positionOnScreen { width: 300 }\"\r\n [filter]=\"filter\" (done)=\"addFilter$.next(null)\" />\r\n", styles: [":host{--mat-button-filled-container-height: 24px;--mat-button-filled-touch-target-display: none;--mat-button-outlined-container-height: 24px;--mat-button-outlined-touch-target-display: none;--mat-button-protected-container-height: 24px;--mat-button-protected-touch-target-display: none;--mat-button-text-container-height: 24px;--mat-button-text-touch-target-display: none;--mat-button-tonal-container-height: 24px;--mat-button-tonal-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;width: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.MatMenuContent, selector: "ng-template[matMenuContent]" }, { 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$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.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: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.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", inputs: ["values", "key"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i1$2.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: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i1$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.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: i8.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i8.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: i2$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i2$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i2$1.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: DialogDirective, selector: "[opDialog]", inputs: ["opDialogAddDialogClass", "opDialogConfig", "opDialog", "opDialogOrigin", "opDialogPositionOnScreen"], outputs: ["opDialogClosed"] }, { kind: "component", type: FilterComponent, selector: "tb-filter", inputs: ["filter"], outputs: ["close", "done"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4211
4298
  }
4212
4299
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ColumnHeaderMenuComponent, decorators: [{
4213
4300
  type: Component,
4214
4301
  args: [{ selector: 'tb-header-menu', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
4215
4302
  MatMenuModule, MatIconModule, MatButtonModule, FormsModule, InListFilterComponent,
4216
- MatInputModule, MatTooltipModule, StopPropagationDirective, MatRadioModule, MatDatepickerModule
4217
- ], template: "@let metaData = $metaData();\r\n@let filterFieldType = $filterFieldType();\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 ($fieldType() !== FieldType.NotMapped || !!$metaData().groupByLogic?.groupBy)\r\n {\r\n <button color=\"primary\" 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 color=\"primary\" 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 <div (keydown)=\"$event.stopImmediatePropagation()\">\r\n @let filterValue = $filterValue();\r\n <ng-template matMenuContent>\r\n @if (filterFieldType !== FieldType.NotMapped)\r\n {\r\n <button color=\"primary\" mat-menu-item (click)=\"addFilter(metaData)\">\r\n <mat-icon color=\"primary\">filter_list</mat-icon>\r\n <span>Choose Other Filter</span>\r\n </button>\r\n <ng-form #myForm=\"ngForm\" class=\"tb-header-filter\" (keydown.enter)=\"onEnter(myForm.value, metaData)\">\r\n @if(currentFilterType === FilterType.In)\r\n {\r\n <tb-in-list-filter name=\"filterValue\" [key]=\"metaData.key\" [ngModel]=\"filterValue\" [values]=\"filterValue\" />\r\n }\r\n @else if(filterFieldType === FieldType.Link || filterFieldType === FieldType.String || filterFieldType === FieldType.Array || filterFieldType === FieldType.Unknown || filterFieldType === FieldType.PhoneNumber)\r\n {\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\" class=\"header-filter-icon-button\" (click)=\"setStringFilterType()\">\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 (filterFieldType === FieldType.Number || filterFieldType === FieldType.Currency)\r\n {\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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberLessThan }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberGreaterThan }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberEquals }\"\r\n (click)=\"setFilterType(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 (filterFieldType === FieldType.Boolean)\r\n {\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 #ctrl=\"matRadioGroup\" #boolField='ngModel' stop-propagation class=\"font\" name=\"filterValue\" [ngModel]=\"undefined\" >\r\n <mat-radio-button class=\"filter-radio-button\" [value]=\"true\" (click)=\"boolField.control.setValue(true);\">True</mat-radio-button><br/>\r\n <mat-radio-button class=\"filter-radio-button\" [value]=\"false\" (click)=\"boolField.control.setValue(false)\">False</mat-radio-button><br/>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n @else if (filterFieldType === FieldType.Date || filterFieldType === FieldType.DateTime)\r\n {\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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrAfter }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrBefore }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateIsOn }\"\r\n (click)=\"setFilterType(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 preventEnter [for]=\"calendar\" />\r\n <mat-datepicker #calendar />\r\n </mat-form-field>\r\n }\r\n <button mat-button disableRipple [disabled]=\"myForm.value.filterValue == undefined\" (click)=\"onEnter(myForm.value, metaData)\">\r\n Apply\r\n </button>\r\n </ng-form>\r\n }\r\n </ng-template>\r\n </div>\r\n\r\n</mat-menu>\r\n", styles: [":host{--mat-button-filled-container-height: 24px;--mat-button-filled-touch-target-display: none;--mat-button-outlined-container-height: 24px;--mat-button-outlined-touch-target-display: none;--mat-button-protected-container-height: 24px;--mat-button-protected-touch-target-display: none;--mat-button-text-container-height: 24px;--mat-button-text-touch-target-display: none;--mat-button-tonal-container-height: 24px;--mat-button-tonal-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;width: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"] }]
4303
+ MatInputModule, MatTooltipModule, StopPropagationDirective, MatRadioModule, MatDatepickerModule,
4304
+ DialogDirective, FilterComponent
4305
+ ], template: "@let metaData = $metaData();\r\n@let filterFieldType = $filterFieldType();\r\n@let currentFilterType = $currentFilterType();\r\n\r\n<button #b 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 ($fieldType() !== FieldType.NotMapped || !!$metaData().groupByLogic?.groupBy)\r\n {\r\n <button color=\"primary\" 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 color=\"primary\" 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 <div (keydown)=\"$event.stopImmediatePropagation()\">\r\n @let filterValue = $filterValue();\r\n <ng-template matMenuContent>\r\n @if (filterFieldType !== FieldType.NotMapped)\r\n {\r\n <button color=\"primary\" mat-menu-item (click)=\"addFilter(metaData)\">\r\n <mat-icon color=\"primary\">filter_list</mat-icon>\r\n <span>Choose Other Filter</span>\r\n </button>\r\n <ng-form #myForm=\"ngForm\" class=\"tb-header-filter\" (keydown.enter)=\"onEnter(myForm.value, metaData)\">\r\n @if(currentFilterType === FilterType.In)\r\n {\r\n <tb-in-list-filter name=\"filterValue\" [key]=\"metaData.key\" [ngModel]=\"filterValue\" [values]=\"filterValue\" />\r\n }\r\n @else if(filterFieldType === FieldType.Link || filterFieldType === FieldType.String || filterFieldType === FieldType.Array || filterFieldType === FieldType.Unknown || filterFieldType === FieldType.PhoneNumber)\r\n {\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\" class=\"header-filter-icon-button\" (click)=\"setStringFilterType()\">\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 (filterFieldType === FieldType.Number || filterFieldType === FieldType.Currency)\r\n {\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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberLessThan }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberGreaterThan }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.NumberEquals }\"\r\n (click)=\"setFilterType(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 (filterFieldType === FieldType.Boolean)\r\n {\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 #ctrl=\"matRadioGroup\" #boolField='ngModel' stop-propagation class=\"font\" name=\"filterValue\" [ngModel]=\"undefined\" >\r\n <mat-radio-button class=\"filter-radio-button\" [value]=\"true\" (click)=\"boolField.control.setValue(true);\">True</mat-radio-button><br/>\r\n <mat-radio-button class=\"filter-radio-button\" [value]=\"false\" (click)=\"boolField.control.setValue(false)\">False</mat-radio-button><br/>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n @else if (filterFieldType === FieldType.Date || filterFieldType === FieldType.DateTime)\r\n {\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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrAfter }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateOnOrBefore }\"\r\n (click)=\"setFilterType(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\" [class]=\"{'chosen-icon': currentFilterType === FilterType.DateIsOn }\"\r\n (click)=\"setFilterType(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 preventEnter [for]=\"calendar\" />\r\n <mat-datepicker #calendar />\r\n </mat-form-field>\r\n }\r\n <button mat-button disableRipple [disabled]=\"myForm.value.filterValue == undefined\" (click)=\"onEnter(myForm.value, metaData)\">\r\n Apply\r\n </button>\r\n </ng-form>\r\n }\r\n </ng-template>\r\n </div>\r\n\r\n</mat-menu>\r\n\r\n<tb-filter\r\n *opDialog=\"addFilter$; let filter; origin b._elementRef.nativeElement; positionOnScreen { width: 300 }\"\r\n [filter]=\"filter\" (done)=\"addFilter$.next(null)\" />\r\n", styles: [":host{--mat-button-filled-container-height: 24px;--mat-button-filled-touch-target-display: none;--mat-button-outlined-container-height: 24px;--mat-button-outlined-touch-target-display: none;--mat-button-protected-container-height: 24px;--mat-button-protected-touch-target-display: none;--mat-button-text-container-height: 24px;--mat-button-text-touch-target-display: none;--mat-button-tonal-container-height: 24px;--mat-button-tonal-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;width: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"] }]
4218
4306
  }] });
4219
4307
 
4220
4308
  class ColumnTotalPipe {
@@ -4498,56 +4586,54 @@ function groupData(groupByData, groupData, level = 1, metaData, parentGroupName)
4498
4586
  };
4499
4587
  });
4500
4588
  if (groupByData.sort) {
4501
- groupedDataArr = sortGroups(groupByData, groupedDataArr);
4589
+ groupedDataArr = sortGroupsByGroupSortOneLevel(groupByData, groupedDataArr);
4502
4590
  }
4503
4591
  return groupedDataArr;
4504
4592
  }
4505
4593
  function setCustomGroupBy(customGroupBy) {
4506
4594
  tbGroupBy = customGroupBy;
4507
4595
  }
4508
- function updateGroupByState(groupedData, { data, groups, expanded, sorts }, firstRun, metaData) {
4596
+ function updateGroupByState(groupedData, { data, groups, expanded, groupSorts }, firstRun, metaData) {
4509
4597
  if (firstRun
4510
- || dataUpdated(data, groups, expanded, sorts)
4511
- || groupsUpdated(groups, expanded, sorts)) {
4598
+ || dataUpdated(data, groups, expanded, groupSorts)
4599
+ || groupsUpdated(groups, expanded, groupSorts)) {
4512
4600
  const combinedGroupsAndSorts = groups.value.map(g => {
4513
- const sortForGroup = sorts.value.find(s => s.key === g.key);
4601
+ const sortForGroup = groupSorts.value.find(s => s.key === g.key);
4514
4602
  return { ...g, sort: sortForGroup?.sort || '' };
4515
4603
  });
4516
4604
  groupedData = groups.value.length ? getGroupedData(data.value, combinedGroupsAndSorts, metaData) : data.value;
4517
4605
  }
4518
4606
  else {
4519
- let curr = [...sorts.value];
4520
- groupedData = sort(groupedData);
4521
- function sort(groups) {
4522
- const sortData = sorts.value?.find(gs => gs.key === groups[0]?.key);
4523
- if (sortData?.sort) {
4524
- groups = sortGroups(sortData, groups);
4525
- }
4526
- else {
4527
- groups = groups.toSorted((a, b) => a[initIndexSymbol] - b[initIndexSymbol]);
4528
- }
4529
- curr = curr.filter(c => c.key !== sortData?.key);
4530
- if (!groups[0]?.hasTheData) {
4531
- groups.forEach((g, i) => groups[i].groups = sort(g.groups));
4532
- }
4533
- return groups;
4534
- }
4607
+ groupedData = sortGroupsDeep(groupedData, groupSorts.value);
4535
4608
  }
4536
4609
  const newDisplayData = expanded.value.length === 0
4537
4610
  ? groupedData
4538
- : groupedData.map(group => mapGroupHeader(group, expanded.value.flatMap(g => g.expandedHeaders))).flat();
4611
+ : groupedData.map(group => mapGroupHeader(group, expanded.value.flatMap(g => g.expandedHeaders), expanded.value.filter(g => g.expandedHeaders === 'all').map(g => g.key))).flat();
4539
4612
  return ({ displayData: newDisplayData, groupedData });
4540
4613
  }
4541
- function sortGroups(sortData, groups) {
4614
+ function sortGroupsByGroupSortOneLevel(sortData, groups) {
4542
4615
  const direction = sortData.sort;
4543
4616
  const multiplier = direction === 'asc' ? 1 : -1;
4544
4617
  return groups.toSorted((a, b) => a.length === b.length ? 0 : (a.length > b.length ? 1 : -1) * multiplier);
4545
4618
  }
4546
- function mapGroupHeader(obj, expandedHeaders) {
4547
- const showChildren = expandedHeaders === true || expandedHeaders.includes(obj.uniqueName);
4619
+ function sortGroupsDeep(groups, sorts) {
4620
+ const sortData = sorts?.find(gs => gs.key === groups[0]?.key);
4621
+ if (sortData?.sort) {
4622
+ groups = sortGroupsByGroupSortOneLevel(sortData, groups);
4623
+ }
4624
+ else {
4625
+ groups = groups.toSorted((a, b) => a[initIndexSymbol] - b[initIndexSymbol]);
4626
+ }
4627
+ if (!groups[0]?.hasTheData) {
4628
+ groups.forEach((g, i) => groups[i].groups = sortGroupsDeep(g.groups, sorts));
4629
+ }
4630
+ return groups;
4631
+ }
4632
+ function mapGroupHeader(obj, expandedHeaders, expandAllGroups = []) {
4633
+ const showChildren = expandedHeaders === true || expandedHeaders.includes(obj.uniqueName) || expandAllGroups.includes(obj.key);
4548
4634
  const children = !showChildren ? [] :
4549
4635
  obj.hasTheData ? obj.children
4550
- : obj.groups.map(a => mapGroupHeader(a, expandedHeaders));
4636
+ : obj.groups.map(a => mapGroupHeader(a, expandedHeaders, expandAllGroups));
4551
4637
  return [obj, ...children].flat();
4552
4638
  }
4553
4639
  function dataUpdated(data, groups, expandedGroups, sorts) {
@@ -4566,12 +4652,18 @@ const getAllGroupHeaderNames = (data) => {
4566
4652
  }, {});
4567
4653
  };
4568
4654
  const getAllGroupHeaderNamesByKeys = (data, keys) => {
4569
- const groups = getGroupHeaders(data, (d) => d.isGroupHeader && keys.includes(d.key));
4570
- return supportsGroupBy ? Object.groupBy(groups, group => group.key) : groupBy(groups, 'key');
4655
+ const groups = getGroupHeaders(data, (d) => d.isGroupHeader && keys.includes(d.key), [], keys.length === 1);
4656
+ const a = supportsGroupBy ? Object.groupBy(groups, group => group.key) : groupBy(groups, 'key');
4657
+ return Object.entries(a).reduce((names, [key, groups]) => {
4658
+ names[key] = groups.map(g => ({ uniqueName: g.uniqueName, key: g.key }));
4659
+ return names;
4660
+ }, {});
4571
4661
  };
4572
- const getGroupHeaders = (data, filterFunc, arr = []) => {
4662
+ const getGroupHeaders = (data, filterFunc, arr = [], oneLevel = false) => {
4573
4663
  const headers = data.filter(filterFunc);
4574
4664
  arr.push(...headers);
4665
+ if (oneLevel)
4666
+ return arr;
4575
4667
  headers.forEach(h => { if (h.hasTheData === false && !!h.groups.length)
4576
4668
  getGroupHeaders(h.groups, filterFunc, arr); });
4577
4669
  return arr;
@@ -4591,7 +4683,8 @@ class GenericTableComponent {
4591
4683
  this.$table = viewChild(MatTable);
4592
4684
  this.$dropList = viewChild(CdkDropList);
4593
4685
  this.selection$ = output({ alias: 'selection' });
4594
- this.$displayDataLength = input.required({ alias: 'displayDataLength' });
4686
+ this.$displayData = input.required({ alias: 'displayData' });
4687
+ this.$displayDataLength = computed(() => this.$displayData().length);
4595
4688
  this.$data = input.required({ alias: 'data' });
4596
4689
  this.$rows = input([], { alias: 'rows' });
4597
4690
  this.$columnInfos = input.required({ alias: 'columnInfos' });
@@ -4947,6 +5040,10 @@ class GenericTableComponent {
4947
5040
  return row.isGroupHeader;
4948
5041
  }
4949
5042
  setExpanded(key, groupUniqueName, isExpanded) {
5043
+ if (!isExpanded && this.state.$expandAllGroupsOfKey(key)()) {
5044
+ const groupHeaders = getAllGroupHeaderNamesByKeys(this.$displayData(), [key]);
5045
+ this.state.expandAllOfGroup({ groupHeadersByKey: groupHeaders });
5046
+ }
4950
5047
  this.state.updateExpandedGroups({ key, isExpanded, groupUniqueName });
4951
5048
  }
4952
5049
  buildColumn(column) {
@@ -5013,7 +5110,7 @@ class GenericTableComponent {
5013
5110
  });
5014
5111
  }
5015
5112
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: GenericTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5016
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", 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 #table\r\n cdkDropList\r\n cdkDropListLockAxis='x'\r\n cdkDropListOrientation=\"horizontal\"\r\n class=\"table-drag-list\"\r\n [dataSource]=\"$dataSource()\"\r\n [trackBy]=\"$trackByFunction()\"\r\n [style]=\"$tableWidth()\"\r\n (cdkDropListDropped)=\"drop($event)\"\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 [checked]=\"!!($masterToggleChecked())\"\r\n [indeterminate]=\"$masterToggleIndeterminate()\"\r\n [matTooltip]=\"$selectAllMessage()\"\r\n (change)=\"$event ? masterToggle() : null\" />\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 <button mat-menu-item>\r\n <mat-slide-toggle [checked]=\"$hasSelectFilter()\" (change)=\"addSelectFilter($event.checked)\">\r\n Show Only Selected\r\n </mat-slide-toggle>\r\n </button>\r\n @if(this.$selection().selected.length)\r\n {\r\n <button mat-menu-item (click)=\"$selection().clear()\">\r\n Clear Selection\r\n </button>\r\n }\r\n <button mat-menu-item (click)=\"selectTop(+i.value)\">\r\n Select top \r\n <input #i class=\"input\" stop-propagation type=\"number\" \r\n placeholder=\"Set Size\"\r\n [value]=\"10\"\r\n [min]=\"1\"\r\n [max]=\"dataStore.state().sortedFilteredDataLength\" />\r\n </button>\r\n </mat-menu>\r\n </mat-header-cell>\r\n\r\n <mat-cell *matCellDef=\"let row\" class=\"select-column\">\r\n <mat-checkbox\r\n [checked]=\"selection.isSelected(row)\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"$event ? selection.toggle(row) : null\"/>\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; let t\" class=\"index-column\">\r\n {{ 1 + i + $offsetIndex() }}\r\n </mat-cell>\r\n <mat-footer-cell *matFooterCellDef class=\"index-column\" />\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.uniqueName );\r\n @let customTemplate = (getCustomGroupRowTemplate | func : row.key)();\r\n \r\n\r\n\r\n <!-- Default group row template -->\r\n <div [style.paddingLeft]=\"row.padding + 'px !important'\" [class]=\"'group-cell'\">\r\n @if($hasSelectColumn())\r\n {\r\n @let contains = (allOfGroupSelected | func : row.uniqueName)();\r\n <mat-checkbox [checked]=\"!!contains.containsAll\"\r\n [indeterminate]=\"!!contains.containsSome && !contains.containsAll\"\r\n [matTooltip]=\"toggleGroupMessage | func : contains.length : contains.containsAll\"\r\n (change)=\"$event ? toggleGroup(row.uniqueName, contains.containsAll) : null\" />\r\n }\r\n <button mat-icon-button (click)=\"setExpanded(row.key, row.uniqueName, !expanded());\">\r\n @if (!expanded())\r\n {\r\n <mat-icon>chevron_right</mat-icon>\r\n }\r\n @else\r\n {\r\n <mat-icon>expand_more</mat-icon>\r\n }\r\n </button>\r\n {{ row.custom ? row.groupHeaderDisplay : ((getGroupHeaderTransform | func : row.key : row.groupHeaderDisplay)() + ` (${row.length})`) }}\r\n </div>\r\n <div style=\"flex-grow: 1\">\r\n @if(customTemplate)\r\n {\r\n <ng-container *ngTemplateOutlet=\"customTemplate; context: { \r\n $implicit: row, \r\n element: row, \r\n expanded: expanded(), \r\n level: row.level, \r\n key: row.key, \r\n uniqueName: row.uniqueName, \r\n groupHeaderDisplay: row.groupHeaderDisplay, \r\n length: row.length, \r\n padding: row.padding \r\n }\" />\r\n }\r\n @else\r\n {\r\n <ng-container *ngTemplateOutlet=\"state.$props().groupHeaderTemplate!; context: { element: row }\" />\r\n }\r\n </div>\r\n </mat-cell>\r\n </ng-container>\r\n\r\n <mat-row\r\n *matRowDef=\"let row; columns: $keys(); let i = index\"\r\n [style.height]=\"$rowHeight()\"\r\n [style.min-height]=\"$rowHeight()\"\r\n [styler]=\"$rowStyles()\"\r\n [element]=\"row\"\r\n [conditionalClasses]=\"$rowClasses()\"\r\n (click)=\"rowClicked(row, $event)\"\r\n />\r\n\r\n <!-- group row -->\r\n <mat-row *matRowDef=\"let row; columns: ['groupHeader']; when: isGroupHeader\"\r\n style=\"background-color: unset;\"\r\n [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</mat-table>\r\n\r\n<mat-header-row *matHeaderRowDef=\"$keys(); sticky: state.$props().isSticky\" [style.height]=\"$headerHeight()\"\r\n [style.min-height]=\"$headerHeight()\" [style.top.px]=\"($offset()! * -1)\"/>\r\n<mat-footer-row *matFooterRowDef=\"$keys(); sticky: $stickyFooter() \" [style.height]=\"$footerHeight()\"\r\n [style.min-height]=\"$footerHeight()\"\r\n [style.bottom.px]=\"$stickyFooter() ? ($offset()) : undefined\"/>\r\n", styles: [":host{--mat-paginator-container-size: var(tb-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)}.page-amounts{color:#0000008a;font-family:Roboto,Helvetica Neue,sans-serif;font-size:12px;margin-right:.2rem}.group-cell{display:flex;align-items:center}: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$1.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.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.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: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { 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: 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: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5113
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", type: GenericTableComponent, isStandalone: true, selector: "tb-generic-table", inputs: { $displayData: { classPropertyName: "$displayData", publicName: "displayData", 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 #table\r\n cdkDropList\r\n cdkDropListLockAxis='x'\r\n cdkDropListOrientation=\"horizontal\"\r\n class=\"table-drag-list\"\r\n [dataSource]=\"$dataSource()\"\r\n [trackBy]=\"$trackByFunction()\"\r\n [style]=\"$tableWidth()\"\r\n (cdkDropListDropped)=\"drop($event)\"\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 [checked]=\"!!($masterToggleChecked())\"\r\n [indeterminate]=\"$masterToggleIndeterminate()\"\r\n [matTooltip]=\"$selectAllMessage()\"\r\n (change)=\"$event ? masterToggle() : null\" />\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 <button mat-menu-item>\r\n <mat-slide-toggle [checked]=\"$hasSelectFilter()\" (change)=\"addSelectFilter($event.checked)\">\r\n Show Only Selected\r\n </mat-slide-toggle>\r\n </button>\r\n @if(this.$selection().selected.length)\r\n {\r\n <button mat-menu-item (click)=\"$selection().clear()\">\r\n Clear Selection\r\n </button>\r\n }\r\n <button mat-menu-item (click)=\"selectTop(+i.value)\">\r\n Select top \r\n <input #i class=\"input\" stop-propagation type=\"number\" \r\n placeholder=\"Set Size\"\r\n [value]=\"10\"\r\n [min]=\"1\"\r\n [max]=\"dataStore.state().sortedFilteredDataLength\" />\r\n </button>\r\n </mat-menu>\r\n </mat-header-cell>\r\n\r\n <mat-cell *matCellDef=\"let row\" class=\"select-column\">\r\n <mat-checkbox\r\n [checked]=\"selection.isSelected(row)\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"$event ? selection.toggle(row) : null\"/>\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; let t\" class=\"index-column\">\r\n {{ 1 + i + $offsetIndex() }}\r\n </mat-cell>\r\n <mat-footer-cell *matFooterCellDef class=\"index-column\" />\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.uniqueName );\r\n @let customTemplate = (getCustomGroupRowTemplate | func : row.key)();\r\n \r\n\r\n\r\n <!-- Default group row template -->\r\n <div [style.paddingLeft]=\"row.padding + 'px !important'\" [class]=\"'group-cell'\">\r\n @if($hasSelectColumn())\r\n {\r\n @let contains = (allOfGroupSelected | func : row.uniqueName)();\r\n <mat-checkbox [checked]=\"!!contains.containsAll\"\r\n [indeterminate]=\"!!contains.containsSome && !contains.containsAll\"\r\n [matTooltip]=\"toggleGroupMessage | func : contains.length : contains.containsAll\"\r\n (change)=\"$event ? toggleGroup(row.uniqueName, contains.containsAll) : null\" />\r\n }\r\n <button mat-icon-button (click)=\"setExpanded(row.key, row.uniqueName, !expanded());\">\r\n @if (!expanded())\r\n {\r\n <mat-icon>chevron_right</mat-icon>\r\n }\r\n @else\r\n {\r\n <mat-icon>expand_more</mat-icon>\r\n }\r\n </button>\r\n {{ row.custom ? row.groupHeaderDisplay : ((getGroupHeaderTransform | func : row.key : row.groupHeaderDisplay)() + ` (${row.length})`) }}\r\n </div>\r\n <div style=\"flex-grow: 1\">\r\n @if(customTemplate)\r\n {\r\n <ng-container *ngTemplateOutlet=\"customTemplate; context: { \r\n $implicit: row, \r\n element: row, \r\n expanded: expanded(), \r\n level: row.level, \r\n key: row.key, \r\n uniqueName: row.uniqueName, \r\n groupHeaderDisplay: row.groupHeaderDisplay, \r\n length: row.length, \r\n padding: row.padding \r\n }\" />\r\n }\r\n @else\r\n {\r\n <ng-container *ngTemplateOutlet=\"state.$props().groupHeaderTemplate!; context: { element: row }\" />\r\n }\r\n </div>\r\n </mat-cell>\r\n </ng-container>\r\n\r\n <mat-row\r\n *matRowDef=\"let row; columns: $keys(); let i = index\"\r\n [style.height]=\"$rowHeight()\"\r\n [style.min-height]=\"$rowHeight()\"\r\n [styler]=\"$rowStyles()\"\r\n [element]=\"row\"\r\n [conditionalClasses]=\"$rowClasses()\"\r\n (click)=\"rowClicked(row, $event)\"\r\n />\r\n\r\n <!-- group row -->\r\n <mat-row *matRowDef=\"let row; columns: ['groupHeader']; when: isGroupHeader\"\r\n style=\"background-color: unset;\"\r\n [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</mat-table>\r\n\r\n<mat-header-row *matHeaderRowDef=\"$keys(); sticky: state.$props().isSticky\" [style.height]=\"$headerHeight()\"\r\n [style.min-height]=\"$headerHeight()\" [style.top.px]=\"($offset()! * -1)\"/>\r\n<mat-footer-row *matFooterRowDef=\"$keys(); sticky: $stickyFooter() \" [style.height]=\"$footerHeight()\"\r\n [style.min-height]=\"$footerHeight()\"\r\n [style.bottom.px]=\"$stickyFooter() ? ($offset()) : undefined\"/>\r\n", styles: [":host{--mat-paginator-container-size: var(tb-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)}.page-amounts{color:#0000008a;font-family:Roboto,Helvetica Neue,sans-serif;font-size:12px;margin-right:.2rem}.group-cell{display:flex;align-items:center}: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$1.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.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.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: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { 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: 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: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "directive", type: StopPropagationDirective, selector: "[stop-propagation]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5017
5114
  }
5018
5115
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: GenericTableComponent, decorators: [{
5019
5116
  type: Component,
@@ -6687,14 +6784,14 @@ class TableContainerComponent {
6687
6784
  const data = this.$sortedAndFilteredData();
6688
6785
  const groups = this.$timestampedGroups();
6689
6786
  const expanded = this.$timestampedExpanded();
6690
- const sorts = this.$timestampedGroupSortUpdated();
6787
+ const groupSorts = this.$timestampedGroupSortUpdated();
6691
6788
  if (!data)
6692
6789
  return undefined;
6693
6790
  return ({
6694
6791
  data,
6695
6792
  groups,
6696
6793
  expanded,
6697
- sorts,
6794
+ groupSorts,
6698
6795
  });
6699
6796
  });
6700
6797
  this.$filteredSortedAndGrouped = linkedSignal({
@@ -6732,7 +6829,7 @@ class TableContainerComponent {
6732
6829
  #setUpAllValuesFilters;
6733
6830
  static { this.headerId = 'tb-header-wrapper'; }
6734
6831
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: TableContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6735
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", type: TableContainerComponent, isStandalone: true, selector: "tb-table-container", inputs: { $tableBuilder: { classPropertyName: "$tableBuilder", publicName: "tableBuilder", isSignal: true, isRequired: true, transformFunction: null }, $tableIdInput: { classPropertyName: "$tableIdInput", publicName: "tableId", isSignal: true, isRequired: false, transformFunction: null }, $trackByInput: { classPropertyName: "$trackByInput", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, $inputFilters: { classPropertyName: "$inputFilters", publicName: "inputFilters", isSignal: true, isRequired: false, transformFunction: null }, $indexColumnInput: { classPropertyName: "$indexColumnInput", publicName: "indexColumn", isSignal: true, isRequired: false, transformFunction: null }, $selectionColumnInput: { classPropertyName: "$selectionColumnInput", publicName: "selectionColumn", isSignal: true, isRequired: false, transformFunction: null }, $stickyHeaderInput: { classPropertyName: "$stickyHeaderInput", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, $stickyFooterInput: { classPropertyName: "$stickyFooterInput", 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: { 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 }, { propertyName: "$customGroupRows", predicate: CustomGroupRowDirective, 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 {\r\n <ng-content select=\".tb-header-title\"/>\r\n @if (tableSettings.title)\r\n {\r\n @switch (tableSettings.title.level)\r\n {\r\n @case (1) { <h1 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h1>}\r\n @case (2) { <h2 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h2>}\r\n @case (4) { <h4 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h4>}\r\n @case (5) { <h5 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h5>}\r\n @case (6) { <h6 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h6>}\r\n @default { <h3 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h3>}\r\n }\r\n }\r\n }\r\n </div>\r\n @if(state.$groupByData().length)\r\n {\r\n <group-by-list />\r\n }\r\n <div class=\"flx-row-end\">\r\n <lib-filter-list />\r\n @if (!tableSettings.hideHeader)\r\n {\r\n @if (!$collapsedHeader())\r\n {\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' [xPosition]=\"'before'\">\r\n <lib-table-header-menu #l/>\r\n </mat-menu>\r\n\r\n }\r\n @else\r\n {\r\n <mat-icon color=\"primary\" class=\"flat-menu-button pointer\" [matMenuTriggerFor]=\"mainMenu\">more_horiz</mat-icon>\r\n <mat-menu #mainMenu='matMenu'>\r\n <div class=\"collapsed-head-row\">\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 class=\"collapse-icon header\" [matTooltip]=\"$collapsedHeader() ? 'expand' : 'collapse'\"\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 [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" (selection)='_selection$.next($event)' />\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 [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" (selection)='_selection$.next($event)' />\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 class=\"collapse-icon footer\" [matTooltip]=\"$collapsedFooter() ? 'expand' : 'collapse'\"\r\n (click)=\"state.toggleCollapseFooter()\">\r\n {{$collapsedFooter() ? 'expand_more' : 'expand_less'}}\r\n </mat-icon>\r\n </div>\r\n }\r\n</ng-container>\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 && !$collapsedHeader()) {<tb-profiles-menu [tableId]=\"tableId\"/>}\r\n</ng-template>\r\n", styles: [".tb-header-wrapper{display:flex;flex-direction:row;width:100%}.flx-row-end{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;margin-left:auto}.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}.collapsed-head-row{display:flex;justify-content:space-evenly}::ng-deep tb-generic-table .mat-mdc-row:nth-child(odd):not(.no-stripe){background-color:var(--tb-odd-row-background-color, #cdeefe)}.tb-container-title{padding-left:var(--tb-container-title-padding-left, 10px);margin:var(--tb-container-title-margin, 0)}\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.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.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 }); }
6832
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", type: TableContainerComponent, isStandalone: true, selector: "tb-table-container", inputs: { $tableBuilder: { classPropertyName: "$tableBuilder", publicName: "tableBuilder", isSignal: true, isRequired: true, transformFunction: null }, $tableIdInput: { classPropertyName: "$tableIdInput", publicName: "tableId", isSignal: true, isRequired: false, transformFunction: null }, $trackByInput: { classPropertyName: "$trackByInput", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, $inputFilters: { classPropertyName: "$inputFilters", publicName: "inputFilters", isSignal: true, isRequired: false, transformFunction: null }, $indexColumnInput: { classPropertyName: "$indexColumnInput", publicName: "indexColumn", isSignal: true, isRequired: false, transformFunction: null }, $selectionColumnInput: { classPropertyName: "$selectionColumnInput", publicName: "selectionColumn", isSignal: true, isRequired: false, transformFunction: null }, $stickyHeaderInput: { classPropertyName: "$stickyHeaderInput", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, $stickyFooterInput: { classPropertyName: "$stickyFooterInput", 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: { 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 }, { propertyName: "$customGroupRows", predicate: CustomGroupRowDirective, 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 {\r\n <ng-content select=\".tb-header-title\"/>\r\n @if (tableSettings.title)\r\n {\r\n @switch (tableSettings.title.level)\r\n {\r\n @case (1) { <h1 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h1>}\r\n @case (2) { <h2 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h2>}\r\n @case (4) { <h4 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h4>}\r\n @case (5) { <h5 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h5>}\r\n @case (6) { <h6 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h6>}\r\n @default { <h3 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h3>}\r\n }\r\n }\r\n }\r\n </div>\r\n @if(state.$groupByData().length)\r\n {\r\n <group-by-list />\r\n }\r\n <div class=\"flx-row-end\">\r\n <lib-filter-list />\r\n @if (!tableSettings.hideHeader)\r\n {\r\n @if (!$collapsedHeader())\r\n {\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' [xPosition]=\"'before'\">\r\n <lib-table-header-menu #l/>\r\n </mat-menu>\r\n\r\n }\r\n @else\r\n {\r\n <mat-icon color=\"primary\" class=\"flat-menu-button pointer\" [matMenuTriggerFor]=\"mainMenu\">more_horiz</mat-icon>\r\n <mat-menu #mainMenu='matMenu'>\r\n <div class=\"collapsed-head-row\">\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 class=\"collapse-icon header\" [matTooltip]=\"$collapsedHeader() ? 'expand' : 'collapse'\"\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()!\" [displayData]=\"$filteredSortedAndGrouped()?.displayData || []\"\r\n [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" (selection)='_selection$.next($event)' />\r\n </tb-virtual-scroll-container>\r\n }\r\n @else\r\n {\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayData]=\"$filteredSortedAndGrouped()?.displayData || []\"\r\n [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" (selection)='_selection$.next($event)' />\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 class=\"collapse-icon footer\" [matTooltip]=\"$collapsedFooter() ? 'expand' : 'collapse'\"\r\n (click)=\"state.toggleCollapseFooter()\">\r\n {{$collapsedFooter() ? 'expand_more' : 'expand_less'}}\r\n </mat-icon>\r\n </div>\r\n }\r\n</ng-container>\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 && !$collapsedHeader()) {<tb-profiles-menu [tableId]=\"tableId\"/>}\r\n</ng-template>\r\n", styles: [".tb-header-wrapper{display:flex;flex-direction:row;width:100%}.flx-row-end{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;margin-left:auto}.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}.collapsed-head-row{display:flex;justify-content:space-evenly}::ng-deep tb-generic-table .mat-mdc-row:nth-child(odd):not(.no-stripe){background-color:var(--tb-odd-row-background-color, #cdeefe)}.tb-container-title{padding-left:var(--tb-container-title-padding-left, 10px);margin:var(--tb-container-title-margin, 0)}\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: ["displayData", "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.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.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 }); }
6736
6833
  }
6737
6834
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: TableContainerComponent, decorators: [{
6738
6835
  type: Component,
@@ -6742,7 +6839,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImpor
6742
6839
  MultiSortDirective, GroupByListComponent, FilterChipsComponent, GenFilterDisplayerComponent, GenColDisplayerComponent,
6743
6840
  SortMenuComponent, GenericTableComponent, ProfilesMenuComponent, TableHeaderMenuComponent,
6744
6841
  MatButtonModule, MatMenuModule, MatIconModule, MatTooltipModule, VirtualScrollContainer,
6745
- ], 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 {\r\n <ng-content select=\".tb-header-title\"/>\r\n @if (tableSettings.title)\r\n {\r\n @switch (tableSettings.title.level)\r\n {\r\n @case (1) { <h1 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h1>}\r\n @case (2) { <h2 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h2>}\r\n @case (4) { <h4 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h4>}\r\n @case (5) { <h5 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h5>}\r\n @case (6) { <h6 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h6>}\r\n @default { <h3 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h3>}\r\n }\r\n }\r\n }\r\n </div>\r\n @if(state.$groupByData().length)\r\n {\r\n <group-by-list />\r\n }\r\n <div class=\"flx-row-end\">\r\n <lib-filter-list />\r\n @if (!tableSettings.hideHeader)\r\n {\r\n @if (!$collapsedHeader())\r\n {\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' [xPosition]=\"'before'\">\r\n <lib-table-header-menu #l/>\r\n </mat-menu>\r\n\r\n }\r\n @else\r\n {\r\n <mat-icon color=\"primary\" class=\"flat-menu-button pointer\" [matMenuTriggerFor]=\"mainMenu\">more_horiz</mat-icon>\r\n <mat-menu #mainMenu='matMenu'>\r\n <div class=\"collapsed-head-row\">\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 class=\"collapse-icon header\" [matTooltip]=\"$collapsedHeader() ? 'expand' : 'collapse'\"\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 [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" (selection)='_selection$.next($event)' />\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 [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" (selection)='_selection$.next($event)' />\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 class=\"collapse-icon footer\" [matTooltip]=\"$collapsedFooter() ? 'expand' : 'collapse'\"\r\n (click)=\"state.toggleCollapseFooter()\">\r\n {{$collapsedFooter() ? 'expand_more' : 'expand_less'}}\r\n </mat-icon>\r\n </div>\r\n }\r\n</ng-container>\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 && !$collapsedHeader()) {<tb-profiles-menu [tableId]=\"tableId\"/>}\r\n</ng-template>\r\n", styles: [".tb-header-wrapper{display:flex;flex-direction:row;width:100%}.flx-row-end{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;margin-left:auto}.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}.collapsed-head-row{display:flex;justify-content:space-evenly}::ng-deep tb-generic-table .mat-mdc-row:nth-child(odd):not(.no-stripe){background-color:var(--tb-odd-row-background-color, #cdeefe)}.tb-container-title{padding-left:var(--tb-container-title-padding-left, 10px);margin:var(--tb-container-title-margin, 0)}\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"] }]
6842
+ ], 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 {\r\n <ng-content select=\".tb-header-title\"/>\r\n @if (tableSettings.title)\r\n {\r\n @switch (tableSettings.title.level)\r\n {\r\n @case (1) { <h1 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h1>}\r\n @case (2) { <h2 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h2>}\r\n @case (4) { <h4 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h4>}\r\n @case (5) { <h5 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h5>}\r\n @case (6) { <h6 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h6>}\r\n @default { <h3 class=\"tb-container-title\" [style]=\"tableSettings.title.styles\">{{tableSettings.title.text}}</h3>}\r\n }\r\n }\r\n }\r\n </div>\r\n @if(state.$groupByData().length)\r\n {\r\n <group-by-list />\r\n }\r\n <div class=\"flx-row-end\">\r\n <lib-filter-list />\r\n @if (!tableSettings.hideHeader)\r\n {\r\n @if (!$collapsedHeader())\r\n {\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' [xPosition]=\"'before'\">\r\n <lib-table-header-menu #l/>\r\n </mat-menu>\r\n\r\n }\r\n @else\r\n {\r\n <mat-icon color=\"primary\" class=\"flat-menu-button pointer\" [matMenuTriggerFor]=\"mainMenu\">more_horiz</mat-icon>\r\n <mat-menu #mainMenu='matMenu'>\r\n <div class=\"collapsed-head-row\">\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 class=\"collapse-icon header\" [matTooltip]=\"$collapsedHeader() ? 'expand' : 'collapse'\"\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()!\" [displayData]=\"$filteredSortedAndGrouped()?.displayData || []\"\r\n [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" (selection)='_selection$.next($event)' />\r\n </tb-virtual-scroll-container>\r\n }\r\n @else\r\n {\r\n <tb-generic-table [rows]=\"$customRows()\" [data]=\"$data()!\" [displayData]=\"$filteredSortedAndGrouped()?.displayData || []\"\r\n [columnInfos]='$myColumns()' [trackBy]=\"$trackBy()\" [dataSource]=\"dataSource\" (selection)='_selection$.next($event)' />\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 class=\"collapse-icon footer\" [matTooltip]=\"$collapsedFooter() ? 'expand' : 'collapse'\"\r\n (click)=\"state.toggleCollapseFooter()\">\r\n {{$collapsedFooter() ? 'expand_more' : 'expand_less'}}\r\n </mat-icon>\r\n </div>\r\n }\r\n</ng-container>\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 && !$collapsedHeader()) {<tb-profiles-menu [tableId]=\"tableId\"/>}\r\n</ng-template>\r\n", styles: [".tb-header-wrapper{display:flex;flex-direction:row;width:100%}.flx-row-end{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;margin-left:auto}.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}.collapsed-head-row{display:flex;justify-content:space-evenly}::ng-deep tb-generic-table .mat-mdc-row:nth-child(odd):not(.no-stripe){background-color:var(--tb-odd-row-background-color, #cdeefe)}.tb-container-title{padding-left:var(--tb-container-title-padding-left, 10px);margin:var(--tb-container-title-margin, 0)}\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"] }]
6746
6843
  }] });
6747
6844
  function isFunction(a) {
6748
6845
  return typeof a === 'function';