@sinequa/atomic-angular 1.13.0 → 1.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -2,12 +2,12 @@ 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,
|
|
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';
|
|
9
9
|
import { signalStore, signalStoreFeature, withState, withMethods, patchState, getState, withComputed } from '@ngrx/signals';
|
|
10
|
-
import { EngineType, fetchApp, extraColumns, sysLang, fetchPrincipal, globalConfig, filter, getQueryParamsFromUrl, isRedirectPending, info, clearSessionTokens, login, error, setGlobalConfig, initializeAppConfig, notify, addConcepts, queryParamsFromUrl, patchUserSettings, deleteUserSettings, fetchUserSettings, warn, buildPathsAndLevels, escapeExpr, fetchQuery, isAuthenticated, isExpired, debug, AuditEventType, fetchSuggest, isObject, Audit, getMetadata, bisect, isNotInputEvent, fetchSponsoredLinks, translateAggregationToDateOptions, aggItemRegex, parseValueAndOperatorFromItem, fetchSuggestField, fetchSimilarDocuments, logout, fetchChangePassword, fetchSendPasswordResetEmail, expiresSoon, suggestionsToTreeAggregationNodes, labels, fetchLabels, guid, getRelativeDate, createUserProfile, deleteUserProfileProperty, patchUserProfile, isJsonable, addAuditAdditionalInfo, getToken, setToken, createHeaders } from '@sinequa/atomic';
|
|
10
|
+
import { EngineType, fetchApp, extraColumns, sysLang, fetchPrincipal, globalConfig, filter, getQueryParamsFromUrl, isRedirectPending, info, clearSessionTokens, login, error, setGlobalConfig, initializeAppConfig, notify, addConcepts, queryParamsFromUrl, patchUserSettings, deleteUserSettings, fetchUserSettings, warn, buildPathsAndLevels, escapeExpr, fetchQuery, flattenLegacyFilterValues, isAuthenticated, isExpired, debug, AuditEventType, fetchSuggest, isObject, Audit, getMetadata, bisect, isNotInputEvent, fetchSponsoredLinks, translateAggregationToDateOptions, aggItemRegex, parseValueAndOperatorFromItem, fetchSuggestField, fetchSimilarDocuments, logout, fetchChangePassword, fetchSendPasswordResetEmail, expiresSoon, suggestionsToTreeAggregationNodes, labels, fetchLabels, guid, getRelativeDate, createUserProfile, deleteUserProfileProperty, patchUserProfile, isJsonable, addAuditAdditionalInfo, getToken, setToken, createHeaders } from '@sinequa/atomic';
|
|
11
11
|
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
|
|
12
12
|
import { DatePipe, DATE_PIPE_DEFAULT_TIMEZONE, DATE_PIPE_DEFAULT_OPTIONS, Location, NgTemplateOutlet, NgStyle, NgClass, NgComponentOutlet } from '@angular/common';
|
|
13
13
|
import { HttpClient, HttpParams, httpResource, HttpResponse, HttpContextToken, HttpHeaders } from '@angular/common/http';
|
|
@@ -3526,7 +3526,7 @@ class AggregationsService {
|
|
|
3526
3526
|
else {
|
|
3527
3527
|
// get current filters for the aggregation
|
|
3528
3528
|
const filters = this.queryParamsStore.getFilter({ field: agg.column, name: agg.name });
|
|
3529
|
-
flattenedValues = filters ?
|
|
3529
|
+
flattenedValues = filters ? flattenLegacyFilterValues([filters]) : [];
|
|
3530
3530
|
}
|
|
3531
3531
|
if (agg.isTree) {
|
|
3532
3532
|
const selectedAgg = agg.items.map(item => this.selectNode(item, flattenedValues));
|
|
@@ -3563,34 +3563,44 @@ class AggregationsService {
|
|
|
3563
3563
|
*/
|
|
3564
3564
|
toFilter(item, field, name, isDistribution) {
|
|
3565
3565
|
if (isDistribution) {
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
if (filters.length === 2) {
|
|
3575
|
-
return {
|
|
3576
|
-
operator: "and",
|
|
3577
|
-
filters,
|
|
3578
|
-
display: filters[0].display || filters[0].value,
|
|
3579
|
-
field,
|
|
3580
|
-
name
|
|
3581
|
-
};
|
|
3582
|
-
}
|
|
3583
|
-
else if (filters.length === 1) {
|
|
3584
|
-
return { ...filters[0], field, name };
|
|
3585
|
-
}
|
|
3586
|
-
throw new Error("Failed to parse distribution expression");
|
|
3566
|
+
// Parsing lives in @sinequa/atomic — `filter.distribution` is the single implementation, and it
|
|
3567
|
+
// recognises all four bounds where this method only ever produced `gte` or `lt`, reading `>` as
|
|
3568
|
+
// `gte` and `<=` as `lt`. What is added here is what the store needs and a `Filter` has no room
|
|
3569
|
+
// for: the aggregation's `name` on every leaf, which is what makes `updateFilter` replace the
|
|
3570
|
+
// entry rather than merge into it, and the human-readable `display`.
|
|
3571
|
+
const parsed = filter.distribution(field, item.value);
|
|
3572
|
+
if (parsed) {
|
|
3573
|
+
return this.nameLeaves(parsed, field, name, item.display || String(item.value ?? ""));
|
|
3587
3574
|
}
|
|
3575
|
+
throw new Error("Failed to parse distribution expression");
|
|
3588
3576
|
}
|
|
3589
3577
|
if (typeof item.value === "string") {
|
|
3590
3578
|
return { name, field, value: item.value, operator: "contains", display: item.display };
|
|
3591
3579
|
}
|
|
3592
3580
|
return { name, field, value: item.value, display: item.display };
|
|
3593
3581
|
}
|
|
3582
|
+
/**
|
|
3583
|
+
* Stamps the aggregation's `name` and the item's `display` onto a filter parsed by
|
|
3584
|
+
* `filter.distribution`.
|
|
3585
|
+
*
|
|
3586
|
+
* A `Filter` carries neither, and the store needs both: `name` is what
|
|
3587
|
+
* `QueryParamsStore.updateFilter` matches on to **replace** an aggregation's entry instead of merging
|
|
3588
|
+
* into it — the only way a selection can shrink — and `display` is the label the applied-filter chips
|
|
3589
|
+
* render. A combined filter also keeps `field` at its root, which is how the store finds the entry.
|
|
3590
|
+
*/
|
|
3591
|
+
nameLeaves(parsed, field, name, display) {
|
|
3592
|
+
const leaves = parsed.filters;
|
|
3593
|
+
if (leaves?.length) {
|
|
3594
|
+
return {
|
|
3595
|
+
...parsed,
|
|
3596
|
+
field,
|
|
3597
|
+
name,
|
|
3598
|
+
display,
|
|
3599
|
+
filters: leaves.map(leaf => ({ ...leaf, field, name, display }))
|
|
3600
|
+
};
|
|
3601
|
+
}
|
|
3602
|
+
return { ...parsed, field, name, display };
|
|
3603
|
+
}
|
|
3594
3604
|
findNode(items, path = "") {
|
|
3595
3605
|
if (!items || items.length === 0) {
|
|
3596
3606
|
return undefined;
|
|
@@ -3638,27 +3648,6 @@ class AggregationsService {
|
|
|
3638
3648
|
}
|
|
3639
3649
|
return node;
|
|
3640
3650
|
}
|
|
3641
|
-
flattenFilters(filters) {
|
|
3642
|
-
const flattenedValues = [];
|
|
3643
|
-
function extractValues(filters) {
|
|
3644
|
-
for (const filter of filters) {
|
|
3645
|
-
if (filter.value) {
|
|
3646
|
-
flattenedValues.push(filter.value);
|
|
3647
|
-
if (filter.display)
|
|
3648
|
-
flattenedValues.push(filter.display);
|
|
3649
|
-
// we handle "values" field for trees
|
|
3650
|
-
}
|
|
3651
|
-
else if (filter.values) {
|
|
3652
|
-
flattenedValues.push(...filter.values);
|
|
3653
|
-
}
|
|
3654
|
-
if (filter.filters) {
|
|
3655
|
-
extractValues(filter.filters);
|
|
3656
|
-
}
|
|
3657
|
-
}
|
|
3658
|
-
}
|
|
3659
|
-
extractValues(filters);
|
|
3660
|
-
return flattenedValues;
|
|
3661
|
-
}
|
|
3662
3651
|
/**
|
|
3663
3652
|
* Recursively opens parent nodes in a tree structure if any of their child nodes are selected or opened.
|
|
3664
3653
|
*
|
|
@@ -5397,6 +5386,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
|
|
|
5397
5386
|
|
|
5398
5387
|
class UserProfileService {
|
|
5399
5388
|
API_URL = `${globalConfig.backendUrl}/api/v2/user-profile`;
|
|
5389
|
+
// Keyed by the userId signal's identity rather than its value: every current caller
|
|
5390
|
+
// passes the same PrincipalStore.userId signal, so sharing the resource here collapses
|
|
5391
|
+
// what would otherwise be one httpResource (and one HTTP request) per caller into one
|
|
5392
|
+
// for the whole app -- and lets a `.set()` from one consumer (e.g. the profile edit
|
|
5393
|
+
// form) show up everywhere else that reads this resource.
|
|
5394
|
+
resources = new WeakMap();
|
|
5400
5395
|
/**
|
|
5401
5396
|
* Retrieves the user profile by user ID.
|
|
5402
5397
|
*
|
|
@@ -5404,11 +5399,16 @@ class UserProfileService {
|
|
|
5404
5399
|
* @returns An Observable that emits an the UserProfile object.
|
|
5405
5400
|
*/
|
|
5406
5401
|
getUserProfile(userId) {
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5402
|
+
let resource = this.resources.get(userId);
|
|
5403
|
+
if (!resource) {
|
|
5404
|
+
resource = httpResource(() => (userId() ? `${this.API_URL}/${userId()}` : undefined), {
|
|
5405
|
+
parse: response => {
|
|
5406
|
+
return response;
|
|
5407
|
+
}
|
|
5408
|
+
});
|
|
5409
|
+
this.resources.set(userId, resource);
|
|
5410
|
+
}
|
|
5411
|
+
return resource;
|
|
5412
5412
|
}
|
|
5413
5413
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: UserProfileService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5414
5414
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: UserProfileService, providedIn: "root" });
|
|
@@ -9475,41 +9475,57 @@ function injectAggregationBase(refs) {
|
|
|
9475
9475
|
}
|
|
9476
9476
|
function addCurrentFiltersToItems(aggregation) {
|
|
9477
9477
|
const currentItems = aggregation?.items || [];
|
|
9478
|
-
if (
|
|
9479
|
-
|
|
9480
|
-
|
|
9481
|
-
|
|
9482
|
-
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
|
|
9489
|
-
|
|
9490
|
-
|
|
9491
|
-
|
|
9492
|
-
|
|
9493
|
-
// multiple values stored as a string array, e.g. { values: ["alice_martin", "caroline_dubois"] }
|
|
9494
|
-
// (no `filters` sub-array and no single `value`) — mark each matching item as selected
|
|
9495
|
-
currentFilters.values.forEach(value => {
|
|
9496
|
-
const found = currentItems.find(item => item.value?.toString().toLocaleLowerCase() === value?.toString().toLocaleLowerCase());
|
|
9497
|
-
if (!found) {
|
|
9498
|
-
currentItems.unshift({ value, display: value, $selected: true });
|
|
9499
|
-
}
|
|
9500
|
-
else {
|
|
9501
|
-
found.$selected = true;
|
|
9502
|
-
}
|
|
9503
|
-
});
|
|
9478
|
+
if (aggregation?.isTree) {
|
|
9479
|
+
return currentItems;
|
|
9480
|
+
}
|
|
9481
|
+
const currentFilters = isControlled() ? selectionAsFilter() : queryParamsStore.getFilter({ field: aggregation?.column, name: aggregation?.name });
|
|
9482
|
+
if (aggregation?.isDistribution) {
|
|
9483
|
+
// A distribution item's `value` is the full backend expression (e.g.
|
|
9484
|
+
// `size`10 Kb to 100 Kb`:(>= 10240 AND < 102400)`), not comparable to what the applied
|
|
9485
|
+
// filter stores — its leaves only ever carry the bucket's numeric thresholds. Flatten the
|
|
9486
|
+
// filter and compare on `display` instead (or `value` when `valuesAreExpressions` is not
|
|
9487
|
+
// set) — same strategy as `AggregationsService.enrichAggregation`.
|
|
9488
|
+
const flattenedValues = currentFilters ? flattenLegacyFilterValues([currentFilters]) : [];
|
|
9489
|
+
currentItems.forEach(item => {
|
|
9490
|
+
const valueToSearch = aggregation.valuesAreExpressions ? item.display : item.value;
|
|
9491
|
+
if (flattenedValues.includes(valueToSearch?.toString() ?? "")) {
|
|
9492
|
+
item.$selected = true;
|
|
9504
9493
|
}
|
|
9505
|
-
|
|
9506
|
-
|
|
9494
|
+
});
|
|
9495
|
+
return currentItems;
|
|
9496
|
+
}
|
|
9497
|
+
if (currentFilters) {
|
|
9498
|
+
if (Array.isArray(currentFilters.filters) && currentFilters.filters.length) {
|
|
9499
|
+
currentFilters.filters.forEach((filter) => {
|
|
9500
|
+
const found = currentItems.find(item => item.value?.toString().toLocaleLowerCase() === filter.value?.toLocaleLowerCase());
|
|
9501
|
+
if (!found) {
|
|
9502
|
+
currentItems.unshift({ value: filter.value, display: filter.display, $selected: true });
|
|
9503
|
+
}
|
|
9504
|
+
else {
|
|
9505
|
+
found.$selected = true;
|
|
9506
|
+
}
|
|
9507
|
+
});
|
|
9508
|
+
}
|
|
9509
|
+
else if (Array.isArray(currentFilters.values) && currentFilters.values.length) {
|
|
9510
|
+
// multiple values stored as a string array, e.g. { values: ["alice_martin", "caroline_dubois"] }
|
|
9511
|
+
// (no `filters` sub-array and no single `value`) — mark each matching item as selected
|
|
9512
|
+
currentFilters.values.forEach(value => {
|
|
9513
|
+
const found = currentItems.find(item => item.value?.toString().toLocaleLowerCase() === value?.toString().toLocaleLowerCase());
|
|
9507
9514
|
if (!found) {
|
|
9508
|
-
currentItems.
|
|
9515
|
+
currentItems.unshift({ value, display: value, $selected: true });
|
|
9509
9516
|
}
|
|
9510
9517
|
else {
|
|
9511
9518
|
found.$selected = true;
|
|
9512
9519
|
}
|
|
9520
|
+
});
|
|
9521
|
+
}
|
|
9522
|
+
else if (currentFilters.value) {
|
|
9523
|
+
const found = currentItems.find(item => item.value?.toString().toLocaleLowerCase() === currentFilters.value?.toLocaleLowerCase());
|
|
9524
|
+
if (!found) {
|
|
9525
|
+
currentItems.push({ value: currentFilters.value, display: currentFilters.display, $selected: true });
|
|
9526
|
+
}
|
|
9527
|
+
else {
|
|
9528
|
+
found.$selected = true;
|
|
9513
9529
|
}
|
|
9514
9530
|
}
|
|
9515
9531
|
}
|
|
@@ -14500,7 +14516,7 @@ class AggregationPanelComponent {
|
|
|
14500
14516
|
this.searchText.set("");
|
|
14501
14517
|
}
|
|
14502
14518
|
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\
|
|
14519
|
+
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
14520
|
}
|
|
14505
14521
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: AggregationPanelComponent, decorators: [{
|
|
14506
14522
|
type: Component,
|
|
@@ -14522,7 +14538,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
|
|
|
14522
14538
|
SquareIcon,
|
|
14523
14539
|
XMarkIcon,
|
|
14524
14540
|
IconButtonComponent,
|
|
14525
|
-
], template: "<details\
|
|
14541
|
+
], 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
14542
|
}], 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
14543
|
|
|
14528
14544
|
class AggregationTreeComponent {
|
|
@@ -15598,6 +15614,15 @@ class AggregationListComponent {
|
|
|
15598
15614
|
const filters = this.queryParamsStore.getFilter({ field: field ?? undefined, name: this.listItemName(item) });
|
|
15599
15615
|
if (!filters)
|
|
15600
15616
|
return false;
|
|
15617
|
+
const agg = this.aggregation();
|
|
15618
|
+
if (agg?.isDistribution) {
|
|
15619
|
+
// Same reasoning as `injectAggregationBase.addCurrentFiltersToItems`: a distribution item's
|
|
15620
|
+
// `value` is the full backend expression, not comparable to the applied filter's stored
|
|
15621
|
+
// thresholds — flatten it and compare on `display` (or `value` without `valuesAreExpressions`).
|
|
15622
|
+
const flattenedValues = flattenLegacyFilterValues([filters]);
|
|
15623
|
+
const valueToSearch = agg.valuesAreExpressions ? item.display : item.value;
|
|
15624
|
+
return flattenedValues.includes(valueToSearch?.toString() ?? "");
|
|
15625
|
+
}
|
|
15601
15626
|
const values = [item.value];
|
|
15602
15627
|
return values.some(v => v === filters.value) || !!(filters.values?.length && filters.values.some((value) => values.some(v => v === value)));
|
|
15603
15628
|
}
|
|
@@ -16238,6 +16263,13 @@ class FilterButtonComponent {
|
|
|
16238
16263
|
column = input.required(...(ngDevMode ? [{ debugName: "column" }] : []));
|
|
16239
16264
|
position = input("bottom-start", ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
16240
16265
|
offset = input(8, ...(ngDevMode ? [{ debugName: "offset" }] : []));
|
|
16266
|
+
/**
|
|
16267
|
+
* When true, forces the popover to stay at the exact `position()` placement,
|
|
16268
|
+
* disabling floating-ui's automatic repositioning based on available viewport space.
|
|
16269
|
+
*
|
|
16270
|
+
* @default false
|
|
16271
|
+
*/
|
|
16272
|
+
lockPosition = input(false, ...(ngDevMode ? [{ debugName: "lockPosition", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
16241
16273
|
expandedLevel = input(undefined, ...(ngDevMode ? [{ debugName: "expandedLevel", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
16242
16274
|
variant = signal("ghost", ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
16243
16275
|
filter = signal({
|
|
@@ -16303,7 +16335,7 @@ class FilterButtonComponent {
|
|
|
16303
16335
|
return this.appStore.isDateColumn(column);
|
|
16304
16336
|
}
|
|
16305
16337
|
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: `
|
|
16338
|
+
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
16339
|
<Popover [disabled]="filter().disabled" class="group">
|
|
16308
16340
|
<button
|
|
16309
16341
|
[variant]="variant()"
|
|
@@ -16336,13 +16368,14 @@ class FilterButtonComponent {
|
|
|
16336
16368
|
class="min-w-fit w-max max-w-[90vw]"
|
|
16337
16369
|
[position]="position()"
|
|
16338
16370
|
[offset]="offset()"
|
|
16371
|
+
[lockPosition]="lockPosition()"
|
|
16339
16372
|
>
|
|
16340
16373
|
@if(contentRef.isVisible) {
|
|
16341
16374
|
@let name = filter().name;
|
|
16342
16375
|
@let column = filter().column;
|
|
16343
16376
|
@if(name) {
|
|
16344
16377
|
<Aggregation
|
|
16345
|
-
class="w-60 [--height:19lh]"
|
|
16378
|
+
class="w-60 [--scroll-height:19lh]"
|
|
16346
16379
|
id="filter-{{ filter().column }}"
|
|
16347
16380
|
[name]="name"
|
|
16348
16381
|
[column]="column"
|
|
@@ -16358,7 +16391,7 @@ class FilterButtonComponent {
|
|
|
16358
16391
|
}
|
|
16359
16392
|
</PopoverContent>
|
|
16360
16393
|
</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" }] });
|
|
16394
|
+
`, 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
16395
|
}
|
|
16363
16396
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: FilterButtonComponent, decorators: [{
|
|
16364
16397
|
type: Component,
|
|
@@ -16409,13 +16442,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
|
|
|
16409
16442
|
class="min-w-fit w-max max-w-[90vw]"
|
|
16410
16443
|
[position]="position()"
|
|
16411
16444
|
[offset]="offset()"
|
|
16445
|
+
[lockPosition]="lockPosition()"
|
|
16412
16446
|
>
|
|
16413
16447
|
@if(contentRef.isVisible) {
|
|
16414
16448
|
@let name = filter().name;
|
|
16415
16449
|
@let column = filter().column;
|
|
16416
16450
|
@if(name) {
|
|
16417
16451
|
<Aggregation
|
|
16418
|
-
class="w-60 [--height:19lh]"
|
|
16452
|
+
class="w-60 [--scroll-height:19lh]"
|
|
16419
16453
|
id="filter-{{ filter().column }}"
|
|
16420
16454
|
[name]="name"
|
|
16421
16455
|
[column]="column"
|
|
@@ -16437,11 +16471,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
|
|
|
16437
16471
|
role: "listitem"
|
|
16438
16472
|
}
|
|
16439
16473
|
}]
|
|
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 }] }] } });
|
|
16474
|
+
}], 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
16475
|
|
|
16442
16476
|
const FILTERS_BREAKPOINT = new InjectionToken('FILTERS_BREAKPOINT', { factory: () => 5 });
|
|
16443
16477
|
|
|
16478
|
+
/**
|
|
16479
|
+
* Below this many overflow filters, the search input adds friction without
|
|
16480
|
+
* helping — scanning a handful of accordion headers is already fast.
|
|
16481
|
+
*/
|
|
16482
|
+
const SEARCH_THRESHOLD = 6;
|
|
16444
16483
|
class MoreComponent {
|
|
16484
|
+
SEARCH_THRESHOLD = SEARCH_THRESHOLD;
|
|
16445
16485
|
count = input(2, ...(ngDevMode ? [{ debugName: "count" }] : []));
|
|
16446
16486
|
includedFilters = input([], ...(ngDevMode ? [{ debugName: "includedFilters" }] : []));
|
|
16447
16487
|
excludedFilters = input([], ...(ngDevMode ? [{ debugName: "excludedFilters" }] : []));
|
|
@@ -16457,6 +16497,7 @@ class MoreComponent {
|
|
|
16457
16497
|
*/
|
|
16458
16498
|
hideWhenEmpty = input(false, ...(ngDevMode ? [{ debugName: "hideWhenEmpty", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
16459
16499
|
aggregationsService = inject(AggregationsService);
|
|
16500
|
+
searchText = model("", ...(ngDevMode ? [{ debugName: "searchText" }] : []));
|
|
16460
16501
|
/**
|
|
16461
16502
|
* The overflow filters rendered as accordions: the authorized filters beyond the
|
|
16462
16503
|
* first `count` (which are already shown in the bar).
|
|
@@ -16469,49 +16510,158 @@ class MoreComponent {
|
|
|
16469
16510
|
filters = computed(() => this.aggregationsService
|
|
16470
16511
|
.getAuthorizedFilters(this.aggregations(), this.includedFilters(), this.excludedFilters(), this.homepage())
|
|
16471
16512
|
.toSpliced(0, this.count()), ...(ngDevMode ? [{ debugName: "filters" }] : []));
|
|
16513
|
+
/** {@link filters}, narrowed to those matching {@link searchText} (case-insensitive, by name). */
|
|
16514
|
+
filteredFilters = computed(() => {
|
|
16515
|
+
const query = this.searchText().trim().toLowerCase();
|
|
16516
|
+
if (!query)
|
|
16517
|
+
return this.filters();
|
|
16518
|
+
return this.filters().filter(filter => filter.name.toLowerCase().includes(query));
|
|
16519
|
+
}, ...(ngDevMode ? [{ debugName: "filteredFilters" }] : []));
|
|
16520
|
+
clearSearch(e) {
|
|
16521
|
+
e.stopImmediatePropagation();
|
|
16522
|
+
this.searchText.set("");
|
|
16523
|
+
}
|
|
16472
16524
|
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: "
|
|
16474
|
-
@
|
|
16475
|
-
<
|
|
16476
|
-
|
|
16477
|
-
|
|
16478
|
-
|
|
16479
|
-
|
|
16480
|
-
|
|
16481
|
-
|
|
16482
|
-
|
|
16483
|
-
|
|
16484
|
-
|
|
16525
|
+
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: `
|
|
16526
|
+
@if (filters().length > SEARCH_THRESHOLD) {
|
|
16527
|
+
<div class="sticky top-0 z-10 bg-menu-bg pb-3 shadow-[0_-1px_0_0_var(--color-menu-bg)]">
|
|
16528
|
+
<InputGroup>
|
|
16529
|
+
<input
|
|
16530
|
+
input-group
|
|
16531
|
+
type="text"
|
|
16532
|
+
[attr.aria-label]="'filters.searchFilters' | transloco"
|
|
16533
|
+
[attr.placeholder]="'filters.searchFilters' | transloco"
|
|
16534
|
+
[(ngModel)]="searchText" />
|
|
16535
|
+
<InputGroupAddon>
|
|
16536
|
+
<SearchIcon class="text-foreground size-4" />
|
|
16537
|
+
</InputGroupAddon>
|
|
16538
|
+
<InputGroupAddon align="inline-end" class="gap-0.5!">
|
|
16539
|
+
<icon-button
|
|
16540
|
+
size="sm"
|
|
16541
|
+
[class]="
|
|
16542
|
+
searchText().length > 0
|
|
16543
|
+
? 'opacity-100 transition-opacity duration-500'
|
|
16544
|
+
: 'pointer-events-none opacity-0 transition-opacity duration-500'
|
|
16545
|
+
"
|
|
16546
|
+
aria-label="Clear search"
|
|
16547
|
+
[tabindex]="searchText().length > 0 ? 0 : -1"
|
|
16548
|
+
(keydown.enter)="clearSearch($event)"
|
|
16549
|
+
(click)="clearSearch($event)">
|
|
16550
|
+
<XMarkIcon />
|
|
16551
|
+
</icon-button>
|
|
16552
|
+
</InputGroupAddon>
|
|
16553
|
+
</InputGroup>
|
|
16554
|
+
</div>
|
|
16485
16555
|
}
|
|
16486
|
-
|
|
16556
|
+
|
|
16557
|
+
<div class="divide-y divide-muted-foreground/18">
|
|
16558
|
+
@for (filter of filteredFilters(); track filter.name) {
|
|
16559
|
+
<Aggregation
|
|
16560
|
+
class="w-full min-w-60 px-1 [--scroll-height:15lh]"
|
|
16561
|
+
id="more-filters"
|
|
16562
|
+
[attr.title]="'filters.openFilter' | transloco: { filter: filter.name }"
|
|
16563
|
+
showFiltersCount
|
|
16564
|
+
[collapsible]="true"
|
|
16565
|
+
[collapsed]="true"
|
|
16566
|
+
[hideWhenEmpty]="hideWhenEmpty()"
|
|
16567
|
+
[name]="filter.name"
|
|
16568
|
+
[column]="filter.column" />
|
|
16569
|
+
} @empty {
|
|
16570
|
+
@if (searchText().trim().length > 0) {
|
|
16571
|
+
<p class="text-muted-foreground px-2 py-4 text-center text-sm">{{ "filters.noFilterMatch" | transloco }}</p>
|
|
16572
|
+
}
|
|
16573
|
+
}
|
|
16574
|
+
</div>
|
|
16575
|
+
`, 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
16576
|
}
|
|
16488
16577
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: MoreComponent, decorators: [{
|
|
16489
16578
|
type: Component,
|
|
16490
|
-
args: [{
|
|
16491
|
-
|
|
16492
|
-
|
|
16493
|
-
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
|
|
16579
|
+
args: [{
|
|
16580
|
+
selector: "more, More",
|
|
16581
|
+
standalone: true,
|
|
16582
|
+
imports: [
|
|
16583
|
+
AggregationComponent,
|
|
16584
|
+
TranslocoPipe,
|
|
16585
|
+
FormsModule,
|
|
16586
|
+
InputGroupComponent,
|
|
16587
|
+
InputGroupInput,
|
|
16588
|
+
InputGroupAddonComponent,
|
|
16589
|
+
SearchIcon,
|
|
16590
|
+
XMarkIcon,
|
|
16591
|
+
IconButtonComponent
|
|
16592
|
+
],
|
|
16593
|
+
template: `
|
|
16594
|
+
@if (filters().length > SEARCH_THRESHOLD) {
|
|
16595
|
+
<div class="sticky top-0 z-10 bg-menu-bg pb-3 shadow-[0_-1px_0_0_var(--color-menu-bg)]">
|
|
16596
|
+
<InputGroup>
|
|
16597
|
+
<input
|
|
16598
|
+
input-group
|
|
16599
|
+
type="text"
|
|
16600
|
+
[attr.aria-label]="'filters.searchFilters' | transloco"
|
|
16601
|
+
[attr.placeholder]="'filters.searchFilters' | transloco"
|
|
16602
|
+
[(ngModel)]="searchText" />
|
|
16603
|
+
<InputGroupAddon>
|
|
16604
|
+
<SearchIcon class="text-foreground size-4" />
|
|
16605
|
+
</InputGroupAddon>
|
|
16606
|
+
<InputGroupAddon align="inline-end" class="gap-0.5!">
|
|
16607
|
+
<icon-button
|
|
16608
|
+
size="sm"
|
|
16609
|
+
[class]="
|
|
16610
|
+
searchText().length > 0
|
|
16611
|
+
? 'opacity-100 transition-opacity duration-500'
|
|
16612
|
+
: 'pointer-events-none opacity-0 transition-opacity duration-500'
|
|
16613
|
+
"
|
|
16614
|
+
aria-label="Clear search"
|
|
16615
|
+
[tabindex]="searchText().length > 0 ? 0 : -1"
|
|
16616
|
+
(keydown.enter)="clearSearch($event)"
|
|
16617
|
+
(click)="clearSearch($event)">
|
|
16618
|
+
<XMarkIcon />
|
|
16619
|
+
</icon-button>
|
|
16620
|
+
</InputGroupAddon>
|
|
16621
|
+
</InputGroup>
|
|
16622
|
+
</div>
|
|
16502
16623
|
}
|
|
16503
|
-
|
|
16504
|
-
|
|
16505
|
-
|
|
16506
|
-
|
|
16624
|
+
|
|
16625
|
+
<div class="divide-y divide-muted-foreground/18">
|
|
16626
|
+
@for (filter of filteredFilters(); track filter.name) {
|
|
16627
|
+
<Aggregation
|
|
16628
|
+
class="w-full min-w-60 px-1 [--scroll-height:15lh]"
|
|
16629
|
+
id="more-filters"
|
|
16630
|
+
[attr.title]="'filters.openFilter' | transloco: { filter: filter.name }"
|
|
16631
|
+
showFiltersCount
|
|
16632
|
+
[collapsible]="true"
|
|
16633
|
+
[collapsed]="true"
|
|
16634
|
+
[hideWhenEmpty]="hideWhenEmpty()"
|
|
16635
|
+
[name]="filter.name"
|
|
16636
|
+
[column]="filter.column" />
|
|
16637
|
+
} @empty {
|
|
16638
|
+
@if (searchText().trim().length > 0) {
|
|
16639
|
+
<p class="text-muted-foreground px-2 py-4 text-center text-sm">{{ "filters.noFilterMatch" | transloco }}</p>
|
|
16640
|
+
}
|
|
16641
|
+
}
|
|
16642
|
+
</div>
|
|
16643
|
+
`,
|
|
16644
|
+
host: {
|
|
16645
|
+
class: "scrollbar-thin"
|
|
16646
|
+
}
|
|
16647
|
+
}]
|
|
16648
|
+
}], 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
16649
|
|
|
16508
16650
|
class MoreButtonComponent {
|
|
16509
16651
|
appStore = inject(AppStore);
|
|
16510
16652
|
queryParamsStore = inject(QueryParamsStore);
|
|
16511
16653
|
nativeElement = inject(ElementRef).nativeElement;
|
|
16654
|
+
breakpointObserver = inject(BreakpointObserverService);
|
|
16512
16655
|
aggregationsService = inject(AggregationsService);
|
|
16513
16656
|
count = input(2, ...(ngDevMode ? [{ debugName: "count", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
16514
16657
|
position = input("bottom-end", ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
16658
|
+
/**
|
|
16659
|
+
* When true, forces the popover to stay at the exact `position()` placement,
|
|
16660
|
+
* disabling floating-ui's automatic repositioning based on available viewport space.
|
|
16661
|
+
*
|
|
16662
|
+
* @default false
|
|
16663
|
+
*/
|
|
16664
|
+
lockPosition = input(false, ...(ngDevMode ? [{ debugName: "lockPosition", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
16515
16665
|
includedFilters = input([], ...(ngDevMode ? [{ debugName: "includedFilters" }] : []));
|
|
16516
16666
|
excludedFilters = input([], ...(ngDevMode ? [{ debugName: "excludedFilters" }] : []));
|
|
16517
16667
|
aggregations = input(...(ngDevMode ? [undefined, { debugName: "aggregations" }] : []));
|
|
@@ -16524,79 +16674,201 @@ class MoreButtonComponent {
|
|
|
16524
16674
|
* @default false
|
|
16525
16675
|
*/
|
|
16526
16676
|
hideWhenEmpty = input(false, ...(ngDevMode ? [{ debugName: "hideWhenEmpty", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
16527
|
-
|
|
16528
|
-
|
|
16529
|
-
|
|
16530
|
-
|
|
16531
|
-
|
|
16532
|
-
|
|
16533
|
-
|
|
16534
|
-
|
|
16535
|
-
|
|
16536
|
-
|
|
16537
|
-
|
|
16538
|
-
|
|
16677
|
+
/**
|
|
16678
|
+
* Above this many overflow filters, the desktop Popover escalates to a modal
|
|
16679
|
+
* Dialog instead of an anchored popover — useful once there are too many facets
|
|
16680
|
+
* to browse comfortably in an anchored popover. Left unset (the default), the
|
|
16681
|
+
* Popover always shows every overflow facet, however many there are, adapting
|
|
16682
|
+
* its own height to the available space (see `PopoverContentComponent`'s
|
|
16683
|
+
* `size()` middleware) rather than escalating. A commonly-used value is `6`.
|
|
16684
|
+
*
|
|
16685
|
+
* @default undefined — never escalate to Dialog
|
|
16686
|
+
*/
|
|
16687
|
+
enrichedThreshold = input(...(ngDevMode ? [undefined, { debugName: "enrichedThreshold" }] : []));
|
|
16688
|
+
/** Mobile drawer open state — the desktop Popover/Dialog manage their own. */
|
|
16689
|
+
sheetOpen = signal(false, ...(ngDevMode ? [{ debugName: "sheetOpen" }] : []));
|
|
16690
|
+
/** The inline enriched Dialog — `<dialog #dialogRefEl>` binds a `DialogComponent` instance to the ref by default. */
|
|
16691
|
+
dialogRef = viewChild("dialogRefEl", ...(ngDevMode ? [{ debugName: "dialogRef" }] : []));
|
|
16692
|
+
/** The authorized filters beyond the first `count` already shown in the bar. */
|
|
16693
|
+
overflowFilters = computed(() => this.aggregationsService
|
|
16694
|
+
.getAuthorizedFilters(this.aggregations(), this.includedFilters(), this.excludedFilters(), this.homepage())
|
|
16695
|
+
.toSpliced(0, this.count()), ...(ngDevMode ? [{ debugName: "overflowFilters" }] : []));
|
|
16696
|
+
totalFiltersCount = computed(() => this.overflowFilters().reduce((acc, filter) => {
|
|
16697
|
+
const f = this.queryParamsStore.getFilter(filter);
|
|
16698
|
+
acc += f?.count || 0;
|
|
16699
|
+
return acc;
|
|
16700
|
+
}, 0), ...(ngDevMode ? [{ debugName: "totalFiltersCount" }] : []));
|
|
16701
|
+
/**
|
|
16702
|
+
* Above {@link enrichedThreshold} overflow filters, the popover escalates to a modal
|
|
16703
|
+
* Dialog. Always `false` while `enrichedThreshold` is unset — the Popover then shows
|
|
16704
|
+
* every overflow facet regardless of count.
|
|
16705
|
+
*/
|
|
16706
|
+
isEnriched = computed(() => {
|
|
16707
|
+
const threshold = this.enrichedThreshold();
|
|
16708
|
+
return threshold !== undefined && this.overflowFilters().length > threshold;
|
|
16709
|
+
}, ...(ngDevMode ? [{ debugName: "isEnriched" }] : []));
|
|
16539
16710
|
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
|
-
<
|
|
16542
|
-
<
|
|
16543
|
-
|
|
16544
|
-
|
|
16545
|
-
|
|
16546
|
-
<
|
|
16547
|
-
|
|
16548
|
-
|
|
16549
|
-
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
|
|
16711
|
+
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: `
|
|
16712
|
+
<ng-template #trigger>
|
|
16713
|
+
<list-filter-icon aria-hidden="true" />
|
|
16714
|
+
<span sr-only class="hidden sm:inline">{{ 'filters.moreFilters' | transloco }}</span>
|
|
16715
|
+
|
|
16716
|
+
@if (totalFiltersCount() > 0) {
|
|
16717
|
+
<Badge size="xs">
|
|
16718
|
+
{{ totalFiltersCount() }}
|
|
16719
|
+
</Badge>
|
|
16720
|
+
}
|
|
16721
|
+
</ng-template>
|
|
16722
|
+
|
|
16723
|
+
@if (breakpointObserver.isMobile()) {
|
|
16724
|
+
<button variant="ghost" class="gap-1 truncate font-semibold" aria-label="more filters" (click)="sheetOpen.set(true)">
|
|
16725
|
+
<ng-container *ngTemplateOutlet="trigger" />
|
|
16554
16726
|
</button>
|
|
16555
16727
|
|
|
16556
|
-
<
|
|
16557
|
-
|
|
16558
|
-
|
|
16559
|
-
|
|
16560
|
-
|
|
16561
|
-
|
|
16562
|
-
|
|
16728
|
+
<sheet [open]="sheetOpen()" (openChange)="sheetOpen.set($event)" side="bottom" class="max-w-none">
|
|
16729
|
+
<sheet-header>
|
|
16730
|
+
<sheet-title>{{ 'filters.moreFilters' | transloco }}</sheet-title>
|
|
16731
|
+
</sheet-header>
|
|
16732
|
+
<div class="max-h-[75vh] overflow-y-auto overscroll-contain">
|
|
16733
|
+
<More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
|
|
16734
|
+
</div>
|
|
16735
|
+
</sheet>
|
|
16736
|
+
} @else if (isEnriched()) {
|
|
16737
|
+
<button variant="ghost" class="gap-1 truncate font-semibold" aria-label="more filters" (click)="dialogRef()?.showModal()">
|
|
16738
|
+
<ng-container *ngTemplateOutlet="trigger" />
|
|
16739
|
+
</button>
|
|
16740
|
+
|
|
16741
|
+
<dialog #dialogRefEl>
|
|
16742
|
+
<DialogContent class="sm:max-w-lg rounded-(--radius-xl,1rem)">
|
|
16743
|
+
<DialogHeader>
|
|
16744
|
+
<DialogTitle>{{ 'filters.moreFilters' | transloco }}</DialogTitle>
|
|
16745
|
+
</DialogHeader>
|
|
16746
|
+
<div class="max-h-[60vh] overflow-y-auto overscroll-contain">
|
|
16747
|
+
<More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
|
|
16748
|
+
</div>
|
|
16749
|
+
</DialogContent>
|
|
16750
|
+
</dialog>
|
|
16751
|
+
} @else {
|
|
16752
|
+
<Popover class="group/more">
|
|
16753
|
+
<button
|
|
16754
|
+
variant="ghost"
|
|
16755
|
+
class="group-open/more:border-foreground/18 gap-1 truncate font-semibold group-open/more:border"
|
|
16756
|
+
aria-label="more filters">
|
|
16757
|
+
<ng-container *ngTemplateOutlet="trigger" />
|
|
16758
|
+
</button>
|
|
16759
|
+
|
|
16760
|
+
<PopoverContent #contentRef="popoverContent" [position]="position()" [lockPosition]="lockPosition()" class="min-w-max max-w-80 min-w-40 rounded-(--radius-xl,1rem) p-5">
|
|
16761
|
+
@if(contentRef.isVisible) {
|
|
16762
|
+
<div class="max-h-[calc(var(--popover-available-height,55vh)_-_2.5rem)] overflow-y-auto overscroll-contain">
|
|
16763
|
+
<More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
|
|
16764
|
+
</div>
|
|
16765
|
+
}
|
|
16766
|
+
</PopoverContent>
|
|
16767
|
+
</Popover>
|
|
16768
|
+
}
|
|
16769
|
+
`, 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
16770
|
}
|
|
16564
16771
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: MoreButtonComponent, decorators: [{
|
|
16565
16772
|
type: Component,
|
|
16566
16773
|
args: [{
|
|
16567
16774
|
selector: "more-button, MoreButton",
|
|
16568
16775
|
standalone: true,
|
|
16569
|
-
imports: [
|
|
16776
|
+
imports: [
|
|
16777
|
+
NgTemplateOutlet,
|
|
16778
|
+
ButtonComponent,
|
|
16779
|
+
PopoverComponent,
|
|
16780
|
+
PopoverContentComponent,
|
|
16781
|
+
TranslocoPipe,
|
|
16782
|
+
MoreComponent,
|
|
16783
|
+
BadgeComponent,
|
|
16784
|
+
ListFilterIcon,
|
|
16785
|
+
SheetComponent,
|
|
16786
|
+
SheetHeaderComponent,
|
|
16787
|
+
SheetTitleComponent,
|
|
16788
|
+
DialogComponent,
|
|
16789
|
+
DialogContentComponent,
|
|
16790
|
+
DialogHeaderComponent,
|
|
16791
|
+
DialogTitleComponent
|
|
16792
|
+
],
|
|
16570
16793
|
template: `
|
|
16571
|
-
<
|
|
16572
|
-
<
|
|
16573
|
-
|
|
16574
|
-
|
|
16575
|
-
|
|
16576
|
-
<
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
|
|
16582
|
-
|
|
16583
|
-
|
|
16794
|
+
<ng-template #trigger>
|
|
16795
|
+
<list-filter-icon aria-hidden="true" />
|
|
16796
|
+
<span sr-only class="hidden sm:inline">{{ 'filters.moreFilters' | transloco }}</span>
|
|
16797
|
+
|
|
16798
|
+
@if (totalFiltersCount() > 0) {
|
|
16799
|
+
<Badge size="xs">
|
|
16800
|
+
{{ totalFiltersCount() }}
|
|
16801
|
+
</Badge>
|
|
16802
|
+
}
|
|
16803
|
+
</ng-template>
|
|
16804
|
+
|
|
16805
|
+
@if (breakpointObserver.isMobile()) {
|
|
16806
|
+
<button variant="ghost" class="gap-1 truncate font-semibold" aria-label="more filters" (click)="sheetOpen.set(true)">
|
|
16807
|
+
<ng-container *ngTemplateOutlet="trigger" />
|
|
16584
16808
|
</button>
|
|
16585
16809
|
|
|
16586
|
-
<
|
|
16587
|
-
|
|
16588
|
-
|
|
16589
|
-
|
|
16590
|
-
|
|
16591
|
-
|
|
16592
|
-
|
|
16810
|
+
<sheet [open]="sheetOpen()" (openChange)="sheetOpen.set($event)" side="bottom" class="max-w-none">
|
|
16811
|
+
<sheet-header>
|
|
16812
|
+
<sheet-title>{{ 'filters.moreFilters' | transloco }}</sheet-title>
|
|
16813
|
+
</sheet-header>
|
|
16814
|
+
<div class="max-h-[75vh] overflow-y-auto overscroll-contain">
|
|
16815
|
+
<More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
|
|
16816
|
+
</div>
|
|
16817
|
+
</sheet>
|
|
16818
|
+
} @else if (isEnriched()) {
|
|
16819
|
+
<button variant="ghost" class="gap-1 truncate font-semibold" aria-label="more filters" (click)="dialogRef()?.showModal()">
|
|
16820
|
+
<ng-container *ngTemplateOutlet="trigger" />
|
|
16821
|
+
</button>
|
|
16822
|
+
|
|
16823
|
+
<dialog #dialogRefEl>
|
|
16824
|
+
<DialogContent class="sm:max-w-lg rounded-(--radius-xl,1rem)">
|
|
16825
|
+
<DialogHeader>
|
|
16826
|
+
<DialogTitle>{{ 'filters.moreFilters' | transloco }}</DialogTitle>
|
|
16827
|
+
</DialogHeader>
|
|
16828
|
+
<div class="max-h-[60vh] overflow-y-auto overscroll-contain">
|
|
16829
|
+
<More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
|
|
16830
|
+
</div>
|
|
16831
|
+
</DialogContent>
|
|
16832
|
+
</dialog>
|
|
16833
|
+
} @else {
|
|
16834
|
+
<Popover class="group/more">
|
|
16835
|
+
<button
|
|
16836
|
+
variant="ghost"
|
|
16837
|
+
class="group-open/more:border-foreground/18 gap-1 truncate font-semibold group-open/more:border"
|
|
16838
|
+
aria-label="more filters">
|
|
16839
|
+
<ng-container *ngTemplateOutlet="trigger" />
|
|
16840
|
+
</button>
|
|
16841
|
+
|
|
16842
|
+
<PopoverContent #contentRef="popoverContent" [position]="position()" [lockPosition]="lockPosition()" class="min-w-max max-w-80 min-w-40 rounded-(--radius-xl,1rem) p-5">
|
|
16843
|
+
@if(contentRef.isVisible) {
|
|
16844
|
+
<div class="max-h-[calc(var(--popover-available-height,55vh)_-_2.5rem)] overflow-y-auto overscroll-contain">
|
|
16845
|
+
<More [count]="count()" [includedFilters]="includedFilters()" [excludedFilters]="excludedFilters()" [aggregations]="aggregations()" [homepage]="homepage()" [hideWhenEmpty]="hideWhenEmpty()" class="block w-full" />
|
|
16846
|
+
</div>
|
|
16847
|
+
}
|
|
16848
|
+
</PopoverContent>
|
|
16849
|
+
</Popover>
|
|
16850
|
+
}
|
|
16851
|
+
`,
|
|
16852
|
+
// Self-registers the scope so <more-button> resolves its own translations when used
|
|
16853
|
+
// standalone, outside <filters-bar> (which already registers it too — harmless overlap).
|
|
16854
|
+
providers: [provideTranslocoScope("filters")]
|
|
16593
16855
|
}]
|
|
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 }] }] } });
|
|
16856
|
+
}], 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
16857
|
|
|
16596
16858
|
class FiltersBarComponent {
|
|
16597
16859
|
class = input(...(ngDevMode ? [undefined, { debugName: "class" }] : []));
|
|
16598
16860
|
position = input("bottom-start", ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
16599
16861
|
morePosition = input("bottom-end", ...(ngDevMode ? [{ debugName: "morePosition" }] : []));
|
|
16862
|
+
/**
|
|
16863
|
+
* When true, forces every popover (filter buttons and the "more filters"
|
|
16864
|
+
* button) to stay at its exact `position()`/`morePosition()` placement,
|
|
16865
|
+
* disabling floating-ui's automatic repositioning based on available
|
|
16866
|
+
* viewport space. Relayed as-is to each `<FilterButton [lockPosition]>`
|
|
16867
|
+
* and to `<MoreButton [lockPosition]>`.
|
|
16868
|
+
*
|
|
16869
|
+
* @default false
|
|
16870
|
+
*/
|
|
16871
|
+
lockPosition = input(false, ...(ngDevMode ? [{ debugName: "lockPosition", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
16600
16872
|
aggregations = input(...(ngDevMode ? [undefined, { debugName: "aggregations" }] : []));
|
|
16601
16873
|
/**
|
|
16602
16874
|
* Filters that should be included from the filters bar.
|
|
@@ -16700,7 +16972,7 @@ class FiltersBarComponent {
|
|
|
16700
16972
|
allAuthorizedFilters = computed(() => {
|
|
16701
16973
|
return this.aggregationsService
|
|
16702
16974
|
.getAuthorizedFilters(this.aggregations(), this.includeFilters(), this.excludeFilters(), this.homepage())
|
|
16703
|
-
.map(
|
|
16975
|
+
.map(f => ({ name: f.name, column: f.column }));
|
|
16704
16976
|
}, ...(ngDevMode ? [{ debugName: "allAuthorizedFilters" }] : []));
|
|
16705
16977
|
/**
|
|
16706
16978
|
* Computes the list of additional filters that can be displayed in the "more filters" popover.
|
|
@@ -16717,7 +16989,7 @@ class FiltersBarComponent {
|
|
|
16717
16989
|
hasMoreFilters = computed(() => {
|
|
16718
16990
|
const moreFiltersAggregations = this.allAuthorizedFilters()
|
|
16719
16991
|
.toSpliced(0, this.visibleFiltersCount())
|
|
16720
|
-
.map(
|
|
16992
|
+
.map(f => this.aggregationsStore.getAggregation(f.column, "column"));
|
|
16721
16993
|
return moreFiltersAggregations;
|
|
16722
16994
|
}, ...(ngDevMode ? [{ debugName: "hasMoreFilters" }] : []));
|
|
16723
16995
|
/**
|
|
@@ -16739,9 +17011,7 @@ class FiltersBarComponent {
|
|
|
16739
17011
|
*/
|
|
16740
17012
|
hasCappedFilters = computed(() => this.allAuthorizedFilters().length > this.filtersCount(), ...(ngDevMode ? [{ debugName: "hasCappedFilters" }] : []));
|
|
16741
17013
|
constructor() {
|
|
16742
|
-
this.transloco.events
|
|
16743
|
-
.pipe(takeUntilDestroyed(this.destroyRef), debounceTime(100))
|
|
16744
|
-
.subscribe(() => this.overflowManagerRef()?.countItems());
|
|
17014
|
+
this.transloco.events$.pipe(takeUntilDestroyed(this.destroyRef), debounceTime(100)).subscribe(() => this.overflowManagerRef()?.countItems());
|
|
16745
17015
|
// Recount the overflow whenever the applied filters or basket change (e.g.
|
|
16746
17016
|
// a filter modified or removed from the "more filters" popover). A
|
|
16747
17017
|
// FilterButton hidden by the overflow manager (display: none) emits no
|
|
@@ -16800,12 +17070,12 @@ class FiltersBarComponent {
|
|
|
16800
17070
|
* @param event - The mouse event triggered by the user's click.
|
|
16801
17071
|
*/
|
|
16802
17072
|
handleClick(event) {
|
|
16803
|
-
this.filterButtonRefs().forEach(
|
|
17073
|
+
this.filterButtonRefs().forEach(ref => {
|
|
16804
17074
|
ref.popoverRef()?.onClick(event);
|
|
16805
17075
|
});
|
|
16806
17076
|
}
|
|
16807
17077
|
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: `
|
|
17078
|
+
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
17079
|
<div overflowManager [direction]="direction()" [reserveStop]="hasCappedFilters()" (count)="adjustFiltersCount($event)" class="flex items-end gap-2 rounded-[inherit] bg-inherit">
|
|
16810
17080
|
@if (hasFilters()) {
|
|
16811
17081
|
<button
|
|
@@ -16839,7 +17109,7 @@ class FiltersBarComponent {
|
|
|
16839
17109
|
role="list"
|
|
16840
17110
|
aria-label="Filters list">
|
|
16841
17111
|
@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()" />
|
|
17112
|
+
<FilterButton class="max-w-60" overflowItem [name]="filter.name" [column]="filter.column" [position]="position()" [lockPosition]="lockPosition()" [offset]="offset()" [expandedLevel]="expandedLevel()" />
|
|
16843
17113
|
}
|
|
16844
17114
|
</div>
|
|
16845
17115
|
|
|
@@ -16851,6 +17121,7 @@ class FiltersBarComponent {
|
|
|
16851
17121
|
role="listitem"
|
|
16852
17122
|
[count]="visibleFiltersCount()"
|
|
16853
17123
|
[position]="morePosition()"
|
|
17124
|
+
[lockPosition]="lockPosition()"
|
|
16854
17125
|
[includedFilters]="includeFilters()"
|
|
16855
17126
|
[excludedFilters]="excludeFilters()"
|
|
16856
17127
|
[aggregations]="aggregations()"
|
|
@@ -16858,7 +17129,7 @@ class FiltersBarComponent {
|
|
|
16858
17129
|
}
|
|
16859
17130
|
}
|
|
16860
17131
|
</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" }] });
|
|
17132
|
+
`, 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
17133
|
}
|
|
16863
17134
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImport: i0, type: FiltersBarComponent, decorators: [{
|
|
16864
17135
|
type: Component,
|
|
@@ -16911,7 +17182,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
|
|
|
16911
17182
|
role="list"
|
|
16912
17183
|
aria-label="Filters list">
|
|
16913
17184
|
@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()" />
|
|
17185
|
+
<FilterButton class="max-w-60" overflowItem [name]="filter.name" [column]="filter.column" [position]="position()" [lockPosition]="lockPosition()" [offset]="offset()" [expandedLevel]="expandedLevel()" />
|
|
16915
17186
|
}
|
|
16916
17187
|
</div>
|
|
16917
17188
|
|
|
@@ -16923,6 +17194,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
|
|
|
16923
17194
|
role="listitem"
|
|
16924
17195
|
[count]="visibleFiltersCount()"
|
|
16925
17196
|
[position]="morePosition()"
|
|
17197
|
+
[lockPosition]="lockPosition()"
|
|
16926
17198
|
[includedFilters]="includeFilters()"
|
|
16927
17199
|
[excludedFilters]="excludeFilters()"
|
|
16928
17200
|
[aggregations]="aggregations()"
|
|
@@ -16936,7 +17208,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.29", ngImpo
|
|
|
16936
17208
|
"(click)": "handleClick($event)"
|
|
16937
17209
|
}
|
|
16938
17210
|
}]
|
|
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 }] }] } });
|
|
17211
|
+
}], 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
17212
|
|
|
16941
17213
|
class LabelService {
|
|
16942
17214
|
appStore = inject(AppStore);
|