@sinequa/atomic-angular 2.9.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,6 @@ import MarkdownIt from "markdown-it";
12
12
  import { Placement } from "@floating-ui/dom";
13
13
  import { Options as Options$1 } from "vanilla-calendar-pro";
14
14
  import { TreeItem } from "@angular/aria/tree";
15
- import { Toolbar } from "@angular/aria/toolbar";
16
15
  import { HttpHandlerFn, HttpInterceptorFn, HttpRequest } from "@angular/common/http";
17
16
  import { HighlightWords } from "highlight-words";
18
17
  import { DatePipe, DatePipeConfig } from "@angular/common";
@@ -90,10 +89,25 @@ export type Basket = {
90
89
  description?: string;
91
90
  ids?: string[];
92
91
  };
92
+ /**
93
+ * A named set of filters the user saved to apply again later ("Recent PDFs" = PDF + last 30 days).
94
+ *
95
+ * Unlike a saved search it holds no query text: applying one replaces the active filters and keeps
96
+ * whatever is typed. `filters` is the very array carried by the `f` URL parameter.
97
+ */
98
+ export type QuickFilter = {
99
+ id: string;
100
+ name: string;
101
+ filters: LegacyFilter[];
102
+ };
93
103
  export type UserSettingsState = {
94
104
  bookmarks: Bookmark[];
95
105
  recentSearches: SearchItem[];
96
106
  savedSearches: SearchItem[];
107
+ /** `url` of the recent searches the user marked as favorite. Removing a favorite never removes the recent search. */
108
+ favoriteSearches?: string[];
109
+ /** Named filter sets the user saved (see {@link QuickFilter}). */
110
+ quickFilters?: QuickFilter[];
97
111
  baskets: Basket[];
98
112
  alerts: Alert[];
99
113
  assistants: Record<string, unknown>;
@@ -1061,8 +1075,8 @@ export declare class MetadataComponent {
1061
1075
  }>;
1062
1076
  class: import("@angular/core").InputSignal<string | undefined>;
1063
1077
  variant: import("@angular/core").InputSignal<"primary" | "secondary" | null | undefined>;
1064
- size: import("@angular/core").InputSignal<"small" | "sm" | "md" | "xs" | "xsmall" | "medium" | null | undefined>;
1065
- scheme: import("@angular/core").InputSignal<"error" | "sage" | "success" | "almond" | "pink" | "grey" | "yellow" | "cherry" | "indigo" | "cyan" | "warning" | "info" | null | undefined>;
1078
+ size: import("@angular/core").InputSignal<"small" | "medium" | "md" | "sm" | "xs" | "xsmall" | null | undefined>;
1079
+ scheme: import("@angular/core").InputSignal<"error" | "sage" | "almond" | "pink" | "grey" | "yellow" | "cherry" | "indigo" | "cyan" | "success" | "warning" | "info" | null | undefined>;
1066
1080
  metadata: import("@angular/core").InputSignal<(string & Record<never, never>) | KeyOf<Article>>;
1067
1081
  article: import("@angular/core").InputSignal<Partial<Article> | (string & Record<never, never>)>;
1068
1082
  limit: import("@angular/core").InputSignalWithTransform<number | undefined, string | number | undefined>;
@@ -3322,8 +3336,10 @@ export declare class UserSettingsPersistence {
3322
3336
  export declare function injectUserSettingsPatch(): <T>(userSettings: Partial<T>, audit?: AuditEvents) => Promise<void>;
3323
3337
  export declare const UserSettingsStore: import("@angular/core").Type<{
3324
3338
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
3339
+ favoriteSearches: import("@angular/core").Signal<string[]>;
3325
3340
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
3326
3341
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
3342
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
3327
3343
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
3328
3344
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
3329
3345
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -3339,12 +3355,20 @@ export declare const UserSettingsStore: import("@angular/core").Type<{
3339
3355
  unbookmark: (id: string) => Promise<void>;
3340
3356
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
3341
3357
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
3358
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
3359
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
3342
3360
  deleteRecentSearch: (index: number) => Promise<void>;
3343
3361
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
3344
3362
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
3345
3363
  deleteSavedSearch: (index: number) => Promise<void>;
3346
3364
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
3347
3365
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
3366
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
3367
+ updateQuickFilter: (id: string, changes: {
3368
+ name?: string;
3369
+ filters?: import("@sinequa/atomic").LegacyFilter[];
3370
+ }) => Promise<void>;
3371
+ removeQuickFilter: (id: string) => Promise<void>;
3348
3372
  deleteBasket: (index: number) => Promise<void>;
3349
3373
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
3350
3374
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -3368,8 +3392,10 @@ export declare const UserSettingsStore: import("@angular/core").Type<{
3368
3392
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
3369
3393
  } & import("@ngrx/signals").StateSource<{
3370
3394
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
3395
+ favoriteSearches: string[];
3371
3396
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
3372
3397
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
3398
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
3373
3399
  baskets: import("@sinequa/atomic-angular").Basket[];
3374
3400
  assistants: Record<string, unknown>;
3375
3401
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -3429,7 +3455,58 @@ export declare function withBookmarkFeatures(): import("@ngrx/signals").SignalSt
3429
3455
  toggleBookmark: (article: Article) => Promise<void>;
3430
3456
  };
3431
3457
  }>;
3432
- export declare function withRecentSearchesFeatures(): import("@ngrx/signals").SignalStoreFeature<import("@ngrx/signals").EmptyFeatureResult, {
3458
+ /**
3459
+ * What identifies a recent search across its re-runs.
3460
+ *
3461
+ * `addCurrentSearch` de-duplicates on the query text and rewrites the `url` of the existing entry
3462
+ * every time the same text is searched again (other filters, other tab), so the `url` is not stable.
3463
+ * The text is, which is why favorites are keyed by it.
3464
+ */
3465
+ export declare function searchItemKey(search: Pick<SearchItem, "label" | "display">): string;
3466
+ /**
3467
+ * User-settings slice holding which recent searches the user marked as favorite.
3468
+ *
3469
+ * Only the keys are stored (see {@link searchItemKey}): a favorite is a flag on a recent search, so
3470
+ * un-favoriting never touches `recentSearches`, while deleting a recent search drops its favorite
3471
+ * (`with-recent-searches.ts`).
3472
+ */
3473
+ export declare function withFavoriteSearchesFeatures(): import("@ngrx/signals").SignalStoreFeature<import("@ngrx/signals").EmptyFeatureResult, {
3474
+ state: {
3475
+ favoriteSearches: NonNullable<UserSettingsState["favoriteSearches"]>;
3476
+ };
3477
+ props: {};
3478
+ methods: {
3479
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
3480
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
3481
+ };
3482
+ }>;
3483
+ /**
3484
+ * User-settings slice holding the user's quick filters: named sets of filters to apply again.
3485
+ *
3486
+ * The store only keeps and persists them. Applying one is the caller's job — it replaces the active
3487
+ * filters, so `queryParamsStore.patch({ filters: quickFilter.filters })` does it.
3488
+ */
3489
+ export declare function withQuickFiltersFeatures(): import("@ngrx/signals").SignalStoreFeature<import("@ngrx/signals").EmptyFeatureResult, {
3490
+ state: {
3491
+ quickFilters: NonNullable<UserSettingsState["quickFilters"]>;
3492
+ };
3493
+ props: {};
3494
+ methods: {
3495
+ addQuickFilter: (name: string, filters: LegacyFilter[]) => Promise<QuickFilter | undefined>;
3496
+ updateQuickFilter: (id: string, changes: {
3497
+ name?: string;
3498
+ filters?: LegacyFilter[];
3499
+ }) => Promise<void>;
3500
+ removeQuickFilter: (id: string) => Promise<void>;
3501
+ };
3502
+ }>;
3503
+ export declare function withRecentSearchesFeatures(): import("@ngrx/signals").SignalStoreFeature<{
3504
+ state: {
3505
+ favoriteSearches: string[];
3506
+ };
3507
+ props: {};
3508
+ methods: {};
3509
+ }, {
3433
3510
  state: {
3434
3511
  recentSearches: UserSettingsState["recentSearches"];
3435
3512
  };
@@ -3456,6 +3533,8 @@ export declare function withUserSettingsFeatures(): import("@ngrx/signals").Sign
3456
3533
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
3457
3534
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
3458
3535
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
3536
+ favoriteSearches?: string[] | undefined;
3537
+ quickFilters?: import("@sinequa/atomic-angular").QuickFilter[] | undefined;
3459
3538
  baskets: import("@sinequa/atomic-angular").Basket[];
3460
3539
  alerts: import("@sinequa/atomic-angular").Alert[];
3461
3540
  assistants: Record<string, unknown>;
@@ -4740,8 +4819,10 @@ export type ComponentMapping = {
4740
4819
  export declare class ApplicationService {
4741
4820
  userSettingsStore: {
4742
4821
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
4822
+ favoriteSearches: import("@angular/core").Signal<string[]>;
4743
4823
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
4744
4824
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
4825
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
4745
4826
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
4746
4827
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
4747
4828
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -4757,12 +4838,20 @@ export declare class ApplicationService {
4757
4838
  unbookmark: (id: string) => Promise<void>;
4758
4839
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
4759
4840
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
4841
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
4842
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
4760
4843
  deleteRecentSearch: (index: number) => Promise<void>;
4761
4844
  updateRecentSearches: (recentSearches: UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
4762
4845
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
4763
4846
  deleteSavedSearch: (index: number) => Promise<void>;
4764
4847
  updateSavedSearches: (savedSearches: UserSettingsState["savedSearches"]) => Promise<void>;
4765
4848
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
4849
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
4850
+ updateQuickFilter: (id: string, changes: {
4851
+ name?: string;
4852
+ filters?: import("@sinequa/atomic").LegacyFilter[];
4853
+ }) => Promise<void>;
4854
+ removeQuickFilter: (id: string) => Promise<void>;
4766
4855
  deleteBasket: (index: number) => Promise<void>;
4767
4856
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
4768
4857
  updateBaskets: (baskets: UserSettingsState["baskets"]) => Promise<void>;
@@ -4786,8 +4875,10 @@ export declare class ApplicationService {
4786
4875
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
4787
4876
  } & import("@ngrx/signals").StateSource<{
4788
4877
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
4878
+ favoriteSearches: string[];
4789
4879
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
4790
4880
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
4881
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
4791
4882
  baskets: import("@sinequa/atomic-angular").Basket[];
4792
4883
  assistants: Record<string, unknown>;
4793
4884
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -5774,8 +5865,10 @@ export declare class AutocompleteService {
5774
5865
  private readonly client;
5775
5866
  userSettingsStore: {
5776
5867
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
5868
+ favoriteSearches: import("@angular/core").Signal<string[]>;
5777
5869
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
5778
5870
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
5871
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
5779
5872
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
5780
5873
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
5781
5874
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -5791,12 +5884,20 @@ export declare class AutocompleteService {
5791
5884
  unbookmark: (id: string) => Promise<void>;
5792
5885
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
5793
5886
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
5887
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
5888
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
5794
5889
  deleteRecentSearch: (index: number) => Promise<void>;
5795
5890
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
5796
5891
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
5797
5892
  deleteSavedSearch: (index: number) => Promise<void>;
5798
5893
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
5799
5894
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
5895
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
5896
+ updateQuickFilter: (id: string, changes: {
5897
+ name?: string;
5898
+ filters?: import("@sinequa/atomic").LegacyFilter[];
5899
+ }) => Promise<void>;
5900
+ removeQuickFilter: (id: string) => Promise<void>;
5800
5901
  deleteBasket: (index: number) => Promise<void>;
5801
5902
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
5802
5903
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -5820,8 +5921,10 @@ export declare class AutocompleteService {
5820
5921
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
5821
5922
  } & import("@ngrx/signals").StateSource<{
5822
5923
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
5924
+ favoriteSearches: string[];
5823
5925
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
5824
5926
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
5927
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
5825
5928
  baskets: import("@sinequa/atomic-angular").Basket[];
5826
5929
  assistants: Record<string, unknown>;
5827
5930
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -6535,9 +6638,9 @@ export declare function getCurrentQueryName(): string | undefined;
6535
6638
  * Les valeurs sont exprimées en tokens Galactik, jamais en dur (cf. `DESIGN_SYSTEM.md`).
6536
6639
  * Elles reproduisent volontairement le rendu de l'ancien `Card` :
6537
6640
  * `p-4` → `--spacing-md` (16px) · `rounded-xl` → `--radius-md` (12px)
6538
- * `gap-4` (CardContent) → `--spacing-md` (16px) · `shadow-sm` → `--shadow-1`
6641
+ * `gap-4` (CardContent) → `--spacing-md` (16px) · `shadow-sm` → `--shadow-2`, avec un liseré `--layer-page-edge`
6539
6642
  */
6540
- export declare const FORM_SURFACE_CLASS = "flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-1)";
6643
+ export declare const FORM_SURFACE_CLASS = "flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) border border-solid border-(--layer-page-edge) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-2)";
6541
6644
  /**
6542
6645
  * Same layout, no card: no background, no padding, no shadow.
6543
6646
  *
@@ -7359,8 +7462,10 @@ export declare class PrincipalService {
7359
7462
  export declare class SavedSearchesService {
7360
7463
  protected readonly userSettingsStore: {
7361
7464
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
7465
+ favoriteSearches: import("@angular/core").Signal<string[]>;
7362
7466
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
7363
7467
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
7468
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
7364
7469
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
7365
7470
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
7366
7471
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -7376,12 +7481,20 @@ export declare class SavedSearchesService {
7376
7481
  unbookmark: (id: string) => Promise<void>;
7377
7482
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
7378
7483
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
7484
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
7485
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
7379
7486
  deleteRecentSearch: (index: number) => Promise<void>;
7380
7487
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
7381
7488
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
7382
7489
  deleteSavedSearch: (index: number) => Promise<void>;
7383
7490
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
7384
7491
  getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
7492
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
7493
+ updateQuickFilter: (id: string, changes: {
7494
+ name?: string;
7495
+ filters?: import("@sinequa/atomic").LegacyFilter[];
7496
+ }) => Promise<void>;
7497
+ removeQuickFilter: (id: string) => Promise<void>;
7385
7498
  deleteBasket: (index: number) => Promise<void>;
7386
7499
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
7387
7500
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -7405,8 +7518,10 @@ export declare class SavedSearchesService {
7405
7518
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
7406
7519
  } & import("@ngrx/signals").StateSource<{
7407
7520
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
7521
+ favoriteSearches: string[];
7408
7522
  recentSearches: SearchItem[];
7409
7523
  savedSearches: SearchItem[];
7524
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
7410
7525
  baskets: import("@sinequa/atomic-angular").Basket[];
7411
7526
  assistants: Record<string, unknown>;
7412
7527
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -7713,8 +7828,10 @@ export declare class SearchService {
7713
7828
  }>;
7714
7829
  protected readonly userSettingsStore: {
7715
7830
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
7831
+ favoriteSearches: import("@angular/core").Signal<string[]>;
7716
7832
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
7717
7833
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
7834
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
7718
7835
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
7719
7836
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
7720
7837
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -7730,12 +7847,20 @@ export declare class SearchService {
7730
7847
  unbookmark: (id: string) => Promise<void>;
7731
7848
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
7732
7849
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
7850
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
7851
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
7733
7852
  deleteRecentSearch: (index: number) => Promise<void>;
7734
7853
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: AuditEvents) => Promise<void>;
7735
7854
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
7736
7855
  deleteSavedSearch: (index: number) => Promise<void>;
7737
7856
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
7738
7857
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
7858
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
7859
+ updateQuickFilter: (id: string, changes: {
7860
+ name?: string;
7861
+ filters?: import("@sinequa/atomic").LegacyFilter[];
7862
+ }) => Promise<void>;
7863
+ removeQuickFilter: (id: string) => Promise<void>;
7739
7864
  deleteBasket: (index: number) => Promise<void>;
7740
7865
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
7741
7866
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -7759,8 +7884,10 @@ export declare class SearchService {
7759
7884
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
7760
7885
  } & import("@ngrx/signals").StateSource<{
7761
7886
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
7887
+ favoriteSearches: string[];
7762
7888
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
7763
7889
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
7890
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
7764
7891
  baskets: import("@sinequa/atomic-angular").Basket[];
7765
7892
  assistants: Record<string, unknown>;
7766
7893
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -8551,8 +8678,10 @@ export declare class ShowBookmarkDirective {
8551
8678
  protected bookmarkHovered: import("@angular/core").WritableSignal<boolean>;
8552
8679
  userSettingsStore: {
8553
8680
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
8681
+ favoriteSearches: import("@angular/core").Signal<string[]>;
8554
8682
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
8555
8683
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
8684
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
8556
8685
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
8557
8686
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
8558
8687
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -8568,12 +8697,20 @@ export declare class ShowBookmarkDirective {
8568
8697
  unbookmark: (id: string) => Promise<void>;
8569
8698
  isBookmarked: (article: Partial<Article>) => boolean;
8570
8699
  toggleBookmark: (article: Article) => Promise<void>;
8700
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
8701
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
8571
8702
  deleteRecentSearch: (index: number) => Promise<void>;
8572
8703
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
8573
8704
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
8574
8705
  deleteSavedSearch: (index: number) => Promise<void>;
8575
8706
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
8576
8707
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
8708
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
8709
+ updateQuickFilter: (id: string, changes: {
8710
+ name?: string;
8711
+ filters?: import("@sinequa/atomic").LegacyFilter[];
8712
+ }) => Promise<void>;
8713
+ removeQuickFilter: (id: string) => Promise<void>;
8577
8714
  deleteBasket: (index: number) => Promise<void>;
8578
8715
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
8579
8716
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -8597,8 +8734,10 @@ export declare class ShowBookmarkDirective {
8597
8734
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
8598
8735
  } & import("@ngrx/signals").StateSource<{
8599
8736
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
8737
+ favoriteSearches: string[];
8600
8738
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
8601
8739
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
8740
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
8602
8741
  baskets: import("@sinequa/atomic-angular").Basket[];
8603
8742
  assistants: Record<string, unknown>;
8604
8743
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -11329,7 +11468,7 @@ export declare class AlertFormComponent {
11329
11468
  */
11330
11469
  private readonly currentSearch;
11331
11470
  readonly canUpdateQuery: import("@angular/core").Signal<boolean>;
11332
- readonly updateStatus: import("@angular/core").WritableSignal<"updating" | "updated" | "idle">;
11471
+ readonly updateStatus: import("@angular/core").WritableSignal<"idle" | "updating" | "updated">;
11333
11472
  /** Why the last save failed — shown in the form until the next attempt. */
11334
11473
  protected readonly saveError: import("@angular/core").WritableSignal<{
11335
11474
  detail?: string;
@@ -11449,7 +11588,7 @@ export declare class ChangePasswordComponent {
11449
11588
  private readonly applicationService;
11450
11589
  private readonly location;
11451
11590
  private readonly auditService;
11452
- protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-1)" | "flex w-full flex-col gap-(--spacing-md)">;
11591
+ protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) border border-solid border-(--layer-page-edge) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-2)" | "flex w-full flex-col gap-(--spacing-md)">;
11453
11592
  protected readonly footerClass = "flex justify-end gap-(--spacing-2xs) -mx-(--spacing-md) -mb-(--spacing-md) rounded-b-(--radius-md) bg-(--layer-page-on-layer) px-(--spacing-md) py-(--spacing-sm)";
11454
11593
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11455
11594
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
@@ -11549,7 +11688,7 @@ export declare class SignInComponent implements OnInit {
11549
11688
  loginPath: string;
11550
11689
  createRoutes: boolean;
11551
11690
  }> & Record<string, unknown>>;
11552
- protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-1)" | "flex w-full flex-col gap-(--spacing-md)">;
11691
+ protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) border border-solid border-(--layer-page-edge) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-2)" | "flex w-full flex-col gap-(--spacing-md)">;
11553
11692
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11554
11693
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
11555
11694
  protected readonly errorClass = "text-(length:--size-base) text-(--font-error-base)";
@@ -11747,7 +11886,7 @@ export declare class ForgotPasswordComponent {
11747
11886
  private readonly client;
11748
11887
  private readonly transloco;
11749
11888
  private readonly auditService;
11750
- protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-1)" | "flex w-full flex-col gap-(--spacing-md)">;
11889
+ protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) border border-solid border-(--layer-page-edge) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-2)" | "flex w-full flex-col gap-(--spacing-md)">;
11751
11890
  protected readonly footerClass = "flex justify-end gap-(--spacing-2xs) -mx-(--spacing-md) -mb-(--spacing-md) rounded-b-(--radius-md) bg-(--layer-page-on-layer) px-(--spacing-md) py-(--spacing-sm)";
11752
11891
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11753
11892
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
@@ -11800,7 +11939,7 @@ export declare class ForgotPasswordComponent {
11800
11939
  export declare class SignedOutComponent {
11801
11940
  private readonly router;
11802
11941
  private readonly client;
11803
- protected readonly surfaceClass = "flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-1)";
11942
+ protected readonly surfaceClass = "flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) border border-solid border-(--layer-page-edge) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-2)";
11804
11943
  /**
11805
11944
  * Navigate to the login screen, which then drives the normal sign-in handshake.
11806
11945
  *
@@ -11813,8 +11952,8 @@ export declare class SignedOutComponent {
11813
11952
  static ɵcmp: i0.ɵɵComponentDeclaration<SignedOutComponent, "signed-out, SignedOut, signedout", never, {}, {}, never, never, true, never>;
11814
11953
  }
11815
11954
  export declare class BookmarkButtonComponent {
11816
- variant: import("@angular/core").InputSignal<"none" | "primary" | "secondary" | "light-accent" | "accent" | "tertiary" | null | undefined>;
11817
- size: import("@angular/core").InputSignal<"small" | "large" | "sm" | "md" | "xs" | "xsmall" | "medium" | "lg" | null | undefined>;
11955
+ variant: import("@angular/core").InputSignal<"none" | "light-accent" | "accent" | "primary" | "secondary" | "tertiary" | null | undefined>;
11956
+ size: import("@angular/core").InputSignal<"small" | "medium" | "large" | "md" | "sm" | "xs" | "xsmall" | "lg" | null | undefined>;
11818
11957
  /**
11819
11958
  * Tab index applied to the inner button.
11820
11959
  *
@@ -12905,7 +13044,7 @@ export declare class SearchFeedbackComponent {
12905
13044
  onClose: import("@angular/core").OutputEmitterRef<void>;
12906
13045
  private readonly injector;
12907
13046
  pages: import("@angular/core").InputSignal<any>;
12908
- variant: import("@angular/core").InputSignal<"none" | "primary" | "secondary" | "light-accent" | "accent" | "tertiary" | null | undefined>;
13047
+ variant: import("@angular/core").InputSignal<"none" | "light-accent" | "accent" | "primary" | "secondary" | "tertiary" | null | undefined>;
12909
13048
  readonly auditService: AuditService;
12910
13049
  protected readonly queryParamsStore: {
12911
13050
  name?: import("@angular/core").Signal<string | undefined> | undefined;
@@ -13193,6 +13332,14 @@ export declare class AggregationDateComponent {
13193
13332
  column: import("@angular/core").InputSignal<string | null>;
13194
13333
  id: import("@angular/core").InputSignal<string | null>;
13195
13334
  collapsible: import("@angular/core").InputSignal<boolean>;
13335
+ /**
13336
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
13337
+ * (the popover of a filter button). Clear and apply are not in the header, whichever way the facet is shown: they sit in a bar at
13338
+ * the top of the facet, as they do under the search field of the list and the tree. Set by the filter button.
13339
+ *
13340
+ * @default false
13341
+ */
13342
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
13196
13343
  collapsed: import("@angular/core").InputSignal<boolean>;
13197
13344
  searchable: import("@angular/core").InputSignal<boolean | undefined>;
13198
13345
  showFiltersCount: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
@@ -13238,7 +13385,7 @@ export declare class AggregationDateComponent {
13238
13385
  *
13239
13386
  * @default 'selection'
13240
13387
  */
13241
- emitOn: import("@angular/core").InputSignal<"apply" | "selection">;
13388
+ emitOn: import("@angular/core").InputSignal<"selection" | "apply">;
13242
13389
  readonly title: import("@angular/core").InputSignal<AggregationTitle>;
13243
13390
  readonly displayEmptyDistributionIntervals: import("@angular/core").InputSignal<boolean>;
13244
13391
  onSelect: import("@angular/core").OutputEmitterRef<AggregationItem[]>;
@@ -13566,6 +13713,11 @@ export declare class AggregationDateComponent {
13566
13713
  "required": false;
13567
13714
  "isSignal": true;
13568
13715
  };
13716
+ "headless": {
13717
+ "alias": "headless";
13718
+ "required": false;
13719
+ "isSignal": true;
13720
+ };
13569
13721
  "collapsed": {
13570
13722
  "alias": "collapsed";
13571
13723
  "required": false;
@@ -13651,6 +13803,15 @@ export declare class AggregationTreeComponent {
13651
13803
  * @default true
13652
13804
  */
13653
13805
  showCheckbox: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
13806
+ /**
13807
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
13808
+ * (the popover of a filter button, whose button already says which facet it is). Select all, clear and apply are not in the
13809
+ * header, whichever way the facet is shown: they sit in a bar under the search field. A popover that holds several facets
13810
+ * (the "more filters" one) keeps the headers: each of them collapses and expands from its title.
13811
+ *
13812
+ * @default false
13813
+ */
13814
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
13654
13815
  /**
13655
13816
  * Whether every selection gesture — row click, checkbox click, Space/Enter on the
13656
13817
  * focused node — applies the filter immediately, instead of only revealing the
@@ -14415,6 +14576,11 @@ export declare class AggregationTreeComponent {
14415
14576
  "required": false;
14416
14577
  "isSignal": true;
14417
14578
  };
14579
+ "headless": {
14580
+ "alias": "headless";
14581
+ "required": false;
14582
+ "isSignal": true;
14583
+ };
14418
14584
  "applyOnSelect": {
14419
14585
  "alias": "applyOnSelect";
14420
14586
  "required": false;
@@ -14493,6 +14659,15 @@ export declare class AggregationListComponent {
14493
14659
  * @default true
14494
14660
  */
14495
14661
  showCheckbox: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
14662
+ /**
14663
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
14664
+ * (the popover of a filter button, whose button already says which facet it is). Select all, clear and apply are not in the
14665
+ * header, whichever way the facet is shown: they sit in a bar under the search field. A popover that holds several facets
14666
+ * (the "more filters" one) keeps the headers: each of them collapses and expands from its title.
14667
+ *
14668
+ * @default false
14669
+ */
14670
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
14496
14671
  /**
14497
14672
  * Whether every selection gesture — row click, checkbox click, Space/Enter on the
14498
14673
  * focused option — applies the filter immediately, instead of only revealing the
@@ -15173,6 +15348,11 @@ export declare class AggregationListComponent {
15173
15348
  "required": false;
15174
15349
  "isSignal": true;
15175
15350
  };
15351
+ "headless": {
15352
+ "alias": "headless";
15353
+ "required": false;
15354
+ "isSignal": true;
15355
+ };
15176
15356
  "applyOnSelect": {
15177
15357
  "alias": "applyOnSelect";
15178
15358
  "required": false;
@@ -15633,6 +15813,15 @@ export declare class AggregationComponent {
15633
15813
  * @default true
15634
15814
  */
15635
15815
  showCheckbox: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
15816
+ /**
15817
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
15818
+ * (the popover of a filter button, whose button already says which facet it is). Select all, clear and apply are not in the
15819
+ * header, whichever way the facet is shown: they sit in a bar under the search field. A popover that holds several facets
15820
+ * (the "more filters" one) keeps the headers: each of them collapses and expands from its title.
15821
+ *
15822
+ * @default false
15823
+ */
15824
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
15636
15825
  /**
15637
15826
  * **List/tree only.** Whether every selection gesture — row click, checkbox click,
15638
15827
  * Space/Enter on the focused item — applies the filter immediately, instead of only
@@ -15698,7 +15887,7 @@ export declare class AggregationComponent {
15698
15887
  *
15699
15888
  * @default 'selection'
15700
15889
  */
15701
- emitOn: import("@angular/core").InputSignal<"apply" | "selection">;
15890
+ emitOn: import("@angular/core").InputSignal<"selection" | "apply">;
15702
15891
  /**
15703
15892
  * Which sub-component renders the aggregation.
15704
15893
  *
@@ -15711,7 +15900,7 @@ export declare class AggregationComponent {
15711
15900
  *
15712
15901
  * @default "auto"
15713
15902
  */
15714
- type: import("@angular/core").InputSignal<"date" | "list" | "tree" | "auto">;
15903
+ type: import("@angular/core").InputSignal<"auto" | "list" | "tree" | "date">;
15715
15904
  /**
15716
15905
  * Whether the host removes itself from the layout (Tailwind's `hidden`, i.e.
15717
15906
  * `display: none`) when it resolves to zero items. When `false` (default), the
@@ -15763,7 +15952,7 @@ export declare class AggregationComponent {
15763
15952
  * The sub-component to render: the explicit `type` input, or the current
15764
15953
  * date/tree/list heuristic when `type` is `"auto"`.
15765
15954
  */
15766
- protected resolvedType: import("@angular/core").Signal<"date" | "list" | "tree">;
15955
+ protected resolvedType: import("@angular/core").Signal<"list" | "tree" | "date">;
15767
15956
  /** Whether a filter is currently applied on this aggregation. */
15768
15957
  private readonly hasFilters;
15769
15958
  /**
@@ -15851,6 +16040,11 @@ export declare class AggregationComponent {
15851
16040
  "required": false;
15852
16041
  "isSignal": true;
15853
16042
  };
16043
+ "headless": {
16044
+ "alias": "headless";
16045
+ "required": false;
16046
+ "isSignal": true;
16047
+ };
15854
16048
  "applyOnSelect": {
15855
16049
  "alias": "applyOnSelect";
15856
16050
  "required": false;
@@ -15922,6 +16116,17 @@ export declare class AggregationPanelComponent {
15922
16116
  hasFilters: import("@angular/core").InputSignal<boolean>;
15923
16117
  selection: import("@angular/core").InputSignal<boolean>;
15924
16118
  isAllSelected: import("@angular/core").InputSignal<boolean>;
16119
+ /**
16120
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
16121
+ * (the popover of a filter button, whose button already says which facet it is). Select all, clear and apply are not in the
16122
+ * header, whichever way the facet is shown: they sit in a bar under the search field. A popover that holds several facets
16123
+ * (the "more filters" one) keeps the headers: each of them collapses and expands from its title.
16124
+ *
16125
+ * @default false
16126
+ */
16127
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16128
+ /** How many items are checked (applied or not yet): the count in the tooltip of the select all checkbox of the bar under the search field. */
16129
+ selectedCount: import("@angular/core").InputSignal<number>;
15925
16130
  searchText: import("@angular/core").ModelSignal<string>;
15926
16131
  itemsLength: import("@angular/core").InputSignal<number>;
15927
16132
  hasMore: import("@angular/core").InputSignal<boolean>;
@@ -15935,7 +16140,7 @@ export declare class AggregationPanelComponent {
15935
16140
  expanded: import("@angular/core").Signal<"" | null>;
15936
16141
  private readonly searchBox;
15937
16142
  /** The galactik popover (`[popover]` / `[dropdown]`) this panel is shown in, if any — resolved through the injector tree. */
15938
- private readonly isInPopover;
16143
+ protected readonly isInPopover: boolean;
15939
16144
  constructor();
15940
16145
  onHeaderClick(event: Event): void;
15941
16146
  onToggle(event: Event): void;
@@ -15996,6 +16201,16 @@ export declare class AggregationPanelComponent {
15996
16201
  "required": false;
15997
16202
  "isSignal": true;
15998
16203
  };
16204
+ "headless": {
16205
+ "alias": "headless";
16206
+ "required": false;
16207
+ "isSignal": true;
16208
+ };
16209
+ "selectedCount": {
16210
+ "alias": "selectedCount";
16211
+ "required": false;
16212
+ "isSignal": true;
16213
+ };
15999
16214
  "searchText": {
16000
16215
  "alias": "searchText";
16001
16216
  "required": false;
@@ -16134,9 +16349,9 @@ export declare class AppliedFiltersComponent {
16134
16349
  */
16135
16350
  readonly variant: import("@angular/core").InputSignal<"primary" | "secondary" | null | undefined>;
16136
16351
  /** Chip colour scheme, passed to galactik's `tag`. */
16137
- readonly scheme: import("@angular/core").InputSignal<"error" | "sage" | "success" | "almond" | "pink" | "grey" | "yellow" | "cherry" | "indigo" | "cyan" | "warning" | "info" | null | undefined>;
16352
+ readonly scheme: import("@angular/core").InputSignal<"error" | "sage" | "almond" | "pink" | "grey" | "yellow" | "cherry" | "indigo" | "cyan" | "success" | "warning" | "info" | null | undefined>;
16138
16353
  /** Chip size, passed to galactik's `tag`. */
16139
- readonly size: import("@angular/core").InputSignal<"small" | "sm" | "md" | "xs" | "xsmall" | "medium" | null | undefined>;
16354
+ readonly size: import("@angular/core").InputSignal<"small" | "medium" | "md" | "sm" | "xs" | "xsmall" | null | undefined>;
16140
16355
  /** Extra classes for each chip, merged by galactik's `tag`. */
16141
16356
  readonly chipClass: import("@angular/core").InputSignal<string>;
16142
16357
  /** A chip was removed. */
@@ -16303,6 +16518,20 @@ export declare class AsideFiltersComponent {
16303
16518
  };
16304
16519
  }, {}, never, never, true, never>;
16305
16520
  }
16521
+ /**
16522
+ * Colour family of a pill-shaped filter button — the twelve schemes of the galactik `Tag`.
16523
+ * `sage` is the default and the primary palette of the theme.
16524
+ */
16525
+ type FilterScheme = "sage" | "almond" | "pink" | "grey" | "yellow" | "cherry" | "indigo" | "cyan" | "success" | "warning" | "info" | "error";
16526
+ /**
16527
+ * Classes of a pill-shaped filter button: its shape, the border and the hover of its scheme, and the scheme's tint
16528
+ * while its popover is open. It is always the outlined pill, with no fill at rest — never the filled `primary` button,
16529
+ * and never a tint either when it holds a selection (`selected` is kept for callers, it changes nothing here).
16530
+ */
16531
+ declare function filterPillClasses(scheme: FilterScheme, state: {
16532
+ selected: boolean;
16533
+ open: boolean;
16534
+ }): string;
16306
16535
  export type CFilterEx = CFilter & {
16307
16536
  name: string;
16308
16537
  count: number;
@@ -16311,6 +16540,8 @@ export type CFilterEx = CFilter & {
16311
16540
  hidden: boolean;
16312
16541
  legacyFilter?: LegacyFilter;
16313
16542
  };
16543
+ /** Look of a filter button: the default flat button, or a rounded outlined pill. */
16544
+ export type FilterAppearance = "default" | "pill";
16314
16545
  export declare class FilterButtonComponent {
16315
16546
  name: import("@angular/core").InputSignal<string | undefined>;
16316
16547
  column: import("@angular/core").InputSignal<string>;
@@ -16325,21 +16556,39 @@ export declare class FilterButtonComponent {
16325
16556
  lockPosition: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16326
16557
  expandedLevel: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
16327
16558
  /**
16328
- * Set by `filters-bar` on the filters that do not fit and are hidden by the overflow manager. They
16329
- * leave the toolbar's keyboard navigation: a roving focus cannot land on an element with
16330
- * `display: none`, so the arrow keys used to stall on the last visible filter while the tab stop
16331
- * silently moved to a hidden one.
16559
+ * Look of the button. `pill` makes it a rounded outlined pill that stays that pill, with no fill, once the filter holds
16560
+ * a selection; the popover it opens is the same.
16561
+ *
16562
+ * @default "default"
16563
+ */
16564
+ appearance: import("@angular/core").InputSignal<FilterAppearance>;
16565
+ /**
16566
+ * Colour family of a `pill`: its outline and its hover, and the tint it takes while its popover is open. The text
16567
+ * is unchanged. Ignored by the default appearance.
16568
+ *
16569
+ * @default "sage"
16332
16570
  */
16333
- overflowed: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16334
- protected variant: import("@angular/core").WritableSignal<"none" | "primary" | "secondary" | "light-accent" | "accent" | "tertiary" | null | undefined>;
16571
+ scheme: import("@angular/core").InputSignal<FilterScheme>;
16572
+ protected variant: import("@angular/core").WritableSignal<"none" | "light-accent" | "accent" | "primary" | "secondary" | "tertiary" | null | undefined>;
16335
16573
  protected filter: import("@angular/core").WritableSignal<CFilterEx>;
16336
16574
  /** Unique id wiring the trigger's `popovertarget` to the `<div popover>` `id`. */
16337
16575
  protected readonly popoverId: string;
16338
16576
  popoverRef: import("@angular/core").Signal<PopoverDirective | undefined>;
16339
16577
  /** True while the native popover is open — drives the trigger's open styling. */
16340
16578
  protected readonly isOpen: import("@angular/core").Signal<boolean>;
16341
- /** Set when this button sits in a `filters-bar` toolbar: the inner button then is the roving widget. */
16342
- protected readonly toolbar: Toolbar | null;
16579
+ /** Classes of the trigger: its shape (`appearance`) and its open state. */
16580
+ protected readonly triggerClass: import("@angular/core").Signal<string>;
16581
+ /**
16582
+ * The popover is placed by Floating UI — flipped above the button when there is no room under it, shifted into the viewport —
16583
+ * until the user resizes it. From then on it stays where it is (`lockPosition`) as long as it is open: a popover that kept
16584
+ * flipping while its height changes would jump under the pointer. It keeps the side it was on. Closing lets it go: the next
16585
+ * opening places it again, and only the height the user chose is kept.
16586
+ */
16587
+ protected readonly resized: import("@angular/core").WritableSignal<boolean>;
16588
+ private readonly flippedAbove;
16589
+ protected readonly placement: import("@angular/core").Signal<Placement>;
16590
+ /** The user has chosen a height at least once: the facet fills the popover instead of keeping its comfortable size. */
16591
+ protected readonly sized: import("@angular/core").WritableSignal<boolean>;
16343
16592
  protected nativeElement: any;
16344
16593
  protected aggregationsStore: {
16345
16594
  aggregations: import("@angular/core").Signal<import("@sinequa/atomic").Aggregation[]>;
@@ -16778,24 +17027,22 @@ export declare class FilterButtonComponent {
16778
17027
  columnMap?: Record<string, import("@sinequa/atomic").CCColumn> | undefined;
16779
17028
  }>;
16780
17029
  constructor();
17030
+ private popoverElement;
17031
+ /** Once the popover is closed, Floating UI places it again the next time it opens; the height the user chose stays. */
17032
+ protected onToggle(): void;
17033
+ /**
17034
+ * Gives the position back to Floating UI: a top edge that was moved is put back where the placement leaves it, and the
17035
+ * popover may flip or shift again. The height the user chose stays.
17036
+ */
17037
+ private unpin;
17038
+ /** The user starts to resize: pins the popover, on the side Floating UI had put it. */
17039
+ protected onResizeStart(): void;
16781
17040
  /**
16782
17041
  * Toggles the popover on keyboard activation of the (roving) toolbar widget
16783
17042
  * host. Always cancels the default action; opening is suppressed for disabled
16784
17043
  * filters, mirroring the previous deprecated-popover behavior.
16785
17044
  */
16786
17045
  protected toggle(event: Event): void;
16787
- /**
16788
- * Keeps the toolbar's roving keyboard handler out of the panel.
16789
- *
16790
- * The panel is a DOM descendant of the `@angular/aria` toolbar, which owns the arrow keys to
16791
- * rove between widgets. Its handler therefore consumed the arrows pressed *inside* the panel,
16792
- * and the native radio group of the date aggregation never moved: focus stayed on the first
16793
- * option whatever the user pressed. Pointer events were already isolated (above) for the same
16794
- * reason — this is the keyboard half of that isolation.
16795
- *
16796
- * Tab and Escape are deliberately let through: they must keep leaving and closing the panel.
16797
- */
16798
- protected isolateNavigationKeys(event: KeyboardEvent): void;
16799
17046
  /**
16800
17047
  * Closes the popover when focus leaves the filter entirely.
16801
17048
  *
@@ -16847,13 +17094,184 @@ export declare class FilterButtonComponent {
16847
17094
  "required": false;
16848
17095
  "isSignal": true;
16849
17096
  };
16850
- "overflowed": {
16851
- "alias": "overflowed";
17097
+ "appearance": {
17098
+ "alias": "appearance";
17099
+ "required": false;
17100
+ "isSignal": true;
17101
+ };
17102
+ "scheme": {
17103
+ "alias": "scheme";
16852
17104
  "required": false;
16853
17105
  "isSignal": true;
16854
17106
  };
16855
17107
  }, {}, never, never, true, never>;
16856
17108
  }
17109
+ /**
17110
+ * How the overflow facets are laid out.
17111
+ *
17112
+ * - `drilldown` (the default): a list of the facets, each with a chevron; picking one replaces the list with that facet
17113
+ * alone (under a header with a back button). Give the host a height (a flex column) and the facet's own list is the one
17114
+ * scroller; in a plain scrolling container it grows and the container scrolls.
17115
+ * - `accordion`: every facet is a collapsible section of one scrolling list.
17116
+ */
17117
+ export type MoreLayout = "accordion" | "drilldown";
17118
+ export declare class MoreComponent {
17119
+ protected readonly SEARCH_THRESHOLD = 6;
17120
+ /**
17121
+ * The facet of the `accordion` layout, its header dressed as a row of the drilldown list (same height, weight, hover and
17122
+ * focus), so the two layouts read alike. It is a descendant selector on the header rather than an input of the facet: the
17123
+ * header belongs to the facet (also shown in a drawer, where it is deliberately not a button to the eye), and only this
17124
+ * popover wants it to look like a row. Whole-row focus ring on `focus-within`: the chevron is the tab stop (the `<summary>` is
17125
+ * out of the tab order), and a ring on a 24px chevron alone is not where the eye looks for it.
17126
+ */
17127
+ protected readonly accordionClass = "w-full px-1 max-h-[calc(15lh+7rem)] [&_details>summary]:h-9 [&_details>summary]:pl-1.5 [&_details>summary]:font-normal [&_details>summary]:hover:bg-(--bg-primary-lighter) [&_details>summary]:focus-within:outline-2 [&_details>summary]:focus-within:outline-(--stroke-focus) [&_details>summary_button]:hover:bg-transparent [&_details>summary_button]:focus-visible:outline-none";
17128
+ /** A row of the drilldown list: a plain button, the same hover and focus as the rows of a facet. */
17129
+ protected readonly rowClass = "flex w-full items-center gap-2 px-2 py-2 text-left text-sm rounded scroll-my-3 aria-disabled:text-(--font-neutral-muted) aria-disabled:cursor-default aria-disabled:pointer-events-none hover:bg-(--bg-primary-lighter) focus:outline-2 focus:outline-(--stroke-focus)";
17130
+ /**
17131
+ * Layout of the facets: a list of facets that opens one at a time (`drilldown`, the default), or collapsible sections
17132
+ * (`accordion`). See {@link MoreLayout}.
17133
+ *
17134
+ * @default "drilldown"
17135
+ */
17136
+ layout: import("@angular/core").InputSignal<MoreLayout>;
17137
+ /**
17138
+ * Whether every selection gesture applies the filter immediately, instead of revealing the Apply button. Relayed as-is to
17139
+ * each `<Aggregation [applyOnSelect]>`. In `drilldown` layout the opened facet then stays open (the user ticks several
17140
+ * values in a row); otherwise applying brings the list back.
17141
+ *
17142
+ * @default false
17143
+ */
17144
+ applyOnSelect: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17145
+ count: import("@angular/core").InputSignal<number>;
17146
+ includedFilters: import("@angular/core").InputSignal<string[]>;
17147
+ excludedFilters: import("@angular/core").InputSignal<string[]>;
17148
+ aggregations: import("@angular/core").InputSignal<Aggregation[] | undefined>;
17149
+ homepage: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17150
+ /**
17151
+ * Whether a section removes itself from the layout when its aggregation
17152
+ * resolves to zero items, instead of staying with a dimmed, non-expandable
17153
+ * header. Relayed as-is to each `<Aggregation [hideWhenEmpty]>` — a missing
17154
+ * aggregation always hides regardless of this input.
17155
+ *
17156
+ * @default false
17157
+ */
17158
+ hideWhenEmpty: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17159
+ aggregationsService: AggregationsService;
17160
+ private readonly injector;
17161
+ private readonly aggregationsStore;
17162
+ private readonly appStore;
17163
+ private readonly queryParamsStore;
17164
+ private readonly host;
17165
+ /** The facet-name search query, cleared whenever the popup is reopened. */
17166
+ searchText: import("@angular/core").ModelSignal<string>;
17167
+ /** Name of the facet opened in `drilldown` layout; `null` while the list shows. */
17168
+ private readonly openedName;
17169
+ private readonly title;
17170
+ /**
17171
+ * The overflow filters rendered as accordions: the authorized filters beyond the
17172
+ * first `count` (which are already shown in the bar).
17173
+ *
17174
+ * @remarks
17175
+ * Pure display wiring — authorization (and the admin `hidden` rule) is handled by
17176
+ * {@link AggregationsService.getAuthorizedFilters}; `toSpliced` just drops the
17177
+ * filters already shown in the bar.
17178
+ */
17179
+ filters: import("@angular/core").Signal<{
17180
+ field: string;
17181
+ column: string;
17182
+ name: string;
17183
+ }[]>;
17184
+ /** {@link filters}, narrowed to those whose name matches {@link searchText}. */
17185
+ filteredFilters: import("@angular/core").Signal<{
17186
+ field: string;
17187
+ column: string;
17188
+ name: string;
17189
+ }[]>;
17190
+ /**
17191
+ * The rows of the `drilldown` list: the filtered facets that resolve to an aggregation, with their icon and the number of
17192
+ * values applied. Same rule as {@link AggregationComponent} for what hides: a missing aggregation always, an empty one
17193
+ * only with `hideWhenEmpty` (a date facet is never empty, its custom range stays usable); otherwise an empty one is dimmed.
17194
+ */
17195
+ protected readonly rows: import("@angular/core").Signal<{
17196
+ filter: {
17197
+ field: string;
17198
+ column: string;
17199
+ name: string;
17200
+ };
17201
+ icon: string | undefined;
17202
+ count: number;
17203
+ empty: boolean;
17204
+ }[]>;
17205
+ /** The facet opened in `drilldown` layout, if it is still one of the overflow filters. */
17206
+ protected readonly active: import("@angular/core").Signal<{
17207
+ filter: {
17208
+ field: string;
17209
+ column: string;
17210
+ name: string;
17211
+ };
17212
+ icon: string | undefined;
17213
+ count: number;
17214
+ empty: boolean;
17215
+ } | undefined>;
17216
+ /** An opened facet stays reachable even if the search narrowed it out of the rows. */
17217
+ private resolveHidden;
17218
+ /** Opens a facet: focus goes to its title; a facet with a search field takes it from there, as in the popover of a filter button. */
17219
+ protected open(name: string): void;
17220
+ /** A facet was applied: the list comes back, unless every gesture applies (`applyOnSelect`), where the facet stays open. */
17221
+ protected onApplied(): void;
17222
+ /** Back to the list of facets; focus returns to the row it came from (the list was destroyed while the facet was open). */
17223
+ protected back(): void;
17224
+ static ɵfac: i0.ɵɵFactoryDeclaration<MoreComponent, never>;
17225
+ static ɵcmp: i0.ɵɵComponentDeclaration<MoreComponent, "more, More", never, {
17226
+ "layout": {
17227
+ "alias": "layout";
17228
+ "required": false;
17229
+ "isSignal": true;
17230
+ };
17231
+ "applyOnSelect": {
17232
+ "alias": "applyOnSelect";
17233
+ "required": false;
17234
+ "isSignal": true;
17235
+ };
17236
+ "count": {
17237
+ "alias": "count";
17238
+ "required": false;
17239
+ "isSignal": true;
17240
+ };
17241
+ "includedFilters": {
17242
+ "alias": "includedFilters";
17243
+ "required": false;
17244
+ "isSignal": true;
17245
+ };
17246
+ "excludedFilters": {
17247
+ "alias": "excludedFilters";
17248
+ "required": false;
17249
+ "isSignal": true;
17250
+ };
17251
+ "aggregations": {
17252
+ "alias": "aggregations";
17253
+ "required": false;
17254
+ "isSignal": true;
17255
+ };
17256
+ "homepage": {
17257
+ "alias": "homepage";
17258
+ "required": false;
17259
+ "isSignal": true;
17260
+ };
17261
+ "hideWhenEmpty": {
17262
+ "alias": "hideWhenEmpty";
17263
+ "required": false;
17264
+ "isSignal": true;
17265
+ };
17266
+ "searchText": {
17267
+ "alias": "searchText";
17268
+ "required": false;
17269
+ "isSignal": true;
17270
+ };
17271
+ }, {
17272
+ "searchText": "searchTextChange";
17273
+ }, never, never, true, never>;
17274
+ }
16857
17275
  export declare class MoreButtonComponent {
16858
17276
  appStore: {
16859
17277
  name: import("@angular/core").Signal<string>;
@@ -17285,15 +17703,45 @@ export declare class MoreButtonComponent {
17285
17703
  nativeElement: any;
17286
17704
  breakpointObserver: BreakpointObserverService;
17287
17705
  aggregationsService: AggregationsService;
17288
- /** Set when this button sits in a `filters-bar` toolbar: the inner button then is the roving widget. */
17289
- protected readonly toolbar: Toolbar | null;
17290
17706
  /**
17291
- * Takes the trigger out of the keyboard navigation (and the toolbar's roving) while there is nothing
17707
+ * Takes the trigger out of the keyboard navigation (Tab) while there is nothing
17292
17708
  * to show behind it, instead of leaving an invisible stop.
17293
17709
  */
17294
17710
  disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17295
- protected readonly triggerClass = "gap-1 truncate font-semibold";
17296
- protected readonly openTriggerClass = "gap-1 truncate font-semibold border border-(--stroke-neutral-dark)/18";
17711
+ /**
17712
+ * Look of the trigger, relayed by `filters-bar` so it matches its filter buttons: `pill` is a rounded
17713
+ * outlined pill.
17714
+ *
17715
+ * @default "default"
17716
+ */
17717
+ appearance: import("@angular/core").InputSignal<FilterAppearance>;
17718
+ /**
17719
+ * Colour family of a `pill` (its outline and hover), relayed by `filters-bar` so the trigger matches its filter buttons.
17720
+ *
17721
+ * @default "sage"
17722
+ */
17723
+ scheme: import("@angular/core").InputSignal<FilterScheme>;
17724
+ /**
17725
+ * Layout of the facets behind the trigger: a list of facets that opens one at a time under a header with a back button
17726
+ * (`drilldown`, the default), or collapsible sections (`accordion`). Relayed to `<More>`.
17727
+ *
17728
+ * @default "drilldown"
17729
+ */
17730
+ layout: import("@angular/core").InputSignal<MoreLayout>;
17731
+ /**
17732
+ * Whether every selection gesture applies the filter immediately, instead of revealing the Apply button. Relayed as-is to
17733
+ * `<More [applyOnSelect]>`.
17734
+ *
17735
+ * @default false
17736
+ */
17737
+ applyOnSelect: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17738
+ protected readonly drilldown: import("@angular/core").Signal<boolean>;
17739
+ protected readonly moreClass: import("@angular/core").Signal<"flex min-h-0 w-full flex-1 flex-col" | "block w-full">;
17740
+ /** The scrolling box of the desktop popover; in drilldown a fixed-height column, so both screens have the same size. */
17741
+ protected readonly wrapperClass: import("@angular/core").Signal<"flex min-h-0 w-[19rem] flex-1 flex-col" | "flex h-[min(calc(19lh+7rem),calc(var(--popover-available-height,55vh)_-_1.5rem))] w-[19rem] flex-col" | "min-h-0 w-60 flex-1 overflow-y-auto overscroll-contain" | "max-h-[calc(var(--popover-available-height,55vh)_-_1.5rem)] w-60 overflow-y-auto overscroll-contain">;
17742
+ protected readonly idleVariant: import("@angular/core").Signal<"secondary" | "tertiary">;
17743
+ protected readonly triggerClass: import("@angular/core").Signal<string>;
17744
+ protected readonly openTriggerClass: import("@angular/core").Signal<string>;
17297
17745
  protected readonly openSheet: () => void | undefined;
17298
17746
  protected readonly openDialog: () => void | undefined;
17299
17747
  count: import("@angular/core").InputSignalWithTransform<number, unknown>;
@@ -17328,6 +17776,23 @@ export declare class MoreButtonComponent {
17328
17776
  * @default undefined — never escalate to Dialog
17329
17777
  */
17330
17778
  enrichedThreshold: import("@angular/core").InputSignal<number | undefined>;
17779
+ /**
17780
+ * Until the user resizes, Floating UI places the popover (flip, shift). From the first resize it stays where it is while
17781
+ * open (`lockPosition`), on the side it was on; closing it or scrolling the page lets Floating UI place it again, and only
17782
+ * the height the user chose is kept. Same behaviour as `<filter-button>`.
17783
+ */
17784
+ protected readonly resized: import("@angular/core").WritableSignal<boolean>;
17785
+ private readonly flippedAbove;
17786
+ protected readonly placement: import("@angular/core").Signal<Placement>;
17787
+ /** The user chose a height at least once: the list fills the popover instead of keeping its comfortable size. */
17788
+ protected readonly sized: import("@angular/core").WritableSignal<boolean>;
17789
+ constructor();
17790
+ private popoverElement;
17791
+ /** Once the popover is closed, Floating UI places it again the next time it opens; the chosen height stays. */
17792
+ protected onToggle(): void;
17793
+ private unpin;
17794
+ /** The user starts to resize: pins the popover, on the side Floating UI had put it. */
17795
+ protected onResizeStart(): void;
17331
17796
  /** Unique id wiring the trigger's `popovertarget` to the `<div popover>` `id`. */
17332
17797
  protected readonly popoverId: string;
17333
17798
  protected readonly popoverRef: import("@angular/core").Signal<PopoverDirective | undefined>;
@@ -17367,6 +17832,26 @@ export declare class MoreButtonComponent {
17367
17832
  "required": false;
17368
17833
  "isSignal": true;
17369
17834
  };
17835
+ "appearance": {
17836
+ "alias": "appearance";
17837
+ "required": false;
17838
+ "isSignal": true;
17839
+ };
17840
+ "scheme": {
17841
+ "alias": "scheme";
17842
+ "required": false;
17843
+ "isSignal": true;
17844
+ };
17845
+ "layout": {
17846
+ "alias": "layout";
17847
+ "required": false;
17848
+ "isSignal": true;
17849
+ };
17850
+ "applyOnSelect": {
17851
+ "alias": "applyOnSelect";
17852
+ "required": false;
17853
+ "isSignal": true;
17854
+ };
17370
17855
  "count": {
17371
17856
  "alias": "count";
17372
17857
  "required": false;
@@ -17477,15 +17962,80 @@ export declare class FiltersBarComponent {
17477
17962
  homepage: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17478
17963
  direction: import("@angular/core").InputSignal<"horizontal" | "vertical">;
17479
17964
  /**
17480
- * The distance in pixels between the popover and its trigger element.
17965
+ * Look of the filter buttons: the default flat buttons, or `pill` — rounded outlined pills that fill
17966
+ * once the filter holds a selection, as in a search page's quick-filter row.
17481
17967
  *
17482
- * @defaultValue 8px
17968
+ * @default "default"
17483
17969
  */
17484
- offset: import("@angular/core").InputSignal<number>;
17485
- expandedLevel: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
17970
+ appearance: import("@angular/core").InputSignal<FilterAppearance>;
17486
17971
  /**
17487
- * Event emitted when the clear filters button is clicked.
17488
- * This event can be used to perform additional actions when filters are cleared.
17972
+ * Where the row of filters sits in the bar: from the start (the default), or `center`, where the filters and the
17973
+ * "more" button form one group in the middle, as under the search field of a home page.
17974
+ *
17975
+ * @default "start"
17976
+ */
17977
+ align: import("@angular/core").InputSignal<"start" | "center">;
17978
+ /**
17979
+ * How far apart the buttons are. `compact` (the default) is the tight spacing of a toolbar; `comfortable` puts
17980
+ * `--spacing-lg` (20px) between every button, the quick filters pill and the "more" button included, as under the
17981
+ * search field of a home page.
17982
+ *
17983
+ * @default "compact"
17984
+ */
17985
+ spacing: import("@angular/core").InputSignal<"compact" | "comfortable">;
17986
+ /**
17987
+ * Colour family of the `pill` appearance, one of the twelve schemes of the galactik `Tag`. It sets the outline
17988
+ * of the pills and their hover — the tint they take while a popover is open — and nothing else: the text is
17989
+ * unchanged. A pill whose filter is applied stays the outlined pill, with no fill. Ignored by the default appearance.
17990
+ *
17991
+ * @default "sage"
17992
+ */
17993
+ scheme: import("@angular/core").InputSignal<FilterScheme>;
17994
+ /**
17995
+ * Whether the bar shows its "clear all filters" and "clear basket" buttons. Turn it off when the page
17996
+ * clears the filters elsewhere.
17997
+ *
17998
+ * @default true
17999
+ */
18000
+ showClearButtons: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18001
+ /**
18002
+ * Above this many overflow filters, the "more filters" popover escalates to a modal dialog. Relayed
18003
+ * as-is to `<MoreButton [enrichedThreshold]>`.
18004
+ *
18005
+ * @default undefined — never escalate
18006
+ */
18007
+ enrichedThreshold: import("@angular/core").InputSignal<number | undefined>;
18008
+ /**
18009
+ * Layout of the "more filters" popover: a list of filters that opens one at a time, with a back button (`drilldown`), or
18010
+ * collapsible sections (`accordion`). Relayed as-is to `<MoreButton [layout]>`.
18011
+ *
18012
+ * @default "drilldown"
18013
+ */
18014
+ moreLayout: import("@angular/core").InputSignal<MoreLayout>;
18015
+ /**
18016
+ * Whether every selection gesture in the "more filters" popover applies the filter immediately, instead of revealing the
18017
+ * Apply button. Relayed as-is to `<MoreButton [applyOnSelect]>`.
18018
+ *
18019
+ * @default false
18020
+ */
18021
+ applyOnSelect: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18022
+ /**
18023
+ * Whether a section of the "more filters" popover removes itself when its aggregation has no item.
18024
+ * Relayed as-is to `<MoreButton [hideWhenEmpty]>`.
18025
+ *
18026
+ * @default false
18027
+ */
18028
+ hideWhenEmpty: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18029
+ /**
18030
+ * The distance in pixels between the popover and its trigger element.
18031
+ *
18032
+ * @defaultValue 8px
18033
+ */
18034
+ offset: import("@angular/core").InputSignal<number>;
18035
+ expandedLevel: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
18036
+ /**
18037
+ * Event emitted when the clear filters button is clicked.
18038
+ * This event can be used to perform additional actions when filters are cleared.
17489
18039
  */
17490
18040
  onClearFilters: import("@angular/core").OutputEmitterRef<void>;
17491
18041
  /**
@@ -17494,6 +18044,8 @@ export declare class FiltersBarComponent {
17494
18044
  */
17495
18045
  onClearBasket: import("@angular/core").OutputEmitterRef<void>;
17496
18046
  protected cn: import("cn").CnFunction;
18047
+ /** The gap between the buttons: the 20px of a home page under `comfortable`, the tight spacing of a toolbar otherwise. */
18048
+ protected readonly pillGap: import("@angular/core").Signal<"gap-(--spacing-lg)" | "gap-2">;
17497
18049
  protected readonly moreButtonRef: import("@angular/core").Signal<MoreButtonComponent | undefined>;
17498
18050
  protected readonly overflowManagerRef: import("@angular/core").Signal<OverflowManagerDirective | undefined>;
17499
18051
  protected cdr: ChangeDetectorRef;
@@ -17943,6 +18495,11 @@ export declare class FiltersBarComponent {
17943
18495
  protected hasFilters: import("@angular/core").Signal<string | boolean>;
17944
18496
  protected currentBasket: import("@angular/core").Signal<string | undefined>;
17945
18497
  protected hasAggregations: import("@angular/core").Signal<boolean>;
18498
+ /**
18499
+ * Whether the bar has anything to show: an applied filter, a basket or aggregations to filter on.
18500
+ * The toolbar is rendered only then, so a page can tell whether to reserve room for the bar.
18501
+ */
18502
+ readonly hasContent: import("@angular/core").Signal<boolean>;
17946
18503
  /**
17947
18504
  * The full list of authorized filters, NOT capped by `filtersCount`.
17948
18505
  *
@@ -18069,84 +18626,43 @@ export declare class FiltersBarComponent {
18069
18626
  "required": false;
18070
18627
  "isSignal": true;
18071
18628
  };
18072
- "offset": {
18073
- "alias": "offset";
18629
+ "appearance": {
18630
+ "alias": "appearance";
18074
18631
  "required": false;
18075
18632
  "isSignal": true;
18076
18633
  };
18077
- "expandedLevel": {
18078
- "alias": "expandedLevel";
18634
+ "align": {
18635
+ "alias": "align";
18079
18636
  "required": false;
18080
18637
  "isSignal": true;
18081
18638
  };
18082
- }, {
18083
- "onClearFilters": "onClearFilters";
18084
- "onClearBasket": "onClearBasket";
18085
- }, never, never, true, never>;
18086
- }
18087
- export declare class MoreComponent {
18088
- protected readonly SEARCH_THRESHOLD = 6;
18089
- count: import("@angular/core").InputSignal<number>;
18090
- includedFilters: import("@angular/core").InputSignal<string[]>;
18091
- excludedFilters: import("@angular/core").InputSignal<string[]>;
18092
- aggregations: import("@angular/core").InputSignal<Aggregation[] | undefined>;
18093
- homepage: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18094
- /**
18095
- * Whether a section removes itself from the layout when its aggregation
18096
- * resolves to zero items, instead of staying with a dimmed, non-expandable
18097
- * header. Relayed as-is to each `<Aggregation [hideWhenEmpty]>` — a missing
18098
- * aggregation always hides regardless of this input.
18099
- *
18100
- * @default false
18101
- */
18102
- hideWhenEmpty: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18103
- aggregationsService: AggregationsService;
18104
- /** The facet-name search query, cleared whenever the popup is reopened. */
18105
- searchText: import("@angular/core").ModelSignal<string>;
18106
- /**
18107
- * The overflow filters rendered as accordions: the authorized filters beyond the
18108
- * first `count` (which are already shown in the bar).
18109
- *
18110
- * @remarks
18111
- * Pure display wiring — authorization (and the admin `hidden` rule) is handled by
18112
- * {@link AggregationsService.getAuthorizedFilters}; `toSpliced` just drops the
18113
- * filters already shown in the bar.
18114
- */
18115
- filters: import("@angular/core").Signal<{
18116
- field: string;
18117
- column: string;
18118
- name: string;
18119
- }[]>;
18120
- /** {@link filters}, narrowed to those whose name matches {@link searchText}. */
18121
- filteredFilters: import("@angular/core").Signal<{
18122
- field: string;
18123
- column: string;
18124
- name: string;
18125
- }[]>;
18126
- static ɵfac: i0.ɵɵFactoryDeclaration<MoreComponent, never>;
18127
- static ɵcmp: i0.ɵɵComponentDeclaration<MoreComponent, "more, More", never, {
18128
- "count": {
18129
- "alias": "count";
18639
+ "spacing": {
18640
+ "alias": "spacing";
18130
18641
  "required": false;
18131
18642
  "isSignal": true;
18132
18643
  };
18133
- "includedFilters": {
18134
- "alias": "includedFilters";
18644
+ "scheme": {
18645
+ "alias": "scheme";
18135
18646
  "required": false;
18136
18647
  "isSignal": true;
18137
18648
  };
18138
- "excludedFilters": {
18139
- "alias": "excludedFilters";
18649
+ "showClearButtons": {
18650
+ "alias": "showClearButtons";
18140
18651
  "required": false;
18141
18652
  "isSignal": true;
18142
18653
  };
18143
- "aggregations": {
18144
- "alias": "aggregations";
18654
+ "enrichedThreshold": {
18655
+ "alias": "enrichedThreshold";
18145
18656
  "required": false;
18146
18657
  "isSignal": true;
18147
18658
  };
18148
- "homepage": {
18149
- "alias": "homepage";
18659
+ "moreLayout": {
18660
+ "alias": "moreLayout";
18661
+ "required": false;
18662
+ "isSignal": true;
18663
+ };
18664
+ "applyOnSelect": {
18665
+ "alias": "applyOnSelect";
18150
18666
  "required": false;
18151
18667
  "isSignal": true;
18152
18668
  };
@@ -18155,14 +18671,20 @@ export declare class MoreComponent {
18155
18671
  "required": false;
18156
18672
  "isSignal": true;
18157
18673
  };
18158
- "searchText": {
18159
- "alias": "searchText";
18674
+ "offset": {
18675
+ "alias": "offset";
18676
+ "required": false;
18677
+ "isSignal": true;
18678
+ };
18679
+ "expandedLevel": {
18680
+ "alias": "expandedLevel";
18160
18681
  "required": false;
18161
18682
  "isSignal": true;
18162
18683
  };
18163
18684
  }, {
18164
- "searchText": "searchTextChange";
18165
- }, never, never, true, never>;
18685
+ "onClearFilters": "onClearFilters";
18686
+ "onClearBasket": "onClearBasket";
18687
+ }, never, ["[filtersBarStart]"], true, never>;
18166
18688
  }
18167
18689
  /**
18168
18690
  * Injection token that indicates whether custom date ranges are allowed.
@@ -18703,20 +19225,75 @@ export type PreviewAssistantSlot = {
18703
19225
  * provides a function that always returns `undefined`, or omits the "discussion" case.
18704
19226
  */
18705
19227
  export declare const PREVIEW_ASSISTANT_COMPONENT: InjectionToken<(kind: "summary" | "discussion") => PreviewAssistantSlot | undefined>;
18706
- export declare const RECENT_SEARCHES_OPTIONS: {
18707
- itemsPerPage: number;
18708
- showLoadMore: boolean;
18709
- routerLink: string;
19228
+ /** What the panel lists: every recent search, or only the ones marked as favorite. */
19229
+ export type HistoryPanelTab = "all" | "favorites";
19230
+ /** A run of searches that share a day (today, yesterday) or, further back, a month. */
19231
+ export type HistoryGroup = {
19232
+ kind: "today" | "yesterday" | "month";
19233
+ /** The month, already formatted for the active language (`kind === "month"` only). */
19234
+ label?: string;
19235
+ items: SearchItem[];
18710
19236
  };
18711
- export declare const RECENT_SEARCHES_CONFIG: InjectionToken<import("@sinequa/atomic-angular").ListPanelConfig>;
18712
- export declare class RecentSearchesComponent {
18713
- options: import("@angular/core").InputSignal<import("@sinequa/atomic-angular").ListPanelConfig | undefined>;
18714
- protected floating: PopoverDirective | null;
18715
- protected config: import("@sinequa/atomic-angular").ListPanelConfig;
19237
+ /**
19238
+ * Splits searches (already sorted, most recent first) into today, yesterday and one group per month,
19239
+ * keeping their order. A search without a valid date is listed with the oldest month's group it
19240
+ * follows, so nothing is dropped.
19241
+ */
19242
+ export declare function groupSearchesByDate(searches: SearchItem[], language: string, now?: Date): HistoryGroup[];
19243
+ /**
19244
+ * Scrolls a title that is cut off, while its row is hovered or holds the focus.
19245
+ *
19246
+ * The title is a clipped box (`[historyTitleMarquee]`) holding an inner element; when the text is wider than the box,
19247
+ * the inner element slides to its end at a reading pace, and goes back when the pointer or the focus leaves. A title
19248
+ * that fits is left alone, and so is everything under `prefers-reduced-motion`. It reads the geometry when it starts,
19249
+ * so a resized panel or a changed language needs nothing.
19250
+ */
19251
+ export declare class HistoryTitleMarqueeDirective {
19252
+ private readonly host;
19253
+ private animation?;
19254
+ protected start(): void;
19255
+ protected stop(): void;
19256
+ static ɵfac: i0.ɵɵFactoryDeclaration<HistoryTitleMarqueeDirective, never>;
19257
+ static ɵdir: i0.ɵɵDirectiveDeclaration<HistoryTitleMarqueeDirective, "[historyTitleMarquee]", never, {}, {}, never, never, true, never>;
19258
+ }
19259
+ /**
19260
+ * Side panel listing the user's recent searches, with a switch to show only the favorite ones.
19261
+ *
19262
+ * It is a plain flex child that grows from `0` to `--history-panel-width` when `open` turns true,
19263
+ * so placed beside a sidebar it pushes the page content aside rather than covering it. Closed, it is
19264
+ * `inert` and hidden from assistive technology. On mobile it becomes a `Sheet` sliding from the left.
19265
+ *
19266
+ * The data is the user's own: recent searches and favorites come from `UserSettingsStore`, and a
19267
+ * click re-runs the search through the router, so the panel needs no wiring beyond `open`.
19268
+ *
19269
+ * Theming: every colour is a CSS variable with a semantic-token fallback, so the panel is a plain light card by
19270
+ * default and a host can retint it — a dark sidebar, say — by setting the variables on it (or an ancestor):
19271
+ * `--history-panel-bg`, `-fg`, `-muted` (header, labels, hints), `-icon`, `-hover`, `-active` (a row),
19272
+ * `-group` (the All / Favorites track), `-toggle-active`, `-toggle-hover`, `-toggle-fg`, `-fav`, `-fav-hover-bg`,
19273
+ * `-del-hover-bg`, `-del-hover-fg` (the Sheet of mobile wears the same ones), and `--history-panel-width` (15.625rem by default). `--history-panel-gap` is the margin
19274
+ * it takes on its start side while open (0 by default), for a layout whose neighbours do not space themselves.
19275
+ *
19276
+ * ```html
19277
+ * <app-sidebar />
19278
+ * <history-panel [(open)]="historyOpen" />
19279
+ * <main>…</main>
19280
+ * ```
19281
+ */
19282
+ export declare class HistoryPanelComponent {
19283
+ /** Whether the panel is shown. Two-way: the close button and `Escape` write it back. */
19284
+ readonly open: import("@angular/core").ModelSignal<boolean>;
19285
+ /** Which list is shown. Two-way. */
19286
+ readonly tab: import("@angular/core").ModelSignal<HistoryPanelTab>;
19287
+ /** Extra classes for the desktop `<aside>` (merged with `cn`). */
19288
+ readonly class: import("@angular/core").InputSignal<string | undefined>;
19289
+ /** Emitted once a search has been re-run from the panel — a host that overlays it can close it then. */
19290
+ readonly searchSelected: import("@angular/core").OutputEmitterRef<SearchItem>;
18716
19291
  protected readonly userSettingsStore: {
18717
19292
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
19293
+ favoriteSearches: import("@angular/core").Signal<string[]>;
18718
19294
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
18719
19295
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
19296
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
18720
19297
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
18721
19298
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
18722
19299
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -18732,12 +19309,20 @@ export declare class RecentSearchesComponent {
18732
19309
  unbookmark: (id: string) => Promise<void>;
18733
19310
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
18734
19311
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
19312
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
19313
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
18735
19314
  deleteRecentSearch: (index: number) => Promise<void>;
18736
19315
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
18737
19316
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
18738
19317
  deleteSavedSearch: (index: number) => Promise<void>;
18739
19318
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
18740
19319
  getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
19320
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
19321
+ updateQuickFilter: (id: string, changes: {
19322
+ name?: string;
19323
+ filters?: import("@sinequa/atomic").LegacyFilter[];
19324
+ }) => Promise<void>;
19325
+ removeQuickFilter: (id: string) => Promise<void>;
18741
19326
  deleteBasket: (index: number) => Promise<void>;
18742
19327
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
18743
19328
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -18761,8 +19346,10 @@ export declare class RecentSearchesComponent {
18761
19346
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
18762
19347
  } & import("@ngrx/signals").StateSource<{
18763
19348
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
19349
+ favoriteSearches: string[];
18764
19350
  recentSearches: SearchItem[];
18765
19351
  savedSearches: SearchItem[];
19352
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
18766
19353
  baskets: import("@sinequa/atomic-angular").Basket[];
18767
19354
  assistants: Record<string, unknown>;
18768
19355
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -18772,72 +19359,1092 @@ export declare class RecentSearchesComponent {
18772
19359
  agents: import("@sinequa/atomic-angular").AgentUserSettings;
18773
19360
  disabledHighlightCategories: string[];
18774
19361
  }>;
18775
- protected readonly transloco: TranslocoService;
19362
+ private readonly transloco;
18776
19363
  private readonly router;
18777
- protected subtextOf: (search: SearchItem) => string | undefined;
18778
- protected urlOf: (search: SearchItem) => string;
18779
- protected labelOf: (search: SearchItem) => string;
18780
- protected readonly range: import("@angular/core").WritableSignal<number>;
18781
- protected readonly recentSearches: import("@angular/core").Signal<SearchItem[]>;
18782
- protected readonly paginatedRecentSearches: import("@angular/core").Signal<SearchItem[]>;
18783
- protected readonly hasMore: import("@angular/core").Signal<boolean>;
19364
+ private readonly breakpointObserver;
19365
+ private readonly sheet;
19366
+ protected readonly isMobile: import("@angular/core").Signal<boolean>;
19367
+ protected readonly sheetClasses: string;
19368
+ protected readonly rowButton = "flex size-5 shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-full border-0 bg-transparent p-0 transition-[max-width,opacity,background-color,color] duration-150 motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-(--stroke-focus) focus-visible:-outline-offset-2";
19369
+ protected readonly rowButtonHidden = "max-w-0 opacity-0 group-hover/row:max-w-5 group-hover/row:opacity-100 group-focus-within/row:max-w-5 group-focus-within/row:opacity-100";
19370
+ /**
19371
+ * Gives a `<history-panel>` an opening and closing animation that does not depend on the host
19372
+ * app: width, padding and margin ease out together, and reduced motion drops the movement. The panel is as tall as
19373
+ * the flex row it sits in; a host that insets its page content gives the panel the same margins.
19374
+ */
19375
+ protected readonly asideClasses: import("@angular/core").Signal<string>;
19376
+ protected readonly searches: import("@angular/core").Signal<SearchItem[]>;
19377
+ protected readonly groups: import("@angular/core").Signal<HistoryGroup[]>;
19378
+ /** Whether a delete is going out, so a second click on the same row is not sent twice. */
19379
+ private readonly deleting;
18784
19380
  constructor();
18785
- onClick(search: SearchItem): void;
18786
- /**
18787
- * Deletes a recent search item at the specified index.
18788
- */
18789
- onDelete(event: ListPanelDeleteEvent<SearchItem>): Promise<void>;
18790
- loadMore(): void;
18791
- static ɵfac: i0.ɵɵFactoryDeclaration<RecentSearchesComponent, never>;
18792
- static ɵcmp: i0.ɵɵComponentDeclaration<RecentSearchesComponent, "RecentSearches, recent-searches", never, {
18793
- "options": {
18794
- "alias": "options";
19381
+ protected titleOf: (search: SearchItem) => string;
19382
+ protected isFavorite: (search: SearchItem) => boolean;
19383
+ protected onTab(value: string[]): void;
19384
+ protected onEscape(event: Event): void;
19385
+ protected select(search: SearchItem): void;
19386
+ protected toggleFavorite(search: SearchItem): Promise<boolean>;
19387
+ protected remove(search: SearchItem): Promise<void>;
19388
+ static ɵfac: i0.ɵɵFactoryDeclaration<HistoryPanelComponent, never>;
19389
+ static ɵcmp: i0.ɵɵComponentDeclaration<HistoryPanelComponent, "HistoryPanel, history-panel", never, {
19390
+ "open": {
19391
+ "alias": "open";
18795
19392
  "required": false;
18796
19393
  "isSignal": true;
18797
19394
  };
18798
- }, {}, never, never, true, never>;
19395
+ "tab": {
19396
+ "alias": "tab";
19397
+ "required": false;
19398
+ "isSignal": true;
19399
+ };
19400
+ "class": {
19401
+ "alias": "class";
19402
+ "required": false;
19403
+ "isSignal": true;
19404
+ };
19405
+ }, {
19406
+ "open": "openChange";
19407
+ "tab": "tabChange";
19408
+ "searchSelected": "searchSelected";
19409
+ }, never, never, true, never>;
18799
19410
  }
18800
- export declare class SavedSearchDialog {
18801
- protected readonly call: import("@sinequa/galactik").CallRef<string, DialogResult>;
18802
- private readonly savedSearchesService;
19411
+ /**
19412
+ * The user's quick filters: named sets of filters that one click applies again. A pill, like the filters of the bar it is
19413
+ * meant to sit in front of (the `filtersBarStart` slot of `<filters-bar>`), that opens a popover with a search field and the
19414
+ * list. A click on a quick filter **replaces** the active filters by its own and closes the popover, and hovering its count of
19415
+ * filters shows what it holds. Quick filters are made, renamed and deleted elsewhere (the filters of the results page): this
19416
+ * is only where they are applied.
19417
+ *
19418
+ * They live in the user settings (`UserSettingsStore.quickFilters`), so they follow the user from one page, and one device, to
19419
+ * the other.
19420
+ *
19421
+ * ```html
19422
+ * <filters-bar appearance="pill">
19423
+ * <quick-filters filtersBarStart appearance="pill" />
19424
+ * </filters-bar>
19425
+ * ```
19426
+ */
19427
+ export declare class QuickFiltersComponent {
19428
+ /** Colour family of the pill, as the filter buttons of the bar. */
19429
+ readonly scheme: import("@angular/core").InputSignal<FilterScheme>;
19430
+ /** The look of the pill: `pill` (rounded, outlined, as the filter pills) or `default` (the flat button). */
19431
+ readonly appearance: import("@angular/core").InputSignal<"default" | "pill">;
19432
+ /** Where the popover goes. */
19433
+ readonly position: import("@angular/core").InputSignal<Placement>;
19434
+ /** Distance in pixels between the pill and its popover. */
19435
+ readonly offset: import("@angular/core").InputSignal<number>;
19436
+ /** Emitted with the quick filter a click has just applied. */
19437
+ readonly applied: import("@angular/core").OutputEmitterRef<QuickFilter>;
19438
+ private readonly userSettingsStore;
19439
+ private readonly queryParamsStore;
19440
+ private readonly appStore;
18803
19441
  private readonly transloco;
18804
- private readonly dialog;
18805
- private readonly nameInputRef;
18806
- saveName: import("@angular/core").WritableSignal<string>;
18807
- protected readonly nameField: import("@angular/forms/signals").FieldTree<string, string | number, "writable">;
19442
+ private readonly host;
19443
+ protected readonly popoverId: string;
19444
+ /**
19445
+ * The popover is placed by Floating UI like those of the filter buttons — flipped above the pill when there is no room
19446
+ * under it, shifted into the viewport — until the user resizes it. From then on it stays where it is (`lockPosition`) as
19447
+ * long as it is open: a popover that kept flipping while its height changes would jump under the pointer. It keeps the side
19448
+ * it was on. Closing lets it go: the next opening places it again, and only the height the user chose is kept.
19449
+ */
19450
+ protected readonly resized: import("@angular/core").WritableSignal<boolean>;
19451
+ private readonly flippedAbove;
19452
+ protected readonly placement: import("@angular/core").Signal<Placement>;
19453
+ /** The row whose hover card is showing: its quick filter, and the element the card hangs from. */
19454
+ protected readonly details: import("@angular/core").WritableSignal<{
19455
+ quickFilter: QuickFilter;
19456
+ anchor: HTMLElement;
19457
+ } | null>;
19458
+ private readonly detailsCard;
19459
+ private hideTimer;
19460
+ private readonly popover;
19461
+ protected readonly isOpen: import("@angular/core").Signal<boolean>;
18808
19462
  constructor();
18809
- confirm(): void;
18810
- static ɵfac: i0.ɵɵFactoryDeclaration<SavedSearchDialog, never>;
18811
- static ɵcmp: i0.ɵɵComponentDeclaration<SavedSearchDialog, "saved-search-dialog, savedsearchdialog, SavedSearchDialog", never, {}, {}, never, never, true, never>;
19463
+ protected readonly variant: import("@angular/core").Signal<"none" | "light-accent" | "accent" | "primary" | "secondary" | "tertiary" | null | undefined>;
19464
+ protected readonly triggerClass: import("@angular/core").Signal<string>;
19465
+ protected readonly quickFilters: import("@angular/core").Signal<QuickFilter[]>;
19466
+ protected readonly query: import("@angular/core").WritableSignal<string>;
19467
+ protected readonly filtered: import("@angular/core").Signal<QuickFilter[]>;
19468
+ /** What was just done, for the screen readers. */
19469
+ protected readonly announcement: import("@angular/core").WritableSignal<string>;
19470
+ /**
19471
+ * What a quick filter holds, one chip per filter: the icon the application gave the aggregation of the filter in the
19472
+ * "filters" custom JSON (the one its filter button shows) and the value. The icon says what is filtered on, so the name is
19473
+ * left out; an aggregation without an icon keeps it (`Authors: John`), or the value alone would say nothing.
19474
+ */
19475
+ protected chips(quickFilter: QuickFilter): {
19476
+ text: string;
19477
+ icon?: string;
19478
+ }[];
19479
+ protected onToggle(): void;
19480
+ /**
19481
+ * Gives the position back to Floating UI: a top edge that was moved is put back where the placement leaves it, and the
19482
+ * popover may flip or shift again. The height the user chose stays.
19483
+ */
19484
+ private unpin;
19485
+ /** The user starts to resize: pins the popover, on the side Floating UI had put it. */
19486
+ protected onResizeStart(): void;
19487
+ /** Shows what a quick filter holds, under its row. */
19488
+ protected showDetails(quickFilter: QuickFilter, event: Event): void;
19489
+ /** Hides the card a moment later, so the pointer can cross from the row to the card. */
19490
+ protected scheduleHideDetails(): void;
19491
+ protected cancelHideDetails(): void;
19492
+ protected hideDetails(): void;
19493
+ /** The popover is closed with nothing half done: no search, no name being typed. */
19494
+ private reset;
19495
+ /** Closes the popover when the focus leaves the whole component. `null` (focus left the document) leaves it open. */
19496
+ protected closeOnFocusLeave(event: FocusEvent): void;
19497
+ /** What the list holds as selected: nothing, ever — choosing a row applies it and the list starts again. */
19498
+ protected readonly picked: import("@angular/core").WritableSignal<QuickFilter[]>;
19499
+ /** A row was chosen in the list. */
19500
+ protected pick(values: readonly QuickFilter[]): void;
19501
+ /** A click on a quick filter: its filters replace the active ones. */
19502
+ protected apply(quickFilter: QuickFilter): void;
19503
+ static ɵfac: i0.ɵɵFactoryDeclaration<QuickFiltersComponent, never>;
19504
+ static ɵcmp: i0.ɵɵComponentDeclaration<QuickFiltersComponent, "QuickFilters, quick-filters", never, {
19505
+ "scheme": {
19506
+ "alias": "scheme";
19507
+ "required": false;
19508
+ "isSignal": true;
19509
+ };
19510
+ "appearance": {
19511
+ "alias": "appearance";
19512
+ "required": false;
19513
+ "isSignal": true;
19514
+ };
19515
+ "position": {
19516
+ "alias": "position";
19517
+ "required": false;
19518
+ "isSignal": true;
19519
+ };
19520
+ "offset": {
19521
+ "alias": "offset";
19522
+ "required": false;
19523
+ "isSignal": true;
19524
+ };
19525
+ }, {
19526
+ "applied": "applied";
19527
+ }, never, never, true, never>;
18812
19528
  }
18813
- /** Imperative entry point: `await SavedSearch.call(initialName)`. */
18814
- export declare const SavedSearch: import("@sinequa/galactik").Callable<string, DialogResult>;
19529
+ /** Order of the categories of the suggestions, first to last. */
19530
+ export declare const SEARCH_BOX_CATEGORIES_SORT: InjectionToken<string[]>;
19531
+ /** The icon of each category of suggestion. */
19532
+ export declare const SEARCH_BOX_CATEGORY_ICONS: InjectionToken<Record<string, Type<unknown>>>;
19533
+ type Suggestion$1 = Partial<Suggestion> & {
19534
+ $isDivider?: boolean;
19535
+ $isTitle?: boolean;
19536
+ /** The translated title of the category, on a title row. */
19537
+ $label?: string;
19538
+ };
19539
+ /** Which list the popup shows. */
19540
+ export type SearchBoxTab = "suggestions" | "saved";
18815
19541
  /**
18816
- * Save/unsave toggle for the current search, as a starred button.
19542
+ * The search field of a search application: a pill with a suggestions popup, and a place to start from.
19543
+ *
19544
+ * Typing opens the popup on its **Suggestions** tab — the type-ahead of the application's suggest queries, with the
19545
+ * user's recent searches, saved searches and bookmarks — and the **Saved** tab lists the saved searches, each of which
19546
+ * runs as it was saved (text, filters, tab). Validating a text, or picking a suggestion, navigates to the search page
19547
+ * with the text and the active filters.
19548
+ *
19549
+ * It drives everything it needs by itself (`QueryParamsStore`, `AutocompleteService`, `UserSettingsStore`, the router),
19550
+ * so the only wiring is a place for it in a layout. Its look follows its `size`: `hero` is the field of a home page,
19551
+ * `medium` the one of a results header.
18817
19552
  *
18818
- * Usage:
18819
19553
  * ```html
18820
- * <saved-search-popover
18821
- * [queryText]="searchInputText()"
18822
- * (onSavedSearch)="saved.emit($event)" />
19554
+ * <search-box size="hero" popup="inline" />
18823
19555
  * ```
18824
19556
  *
18825
- * When the current search is not yet saved, opens {@link SavedSearchDialog} to name and save it.
18826
- * When it is already saved, the button unsaves it directly (no dialog, no name to pick again).
19557
+ * The application can add its own call to action to the bar, after the send button, by marking it `slot="trailing"` (an
19558
+ * "Ask AI" button, say). The text of the field is available to it through `[(searchInputText)]`. Never give it a `disabled`
19559
+ * attribute — the bar greys out whole on any disabled descendant — but `aria-disabled`; and wrap an `@if` in an
19560
+ * `<ng-container slot="trailing">`, since the projection only looks at the attributes of a single root element.
19561
+ *
19562
+ * ```html
19563
+ * <search-box [(searchInputText)]="text">
19564
+ * <button slot="trailing" variant="accent" size="sm" [attr.aria-disabled]="!text()" (click)="askAi()">Ask AI</button>
19565
+ * </search-box>
19566
+ * ```
18827
19567
  */
18828
- export declare class SavedSearchPopover {
18829
- protected readonly userSettingsStore: {
18830
- bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
18831
- recentSearches: import("@angular/core").Signal<SearchItem[]>;
18832
- savedSearches: import("@angular/core").Signal<SearchItem[]>;
18833
- baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
18834
- assistants: import("@angular/core").Signal<Record<string, unknown>>;
18835
- alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
18836
- collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
18837
- language?: import("@angular/core").Signal<string | undefined> | undefined;
18838
- userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
18839
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
18840
- disabledHighlightCategories: import("@angular/core").Signal<string[]>;
19568
+ export declare class SearchBoxComponent {
19569
+ /** Scale of the field: `hero` for a home page (the prototype's pill), `medium` (36px) for the header of a results page. */
19570
+ readonly size: import("@angular/core").InputSignal<"small" | "medium" | "large" | "hero" | null | undefined>;
19571
+ /** Shows the saved-search star once there is something to save. */
19572
+ readonly showSave: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
19573
+ /** The route a search leads to. */
19574
+ readonly searchPath: import("@angular/core").InputSignal<string>;
19575
+ /**
19576
+ * How the popup is presented. `card` floats over the page under the field, as in a results header. `inline` is flat, a little narrower than
19577
+ * the field and right under it, out of the flow so that opening it moves nothing: it takes the place of what sits under
19578
+ * the field, as on a home page, where the host hides the filters while it is open (see `expandedChange`).
19579
+ */
19580
+ readonly popup: import("@angular/core").InputSignal<"card" | "inline">;
19581
+ /** Distance, in pixels, between the field and the `card` popup. The card is placed with Floating UI, like the other popups. */
19582
+ readonly popupOffset: import("@angular/core").InputSignalWithTransform<number, unknown>;
19583
+ /** Replaces the translated placeholder. */
19584
+ readonly placeholderOverride: import("@angular/core").InputSignal<string | undefined>;
19585
+ /** Emitted with the text each time the user validates a search (Enter, the send button, a picked suggestion). */
19586
+ readonly searched: import("@angular/core").OutputEmitterRef<string>;
19587
+ /** Emitted once the text typed has settled (300ms), which is when the suggestions are fetched. */
19588
+ readonly debounced: import("@angular/core").OutputEmitterRef<string>;
19589
+ readonly saved: import("@angular/core").OutputEmitterRef<SearchItem | undefined>;
19590
+ /** Emitted when the popup opens or closes, so a host can step aside while it is open (the filters of a home page). */
19591
+ readonly expandedChange: import("@angular/core").OutputEmitterRef<boolean>;
19592
+ /** The text of the field. Two-way. */
19593
+ readonly searchInputText: import("@angular/core").ModelSignal<string>;
19594
+ protected readonly cn: import("cn").CnFunction;
19595
+ private readonly route;
19596
+ private readonly router;
19597
+ private readonly transloco;
19598
+ private readonly destroyRef;
19599
+ private readonly injector;
19600
+ private readonly eventManager;
19601
+ private readonly host;
19602
+ protected readonly queryParamsStore: {
19603
+ name?: import("@angular/core").Signal<string | undefined> | undefined;
19604
+ text?: import("@angular/core").Signal<string | undefined> | undefined;
19605
+ action?: import("@angular/core").Signal<"" | "open" | "search" | "aggregate" | undefined> | undefined;
19606
+ select?: import("@angular/core").Signal<import("@sinequa/atomic").Select[] | undefined> | undefined;
19607
+ open?: import("@angular/core").Signal<import("@sinequa/atomic").Open[] | undefined> | undefined;
19608
+ page?: import("@angular/core").Signal<number | undefined> | undefined;
19609
+ pageSize?: import("@angular/core").Signal<number | undefined> | undefined;
19610
+ tab?: import("@angular/core").Signal<string | undefined> | undefined;
19611
+ scope?: import("@angular/core").Signal<string | undefined> | undefined;
19612
+ sort?: import("@angular/core").Signal<string | undefined> | undefined;
19613
+ aggregation_overrides?: import("@angular/core").Signal<Record<string, {
19614
+ mask?: string;
19615
+ }> | undefined> | undefined;
19616
+ basket?: import("@angular/core").Signal<string | undefined> | undefined;
19617
+ isFirstPage?: import("@angular/core").Signal<boolean | undefined> | undefined;
19618
+ strictRefine?: import("@angular/core").Signal<boolean | undefined> | undefined;
19619
+ globalRelevance?: import("@angular/core").Signal<number | undefined> | undefined;
19620
+ questionLanguage?: import("@angular/core").Signal<string | undefined> | undefined;
19621
+ questionDefaultLanguage?: import("@angular/core").Signal<string | undefined> | undefined;
19622
+ spellingCorrectionMode?: import("@angular/core").Signal<import("@sinequa/atomic").SpellingCorrectionMode | undefined> | undefined;
19623
+ spellingCorrectionFilter?: import("@angular/core").Signal<string | undefined> | undefined;
19624
+ documentWeight?: import("@angular/core").Signal<string | undefined> | undefined;
19625
+ textPartWeights?: import("@angular/core").Signal<string | undefined> | undefined;
19626
+ relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
19627
+ removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
19628
+ queryId?: import("@angular/core").Signal<string | undefined> | undefined;
19629
+ aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
19630
+ orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
19631
+ groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
19632
+ neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
19633
+ path?: import("@angular/core").Signal<string | undefined> | undefined;
19634
+ filters: import("@angular/core").Signal<import("@sinequa/atomic").LegacyFilter[]>;
19635
+ id?: import("@angular/core").Signal<string | undefined> | undefined;
19636
+ setFromUrl: (href: string) => void;
19637
+ getQueryParams: () => {
19638
+ f?: string;
19639
+ p?: number;
19640
+ s?: string;
19641
+ t?: string;
19642
+ q?: string;
19643
+ b?: string;
19644
+ n?: string;
19645
+ };
19646
+ addFilter: (filter: import("@sinequa/atomic").LegacyFilter, audit?: import("@sinequa/atomic").AuditEvents, options?: {
19647
+ syncUrl?: boolean;
19648
+ }) => void;
19649
+ updateFilter: (newFilter: import("@sinequa/atomic").LegacyFilter, audit?: import("@sinequa/atomic").AuditEvents, options?: {
19650
+ syncUrl?: boolean;
19651
+ }) => void;
19652
+ removeFilter: (field?: string, options?: {
19653
+ syncUrl?: boolean;
19654
+ }) => void;
19655
+ removeFilterByName: (name?: string, column?: string, options?: {
19656
+ syncUrl?: boolean;
19657
+ }) => void;
19658
+ clearFilters: (options?: {
19659
+ syncUrl?: boolean;
19660
+ }) => void;
19661
+ clearBasket: (options?: {
19662
+ syncUrl?: boolean;
19663
+ }) => void;
19664
+ patch: (params: Partial<import("@sinequa/atomic").QueryParams>, audit?: import("@sinequa/atomic").AuditEvents, options?: {
19665
+ syncUrl?: boolean;
19666
+ }) => void;
19667
+ reset: (options?: {
19668
+ syncUrl?: boolean;
19669
+ }) => void;
19670
+ getFilter: ({ field, name }: {
19671
+ field: string | undefined;
19672
+ name: string | undefined;
19673
+ }) => Partial<import("@sinequa/atomic").LegacyFilter & {
19674
+ count: number;
19675
+ }> | null;
19676
+ getQuery: () => import("@sinequa/atomic").Query;
19677
+ } & import("@ngrx/signals").StateSource<{
19678
+ name?: string | undefined;
19679
+ text?: string | undefined;
19680
+ action?: "" | "search" | "open" | "aggregate" | undefined;
19681
+ select?: import("@sinequa/atomic").Select[] | undefined;
19682
+ open?: import("@sinequa/atomic").Open[] | undefined;
19683
+ page?: number | undefined;
19684
+ pageSize?: number | undefined;
19685
+ tab?: string | undefined;
19686
+ scope?: string | undefined;
19687
+ sort?: string | undefined;
19688
+ aggregation_overrides?: Record<string, {
19689
+ mask?: string;
19690
+ }> | undefined;
19691
+ basket?: string | undefined;
19692
+ isFirstPage?: boolean | undefined;
19693
+ strictRefine?: boolean | undefined;
19694
+ globalRelevance?: number | undefined;
19695
+ questionLanguage?: string | undefined;
19696
+ questionDefaultLanguage?: string | undefined;
19697
+ spellingCorrectionMode?: import("@sinequa/atomic").SpellingCorrectionMode | undefined;
19698
+ spellingCorrectionFilter?: string | undefined;
19699
+ documentWeight?: string | undefined;
19700
+ textPartWeights?: string | undefined;
19701
+ relevanceTransforms?: string | undefined;
19702
+ removeDuplicates?: boolean | undefined;
19703
+ queryId?: string | undefined;
19704
+ aggregations?: (Record<string, import("@sinequa/atomic").AggregationOptions> | string[]) | undefined;
19705
+ orderBy?: string | undefined;
19706
+ groupBy?: string | undefined;
19707
+ neuralSearch?: boolean | undefined;
19708
+ path?: string | undefined;
19709
+ filters: import("@sinequa/atomic").LegacyFilter[];
19710
+ id?: string | undefined;
19711
+ }>;
19712
+ protected readonly appStore: {
19713
+ name: import("@angular/core").Signal<string>;
19714
+ description?: import("@angular/core").Signal<string | undefined> | undefined;
19715
+ versionId: import("@angular/core").Signal<string>;
19716
+ queries: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCQuery>>;
19717
+ rfms: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCRFM>>;
19718
+ indexes: import("@angular/core").Signal<{
19719
+ _: import("@sinequa/atomic").CCIndex;
19720
+ } & Record<string, import("@sinequa/atomic").CCIndex>>;
19721
+ lists: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCList>>;
19722
+ webServices: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCWebService>>;
19723
+ queryNames: import("@angular/core").Signal<string>;
19724
+ labels: import("@angular/core").Signal<string>;
19725
+ preview: import("@angular/core").Signal<string>;
19726
+ autocomplete: import("@angular/core").Signal<string>;
19727
+ sponsoredLinks: import("@angular/core").Signal<string>;
19728
+ queryExport: import("@angular/core").Signal<string>;
19729
+ queryRssEnabled: import("@angular/core").Signal<boolean>;
19730
+ data: import("@angular/core").Signal<Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
19731
+ filters?: import("@sinequa/atomic-angular").CAggregation[];
19732
+ autocomplete?: Autocomplete;
19733
+ tabs?: Record<string, {
19734
+ filters: string[];
19735
+ overviews?: Record<string, {
19736
+ minRelevance: number;
19737
+ }>;
19738
+ }>;
19739
+ sources?: import("@sinequa/atomic-angular").CSources;
19740
+ features?: {
19741
+ [key: string]: boolean | {
19742
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
19743
+ } | undefined;
19744
+ allowChangePassword?: boolean;
19745
+ editablepartition?: boolean;
19746
+ advancedSearch?: boolean;
19747
+ allowChatDrawer?: boolean;
19748
+ filterLinkChildren?: boolean;
19749
+ expandPreview?: boolean;
19750
+ quickFilter?: boolean;
19751
+ showAggregationItemCount?: boolean;
19752
+ assistant?: {
19753
+ usePrefixName?: boolean;
19754
+ };
19755
+ filters?: {
19756
+ homepage?: boolean;
19757
+ };
19758
+ userProfile?: {
19759
+ enabled?: boolean;
19760
+ data?: string[];
19761
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
19762
+ };
19763
+ previewMultiConversion?: boolean;
19764
+ persistFiltersAcrossTabs?: boolean;
19765
+ };
19766
+ allowAdvancedFilters?: boolean;
19767
+ general?: {
19768
+ name?: string;
19769
+ logo?: {
19770
+ alt?: string;
19771
+ light?: {
19772
+ small?: string;
19773
+ large?: string;
19774
+ sidebar?: string;
19775
+ };
19776
+ dark?: {
19777
+ small?: string;
19778
+ large?: string;
19779
+ sidebar?: string;
19780
+ };
19781
+ };
19782
+ features?: {
19783
+ [key: string]: boolean | {
19784
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
19785
+ } | undefined;
19786
+ allowChangePassword?: boolean;
19787
+ editablepartition?: boolean;
19788
+ advancedSearch?: boolean;
19789
+ allowChatDrawer?: boolean;
19790
+ filterLinkChildren?: boolean;
19791
+ expandPreview?: boolean;
19792
+ quickFilter?: boolean;
19793
+ showAggregationItemCount?: boolean;
19794
+ assistant?: {
19795
+ usePrefixName?: boolean;
19796
+ };
19797
+ filters?: {
19798
+ homepage?: boolean;
19799
+ };
19800
+ userProfile?: {
19801
+ enabled?: boolean;
19802
+ data?: string[];
19803
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
19804
+ };
19805
+ previewMultiConversion?: boolean;
19806
+ persistFiltersAcrossTabs?: boolean;
19807
+ };
19808
+ converters?: import("@sinequa/atomic-angular").CConverter[];
19809
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
19810
+ };
19811
+ documentsUploadSettings?: {
19812
+ enabled?: boolean;
19813
+ };
19814
+ }>;
19815
+ customJSONs: import("@angular/core").Signal<{
19816
+ name: string;
19817
+ data: Record<string, unknown>;
19818
+ }[] & import("@sinequa/atomic-angular").SideCJson[]>;
19819
+ apiVersion: import("@angular/core").Signal<string>;
19820
+ workspaceApp: import("@angular/core").Signal<string>;
19821
+ defaultQueryName: import("@angular/core").Signal<string>;
19822
+ auditEnabled?: import("@angular/core").Signal<boolean | undefined> | undefined;
19823
+ dataSets?: import("@angular/core").Signal<string | undefined> | undefined;
19824
+ revision?: import("@angular/core").Signal<number | undefined> | undefined;
19825
+ runnableModels?: import("@angular/core").Signal<string | undefined> | undefined;
19826
+ authorizationLevel?: import("@angular/core").Signal<string | undefined> | undefined;
19827
+ columnMap?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCColumn> | undefined> | undefined;
19828
+ customizationJson: import("@angular/core").Signal<import("@sinequa/atomic-angular").CJsonMint>;
19829
+ sources: import("@angular/core").Signal<import("@sinequa/atomic-angular").CSources>;
19830
+ filters: import("@angular/core").Signal<import("@sinequa/atomic-angular").CFilter[]>;
19831
+ general: import("@angular/core").Signal<{
19832
+ name?: string;
19833
+ logo?: {
19834
+ alt?: string;
19835
+ light?: {
19836
+ small?: string;
19837
+ large?: string;
19838
+ sidebar?: string;
19839
+ };
19840
+ dark?: {
19841
+ small?: string;
19842
+ large?: string;
19843
+ sidebar?: string;
19844
+ };
19845
+ };
19846
+ features?: {
19847
+ [key: string]: boolean | {
19848
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
19849
+ } | undefined;
19850
+ allowChangePassword?: boolean;
19851
+ editablepartition?: boolean;
19852
+ advancedSearch?: boolean;
19853
+ allowChatDrawer?: boolean;
19854
+ filterLinkChildren?: boolean;
19855
+ expandPreview?: boolean;
19856
+ quickFilter?: boolean;
19857
+ showAggregationItemCount?: boolean;
19858
+ assistant?: {
19859
+ usePrefixName?: boolean;
19860
+ };
19861
+ filters?: {
19862
+ homepage?: boolean;
19863
+ };
19864
+ userProfile?: {
19865
+ enabled?: boolean;
19866
+ data?: string[];
19867
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
19868
+ };
19869
+ previewMultiConversion?: boolean;
19870
+ persistFiltersAcrossTabs?: boolean;
19871
+ };
19872
+ converters?: import("@sinequa/atomic-angular").CConverter[];
19873
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
19874
+ } | undefined>;
19875
+ assistants: import("@angular/core").Signal<{
19876
+ [x: string]: import("@sinequa/atomic-angular").AssistantDetails;
19877
+ }>;
19878
+ agents: import("@angular/core").Signal<{
19879
+ [x: string]: {
19880
+ defaultAgent: string;
19881
+ };
19882
+ }>;
19883
+ initialize: () => Promise<undefined>;
19884
+ hydrate: (app: import("@sinequa/atomic").CCApp) => void;
19885
+ fail: (error: unknown) => never;
19886
+ initializeWithAppName: (appName: string) => Promise<void>;
19887
+ update: (app: Partial<import("@sinequa/atomic-angular").CCAppState>) => void;
19888
+ getWebServiceByType: (type: import("@sinequa/atomic").CCWebService["webServiceType"]) => import("@sinequa/atomic").CCWebService | undefined;
19889
+ getLabels: () => {
19890
+ private: string;
19891
+ public: string;
19892
+ };
19893
+ getQueryByName: (name: string | undefined) => import("@sinequa/atomic").CCQuery | undefined;
19894
+ getQueryByIndex: (index: number) => import("@sinequa/atomic").CCQuery | undefined;
19895
+ getDefaultQuery: () => import("@sinequa/atomic").CCQuery | undefined;
19896
+ allowEmptySearch: (queryName: string) => boolean;
19897
+ enableFieldedSearch: (queryName: string) => boolean;
19898
+ allowLabels: () => boolean;
19899
+ getColumnAlias: (column: string) => string;
19900
+ getColumn: (columnOrAlias: string) => import("@sinequa/atomic").CCColumn | undefined;
19901
+ isDateColumn: (column: string) => boolean;
19902
+ isTabSearch: (queryName: string) => boolean;
19903
+ getAggregationCount: (queryName: string | undefined, aggregationName: string) => number;
19904
+ getAuthorizedFilters: () => import("@sinequa/atomic").Aggregation[];
19905
+ getAuthorized: (filters: Pick<import("@sinequa/atomic-angular").CFilter, "column" | "name">[]) => import("@sinequa/atomic").Aggregation[];
19906
+ getNamedCustomizationJson: (name: string) => unknown | undefined;
19907
+ getAggregationIcon: (column: string) => string | undefined;
19908
+ getAggregationItemsCustomization: (column: string) => import("@sinequa/atomic-angular").CFilterItem[] | undefined;
19909
+ getAggregationCustomization: (aggColumn: string, aggName?: string) => import("@sinequa/atomic-angular").CFilter | undefined;
19910
+ isAssistantAllowed: (assistantName: string) => boolean;
19911
+ isAgentAllowed: (agentName: string) => boolean;
19912
+ } & import("@ngrx/signals").StateSource<{
19913
+ name: string;
19914
+ description?: string | undefined;
19915
+ versionId: string;
19916
+ queries: Record<string, import("@sinequa/atomic").CCQuery>;
19917
+ rfms: Record<string, import("@sinequa/atomic").CCRFM>;
19918
+ indexes: {
19919
+ _: import("@sinequa/atomic").CCIndex;
19920
+ } & Record<string, import("@sinequa/atomic").CCIndex>;
19921
+ lists: Record<string, import("@sinequa/atomic").CCList>;
19922
+ webServices: Record<string, import("@sinequa/atomic").CCWebService>;
19923
+ queryNames: string;
19924
+ labels: string;
19925
+ preview: string;
19926
+ autocomplete: string;
19927
+ sponsoredLinks: string;
19928
+ queryExport: string;
19929
+ queryRssEnabled: boolean;
19930
+ data: Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
19931
+ filters?: import("@sinequa/atomic-angular").CAggregation[];
19932
+ autocomplete?: Autocomplete;
19933
+ tabs?: Record<string, {
19934
+ filters: string[];
19935
+ overviews?: Record<string, {
19936
+ minRelevance: number;
19937
+ }>;
19938
+ }>;
19939
+ sources?: import("@sinequa/atomic-angular").CSources;
19940
+ features?: {
19941
+ [key: string]: boolean | {
19942
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
19943
+ } | undefined;
19944
+ allowChangePassword?: boolean;
19945
+ editablepartition?: boolean;
19946
+ advancedSearch?: boolean;
19947
+ allowChatDrawer?: boolean;
19948
+ filterLinkChildren?: boolean;
19949
+ expandPreview?: boolean;
19950
+ quickFilter?: boolean;
19951
+ showAggregationItemCount?: boolean;
19952
+ assistant?: {
19953
+ usePrefixName?: boolean;
19954
+ };
19955
+ filters?: {
19956
+ homepage?: boolean;
19957
+ };
19958
+ userProfile?: {
19959
+ enabled?: boolean;
19960
+ data?: string[];
19961
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
19962
+ };
19963
+ previewMultiConversion?: boolean;
19964
+ persistFiltersAcrossTabs?: boolean;
19965
+ };
19966
+ allowAdvancedFilters?: boolean;
19967
+ general?: {
19968
+ name?: string;
19969
+ logo?: {
19970
+ alt?: string;
19971
+ light?: {
19972
+ small?: string;
19973
+ large?: string;
19974
+ sidebar?: string;
19975
+ };
19976
+ dark?: {
19977
+ small?: string;
19978
+ large?: string;
19979
+ sidebar?: string;
19980
+ };
19981
+ };
19982
+ features?: {
19983
+ [key: string]: boolean | {
19984
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
19985
+ } | undefined;
19986
+ allowChangePassword?: boolean;
19987
+ editablepartition?: boolean;
19988
+ advancedSearch?: boolean;
19989
+ allowChatDrawer?: boolean;
19990
+ filterLinkChildren?: boolean;
19991
+ expandPreview?: boolean;
19992
+ quickFilter?: boolean;
19993
+ showAggregationItemCount?: boolean;
19994
+ assistant?: {
19995
+ usePrefixName?: boolean;
19996
+ };
19997
+ filters?: {
19998
+ homepage?: boolean;
19999
+ };
20000
+ userProfile?: {
20001
+ enabled?: boolean;
20002
+ data?: string[];
20003
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
20004
+ };
20005
+ previewMultiConversion?: boolean;
20006
+ persistFiltersAcrossTabs?: boolean;
20007
+ };
20008
+ converters?: import("@sinequa/atomic-angular").CConverter[];
20009
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
20010
+ };
20011
+ documentsUploadSettings?: {
20012
+ enabled?: boolean;
20013
+ };
20014
+ };
20015
+ customJSONs: {
20016
+ name: string;
20017
+ data: Record<string, unknown>;
20018
+ }[] & import("@sinequa/atomic-angular").SideCJson[];
20019
+ apiVersion: string;
20020
+ workspaceApp: string;
20021
+ defaultQueryName: string;
20022
+ auditEnabled?: boolean | undefined;
20023
+ dataSets?: string | undefined;
20024
+ revision?: number | undefined;
20025
+ runnableModels?: string | undefined;
20026
+ authorizationLevel?: string | undefined;
20027
+ columnMap?: Record<string, import("@sinequa/atomic").CCColumn> | undefined;
20028
+ }>;
20029
+ protected readonly userSettingsStore: {
20030
+ bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20031
+ favoriteSearches: import("@angular/core").Signal<string[]>;
20032
+ recentSearches: import("@angular/core").Signal<SearchItem[]>;
20033
+ savedSearches: import("@angular/core").Signal<SearchItem[]>;
20034
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
20035
+ baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
20036
+ assistants: import("@angular/core").Signal<Record<string, unknown>>;
20037
+ alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
20038
+ collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
20039
+ language?: import("@angular/core").Signal<string | undefined> | undefined;
20040
+ userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
20041
+ agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
20042
+ disabledHighlightCategories: import("@angular/core").Signal<string[]>;
20043
+ isDebugMode: import("@angular/core").Signal<boolean>;
20044
+ isDarkMode: import("@angular/core").Signal<boolean>;
20045
+ updateBookmarks: (bookmarks: import("@sinequa/atomic-angular").UserSettingsState["bookmarks"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20046
+ bookmark: (article: import("@sinequa/atomic").Article, queryName?: string) => Promise<void>;
20047
+ unbookmark: (id: string) => Promise<void>;
20048
+ isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
20049
+ toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
20050
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
20051
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
20052
+ deleteRecentSearch: (index: number) => Promise<void>;
20053
+ updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20054
+ addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
20055
+ deleteSavedSearch: (index: number) => Promise<void>;
20056
+ updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
20057
+ getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
20058
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
20059
+ updateQuickFilter: (id: string, changes: {
20060
+ name?: string;
20061
+ filters?: import("@sinequa/atomic").LegacyFilter[];
20062
+ }) => Promise<void>;
20063
+ removeQuickFilter: (id: string) => Promise<void>;
20064
+ deleteBasket: (index: number) => Promise<void>;
20065
+ createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
20066
+ updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
20067
+ updateBasket: (basket: import("@sinequa/atomic-angular").Basket, index: number) => Promise<void>;
20068
+ addToBasket: (name: string, ids: string | string[]) => Promise<void>;
20069
+ removeFromBasket: (name: string, ids: string | string[]) => Promise<void>;
20070
+ updateAssistantSettings: (assistantSettings: import("@sinequa/atomic-angular").UserSettingsState["assistants"]) => Promise<void>;
20071
+ updateLanguage: (language: import("@sinequa/atomic-angular").UserSettingsState["language"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20072
+ updateAssistantCollapsed: (collapseAssistant: import("@sinequa/atomic-angular").UserSettingsState["collapseAssistant"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20073
+ hydrate: (settings: import("@sinequa/atomic-angular").UserSettingsState) => void;
20074
+ fail: (err: unknown) => void;
20075
+ initialize: () => Promise<void>;
20076
+ reset: () => Promise<void>;
20077
+ deleteAlert: (index: number) => Promise<void>;
20078
+ createAlert: (alert: import("@sinequa/atomic-angular").Alert) => Promise<void>;
20079
+ updateAlert: (alert: import("@sinequa/atomic-angular").Alert, index: number) => Promise<void>;
20080
+ updateAlerts: (alerts: import("@sinequa/atomic-angular").Alert[]) => Promise<void>;
20081
+ setDebugMode: (value: boolean) => Promise<void>;
20082
+ setUserTheme: (userTheme: "dark" | "light" | "system") => Promise<void>;
20083
+ toggleDarkMode: () => Promise<void>;
20084
+ setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
20085
+ } & import("@ngrx/signals").StateSource<{
20086
+ bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20087
+ favoriteSearches: string[];
20088
+ recentSearches: SearchItem[];
20089
+ savedSearches: SearchItem[];
20090
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
20091
+ baskets: import("@sinequa/atomic-angular").Basket[];
20092
+ assistants: Record<string, unknown>;
20093
+ alerts: import("@sinequa/atomic-angular").Alert[];
20094
+ collapseAssistant?: boolean | undefined;
20095
+ language?: string | undefined;
20096
+ userTheme: "dark" | "light" | "system";
20097
+ agents: import("@sinequa/atomic-angular").AgentUserSettings;
20098
+ disabledHighlightCategories: string[];
20099
+ }>;
20100
+ private readonly savedSearchesService;
20101
+ protected readonly autocompleteService: AutocompleteService;
20102
+ private readonly categoriesOrder;
20103
+ private readonly categoryIcons;
20104
+ /** The SearchBar, read before its view is initialised by the popup template. */
20105
+ private readonly inputComponent;
20106
+ /** The `ngCombobox` of the SearchBar — the popup template binds to it. */
20107
+ protected readonly combobox: import("@angular/core").Signal<import("@angular/aria/combobox").Combobox | undefined>;
20108
+ /** The bar the `card` popup hangs from, and the card itself (rendered inside the deferred popup template). */
20109
+ private readonly barElement;
20110
+ private readonly popupCard;
20111
+ /** The suggestions listbox, rendered inside the deferred popup template. */
20112
+ private readonly listbox;
20113
+ /** The saved-searches list, rendered inside the deferred popup template while its tab is selected. */
20114
+ private readonly savedList;
20115
+ /**
20116
+ * The field: a form over the text model. What the user types reaches the model, so `searchInputText` and `debounced`,
20117
+ * only once it has settled (300ms, or as soon as the field is touched); `typed` is the text as it is in the bar.
20118
+ */
20119
+ protected readonly field: import("@angular/forms/signals").FieldTree<string, string | number, "writable">;
20120
+ /** The text as it is in the bar, before the debounce. */
20121
+ protected readonly typed: import("@angular/core").Signal<string>;
20122
+ /** The text a keyboard preview put in the field: it is not a request for new suggestions. */
20123
+ private silentText;
20124
+ /** The text the suggestions are fetched for: the field's, once it has settled. */
20125
+ protected readonly text: import("@angular/core").WritableSignal<string>;
20126
+ private readonly wasSearchClicked;
20127
+ /** Which list the popup shows. Back on the suggestions every time it opens — they are what typing is for. */
20128
+ protected readonly tab: import("@angular/core").WritableSignal<string | undefined>;
20129
+ /** The text of the row whose star just saved or removed it: it plays its pop animation. */
20130
+ protected readonly popping: import("@angular/core").WritableSignal<string | null>;
20131
+ /** What the shortcut just did, for the screen readers. */
20132
+ protected readonly announcement: import("@angular/core").WritableSignal<string>;
20133
+ protected readonly hintId: string;
20134
+ protected readonly savedSearches: import("@angular/core").Signal<SearchItem[]>;
20135
+ private readonly savedTexts;
20136
+ private readonly inline;
20137
+ /** The bar keeps the room of its own padding on the `hero` size, whose send button sets it. */
20138
+ protected readonly barClass: import("@angular/core").Signal<"w-full" | "w-full gap-(--spacing-3xs)! pe-(--spacing-3xs)">;
20139
+ protected readonly popupClass: import("@angular/core").Signal<string>;
20140
+ protected readonly listClass: import("@angular/core").Signal<string>;
20141
+ protected readonly rowClass: import("@angular/core").Signal<string>;
20142
+ protected readonly titleClass: import("@angular/core").Signal<string>;
20143
+ protected readonly hasFilters: import("@angular/core").Signal<boolean>;
20144
+ private readonly allowEmptySearch;
20145
+ private readonly allowAdvancedFilters;
20146
+ private readonly autocomplete;
20147
+ /**
20148
+ * Whether the user pressed an arrow key since the last typed character. Only then is a listbox selection previewed in
20149
+ * the field: the listbox auto-selects its first option whenever the suggestions render, and that programmatic
20150
+ * selection must never overwrite what the user is typing.
20151
+ */
20152
+ readonly navigatedSinceTyping: import("@angular/core").WritableSignal<boolean>;
20153
+ /** The suggestions: what the suggest queries return, with the user's recent searches, saved searches and bookmarks. */
20154
+ private readonly suggestionsResource;
20155
+ private previousSuggestions;
20156
+ protected readonly suggestions: import("@angular/core").Signal<Suggestion$1[]>;
20157
+ private inputListenersAttached;
20158
+ constructor();
20159
+ /**
20160
+ * Expands the popup when focus enters the field from outside (a click, a tap, Tab). Focus that comes from within —
20161
+ * the clear button handing it back after clearing — is a programmatic refocus and must not re-expand the popup.
20162
+ */
20163
+ protected expandOnFocusEntering(event: FocusEvent): void;
20164
+ /**
20165
+ * Collapses the popup once focus leaves the search block entirely. The popup is a DOM descendant of this component, so
20166
+ * tabbing from the field walks into the tabs and the list instead of leaving them. `null` (focus left the document)
20167
+ * leaves the popup alone, so an alt-tab does not discard what the user was reading.
20168
+ */
20169
+ protected collapseOnFocusLeave(event: FocusEvent): void;
20170
+ /** Collapses the suggestions popup. */
20171
+ collapse(): void;
20172
+ /**
20173
+ * Previews a suggestion in the field while navigating with the keyboard (URL-bar style): the text shown changes but the
20174
+ * list is not fetched again under the user (see `silentText`).
20175
+ */
20176
+ private previewSuggestion;
20177
+ /** The preview of the selection of the list while the keyboard navigates — never of a programmatic selection. */
20178
+ protected onListboxValueChange(values: readonly Suggestion$1[]): void;
20179
+ /** The same preview for the saved searches: the arrows put the text of the active one in the field, and Enter then runs it as it was saved. */
20180
+ protected onSavedValueChange(values: readonly SearchItem[]): void;
20181
+ /**
20182
+ * A click on a tab, or an arrow key while the tab list holds the focus. Never leaves the list without a selection.
20183
+ * The new list selects its first option by itself when it renders: that is no navigation of the user's, so it must not be
20184
+ * previewed in the field — the arrows start again from the text the field holds.
20185
+ */
20186
+ protected onTabChange(tab: string | undefined): void;
20187
+ /**
20188
+ * A click on a tab focuses the tab. The block of tabs is a widget of the combobox, so the popup stays open while the focus
20189
+ * is in it (and Tab and the arrows reach the tabs from the keyboard); a click gives the focus back to the field, where the
20190
+ * user is typing.
20191
+ */
20192
+ protected focusField(): void;
20193
+ /** Commits a clicked suggestion: writes it into the field and runs the search. */
20194
+ protected commitSuggestion(suggestion: Suggestion$1, event: Event): void;
20195
+ /**
20196
+ * Runs a saved search as it was saved: its text, its filters and its tab, not only its text. The popup closes first,
20197
+ * since the page it leads to replaces what sits under it.
20198
+ */
20199
+ protected openSaved(saved: SearchItem): void;
20200
+ /**
20201
+ * Shift+Tab in the field, while the popup is open, goes up to the tabs — they sit above the list — instead of leaving the
20202
+ * field backwards and closing the popup: the focus is the selected tab, where the arrows change tab. Shift+Tab from the tab
20203
+ * comes back to the field, since it is the element before it. With the popup closed it is the ordinary Shift+Tab.
20204
+ */
20205
+ private focusSelectedTab;
20206
+ /**
20207
+ * Tab on a tab: into the list. The list is never focused itself (its active option is announced from the field), so the
20208
+ * focus goes back to the field and its FIRST row becomes the active one, exactly as a first Down arrow does — the arrows
20209
+ * then walk the list. A row that was already active is let go first, or the arrow would land on the one after it.
20210
+ */
20211
+ protected intoList(event: Event): void;
20212
+ /**
20213
+ * Shift+Tab on a tab: back to the field, which is the way the focus came. The previous element in the page is the send
20214
+ * button of the bar, and landing there would close the popup.
20215
+ */
20216
+ protected backToField(event: Event): void;
20217
+ /** Escape on a tab: the focus goes back to the field and the popup closes, as Escape does from the field. */
20218
+ protected closeFromTabs(event: Event): void;
20219
+ /** Whether a suggestion is a search the user has saved. */
20220
+ protected isSavedRow(suggestion: Suggestion$1): boolean;
20221
+ /** What the star of a row does, for its tooltip. */
20222
+ protected starTooltip(suggestion: Suggestion$1): string;
20223
+ /** The star of a suggestion: saves the search, or removes it from the saved ones. Never runs it. */
20224
+ protected toggleSaved(suggestion: Suggestion$1, event: Event): void;
20225
+ /**
20226
+ * Ctrl+Enter (Cmd+Enter) in the field: the star of the highlighted row, for the keyboard. It saves that search, or removes
20227
+ * it from the saved ones, on either tab, and never runs it. Nothing happens, and Enter is left alone, when no row is
20228
+ * highlighted.
20229
+ */
20230
+ private toggleActiveRow;
20231
+ private toggleSavedText;
20232
+ /** Removes a saved search from its row, without running it. */
20233
+ protected removeSaved(saved: SearchItem, event: Event): void;
20234
+ /**
20235
+ * The saved search the keyboard is on, from the active option of the saved list — and only once the user has navigated
20236
+ * with the arrows, since the listbox activates its first option on its own when it renders.
20237
+ */
20238
+ private activeSaved;
20239
+ /** Enter in the field. A search is validated only when the application allows it for this query. */
20240
+ protected emitText(event: Event): void;
20241
+ /** The built-in send button of the SearchBar. It has already stopped the event, so no DOM event reaches this handler. */
20242
+ protected onSearchText(value: string): void;
20243
+ private runSearch;
20244
+ protected getIconForCategory(category: string | undefined): Type<unknown>;
20245
+ /** The title of a category: the library's own string, then an application key of the same name, then the category itself. */
20246
+ private categoryLabel;
20247
+ /**
20248
+ * Fetches the suggestions for a text: the user's own (recent and saved searches, bookmarks) with the suggest queries of
20249
+ * the application, ordered by category, with a title row ahead of each category.
20250
+ *
20251
+ * A 401 on the suggest queries starts the sign-in flow; any other error is logged and leaves only the user's own.
20252
+ */
20253
+ private fetchSuggestions;
20254
+ static ɵfac: i0.ɵɵFactoryDeclaration<SearchBoxComponent, never>;
20255
+ static ɵcmp: i0.ɵɵComponentDeclaration<SearchBoxComponent, "SearchBox, search-box", never, {
20256
+ "size": {
20257
+ "alias": "size";
20258
+ "required": false;
20259
+ "isSignal": true;
20260
+ };
20261
+ "showSave": {
20262
+ "alias": "showSave";
20263
+ "required": false;
20264
+ "isSignal": true;
20265
+ };
20266
+ "searchPath": {
20267
+ "alias": "searchPath";
20268
+ "required": false;
20269
+ "isSignal": true;
20270
+ };
20271
+ "popup": {
20272
+ "alias": "popup";
20273
+ "required": false;
20274
+ "isSignal": true;
20275
+ };
20276
+ "popupOffset": {
20277
+ "alias": "popupOffset";
20278
+ "required": false;
20279
+ "isSignal": true;
20280
+ };
20281
+ "placeholderOverride": {
20282
+ "alias": "placeholder";
20283
+ "required": false;
20284
+ "isSignal": true;
20285
+ };
20286
+ "searchInputText": {
20287
+ "alias": "searchInputText";
20288
+ "required": false;
20289
+ "isSignal": true;
20290
+ };
20291
+ }, {
20292
+ "searched": "searched";
20293
+ "debounced": "debounced";
20294
+ "saved": "saved";
20295
+ "expandedChange": "expandedChange";
20296
+ "searchInputText": "searchInputTextChange";
20297
+ }, never, ["[slot='trailing']"], true, never>;
20298
+ }
20299
+ export declare const RECENT_SEARCHES_OPTIONS: {
20300
+ itemsPerPage: number;
20301
+ showLoadMore: boolean;
20302
+ routerLink: string;
20303
+ };
20304
+ export declare const RECENT_SEARCHES_CONFIG: InjectionToken<import("@sinequa/atomic-angular").ListPanelConfig>;
20305
+ export declare class RecentSearchesComponent {
20306
+ options: import("@angular/core").InputSignal<import("@sinequa/atomic-angular").ListPanelConfig | undefined>;
20307
+ protected floating: PopoverDirective | null;
20308
+ protected config: import("@sinequa/atomic-angular").ListPanelConfig;
20309
+ protected readonly userSettingsStore: {
20310
+ bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20311
+ favoriteSearches: import("@angular/core").Signal<string[]>;
20312
+ recentSearches: import("@angular/core").Signal<SearchItem[]>;
20313
+ savedSearches: import("@angular/core").Signal<SearchItem[]>;
20314
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
20315
+ baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
20316
+ assistants: import("@angular/core").Signal<Record<string, unknown>>;
20317
+ alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
20318
+ collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
20319
+ language?: import("@angular/core").Signal<string | undefined> | undefined;
20320
+ userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
20321
+ agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
20322
+ disabledHighlightCategories: import("@angular/core").Signal<string[]>;
20323
+ isDebugMode: import("@angular/core").Signal<boolean>;
20324
+ isDarkMode: import("@angular/core").Signal<boolean>;
20325
+ updateBookmarks: (bookmarks: import("@sinequa/atomic-angular").UserSettingsState["bookmarks"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20326
+ bookmark: (article: import("@sinequa/atomic").Article, queryName?: string) => Promise<void>;
20327
+ unbookmark: (id: string) => Promise<void>;
20328
+ isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
20329
+ toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
20330
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
20331
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
20332
+ deleteRecentSearch: (index: number) => Promise<void>;
20333
+ updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20334
+ addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
20335
+ deleteSavedSearch: (index: number) => Promise<void>;
20336
+ updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
20337
+ getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
20338
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
20339
+ updateQuickFilter: (id: string, changes: {
20340
+ name?: string;
20341
+ filters?: import("@sinequa/atomic").LegacyFilter[];
20342
+ }) => Promise<void>;
20343
+ removeQuickFilter: (id: string) => Promise<void>;
20344
+ deleteBasket: (index: number) => Promise<void>;
20345
+ createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
20346
+ updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
20347
+ updateBasket: (basket: import("@sinequa/atomic-angular").Basket, index: number) => Promise<void>;
20348
+ addToBasket: (name: string, ids: string | string[]) => Promise<void>;
20349
+ removeFromBasket: (name: string, ids: string | string[]) => Promise<void>;
20350
+ updateAssistantSettings: (assistantSettings: import("@sinequa/atomic-angular").UserSettingsState["assistants"]) => Promise<void>;
20351
+ updateLanguage: (language: import("@sinequa/atomic-angular").UserSettingsState["language"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20352
+ updateAssistantCollapsed: (collapseAssistant: import("@sinequa/atomic-angular").UserSettingsState["collapseAssistant"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20353
+ hydrate: (settings: import("@sinequa/atomic-angular").UserSettingsState) => void;
20354
+ fail: (err: unknown) => void;
20355
+ initialize: () => Promise<void>;
20356
+ reset: () => Promise<void>;
20357
+ deleteAlert: (index: number) => Promise<void>;
20358
+ createAlert: (alert: import("@sinequa/atomic-angular").Alert) => Promise<void>;
20359
+ updateAlert: (alert: import("@sinequa/atomic-angular").Alert, index: number) => Promise<void>;
20360
+ updateAlerts: (alerts: import("@sinequa/atomic-angular").Alert[]) => Promise<void>;
20361
+ setDebugMode: (value: boolean) => Promise<void>;
20362
+ setUserTheme: (userTheme: "dark" | "light" | "system") => Promise<void>;
20363
+ toggleDarkMode: () => Promise<void>;
20364
+ setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
20365
+ } & import("@ngrx/signals").StateSource<{
20366
+ bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20367
+ favoriteSearches: string[];
20368
+ recentSearches: SearchItem[];
20369
+ savedSearches: SearchItem[];
20370
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
20371
+ baskets: import("@sinequa/atomic-angular").Basket[];
20372
+ assistants: Record<string, unknown>;
20373
+ alerts: import("@sinequa/atomic-angular").Alert[];
20374
+ collapseAssistant?: boolean | undefined;
20375
+ language?: string | undefined;
20376
+ userTheme: "dark" | "light" | "system";
20377
+ agents: import("@sinequa/atomic-angular").AgentUserSettings;
20378
+ disabledHighlightCategories: string[];
20379
+ }>;
20380
+ protected readonly transloco: TranslocoService;
20381
+ private readonly router;
20382
+ protected subtextOf: (search: SearchItem) => string | undefined;
20383
+ protected urlOf: (search: SearchItem) => string;
20384
+ protected labelOf: (search: SearchItem) => string;
20385
+ protected readonly range: import("@angular/core").WritableSignal<number>;
20386
+ protected readonly recentSearches: import("@angular/core").Signal<SearchItem[]>;
20387
+ protected readonly paginatedRecentSearches: import("@angular/core").Signal<SearchItem[]>;
20388
+ protected readonly hasMore: import("@angular/core").Signal<boolean>;
20389
+ constructor();
20390
+ onClick(search: SearchItem): void;
20391
+ /**
20392
+ * Deletes a recent search item at the specified index.
20393
+ */
20394
+ onDelete(event: ListPanelDeleteEvent<SearchItem>): Promise<void>;
20395
+ loadMore(): void;
20396
+ static ɵfac: i0.ɵɵFactoryDeclaration<RecentSearchesComponent, never>;
20397
+ static ɵcmp: i0.ɵɵComponentDeclaration<RecentSearchesComponent, "RecentSearches, recent-searches", never, {
20398
+ "options": {
20399
+ "alias": "options";
20400
+ "required": false;
20401
+ "isSignal": true;
20402
+ };
20403
+ }, {}, never, never, true, never>;
20404
+ }
20405
+ export declare class SavedSearchDialog {
20406
+ protected readonly call: import("@sinequa/galactik").CallRef<string, DialogResult>;
20407
+ private readonly savedSearchesService;
20408
+ private readonly transloco;
20409
+ private readonly dialog;
20410
+ private readonly nameInputRef;
20411
+ saveName: import("@angular/core").WritableSignal<string>;
20412
+ protected readonly nameField: import("@angular/forms/signals").FieldTree<string, string | number, "writable">;
20413
+ constructor();
20414
+ confirm(): void;
20415
+ static ɵfac: i0.ɵɵFactoryDeclaration<SavedSearchDialog, never>;
20416
+ static ɵcmp: i0.ɵɵComponentDeclaration<SavedSearchDialog, "saved-search-dialog, savedsearchdialog, SavedSearchDialog", never, {}, {}, never, never, true, never>;
20417
+ }
20418
+ /** Imperative entry point: `await SavedSearch.call(initialName)`. */
20419
+ export declare const SavedSearch: import("@sinequa/galactik").Callable<string, DialogResult>;
20420
+ /**
20421
+ * Save/unsave toggle for the current search, as a starred button.
20422
+ *
20423
+ * Usage:
20424
+ * ```html
20425
+ * <saved-search-popover
20426
+ * [queryText]="searchInputText()"
20427
+ * (onSavedSearch)="saved.emit($event)" />
20428
+ * ```
20429
+ *
20430
+ * When the current search is not yet saved, opens {@link SavedSearchDialog} to name and save it.
20431
+ * When it is already saved, the button unsaves it directly (no dialog, no name to pick again).
20432
+ */
20433
+ export declare class SavedSearchPopover {
20434
+ protected readonly userSettingsStore: {
20435
+ bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20436
+ favoriteSearches: import("@angular/core").Signal<string[]>;
20437
+ recentSearches: import("@angular/core").Signal<SearchItem[]>;
20438
+ savedSearches: import("@angular/core").Signal<SearchItem[]>;
20439
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
20440
+ baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
20441
+ assistants: import("@angular/core").Signal<Record<string, unknown>>;
20442
+ alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
20443
+ collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
20444
+ language?: import("@angular/core").Signal<string | undefined> | undefined;
20445
+ userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
20446
+ agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
20447
+ disabledHighlightCategories: import("@angular/core").Signal<string[]>;
18841
20448
  isDebugMode: import("@angular/core").Signal<boolean>;
18842
20449
  isDarkMode: import("@angular/core").Signal<boolean>;
18843
20450
  updateBookmarks: (bookmarks: import("@sinequa/atomic-angular").UserSettingsState["bookmarks"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
@@ -18845,12 +20452,20 @@ export declare class SavedSearchPopover {
18845
20452
  unbookmark: (id: string) => Promise<void>;
18846
20453
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
18847
20454
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
20455
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
20456
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
18848
20457
  deleteRecentSearch: (index: number) => Promise<void>;
18849
20458
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
18850
20459
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
18851
20460
  deleteSavedSearch: (index: number) => Promise<void>;
18852
20461
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
18853
20462
  getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
20463
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
20464
+ updateQuickFilter: (id: string, changes: {
20465
+ name?: string;
20466
+ filters?: import("@sinequa/atomic").LegacyFilter[];
20467
+ }) => Promise<void>;
20468
+ removeQuickFilter: (id: string) => Promise<void>;
18854
20469
  deleteBasket: (index: number) => Promise<void>;
18855
20470
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
18856
20471
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -18874,8 +20489,10 @@ export declare class SavedSearchPopover {
18874
20489
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
18875
20490
  } & import("@ngrx/signals").StateSource<{
18876
20491
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20492
+ favoriteSearches: string[];
18877
20493
  recentSearches: SearchItem[];
18878
20494
  savedSearches: SearchItem[];
20495
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
18879
20496
  baskets: import("@sinequa/atomic-angular").Basket[];
18880
20497
  assistants: Record<string, unknown>;
18881
20498
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -18912,8 +20529,10 @@ export declare class SavedSearchesComponent {
18912
20529
  protected config: import("@sinequa/atomic-angular").ListPanelConfig;
18913
20530
  protected readonly userSettingsStore: {
18914
20531
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20532
+ favoriteSearches: import("@angular/core").Signal<string[]>;
18915
20533
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
18916
20534
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
20535
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
18917
20536
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
18918
20537
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
18919
20538
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -18929,12 +20548,20 @@ export declare class SavedSearchesComponent {
18929
20548
  unbookmark: (id: string) => Promise<void>;
18930
20549
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
18931
20550
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
20551
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
20552
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
18932
20553
  deleteRecentSearch: (index: number) => Promise<void>;
18933
20554
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
18934
20555
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
18935
20556
  deleteSavedSearch: (index: number) => Promise<void>;
18936
20557
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
18937
20558
  getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
20559
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
20560
+ updateQuickFilter: (id: string, changes: {
20561
+ name?: string;
20562
+ filters?: import("@sinequa/atomic").LegacyFilter[];
20563
+ }) => Promise<void>;
20564
+ removeQuickFilter: (id: string) => Promise<void>;
18938
20565
  deleteBasket: (index: number) => Promise<void>;
18939
20566
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
18940
20567
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -18958,8 +20585,10 @@ export declare class SavedSearchesComponent {
18958
20585
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
18959
20586
  } & import("@ngrx/signals").StateSource<{
18960
20587
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20588
+ favoriteSearches: string[];
18961
20589
  recentSearches: SearchItem[];
18962
20590
  savedSearches: SearchItem[];
20591
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
18963
20592
  baskets: import("@sinequa/atomic-angular").Basket[];
18964
20593
  assistants: Record<string, unknown>;
18965
20594
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -20752,4 +22381,4 @@ export type AppFeatures = {
20752
22381
  * @deprecated use `general` configuration json instead from the app store
20753
22382
  */
20754
22383
  export declare const APP_FEATURES: InjectionToken<AppFeatures>;
20755
- export type { ConverterOption, DateRange, DateRangeDialogProps, Shortcut, ShortcutDefinition };
22384
+ export type { ConverterOption, DateRange, DateRangeDialogProps, FilterScheme, Shortcut, ShortcutDefinition };