@firestitch/filter 18.2.39 → 18.2.41

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.
@@ -1548,6 +1548,83 @@ class DateTimeItem extends BaseDateItem {
1548
1548
  }
1549
1549
  }
1550
1550
 
1551
+ class TextItem extends BaseItem {
1552
+ _additionalConfig;
1553
+ _filter;
1554
+ constructor(itemConfig, _additionalConfig, _filter) {
1555
+ super(itemConfig, _additionalConfig, _filter);
1556
+ this._additionalConfig = _additionalConfig;
1557
+ this._filter = _filter;
1558
+ this.prefix = itemConfig.prefix;
1559
+ this.suffix = itemConfig.suffix;
1560
+ }
1561
+ static create(config, filter) {
1562
+ return new TextItem(config, null, filter);
1563
+ }
1564
+ get hasValue() {
1565
+ return typeof this.value === 'string' && this.value.length > 0;
1566
+ }
1567
+ get query() {
1568
+ if (!this.hasValue) {
1569
+ return {};
1570
+ }
1571
+ const value = this.value;
1572
+ const name = this.name;
1573
+ const params = {};
1574
+ params[name] = value;
1575
+ return params;
1576
+ }
1577
+ get chips() {
1578
+ if (!this.hasValue || this.isTypeKeyword) {
1579
+ return [];
1580
+ }
1581
+ return [
1582
+ {
1583
+ value: this.value,
1584
+ label: this.label,
1585
+ },
1586
+ ];
1587
+ }
1588
+ }
1589
+
1590
+ class KeywordItem extends TextItem {
1591
+ _additionalConfig;
1592
+ _filter;
1593
+ constructor(itemConfig, _additionalConfig, _filter) {
1594
+ super(itemConfig, _additionalConfig, _filter);
1595
+ this._additionalConfig = _additionalConfig;
1596
+ this._filter = _filter;
1597
+ this.fullWidth = itemConfig.fullWidth;
1598
+ }
1599
+ static create(config, filter) {
1600
+ return new KeywordItem(config, null, filter);
1601
+ }
1602
+ get hasValue() {
1603
+ return typeof this.value === 'string' && this.value.length > 0;
1604
+ }
1605
+ get query() {
1606
+ if (!this.hasValue) {
1607
+ return {};
1608
+ }
1609
+ const value = this.value;
1610
+ const name = this.name;
1611
+ const params = {};
1612
+ params[name] = value;
1613
+ return params;
1614
+ }
1615
+ get chips() {
1616
+ if (!this.hasValue || this.isTypeKeyword) {
1617
+ return [];
1618
+ }
1619
+ return [
1620
+ {
1621
+ value: this.value,
1622
+ label: this.label,
1623
+ },
1624
+ ];
1625
+ }
1626
+ }
1627
+
1551
1628
  class SelectItem extends BaseItem {
1552
1629
  _additionalConfig;
1553
1630
  _filter;
@@ -1653,45 +1730,6 @@ class SelectItem extends BaseItem {
1653
1730
  }
1654
1731
  }
1655
1732
 
1656
- class TextItem extends BaseItem {
1657
- _additionalConfig;
1658
- _filter;
1659
- constructor(itemConfig, _additionalConfig, _filter) {
1660
- super(itemConfig, _additionalConfig, _filter);
1661
- this._additionalConfig = _additionalConfig;
1662
- this._filter = _filter;
1663
- this.prefix = itemConfig.prefix;
1664
- this.suffix = itemConfig.suffix;
1665
- }
1666
- static create(config, filter) {
1667
- return new TextItem(config, null, filter);
1668
- }
1669
- get hasValue() {
1670
- return typeof this.value === 'string' && this.value.length > 0;
1671
- }
1672
- get query() {
1673
- if (!this.hasValue) {
1674
- return {};
1675
- }
1676
- const value = this.value;
1677
- const name = this.name;
1678
- const params = {};
1679
- params[name] = value;
1680
- return params;
1681
- }
1682
- get chips() {
1683
- if (!this.hasValue || this.isTypeKeyword) {
1684
- return [];
1685
- }
1686
- return [
1687
- {
1688
- value: this.value,
1689
- label: this.label,
1690
- },
1691
- ];
1692
- }
1693
- }
1694
-
1695
1733
  function createFilterItem(item, config, filter) {
1696
1734
  switch (item.type) {
1697
1735
  case ItemType.Select: {
@@ -1727,7 +1765,9 @@ function createFilterItem(item, config, filter) {
1727
1765
  case ItemType.Checkbox: {
1728
1766
  return new CheckboxItem(item, null, filter);
1729
1767
  }
1730
- case ItemType.Keyword:
1768
+ case ItemType.Keyword: {
1769
+ return KeywordItem.create(item, filter);
1770
+ }
1731
1771
  case ItemType.Text: {
1732
1772
  return TextItem.create(item, filter);
1733
1773
  }
@@ -1737,19 +1777,25 @@ function createFilterItem(item, config, filter) {
1737
1777
  class KeywordController {
1738
1778
  _keywordItem$ = new BehaviorSubject(null);
1739
1779
  _keywordVisible$ = new BehaviorSubject(null);
1780
+ _keywordFullWidth$ = new BehaviorSubject(null);
1740
1781
  _destroyRef = inject(DestroyRef);
1741
- _filterController;
1742
- init(filterController) {
1743
- this._filterController = filterController;
1782
+ init() {
1744
1783
  this._keywordItem$
1745
1784
  .pipe(
1746
1785
  // when item changes, unsubscribe from the previous visible$
1747
1786
  switchMap$1((item) => item ? item.visible$ : of(false)),
1748
1787
  // avoid redundant writes
1749
- distinctUntilChanged$1(),
1788
+ distinctUntilChanged$1(), tap$1((visible) => this._keywordVisible$.next(visible)),
1750
1789
  // clean up on destroy,
1751
1790
  takeUntilDestroyed(this._destroyRef))
1752
- .subscribe((visible) => this._keywordVisible$.next(visible));
1791
+ .subscribe();
1792
+ this._keywordItem$
1793
+ .pipe(map$1((item) => !!item?.fullWidth),
1794
+ // avoid redundant writes
1795
+ distinctUntilChanged$1(), tap$1((fullWidth) => this._keywordFullWidth$.next(fullWidth)),
1796
+ // clean up on destroy,
1797
+ takeUntilDestroyed(this._destroyRef))
1798
+ .subscribe();
1753
1799
  }
1754
1800
  get keywordItem$() {
1755
1801
  return this._keywordItem$.asObservable();
@@ -1772,6 +1818,9 @@ class KeywordController {
1772
1818
  get keywordVisible$() {
1773
1819
  return this._keywordVisible$.asObservable();
1774
1820
  }
1821
+ get keywordFullWidth$() {
1822
+ return this._keywordFullWidth$.asObservable();
1823
+ }
1775
1824
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: KeywordController, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1776
1825
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: KeywordController });
1777
1826
  }
@@ -2025,7 +2074,7 @@ class FilterController {
2025
2074
  init(config) {
2026
2075
  this._config = config;
2027
2076
  of(null)
2028
- .pipe(tap(() => this._addItems(this._config.items || [])), tap(() => this._keywordController.init(this)), tap(() => this._sortController.init(this)), switchMap(() => forkJoin({
2077
+ .pipe(tap(() => this._addItems(this._config.items || [])), tap(() => this._keywordController.init()), tap(() => this._sortController.init(this)), switchMap(() => forkJoin({
2029
2078
  savedFilters: this._savedFilterController.init(this),
2030
2079
  persistance: this._persistanceController.init(this),
2031
2080
  queryParams: this._queryParamController.init(this),
@@ -2142,7 +2191,7 @@ class FilterController {
2142
2191
  })
2143
2192
  .map((item) => {
2144
2193
  const filterItem = createFilterItem(item, {}, this.filter);
2145
- if (filterItem.type === ItemType.Keyword) {
2194
+ if (filterItem instanceof KeywordItem) {
2146
2195
  this._keywordController.keywordItem = filterItem;
2147
2196
  }
2148
2197
  this._items.set(item.name, filterItem);
@@ -2213,14 +2262,14 @@ class FsFilterChipsComponent {
2213
2262
  item.clear(chip.name);
2214
2263
  }
2215
2264
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FsFilterChipsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2216
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: FsFilterChipsComponent, isStandalone: true, selector: "fs-filter-chips", ngImport: i0, template: "@for (item of items; track item.name) {\n @for (chip of item.chips$ | async; track chip.label) {\n <fs-chip\n [removable]=\"item.clearable\"\n size=\"small\"\n (click)=\"click(item, chip)\"\n (removed)=\"remove(item, chip)\">\n {{ chip.value ? chip.label + ': ' + chip.value : chip.label }}\n </fs-chip>\n }\n}", styles: [":host{display:flex;flex-wrap:wrap;column-gap:4px}fs-chip{margin-top:4px}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "ngmodule", type: FsChipModule }, { kind: "component", type: i1$2.FsChipComponent, selector: "fs-chip", inputs: ["selectable", "removable", "value", "maxWidth", "width", "backgroundColor", "borderColor", "color", "shape", "outlined", "icon", "image", "selected", "padding", "contrastColor", "size"], outputs: ["selectedToggled", "removed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2265
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: FsFilterChipsComponent, isStandalone: true, selector: "fs-filter-chips", ngImport: i0, template: "@for (item of items; track item.name) {\n @for (chip of item.chips$ | async; track chip.label) {\n <fs-chip\n [removable]=\"item.clearable\"\n size=\"small\"\n (click)=\"click(item, chip)\"\n (removed)=\"remove(item, chip)\">\n {{ chip.value ? chip.label + ': ' + chip.value : chip.label }}\n </fs-chip>\n }\n}", styles: [":host{display:flex;flex-wrap:wrap;column-gap:4px;max-width:100%}fs-chip{margin-top:4px}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "ngmodule", type: FsChipModule }, { kind: "component", type: i1$2.FsChipComponent, selector: "fs-chip", inputs: ["selectable", "removable", "value", "maxWidth", "width", "backgroundColor", "borderColor", "color", "shape", "outlined", "icon", "image", "selected", "padding", "contrastColor", "size"], outputs: ["selectedToggled", "removed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2217
2266
  }
2218
2267
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FsFilterChipsComponent, decorators: [{
2219
2268
  type: Component,
2220
2269
  args: [{ selector: 'fs-filter-chips', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
2221
2270
  AsyncPipe,
2222
2271
  FsChipModule,
2223
- ], template: "@for (item of items; track item.name) {\n @for (chip of item.chips$ | async; track chip.label) {\n <fs-chip\n [removable]=\"item.clearable\"\n size=\"small\"\n (click)=\"click(item, chip)\"\n (removed)=\"remove(item, chip)\">\n {{ chip.value ? chip.label + ': ' + chip.value : chip.label }}\n </fs-chip>\n }\n}", styles: [":host{display:flex;flex-wrap:wrap;column-gap:4px}fs-chip{margin-top:4px}\n"] }]
2272
+ ], template: "@for (item of items; track item.name) {\n @for (chip of item.chips$ | async; track chip.label) {\n <fs-chip\n [removable]=\"item.clearable\"\n size=\"small\"\n (click)=\"click(item, chip)\"\n (removed)=\"remove(item, chip)\">\n {{ chip.value ? chip.label + ': ' + chip.value : chip.label }}\n </fs-chip>\n }\n}", styles: [":host{display:flex;flex-wrap:wrap;column-gap:4px;max-width:100%}fs-chip{margin-top:4px}\n"] }]
2224
2273
  }] });
2225
2274
 
2226
2275
  class FsFilterDrawerActionsComponent {
@@ -2845,7 +2894,6 @@ class KeywordInputComponent {
2845
2894
  _destroyRef = inject(DestroyRef);
2846
2895
  _destroy$ = new Subject();
2847
2896
  _keywordController = inject(KeywordController);
2848
- _filterController = inject(FilterController);
2849
2897
  _cdRef = inject(ChangeDetectorRef);
2850
2898
  get keywordVisible$() {
2851
2899
  return this._keywordController.keywordVisible$;
@@ -3241,6 +3289,9 @@ class FilterComponent {
3241
3289
  get keywordVisible$() {
3242
3290
  return this._keywordController.keywordVisible$;
3243
3291
  }
3292
+ get keywordFullWidth$() {
3293
+ return this._keywordController.keywordFullWidth$;
3294
+ }
3244
3295
  get filterInputVisible$() {
3245
3296
  return combineLatest({
3246
3297
  keywordVisible: this.keywordVisible$,
@@ -3493,7 +3544,7 @@ class FilterComponent {
3493
3544
  ActionsController,
3494
3545
  KeywordController,
3495
3546
  SortController,
3496
- ], queries: [{ propertyName: "statusBar", first: true, predicate: FilterStatusBarDirective, descendants: true }, { propertyName: "headingTemplate", first: true, predicate: FilterHeadingDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "keywordInput", first: true, predicate: KeywordInputComponent, descendants: true }, { propertyName: "reloadEl", first: true, predicate: ["reloadEl"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div\n class=\"filter-container\"\n [ngClass]=\"{ 'has-input': filterInputVisible$ | async }\">\n @if (filterInputVisible$ | async) {\n <ng-container *ngTemplateOutlet=\"heading\"></ng-container>\n }\n <div class=\"filter-bar-container\">\n @if (filterInputVisible$ | async) {\n <div class=\"filter-input-container\">\n @if (keywordVisible$ | async) {\n <fs-keyword-input [autofocus]=\"config.autofocus\"></fs-keyword-input>\n }\n @if (savedFilterController.enabled) {\n <fs-saved-filter-autocomplete-chips [savedFiltersController]=\"savedFilterController\"></fs-saved-filter-autocomplete-chips>\n }\n <ng-container [ngTemplateOutlet]=\"filterToolbar\"></ng-container>\n </div>\n } @else {\n @if (hasHeading) {\n <div class=\"filter-heading-container\">\n <ng-container *ngTemplateOutlet=\"heading\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"filterToolbar\"></ng-container>\n </div>\n }\n }\n <ng-container [ngTemplateOutlet]=\"filterActions\"></ng-container>\n </div>\n <ng-container *ngTemplateOutlet=\"filterStatusBarChips\"></ng-container>\n</div>\n<ng-template #filterStatusBarChips>\n @if (statusBar) {\n <div\n class=\"filter-status-container\"\n [ngClass]=\"{ 'has-status': !!filterStatus.textContent }\">\n <div\n class=\"filter-status\"\n #filterStatus>\n <ng-container *ngTemplateOutlet=\"statusBar.templateRef\"></ng-container>\n </div>\n </div>\n }\n @if (config.chips) {\n <fs-filter-chips class=\"filter-chips\"></fs-filter-chips>\n }\n</ng-template>\n<ng-template #filterActions>\n @if ((actionsVisible$ | async)) {\n <div class=\"filter-actions\">\n <fs-filter-actions\n [actions]=\"actions$ | async\"\n [kebabActions]=\"menuActions$ | async\">\n </fs-filter-actions>\n </div>\n }\n</ng-template>\n<ng-template #filterToolbar>\n @if (config.reload || config.autoReload || (filtersVisible$ | async)) {\n <div class=\"filter-toolbar\">\n @if ((filtersVisible$ | async)) {\n <a\n mat-icon-button\n class=\"button-filters\"\n (click)=\"filterButtonClick($event)\"\n [color]=\"config.button.color\">\n @if (config.button.icon) {\n <mat-icon [svgIcon]=\"'filterOutline'\"></mat-icon>\n }\n </a>\n }\n @if (config.reload) {\n <a\n mat-icon-button\n (click)=\"reload($event)\"\n class=\"button-reload\">\n <mat-icon #reloadEl>\n refresh\n </mat-icon>\n </a>\n }\n @if (config.autoReload) {\n <div class=\"filter-reload\">\n <mat-slide-toggle\n name=\"autoReload\"\n class=\"auto-reload\"\n [ngModel]=\"config.autoReload.enabled\"\n (ngModelChange)=\"config.autoReload.enabled = $event\">\n <span>\n Auto refresh\n </span>\n </mat-slide-toggle>\n </div>\n }\n </div>\n }\n</ng-template>\n<ng-template #heading>\n @if (headingTemplate) {\n <ng-container *ngTemplateOutlet=\"headingTemplate\"></ng-container>\n } @else if (config.heading) {\n <div class=\"heading\">\n <h2>\n {{ config.heading }}\n </h2>\n <div class=\"subheading\">\n {{ config.subheading }}\n </div>\n </div>\n }\n</ng-template>", styles: [":host{margin-bottom:20px;display:block}.filter-status-container{flex-grow:1;display:flex;justify-content:center;flex-direction:column;align-self:flex-end}.filter-status-container .filter-status{overflow:hidden;text-overflow:ellipsis}.filter-container{width:100%}.filter-container.has-input .heading{margin-bottom:10px}.filter-container.has-input .filter-bar-container{margin-bottom:4px}.filter-container .filter-bar-container{flex-direction:row;box-sizing:border-box;display:flex;position:relative;align-items:center}.filter-container .filter-bar-container .filter-input-container{flex-direction:row;box-sizing:border-box;display:flex;align-items:center;min-width:0;gap:5px}.filter-container .filter-bar-container .filter-heading-container{flex-direction:row;box-sizing:border-box;display:flex;align-items:center;min-width:0}.filter-container .filter-bar-container .filter-heading-container fs-keyword-input+fs-saved-filter-autocomplete-chips{margin-left:5px}.filter-actions{display:flex;align-items:center;flex:1;justify-content:flex-end}.filter-toolbar{white-space:nowrap;display:flex;align-items:center}.filter-toolbar .button-filters,.filter-toolbar .button-reload{display:flex;--mdc-icon-button-state-layer-size: 40px;padding:8px}.filter-toolbar .button-filters ::ng-deep svg,.filter-toolbar .button-reload ::ng-deep svg{display:flex}.filter-toolbar .button-reload{display:flex;align-items:center}.filter-toolbar .button-reload .auto-reload{margin-right:5px}.filter-toolbar .button-reload .auto-reload span{font-size:80%}.heading{margin-right:8px}.heading h2{margin:0}.heading h2+.subheading{margin:0}@media screen and (min-width: 1200px){html.fs-filter-open body{margin-right:350px}}html.fs-filter-open{scrollbar-width:none}:host ::ng-deep .auto-reload.mat-checked .mat-slide-toggle-thumb-container{transform:translate3d(12px,0,0)}:host ::ng-deep .auto-reload:not(.mat-checked) .mat-slide-toggle-content{color:#ccc}:host ::ng-deep .auto-reload .mat-slide-toggle-thumb,:host ::ng-deep .auto-reload .mat-slide-toggle-thumb-container{height:15px;width:15px}:host ::ng-deep .auto-reload .mat-slide-toggle-content{font-size:90%}:host ::ng-deep .auto-reload .mat-slide-toggle-bar{width:26px;height:10px;border-radius:10px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FsSavedFilterAutocompleteChipsComponent, selector: "fs-saved-filter-autocomplete-chips", inputs: ["savedFiltersController"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: "ngmodule", type: FsClearModule }, { kind: "component", type: FsFilterChipsComponent, selector: "fs-filter-chips" }, { kind: "component", type: FsFilterActionsComponent, selector: "fs-filter-actions", inputs: ["kebabActions", "actions"] }, { kind: "component", type: MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: KeywordInputComponent, selector: "fs-keyword-input", inputs: ["autofocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3547
+ ], queries: [{ propertyName: "statusBar", first: true, predicate: FilterStatusBarDirective, descendants: true }, { propertyName: "headingTemplate", first: true, predicate: FilterHeadingDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "keywordInput", first: true, predicate: KeywordInputComponent, descendants: true }, { propertyName: "reloadEl", first: true, predicate: ["reloadEl"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div\n class=\"filter-container\"\n [ngClass]=\"{ 'has-input': filterInputVisible$ | async }\"\n [ngClass]=\"{ 'keyword-full-width': keywordFullWidth$ | async }\">\n @if (filterInputVisible$ | async) {\n <ng-container *ngTemplateOutlet=\"heading\"></ng-container>\n }\n <div class=\"filter-bar-container\">\n @if (filterInputVisible$ | async) {\n <div class=\"filter-input-container\">\n @if (keywordVisible$ | async) {\n <fs-keyword-input [autofocus]=\"config.autofocus\"></fs-keyword-input>\n }\n @if (savedFilterController.enabled) {\n <fs-saved-filter-autocomplete-chips [savedFiltersController]=\"savedFilterController\"></fs-saved-filter-autocomplete-chips>\n }\n <ng-container [ngTemplateOutlet]=\"filterToolbar\"></ng-container>\n </div>\n } @else {\n @if (hasHeading) {\n <div class=\"filter-heading-container\">\n <ng-container *ngTemplateOutlet=\"heading\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"filterToolbar\"></ng-container>\n </div>\n }\n }\n <ng-container [ngTemplateOutlet]=\"filterActions\"></ng-container>\n </div>\n <ng-container *ngTemplateOutlet=\"filterStatusBarChips\"></ng-container>\n</div>\n<ng-template #filterStatusBarChips>\n @if (statusBar) {\n <div\n class=\"filter-status-container\"\n [ngClass]=\"{ 'has-status': !!filterStatus.textContent }\">\n <div\n class=\"filter-status\"\n #filterStatus>\n <ng-container *ngTemplateOutlet=\"statusBar.templateRef\"></ng-container>\n </div>\n </div>\n }\n @if (config.chips) {\n <fs-filter-chips class=\"filter-chips\"></fs-filter-chips>\n }\n</ng-template>\n<ng-template #filterActions>\n @if ((actionsVisible$ | async)) {\n <div class=\"filter-actions\">\n <fs-filter-actions\n [actions]=\"actions$ | async\"\n [kebabActions]=\"menuActions$ | async\">\n </fs-filter-actions>\n </div>\n }\n</ng-template>\n<ng-template #filterToolbar>\n @if (config.reload || config.autoReload || (filtersVisible$ | async)) {\n <div class=\"filter-toolbar\">\n @if ((filtersVisible$ | async)) {\n <a\n mat-icon-button\n class=\"button-filters\"\n (click)=\"filterButtonClick($event)\"\n [color]=\"config.button.color\">\n @if (config.button.icon) {\n <mat-icon [svgIcon]=\"'filterOutline'\"></mat-icon>\n }\n </a>\n }\n @if (config.reload) {\n <a\n mat-icon-button\n (click)=\"reload($event)\"\n class=\"button-reload\">\n <mat-icon #reloadEl>\n refresh\n </mat-icon>\n </a>\n }\n @if (config.autoReload) {\n <div class=\"filter-reload\">\n <mat-slide-toggle\n name=\"autoReload\"\n class=\"auto-reload\"\n [ngModel]=\"config.autoReload.enabled\"\n (ngModelChange)=\"config.autoReload.enabled = $event\">\n <span>\n Auto refresh\n </span>\n </mat-slide-toggle>\n </div>\n }\n </div>\n }\n</ng-template>\n<ng-template #heading>\n @if (headingTemplate) {\n <ng-container *ngTemplateOutlet=\"headingTemplate\"></ng-container>\n } @else if (config.heading) {\n <div class=\"heading\">\n <h2>\n {{ config.heading }}\n </h2>\n <div class=\"subheading\">\n {{ config.subheading }}\n </div>\n </div>\n }\n</ng-template>", styles: [":host{margin-bottom:20px;display:block}.filter-status-container{flex-grow:1;display:flex;justify-content:center;flex-direction:column;align-self:flex-end}.filter-status-container .filter-status{overflow:hidden;text-overflow:ellipsis}.filter-container{width:100%}.filter-container.has-input .heading{margin-bottom:10px}.filter-container.has-input .filter-bar-container{margin-bottom:4px}.filter-container.keyword-full-width .filter-input-container{flex:1}.filter-container.keyword-full-width .filter-input-container fs-keyword-input{flex:1}.filter-container.keyword-full-width .filter-input-container fs-keyword-input ::ng-deep mat-form-field{width:100%}.filter-container .filter-bar-container{flex-direction:row;box-sizing:border-box;display:flex;position:relative;align-items:center}.filter-container .filter-bar-container .filter-input-container{flex-direction:row;box-sizing:border-box;display:flex;align-items:center;min-width:0;gap:5px}.filter-container .filter-bar-container .filter-heading-container{flex-direction:row;box-sizing:border-box;display:flex;align-items:center;min-width:0}.filter-container .filter-bar-container .filter-heading-container fs-keyword-input+fs-saved-filter-autocomplete-chips{margin-left:5px}.filter-actions{display:flex;align-items:center;flex:1;justify-content:flex-end}.filter-toolbar{white-space:nowrap;display:flex;align-items:center}.filter-toolbar .button-filters,.filter-toolbar .button-reload{display:flex;--mdc-icon-button-state-layer-size: 40px;padding:8px}.filter-toolbar .button-filters ::ng-deep svg,.filter-toolbar .button-reload ::ng-deep svg{display:flex}.filter-toolbar .button-reload{display:flex;align-items:center}.filter-toolbar .button-reload .auto-reload{margin-right:5px}.filter-toolbar .button-reload .auto-reload span{font-size:80%}.heading{margin-right:8px}.heading h2{margin:0}.heading h2+.subheading{margin:0}@media screen and (min-width: 1200px){html.fs-filter-open body{margin-right:350px}}html.fs-filter-open{scrollbar-width:none}:host ::ng-deep .auto-reload.mat-checked .mat-slide-toggle-thumb-container{transform:translate3d(12px,0,0)}:host ::ng-deep .auto-reload:not(.mat-checked) .mat-slide-toggle-content{color:#ccc}:host ::ng-deep .auto-reload .mat-slide-toggle-thumb,:host ::ng-deep .auto-reload .mat-slide-toggle-thumb-container{height:15px;width:15px}:host ::ng-deep .auto-reload .mat-slide-toggle-content{font-size:90%}:host ::ng-deep .auto-reload .mat-slide-toggle-bar{width:26px;height:10px;border-radius:10px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FsSavedFilterAutocompleteChipsComponent, selector: "fs-saved-filter-autocomplete-chips", inputs: ["savedFiltersController"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: "ngmodule", type: FsClearModule }, { kind: "component", type: FsFilterChipsComponent, selector: "fs-filter-chips" }, { kind: "component", type: FsFilterActionsComponent, selector: "fs-filter-actions", inputs: ["kebabActions", "actions"] }, { kind: "component", type: MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: KeywordInputComponent, selector: "fs-keyword-input", inputs: ["autofocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3497
3548
  }
3498
3549
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FilterComponent, decorators: [{
3499
3550
  type: Component,
@@ -3521,7 +3572,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
3521
3572
  MatSlideToggle,
3522
3573
  AsyncPipe,
3523
3574
  KeywordInputComponent,
3524
- ], template: "<div\n class=\"filter-container\"\n [ngClass]=\"{ 'has-input': filterInputVisible$ | async }\">\n @if (filterInputVisible$ | async) {\n <ng-container *ngTemplateOutlet=\"heading\"></ng-container>\n }\n <div class=\"filter-bar-container\">\n @if (filterInputVisible$ | async) {\n <div class=\"filter-input-container\">\n @if (keywordVisible$ | async) {\n <fs-keyword-input [autofocus]=\"config.autofocus\"></fs-keyword-input>\n }\n @if (savedFilterController.enabled) {\n <fs-saved-filter-autocomplete-chips [savedFiltersController]=\"savedFilterController\"></fs-saved-filter-autocomplete-chips>\n }\n <ng-container [ngTemplateOutlet]=\"filterToolbar\"></ng-container>\n </div>\n } @else {\n @if (hasHeading) {\n <div class=\"filter-heading-container\">\n <ng-container *ngTemplateOutlet=\"heading\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"filterToolbar\"></ng-container>\n </div>\n }\n }\n <ng-container [ngTemplateOutlet]=\"filterActions\"></ng-container>\n </div>\n <ng-container *ngTemplateOutlet=\"filterStatusBarChips\"></ng-container>\n</div>\n<ng-template #filterStatusBarChips>\n @if (statusBar) {\n <div\n class=\"filter-status-container\"\n [ngClass]=\"{ 'has-status': !!filterStatus.textContent }\">\n <div\n class=\"filter-status\"\n #filterStatus>\n <ng-container *ngTemplateOutlet=\"statusBar.templateRef\"></ng-container>\n </div>\n </div>\n }\n @if (config.chips) {\n <fs-filter-chips class=\"filter-chips\"></fs-filter-chips>\n }\n</ng-template>\n<ng-template #filterActions>\n @if ((actionsVisible$ | async)) {\n <div class=\"filter-actions\">\n <fs-filter-actions\n [actions]=\"actions$ | async\"\n [kebabActions]=\"menuActions$ | async\">\n </fs-filter-actions>\n </div>\n }\n</ng-template>\n<ng-template #filterToolbar>\n @if (config.reload || config.autoReload || (filtersVisible$ | async)) {\n <div class=\"filter-toolbar\">\n @if ((filtersVisible$ | async)) {\n <a\n mat-icon-button\n class=\"button-filters\"\n (click)=\"filterButtonClick($event)\"\n [color]=\"config.button.color\">\n @if (config.button.icon) {\n <mat-icon [svgIcon]=\"'filterOutline'\"></mat-icon>\n }\n </a>\n }\n @if (config.reload) {\n <a\n mat-icon-button\n (click)=\"reload($event)\"\n class=\"button-reload\">\n <mat-icon #reloadEl>\n refresh\n </mat-icon>\n </a>\n }\n @if (config.autoReload) {\n <div class=\"filter-reload\">\n <mat-slide-toggle\n name=\"autoReload\"\n class=\"auto-reload\"\n [ngModel]=\"config.autoReload.enabled\"\n (ngModelChange)=\"config.autoReload.enabled = $event\">\n <span>\n Auto refresh\n </span>\n </mat-slide-toggle>\n </div>\n }\n </div>\n }\n</ng-template>\n<ng-template #heading>\n @if (headingTemplate) {\n <ng-container *ngTemplateOutlet=\"headingTemplate\"></ng-container>\n } @else if (config.heading) {\n <div class=\"heading\">\n <h2>\n {{ config.heading }}\n </h2>\n <div class=\"subheading\">\n {{ config.subheading }}\n </div>\n </div>\n }\n</ng-template>", styles: [":host{margin-bottom:20px;display:block}.filter-status-container{flex-grow:1;display:flex;justify-content:center;flex-direction:column;align-self:flex-end}.filter-status-container .filter-status{overflow:hidden;text-overflow:ellipsis}.filter-container{width:100%}.filter-container.has-input .heading{margin-bottom:10px}.filter-container.has-input .filter-bar-container{margin-bottom:4px}.filter-container .filter-bar-container{flex-direction:row;box-sizing:border-box;display:flex;position:relative;align-items:center}.filter-container .filter-bar-container .filter-input-container{flex-direction:row;box-sizing:border-box;display:flex;align-items:center;min-width:0;gap:5px}.filter-container .filter-bar-container .filter-heading-container{flex-direction:row;box-sizing:border-box;display:flex;align-items:center;min-width:0}.filter-container .filter-bar-container .filter-heading-container fs-keyword-input+fs-saved-filter-autocomplete-chips{margin-left:5px}.filter-actions{display:flex;align-items:center;flex:1;justify-content:flex-end}.filter-toolbar{white-space:nowrap;display:flex;align-items:center}.filter-toolbar .button-filters,.filter-toolbar .button-reload{display:flex;--mdc-icon-button-state-layer-size: 40px;padding:8px}.filter-toolbar .button-filters ::ng-deep svg,.filter-toolbar .button-reload ::ng-deep svg{display:flex}.filter-toolbar .button-reload{display:flex;align-items:center}.filter-toolbar .button-reload .auto-reload{margin-right:5px}.filter-toolbar .button-reload .auto-reload span{font-size:80%}.heading{margin-right:8px}.heading h2{margin:0}.heading h2+.subheading{margin:0}@media screen and (min-width: 1200px){html.fs-filter-open body{margin-right:350px}}html.fs-filter-open{scrollbar-width:none}:host ::ng-deep .auto-reload.mat-checked .mat-slide-toggle-thumb-container{transform:translate3d(12px,0,0)}:host ::ng-deep .auto-reload:not(.mat-checked) .mat-slide-toggle-content{color:#ccc}:host ::ng-deep .auto-reload .mat-slide-toggle-thumb,:host ::ng-deep .auto-reload .mat-slide-toggle-thumb-container{height:15px;width:15px}:host ::ng-deep .auto-reload .mat-slide-toggle-content{font-size:90%}:host ::ng-deep .auto-reload .mat-slide-toggle-bar{width:26px;height:10px;border-radius:10px}\n"] }]
3575
+ ], template: "<div\n class=\"filter-container\"\n [ngClass]=\"{ 'has-input': filterInputVisible$ | async }\"\n [ngClass]=\"{ 'keyword-full-width': keywordFullWidth$ | async }\">\n @if (filterInputVisible$ | async) {\n <ng-container *ngTemplateOutlet=\"heading\"></ng-container>\n }\n <div class=\"filter-bar-container\">\n @if (filterInputVisible$ | async) {\n <div class=\"filter-input-container\">\n @if (keywordVisible$ | async) {\n <fs-keyword-input [autofocus]=\"config.autofocus\"></fs-keyword-input>\n }\n @if (savedFilterController.enabled) {\n <fs-saved-filter-autocomplete-chips [savedFiltersController]=\"savedFilterController\"></fs-saved-filter-autocomplete-chips>\n }\n <ng-container [ngTemplateOutlet]=\"filterToolbar\"></ng-container>\n </div>\n } @else {\n @if (hasHeading) {\n <div class=\"filter-heading-container\">\n <ng-container *ngTemplateOutlet=\"heading\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"filterToolbar\"></ng-container>\n </div>\n }\n }\n <ng-container [ngTemplateOutlet]=\"filterActions\"></ng-container>\n </div>\n <ng-container *ngTemplateOutlet=\"filterStatusBarChips\"></ng-container>\n</div>\n<ng-template #filterStatusBarChips>\n @if (statusBar) {\n <div\n class=\"filter-status-container\"\n [ngClass]=\"{ 'has-status': !!filterStatus.textContent }\">\n <div\n class=\"filter-status\"\n #filterStatus>\n <ng-container *ngTemplateOutlet=\"statusBar.templateRef\"></ng-container>\n </div>\n </div>\n }\n @if (config.chips) {\n <fs-filter-chips class=\"filter-chips\"></fs-filter-chips>\n }\n</ng-template>\n<ng-template #filterActions>\n @if ((actionsVisible$ | async)) {\n <div class=\"filter-actions\">\n <fs-filter-actions\n [actions]=\"actions$ | async\"\n [kebabActions]=\"menuActions$ | async\">\n </fs-filter-actions>\n </div>\n }\n</ng-template>\n<ng-template #filterToolbar>\n @if (config.reload || config.autoReload || (filtersVisible$ | async)) {\n <div class=\"filter-toolbar\">\n @if ((filtersVisible$ | async)) {\n <a\n mat-icon-button\n class=\"button-filters\"\n (click)=\"filterButtonClick($event)\"\n [color]=\"config.button.color\">\n @if (config.button.icon) {\n <mat-icon [svgIcon]=\"'filterOutline'\"></mat-icon>\n }\n </a>\n }\n @if (config.reload) {\n <a\n mat-icon-button\n (click)=\"reload($event)\"\n class=\"button-reload\">\n <mat-icon #reloadEl>\n refresh\n </mat-icon>\n </a>\n }\n @if (config.autoReload) {\n <div class=\"filter-reload\">\n <mat-slide-toggle\n name=\"autoReload\"\n class=\"auto-reload\"\n [ngModel]=\"config.autoReload.enabled\"\n (ngModelChange)=\"config.autoReload.enabled = $event\">\n <span>\n Auto refresh\n </span>\n </mat-slide-toggle>\n </div>\n }\n </div>\n }\n</ng-template>\n<ng-template #heading>\n @if (headingTemplate) {\n <ng-container *ngTemplateOutlet=\"headingTemplate\"></ng-container>\n } @else if (config.heading) {\n <div class=\"heading\">\n <h2>\n {{ config.heading }}\n </h2>\n <div class=\"subheading\">\n {{ config.subheading }}\n </div>\n </div>\n }\n</ng-template>", styles: [":host{margin-bottom:20px;display:block}.filter-status-container{flex-grow:1;display:flex;justify-content:center;flex-direction:column;align-self:flex-end}.filter-status-container .filter-status{overflow:hidden;text-overflow:ellipsis}.filter-container{width:100%}.filter-container.has-input .heading{margin-bottom:10px}.filter-container.has-input .filter-bar-container{margin-bottom:4px}.filter-container.keyword-full-width .filter-input-container{flex:1}.filter-container.keyword-full-width .filter-input-container fs-keyword-input{flex:1}.filter-container.keyword-full-width .filter-input-container fs-keyword-input ::ng-deep mat-form-field{width:100%}.filter-container .filter-bar-container{flex-direction:row;box-sizing:border-box;display:flex;position:relative;align-items:center}.filter-container .filter-bar-container .filter-input-container{flex-direction:row;box-sizing:border-box;display:flex;align-items:center;min-width:0;gap:5px}.filter-container .filter-bar-container .filter-heading-container{flex-direction:row;box-sizing:border-box;display:flex;align-items:center;min-width:0}.filter-container .filter-bar-container .filter-heading-container fs-keyword-input+fs-saved-filter-autocomplete-chips{margin-left:5px}.filter-actions{display:flex;align-items:center;flex:1;justify-content:flex-end}.filter-toolbar{white-space:nowrap;display:flex;align-items:center}.filter-toolbar .button-filters,.filter-toolbar .button-reload{display:flex;--mdc-icon-button-state-layer-size: 40px;padding:8px}.filter-toolbar .button-filters ::ng-deep svg,.filter-toolbar .button-reload ::ng-deep svg{display:flex}.filter-toolbar .button-reload{display:flex;align-items:center}.filter-toolbar .button-reload .auto-reload{margin-right:5px}.filter-toolbar .button-reload .auto-reload span{font-size:80%}.heading{margin-right:8px}.heading h2{margin:0}.heading h2+.subheading{margin:0}@media screen and (min-width: 1200px){html.fs-filter-open body{margin-right:350px}}html.fs-filter-open{scrollbar-width:none}:host ::ng-deep .auto-reload.mat-checked .mat-slide-toggle-thumb-container{transform:translate3d(12px,0,0)}:host ::ng-deep .auto-reload:not(.mat-checked) .mat-slide-toggle-content{color:#ccc}:host ::ng-deep .auto-reload .mat-slide-toggle-thumb,:host ::ng-deep .auto-reload .mat-slide-toggle-thumb-container{height:15px;width:15px}:host ::ng-deep .auto-reload .mat-slide-toggle-content{font-size:90%}:host ::ng-deep .auto-reload .mat-slide-toggle-bar{width:26px;height:10px;border-radius:10px}\n"] }]
3525
3576
  }], ctorParameters: () => [], propDecorators: { keywordInput: [{
3526
3577
  type: ViewChild,
3527
3578
  args: [KeywordInputComponent]