@drsutphin/ngx-mat-facet-toolkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -0
- package/_facet-toolkit-theme.scss +66 -0
- package/fesm2022/drsutphin-ngx-mat-facet-toolkit.mjs +1093 -0
- package/fesm2022/drsutphin-ngx-mat-facet-toolkit.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/directives/focus-on-show.directive.d.ts +12 -0
- package/lib/facet-toolkit.config.d.ts +4 -0
- package/lib/misc/parent.helper.d.ts +7 -0
- package/lib/modals/facet-details-modal/facet-details-modal.component.d.ts +41 -0
- package/lib/modals/facet-modal/facet-modal.animations.d.ts +4 -0
- package/lib/modals/facet-modal/facet-modal.component.d.ts +23 -0
- package/lib/modals/facet-modal.config.d.ts +12 -0
- package/lib/modals/facet-modal.data.d.ts +2 -0
- package/lib/modals/facet-modal.ref.d.ts +17 -0
- package/lib/modals/facet-modal.service.d.ts +14 -0
- package/lib/models/facet-data-type.model.d.ts +10 -0
- package/lib/models/facet-definition.model.d.ts +24 -0
- package/lib/models/facet-editor-state.model.d.ts +9 -0
- package/lib/models/facet-filter-type.model.d.ts +12 -0
- package/lib/models/facet-result.model.d.ts +10 -0
- package/lib/models/facet-selection.model.d.ts +9 -0
- package/lib/models/facet-toolkit-config.model.d.ts +14 -0
- package/lib/models/facet-value.model.d.ts +11 -0
- package/lib/models/index.d.ts +6 -0
- package/lib/ngx-mat-facet-toolkit.animations.d.ts +1 -0
- package/lib/ngx-mat-facet-toolkit.component.d.ts +80 -0
- package/lib/pipes/csv/csv.pipe.d.ts +9 -0
- package/lib/pipes/filter/filter.pipe.d.ts +9 -0
- package/lib/pipes/index.d.ts +3 -0
- package/lib/pipes/keys/keys.pipe.d.ts +7 -0
- package/lib/services/facet-storage.service.d.ts +28 -0
- package/package.json +45 -0
- package/public-api.d.ts +3 -0
|
@@ -0,0 +1,1093 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, Input, Directive, ViewChildren, Inject, Component, EventEmitter, HostListener, HostBinding, ViewChild, Injector, Injectable, makeEnvironmentProviders, Pipe, input, output, signal, inject, ViewContainerRef, computed, effect } from '@angular/core';
|
|
3
|
+
import * as i2 from '@angular/common';
|
|
4
|
+
import { CommonModule } from '@angular/common';
|
|
5
|
+
import * as i3 from '@angular/forms';
|
|
6
|
+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
7
|
+
import * as i9$1 from '@angular/material/autocomplete';
|
|
8
|
+
import { MatAutocompleteModule, MatAutocompleteTrigger } from '@angular/material/autocomplete';
|
|
9
|
+
import * as i6 from '@angular/material/button';
|
|
10
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
11
|
+
import * as i14 from '@angular/material/checkbox';
|
|
12
|
+
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
13
|
+
import * as i7$1 from '@angular/material/chips';
|
|
14
|
+
import { MatChipsModule } from '@angular/material/chips';
|
|
15
|
+
import { MatNativeDateModule, MatOptionModule } from '@angular/material/core';
|
|
16
|
+
import * as i13 from '@angular/material/datepicker';
|
|
17
|
+
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
18
|
+
import * as i11 from '@angular/material/form-field';
|
|
19
|
+
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
20
|
+
import * as i5 from '@angular/material/icon';
|
|
21
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
22
|
+
import * as i12 from '@angular/material/input';
|
|
23
|
+
import { MatInputModule } from '@angular/material/input';
|
|
24
|
+
import * as i10 from '@angular/material/list';
|
|
25
|
+
import { MatListModule } from '@angular/material/list';
|
|
26
|
+
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
27
|
+
import * as i8 from '@angular/material/progress-spinner';
|
|
28
|
+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
29
|
+
import * as i15 from '@angular/material/select';
|
|
30
|
+
import { MatSelectModule } from '@angular/material/select';
|
|
31
|
+
import * as i4 from '@angular/material/toolbar';
|
|
32
|
+
import { MatToolbarModule } from '@angular/material/toolbar';
|
|
33
|
+
import * as i7 from '@angular/material/tooltip';
|
|
34
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
35
|
+
import { A11yModule } from '@angular/cdk/a11y';
|
|
36
|
+
import * as i1$1 from '@angular/cdk/overlay';
|
|
37
|
+
import { OverlayModule } from '@angular/cdk/overlay';
|
|
38
|
+
import * as i1 from '@angular/cdk/portal';
|
|
39
|
+
import { BasePortalOutlet, PortalModule, CdkPortalOutlet, ComponentPortal } from '@angular/cdk/portal';
|
|
40
|
+
import { Subject, BehaviorSubject, of, fromEvent, isObservable } from 'rxjs';
|
|
41
|
+
import { filter, tap, debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
|
|
42
|
+
import * as i9 from '@angular/material/divider';
|
|
43
|
+
import { MatDividerModule } from '@angular/material/divider';
|
|
44
|
+
import { trigger, transition, style, animate, state } from '@angular/animations';
|
|
45
|
+
import { v4 } from 'uuid';
|
|
46
|
+
|
|
47
|
+
var FacetDataType;
|
|
48
|
+
(function (FacetDataType) {
|
|
49
|
+
FacetDataType["Text"] = "Text";
|
|
50
|
+
// eslint-disable-next-line id-blacklist
|
|
51
|
+
FacetDataType["Boolean"] = "Boolean";
|
|
52
|
+
FacetDataType["Category"] = "Category";
|
|
53
|
+
FacetDataType["CategorySingle"] = "CategorySingle";
|
|
54
|
+
FacetDataType["Date"] = "Date";
|
|
55
|
+
FacetDataType["DateRange"] = "DateRange";
|
|
56
|
+
FacetDataType["Typeahead"] = "Typeahead";
|
|
57
|
+
FacetDataType["TypeaheadSingle"] = "TypeaheadSingle";
|
|
58
|
+
})(FacetDataType || (FacetDataType = {}));
|
|
59
|
+
|
|
60
|
+
var FacetFilterType;
|
|
61
|
+
(function (FacetFilterType) {
|
|
62
|
+
FacetFilterType["contains"] = "contains";
|
|
63
|
+
FacetFilterType["startsWith"] = "startsWith";
|
|
64
|
+
FacetFilterType["endsWith"] = "endsWith";
|
|
65
|
+
FacetFilterType["equal"] = "equal";
|
|
66
|
+
FacetFilterType["and"] = "and";
|
|
67
|
+
FacetFilterType["between"] = "between";
|
|
68
|
+
FacetFilterType["greaterThan"] = "greaterThan";
|
|
69
|
+
FacetFilterType["lessThan"] = "lessThan";
|
|
70
|
+
FacetFilterType["greaterThanOrEqual"] = "greaterThanOrEqual";
|
|
71
|
+
FacetFilterType["lessThanOrEqual"] = "lessThanOrEqual";
|
|
72
|
+
})(FacetFilterType || (FacetFilterType = {}));
|
|
73
|
+
|
|
74
|
+
var FacetIdentifierStrategy;
|
|
75
|
+
(function (FacetIdentifierStrategy) {
|
|
76
|
+
FacetIdentifierStrategy["WindowURL"] = "windowURL";
|
|
77
|
+
FacetIdentifierStrategy["ParentID"] = "parentID";
|
|
78
|
+
FacetIdentifierStrategy["Random"] = "random";
|
|
79
|
+
FacetIdentifierStrategy["Manual"] = "manual";
|
|
80
|
+
})(FacetIdentifierStrategy || (FacetIdentifierStrategy = {}));
|
|
81
|
+
const DEFAULT_FACET_TOOLKIT_CONFIG = {
|
|
82
|
+
allowDebugClick: false,
|
|
83
|
+
identifierStrategy: FacetIdentifierStrategy.ParentID,
|
|
84
|
+
loggingCallback: () => { },
|
|
85
|
+
storage: 'session'
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const FACET_MODAL_DATA = new InjectionToken('facet.data');
|
|
89
|
+
|
|
90
|
+
var FacetResultType;
|
|
91
|
+
(function (FacetResultType) {
|
|
92
|
+
FacetResultType[FacetResultType["REMOVE"] = 0] = "REMOVE";
|
|
93
|
+
FacetResultType[FacetResultType["CANCEL"] = 1] = "CANCEL";
|
|
94
|
+
FacetResultType[FacetResultType["ADD"] = 2] = "ADD";
|
|
95
|
+
})(FacetResultType || (FacetResultType = {}));
|
|
96
|
+
|
|
97
|
+
class FocusOnShowDirective {
|
|
98
|
+
el;
|
|
99
|
+
timeout = '0';
|
|
100
|
+
firstElement = true;
|
|
101
|
+
constructor(el) {
|
|
102
|
+
this.el = el;
|
|
103
|
+
if (!el.nativeElement.focus) {
|
|
104
|
+
throw new Error('Element does not accept focus.');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
ngOnInit() {
|
|
108
|
+
if (this.firstElement) {
|
|
109
|
+
setTimeout(() => {
|
|
110
|
+
this.focusInput();
|
|
111
|
+
}, (Number(this.timeout) || 0));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
focusInput() {
|
|
115
|
+
const input = this.el.nativeElement;
|
|
116
|
+
input.focus();
|
|
117
|
+
if (this.el.nativeElement.hasOwnProperty('select')) {
|
|
118
|
+
input.select();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FocusOnShowDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
122
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.17", type: FocusOnShowDirective, isStandalone: true, selector: "[focusOnShow]", inputs: { timeout: ["focusOnShow", "timeout"], firstElement: "firstElement" }, ngImport: i0 });
|
|
123
|
+
}
|
|
124
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FocusOnShowDirective, decorators: [{
|
|
125
|
+
type: Directive,
|
|
126
|
+
args: [{
|
|
127
|
+
selector: '[focusOnShow]',
|
|
128
|
+
standalone: true
|
|
129
|
+
}]
|
|
130
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { timeout: [{
|
|
131
|
+
type: Input,
|
|
132
|
+
args: ['focusOnShow']
|
|
133
|
+
}], firstElement: [{
|
|
134
|
+
type: Input
|
|
135
|
+
}] } });
|
|
136
|
+
|
|
137
|
+
class FacetModalRef {
|
|
138
|
+
overlayRef;
|
|
139
|
+
positionStrategy;
|
|
140
|
+
config;
|
|
141
|
+
afterClosedSubject = new Subject();
|
|
142
|
+
beforeClosedSubject = new Subject();
|
|
143
|
+
_result = { type: FacetResultType.CANCEL };
|
|
144
|
+
constructor(overlayRef, positionStrategy, config) {
|
|
145
|
+
this.overlayRef = overlayRef;
|
|
146
|
+
this.positionStrategy = positionStrategy;
|
|
147
|
+
this.config = config;
|
|
148
|
+
if (!config.disableClose) {
|
|
149
|
+
this.overlayRef.backdropClick().subscribe(() => {
|
|
150
|
+
this.close(this._result);
|
|
151
|
+
});
|
|
152
|
+
this.overlayRef.detachments().subscribe(() => {
|
|
153
|
+
this.beforeClosedSubject.next(this._result);
|
|
154
|
+
this.beforeClosedSubject.complete();
|
|
155
|
+
});
|
|
156
|
+
this.overlayRef.keydownEvents().pipe(filter(event => event.key === 'Escape')).subscribe(() => {
|
|
157
|
+
this.close();
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
close(dialogResult) {
|
|
162
|
+
if (!!dialogResult) {
|
|
163
|
+
this._result = dialogResult;
|
|
164
|
+
}
|
|
165
|
+
this.beforeClosedSubject.next(this._result);
|
|
166
|
+
this.beforeClosedSubject.complete();
|
|
167
|
+
this.afterClosedSubject.next(this._result);
|
|
168
|
+
this.afterClosedSubject.complete();
|
|
169
|
+
this.overlayRef.dispose();
|
|
170
|
+
}
|
|
171
|
+
afterClosed() {
|
|
172
|
+
return this.afterClosedSubject.asObservable();
|
|
173
|
+
}
|
|
174
|
+
beforeClosed() {
|
|
175
|
+
return this.beforeClosedSubject.asObservable();
|
|
176
|
+
}
|
|
177
|
+
positionChanges() {
|
|
178
|
+
return this.positionStrategy.positionChanges;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const MAX_TEXT_LENGTH = 60;
|
|
183
|
+
class FacetDetailsModalComponent {
|
|
184
|
+
data;
|
|
185
|
+
modalRef;
|
|
186
|
+
typeAheadInputs;
|
|
187
|
+
isUpdate;
|
|
188
|
+
typeaheadText;
|
|
189
|
+
clearButtonDisabled = true;
|
|
190
|
+
resolvedOptions$;
|
|
191
|
+
FacetDataType = FacetDataType;
|
|
192
|
+
FacetFilterType = FacetFilterType;
|
|
193
|
+
typeAheadInputChanged = new BehaviorSubject('');
|
|
194
|
+
constructor(data, modalRef) {
|
|
195
|
+
this.data = data;
|
|
196
|
+
this.modalRef = modalRef;
|
|
197
|
+
this.isUpdate = modalRef.config.isUpdate;
|
|
198
|
+
}
|
|
199
|
+
ngOnInit() {
|
|
200
|
+
switch (this.data.type) {
|
|
201
|
+
case FacetDataType.Typeahead:
|
|
202
|
+
case FacetDataType.TypeaheadSingle:
|
|
203
|
+
if (this.data.typeahead?.provider) {
|
|
204
|
+
this.resolvedOptions$ = this.data.typeahead.provider('');
|
|
205
|
+
}
|
|
206
|
+
break;
|
|
207
|
+
case FacetDataType.Date:
|
|
208
|
+
this.data.values = this.data.values?.length ? this.data.values : [{ value: null }];
|
|
209
|
+
break;
|
|
210
|
+
case FacetDataType.DateRange:
|
|
211
|
+
this.data.values = this.data.values?.length ? this.data.values : [{ value: null }, { value: null }];
|
|
212
|
+
break;
|
|
213
|
+
case FacetDataType.Boolean:
|
|
214
|
+
this.data.values = this.data.values?.length ? this.data.values : [{ value: null }];
|
|
215
|
+
break;
|
|
216
|
+
case FacetDataType.Text:
|
|
217
|
+
this.data.values = this.data.values?.length ? this.data.values : [{ value: '' }];
|
|
218
|
+
this.data.filterType = this.data.filterType || this.data.fixedFilterType || FacetFilterType.contains;
|
|
219
|
+
break;
|
|
220
|
+
default:
|
|
221
|
+
this.data.values = this.data.values?.length ? this.data.values : [{ value: null }];
|
|
222
|
+
}
|
|
223
|
+
if (!this.resolvedOptions$ && this.data.options) {
|
|
224
|
+
this.resolvedOptions$ = this.normalizeOptions(this.data.options);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
ngAfterViewInit() {
|
|
228
|
+
if (this.typeAheadInputs.length > 0) {
|
|
229
|
+
this.typeAheadInputChanged.pipe(tap(() => this.resolvedOptions$ = undefined), debounceTime(this.data.typeahead?.debounce || 300)).subscribe(search => {
|
|
230
|
+
if (!!this.data.typeahead?.provider) {
|
|
231
|
+
this.data.typeahead.provider((search || '')).subscribe(options => {
|
|
232
|
+
this.resolvedOptions$ = of(options || []);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
typeaheadValueChanged(event) {
|
|
239
|
+
this.typeAheadInputChanged.next(event || '');
|
|
240
|
+
this.clearButtonDisabled = (!event || event.length === 0);
|
|
241
|
+
}
|
|
242
|
+
truncateText(txt) {
|
|
243
|
+
if (txt && txt.length) {
|
|
244
|
+
return txt.length > MAX_TEXT_LENGTH ?
|
|
245
|
+
`${txt.substring(0, MAX_TEXT_LENGTH).trim()}...` :
|
|
246
|
+
txt;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
return txt;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
onOk() {
|
|
253
|
+
this.modalRef.close({
|
|
254
|
+
type: FacetResultType.ADD,
|
|
255
|
+
data: this.data
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
onRemove() {
|
|
259
|
+
this.modalRef.close({
|
|
260
|
+
type: FacetResultType.REMOVE,
|
|
261
|
+
data: this.data
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
onCancel() {
|
|
265
|
+
this.modalRef.close({
|
|
266
|
+
type: FacetResultType.CANCEL,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
onClose() {
|
|
270
|
+
this.modalRef.close();
|
|
271
|
+
}
|
|
272
|
+
validateAndSubmit() {
|
|
273
|
+
if (!this.isUpdateButtonDisabled()) {
|
|
274
|
+
this.onOk();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
isItemSelected = (option) => (this.data.values || []).some(o => o.value === option.value);
|
|
278
|
+
addOptionToSelected = (facet, option) => {
|
|
279
|
+
const isSelected = (facet.values || []).some(f => f.value === option.value);
|
|
280
|
+
if (isSelected && (facet.type === FacetDataType.Category || facet.type === FacetDataType.Typeahead)) {
|
|
281
|
+
facet.values = (facet.values || []).filter(f => f.value !== option.value);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
option.selected = true;
|
|
285
|
+
switch (facet.type) {
|
|
286
|
+
case FacetDataType.Category:
|
|
287
|
+
case FacetDataType.Typeahead:
|
|
288
|
+
facet.values = (facet.values || []);
|
|
289
|
+
facet.values.push(option);
|
|
290
|
+
break;
|
|
291
|
+
case FacetDataType.CategorySingle:
|
|
292
|
+
case FacetDataType.TypeaheadSingle:
|
|
293
|
+
facet.values = [option];
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
isUpdateButtonDisabled = () => {
|
|
299
|
+
switch (this.data.type) {
|
|
300
|
+
case FacetDataType.Category:
|
|
301
|
+
case FacetDataType.CategorySingle:
|
|
302
|
+
case FacetDataType.Date:
|
|
303
|
+
case FacetDataType.Text:
|
|
304
|
+
case FacetDataType.Typeahead:
|
|
305
|
+
case FacetDataType.TypeaheadSingle:
|
|
306
|
+
return !(this.data.values || []).some(v => !!v?.value);
|
|
307
|
+
case FacetDataType.DateRange:
|
|
308
|
+
return !(this.getRawValue(this.data)) || !(this.getRawValue(this.data, 1));
|
|
309
|
+
case FacetDataType.Boolean:
|
|
310
|
+
return !(this.getRawValue(this.data));
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
emptyFunction() { }
|
|
314
|
+
clearInput() {
|
|
315
|
+
this.typeaheadText = null;
|
|
316
|
+
this.typeaheadValueChanged('');
|
|
317
|
+
}
|
|
318
|
+
getRawValue(facet, offset) {
|
|
319
|
+
if (!!facet?.values?.length && facet.values[offset || 0]) {
|
|
320
|
+
return facet.values[offset || 0].value;
|
|
321
|
+
}
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
setValue(facet, newValue, offset) {
|
|
325
|
+
if (!!facet?.values?.length && facet.values[offset || 0]) {
|
|
326
|
+
facet.values[offset || 0] = {
|
|
327
|
+
...facet.values[offset || 0],
|
|
328
|
+
value: newValue
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
setType(newType) {
|
|
333
|
+
this.data.filterType = newType;
|
|
334
|
+
}
|
|
335
|
+
normalizeOptions(options) {
|
|
336
|
+
return Array.isArray(options) ? of(options) : options;
|
|
337
|
+
}
|
|
338
|
+
selectionChange(selection, facet, options) {
|
|
339
|
+
selection.options
|
|
340
|
+
.map(selectedOption => (options || []).find(option => option.value === selectedOption.value))
|
|
341
|
+
.filter((option) => !!option)
|
|
342
|
+
.filter(facetOption => !(facet.values || []).find(v => v.value === facetOption.value))
|
|
343
|
+
.forEach(selectedOption => this.addOptionToSelected(facet, selectedOption));
|
|
344
|
+
}
|
|
345
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetDetailsModalComponent, deps: [{ token: FACET_MODAL_DATA }, { token: FacetModalRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
346
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: FacetDetailsModalComponent, isStandalone: true, selector: "ngx-mat-facet-details-modal", viewQueries: [{ propertyName: "typeAheadInputs", predicate: ["typeAheadInput"], descendants: true }], ngImport: i0, template: "<div class=\"mat-typography details\">\n\n <mat-toolbar color=\"primary\" class=\"modal-header\">\n <h2 class=\"modal-title\">{{data.label}}</h2>\n <button class=\"modal-close\" mat-icon-button (click)=\"onCancel()\">\n <mat-icon>clear</mat-icon>\n </button>\n </mat-toolbar>\n\n <div class=\"content\">\n\n @if (data.description) {\n <p class=\"description\">{{data.description}}</p>\n }\n\n <ng-template #loading>\n <mat-spinner diameter=\"20\"></mat-spinner>\n </ng-template>\n\n <ng-template #noResults>\n <span class=\"facet-no-results\" @fadeIn>No Results</span>\n </ng-template>\n\n @switch (true) {\n @case (data.type === FacetDataType.Category || data.type === FacetDataType.CategorySingle) {\n <div class=\"category-wrapper\">\n @if (resolvedOptions$ | async; as options) {\n <mat-divider></mat-divider>\n @if (options.length > 0) {\n <mat-selection-list (selectionChange)=\"selectionChange($event, data, options)\">\n @for (item of options; track item.value) {\n <mat-list-option [value]=\"item.value\" [selected]=\"isItemSelected(item)\"\n @fadeIn\n focusOnShow\n [firstElement]=\"$first\">\n <span>\n {{ item.label ? truncateText(item.label) : \"- empty -\" }}\n @if (item.count) {\n <small><i>({{item.count}})</i></small>\n }\n </span>\n </mat-list-option>\n }\n </mat-selection-list>\n } @else {\n <ng-container *ngTemplateOutlet=\"noResults\"></ng-container>\n }\n <mat-divider></mat-divider>\n } @else {\n <ng-container *ngTemplateOutlet=\"loading\"></ng-container>\n }\n </div>\n }\n @case (data.type === FacetDataType.Typeahead || data.type === FacetDataType.TypeaheadSingle) {\n <div class=\"typeahead-wrapper\">\n\n <mat-form-field class=\"typeahead-form-field\" appearance=\"outline\" floatLabel=\"auto\">\n <mat-label>Search...</mat-label>\n <input matInput #typeAheadInput\n autocomplete=\"off\"\n focusOnShow=\"100\"\n [(ngModel)]=\"typeaheadText\"\n placeholder=\"{{(data.typeahead || {placeholder: ''}).placeholder}}\"\n (ngModelChange)=\"typeaheadValueChanged($event)\"/>\n\n @if (!clearButtonDisabled) {\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"clearInput()\">\n <mat-icon>clear</mat-icon>\n </button>\n }\n </mat-form-field>\n\n @if (resolvedOptions$ | async; as options) {\n <mat-divider></mat-divider>\n @if (options.length > 0) {\n <mat-selection-list (selectionChange)=\"selectionChange($event, data, options)\">\n @for (item of options; track item.value) {\n <mat-list-option [value]=\"item.value\"\n @fadeIn\n focusOnShow\n [firstElement]=\"$first\"\n [selected]=\"isItemSelected(item)\">\n <span>\n {{ item.label ? truncateText(item.label) : \"- empty -\" }}\n @if (item.count) {\n <small><i>({{item.count}})</i></small>\n }\n </span>\n </mat-list-option>\n }\n </mat-selection-list>\n } @else {\n <ng-container *ngTemplateOutlet=\"noResults\"></ng-container>\n }\n <mat-divider></mat-divider>\n } @else {\n <ng-container *ngTemplateOutlet=\"loading\"></ng-container>\n }\n\n </div>\n }\n @case (data.type === FacetDataType.Date) {\n <div class=\"date-wrapper\">\n\n <mat-form-field appearance=\"outline\" floatLabel=\"always\" class=\"date-field\">\n <mat-label>{{data.label}}</mat-label>\n <input matInput autocomplete=\"off\" focusOnShow=\"100\" [matDatepicker]=\"picker\" [ngModel]=\"getRawValue(data)\" (ngModelChange)=\"setValue(data, $event)\"\n placeholder=\"Choose a date\" (focus)=\"isUpdate ? emptyFunction() : picker.open()\"/>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n </mat-form-field>\n <mat-datepicker #picker></mat-datepicker>\n\n </div>\n }\n @case (data.type === FacetDataType.DateRange) {\n <div class=\"date-range-wrapper\">\n\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\n <mat-label>{{data.label}} - Start</mat-label>\n <input matInput focusOnShow=\"100\" autocomplete=\"off\" [matDatepicker]=\"startDatePicker\"\n [ngModel]=\"getRawValue(data)\" (ngModelChange)=\"setValue(data, $event)\" placeholder=\"Choose a starting date\"\n (focus)=\"isUpdate ? emptyFunction() : startDatePicker.open()\"/>\n <mat-datepicker-toggle matSuffix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n </mat-form-field>\n <mat-datepicker #startDatePicker></mat-datepicker>\n\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\n <mat-label>{{data.label}} - End</mat-label>\n <input matInput autocomplete=\"off\" [matDatepicker]=\"endDatePicker\"\n [ngModel]=\"getRawValue(data, 1)\" (ngModelChange)=\"setValue(data, $event, 1)\" placeholder=\"Choose an end date\"/>\n <mat-datepicker-toggle matSuffix [for]=\"endDatePicker\"></mat-datepicker-toggle>\n </mat-form-field>\n <mat-datepicker #endDatePicker></mat-datepicker>\n\n </div>\n }\n @case (data.type === FacetDataType.Text) {\n <div class=\"text-wrapper\">\n\n <mat-form-field class=\"criteria-field\" appearance=\"outline\">\n <mat-label>Criteria Type</mat-label>\n <mat-select [value]=\"data.fixedFilterType || data.filterType\"\n (valueChange)=\"setType($event)\" placeholder=\"Criteria Type\">\n <mat-option [value]=\"FacetFilterType.contains\">Contains</mat-option>\n <mat-option [value]=\"FacetFilterType.endsWith\">Ends With</mat-option>\n <mat-option [value]=\"FacetFilterType.equal\">Equals</mat-option>\n <mat-option [value]=\"FacetFilterType.startsWith\">Starts With</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field class=\"search-field\" appearance=\"outline\">\n <mat-label>Search Text</mat-label>\n <input matInput focusOnShow (keydown.enter)=\"validateAndSubmit()\" autocomplete=\"off\"\n [ngModel]=\"getRawValue(data)\" (ngModelChange)=\"setValue(data, $event)\"\n placeholder=\"{{data.placeholder || data.label }}\" autofocus/>\n @if (data.values) {\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"data.values = []\">\n <mat-icon>close</mat-icon>\n </button>\n }\n </mat-form-field>\n\n </div>\n }\n @case (data.type === FacetDataType.Boolean) {\n <div class=\"boolean-wrapper\">\n <mat-checkbox [ngModel]=\"getRawValue(data)\" (ngModelChange)=\"setValue(data, $event)\">{{data.placeholder || data.label}}</mat-checkbox>\n </div>\n }\n }\n\n </div>\n\n <div class=\"actions\">\n\n <button mat-flat-button class=\"add-update-button\" [color]=\"isUpdate ? 'accent' : 'primary'\" (click)=\"onOk()\"\n [disabled]=\"isUpdateButtonDisabled()\">{{isUpdate ? 'Update' : 'Add'}}</button>\n\n @if (isUpdate) {\n <button mat-icon-button class=\"remove-button\" color=\"warn\" (click)=\"onRemove()\" matTooltip=\"Delete Filter\" matTooltipPosition=\"after\">\n <mat-icon>delete</mat-icon>\n </button>\n }\n\n </div>\n</div>\n", styles: ["mat-spinner{margin:1em auto}.details{display:flex;flex-direction:column;align-items:stretch}.content{min-height:120px;padding-top:22px;display:flex;flex-direction:column;align-items:normal}.content mat-selection-list{flex:1;max-height:30vh;overflow-y:auto}.actions{padding:16px;display:flex;justify-content:space-between;flex-direction:row-reverse}span.facet-no-results{text-align:center;color:gray;margin-top:1em;margin-bottom:1em}.mat-selection-list{margin-top:0;padding-top:0}.mat-form-field{margin:0!important;padding-left:15px;padding-right:15px}.mat-dialog-actions{padding:0 15px 15px}.modal-header{display:flex;justify-content:space-between;align-items:center!important;border-top-left-radius:8px;border-top-right-radius:8px}.modal-header .modal-title{height:40px!important;margin:0!important;line-height:45px}p.description{padding-left:15px;padding-right:15px;margin-bottom:0;color:gray;flex:1}.date-range-wrapper{padding-left:15px;padding-right:15px;display:flex;flex-direction:column;align-items:stretch;justify-content:space-between}.date-range-wrapper,.category-wrapper{margin-top:1em}.boolean-wrapper{padding-left:15px;padding-right:15px;flex:4;display:flex;justify-content:flex-start;align-items:center}.text-wrapper{padding-left:15px;padding-right:15px;display:flex;flex-direction:column;flex:2;margin-top:1rem}.date-wrapper{padding-left:15px;padding-right:15px;display:flex;justify-content:center;align-items:center}.date-wrapper .date-field{flex:1}.typeahead-wrapper{padding-left:15px;padding-right:15px;display:flex;flex-direction:column;align-items:stretch;margin-top:1em}.typeahead-wrapper .typeahead-form-field{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i4.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i9.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i10.MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: i10.MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i11.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i11.MatLabel, selector: "mat-label" }, { kind: "directive", type: i11.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i12.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: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i13.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i13.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i13.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i14.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: MatSelectModule }, { kind: "component", type: i15.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: i15.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "directive", type: FocusOnShowDirective, selector: "[focusOnShow]", inputs: ["focusOnShow", "firstElement"] }], animations: [
|
|
347
|
+
trigger('fadeIn', [
|
|
348
|
+
transition(':enter', [
|
|
349
|
+
style({ opacity: '0', height: 0 }),
|
|
350
|
+
animate('.2s ease-out', style({ opacity: '1', height: '*' })),
|
|
351
|
+
]),
|
|
352
|
+
]),
|
|
353
|
+
] });
|
|
354
|
+
}
|
|
355
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetDetailsModalComponent, decorators: [{
|
|
356
|
+
type: Component,
|
|
357
|
+
args: [{ selector: 'ngx-mat-facet-details-modal', standalone: true, imports: [
|
|
358
|
+
CommonModule,
|
|
359
|
+
FormsModule,
|
|
360
|
+
MatToolbarModule,
|
|
361
|
+
MatIconModule,
|
|
362
|
+
MatButtonModule,
|
|
363
|
+
MatTooltipModule,
|
|
364
|
+
MatProgressSpinnerModule,
|
|
365
|
+
MatDividerModule,
|
|
366
|
+
MatListModule,
|
|
367
|
+
MatFormFieldModule,
|
|
368
|
+
MatInputModule,
|
|
369
|
+
MatDatepickerModule,
|
|
370
|
+
MatNativeDateModule,
|
|
371
|
+
MatCheckboxModule,
|
|
372
|
+
MatSelectModule,
|
|
373
|
+
MatOptionModule,
|
|
374
|
+
FocusOnShowDirective
|
|
375
|
+
], animations: [
|
|
376
|
+
trigger('fadeIn', [
|
|
377
|
+
transition(':enter', [
|
|
378
|
+
style({ opacity: '0', height: 0 }),
|
|
379
|
+
animate('.2s ease-out', style({ opacity: '1', height: '*' })),
|
|
380
|
+
]),
|
|
381
|
+
]),
|
|
382
|
+
], template: "<div class=\"mat-typography details\">\n\n <mat-toolbar color=\"primary\" class=\"modal-header\">\n <h2 class=\"modal-title\">{{data.label}}</h2>\n <button class=\"modal-close\" mat-icon-button (click)=\"onCancel()\">\n <mat-icon>clear</mat-icon>\n </button>\n </mat-toolbar>\n\n <div class=\"content\">\n\n @if (data.description) {\n <p class=\"description\">{{data.description}}</p>\n }\n\n <ng-template #loading>\n <mat-spinner diameter=\"20\"></mat-spinner>\n </ng-template>\n\n <ng-template #noResults>\n <span class=\"facet-no-results\" @fadeIn>No Results</span>\n </ng-template>\n\n @switch (true) {\n @case (data.type === FacetDataType.Category || data.type === FacetDataType.CategorySingle) {\n <div class=\"category-wrapper\">\n @if (resolvedOptions$ | async; as options) {\n <mat-divider></mat-divider>\n @if (options.length > 0) {\n <mat-selection-list (selectionChange)=\"selectionChange($event, data, options)\">\n @for (item of options; track item.value) {\n <mat-list-option [value]=\"item.value\" [selected]=\"isItemSelected(item)\"\n @fadeIn\n focusOnShow\n [firstElement]=\"$first\">\n <span>\n {{ item.label ? truncateText(item.label) : \"- empty -\" }}\n @if (item.count) {\n <small><i>({{item.count}})</i></small>\n }\n </span>\n </mat-list-option>\n }\n </mat-selection-list>\n } @else {\n <ng-container *ngTemplateOutlet=\"noResults\"></ng-container>\n }\n <mat-divider></mat-divider>\n } @else {\n <ng-container *ngTemplateOutlet=\"loading\"></ng-container>\n }\n </div>\n }\n @case (data.type === FacetDataType.Typeahead || data.type === FacetDataType.TypeaheadSingle) {\n <div class=\"typeahead-wrapper\">\n\n <mat-form-field class=\"typeahead-form-field\" appearance=\"outline\" floatLabel=\"auto\">\n <mat-label>Search...</mat-label>\n <input matInput #typeAheadInput\n autocomplete=\"off\"\n focusOnShow=\"100\"\n [(ngModel)]=\"typeaheadText\"\n placeholder=\"{{(data.typeahead || {placeholder: ''}).placeholder}}\"\n (ngModelChange)=\"typeaheadValueChanged($event)\"/>\n\n @if (!clearButtonDisabled) {\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"clearInput()\">\n <mat-icon>clear</mat-icon>\n </button>\n }\n </mat-form-field>\n\n @if (resolvedOptions$ | async; as options) {\n <mat-divider></mat-divider>\n @if (options.length > 0) {\n <mat-selection-list (selectionChange)=\"selectionChange($event, data, options)\">\n @for (item of options; track item.value) {\n <mat-list-option [value]=\"item.value\"\n @fadeIn\n focusOnShow\n [firstElement]=\"$first\"\n [selected]=\"isItemSelected(item)\">\n <span>\n {{ item.label ? truncateText(item.label) : \"- empty -\" }}\n @if (item.count) {\n <small><i>({{item.count}})</i></small>\n }\n </span>\n </mat-list-option>\n }\n </mat-selection-list>\n } @else {\n <ng-container *ngTemplateOutlet=\"noResults\"></ng-container>\n }\n <mat-divider></mat-divider>\n } @else {\n <ng-container *ngTemplateOutlet=\"loading\"></ng-container>\n }\n\n </div>\n }\n @case (data.type === FacetDataType.Date) {\n <div class=\"date-wrapper\">\n\n <mat-form-field appearance=\"outline\" floatLabel=\"always\" class=\"date-field\">\n <mat-label>{{data.label}}</mat-label>\n <input matInput autocomplete=\"off\" focusOnShow=\"100\" [matDatepicker]=\"picker\" [ngModel]=\"getRawValue(data)\" (ngModelChange)=\"setValue(data, $event)\"\n placeholder=\"Choose a date\" (focus)=\"isUpdate ? emptyFunction() : picker.open()\"/>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n </mat-form-field>\n <mat-datepicker #picker></mat-datepicker>\n\n </div>\n }\n @case (data.type === FacetDataType.DateRange) {\n <div class=\"date-range-wrapper\">\n\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\n <mat-label>{{data.label}} - Start</mat-label>\n <input matInput focusOnShow=\"100\" autocomplete=\"off\" [matDatepicker]=\"startDatePicker\"\n [ngModel]=\"getRawValue(data)\" (ngModelChange)=\"setValue(data, $event)\" placeholder=\"Choose a starting date\"\n (focus)=\"isUpdate ? emptyFunction() : startDatePicker.open()\"/>\n <mat-datepicker-toggle matSuffix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n </mat-form-field>\n <mat-datepicker #startDatePicker></mat-datepicker>\n\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\n <mat-label>{{data.label}} - End</mat-label>\n <input matInput autocomplete=\"off\" [matDatepicker]=\"endDatePicker\"\n [ngModel]=\"getRawValue(data, 1)\" (ngModelChange)=\"setValue(data, $event, 1)\" placeholder=\"Choose an end date\"/>\n <mat-datepicker-toggle matSuffix [for]=\"endDatePicker\"></mat-datepicker-toggle>\n </mat-form-field>\n <mat-datepicker #endDatePicker></mat-datepicker>\n\n </div>\n }\n @case (data.type === FacetDataType.Text) {\n <div class=\"text-wrapper\">\n\n <mat-form-field class=\"criteria-field\" appearance=\"outline\">\n <mat-label>Criteria Type</mat-label>\n <mat-select [value]=\"data.fixedFilterType || data.filterType\"\n (valueChange)=\"setType($event)\" placeholder=\"Criteria Type\">\n <mat-option [value]=\"FacetFilterType.contains\">Contains</mat-option>\n <mat-option [value]=\"FacetFilterType.endsWith\">Ends With</mat-option>\n <mat-option [value]=\"FacetFilterType.equal\">Equals</mat-option>\n <mat-option [value]=\"FacetFilterType.startsWith\">Starts With</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field class=\"search-field\" appearance=\"outline\">\n <mat-label>Search Text</mat-label>\n <input matInput focusOnShow (keydown.enter)=\"validateAndSubmit()\" autocomplete=\"off\"\n [ngModel]=\"getRawValue(data)\" (ngModelChange)=\"setValue(data, $event)\"\n placeholder=\"{{data.placeholder || data.label }}\" autofocus/>\n @if (data.values) {\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"data.values = []\">\n <mat-icon>close</mat-icon>\n </button>\n }\n </mat-form-field>\n\n </div>\n }\n @case (data.type === FacetDataType.Boolean) {\n <div class=\"boolean-wrapper\">\n <mat-checkbox [ngModel]=\"getRawValue(data)\" (ngModelChange)=\"setValue(data, $event)\">{{data.placeholder || data.label}}</mat-checkbox>\n </div>\n }\n }\n\n </div>\n\n <div class=\"actions\">\n\n <button mat-flat-button class=\"add-update-button\" [color]=\"isUpdate ? 'accent' : 'primary'\" (click)=\"onOk()\"\n [disabled]=\"isUpdateButtonDisabled()\">{{isUpdate ? 'Update' : 'Add'}}</button>\n\n @if (isUpdate) {\n <button mat-icon-button class=\"remove-button\" color=\"warn\" (click)=\"onRemove()\" matTooltip=\"Delete Filter\" matTooltipPosition=\"after\">\n <mat-icon>delete</mat-icon>\n </button>\n }\n\n </div>\n</div>\n", styles: ["mat-spinner{margin:1em auto}.details{display:flex;flex-direction:column;align-items:stretch}.content{min-height:120px;padding-top:22px;display:flex;flex-direction:column;align-items:normal}.content mat-selection-list{flex:1;max-height:30vh;overflow-y:auto}.actions{padding:16px;display:flex;justify-content:space-between;flex-direction:row-reverse}span.facet-no-results{text-align:center;color:gray;margin-top:1em;margin-bottom:1em}.mat-selection-list{margin-top:0;padding-top:0}.mat-form-field{margin:0!important;padding-left:15px;padding-right:15px}.mat-dialog-actions{padding:0 15px 15px}.modal-header{display:flex;justify-content:space-between;align-items:center!important;border-top-left-radius:8px;border-top-right-radius:8px}.modal-header .modal-title{height:40px!important;margin:0!important;line-height:45px}p.description{padding-left:15px;padding-right:15px;margin-bottom:0;color:gray;flex:1}.date-range-wrapper{padding-left:15px;padding-right:15px;display:flex;flex-direction:column;align-items:stretch;justify-content:space-between}.date-range-wrapper,.category-wrapper{margin-top:1em}.boolean-wrapper{padding-left:15px;padding-right:15px;flex:4;display:flex;justify-content:flex-start;align-items:center}.text-wrapper{padding-left:15px;padding-right:15px;display:flex;flex-direction:column;flex:2;margin-top:1rem}.date-wrapper{padding-left:15px;padding-right:15px;display:flex;justify-content:center;align-items:center}.date-wrapper .date-field{flex:1}.typeahead-wrapper{padding-left:15px;padding-right:15px;display:flex;flex-direction:column;align-items:stretch;margin-top:1em}.typeahead-wrapper .typeahead-form-field{flex:1}\n"] }]
|
|
383
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
384
|
+
type: Inject,
|
|
385
|
+
args: [FACET_MODAL_DATA]
|
|
386
|
+
}] }, { type: FacetModalRef }], propDecorators: { typeAheadInputs: [{
|
|
387
|
+
type: ViewChildren,
|
|
388
|
+
args: ['typeAheadInput']
|
|
389
|
+
}] } });
|
|
390
|
+
|
|
391
|
+
const DefaultFacetModalConfig = {
|
|
392
|
+
backdropClass: '',
|
|
393
|
+
disableClose: false,
|
|
394
|
+
hasBackdrop: true,
|
|
395
|
+
panelClass: '',
|
|
396
|
+
isUpdate: false,
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
const facetModalAnimations = {
|
|
400
|
+
modalContainer: trigger('modalContainer', [
|
|
401
|
+
state('void, exit', style({ opacity: 0, transform: 'scale(0.7)' })),
|
|
402
|
+
state('enter', style({ transform: 'none' })),
|
|
403
|
+
transition('* => enter', animate('150ms cubic-bezier(0, 0, 0.2, 1)', style({ transform: 'none', opacity: 1 }))),
|
|
404
|
+
transition('* => void, * => exit', animate('75ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ opacity: 0 }))),
|
|
405
|
+
])
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
class FacetModalComponent extends BasePortalOutlet {
|
|
409
|
+
portalOutlet;
|
|
410
|
+
hostClass = 'facet-modal-component';
|
|
411
|
+
state = 'enter';
|
|
412
|
+
animationStateChanged = new EventEmitter();
|
|
413
|
+
get animationState() {
|
|
414
|
+
return this.state;
|
|
415
|
+
}
|
|
416
|
+
_onAnimationDone({ toState, totalTime }) {
|
|
417
|
+
if (toState === 'enter') {
|
|
418
|
+
this.animationStateChanged.next({ state: 'opened', totalTime });
|
|
419
|
+
}
|
|
420
|
+
else if (toState === 'exit') {
|
|
421
|
+
this.animationStateChanged.next({ state: 'closed', totalTime });
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
_onAnimationStart({ toState, totalTime }) {
|
|
425
|
+
if (toState === 'enter') {
|
|
426
|
+
this.animationStateChanged.next({ state: 'opening', totalTime });
|
|
427
|
+
}
|
|
428
|
+
else if (toState === 'exit' || toState === 'void') {
|
|
429
|
+
this.animationStateChanged.next({ state: 'closing', totalTime });
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
attachComponentPortal(componentPortal) {
|
|
433
|
+
return this.portalOutlet.attachComponentPortal(componentPortal);
|
|
434
|
+
}
|
|
435
|
+
attachTemplatePortal(portal) {
|
|
436
|
+
throw new Error('Method not implemented.');
|
|
437
|
+
}
|
|
438
|
+
_startExitAnimation() {
|
|
439
|
+
this.state = 'exit';
|
|
440
|
+
}
|
|
441
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetModalComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
442
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: FacetModalComponent, isStandalone: true, selector: "ngx-facet-modal", host: { listeners: { "@modalContainer.done": "_onAnimationDone($event)", "@modalContainer.start": "_onAnimationStart($event)" }, properties: { "class": "this.hostClass", "@modalContainer": "this.animationState" } }, viewQueries: [{ propertyName: "portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ng-template cdkPortalOutlet></ng-template>\n<div class=\"arrow\"></div>\n", styles: [":host{position:relative;background:#fff;border-radius:8px;min-width:300px}.arrow{position:absolute;z-index:-1;width:20px;height:20px;top:-10px;left:24px;border-radius:4px;transform-origin:top left;transform:rotate(45deg)}\n"], dependencies: [{ kind: "ngmodule", type: PortalModule }, { kind: "directive", type: i1.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }], animations: [facetModalAnimations.modalContainer] });
|
|
443
|
+
}
|
|
444
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetModalComponent, decorators: [{
|
|
445
|
+
type: Component,
|
|
446
|
+
args: [{ selector: 'ngx-facet-modal', standalone: true, imports: [PortalModule], animations: [facetModalAnimations.modalContainer], template: "<ng-template cdkPortalOutlet></ng-template>\n<div class=\"arrow\"></div>\n", styles: [":host{position:relative;background:#fff;border-radius:8px;min-width:300px}.arrow{position:absolute;z-index:-1;width:20px;height:20px;top:-10px;left:24px;border-radius:4px;transform-origin:top left;transform:rotate(45deg)}\n"] }]
|
|
447
|
+
}], propDecorators: { portalOutlet: [{
|
|
448
|
+
type: ViewChild,
|
|
449
|
+
args: [CdkPortalOutlet, { static: true }]
|
|
450
|
+
}], hostClass: [{
|
|
451
|
+
type: HostBinding,
|
|
452
|
+
args: ['class']
|
|
453
|
+
}], animationState: [{
|
|
454
|
+
type: HostBinding,
|
|
455
|
+
args: ['@modalContainer']
|
|
456
|
+
}], _onAnimationDone: [{
|
|
457
|
+
type: HostListener,
|
|
458
|
+
args: ['@modalContainer.done', ['$event']]
|
|
459
|
+
}], _onAnimationStart: [{
|
|
460
|
+
type: HostListener,
|
|
461
|
+
args: ['@modalContainer.start', ['$event']]
|
|
462
|
+
}] } });
|
|
463
|
+
|
|
464
|
+
class FacetModalService {
|
|
465
|
+
overlay;
|
|
466
|
+
injector;
|
|
467
|
+
constructor(overlay, injector) {
|
|
468
|
+
this.overlay = overlay;
|
|
469
|
+
this.injector = injector;
|
|
470
|
+
}
|
|
471
|
+
open(component, target, config = {}) {
|
|
472
|
+
const facetModalConfig = Object.assign({}, DefaultFacetModalConfig, config);
|
|
473
|
+
const offsetY = facetModalConfig.offsetY || 0;
|
|
474
|
+
const offsetX = facetModalConfig.offsetX || 0;
|
|
475
|
+
const positionStrategy = this.overlay
|
|
476
|
+
.position()
|
|
477
|
+
.flexibleConnectedTo(target)
|
|
478
|
+
.withPush(false)
|
|
479
|
+
.withFlexibleDimensions(true)
|
|
480
|
+
.withPositions([
|
|
481
|
+
{
|
|
482
|
+
overlayX: 'start',
|
|
483
|
+
overlayY: 'top',
|
|
484
|
+
originX: 'start',
|
|
485
|
+
originY: 'center',
|
|
486
|
+
offsetX,
|
|
487
|
+
offsetY,
|
|
488
|
+
},
|
|
489
|
+
]);
|
|
490
|
+
const overlayRef = this.overlay.create({
|
|
491
|
+
hasBackdrop: facetModalConfig.hasBackdrop ?? true,
|
|
492
|
+
backdropClass: facetModalConfig.backdropClass,
|
|
493
|
+
panelClass: facetModalConfig.panelClass,
|
|
494
|
+
positionStrategy,
|
|
495
|
+
scrollStrategy: this.overlay.scrollStrategies.block()
|
|
496
|
+
});
|
|
497
|
+
if (facetModalConfig.width) {
|
|
498
|
+
overlayRef.updateSize({ width: facetModalConfig.width });
|
|
499
|
+
}
|
|
500
|
+
const modalRef = new FacetModalRef(overlayRef, positionStrategy, facetModalConfig);
|
|
501
|
+
const injector = Injector.create({
|
|
502
|
+
providers: [
|
|
503
|
+
{
|
|
504
|
+
provide: FACET_MODAL_DATA,
|
|
505
|
+
useValue: config.data
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
provide: FacetModalRef,
|
|
509
|
+
useValue: modalRef
|
|
510
|
+
},
|
|
511
|
+
],
|
|
512
|
+
parent: this.injector
|
|
513
|
+
});
|
|
514
|
+
const modal = overlayRef.attach(new ComponentPortal(FacetModalComponent, null, injector)).instance;
|
|
515
|
+
modal.attachComponentPortal(new ComponentPortal(component, null, injector));
|
|
516
|
+
return modalRef;
|
|
517
|
+
}
|
|
518
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetModalService, deps: [{ token: i1$1.Overlay }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
519
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetModalService, providedIn: 'root' });
|
|
520
|
+
}
|
|
521
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetModalService, decorators: [{
|
|
522
|
+
type: Injectable,
|
|
523
|
+
args: [{
|
|
524
|
+
providedIn: 'root'
|
|
525
|
+
}]
|
|
526
|
+
}], ctorParameters: () => [{ type: i1$1.Overlay }, { type: i0.Injector }] });
|
|
527
|
+
|
|
528
|
+
class VCRefInjector {
|
|
529
|
+
raw;
|
|
530
|
+
constructor(injector) {
|
|
531
|
+
this.raw = injector;
|
|
532
|
+
}
|
|
533
|
+
get parentIdentifier() {
|
|
534
|
+
const parent = this.parent;
|
|
535
|
+
if (!!parent) {
|
|
536
|
+
return parent.tagName.toLowerCase();
|
|
537
|
+
}
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
get parent() {
|
|
541
|
+
if (!!this.raw && this.raw._lView && this.raw._lView.length > 0) {
|
|
542
|
+
return this.raw._lView[0];
|
|
543
|
+
}
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const chipAnimation = [
|
|
549
|
+
trigger('chipAnimation', [
|
|
550
|
+
state('in', style({
|
|
551
|
+
transform: 'translateX(0)',
|
|
552
|
+
opacity: 0,
|
|
553
|
+
position: 'absolute'
|
|
554
|
+
})),
|
|
555
|
+
transition('void => *', [
|
|
556
|
+
style({
|
|
557
|
+
transform: 'translateX(-100%)',
|
|
558
|
+
opacity: 1,
|
|
559
|
+
position: '*'
|
|
560
|
+
}),
|
|
561
|
+
animate('200ms ease-out')
|
|
562
|
+
]),
|
|
563
|
+
transition('* => void', [
|
|
564
|
+
style({
|
|
565
|
+
position: 'absolute'
|
|
566
|
+
}),
|
|
567
|
+
animate('200ms ease-in', style({
|
|
568
|
+
transform: 'translateX(-100%)',
|
|
569
|
+
opacity: 0
|
|
570
|
+
}))
|
|
571
|
+
])
|
|
572
|
+
])
|
|
573
|
+
];
|
|
574
|
+
|
|
575
|
+
class FacetStorageService {
|
|
576
|
+
storageStrategy = 'session';
|
|
577
|
+
/**
|
|
578
|
+
* Update the loggingCallback function
|
|
579
|
+
*/
|
|
580
|
+
updateLoggingCallback(loggingCallback) {
|
|
581
|
+
this.loggingCallback = loggingCallback;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Saves the selected facets to localStorage for our current identifier
|
|
585
|
+
*/
|
|
586
|
+
updateSavedFacets(identifier, selectedFacets) {
|
|
587
|
+
if (!identifier) {
|
|
588
|
+
this.loggingCallback(`Cannot update ${this.mode}, no ID set`);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
if (this.storageStrategy === 'none') {
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
this.loggingCallback(`Saving facets in ${this.mode} for component with ID`, identifier);
|
|
595
|
+
this.storageBackend?.setItem(identifier, JSON.stringify(selectedFacets));
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Clears previously saved facets for this specific component
|
|
599
|
+
*/
|
|
600
|
+
clearStorage(identifier) {
|
|
601
|
+
if (!identifier) {
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
if (this.storageStrategy === 'none') {
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
this.loggingCallback(`Clearing ${this.mode} for ID`, identifier);
|
|
608
|
+
this.storageBackend?.removeItem(identifier);
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Loads facets from storage for our current identifier
|
|
612
|
+
*/
|
|
613
|
+
loadFacetsFromStorage(identifier) {
|
|
614
|
+
let sessionFacets = [];
|
|
615
|
+
if (this.storageStrategy === 'none') {
|
|
616
|
+
return [];
|
|
617
|
+
}
|
|
618
|
+
if (!!identifier && !this.checkStorage(identifier)) {
|
|
619
|
+
sessionFacets = JSON.parse(this.storageBackend?.getItem(identifier) || '[]');
|
|
620
|
+
sessionFacets = (sessionFacets || []);
|
|
621
|
+
this.loggingCallback('Loaded facets for component with ID', identifier, sessionFacets);
|
|
622
|
+
}
|
|
623
|
+
else if (!identifier) {
|
|
624
|
+
this.loggingCallback('No identifier set on this component');
|
|
625
|
+
}
|
|
626
|
+
else if (this.checkStorage(identifier)) {
|
|
627
|
+
this.loggingCallback(`No ${this.mode} variable set for component with ID`, identifier, localStorage.getItem(identifier));
|
|
628
|
+
}
|
|
629
|
+
return sessionFacets;
|
|
630
|
+
}
|
|
631
|
+
loggingCallback = () => {
|
|
632
|
+
};
|
|
633
|
+
updateStorageStrategy(strategy) {
|
|
634
|
+
this.storageStrategy = strategy;
|
|
635
|
+
}
|
|
636
|
+
get mode() {
|
|
637
|
+
if (this.storageStrategy === 'none') {
|
|
638
|
+
return 'none';
|
|
639
|
+
}
|
|
640
|
+
return (this.storageStrategy === 'local' ? 'localStorage' : 'sessionStorage');
|
|
641
|
+
}
|
|
642
|
+
checkStorage(key) {
|
|
643
|
+
return !this.storageBackend?.getItem(key);
|
|
644
|
+
}
|
|
645
|
+
get storageBackend() {
|
|
646
|
+
if (this.storageStrategy === 'none') {
|
|
647
|
+
return null;
|
|
648
|
+
}
|
|
649
|
+
return this.storageStrategy === 'local' ? localStorage : sessionStorage;
|
|
650
|
+
}
|
|
651
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
652
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetStorageService, providedIn: 'root' });
|
|
653
|
+
}
|
|
654
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FacetStorageService, decorators: [{
|
|
655
|
+
type: Injectable,
|
|
656
|
+
args: [{
|
|
657
|
+
providedIn: 'root'
|
|
658
|
+
}]
|
|
659
|
+
}] });
|
|
660
|
+
|
|
661
|
+
const FACET_TOOLKIT_CONFIG = new InjectionToken('Facet Toolkit Configuration', {
|
|
662
|
+
providedIn: 'root',
|
|
663
|
+
factory: () => DEFAULT_FACET_TOOLKIT_CONFIG
|
|
664
|
+
});
|
|
665
|
+
const provideFacetToolkitConfig = (config) => makeEnvironmentProviders([
|
|
666
|
+
{
|
|
667
|
+
provide: FACET_TOOLKIT_CONFIG,
|
|
668
|
+
useValue: {
|
|
669
|
+
...DEFAULT_FACET_TOOLKIT_CONFIG,
|
|
670
|
+
...config
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
]);
|
|
674
|
+
|
|
675
|
+
class CSVPipe {
|
|
676
|
+
transform(value, objectKeyName, separator) {
|
|
677
|
+
return value.map(e => objectKeyName ? e[objectKeyName] : e).join(separator || ',');
|
|
678
|
+
}
|
|
679
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CSVPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
680
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: CSVPipe, isStandalone: true, name: "csv", pure: false });
|
|
681
|
+
}
|
|
682
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CSVPipe, decorators: [{
|
|
683
|
+
type: Pipe,
|
|
684
|
+
args: [{
|
|
685
|
+
name: 'csv',
|
|
686
|
+
standalone: true,
|
|
687
|
+
pure: false
|
|
688
|
+
}]
|
|
689
|
+
}] });
|
|
690
|
+
|
|
691
|
+
class FilterPipe {
|
|
692
|
+
transform(objectArray, fieldName, fieldValue) {
|
|
693
|
+
return objectArray.filter(obj => obj[fieldName] === fieldValue);
|
|
694
|
+
}
|
|
695
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FilterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
696
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: FilterPipe, isStandalone: true, name: "filter", pure: false });
|
|
697
|
+
}
|
|
698
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FilterPipe, decorators: [{
|
|
699
|
+
type: Pipe,
|
|
700
|
+
args: [{
|
|
701
|
+
name: 'filter',
|
|
702
|
+
standalone: true,
|
|
703
|
+
pure: false
|
|
704
|
+
}]
|
|
705
|
+
}] });
|
|
706
|
+
|
|
707
|
+
class KeysPipe {
|
|
708
|
+
transform(value) {
|
|
709
|
+
return Object.keys(value).map(k => ({ key: k, value: k }));
|
|
710
|
+
}
|
|
711
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: KeysPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
712
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: KeysPipe, isStandalone: true, name: "keys", pure: false });
|
|
713
|
+
}
|
|
714
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: KeysPipe, decorators: [{
|
|
715
|
+
type: Pipe,
|
|
716
|
+
args: [{
|
|
717
|
+
name: 'keys',
|
|
718
|
+
standalone: true,
|
|
719
|
+
pure: false
|
|
720
|
+
}]
|
|
721
|
+
}] });
|
|
722
|
+
|
|
723
|
+
class NgxMatFacetToolkitComponent {
|
|
724
|
+
facets = input([]);
|
|
725
|
+
config = input({});
|
|
726
|
+
placeholder = input('Filter Table...');
|
|
727
|
+
clearButtonText = input('Clear Filters');
|
|
728
|
+
clearButtonEnabled = input(true);
|
|
729
|
+
dateFormat = input('M/d/yyyy');
|
|
730
|
+
tooltip = input(null);
|
|
731
|
+
displayFilterIcon = input(true);
|
|
732
|
+
facetWidth = input('400px');
|
|
733
|
+
facetHasBackdrop = input(true);
|
|
734
|
+
confirmOnRemove = input(true);
|
|
735
|
+
chipLabelsEnabled = input(true);
|
|
736
|
+
identifier = input(null);
|
|
737
|
+
facetChange = output();
|
|
738
|
+
facetRemoved = output();
|
|
739
|
+
facetReset = output();
|
|
740
|
+
filterInput;
|
|
741
|
+
inputAutoComplete;
|
|
742
|
+
FacetDataType = FacetDataType;
|
|
743
|
+
FacetFilterType = FacetFilterType;
|
|
744
|
+
selectedFacetId = signal(null);
|
|
745
|
+
filterText = signal('');
|
|
746
|
+
injectedConfig = inject(FACET_TOOLKIT_CONFIG);
|
|
747
|
+
storageService = inject(FacetStorageService);
|
|
748
|
+
modal = inject(FacetModalService);
|
|
749
|
+
vcRef = inject(ViewContainerRef);
|
|
750
|
+
identifierStrategy = signal(FacetIdentifierStrategy.ParentID);
|
|
751
|
+
resolvedIdentifier = signal(null);
|
|
752
|
+
allowDebugClick = signal(false);
|
|
753
|
+
loggingCallback = signal(() => { });
|
|
754
|
+
timeoutHandler = null;
|
|
755
|
+
injectorRef = new VCRefInjector(this.vcRef.injector);
|
|
756
|
+
selectedFacets = signal([]);
|
|
757
|
+
facetDefinitions = computed(() => this.facets() || []);
|
|
758
|
+
selectedFacetViews = computed(() => this.selectedFacets()
|
|
759
|
+
.map(selection => this.toEditorState(selection))
|
|
760
|
+
.filter((facet) => !!facet));
|
|
761
|
+
availableFacets = computed(() => {
|
|
762
|
+
const selectedIds = new Set(this.selectedFacets().map(selection => selection.id));
|
|
763
|
+
return this.facetDefinitions().filter(facet => !selectedIds.has(facet.id));
|
|
764
|
+
});
|
|
765
|
+
filteredFacets = computed(() => {
|
|
766
|
+
const filterText = this.filterText().toLowerCase();
|
|
767
|
+
if (!filterText) {
|
|
768
|
+
return this.availableFacets();
|
|
769
|
+
}
|
|
770
|
+
return this.availableFacets().filter(facet => facet.label.toLowerCase().includes(filterText));
|
|
771
|
+
});
|
|
772
|
+
constructor() {
|
|
773
|
+
effect(() => {
|
|
774
|
+
this.identifier();
|
|
775
|
+
const config = {
|
|
776
|
+
...DEFAULT_FACET_TOOLKIT_CONFIG,
|
|
777
|
+
...this.injectedConfig,
|
|
778
|
+
...this.config()
|
|
779
|
+
};
|
|
780
|
+
this.allowDebugClick.set(config.allowDebugClick);
|
|
781
|
+
this.identifierStrategy.set(config.identifierStrategy);
|
|
782
|
+
this.loggingCallback.set(config.loggingCallback);
|
|
783
|
+
this.storageService.updateLoggingCallback(config.loggingCallback);
|
|
784
|
+
this.storageService.updateStorageStrategy(config.storage);
|
|
785
|
+
this.resolveIdentity();
|
|
786
|
+
});
|
|
787
|
+
effect(() => {
|
|
788
|
+
const facets = this.facetDefinitions();
|
|
789
|
+
const identifier = this.resolvedIdentifier();
|
|
790
|
+
this.refreshSelectionsFromFacets(facets, identifier);
|
|
791
|
+
});
|
|
792
|
+
effect(() => {
|
|
793
|
+
const selections = this.selectedFacets();
|
|
794
|
+
this.facetChange.emit(selections);
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
static getFixedURL() {
|
|
798
|
+
return window.location.pathname.toString()
|
|
799
|
+
.replace(/\s+/g, '-')
|
|
800
|
+
.replace(/\//g, '-')
|
|
801
|
+
.replace(/^-/g, '')
|
|
802
|
+
.replace(/--/g, '-');
|
|
803
|
+
}
|
|
804
|
+
ngAfterViewInit() {
|
|
805
|
+
fromEvent(this.filterInput.nativeElement, 'keyup')
|
|
806
|
+
.pipe(filter(Boolean), debounceTime(150), distinctUntilChanged(), map(() => this.filterInput.nativeElement.value))
|
|
807
|
+
.subscribe((text) => {
|
|
808
|
+
this.filterText.set(text || '');
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
chipSelected(event, facet) {
|
|
812
|
+
if (event.selected && !facet.readonly) {
|
|
813
|
+
const elementRef = event.source._elementRef.nativeElement;
|
|
814
|
+
this.facetSelected(facet, {
|
|
815
|
+
top: (elementRef.clientHeight - 5),
|
|
816
|
+
left: -3,
|
|
817
|
+
}, true, elementRef);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
autoCompleteDisplay(_) {
|
|
821
|
+
return '';
|
|
822
|
+
}
|
|
823
|
+
autoCompleteSelected(event) {
|
|
824
|
+
const selectedFacet = event.option.value;
|
|
825
|
+
const parentElement = this.filterInput.nativeElement;
|
|
826
|
+
if (!!parentElement) {
|
|
827
|
+
const elementRef = parentElement.getBoundingClientRect();
|
|
828
|
+
const top = elementRef.height - 3;
|
|
829
|
+
const left = -38;
|
|
830
|
+
const editorState = this.toEditorState(this.toSelection(selectedFacet, [])) || {
|
|
831
|
+
...selectedFacet,
|
|
832
|
+
values: [],
|
|
833
|
+
options: this.normalizeOptions(selectedFacet.options)
|
|
834
|
+
};
|
|
835
|
+
this.facetSelected(editorState, { top, left }, false, this.filterInput);
|
|
836
|
+
this.filterInput.nativeElement.value = '';
|
|
837
|
+
this.filterText.set('');
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
facetSelected(facet, position, isUpdate, target) {
|
|
841
|
+
this.promptFacet({ ...facet }, position, isUpdate, target);
|
|
842
|
+
}
|
|
843
|
+
promptFacet(facet, position, isUpdate, target) {
|
|
844
|
+
const facetDetailsModal = this.modal.open(FacetDetailsModalComponent, target, {
|
|
845
|
+
data: facet,
|
|
846
|
+
offsetY: position.top,
|
|
847
|
+
offsetX: position.left,
|
|
848
|
+
isUpdate,
|
|
849
|
+
hasBackdrop: this.facetHasBackdrop(),
|
|
850
|
+
width: this.facetWidth()
|
|
851
|
+
});
|
|
852
|
+
facetDetailsModal.beforeClosed().subscribe(() => {
|
|
853
|
+
this.selectedFacetId.set(null);
|
|
854
|
+
});
|
|
855
|
+
facetDetailsModal.afterClosed().subscribe(result => {
|
|
856
|
+
if (result.type === FacetResultType.REMOVE && result.data) {
|
|
857
|
+
this.removeFacet(result.data);
|
|
858
|
+
}
|
|
859
|
+
else if (result.type === FacetResultType.ADD && result.data) {
|
|
860
|
+
this.addOrUpdateFacet(result.data);
|
|
861
|
+
}
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
addOrUpdateFacet(facet) {
|
|
865
|
+
const selection = this.toSelection(facet, facet.values, facet.filterType);
|
|
866
|
+
const nextSelections = this.selectedFacets()
|
|
867
|
+
.filter(existing => existing.id !== selection.id)
|
|
868
|
+
.concat(selection);
|
|
869
|
+
this.selectedFacets.set(nextSelections);
|
|
870
|
+
this.storageService.updateSavedFacets(this.resolvedIdentifier(), nextSelections);
|
|
871
|
+
}
|
|
872
|
+
removeFacet(facet) {
|
|
873
|
+
if (!this.confirmOnRemove() || (this.confirmOnRemove() && confirm(`Do you really want to remove "${facet.label}" filter?`))) {
|
|
874
|
+
const updatedSelections = this.selectedFacets().filter(selection => selection.id !== facet.id);
|
|
875
|
+
this.selectedFacets.set(updatedSelections);
|
|
876
|
+
this.storageService.updateSavedFacets(this.resolvedIdentifier(), updatedSelections);
|
|
877
|
+
this.facetRemoved.emit(this.toSelection(facet, facet.values, facet.filterType));
|
|
878
|
+
return true;
|
|
879
|
+
}
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
882
|
+
reset() {
|
|
883
|
+
const readonlySelections = this.facetDefinitions()
|
|
884
|
+
.filter(facet => facet.readonly && (facet.defaultValues || []).length > 0)
|
|
885
|
+
.map(facet => this.toSelection(facet, facet.defaultValues || []));
|
|
886
|
+
this.selectedFacets.set(readonlySelections);
|
|
887
|
+
this.storageService.clearStorage(this.resolvedIdentifier());
|
|
888
|
+
this.facetReset.emit();
|
|
889
|
+
}
|
|
890
|
+
focus(event) {
|
|
891
|
+
event.stopPropagation();
|
|
892
|
+
this.inputAutoComplete.openPanel();
|
|
893
|
+
}
|
|
894
|
+
getValue(facet, offset) {
|
|
895
|
+
if (!!facet?.values?.length && facet.values[offset || 0]?.value !== undefined) {
|
|
896
|
+
return facet.values[offset || 0];
|
|
897
|
+
}
|
|
898
|
+
return null;
|
|
899
|
+
}
|
|
900
|
+
getRawValue(facet, offset) {
|
|
901
|
+
const value = this.getValue(facet, offset);
|
|
902
|
+
return value ? value.value : null;
|
|
903
|
+
}
|
|
904
|
+
getDateValue(facet, offset) {
|
|
905
|
+
const value = this.getRawValue(facet, offset);
|
|
906
|
+
if (value instanceof Date || typeof value === 'string' || typeof value === 'number') {
|
|
907
|
+
return value;
|
|
908
|
+
}
|
|
909
|
+
return null;
|
|
910
|
+
}
|
|
911
|
+
setValue(facet, newValue, offset) {
|
|
912
|
+
if (!!facet?.values?.length && facet.values[offset || 0]) {
|
|
913
|
+
facet.values[offset || 0] = {
|
|
914
|
+
...facet.values[offset || 0],
|
|
915
|
+
value: newValue
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
identify(identifier) {
|
|
920
|
+
this.loggingCallback()(`Identifying facet with ID: ${identifier}`);
|
|
921
|
+
if (!identifier || identifier.length === 0 || identifier === '-') {
|
|
922
|
+
this.resolvedIdentifier.set('default-facet');
|
|
923
|
+
}
|
|
924
|
+
else {
|
|
925
|
+
this.resolvedIdentifier.set(`${identifier}-facet`);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
getIdentifierStrategy() {
|
|
929
|
+
return this.identifierStrategy();
|
|
930
|
+
}
|
|
931
|
+
printIdentity() {
|
|
932
|
+
console.log(this.resolvedIdentifier());
|
|
933
|
+
}
|
|
934
|
+
clickStarted() {
|
|
935
|
+
if (!this.allowDebugClick()) {
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
this.timeoutHandler = setTimeout(() => {
|
|
939
|
+
this.printIdentity();
|
|
940
|
+
this.timeoutHandler = null;
|
|
941
|
+
}, 1000);
|
|
942
|
+
}
|
|
943
|
+
clickEnded() {
|
|
944
|
+
if (this.timeoutHandler) {
|
|
945
|
+
clearTimeout(this.timeoutHandler);
|
|
946
|
+
this.timeoutHandler = null;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
resolveIdentity(manual) {
|
|
950
|
+
const identifierInput = manual ?? this.identifier();
|
|
951
|
+
let identity;
|
|
952
|
+
this.loggingCallback()('Generating ID with strategy', this.identifierStrategy());
|
|
953
|
+
switch (this.identifierStrategy()) {
|
|
954
|
+
case FacetIdentifierStrategy.WindowURL:
|
|
955
|
+
identity = NgxMatFacetToolkitComponent.getFixedURL();
|
|
956
|
+
break;
|
|
957
|
+
case FacetIdentifierStrategy.ParentID:
|
|
958
|
+
identity = this.injectorRef.parentIdentifier;
|
|
959
|
+
break;
|
|
960
|
+
case FacetIdentifierStrategy.Random:
|
|
961
|
+
identity = v4();
|
|
962
|
+
break;
|
|
963
|
+
default:
|
|
964
|
+
identity = identifierInput;
|
|
965
|
+
break;
|
|
966
|
+
}
|
|
967
|
+
this.identify(identity);
|
|
968
|
+
}
|
|
969
|
+
refreshSelectionsFromFacets(facets, identifier) {
|
|
970
|
+
if (!facets.length) {
|
|
971
|
+
this.selectedFacets.set([]);
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
const storedSelections = this.storageService.loadFacetsFromStorage(identifier);
|
|
975
|
+
const storedById = new Map(storedSelections.map(selection => [selection.id, selection]));
|
|
976
|
+
const nextSelections = facets
|
|
977
|
+
.map(facet => {
|
|
978
|
+
const stored = storedById.get(facet.id);
|
|
979
|
+
if (stored) {
|
|
980
|
+
return stored;
|
|
981
|
+
}
|
|
982
|
+
if (facet.defaultValues && facet.defaultValues.length > 0) {
|
|
983
|
+
return this.toSelection(facet, facet.defaultValues);
|
|
984
|
+
}
|
|
985
|
+
return null;
|
|
986
|
+
})
|
|
987
|
+
.filter((selection) => !!selection);
|
|
988
|
+
this.selectedFacets.set(nextSelections);
|
|
989
|
+
}
|
|
990
|
+
toSelection(facet, values, filterType) {
|
|
991
|
+
return {
|
|
992
|
+
id: facet.id,
|
|
993
|
+
type: facet.type,
|
|
994
|
+
filterType: this.resolveFilterType(facet, filterType),
|
|
995
|
+
values: values || []
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
resolveFilterType(facet, filterType) {
|
|
999
|
+
if (filterType) {
|
|
1000
|
+
return filterType;
|
|
1001
|
+
}
|
|
1002
|
+
if (facet.fixedFilterType) {
|
|
1003
|
+
return facet.fixedFilterType;
|
|
1004
|
+
}
|
|
1005
|
+
switch (facet.type) {
|
|
1006
|
+
case FacetDataType.Date:
|
|
1007
|
+
case FacetDataType.Boolean:
|
|
1008
|
+
return FacetFilterType.equal;
|
|
1009
|
+
case FacetDataType.DateRange:
|
|
1010
|
+
return FacetFilterType.between;
|
|
1011
|
+
case FacetDataType.CategorySingle:
|
|
1012
|
+
case FacetDataType.TypeaheadSingle:
|
|
1013
|
+
return FacetFilterType.equal;
|
|
1014
|
+
case FacetDataType.Text:
|
|
1015
|
+
case FacetDataType.Category:
|
|
1016
|
+
case FacetDataType.Typeahead:
|
|
1017
|
+
default:
|
|
1018
|
+
return FacetFilterType.contains;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
toEditorState(selection) {
|
|
1022
|
+
const facet = this.facetDefinitions().find(definition => definition.id === selection.id);
|
|
1023
|
+
if (!facet) {
|
|
1024
|
+
return null;
|
|
1025
|
+
}
|
|
1026
|
+
return {
|
|
1027
|
+
...facet,
|
|
1028
|
+
values: selection.values,
|
|
1029
|
+
filterType: selection.filterType,
|
|
1030
|
+
options: this.normalizeOptions(facet.options)
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
normalizeOptions(options) {
|
|
1034
|
+
if (!options) {
|
|
1035
|
+
return undefined;
|
|
1036
|
+
}
|
|
1037
|
+
return isObservable(options) ? options : of(options);
|
|
1038
|
+
}
|
|
1039
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: NgxMatFacetToolkitComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1040
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: NgxMatFacetToolkitComponent, isStandalone: true, selector: "ngx-mat-facet-toolkit", inputs: { facets: { classPropertyName: "facets", publicName: "facets", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, clearButtonText: { classPropertyName: "clearButtonText", publicName: "clearButtonText", isSignal: true, isRequired: false, transformFunction: null }, clearButtonEnabled: { classPropertyName: "clearButtonEnabled", publicName: "clearButtonEnabled", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null }, displayFilterIcon: { classPropertyName: "displayFilterIcon", publicName: "displayFilterIcon", isSignal: true, isRequired: false, transformFunction: null }, facetWidth: { classPropertyName: "facetWidth", publicName: "facetWidth", isSignal: true, isRequired: false, transformFunction: null }, facetHasBackdrop: { classPropertyName: "facetHasBackdrop", publicName: "facetHasBackdrop", isSignal: true, isRequired: false, transformFunction: null }, confirmOnRemove: { classPropertyName: "confirmOnRemove", publicName: "confirmOnRemove", isSignal: true, isRequired: false, transformFunction: null }, chipLabelsEnabled: { classPropertyName: "chipLabelsEnabled", publicName: "chipLabelsEnabled", isSignal: true, isRequired: false, transformFunction: null }, identifier: { classPropertyName: "identifier", publicName: "identifier", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { facetChange: "facetChange", facetRemoved: "facetRemoved", facetReset: "facetReset" }, viewQueries: [{ propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }, { propertyName: "inputAutoComplete", first: true, predicate: MatAutocompleteTrigger, descendants: true, read: MatAutocompleteTrigger }], ngImport: i0, template: "<div class=\"main-facet-wrapper\">\n\n @if (displayFilterIcon()) {\n <div class=\"icon-wrapper\">\n @if (tooltip() !== null) {\n <mat-icon class=\"filter-list-icon\" (mousedown)=\"clickStarted()\" (mouseup)=\"clickEnded()\" (mouseleave)=\"clickEnded()\" [matTooltip]=\"tooltip()\">filter_list</mat-icon>\n } @else {\n <mat-icon class=\"filter-list-icon\" (mousedown)=\"clickStarted()\" (mouseup)=\"clickEnded()\" (mouseleave)=\"clickEnded()\">filter_list</mat-icon>\n }\n </div>\n }\n\n <div class=\"content-wrapper\">\n\n <mat-chip-grid #chipList>\n\n @for (facet of selectedFacetViews(); track facet.id) {\n <mat-chip-option @chipAnimation [color]=\"facet.readonly ? 'accent' : undefined\"\n class=\"facet-chip\"\n (selectionChange)=\"chipSelected($event, facet)\" (click)=\"selectedFacetId.set(facet.id)\"\n [selected]=\"facet.id === selectedFacetId()\"\n matTooltip=\"{{facet.label + (facet.description ? ': ' + facet.description : '')}}\"\n matTooltipShowDelay=\"1000\">\n <span class=\"flex-facet\">\n\n @if (facet.icon) {\n <mat-icon class=\"inline-chip-icon\">{{facet.icon}}</mat-icon>\n }\n\n @if (chipLabelsEnabled()) {\n <span>{{ facet.label + ': '}}</span>\n }\n\n @switch (facet.type) {\n @case (FacetDataType.Category) {\n {{facet.values | csv:'label':' / '}}\n }\n @case (FacetDataType.CategorySingle) {\n {{facet.values | csv:'label':' / '}}\n }\n @case (FacetDataType.Typeahead) {\n {{facet.values | csv:'label':' / '}}\n }\n @case (FacetDataType.TypeaheadSingle) {\n {{facet.values | csv:'label':' / '}}\n }\n @case (FacetDataType.Date) {\n \u201C{{getDateValue(facet) | date:dateFormat()}}\u201D\n }\n @case (FacetDataType.DateRange) {\n \u201C{{getDateValue(facet) | date:dateFormat()}}\u201D ~ \u201C{{getDateValue(facet, 1) | date:dateFormat()}}\u201D\n }\n @case (FacetDataType.Boolean) {\n <mat-checkbox [disabled]=\"true\" class=\"inline-chip-checkbox\" [ngModel]=\"getRawValue(facet)\" (ngModelChange)=\"setValue(facet, $event)\">\n {{facet.label}}\n </mat-checkbox>\n }\n @case (FacetDataType.Text) {\n @switch (facet.filterType) {\n @case (FacetFilterType.contains) {\n \u201C..{{getRawValue(facet)}}..\u201D\n }\n @case (FacetFilterType.equal) {\n \u201C{{getRawValue(facet)}}\u201D\n }\n @case (FacetFilterType.startsWith) {\n \u201C{{getRawValue(facet)}}...\u201D\n }\n @case (FacetFilterType.endsWith) {\n \u201C...{{getRawValue(facet)}}\u201D\n }\n }\n }\n }\n\n @if (!facet.readonly) {\n <mat-icon matChipRemove (click)=\"removeFacet(facet)\">cancel</mat-icon>\n }\n\n </span>\n\n </mat-chip-option>\n }\n\n <mat-chip-row class=\"filter-input-container\" disableRipple=\"true\" disabled=\"true\" @chipAnimation>\n\n <span class=\"flex-facet-autocomplete\">\n\n <mat-icon class=\"add-icon\" (click)=\"focus($event)\">add</mat-icon>\n\n <input #filterInput [matChipInputFor]=\"chipList\" class=\"filter-input\" [placeholder]=\"placeholder()\"\n [matChipInputAddOnBlur]=\"false\" [matAutocomplete]=\"auto\">\n\n <mat-autocomplete #auto=\"matAutocomplete\" class=\"mat-facet-autocomplete\" (optionSelected)=\"autoCompleteSelected($event)\"\n [displayWith]=\"autoCompleteDisplay\" panelWidth=\"250px\">\n @for (facet of filteredFacets(); track facet.id) {\n <mat-option [value]=\"facet\">\n @if (facet.icon) {\n <mat-icon>{{facet.icon}}</mat-icon>\n }\n <span>{{ facet.label }}</span>\n </mat-option>\n }\n </mat-autocomplete>\n\n </span>\n\n </mat-chip-row>\n\n </mat-chip-grid>\n\n </div>\n\n\n @if (clearButtonEnabled() && selectedFacets().length > 0) {\n <button mat-flat-button (click)=\"reset()\" color=\"accent\">\n {{clearButtonText()}}\n </button>\n }\n\n</div>\n", styles: ["*{outline:0}.filter-input-container{background-color:transparent!important;opacity:1!important;box-shadow:none!important}.filter-input-container .filter-input{border:none!important;background:none!important;width:85px;font-size:14px!important;font-weight:400;text-align:right;position:relative;top:-7px;margin-left:2px}::placeholder{color:#000000db;opacity:1}.inline-chip-icon{width:18px;height:18px;font-size:18px;margin-right:7px;margin-left:0}:host-context .mat-checkbox-inner-container{transform:scale(.7)}:host-context(.inlineChipCheckbox) label.mat-checkbox-layout div.mat-checkbox-inner-container{transform:scale(.7)}.add-icon{margin-top:8px}.add-icon:hover,.filter-input-container:hover{cursor:pointer}.main-facet-wrapper{min-height:36px;display:flex;align-items:center}.main-facet-wrapper .icon-wrapper{height:100%;display:flex;justify-content:center;align-items:center;margin-right:20px}::ng-deep .mat-autocomplete-panel.mat-autocomplete-visible{left:-40px!important;top:15px!important}::ng-deep .mat-chip-list-wrapper{transition:width .3s ease-in-out}.content-wrapper{flex:1}.flex-facet{display:flex;align-items:center}.flex-facet-autocomplete{justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2.DatePipe, name: "date" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: i15.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i14.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: MatInputModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i7$1.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i7$1.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "component", type: i7$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: i7$1.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i7$1.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i9$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i9$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "ngmodule", type: OverlayModule }, { kind: "ngmodule", type: PortalModule }, { kind: "pipe", type: CSVPipe, name: "csv" }], animations: [
|
|
1041
|
+
chipAnimation
|
|
1042
|
+
] });
|
|
1043
|
+
}
|
|
1044
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: NgxMatFacetToolkitComponent, decorators: [{
|
|
1045
|
+
type: Component,
|
|
1046
|
+
args: [{ selector: 'ngx-mat-facet-toolkit', standalone: true, imports: [
|
|
1047
|
+
A11yModule,
|
|
1048
|
+
CommonModule,
|
|
1049
|
+
FormsModule,
|
|
1050
|
+
ReactiveFormsModule,
|
|
1051
|
+
MatIconModule,
|
|
1052
|
+
MatToolbarModule,
|
|
1053
|
+
MatProgressBarModule,
|
|
1054
|
+
MatListModule,
|
|
1055
|
+
MatFormFieldModule,
|
|
1056
|
+
MatDatepickerModule,
|
|
1057
|
+
MatOptionModule,
|
|
1058
|
+
MatSelectModule,
|
|
1059
|
+
MatButtonModule,
|
|
1060
|
+
MatCheckboxModule,
|
|
1061
|
+
MatInputModule,
|
|
1062
|
+
MatChipsModule,
|
|
1063
|
+
MatTooltipModule,
|
|
1064
|
+
MatAutocompleteModule,
|
|
1065
|
+
MatNativeDateModule,
|
|
1066
|
+
MatProgressSpinnerModule,
|
|
1067
|
+
OverlayModule,
|
|
1068
|
+
PortalModule,
|
|
1069
|
+
CSVPipe,
|
|
1070
|
+
FilterPipe,
|
|
1071
|
+
KeysPipe,
|
|
1072
|
+
FocusOnShowDirective
|
|
1073
|
+
], animations: [
|
|
1074
|
+
chipAnimation
|
|
1075
|
+
], template: "<div class=\"main-facet-wrapper\">\n\n @if (displayFilterIcon()) {\n <div class=\"icon-wrapper\">\n @if (tooltip() !== null) {\n <mat-icon class=\"filter-list-icon\" (mousedown)=\"clickStarted()\" (mouseup)=\"clickEnded()\" (mouseleave)=\"clickEnded()\" [matTooltip]=\"tooltip()\">filter_list</mat-icon>\n } @else {\n <mat-icon class=\"filter-list-icon\" (mousedown)=\"clickStarted()\" (mouseup)=\"clickEnded()\" (mouseleave)=\"clickEnded()\">filter_list</mat-icon>\n }\n </div>\n }\n\n <div class=\"content-wrapper\">\n\n <mat-chip-grid #chipList>\n\n @for (facet of selectedFacetViews(); track facet.id) {\n <mat-chip-option @chipAnimation [color]=\"facet.readonly ? 'accent' : undefined\"\n class=\"facet-chip\"\n (selectionChange)=\"chipSelected($event, facet)\" (click)=\"selectedFacetId.set(facet.id)\"\n [selected]=\"facet.id === selectedFacetId()\"\n matTooltip=\"{{facet.label + (facet.description ? ': ' + facet.description : '')}}\"\n matTooltipShowDelay=\"1000\">\n <span class=\"flex-facet\">\n\n @if (facet.icon) {\n <mat-icon class=\"inline-chip-icon\">{{facet.icon}}</mat-icon>\n }\n\n @if (chipLabelsEnabled()) {\n <span>{{ facet.label + ': '}}</span>\n }\n\n @switch (facet.type) {\n @case (FacetDataType.Category) {\n {{facet.values | csv:'label':' / '}}\n }\n @case (FacetDataType.CategorySingle) {\n {{facet.values | csv:'label':' / '}}\n }\n @case (FacetDataType.Typeahead) {\n {{facet.values | csv:'label':' / '}}\n }\n @case (FacetDataType.TypeaheadSingle) {\n {{facet.values | csv:'label':' / '}}\n }\n @case (FacetDataType.Date) {\n \u201C{{getDateValue(facet) | date:dateFormat()}}\u201D\n }\n @case (FacetDataType.DateRange) {\n \u201C{{getDateValue(facet) | date:dateFormat()}}\u201D ~ \u201C{{getDateValue(facet, 1) | date:dateFormat()}}\u201D\n }\n @case (FacetDataType.Boolean) {\n <mat-checkbox [disabled]=\"true\" class=\"inline-chip-checkbox\" [ngModel]=\"getRawValue(facet)\" (ngModelChange)=\"setValue(facet, $event)\">\n {{facet.label}}\n </mat-checkbox>\n }\n @case (FacetDataType.Text) {\n @switch (facet.filterType) {\n @case (FacetFilterType.contains) {\n \u201C..{{getRawValue(facet)}}..\u201D\n }\n @case (FacetFilterType.equal) {\n \u201C{{getRawValue(facet)}}\u201D\n }\n @case (FacetFilterType.startsWith) {\n \u201C{{getRawValue(facet)}}...\u201D\n }\n @case (FacetFilterType.endsWith) {\n \u201C...{{getRawValue(facet)}}\u201D\n }\n }\n }\n }\n\n @if (!facet.readonly) {\n <mat-icon matChipRemove (click)=\"removeFacet(facet)\">cancel</mat-icon>\n }\n\n </span>\n\n </mat-chip-option>\n }\n\n <mat-chip-row class=\"filter-input-container\" disableRipple=\"true\" disabled=\"true\" @chipAnimation>\n\n <span class=\"flex-facet-autocomplete\">\n\n <mat-icon class=\"add-icon\" (click)=\"focus($event)\">add</mat-icon>\n\n <input #filterInput [matChipInputFor]=\"chipList\" class=\"filter-input\" [placeholder]=\"placeholder()\"\n [matChipInputAddOnBlur]=\"false\" [matAutocomplete]=\"auto\">\n\n <mat-autocomplete #auto=\"matAutocomplete\" class=\"mat-facet-autocomplete\" (optionSelected)=\"autoCompleteSelected($event)\"\n [displayWith]=\"autoCompleteDisplay\" panelWidth=\"250px\">\n @for (facet of filteredFacets(); track facet.id) {\n <mat-option [value]=\"facet\">\n @if (facet.icon) {\n <mat-icon>{{facet.icon}}</mat-icon>\n }\n <span>{{ facet.label }}</span>\n </mat-option>\n }\n </mat-autocomplete>\n\n </span>\n\n </mat-chip-row>\n\n </mat-chip-grid>\n\n </div>\n\n\n @if (clearButtonEnabled() && selectedFacets().length > 0) {\n <button mat-flat-button (click)=\"reset()\" color=\"accent\">\n {{clearButtonText()}}\n </button>\n }\n\n</div>\n", styles: ["*{outline:0}.filter-input-container{background-color:transparent!important;opacity:1!important;box-shadow:none!important}.filter-input-container .filter-input{border:none!important;background:none!important;width:85px;font-size:14px!important;font-weight:400;text-align:right;position:relative;top:-7px;margin-left:2px}::placeholder{color:#000000db;opacity:1}.inline-chip-icon{width:18px;height:18px;font-size:18px;margin-right:7px;margin-left:0}:host-context .mat-checkbox-inner-container{transform:scale(.7)}:host-context(.inlineChipCheckbox) label.mat-checkbox-layout div.mat-checkbox-inner-container{transform:scale(.7)}.add-icon{margin-top:8px}.add-icon:hover,.filter-input-container:hover{cursor:pointer}.main-facet-wrapper{min-height:36px;display:flex;align-items:center}.main-facet-wrapper .icon-wrapper{height:100%;display:flex;justify-content:center;align-items:center;margin-right:20px}::ng-deep .mat-autocomplete-panel.mat-autocomplete-visible{left:-40px!important;top:15px!important}::ng-deep .mat-chip-list-wrapper{transition:width .3s ease-in-out}.content-wrapper{flex:1}.flex-facet{display:flex;align-items:center}.flex-facet-autocomplete{justify-content:center}\n"] }]
|
|
1076
|
+
}], ctorParameters: () => [], propDecorators: { filterInput: [{
|
|
1077
|
+
type: ViewChild,
|
|
1078
|
+
args: ['filterInput']
|
|
1079
|
+
}], inputAutoComplete: [{
|
|
1080
|
+
type: ViewChild,
|
|
1081
|
+
args: [MatAutocompleteTrigger, { read: MatAutocompleteTrigger }]
|
|
1082
|
+
}] } });
|
|
1083
|
+
|
|
1084
|
+
/*
|
|
1085
|
+
* Public API Surface of ngx-mat-facet-toolkit
|
|
1086
|
+
*/
|
|
1087
|
+
|
|
1088
|
+
/**
|
|
1089
|
+
* Generated bundle index. Do not edit.
|
|
1090
|
+
*/
|
|
1091
|
+
|
|
1092
|
+
export { DEFAULT_FACET_TOOLKIT_CONFIG, FACET_TOOLKIT_CONFIG, FacetDataType, FacetFilterType, FacetIdentifierStrategy, NgxMatFacetToolkitComponent, provideFacetToolkitConfig };
|
|
1093
|
+
//# sourceMappingURL=drsutphin-ngx-mat-facet-toolkit.mjs.map
|