@sinequa/atomic-angular 2.9.0 → 2.11.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>;
@@ -877,7 +891,7 @@ export declare class DocumentLocatorComponent implements OnDestroy {
877
891
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
878
892
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
879
893
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
880
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
894
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
881
895
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
882
896
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
883
897
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -1060,11 +1074,11 @@ export declare class MetadataComponent {
1060
1074
  event: Event;
1061
1075
  }>;
1062
1076
  class: import("@angular/core").InputSignal<string | undefined>;
1063
- 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>;
1077
+ variant: import("@angular/core").InputSignal<"secondary" | "primary" | null | undefined>;
1078
+ size: import("@angular/core").InputSignal<"md" | "small" | "medium" | "sm" | "xsmall" | "xs" | 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
- article: import("@angular/core").InputSignal<Partial<Article> | (string & Record<never, never>)>;
1081
+ article: import("@angular/core").InputSignal<(string & Record<never, never>) | Partial<Article>>;
1068
1082
  limit: import("@angular/core").InputSignalWithTransform<number | undefined, string | number | undefined>;
1069
1083
  items: import("@angular/core").Signal<string[]>;
1070
1084
  handleClick(event: Event, item: LegacyFilter): void;
@@ -1138,7 +1152,7 @@ export declare class MissingTermsComponent {
1138
1152
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
1139
1153
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
1140
1154
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
1141
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
1155
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
1142
1156
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
1143
1157
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
1144
1158
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -1561,7 +1575,7 @@ export declare class MultiSelectionToolbarComponent {
1561
1575
  columnMap?: Record<string, import("@sinequa/atomic").CCColumn> | undefined;
1562
1576
  }>;
1563
1577
  readonly selection: {
1564
- article?: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic").Article> | undefined;
1578
+ article?: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic").Article> | import("@angular/core").Signal<undefined> | undefined;
1565
1579
  id?: import("@angular/core").Signal<string | undefined> | undefined;
1566
1580
  queryText?: import("@angular/core").Signal<string | undefined> | undefined;
1567
1581
  queryName?: import("@angular/core").Signal<string | undefined> | undefined;
@@ -2032,6 +2046,21 @@ export declare class NavbarTabsComponent {
2032
2046
  * than "tabs" in that context (e.g. "result categories").
2033
2047
  */
2034
2048
  ariaLabel: import("@angular/core").InputSignal<string | undefined>;
2049
+ /**
2050
+ * Look of the tab strip, from galactik's `TabList`.
2051
+ *
2052
+ * - `primary` (default): the tabs sit in a bordered pill strip, the selected one filled;
2053
+ * - `secondary`: a flat row on a white background, the selected tab underlined;
2054
+ * - `inner`: the same underline on a transparent background — for a strip that lives inside a
2055
+ * page rather than on a bar of its own, such as the result categories under a search field.
2056
+ *
2057
+ * The two underline variants also get the larger tab of the design (44px, 14px semibold).
2058
+ *
2059
+ * @default "primary"
2060
+ */
2061
+ variant: import("@angular/core").InputSignal<"secondary" | "primary" | "inner">;
2062
+ /** The pill strip is the only variant whose tabs keep galactik's own, smaller size. */
2063
+ protected readonly isPill: import("@angular/core").Signal<boolean>;
2035
2064
  showCount: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
2036
2065
  /**
2037
2066
  * When enabled (default), tab labels are never clipped: tabs that do not fit
@@ -2104,6 +2133,11 @@ export declare class NavbarTabsComponent {
2104
2133
  "required": false;
2105
2134
  "isSignal": true;
2106
2135
  };
2136
+ "variant": {
2137
+ "alias": "variant";
2138
+ "required": false;
2139
+ "isSignal": true;
2140
+ };
2107
2141
  "showCount": {
2108
2142
  "alias": "showCount";
2109
2143
  "required": false;
@@ -2933,7 +2967,7 @@ export declare const PrincipalStore: import("@angular/core").Type<{
2933
2967
  param9: import("@angular/core").Signal<string>;
2934
2968
  param10: import("@angular/core").Signal<string>;
2935
2969
  userOverrideActive: import("@angular/core").Signal<boolean>;
2936
- state: import("@angular/core").Signal<"error" | "initial" | "loading" | "loaded">;
2970
+ state: import("@angular/core").Signal<"error" | "loading" | "loaded" | "initial">;
2937
2971
  allowUserOverride: import("@angular/core").Signal<boolean>;
2938
2972
  isOverridingUser: import("@angular/core").Signal<boolean>;
2939
2973
  initials: import("@angular/core").Signal<string>;
@@ -3015,7 +3049,7 @@ export declare const QueryParamsStore: import("@angular/core").Type<{
3015
3049
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
3016
3050
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
3017
3051
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
3018
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
3052
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
3019
3053
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
3020
3054
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
3021
3055
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -3160,7 +3194,7 @@ export type SelectionState = {
3160
3194
  * - `clear()`: Clears the selection state, setting `article`, `id`, and `queryText` to `undefined`.
3161
3195
  */
3162
3196
  export declare const SelectionStore: import("@angular/core").Type<{
3163
- article?: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<Article> | undefined;
3197
+ article?: import("@ngrx/signals").DeepSignal<Article> | import("@angular/core").Signal<undefined> | undefined;
3164
3198
  id?: import("@angular/core").Signal<string | undefined> | undefined;
3165
3199
  queryText?: import("@angular/core").Signal<string | undefined> | undefined;
3166
3200
  queryName?: import("@angular/core").Signal<string | undefined> | undefined;
@@ -3322,15 +3356,17 @@ export declare class UserSettingsPersistence {
3322
3356
  export declare function injectUserSettingsPatch(): <T>(userSettings: Partial<T>, audit?: AuditEvents) => Promise<void>;
3323
3357
  export declare const UserSettingsStore: import("@angular/core").Type<{
3324
3358
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
3359
+ favoriteSearches: import("@angular/core").Signal<string[]>;
3325
3360
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
3326
3361
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
3362
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
3327
3363
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
3328
3364
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
3329
3365
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
3330
3366
  collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
3331
3367
  language?: import("@angular/core").Signal<string | undefined> | undefined;
3332
3368
  userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
3333
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
3369
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
3334
3370
  disabledHighlightCategories: import("@angular/core").Signal<string[]>;
3335
3371
  isDebugMode: import("@angular/core").Signal<boolean>;
3336
3372
  isDarkMode: import("@angular/core").Signal<boolean>;
@@ -3339,12 +3375,20 @@ export declare const UserSettingsStore: import("@angular/core").Type<{
3339
3375
  unbookmark: (id: string) => Promise<void>;
3340
3376
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
3341
3377
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
3378
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
3379
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
3342
3380
  deleteRecentSearch: (index: number) => Promise<void>;
3343
3381
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
3344
3382
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
3345
3383
  deleteSavedSearch: (index: number) => Promise<void>;
3346
3384
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
3347
3385
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
3386
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
3387
+ updateQuickFilter: (id: string, changes: {
3388
+ name?: string;
3389
+ filters?: import("@sinequa/atomic").LegacyFilter[];
3390
+ }) => Promise<void>;
3391
+ removeQuickFilter: (id: string) => Promise<void>;
3348
3392
  deleteBasket: (index: number) => Promise<void>;
3349
3393
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
3350
3394
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -3368,8 +3412,10 @@ export declare const UserSettingsStore: import("@angular/core").Type<{
3368
3412
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
3369
3413
  } & import("@ngrx/signals").StateSource<{
3370
3414
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
3415
+ favoriteSearches: string[];
3371
3416
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
3372
3417
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
3418
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
3373
3419
  baskets: import("@sinequa/atomic-angular").Basket[];
3374
3420
  assistants: Record<string, unknown>;
3375
3421
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -3429,7 +3475,58 @@ export declare function withBookmarkFeatures(): import("@ngrx/signals").SignalSt
3429
3475
  toggleBookmark: (article: Article) => Promise<void>;
3430
3476
  };
3431
3477
  }>;
3432
- export declare function withRecentSearchesFeatures(): import("@ngrx/signals").SignalStoreFeature<import("@ngrx/signals").EmptyFeatureResult, {
3478
+ /**
3479
+ * What identifies a recent search across its re-runs.
3480
+ *
3481
+ * `addCurrentSearch` de-duplicates on the query text and rewrites the `url` of the existing entry
3482
+ * every time the same text is searched again (other filters, other tab), so the `url` is not stable.
3483
+ * The text is, which is why favorites are keyed by it.
3484
+ */
3485
+ export declare function searchItemKey(search: Pick<SearchItem, "label" | "display">): string;
3486
+ /**
3487
+ * User-settings slice holding which recent searches the user marked as favorite.
3488
+ *
3489
+ * Only the keys are stored (see {@link searchItemKey}): a favorite is a flag on a recent search, so
3490
+ * un-favoriting never touches `recentSearches`, while deleting a recent search drops its favorite
3491
+ * (`with-recent-searches.ts`).
3492
+ */
3493
+ export declare function withFavoriteSearchesFeatures(): import("@ngrx/signals").SignalStoreFeature<import("@ngrx/signals").EmptyFeatureResult, {
3494
+ state: {
3495
+ favoriteSearches: NonNullable<UserSettingsState["favoriteSearches"]>;
3496
+ };
3497
+ props: {};
3498
+ methods: {
3499
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
3500
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
3501
+ };
3502
+ }>;
3503
+ /**
3504
+ * User-settings slice holding the user's quick filters: named sets of filters to apply again.
3505
+ *
3506
+ * The store only keeps and persists them. Applying one is the caller's job — it replaces the active
3507
+ * filters, so `queryParamsStore.patch({ filters: quickFilter.filters })` does it.
3508
+ */
3509
+ export declare function withQuickFiltersFeatures(): import("@ngrx/signals").SignalStoreFeature<import("@ngrx/signals").EmptyFeatureResult, {
3510
+ state: {
3511
+ quickFilters: NonNullable<UserSettingsState["quickFilters"]>;
3512
+ };
3513
+ props: {};
3514
+ methods: {
3515
+ addQuickFilter: (name: string, filters: LegacyFilter[]) => Promise<QuickFilter | undefined>;
3516
+ updateQuickFilter: (id: string, changes: {
3517
+ name?: string;
3518
+ filters?: LegacyFilter[];
3519
+ }) => Promise<void>;
3520
+ removeQuickFilter: (id: string) => Promise<void>;
3521
+ };
3522
+ }>;
3523
+ export declare function withRecentSearchesFeatures(): import("@ngrx/signals").SignalStoreFeature<{
3524
+ state: {
3525
+ favoriteSearches: string[];
3526
+ };
3527
+ props: {};
3528
+ methods: {};
3529
+ }, {
3433
3530
  state: {
3434
3531
  recentSearches: UserSettingsState["recentSearches"];
3435
3532
  };
@@ -3456,6 +3553,8 @@ export declare function withUserSettingsFeatures(): import("@ngrx/signals").Sign
3456
3553
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
3457
3554
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
3458
3555
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
3556
+ favoriteSearches?: string[] | undefined;
3557
+ quickFilters?: import("@sinequa/atomic-angular").QuickFilter[] | undefined;
3459
3558
  baskets: import("@sinequa/atomic-angular").Basket[];
3460
3559
  alerts: import("@sinequa/atomic-angular").Alert[];
3461
3560
  assistants: Record<string, unknown>;
@@ -4501,7 +4600,7 @@ export declare class AggregationsService {
4501
4600
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
4502
4601
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
4503
4602
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
4504
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
4603
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
4505
4604
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
4506
4605
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
4507
4606
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -4740,15 +4839,17 @@ export type ComponentMapping = {
4740
4839
  export declare class ApplicationService {
4741
4840
  userSettingsStore: {
4742
4841
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
4842
+ favoriteSearches: import("@angular/core").Signal<string[]>;
4743
4843
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
4744
4844
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
4845
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
4745
4846
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
4746
4847
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
4747
4848
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
4748
4849
  collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
4749
4850
  language?: import("@angular/core").Signal<string | undefined> | undefined;
4750
4851
  userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
4751
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
4852
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
4752
4853
  disabledHighlightCategories: import("@angular/core").Signal<string[]>;
4753
4854
  isDebugMode: import("@angular/core").Signal<boolean>;
4754
4855
  isDarkMode: import("@angular/core").Signal<boolean>;
@@ -4757,12 +4858,20 @@ export declare class ApplicationService {
4757
4858
  unbookmark: (id: string) => Promise<void>;
4758
4859
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
4759
4860
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
4861
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
4862
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
4760
4863
  deleteRecentSearch: (index: number) => Promise<void>;
4761
4864
  updateRecentSearches: (recentSearches: UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
4762
4865
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
4763
4866
  deleteSavedSearch: (index: number) => Promise<void>;
4764
4867
  updateSavedSearches: (savedSearches: UserSettingsState["savedSearches"]) => Promise<void>;
4765
4868
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
4869
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
4870
+ updateQuickFilter: (id: string, changes: {
4871
+ name?: string;
4872
+ filters?: import("@sinequa/atomic").LegacyFilter[];
4873
+ }) => Promise<void>;
4874
+ removeQuickFilter: (id: string) => Promise<void>;
4766
4875
  deleteBasket: (index: number) => Promise<void>;
4767
4876
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
4768
4877
  updateBaskets: (baskets: UserSettingsState["baskets"]) => Promise<void>;
@@ -4786,8 +4895,10 @@ export declare class ApplicationService {
4786
4895
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
4787
4896
  } & import("@ngrx/signals").StateSource<{
4788
4897
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
4898
+ favoriteSearches: string[];
4789
4899
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
4790
4900
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
4901
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
4791
4902
  baskets: import("@sinequa/atomic-angular").Basket[];
4792
4903
  assistants: Record<string, unknown>;
4793
4904
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -4824,7 +4935,7 @@ export declare class ApplicationService {
4824
4935
  param9: import("@angular/core").Signal<string>;
4825
4936
  param10: import("@angular/core").Signal<string>;
4826
4937
  userOverrideActive: import("@angular/core").Signal<boolean>;
4827
- state: import("@angular/core").Signal<"error" | "initial" | "loading" | "loaded">;
4938
+ state: import("@angular/core").Signal<"error" | "loading" | "loaded" | "initial">;
4828
4939
  allowUserOverride: import("@angular/core").Signal<boolean>;
4829
4940
  isOverridingUser: import("@angular/core").Signal<boolean>;
4830
4941
  initials: import("@angular/core").Signal<string>;
@@ -5205,7 +5316,7 @@ export declare class ApplicationService {
5205
5316
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
5206
5317
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
5207
5318
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
5208
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
5319
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
5209
5320
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
5210
5321
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
5211
5322
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -5774,15 +5885,17 @@ export declare class AutocompleteService {
5774
5885
  private readonly client;
5775
5886
  userSettingsStore: {
5776
5887
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
5888
+ favoriteSearches: import("@angular/core").Signal<string[]>;
5777
5889
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
5778
5890
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
5891
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
5779
5892
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
5780
5893
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
5781
5894
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
5782
5895
  collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
5783
5896
  language?: import("@angular/core").Signal<string | undefined> | undefined;
5784
5897
  userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
5785
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
5898
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
5786
5899
  disabledHighlightCategories: import("@angular/core").Signal<string[]>;
5787
5900
  isDebugMode: import("@angular/core").Signal<boolean>;
5788
5901
  isDarkMode: import("@angular/core").Signal<boolean>;
@@ -5791,12 +5904,20 @@ export declare class AutocompleteService {
5791
5904
  unbookmark: (id: string) => Promise<void>;
5792
5905
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
5793
5906
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
5907
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
5908
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
5794
5909
  deleteRecentSearch: (index: number) => Promise<void>;
5795
5910
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
5796
5911
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
5797
5912
  deleteSavedSearch: (index: number) => Promise<void>;
5798
5913
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
5799
5914
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
5915
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
5916
+ updateQuickFilter: (id: string, changes: {
5917
+ name?: string;
5918
+ filters?: import("@sinequa/atomic").LegacyFilter[];
5919
+ }) => Promise<void>;
5920
+ removeQuickFilter: (id: string) => Promise<void>;
5800
5921
  deleteBasket: (index: number) => Promise<void>;
5801
5922
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
5802
5923
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -5820,8 +5941,10 @@ export declare class AutocompleteService {
5820
5941
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
5821
5942
  } & import("@ngrx/signals").StateSource<{
5822
5943
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
5944
+ favoriteSearches: string[];
5823
5945
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
5824
5946
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
5947
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
5825
5948
  baskets: import("@sinequa/atomic-angular").Basket[];
5826
5949
  assistants: Record<string, unknown>;
5827
5950
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -6535,9 +6658,9 @@ export declare function getCurrentQueryName(): string | undefined;
6535
6658
  * Les valeurs sont exprimées en tokens Galactik, jamais en dur (cf. `DESIGN_SYSTEM.md`).
6536
6659
  * Elles reproduisent volontairement le rendu de l'ancien `Card` :
6537
6660
  * `p-4` → `--spacing-md` (16px) · `rounded-xl` → `--radius-md` (12px)
6538
- * `gap-4` (CardContent) → `--spacing-md` (16px) · `shadow-sm` → `--shadow-1`
6661
+ * `gap-4` (CardContent) → `--spacing-md` (16px) · `shadow-sm` → `--shadow-2`, avec un liseré `--layer-page-edge`
6539
6662
  */
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)";
6663
+ 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
6664
  /**
6542
6665
  * Same layout, no card: no background, no padding, no shadow.
6543
6666
  *
@@ -6722,7 +6845,7 @@ export declare class PreviewService {
6722
6845
  extracts: Map<string, Extract[]>;
6723
6846
  }>;
6724
6847
  protected readonly selectionStore: {
6725
- article?: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<Article> | undefined;
6848
+ article?: import("@ngrx/signals").DeepSignal<Article> | import("@angular/core").Signal<undefined> | undefined;
6726
6849
  id?: import("@angular/core").Signal<string | undefined> | undefined;
6727
6850
  queryText?: import("@angular/core").Signal<string | undefined> | undefined;
6728
6851
  queryName?: import("@angular/core").Signal<string | undefined> | undefined;
@@ -6771,7 +6894,7 @@ export declare class PreviewService {
6771
6894
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
6772
6895
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
6773
6896
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
6774
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
6897
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
6775
6898
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
6776
6899
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
6777
6900
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -7359,15 +7482,17 @@ export declare class PrincipalService {
7359
7482
  export declare class SavedSearchesService {
7360
7483
  protected readonly userSettingsStore: {
7361
7484
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
7485
+ favoriteSearches: import("@angular/core").Signal<string[]>;
7362
7486
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
7363
7487
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
7488
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
7364
7489
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
7365
7490
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
7366
7491
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
7367
7492
  collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
7368
7493
  language?: import("@angular/core").Signal<string | undefined> | undefined;
7369
7494
  userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
7370
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
7495
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
7371
7496
  disabledHighlightCategories: import("@angular/core").Signal<string[]>;
7372
7497
  isDebugMode: import("@angular/core").Signal<boolean>;
7373
7498
  isDarkMode: import("@angular/core").Signal<boolean>;
@@ -7376,12 +7501,20 @@ export declare class SavedSearchesService {
7376
7501
  unbookmark: (id: string) => Promise<void>;
7377
7502
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
7378
7503
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
7504
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
7505
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
7379
7506
  deleteRecentSearch: (index: number) => Promise<void>;
7380
7507
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
7381
7508
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
7382
7509
  deleteSavedSearch: (index: number) => Promise<void>;
7383
7510
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
7384
7511
  getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
7512
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
7513
+ updateQuickFilter: (id: string, changes: {
7514
+ name?: string;
7515
+ filters?: import("@sinequa/atomic").LegacyFilter[];
7516
+ }) => Promise<void>;
7517
+ removeQuickFilter: (id: string) => Promise<void>;
7385
7518
  deleteBasket: (index: number) => Promise<void>;
7386
7519
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
7387
7520
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -7405,8 +7538,10 @@ export declare class SavedSearchesService {
7405
7538
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
7406
7539
  } & import("@ngrx/signals").StateSource<{
7407
7540
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
7541
+ favoriteSearches: string[];
7408
7542
  recentSearches: SearchItem[];
7409
7543
  savedSearches: SearchItem[];
7544
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
7410
7545
  baskets: import("@sinequa/atomic-angular").Basket[];
7411
7546
  assistants: Record<string, unknown>;
7412
7547
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -7443,7 +7578,7 @@ export declare class SavedSearchesService {
7443
7578
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
7444
7579
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
7445
7580
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
7446
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
7581
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
7447
7582
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
7448
7583
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
7449
7584
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -7628,7 +7763,7 @@ export declare class SearchService {
7628
7763
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
7629
7764
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
7630
7765
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
7631
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
7766
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
7632
7767
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
7633
7768
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
7634
7769
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -7713,15 +7848,17 @@ export declare class SearchService {
7713
7848
  }>;
7714
7849
  protected readonly userSettingsStore: {
7715
7850
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
7851
+ favoriteSearches: import("@angular/core").Signal<string[]>;
7716
7852
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
7717
7853
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
7854
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
7718
7855
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
7719
7856
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
7720
7857
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
7721
7858
  collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
7722
7859
  language?: import("@angular/core").Signal<string | undefined> | undefined;
7723
7860
  userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
7724
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
7861
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
7725
7862
  disabledHighlightCategories: import("@angular/core").Signal<string[]>;
7726
7863
  isDebugMode: import("@angular/core").Signal<boolean>;
7727
7864
  isDarkMode: import("@angular/core").Signal<boolean>;
@@ -7730,12 +7867,20 @@ export declare class SearchService {
7730
7867
  unbookmark: (id: string) => Promise<void>;
7731
7868
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
7732
7869
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
7870
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
7871
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
7733
7872
  deleteRecentSearch: (index: number) => Promise<void>;
7734
7873
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: AuditEvents) => Promise<void>;
7735
7874
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
7736
7875
  deleteSavedSearch: (index: number) => Promise<void>;
7737
7876
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
7738
7877
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
7878
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
7879
+ updateQuickFilter: (id: string, changes: {
7880
+ name?: string;
7881
+ filters?: import("@sinequa/atomic").LegacyFilter[];
7882
+ }) => Promise<void>;
7883
+ removeQuickFilter: (id: string) => Promise<void>;
7739
7884
  deleteBasket: (index: number) => Promise<void>;
7740
7885
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
7741
7886
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -7759,8 +7904,10 @@ export declare class SearchService {
7759
7904
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
7760
7905
  } & import("@ngrx/signals").StateSource<{
7761
7906
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
7907
+ favoriteSearches: string[];
7762
7908
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
7763
7909
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
7910
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
7764
7911
  baskets: import("@sinequa/atomic-angular").Basket[];
7765
7912
  assistants: Record<string, unknown>;
7766
7913
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -7845,7 +7992,7 @@ export declare class SelectionService {
7845
7992
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
7846
7993
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
7847
7994
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
7848
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
7995
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
7849
7996
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
7850
7997
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
7851
7998
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -8551,15 +8698,17 @@ export declare class ShowBookmarkDirective {
8551
8698
  protected bookmarkHovered: import("@angular/core").WritableSignal<boolean>;
8552
8699
  userSettingsStore: {
8553
8700
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
8701
+ favoriteSearches: import("@angular/core").Signal<string[]>;
8554
8702
  recentSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
8555
8703
  savedSearches: import("@angular/core").Signal<import("@sinequa/atomic-angular").SearchItem[]>;
8704
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
8556
8705
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
8557
8706
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
8558
8707
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
8559
8708
  collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
8560
8709
  language?: import("@angular/core").Signal<string | undefined> | undefined;
8561
8710
  userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
8562
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
8711
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
8563
8712
  disabledHighlightCategories: import("@angular/core").Signal<string[]>;
8564
8713
  isDebugMode: import("@angular/core").Signal<boolean>;
8565
8714
  isDarkMode: import("@angular/core").Signal<boolean>;
@@ -8568,12 +8717,20 @@ export declare class ShowBookmarkDirective {
8568
8717
  unbookmark: (id: string) => Promise<void>;
8569
8718
  isBookmarked: (article: Partial<Article>) => boolean;
8570
8719
  toggleBookmark: (article: Article) => Promise<void>;
8720
+ isFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => boolean;
8721
+ toggleFavoriteSearch: (search: Pick<import("@sinequa/atomic-angular").SearchItem, "label" | "display">) => Promise<boolean>;
8571
8722
  deleteRecentSearch: (index: number) => Promise<void>;
8572
8723
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
8573
8724
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
8574
8725
  deleteSavedSearch: (index: number) => Promise<void>;
8575
8726
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
8576
8727
  getSavedSearch: (search: string, tab?: string) => import("@sinequa/atomic-angular").SearchItem | undefined;
8728
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
8729
+ updateQuickFilter: (id: string, changes: {
8730
+ name?: string;
8731
+ filters?: import("@sinequa/atomic").LegacyFilter[];
8732
+ }) => Promise<void>;
8733
+ removeQuickFilter: (id: string) => Promise<void>;
8577
8734
  deleteBasket: (index: number) => Promise<void>;
8578
8735
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
8579
8736
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -8597,8 +8754,10 @@ export declare class ShowBookmarkDirective {
8597
8754
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
8598
8755
  } & import("@ngrx/signals").StateSource<{
8599
8756
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
8757
+ favoriteSearches: string[];
8600
8758
  recentSearches: import("@sinequa/atomic-angular").SearchItem[];
8601
8759
  savedSearches: import("@sinequa/atomic-angular").SearchItem[];
8760
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
8602
8761
  baskets: import("@sinequa/atomic-angular").Basket[];
8603
8762
  assistants: Record<string, unknown>;
8604
8763
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -9325,7 +9484,7 @@ export declare class SponsoredResultsComponent {
9325
9484
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
9326
9485
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
9327
9486
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
9328
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
9487
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
9329
9488
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
9330
9489
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
9331
9490
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -10364,7 +10523,7 @@ export declare class AdvancedSearch {
10364
10523
  readonly similarDocuments: import("@angular/core").InputSignal<Article[] | undefined>;
10365
10524
  readonly selected: import("@angular/core").OutputEmitterRef<Article>;
10366
10525
  protected readonly selectionStore: {
10367
- article?: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<Article> | undefined;
10526
+ article?: import("@ngrx/signals").DeepSignal<Article> | import("@angular/core").Signal<undefined> | undefined;
10368
10527
  id?: import("@angular/core").Signal<string | undefined> | undefined;
10369
10528
  queryText?: import("@angular/core").Signal<string | undefined> | undefined;
10370
10529
  queryName?: import("@angular/core").Signal<string | undefined> | undefined;
@@ -10413,7 +10572,7 @@ export declare class AdvancedSearch {
10413
10572
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
10414
10573
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
10415
10574
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
10416
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
10575
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
10417
10576
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
10418
10577
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
10419
10578
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -10599,7 +10758,7 @@ export declare class AdvancedSearchTabs {
10599
10758
  readonly similarDocuments: import("@angular/core").InputSignal<Article[] | undefined>;
10600
10759
  readonly selected: import("@angular/core").OutputEmitterRef<Article>;
10601
10760
  protected readonly selectionStore: {
10602
- article?: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<Article> | undefined;
10761
+ article?: import("@ngrx/signals").DeepSignal<Article> | import("@angular/core").Signal<undefined> | undefined;
10603
10762
  id?: import("@angular/core").Signal<string | undefined> | undefined;
10604
10763
  queryText?: import("@angular/core").Signal<string | undefined> | undefined;
10605
10764
  queryName?: import("@angular/core").Signal<string | undefined> | undefined;
@@ -11329,7 +11488,7 @@ export declare class AlertFormComponent {
11329
11488
  */
11330
11489
  private readonly currentSearch;
11331
11490
  readonly canUpdateQuery: import("@angular/core").Signal<boolean>;
11332
- readonly updateStatus: import("@angular/core").WritableSignal<"updating" | "updated" | "idle">;
11491
+ readonly updateStatus: import("@angular/core").WritableSignal<"idle" | "updating" | "updated">;
11333
11492
  /** Why the last save failed — shown in the form until the next attempt. */
11334
11493
  protected readonly saveError: import("@angular/core").WritableSignal<{
11335
11494
  detail?: string;
@@ -11449,7 +11608,7 @@ export declare class ChangePasswordComponent {
11449
11608
  private readonly applicationService;
11450
11609
  private readonly location;
11451
11610
  private readonly auditService;
11452
- protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-1)" | "flex w-full flex-col gap-(--spacing-md)">;
11611
+ protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) border border-solid border-(--layer-page-edge) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-2)" | "flex w-full flex-col gap-(--spacing-md)">;
11453
11612
  protected readonly footerClass = "flex justify-end gap-(--spacing-2xs) -mx-(--spacing-md) -mb-(--spacing-md) rounded-b-(--radius-md) bg-(--layer-page-on-layer) px-(--spacing-md) py-(--spacing-sm)";
11454
11613
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11455
11614
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
@@ -11549,7 +11708,7 @@ export declare class SignInComponent implements OnInit {
11549
11708
  loginPath: string;
11550
11709
  createRoutes: boolean;
11551
11710
  }> & Record<string, unknown>>;
11552
- protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-1)" | "flex w-full flex-col gap-(--spacing-md)">;
11711
+ protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) border border-solid border-(--layer-page-edge) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-2)" | "flex w-full flex-col gap-(--spacing-md)">;
11553
11712
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11554
11713
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
11555
11714
  protected readonly errorClass = "text-(length:--size-base) text-(--font-error-base)";
@@ -11747,7 +11906,7 @@ export declare class ForgotPasswordComponent {
11747
11906
  private readonly client;
11748
11907
  private readonly transloco;
11749
11908
  private readonly auditService;
11750
- protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-1)" | "flex w-full flex-col gap-(--spacing-md)">;
11909
+ protected readonly containerClass: import("@angular/core").Signal<"flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) border border-solid border-(--layer-page-edge) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-2)" | "flex w-full flex-col gap-(--spacing-md)">;
11751
11910
  protected readonly footerClass = "flex justify-end gap-(--spacing-2xs) -mx-(--spacing-md) -mb-(--spacing-md) rounded-b-(--radius-md) bg-(--layer-page-on-layer) px-(--spacing-md) py-(--spacing-sm)";
11752
11911
  protected readonly fieldClass = "flex flex-col gap-(--spacing-2xs)";
11753
11912
  protected readonly labelClass = "text-(length:--size-base) font-(--weight-semibold) text-(--font-primary-base)";
@@ -11800,7 +11959,7 @@ export declare class ForgotPasswordComponent {
11800
11959
  export declare class SignedOutComponent {
11801
11960
  private readonly router;
11802
11961
  private readonly client;
11803
- protected readonly surfaceClass = "flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-1)";
11962
+ protected readonly surfaceClass = "flex w-full flex-col gap-(--spacing-md) rounded-(--radius-md) border border-solid border-(--layer-page-edge) bg-(--layer-page-layer) p-(--spacing-md) shadow-(--shadow-2)";
11804
11963
  /**
11805
11964
  * Navigate to the login screen, which then drives the normal sign-in handshake.
11806
11965
  *
@@ -11813,8 +11972,8 @@ export declare class SignedOutComponent {
11813
11972
  static ɵcmp: i0.ɵɵComponentDeclaration<SignedOutComponent, "signed-out, SignedOut, signedout", never, {}, {}, never, never, true, never>;
11814
11973
  }
11815
11974
  export declare class BookmarkButtonComponent {
11816
- variant: import("@angular/core").InputSignal<"none" | "primary" | "secondary" | "light-accent" | "accent" | "tertiary" | null | undefined>;
11817
- size: import("@angular/core").InputSignal<"small" | "large" | "sm" | "md" | "xs" | "xsmall" | "medium" | "lg" | null | undefined>;
11975
+ variant: import("@angular/core").InputSignal<"secondary" | "tertiary" | "none" | "light-accent" | "accent" | "primary" | null | undefined>;
11976
+ size: import("@angular/core").InputSignal<"md" | "small" | "medium" | "large" | "sm" | "xsmall" | "xs" | "lg" | null | undefined>;
11818
11977
  /**
11819
11978
  * Tab index applied to the inner button.
11820
11979
  *
@@ -12066,7 +12225,7 @@ export declare class CollectionsDialog {
12066
12225
  readonly showSearch: import("@angular/core").Signal<boolean>;
12067
12226
  /** Collections matching the search text (case-insensitive, by name). */
12068
12227
  readonly filteredCollections: import("@angular/core").Signal<Basket[]>;
12069
- readonly collectionsMap: import("@angular/core").WritableSignal<Record<string, "some" | "none" | "all">>;
12228
+ readonly collectionsMap: import("@angular/core").WritableSignal<Record<string, "some" | "all" | "none">>;
12070
12229
  /** Windowing over the filtered list — renders only the visible rows. */
12071
12230
  readonly virtualizer: import("@tanstack/angular-virtual").AngularVirtualizer<HTMLDivElement, Element>;
12072
12231
  constructor();
@@ -12421,7 +12580,7 @@ export declare class ExportDialog {
12421
12580
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
12422
12581
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
12423
12582
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
12424
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
12583
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
12425
12584
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
12426
12585
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
12427
12586
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -12905,7 +13064,7 @@ export declare class SearchFeedbackComponent {
12905
13064
  onClose: import("@angular/core").OutputEmitterRef<void>;
12906
13065
  private readonly injector;
12907
13066
  pages: import("@angular/core").InputSignal<any>;
12908
- variant: import("@angular/core").InputSignal<"none" | "primary" | "secondary" | "light-accent" | "accent" | "tertiary" | null | undefined>;
13067
+ variant: import("@angular/core").InputSignal<"secondary" | "tertiary" | "none" | "light-accent" | "accent" | "primary" | null | undefined>;
12909
13068
  readonly auditService: AuditService;
12910
13069
  protected readonly queryParamsStore: {
12911
13070
  name?: import("@angular/core").Signal<string | undefined> | undefined;
@@ -12934,7 +13093,7 @@ export declare class SearchFeedbackComponent {
12934
13093
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
12935
13094
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
12936
13095
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
12937
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
13096
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
12938
13097
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
12939
13098
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
12940
13099
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -13193,6 +13352,14 @@ export declare class AggregationDateComponent {
13193
13352
  column: import("@angular/core").InputSignal<string | null>;
13194
13353
  id: import("@angular/core").InputSignal<string | null>;
13195
13354
  collapsible: import("@angular/core").InputSignal<boolean>;
13355
+ /**
13356
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
13357
+ * (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
13358
+ * the top of the facet, as they do under the search field of the list and the tree. Set by the filter button.
13359
+ *
13360
+ * @default false
13361
+ */
13362
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
13196
13363
  collapsed: import("@angular/core").InputSignal<boolean>;
13197
13364
  searchable: import("@angular/core").InputSignal<boolean | undefined>;
13198
13365
  showFiltersCount: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
@@ -13238,7 +13405,7 @@ export declare class AggregationDateComponent {
13238
13405
  *
13239
13406
  * @default 'selection'
13240
13407
  */
13241
- emitOn: import("@angular/core").InputSignal<"apply" | "selection">;
13408
+ emitOn: import("@angular/core").InputSignal<"selection" | "apply">;
13242
13409
  readonly title: import("@angular/core").InputSignal<AggregationTitle>;
13243
13410
  readonly displayEmptyDistributionIntervals: import("@angular/core").InputSignal<boolean>;
13244
13411
  onSelect: import("@angular/core").OutputEmitterRef<AggregationItem[]>;
@@ -13306,7 +13473,7 @@ export declare class AggregationDateComponent {
13306
13473
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
13307
13474
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
13308
13475
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
13309
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
13476
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
13310
13477
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
13311
13478
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
13312
13479
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -13566,6 +13733,11 @@ export declare class AggregationDateComponent {
13566
13733
  "required": false;
13567
13734
  "isSignal": true;
13568
13735
  };
13736
+ "headless": {
13737
+ "alias": "headless";
13738
+ "required": false;
13739
+ "isSignal": true;
13740
+ };
13569
13741
  "collapsed": {
13570
13742
  "alias": "collapsed";
13571
13743
  "required": false;
@@ -13651,6 +13823,15 @@ export declare class AggregationTreeComponent {
13651
13823
  * @default true
13652
13824
  */
13653
13825
  showCheckbox: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
13826
+ /**
13827
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
13828
+ * (the popover of a filter button, whose button already says which facet it is). Select all, clear and apply are not in the
13829
+ * header, whichever way the facet is shown: they sit in a bar under the search field. A popover that holds several facets
13830
+ * (the "more filters" one) keeps the headers: each of them collapses and expands from its title.
13831
+ *
13832
+ * @default false
13833
+ */
13834
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
13654
13835
  /**
13655
13836
  * Whether every selection gesture — row click, checkbox click, Space/Enter on the
13656
13837
  * focused node — applies the filter immediately, instead of only revealing the
@@ -13804,7 +13985,7 @@ export declare class AggregationTreeComponent {
13804
13985
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
13805
13986
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
13806
13987
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
13807
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
13988
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
13808
13989
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
13809
13990
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
13810
13991
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -14415,6 +14596,11 @@ export declare class AggregationTreeComponent {
14415
14596
  "required": false;
14416
14597
  "isSignal": true;
14417
14598
  };
14599
+ "headless": {
14600
+ "alias": "headless";
14601
+ "required": false;
14602
+ "isSignal": true;
14603
+ };
14418
14604
  "applyOnSelect": {
14419
14605
  "alias": "applyOnSelect";
14420
14606
  "required": false;
@@ -14493,6 +14679,15 @@ export declare class AggregationListComponent {
14493
14679
  * @default true
14494
14680
  */
14495
14681
  showCheckbox: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
14682
+ /**
14683
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
14684
+ * (the popover of a filter button, whose button already says which facet it is). Select all, clear and apply are not in the
14685
+ * header, whichever way the facet is shown: they sit in a bar under the search field. A popover that holds several facets
14686
+ * (the "more filters" one) keeps the headers: each of them collapses and expands from its title.
14687
+ *
14688
+ * @default false
14689
+ */
14690
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
14496
14691
  /**
14497
14692
  * Whether every selection gesture — row click, checkbox click, Space/Enter on the
14498
14693
  * focused option — applies the filter immediately, instead of only revealing the
@@ -14663,7 +14858,7 @@ export declare class AggregationListComponent {
14663
14858
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
14664
14859
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
14665
14860
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
14666
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
14861
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
14667
14862
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
14668
14863
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
14669
14864
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -15173,6 +15368,11 @@ export declare class AggregationListComponent {
15173
15368
  "required": false;
15174
15369
  "isSignal": true;
15175
15370
  };
15371
+ "headless": {
15372
+ "alias": "headless";
15373
+ "required": false;
15374
+ "isSignal": true;
15375
+ };
15176
15376
  "applyOnSelect": {
15177
15377
  "alias": "applyOnSelect";
15178
15378
  "required": false;
@@ -15633,6 +15833,15 @@ export declare class AggregationComponent {
15633
15833
  * @default true
15634
15834
  */
15635
15835
  showCheckbox: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
15836
+ /**
15837
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
15838
+ * (the popover of a filter button, whose button already says which facet it is). Select all, clear and apply are not in the
15839
+ * header, whichever way the facet is shown: they sit in a bar under the search field. A popover that holds several facets
15840
+ * (the "more filters" one) keeps the headers: each of them collapses and expands from its title.
15841
+ *
15842
+ * @default false
15843
+ */
15844
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
15636
15845
  /**
15637
15846
  * **List/tree only.** Whether every selection gesture — row click, checkbox click,
15638
15847
  * Space/Enter on the focused item — applies the filter immediately, instead of only
@@ -15698,7 +15907,7 @@ export declare class AggregationComponent {
15698
15907
  *
15699
15908
  * @default 'selection'
15700
15909
  */
15701
- emitOn: import("@angular/core").InputSignal<"apply" | "selection">;
15910
+ emitOn: import("@angular/core").InputSignal<"selection" | "apply">;
15702
15911
  /**
15703
15912
  * Which sub-component renders the aggregation.
15704
15913
  *
@@ -15711,7 +15920,7 @@ export declare class AggregationComponent {
15711
15920
  *
15712
15921
  * @default "auto"
15713
15922
  */
15714
- type: import("@angular/core").InputSignal<"date" | "list" | "tree" | "auto">;
15923
+ type: import("@angular/core").InputSignal<"list" | "auto" | "tree" | "date">;
15715
15924
  /**
15716
15925
  * Whether the host removes itself from the layout (Tailwind's `hidden`, i.e.
15717
15926
  * `display: none`) when it resolves to zero items. When `false` (default), the
@@ -15763,7 +15972,7 @@ export declare class AggregationComponent {
15763
15972
  * The sub-component to render: the explicit `type` input, or the current
15764
15973
  * date/tree/list heuristic when `type` is `"auto"`.
15765
15974
  */
15766
- protected resolvedType: import("@angular/core").Signal<"date" | "list" | "tree">;
15975
+ protected resolvedType: import("@angular/core").Signal<"list" | "tree" | "date">;
15767
15976
  /** Whether a filter is currently applied on this aggregation. */
15768
15977
  private readonly hasFilters;
15769
15978
  /**
@@ -15851,6 +16060,11 @@ export declare class AggregationComponent {
15851
16060
  "required": false;
15852
16061
  "isSignal": true;
15853
16062
  };
16063
+ "headless": {
16064
+ "alias": "headless";
16065
+ "required": false;
16066
+ "isSignal": true;
16067
+ };
15854
16068
  "applyOnSelect": {
15855
16069
  "alias": "applyOnSelect";
15856
16070
  "required": false;
@@ -15922,6 +16136,17 @@ export declare class AggregationPanelComponent {
15922
16136
  hasFilters: import("@angular/core").InputSignal<boolean>;
15923
16137
  selection: import("@angular/core").InputSignal<boolean>;
15924
16138
  isAllSelected: import("@angular/core").InputSignal<boolean>;
16139
+ /**
16140
+ * Leaves out the header of the facet — its icon, its title, the collapse chevron — for a popover that holds this one facet
16141
+ * (the popover of a filter button, whose button already says which facet it is). Select all, clear and apply are not in the
16142
+ * header, whichever way the facet is shown: they sit in a bar under the search field. A popover that holds several facets
16143
+ * (the "more filters" one) keeps the headers: each of them collapses and expands from its title.
16144
+ *
16145
+ * @default false
16146
+ */
16147
+ headless: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16148
+ /** 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. */
16149
+ selectedCount: import("@angular/core").InputSignal<number>;
15925
16150
  searchText: import("@angular/core").ModelSignal<string>;
15926
16151
  itemsLength: import("@angular/core").InputSignal<number>;
15927
16152
  hasMore: import("@angular/core").InputSignal<boolean>;
@@ -15934,9 +16159,28 @@ export declare class AggregationPanelComponent {
15934
16159
  isCollapsed: import("@angular/core").WritableSignal<boolean>;
15935
16160
  expanded: import("@angular/core").Signal<"" | null>;
15936
16161
  private readonly searchBox;
16162
+ private readonly searchToggle;
16163
+ private readonly injector;
15937
16164
  /** The galactik popover (`[popover]` / `[dropdown]`) this panel is shown in, if any — resolved through the injector tree. */
15938
- private readonly isInPopover;
15939
- constructor();
16165
+ protected readonly isInPopover: boolean;
16166
+ private static nextId;
16167
+ protected readonly searchId: string;
16168
+ private readonly searchRequested;
16169
+ /**
16170
+ * Whether the facet has a search field at all: the facet allows it (`searchable`, from the custom JSON or the
16171
+ * `searchable` input of the facet) and there is something to search in.
16172
+ */
16173
+ protected readonly canSearch: import("@angular/core").Signal<boolean>;
16174
+ /**
16175
+ * The search field is out of the way until the user asks for it with the magnifier: a field that is always there costs a
16176
+ * line per facet, and most of the time nobody searches. A text already in the field keeps it open — it is filtering the
16177
+ * values, and a filter you cannot see is not a filter you can undo.
16178
+ */
16179
+ protected readonly showSearch: import("@angular/core").Signal<boolean>;
16180
+ /** Opens the search field and puts the focus in it, or closes it, drops its text and gives the focus back to the magnifier. */
16181
+ protected toggleSearch(event?: Event): void;
16182
+ /** Escape in the field closes it, as it would a popover: the way back is the key the user already knows. */
16183
+ protected onSearchEscape(event: Event): void;
15940
16184
  onHeaderClick(event: Event): void;
15941
16185
  onToggle(event: Event): void;
15942
16186
  static ɵfac: i0.ɵɵFactoryDeclaration<AggregationPanelComponent, never>;
@@ -15996,6 +16240,16 @@ export declare class AggregationPanelComponent {
15996
16240
  "required": false;
15997
16241
  "isSignal": true;
15998
16242
  };
16243
+ "headless": {
16244
+ "alias": "headless";
16245
+ "required": false;
16246
+ "isSignal": true;
16247
+ };
16248
+ "selectedCount": {
16249
+ "alias": "selectedCount";
16250
+ "required": false;
16251
+ "isSignal": true;
16252
+ };
15999
16253
  "searchText": {
16000
16254
  "alias": "searchText";
16001
16255
  "required": false;
@@ -16107,6 +16361,19 @@ export declare function filterKey(leaf: LegacyFilter): string;
16107
16361
  */
16108
16362
  export declare class AppliedFiltersComponent {
16109
16363
  private readonly queryParamsStore;
16364
+ private static nextId;
16365
+ protected readonly listId: string;
16366
+ private readonly list;
16367
+ /** Whether the chips take more lines than `maxLines`: only then is there anything to fold. */
16368
+ protected readonly foldable: import("@angular/core").WritableSignal<boolean>;
16369
+ /** The list is unfolded. */
16370
+ protected readonly expanded: import("@angular/core").WritableSignal<boolean>;
16371
+ /** Height of `maxLines` lines of chips, and of all of them, in pixels — measured, as the chips wrap with the width. */
16372
+ private readonly foldedHeight;
16373
+ private readonly fullHeight;
16374
+ /** The height the list is given: none (it is as tall as its chips) until there is something to fold. */
16375
+ protected readonly listHeight: import("@angular/core").Signal<number | null>;
16376
+ protected toggle(): void;
16110
16377
  /**
16111
16378
  * The filters to display. Omit it to read the current query's own — the common case.
16112
16379
  *
@@ -16132,13 +16399,26 @@ export declare class AppliedFiltersComponent {
16132
16399
  * than as "unset". A `null` here would therefore silently neutralise `scheme` — the chips would keep
16133
16400
  * their base look whatever colour was asked for. `undefined` lets the tag apply its own default.
16134
16401
  */
16135
- readonly variant: import("@angular/core").InputSignal<"primary" | "secondary" | null | undefined>;
16402
+ readonly variant: import("@angular/core").InputSignal<"secondary" | "primary" | null | undefined>;
16136
16403
  /** Chip colour scheme, passed to galactik's `tag`. */
16137
- readonly scheme: import("@angular/core").InputSignal<"error" | "sage" | "success" | "almond" | "pink" | "grey" | "yellow" | "cherry" | "indigo" | "cyan" | "warning" | "info" | null | undefined>;
16404
+ readonly scheme: import("@angular/core").InputSignal<"error" | "sage" | "almond" | "pink" | "grey" | "yellow" | "cherry" | "indigo" | "cyan" | "success" | "warning" | "info" | null | undefined>;
16138
16405
  /** Chip size, passed to galactik's `tag`. */
16139
- readonly size: import("@angular/core").InputSignal<"small" | "sm" | "md" | "xs" | "xsmall" | "medium" | null | undefined>;
16406
+ readonly size: import("@angular/core").InputSignal<"md" | "small" | "medium" | "sm" | "xsmall" | "xs" | null | undefined>;
16140
16407
  /** Extra classes for each chip, merged by galactik's `tag`. */
16141
16408
  readonly chipClass: import("@angular/core").InputSignal<string>;
16409
+ /**
16410
+ * How many lines of chips are shown before the rest is folded behind a "show more" button. `0` never folds.
16411
+ *
16412
+ * @default 2
16413
+ */
16414
+ readonly maxLines: import("@angular/core").InputSignalWithTransform<number, unknown>;
16415
+ /**
16416
+ * Whether the "clear all" button ends the list of chips (shown from two chips on). Turn it off when the screen has a clear
16417
+ * button of its own.
16418
+ *
16419
+ * @default true
16420
+ */
16421
+ readonly showClearAll: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16142
16422
  /** A chip was removed. */
16143
16423
  readonly removed: import("@angular/core").OutputEmitterRef<AppliedFilterChip>;
16144
16424
  /** Every chip was removed. */
@@ -16147,6 +16427,12 @@ export declare class AppliedFiltersComponent {
16147
16427
  readonly filtersChange: import("@angular/core").OutputEmitterRef<LegacyFilter[]>;
16148
16428
  /** Something changed, whichever way. Re-run the search on this and ignore the rest. */
16149
16429
  readonly changed: import("@angular/core").OutputEmitterRef<void>;
16430
+ constructor();
16431
+ /**
16432
+ * Reads how the chips wrap: the rows are the distinct tops of the chips, so the height of `maxLines` lines is the top of the
16433
+ * next row less the gap, and the whole list is its `scrollHeight`. The chips below the folded height are made `inert`.
16434
+ */
16435
+ private measure;
16150
16436
  /** One chip per applied value, expanded from the stored entries through their leaves. */
16151
16437
  readonly chips: import("@angular/core").Signal<AppliedFilterChip[]>;
16152
16438
  /**
@@ -16195,6 +16481,16 @@ export declare class AppliedFiltersComponent {
16195
16481
  "required": false;
16196
16482
  "isSignal": true;
16197
16483
  };
16484
+ "maxLines": {
16485
+ "alias": "maxLines";
16486
+ "required": false;
16487
+ "isSignal": true;
16488
+ };
16489
+ "showClearAll": {
16490
+ "alias": "showClearAll";
16491
+ "required": false;
16492
+ "isSignal": true;
16493
+ };
16198
16494
  }, {
16199
16495
  "removed": "removed";
16200
16496
  "cleared": "cleared";
@@ -16303,6 +16599,20 @@ export declare class AsideFiltersComponent {
16303
16599
  };
16304
16600
  }, {}, never, never, true, never>;
16305
16601
  }
16602
+ /**
16603
+ * Colour family of a pill-shaped filter button — the twelve schemes of the galactik `Tag`.
16604
+ * `sage` is the default and the primary palette of the theme.
16605
+ */
16606
+ type FilterScheme = "sage" | "almond" | "pink" | "grey" | "yellow" | "cherry" | "indigo" | "cyan" | "success" | "warning" | "info" | "error";
16607
+ /**
16608
+ * Classes of a pill-shaped filter button: its shape, the border and the hover of its scheme, and the scheme's tint
16609
+ * while its popover is open. It is always the outlined pill, with no fill at rest — never the filled `primary` button,
16610
+ * and never a tint either when it holds a selection (`selected` is kept for callers, it changes nothing here).
16611
+ */
16612
+ declare function filterPillClasses(scheme: FilterScheme, state: {
16613
+ selected: boolean;
16614
+ open: boolean;
16615
+ }): string;
16306
16616
  export type CFilterEx = CFilter & {
16307
16617
  name: string;
16308
16618
  count: number;
@@ -16311,6 +16621,8 @@ export type CFilterEx = CFilter & {
16311
16621
  hidden: boolean;
16312
16622
  legacyFilter?: LegacyFilter;
16313
16623
  };
16624
+ /** Look of a filter button: the default flat button, or a rounded outlined pill. */
16625
+ export type FilterAppearance = "default" | "pill";
16314
16626
  export declare class FilterButtonComponent {
16315
16627
  name: import("@angular/core").InputSignal<string | undefined>;
16316
16628
  column: import("@angular/core").InputSignal<string>;
@@ -16325,21 +16637,39 @@ export declare class FilterButtonComponent {
16325
16637
  lockPosition: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16326
16638
  expandedLevel: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
16327
16639
  /**
16328
- * Set by `filters-bar` on the filters that do not fit and are hidden by the overflow manager. They
16329
- * leave the toolbar's keyboard navigation: a roving focus cannot land on an element with
16330
- * `display: none`, so the arrow keys used to stall on the last visible filter while the tab stop
16331
- * silently moved to a hidden one.
16640
+ * Look of the button. `pill` makes it a rounded outlined pill that stays that pill, with no fill, once the filter holds
16641
+ * a selection; the popover it opens is the same.
16642
+ *
16643
+ * @default "default"
16644
+ */
16645
+ appearance: import("@angular/core").InputSignal<FilterAppearance>;
16646
+ /**
16647
+ * Colour family of a `pill`: its outline and its hover, and the tint it takes while its popover is open. The text
16648
+ * is unchanged. Ignored by the default appearance.
16649
+ *
16650
+ * @default "sage"
16332
16651
  */
16333
- overflowed: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16334
- protected variant: import("@angular/core").WritableSignal<"none" | "primary" | "secondary" | "light-accent" | "accent" | "tertiary" | null | undefined>;
16652
+ scheme: import("@angular/core").InputSignal<FilterScheme>;
16653
+ protected variant: import("@angular/core").WritableSignal<"secondary" | "tertiary" | "none" | "light-accent" | "accent" | "primary" | null | undefined>;
16335
16654
  protected filter: import("@angular/core").WritableSignal<CFilterEx>;
16336
16655
  /** Unique id wiring the trigger's `popovertarget` to the `<div popover>` `id`. */
16337
16656
  protected readonly popoverId: string;
16338
16657
  popoverRef: import("@angular/core").Signal<PopoverDirective | undefined>;
16339
16658
  /** True while the native popover is open — drives the trigger's open styling. */
16340
16659
  protected readonly isOpen: import("@angular/core").Signal<boolean>;
16341
- /** Set when this button sits in a `filters-bar` toolbar: the inner button then is the roving widget. */
16342
- protected readonly toolbar: Toolbar | null;
16660
+ /** Classes of the trigger: its shape (`appearance`) and its open state. */
16661
+ protected readonly triggerClass: import("@angular/core").Signal<string>;
16662
+ /**
16663
+ * The popover is placed by Floating UI — flipped above the button when there is no room under it, shifted into the viewport —
16664
+ * until the user resizes it. From then on it stays where it is (`lockPosition`) as long as it is open: a popover that kept
16665
+ * flipping while its height changes would jump under the pointer. It keeps the side it was on. Closing lets it go: the next
16666
+ * opening places it again, and only the height the user chose is kept.
16667
+ */
16668
+ protected readonly resized: import("@angular/core").WritableSignal<boolean>;
16669
+ private readonly flippedAbove;
16670
+ protected readonly placement: import("@angular/core").Signal<Placement>;
16671
+ /** The user has chosen a height at least once: the facet fills the popover instead of keeping its comfortable size. */
16672
+ protected readonly sized: import("@angular/core").WritableSignal<boolean>;
16343
16673
  protected nativeElement: any;
16344
16674
  protected aggregationsStore: {
16345
16675
  aggregations: import("@angular/core").Signal<import("@sinequa/atomic").Aggregation[]>;
@@ -16377,7 +16707,7 @@ export declare class FilterButtonComponent {
16377
16707
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
16378
16708
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
16379
16709
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
16380
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
16710
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
16381
16711
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
16382
16712
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
16383
16713
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -16778,24 +17108,22 @@ export declare class FilterButtonComponent {
16778
17108
  columnMap?: Record<string, import("@sinequa/atomic").CCColumn> | undefined;
16779
17109
  }>;
16780
17110
  constructor();
17111
+ private popoverElement;
17112
+ /** Once the popover is closed, Floating UI places it again the next time it opens; the height the user chose stays. */
17113
+ protected onToggle(): void;
17114
+ /**
17115
+ * Gives the position back to Floating UI: a top edge that was moved is put back where the placement leaves it, and the
17116
+ * popover may flip or shift again. The height the user chose stays.
17117
+ */
17118
+ private unpin;
17119
+ /** The user starts to resize: pins the popover, on the side Floating UI had put it. */
17120
+ protected onResizeStart(): void;
16781
17121
  /**
16782
17122
  * Toggles the popover on keyboard activation of the (roving) toolbar widget
16783
17123
  * host. Always cancels the default action; opening is suppressed for disabled
16784
17124
  * filters, mirroring the previous deprecated-popover behavior.
16785
17125
  */
16786
17126
  protected toggle(event: Event): void;
16787
- /**
16788
- * Keeps the toolbar's roving keyboard handler out of the panel.
16789
- *
16790
- * The panel is a DOM descendant of the `@angular/aria` toolbar, which owns the arrow keys to
16791
- * rove between widgets. Its handler therefore consumed the arrows pressed *inside* the panel,
16792
- * and the native radio group of the date aggregation never moved: focus stayed on the first
16793
- * option whatever the user pressed. Pointer events were already isolated (above) for the same
16794
- * reason — this is the keyboard half of that isolation.
16795
- *
16796
- * Tab and Escape are deliberately let through: they must keep leaving and closing the panel.
16797
- */
16798
- protected isolateNavigationKeys(event: KeyboardEvent): void;
16799
17127
  /**
16800
17128
  * Closes the popover when focus leaves the filter entirely.
16801
17129
  *
@@ -16847,13 +17175,184 @@ export declare class FilterButtonComponent {
16847
17175
  "required": false;
16848
17176
  "isSignal": true;
16849
17177
  };
16850
- "overflowed": {
16851
- "alias": "overflowed";
17178
+ "appearance": {
17179
+ "alias": "appearance";
17180
+ "required": false;
17181
+ "isSignal": true;
17182
+ };
17183
+ "scheme": {
17184
+ "alias": "scheme";
16852
17185
  "required": false;
16853
17186
  "isSignal": true;
16854
17187
  };
16855
17188
  }, {}, never, never, true, never>;
16856
17189
  }
17190
+ /**
17191
+ * How the overflow facets are laid out.
17192
+ *
17193
+ * - `drilldown` (the default): a list of the facets, each with a chevron; picking one replaces the list with that facet
17194
+ * 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
17195
+ * scroller; in a plain scrolling container it grows and the container scrolls.
17196
+ * - `accordion`: every facet is a collapsible section of one scrolling list.
17197
+ */
17198
+ export type MoreLayout = "accordion" | "drilldown";
17199
+ export declare class MoreComponent {
17200
+ protected readonly SEARCH_THRESHOLD = 6;
17201
+ /**
17202
+ * The facet of the `accordion` layout, its header dressed as a row of the drilldown list (same height, weight, hover and
17203
+ * focus), so the two layouts read alike. It is a descendant selector on the header rather than an input of the facet: the
17204
+ * header belongs to the facet (also shown in a drawer, where it is deliberately not a button to the eye), and only this
17205
+ * popover wants it to look like a row. Whole-row focus ring on `focus-within`: the chevron is the tab stop (the `<summary>` is
17206
+ * out of the tab order), and a ring on a 24px chevron alone is not where the eye looks for it.
17207
+ */
17208
+ 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";
17209
+ /** A row of the drilldown list: a plain button, the same hover and focus as the rows of a facet. */
17210
+ 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)";
17211
+ /**
17212
+ * Layout of the facets: a list of facets that opens one at a time (`drilldown`, the default), or collapsible sections
17213
+ * (`accordion`). See {@link MoreLayout}.
17214
+ *
17215
+ * @default "drilldown"
17216
+ */
17217
+ layout: import("@angular/core").InputSignal<MoreLayout>;
17218
+ /**
17219
+ * Whether every selection gesture applies the filter immediately, instead of revealing the Apply button. Relayed as-is to
17220
+ * each `<Aggregation [applyOnSelect]>`. In `drilldown` layout the opened facet then stays open (the user ticks several
17221
+ * values in a row); otherwise applying brings the list back.
17222
+ *
17223
+ * @default false
17224
+ */
17225
+ applyOnSelect: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17226
+ count: import("@angular/core").InputSignal<number>;
17227
+ includedFilters: import("@angular/core").InputSignal<string[]>;
17228
+ excludedFilters: import("@angular/core").InputSignal<string[]>;
17229
+ aggregations: import("@angular/core").InputSignal<Aggregation[] | undefined>;
17230
+ homepage: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17231
+ /**
17232
+ * Whether a section removes itself from the layout when its aggregation
17233
+ * resolves to zero items, instead of staying with a dimmed, non-expandable
17234
+ * header. Relayed as-is to each `<Aggregation [hideWhenEmpty]>` — a missing
17235
+ * aggregation always hides regardless of this input.
17236
+ *
17237
+ * @default false
17238
+ */
17239
+ hideWhenEmpty: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17240
+ aggregationsService: AggregationsService;
17241
+ private readonly injector;
17242
+ private readonly aggregationsStore;
17243
+ private readonly appStore;
17244
+ private readonly queryParamsStore;
17245
+ private readonly host;
17246
+ /** The facet-name search query, cleared whenever the popup is reopened. */
17247
+ searchText: import("@angular/core").ModelSignal<string>;
17248
+ /** Name of the facet opened in `drilldown` layout; `null` while the list shows. */
17249
+ private readonly openedName;
17250
+ private readonly title;
17251
+ /**
17252
+ * The overflow filters rendered as accordions: the authorized filters beyond the
17253
+ * first `count` (which are already shown in the bar).
17254
+ *
17255
+ * @remarks
17256
+ * Pure display wiring — authorization (and the admin `hidden` rule) is handled by
17257
+ * {@link AggregationsService.getAuthorizedFilters}; `toSpliced` just drops the
17258
+ * filters already shown in the bar.
17259
+ */
17260
+ filters: import("@angular/core").Signal<{
17261
+ field: string;
17262
+ column: string;
17263
+ name: string;
17264
+ }[]>;
17265
+ /** {@link filters}, narrowed to those whose name matches {@link searchText}. */
17266
+ filteredFilters: import("@angular/core").Signal<{
17267
+ field: string;
17268
+ column: string;
17269
+ name: string;
17270
+ }[]>;
17271
+ /**
17272
+ * The rows of the `drilldown` list: the filtered facets that resolve to an aggregation, with their icon and the number of
17273
+ * values applied. Same rule as {@link AggregationComponent} for what hides: a missing aggregation always, an empty one
17274
+ * only with `hideWhenEmpty` (a date facet is never empty, its custom range stays usable); otherwise an empty one is dimmed.
17275
+ */
17276
+ protected readonly rows: import("@angular/core").Signal<{
17277
+ filter: {
17278
+ field: string;
17279
+ column: string;
17280
+ name: string;
17281
+ };
17282
+ icon: string | undefined;
17283
+ count: number;
17284
+ empty: boolean;
17285
+ }[]>;
17286
+ /** The facet opened in `drilldown` layout, if it is still one of the overflow filters. */
17287
+ protected readonly active: import("@angular/core").Signal<{
17288
+ filter: {
17289
+ field: string;
17290
+ column: string;
17291
+ name: string;
17292
+ };
17293
+ icon: string | undefined;
17294
+ count: number;
17295
+ empty: boolean;
17296
+ } | undefined>;
17297
+ /** An opened facet stays reachable even if the search narrowed it out of the rows. */
17298
+ private resolveHidden;
17299
+ /** 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. */
17300
+ protected open(name: string): void;
17301
+ /** A facet was applied: the list comes back, unless every gesture applies (`applyOnSelect`), where the facet stays open. */
17302
+ protected onApplied(): void;
17303
+ /** Back to the list of facets; focus returns to the row it came from (the list was destroyed while the facet was open). */
17304
+ protected back(): void;
17305
+ static ɵfac: i0.ɵɵFactoryDeclaration<MoreComponent, never>;
17306
+ static ɵcmp: i0.ɵɵComponentDeclaration<MoreComponent, "more, More", never, {
17307
+ "layout": {
17308
+ "alias": "layout";
17309
+ "required": false;
17310
+ "isSignal": true;
17311
+ };
17312
+ "applyOnSelect": {
17313
+ "alias": "applyOnSelect";
17314
+ "required": false;
17315
+ "isSignal": true;
17316
+ };
17317
+ "count": {
17318
+ "alias": "count";
17319
+ "required": false;
17320
+ "isSignal": true;
17321
+ };
17322
+ "includedFilters": {
17323
+ "alias": "includedFilters";
17324
+ "required": false;
17325
+ "isSignal": true;
17326
+ };
17327
+ "excludedFilters": {
17328
+ "alias": "excludedFilters";
17329
+ "required": false;
17330
+ "isSignal": true;
17331
+ };
17332
+ "aggregations": {
17333
+ "alias": "aggregations";
17334
+ "required": false;
17335
+ "isSignal": true;
17336
+ };
17337
+ "homepage": {
17338
+ "alias": "homepage";
17339
+ "required": false;
17340
+ "isSignal": true;
17341
+ };
17342
+ "hideWhenEmpty": {
17343
+ "alias": "hideWhenEmpty";
17344
+ "required": false;
17345
+ "isSignal": true;
17346
+ };
17347
+ "searchText": {
17348
+ "alias": "searchText";
17349
+ "required": false;
17350
+ "isSignal": true;
17351
+ };
17352
+ }, {
17353
+ "searchText": "searchTextChange";
17354
+ }, never, never, true, never>;
17355
+ }
16857
17356
  export declare class MoreButtonComponent {
16858
17357
  appStore: {
16859
17358
  name: import("@angular/core").Signal<string>;
@@ -17199,7 +17698,7 @@ export declare class MoreButtonComponent {
17199
17698
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
17200
17699
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
17201
17700
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
17202
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
17701
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
17203
17702
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
17204
17703
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
17205
17704
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -17285,21 +17784,51 @@ export declare class MoreButtonComponent {
17285
17784
  nativeElement: any;
17286
17785
  breakpointObserver: BreakpointObserverService;
17287
17786
  aggregationsService: AggregationsService;
17288
- /** Set when this button sits in a `filters-bar` toolbar: the inner button then is the roving widget. */
17289
- protected readonly toolbar: Toolbar | null;
17290
17787
  /**
17291
- * Takes the trigger out of the keyboard navigation (and the toolbar's roving) while there is nothing
17788
+ * Takes the trigger out of the keyboard navigation (Tab) while there is nothing
17292
17789
  * to show behind it, instead of leaving an invisible stop.
17293
17790
  */
17294
17791
  disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17295
- protected readonly triggerClass = "gap-1 truncate font-semibold";
17296
- protected readonly openTriggerClass = "gap-1 truncate font-semibold border border-(--stroke-neutral-dark)/18";
17297
- protected readonly openSheet: () => void | undefined;
17298
- protected readonly openDialog: () => void | undefined;
17299
- count: import("@angular/core").InputSignalWithTransform<number, unknown>;
17300
- position: import("@angular/core").InputSignal<Placement>;
17301
17792
  /**
17302
- * When true, forces the popover to stay at the exact `position()` placement, disabling
17793
+ * Look of the trigger, relayed by `filters-bar` so it matches its filter buttons: `pill` is a rounded
17794
+ * outlined pill.
17795
+ *
17796
+ * @default "default"
17797
+ */
17798
+ appearance: import("@angular/core").InputSignal<FilterAppearance>;
17799
+ /**
17800
+ * Colour family of a `pill` (its outline and hover), relayed by `filters-bar` so the trigger matches its filter buttons.
17801
+ *
17802
+ * @default "sage"
17803
+ */
17804
+ scheme: import("@angular/core").InputSignal<FilterScheme>;
17805
+ /**
17806
+ * Layout of the facets behind the trigger: a list of facets that opens one at a time under a header with a back button
17807
+ * (`drilldown`, the default), or collapsible sections (`accordion`). Relayed to `<More>`.
17808
+ *
17809
+ * @default "drilldown"
17810
+ */
17811
+ layout: import("@angular/core").InputSignal<MoreLayout>;
17812
+ /**
17813
+ * Whether every selection gesture applies the filter immediately, instead of revealing the Apply button. Relayed as-is to
17814
+ * `<More [applyOnSelect]>`.
17815
+ *
17816
+ * @default false
17817
+ */
17818
+ applyOnSelect: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17819
+ protected readonly drilldown: import("@angular/core").Signal<boolean>;
17820
+ protected readonly moreClass: import("@angular/core").Signal<"flex min-h-0 w-full flex-1 flex-col" | "block w-full">;
17821
+ /** The scrolling box of the desktop popover; in drilldown a fixed-height column, so both screens have the same size. */
17822
+ 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">;
17823
+ protected readonly idleVariant: import("@angular/core").Signal<"secondary" | "tertiary">;
17824
+ protected readonly triggerClass: import("@angular/core").Signal<string>;
17825
+ protected readonly openTriggerClass: import("@angular/core").Signal<string>;
17826
+ protected readonly openSheet: () => void | undefined;
17827
+ protected readonly openDialog: () => void | undefined;
17828
+ count: import("@angular/core").InputSignalWithTransform<number, unknown>;
17829
+ position: import("@angular/core").InputSignal<Placement>;
17830
+ /**
17831
+ * When true, forces the popover to stay at the exact `position()` placement, disabling
17303
17832
  * floating-ui's automatic repositioning based on available viewport space.
17304
17833
  *
17305
17834
  * @default false
@@ -17328,6 +17857,23 @@ export declare class MoreButtonComponent {
17328
17857
  * @default undefined — never escalate to Dialog
17329
17858
  */
17330
17859
  enrichedThreshold: import("@angular/core").InputSignal<number | undefined>;
17860
+ /**
17861
+ * Until the user resizes, Floating UI places the popover (flip, shift). From the first resize it stays where it is while
17862
+ * open (`lockPosition`), on the side it was on; closing it or scrolling the page lets Floating UI place it again, and only
17863
+ * the height the user chose is kept. Same behaviour as `<filter-button>`.
17864
+ */
17865
+ protected readonly resized: import("@angular/core").WritableSignal<boolean>;
17866
+ private readonly flippedAbove;
17867
+ protected readonly placement: import("@angular/core").Signal<Placement>;
17868
+ /** The user chose a height at least once: the list fills the popover instead of keeping its comfortable size. */
17869
+ protected readonly sized: import("@angular/core").WritableSignal<boolean>;
17870
+ constructor();
17871
+ private popoverElement;
17872
+ /** Once the popover is closed, Floating UI places it again the next time it opens; the chosen height stays. */
17873
+ protected onToggle(): void;
17874
+ private unpin;
17875
+ /** The user starts to resize: pins the popover, on the side Floating UI had put it. */
17876
+ protected onResizeStart(): void;
17331
17877
  /** Unique id wiring the trigger's `popovertarget` to the `<div popover>` `id`. */
17332
17878
  protected readonly popoverId: string;
17333
17879
  protected readonly popoverRef: import("@angular/core").Signal<PopoverDirective | undefined>;
@@ -17367,6 +17913,26 @@ export declare class MoreButtonComponent {
17367
17913
  "required": false;
17368
17914
  "isSignal": true;
17369
17915
  };
17916
+ "appearance": {
17917
+ "alias": "appearance";
17918
+ "required": false;
17919
+ "isSignal": true;
17920
+ };
17921
+ "scheme": {
17922
+ "alias": "scheme";
17923
+ "required": false;
17924
+ "isSignal": true;
17925
+ };
17926
+ "layout": {
17927
+ "alias": "layout";
17928
+ "required": false;
17929
+ "isSignal": true;
17930
+ };
17931
+ "applyOnSelect": {
17932
+ "alias": "applyOnSelect";
17933
+ "required": false;
17934
+ "isSignal": true;
17935
+ };
17370
17936
  "count": {
17371
17937
  "alias": "count";
17372
17938
  "required": false;
@@ -17476,6 +18042,71 @@ export declare class FiltersBarComponent {
17476
18042
  */
17477
18043
  homepage: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17478
18044
  direction: import("@angular/core").InputSignal<"horizontal" | "vertical">;
18045
+ /**
18046
+ * Look of the filter buttons: the default flat buttons, or `pill` — rounded outlined pills that fill
18047
+ * once the filter holds a selection, as in a search page's quick-filter row.
18048
+ *
18049
+ * @default "default"
18050
+ */
18051
+ appearance: import("@angular/core").InputSignal<FilterAppearance>;
18052
+ /**
18053
+ * Where the row of filters sits in the bar: from the start (the default), or `center`, where the filters and the
18054
+ * "more" button form one group in the middle, as under the search field of a home page.
18055
+ *
18056
+ * @default "start"
18057
+ */
18058
+ align: import("@angular/core").InputSignal<"start" | "center">;
18059
+ /**
18060
+ * How far apart the buttons are. `compact` (the default) is the tight spacing of a toolbar; `comfortable` puts
18061
+ * `--spacing-lg` (20px) between every button, the quick filters pill and the "more" button included, as under the
18062
+ * search field of a home page.
18063
+ *
18064
+ * @default "compact"
18065
+ */
18066
+ spacing: import("@angular/core").InputSignal<"compact" | "comfortable">;
18067
+ /**
18068
+ * Colour family of the `pill` appearance, one of the twelve schemes of the galactik `Tag`. It sets the outline
18069
+ * of the pills and their hover — the tint they take while a popover is open — and nothing else: the text is
18070
+ * unchanged. A pill whose filter is applied stays the outlined pill, with no fill. Ignored by the default appearance.
18071
+ *
18072
+ * @default "sage"
18073
+ */
18074
+ scheme: import("@angular/core").InputSignal<FilterScheme>;
18075
+ /**
18076
+ * Whether the bar shows its "clear all filters" and "clear basket" buttons. Turn it off when the page
18077
+ * clears the filters elsewhere.
18078
+ *
18079
+ * @default true
18080
+ */
18081
+ showClearButtons: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18082
+ /**
18083
+ * Above this many overflow filters, the "more filters" popover escalates to a modal dialog. Relayed
18084
+ * as-is to `<MoreButton [enrichedThreshold]>`.
18085
+ *
18086
+ * @default undefined — never escalate
18087
+ */
18088
+ enrichedThreshold: import("@angular/core").InputSignal<number | undefined>;
18089
+ /**
18090
+ * Layout of the "more filters" popover: a list of filters that opens one at a time, with a back button (`drilldown`), or
18091
+ * collapsible sections (`accordion`). Relayed as-is to `<MoreButton [layout]>`.
18092
+ *
18093
+ * @default "drilldown"
18094
+ */
18095
+ moreLayout: import("@angular/core").InputSignal<MoreLayout>;
18096
+ /**
18097
+ * Whether every selection gesture in the "more filters" popover applies the filter immediately, instead of revealing the
18098
+ * Apply button. Relayed as-is to `<MoreButton [applyOnSelect]>`.
18099
+ *
18100
+ * @default false
18101
+ */
18102
+ applyOnSelect: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18103
+ /**
18104
+ * Whether a section of the "more filters" popover removes itself when its aggregation has no item.
18105
+ * Relayed as-is to `<MoreButton [hideWhenEmpty]>`.
18106
+ *
18107
+ * @default false
18108
+ */
18109
+ hideWhenEmpty: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17479
18110
  /**
17480
18111
  * The distance in pixels between the popover and its trigger element.
17481
18112
  *
@@ -17494,6 +18125,8 @@ export declare class FiltersBarComponent {
17494
18125
  */
17495
18126
  onClearBasket: import("@angular/core").OutputEmitterRef<void>;
17496
18127
  protected cn: import("cn").CnFunction;
18128
+ /** The gap between the buttons: the 20px of a home page under `comfortable`, the tight spacing of a toolbar otherwise. */
18129
+ protected readonly pillGap: import("@angular/core").Signal<"gap-(--spacing-lg)" | "gap-2">;
17497
18130
  protected readonly moreButtonRef: import("@angular/core").Signal<MoreButtonComponent | undefined>;
17498
18131
  protected readonly overflowManagerRef: import("@angular/core").Signal<OverflowManagerDirective | undefined>;
17499
18132
  protected cdr: ChangeDetectorRef;
@@ -17851,7 +18484,7 @@ export declare class FiltersBarComponent {
17851
18484
  relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
17852
18485
  removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
17853
18486
  queryId?: import("@angular/core").Signal<string | undefined> | undefined;
17854
- aggregations?: import("@angular/core").Signal<string[] | Record<string, import("@sinequa/atomic").AggregationOptions> | undefined> | undefined;
18487
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
17855
18488
  orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
17856
18489
  groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
17857
18490
  neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
@@ -17943,6 +18576,11 @@ export declare class FiltersBarComponent {
17943
18576
  protected hasFilters: import("@angular/core").Signal<string | boolean>;
17944
18577
  protected currentBasket: import("@angular/core").Signal<string | undefined>;
17945
18578
  protected hasAggregations: import("@angular/core").Signal<boolean>;
18579
+ /**
18580
+ * Whether the bar has anything to show: an applied filter, a basket or aggregations to filter on.
18581
+ * The toolbar is rendered only then, so a page can tell whether to reserve room for the bar.
18582
+ */
18583
+ readonly hasContent: import("@angular/core").Signal<boolean>;
17946
18584
  /**
17947
18585
  * The full list of authorized filters, NOT capped by `filtersCount`.
17948
18586
  *
@@ -18069,84 +18707,43 @@ export declare class FiltersBarComponent {
18069
18707
  "required": false;
18070
18708
  "isSignal": true;
18071
18709
  };
18072
- "offset": {
18073
- "alias": "offset";
18710
+ "appearance": {
18711
+ "alias": "appearance";
18074
18712
  "required": false;
18075
18713
  "isSignal": true;
18076
18714
  };
18077
- "expandedLevel": {
18078
- "alias": "expandedLevel";
18715
+ "align": {
18716
+ "alias": "align";
18079
18717
  "required": false;
18080
18718
  "isSignal": true;
18081
18719
  };
18082
- }, {
18083
- "onClearFilters": "onClearFilters";
18084
- "onClearBasket": "onClearBasket";
18085
- }, never, never, true, never>;
18086
- }
18087
- export declare class MoreComponent {
18088
- protected readonly SEARCH_THRESHOLD = 6;
18089
- count: import("@angular/core").InputSignal<number>;
18090
- includedFilters: import("@angular/core").InputSignal<string[]>;
18091
- excludedFilters: import("@angular/core").InputSignal<string[]>;
18092
- aggregations: import("@angular/core").InputSignal<Aggregation[] | undefined>;
18093
- homepage: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18094
- /**
18095
- * Whether a section removes itself from the layout when its aggregation
18096
- * resolves to zero items, instead of staying with a dimmed, non-expandable
18097
- * header. Relayed as-is to each `<Aggregation [hideWhenEmpty]>` — a missing
18098
- * aggregation always hides regardless of this input.
18099
- *
18100
- * @default false
18101
- */
18102
- hideWhenEmpty: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18103
- aggregationsService: AggregationsService;
18104
- /** The facet-name search query, cleared whenever the popup is reopened. */
18105
- searchText: import("@angular/core").ModelSignal<string>;
18106
- /**
18107
- * The overflow filters rendered as accordions: the authorized filters beyond the
18108
- * first `count` (which are already shown in the bar).
18109
- *
18110
- * @remarks
18111
- * Pure display wiring — authorization (and the admin `hidden` rule) is handled by
18112
- * {@link AggregationsService.getAuthorizedFilters}; `toSpliced` just drops the
18113
- * filters already shown in the bar.
18114
- */
18115
- filters: import("@angular/core").Signal<{
18116
- field: string;
18117
- column: string;
18118
- name: string;
18119
- }[]>;
18120
- /** {@link filters}, narrowed to those whose name matches {@link searchText}. */
18121
- filteredFilters: import("@angular/core").Signal<{
18122
- field: string;
18123
- column: string;
18124
- name: string;
18125
- }[]>;
18126
- static ɵfac: i0.ɵɵFactoryDeclaration<MoreComponent, never>;
18127
- static ɵcmp: i0.ɵɵComponentDeclaration<MoreComponent, "more, More", never, {
18128
- "count": {
18129
- "alias": "count";
18720
+ "spacing": {
18721
+ "alias": "spacing";
18130
18722
  "required": false;
18131
18723
  "isSignal": true;
18132
18724
  };
18133
- "includedFilters": {
18134
- "alias": "includedFilters";
18725
+ "scheme": {
18726
+ "alias": "scheme";
18135
18727
  "required": false;
18136
18728
  "isSignal": true;
18137
18729
  };
18138
- "excludedFilters": {
18139
- "alias": "excludedFilters";
18730
+ "showClearButtons": {
18731
+ "alias": "showClearButtons";
18140
18732
  "required": false;
18141
18733
  "isSignal": true;
18142
18734
  };
18143
- "aggregations": {
18144
- "alias": "aggregations";
18735
+ "enrichedThreshold": {
18736
+ "alias": "enrichedThreshold";
18145
18737
  "required": false;
18146
18738
  "isSignal": true;
18147
18739
  };
18148
- "homepage": {
18149
- "alias": "homepage";
18740
+ "moreLayout": {
18741
+ "alias": "moreLayout";
18742
+ "required": false;
18743
+ "isSignal": true;
18744
+ };
18745
+ "applyOnSelect": {
18746
+ "alias": "applyOnSelect";
18150
18747
  "required": false;
18151
18748
  "isSignal": true;
18152
18749
  };
@@ -18155,13 +18752,93 @@ export declare class MoreComponent {
18155
18752
  "required": false;
18156
18753
  "isSignal": true;
18157
18754
  };
18158
- "searchText": {
18159
- "alias": "searchText";
18755
+ "offset": {
18756
+ "alias": "offset";
18757
+ "required": false;
18758
+ "isSignal": true;
18759
+ };
18760
+ "expandedLevel": {
18761
+ "alias": "expandedLevel";
18160
18762
  "required": false;
18161
18763
  "isSignal": true;
18162
18764
  };
18163
18765
  }, {
18164
- "searchText": "searchTextChange";
18766
+ "onClearFilters": "onClearFilters";
18767
+ "onClearBasket": "onClearBasket";
18768
+ }, never, ["[filtersBarStart]"], true, never>;
18769
+ }
18770
+ type FiltersTab = "all" | "quick";
18771
+ /**
18772
+ * The filters panel: the facets of the search, and the quick filters of the user, in one card-sized column.
18773
+ *
18774
+ * "All" holds the facets (`<aside-filters>`, driven by the application's filters configuration) with a field that narrows them by
18775
+ * name, the count of documents, and a button that saves the filters applied right now as a quick filter (a card under the button
18776
+ * asks for its name). "Quick Filters" is the list of the `<quick-filters>` pill, inline (`<quick-filters-list>`): one line per quick filter, with the
18777
+ * count of its filters — hovering it shows them as tags — and a cross that deletes it. A click on a quick filter replaces **all** the
18778
+ * applied filters by its own and keeps the rest of the query, the text above all.
18779
+ *
18780
+ * The panel is the content only: it fills the height it is given and scrolls inside. Where it goes — a column next to the results, an
18781
+ * overlay, a sheet — and what surrounds it are the host's. The host closes it on `closed`.
18782
+ *
18783
+ * ```html
18784
+ * <filters-panel [documentCount]="result()?.rowCount ?? 0" (closed)="open.set(false)" />
18785
+ * ```
18786
+ */
18787
+ export declare class FiltersPanelComponent {
18788
+ /**
18789
+ * How many documents the search found: the count under the field, which is also what a quick filter would be saved over. The panel
18790
+ * does not run the search, the page does.
18791
+ */
18792
+ readonly documentCount: import("@angular/core").InputSignal<number>;
18793
+ /** The user closes the panel (the cross of its header). Closing is the host's: it decides how the panel is shown. */
18794
+ readonly closed: import("@angular/core").OutputEmitterRef<void>;
18795
+ private readonly appStore;
18796
+ private readonly aggregationsStore;
18797
+ private readonly queryParamsStore;
18798
+ private readonly userSettingsStore;
18799
+ private readonly transloco;
18800
+ private readonly injector;
18801
+ protected readonly nameId: string;
18802
+ protected readonly tab: import("@angular/core").WritableSignal<FiltersTab>;
18803
+ protected readonly query: import("@angular/core").WritableSignal<string>;
18804
+ protected readonly saving: import("@angular/core").WritableSignal<boolean>;
18805
+ protected readonly announcement: import("@angular/core").WritableSignal<string>;
18806
+ protected readonly name: import("@angular/core").WritableSignal<string>;
18807
+ /** How many values the query is filtered by: nothing to save as a quick filter when it is zero. */
18808
+ protected readonly appliedCount: import("@angular/core").Signal<number>;
18809
+ private readonly nameInput;
18810
+ private readonly saveButton;
18811
+ /**
18812
+ * The facets whose name contains the query, as the names `<aside-filters [aggregations]>` takes.
18813
+ * Empty query → the component's own configuration-driven list (the input is left empty).
18814
+ *
18815
+ * An explicit list bypasses the `position` and "hidden" rules of that configuration, so the same two
18816
+ * rules are applied here first.
18817
+ */
18818
+ protected readonly matching: import("@angular/core").Signal<string[]>;
18819
+ protected selectTab(values: readonly string[]): void;
18820
+ /** The leaf filters of an entry, flattening a nested and/or tree. */
18821
+ private leaves;
18822
+ /** How many values a leaf holds: an `in` list holds several, anything else one. */
18823
+ private valuesOf;
18824
+ /** Opens the card under the button and puts the focus in its field: it appears at the user's request, so the next key is the name. */
18825
+ protected startSaving(): void;
18826
+ /** Closes the card without saving, and gives the focus back to the button that opened it. */
18827
+ protected closeSaving(): void;
18828
+ /** Escape closes the card, not the whole filters panel the card is in. */
18829
+ protected onSaveEscape(event: Event): void;
18830
+ protected saveQuickFilter(event: Event): Promise<void>;
18831
+ /** The list applied a quick filter (it replaced the filters of the query by its own): the screen readers are told. */
18832
+ protected onQuickFilterApplied(quickFilter: QuickFilter): void;
18833
+ static ɵfac: i0.ɵɵFactoryDeclaration<FiltersPanelComponent, never>;
18834
+ static ɵcmp: i0.ɵɵComponentDeclaration<FiltersPanelComponent, "filters-panel, FiltersPanel, filterspanel", never, {
18835
+ "documentCount": {
18836
+ "alias": "documentCount";
18837
+ "required": false;
18838
+ "isSignal": true;
18839
+ };
18840
+ }, {
18841
+ "closed": "closed";
18165
18842
  }, never, never, true, never>;
18166
18843
  }
18167
18844
  /**
@@ -18201,7 +18878,1067 @@ export declare class LabelService {
18201
18878
  _: import("@sinequa/atomic").CCIndex;
18202
18879
  } & Record<string, import("@sinequa/atomic").CCIndex>>;
18203
18880
  lists: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCList>>;
18204
- webServices: import("@angular/core").Signal<Record<string, CCWebService>>;
18881
+ webServices: import("@angular/core").Signal<Record<string, CCWebService>>;
18882
+ queryNames: import("@angular/core").Signal<string>;
18883
+ labels: import("@angular/core").Signal<string>;
18884
+ preview: import("@angular/core").Signal<string>;
18885
+ autocomplete: import("@angular/core").Signal<string>;
18886
+ sponsoredLinks: import("@angular/core").Signal<string>;
18887
+ queryExport: import("@angular/core").Signal<string>;
18888
+ queryRssEnabled: import("@angular/core").Signal<boolean>;
18889
+ data: import("@angular/core").Signal<Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
18890
+ filters?: import("@sinequa/atomic-angular").CAggregation[];
18891
+ autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
18892
+ tabs?: Record<string, {
18893
+ filters: string[];
18894
+ overviews?: Record<string, {
18895
+ minRelevance: number;
18896
+ }>;
18897
+ }>;
18898
+ sources?: import("@sinequa/atomic-angular").CSources;
18899
+ features?: {
18900
+ [key: string]: boolean | {
18901
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
18902
+ } | undefined;
18903
+ allowChangePassword?: boolean;
18904
+ editablepartition?: boolean;
18905
+ advancedSearch?: boolean;
18906
+ allowChatDrawer?: boolean;
18907
+ filterLinkChildren?: boolean;
18908
+ expandPreview?: boolean;
18909
+ quickFilter?: boolean;
18910
+ showAggregationItemCount?: boolean;
18911
+ assistant?: {
18912
+ usePrefixName?: boolean;
18913
+ };
18914
+ filters?: {
18915
+ homepage?: boolean;
18916
+ };
18917
+ userProfile?: {
18918
+ enabled?: boolean;
18919
+ data?: string[];
18920
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
18921
+ };
18922
+ previewMultiConversion?: boolean;
18923
+ persistFiltersAcrossTabs?: boolean;
18924
+ };
18925
+ allowAdvancedFilters?: boolean;
18926
+ general?: {
18927
+ name?: string;
18928
+ logo?: {
18929
+ alt?: string;
18930
+ light?: {
18931
+ small?: string;
18932
+ large?: string;
18933
+ sidebar?: string;
18934
+ };
18935
+ dark?: {
18936
+ small?: string;
18937
+ large?: string;
18938
+ sidebar?: string;
18939
+ };
18940
+ };
18941
+ features?: {
18942
+ [key: string]: boolean | {
18943
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
18944
+ } | undefined;
18945
+ allowChangePassword?: boolean;
18946
+ editablepartition?: boolean;
18947
+ advancedSearch?: boolean;
18948
+ allowChatDrawer?: boolean;
18949
+ filterLinkChildren?: boolean;
18950
+ expandPreview?: boolean;
18951
+ quickFilter?: boolean;
18952
+ showAggregationItemCount?: boolean;
18953
+ assistant?: {
18954
+ usePrefixName?: boolean;
18955
+ };
18956
+ filters?: {
18957
+ homepage?: boolean;
18958
+ };
18959
+ userProfile?: {
18960
+ enabled?: boolean;
18961
+ data?: string[];
18962
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
18963
+ };
18964
+ previewMultiConversion?: boolean;
18965
+ persistFiltersAcrossTabs?: boolean;
18966
+ };
18967
+ converters?: import("@sinequa/atomic-angular").CConverter[];
18968
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
18969
+ };
18970
+ documentsUploadSettings?: {
18971
+ enabled?: boolean;
18972
+ };
18973
+ }>;
18974
+ customJSONs: import("@angular/core").Signal<{
18975
+ name: string;
18976
+ data: Record<string, unknown>;
18977
+ }[] & import("@sinequa/atomic-angular").SideCJson[]>;
18978
+ apiVersion: import("@angular/core").Signal<string>;
18979
+ workspaceApp: import("@angular/core").Signal<string>;
18980
+ defaultQueryName: import("@angular/core").Signal<string>;
18981
+ auditEnabled?: import("@angular/core").Signal<boolean | undefined> | undefined;
18982
+ dataSets?: import("@angular/core").Signal<string | undefined> | undefined;
18983
+ revision?: import("@angular/core").Signal<number | undefined> | undefined;
18984
+ runnableModels?: import("@angular/core").Signal<string | undefined> | undefined;
18985
+ authorizationLevel?: import("@angular/core").Signal<string | undefined> | undefined;
18986
+ columnMap?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCColumn> | undefined> | undefined;
18987
+ customizationJson: import("@angular/core").Signal<import("@sinequa/atomic-angular").CJsonMint>;
18988
+ sources: import("@angular/core").Signal<import("@sinequa/atomic-angular").CSources>;
18989
+ filters: import("@angular/core").Signal<import("@sinequa/atomic-angular").CFilter[]>;
18990
+ general: import("@angular/core").Signal<{
18991
+ name?: string;
18992
+ logo?: {
18993
+ alt?: string;
18994
+ light?: {
18995
+ small?: string;
18996
+ large?: string;
18997
+ sidebar?: string;
18998
+ };
18999
+ dark?: {
19000
+ small?: string;
19001
+ large?: string;
19002
+ sidebar?: string;
19003
+ };
19004
+ };
19005
+ features?: {
19006
+ [key: string]: boolean | {
19007
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
19008
+ } | undefined;
19009
+ allowChangePassword?: boolean;
19010
+ editablepartition?: boolean;
19011
+ advancedSearch?: boolean;
19012
+ allowChatDrawer?: boolean;
19013
+ filterLinkChildren?: boolean;
19014
+ expandPreview?: boolean;
19015
+ quickFilter?: boolean;
19016
+ showAggregationItemCount?: boolean;
19017
+ assistant?: {
19018
+ usePrefixName?: boolean;
19019
+ };
19020
+ filters?: {
19021
+ homepage?: boolean;
19022
+ };
19023
+ userProfile?: {
19024
+ enabled?: boolean;
19025
+ data?: string[];
19026
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
19027
+ };
19028
+ previewMultiConversion?: boolean;
19029
+ persistFiltersAcrossTabs?: boolean;
19030
+ };
19031
+ converters?: import("@sinequa/atomic-angular").CConverter[];
19032
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
19033
+ } | undefined>;
19034
+ assistants: import("@angular/core").Signal<{
19035
+ [x: string]: import("@sinequa/atomic-angular").AssistantDetails;
19036
+ }>;
19037
+ agents: import("@angular/core").Signal<{
19038
+ [x: string]: {
19039
+ defaultAgent: string;
19040
+ };
19041
+ }>;
19042
+ initialize: () => Promise<undefined>;
19043
+ hydrate: (app: import("@sinequa/atomic").CCApp) => void;
19044
+ fail: (error: unknown) => never;
19045
+ initializeWithAppName: (appName: string) => Promise<void>;
19046
+ update: (app: Partial<import("@sinequa/atomic-angular").CCAppState>) => void;
19047
+ getWebServiceByType: (type: CCWebService["webServiceType"]) => CCWebService | undefined;
19048
+ getLabels: () => {
19049
+ private: string;
19050
+ public: string;
19051
+ };
19052
+ getQueryByName: (name: string | undefined) => import("@sinequa/atomic").CCQuery | undefined;
19053
+ getQueryByIndex: (index: number) => import("@sinequa/atomic").CCQuery | undefined;
19054
+ getDefaultQuery: () => import("@sinequa/atomic").CCQuery | undefined;
19055
+ allowEmptySearch: (queryName: string) => boolean;
19056
+ enableFieldedSearch: (queryName: string) => boolean;
19057
+ allowLabels: () => boolean;
19058
+ getColumnAlias: (column: string) => string;
19059
+ getColumn: (columnOrAlias: string) => import("@sinequa/atomic").CCColumn | undefined;
19060
+ isDateColumn: (column: string) => boolean;
19061
+ isTabSearch: (queryName: string) => boolean;
19062
+ getAggregationCount: (queryName: string | undefined, aggregationName: string) => number;
19063
+ getAuthorizedFilters: () => import("@sinequa/atomic").Aggregation[];
19064
+ getAuthorized: (filters: Pick<import("@sinequa/atomic-angular").CFilter, "column" | "name">[]) => import("@sinequa/atomic").Aggregation[];
19065
+ getNamedCustomizationJson: (name: string) => unknown | undefined;
19066
+ getAggregationIcon: (column: string) => string | undefined;
19067
+ getAggregationItemsCustomization: (column: string) => import("@sinequa/atomic-angular").CFilterItem[] | undefined;
19068
+ getAggregationCustomization: (aggColumn: string, aggName?: string) => import("@sinequa/atomic-angular").CFilter | undefined;
19069
+ isAssistantAllowed: (assistantName: string) => boolean;
19070
+ isAgentAllowed: (agentName: string) => boolean;
19071
+ } & import("@ngrx/signals").StateSource<{
19072
+ name: string;
19073
+ description?: string | undefined;
19074
+ versionId: string;
19075
+ queries: Record<string, import("@sinequa/atomic").CCQuery>;
19076
+ rfms: Record<string, import("@sinequa/atomic").CCRFM>;
19077
+ indexes: {
19078
+ _: import("@sinequa/atomic").CCIndex;
19079
+ } & Record<string, import("@sinequa/atomic").CCIndex>;
19080
+ lists: Record<string, import("@sinequa/atomic").CCList>;
19081
+ webServices: Record<string, CCWebService>;
19082
+ queryNames: string;
19083
+ labels: string;
19084
+ preview: string;
19085
+ autocomplete: string;
19086
+ sponsoredLinks: string;
19087
+ queryExport: string;
19088
+ queryRssEnabled: boolean;
19089
+ data: Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
19090
+ filters?: import("@sinequa/atomic-angular").CAggregation[];
19091
+ autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
19092
+ tabs?: Record<string, {
19093
+ filters: string[];
19094
+ overviews?: Record<string, {
19095
+ minRelevance: number;
19096
+ }>;
19097
+ }>;
19098
+ sources?: import("@sinequa/atomic-angular").CSources;
19099
+ features?: {
19100
+ [key: string]: boolean | {
19101
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
19102
+ } | undefined;
19103
+ allowChangePassword?: boolean;
19104
+ editablepartition?: boolean;
19105
+ advancedSearch?: boolean;
19106
+ allowChatDrawer?: boolean;
19107
+ filterLinkChildren?: boolean;
19108
+ expandPreview?: boolean;
19109
+ quickFilter?: boolean;
19110
+ showAggregationItemCount?: boolean;
19111
+ assistant?: {
19112
+ usePrefixName?: boolean;
19113
+ };
19114
+ filters?: {
19115
+ homepage?: boolean;
19116
+ };
19117
+ userProfile?: {
19118
+ enabled?: boolean;
19119
+ data?: string[];
19120
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
19121
+ };
19122
+ previewMultiConversion?: boolean;
19123
+ persistFiltersAcrossTabs?: boolean;
19124
+ };
19125
+ allowAdvancedFilters?: boolean;
19126
+ general?: {
19127
+ name?: string;
19128
+ logo?: {
19129
+ alt?: string;
19130
+ light?: {
19131
+ small?: string;
19132
+ large?: string;
19133
+ sidebar?: string;
19134
+ };
19135
+ dark?: {
19136
+ small?: string;
19137
+ large?: string;
19138
+ sidebar?: string;
19139
+ };
19140
+ };
19141
+ features?: {
19142
+ [key: string]: boolean | {
19143
+ [key: string]: string | boolean | string[] | import("@sinequa/atomic-angular").CustomDataEntry[] | undefined;
19144
+ } | undefined;
19145
+ allowChangePassword?: boolean;
19146
+ editablepartition?: boolean;
19147
+ advancedSearch?: boolean;
19148
+ allowChatDrawer?: boolean;
19149
+ filterLinkChildren?: boolean;
19150
+ expandPreview?: boolean;
19151
+ quickFilter?: boolean;
19152
+ showAggregationItemCount?: boolean;
19153
+ assistant?: {
19154
+ usePrefixName?: boolean;
19155
+ };
19156
+ filters?: {
19157
+ homepage?: boolean;
19158
+ };
19159
+ userProfile?: {
19160
+ enabled?: boolean;
19161
+ data?: string[];
19162
+ customData?: import("@sinequa/atomic-angular").CustomDataEntry[];
19163
+ };
19164
+ previewMultiConversion?: boolean;
19165
+ persistFiltersAcrossTabs?: boolean;
19166
+ };
19167
+ converters?: import("@sinequa/atomic-angular").CConverter[];
19168
+ feedback?: import("@sinequa/atomic-angular").CFeedback;
19169
+ };
19170
+ documentsUploadSettings?: {
19171
+ enabled?: boolean;
19172
+ };
19173
+ };
19174
+ customJSONs: {
19175
+ name: string;
19176
+ data: Record<string, unknown>;
19177
+ }[] & import("@sinequa/atomic-angular").SideCJson[];
19178
+ apiVersion: string;
19179
+ workspaceApp: string;
19180
+ defaultQueryName: string;
19181
+ auditEnabled?: boolean | undefined;
19182
+ dataSets?: string | undefined;
19183
+ revision?: number | undefined;
19184
+ runnableModels?: string | undefined;
19185
+ authorizationLevel?: string | undefined;
19186
+ columnMap?: Record<string, import("@sinequa/atomic").CCColumn> | undefined;
19187
+ }>;
19188
+ private readonly client;
19189
+ hasAccess: import("@angular/core").WritableSignal<boolean | undefined>;
19190
+ /**
19191
+ * Check user rights to verify if they can access labels handling
19192
+ * @returns if has the rights
19193
+ */
19194
+ canHandleLabels(): Promise<boolean>;
19195
+ /**
19196
+ * Get relevant config info from the labels web service
19197
+ * @returns the LabelsConfig or undefined if no rights
19198
+ */
19199
+ getLabelsConfig(): Observable<LabelsConfig | undefined>;
19200
+ /**
19201
+ * Fetch labels from string
19202
+ * @param prefix the string prefix to filter with
19203
+ * @param publicOnly whether they should be public or not
19204
+ * @param locale optional locale filtering
19205
+ * @returns list of label strings
19206
+ */
19207
+ fetch(prefix: string, publicOnly?: boolean, locale?: string): Observable<string[]>;
19208
+ /**
19209
+ * Add some labels to many documents
19210
+ * @param labelsToAdd list of labels to add
19211
+ * @param ids list of document id to add the label
19212
+ * @param publicOnly whether the operation should be public only
19213
+ * @returns a promise that resolves when the operation is complete
19214
+ */
19215
+ add(labelsToAdd: string[], ids: string[], publicOnly?: boolean): Observable<void>;
19216
+ /**
19217
+ * Remove some labels from many documents
19218
+ * @param labelsToRemove list of labels to remove
19219
+ * @param ids list of document id to add the label
19220
+ * @param publicOnly whether the operation should be public only
19221
+ * @returns a promise that resolves when the operation is complete
19222
+ */
19223
+ remove(labelsToRemove: string[], ids: string[], publicOnly?: boolean): Observable<void>;
19224
+ /**
19225
+ * Name some labels to a new name
19226
+ * @param labelsToRename list of labels to rename
19227
+ * @param newLabel the new label name
19228
+ * @param publicOnly whether the operation should be public only
19229
+ * @returns a promise that resolves when the operation is complete
19230
+ */
19231
+ rename(labelsToRename: string[], newLabel: string, publicOnly?: boolean): Observable<void>;
19232
+ /**
19233
+ * Delete some labels
19234
+ * @param labelsToDelete the labels to delete
19235
+ * @param publicOnly whether the operation should be public only
19236
+ * @returns a promise that resolves when the operation is complete
19237
+ */
19238
+ delete(labelsToDelete: string[], publicOnly?: boolean): Observable<void>;
19239
+ /**
19240
+ * Create some labels for a query
19241
+ * @param labelstoAdd the labels to create
19242
+ * @param query the query object to which the labels will be added
19243
+ * @param publicOnly whether the operation should be public only
19244
+ * @returns a promise that resolves when the operation is complete
19245
+ */
19246
+ bulkAdd(labelstoAdd: string[], query: Query, publicOnly?: boolean): Observable<void>;
19247
+ /**
19248
+ * Delete some labels from a query
19249
+ * @param labelsToRemove the labels to remove
19250
+ * @param query the query object to which the labels will be removed
19251
+ * @param publicOnly whether the operation should be public only
19252
+ * @returns a promise that resolves when the operation is complete
19253
+ */
19254
+ bulkRemove(labelsToRemove: string[], query: Query, publicOnly?: boolean): Observable<void>;
19255
+ static ɵfac: i0.ɵɵFactoryDeclaration<LabelService, never>;
19256
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
19257
+ }
19258
+ /** Result of an edit-labels call: the close event plus the (possibly edited) article. */
19259
+ export interface LabelsEditResult {
19260
+ type: DialogEvent;
19261
+ article: Article;
19262
+ }
19263
+ export declare class LabelsEditDialog {
19264
+ protected readonly call: import("@sinequa/galactik").CallRef<Article, LabelsEditResult>;
19265
+ readonly dialog: import("@angular/core").Signal<DialogComponent | undefined>;
19266
+ labelService: LabelService;
19267
+ readonly article: import("@angular/core").ModelSignal<Article>;
19268
+ readonly labelsConfig: import("@angular/core").WritableSignal<LabelsConfig | undefined>;
19269
+ private readonly destroyRef;
19270
+ constructor();
19271
+ close(event: DialogEvent): void;
19272
+ static ɵfac: i0.ɵɵFactoryDeclaration<LabelsEditDialog, never>;
19273
+ static ɵcmp: i0.ɵɵComponentDeclaration<LabelsEditDialog, "labels-edit-dialog, labelseditdialog, LabelsEditDialog", never, {
19274
+ "article": {
19275
+ "alias": "article";
19276
+ "required": false;
19277
+ "isSignal": true;
19278
+ };
19279
+ }, {
19280
+ "article": "articleChange";
19281
+ }, never, never, true, never>;
19282
+ }
19283
+ /** Imperative entry point: `await EditLabels.call(article)` → resolves with `{ type, article }`. */
19284
+ export declare const EditLabels: import("@sinequa/galactik").Callable<Article, LabelsEditResult>;
19285
+ type Article$1 = Article & {
19286
+ [key: string]: unknown;
19287
+ };
19288
+ export declare class MultiSelectLabelsComponent {
19289
+ injector: Injector;
19290
+ private readonly client;
19291
+ article: import("@angular/core").ModelSignal<Article$1 | undefined>;
19292
+ isPublic: import("@angular/core").InputSignal<boolean>;
19293
+ allowModification: import("@angular/core").InputSignal<boolean>;
19294
+ labelsField: import("@angular/core").InputSignal<string | undefined>;
19295
+ protected labels: import("@angular/core").WritableSignal<string[]>;
19296
+ protected hasError: import("@angular/core").WritableSignal<boolean>;
19297
+ protected readonly identity: (label: string) => string;
19298
+ protected readonly loadSuggestions: (query: string) => Promise<string[]>;
19299
+ constructor();
19300
+ protected onPicked(label: string): void;
19301
+ protected onRemoved(label: string): void;
19302
+ /**
19303
+ * Adds a new label to the current list of labels and updates the associated article.
19304
+ *
19305
+ * This method performs the following steps:
19306
+ * 1. Updates the local labels state by appending the new label.
19307
+ * 2. Persists the new label to the backend, associating it with the current article.
19308
+ * 3. Refreshes the article's label data.
19309
+ *
19310
+ * @param label - The label to be added.
19311
+ * @param isPublic - A boolean indicating whether the label is public or private.
19312
+ * @returns A promise that resolves once the label has been added and the article updated.
19313
+ */
19314
+ addLabel(label: string, isPublic: boolean): Promise<void>;
19315
+ /**
19316
+ * Removes a label from the current list of labels and updates the associated article.
19317
+ *
19318
+ * @param label - The label to be removed.
19319
+ * @param isPublic - A boolean indicating whether the label is public.
19320
+ * @returns A promise that resolves once the label is removed and the article is updated.
19321
+ */
19322
+ removeLabel(label: string, isPublic: boolean): Promise<void>;
19323
+ /**
19324
+ * Updates the article object by assigning the current labels to the specified labels field.
19325
+ *
19326
+ * This method retrieves the article object and the labels field dynamically,
19327
+ * then assigns the current labels to the corresponding field in the article.
19328
+ *
19329
+ * @remarks
19330
+ * Ensure that `this.article`, `this.labelsField`, and `this.labels` return valid values
19331
+ * before invoking this method to avoid runtime errors.
19332
+ *
19333
+ */
19334
+ updateArticleWithLabels(): void;
19335
+ static ɵfac: i0.ɵɵFactoryDeclaration<MultiSelectLabelsComponent, never>;
19336
+ static ɵcmp: i0.ɵɵComponentDeclaration<MultiSelectLabelsComponent, "multiselect-labels, multiselectlabels, MultiSelectLabels", never, {
19337
+ "article": {
19338
+ "alias": "article";
19339
+ "required": false;
19340
+ "isSignal": true;
19341
+ };
19342
+ "isPublic": {
19343
+ "alias": "isPublic";
19344
+ "required": false;
19345
+ "isSignal": true;
19346
+ };
19347
+ "allowModification": {
19348
+ "alias": "allowModification";
19349
+ "required": false;
19350
+ "isSignal": true;
19351
+ };
19352
+ "labelsField": {
19353
+ "alias": "labelsField";
19354
+ "required": false;
19355
+ "isSignal": true;
19356
+ };
19357
+ }, {
19358
+ "article": "articleChange";
19359
+ }, never, never, true, never>;
19360
+ }
19361
+ /**
19362
+ * Inputs handed to whichever component a host app plugs into a `PreviewTabsComponent` assistant
19363
+ * slot ("summary" or "discussion"). `onStreamingChange` stands in for an `@Output` — `NgComponentOutlet`
19364
+ * only binds inputs, so a streaming notification is passed down as a callback the mounted component
19365
+ * calls itself, rather than an Angular event binding.
19366
+ */
19367
+ export type PreviewAssistantInputs = {
19368
+ instanceId: string;
19369
+ query: Query;
19370
+ showAssistant: boolean;
19371
+ onStreamingChange?: (streaming: boolean) => void;
19372
+ };
19373
+ export type PreviewAssistantSlot = {
19374
+ component: Type<unknown>;
19375
+ inputs: PreviewAssistantInputs;
19376
+ };
19377
+ /**
19378
+ * Resolves the component (and its inputs) to mount in a `PreviewTabsComponent` assistant tab, for
19379
+ * a given kind. Returning `undefined` hides that tab entirely — a host app with no assistant feature
19380
+ * provides a function that always returns `undefined`, or omits the "discussion" case.
19381
+ */
19382
+ export declare const PREVIEW_ASSISTANT_COMPONENT: InjectionToken<(kind: "summary" | "discussion") => PreviewAssistantSlot | undefined>;
19383
+ /** What the panel lists: every recent search, or only the ones marked as favorite. */
19384
+ export type HistoryPanelTab = "all" | "favorites";
19385
+ /** A run of searches that share a day (today, yesterday) or, further back, a month. */
19386
+ export type HistoryGroup = {
19387
+ kind: "today" | "yesterday" | "month";
19388
+ /** The month, already formatted for the active language (`kind === "month"` only). */
19389
+ label?: string;
19390
+ items: SearchItem[];
19391
+ };
19392
+ /**
19393
+ * Splits searches (already sorted, most recent first) into today, yesterday and one group per month,
19394
+ * keeping their order. A search without a valid date is listed with the oldest month's group it
19395
+ * follows, so nothing is dropped.
19396
+ */
19397
+ export declare function groupSearchesByDate(searches: SearchItem[], language: string, now?: Date): HistoryGroup[];
19398
+ /**
19399
+ * Scrolls a title that is cut off, while its row is hovered or holds the focus.
19400
+ *
19401
+ * The title is a clipped box (`[historyTitleMarquee]`) holding an inner element; when the text is wider than the box,
19402
+ * the inner element slides to its end at a reading pace, and goes back when the pointer or the focus leaves. A title
19403
+ * that fits is left alone, and so is everything under `prefers-reduced-motion`. It reads the geometry when it starts,
19404
+ * so a resized panel or a changed language needs nothing.
19405
+ */
19406
+ export declare class HistoryTitleMarqueeDirective {
19407
+ private readonly host;
19408
+ private animation?;
19409
+ protected start(): void;
19410
+ protected stop(): void;
19411
+ static ɵfac: i0.ɵɵFactoryDeclaration<HistoryTitleMarqueeDirective, never>;
19412
+ static ɵdir: i0.ɵɵDirectiveDeclaration<HistoryTitleMarqueeDirective, "[historyTitleMarquee]", never, {}, {}, never, never, true, never>;
19413
+ }
19414
+ /**
19415
+ * Side panel listing the user's recent searches, with a switch to show only the favorite ones.
19416
+ *
19417
+ * It is a plain flex child that grows from `0` to `--history-panel-width` when `open` turns true,
19418
+ * so placed beside a sidebar it pushes the page content aside rather than covering it. Closed, it is
19419
+ * `inert` and hidden from assistive technology. On mobile it becomes a `Sheet` sliding from the left.
19420
+ *
19421
+ * The data is the user's own: recent searches and favorites come from `UserSettingsStore`, and a
19422
+ * click re-runs the search through the router, so the panel needs no wiring beyond `open`.
19423
+ *
19424
+ * Theming: every colour is a CSS variable with a semantic-token fallback, so the panel is a plain light card by
19425
+ * default and a host can retint it — a dark sidebar, say — by setting the variables on it (or an ancestor):
19426
+ * `--history-panel-bg`, `-fg`, `-muted` (header, labels, hints), `-icon`, `-hover`, `-active` (a row),
19427
+ * `-group` (the All / Favorites track), `-toggle-active`, `-toggle-hover`, `-toggle-fg`, `-fav`, `-fav-hover-bg`,
19428
+ * `-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
19429
+ * it takes on its start side while open (0 by default), for a layout whose neighbours do not space themselves.
19430
+ *
19431
+ * ```html
19432
+ * <app-sidebar />
19433
+ * <history-panel [(open)]="historyOpen" />
19434
+ * <main>…</main>
19435
+ * ```
19436
+ */
19437
+ export declare class HistoryPanelComponent {
19438
+ /** Whether the panel is shown. Two-way: the close button and `Escape` write it back. */
19439
+ readonly open: import("@angular/core").ModelSignal<boolean>;
19440
+ /** Which list is shown. Two-way. */
19441
+ readonly tab: import("@angular/core").ModelSignal<HistoryPanelTab>;
19442
+ /** Extra classes for the desktop `<aside>` (merged with `cn`). */
19443
+ readonly class: import("@angular/core").InputSignal<string | undefined>;
19444
+ /** Emitted once a search has been re-run from the panel — a host that overlays it can close it then. */
19445
+ readonly searchSelected: import("@angular/core").OutputEmitterRef<SearchItem>;
19446
+ protected readonly userSettingsStore: {
19447
+ bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
19448
+ favoriteSearches: import("@angular/core").Signal<string[]>;
19449
+ recentSearches: import("@angular/core").Signal<SearchItem[]>;
19450
+ savedSearches: import("@angular/core").Signal<SearchItem[]>;
19451
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
19452
+ baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
19453
+ assistants: import("@angular/core").Signal<Record<string, unknown>>;
19454
+ alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
19455
+ collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
19456
+ language?: import("@angular/core").Signal<string | undefined> | undefined;
19457
+ userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
19458
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
19459
+ disabledHighlightCategories: import("@angular/core").Signal<string[]>;
19460
+ isDebugMode: import("@angular/core").Signal<boolean>;
19461
+ isDarkMode: import("@angular/core").Signal<boolean>;
19462
+ updateBookmarks: (bookmarks: import("@sinequa/atomic-angular").UserSettingsState["bookmarks"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
19463
+ bookmark: (article: import("@sinequa/atomic").Article, queryName?: string) => Promise<void>;
19464
+ unbookmark: (id: string) => Promise<void>;
19465
+ isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
19466
+ toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
19467
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
19468
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
19469
+ deleteRecentSearch: (index: number) => Promise<void>;
19470
+ updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
19471
+ addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
19472
+ deleteSavedSearch: (index: number) => Promise<void>;
19473
+ updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
19474
+ getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
19475
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
19476
+ updateQuickFilter: (id: string, changes: {
19477
+ name?: string;
19478
+ filters?: import("@sinequa/atomic").LegacyFilter[];
19479
+ }) => Promise<void>;
19480
+ removeQuickFilter: (id: string) => Promise<void>;
19481
+ deleteBasket: (index: number) => Promise<void>;
19482
+ createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
19483
+ updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
19484
+ updateBasket: (basket: import("@sinequa/atomic-angular").Basket, index: number) => Promise<void>;
19485
+ addToBasket: (name: string, ids: string | string[]) => Promise<void>;
19486
+ removeFromBasket: (name: string, ids: string | string[]) => Promise<void>;
19487
+ updateAssistantSettings: (assistantSettings: import("@sinequa/atomic-angular").UserSettingsState["assistants"]) => Promise<void>;
19488
+ updateLanguage: (language: import("@sinequa/atomic-angular").UserSettingsState["language"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
19489
+ updateAssistantCollapsed: (collapseAssistant: import("@sinequa/atomic-angular").UserSettingsState["collapseAssistant"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
19490
+ hydrate: (settings: import("@sinequa/atomic-angular").UserSettingsState) => void;
19491
+ fail: (err: unknown) => void;
19492
+ initialize: () => Promise<void>;
19493
+ reset: () => Promise<void>;
19494
+ deleteAlert: (index: number) => Promise<void>;
19495
+ createAlert: (alert: import("@sinequa/atomic-angular").Alert) => Promise<void>;
19496
+ updateAlert: (alert: import("@sinequa/atomic-angular").Alert, index: number) => Promise<void>;
19497
+ updateAlerts: (alerts: import("@sinequa/atomic-angular").Alert[]) => Promise<void>;
19498
+ setDebugMode: (value: boolean) => Promise<void>;
19499
+ setUserTheme: (userTheme: "dark" | "light" | "system") => Promise<void>;
19500
+ toggleDarkMode: () => Promise<void>;
19501
+ setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
19502
+ } & import("@ngrx/signals").StateSource<{
19503
+ bookmarks: import("@sinequa/atomic-angular").Bookmark[];
19504
+ favoriteSearches: string[];
19505
+ recentSearches: SearchItem[];
19506
+ savedSearches: SearchItem[];
19507
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
19508
+ baskets: import("@sinequa/atomic-angular").Basket[];
19509
+ assistants: Record<string, unknown>;
19510
+ alerts: import("@sinequa/atomic-angular").Alert[];
19511
+ collapseAssistant?: boolean | undefined;
19512
+ language?: string | undefined;
19513
+ userTheme: "dark" | "light" | "system";
19514
+ agents: import("@sinequa/atomic-angular").AgentUserSettings;
19515
+ disabledHighlightCategories: string[];
19516
+ }>;
19517
+ private readonly transloco;
19518
+ private readonly router;
19519
+ private readonly breakpointObserver;
19520
+ private readonly sheet;
19521
+ protected readonly isMobile: import("@angular/core").Signal<boolean>;
19522
+ protected readonly sheetClasses: string;
19523
+ 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";
19524
+ 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";
19525
+ /**
19526
+ * Gives a `<history-panel>` an opening and closing animation that does not depend on the host
19527
+ * app: width, padding and margin ease out together, and reduced motion drops the movement. The panel is as tall as
19528
+ * the flex row it sits in; a host that insets its page content gives the panel the same margins.
19529
+ */
19530
+ protected readonly asideClasses: import("@angular/core").Signal<string>;
19531
+ protected readonly searches: import("@angular/core").Signal<SearchItem[]>;
19532
+ protected readonly groups: import("@angular/core").Signal<HistoryGroup[]>;
19533
+ /** Whether a delete is going out, so a second click on the same row is not sent twice. */
19534
+ private readonly deleting;
19535
+ constructor();
19536
+ protected titleOf: (search: SearchItem) => string;
19537
+ protected isFavorite: (search: SearchItem) => boolean;
19538
+ protected onTab(value: string[]): void;
19539
+ protected onEscape(event: Event): void;
19540
+ protected select(search: SearchItem): void;
19541
+ protected toggleFavorite(search: SearchItem): Promise<boolean>;
19542
+ protected remove(search: SearchItem): Promise<void>;
19543
+ static ɵfac: i0.ɵɵFactoryDeclaration<HistoryPanelComponent, never>;
19544
+ static ɵcmp: i0.ɵɵComponentDeclaration<HistoryPanelComponent, "HistoryPanel, history-panel", never, {
19545
+ "open": {
19546
+ "alias": "open";
19547
+ "required": false;
19548
+ "isSignal": true;
19549
+ };
19550
+ "tab": {
19551
+ "alias": "tab";
19552
+ "required": false;
19553
+ "isSignal": true;
19554
+ };
19555
+ "class": {
19556
+ "alias": "class";
19557
+ "required": false;
19558
+ "isSignal": true;
19559
+ };
19560
+ }, {
19561
+ "open": "openChange";
19562
+ "tab": "tabChange";
19563
+ "searchSelected": "searchSelected";
19564
+ }, never, never, true, never>;
19565
+ }
19566
+ /**
19567
+ * The user's quick filters: named sets of filters that one click applies again. A pill, like the filters of the bar it is
19568
+ * meant to sit in front of (the `filtersBarStart` slot of `<filters-bar>`), that opens a popover with a search field and the
19569
+ * list. A click on a quick filter **replaces** the active filters by its own and closes the popover, and hovering its count of
19570
+ * filters shows what it holds, and the cross at the end of a row deletes it. Quick filters are made elsewhere (the filters of
19571
+ * the results page): this is where they are applied and deleted.
19572
+ *
19573
+ * They live in the user settings (`UserSettingsStore.quickFilters`), so they follow the user from one page, and one device, to
19574
+ * the other.
19575
+ *
19576
+ * ```html
19577
+ * <filters-bar appearance="pill">
19578
+ * <quick-filters filtersBarStart appearance="pill" />
19579
+ * </filters-bar>
19580
+ * ```
19581
+ */
19582
+ export declare class QuickFiltersComponent {
19583
+ /** Colour family of the pill, as the filter buttons of the bar. */
19584
+ readonly scheme: import("@angular/core").InputSignal<FilterScheme>;
19585
+ /** The look of the pill: `pill` (rounded, outlined, as the filter pills) or `default` (the flat button). */
19586
+ readonly appearance: import("@angular/core").InputSignal<"default" | "pill">;
19587
+ /** Where the popover goes. */
19588
+ readonly position: import("@angular/core").InputSignal<Placement>;
19589
+ /** Distance in pixels between the pill and its popover. */
19590
+ readonly offset: import("@angular/core").InputSignal<number>;
19591
+ /** Emitted with the quick filter a click has just applied. */
19592
+ readonly applied: import("@angular/core").OutputEmitterRef<QuickFilter>;
19593
+ private readonly transloco;
19594
+ private readonly host;
19595
+ protected readonly popoverId: string;
19596
+ /**
19597
+ * The popover is placed by Floating UI like those of the filter buttons — flipped above the pill when there is no room
19598
+ * under it, shifted into the viewport — until the user resizes it. From then on it stays where it is (`lockPosition`) as
19599
+ * long as it is open: a popover that kept flipping while its height changes would jump under the pointer. It keeps the side
19600
+ * it was on. Closing lets it go: the next opening places it again, and only the height the user chose is kept.
19601
+ */
19602
+ protected readonly resized: import("@angular/core").WritableSignal<boolean>;
19603
+ private readonly flippedAbove;
19604
+ protected readonly placement: import("@angular/core").Signal<Placement>;
19605
+ private readonly popover;
19606
+ protected readonly isOpen: import("@angular/core").Signal<boolean>;
19607
+ constructor();
19608
+ protected readonly variant: import("@angular/core").Signal<"secondary" | "tertiary" | "none" | "light-accent" | "accent" | "primary" | null | undefined>;
19609
+ protected readonly triggerClass: import("@angular/core").Signal<string>;
19610
+ /** What was just done, for the screen readers: kept here, as the list goes with the popover once a quick filter is applied. */
19611
+ protected readonly announcement: import("@angular/core").WritableSignal<string>;
19612
+ protected onToggle(): void;
19613
+ /**
19614
+ * Gives the position back to Floating UI: a top edge that was moved is put back where the placement leaves it, and the
19615
+ * popover may flip or shift again. The height the user chose stays.
19616
+ */
19617
+ private unpin;
19618
+ /** The user starts to resize: pins the popover, on the side Floating UI had put it. */
19619
+ protected onResizeStart(): void;
19620
+ /** Closes the popover when the focus leaves the whole component. `null` (focus left the document) leaves it open. */
19621
+ protected closeOnFocusLeave(event: FocusEvent): void;
19622
+ /** The list applied a quick filter: the popover closes, and the page is told. */
19623
+ protected apply(quickFilter: QuickFilter): void;
19624
+ static ɵfac: i0.ɵɵFactoryDeclaration<QuickFiltersComponent, never>;
19625
+ static ɵcmp: i0.ɵɵComponentDeclaration<QuickFiltersComponent, "QuickFilters, quick-filters", never, {
19626
+ "scheme": {
19627
+ "alias": "scheme";
19628
+ "required": false;
19629
+ "isSignal": true;
19630
+ };
19631
+ "appearance": {
19632
+ "alias": "appearance";
19633
+ "required": false;
19634
+ "isSignal": true;
19635
+ };
19636
+ "position": {
19637
+ "alias": "position";
19638
+ "required": false;
19639
+ "isSignal": true;
19640
+ };
19641
+ "offset": {
19642
+ "alias": "offset";
19643
+ "required": false;
19644
+ "isSignal": true;
19645
+ };
19646
+ }, {
19647
+ "applied": "applied";
19648
+ }, never, never, true, never>;
19649
+ }
19650
+ /**
19651
+ * The list of the user's quick filters, to be placed where the host wants it: inline (a tab of the filters panel) or in a popover
19652
+ * (the `<quick-filters>` pill). It is the content only; the host owns the container, and what happens once a quick filter is applied.
19653
+ *
19654
+ * One row per quick filter: its name and, under it, the count of its filters — hovering that line (or focusing the row) shows them as
19655
+ * chips in a card, whose cut-off texts get a tooltip. A click on a row **replaces** the active filters by its own (the rest of the query stays, the text above all) and the host
19656
+ * is told with `applied`. The cross at the end of the row (or `Del` when the row has the focus) deletes the quick filter from the
19657
+ * user's settings. Quick filters are made elsewhere: where the filters are saved as one.
19658
+ *
19659
+ * ```html
19660
+ * <quick-filters-list [searchable]="true" (applied)="popover.close()" />
19661
+ * ```
19662
+ */
19663
+ export declare class QuickFiltersListComponent {
19664
+ /** Shows a field that narrows the list by name. It only appears once there is something to narrow. */
19665
+ readonly searchable: import("@angular/core").InputSignal<boolean>;
19666
+ /** Shows the cross that deletes a quick filter, and lets `Del` do the same. */
19667
+ readonly deletable: import("@angular/core").InputSignal<boolean>;
19668
+ /** What the empty state says under its title, when the default does not fit where the list is. */
19669
+ readonly emptyHint: import("@angular/core").InputSignal<string | undefined>;
19670
+ /** Emitted with the quick filter a click has just applied: the host decides what follows (close a popover…). */
19671
+ readonly applied: import("@angular/core").OutputEmitterRef<QuickFilter>;
19672
+ /** Emitted with the quick filter that has just been deleted. */
19673
+ readonly deleted: import("@angular/core").OutputEmitterRef<QuickFilter>;
19674
+ private readonly userSettingsStore;
19675
+ private readonly queryParamsStore;
19676
+ private readonly appStore;
19677
+ private readonly transloco;
19678
+ private readonly host;
19679
+ private readonly injector;
19680
+ protected readonly deleteKeys: string[];
19681
+ protected readonly quickFilters: import("@angular/core").Signal<QuickFilter[]>;
19682
+ protected readonly query: import("@angular/core").WritableSignal<string>;
19683
+ protected readonly filtered: import("@angular/core").Signal<QuickFilter[]>;
19684
+ /** What was just done, for the screen readers. */
19685
+ protected readonly announcement: import("@angular/core").WritableSignal<string>;
19686
+ /** The row whose hover card is showing: its quick filter, and the element the card hangs from. */
19687
+ protected readonly details: import("@angular/core").WritableSignal<{
19688
+ quickFilter: QuickFilter;
19689
+ anchor: HTMLElement;
19690
+ } | null>;
19691
+ private readonly detailsCard;
19692
+ private hideTimer;
19693
+ private readonly deleting;
19694
+ constructor();
19695
+ /**
19696
+ * What a quick filter holds, one chip per filter: the icon the application gave the aggregation of the filter in the
19697
+ * "filters" custom JSON (the one its filter button shows) and the value. The icon says what is filtered on, so the name is
19698
+ * left out; an aggregation without an icon keeps it (`Authors: John`), or the value alone would say nothing.
19699
+ */
19700
+ protected chips(quickFilter: QuickFilter): {
19701
+ text: string;
19702
+ icon?: string;
19703
+ }[];
19704
+ /** Shows what a quick filter holds, under the line of its count of filters. */
19705
+ protected showDetails(quickFilter: QuickFilter, anchor: HTMLElement): void;
19706
+ /** Hides the card a moment later, so the pointer can cross from the row to the card. */
19707
+ protected scheduleHideDetails(): void;
19708
+ protected cancelHideDetails(): void;
19709
+ /** Escape takes the card away first (WCAG 1.4.13); only a second one reaches what the list is in (a panel, a popover). */
19710
+ protected onEscape(event: Event): void;
19711
+ /** What the list holds as selected: nothing, ever — choosing a row applies it and the list starts again. */
19712
+ protected readonly picked: import("@angular/core").WritableSignal<QuickFilter[]>;
19713
+ /** A row was chosen in the list. */
19714
+ protected pick(values: readonly QuickFilter[]): void;
19715
+ /**
19716
+ * A click on a quick filter: its filters replace ALL the applied ones — the whole `filters` of the query, not a merge with them.
19717
+ * Everything else the query holds stays, the text above all: `patch` only writes what it is given.
19718
+ */
19719
+ private apply;
19720
+ /**
19721
+ * Deletes a quick filter from the user's settings. The toast says it is done. A deleted row leaves the DOM with the focus: when the
19722
+ * focus was in the list it goes to the row that took its place, or to the list itself when it was the last, so it is never dropped
19723
+ * on the page.
19724
+ */
19725
+ protected remove(quickFilter: QuickFilter, index: number, event: Event): Promise<void>;
19726
+ static ɵfac: i0.ɵɵFactoryDeclaration<QuickFiltersListComponent, never>;
19727
+ static ɵcmp: i0.ɵɵComponentDeclaration<QuickFiltersListComponent, "QuickFiltersList, quick-filters-list", never, {
19728
+ "searchable": {
19729
+ "alias": "searchable";
19730
+ "required": false;
19731
+ "isSignal": true;
19732
+ };
19733
+ "deletable": {
19734
+ "alias": "deletable";
19735
+ "required": false;
19736
+ "isSignal": true;
19737
+ };
19738
+ "emptyHint": {
19739
+ "alias": "emptyHint";
19740
+ "required": false;
19741
+ "isSignal": true;
19742
+ };
19743
+ }, {
19744
+ "applied": "applied";
19745
+ "deleted": "deleted";
19746
+ }, never, never, true, never>;
19747
+ }
19748
+ /** Order of the categories of the suggestions, first to last. */
19749
+ export declare const SEARCH_BOX_CATEGORIES_SORT: InjectionToken<string[]>;
19750
+ /** The icon of each category of suggestion. */
19751
+ export declare const SEARCH_BOX_CATEGORY_ICONS: InjectionToken<Record<string, Type<unknown>>>;
19752
+ type Suggestion$1 = Partial<Suggestion> & {
19753
+ $isDivider?: boolean;
19754
+ $isTitle?: boolean;
19755
+ /** The translated title of the category, on a title row. */
19756
+ $label?: string;
19757
+ };
19758
+ /** Which list the popup shows. */
19759
+ export type SearchBoxTab = "suggestions" | "saved";
19760
+ /**
19761
+ * The search field of a search application: a pill with a suggestions popup, and a place to start from.
19762
+ *
19763
+ * Typing opens the popup on its **Suggestions** tab — the type-ahead of the application's suggest queries, with the
19764
+ * user's recent searches, saved searches and bookmarks — and the **Saved** tab lists the saved searches, each of which
19765
+ * runs as it was saved (text, filters, tab). Validating a text, or picking a suggestion, navigates to the search page
19766
+ * with the text and the active filters.
19767
+ *
19768
+ * It drives everything it needs by itself (`QueryParamsStore`, `AutocompleteService`, `UserSettingsStore`, the router),
19769
+ * 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,
19770
+ * `medium` the one of a results header.
19771
+ *
19772
+ * ```html
19773
+ * <search-box size="hero" popup="inline" />
19774
+ * ```
19775
+ *
19776
+ * The application can add its own call to action to the bar, after the send button, by marking it `slot="trailing"` (an
19777
+ * "Ask AI" button, say). The text of the field is available to it through `[(searchInputText)]`. Never give it a `disabled`
19778
+ * attribute — the bar greys out whole on any disabled descendant — but `aria-disabled`; and wrap an `@if` in an
19779
+ * `<ng-container slot="trailing">`, since the projection only looks at the attributes of a single root element.
19780
+ *
19781
+ * ```html
19782
+ * <search-box [(searchInputText)]="text">
19783
+ * <button slot="trailing" variant="accent" size="sm" [attr.aria-disabled]="!text()" (click)="askAi()">Ask AI</button>
19784
+ * </search-box>
19785
+ * ```
19786
+ */
19787
+ export declare class SearchBoxComponent {
19788
+ /** Scale of the field: `hero` for a home page (the prototype's pill), `medium` (36px) for the header of a results page. */
19789
+ readonly size: import("@angular/core").InputSignal<"small" | "medium" | "large" | "hero" | null | undefined>;
19790
+ /** Shows the saved-search star once there is something to save. */
19791
+ readonly showSave: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
19792
+ /** The route a search leads to. */
19793
+ readonly searchPath: import("@angular/core").InputSignal<string>;
19794
+ /**
19795
+ * 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
19796
+ * the field and right under it, out of the flow so that opening it moves nothing: it takes the place of what sits under
19797
+ * the field, as on a home page, where the host hides the filters while it is open (see `expandedChange`).
19798
+ */
19799
+ readonly popup: import("@angular/core").InputSignal<"card" | "inline">;
19800
+ /** Distance, in pixels, between the field and the `card` popup. The card is placed with Floating UI, like the other popups. */
19801
+ readonly popupOffset: import("@angular/core").InputSignalWithTransform<number, unknown>;
19802
+ /** Replaces the translated placeholder. */
19803
+ readonly placeholderOverride: import("@angular/core").InputSignal<string | undefined>;
19804
+ /** Emitted with the text each time the user validates a search (Enter, the send button, a picked suggestion). */
19805
+ readonly searched: import("@angular/core").OutputEmitterRef<string>;
19806
+ /** Emitted once the text typed has settled (300ms), which is when the suggestions are fetched. */
19807
+ readonly debounced: import("@angular/core").OutputEmitterRef<string>;
19808
+ readonly saved: import("@angular/core").OutputEmitterRef<SearchItem | undefined>;
19809
+ /** Emitted when the popup opens or closes, so a host can step aside while it is open (the filters of a home page). */
19810
+ readonly expandedChange: import("@angular/core").OutputEmitterRef<boolean>;
19811
+ /** The text of the field. Two-way. */
19812
+ readonly searchInputText: import("@angular/core").ModelSignal<string>;
19813
+ protected readonly cn: import("cn").CnFunction;
19814
+ private readonly route;
19815
+ private readonly router;
19816
+ private readonly transloco;
19817
+ private readonly destroyRef;
19818
+ private readonly injector;
19819
+ private readonly eventManager;
19820
+ private readonly host;
19821
+ protected readonly queryParamsStore: {
19822
+ name?: import("@angular/core").Signal<string | undefined> | undefined;
19823
+ text?: import("@angular/core").Signal<string | undefined> | undefined;
19824
+ action?: import("@angular/core").Signal<"" | "open" | "search" | "aggregate" | undefined> | undefined;
19825
+ select?: import("@angular/core").Signal<import("@sinequa/atomic").Select[] | undefined> | undefined;
19826
+ open?: import("@angular/core").Signal<import("@sinequa/atomic").Open[] | undefined> | undefined;
19827
+ page?: import("@angular/core").Signal<number | undefined> | undefined;
19828
+ pageSize?: import("@angular/core").Signal<number | undefined> | undefined;
19829
+ tab?: import("@angular/core").Signal<string | undefined> | undefined;
19830
+ scope?: import("@angular/core").Signal<string | undefined> | undefined;
19831
+ sort?: import("@angular/core").Signal<string | undefined> | undefined;
19832
+ aggregation_overrides?: import("@angular/core").Signal<Record<string, {
19833
+ mask?: string;
19834
+ }> | undefined> | undefined;
19835
+ basket?: import("@angular/core").Signal<string | undefined> | undefined;
19836
+ isFirstPage?: import("@angular/core").Signal<boolean | undefined> | undefined;
19837
+ strictRefine?: import("@angular/core").Signal<boolean | undefined> | undefined;
19838
+ globalRelevance?: import("@angular/core").Signal<number | undefined> | undefined;
19839
+ questionLanguage?: import("@angular/core").Signal<string | undefined> | undefined;
19840
+ questionDefaultLanguage?: import("@angular/core").Signal<string | undefined> | undefined;
19841
+ spellingCorrectionMode?: import("@angular/core").Signal<import("@sinequa/atomic").SpellingCorrectionMode | undefined> | undefined;
19842
+ spellingCorrectionFilter?: import("@angular/core").Signal<string | undefined> | undefined;
19843
+ documentWeight?: import("@angular/core").Signal<string | undefined> | undefined;
19844
+ textPartWeights?: import("@angular/core").Signal<string | undefined> | undefined;
19845
+ relevanceTransforms?: import("@angular/core").Signal<string | undefined> | undefined;
19846
+ removeDuplicates?: import("@angular/core").Signal<boolean | undefined> | undefined;
19847
+ queryId?: import("@angular/core").Signal<string | undefined> | undefined;
19848
+ aggregations?: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").AggregationOptions> | string[] | undefined> | undefined;
19849
+ orderBy?: import("@angular/core").Signal<string | undefined> | undefined;
19850
+ groupBy?: import("@angular/core").Signal<string | undefined> | undefined;
19851
+ neuralSearch?: import("@angular/core").Signal<boolean | undefined> | undefined;
19852
+ path?: import("@angular/core").Signal<string | undefined> | undefined;
19853
+ filters: import("@angular/core").Signal<import("@sinequa/atomic").LegacyFilter[]>;
19854
+ id?: import("@angular/core").Signal<string | undefined> | undefined;
19855
+ setFromUrl: (href: string) => void;
19856
+ getQueryParams: () => {
19857
+ f?: string;
19858
+ p?: number;
19859
+ s?: string;
19860
+ t?: string;
19861
+ q?: string;
19862
+ b?: string;
19863
+ n?: string;
19864
+ };
19865
+ addFilter: (filter: import("@sinequa/atomic").LegacyFilter, audit?: import("@sinequa/atomic").AuditEvents, options?: {
19866
+ syncUrl?: boolean;
19867
+ }) => void;
19868
+ updateFilter: (newFilter: import("@sinequa/atomic").LegacyFilter, audit?: import("@sinequa/atomic").AuditEvents, options?: {
19869
+ syncUrl?: boolean;
19870
+ }) => void;
19871
+ removeFilter: (field?: string, options?: {
19872
+ syncUrl?: boolean;
19873
+ }) => void;
19874
+ removeFilterByName: (name?: string, column?: string, options?: {
19875
+ syncUrl?: boolean;
19876
+ }) => void;
19877
+ clearFilters: (options?: {
19878
+ syncUrl?: boolean;
19879
+ }) => void;
19880
+ clearBasket: (options?: {
19881
+ syncUrl?: boolean;
19882
+ }) => void;
19883
+ patch: (params: Partial<import("@sinequa/atomic").QueryParams>, audit?: import("@sinequa/atomic").AuditEvents, options?: {
19884
+ syncUrl?: boolean;
19885
+ }) => void;
19886
+ reset: (options?: {
19887
+ syncUrl?: boolean;
19888
+ }) => void;
19889
+ getFilter: ({ field, name }: {
19890
+ field: string | undefined;
19891
+ name: string | undefined;
19892
+ }) => Partial<import("@sinequa/atomic").LegacyFilter & {
19893
+ count: number;
19894
+ }> | null;
19895
+ getQuery: () => import("@sinequa/atomic").Query;
19896
+ } & import("@ngrx/signals").StateSource<{
19897
+ name?: string | undefined;
19898
+ text?: string | undefined;
19899
+ action?: "" | "search" | "open" | "aggregate" | undefined;
19900
+ select?: import("@sinequa/atomic").Select[] | undefined;
19901
+ open?: import("@sinequa/atomic").Open[] | undefined;
19902
+ page?: number | undefined;
19903
+ pageSize?: number | undefined;
19904
+ tab?: string | undefined;
19905
+ scope?: string | undefined;
19906
+ sort?: string | undefined;
19907
+ aggregation_overrides?: Record<string, {
19908
+ mask?: string;
19909
+ }> | undefined;
19910
+ basket?: string | undefined;
19911
+ isFirstPage?: boolean | undefined;
19912
+ strictRefine?: boolean | undefined;
19913
+ globalRelevance?: number | undefined;
19914
+ questionLanguage?: string | undefined;
19915
+ questionDefaultLanguage?: string | undefined;
19916
+ spellingCorrectionMode?: import("@sinequa/atomic").SpellingCorrectionMode | undefined;
19917
+ spellingCorrectionFilter?: string | undefined;
19918
+ documentWeight?: string | undefined;
19919
+ textPartWeights?: string | undefined;
19920
+ relevanceTransforms?: string | undefined;
19921
+ removeDuplicates?: boolean | undefined;
19922
+ queryId?: string | undefined;
19923
+ aggregations?: (Record<string, import("@sinequa/atomic").AggregationOptions> | string[]) | undefined;
19924
+ orderBy?: string | undefined;
19925
+ groupBy?: string | undefined;
19926
+ neuralSearch?: boolean | undefined;
19927
+ path?: string | undefined;
19928
+ filters: import("@sinequa/atomic").LegacyFilter[];
19929
+ id?: string | undefined;
19930
+ }>;
19931
+ protected readonly appStore: {
19932
+ name: import("@angular/core").Signal<string>;
19933
+ description?: import("@angular/core").Signal<string | undefined> | undefined;
19934
+ versionId: import("@angular/core").Signal<string>;
19935
+ queries: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCQuery>>;
19936
+ rfms: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCRFM>>;
19937
+ indexes: import("@angular/core").Signal<{
19938
+ _: import("@sinequa/atomic").CCIndex;
19939
+ } & Record<string, import("@sinequa/atomic").CCIndex>>;
19940
+ lists: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCList>>;
19941
+ webServices: import("@angular/core").Signal<Record<string, import("@sinequa/atomic").CCWebService>>;
18205
19942
  queryNames: import("@angular/core").Signal<string>;
18206
19943
  labels: import("@angular/core").Signal<string>;
18207
19944
  preview: import("@angular/core").Signal<string>;
@@ -18211,7 +19948,7 @@ export declare class LabelService {
18211
19948
  queryRssEnabled: import("@angular/core").Signal<boolean>;
18212
19949
  data: import("@angular/core").Signal<Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
18213
19950
  filters?: import("@sinequa/atomic-angular").CAggregation[];
18214
- autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
19951
+ autocomplete?: Autocomplete;
18215
19952
  tabs?: Record<string, {
18216
19953
  filters: string[];
18217
19954
  overviews?: Record<string, {
@@ -18367,7 +20104,7 @@ export declare class LabelService {
18367
20104
  fail: (error: unknown) => never;
18368
20105
  initializeWithAppName: (appName: string) => Promise<void>;
18369
20106
  update: (app: Partial<import("@sinequa/atomic-angular").CCAppState>) => void;
18370
- getWebServiceByType: (type: CCWebService["webServiceType"]) => CCWebService | undefined;
20107
+ getWebServiceByType: (type: import("@sinequa/atomic").CCWebService["webServiceType"]) => import("@sinequa/atomic").CCWebService | undefined;
18371
20108
  getLabels: () => {
18372
20109
  private: string;
18373
20110
  public: string;
@@ -18401,7 +20138,7 @@ export declare class LabelService {
18401
20138
  _: import("@sinequa/atomic").CCIndex;
18402
20139
  } & Record<string, import("@sinequa/atomic").CCIndex>;
18403
20140
  lists: Record<string, import("@sinequa/atomic").CCList>;
18404
- webServices: Record<string, CCWebService>;
20141
+ webServices: Record<string, import("@sinequa/atomic").CCWebService>;
18405
20142
  queryNames: string;
18406
20143
  labels: string;
18407
20144
  preview: string;
@@ -18411,7 +20148,7 @@ export declare class LabelService {
18411
20148
  queryRssEnabled: boolean;
18412
20149
  data: Record<string, unknown> & import("@sinequa/atomic-angular").CJson & {
18413
20150
  filters?: import("@sinequa/atomic-angular").CAggregation[];
18414
- autocomplete?: import("@sinequa/atomic-angular").Autocomplete;
20151
+ autocomplete?: Autocomplete;
18415
20152
  tabs?: Record<string, {
18416
20153
  filters: string[];
18417
20154
  overviews?: Record<string, {
@@ -18508,201 +20245,276 @@ export declare class LabelService {
18508
20245
  authorizationLevel?: string | undefined;
18509
20246
  columnMap?: Record<string, import("@sinequa/atomic").CCColumn> | undefined;
18510
20247
  }>;
18511
- private readonly client;
18512
- hasAccess: import("@angular/core").WritableSignal<boolean | undefined>;
20248
+ protected readonly userSettingsStore: {
20249
+ bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20250
+ favoriteSearches: import("@angular/core").Signal<string[]>;
20251
+ recentSearches: import("@angular/core").Signal<SearchItem[]>;
20252
+ savedSearches: import("@angular/core").Signal<SearchItem[]>;
20253
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
20254
+ baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
20255
+ assistants: import("@angular/core").Signal<Record<string, unknown>>;
20256
+ alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
20257
+ collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
20258
+ language?: import("@angular/core").Signal<string | undefined> | undefined;
20259
+ userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
20260
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
20261
+ disabledHighlightCategories: import("@angular/core").Signal<string[]>;
20262
+ isDebugMode: import("@angular/core").Signal<boolean>;
20263
+ isDarkMode: import("@angular/core").Signal<boolean>;
20264
+ updateBookmarks: (bookmarks: import("@sinequa/atomic-angular").UserSettingsState["bookmarks"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20265
+ bookmark: (article: import("@sinequa/atomic").Article, queryName?: string) => Promise<void>;
20266
+ unbookmark: (id: string) => Promise<void>;
20267
+ isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
20268
+ toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
20269
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
20270
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
20271
+ deleteRecentSearch: (index: number) => Promise<void>;
20272
+ updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20273
+ addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
20274
+ deleteSavedSearch: (index: number) => Promise<void>;
20275
+ updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
20276
+ getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
20277
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
20278
+ updateQuickFilter: (id: string, changes: {
20279
+ name?: string;
20280
+ filters?: import("@sinequa/atomic").LegacyFilter[];
20281
+ }) => Promise<void>;
20282
+ removeQuickFilter: (id: string) => Promise<void>;
20283
+ deleteBasket: (index: number) => Promise<void>;
20284
+ createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
20285
+ updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
20286
+ updateBasket: (basket: import("@sinequa/atomic-angular").Basket, index: number) => Promise<void>;
20287
+ addToBasket: (name: string, ids: string | string[]) => Promise<void>;
20288
+ removeFromBasket: (name: string, ids: string | string[]) => Promise<void>;
20289
+ updateAssistantSettings: (assistantSettings: import("@sinequa/atomic-angular").UserSettingsState["assistants"]) => Promise<void>;
20290
+ updateLanguage: (language: import("@sinequa/atomic-angular").UserSettingsState["language"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20291
+ updateAssistantCollapsed: (collapseAssistant: import("@sinequa/atomic-angular").UserSettingsState["collapseAssistant"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
20292
+ hydrate: (settings: import("@sinequa/atomic-angular").UserSettingsState) => void;
20293
+ fail: (err: unknown) => void;
20294
+ initialize: () => Promise<void>;
20295
+ reset: () => Promise<void>;
20296
+ deleteAlert: (index: number) => Promise<void>;
20297
+ createAlert: (alert: import("@sinequa/atomic-angular").Alert) => Promise<void>;
20298
+ updateAlert: (alert: import("@sinequa/atomic-angular").Alert, index: number) => Promise<void>;
20299
+ updateAlerts: (alerts: import("@sinequa/atomic-angular").Alert[]) => Promise<void>;
20300
+ setDebugMode: (value: boolean) => Promise<void>;
20301
+ setUserTheme: (userTheme: "dark" | "light" | "system") => Promise<void>;
20302
+ toggleDarkMode: () => Promise<void>;
20303
+ setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
20304
+ } & import("@ngrx/signals").StateSource<{
20305
+ bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20306
+ favoriteSearches: string[];
20307
+ recentSearches: SearchItem[];
20308
+ savedSearches: SearchItem[];
20309
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
20310
+ baskets: import("@sinequa/atomic-angular").Basket[];
20311
+ assistants: Record<string, unknown>;
20312
+ alerts: import("@sinequa/atomic-angular").Alert[];
20313
+ collapseAssistant?: boolean | undefined;
20314
+ language?: string | undefined;
20315
+ userTheme: "dark" | "light" | "system";
20316
+ agents: import("@sinequa/atomic-angular").AgentUserSettings;
20317
+ disabledHighlightCategories: string[];
20318
+ }>;
20319
+ private readonly savedSearchesService;
20320
+ protected readonly autocompleteService: AutocompleteService;
20321
+ private readonly categoriesOrder;
20322
+ private readonly categoryIcons;
20323
+ /** The SearchBar, read before its view is initialised by the popup template. */
20324
+ private readonly inputComponent;
20325
+ /** The `ngCombobox` of the SearchBar — the popup template binds to it. */
20326
+ protected readonly combobox: import("@angular/core").Signal<import("@angular/aria/combobox").Combobox | undefined>;
20327
+ /** The bar the `card` popup hangs from, and the card itself (rendered inside the deferred popup template). */
20328
+ private readonly barElement;
20329
+ private readonly popupCard;
20330
+ /** The suggestions listbox, rendered inside the deferred popup template. */
20331
+ private readonly listbox;
20332
+ /** The saved-searches list, rendered inside the deferred popup template while its tab is selected. */
20333
+ private readonly savedList;
20334
+ /**
20335
+ * The field: a form over the text model. What the user types reaches the model, so `searchInputText` and `debounced`,
20336
+ * only once it has settled (300ms, or as soon as the field is touched); `typed` is the text as it is in the bar.
20337
+ */
20338
+ protected readonly field: import("@angular/forms/signals").FieldTree<string, string | number, "writable">;
20339
+ /** The text as it is in the bar, before the debounce. */
20340
+ protected readonly typed: import("@angular/core").Signal<string>;
20341
+ /** The text a keyboard preview put in the field: it is not a request for new suggestions. */
20342
+ private silentText;
20343
+ /** The text the suggestions are fetched for: the field's, once it has settled. */
20344
+ protected readonly text: import("@angular/core").WritableSignal<string>;
20345
+ private readonly wasSearchClicked;
20346
+ /** Which list the popup shows. Back on the suggestions every time it opens — they are what typing is for. */
20347
+ protected readonly tab: import("@angular/core").WritableSignal<string | undefined>;
20348
+ /** The text of the row whose star just saved or removed it: it plays its pop animation. */
20349
+ protected readonly popping: import("@angular/core").WritableSignal<string | null>;
20350
+ /** What the shortcut just did, for the screen readers. */
20351
+ protected readonly announcement: import("@angular/core").WritableSignal<string>;
20352
+ protected readonly hintId: string;
20353
+ protected readonly savedSearches: import("@angular/core").Signal<SearchItem[]>;
20354
+ private readonly savedTexts;
20355
+ private readonly inline;
20356
+ /** The bar keeps the room of its own padding on the `hero` size, whose send button sets it. */
20357
+ protected readonly barClass: import("@angular/core").Signal<"w-full" | "w-full gap-(--spacing-3xs)! pe-(--spacing-3xs)">;
20358
+ protected readonly popupClass: import("@angular/core").Signal<string>;
20359
+ protected readonly listClass: import("@angular/core").Signal<string>;
20360
+ protected readonly rowClass: import("@angular/core").Signal<string>;
20361
+ protected readonly titleClass: import("@angular/core").Signal<string>;
20362
+ protected readonly hasFilters: import("@angular/core").Signal<boolean>;
20363
+ private readonly allowEmptySearch;
20364
+ private readonly allowAdvancedFilters;
20365
+ private readonly autocomplete;
20366
+ /**
20367
+ * Whether the user pressed an arrow key since the last typed character. Only then is a listbox selection previewed in
20368
+ * the field: the listbox auto-selects its first option whenever the suggestions render, and that programmatic
20369
+ * selection must never overwrite what the user is typing.
20370
+ */
20371
+ readonly navigatedSinceTyping: import("@angular/core").WritableSignal<boolean>;
20372
+ /** The suggestions: what the suggest queries return, with the user's recent searches, saved searches and bookmarks. */
20373
+ private readonly suggestionsResource;
20374
+ private previousSuggestions;
20375
+ protected readonly suggestions: import("@angular/core").Signal<Suggestion$1[]>;
20376
+ private inputListenersAttached;
20377
+ constructor();
18513
20378
  /**
18514
- * Check user rights to verify if they can access labels handling
18515
- * @returns if has the rights
20379
+ * Expands the popup when focus enters the field from outside (a click, a tap, Tab). Focus that comes from within —
20380
+ * the clear button handing it back after clearing — is a programmatic refocus and must not re-expand the popup.
18516
20381
  */
18517
- canHandleLabels(): Promise<boolean>;
20382
+ protected expandOnFocusEntering(event: FocusEvent): void;
18518
20383
  /**
18519
- * Get relevant config info from the labels web service
18520
- * @returns the LabelsConfig or undefined if no rights
20384
+ * Collapses the popup once focus leaves the search block entirely. The popup is a DOM descendant of this component, so
20385
+ * tabbing from the field walks into the tabs and the list instead of leaving them. `null` (focus left the document)
20386
+ * leaves the popup alone, so an alt-tab does not discard what the user was reading.
18521
20387
  */
18522
- getLabelsConfig(): Observable<LabelsConfig | undefined>;
20388
+ protected collapseOnFocusLeave(event: FocusEvent): void;
20389
+ /** Collapses the suggestions popup. */
20390
+ collapse(): void;
18523
20391
  /**
18524
- * Fetch labels from string
18525
- * @param prefix the string prefix to filter with
18526
- * @param publicOnly whether they should be public or not
18527
- * @param locale optional locale filtering
18528
- * @returns list of label strings
20392
+ * Previews a suggestion in the field while navigating with the keyboard (URL-bar style): the text shown changes but the
20393
+ * list is not fetched again under the user (see `silentText`).
18529
20394
  */
18530
- fetch(prefix: string, publicOnly?: boolean, locale?: string): Observable<string[]>;
20395
+ private previewSuggestion;
20396
+ /** The preview of the selection of the list while the keyboard navigates — never of a programmatic selection. */
20397
+ protected onListboxValueChange(values: readonly Suggestion$1[]): void;
20398
+ /** 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. */
20399
+ protected onSavedValueChange(values: readonly SearchItem[]): void;
18531
20400
  /**
18532
- * Add some labels to many documents
18533
- * @param labelsToAdd list of labels to add
18534
- * @param ids list of document id to add the label
18535
- * @param publicOnly whether the operation should be public only
18536
- * @returns a promise that resolves when the operation is complete
20401
+ * A click on a tab, or an arrow key while the tab list holds the focus. Never leaves the list without a selection.
20402
+ * 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
20403
+ * previewed in the field — the arrows start again from the text the field holds.
18537
20404
  */
18538
- add(labelsToAdd: string[], ids: string[], publicOnly?: boolean): Observable<void>;
20405
+ protected onTabChange(tab: string | undefined): void;
18539
20406
  /**
18540
- * Remove some labels from many documents
18541
- * @param labelsToRemove list of labels to remove
18542
- * @param ids list of document id to add the label
18543
- * @param publicOnly whether the operation should be public only
18544
- * @returns a promise that resolves when the operation is complete
20407
+ * 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
20408
+ * 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
20409
+ * user is typing.
18545
20410
  */
18546
- remove(labelsToRemove: string[], ids: string[], publicOnly?: boolean): Observable<void>;
20411
+ protected focusField(): void;
20412
+ /** Commits a clicked suggestion: writes it into the field and runs the search. */
20413
+ protected commitSuggestion(suggestion: Suggestion$1, event: Event): void;
18547
20414
  /**
18548
- * Name some labels to a new name
18549
- * @param labelsToRename list of labels to rename
18550
- * @param newLabel the new label name
18551
- * @param publicOnly whether the operation should be public only
18552
- * @returns a promise that resolves when the operation is complete
20415
+ * Runs a saved search as it was saved: its text, its filters and its tab, not only its text. The popup closes first,
20416
+ * since the page it leads to replaces what sits under it.
18553
20417
  */
18554
- rename(labelsToRename: string[], newLabel: string, publicOnly?: boolean): Observable<void>;
20418
+ protected openSaved(saved: SearchItem): void;
18555
20419
  /**
18556
- * Delete some labels
18557
- * @param labelsToDelete the labels to delete
18558
- * @param publicOnly whether the operation should be public only
18559
- * @returns a promise that resolves when the operation is complete
20420
+ * Shift+Tab in the field, while the popup is open, goes up to the tabs — they sit above the list — instead of leaving the
20421
+ * field backwards and closing the popup: the focus is the selected tab, where the arrows change tab. Shift+Tab from the tab
20422
+ * comes back to the field, since it is the element before it. With the popup closed it is the ordinary Shift+Tab.
18560
20423
  */
18561
- delete(labelsToDelete: string[], publicOnly?: boolean): Observable<void>;
20424
+ private focusSelectedTab;
18562
20425
  /**
18563
- * Create some labels for a query
18564
- * @param labelstoAdd the labels to create
18565
- * @param query the query object to which the labels will be added
18566
- * @param publicOnly whether the operation should be public only
18567
- * @returns a promise that resolves when the operation is complete
20426
+ * Tab on a tab: into the list. The list is never focused itself (its active option is announced from the field), so the
20427
+ * focus goes back to the field and its FIRST row becomes the active one, exactly as a first Down arrow does — the arrows
20428
+ * then walk the list. A row that was already active is let go first, or the arrow would land on the one after it.
18568
20429
  */
18569
- bulkAdd(labelstoAdd: string[], query: Query, publicOnly?: boolean): Observable<void>;
20430
+ protected intoList(event: Event): void;
18570
20431
  /**
18571
- * Delete some labels from a query
18572
- * @param labelsToRemove the labels to remove
18573
- * @param query the query object to which the labels will be removed
18574
- * @param publicOnly whether the operation should be public only
18575
- * @returns a promise that resolves when the operation is complete
20432
+ * 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
20433
+ * button of the bar, and landing there would close the popup.
18576
20434
  */
18577
- bulkRemove(labelsToRemove: string[], query: Query, publicOnly?: boolean): Observable<void>;
18578
- static ɵfac: i0.ɵɵFactoryDeclaration<LabelService, never>;
18579
- static ɵprov: i0.ɵɵInjectableDeclaration<any>;
18580
- }
18581
- /** Result of an edit-labels call: the close event plus the (possibly edited) article. */
18582
- export interface LabelsEditResult {
18583
- type: DialogEvent;
18584
- article: Article;
18585
- }
18586
- export declare class LabelsEditDialog {
18587
- protected readonly call: import("@sinequa/galactik").CallRef<Article, LabelsEditResult>;
18588
- readonly dialog: import("@angular/core").Signal<DialogComponent | undefined>;
18589
- labelService: LabelService;
18590
- readonly article: import("@angular/core").ModelSignal<Article>;
18591
- readonly labelsConfig: import("@angular/core").WritableSignal<LabelsConfig | undefined>;
18592
- private readonly destroyRef;
18593
- constructor();
18594
- close(event: DialogEvent): void;
18595
- static ɵfac: i0.ɵɵFactoryDeclaration<LabelsEditDialog, never>;
18596
- static ɵcmp: i0.ɵɵComponentDeclaration<LabelsEditDialog, "labels-edit-dialog, labelseditdialog, LabelsEditDialog", never, {
18597
- "article": {
18598
- "alias": "article";
18599
- "required": false;
18600
- "isSignal": true;
18601
- };
18602
- }, {
18603
- "article": "articleChange";
18604
- }, never, never, true, never>;
18605
- }
18606
- /** Imperative entry point: `await EditLabels.call(article)` → resolves with `{ type, article }`. */
18607
- export declare const EditLabels: import("@sinequa/galactik").Callable<Article, LabelsEditResult>;
18608
- type Article$1 = Article & {
18609
- [key: string]: unknown;
18610
- };
18611
- export declare class MultiSelectLabelsComponent {
18612
- injector: Injector;
18613
- private readonly client;
18614
- article: import("@angular/core").ModelSignal<Article$1 | undefined>;
18615
- isPublic: import("@angular/core").InputSignal<boolean>;
18616
- allowModification: import("@angular/core").InputSignal<boolean>;
18617
- labelsField: import("@angular/core").InputSignal<string | undefined>;
18618
- protected labels: import("@angular/core").WritableSignal<string[]>;
18619
- protected hasError: import("@angular/core").WritableSignal<boolean>;
18620
- protected readonly identity: (label: string) => string;
18621
- protected readonly loadSuggestions: (query: string) => Promise<string[]>;
18622
- constructor();
18623
- protected onPicked(label: string): void;
18624
- protected onRemoved(label: string): void;
20435
+ protected backToField(event: Event): void;
20436
+ /** Escape on a tab: the focus goes back to the field and the popup closes, as Escape does from the field. */
20437
+ protected closeFromTabs(event: Event): void;
20438
+ /** Whether a suggestion is a search the user has saved. */
20439
+ protected isSavedRow(suggestion: Suggestion$1): boolean;
20440
+ /** What the star of a row does, for its tooltip. */
20441
+ protected starTooltip(suggestion: Suggestion$1): string;
20442
+ /** The star of a suggestion: saves the search, or removes it from the saved ones. Never runs it. */
20443
+ protected toggleSaved(suggestion: Suggestion$1, event: Event): void;
18625
20444
  /**
18626
- * Adds a new label to the current list of labels and updates the associated article.
18627
- *
18628
- * This method performs the following steps:
18629
- * 1. Updates the local labels state by appending the new label.
18630
- * 2. Persists the new label to the backend, associating it with the current article.
18631
- * 3. Refreshes the article's label data.
18632
- *
18633
- * @param label - The label to be added.
18634
- * @param isPublic - A boolean indicating whether the label is public or private.
18635
- * @returns A promise that resolves once the label has been added and the article updated.
20445
+ * Ctrl+Enter (Cmd+Enter) in the field: the star of the highlighted row, for the keyboard. It saves that search, or removes
20446
+ * it from the saved ones, on either tab, and never runs it. Nothing happens, and Enter is left alone, when no row is
20447
+ * highlighted.
18636
20448
  */
18637
- addLabel(label: string, isPublic: boolean): Promise<void>;
20449
+ private toggleActiveRow;
20450
+ private toggleSavedText;
20451
+ /** Removes a saved search from its row, without running it. */
20452
+ protected removeSaved(saved: SearchItem, event: Event): void;
18638
20453
  /**
18639
- * Removes a label from the current list of labels and updates the associated article.
18640
- *
18641
- * @param label - The label to be removed.
18642
- * @param isPublic - A boolean indicating whether the label is public.
18643
- * @returns A promise that resolves once the label is removed and the article is updated.
20454
+ * The saved search the keyboard is on, from the active option of the saved list — and only once the user has navigated
20455
+ * with the arrows, since the listbox activates its first option on its own when it renders.
18644
20456
  */
18645
- removeLabel(label: string, isPublic: boolean): Promise<void>;
20457
+ private activeSaved;
20458
+ /** Enter in the field. A search is validated only when the application allows it for this query. */
20459
+ protected emitText(event: Event): void;
20460
+ /** The built-in send button of the SearchBar. It has already stopped the event, so no DOM event reaches this handler. */
20461
+ protected onSearchText(value: string): void;
20462
+ private runSearch;
20463
+ protected getIconForCategory(category: string | undefined): Type<unknown>;
20464
+ /** The title of a category: the library's own string, then an application key of the same name, then the category itself. */
20465
+ private categoryLabel;
18646
20466
  /**
18647
- * Updates the article object by assigning the current labels to the specified labels field.
18648
- *
18649
- * This method retrieves the article object and the labels field dynamically,
18650
- * then assigns the current labels to the corresponding field in the article.
18651
- *
18652
- * @remarks
18653
- * Ensure that `this.article`, `this.labelsField`, and `this.labels` return valid values
18654
- * before invoking this method to avoid runtime errors.
20467
+ * Fetches the suggestions for a text: the user's own (recent and saved searches, bookmarks) with the suggest queries of
20468
+ * the application, ordered by category, with a title row ahead of each category.
18655
20469
  *
20470
+ * A 401 on the suggest queries starts the sign-in flow; any other error is logged and leaves only the user's own.
18656
20471
  */
18657
- updateArticleWithLabels(): void;
18658
- static ɵfac: i0.ɵɵFactoryDeclaration<MultiSelectLabelsComponent, never>;
18659
- static ɵcmp: i0.ɵɵComponentDeclaration<MultiSelectLabelsComponent, "multiselect-labels, multiselectlabels, MultiSelectLabels", never, {
18660
- "article": {
18661
- "alias": "article";
20472
+ private fetchSuggestions;
20473
+ static ɵfac: i0.ɵɵFactoryDeclaration<SearchBoxComponent, never>;
20474
+ static ɵcmp: i0.ɵɵComponentDeclaration<SearchBoxComponent, "SearchBox, search-box", never, {
20475
+ "size": {
20476
+ "alias": "size";
18662
20477
  "required": false;
18663
20478
  "isSignal": true;
18664
20479
  };
18665
- "isPublic": {
18666
- "alias": "isPublic";
20480
+ "showSave": {
20481
+ "alias": "showSave";
18667
20482
  "required": false;
18668
20483
  "isSignal": true;
18669
20484
  };
18670
- "allowModification": {
18671
- "alias": "allowModification";
20485
+ "searchPath": {
20486
+ "alias": "searchPath";
18672
20487
  "required": false;
18673
20488
  "isSignal": true;
18674
20489
  };
18675
- "labelsField": {
18676
- "alias": "labelsField";
20490
+ "popup": {
20491
+ "alias": "popup";
20492
+ "required": false;
20493
+ "isSignal": true;
20494
+ };
20495
+ "popupOffset": {
20496
+ "alias": "popupOffset";
20497
+ "required": false;
20498
+ "isSignal": true;
20499
+ };
20500
+ "placeholderOverride": {
20501
+ "alias": "placeholder";
20502
+ "required": false;
20503
+ "isSignal": true;
20504
+ };
20505
+ "searchInputText": {
20506
+ "alias": "searchInputText";
18677
20507
  "required": false;
18678
20508
  "isSignal": true;
18679
20509
  };
18680
20510
  }, {
18681
- "article": "articleChange";
18682
- }, never, never, true, never>;
20511
+ "searched": "searched";
20512
+ "debounced": "debounced";
20513
+ "saved": "saved";
20514
+ "expandedChange": "expandedChange";
20515
+ "searchInputText": "searchInputTextChange";
20516
+ }, never, ["[slot='trailing']"], true, never>;
18683
20517
  }
18684
- /**
18685
- * Inputs handed to whichever component a host app plugs into a `PreviewTabsComponent` assistant
18686
- * slot ("summary" or "discussion"). `onStreamingChange` stands in for an `@Output` — `NgComponentOutlet`
18687
- * only binds inputs, so a streaming notification is passed down as a callback the mounted component
18688
- * calls itself, rather than an Angular event binding.
18689
- */
18690
- export type PreviewAssistantInputs = {
18691
- instanceId: string;
18692
- query: Query;
18693
- showAssistant: boolean;
18694
- onStreamingChange?: (streaming: boolean) => void;
18695
- };
18696
- export type PreviewAssistantSlot = {
18697
- component: Type<unknown>;
18698
- inputs: PreviewAssistantInputs;
18699
- };
18700
- /**
18701
- * Resolves the component (and its inputs) to mount in a `PreviewTabsComponent` assistant tab, for
18702
- * a given kind. Returning `undefined` hides that tab entirely — a host app with no assistant feature
18703
- * provides a function that always returns `undefined`, or omits the "discussion" case.
18704
- */
18705
- export declare const PREVIEW_ASSISTANT_COMPONENT: InjectionToken<(kind: "summary" | "discussion") => PreviewAssistantSlot | undefined>;
18706
20518
  export declare const RECENT_SEARCHES_OPTIONS: {
18707
20519
  itemsPerPage: number;
18708
20520
  showLoadMore: boolean;
@@ -18715,15 +20527,17 @@ export declare class RecentSearchesComponent {
18715
20527
  protected config: import("@sinequa/atomic-angular").ListPanelConfig;
18716
20528
  protected readonly userSettingsStore: {
18717
20529
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20530
+ favoriteSearches: import("@angular/core").Signal<string[]>;
18718
20531
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
18719
20532
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
20533
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
18720
20534
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
18721
20535
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
18722
20536
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
18723
20537
  collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
18724
20538
  language?: import("@angular/core").Signal<string | undefined> | undefined;
18725
20539
  userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
18726
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
20540
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
18727
20541
  disabledHighlightCategories: import("@angular/core").Signal<string[]>;
18728
20542
  isDebugMode: import("@angular/core").Signal<boolean>;
18729
20543
  isDarkMode: import("@angular/core").Signal<boolean>;
@@ -18732,12 +20546,20 @@ export declare class RecentSearchesComponent {
18732
20546
  unbookmark: (id: string) => Promise<void>;
18733
20547
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
18734
20548
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
20549
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
20550
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
18735
20551
  deleteRecentSearch: (index: number) => Promise<void>;
18736
20552
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
18737
20553
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
18738
20554
  deleteSavedSearch: (index: number) => Promise<void>;
18739
20555
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
18740
20556
  getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
20557
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
20558
+ updateQuickFilter: (id: string, changes: {
20559
+ name?: string;
20560
+ filters?: import("@sinequa/atomic").LegacyFilter[];
20561
+ }) => Promise<void>;
20562
+ removeQuickFilter: (id: string) => Promise<void>;
18741
20563
  deleteBasket: (index: number) => Promise<void>;
18742
20564
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
18743
20565
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -18761,8 +20583,10 @@ export declare class RecentSearchesComponent {
18761
20583
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
18762
20584
  } & import("@ngrx/signals").StateSource<{
18763
20585
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20586
+ favoriteSearches: string[];
18764
20587
  recentSearches: SearchItem[];
18765
20588
  savedSearches: SearchItem[];
20589
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
18766
20590
  baskets: import("@sinequa/atomic-angular").Basket[];
18767
20591
  assistants: Record<string, unknown>;
18768
20592
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -18828,15 +20652,17 @@ export declare const SavedSearch: import("@sinequa/galactik").Callable<string, D
18828
20652
  export declare class SavedSearchPopover {
18829
20653
  protected readonly userSettingsStore: {
18830
20654
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20655
+ favoriteSearches: import("@angular/core").Signal<string[]>;
18831
20656
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
18832
20657
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
20658
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
18833
20659
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
18834
20660
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
18835
20661
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
18836
20662
  collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
18837
20663
  language?: import("@angular/core").Signal<string | undefined> | undefined;
18838
20664
  userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
18839
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
20665
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
18840
20666
  disabledHighlightCategories: import("@angular/core").Signal<string[]>;
18841
20667
  isDebugMode: import("@angular/core").Signal<boolean>;
18842
20668
  isDarkMode: import("@angular/core").Signal<boolean>;
@@ -18845,12 +20671,20 @@ export declare class SavedSearchPopover {
18845
20671
  unbookmark: (id: string) => Promise<void>;
18846
20672
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
18847
20673
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
20674
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
20675
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
18848
20676
  deleteRecentSearch: (index: number) => Promise<void>;
18849
20677
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
18850
20678
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
18851
20679
  deleteSavedSearch: (index: number) => Promise<void>;
18852
20680
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
18853
20681
  getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
20682
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
20683
+ updateQuickFilter: (id: string, changes: {
20684
+ name?: string;
20685
+ filters?: import("@sinequa/atomic").LegacyFilter[];
20686
+ }) => Promise<void>;
20687
+ removeQuickFilter: (id: string) => Promise<void>;
18854
20688
  deleteBasket: (index: number) => Promise<void>;
18855
20689
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
18856
20690
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -18874,8 +20708,10 @@ export declare class SavedSearchPopover {
18874
20708
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
18875
20709
  } & import("@ngrx/signals").StateSource<{
18876
20710
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20711
+ favoriteSearches: string[];
18877
20712
  recentSearches: SearchItem[];
18878
20713
  savedSearches: SearchItem[];
20714
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
18879
20715
  baskets: import("@sinequa/atomic-angular").Basket[];
18880
20716
  assistants: Record<string, unknown>;
18881
20717
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -18912,15 +20748,17 @@ export declare class SavedSearchesComponent {
18912
20748
  protected config: import("@sinequa/atomic-angular").ListPanelConfig;
18913
20749
  protected readonly userSettingsStore: {
18914
20750
  bookmarks: import("@angular/core").Signal<import("@sinequa/atomic-angular").Bookmark[]>;
20751
+ favoriteSearches: import("@angular/core").Signal<string[]>;
18915
20752
  recentSearches: import("@angular/core").Signal<SearchItem[]>;
18916
20753
  savedSearches: import("@angular/core").Signal<SearchItem[]>;
20754
+ quickFilters: import("@angular/core").Signal<import("@sinequa/atomic-angular").QuickFilter[]>;
18917
20755
  baskets: import("@angular/core").Signal<import("@sinequa/atomic-angular").Basket[]>;
18918
20756
  assistants: import("@angular/core").Signal<Record<string, unknown>>;
18919
20757
  alerts: import("@angular/core").Signal<import("@sinequa/atomic-angular").Alert[]>;
18920
20758
  collapseAssistant?: import("@angular/core").Signal<boolean | undefined> | undefined;
18921
20759
  language?: import("@angular/core").Signal<string | undefined> | undefined;
18922
20760
  userTheme: import("@angular/core").Signal<"light" | "dark" | "system" | undefined>;
18923
- agents: import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings> | import("@angular/core").Signal<undefined>;
20761
+ agents: import("@angular/core").Signal<undefined> | import("@ngrx/signals").DeepSignal<import("@sinequa/atomic-angular").AgentUserSettings>;
18924
20762
  disabledHighlightCategories: import("@angular/core").Signal<string[]>;
18925
20763
  isDebugMode: import("@angular/core").Signal<boolean>;
18926
20764
  isDarkMode: import("@angular/core").Signal<boolean>;
@@ -18929,12 +20767,20 @@ export declare class SavedSearchesComponent {
18929
20767
  unbookmark: (id: string) => Promise<void>;
18930
20768
  isBookmarked: (article: Partial<import("@sinequa/atomic").Article>) => boolean;
18931
20769
  toggleBookmark: (article: import("@sinequa/atomic").Article) => Promise<void>;
20770
+ isFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => boolean;
20771
+ toggleFavoriteSearch: (search: Pick<SearchItem, "label" | "display">) => Promise<boolean>;
18932
20772
  deleteRecentSearch: (index: number) => Promise<void>;
18933
20773
  updateRecentSearches: (recentSearches: import("@sinequa/atomic-angular").UserSettingsState["recentSearches"], auditEvents?: import("@sinequa/atomic").AuditEvents) => Promise<void>;
18934
20774
  addCurrentSearch: (queryParams: import("@sinequa/atomic").QueryParams) => Promise<void>;
18935
20775
  deleteSavedSearch: (index: number) => Promise<void>;
18936
20776
  updateSavedSearches: (savedSearches: import("@sinequa/atomic-angular").UserSettingsState["savedSearches"]) => Promise<void>;
18937
20777
  getSavedSearch: (search: string, tab?: string) => SearchItem | undefined;
20778
+ addQuickFilter: (name: string, filters: import("@sinequa/atomic").LegacyFilter[]) => Promise<import("@sinequa/atomic-angular").QuickFilter | undefined>;
20779
+ updateQuickFilter: (id: string, changes: {
20780
+ name?: string;
20781
+ filters?: import("@sinequa/atomic").LegacyFilter[];
20782
+ }) => Promise<void>;
20783
+ removeQuickFilter: (id: string) => Promise<void>;
18938
20784
  deleteBasket: (index: number) => Promise<void>;
18939
20785
  createBasket: (basket: import("@sinequa/atomic-angular").Basket) => Promise<void>;
18940
20786
  updateBaskets: (baskets: import("@sinequa/atomic-angular").UserSettingsState["baskets"]) => Promise<void>;
@@ -18958,8 +20804,10 @@ export declare class SavedSearchesComponent {
18958
20804
  setDisabledHighlightCategories: (keys: string[]) => Promise<void>;
18959
20805
  } & import("@ngrx/signals").StateSource<{
18960
20806
  bookmarks: import("@sinequa/atomic-angular").Bookmark[];
20807
+ favoriteSearches: string[];
18961
20808
  recentSearches: SearchItem[];
18962
20809
  savedSearches: SearchItem[];
20810
+ quickFilters: import("@sinequa/atomic-angular").QuickFilter[];
18963
20811
  baskets: import("@sinequa/atomic-angular").Basket[];
18964
20812
  assistants: Record<string, unknown>;
18965
20813
  alerts: import("@sinequa/atomic-angular").Alert[];
@@ -19067,7 +20915,7 @@ export declare class SettingsAccountPanelComponent {
19067
20915
  param9: import("@angular/core").Signal<string>;
19068
20916
  param10: import("@angular/core").Signal<string>;
19069
20917
  userOverrideActive: import("@angular/core").Signal<boolean>;
19070
- state: import("@angular/core").Signal<"error" | "initial" | "loading" | "loaded">;
20918
+ state: import("@angular/core").Signal<"error" | "loading" | "loaded" | "initial">;
19071
20919
  allowUserOverride: import("@angular/core").Signal<boolean>;
19072
20920
  isOverridingUser: import("@angular/core").Signal<boolean>;
19073
20921
  initials: import("@angular/core").Signal<string>;
@@ -19226,7 +21074,7 @@ export declare class UserProfileFormComponent {
19226
21074
  param9: Signal<string>;
19227
21075
  param10: Signal<string>;
19228
21076
  userOverrideActive: Signal<boolean>;
19229
- state: Signal<"error" | "initial" | "loading" | "loaded">;
21077
+ state: Signal<"error" | "loading" | "loaded" | "initial">;
19230
21078
  allowUserOverride: Signal<boolean>;
19231
21079
  isOverridingUser: Signal<boolean>;
19232
21080
  initials: Signal<string>;
@@ -20387,6 +22235,22 @@ export declare class FileSizePipe implements PipeTransform {
20387
22235
  static ɵfac: i0.ɵɵFactoryDeclaration<FileSizePipe, never>;
20388
22236
  static ɵpipe: i0.ɵɵPipeDeclaration<FileSizePipe, "fileSize", true>;
20389
22237
  }
22238
+ /**
22239
+ * Writes a number the way the interface language does: `1,060` in English, `1 060` in French, `1.060` in German.
22240
+ *
22241
+ * Not Angular's `number` pipe: that one follows `LOCALE_ID`, which an application fixes once for good, so it would keep grouping
22242
+ * digits the same way in another language. The language here is the one transloco holds, read as a signal so a template using the
22243
+ * pipe updates by itself when the user changes it (the pipe stays pure).
22244
+ *
22245
+ * `null` and `undefined` are written as `0`.
22246
+ */
22247
+ export declare class LocalizedNumberPipe implements PipeTransform {
22248
+ private readonly transloco;
22249
+ private readonly lang;
22250
+ transform(value: number | null | undefined): string;
22251
+ static ɵfac: i0.ɵɵFactoryDeclaration<LocalizedNumberPipe, never>;
22252
+ static ɵpipe: i0.ɵɵPipeDeclaration<LocalizedNumberPipe, "localizedNumber", true>;
22253
+ }
20390
22254
  /**
20391
22255
  * The `@sinequa/atomic` client the surrounding injector works with.
20392
22256
  *
@@ -20752,4 +22616,4 @@ export type AppFeatures = {
20752
22616
  * @deprecated use `general` configuration json instead from the app store
20753
22617
  */
20754
22618
  export declare const APP_FEATURES: InjectionToken<AppFeatures>;
20755
- export type { ConverterOption, DateRange, DateRangeDialogProps, Shortcut, ShortcutDefinition };
22619
+ export type { ConverterOption, DateRange, DateRangeDialogProps, FilterScheme, Shortcut, ShortcutDefinition };