@sinequa/atomic-angular 2.8.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[];
@@ -11094,9 +11233,15 @@ export declare class ArticleSimilarDocumentsTabPanel {
11094
11233
  "selected": "selected";
11095
11234
  }, never, never, true, never>;
11096
11235
  }
11236
+ /**
11237
+ * Short weekday names in the active language ("Mon", "lun."), Monday first. 2024-01-01 is a Monday.
11238
+ */
11239
+ declare function weekdayNames(lang: string): string[];
11097
11240
  /** One piece of the summary: a translation key (translated by the template's pipe) or a ready text. */
11098
11241
  interface AlertSummaryPart {
11099
11242
  key?: string;
11243
+ /** Interpolation parameters of `key`. */
11244
+ params?: Record<string, unknown>;
11100
11245
  text?: string;
11101
11246
  }
11102
11247
  /**
@@ -11109,6 +11254,11 @@ interface AlertSummaryPart {
11109
11254
  * Tolerant of an alert that lacks `times` or `days`: the piece is left out rather than shown empty.
11110
11255
  */
11111
11256
  declare function alertSummary(lang: string, alert: Alert): AlertSummaryPart[];
11257
+ /**
11258
+ * What an alert watches, in pieces — « “data protection” · Web tab · 2 filters ». Same contract as
11259
+ * {@link alertSummary}: translation keys for the template's pipe, ready text for the rest.
11260
+ */
11261
+ declare function querySummary(query: Query | undefined): AlertSummaryPart[];
11112
11262
  /**
11113
11263
  * The user's alerts: one row per alert (name, when it fires, an on/off switch), "Create" in the header.
11114
11264
  *
@@ -11124,6 +11274,23 @@ export declare class AlertsComponent {
11124
11274
  private readonly transloco;
11125
11275
  private readonly lang;
11126
11276
  query: Query;
11277
+ /**
11278
+ * Whether the form opens in a dialog (`AlertForm`), which is what a click on a row or on "Create" does by
11279
+ * default. Set it to `false` to show the form yourself, wherever you like (see `AlertFormComponent`): the
11280
+ * list then only reports the request, with `editRequested` and `createRequested`.
11281
+ */
11282
+ readonly dialog: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
11283
+ /** The user asked to edit an alert: its index in `UserSettingsStore.alerts()`. Only with `[dialog]="false"`. */
11284
+ readonly editRequested: import("@angular/core").OutputEmitterRef<number>;
11285
+ /** The user asked to create an alert. Only with `[dialog]="false"`. */
11286
+ readonly createRequested: import("@angular/core").OutputEmitterRef<void>;
11287
+ /**
11288
+ * Why the last change could not be saved, shown above the list until the next one. A toast would not do: the
11289
+ * list lives in popovers and modal dialogs, which are in the top layer, above any toast.
11290
+ */
11291
+ protected readonly saveError: import("@angular/core").WritableSignal<{
11292
+ detail?: string;
11293
+ } | undefined>;
11127
11294
  protected readonly alerts: import("@angular/core").Signal<Alert[]>;
11128
11295
  /**
11129
11296
  * The order on screen. A copy of the store's list (the store edits its own array in place), and ahead of it
@@ -11165,7 +11332,16 @@ export declare class AlertsComponent {
11165
11332
  /** The new order of the alerts shown. An alert being deleted is not in it: it goes after them, as it is about to leave. */
11166
11333
  protected saveOrder(shown: Alert[]): Promise<void>;
11167
11334
  static ɵfac: i0.ɵɵFactoryDeclaration<AlertsComponent, never>;
11168
- static ɵcmp: i0.ɵɵComponentDeclaration<AlertsComponent, "Alerts", never, {}, {}, never, never, true, never>;
11335
+ static ɵcmp: i0.ɵɵComponentDeclaration<AlertsComponent, "Alerts", never, {
11336
+ "dialog": {
11337
+ "alias": "dialog";
11338
+ "required": false;
11339
+ "isSignal": true;
11340
+ };
11341
+ }, {
11342
+ "editRequested": "editRequested";
11343
+ "createRequested": "createRequested";
11344
+ }, never, never, true, never>;
11169
11345
  }
11170
11346
  /**
11171
11347
  * The seven weekdays, in display order, each paired with its bit in {@link Alert.Days}.
@@ -11220,22 +11396,47 @@ export interface AlertFormModel {
11220
11396
  export declare function weekdaysFromFlags(mask: Alert.Days): Record<WeekdayKey, boolean>;
11221
11397
  /** Folds the seven booleans of the form model back into an {@link Alert.Days} bitfield. */
11222
11398
  export declare function flagsFromWeekdays(days: Record<WeekdayKey, boolean>): Alert.Days;
11223
- export declare class AlertDialog {
11224
- protected readonly call: import("@sinequa/galactik").CallRef<number | undefined, DialogEvent>;
11399
+ /**
11400
+ * The form that creates or edits one alert: name, frequency and time, weekdays, on/off, and — for an
11401
+ * existing alert — the search it watches.
11402
+ *
11403
+ * It knows nothing of its container. `<alert-form [index]="…" (saved)="…" />` can sit in a dialog (see
11404
+ * {@link AlertDialog}), a panel, a drawer or a page: it saves through {@link UserSettingsStore} and tells its
11405
+ * container with `saved` once the save has succeeded, or `executed` once the user has run the watched search.
11406
+ * A failed save keeps what was typed and is shown inside the form — a toast would sit behind a modal dialog.
11407
+ *
11408
+ * The form renders no button of its own that submits or cancels: those belong to the container. A submit
11409
+ * button placed outside the form submits it by pointing at {@link AlertFormComponent.formId} with its `form`
11410
+ * attribute, and can use {@link AlertFormComponent.saving} to wait for the save.
11411
+ *
11412
+ * The layout follows the width of the form (a container query), not that of the window: frequency and time
11413
+ * share a line from 24rem up and stack below.
11414
+ */
11415
+ export declare class AlertFormComponent {
11225
11416
  private readonly queryService;
11226
11417
  private readonly queryParamsStore;
11227
11418
  private readonly userSettingsStore;
11228
11419
  private readonly transloco;
11229
- readonly dialog: import("@angular/core").Signal<DialogComponent | undefined>;
11420
+ private readonly lang;
11421
+ /** Index, in the user settings, of the alert to edit — leave it unset to create one. */
11422
+ readonly index: import("@angular/core").InputSignal<number | undefined>;
11423
+ /** Emitted once the alert has been saved. */
11424
+ readonly saved: import("@angular/core").OutputEmitterRef<void>;
11425
+ /** Emitted once the user has run the watched search: the query parameters now hold it. */
11426
+ readonly executed: import("@angular/core").OutputEmitterRef<void>;
11427
+ /** Id of the `<form>`: a submit button outside the component points at it with its `form` attribute. */
11428
+ readonly formId: string;
11230
11429
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11231
11430
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
11232
11431
  protected readonly errorClass = "text-(length:--size-base) text-(--font-error-base)";
11233
- frequencies: Alert.Frequency[];
11234
- frequency: typeof Alert.Frequency;
11432
+ protected readonly frequencies: Alert.Frequency[];
11433
+ protected readonly frequency: typeof Alert.Frequency;
11434
+ protected readonly Days: typeof Alert.Days;
11435
+ protected readonly querySummary: typeof querySummary;
11235
11436
  /** Libellé traduit d'une fréquence — utilisé par le typeahead du `SelectMenu`. */
11236
- readonly frequencyLabel: (value: Alert.Frequency) => string;
11237
- /** The seven weekdays, exposed to the template for the checkbox grid. */
11238
- readonly weekdays: readonly [{
11437
+ protected readonly frequencyLabel: (value: Alert.Frequency) => string;
11438
+ /** The seven weekdays, exposed to the template for the toggle chips. */
11439
+ protected readonly weekdays: readonly [{
11239
11440
  readonly key: "monday";
11240
11441
  readonly flag: Alert.Days.Monday;
11241
11442
  }, {
@@ -11257,30 +11458,33 @@ export declare class AlertDialog {
11257
11458
  readonly key: "sunday";
11258
11459
  readonly flag: Alert.Days.Sunday;
11259
11460
  }];
11260
- /**
11261
- * The alert being edited, and its index in the user settings — `undefined` in "create" mode.
11262
- *
11263
- * Signals and not plain properties: they are written from `init()`, outside any template listener,
11264
- * and the template branches on them. A plain property mutated there does not mark the view dirty.
11265
- */
11266
- readonly index: import("@angular/core").WritableSignal<number | undefined>;
11267
- readonly alert: import("@angular/core").WritableSignal<Alert | undefined>;
11268
- canUpdateQuery: import("@angular/core").WritableSignal<boolean>;
11269
- updateStatus: import("@angular/core").WritableSignal<"idle" | "updating" | "updated">;
11270
- /** Why the last save failed — shown in the dialog until the next attempt. */
11461
+ /** Their short names in the active language, Monday first — what the chips show. */
11462
+ protected readonly dayNames: import("@angular/core").Signal<string[]>;
11463
+ /** The alert being edited — `undefined` in "create" mode. */
11464
+ readonly alert: import("@angular/core").Signal<Alert | undefined>;
11465
+ /**
11466
+ * Whether the search currently on screen can replace the one the alert watches: it must have results.
11467
+ * Only an existing alert has anything to replace, so a new one issues no search.
11468
+ */
11469
+ private readonly currentSearch;
11470
+ readonly canUpdateQuery: import("@angular/core").Signal<boolean>;
11471
+ readonly updateStatus: import("@angular/core").WritableSignal<"idle" | "updating" | "updated">;
11472
+ /** Why the last save failed — shown in the form until the next attempt. */
11271
11473
  protected readonly saveError: import("@angular/core").WritableSignal<{
11272
11474
  detail?: string;
11273
11475
  } | undefined>;
11274
- /** Form model. Replaces the five former scalar signals. */
11476
+ /** Form model: the stored alert's values, or the defaults of a new one. Follows the alert it edits. */
11275
11477
  readonly alertModel: import("@angular/core").WritableSignal<AlertFormModel>;
11276
11478
  protected readonly alertForm: FieldTree<AlertFormModel, string | number, "writable">;
11479
+ /** True while a submission is being saved — for a container that disables its confirm button meanwhile. */
11480
+ readonly saving: import("@angular/core").Signal<boolean>;
11277
11481
  /**
11278
11482
  * The weekday group shows its error like any other field: once touched — which, for a group the
11279
11483
  * checkboxes cannot blur, means once the form has been submitted.
11280
11484
  */
11281
11485
  protected readonly showDaysError: import("@angular/core").Signal<boolean>;
11282
- constructor();
11283
- private init;
11486
+ /** Checks exactly the days of `mask` — the "Weekdays" and "Every day" shortcuts. */
11487
+ protected setDays(mask: Alert.Days): void;
11284
11488
  /**
11285
11489
  * The submission itself, only ever reached with a valid form: `submit()` marks every field as
11286
11490
  * touched — revealing the messages — and runs the action only when the form is valid.
@@ -11292,8 +11496,35 @@ export declare class AlertDialog {
11292
11496
  protected showError<T>(field: FieldTree<T>): boolean;
11293
11497
  /** Maps the first validation error to its translation key (`alerts.errors.noDaySelected`, …). */
11294
11498
  protected errorKey<T>(field: FieldTree<T>): string;
11295
- updateQuery(): void;
11296
- execute(): void;
11499
+ protected updateQuery(): void;
11500
+ protected execute(): void;
11501
+ static ɵfac: i0.ɵɵFactoryDeclaration<AlertFormComponent, never>;
11502
+ static ɵcmp: i0.ɵɵComponentDeclaration<AlertFormComponent, "alert-form, alertform, AlertFormComponent", never, {
11503
+ "index": {
11504
+ "alias": "index";
11505
+ "required": false;
11506
+ "isSignal": true;
11507
+ };
11508
+ }, {
11509
+ "saved": "saved";
11510
+ "executed": "executed";
11511
+ }, never, never, true, never>;
11512
+ }
11513
+ /**
11514
+ * The modal dialog around {@link AlertFormComponent}: a title, the form, and the Cancel / Confirm buttons.
11515
+ *
11516
+ * It only hosts the form — the fields, the validation and the save are the form's. Confirm sits outside the
11517
+ * `<form>` and submits it through its `form` attribute; the dialog closes when the form says the alert is
11518
+ * saved (`dialog-confirm`) or that the watched search has been run.
11519
+ *
11520
+ * Open it with {@link AlertForm}, which takes the index of the alert to edit (none to create one).
11521
+ */
11522
+ export declare class AlertDialog {
11523
+ protected readonly call: import("@sinequa/galactik").CallRef<number | undefined, DialogEvent>;
11524
+ readonly dialog: import("@angular/core").Signal<DialogComponent | undefined>;
11525
+ /** Index, in the user settings, of the alert being edited — `undefined` in "create" mode. */
11526
+ protected readonly index: import("@angular/core").WritableSignal<number | undefined>;
11527
+ constructor();
11297
11528
  static ɵfac: i0.ɵɵFactoryDeclaration<AlertDialog, never>;
11298
11529
  static ɵcmp: i0.ɵɵComponentDeclaration<AlertDialog, "alert-dialog, alertdialog, AlertDialog", never, {}, {}, never, never, true, never>;
11299
11530
  }
@@ -11357,7 +11588,7 @@ export declare class ChangePasswordComponent {
11357
11588
  private readonly applicationService;
11358
11589
  private readonly location;
11359
11590
  private readonly auditService;
11360
- 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)">;
11361
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)";
11362
11593
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11363
11594
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
@@ -11457,7 +11688,7 @@ export declare class SignInComponent implements OnInit {
11457
11688
  loginPath: string;
11458
11689
  createRoutes: boolean;
11459
11690
  }> & Record<string, unknown>>;
11460
- 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)">;
11461
11692
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11462
11693
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
11463
11694
  protected readonly errorClass = "text-(length:--size-base) text-(--font-error-base)";
@@ -11655,7 +11886,7 @@ export declare class ForgotPasswordComponent {
11655
11886
  private readonly client;
11656
11887
  private readonly transloco;
11657
11888
  private readonly auditService;
11658
- 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)">;
11659
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)";
11660
11891
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11661
11892
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
@@ -11708,7 +11939,7 @@ export declare class ForgotPasswordComponent {
11708
11939
  export declare class SignedOutComponent {
11709
11940
  private readonly router;
11710
11941
  private readonly client;
11711
- 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)";
11712
11943
  /**
11713
11944
  * Navigate to the login screen, which then drives the normal sign-in handshake.
11714
11945
  *
@@ -11721,8 +11952,8 @@ export declare class SignedOutComponent {
11721
11952
  static ɵcmp: i0.ɵɵComponentDeclaration<SignedOutComponent, "signed-out, SignedOut, signedout", never, {}, {}, never, never, true, never>;
11722
11953
  }
11723
11954
  export declare class BookmarkButtonComponent {
11724
- variant: import("@angular/core").InputSignal<"primary" | "secondary" | "none" | "light-accent" | "accent" | "tertiary" | null | undefined>;
11725
- size: import("@angular/core").InputSignal<"small" | "sm" | "md" | "xs" | "xsmall" | "medium" | "lg" | "large" | 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>;
11726
11957
  /**
11727
11958
  * Tab index applied to the inner button.
11728
11959
  *
@@ -12813,7 +13044,7 @@ export declare class SearchFeedbackComponent {
12813
13044
  onClose: import("@angular/core").OutputEmitterRef<void>;
12814
13045
  private readonly injector;
12815
13046
  pages: import("@angular/core").InputSignal<any>;
12816
- variant: import("@angular/core").InputSignal<"primary" | "secondary" | "none" | "light-accent" | "accent" | "tertiary" | null | undefined>;
13047
+ variant: import("@angular/core").InputSignal<"none" | "light-accent" | "accent" | "primary" | "secondary" | "tertiary" | null | undefined>;
12817
13048
  readonly auditService: AuditService;
12818
13049
  protected readonly queryParamsStore: {
12819
13050
  name?: import("@angular/core").Signal<string | undefined> | undefined;
@@ -13101,6 +13332,14 @@ export declare class AggregationDateComponent {
13101
13332
  column: import("@angular/core").InputSignal<string | null>;
13102
13333
  id: import("@angular/core").InputSignal<string | null>;
13103
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>;
13104
13343
  collapsed: import("@angular/core").InputSignal<boolean>;
13105
13344
  searchable: import("@angular/core").InputSignal<boolean | undefined>;
13106
13345
  showFiltersCount: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
@@ -13474,6 +13713,11 @@ export declare class AggregationDateComponent {
13474
13713
  "required": false;
13475
13714
  "isSignal": true;
13476
13715
  };
13716
+ "headless": {
13717
+ "alias": "headless";
13718
+ "required": false;
13719
+ "isSignal": true;
13720
+ };
13477
13721
  "collapsed": {
13478
13722
  "alias": "collapsed";
13479
13723
  "required": false;
@@ -13559,6 +13803,15 @@ export declare class AggregationTreeComponent {
13559
13803
  * @default true
13560
13804
  */
13561
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>;
13562
13815
  /**
13563
13816
  * Whether every selection gesture — row click, checkbox click, Space/Enter on the
13564
13817
  * focused node — applies the filter immediately, instead of only revealing the
@@ -14323,6 +14576,11 @@ export declare class AggregationTreeComponent {
14323
14576
  "required": false;
14324
14577
  "isSignal": true;
14325
14578
  };
14579
+ "headless": {
14580
+ "alias": "headless";
14581
+ "required": false;
14582
+ "isSignal": true;
14583
+ };
14326
14584
  "applyOnSelect": {
14327
14585
  "alias": "applyOnSelect";
14328
14586
  "required": false;
@@ -14401,6 +14659,15 @@ export declare class AggregationListComponent {
14401
14659
  * @default true
14402
14660
  */
14403
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>;
14404
14671
  /**
14405
14672
  * Whether every selection gesture — row click, checkbox click, Space/Enter on the
14406
14673
  * focused option — applies the filter immediately, instead of only revealing the
@@ -15081,6 +15348,11 @@ export declare class AggregationListComponent {
15081
15348
  "required": false;
15082
15349
  "isSignal": true;
15083
15350
  };
15351
+ "headless": {
15352
+ "alias": "headless";
15353
+ "required": false;
15354
+ "isSignal": true;
15355
+ };
15084
15356
  "applyOnSelect": {
15085
15357
  "alias": "applyOnSelect";
15086
15358
  "required": false;
@@ -15541,6 +15813,15 @@ export declare class AggregationComponent {
15541
15813
  * @default true
15542
15814
  */
15543
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>;
15544
15825
  /**
15545
15826
  * **List/tree only.** Whether every selection gesture — row click, checkbox click,
15546
15827
  * Space/Enter on the focused item — applies the filter immediately, instead of only
@@ -15759,6 +16040,11 @@ export declare class AggregationComponent {
15759
16040
  "required": false;
15760
16041
  "isSignal": true;
15761
16042
  };
16043
+ "headless": {
16044
+ "alias": "headless";
16045
+ "required": false;
16046
+ "isSignal": true;
16047
+ };
15762
16048
  "applyOnSelect": {
15763
16049
  "alias": "applyOnSelect";
15764
16050
  "required": false;
@@ -15830,6 +16116,17 @@ export declare class AggregationPanelComponent {
15830
16116
  hasFilters: import("@angular/core").InputSignal<boolean>;
15831
16117
  selection: import("@angular/core").InputSignal<boolean>;
15832
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>;
15833
16130
  searchText: import("@angular/core").ModelSignal<string>;
15834
16131
  itemsLength: import("@angular/core").InputSignal<number>;
15835
16132
  hasMore: import("@angular/core").InputSignal<boolean>;
@@ -15843,7 +16140,7 @@ export declare class AggregationPanelComponent {
15843
16140
  expanded: import("@angular/core").Signal<"" | null>;
15844
16141
  private readonly searchBox;
15845
16142
  /** The galactik popover (`[popover]` / `[dropdown]`) this panel is shown in, if any — resolved through the injector tree. */
15846
- private readonly isInPopover;
16143
+ protected readonly isInPopover: boolean;
15847
16144
  constructor();
15848
16145
  onHeaderClick(event: Event): void;
15849
16146
  onToggle(event: Event): void;
@@ -15904,6 +16201,16 @@ export declare class AggregationPanelComponent {
15904
16201
  "required": false;
15905
16202
  "isSignal": true;
15906
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
+ };
15907
16214
  "searchText": {
15908
16215
  "alias": "searchText";
15909
16216
  "required": false;
@@ -16042,9 +16349,9 @@ export declare class AppliedFiltersComponent {
16042
16349
  */
16043
16350
  readonly variant: import("@angular/core").InputSignal<"primary" | "secondary" | null | undefined>;
16044
16351
  /** Chip colour scheme, passed to galactik's `tag`. */
16045
- 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>;
16046
16353
  /** Chip size, passed to galactik's `tag`. */
16047
- 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>;
16048
16355
  /** Extra classes for each chip, merged by galactik's `tag`. */
16049
16356
  readonly chipClass: import("@angular/core").InputSignal<string>;
16050
16357
  /** A chip was removed. */
@@ -16211,6 +16518,20 @@ export declare class AsideFiltersComponent {
16211
16518
  };
16212
16519
  }, {}, never, never, true, never>;
16213
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;
16214
16535
  export type CFilterEx = CFilter & {
16215
16536
  name: string;
16216
16537
  count: number;
@@ -16219,6 +16540,8 @@ export type CFilterEx = CFilter & {
16219
16540
  hidden: boolean;
16220
16541
  legacyFilter?: LegacyFilter;
16221
16542
  };
16543
+ /** Look of a filter button: the default flat button, or a rounded outlined pill. */
16544
+ export type FilterAppearance = "default" | "pill";
16222
16545
  export declare class FilterButtonComponent {
16223
16546
  name: import("@angular/core").InputSignal<string | undefined>;
16224
16547
  column: import("@angular/core").InputSignal<string>;
@@ -16233,21 +16556,39 @@ export declare class FilterButtonComponent {
16233
16556
  lockPosition: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16234
16557
  expandedLevel: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
16235
16558
  /**
16236
- * Set by `filters-bar` on the filters that do not fit and are hidden by the overflow manager. They
16237
- * leave the toolbar's keyboard navigation: a roving focus cannot land on an element with
16238
- * `display: none`, so the arrow keys used to stall on the last visible filter while the tab stop
16239
- * 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"
16240
16570
  */
16241
- overflowed: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16242
- protected variant: import("@angular/core").WritableSignal<"primary" | "secondary" | "none" | "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>;
16243
16573
  protected filter: import("@angular/core").WritableSignal<CFilterEx>;
16244
16574
  /** Unique id wiring the trigger's `popovertarget` to the `<div popover>` `id`. */
16245
16575
  protected readonly popoverId: string;
16246
16576
  popoverRef: import("@angular/core").Signal<PopoverDirective | undefined>;
16247
16577
  /** True while the native popover is open — drives the trigger's open styling. */
16248
16578
  protected readonly isOpen: import("@angular/core").Signal<boolean>;
16249
- /** Set when this button sits in a `filters-bar` toolbar: the inner button then is the roving widget. */
16250
- 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>;
16251
16592
  protected nativeElement: any;
16252
16593
  protected aggregationsStore: {
16253
16594
  aggregations: import("@angular/core").Signal<import("@sinequa/atomic").Aggregation[]>;
@@ -16686,24 +17027,22 @@ export declare class FilterButtonComponent {
16686
17027
  columnMap?: Record<string, import("@sinequa/atomic").CCColumn> | undefined;
16687
17028
  }>;
16688
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;
16689
17040
  /**
16690
17041
  * Toggles the popover on keyboard activation of the (roving) toolbar widget
16691
17042
  * host. Always cancels the default action; opening is suppressed for disabled
16692
17043
  * filters, mirroring the previous deprecated-popover behavior.
16693
17044
  */
16694
17045
  protected toggle(event: Event): void;
16695
- /**
16696
- * Keeps the toolbar's roving keyboard handler out of the panel.
16697
- *
16698
- * The panel is a DOM descendant of the `@angular/aria` toolbar, which owns the arrow keys to
16699
- * rove between widgets. Its handler therefore consumed the arrows pressed *inside* the panel,
16700
- * and the native radio group of the date aggregation never moved: focus stayed on the first
16701
- * option whatever the user pressed. Pointer events were already isolated (above) for the same
16702
- * reason — this is the keyboard half of that isolation.
16703
- *
16704
- * Tab and Escape are deliberately let through: they must keep leaving and closing the panel.
16705
- */
16706
- protected isolateNavigationKeys(event: KeyboardEvent): void;
16707
17046
  /**
16708
17047
  * Closes the popover when focus leaves the filter entirely.
16709
17048
  *
@@ -16755,129 +17094,300 @@ export declare class FilterButtonComponent {
16755
17094
  "required": false;
16756
17095
  "isSignal": true;
16757
17096
  };
16758
- "overflowed": {
16759
- "alias": "overflowed";
17097
+ "appearance": {
17098
+ "alias": "appearance";
17099
+ "required": false;
17100
+ "isSignal": true;
17101
+ };
17102
+ "scheme": {
17103
+ "alias": "scheme";
16760
17104
  "required": false;
16761
17105
  "isSignal": true;
16762
17106
  };
16763
17107
  }, {}, never, never, true, never>;
16764
17108
  }
16765
- export declare class MoreButtonComponent {
16766
- appStore: {
16767
- name: import("@angular/core").Signal<string>;
16768
- description?: import("@angular/core").Signal<string | undefined> | undefined;
16769
- versionId: import("@angular/core").Signal<string>;
16770
- queries: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCQuery>>;
16771
- rfms: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCRFM>>;
16772
- indexes: import("@angular/core").Signal<{
16773
- _: import("@sinequa/atomic").CCIndex;
16774
- } & Record<string, import("@sinequa/atomic").CCIndex>>;
16775
- lists: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCList>>;
16776
- webServices: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCWebService>>;
16777
- queryNames: import("@angular/core").Signal<string>;
16778
- labels: import("@angular/core").Signal<string>;
16779
- preview: import("@angular/core").Signal<string>;
16780
- autocomplete: import("@angular/core").Signal<string>;
16781
- sponsoredLinks: import("@angular/core").Signal<string>;
16782
- queryExport: import("@angular/core").Signal<string>;
16783
- queryRssEnabled: import("@angular/core").Signal<boolean>;
16784
- data: import("@angular/core").Signal<Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
16785
- filters?: import("@sinequa/atomic-angular").CAggregation[];
16786
- autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
16787
- tabs?: Record<string, {
16788
- filters: string[];
16789
- overviews?: Record<string, {
16790
- minRelevance: number;
16791
- }>;
16792
- }>;
16793
- sources?: import("@sinequa/atomic-angular").CSources;
16794
- features?: {
16795
- [key: string]: boolean | {
16796
- [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
16797
- } | undefined;
16798
- allowChangePassword?: boolean;
16799
- editablepartition?: boolean;
16800
- advancedSearch?: boolean;
16801
- allowChatDrawer?: boolean;
16802
- filterLinkChildren?: boolean;
16803
- expandPreview?: boolean;
16804
- quickFilter?: boolean;
16805
- showAggregationItemCount?: boolean;
16806
- assistant?: {
16807
- usePrefixName?: boolean;
16808
- };
16809
- filters?: {
16810
- homepage?: boolean;
16811
- };
16812
- userProfile?: {
16813
- enabled?: boolean;
16814
- data?: string[];
16815
- customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
16816
- };
16817
- previewMultiConversion?: boolean;
16818
- persistFiltersAcrossTabs?: boolean;
16819
- };
16820
- allowAdvancedFilters?: boolean;
16821
- general?: {
16822
- name?: string;
16823
- logo?: {
16824
- alt?: string;
16825
- light?: {
16826
- small?: string;
16827
- large?: string;
16828
- sidebar?: string;
16829
- };
16830
- dark?: {
16831
- small?: string;
16832
- large?: string;
16833
- sidebar?: string;
16834
- };
16835
- };
16836
- features?: {
16837
- [key: string]: boolean | {
16838
- [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
16839
- } | undefined;
16840
- allowChangePassword?: boolean;
16841
- editablepartition?: boolean;
16842
- advancedSearch?: boolean;
16843
- allowChatDrawer?: boolean;
16844
- filterLinkChildren?: boolean;
16845
- expandPreview?: boolean;
16846
- quickFilter?: boolean;
16847
- showAggregationItemCount?: boolean;
16848
- assistant?: {
16849
- usePrefixName?: boolean;
16850
- };
16851
- filters?: {
16852
- homepage?: boolean;
16853
- };
16854
- userProfile?: {
16855
- enabled?: boolean;
16856
- data?: string[];
16857
- customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
16858
- };
16859
- previewMultiConversion?: boolean;
16860
- persistFiltersAcrossTabs?: boolean;
16861
- };
16862
- converters?: import("@sinequa/atomic-angular").CConverter[];
16863
- feedback?: import("@sinequa/atomic-angular").CFeedback;
16864
- };
16865
- documentsUploadSettings?: {
16866
- enabled?: boolean;
16867
- };
16868
- }>;
16869
- customJSONs: import("@angular/core").Signal<{
16870
- name: string;
16871
- data: Record<string, unknown>;
16872
- }[] & import("@sinequa/atomic-angular").SideCJson[]>;
16873
- apiVersion: import("@angular/core").Signal<string>;
16874
- workspaceApp: import("@angular/core").Signal<string>;
16875
- defaultQueryName: import("@angular/core").Signal<string>;
16876
- auditEnabled?: import("@angular/core").Signal<boolean | undefined> | undefined;
16877
- dataSets?: import("@angular/core").Signal<string | undefined> | undefined;
16878
- revision?: import("@angular/core").Signal<number | undefined> | undefined;
16879
- runnableModels?: import("@angular/core").Signal<string | undefined> | undefined;
16880
- authorizationLevel?: import("@angular/core").Signal<string | undefined> | undefined;
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
+ }
17275
+ export declare class MoreButtonComponent {
17276
+ appStore: {
17277
+ name: import("@angular/core").Signal<string>;
17278
+ description?: import("@angular/core").Signal<string | undefined> | undefined;
17279
+ versionId: import("@angular/core").Signal<string>;
17280
+ queries: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCQuery>>;
17281
+ rfms: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCRFM>>;
17282
+ indexes: import("@angular/core").Signal<{
17283
+ _: import("@sinequa/atomic").CCIndex;
17284
+ } & Record<string, import("@sinequa/atomic").CCIndex>>;
17285
+ lists: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCList>>;
17286
+ webServices: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCWebService>>;
17287
+ queryNames: import("@angular/core").Signal<string>;
17288
+ labels: import("@angular/core").Signal<string>;
17289
+ preview: import("@angular/core").Signal<string>;
17290
+ autocomplete: import("@angular/core").Signal<string>;
17291
+ sponsoredLinks: import("@angular/core").Signal<string>;
17292
+ queryExport: import("@angular/core").Signal<string>;
17293
+ queryRssEnabled: import("@angular/core").Signal<boolean>;
17294
+ data: import("@angular/core").Signal<Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
17295
+ filters?: import("@sinequa/atomic-angular").CAggregation[];
17296
+ autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
17297
+ tabs?: Record<string, {
17298
+ filters: string[];
17299
+ overviews?: Record<string, {
17300
+ minRelevance: number;
17301
+ }>;
17302
+ }>;
17303
+ sources?: import("@sinequa/atomic-angular").CSources;
17304
+ features?: {
17305
+ [key: string]: boolean | {
17306
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
17307
+ } | undefined;
17308
+ allowChangePassword?: boolean;
17309
+ editablepartition?: boolean;
17310
+ advancedSearch?: boolean;
17311
+ allowChatDrawer?: boolean;
17312
+ filterLinkChildren?: boolean;
17313
+ expandPreview?: boolean;
17314
+ quickFilter?: boolean;
17315
+ showAggregationItemCount?: boolean;
17316
+ assistant?: {
17317
+ usePrefixName?: boolean;
17318
+ };
17319
+ filters?: {
17320
+ homepage?: boolean;
17321
+ };
17322
+ userProfile?: {
17323
+ enabled?: boolean;
17324
+ data?: string[];
17325
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
17326
+ };
17327
+ previewMultiConversion?: boolean;
17328
+ persistFiltersAcrossTabs?: boolean;
17329
+ };
17330
+ allowAdvancedFilters?: boolean;
17331
+ general?: {
17332
+ name?: string;
17333
+ logo?: {
17334
+ alt?: string;
17335
+ light?: {
17336
+ small?: string;
17337
+ large?: string;
17338
+ sidebar?: string;
17339
+ };
17340
+ dark?: {
17341
+ small?: string;
17342
+ large?: string;
17343
+ sidebar?: string;
17344
+ };
17345
+ };
17346
+ features?: {
17347
+ [key: string]: boolean | {
17348
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
17349
+ } | undefined;
17350
+ allowChangePassword?: boolean;
17351
+ editablepartition?: boolean;
17352
+ advancedSearch?: boolean;
17353
+ allowChatDrawer?: boolean;
17354
+ filterLinkChildren?: boolean;
17355
+ expandPreview?: boolean;
17356
+ quickFilter?: boolean;
17357
+ showAggregationItemCount?: boolean;
17358
+ assistant?: {
17359
+ usePrefixName?: boolean;
17360
+ };
17361
+ filters?: {
17362
+ homepage?: boolean;
17363
+ };
17364
+ userProfile?: {
17365
+ enabled?: boolean;
17366
+ data?: string[];
17367
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
17368
+ };
17369
+ previewMultiConversion?: boolean;
17370
+ persistFiltersAcrossTabs?: boolean;
17371
+ };
17372
+ converters?: import("@sinequa/atomic-angular").CConverter[];
17373
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
17374
+ };
17375
+ documentsUploadSettings?: {
17376
+ enabled?: boolean;
17377
+ };
17378
+ }>;
17379
+ customJSONs: import("@angular/core").Signal<{
17380
+ name: string;
17381
+ data: Record<string, unknown>;
17382
+ }[] & import("@sinequa/atomic-angular").SideCJson[]>;
17383
+ apiVersion: import("@angular/core").Signal<string>;
17384
+ workspaceApp: import("@angular/core").Signal<string>;
17385
+ defaultQueryName: import("@angular/core").Signal<string>;
17386
+ auditEnabled?: import("@angular/core").Signal<boolean | undefined> | undefined;
17387
+ dataSets?: import("@angular/core").Signal<string | undefined> | undefined;
17388
+ revision?: import("@angular/core").Signal<number | undefined> | undefined;
17389
+ runnableModels?: import("@angular/core").Signal<string | undefined> | undefined;
17390
+ authorizationLevel?: import("@angular/core").Signal<string | undefined> | undefined;
16881
17391
  columnMap?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCColumn> | undefined> | undefined;
16882
17392
  customizationJson: import("@angular/core").Signal<import("@sinequa/atomic-angular").CJsonMint>;
16883
17393
  sources: import("@angular/core").Signal<import("@sinequa/atomic-angular").CSources>;
@@ -17193,15 +17703,45 @@ export declare class MoreButtonComponent {
17193
17703
  nativeElement: any;
17194
17704
  breakpointObserver: BreakpointObserverService;
17195
17705
  aggregationsService: AggregationsService;
17196
- /** Set when this button sits in a `filters-bar` toolbar: the inner button then is the roving widget. */
17197
- protected readonly toolbar: Toolbar | null;
17198
17706
  /**
17199
- * 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
17200
17708
  * to show behind it, instead of leaving an invisible stop.
17201
17709
  */
17202
17710
  disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17203
- protected readonly triggerClass = "gap-1 truncate font-semibold";
17204
- 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>;
17205
17745
  protected readonly openSheet: () => void | undefined;
17206
17746
  protected readonly openDialog: () => void | undefined;
17207
17747
  count: import("@angular/core").InputSignalWithTransform<number, unknown>;
@@ -17236,6 +17776,23 @@ export declare class MoreButtonComponent {
17236
17776
  * @default undefined — never escalate to Dialog
17237
17777
  */
17238
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;
17239
17796
  /** Unique id wiring the trigger's `popovertarget` to the `<div popover>` `id`. */
17240
17797
  protected readonly popoverId: string;
17241
17798
  protected readonly popoverRef: import("@angular/core").Signal<PopoverDirective | undefined>;
@@ -17275,14 +17832,34 @@ export declare class MoreButtonComponent {
17275
17832
  "required": false;
17276
17833
  "isSignal": true;
17277
17834
  };
17278
- "count": {
17279
- "alias": "count";
17835
+ "appearance": {
17836
+ "alias": "appearance";
17280
17837
  "required": false;
17281
17838
  "isSignal": true;
17282
17839
  };
17283
- "position": {
17284
- "alias": "position";
17285
- "required": false;
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
+ };
17855
+ "count": {
17856
+ "alias": "count";
17857
+ "required": false;
17858
+ "isSignal": true;
17859
+ };
17860
+ "position": {
17861
+ "alias": "position";
17862
+ "required": false;
17286
17863
  "isSignal": true;
17287
17864
  };
17288
17865
  "lockPosition": {
@@ -17384,6 +17961,71 @@ export declare class FiltersBarComponent {
17384
17961
  */
17385
17962
  homepage: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17386
17963
  direction: import("@angular/core").InputSignal<"horizontal" | "vertical">;
17964
+ /**
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.
17967
+ *
17968
+ * @default "default"
17969
+ */
17970
+ appearance: import("@angular/core").InputSignal<FilterAppearance>;
17971
+ /**
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>;
17387
18029
  /**
17388
18030
  * The distance in pixels between the popover and its trigger element.
17389
18031
  *
@@ -17402,6 +18044,8 @@ export declare class FiltersBarComponent {
17402
18044
  */
17403
18045
  onClearBasket: import("@angular/core").OutputEmitterRef<void>;
17404
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">;
17405
18049
  protected readonly moreButtonRef: import("@angular/core").Signal<MoreButtonComponent | undefined>;
17406
18050
  protected readonly overflowManagerRef: import("@angular/core").Signal<OverflowManagerDirective | undefined>;
17407
18051
  protected cdr: ChangeDetectorRef;
@@ -17851,6 +18495,11 @@ export declare class FiltersBarComponent {
17851
18495
  protected hasFilters: import("@angular/core").Signal<string | boolean>;
17852
18496
  protected currentBasket: import("@angular/core").Signal<string | undefined>;
17853
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>;
17854
18503
  /**
17855
18504
  * The full list of authorized filters, NOT capped by `filtersCount`.
17856
18505
  *
@@ -17977,84 +18626,43 @@ export declare class FiltersBarComponent {
17977
18626
  "required": false;
17978
18627
  "isSignal": true;
17979
18628
  };
17980
- "offset": {
17981
- "alias": "offset";
18629
+ "appearance": {
18630
+ "alias": "appearance";
17982
18631
  "required": false;
17983
18632
  "isSignal": true;
17984
18633
  };
17985
- "expandedLevel": {
17986
- "alias": "expandedLevel";
18634
+ "align": {
18635
+ "alias": "align";
17987
18636
  "required": false;
17988
18637
  "isSignal": true;
17989
18638
  };
17990
- }, {
17991
- "onClearFilters": "onClearFilters";
17992
- "onClearBasket": "onClearBasket";
17993
- }, never, never, true, never>;
17994
- }
17995
- export declare class MoreComponent {
17996
- protected readonly SEARCH_THRESHOLD = 6;
17997
- count: import("@angular/core").InputSignal<number>;
17998
- includedFilters: import("@angular/core").InputSignal<string[]>;
17999
- excludedFilters: import("@angular/core").InputSignal<string[]>;
18000
- aggregations: import("@angular/core").InputSignal<Aggregation[] | undefined>;
18001
- homepage: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18002
- /**
18003
- * Whether a section removes itself from the layout when its aggregation
18004
- * resolves to zero items, instead of staying with a dimmed, non-expandable
18005
- * header. Relayed as-is to each `<Aggregation [hideWhenEmpty]>` — a missing
18006
- * aggregation always hides regardless of this input.
18007
- *
18008
- * @default false
18009
- */
18010
- hideWhenEmpty: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18011
- aggregationsService: AggregationsService;
18012
- /** The facet-name search query, cleared whenever the popup is reopened. */
18013
- searchText: import("@angular/core").ModelSignal<string>;
18014
- /**
18015
- * The overflow filters rendered as accordions: the authorized filters beyond the
18016
- * first `count` (which are already shown in the bar).
18017
- *
18018
- * @remarks
18019
- * Pure display wiring — authorization (and the admin `hidden` rule) is handled by
18020
- * {@link AggregationsService.getAuthorizedFilters}; `toSpliced` just drops the
18021
- * filters already shown in the bar.
18022
- */
18023
- filters: import("@angular/core").Signal<{
18024
- field: string;
18025
- column: string;
18026
- name: string;
18027
- }[]>;
18028
- /** {@link filters}, narrowed to those whose name matches {@link searchText}. */
18029
- filteredFilters: import("@angular/core").Signal<{
18030
- field: string;
18031
- column: string;
18032
- name: string;
18033
- }[]>;
18034
- static ɵfac: i0.ɵɵFactoryDeclaration<MoreComponent, never>;
18035
- static ɵcmp: i0.ɵɵComponentDeclaration<MoreComponent, "more, More", never, {
18036
- "count": {
18037
- "alias": "count";
18639
+ "spacing": {
18640
+ "alias": "spacing";
18038
18641
  "required": false;
18039
18642
  "isSignal": true;
18040
18643
  };
18041
- "includedFilters": {
18042
- "alias": "includedFilters";
18644
+ "scheme": {
18645
+ "alias": "scheme";
18043
18646
  "required": false;
18044
18647
  "isSignal": true;
18045
18648
  };
18046
- "excludedFilters": {
18047
- "alias": "excludedFilters";
18649
+ "showClearButtons": {
18650
+ "alias": "showClearButtons";
18048
18651
  "required": false;
18049
18652
  "isSignal": true;
18050
18653
  };
18051
- "aggregations": {
18052
- "alias": "aggregations";
18654
+ "enrichedThreshold": {
18655
+ "alias": "enrichedThreshold";
18053
18656
  "required": false;
18054
18657
  "isSignal": true;
18055
18658
  };
18056
- "homepage": {
18057
- "alias": "homepage";
18659
+ "moreLayout": {
18660
+ "alias": "moreLayout";
18661
+ "required": false;
18662
+ "isSignal": true;
18663
+ };
18664
+ "applyOnSelect": {
18665
+ "alias": "applyOnSelect";
18058
18666
  "required": false;
18059
18667
  "isSignal": true;
18060
18668
  };
@@ -18063,14 +18671,20 @@ export declare class MoreComponent {
18063
18671
  "required": false;
18064
18672
  "isSignal": true;
18065
18673
  };
18066
- "searchText": {
18067
- "alias": "searchText";
18674
+ "offset": {
18675
+ "alias": "offset";
18676
+ "required": false;
18677
+ "isSignal": true;
18678
+ };
18679
+ "expandedLevel": {
18680
+ "alias": "expandedLevel";
18068
18681
  "required": false;
18069
18682
  "isSignal": true;
18070
18683
  };
18071
18684
  }, {
18072
- "searchText": "searchTextChange";
18073
- }, never, never, true, never>;
18685
+ "onClearFilters": "onClearFilters";
18686
+ "onClearBasket": "onClearBasket";
18687
+ }, never, ["[filtersBarStart]"], true, never>;
18074
18688
  }
18075
18689
  /**
18076
18690
  * Injection token that indicates whether custom date ranges are allowed.
@@ -18109,7 +18723,1003 @@ export declare class LabelService {
18109
18723
  _: import("@sinequa/atomic").CCIndex;
18110
18724
  } & Record<string, import("@sinequa/atomic").CCIndex>>;
18111
18725
  lists: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCList>>;
18112
- webServices: import("@angular/core").Signal<Record<string, CCWebService>>;
18726
+ webServices: import("@angular/core").Signal<Record<string, CCWebService>>;
18727
+ queryNames: import("@angular/core").Signal<string>;
18728
+ labels: import("@angular/core").Signal<string>;
18729
+ preview: import("@angular/core").Signal<string>;
18730
+ autocomplete: import("@angular/core").Signal<string>;
18731
+ sponsoredLinks: import("@angular/core").Signal<string>;
18732
+ queryExport: import("@angular/core").Signal<string>;
18733
+ queryRssEnabled: import("@angular/core").Signal<boolean>;
18734
+ data: import("@angular/core").Signal<Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
18735
+ filters?: import("@sinequa/atomic-angular").CAggregation[];
18736
+ autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
18737
+ tabs?: Record<string, {
18738
+ filters: string[];
18739
+ overviews?: Record<string, {
18740
+ minRelevance: number;
18741
+ }>;
18742
+ }>;
18743
+ sources?: import("@sinequa/atomic-angular").CSources;
18744
+ features?: {
18745
+ [key: string]: boolean | {
18746
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
18747
+ } | undefined;
18748
+ allowChangePassword?: boolean;
18749
+ editablepartition?: boolean;
18750
+ advancedSearch?: boolean;
18751
+ allowChatDrawer?: boolean;
18752
+ filterLinkChildren?: boolean;
18753
+ expandPreview?: boolean;
18754
+ quickFilter?: boolean;
18755
+ showAggregationItemCount?: boolean;
18756
+ assistant?: {
18757
+ usePrefixName?: boolean;
18758
+ };
18759
+ filters?: {
18760
+ homepage?: boolean;
18761
+ };
18762
+ userProfile?: {
18763
+ enabled?: boolean;
18764
+ data?: string[];
18765
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
18766
+ };
18767
+ previewMultiConversion?: boolean;
18768
+ persistFiltersAcrossTabs?: boolean;
18769
+ };
18770
+ allowAdvancedFilters?: boolean;
18771
+ general?: {
18772
+ name?: string;
18773
+ logo?: {
18774
+ alt?: string;
18775
+ light?: {
18776
+ small?: string;
18777
+ large?: string;
18778
+ sidebar?: string;
18779
+ };
18780
+ dark?: {
18781
+ small?: string;
18782
+ large?: string;
18783
+ sidebar?: string;
18784
+ };
18785
+ };
18786
+ features?: {
18787
+ [key: string]: boolean | {
18788
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
18789
+ } | undefined;
18790
+ allowChangePassword?: boolean;
18791
+ editablepartition?: boolean;
18792
+ advancedSearch?: boolean;
18793
+ allowChatDrawer?: boolean;
18794
+ filterLinkChildren?: boolean;
18795
+ expandPreview?: boolean;
18796
+ quickFilter?: boolean;
18797
+ showAggregationItemCount?: boolean;
18798
+ assistant?: {
18799
+ usePrefixName?: boolean;
18800
+ };
18801
+ filters?: {
18802
+ homepage?: boolean;
18803
+ };
18804
+ userProfile?: {
18805
+ enabled?: boolean;
18806
+ data?: string[];
18807
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
18808
+ };
18809
+ previewMultiConversion?: boolean;
18810
+ persistFiltersAcrossTabs?: boolean;
18811
+ };
18812
+ converters?: import("@sinequa/atomic-angular").CConverter[];
18813
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
18814
+ };
18815
+ documentsUploadSettings?: {
18816
+ enabled?: boolean;
18817
+ };
18818
+ }>;
18819
+ customJSONs: import("@angular/core").Signal<{
18820
+ name: string;
18821
+ data: Record<string, unknown>;
18822
+ }[] & import("@sinequa/atomic-angular").SideCJson[]>;
18823
+ apiVersion: import("@angular/core").Signal<string>;
18824
+ workspaceApp: import("@angular/core").Signal<string>;
18825
+ defaultQueryName: import("@angular/core").Signal<string>;
18826
+ auditEnabled?: import("@angular/core").Signal<boolean | undefined> | undefined;
18827
+ dataSets?: import("@angular/core").Signal<string | undefined> | undefined;
18828
+ revision?: import("@angular/core").Signal<number | undefined> | undefined;
18829
+ runnableModels?: import("@angular/core").Signal<string | undefined> | undefined;
18830
+ authorizationLevel?: import("@angular/core").Signal<string | undefined> | undefined;
18831
+ columnMap?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCColumn> | undefined> | undefined;
18832
+ customizationJson: import("@angular/core").Signal<import("@sinequa/atomic-angular").CJsonMint>;
18833
+ sources: import("@angular/core").Signal<import("@sinequa/atomic-angular").CSources>;
18834
+ filters: import("@angular/core").Signal<import("@sinequa/atomic-angular").CFilter[]>;
18835
+ general: import("@angular/core").Signal<{
18836
+ name?: string;
18837
+ logo?: {
18838
+ alt?: string;
18839
+ light?: {
18840
+ small?: string;
18841
+ large?: string;
18842
+ sidebar?: string;
18843
+ };
18844
+ dark?: {
18845
+ small?: string;
18846
+ large?: string;
18847
+ sidebar?: string;
18848
+ };
18849
+ };
18850
+ features?: {
18851
+ [key: string]: boolean | {
18852
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
18853
+ } | undefined;
18854
+ allowChangePassword?: boolean;
18855
+ editablepartition?: boolean;
18856
+ advancedSearch?: boolean;
18857
+ allowChatDrawer?: boolean;
18858
+ filterLinkChildren?: boolean;
18859
+ expandPreview?: boolean;
18860
+ quickFilter?: boolean;
18861
+ showAggregationItemCount?: boolean;
18862
+ assistant?: {
18863
+ usePrefixName?: boolean;
18864
+ };
18865
+ filters?: {
18866
+ homepage?: boolean;
18867
+ };
18868
+ userProfile?: {
18869
+ enabled?: boolean;
18870
+ data?: string[];
18871
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
18872
+ };
18873
+ previewMultiConversion?: boolean;
18874
+ persistFiltersAcrossTabs?: boolean;
18875
+ };
18876
+ converters?: import("@sinequa/atomic-angular").CConverter[];
18877
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
18878
+ } | undefined>;
18879
+ assistants: import("@angular/core").Signal<{
18880
+ [x: string]: import("@sinequa/atomic-angular").AssistantDetails;
18881
+ }>;
18882
+ agents: import("@angular/core").Signal<{
18883
+ [x: string]: {
18884
+ defaultAgent: string;
18885
+ };
18886
+ }>;
18887
+ initialize: () => Promise<undefined>;
18888
+ hydrate: (app: import("@sinequa/atomic").CCApp) => void;
18889
+ fail: (error: unknown) => never;
18890
+ initializeWithAppName: (appName: string) => Promise<void>;
18891
+ update: (app: Partial<import("@sinequa/atomic-angular").CCAppState>) => void;
18892
+ getWebServiceByType: (type: CCWebService["webServiceType"]) => CCWebService | undefined;
18893
+ getLabels: () => {
18894
+ private: string;
18895
+ public: string;
18896
+ };
18897
+ getQueryByName: (name: string | undefined) => import("@sinequa/atomic").CCQuery | undefined;
18898
+ getQueryByIndex: (index: number) => import("@sinequa/atomic").CCQuery | undefined;
18899
+ getDefaultQuery: () => import("@sinequa/atomic").CCQuery | undefined;
18900
+ allowEmptySearch: (queryName: string) => boolean;
18901
+ enableFieldedSearch: (queryName: string) => boolean;
18902
+ allowLabels: () => boolean;
18903
+ getColumnAlias: (column: string) => string;
18904
+ getColumn: (columnOrAlias: string) => import("@sinequa/atomic").CCColumn | undefined;
18905
+ isDateColumn: (column: string) => boolean;
18906
+ isTabSearch: (queryName: string) => boolean;
18907
+ getAggregationCount: (queryName: string | undefined, aggregationName: string) => number;
18908
+ getAuthorizedFilters: () => import("@sinequa/atomic").Aggregation[];
18909
+ getAuthorized: (filters: Pick<import("@sinequa/atomic-angular").CFilter, "column" | "name">[]) => import("@sinequa/atomic").Aggregation[];
18910
+ getNamedCustomizationJson: (name: string) => unknown | undefined;
18911
+ getAggregationIcon: (column: string) => string | undefined;
18912
+ getAggregationItemsCustomization: (column: string) => import("@sinequa/atomic-angular").CFilterItem[] | undefined;
18913
+ getAggregationCustomization: (aggColumn: string, aggName?: string) => import("@sinequa/atomic-angular").CFilter | undefined;
18914
+ isAssistantAllowed: (assistantName: string) => boolean;
18915
+ isAgentAllowed: (agentName: string) => boolean;
18916
+ } & import("@ngrx/signals").StateSource<{
18917
+ name: string;
18918
+ description?: string | undefined;
18919
+ versionId: string;
18920
+ queries: Record<string, import("@sinequa/atomic").CCQuery>;
18921
+ rfms: Record<string, import("@sinequa/atomic").CCRFM>;
18922
+ indexes: {
18923
+ _: import("@sinequa/atomic").CCIndex;
18924
+ } & Record<string, import("@sinequa/atomic").CCIndex>;
18925
+ lists: Record<string, import("@sinequa/atomic").CCList>;
18926
+ webServices: Record<string, CCWebService>;
18927
+ queryNames: string;
18928
+ labels: string;
18929
+ preview: string;
18930
+ autocomplete: string;
18931
+ sponsoredLinks: string;
18932
+ queryExport: string;
18933
+ queryRssEnabled: boolean;
18934
+ data: Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
18935
+ filters?: import("@sinequa/atomic-angular").CAggregation[];
18936
+ autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
18937
+ tabs?: Record<string, {
18938
+ filters: string[];
18939
+ overviews?: Record<string, {
18940
+ minRelevance: number;
18941
+ }>;
18942
+ }>;
18943
+ sources?: import("@sinequa/atomic-angular").CSources;
18944
+ features?: {
18945
+ [key: string]: boolean | {
18946
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
18947
+ } | undefined;
18948
+ allowChangePassword?: boolean;
18949
+ editablepartition?: boolean;
18950
+ advancedSearch?: boolean;
18951
+ allowChatDrawer?: boolean;
18952
+ filterLinkChildren?: boolean;
18953
+ expandPreview?: boolean;
18954
+ quickFilter?: boolean;
18955
+ showAggregationItemCount?: boolean;
18956
+ assistant?: {
18957
+ usePrefixName?: boolean;
18958
+ };
18959
+ filters?: {
18960
+ homepage?: boolean;
18961
+ };
18962
+ userProfile?: {
18963
+ enabled?: boolean;
18964
+ data?: string[];
18965
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
18966
+ };
18967
+ previewMultiConversion?: boolean;
18968
+ persistFiltersAcrossTabs?: boolean;
18969
+ };
18970
+ allowAdvancedFilters?: boolean;
18971
+ general?: {
18972
+ name?: string;
18973
+ logo?: {
18974
+ alt?: string;
18975
+ light?: {
18976
+ small?: string;
18977
+ large?: string;
18978
+ sidebar?: string;
18979
+ };
18980
+ dark?: {
18981
+ small?: string;
18982
+ large?: string;
18983
+ sidebar?: string;
18984
+ };
18985
+ };
18986
+ features?: {
18987
+ [key: string]: boolean | {
18988
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
18989
+ } | undefined;
18990
+ allowChangePassword?: boolean;
18991
+ editablepartition?: boolean;
18992
+ advancedSearch?: boolean;
18993
+ allowChatDrawer?: boolean;
18994
+ filterLinkChildren?: boolean;
18995
+ expandPreview?: boolean;
18996
+ quickFilter?: boolean;
18997
+ showAggregationItemCount?: boolean;
18998
+ assistant?: {
18999
+ usePrefixName?: boolean;
19000
+ };
19001
+ filters?: {
19002
+ homepage?: boolean;
19003
+ };
19004
+ userProfile?: {
19005
+ enabled?: boolean;
19006
+ data?: string[];
19007
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
19008
+ };
19009
+ previewMultiConversion?: boolean;
19010
+ persistFiltersAcrossTabs?: boolean;
19011
+ };
19012
+ converters?: import("@sinequa/atomic-angular").CConverter[];
19013
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
19014
+ };
19015
+ documentsUploadSettings?: {
19016
+ enabled?: boolean;
19017
+ };
19018
+ };
19019
+ customJSONs: {
19020
+ name: string;
19021
+ data: Record<string, unknown>;
19022
+ }[] & import("@sinequa/atomic-angular").SideCJson[];
19023
+ apiVersion: string;
19024
+ workspaceApp: string;
19025
+ defaultQueryName: string;
19026
+ auditEnabled?: boolean | undefined;
19027
+ dataSets?: string | undefined;
19028
+ revision?: number | undefined;
19029
+ runnableModels?: string | undefined;
19030
+ authorizationLevel?: string | undefined;
19031
+ columnMap?: Record<string, import("@sinequa/atomic").CCColumn> | undefined;
19032
+ }>;
19033
+ private readonly client;
19034
+ hasAccess: import("@angular/core").WritableSignal<boolean | undefined>;
19035
+ /**
19036
+ * Check user rights to verify if they can access labels handling
19037
+ * @returns if has the rights
19038
+ */
19039
+ canHandleLabels(): Promise<boolean>;
19040
+ /**
19041
+ * Get relevant config info from the labels web service
19042
+ * @returns the LabelsConfig or undefined if no rights
19043
+ */
19044
+ getLabelsConfig(): Observable<LabelsConfig | undefined>;
19045
+ /**
19046
+ * Fetch labels from string
19047
+ * @param prefix the string prefix to filter with
19048
+ * @param publicOnly whether they should be public or not
19049
+ * @param locale optional locale filtering
19050
+ * @returns list of label strings
19051
+ */
19052
+ fetch(prefix: string, publicOnly?: boolean, locale?: string): Observable<string[]>;
19053
+ /**
19054
+ * Add some labels to many documents
19055
+ * @param labelsToAdd list of labels to add
19056
+ * @param ids list of document id to add the label
19057
+ * @param publicOnly whether the operation should be public only
19058
+ * @returns a promise that resolves when the operation is complete
19059
+ */
19060
+ add(labelsToAdd: string[], ids: string[], publicOnly?: boolean): Observable<void>;
19061
+ /**
19062
+ * Remove some labels from many documents
19063
+ * @param labelsToRemove list of labels to remove
19064
+ * @param ids list of document id to add the label
19065
+ * @param publicOnly whether the operation should be public only
19066
+ * @returns a promise that resolves when the operation is complete
19067
+ */
19068
+ remove(labelsToRemove: string[], ids: string[], publicOnly?: boolean): Observable<void>;
19069
+ /**
19070
+ * Name some labels to a new name
19071
+ * @param labelsToRename list of labels to rename
19072
+ * @param newLabel the new label name
19073
+ * @param publicOnly whether the operation should be public only
19074
+ * @returns a promise that resolves when the operation is complete
19075
+ */
19076
+ rename(labelsToRename: string[], newLabel: string, publicOnly?: boolean): Observable<void>;
19077
+ /**
19078
+ * Delete some labels
19079
+ * @param labelsToDelete the labels to delete
19080
+ * @param publicOnly whether the operation should be public only
19081
+ * @returns a promise that resolves when the operation is complete
19082
+ */
19083
+ delete(labelsToDelete: string[], publicOnly?: boolean): Observable<void>;
19084
+ /**
19085
+ * Create some labels for a query
19086
+ * @param labelstoAdd the labels to create
19087
+ * @param query the query object to which the labels will be added
19088
+ * @param publicOnly whether the operation should be public only
19089
+ * @returns a promise that resolves when the operation is complete
19090
+ */
19091
+ bulkAdd(labelstoAdd: string[], query: Query, publicOnly?: boolean): Observable<void>;
19092
+ /**
19093
+ * Delete some labels from a query
19094
+ * @param labelsToRemove the labels to remove
19095
+ * @param query the query object to which the labels will be removed
19096
+ * @param publicOnly whether the operation should be public only
19097
+ * @returns a promise that resolves when the operation is complete
19098
+ */
19099
+ bulkRemove(labelsToRemove: string[], query: Query, publicOnly?: boolean): Observable<void>;
19100
+ static ɵfac: i0.ɵɵFactoryDeclaration<LabelService, never>;
19101
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
19102
+ }
19103
+ /** Result of an edit-labels call: the close event plus the (possibly edited) article. */
19104
+ export interface LabelsEditResult {
19105
+ type: DialogEvent;
19106
+ article: Article;
19107
+ }
19108
+ export declare class LabelsEditDialog {
19109
+ protected readonly call: import("@sinequa/galactik").CallRef<Article, LabelsEditResult>;
19110
+ readonly dialog: import("@angular/core").Signal<DialogComponent | undefined>;
19111
+ labelService: LabelService;
19112
+ readonly article: import("@angular/core").ModelSignal<Article>;
19113
+ readonly labelsConfig: import("@angular/core").WritableSignal<LabelsConfig | undefined>;
19114
+ private readonly destroyRef;
19115
+ constructor();
19116
+ close(event: DialogEvent): void;
19117
+ static ɵfac: i0.ɵɵFactoryDeclaration<LabelsEditDialog, never>;
19118
+ static ɵcmp: i0.ɵɵComponentDeclaration<LabelsEditDialog, "labels-edit-dialog, labelseditdialog, LabelsEditDialog", never, {
19119
+ "article": {
19120
+ "alias": "article";
19121
+ "required": false;
19122
+ "isSignal": true;
19123
+ };
19124
+ }, {
19125
+ "article": "articleChange";
19126
+ }, never, never, true, never>;
19127
+ }
19128
+ /** Imperative entry point: `await EditLabels.call(article)` → resolves with `{ type, article }`. */
19129
+ export declare const EditLabels: import("@sinequa/galactik").Callable<Article, LabelsEditResult>;
19130
+ type Article$1 = Article & {
19131
+ [key: string]: unknown;
19132
+ };
19133
+ export declare class MultiSelectLabelsComponent {
19134
+ injector: Injector;
19135
+ private readonly client;
19136
+ article: import("@angular/core").ModelSignal<Article$1 | undefined>;
19137
+ isPublic: import("@angular/core").InputSignal<boolean>;
19138
+ allowModification: import("@angular/core").InputSignal<boolean>;
19139
+ labelsField: import("@angular/core").InputSignal<string | undefined>;
19140
+ protected labels: import("@angular/core").WritableSignal<string[]>;
19141
+ protected hasError: import("@angular/core").WritableSignal<boolean>;
19142
+ protected readonly identity: (label: string) => string;
19143
+ protected readonly loadSuggestions: (query: string) => Promise<string[]>;
19144
+ constructor();
19145
+ protected onPicked(label: string): void;
19146
+ protected onRemoved(label: string): void;
19147
+ /**
19148
+ * Adds a new label to the current list of labels and updates the associated article.
19149
+ *
19150
+ * This method performs the following steps:
19151
+ * 1. Updates the local labels state by appending the new label.
19152
+ * 2. Persists the new label to the backend, associating it with the current article.
19153
+ * 3. Refreshes the article's label data.
19154
+ *
19155
+ * @param label - The label to be added.
19156
+ * @param isPublic - A boolean indicating whether the label is public or private.
19157
+ * @returns A promise that resolves once the label has been added and the article updated.
19158
+ */
19159
+ addLabel(label: string, isPublic: boolean): Promise<void>;
19160
+ /**
19161
+ * Removes a label from the current list of labels and updates the associated article.
19162
+ *
19163
+ * @param label - The label to be removed.
19164
+ * @param isPublic - A boolean indicating whether the label is public.
19165
+ * @returns A promise that resolves once the label is removed and the article is updated.
19166
+ */
19167
+ removeLabel(label: string, isPublic: boolean): Promise<void>;
19168
+ /**
19169
+ * Updates the article object by assigning the current labels to the specified labels field.
19170
+ *
19171
+ * This method retrieves the article object and the labels field dynamically,
19172
+ * then assigns the current labels to the corresponding field in the article.
19173
+ *
19174
+ * @remarks
19175
+ * Ensure that `this.article`, `this.labelsField`, and `this.labels` return valid values
19176
+ * before invoking this method to avoid runtime errors.
19177
+ *
19178
+ */
19179
+ updateArticleWithLabels(): void;
19180
+ static ɵfac: i0.ɵɵFactoryDeclaration<MultiSelectLabelsComponent, never>;
19181
+ static ɵcmp: i0.ɵɵComponentDeclaration<MultiSelectLabelsComponent, "multiselect-labels, multiselectlabels, MultiSelectLabels", never, {
19182
+ "article": {
19183
+ "alias": "article";
19184
+ "required": false;
19185
+ "isSignal": true;
19186
+ };
19187
+ "isPublic": {
19188
+ "alias": "isPublic";
19189
+ "required": false;
19190
+ "isSignal": true;
19191
+ };
19192
+ "allowModification": {
19193
+ "alias": "allowModification";
19194
+ "required": false;
19195
+ "isSignal": true;
19196
+ };
19197
+ "labelsField": {
19198
+ "alias": "labelsField";
19199
+ "required": false;
19200
+ "isSignal": true;
19201
+ };
19202
+ }, {
19203
+ "article": "articleChange";
19204
+ }, never, never, true, never>;
19205
+ }
19206
+ /**
19207
+ * Inputs handed to whichever component a host app plugs into a `PreviewTabsComponent` assistant
19208
+ * slot ("summary" or "discussion"). `onStreamingChange` stands in for an `@Output` — `NgComponentOutlet`
19209
+ * only binds inputs, so a streaming notification is passed down as a callback the mounted component
19210
+ * calls itself, rather than an Angular event binding.
19211
+ */
19212
+ export type PreviewAssistantInputs = {
19213
+ instanceId: string;
19214
+ query: Query;
19215
+ showAssistant: boolean;
19216
+ onStreamingChange?: (streaming: boolean) => void;
19217
+ };
19218
+ export type PreviewAssistantSlot = {
19219
+ component: Type<unknown>;
19220
+ inputs: PreviewAssistantInputs;
19221
+ };
19222
+ /**
19223
+ * Resolves the component (and its inputs) to mount in a `PreviewTabsComponent` assistant tab, for
19224
+ * a given kind. Returning `undefined` hides that tab entirely — a host app with no assistant feature
19225
+ * provides a function that always returns `undefined`, or omits the "discussion" case.
19226
+ */
19227
+ export declare const PREVIEW_ASSISTANT_COMPONENT: InjectionToken<(kind: "summary" | "discussion") => PreviewAssistantSlot | undefined>;
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[];
19236
+ };
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>;
19291
+ protected readonly userSettingsStore: {
19292
+ bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
19293
+ favoriteSearches: import("@angular/core").Signal<string[]>;
19294
+ recentSearches: import("@angular/core").Signal<SearchItem[]>;
19295
+ savedSearches: import("@angular/core").Signal<SearchItem[]>;
19296
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
19297
+ baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
19298
+ assistants: import("@angular/core").Signal<Record<string, unknown>>;
19299
+ alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
19300
+ collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
19301
+ language?: import("@angular/core").Signal<string | undefined> | undefined;
19302
+ userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
19303
+ agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
19304
+ disabledHighlightCategories: import("@angular/core").Signal<string[]>;
19305
+ isDebugMode: import("@angular/core").Signal<boolean>;
19306
+ isDarkMode: import("@angular/core").Signal<boolean>;
19307
+ updateBookmarks: (bookmarks: import("@sinequa/atomic-angular").UserSettingsState["bookmarks"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
19308
+ bookmark: (article: import("@sinequa/atomic").Article, queryName?: string) => Promise<void>;
19309
+ unbookmark: (id: string) => Promise<void>;
19310
+ isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
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>;
19314
+ deleteRecentSearch: (index: number) => Promise<void>;
19315
+ updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
19316
+ addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
19317
+ deleteSavedSearch: (index: number) => Promise<void>;
19318
+ updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
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>;
19326
+ deleteBasket: (index: number) => Promise<void>;
19327
+ createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
19328
+ updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
19329
+ updateBasket: (basket: import("@sinequa/atomic-angular").Basket, index: number) => Promise<void>;
19330
+ addToBasket: (name: string, ids: string | string[]) => Promise<void>;
19331
+ removeFromBasket: (name: string, ids: string | string[]) => Promise<void>;
19332
+ updateAssistantSettings: (assistantSettings: import("@sinequa/atomic-angular").UserSettingsState["assistants"]) => Promise<void>;
19333
+ updateLanguage: (language: import("@sinequa/atomic-angular").UserSettingsState["language"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
19334
+ updateAssistantCollapsed: (collapseAssistant: import("@sinequa/atomic-angular").UserSettingsState["collapseAssistant"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
19335
+ hydrate: (settings: import("@sinequa/atomic-angular").UserSettingsState) => void;
19336
+ fail: (err: unknown) => void;
19337
+ initialize: () => Promise<void>;
19338
+ reset: () => Promise<void>;
19339
+ deleteAlert: (index: number) => Promise<void>;
19340
+ createAlert: (alert: import("@sinequa/atomic-angular").Alert) => Promise<void>;
19341
+ updateAlert: (alert: import("@sinequa/atomic-angular").Alert, index: number) => Promise<void>;
19342
+ updateAlerts: (alerts: import("@sinequa/atomic-angular").Alert[]) => Promise<void>;
19343
+ setDebugMode: (value: boolean) => Promise<void>;
19344
+ setUserTheme: (userTheme: "dark" | "light" | "system") => Promise<void>;
19345
+ toggleDarkMode: () => Promise<void>;
19346
+ setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
19347
+ } & import("@ngrx/signals").StateSource<{
19348
+ bookmarks: import("@sinequa/atomic-angular").Bookmark[];
19349
+ favoriteSearches: string[];
19350
+ recentSearches: SearchItem[];
19351
+ savedSearches: SearchItem[];
19352
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
19353
+ baskets: import("@sinequa/atomic-angular").Basket[];
19354
+ assistants: Record<string, unknown>;
19355
+ alerts: import("@sinequa/atomic-angular").Alert[];
19356
+ collapseAssistant?: boolean | undefined;
19357
+ language?: string | undefined;
19358
+ userTheme: "dark" | "light" | "system";
19359
+ agents: import("@sinequa/atomic-angular").AgentUserSettings;
19360
+ disabledHighlightCategories: string[];
19361
+ }>;
19362
+ private readonly transloco;
19363
+ private readonly router;
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;
19380
+ constructor();
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";
19392
+ "required": false;
19393
+ "isSignal": true;
19394
+ };
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>;
19410
+ }
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;
19441
+ private readonly transloco;
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>;
19462
+ constructor();
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>;
19528
+ }
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";
19541
+ /**
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.
19552
+ *
19553
+ * ```html
19554
+ * <search-box size="hero" popup="inline" />
19555
+ * ```
19556
+ *
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
+ * ```
19567
+ */
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>>;
18113
19723
  queryNames: import("@angular/core").Signal<string>;
18114
19724
  labels: import("@angular/core").Signal<string>;
18115
19725
  preview: import("@angular/core").Signal<string>;
@@ -18119,7 +19729,7 @@ export declare class LabelService {
18119
19729
  queryRssEnabled: import("@angular/core").Signal<boolean>;
18120
19730
  data: import("@angular/core").Signal<Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
18121
19731
  filters?: import("@sinequa/atomic-angular").CAggregation[];
18122
- autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
19732
+ autocomplete?: Autocomplete;
18123
19733
  tabs?: Record<string, {
18124
19734
  filters: string[];
18125
19735
  overviews?: Record<string, {
@@ -18275,7 +19885,7 @@ export declare class LabelService {
18275
19885
  fail: (error: unknown) => never;
18276
19886
  initializeWithAppName: (appName: string) => Promise<void>;
18277
19887
  update: (app: Partial<import("@sinequa/atomic-angular").CCAppState>) => void;
18278
- getWebServiceByType: (type: CCWebService["webServiceType"]) => CCWebService | undefined;
19888
+ getWebServiceByType: (type: import("@sinequa/atomic").CCWebService["webServiceType"]) => import("@sinequa/atomic").CCWebService | undefined;
18279
19889
  getLabels: () => {
18280
19890
  private: string;
18281
19891
  public: string;
@@ -18309,7 +19919,7 @@ export declare class LabelService {
18309
19919
  _: import("@sinequa/atomic").CCIndex;
18310
19920
  } & Record<string, import("@sinequa/atomic").CCIndex>;
18311
19921
  lists: Record<string, import("@sinequa/atomic").CCList>;
18312
- webServices: Record<string, CCWebService>;
19922
+ webServices: Record<string, import("@sinequa/atomic").CCWebService>;
18313
19923
  queryNames: string;
18314
19924
  labels: string;
18315
19925
  preview: string;
@@ -18319,7 +19929,7 @@ export declare class LabelService {
18319
19929
  queryRssEnabled: boolean;
18320
19930
  data: Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
18321
19931
  filters?: import("@sinequa/atomic-angular").CAggregation[];
18322
- autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
19932
+ autocomplete?: Autocomplete;
18323
19933
  tabs?: Record<string, {
18324
19934
  filters: string[];
18325
19935
  overviews?: Record<string, {
@@ -18416,201 +20026,276 @@ export declare class LabelService {
18416
20026
  authorizationLevel?: string | undefined;
18417
20027
  columnMap?: Record<string, import("@sinequa/atomic").CCColumn> | undefined;
18418
20028
  }>;
18419
- private readonly client;
18420
- hasAccess: import("@angular/core").WritableSignal<boolean | undefined>;
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();
18421
20159
  /**
18422
- * Check user rights to verify if they can access labels handling
18423
- * @returns if has the rights
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.
18424
20162
  */
18425
- canHandleLabels(): Promise<boolean>;
20163
+ protected expandOnFocusEntering(event: FocusEvent): void;
18426
20164
  /**
18427
- * Get relevant config info from the labels web service
18428
- * @returns the LabelsConfig or undefined if no rights
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.
18429
20168
  */
18430
- getLabelsConfig(): Observable<LabelsConfig | undefined>;
20169
+ protected collapseOnFocusLeave(event: FocusEvent): void;
20170
+ /** Collapses the suggestions popup. */
20171
+ collapse(): void;
18431
20172
  /**
18432
- * Fetch labels from string
18433
- * @param prefix the string prefix to filter with
18434
- * @param publicOnly whether they should be public or not
18435
- * @param locale optional locale filtering
18436
- * @returns list of label strings
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`).
18437
20175
  */
18438
- fetch(prefix: string, publicOnly?: boolean, locale?: string): Observable<string[]>;
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;
18439
20181
  /**
18440
- * Add some labels to many documents
18441
- * @param labelsToAdd list of labels to add
18442
- * @param ids list of document id to add the label
18443
- * @param publicOnly whether the operation should be public only
18444
- * @returns a promise that resolves when the operation is complete
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.
18445
20185
  */
18446
- add(labelsToAdd: string[], ids: string[], publicOnly?: boolean): Observable<void>;
20186
+ protected onTabChange(tab: string | undefined): void;
18447
20187
  /**
18448
- * Remove some labels from many documents
18449
- * @param labelsToRemove list of labels to remove
18450
- * @param ids list of document id to add the label
18451
- * @param publicOnly whether the operation should be public only
18452
- * @returns a promise that resolves when the operation is complete
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.
18453
20191
  */
18454
- remove(labelsToRemove: string[], ids: string[], publicOnly?: boolean): Observable<void>;
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;
18455
20195
  /**
18456
- * Name some labels to a new name
18457
- * @param labelsToRename list of labels to rename
18458
- * @param newLabel the new label name
18459
- * @param publicOnly whether the operation should be public only
18460
- * @returns a promise that resolves when the operation is complete
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.
18461
20198
  */
18462
- rename(labelsToRename: string[], newLabel: string, publicOnly?: boolean): Observable<void>;
20199
+ protected openSaved(saved: SearchItem): void;
18463
20200
  /**
18464
- * Delete some labels
18465
- * @param labelsToDelete the labels to delete
18466
- * @param publicOnly whether the operation should be public only
18467
- * @returns a promise that resolves when the operation is complete
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.
18468
20204
  */
18469
- delete(labelsToDelete: string[], publicOnly?: boolean): Observable<void>;
20205
+ private focusSelectedTab;
18470
20206
  /**
18471
- * Create some labels for a query
18472
- * @param labelstoAdd the labels to create
18473
- * @param query the query object to which the labels will be added
18474
- * @param publicOnly whether the operation should be public only
18475
- * @returns a promise that resolves when the operation is complete
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.
18476
20210
  */
18477
- bulkAdd(labelstoAdd: string[], query: Query, publicOnly?: boolean): Observable<void>;
20211
+ protected intoList(event: Event): void;
18478
20212
  /**
18479
- * Delete some labels from a query
18480
- * @param labelsToRemove the labels to remove
18481
- * @param query the query object to which the labels will be removed
18482
- * @param publicOnly whether the operation should be public only
18483
- * @returns a promise that resolves when the operation is complete
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.
18484
20215
  */
18485
- bulkRemove(labelsToRemove: string[], query: Query, publicOnly?: boolean): Observable<void>;
18486
- static ɵfac: i0.ɵɵFactoryDeclaration<LabelService, never>;
18487
- static ɵprov: i0.ɵɵInjectableDeclaration<any>;
18488
- }
18489
- /** Result of an edit-labels call: the close event plus the (possibly edited) article. */
18490
- export interface LabelsEditResult {
18491
- type: DialogEvent;
18492
- article: Article;
18493
- }
18494
- export declare class LabelsEditDialog {
18495
- protected readonly call: import("@sinequa/galactik").CallRef<Article, LabelsEditResult>;
18496
- readonly dialog: import("@angular/core").Signal<DialogComponent | undefined>;
18497
- labelService: LabelService;
18498
- readonly article: import("@angular/core").ModelSignal<Article>;
18499
- readonly labelsConfig: import("@angular/core").WritableSignal<LabelsConfig | undefined>;
18500
- private readonly destroyRef;
18501
- constructor();
18502
- close(event: DialogEvent): void;
18503
- static ɵfac: i0.ɵɵFactoryDeclaration<LabelsEditDialog, never>;
18504
- static ɵcmp: i0.ɵɵComponentDeclaration<LabelsEditDialog, "labels-edit-dialog, labelseditdialog, LabelsEditDialog", never, {
18505
- "article": {
18506
- "alias": "article";
18507
- "required": false;
18508
- "isSignal": true;
18509
- };
18510
- }, {
18511
- "article": "articleChange";
18512
- }, never, never, true, never>;
18513
- }
18514
- /** Imperative entry point: `await EditLabels.call(article)` → resolves with `{ type, article }`. */
18515
- export declare const EditLabels: import("@sinequa/galactik").Callable<Article, LabelsEditResult>;
18516
- type Article$1 = Article & {
18517
- [key: string]: unknown;
18518
- };
18519
- export declare class MultiSelectLabelsComponent {
18520
- injector: Injector;
18521
- private readonly client;
18522
- article: import("@angular/core").ModelSignal<Article$1 | undefined>;
18523
- isPublic: import("@angular/core").InputSignal<boolean>;
18524
- allowModification: import("@angular/core").InputSignal<boolean>;
18525
- labelsField: import("@angular/core").InputSignal<string | undefined>;
18526
- protected labels: import("@angular/core").WritableSignal<string[]>;
18527
- protected hasError: import("@angular/core").WritableSignal<boolean>;
18528
- protected readonly identity: (label: string) => string;
18529
- protected readonly loadSuggestions: (query: string) => Promise<string[]>;
18530
- constructor();
18531
- protected onPicked(label: string): void;
18532
- protected onRemoved(label: string): void;
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;
18533
20225
  /**
18534
- * Adds a new label to the current list of labels and updates the associated article.
18535
- *
18536
- * This method performs the following steps:
18537
- * 1. Updates the local labels state by appending the new label.
18538
- * 2. Persists the new label to the backend, associating it with the current article.
18539
- * 3. Refreshes the article's label data.
18540
- *
18541
- * @param label - The label to be added.
18542
- * @param isPublic - A boolean indicating whether the label is public or private.
18543
- * @returns A promise that resolves once the label has been added and the article updated.
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.
18544
20229
  */
18545
- addLabel(label: string, isPublic: boolean): Promise<void>;
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;
18546
20234
  /**
18547
- * Removes a label from the current list of labels and updates the associated article.
18548
- *
18549
- * @param label - The label to be removed.
18550
- * @param isPublic - A boolean indicating whether the label is public.
18551
- * @returns A promise that resolves once the label is removed and the article is updated.
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.
18552
20237
  */
18553
- removeLabel(label: string, isPublic: boolean): Promise<void>;
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;
18554
20247
  /**
18555
- * Updates the article object by assigning the current labels to the specified labels field.
18556
- *
18557
- * This method retrieves the article object and the labels field dynamically,
18558
- * then assigns the current labels to the corresponding field in the article.
18559
- *
18560
- * @remarks
18561
- * Ensure that `this.article`, `this.labelsField`, and `this.labels` return valid values
18562
- * before invoking this method to avoid runtime errors.
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.
18563
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.
18564
20252
  */
18565
- updateArticleWithLabels(): void;
18566
- static ɵfac: i0.ɵɵFactoryDeclaration<MultiSelectLabelsComponent, never>;
18567
- static ɵcmp: i0.ɵɵComponentDeclaration<MultiSelectLabelsComponent, "multiselect-labels, multiselectlabels, MultiSelectLabels", never, {
18568
- "article": {
18569
- "alias": "article";
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";
18570
20258
  "required": false;
18571
20259
  "isSignal": true;
18572
20260
  };
18573
- "isPublic": {
18574
- "alias": "isPublic";
20261
+ "showSave": {
20262
+ "alias": "showSave";
18575
20263
  "required": false;
18576
20264
  "isSignal": true;
18577
20265
  };
18578
- "allowModification": {
18579
- "alias": "allowModification";
20266
+ "searchPath": {
20267
+ "alias": "searchPath";
18580
20268
  "required": false;
18581
20269
  "isSignal": true;
18582
20270
  };
18583
- "labelsField": {
18584
- "alias": "labelsField";
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";
18585
20288
  "required": false;
18586
20289
  "isSignal": true;
18587
20290
  };
18588
20291
  }, {
18589
- "article": "articleChange";
18590
- }, never, never, true, never>;
20292
+ "searched": "searched";
20293
+ "debounced": "debounced";
20294
+ "saved": "saved";
20295
+ "expandedChange": "expandedChange";
20296
+ "searchInputText": "searchInputTextChange";
20297
+ }, never, ["[slot='trailing']"], true, never>;
18591
20298
  }
18592
- /**
18593
- * Inputs handed to whichever component a host app plugs into a `PreviewTabsComponent` assistant
18594
- * slot ("summary" or "discussion"). `onStreamingChange` stands in for an `@Output` — `NgComponentOutlet`
18595
- * only binds inputs, so a streaming notification is passed down as a callback the mounted component
18596
- * calls itself, rather than an Angular event binding.
18597
- */
18598
- export type PreviewAssistantInputs = {
18599
- instanceId: string;
18600
- query: Query;
18601
- showAssistant: boolean;
18602
- onStreamingChange?: (streaming: boolean) => void;
18603
- };
18604
- export type PreviewAssistantSlot = {
18605
- component: Type<unknown>;
18606
- inputs: PreviewAssistantInputs;
18607
- };
18608
- /**
18609
- * Resolves the component (and its inputs) to mount in a `PreviewTabsComponent` assistant tab, for
18610
- * a given kind. Returning `undefined` hides that tab entirely — a host app with no assistant feature
18611
- * provides a function that always returns `undefined`, or omits the "discussion" case.
18612
- */
18613
- export declare const PREVIEW_ASSISTANT_COMPONENT: InjectionToken<(kind: "summary" | "discussion") => PreviewAssistantSlot | undefined>;
18614
20299
  export declare const RECENT_SEARCHES_OPTIONS: {
18615
20300
  itemsPerPage: number;
18616
20301
  showLoadMore: boolean;
@@ -18623,8 +20308,10 @@ export declare class RecentSearchesComponent {
18623
20308
  protected config: import("@sinequa/atomic-angular").ListPanelConfig;
18624
20309
  protected readonly userSettingsStore: {
18625
20310
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20311
+ favoriteSearches: import("@angular/core").Signal<string[]>;
18626
20312
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
18627
20313
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
20314
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
18628
20315
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
18629
20316
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
18630
20317
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -18640,12 +20327,20 @@ export declare class RecentSearchesComponent {
18640
20327
  unbookmark: (id: string) => Promise<void>;
18641
20328
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
18642
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>;
18643
20332
  deleteRecentSearch: (index: number) => Promise<void>;
18644
20333
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
18645
20334
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
18646
20335
  deleteSavedSearch: (index: number) => Promise<void>;
18647
20336
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
18648
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>;
18649
20344
  deleteBasket: (index: number) => Promise<void>;
18650
20345
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
18651
20346
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -18669,8 +20364,10 @@ export declare class RecentSearchesComponent {
18669
20364
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
18670
20365
  } & import("@ngrx/signals").StateSource<{
18671
20366
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20367
+ favoriteSearches: string[];
18672
20368
  recentSearches: SearchItem[];
18673
20369
  savedSearches: SearchItem[];
20370
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
18674
20371
  baskets: import("@sinequa/atomic-angular").Basket[];
18675
20372
  assistants: Record<string, unknown>;
18676
20373
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -18736,8 +20433,10 @@ export declare const SavedSearch: import("@sinequa/galactik").Callable<string, D
18736
20433
  export declare class SavedSearchPopover {
18737
20434
  protected readonly userSettingsStore: {
18738
20435
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20436
+ favoriteSearches: import("@angular/core").Signal<string[]>;
18739
20437
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
18740
20438
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
20439
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
18741
20440
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
18742
20441
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
18743
20442
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -18753,12 +20452,20 @@ export declare class SavedSearchPopover {
18753
20452
  unbookmark: (id: string) => Promise<void>;
18754
20453
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
18755
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>;
18756
20457
  deleteRecentSearch: (index: number) => Promise<void>;
18757
20458
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
18758
20459
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
18759
20460
  deleteSavedSearch: (index: number) => Promise<void>;
18760
20461
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
18761
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>;
18762
20469
  deleteBasket: (index: number) => Promise<void>;
18763
20470
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
18764
20471
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -18782,8 +20489,10 @@ export declare class SavedSearchPopover {
18782
20489
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
18783
20490
  } & import("@ngrx/signals").StateSource<{
18784
20491
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20492
+ favoriteSearches: string[];
18785
20493
  recentSearches: SearchItem[];
18786
20494
  savedSearches: SearchItem[];
20495
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
18787
20496
  baskets: import("@sinequa/atomic-angular").Basket[];
18788
20497
  assistants: Record<string, unknown>;
18789
20498
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -18820,8 +20529,10 @@ export declare class SavedSearchesComponent {
18820
20529
  protected config: import("@sinequa/atomic-angular").ListPanelConfig;
18821
20530
  protected readonly userSettingsStore: {
18822
20531
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20532
+ favoriteSearches: import("@angular/core").Signal<string[]>;
18823
20533
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
18824
20534
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
20535
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
18825
20536
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
18826
20537
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
18827
20538
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
@@ -18837,12 +20548,20 @@ export declare class SavedSearchesComponent {
18837
20548
  unbookmark: (id: string) => Promise<void>;
18838
20549
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
18839
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>;
18840
20553
  deleteRecentSearch: (index: number) => Promise<void>;
18841
20554
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
18842
20555
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
18843
20556
  deleteSavedSearch: (index: number) => Promise<void>;
18844
20557
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
18845
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>;
18846
20565
  deleteBasket: (index: number) => Promise<void>;
18847
20566
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
18848
20567
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -18866,8 +20585,10 @@ export declare class SavedSearchesComponent {
18866
20585
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
18867
20586
  } & import("@ngrx/signals").StateSource<{
18868
20587
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20588
+ favoriteSearches: string[];
18869
20589
  recentSearches: SearchItem[];
18870
20590
  savedSearches: SearchItem[];
20591
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
18871
20592
  baskets: import("@sinequa/atomic-angular").Basket[];
18872
20593
  assistants: Record<string, unknown>;
18873
20594
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -18899,7 +20620,7 @@ export declare class SavedSearchesComponent {
18899
20620
  };
18900
20621
  }, {}, never, never, true, never>;
18901
20622
  }
18902
- export type SettingsPanelId = "account" | "appearance" | "shortcuts";
20623
+ export type SettingsPanelId = "account" | "appearance" | "alerts" | "shortcuts";
18903
20624
  /** Payload of `Settings.call()`: the panel to show first (default `account`). */
18904
20625
  export interface SettingsDialogProps {
18905
20626
  panel?: SettingsPanelId;
@@ -19062,6 +20783,27 @@ export declare class SettingsAppearancePanelComponent {
19062
20783
  static ɵfac: i0.ɵɵFactoryDeclaration<SettingsAppearancePanelComponent, never>;
19063
20784
  static ɵcmp: i0.ɵɵComponentDeclaration<SettingsAppearancePanelComponent, "settings-appearance-panel", never, {}, {}, never, never, true, never>;
19064
20785
  }
20786
+ /**
20787
+ * The user's alerts: the list, and — once one is picked, or "Create" is pressed — the form in the same panel.
20788
+ *
20789
+ * The form is not a second dialog on top of the settings: the panel swaps from the list to the form and back,
20790
+ * and a failed save is shown in the form itself, which a toast could not do behind a modal dialog.
20791
+ */
20792
+ export declare class SettingsAlertsPanelComponent {
20793
+ /** The user ran an alert's search: the settings have nothing more to show, the page behind has the results. */
20794
+ readonly closeRequested: import("@angular/core").OutputEmitterRef<void>;
20795
+ /** The form being shown — `index` is the alert to edit, `undefined` to create one — or nothing: the list. */
20796
+ protected readonly form: import("@angular/core").WritableSignal<{
20797
+ index: number | undefined;
20798
+ } | undefined>;
20799
+ protected edit(index: number): void;
20800
+ protected create(): void;
20801
+ protected back(): void;
20802
+ static ɵfac: i0.ɵɵFactoryDeclaration<SettingsAlertsPanelComponent, never>;
20803
+ static ɵcmp: i0.ɵɵComponentDeclaration<SettingsAlertsPanelComponent, "settings-alerts-panel", never, {}, {
20804
+ "closeRequested": "closeRequested";
20805
+ }, never, never, true, never>;
20806
+ }
19065
20807
  /** The keyboard shortcuts currently registered, as documented by the registry itself. */
19066
20808
  export declare class SettingsShortcutsPanelComponent {
19067
20809
  static ɵfac: i0.ɵɵFactoryDeclaration<SettingsShortcutsPanelComponent, never>;
@@ -20639,4 +22381,4 @@ export type AppFeatures = {
20639
22381
  * @deprecated use `general` configuration json instead from the app store
20640
22382
  */
20641
22383
  export declare const APP_FEATURES: InjectionToken<AppFeatures>;
20642
- export type { ConverterOption, DateRange, DateRangeDialogProps, Shortcut, ShortcutDefinition };
22384
+ export type { ConverterOption, DateRange, DateRangeDialogProps, FilterScheme, Shortcut, ShortcutDefinition };