@sinequa/atomic-angular 1.13.0 → 1.14.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.
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { Injectable, inject, HostBinding, Component, Pipe, InjectionToken, computed, ChangeDetectorRef, DestroyRef, LOCALE_ID, Inject, Optional, input, output, signal, effect, assertInInjectionContext, runInInjectionContext, EnvironmentInjector, Injector, EventEmitter, Directive, viewChild, ElementRef, afterNextRender, untracked, linkedSignal, model, TemplateRef, HostListener, Renderer2, contentChildren, contentChild, booleanAttribute, resource, ChangeDetectionStrategy, ViewContainerRef, numberAttribute, viewChildren, afterRenderEffect, afterEveryRender } from '@angular/core';
3
3
  import { BehaviorSubject, Subscription, Subject, of, catchError, map, tap, EMPTY, throwError, from, filter as filter$1, shareReplay, switchMap, firstValueFrom, fromEvent, debounceTime } from 'rxjs';
4
4
  import { TranslocoService, TranslocoPipe, provideTranslocoScope } from '@jsverse/transloco';
5
- import { DropdownComponent, DropdownContentComponent, InputComponent, ButtonComponent, cn, FaIconComponent, EllipsisIcon, ChevronRightIcon, MenuComponent, MenuContentComponent, MenuItemComponent, LinkComponent, CardComponent, CardHeaderComponent, CardContentComponent, BadgeComponent, DialogComponent, DialogHeaderComponent, DialogTitleComponent, DialogContentComponent, DialogFooterComponent, ListItemComponent, SquareCheckIcon, SquareMinusIcon, SquareIcon, SwitchComponent, SelectOptionDirective, DialogService, XMarkIcon, InboxIcon, SparklesIcon, FileOutputIcon, TabsComponent, TabsListComponent, TabComponent, SidebarMenuComponent, SidebarMenuItemComponent, SidebarMenuButtonComponent, TooltipDirective, FrownIcon, ChevronLeftIcon, ChevronsLeftIcon, ChevronsRightIcon, ArrowUpAzIcon, ArrowDownZaIcon, ArrowUpRightFromSquareIcon, ToggleRightIcon, ToggleLeftIcon, Separator, SheetCloseDirective, ArrowLeftIcon, SheetService, DateRangePickerDirective, DatepickerDirective, FilterIcon, FilterXIcon, IconButtonComponent, HighlighterIcon, TagsIcon, SpinnerIcon, MagnifyingGlassIcon, LoadingCircleIcon, CircleCheckIcon, PopoverComponent, BellIcon, TrashIcon, BarsIcon, CardFooterComponent, InputGroupInput, InputGroupComponent, InputGroupAddonComponent, EyeSlashIcon, EyeIcon, BookmarkIcon, PopoverContentComponent, UserIcon, FolderIcon, DialogDescriptionComponent, VerticalDividerComponent, CommentIcon, ThumbsUpIcon, ThumbsDownIcon, DropdownDirective, SearchIcon, TriangleAlertIcon, ListFilterIcon, BreakpointObserverService, TrashCanIcon, CircleXIcon, InfoCircleIcon, HorizontalDividerComponent, HistoryIcon, StarIcon, FlagEnglishIcon, FlagFrenchIcon, FlagGermanIcon, EditIcon, UndoIcon, SaveIcon, AvatarComponent, AvatarFallbackComponent, AvatarImageComponent } from '@sinequa/ui';
5
+ import { DropdownComponent, DropdownContentComponent, InputComponent, ButtonComponent, cn, FaIconComponent, EllipsisIcon, ChevronRightIcon, MenuComponent, MenuContentComponent, MenuItemComponent, LinkComponent, CardComponent, CardHeaderComponent, CardContentComponent, BadgeComponent, DialogComponent, DialogHeaderComponent, DialogTitleComponent, DialogContentComponent, DialogFooterComponent, ListItemComponent, SquareCheckIcon, SquareMinusIcon, SquareIcon, SwitchComponent, SelectOptionDirective, DialogService, XMarkIcon, InboxIcon, SparklesIcon, FileOutputIcon, TabsComponent, TabsListComponent, TabComponent, SidebarMenuComponent, SidebarMenuItemComponent, SidebarMenuButtonComponent, TooltipDirective, FrownIcon, ChevronLeftIcon, ChevronsLeftIcon, ChevronsRightIcon, ArrowUpAzIcon, ArrowDownZaIcon, ArrowUpRightFromSquareIcon, ToggleRightIcon, ToggleLeftIcon, Separator, SheetCloseDirective, ArrowLeftIcon, SheetService, DateRangePickerDirective, DatepickerDirective, FilterIcon, FilterXIcon, IconButtonComponent, HighlighterIcon, TagsIcon, SpinnerIcon, MagnifyingGlassIcon, LoadingCircleIcon, CircleCheckIcon, PopoverComponent, BellIcon, TrashIcon, BarsIcon, CardFooterComponent, InputGroupInput, InputGroupComponent, InputGroupAddonComponent, EyeSlashIcon, EyeIcon, BookmarkIcon, PopoverContentComponent, UserIcon, FolderIcon, DialogDescriptionComponent, VerticalDividerComponent, CommentIcon, ThumbsUpIcon, ThumbsDownIcon, DropdownDirective, SearchIcon, TriangleAlertIcon, BreakpointObserverService, ListFilterIcon, SheetComponent, SheetHeaderComponent, SheetTitleComponent, TrashCanIcon, CircleXIcon, InfoCircleIcon, HorizontalDividerComponent, HistoryIcon, StarIcon, FlagEnglishIcon, FlagFrenchIcon, FlagGermanIcon, EditIcon, UndoIcon, SaveIcon, AvatarComponent, AvatarFallbackComponent, AvatarImageComponent } from '@sinequa/ui';
6
6
  import highlightWords from 'highlight-words';
7
7
  import { ActivatedRoute, Router, NavigationEnd, RouterLink, RouterLinkActive, RouterModule } from '@angular/router';
8
8
  import { withDevtools } from '@angular-architects/ngrx-toolkit';
@@ -14500,7 +14500,7 @@ class AggregationPanelComponent {
14500
14500
  this.searchText.set("");
14501
14501
  }
14502
14502
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: AggregationPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14503
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: AggregationPanelComponent, isStandalone: true, selector: "AggregationPanel, aggregation-panel", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, isDate: { classPropertyName: "isDate", publicName: "isDate", isSignal: true, isRequired: false, transformFunction: null }, isEmpty: { classPropertyName: "isEmpty", publicName: "isEmpty", isSignal: true, isRequired: false, transformFunction: null }, aggregation: { classPropertyName: "aggregation", publicName: "aggregation", isSignal: true, isRequired: false, transformFunction: null }, showFiltersCount: { classPropertyName: "showFiltersCount", publicName: "showFiltersCount", isSignal: true, isRequired: false, transformFunction: null }, filtersCount: { classPropertyName: "filtersCount", publicName: "filtersCount", isSignal: true, isRequired: false, transformFunction: null }, hasFilters: { classPropertyName: "hasFilters", publicName: "hasFilters", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, isAllSelected: { classPropertyName: "isAllSelected", publicName: "isAllSelected", isSignal: true, isRequired: false, transformFunction: null }, searchText: { classPropertyName: "searchText", publicName: "searchText", isSignal: true, isRequired: false, transformFunction: null }, itemsLength: { classPropertyName: "itemsLength", publicName: "itemsLength", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, searchedItemsLength: { classPropertyName: "searchedItemsLength", publicName: "searchedItemsLength", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchText: "searchTextChange", cleared: "cleared", applied: "applied", allSelected: "allSelected", allUnselected: "allUnselected", loadedMore: "loadedMore" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<details\r\n [attr.open]=\"expanded()\"\r\n [attr.name]=\"id()\"\r\n class=\"group space-y-2\"\r\n (toggle)=\"onToggle($event)\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible() && !isEmpty()\"\r\n [class.text-muted-foreground]=\"isEmpty()\"\r\n class=\"m-0 mt-1 flex h-8 w-full items-center gap-1 pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @let icon = aggregation()?.icon;\r\n @if (icon) {\r\n <FaIcon [faClass]=\"icon\" class=\"mr-1 shrink-0\" />\r\n }\r\n <span class=\"grow truncate\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (showFiltersCount() && filtersCount() > 0) {\r\n <Badge size=\"xs\" class=\"ml-1\">\r\n {{ filtersCount() }}\r\n </Badge>\r\n }\r\n @if (!isCollapsed()) {\r\n @if (hasFilters()) {\r\n @let label = \"filters.clearFilters\" | transloco;\r\n <button\r\n variant=\"none\"\r\n icon-button\r\n [aria-label]=\"label\"\r\n (click)=\"$event.stopPropagation(); cleared.emit()\">\r\n <filter-x-icon />\r\n </button>\r\n }\r\n @if (selection()) {\r\n @let label = \"filters.apply\" | transloco;\r\n <button\r\n variant=\"accent\"\r\n size=\"sm\"\r\n [aria-label]=\"label\"\r\n (click)=\"$event.stopPropagation(); applied.emit()\">\r\n <FilterIcon />\r\n {{ label }}\r\n </button>\r\n }\r\n\r\n @if (isAllSelected()) {\r\n @let label = \"filters.unselectAllFilters\" | transloco;\r\n <button\r\n variant=\"none\"\r\n icon-button\r\n [aria-label]=\"label\"\r\n (click)=\"$event.stopPropagation(); allUnselected.emit()\">\r\n <square-check-icon />\r\n </button>\r\n } @else {\r\n @let label = \"filters.selectAllFilters\" | transloco;\r\n <button\r\n variant=\"none\"\r\n icon-button\r\n [aria-label]=\"label\"\r\n (click)=\"$event.stopPropagation(); allSelected.emit()\">\r\n <square-icon />\r\n </button>\r\n }\r\n }\r\n\r\n @if (collapsible()) {\r\n <icon-button\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n <span class=\"sr-only\">{{ \"filters.toggle\" | transloco }}</span>\r\n </icon-button>\r\n }\r\n </summary>\r\n\r\n @if (aggregation()?.searchable && itemsLength() > 0) {\r\n <InputGroup class=\"group/item mt-1\">\r\n <input\r\n #searchInput\r\n input-group\r\n id=\"aggregation-input-{{ aggregation()?.column }}\"\r\n type=\"text\"\r\n [attr.aria-label]=\"'search' | transloco\"\r\n [attr.placeholder]=\"'search' | transloco\"\r\n [(ngModel)]=\"searchText\"\r\n class=\"mt-1\" />\r\n <InputGroupAddon>\r\n <SearchIcon\r\n class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\r\n </InputGroupAddon>\r\n <InputGroupAddon align=\"inline-end\" class=\"gap-0.5!\">\r\n <icon-button\r\n size=\"sm\"\r\n [class]=\"\r\n searchText().length > 0\r\n ? 'rotate-90 cursor-pointer opacity-100 transition-[rotate,opacity] duration-500'\r\n : 'pointer-events-none rotate-0 opacity-0 transition-[rotate,opacity] duration-500'\r\n \"\r\n aria-label=\"Clear search\"\r\n [tabindex]=\"searchText().length > 0 ? 0 : -1\"\r\n (keydown.enter)=\"clearSearch($event)\"\r\n (click)=\"clearSearch($event)\">\r\n <XMarkIcon />\r\n </icon-button>\r\n <ng-content select=\"[search-addon]\" />\r\n </InputGroupAddon>\r\n </InputGroup>\r\n }\r\n\r\n <ng-content />\r\n\r\n @if (hasMore() && searchedItemsLength() === 0) {\r\n <button\r\n class=\"mt-1 flex w-full justify-center\"\r\n [attr.aria-label]=\"'loadMore' | transloco\"\r\n (click)=\"loadedMore.emit()\">\r\n {{ \"loadMore\" | transloco }}\r\n </button>\r\n }\r\n</details>\r\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant", "scheme", "size", "aria-label"] }, { kind: "component", type: ChevronRightIcon, selector: "chevron-right, ChevronRight, chevronright, ChevronRightIcon, chevron-right-icon, chevronrighticon", inputs: ["class"] }, { kind: "directive", type: InputGroupInput, selector: "input[input-group]", inputs: ["class", "type", "placeholder", "disabled"] }, { kind: "directive", type: InputGroupComponent, selector: "input-group, inputgroup, InputGroup", inputs: ["class"] }, { kind: "directive", type: InputGroupAddonComponent, selector: "input-group-addon, inputgroupaddon, InputGroupAddon", inputs: ["class", "align"] }, { kind: "component", type: SearchIcon, selector: "SearchIcon", inputs: ["class"] }, { kind: "component", type: FilterIcon, selector: "filter-icon, FilterIcon", inputs: ["class"] }, { kind: "component", type: FaIconComponent, selector: "fa-icon, FaIcon", inputs: ["faClass", "class"] }, { kind: "component", type: FilterXIcon, selector: "filter-x-icon, FilterXIcon", inputs: ["class"] }, { kind: "component", type: SquareCheckIcon, selector: "square-check-icon, SquareCheckIcon", inputs: ["class"] }, { kind: "component", type: SquareIcon, selector: "square-icon, SquareIcon", inputs: ["class"] }, { kind: "component", type: XMarkIcon, selector: "XMarkIcon, xmark-icon, x-mark-icon", inputs: ["class"] }, { kind: "directive", type: IconButtonComponent, selector: "button[icon-button], icon-button, IconButton", inputs: ["class", "size"] }, { kind: "pipe", type: SyslangPipe, name: "syslang" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
14503
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: AggregationPanelComponent, isStandalone: true, selector: "AggregationPanel, aggregation-panel", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, isDate: { classPropertyName: "isDate", publicName: "isDate", isSignal: true, isRequired: false, transformFunction: null }, isEmpty: { classPropertyName: "isEmpty", publicName: "isEmpty", isSignal: true, isRequired: false, transformFunction: null }, aggregation: { classPropertyName: "aggregation", publicName: "aggregation", isSignal: true, isRequired: false, transformFunction: null }, showFiltersCount: { classPropertyName: "showFiltersCount", publicName: "showFiltersCount", isSignal: true, isRequired: false, transformFunction: null }, filtersCount: { classPropertyName: "filtersCount", publicName: "filtersCount", isSignal: true, isRequired: false, transformFunction: null }, hasFilters: { classPropertyName: "hasFilters", publicName: "hasFilters", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, isAllSelected: { classPropertyName: "isAllSelected", publicName: "isAllSelected", isSignal: true, isRequired: false, transformFunction: null }, searchText: { classPropertyName: "searchText", publicName: "searchText", isSignal: true, isRequired: false, transformFunction: null }, itemsLength: { classPropertyName: "itemsLength", publicName: "itemsLength", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, searchedItemsLength: { classPropertyName: "searchedItemsLength", publicName: "searchedItemsLength", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchText: "searchTextChange", cleared: "cleared", applied: "applied", allSelected: "allSelected", allUnselected: "allUnselected", loadedMore: "loadedMore" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<details\n [attr.open]=\"expanded()\"\n [attr.name]=\"id()\"\n class=\"group space-y-2\"\n (toggle)=\"onToggle($event)\">\n <summary\n [class.cursor-pointer]=\"collapsible() && !isEmpty()\"\n [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex h-8 w-full items-center gap-1 pl-1 font-semibold select-none\"\n (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @let icon = aggregation()?.icon;\n @if (icon) {\n <FaIcon [faClass]=\"icon\" class=\"mr-1 shrink-0\" />\n }\n <span class=\"grow truncate\">{{\n aggregation()?.display | syslang | transloco\n }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <Badge size=\"xs\" class=\"ml-1\">\n {{ filtersCount() }}\n </Badge>\n }\n @if (!isCollapsed()) {\n @if (hasFilters()) {\n @let label = \"filters.clearFilters\" | transloco;\n <button\n variant=\"none\"\n icon-button\n [aria-label]=\"label\"\n (click)=\"$event.stopPropagation(); cleared.emit()\">\n <filter-x-icon />\n </button>\n }\n @if (selection()) {\n @let label = \"filters.apply\" | transloco;\n <button\n variant=\"accent\"\n size=\"sm\"\n [aria-label]=\"label\"\n (click)=\"$event.stopPropagation(); applied.emit()\">\n <FilterIcon />\n {{ label }}\n </button>\n }\n\n @if (isAllSelected()) {\n @let label = \"filters.unselectAllFilters\" | transloco;\n <button\n variant=\"none\"\n icon-button\n [aria-label]=\"label\"\n (click)=\"$event.stopPropagation(); allUnselected.emit()\">\n <square-check-icon />\n </button>\n } @else {\n @let label = \"filters.selectAllFilters\" | transloco;\n <button\n variant=\"none\"\n icon-button\n [aria-label]=\"label\"\n (click)=\"$event.stopPropagation(); allSelected.emit()\">\n <square-icon />\n </button>\n }\n }\n\n @if (collapsible()) {\n <icon-button\n title=\"Open/Close\"\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\n <chevronright />\n <span class=\"sr-only\">{{ \"filters.toggle\" | transloco }}</span>\n </icon-button>\n }\n </summary>\n\n @if (aggregation()?.searchable && itemsLength() > 0) {\n <InputGroup class=\"group/item mt-3\">\n <input\n #searchInput\n input-group\n id=\"aggregation-input-{{ aggregation()?.column }}\"\n type=\"text\"\n [attr.aria-label]=\"'search' | transloco\"\n [attr.placeholder]=\"'search' | transloco\"\n [(ngModel)]=\"searchText\"\n class=\"mt-1\" />\n <InputGroupAddon>\n <SearchIcon\n class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\n </InputGroupAddon>\n <InputGroupAddon align=\"inline-end\" class=\"gap-0.5!\">\n <icon-button\n size=\"sm\"\n [class]=\"\n searchText().length > 0\n ? 'rotate-90 cursor-pointer opacity-100 transition-[rotate,opacity] duration-500'\n : 'pointer-events-none rotate-0 opacity-0 transition-[rotate,opacity] duration-500'\n \"\n aria-label=\"Clear search\"\n [tabindex]=\"searchText().length > 0 ? 0 : -1\"\n (keydown.enter)=\"clearSearch($event)\"\n (click)=\"clearSearch($event)\">\n <XMarkIcon />\n </icon-button>\n <ng-content select=\"[search-addon]\" />\n </InputGroupAddon>\n </InputGroup>\n }\n\n <ng-content />\n\n @if (hasMore() && searchedItemsLength() === 0) {\n <button\n class=\"mt-1 flex w-full justify-center\"\n [attr.aria-label]=\"'loadMore' | transloco\"\n (click)=\"loadedMore.emit()\">\n {{ \"loadMore\" | transloco }}\n </button>\n }\n</details>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant", "scheme", "size", "aria-label"] }, { kind: "component", type: ChevronRightIcon, selector: "chevron-right, ChevronRight, chevronright, ChevronRightIcon, chevron-right-icon, chevronrighticon", inputs: ["class"] }, { kind: "directive", type: InputGroupInput, selector: "input[input-group]", inputs: ["class", "type", "placeholder", "disabled"] }, { kind: "directive", type: InputGroupComponent, selector: "input-group, inputgroup, InputGroup", inputs: ["class"] }, { kind: "directive", type: InputGroupAddonComponent, selector: "input-group-addon, inputgroupaddon, InputGroupAddon", inputs: ["class", "align"] }, { kind: "component", type: SearchIcon, selector: "SearchIcon", inputs: ["class"] }, { kind: "component", type: FilterIcon, selector: "filter-icon, FilterIcon", inputs: ["class"] }, { kind: "component", type: FaIconComponent, selector: "fa-icon, FaIcon", inputs: ["faClass", "class"] }, { kind: "component", type: FilterXIcon, selector: "filter-x-icon, FilterXIcon", inputs: ["class"] }, { kind: "component", type: SquareCheckIcon, selector: "square-check-icon, SquareCheckIcon", inputs: ["class"] }, { kind: "component", type: SquareIcon, selector: "square-icon, SquareIcon", inputs: ["class"] }, { kind: "component", type: XMarkIcon, selector: "XMarkIcon, xmark-icon, x-mark-icon", inputs: ["class"] }, { kind: "directive", type: IconButtonComponent, selector: "button[icon-button], icon-button, IconButton", inputs: ["class", "size"] }, { kind: "pipe", type: SyslangPipe, name: "syslang" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
14504
14504
  }
14505
14505
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: AggregationPanelComponent, decorators: [{
14506
14506
  type: Component,
@@ -14522,7 +14522,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
14522
14522
  SquareIcon,
14523
14523
  XMarkIcon,
14524
14524
  IconButtonComponent,
14525
- ], template: "<details\r\n [attr.open]=\"expanded()\"\r\n [attr.name]=\"id()\"\r\n class=\"group space-y-2\"\r\n (toggle)=\"onToggle($event)\">\r\n <summary\r\n [class.cursor-pointer]=\"collapsible() && !isEmpty()\"\r\n [class.text-muted-foreground]=\"isEmpty()\"\r\n class=\"m-0 mt-1 flex h-8 w-full items-center gap-1 pl-1 font-semibold select-none\"\r\n (click)=\"onHeaderClick($event)\">\r\n <ng-content select=\"label\">\r\n @let icon = aggregation()?.icon;\r\n @if (icon) {\r\n <FaIcon [faClass]=\"icon\" class=\"mr-1 shrink-0\" />\r\n }\r\n <span class=\"grow truncate\">{{\r\n aggregation()?.display | syslang | transloco\r\n }}</span>\r\n </ng-content>\r\n\r\n @if (showFiltersCount() && filtersCount() > 0) {\r\n <Badge size=\"xs\" class=\"ml-1\">\r\n {{ filtersCount() }}\r\n </Badge>\r\n }\r\n @if (!isCollapsed()) {\r\n @if (hasFilters()) {\r\n @let label = \"filters.clearFilters\" | transloco;\r\n <button\r\n variant=\"none\"\r\n icon-button\r\n [aria-label]=\"label\"\r\n (click)=\"$event.stopPropagation(); cleared.emit()\">\r\n <filter-x-icon />\r\n </button>\r\n }\r\n @if (selection()) {\r\n @let label = \"filters.apply\" | transloco;\r\n <button\r\n variant=\"accent\"\r\n size=\"sm\"\r\n [aria-label]=\"label\"\r\n (click)=\"$event.stopPropagation(); applied.emit()\">\r\n <FilterIcon />\r\n {{ label }}\r\n </button>\r\n }\r\n\r\n @if (isAllSelected()) {\r\n @let label = \"filters.unselectAllFilters\" | transloco;\r\n <button\r\n variant=\"none\"\r\n icon-button\r\n [aria-label]=\"label\"\r\n (click)=\"$event.stopPropagation(); allUnselected.emit()\">\r\n <square-check-icon />\r\n </button>\r\n } @else {\r\n @let label = \"filters.selectAllFilters\" | transloco;\r\n <button\r\n variant=\"none\"\r\n icon-button\r\n [aria-label]=\"label\"\r\n (click)=\"$event.stopPropagation(); allSelected.emit()\">\r\n <square-icon />\r\n </button>\r\n }\r\n }\r\n\r\n @if (collapsible()) {\r\n <icon-button\r\n title=\"Open/Close\"\r\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\r\n <chevronright />\r\n <span class=\"sr-only\">{{ \"filters.toggle\" | transloco }}</span>\r\n </icon-button>\r\n }\r\n </summary>\r\n\r\n @if (aggregation()?.searchable && itemsLength() > 0) {\r\n <InputGroup class=\"group/item mt-1\">\r\n <input\r\n #searchInput\r\n input-group\r\n id=\"aggregation-input-{{ aggregation()?.column }}\"\r\n type=\"text\"\r\n [attr.aria-label]=\"'search' | transloco\"\r\n [attr.placeholder]=\"'search' | transloco\"\r\n [(ngModel)]=\"searchText\"\r\n class=\"mt-1\" />\r\n <InputGroupAddon>\r\n <SearchIcon\r\n class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\r\n </InputGroupAddon>\r\n <InputGroupAddon align=\"inline-end\" class=\"gap-0.5!\">\r\n <icon-button\r\n size=\"sm\"\r\n [class]=\"\r\n searchText().length > 0\r\n ? 'rotate-90 cursor-pointer opacity-100 transition-[rotate,opacity] duration-500'\r\n : 'pointer-events-none rotate-0 opacity-0 transition-[rotate,opacity] duration-500'\r\n \"\r\n aria-label=\"Clear search\"\r\n [tabindex]=\"searchText().length > 0 ? 0 : -1\"\r\n (keydown.enter)=\"clearSearch($event)\"\r\n (click)=\"clearSearch($event)\">\r\n <XMarkIcon />\r\n </icon-button>\r\n <ng-content select=\"[search-addon]\" />\r\n </InputGroupAddon>\r\n </InputGroup>\r\n }\r\n\r\n <ng-content />\r\n\r\n @if (hasMore() && searchedItemsLength() === 0) {\r\n <button\r\n class=\"mt-1 flex w-full justify-center\"\r\n [attr.aria-label]=\"'loadMore' | transloco\"\r\n (click)=\"loadedMore.emit()\">\r\n {{ \"loadMore\" | transloco }}\r\n </button>\r\n }\r\n</details>\r\n" }]
14525
+ ], template: "<details\n [attr.open]=\"expanded()\"\n [attr.name]=\"id()\"\n class=\"group space-y-2\"\n (toggle)=\"onToggle($event)\">\n <summary\n [class.cursor-pointer]=\"collapsible() && !isEmpty()\"\n [class.text-muted-foreground]=\"isEmpty()\"\n class=\"m-0 mt-1 flex h-8 w-full items-center gap-1 pl-1 font-semibold select-none\"\n (click)=\"onHeaderClick($event)\">\n <ng-content select=\"label\">\n @let icon = aggregation()?.icon;\n @if (icon) {\n <FaIcon [faClass]=\"icon\" class=\"mr-1 shrink-0\" />\n }\n <span class=\"grow truncate\">{{\n aggregation()?.display | syslang | transloco\n }}</span>\n </ng-content>\n\n @if (showFiltersCount() && filtersCount() > 0) {\n <Badge size=\"xs\" class=\"ml-1\">\n {{ filtersCount() }}\n </Badge>\n }\n @if (!isCollapsed()) {\n @if (hasFilters()) {\n @let label = \"filters.clearFilters\" | transloco;\n <button\n variant=\"none\"\n icon-button\n [aria-label]=\"label\"\n (click)=\"$event.stopPropagation(); cleared.emit()\">\n <filter-x-icon />\n </button>\n }\n @if (selection()) {\n @let label = \"filters.apply\" | transloco;\n <button\n variant=\"accent\"\n size=\"sm\"\n [aria-label]=\"label\"\n (click)=\"$event.stopPropagation(); applied.emit()\">\n <FilterIcon />\n {{ label }}\n </button>\n }\n\n @if (isAllSelected()) {\n @let label = \"filters.unselectAllFilters\" | transloco;\n <button\n variant=\"none\"\n icon-button\n [aria-label]=\"label\"\n (click)=\"$event.stopPropagation(); allUnselected.emit()\">\n <square-check-icon />\n </button>\n } @else {\n @let label = \"filters.selectAllFilters\" | transloco;\n <button\n variant=\"none\"\n icon-button\n [aria-label]=\"label\"\n (click)=\"$event.stopPropagation(); allSelected.emit()\">\n <square-icon />\n </button>\n }\n }\n\n @if (collapsible()) {\n <icon-button\n title=\"Open/Close\"\n class=\"cursor-pointer [&_svg]:transition-transform [&_svg]:duration-150 group-open:[&_svg]:rotate-90\">\n <chevronright />\n <span class=\"sr-only\">{{ \"filters.toggle\" | transloco }}</span>\n </icon-button>\n }\n </summary>\n\n @if (aggregation()?.searchable && itemsLength() > 0) {\n <InputGroup class=\"group/item mt-3\">\n <input\n #searchInput\n input-group\n id=\"aggregation-input-{{ aggregation()?.column }}\"\n type=\"text\"\n [attr.aria-label]=\"'search' | transloco\"\n [attr.placeholder]=\"'search' | transloco\"\n [(ngModel)]=\"searchText\"\n class=\"mt-1\" />\n <InputGroupAddon>\n <SearchIcon\n class=\"text-foreground size-4 rotate-0 transition-[rotate] duration-500 group-focus-within/item:rotate-90\" />\n </InputGroupAddon>\n <InputGroupAddon align=\"inline-end\" class=\"gap-0.5!\">\n <icon-button\n size=\"sm\"\n [class]=\"\n searchText().length > 0\n ? 'rotate-90 cursor-pointer opacity-100 transition-[rotate,opacity] duration-500'\n : 'pointer-events-none rotate-0 opacity-0 transition-[rotate,opacity] duration-500'\n \"\n aria-label=\"Clear search\"\n [tabindex]=\"searchText().length > 0 ? 0 : -1\"\n (keydown.enter)=\"clearSearch($event)\"\n (click)=\"clearSearch($event)\">\n <XMarkIcon />\n </icon-button>\n <ng-content select=\"[search-addon]\" />\n </InputGroupAddon>\n </InputGroup>\n }\n\n <ng-content />\n\n @if (hasMore() && searchedItemsLength() === 0) {\n <button\n class=\"mt-1 flex w-full justify-center\"\n [attr.aria-label]=\"'loadMore' | transloco\"\n (click)=\"loadedMore.emit()\">\n {{ \"loadMore\" | transloco }}\n </button>\n }\n</details>\n" }]
14526
14526
  }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], isDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDate", required: false }] }], isEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEmpty", required: false }] }], aggregation: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregation", required: false }] }], showFiltersCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFiltersCount", required: false }] }], filtersCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtersCount", required: false }] }], hasFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasFilters", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], isAllSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "isAllSelected", required: false }] }], searchText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchText", required: false }] }, { type: i0.Output, args: ["searchTextChange"] }], itemsLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsLength", required: false }] }], hasMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMore", required: false }] }], searchedItemsLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchedItemsLength", required: false }] }], cleared: [{ type: i0.Output, args: ["cleared"] }], applied: [{ type: i0.Output, args: ["applied"] }], allSelected: [{ type: i0.Output, args: ["allSelected"] }], allUnselected: [{ type: i0.Output, args: ["allUnselected"] }], loadedMore: [{ type: i0.Output, args: ["loadedMore"] }], searchInput: [{ type: i0.ViewChild, args: ["searchInput", { isSignal: true }] }] } });
14527
14527
 
14528
14528
  class AggregationTreeComponent {
@@ -16238,6 +16238,13 @@ class FilterButtonComponent {
16238
16238
  column = input.required(...(ngDevMode ? [{ debugName: "column" }] : []));
16239
16239
  position = input("bottom-start", ...(ngDevMode ? [{ debugName: "position" }] : []));
16240
16240
  offset = input(8, ...(ngDevMode ? [{ debugName: "offset" }] : []));
16241
+ /**
16242
+ * When true, forces the popover to stay at the exact `position()` placement,
16243
+ * disabling floating-ui's automatic repositioning based on available viewport space.
16244
+ *
16245
+ * @default false
16246
+ */
16247
+ lockPosition = input(false, ...(ngDevMode ? [{ debugName: "lockPosition", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
16241
16248
  expandedLevel = input(undefined, ...(ngDevMode ? [{ debugName: "expandedLevel", transform: numberAttribute }] : [{ transform: numberAttribute }]));
16242
16249
  variant = signal("ghost", ...(ngDevMode ? [{ debugName: "variant" }] : []));
16243
16250
  filter = signal({
@@ -16303,7 +16310,7 @@ class FilterButtonComponent {
16303
16310
  return this.appStore.isDateColumn(column);
16304
16311
  }
16305
16312
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: FilterButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16306
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: FilterButtonComponent, isStandalone: true, selector: "filter-button, FilterButton", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, expandedLevel: { classPropertyName: "expandedLevel", publicName: "expandedLevel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "listitem" }, properties: { "class.hidden": "filter().hidden" } }, viewQueries: [{ propertyName: "popoverRef", first: true, predicate: PopoverComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
16313
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: FilterButtonComponent, isStandalone: true, selector: "filter-button, FilterButton", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, lockPosition: { classPropertyName: "lockPosition", publicName: "lockPosition", isSignal: true, isRequired: false, transformFunction: null }, expandedLevel: { classPropertyName: "expandedLevel", publicName: "expandedLevel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "listitem" }, properties: { "class.hidden": "filter().hidden" } }, viewQueries: [{ propertyName: "popoverRef", first: true, predicate: PopoverComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
16307
16314
  <Popover [disabled]="filter().disabled" class="group">
16308
16315
  <button
16309
16316
  [variant]="variant()"
@@ -16336,13 +16343,14 @@ class FilterButtonComponent {
16336
16343
  class="min-w-fit w-max max-w-[90vw]"
16337
16344
  [position]="position()"
16338
16345
  [offset]="offset()"
16346
+ [lockPosition]="lockPosition()"
16339
16347
  >
16340
16348
  @if(contentRef.isVisible) {
16341
16349
  @let name = filter().name;
16342
16350
  @let column = filter().column;
16343
16351
  @if(name) {
16344
16352
  <Aggregation
16345
- class="w-60 [--height:19lh]"
16353
+ class="w-60 [--scroll-height:19lh]"
16346
16354
  id="filter-{{ filter().column }}"
16347
16355
  [name]="name"
16348
16356
  [column]="column"
@@ -16358,7 +16366,7 @@ class FilterButtonComponent {
16358
16366
  }
16359
16367
  </PopoverContent>
16360
16368
  </Popover>
16361
- `, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["class", "position", "keepOpen", "offset", "strategy"], exportAs: ["popoverContent"] }, { kind: "component", type: AggregationComponent, selector: "Aggregation, aggregation", inputs: ["class", "id", "name", "column", "showFiltersCount", "collapsible", "collapsed", "searchable", "showCheckbox", "applyOnSelect", "expandedLevel", "syncUrl", "query", "aggregation", "selection", "emitOn", "type", "hideWhenEmpty"], outputs: ["onSelect", "onApply", "onClear", "selectionChange", "filtersChange"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant", "scheme", "size", "aria-label"] }, { kind: "component", type: FaIconComponent, selector: "fa-icon, FaIcon", inputs: ["faClass", "class"] }, { kind: "pipe", type: OperatorPipe, name: "operator" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: SyslangPipe, name: "syslang" }] });
16369
+ `, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["class", "position", "keepOpen", "offset", "strategy", "lockPosition"], exportAs: ["popoverContent"] }, { kind: "component", type: AggregationComponent, selector: "Aggregation, aggregation", inputs: ["class", "id", "name", "column", "showFiltersCount", "collapsible", "collapsed", "searchable", "showCheckbox", "applyOnSelect", "expandedLevel", "syncUrl", "query", "aggregation", "selection", "emitOn", "type", "hideWhenEmpty"], outputs: ["onSelect", "onApply", "onClear", "selectionChange", "filtersChange"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant", "scheme", "size", "aria-label"] }, { kind: "component", type: FaIconComponent, selector: "fa-icon, FaIcon", inputs: ["faClass", "class"] }, { kind: "pipe", type: OperatorPipe, name: "operator" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: SyslangPipe, name: "syslang" }] });
16362
16370
  }
16363
16371
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: FilterButtonComponent, decorators: [{
16364
16372
  type: Component,
@@ -16409,13 +16417,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
16409
16417
  class="min-w-fit w-max max-w-[90vw]"
16410
16418
  [position]="position()"
16411
16419
  [offset]="offset()"
16420
+ [lockPosition]="lockPosition()"
16412
16421
  >
16413
16422
  @if(contentRef.isVisible) {
16414
16423
  @let name = filter().name;
16415
16424
  @let column = filter().column;
16416
16425
  @if(name) {
16417
16426
  <Aggregation
16418
- class="w-60 [--height:19lh]"
16427
+ class="w-60 [--scroll-height:19lh]"
16419
16428
  id="filter-{{ filter().column }}"
16420
16429
  [name]="name"
16421
16430
  [column]="column"
@@ -16437,11 +16446,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
16437
16446
  role: "listitem"
16438
16447
  }
16439
16448
  }]
16440
- }], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], expandedLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedLevel", required: false }] }], popoverRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => PopoverComponent), { isSignal: true }] }] } });
16449
+ }], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], lockPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockPosition", required: false }] }], expandedLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedLevel", required: false }] }], popoverRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => PopoverComponent), { isSignal: true }] }] } });
16441
16450
 
16442
16451
  const FILTERS_BREAKPOINT = new InjectionToken('FILTERS_BREAKPOINT', { factory: () => 5 });
16443
16452
 
16453
+ /**
16454
+ * Below this many overflow filters, the search input adds friction without
16455
+ * helping — scanning a handful of accordion headers is already fast.
16456
+ */
16457
+ const SEARCH_THRESHOLD = 6;
16444
16458
  class MoreComponent {
16459
+ SEARCH_THRESHOLD = SEARCH_THRESHOLD;
16445
16460
  count = input(2, ...(ngDevMode ? [{ debugName: "count" }] : []));
16446
16461
  includedFilters = input([], ...(ngDevMode ? [{ debugName: "includedFilters" }] : []));
16447
16462
  excludedFilters = input([], ...(ngDevMode ? [{ debugName: "excludedFilters" }] : []));
@@ -16457,6 +16472,7 @@ class MoreComponent {
16457
16472
  */
16458
16473
  hideWhenEmpty = input(false, ...(ngDevMode ? [{ debugName: "hideWhenEmpty", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
16459
16474
  aggregationsService = inject(AggregationsService);
16475
+ searchText = model("", ...(ngDevMode ? [{ debugName: "searchText" }] : []));
16460
16476
  /**
16461
16477
  * The overflow filters rendered as accordions: the authorized filters beyond the
16462
16478
  * first `count` (which are already shown in the bar).
@@ -16469,49 +16485,158 @@ class MoreComponent {
16469
16485
  filters = computed(() => this.aggregationsService
16470
16486
  .getAuthorizedFilters(this.aggregations(), this.includedFilters(), this.excludedFilters(), this.homepage())
16471
16487
  .toSpliced(0, this.count()), ...(ngDevMode ? [{ debugName: "filters" }] : []));
16488
+ /** {@link filters}, narrowed to those matching {@link searchText} (case-insensitive, by name). */
16489
+ filteredFilters = computed(() => {
16490
+ const query = this.searchText().trim().toLowerCase();
16491
+ if (!query)
16492
+ return this.filters();
16493
+ return this.filters().filter(filter => filter.name.toLowerCase().includes(query));
16494
+ }, ...(ngDevMode ? [{ debugName: "filteredFilters" }] : []));
16495
+ clearSearch(e) {
16496
+ e.stopImmediatePropagation();
16497
+ this.searchText.set("");
16498
+ }
16472
16499
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: MoreComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16473
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: MoreComponent, isStandalone: true, selector: "more, More", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, includedFilters: { classPropertyName: "includedFilters", publicName: "includedFilters", isSignal: true, isRequired: false, transformFunction: null }, excludedFilters: { classPropertyName: "excludedFilters", publicName: "excludedFilters", isSignal: true, isRequired: false, transformFunction: null }, aggregations: { classPropertyName: "aggregations", publicName: "aggregations", isSignal: true, isRequired: false, transformFunction: null }, homepage: { classPropertyName: "homepage", publicName: "homepage", isSignal: true, isRequired: false, transformFunction: null }, hideWhenEmpty: { classPropertyName: "hideWhenEmpty", publicName: "hideWhenEmpty", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "divide-y divide-muted-foreground/18" }, ngImport: i0, template: `
16474
- @for (filter of filters(); track $index) {
16475
- <Aggregation
16476
- class="w-60 max-w-80 px-1 [--height:15lh]"
16477
- id="more-filters"
16478
- [attr.title]="'filters.openFilter' | transloco: { filter: filter.name }"
16479
- showFiltersCount
16480
- [collapsible]="true"
16481
- [collapsed]="true"
16482
- [hideWhenEmpty]="hideWhenEmpty()"
16483
- [name]="filter.name"
16484
- [column]="filter.column" />
16500
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: MoreComponent, isStandalone: true, selector: "more, More", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, includedFilters: { classPropertyName: "includedFilters", publicName: "includedFilters", isSignal: true, isRequired: false, transformFunction: null }, excludedFilters: { classPropertyName: "excludedFilters", publicName: "excludedFilters", isSignal: true, isRequired: false, transformFunction: null }, aggregations: { classPropertyName: "aggregations", publicName: "aggregations", isSignal: true, isRequired: false, transformFunction: null }, homepage: { classPropertyName: "homepage", publicName: "homepage", isSignal: true, isRequired: false, transformFunction: null }, hideWhenEmpty: { classPropertyName: "hideWhenEmpty", publicName: "hideWhenEmpty", isSignal: true, isRequired: false, transformFunction: null }, searchText: { classPropertyName: "searchText", publicName: "searchText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchText: "searchTextChange" }, host: { classAttribute: "scrollbar-thin" }, ngImport: i0, template: `
16501
+ @if (filters().length > SEARCH_THRESHOLD) {
16502
+ <div class="sticky top-0 z-10 bg-menu-bg pb-3 shadow-[0_-1px_0_0_var(--color-menu-bg)]">
16503
+ <InputGroup>
16504
+ <input
16505
+ input-group
16506
+ type="text"
16507
+ [attr.aria-label]="'filters.searchFilters' | transloco"
16508
+ [attr.placeholder]="'filters.searchFilters' | transloco"
16509
+ [(ngModel)]="searchText" />
16510
+ <InputGroupAddon>
16511
+ <SearchIcon class="text-foreground size-4" />
16512
+ </InputGroupAddon>
16513
+ <InputGroupAddon align="inline-end" class="gap-0.5!">
16514
+ <icon-button
16515
+ size="sm"
16516
+ [class]="
16517
+ searchText().length > 0
16518
+ ? 'opacity-100 transition-opacity duration-500'
16519
+ : 'pointer-events-none opacity-0 transition-opacity duration-500'
16520
+ "
16521
+ aria-label="Clear search"
16522
+ [tabindex]="searchText().length > 0 ? 0 : -1"
16523
+ (keydown.enter)="clearSearch($event)"
16524
+ (click)="clearSearch($event)">
16525
+ <XMarkIcon />
16526
+ </icon-button>
16527
+ </InputGroupAddon>
16528
+ </InputGroup>
16529
+ </div>
16485
16530
  }
16486
- `, isInline: true, styles: [":host{scrollbar-width:none}\n"], dependencies: [{ kind: "component", type: AggregationComponent, selector: "Aggregation, aggregation", inputs: ["class", "id", "name", "column", "showFiltersCount", "collapsible", "collapsed", "searchable", "showCheckbox", "applyOnSelect", "expandedLevel", "syncUrl", "query", "aggregation", "selection", "emitOn", "type", "hideWhenEmpty"], outputs: ["onSelect", "onApply", "onClear", "selectionChange", "filtersChange"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
16531
+
16532
+ <div class="divide-y divide-muted-foreground/18">
16533
+ @for (filter of filteredFilters(); track filter.name) {
16534
+ <Aggregation
16535
+ class="w-full min-w-60 px-1 [--scroll-height:15lh]"
16536
+ id="more-filters"
16537
+ [attr.title]="'filters.openFilter' | transloco: { filter: filter.name }"
16538
+ showFiltersCount
16539
+ [collapsible]="true"
16540
+ [collapsed]="true"
16541
+ [hideWhenEmpty]="hideWhenEmpty()"
16542
+ [name]="filter.name"
16543
+ [column]="filter.column" />
16544
+ } @empty {
16545
+ @if (searchText().trim().length > 0) {
16546
+ <p class="text-muted-foreground px-2 py-4 text-center text-sm">{{ "filters.noFilterMatch" | transloco }}</p>
16547
+ }
16548
+ }
16549
+ </div>
16550
+ `, isInline: true, dependencies: [{ kind: "component", type: AggregationComponent, selector: "Aggregation, aggregation", inputs: ["class", "id", "name", "column", "showFiltersCount", "collapsible", "collapsed", "searchable", "showCheckbox", "applyOnSelect", "expandedLevel", "syncUrl", "query", "aggregation", "selection", "emitOn", "type", "hideWhenEmpty"], outputs: ["onSelect", "onApply", "onClear", "selectionChange", "filtersChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: InputGroupComponent, selector: "input-group, inputgroup, InputGroup", inputs: ["class"] }, { kind: "directive", type: InputGroupInput, selector: "input[input-group]", inputs: ["class", "type", "placeholder", "disabled"] }, { kind: "directive", type: InputGroupAddonComponent, selector: "input-group-addon, inputgroupaddon, InputGroupAddon", inputs: ["class", "align"] }, { kind: "component", type: SearchIcon, selector: "SearchIcon", inputs: ["class"] }, { kind: "component", type: XMarkIcon, selector: "XMarkIcon, xmark-icon, x-mark-icon", inputs: ["class"] }, { kind: "directive", type: IconButtonComponent, selector: "button[icon-button], icon-button, IconButton", inputs: ["class", "size"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
16487
16551
  }
16488
16552
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: MoreComponent, decorators: [{
16489
16553
  type: Component,
16490
- args: [{ selector: "more, More", standalone: true, imports: [AggregationComponent, TranslocoPipe], template: `
16491
- @for (filter of filters(); track $index) {
16492
- <Aggregation
16493
- class="w-60 max-w-80 px-1 [--height:15lh]"
16494
- id="more-filters"
16495
- [attr.title]="'filters.openFilter' | transloco: { filter: filter.name }"
16496
- showFiltersCount
16497
- [collapsible]="true"
16498
- [collapsed]="true"
16499
- [hideWhenEmpty]="hideWhenEmpty()"
16500
- [name]="filter.name"
16501
- [column]="filter.column" />
16554
+ args: [{
16555
+ selector: "more, More",
16556
+ standalone: true,
16557
+ imports: [
16558
+ AggregationComponent,
16559
+ TranslocoPipe,
16560
+ FormsModule,
16561
+ InputGroupComponent,
16562
+ InputGroupInput,
16563
+ InputGroupAddonComponent,
16564
+ SearchIcon,
16565
+ XMarkIcon,
16566
+ IconButtonComponent
16567
+ ],
16568
+ template: `
16569
+ @if (filters().length > SEARCH_THRESHOLD) {
16570
+ <div class="sticky top-0 z-10 bg-menu-bg pb-3 shadow-[0_-1px_0_0_var(--color-menu-bg)]">
16571
+ <InputGroup>
16572
+ <input
16573
+ input-group
16574
+ type="text"
16575
+ [attr.aria-label]="'filters.searchFilters' | transloco"
16576
+ [attr.placeholder]="'filters.searchFilters' | transloco"
16577
+ [(ngModel)]="searchText" />
16578
+ <InputGroupAddon>
16579
+ <SearchIcon class="text-foreground size-4" />
16580
+ </InputGroupAddon>
16581
+ <InputGroupAddon align="inline-end" class="gap-0.5!">
16582
+ <icon-button
16583
+ size="sm"
16584
+ [class]="
16585
+ searchText().length > 0
16586
+ ? 'opacity-100 transition-opacity duration-500'
16587
+ : 'pointer-events-none opacity-0 transition-opacity duration-500'
16588
+ "
16589
+ aria-label="Clear search"
16590
+ [tabindex]="searchText().length > 0 ? 0 : -1"
16591
+ (keydown.enter)="clearSearch($event)"
16592
+ (click)="clearSearch($event)">
16593
+ <XMarkIcon />
16594
+ </icon-button>
16595
+ </InputGroupAddon>
16596
+ </InputGroup>
16597
+ </div>
16502
16598
  }
16503
- `, host: {
16504
- class: "divide-y divide-muted-foreground/18"
16505
- }, styles: [":host{scrollbar-width:none}\n"] }]
16506
- }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], includedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "includedFilters", required: false }] }], excludedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "excludedFilters", required: false }] }], aggregations: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregations", required: false }] }], homepage: [{ type: i0.Input, args: [{ isSignal: true, alias: "homepage", required: false }] }], hideWhenEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideWhenEmpty", required: false }] }] } });
16599
+
16600
+ <div class="divide-y divide-muted-foreground/18">
16601
+ @for (filter of filteredFilters(); track filter.name) {
16602
+ <Aggregation
16603
+ class="w-full min-w-60 px-1 [--scroll-height:15lh]"
16604
+ id="more-filters"
16605
+ [attr.title]="'filters.openFilter' | transloco: { filter: filter.name }"
16606
+ showFiltersCount
16607
+ [collapsible]="true"
16608
+ [collapsed]="true"
16609
+ [hideWhenEmpty]="hideWhenEmpty()"
16610
+ [name]="filter.name"
16611
+ [column]="filter.column" />
16612
+ } @empty {
16613
+ @if (searchText().trim().length > 0) {
16614
+ <p class="text-muted-foreground px-2 py-4 text-center text-sm">{{ "filters.noFilterMatch" | transloco }}</p>
16615
+ }
16616
+ }
16617
+ </div>
16618
+ `,
16619
+ host: {
16620
+ class: "scrollbar-thin"
16621
+ }
16622
+ }]
16623
+ }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], includedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "includedFilters", required: false }] }], excludedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "excludedFilters", required: false }] }], aggregations: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregations", required: false }] }], homepage: [{ type: i0.Input, args: [{ isSignal: true, alias: "homepage", required: false }] }], hideWhenEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideWhenEmpty", required: false }] }], searchText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchText", required: false }] }, { type: i0.Output, args: ["searchTextChange"] }] } });
16507
16624
 
16508
16625
  class MoreButtonComponent {
16509
16626
  appStore = inject(AppStore);
16510
16627
  queryParamsStore = inject(QueryParamsStore);
16511
16628
  nativeElement = inject(ElementRef).nativeElement;
16629
+ breakpointObserver = inject(BreakpointObserverService);
16512
16630
  aggregationsService = inject(AggregationsService);
16513
16631
  count = input(2, ...(ngDevMode ? [{ debugName: "count", transform: numberAttribute }] : [{ transform: numberAttribute }]));
16514
16632
  position = input("bottom-end", ...(ngDevMode ? [{ debugName: "position" }] : []));
16633
+ /**
16634
+ * When true, forces the popover to stay at the exact `position()` placement,
16635
+ * disabling floating-ui's automatic repositioning based on available viewport space.
16636
+ *
16637
+ * @default false
16638
+ */
16639
+ lockPosition = input(false, ...(ngDevMode ? [{ debugName: "lockPosition", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
16515
16640
  includedFilters = input([], ...(ngDevMode ? [{ debugName: "includedFilters" }] : []));
16516
16641
  excludedFilters = input([], ...(ngDevMode ? [{ debugName: "excludedFilters" }] : []));
16517
16642
  aggregations = input(...(ngDevMode ? [undefined, { debugName: "aggregations" }] : []));
@@ -16524,79 +16649,201 @@ class MoreButtonComponent {
16524
16649
  * @default false
16525
16650
  */
16526
16651
  hideWhenEmpty = input(false, ...(ngDevMode ? [{ debugName: "hideWhenEmpty", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
16527
- totalFiltersCount = computed(() => {
16528
- const count = this.count();
16529
- const authorizedFilters = this.aggregationsService
16530
- .getAuthorizedFilters(this.aggregations(), this.includedFilters(), this.excludedFilters(), this.homepage())
16531
- .toSpliced(0, count);
16532
- const total = authorizedFilters.reduce((acc, filter) => {
16533
- const f = this.queryParamsStore.getFilter(filter);
16534
- acc += f?.count || 0;
16535
- return acc;
16536
- }, 0);
16537
- return total;
16538
- }, ...(ngDevMode ? [{ debugName: "totalFiltersCount" }] : []));
16652
+ /**
16653
+ * Above this many overflow filters, the desktop Popover escalates to a modal
16654
+ * Dialog instead of an anchored popover — useful once there are too many facets
16655
+ * to browse comfortably in an anchored popover. Left unset (the default), the
16656
+ * Popover always shows every overflow facet, however many there are, adapting
16657
+ * its own height to the available space (see `PopoverContentComponent`'s
16658
+ * `size()` middleware) rather than escalating. A commonly-used value is `6`.
16659
+ *
16660
+ * @default undefined — never escalate to Dialog
16661
+ */
16662
+ enrichedThreshold = input(...(ngDevMode ? [undefined, { debugName: "enrichedThreshold" }] : []));
16663
+ /** Mobile drawer open state — the desktop Popover/Dialog manage their own. */
16664
+ sheetOpen = signal(false, ...(ngDevMode ? [{ debugName: "sheetOpen" }] : []));
16665
+ /** The inline enriched Dialog — `<dialog #dialogRefEl>` binds a `DialogComponent` instance to the ref by default. */
16666
+ dialogRef = viewChild("dialogRefEl", ...(ngDevMode ? [{ debugName: "dialogRef" }] : []));
16667
+ /** The authorized filters beyond the first `count` already shown in the bar. */
16668
+ overflowFilters = computed(() => this.aggregationsService
16669
+ .getAuthorizedFilters(this.aggregations(), this.includedFilters(), this.excludedFilters(), this.homepage())
16670
+ .toSpliced(0, this.count()), ...(ngDevMode ? [{ debugName: "overflowFilters" }] : []));
16671
+ totalFiltersCount = computed(() => this.overflowFilters().reduce((acc, filter) => {
16672
+ const f = this.queryParamsStore.getFilter(filter);
16673
+ acc += f?.count || 0;
16674
+ return acc;
16675
+ }, 0), ...(ngDevMode ? [{ debugName: "totalFiltersCount" }] : []));
16676
+ /**
16677
+ * Above {@link enrichedThreshold} overflow filters, the popover escalates to a modal
16678
+ * Dialog. Always `false` while `enrichedThreshold` is unset — the Popover then shows
16679
+ * every overflow facet regardless of count.
16680
+ */
16681
+ isEnriched = computed(() => {
16682
+ const threshold = this.enrichedThreshold();
16683
+ return threshold !== undefined && this.overflowFilters().length > threshold;
16684
+ }, ...(ngDevMode ? [{ debugName: "isEnriched" }] : []));
16539
16685
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: MoreButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16540
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: MoreButtonComponent, isStandalone: true, selector: "more-button, MoreButton", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, includedFilters: { classPropertyName: "includedFilters", publicName: "includedFilters", isSignal: true, isRequired: false, transformFunction: null }, excludedFilters: { classPropertyName: "excludedFilters", publicName: "excludedFilters", isSignal: true, isRequired: false, transformFunction: null }, aggregations: { classPropertyName: "aggregations", publicName: "aggregations", isSignal: true, isRequired: false, transformFunction: null }, homepage: { classPropertyName: "homepage", publicName: "homepage", isSignal: true, isRequired: false, transformFunction: null }, hideWhenEmpty: { classPropertyName: "hideWhenEmpty", publicName: "hideWhenEmpty", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
16541
- <Popover class="group/more">
16542
- <button
16543
- variant="ghost"
16544
- class="group-open/more:border-foreground/18 gap-1 truncate font-semibold group-open/more:border"
16545
- aria-label="more filters">
16546
- <list-filter-icon aria-hidden="true" />
16547
- <span sr-only class="hidden sm:inline">{{ 'filters.moreFilters' | transloco }}</span>
16548
-
16549
- @if (totalFiltersCount() > 0) {
16550
- <Badge size="xs">
16551
- {{ totalFiltersCount() }}
16552
- </Badge>
16553
- }
16686
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: MoreButtonComponent, isStandalone: true, selector: "more-button, MoreButton", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, lockPosition: { classPropertyName: "lockPosition", publicName: "lockPosition", isSignal: true, isRequired: false, transformFunction: null }, includedFilters: { classPropertyName: "includedFilters", publicName: "includedFilters", isSignal: true, isRequired: false, transformFunction: null }, excludedFilters: { classPropertyName: "excludedFilters", publicName: "excludedFilters", isSignal: true, isRequired: false, transformFunction: null }, aggregations: { classPropertyName: "aggregations", publicName: "aggregations", isSignal: true, isRequired: false, transformFunction: null }, homepage: { classPropertyName: "homepage", publicName: "homepage", isSignal: true, isRequired: false, transformFunction: null }, hideWhenEmpty: { classPropertyName: "hideWhenEmpty", publicName: "hideWhenEmpty", isSignal: true, isRequired: false, transformFunction: null }, enrichedThreshold: { classPropertyName: "enrichedThreshold", publicName: "enrichedThreshold", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideTranslocoScope("filters")], viewQueries: [{ propertyName: "dialogRef", first: true, predicate: ["dialogRefEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
16687
+ <ng-template #trigger>
16688
+ <list-filter-icon aria-hidden="true" />
16689
+ <span sr-only class="hidden sm:inline">{{ 'filters.moreFilters' | transloco }}</span>
16690
+
16691
+ @if (totalFiltersCount() > 0) {
16692
+ <Badge size="xs">
16693
+ {{ totalFiltersCount() }}
16694
+ </Badge>
16695
+ }
16696
+ </ng-template>
16697
+
16698
+ @if (breakpointObserver.isMobile()) {
16699
+ <button variant="ghost" class="gap-1 truncate font-semibold" aria-label="more filters" (click)="sheetOpen.set(true)">
16700
+ <ng-container *ngTemplateOutlet="trigger" />
16554
16701
  </button>
16555
16702
 
16556
- <PopoverContent #contentRef="popoverContent" [position]="position()" class="min-w-max">
16557
- @if(contentRef.isVisible) {
16558
- <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block h-full w-full max-w-80 [--height:55vh] min-w-40 overflow-hidden" />
16559
- }
16560
- </PopoverContent>
16561
- </Popover>
16562
- `, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["class", "position", "keepOpen", "offset", "strategy"], exportAs: ["popoverContent"] }, { kind: "component", type: MoreComponent, selector: "more, More", inputs: ["count", "includedFilters", "excludedFilters", "aggregations", "homepage", "hideWhenEmpty"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant", "scheme", "size", "aria-label"] }, { kind: "component", type: ListFilterIcon, selector: "list-filter-icon, ListFilterIcon", inputs: ["class"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
16703
+ <sheet [open]="sheetOpen()" (openChange)="sheetOpen.set($event)" side="bottom" class="max-w-none">
16704
+ <sheet-header>
16705
+ <sheet-title>{{ 'filters.moreFilters' | transloco }}</sheet-title>
16706
+ </sheet-header>
16707
+ <div class="max-h-[75vh] overflow-y-auto overscroll-contain">
16708
+ <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
16709
+ </div>
16710
+ </sheet>
16711
+ } @else if (isEnriched()) {
16712
+ <button variant="ghost" class="gap-1 truncate font-semibold" aria-label="more filters" (click)="dialogRef()?.showModal()">
16713
+ <ng-container *ngTemplateOutlet="trigger" />
16714
+ </button>
16715
+
16716
+ <dialog #dialogRefEl>
16717
+ <DialogContent class="sm:max-w-lg rounded-(--radius-xl,1rem)">
16718
+ <DialogHeader>
16719
+ <DialogTitle>{{ 'filters.moreFilters' | transloco }}</DialogTitle>
16720
+ </DialogHeader>
16721
+ <div class="max-h-[60vh] overflow-y-auto overscroll-contain">
16722
+ <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
16723
+ </div>
16724
+ </DialogContent>
16725
+ </dialog>
16726
+ } @else {
16727
+ <Popover class="group/more">
16728
+ <button
16729
+ variant="ghost"
16730
+ class="group-open/more:border-foreground/18 gap-1 truncate font-semibold group-open/more:border"
16731
+ aria-label="more filters">
16732
+ <ng-container *ngTemplateOutlet="trigger" />
16733
+ </button>
16734
+
16735
+ <PopoverContent #contentRef="popoverContent" [position]="position()" [lockPosition]="lockPosition()" class="min-w-max max-w-80 min-w-40 rounded-(--radius-xl,1rem) p-5">
16736
+ @if(contentRef.isVisible) {
16737
+ <div class="max-h-[calc(var(--popover-available-height,55vh)_-_2.5rem)] overflow-y-auto overscroll-contain">
16738
+ <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
16739
+ </div>
16740
+ }
16741
+ </PopoverContent>
16742
+ </Popover>
16743
+ }
16744
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "component", type: PopoverComponent, selector: "popover, Popover", inputs: ["disabled", "closeOnScroll"], outputs: ["closed"] }, { kind: "directive", type: PopoverContentComponent, selector: "popover-content, PopoverContent, popovercontent", inputs: ["class", "position", "keepOpen", "offset", "strategy", "lockPosition"], exportAs: ["popoverContent"] }, { kind: "component", type: MoreComponent, selector: "more, More", inputs: ["count", "includedFilters", "excludedFilters", "aggregations", "homepage", "hideWhenEmpty", "searchText"], outputs: ["searchTextChange"] }, { kind: "directive", type: BadgeComponent, selector: "badge, Badge", inputs: ["class", "variant", "scheme", "size", "aria-label"] }, { kind: "component", type: ListFilterIcon, selector: "list-filter-icon, ListFilterIcon", inputs: ["class"] }, { kind: "component", type: SheetComponent, selector: "sheet", inputs: ["open", "side", "class", "showCloseButton"], outputs: ["openChange"] }, { kind: "directive", type: SheetHeaderComponent, selector: "sheet-header", inputs: ["class"] }, { kind: "directive", type: SheetTitleComponent, selector: "sheet-title", inputs: ["class"] }, { kind: "component", type: DialogComponent, selector: "dialog, [dialog]", outputs: ["closed"], exportAs: ["dialog"] }, { kind: "directive", type: DialogContentComponent, selector: "DialogContent", inputs: ["class"] }, { kind: "component", type: DialogHeaderComponent, selector: "DialogHeader" }, { kind: "directive", type: DialogTitleComponent, selector: "DialogTitle", inputs: ["class"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
16563
16745
  }
16564
16746
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: MoreButtonComponent, decorators: [{
16565
16747
  type: Component,
16566
16748
  args: [{
16567
16749
  selector: "more-button, MoreButton",
16568
16750
  standalone: true,
16569
- imports: [ButtonComponent, PopoverComponent, PopoverContentComponent, TranslocoPipe, MoreComponent, BadgeComponent, ListFilterIcon],
16751
+ imports: [
16752
+ NgTemplateOutlet,
16753
+ ButtonComponent,
16754
+ PopoverComponent,
16755
+ PopoverContentComponent,
16756
+ TranslocoPipe,
16757
+ MoreComponent,
16758
+ BadgeComponent,
16759
+ ListFilterIcon,
16760
+ SheetComponent,
16761
+ SheetHeaderComponent,
16762
+ SheetTitleComponent,
16763
+ DialogComponent,
16764
+ DialogContentComponent,
16765
+ DialogHeaderComponent,
16766
+ DialogTitleComponent
16767
+ ],
16570
16768
  template: `
16571
- <Popover class="group/more">
16572
- <button
16573
- variant="ghost"
16574
- class="group-open/more:border-foreground/18 gap-1 truncate font-semibold group-open/more:border"
16575
- aria-label="more filters">
16576
- <list-filter-icon aria-hidden="true" />
16577
- <span sr-only class="hidden sm:inline">{{ 'filters.moreFilters' | transloco }}</span>
16578
-
16579
- @if (totalFiltersCount() > 0) {
16580
- <Badge size="xs">
16581
- {{ totalFiltersCount() }}
16582
- </Badge>
16583
- }
16769
+ <ng-template #trigger>
16770
+ <list-filter-icon aria-hidden="true" />
16771
+ <span sr-only class="hidden sm:inline">{{ 'filters.moreFilters' | transloco }}</span>
16772
+
16773
+ @if (totalFiltersCount() > 0) {
16774
+ <Badge size="xs">
16775
+ {{ totalFiltersCount() }}
16776
+ </Badge>
16777
+ }
16778
+ </ng-template>
16779
+
16780
+ @if (breakpointObserver.isMobile()) {
16781
+ <button variant="ghost" class="gap-1 truncate font-semibold" aria-label="more filters" (click)="sheetOpen.set(true)">
16782
+ <ng-container *ngTemplateOutlet="trigger" />
16584
16783
  </button>
16585
16784
 
16586
- <PopoverContent #contentRef="popoverContent" [position]="position()" class="min-w-max">
16587
- @if(contentRef.isVisible) {
16588
- <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block h-full w-full max-w-80 [--height:55vh] min-w-40 overflow-hidden" />
16589
- }
16590
- </PopoverContent>
16591
- </Popover>
16592
- `
16785
+ <sheet [open]="sheetOpen()" (openChange)="sheetOpen.set($event)" side="bottom" class="max-w-none">
16786
+ <sheet-header>
16787
+ <sheet-title>{{ 'filters.moreFilters' | transloco }}</sheet-title>
16788
+ </sheet-header>
16789
+ <div class="max-h-[75vh] overflow-y-auto overscroll-contain">
16790
+ <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
16791
+ </div>
16792
+ </sheet>
16793
+ } @else if (isEnriched()) {
16794
+ <button variant="ghost" class="gap-1 truncate font-semibold" aria-label="more filters" (click)="dialogRef()?.showModal()">
16795
+ <ng-container *ngTemplateOutlet="trigger" />
16796
+ </button>
16797
+
16798
+ <dialog #dialogRefEl>
16799
+ <DialogContent class="sm:max-w-lg rounded-(--radius-xl,1rem)">
16800
+ <DialogHeader>
16801
+ <DialogTitle>{{ 'filters.moreFilters' | transloco }}</DialogTitle>
16802
+ </DialogHeader>
16803
+ <div class="max-h-[60vh] overflow-y-auto overscroll-contain">
16804
+ <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
16805
+ </div>
16806
+ </DialogContent>
16807
+ </dialog>
16808
+ } @else {
16809
+ <Popover class="group/more">
16810
+ <button
16811
+ variant="ghost"
16812
+ class="group-open/more:border-foreground/18 gap-1 truncate font-semibold group-open/more:border"
16813
+ aria-label="more filters">
16814
+ <ng-container *ngTemplateOutlet="trigger" />
16815
+ </button>
16816
+
16817
+ <PopoverContent #contentRef="popoverContent" [position]="position()" [lockPosition]="lockPosition()" class="min-w-max max-w-80 min-w-40 rounded-(--radius-xl,1rem) p-5">
16818
+ @if(contentRef.isVisible) {
16819
+ <div class="max-h-[calc(var(--popover-available-height,55vh)_-_2.5rem)] overflow-y-auto overscroll-contain">
16820
+ <More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
16821
+ </div>
16822
+ }
16823
+ </PopoverContent>
16824
+ </Popover>
16825
+ }
16826
+ `,
16827
+ // Self-registers the scope so <more-button> resolves its own translations when used
16828
+ // standalone, outside <filters-bar> (which already registers it too — harmless overlap).
16829
+ providers: [provideTranslocoScope("filters")]
16593
16830
  }]
16594
- }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], includedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "includedFilters", required: false }] }], excludedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "excludedFilters", required: false }] }], aggregations: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregations", required: false }] }], homepage: [{ type: i0.Input, args: [{ isSignal: true, alias: "homepage", required: false }] }], hideWhenEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideWhenEmpty", required: false }] }] } });
16831
+ }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], lockPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockPosition", required: false }] }], includedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "includedFilters", required: false }] }], excludedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "excludedFilters", required: false }] }], aggregations: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregations", required: false }] }], homepage: [{ type: i0.Input, args: [{ isSignal: true, alias: "homepage", required: false }] }], hideWhenEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideWhenEmpty", required: false }] }], enrichedThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "enrichedThreshold", required: false }] }], dialogRef: [{ type: i0.ViewChild, args: ["dialogRefEl", { isSignal: true }] }] } });
16595
16832
 
16596
16833
  class FiltersBarComponent {
16597
16834
  class = input(...(ngDevMode ? [undefined, { debugName: "class" }] : []));
16598
16835
  position = input("bottom-start", ...(ngDevMode ? [{ debugName: "position" }] : []));
16599
16836
  morePosition = input("bottom-end", ...(ngDevMode ? [{ debugName: "morePosition" }] : []));
16837
+ /**
16838
+ * When true, forces every popover (filter buttons and the "more filters"
16839
+ * button) to stay at its exact `position()`/`morePosition()` placement,
16840
+ * disabling floating-ui's automatic repositioning based on available
16841
+ * viewport space. Relayed as-is to each `<FilterButton [lockPosition]>`
16842
+ * and to `<MoreButton [lockPosition]>`.
16843
+ *
16844
+ * @default false
16845
+ */
16846
+ lockPosition = input(false, ...(ngDevMode ? [{ debugName: "lockPosition", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
16600
16847
  aggregations = input(...(ngDevMode ? [undefined, { debugName: "aggregations" }] : []));
16601
16848
  /**
16602
16849
  * Filters that should be included from the filters bar.
@@ -16700,7 +16947,7 @@ class FiltersBarComponent {
16700
16947
  allAuthorizedFilters = computed(() => {
16701
16948
  return this.aggregationsService
16702
16949
  .getAuthorizedFilters(this.aggregations(), this.includeFilters(), this.excludeFilters(), this.homepage())
16703
- .map((f) => ({ name: f.name, column: f.column }));
16950
+ .map(f => ({ name: f.name, column: f.column }));
16704
16951
  }, ...(ngDevMode ? [{ debugName: "allAuthorizedFilters" }] : []));
16705
16952
  /**
16706
16953
  * Computes the list of additional filters that can be displayed in the "more filters" popover.
@@ -16717,7 +16964,7 @@ class FiltersBarComponent {
16717
16964
  hasMoreFilters = computed(() => {
16718
16965
  const moreFiltersAggregations = this.allAuthorizedFilters()
16719
16966
  .toSpliced(0, this.visibleFiltersCount())
16720
- .map((f) => this.aggregationsStore.getAggregation(f.column, "column"));
16967
+ .map(f => this.aggregationsStore.getAggregation(f.column, "column"));
16721
16968
  return moreFiltersAggregations;
16722
16969
  }, ...(ngDevMode ? [{ debugName: "hasMoreFilters" }] : []));
16723
16970
  /**
@@ -16739,9 +16986,7 @@ class FiltersBarComponent {
16739
16986
  */
16740
16987
  hasCappedFilters = computed(() => this.allAuthorizedFilters().length > this.filtersCount(), ...(ngDevMode ? [{ debugName: "hasCappedFilters" }] : []));
16741
16988
  constructor() {
16742
- this.transloco.events$
16743
- .pipe(takeUntilDestroyed(this.destroyRef), debounceTime(100))
16744
- .subscribe(() => this.overflowManagerRef()?.countItems());
16989
+ this.transloco.events$.pipe(takeUntilDestroyed(this.destroyRef), debounceTime(100)).subscribe(() => this.overflowManagerRef()?.countItems());
16745
16990
  // Recount the overflow whenever the applied filters or basket change (e.g.
16746
16991
  // a filter modified or removed from the "more filters" popover). A
16747
16992
  // FilterButton hidden by the overflow manager (display: none) emits no
@@ -16800,12 +17045,12 @@ class FiltersBarComponent {
16800
17045
  * @param event - The mouse event triggered by the user's click.
16801
17046
  */
16802
17047
  handleClick(event) {
16803
- this.filterButtonRefs().forEach((ref) => {
17048
+ this.filterButtonRefs().forEach(ref => {
16804
17049
  ref.popoverRef()?.onClick(event);
16805
17050
  });
16806
17051
  }
16807
17052
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: FiltersBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16808
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: FiltersBarComponent, isStandalone: true, selector: "filters-bar, FiltersBar, filtersbar", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, morePosition: { classPropertyName: "morePosition", publicName: "morePosition", isSignal: true, isRequired: false, transformFunction: null }, aggregations: { classPropertyName: "aggregations", publicName: "aggregations", isSignal: true, isRequired: false, transformFunction: null }, includeFilters: { classPropertyName: "includeFilters", publicName: "includeFilters", isSignal: true, isRequired: false, transformFunction: null }, excludeFilters: { classPropertyName: "excludeFilters", publicName: "excludeFilters", isSignal: true, isRequired: false, transformFunction: null }, filtersCount: { classPropertyName: "filtersCount", publicName: "filtersCount", isSignal: true, isRequired: false, transformFunction: null }, showMoreFiltersButton: { classPropertyName: "showMoreFiltersButton", publicName: "showMoreFiltersButton", isSignal: true, isRequired: false, transformFunction: null }, homepage: { classPropertyName: "homepage", publicName: "homepage", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, expandedLevel: { classPropertyName: "expandedLevel", publicName: "expandedLevel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClearFilters: "onClearFilters", onClearBasket: "onClearBasket" }, host: { listeners: { "click": "handleClick($event)" }, properties: { "class": "cn('block relative min-w-0', class())" } }, providers: [provideTranslocoScope("filters")], viewQueries: [{ propertyName: "moreButtonRef", first: true, predicate: MoreButtonComponent, descendants: true, isSignal: true }, { propertyName: "filterButtonRefs", predicate: FilterButtonComponent, descendants: true, isSignal: true }, { propertyName: "overflowManagerRef", first: true, predicate: OverflowManagerDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
17053
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.29", type: FiltersBarComponent, isStandalone: true, selector: "filters-bar, FiltersBar, filtersbar", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, morePosition: { classPropertyName: "morePosition", publicName: "morePosition", isSignal: true, isRequired: false, transformFunction: null }, lockPosition: { classPropertyName: "lockPosition", publicName: "lockPosition", isSignal: true, isRequired: false, transformFunction: null }, aggregations: { classPropertyName: "aggregations", publicName: "aggregations", isSignal: true, isRequired: false, transformFunction: null }, includeFilters: { classPropertyName: "includeFilters", publicName: "includeFilters", isSignal: true, isRequired: false, transformFunction: null }, excludeFilters: { classPropertyName: "excludeFilters", publicName: "excludeFilters", isSignal: true, isRequired: false, transformFunction: null }, filtersCount: { classPropertyName: "filtersCount", publicName: "filtersCount", isSignal: true, isRequired: false, transformFunction: null }, showMoreFiltersButton: { classPropertyName: "showMoreFiltersButton", publicName: "showMoreFiltersButton", isSignal: true, isRequired: false, transformFunction: null }, homepage: { classPropertyName: "homepage", publicName: "homepage", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, expandedLevel: { classPropertyName: "expandedLevel", publicName: "expandedLevel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClearFilters: "onClearFilters", onClearBasket: "onClearBasket" }, host: { listeners: { "click": "handleClick($event)" }, properties: { "class": "cn('block relative min-w-0', class())" } }, providers: [provideTranslocoScope("filters")], viewQueries: [{ propertyName: "moreButtonRef", first: true, predicate: MoreButtonComponent, descendants: true, isSignal: true }, { propertyName: "filterButtonRefs", predicate: FilterButtonComponent, descendants: true, isSignal: true }, { propertyName: "overflowManagerRef", first: true, predicate: OverflowManagerDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
16809
17054
  <div overflowManager [direction]="direction()" [reserveStop]="hasCappedFilters()" (count)="adjustFiltersCount($event)" class="flex items-end gap-2 rounded-[inherit] bg-inherit">
16810
17055
  @if (hasFilters()) {
16811
17056
  <button
@@ -16839,7 +17084,7 @@ class FiltersBarComponent {
16839
17084
  role="list"
16840
17085
  aria-label="Filters list">
16841
17086
  @for (filter of authorizedFilters(); track filter.name) {
16842
- <FilterButton class="max-w-60" overflowItem [name]="filter.name" [column]="filter.column" [position]="position()" [offset]="offset()" [expandedLevel]="expandedLevel()" />
17087
+ <FilterButton class="max-w-60" overflowItem [name]="filter.name" [column]="filter.column" [position]="position()" [lockPosition]="lockPosition()" [offset]="offset()" [expandedLevel]="expandedLevel()" />
16843
17088
  }
16844
17089
  </div>
16845
17090
 
@@ -16851,6 +17096,7 @@ class FiltersBarComponent {
16851
17096
  role="listitem"
16852
17097
  [count]="visibleFiltersCount()"
16853
17098
  [position]="morePosition()"
17099
+ [lockPosition]="lockPosition()"
16854
17100
  [includedFilters]="includeFilters()"
16855
17101
  [excludedFilters]="excludeFilters()"
16856
17102
  [aggregations]="aggregations()"
@@ -16858,7 +17104,7 @@ class FiltersBarComponent {
16858
17104
  }
16859
17105
  }
16860
17106
  </div>
16861
- `, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "component", type: MoreButtonComponent, selector: "more-button, MoreButton", inputs: ["count", "position", "includedFilters", "excludedFilters", "aggregations", "homepage", "hideWhenEmpty"] }, { kind: "component", type: FilterButtonComponent, selector: "filter-button, FilterButton", inputs: ["name", "column", "position", "offset", "expandedLevel"] }, { kind: "directive", type: OverflowManagerDirective, selector: "[overflowManager]", inputs: ["target", "margin", "direction", "reserveStop"], outputs: ["count"] }, { kind: "directive", type: OverflowItemDirective, selector: "[overflowItem]" }, { kind: "directive", type: OverflowStopDirective, selector: "[overflowStop]" }, { kind: "component", type: TrashCanIcon, selector: "trash-can-icon, TrashCanIcon", inputs: ["class"] }, { kind: "component", type: InboxIcon, selector: "inbox-icon, InboxIcon", inputs: ["class"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
17107
+ `, isInline: true, dependencies: [{ kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "component", type: MoreButtonComponent, selector: "more-button, MoreButton", inputs: ["count", "position", "lockPosition", "includedFilters", "excludedFilters", "aggregations", "homepage", "hideWhenEmpty", "enrichedThreshold"] }, { kind: "component", type: FilterButtonComponent, selector: "filter-button, FilterButton", inputs: ["name", "column", "position", "offset", "lockPosition", "expandedLevel"] }, { kind: "directive", type: OverflowManagerDirective, selector: "[overflowManager]", inputs: ["target", "margin", "direction", "reserveStop"], outputs: ["count"] }, { kind: "directive", type: OverflowItemDirective, selector: "[overflowItem]" }, { kind: "directive", type: OverflowStopDirective, selector: "[overflowStop]" }, { kind: "component", type: TrashCanIcon, selector: "trash-can-icon, TrashCanIcon", inputs: ["class"] }, { kind: "component", type: InboxIcon, selector: "inbox-icon, InboxIcon", inputs: ["class"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
16862
17108
  }
16863
17109
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: FiltersBarComponent, decorators: [{
16864
17110
  type: Component,
@@ -16911,7 +17157,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
16911
17157
  role="list"
16912
17158
  aria-label="Filters list">
16913
17159
  @for (filter of authorizedFilters(); track filter.name) {
16914
- <FilterButton class="max-w-60" overflowItem [name]="filter.name" [column]="filter.column" [position]="position()" [offset]="offset()" [expandedLevel]="expandedLevel()" />
17160
+ <FilterButton class="max-w-60" overflowItem [name]="filter.name" [column]="filter.column" [position]="position()" [lockPosition]="lockPosition()" [offset]="offset()" [expandedLevel]="expandedLevel()" />
16915
17161
  }
16916
17162
  </div>
16917
17163
 
@@ -16923,6 +17169,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
16923
17169
  role="listitem"
16924
17170
  [count]="visibleFiltersCount()"
16925
17171
  [position]="morePosition()"
17172
+ [lockPosition]="lockPosition()"
16926
17173
  [includedFilters]="includeFilters()"
16927
17174
  [excludedFilters]="excludeFilters()"
16928
17175
  [aggregations]="aggregations()"
@@ -16936,7 +17183,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
16936
17183
  "(click)": "handleClick($event)"
16937
17184
  }
16938
17185
  }]
16939
- }], ctorParameters: () => [], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], morePosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "morePosition", required: false }] }], aggregations: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregations", required: false }] }], includeFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "includeFilters", required: false }] }], excludeFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "excludeFilters", required: false }] }], filtersCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtersCount", required: false }] }], showMoreFiltersButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMoreFiltersButton", required: false }] }], homepage: [{ type: i0.Input, args: [{ isSignal: true, alias: "homepage", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], expandedLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedLevel", required: false }] }], onClearFilters: [{ type: i0.Output, args: ["onClearFilters"] }], onClearBasket: [{ type: i0.Output, args: ["onClearBasket"] }], moreButtonRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MoreButtonComponent), { isSignal: true }] }], filterButtonRefs: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => FilterButtonComponent), { isSignal: true }] }], overflowManagerRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => OverflowManagerDirective), { isSignal: true }] }] } });
17186
+ }], ctorParameters: () => [], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], morePosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "morePosition", required: false }] }], lockPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockPosition", required: false }] }], aggregations: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregations", required: false }] }], includeFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "includeFilters", required: false }] }], excludeFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "excludeFilters", required: false }] }], filtersCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtersCount", required: false }] }], showMoreFiltersButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMoreFiltersButton", required: false }] }], homepage: [{ type: i0.Input, args: [{ isSignal: true, alias: "homepage", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], expandedLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedLevel", required: false }] }], onClearFilters: [{ type: i0.Output, args: ["onClearFilters"] }], onClearBasket: [{ type: i0.Output, args: ["onClearBasket"] }], moreButtonRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MoreButtonComponent), { isSignal: true }] }], filterButtonRefs: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => FilterButtonComponent), { isSignal: true }] }], overflowManagerRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => OverflowManagerDirective), { isSignal: true }] }] } });
16940
17187
 
16941
17188
  class LabelService {
16942
17189
  appStore = inject(AppStore);