@firestitch/filter 18.2.71 → 18.2.73
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.
- package/app/components/filter-chips/filter-chips.component.d.ts +14 -3
- package/app/helpers/create-filter-item.d.ts +1 -1
- package/app/interfaces/config.interface.d.ts +1 -0
- package/app/interfaces/items/base.interface.d.ts +1 -0
- package/app/models/filter-config.d.ts +1 -0
- package/app/models/items/base-item.d.ts +7 -0
- package/app/services/filter-controller.service.d.ts +1 -2
- package/app/services/saved-filter-controller.service.d.ts +0 -1
- package/esm2022/app/components/filter-chips/filter-chips.component.mjs +63 -25
- package/esm2022/app/components/filters-item/select/select.component.mjs +4 -5
- package/esm2022/app/interfaces/config.interface.mjs +1 -1
- package/esm2022/app/interfaces/items/base.interface.mjs +1 -1
- package/esm2022/app/models/filter-config.mjs +3 -1
- package/esm2022/app/models/items/base-item.mjs +29 -4
- package/esm2022/app/services/filter-controller.service.mjs +31 -10
- package/esm2022/app/services/saved-filter-controller.service.mjs +1 -3
- package/fesm2022/firestitch-filter.mjs +124 -41
- package/fesm2022/firestitch-filter.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injectable, Directive, Input, TemplateRef, DestroyRef, Component, ChangeDetectionStrategy, InjectionToken, KeyValueDiffers, ChangeDetectorRef, Injector, ViewChild, EventEmitter, NgZone,
|
|
3
|
-
import { FsMessage } from '@firestitch/message';
|
|
2
|
+
import { inject, Injectable, Directive, Input, TemplateRef, DestroyRef, Component, ChangeDetectionStrategy, InjectionToken, KeyValueDiffers, ChangeDetectorRef, Injector, ViewChild, ElementRef, EventEmitter, NgZone, Output, ContentChild, HostBinding, NgModule } from '@angular/core';
|
|
4
3
|
import { FsPrompt } from '@firestitch/prompt';
|
|
5
4
|
import { BehaviorSubject, Subject, of, forkJoin, Observable, tap as tap$1, map as map$1, switchMap as switchMap$1, distinctUntilChanged as distinctUntilChanged$1, merge, filter, takeUntil as takeUntil$1, debounceTime as debounceTime$1, fromEvent, combineLatest, interval } from 'rxjs';
|
|
6
5
|
import { distinctUntilChanged, switchMap, tap, skip, takeUntil, map, debounceTime, finalize, filter as filter$1 } from 'rxjs/operators';
|
|
@@ -47,14 +46,14 @@ import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
|
|
|
47
46
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
48
47
|
import * as i1$5 from '@firestitch/chip';
|
|
49
48
|
import { FsChipModule } from '@firestitch/chip';
|
|
49
|
+
import { FsMessage } from '@firestitch/message';
|
|
50
50
|
import { FsSkeletonModule } from '@firestitch/skeleton';
|
|
51
51
|
import * as i1$4 from '@firestitch/label';
|
|
52
52
|
import { FsLabelModule } from '@firestitch/label';
|
|
53
|
-
import { MatFormField, MatLabel, MatPrefix, MatSuffix
|
|
53
|
+
import { MatFormField, MatLabel, MatPrefix, MatSuffix } from '@angular/material/form-field';
|
|
54
54
|
import { MatCheckbox } from '@angular/material/checkbox';
|
|
55
55
|
|
|
56
56
|
class SavedFilterController {
|
|
57
|
-
_message = inject(FsMessage);
|
|
58
57
|
_filterController;
|
|
59
58
|
_savedFilters$ = new BehaviorSubject([]);
|
|
60
59
|
_activeFilter$ = new BehaviorSubject(null);
|
|
@@ -792,6 +791,7 @@ class FsFilterConfig {
|
|
|
792
791
|
namespace; // for persistance
|
|
793
792
|
heading;
|
|
794
793
|
subheading;
|
|
794
|
+
maxEnabled;
|
|
795
795
|
constructor(data = {}) {
|
|
796
796
|
this._init(data);
|
|
797
797
|
}
|
|
@@ -802,6 +802,7 @@ class FsFilterConfig {
|
|
|
802
802
|
savedFilters: data.savedFilters,
|
|
803
803
|
autofocus: data.autofocus ?? false,
|
|
804
804
|
chips: data.chips ?? false,
|
|
805
|
+
maxEnabled: data.maxEnabled ?? 0,
|
|
805
806
|
sort: data.sort,
|
|
806
807
|
queryParam: data.queryParam ?? false,
|
|
807
808
|
init: data.init,
|
|
@@ -1002,6 +1003,7 @@ class BaseItem {
|
|
|
1002
1003
|
persistanceDisabled;
|
|
1003
1004
|
queryParamsDisabled;
|
|
1004
1005
|
primary;
|
|
1006
|
+
secondary;
|
|
1005
1007
|
changeCallback;
|
|
1006
1008
|
initCallback;
|
|
1007
1009
|
_type;
|
|
@@ -1009,12 +1011,25 @@ class BaseItem {
|
|
|
1009
1011
|
_hidden$ = new BehaviorSubject(false);
|
|
1010
1012
|
_value$ = new BehaviorSubject({ value: undefined, emitChange: true });
|
|
1011
1013
|
_values$ = new BehaviorSubject(null);
|
|
1014
|
+
_secondaryVisible$ = new BehaviorSubject(false);
|
|
1012
1015
|
_destroy$ = new Subject();
|
|
1013
1016
|
constructor(itemConfig, _filter) {
|
|
1014
1017
|
this._filter = _filter;
|
|
1015
1018
|
this._type = itemConfig.type;
|
|
1016
1019
|
this._initConfig(itemConfig);
|
|
1017
1020
|
}
|
|
1021
|
+
secondaryShow() {
|
|
1022
|
+
this._secondaryVisible$.next(true);
|
|
1023
|
+
}
|
|
1024
|
+
secondaryHide() {
|
|
1025
|
+
this._secondaryVisible$.next(false);
|
|
1026
|
+
}
|
|
1027
|
+
get secondaryVisible$() {
|
|
1028
|
+
return this._secondaryVisible$.asObservable();
|
|
1029
|
+
}
|
|
1030
|
+
get secondaryVisible() {
|
|
1031
|
+
return this._secondaryVisible$.getValue();
|
|
1032
|
+
}
|
|
1018
1033
|
get filter() {
|
|
1019
1034
|
return this._filter;
|
|
1020
1035
|
}
|
|
@@ -1079,6 +1094,10 @@ class BaseItem {
|
|
|
1079
1094
|
get hasValue() {
|
|
1080
1095
|
return this.value !== null && this.value !== undefined;
|
|
1081
1096
|
}
|
|
1097
|
+
get notValue$() {
|
|
1098
|
+
return this.value$
|
|
1099
|
+
.pipe(map(() => !this.hasValue));
|
|
1100
|
+
}
|
|
1082
1101
|
get hasValue$() {
|
|
1083
1102
|
return this.value$
|
|
1084
1103
|
.pipe(map(() => this.hasValue));
|
|
@@ -1122,9 +1141,15 @@ class BaseItem {
|
|
|
1122
1141
|
return this.query;
|
|
1123
1142
|
}
|
|
1124
1143
|
hide() {
|
|
1144
|
+
if (!this.primary) {
|
|
1145
|
+
this.secondaryHide();
|
|
1146
|
+
}
|
|
1125
1147
|
this._hidden$.next(true);
|
|
1126
1148
|
}
|
|
1127
1149
|
show() {
|
|
1150
|
+
if (!this.primary) {
|
|
1151
|
+
this.secondaryShow();
|
|
1152
|
+
}
|
|
1128
1153
|
this._hidden$.next(false);
|
|
1129
1154
|
}
|
|
1130
1155
|
get query() {
|
|
@@ -1190,12 +1215,13 @@ class BaseItem {
|
|
|
1190
1215
|
}
|
|
1191
1216
|
}
|
|
1192
1217
|
_initConfig(item) {
|
|
1193
|
-
const hidden = item.hide ?? !(item.show ?? true);
|
|
1194
1218
|
this.name = item.name;
|
|
1195
1219
|
this.label = item.label;
|
|
1196
|
-
this.primary = item.primary ?? false;
|
|
1220
|
+
this.primary = this.isTypeKeyword || (item.primary ?? false);
|
|
1221
|
+
this.secondary = item.secondary ?? false;
|
|
1197
1222
|
this.chipLabel = item.chipLabel;
|
|
1198
|
-
this._hidden$.next(
|
|
1223
|
+
this._hidden$.next(item.hide ?? !(item.show ?? true));
|
|
1224
|
+
this._secondaryVisible$.next(item.secondary ?? false);
|
|
1199
1225
|
this.clearable = item.clear ?? true;
|
|
1200
1226
|
this.persistanceDisabled = item.disablePersist ?? false;
|
|
1201
1227
|
this.queryParamsDisabled = item.disableQueryParams ?? false;
|
|
@@ -2260,7 +2286,6 @@ class FilterController {
|
|
|
2260
2286
|
_ready$ = new BehaviorSubject(false);
|
|
2261
2287
|
_items = new Map();
|
|
2262
2288
|
_config;
|
|
2263
|
-
_add$ = new Subject();
|
|
2264
2289
|
_init$ = new Subject();
|
|
2265
2290
|
_change$ = new Subject();
|
|
2266
2291
|
_destroy$ = new Subject();
|
|
@@ -2281,9 +2306,6 @@ class FilterController {
|
|
|
2281
2306
|
get init$() {
|
|
2282
2307
|
return this._init$.asObservable();
|
|
2283
2308
|
}
|
|
2284
|
-
get add$() {
|
|
2285
|
-
return this._add$.asObservable();
|
|
2286
|
-
}
|
|
2287
2309
|
get change$() {
|
|
2288
2310
|
return this._change$
|
|
2289
2311
|
.pipe(debounceTime(30));
|
|
@@ -2404,13 +2426,38 @@ class FilterController {
|
|
|
2404
2426
|
.map((item) => {
|
|
2405
2427
|
return item.init(values[item.name]);
|
|
2406
2428
|
}))
|
|
2407
|
-
.pipe(tap(() =>
|
|
2429
|
+
.pipe(tap(() => {
|
|
2430
|
+
this._initEnabledItems();
|
|
2431
|
+
}), tap(() => this.items
|
|
2432
|
+
.forEach((item) => {
|
|
2408
2433
|
item.initCallback(item, this.filter);
|
|
2409
2434
|
})));
|
|
2410
2435
|
}
|
|
2436
|
+
_initEnabledItems() {
|
|
2437
|
+
let enabled = 0;
|
|
2438
|
+
this.items
|
|
2439
|
+
.forEach((item) => {
|
|
2440
|
+
if (!item.primary) {
|
|
2441
|
+
if (item.hasValue) {
|
|
2442
|
+
item.secondaryShow();
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
});
|
|
2446
|
+
this.items
|
|
2447
|
+
.forEach((item) => {
|
|
2448
|
+
if (!item.primary) {
|
|
2449
|
+
if (item.secondaryVisible) {
|
|
2450
|
+
enabled++;
|
|
2451
|
+
}
|
|
2452
|
+
else if (enabled < this._config.maxEnabled) {
|
|
2453
|
+
item.secondaryShow();
|
|
2454
|
+
enabled++;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
});
|
|
2458
|
+
}
|
|
2411
2459
|
_addItems(items) {
|
|
2412
|
-
|
|
2413
|
-
this._items = new Map(items
|
|
2460
|
+
const itemMap = items
|
|
2414
2461
|
.filter((item) => {
|
|
2415
2462
|
if (this._items.has(item.name)) {
|
|
2416
2463
|
throw Error('Filter init error. Items name must be unique.');
|
|
@@ -2422,9 +2469,9 @@ class FilterController {
|
|
|
2422
2469
|
if (filterItem instanceof KeywordItem) {
|
|
2423
2470
|
this._keywordController.keywordItem = filterItem;
|
|
2424
2471
|
}
|
|
2425
|
-
this._items.set(item.name, filterItem);
|
|
2426
2472
|
return [item.name, filterItem];
|
|
2427
|
-
})
|
|
2473
|
+
});
|
|
2474
|
+
this._items = new Map(itemMap);
|
|
2428
2475
|
}
|
|
2429
2476
|
_initChanges() {
|
|
2430
2477
|
merge(...this.items
|
|
@@ -2948,7 +2995,7 @@ class SelectComponent {
|
|
|
2948
2995
|
}
|
|
2949
2996
|
}
|
|
2950
2997
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2951
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: SelectComponent, isStandalone: true, selector: "filter-item-select", inputs: { autofocus: "autofocus", floatLabel: "floatLabel", item: "item" }, viewQueries: [{ propertyName: "select", first: true, predicate: MatSelect, descendants: true, static: true }], ngImport: i0, template: "<mat-form-field\n [ngClass]=\"{ isolate: item.isolate }\"\n [floatLabel]=\"floatLabel\"\n class=\"form-field-padless\">\n <mat-label>\n {{ item.label }}\n </mat-label>\n <mat-select\n [fsFilterFocusTrigger]=\"autofocus\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"changed()\"\n [multiple]=\"item.multiple\">\n @if (item.children) {\n @for (option of item.values$ | async; track option) {\n @if (option[item.children]) {\n <mat-optgroup [label]=\"option.name\">\n @for (childOption of option[item.children]; track childOption.value) {\n <mat-option [value]=\"childOption.value\">\n {{ childOption.name }}\n </mat-option>\n }\n </mat-optgroup>\n } @else {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n }\n } @else {\n @for (option of item.values$ | async; track option) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n }\n </mat-select>\n
|
|
2998
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: SelectComponent, isStandalone: true, selector: "filter-item-select", inputs: { autofocus: "autofocus", floatLabel: "floatLabel", item: "item" }, viewQueries: [{ propertyName: "select", first: true, predicate: MatSelect, descendants: true, static: true }], ngImport: i0, template: "<mat-form-field\n [ngClass]=\"{ isolate: item.isolate }\"\n [floatLabel]=\"floatLabel\"\n class=\"form-field-padless\">\n <mat-label>\n {{ item.label }}\n </mat-label>\n <mat-select\n [fsFilterFocusTrigger]=\"autofocus && !item.isolate\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"changed()\"\n [multiple]=\"item.multiple\">\n @if (item.children) {\n @for (option of item.values$ | async; track option) {\n @if (option[item.children]) {\n <mat-optgroup [label]=\"option.name\">\n @for (childOption of option[item.children]; track childOption.value) {\n <mat-option [value]=\"childOption.value\">\n {{ childOption.name }}\n </mat-option>\n }\n </mat-optgroup>\n } @else {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n }\n } @else {\n @for (option of item.values$ | async; track option) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n }\n </mat-select>\n</mat-form-field>\n@if (item.isolate) {\n <div class=\"isolate-checkbox\">\n <mat-checkbox\n (change)=\"isolateChange($event)\"\n [(ngModel)]=\"item.isolated\">\n <span class=\"checkbox-label\">\n {{ item.isolateLabel }}\n </span>\n </mat-checkbox>\n </div>\n}", styles: [":host ::ng-deep .isolate .mat-mdc-form-field-hint-wrapper{padding-left:0;padding-right:0;padding-top:8px}:host ::ng-deep .isolate .mat-mdc-form-field-hint-wrapper mat-hint .mat-internal-form-field{position:relative}:host ::ng-deep .isolate .mat-mdc-form-field-hint-wrapper mat-hint .mat-internal-form-field .mdc-checkbox{position:absolute}:host ::ng-deep .isolate .mat-mdc-form-field-hint-wrapper mat-hint .mat-internal-form-field .mdc-label{margin-left:32px;font-size:smaller;line-height:normal}\n"], dependencies: [{ kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: 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"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: FocusToItemDirective, selector: "[fsFilterFocusTrigger]", inputs: ["fsFilterFocusTrigger"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2952
2999
|
}
|
|
2953
3000
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectComponent, decorators: [{
|
|
2954
3001
|
type: Component,
|
|
@@ -2962,10 +3009,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
2962
3009
|
FsFormModule,
|
|
2963
3010
|
MatOption,
|
|
2964
3011
|
MatOptgroup,
|
|
2965
|
-
MatHint,
|
|
2966
3012
|
MatCheckbox,
|
|
2967
3013
|
AsyncPipe,
|
|
2968
|
-
], template: "<mat-form-field\n [ngClass]=\"{ isolate: item.isolate }\"\n [floatLabel]=\"floatLabel\"\n class=\"form-field-padless\">\n <mat-label>\n {{ item.label }}\n </mat-label>\n <mat-select\n [fsFilterFocusTrigger]=\"autofocus\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"changed()\"\n [multiple]=\"item.multiple\">\n @if (item.children) {\n @for (option of item.values$ | async; track option) {\n @if (option[item.children]) {\n <mat-optgroup [label]=\"option.name\">\n @for (childOption of option[item.children]; track childOption.value) {\n <mat-option [value]=\"childOption.value\">\n {{ childOption.name }}\n </mat-option>\n }\n </mat-optgroup>\n } @else {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n }\n } @else {\n @for (option of item.values$ | async; track option) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n }\n </mat-select>\n
|
|
3014
|
+
], template: "<mat-form-field\n [ngClass]=\"{ isolate: item.isolate }\"\n [floatLabel]=\"floatLabel\"\n class=\"form-field-padless\">\n <mat-label>\n {{ item.label }}\n </mat-label>\n <mat-select\n [fsFilterFocusTrigger]=\"autofocus && !item.isolate\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"changed()\"\n [multiple]=\"item.multiple\">\n @if (item.children) {\n @for (option of item.values$ | async; track option) {\n @if (option[item.children]) {\n <mat-optgroup [label]=\"option.name\">\n @for (childOption of option[item.children]; track childOption.value) {\n <mat-option [value]=\"childOption.value\">\n {{ childOption.name }}\n </mat-option>\n }\n </mat-optgroup>\n } @else {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n }\n } @else {\n @for (option of item.values$ | async; track option) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n }\n </mat-select>\n</mat-form-field>\n@if (item.isolate) {\n <div class=\"isolate-checkbox\">\n <mat-checkbox\n (change)=\"isolateChange($event)\"\n [(ngModel)]=\"item.isolated\">\n <span class=\"checkbox-label\">\n {{ item.isolateLabel }}\n </span>\n </mat-checkbox>\n </div>\n}", styles: [":host ::ng-deep .isolate .mat-mdc-form-field-hint-wrapper{padding-left:0;padding-right:0;padding-top:8px}:host ::ng-deep .isolate .mat-mdc-form-field-hint-wrapper mat-hint .mat-internal-form-field{position:relative}:host ::ng-deep .isolate .mat-mdc-form-field-hint-wrapper mat-hint .mat-internal-form-field .mdc-checkbox{position:absolute}:host ::ng-deep .isolate .mat-mdc-form-field-hint-wrapper mat-hint .mat-internal-form-field .mdc-label{margin-left:32px;font-size:smaller;line-height:normal}\n"] }]
|
|
2969
3015
|
}], propDecorators: { autofocus: [{
|
|
2970
3016
|
type: Input
|
|
2971
3017
|
}], floatLabel: [{
|
|
@@ -3239,6 +3285,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
3239
3285
|
|
|
3240
3286
|
class FsFilterChipsComponent {
|
|
3241
3287
|
ItemType = ItemType;
|
|
3288
|
+
secondaryItems = [];
|
|
3242
3289
|
_filterController = inject(FilterController);
|
|
3243
3290
|
_dialog = inject(MatDialog);
|
|
3244
3291
|
_message = inject(FsMessage);
|
|
@@ -3246,45 +3293,55 @@ class FsFilterChipsComponent {
|
|
|
3246
3293
|
_injector = inject(Injector);
|
|
3247
3294
|
_overlay = inject(Overlay);
|
|
3248
3295
|
_overlayRef;
|
|
3296
|
+
_destroyRef = inject(DestroyRef);
|
|
3297
|
+
_elementRef = inject(ElementRef);
|
|
3298
|
+
_hasSecondaryValue$ = new BehaviorSubject(false);
|
|
3249
3299
|
get items() {
|
|
3250
3300
|
return this._filterController.items
|
|
3251
3301
|
.filter((item) => !item.isTypeKeyword);
|
|
3252
3302
|
}
|
|
3253
|
-
|
|
3303
|
+
addFilter(event) {
|
|
3304
|
+
const item = event.value;
|
|
3305
|
+
item.secondaryShow();
|
|
3306
|
+
setTimeout(() => {
|
|
3307
|
+
this.openChip(item);
|
|
3308
|
+
});
|
|
3309
|
+
}
|
|
3310
|
+
get disabledItems() {
|
|
3254
3311
|
return this.items
|
|
3255
|
-
.filter((item) => !item.primary)
|
|
3256
|
-
|
|
3312
|
+
.filter((item) => !item.secondaryVisible && !item.hasValue && !item.primary);
|
|
3313
|
+
}
|
|
3314
|
+
get hasSecondaryValue$() {
|
|
3315
|
+
return this._hasSecondaryValue$.asObservable();
|
|
3257
3316
|
}
|
|
3258
3317
|
get savedFilterController() {
|
|
3259
3318
|
return this._savedFilterController;
|
|
3260
3319
|
}
|
|
3320
|
+
get hasSecondaryValue() {
|
|
3321
|
+
return this._filterController.items
|
|
3322
|
+
.some((item) => item.hasValue && item.visible && !item.primary);
|
|
3323
|
+
}
|
|
3261
3324
|
ngOnInit() {
|
|
3262
|
-
|
|
3263
|
-
.
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
return !!this.getNestedElement(element, 'cdk-overlay-pane');
|
|
3267
|
-
});
|
|
3268
|
-
const item2 = elements.some((element) => {
|
|
3269
|
-
return !!this.getNestedElement(element, 'filter-chip');
|
|
3270
|
-
});
|
|
3271
|
-
if (!item1 && !item2) {
|
|
3272
|
-
this._destroyOverlay();
|
|
3273
|
-
}
|
|
3274
|
-
});
|
|
3325
|
+
this.secondaryItems = this.items
|
|
3326
|
+
.filter((item) => !item.primary);
|
|
3327
|
+
this._initHasSecondaryValue();
|
|
3328
|
+
this._initChipClick();
|
|
3275
3329
|
}
|
|
3276
3330
|
clear() {
|
|
3277
|
-
this.items
|
|
3331
|
+
this._filterController.items
|
|
3278
3332
|
.filter((item) => item.clearable)
|
|
3279
3333
|
.forEach((item) => {
|
|
3334
|
+
if (!item.secondary) {
|
|
3335
|
+
item.secondaryHide();
|
|
3336
|
+
}
|
|
3280
3337
|
item.clear(false);
|
|
3281
3338
|
});
|
|
3282
3339
|
this._filterController.change();
|
|
3283
3340
|
this._savedFilterController.setActiveFilter(null);
|
|
3284
3341
|
}
|
|
3285
|
-
|
|
3342
|
+
openChip(item, name = null) {
|
|
3286
3343
|
this._destroyOverlay();
|
|
3287
|
-
el = this.
|
|
3344
|
+
const el = this._elementRef.nativeElement.querySelector(`[data-filter-item="${item.name}"]`);
|
|
3288
3345
|
const positions = [
|
|
3289
3346
|
{
|
|
3290
3347
|
originX: 'start',
|
|
@@ -3365,7 +3422,10 @@ class FsFilterChipsComponent {
|
|
|
3365
3422
|
this._overlayRef.dispose();
|
|
3366
3423
|
}
|
|
3367
3424
|
}
|
|
3368
|
-
|
|
3425
|
+
removeChip(item, chip) {
|
|
3426
|
+
if (!item.secondary) {
|
|
3427
|
+
item.secondaryHide();
|
|
3428
|
+
}
|
|
3369
3429
|
if (chip.name) {
|
|
3370
3430
|
item.clearByName(chip.name);
|
|
3371
3431
|
}
|
|
@@ -3388,8 +3448,31 @@ class FsFilterChipsComponent {
|
|
|
3388
3448
|
parent: this._injector,
|
|
3389
3449
|
});
|
|
3390
3450
|
}
|
|
3451
|
+
_initChipClick() {
|
|
3452
|
+
fromEvent(document, 'click')
|
|
3453
|
+
.subscribe((event) => {
|
|
3454
|
+
const elements = document.elementsFromPoint(event.clientX, event.clientY);
|
|
3455
|
+
const item1 = elements.some((element) => {
|
|
3456
|
+
return !!this.getNestedElement(element, 'cdk-overlay-pane');
|
|
3457
|
+
});
|
|
3458
|
+
const item2 = elements.some((element) => {
|
|
3459
|
+
return !!this.getNestedElement(element, 'filter-chip');
|
|
3460
|
+
});
|
|
3461
|
+
if (!item1 && !item2) {
|
|
3462
|
+
this._destroyOverlay();
|
|
3463
|
+
}
|
|
3464
|
+
});
|
|
3465
|
+
}
|
|
3466
|
+
_initHasSecondaryValue() {
|
|
3467
|
+
this._hasSecondaryValue$.next(this.hasSecondaryValue);
|
|
3468
|
+
this._filterController.change$
|
|
3469
|
+
.pipe(tap$1(() => {
|
|
3470
|
+
this._hasSecondaryValue$.next(this.hasSecondaryValue);
|
|
3471
|
+
}), takeUntilDestroyed(this._destroyRef))
|
|
3472
|
+
.subscribe();
|
|
3473
|
+
}
|
|
3391
3474
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FsFilterChipsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3392
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: FsFilterChipsComponent, isStandalone: true, selector: "fs-filter-chips", ngImport: i0, template: "@if (items.length !== 0) {\n @for (item of
|
|
3475
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: FsFilterChipsComponent, isStandalone: true, selector: "fs-filter-chips", ngImport: i0, template: "@if (items.length !== 0) {\n @for (item of secondaryItems; track item.name) {\n @if ((item.visible$ | async) && (item.hasValue$ | async)) {\n @for (chip of item.chips$ | async; track chip.label) {\n <fs-chip\n class=\"filter-chip selected\"\n [size]=\"'medium'\"\n [borderColor]=\"'#ddd'\"\n [attr.data-filter-item]=\"item.name\"\n [outlined]=\"true\"\n (click)=\"openChip(item, chip.name)\">\n @if (chip.value) {\n {{ chip.label }}:\n <a>\n {{ chip.value }}\n </a>\n } @else {\n {{ chip.label }}\n }\n <ng-template\n fsChipSuffix\n [icon]=\"'cancel_circle_outline'\"\n (click)=\"removeChip(item, chip)\">\n </ng-template>\n </fs-chip>\n }\n }\n @if ((item.visible$ | async) && (item.notValue$ | async) && (item.secondaryVisible$ | async)) {\n <fs-chip\n class=\"filter-chip\"\n [attr.data-filter-item]=\"item.name\"\n [size]=\"'medium'\"\n [borderColor]=\"'#ddd'\"\n (click)=\"openChip(item)\"\n [outlined]=\"true\">\n {{ item.mergedLabel }}\n <ng-template\n fsChipSuffix\n [icon]=\"'add_circle_outline'\"\n (click)=\"openChip(item)\">\n </ng-template>\n </fs-chip>\n }\n }\n <mat-select\n class=\"more-filters-select mat-mdc-button-base\"\n [buttonType]=\"'basic'\"\n fsSelectButton\n [placeholder]=\"'More filters'\"\n (selectionChange)=\"addFilter($event)\"\n [deselectOnChange]=\"true\">\n @for (item of disabledItems; track item.name) {\n <mat-option [value]=\"item\">\n {{ item.mergedLabel }}\n </mat-option>\n }\n </mat-select>\n <mat-select\n class=\"saved-filters-select mat-mdc-button-base\"\n [buttonType]=\"'basic'\"\n fsSelectButton\n [placeholder]=\"(savedFilterController.activeFilter$ | async) ? savedFilterController.singularLabel + ': ' + (savedFilterController.activeFilter$ | async).name : savedFilterController.pluralLabel\"\n [deselectOnChange]=\"true\">\n @if (savedFilterController.activeFilter$ | async) {\n <mat-option (click)=\"saveActiveFilter()\">\n Update filters\n </mat-option>\n <mat-option (click)=\"saveAs()\">\n Save as new\n </mat-option>\n } @else {\n <mat-option (click)=\"createSavedFilter()\">\n Create new\n </mat-option>\n }\n <mat-option (click)=\"manageSavedFilters()\">\n View all\n </mat-option>\n </mat-select>\n @if (hasSecondaryValue$ | async) {\n <a\n class=\"clear\"\n mat-button\n (click)=\"clear()\">\n Clear filters\n </a>\n }\n}", styles: [":host{display:flex;flex-wrap:wrap;align-items:center;gap:5px;max-width:100%;margin-top:4px}.saved-filters-select,.more-filters-select,.clear{display:flex;height:30px}.saved-filters-select.clear,.more-filters-select.clear,.clear.clear{padding:0 10px}.saved-filters-select ::ng-deep .mat-mdc-select-value,.more-filters-select ::ng-deep .mat-mdc-select-value,.clear ::ng-deep .mat-mdc-select-value{padding:0 5px}.saved-filters-select ::ng-deep .mat-mdc-select-arrow-wrapper,.more-filters-select ::ng-deep .mat-mdc-select-arrow-wrapper,.clear ::ng-deep .mat-mdc-select-arrow-wrapper{padding-right:10px}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "ngmodule", type: FsChipModule }, { kind: "component", type: i1$5.FsChipComponent, selector: "fs-chip", inputs: ["selectable", "removable", "value", "maxWidth", "width", "backgroundColor", "borderColor", "color", "shape", "outlined", "outlineDash", "icon", "image", "selected", "padding", "contrastColor", "size"], outputs: ["selectedToggled", "removed", "click"] }, { kind: "directive", type: i1$5.FsChipSuffixDirective, selector: "[fsChipSuffix]", inputs: ["icon", "link", "linkTarget", "color", "data", "tooltip"], outputs: ["click"] }, { kind: "component", type: 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"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption$1, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: FsSelectButtonModule }, { kind: "directive", type: i3$1.FsSelectButtonDirective, selector: "[fsSelectButton]", inputs: ["color", "minWidth", "maxWidth", "width", "buttonType", "deselectOnChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$2.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: FsButtonDirective, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: ["name", "dirtySubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3393
3476
|
}
|
|
3394
3477
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FsFilterChipsComponent, decorators: [{
|
|
3395
3478
|
type: Component,
|
|
@@ -3401,7 +3484,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
3401
3484
|
FsSelectButtonModule,
|
|
3402
3485
|
MatButtonModule,
|
|
3403
3486
|
FsButtonDirective,
|
|
3404
|
-
], template: "@if (items.length !== 0) {\n @for (item of
|
|
3487
|
+
], template: "@if (items.length !== 0) {\n @for (item of secondaryItems; track item.name) {\n @if ((item.visible$ | async) && (item.hasValue$ | async)) {\n @for (chip of item.chips$ | async; track chip.label) {\n <fs-chip\n class=\"filter-chip selected\"\n [size]=\"'medium'\"\n [borderColor]=\"'#ddd'\"\n [attr.data-filter-item]=\"item.name\"\n [outlined]=\"true\"\n (click)=\"openChip(item, chip.name)\">\n @if (chip.value) {\n {{ chip.label }}:\n <a>\n {{ chip.value }}\n </a>\n } @else {\n {{ chip.label }}\n }\n <ng-template\n fsChipSuffix\n [icon]=\"'cancel_circle_outline'\"\n (click)=\"removeChip(item, chip)\">\n </ng-template>\n </fs-chip>\n }\n }\n @if ((item.visible$ | async) && (item.notValue$ | async) && (item.secondaryVisible$ | async)) {\n <fs-chip\n class=\"filter-chip\"\n [attr.data-filter-item]=\"item.name\"\n [size]=\"'medium'\"\n [borderColor]=\"'#ddd'\"\n (click)=\"openChip(item)\"\n [outlined]=\"true\">\n {{ item.mergedLabel }}\n <ng-template\n fsChipSuffix\n [icon]=\"'add_circle_outline'\"\n (click)=\"openChip(item)\">\n </ng-template>\n </fs-chip>\n }\n }\n <mat-select\n class=\"more-filters-select mat-mdc-button-base\"\n [buttonType]=\"'basic'\"\n fsSelectButton\n [placeholder]=\"'More filters'\"\n (selectionChange)=\"addFilter($event)\"\n [deselectOnChange]=\"true\">\n @for (item of disabledItems; track item.name) {\n <mat-option [value]=\"item\">\n {{ item.mergedLabel }}\n </mat-option>\n }\n </mat-select>\n <mat-select\n class=\"saved-filters-select mat-mdc-button-base\"\n [buttonType]=\"'basic'\"\n fsSelectButton\n [placeholder]=\"(savedFilterController.activeFilter$ | async) ? savedFilterController.singularLabel + ': ' + (savedFilterController.activeFilter$ | async).name : savedFilterController.pluralLabel\"\n [deselectOnChange]=\"true\">\n @if (savedFilterController.activeFilter$ | async) {\n <mat-option (click)=\"saveActiveFilter()\">\n Update filters\n </mat-option>\n <mat-option (click)=\"saveAs()\">\n Save as new\n </mat-option>\n } @else {\n <mat-option (click)=\"createSavedFilter()\">\n Create new\n </mat-option>\n }\n <mat-option (click)=\"manageSavedFilters()\">\n View all\n </mat-option>\n </mat-select>\n @if (hasSecondaryValue$ | async) {\n <a\n class=\"clear\"\n mat-button\n (click)=\"clear()\">\n Clear filters\n </a>\n }\n}", styles: [":host{display:flex;flex-wrap:wrap;align-items:center;gap:5px;max-width:100%;margin-top:4px}.saved-filters-select,.more-filters-select,.clear{display:flex;height:30px}.saved-filters-select.clear,.more-filters-select.clear,.clear.clear{padding:0 10px}.saved-filters-select ::ng-deep .mat-mdc-select-value,.more-filters-select ::ng-deep .mat-mdc-select-value,.clear ::ng-deep .mat-mdc-select-value{padding:0 5px}.saved-filters-select ::ng-deep .mat-mdc-select-arrow-wrapper,.more-filters-select ::ng-deep .mat-mdc-select-arrow-wrapper,.clear ::ng-deep .mat-mdc-select-arrow-wrapper{padding-right:10px}\n"] }]
|
|
3405
3488
|
}] });
|
|
3406
3489
|
|
|
3407
3490
|
class KeywordInputComponent {
|