@sinequa/atomic-angular 1.9.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1854,42 +1854,49 @@ async function withFetch(callback, injector) {
1854
1854
  }
1855
1855
  }
1856
1856
 
1857
+ /**
1858
+ * Canonical default shape of the query params state.
1859
+ *
1860
+ * Shared between `withState()` (initial value) and `reset()` (replacement state) so the
1861
+ * two cannot drift apart. Keep in sync with `QueryParamsState`.
1862
+ */
1863
+ const QUERY_PARAMS_DEFAULTS = {
1864
+ // QueryParams specific properties
1865
+ path: "",
1866
+ filters: [],
1867
+ id: "",
1868
+ // Query properties (all optional due to Partial<>)
1869
+ name: "",
1870
+ text: "",
1871
+ action: "",
1872
+ select: [],
1873
+ open: [],
1874
+ page: undefined,
1875
+ pageSize: undefined,
1876
+ tab: "",
1877
+ scope: "",
1878
+ sort: "",
1879
+ basket: "",
1880
+ isFirstPage: undefined,
1881
+ strictRefine: undefined,
1882
+ globalRelevance: undefined,
1883
+ questionLanguage: "",
1884
+ questionDefaultLanguage: "",
1885
+ spellingCorrectionMode: undefined,
1886
+ spellingCorrectionFilter: "",
1887
+ documentWeight: "",
1888
+ textPartWeights: "",
1889
+ relevanceTransforms: "",
1890
+ removeDuplicates: undefined,
1891
+ queryId: "",
1892
+ aggregations: undefined,
1893
+ orderBy: "",
1894
+ groupBy: "",
1895
+ neuralSearch: undefined
1896
+ };
1857
1897
  const QueryParamsStore = signalStore({ providedIn: "root" }, withDevtools("QueryParams"), withQueryParamsFeatures());
1858
1898
  function withQueryParamsFeatures() {
1859
- return signalStoreFeature(withState({
1860
- // QueryParams specific properties
1861
- path: "",
1862
- filters: [],
1863
- id: "",
1864
- // Query properties (all optional due to Partial<>)
1865
- name: "",
1866
- text: "",
1867
- action: "",
1868
- select: [],
1869
- open: [],
1870
- page: undefined,
1871
- pageSize: undefined,
1872
- tab: "",
1873
- scope: "",
1874
- sort: "",
1875
- basket: "",
1876
- isFirstPage: undefined,
1877
- strictRefine: undefined,
1878
- globalRelevance: undefined,
1879
- questionLanguage: "",
1880
- questionDefaultLanguage: "",
1881
- spellingCorrectionMode: undefined,
1882
- spellingCorrectionFilter: "",
1883
- documentWeight: "",
1884
- textPartWeights: "",
1885
- relevanceTransforms: "",
1886
- removeDuplicates: undefined,
1887
- queryId: "",
1888
- aggregations: undefined,
1889
- orderBy: "",
1890
- groupBy: "",
1891
- neuralSearch: undefined
1892
- }), withMethods((store, injector = inject(Injector), router = inject(Router), route = inject(ActivatedRoute), appStore = inject(AppStore)) => ({
1899
+ return signalStoreFeature(withState(QUERY_PARAMS_DEFAULTS), withMethods((store, injector = inject(Injector), router = inject(Router), route = inject(ActivatedRoute), appStore = inject(AppStore)) => ({
1893
1900
  /**
1894
1901
  * Sets the state from the given URL by extracting query parameters and updating the store.
1895
1902
  *
@@ -2127,6 +2134,18 @@ function withQueryParamsFeatures() {
2127
2134
  return newState;
2128
2135
  });
2129
2136
  },
2137
+ /**
2138
+ * Resets the query params to their default state.
2139
+ *
2140
+ * Called on every application (re-)initialization (first login, sign-in, and user
2141
+ * override/impersonation) so that a previous user's search text/filters/sort/etc. don't
2142
+ * leak into the next user's session — `QueryParamsStore` is a root-level singleton that
2143
+ * otherwise survives across logins. See ES-32053.
2144
+ */
2145
+ reset(options) {
2146
+ patchState(store, QUERY_PARAMS_DEFAULTS);
2147
+ this._updateUrlQueryParams(QUERY_PARAMS_DEFAULTS, undefined, options);
2148
+ },
2130
2149
  /**
2131
2150
  * Retrieves a filter object based on the provided field or name.
2132
2151
  *
@@ -3742,6 +3761,7 @@ class ApplicationService {
3742
3761
  userSettingsStore = inject(UserSettingsStore);
3743
3762
  principalStore = inject(PrincipalStore);
3744
3763
  appStore = inject(AppStore);
3764
+ queryParamsStore = inject(QueryParamsStore);
3745
3765
  router = inject(Router);
3746
3766
  titleService = inject(Title);
3747
3767
  components = inject(ROUTE_COMPONENTS);
@@ -3792,6 +3812,8 @@ class ApplicationService {
3792
3812
  * Initializes the application stores.
3793
3813
  * - Fetches the application configuration.
3794
3814
  * - Sets the fetched application configuration in the app store.
3815
+ * - Resets the query params store (runs on first login as well as on every subsequent
3816
+ * re-initialization, e.g. user override, so no previous user's search state leaks in).
3795
3817
  * - Loads the user settings and logs the state of the user settings store.
3796
3818
  */
3797
3819
  async initializeStores() {
@@ -3802,6 +3824,9 @@ class ApplicationService {
3802
3824
  // Load the principal (user information)
3803
3825
  await this.principalStore.initialize();
3804
3826
  info("principalStore", getState(this.principalStore));
3827
+ // Reset the query params (search text, filters, sort, ...) so a previous user's
3828
+ // in-memory search state doesn't leak into the next user's session. ES-32053.
3829
+ this.queryParamsStore.reset();
3805
3830
  // Load the user settings
3806
3831
  await this.userSettingsStore.initialize();
3807
3832
  info("userSettingsStore", getState(this.userSettingsStore));
@@ -14714,7 +14739,7 @@ class AggregationTreeComponent {
14714
14739
  return false;
14715
14740
  }
14716
14741
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AggregationTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14717
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AggregationTreeComponent, isStandalone: true, selector: "AggregationTree, aggregation-tree, aggregationtree", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, showFiltersCount: { classPropertyName: "showFiltersCount", publicName: "showFiltersCount", isSignal: true, isRequired: false, transformFunction: null }, showCheckbox: { classPropertyName: "showCheckbox", publicName: "showCheckbox", isSignal: true, isRequired: false, transformFunction: null }, expandedLevel: { classPropertyName: "expandedLevel", publicName: "expandedLevel", isSignal: true, isRequired: false, transformFunction: null }, syncUrl: { classPropertyName: "syncUrl", publicName: "syncUrl", isSignal: true, isRequired: false, transformFunction: null }, controlledQuery: { classPropertyName: "controlledQuery", publicName: "query", isSignal: true, isRequired: false, transformFunction: null }, controlledAggregation: { classPropertyName: "controlledAggregation", publicName: "aggregation", isSignal: true, isRequired: false, transformFunction: null }, controlledSelection: { classPropertyName: "controlledSelection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, itemTemplateInput: { classPropertyName: "itemTemplateInput", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, searchText: { classPropertyName: "searchText", publicName: "searchText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect", onApply: "onApply", onClear: "onClear", selectionChange: "selectionChange", filtersChange: "filtersChange", searchText: "searchTextChange" }, host: { properties: { "class": "cn(\"block h-[inherit] max-h-[inherit] w-[inherit]\", class())" } }, queries: [{ propertyName: "itemDirective", first: true, predicate: AggregationItemDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "virtualItems", predicate: ["virtualItem"], descendants: true, isSignal: true }, { propertyName: "scrollElement", first: true, predicate: ["scrollElement"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (!aggregation()?.isTree) {\r\n <div class=\"p-2 text-sm text-red-500\">\r\n <triangle-alert-icon class=\"mr-1\" />\r\n The aggregationTree component does not support list aggregations. Please use\r\n the &lt;Aggregation /&gt; component instead.\r\n </div>\r\n}\r\n<aggregation-panel\r\n [id]=\"id()\"\r\n [collapsible]=\"collapsible()\"\r\n [collapsed]=\"collapsed()\"\r\n [isEmpty]=\"isEmpty()\"\r\n [isDate]=\"isDate()\"\r\n [aggregation]=\"aggregation()\"\r\n [showFiltersCount]=\"showFiltersCount()\"\r\n [filtersCount]=\"filtersCount()\"\r\n [hasFilters]=\"hasFilters()\"\r\n [selection]=\"selection()\"\r\n [isAllSelected]=\"isAllSelected()\"\r\n [(searchText)]=\"searchText\"\r\n [itemsLength]=\"items().length\"\r\n [hasMore]=\"aggregation()?.$hasMore ?? false\"\r\n [searchedItemsLength]=\"searchedItems().length\"\r\n (cleared)=\"clear()\"\r\n (applied)=\"apply()\"\r\n (allSelected)=\"selectAll()\"\r\n (allUnselected)=\"unselectAll()\"\r\n (loadedMore)=\"loadMore()\">\r\n <div\r\n #scrollElement\r\n class=\"max-h-(--scroll-height,20rem) w-full scrollbar-thin overflow-auto\">\r\n <div\r\n class=\"relative w-full\"\r\n [style.height]=\"virtualizer.getTotalSize() + 'px'\"\r\n role=\"tree\"\r\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\r\n <div\r\n class=\"absolute top-0 left-0 w-full\"\r\n [style.transform]=\"\r\n 'translateY(' +\r\n (virtualizer.getVirtualItems()[0]\r\n ? virtualizer.getVirtualItems()[0].start\r\n : 0) +\r\n 'px)'\r\n \">\r\n @for (vItem of virtualizer.getVirtualItems(); track vItem.index) {\r\n @let item = items()[vItem.index];\r\n <div #virtualItem [attr.data-index]=\"vItem.index\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"treeItemTpl\"\r\n [ngTemplateOutletContext]=\"{\r\n node: item,\r\n path: [],\r\n field: aggregation()?.column,\r\n tpl: treeItemTpl,\r\n parent: null\r\n }\">\r\n </ng-container>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</aggregation-panel>\r\n\r\n<ng-template\r\n #treeItemTpl\r\n let-node=\"node\"\r\n let-path=\"path\"\r\n let-field=\"field\"\r\n let-tpl=\"tpl\"\r\n let-parent=\"parent\">\r\n <div\r\n role=\"treeitem\"\r\n [style.--level]=\"treeItemLevel(node)\"\r\n [attr.aria-selected]=\"node.$selected ?? false\"\r\n [attr.aria-expanded]=\"\r\n node.hasChildren !== false ? (node.$opened ?? false) : null\r\n \"\r\n [attr.aria-disabled]=\"node.count === 0 ? 'true' : null\"\r\n [attr.disabled]=\"node.count === 0 ? 'disabled' : null\">\r\n <a\r\n [attr.aria-label]=\"treeItemName(node) | syslang\"\r\n [class]=\"\r\n cn(\r\n 'flex grow items-center gap-2 p-1 leading-7',\r\n node.count === 0 && 'disabled pointer-events-none',\r\n (node.$selected || node.$selectedVisually) && ''\r\n )\r\n \"\r\n (click)=\"selectTreeItem(node, parent, $event, true)\">\r\n <button\r\n variant=\"none\"\r\n [iconOnly]=\"true\"\r\n (click)=\"toggleTreeNode($event, node)\"\r\n class=\"transition-transform ease-in hover:scale-125\"\r\n aria-label=\"Open\">\r\n <ChevronRight\r\n [class]=\"\r\n cn(\r\n 'size-4 translate-x-1',\r\n node.$opened && 'rotate-90',\r\n !node.hasChildren && 'hidden'\r\n )\r\n \"\r\n width=\"16\"\r\n height=\"16\" />\r\n </button>\r\n @if (showCheckbox()) {\r\n <input\r\n type=\"checkbox\"\r\n role=\"checkbox\"\r\n value=\"{{ node.value }}\"\r\n [attr.disabled]=\"node.count === 0 ? true : null\"\r\n [attr.aria-disabled]=\"node.count === 0\"\r\n (keydown.enter)=\"selectTreeItem(node, parent, $event)\"\r\n [checked]=\"node.$selected || node.$selectedVisually\" />\r\n }\r\n @if (resolvedItemTemplate(); as tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tpl\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: node,\r\n field: field,\r\n selected: node.$selected || node.$selectedVisually || false,\r\n count: node.count,\r\n name: (treeItemName(node) | syslang) ?? '',\r\n searchText: searchText(),\r\n level: treeItemLevel(node),\r\n expanded: node.$opened ?? false,\r\n hasChildren: node.hasChildren ?? false\r\n }\" />\r\n } @else {\r\n @let icon = node.icon;\r\n @if (icon) {\r\n <FaIcon [faClass]=\"icon\" class=\"self-center justify-self-center\" />\r\n }\r\n <span\r\n [class]=\"\r\n cn(\r\n 'line-clamp-1 break-all text-ellipsis',\r\n quickFilter() && 'hover:underline'\r\n )\r\n \"\r\n [title]=\"\r\n quickFilter()\r\n ? ((isTreeItemFiltered(node, field)\r\n ? 'filters.removeFilter'\r\n : 'filters.addFilter'\r\n ) | transloco) +\r\n ': ' +\r\n (treeItemName(node) | syslang)\r\n : (treeItemName(node) | syslang)\r\n \"\r\n (click)=\"onTreeItemTextClick(node, parent, $event)\">\r\n @for (\r\n chunk of (treeItemName(node) | syslang) ?? \"\"\r\n | highlightWord: searchText() : 10;\r\n track $index\r\n ) {\r\n <span [class]=\"{ 'font-bold': chunk.match }\" aria-hidden=\"true\">{{\r\n chunk.text\r\n }}</span>\r\n }\r\n </span>\r\n @if (showCount() && node.count > 0) {\r\n <span class=\"ml-auto px-1 text-xs empty:hidden\" aria-hidden=\"true\">{{\r\n node.count\r\n }}</span>\r\n }\r\n }\r\n </a>\r\n @if (node.hasChildren && node.$opened) {\r\n <div role=\"group\">\r\n @for (child of node.items; track $index) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tpl\"\r\n [ngTemplateOutletContext]=\"{\r\n node: child,\r\n path: treeChildrenPath(node, path),\r\n field: field,\r\n tpl: tpl,\r\n parent: node\r\n }\">\r\n </ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-template>\r\n", styles: ["div[role=treeitem]:has(+div[role=treeitem]){margin-bottom:var(--agg-item-gap, 0)}div[role=treeitem]{display:block;-webkit-user-select:none;user-select:none}div[role=treeitem] a{padding-left:calc(var(--agg-tree-indent, .5rem) * var(--level, 0));line-height:var(--agg-item-height, inherit)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "component", type: ChevronRightIcon, selector: "chevron-right, ChevronRight, chevronright, ChevronRightIcon, chevron-right-icon, chevronrighticon", inputs: ["class"] }, { kind: "component", type: FaIconComponent, selector: "fa-icon, FaIcon", inputs: ["faClass", "class"] }, { kind: "component", type: TriangleAlertIcon, selector: "triangle-alert-icon, TriangleAlertIcon", inputs: ["class"] }, { kind: "component", type: AggregationPanelComponent, selector: "AggregationPanel, aggregation-panel", inputs: ["id", "collapsible", "collapsed", "isDate", "isEmpty", "aggregation", "showFiltersCount", "filtersCount", "hasFilters", "selection", "isAllSelected", "searchText", "itemsLength", "hasMore", "searchedItemsLength"], outputs: ["searchTextChange", "cleared", "applied", "allSelected", "allUnselected", "loadedMore"] }, { kind: "pipe", type: SyslangPipe, name: "syslang" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: HighlightWordPipe, name: "highlightWord" }] });
14742
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AggregationTreeComponent, isStandalone: true, selector: "AggregationTree, aggregation-tree, aggregationtree", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, showFiltersCount: { classPropertyName: "showFiltersCount", publicName: "showFiltersCount", isSignal: true, isRequired: false, transformFunction: null }, showCheckbox: { classPropertyName: "showCheckbox", publicName: "showCheckbox", isSignal: true, isRequired: false, transformFunction: null }, expandedLevel: { classPropertyName: "expandedLevel", publicName: "expandedLevel", isSignal: true, isRequired: false, transformFunction: null }, syncUrl: { classPropertyName: "syncUrl", publicName: "syncUrl", isSignal: true, isRequired: false, transformFunction: null }, controlledQuery: { classPropertyName: "controlledQuery", publicName: "query", isSignal: true, isRequired: false, transformFunction: null }, controlledAggregation: { classPropertyName: "controlledAggregation", publicName: "aggregation", isSignal: true, isRequired: false, transformFunction: null }, controlledSelection: { classPropertyName: "controlledSelection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, itemTemplateInput: { classPropertyName: "itemTemplateInput", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null }, searchText: { classPropertyName: "searchText", publicName: "searchText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect", onApply: "onApply", onClear: "onClear", selectionChange: "selectionChange", filtersChange: "filtersChange", searchText: "searchTextChange" }, host: { properties: { "class": "cn(\"block h-[inherit] max-h-[inherit] w-[inherit]\", class())" } }, queries: [{ propertyName: "itemDirective", first: true, predicate: AggregationItemDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "virtualItems", predicate: ["virtualItem"], descendants: true, isSignal: true }, { propertyName: "scrollElement", first: true, predicate: ["scrollElement"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (!aggregation()?.isTree) {\r\n <div class=\"p-2 text-sm text-red-500\">\r\n <triangle-alert-icon class=\"mr-1\" />\r\n The aggregationTree component does not support list aggregations. Please use\r\n the &lt;Aggregation /&gt; component instead.\r\n </div>\r\n}\r\n<aggregation-panel\r\n [id]=\"id()\"\r\n [collapsible]=\"collapsible()\"\r\n [collapsed]=\"collapsed()\"\r\n [isEmpty]=\"isEmpty()\"\r\n [isDate]=\"isDate()\"\r\n [aggregation]=\"aggregation()\"\r\n [showFiltersCount]=\"showFiltersCount()\"\r\n [filtersCount]=\"filtersCount()\"\r\n [hasFilters]=\"hasFilters()\"\r\n [selection]=\"selection()\"\r\n [isAllSelected]=\"isAllSelected()\"\r\n [(searchText)]=\"searchText\"\r\n [itemsLength]=\"items().length\"\r\n [hasMore]=\"aggregation()?.$hasMore ?? false\"\r\n [searchedItemsLength]=\"searchedItems().length\"\r\n (cleared)=\"clear()\"\r\n (applied)=\"apply()\"\r\n (allSelected)=\"selectAll()\"\r\n (allUnselected)=\"unselectAll()\"\r\n (loadedMore)=\"loadMore()\">\r\n <div\r\n #scrollElement\r\n class=\"max-h-(--scroll-height,20rem) w-full scrollbar-thin overflow-auto\">\r\n <div\r\n class=\"relative w-full\"\r\n [style.height]=\"virtualizer.getTotalSize() + 'px'\"\r\n role=\"tree\"\r\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\r\n <div\r\n class=\"absolute top-0 left-0 w-full\"\r\n [style.transform]=\"\r\n 'translateY(' +\r\n (virtualizer.getVirtualItems()[0]\r\n ? virtualizer.getVirtualItems()[0].start\r\n : 0) +\r\n 'px)'\r\n \">\r\n @for (vItem of virtualizer.getVirtualItems(); track vItem.index) {\r\n @let item = items()[vItem.index];\r\n <div #virtualItem [attr.data-index]=\"vItem.index\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"treeItemTpl\"\r\n [ngTemplateOutletContext]=\"{\r\n node: item,\r\n path: [],\r\n field: aggregation()?.column,\r\n tpl: treeItemTpl,\r\n parent: null\r\n }\">\r\n </ng-container>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</aggregation-panel>\r\n\r\n<ng-template\r\n #treeItemTpl\r\n let-node=\"node\"\r\n let-path=\"path\"\r\n let-field=\"field\"\r\n let-tpl=\"tpl\"\r\n let-parent=\"parent\">\r\n <div\r\n role=\"treeitem\"\r\n [style.--level]=\"treeItemLevel(node)\"\r\n [attr.aria-selected]=\"node.$selected ?? false\"\r\n [attr.aria-expanded]=\"\r\n node.hasChildren !== false ? (node.$opened ?? false) : null\r\n \"\r\n [attr.aria-disabled]=\"node.count === 0 ? 'true' : null\"\r\n [attr.disabled]=\"node.count === 0 ? 'disabled' : null\">\r\n <a\r\n [attr.aria-label]=\"treeItemName(node) | syslang\"\r\n [class]=\"\r\n cn(\r\n 'flex grow items-center gap-2 p-1 leading-7',\r\n node.count === 0 && 'disabled pointer-events-none',\r\n (node.$selected || node.$selectedVisually) && ''\r\n )\r\n \"\r\n (click)=\"selectTreeItem(node, parent, $event, true)\">\r\n <button\r\n variant=\"none\"\r\n [iconOnly]=\"true\"\r\n (click)=\"toggleTreeNode($event, node)\"\r\n class=\"transition-transform ease-in hover:scale-125\"\r\n aria-label=\"Open\">\r\n <ChevronRight\r\n [class]=\"\r\n cn(\r\n 'size-4 translate-x-1',\r\n node.$opened && 'rotate-90',\r\n !node.hasChildren && 'hidden'\r\n )\r\n \"\r\n width=\"16\"\r\n height=\"16\" />\r\n </button>\r\n @if (showCheckbox()) {\r\n <input\r\n type=\"checkbox\"\r\n role=\"checkbox\"\r\n value=\"{{ node.value }}\"\r\n [attr.disabled]=\"node.count === 0 ? true : null\"\r\n [attr.aria-disabled]=\"node.count === 0\"\r\n (keydown.enter)=\"selectTreeItem(node, parent, $event, true)\"\r\n [checked]=\"node.$selected || node.$selectedVisually\" />\r\n }\r\n @if (resolvedItemTemplate(); as tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tpl\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: node,\r\n field: field,\r\n selected: node.$selected || node.$selectedVisually || false,\r\n count: node.count,\r\n name: (treeItemName(node) | syslang) ?? '',\r\n searchText: searchText(),\r\n level: treeItemLevel(node),\r\n expanded: node.$opened ?? false,\r\n hasChildren: node.hasChildren ?? false\r\n }\" />\r\n } @else {\r\n @let icon = node.icon;\r\n @if (icon) {\r\n <FaIcon [faClass]=\"icon\" class=\"self-center justify-self-center\" />\r\n }\r\n <span\r\n [class]=\"\r\n cn(\r\n 'line-clamp-1 break-all text-ellipsis',\r\n quickFilter() && 'hover:underline'\r\n )\r\n \"\r\n [title]=\"\r\n quickFilter()\r\n ? ((isTreeItemFiltered(node, field)\r\n ? 'filters.removeFilter'\r\n : 'filters.addFilter'\r\n ) | transloco) +\r\n ': ' +\r\n (treeItemName(node) | syslang)\r\n : (treeItemName(node) | syslang)\r\n \"\r\n (click)=\"onTreeItemTextClick(node, parent, $event)\">\r\n @for (\r\n chunk of (treeItemName(node) | syslang) ?? \"\"\r\n | highlightWord: searchText() : 10;\r\n track $index\r\n ) {\r\n <span [class]=\"{ 'font-bold': chunk.match }\" aria-hidden=\"true\">{{\r\n chunk.text\r\n }}</span>\r\n }\r\n </span>\r\n @if (showCount() && node.count > 0) {\r\n <span class=\"ml-auto px-1 text-xs empty:hidden\" aria-hidden=\"true\">{{\r\n node.count\r\n }}</span>\r\n }\r\n }\r\n </a>\r\n @if (node.hasChildren && node.$opened) {\r\n <div role=\"group\">\r\n @for (child of node.items; track $index) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tpl\"\r\n [ngTemplateOutletContext]=\"{\r\n node: child,\r\n path: treeChildrenPath(node, path),\r\n field: field,\r\n tpl: tpl,\r\n parent: node\r\n }\">\r\n </ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-template>\r\n", styles: ["div[role=treeitem]:has(+div[role=treeitem]){margin-bottom:var(--agg-item-gap, 0)}div[role=treeitem]{display:block;-webkit-user-select:none;user-select:none}div[role=treeitem] a{padding-left:calc(var(--agg-tree-indent, .5rem) * var(--level, 0));line-height:var(--agg-item-height, inherit)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: ButtonComponent, selector: "button", inputs: ["class", "variant", "decoration", "scheme", "iconOnly", "size", "solid"] }, { kind: "component", type: ChevronRightIcon, selector: "chevron-right, ChevronRight, chevronright, ChevronRightIcon, chevron-right-icon, chevronrighticon", inputs: ["class"] }, { kind: "component", type: FaIconComponent, selector: "fa-icon, FaIcon", inputs: ["faClass", "class"] }, { kind: "component", type: TriangleAlertIcon, selector: "triangle-alert-icon, TriangleAlertIcon", inputs: ["class"] }, { kind: "component", type: AggregationPanelComponent, selector: "AggregationPanel, aggregation-panel", inputs: ["id", "collapsible", "collapsed", "isDate", "isEmpty", "aggregation", "showFiltersCount", "filtersCount", "hasFilters", "selection", "isAllSelected", "searchText", "itemsLength", "hasMore", "searchedItemsLength"], outputs: ["searchTextChange", "cleared", "applied", "allSelected", "allUnselected", "loadedMore"] }, { kind: "pipe", type: SyslangPipe, name: "syslang" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: HighlightWordPipe, name: "highlightWord" }] });
14718
14743
  }
14719
14744
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AggregationTreeComponent, decorators: [{
14720
14745
  type: Component,
@@ -14732,7 +14757,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
14732
14757
  AggregationPanelComponent,
14733
14758
  ], standalone: true, host: {
14734
14759
  "[class]": 'cn("block h-[inherit] max-h-[inherit] w-[inherit]", class())',
14735
- }, template: "@if (!aggregation()?.isTree) {\r\n <div class=\"p-2 text-sm text-red-500\">\r\n <triangle-alert-icon class=\"mr-1\" />\r\n The aggregationTree component does not support list aggregations. Please use\r\n the &lt;Aggregation /&gt; component instead.\r\n </div>\r\n}\r\n<aggregation-panel\r\n [id]=\"id()\"\r\n [collapsible]=\"collapsible()\"\r\n [collapsed]=\"collapsed()\"\r\n [isEmpty]=\"isEmpty()\"\r\n [isDate]=\"isDate()\"\r\n [aggregation]=\"aggregation()\"\r\n [showFiltersCount]=\"showFiltersCount()\"\r\n [filtersCount]=\"filtersCount()\"\r\n [hasFilters]=\"hasFilters()\"\r\n [selection]=\"selection()\"\r\n [isAllSelected]=\"isAllSelected()\"\r\n [(searchText)]=\"searchText\"\r\n [itemsLength]=\"items().length\"\r\n [hasMore]=\"aggregation()?.$hasMore ?? false\"\r\n [searchedItemsLength]=\"searchedItems().length\"\r\n (cleared)=\"clear()\"\r\n (applied)=\"apply()\"\r\n (allSelected)=\"selectAll()\"\r\n (allUnselected)=\"unselectAll()\"\r\n (loadedMore)=\"loadMore()\">\r\n <div\r\n #scrollElement\r\n class=\"max-h-(--scroll-height,20rem) w-full scrollbar-thin overflow-auto\">\r\n <div\r\n class=\"relative w-full\"\r\n [style.height]=\"virtualizer.getTotalSize() + 'px'\"\r\n role=\"tree\"\r\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\r\n <div\r\n class=\"absolute top-0 left-0 w-full\"\r\n [style.transform]=\"\r\n 'translateY(' +\r\n (virtualizer.getVirtualItems()[0]\r\n ? virtualizer.getVirtualItems()[0].start\r\n : 0) +\r\n 'px)'\r\n \">\r\n @for (vItem of virtualizer.getVirtualItems(); track vItem.index) {\r\n @let item = items()[vItem.index];\r\n <div #virtualItem [attr.data-index]=\"vItem.index\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"treeItemTpl\"\r\n [ngTemplateOutletContext]=\"{\r\n node: item,\r\n path: [],\r\n field: aggregation()?.column,\r\n tpl: treeItemTpl,\r\n parent: null\r\n }\">\r\n </ng-container>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</aggregation-panel>\r\n\r\n<ng-template\r\n #treeItemTpl\r\n let-node=\"node\"\r\n let-path=\"path\"\r\n let-field=\"field\"\r\n let-tpl=\"tpl\"\r\n let-parent=\"parent\">\r\n <div\r\n role=\"treeitem\"\r\n [style.--level]=\"treeItemLevel(node)\"\r\n [attr.aria-selected]=\"node.$selected ?? false\"\r\n [attr.aria-expanded]=\"\r\n node.hasChildren !== false ? (node.$opened ?? false) : null\r\n \"\r\n [attr.aria-disabled]=\"node.count === 0 ? 'true' : null\"\r\n [attr.disabled]=\"node.count === 0 ? 'disabled' : null\">\r\n <a\r\n [attr.aria-label]=\"treeItemName(node) | syslang\"\r\n [class]=\"\r\n cn(\r\n 'flex grow items-center gap-2 p-1 leading-7',\r\n node.count === 0 && 'disabled pointer-events-none',\r\n (node.$selected || node.$selectedVisually) && ''\r\n )\r\n \"\r\n (click)=\"selectTreeItem(node, parent, $event, true)\">\r\n <button\r\n variant=\"none\"\r\n [iconOnly]=\"true\"\r\n (click)=\"toggleTreeNode($event, node)\"\r\n class=\"transition-transform ease-in hover:scale-125\"\r\n aria-label=\"Open\">\r\n <ChevronRight\r\n [class]=\"\r\n cn(\r\n 'size-4 translate-x-1',\r\n node.$opened && 'rotate-90',\r\n !node.hasChildren && 'hidden'\r\n )\r\n \"\r\n width=\"16\"\r\n height=\"16\" />\r\n </button>\r\n @if (showCheckbox()) {\r\n <input\r\n type=\"checkbox\"\r\n role=\"checkbox\"\r\n value=\"{{ node.value }}\"\r\n [attr.disabled]=\"node.count === 0 ? true : null\"\r\n [attr.aria-disabled]=\"node.count === 0\"\r\n (keydown.enter)=\"selectTreeItem(node, parent, $event)\"\r\n [checked]=\"node.$selected || node.$selectedVisually\" />\r\n }\r\n @if (resolvedItemTemplate(); as tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tpl\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: node,\r\n field: field,\r\n selected: node.$selected || node.$selectedVisually || false,\r\n count: node.count,\r\n name: (treeItemName(node) | syslang) ?? '',\r\n searchText: searchText(),\r\n level: treeItemLevel(node),\r\n expanded: node.$opened ?? false,\r\n hasChildren: node.hasChildren ?? false\r\n }\" />\r\n } @else {\r\n @let icon = node.icon;\r\n @if (icon) {\r\n <FaIcon [faClass]=\"icon\" class=\"self-center justify-self-center\" />\r\n }\r\n <span\r\n [class]=\"\r\n cn(\r\n 'line-clamp-1 break-all text-ellipsis',\r\n quickFilter() && 'hover:underline'\r\n )\r\n \"\r\n [title]=\"\r\n quickFilter()\r\n ? ((isTreeItemFiltered(node, field)\r\n ? 'filters.removeFilter'\r\n : 'filters.addFilter'\r\n ) | transloco) +\r\n ': ' +\r\n (treeItemName(node) | syslang)\r\n : (treeItemName(node) | syslang)\r\n \"\r\n (click)=\"onTreeItemTextClick(node, parent, $event)\">\r\n @for (\r\n chunk of (treeItemName(node) | syslang) ?? \"\"\r\n | highlightWord: searchText() : 10;\r\n track $index\r\n ) {\r\n <span [class]=\"{ 'font-bold': chunk.match }\" aria-hidden=\"true\">{{\r\n chunk.text\r\n }}</span>\r\n }\r\n </span>\r\n @if (showCount() && node.count > 0) {\r\n <span class=\"ml-auto px-1 text-xs empty:hidden\" aria-hidden=\"true\">{{\r\n node.count\r\n }}</span>\r\n }\r\n }\r\n </a>\r\n @if (node.hasChildren && node.$opened) {\r\n <div role=\"group\">\r\n @for (child of node.items; track $index) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tpl\"\r\n [ngTemplateOutletContext]=\"{\r\n node: child,\r\n path: treeChildrenPath(node, path),\r\n field: field,\r\n tpl: tpl,\r\n parent: node\r\n }\">\r\n </ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-template>\r\n", styles: ["div[role=treeitem]:has(+div[role=treeitem]){margin-bottom:var(--agg-item-gap, 0)}div[role=treeitem]{display:block;-webkit-user-select:none;user-select:none}div[role=treeitem] a{padding-left:calc(var(--agg-tree-indent, .5rem) * var(--level, 0));line-height:var(--agg-item-height, inherit)}\n"] }]
14760
+ }, template: "@if (!aggregation()?.isTree) {\r\n <div class=\"p-2 text-sm text-red-500\">\r\n <triangle-alert-icon class=\"mr-1\" />\r\n The aggregationTree component does not support list aggregations. Please use\r\n the &lt;Aggregation /&gt; component instead.\r\n </div>\r\n}\r\n<aggregation-panel\r\n [id]=\"id()\"\r\n [collapsible]=\"collapsible()\"\r\n [collapsed]=\"collapsed()\"\r\n [isEmpty]=\"isEmpty()\"\r\n [isDate]=\"isDate()\"\r\n [aggregation]=\"aggregation()\"\r\n [showFiltersCount]=\"showFiltersCount()\"\r\n [filtersCount]=\"filtersCount()\"\r\n [hasFilters]=\"hasFilters()\"\r\n [selection]=\"selection()\"\r\n [isAllSelected]=\"isAllSelected()\"\r\n [(searchText)]=\"searchText\"\r\n [itemsLength]=\"items().length\"\r\n [hasMore]=\"aggregation()?.$hasMore ?? false\"\r\n [searchedItemsLength]=\"searchedItems().length\"\r\n (cleared)=\"clear()\"\r\n (applied)=\"apply()\"\r\n (allSelected)=\"selectAll()\"\r\n (allUnselected)=\"unselectAll()\"\r\n (loadedMore)=\"loadMore()\">\r\n <div\r\n #scrollElement\r\n class=\"max-h-(--scroll-height,20rem) w-full scrollbar-thin overflow-auto\">\r\n <div\r\n class=\"relative w-full\"\r\n [style.height]=\"virtualizer.getTotalSize() + 'px'\"\r\n role=\"tree\"\r\n [attr.aria-label]=\"aggregation()?.display | syslang | transloco\">\r\n <div\r\n class=\"absolute top-0 left-0 w-full\"\r\n [style.transform]=\"\r\n 'translateY(' +\r\n (virtualizer.getVirtualItems()[0]\r\n ? virtualizer.getVirtualItems()[0].start\r\n : 0) +\r\n 'px)'\r\n \">\r\n @for (vItem of virtualizer.getVirtualItems(); track vItem.index) {\r\n @let item = items()[vItem.index];\r\n <div #virtualItem [attr.data-index]=\"vItem.index\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"treeItemTpl\"\r\n [ngTemplateOutletContext]=\"{\r\n node: item,\r\n path: [],\r\n field: aggregation()?.column,\r\n tpl: treeItemTpl,\r\n parent: null\r\n }\">\r\n </ng-container>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</aggregation-panel>\r\n\r\n<ng-template\r\n #treeItemTpl\r\n let-node=\"node\"\r\n let-path=\"path\"\r\n let-field=\"field\"\r\n let-tpl=\"tpl\"\r\n let-parent=\"parent\">\r\n <div\r\n role=\"treeitem\"\r\n [style.--level]=\"treeItemLevel(node)\"\r\n [attr.aria-selected]=\"node.$selected ?? false\"\r\n [attr.aria-expanded]=\"\r\n node.hasChildren !== false ? (node.$opened ?? false) : null\r\n \"\r\n [attr.aria-disabled]=\"node.count === 0 ? 'true' : null\"\r\n [attr.disabled]=\"node.count === 0 ? 'disabled' : null\">\r\n <a\r\n [attr.aria-label]=\"treeItemName(node) | syslang\"\r\n [class]=\"\r\n cn(\r\n 'flex grow items-center gap-2 p-1 leading-7',\r\n node.count === 0 && 'disabled pointer-events-none',\r\n (node.$selected || node.$selectedVisually) && ''\r\n )\r\n \"\r\n (click)=\"selectTreeItem(node, parent, $event, true)\">\r\n <button\r\n variant=\"none\"\r\n [iconOnly]=\"true\"\r\n (click)=\"toggleTreeNode($event, node)\"\r\n class=\"transition-transform ease-in hover:scale-125\"\r\n aria-label=\"Open\">\r\n <ChevronRight\r\n [class]=\"\r\n cn(\r\n 'size-4 translate-x-1',\r\n node.$opened && 'rotate-90',\r\n !node.hasChildren && 'hidden'\r\n )\r\n \"\r\n width=\"16\"\r\n height=\"16\" />\r\n </button>\r\n @if (showCheckbox()) {\r\n <input\r\n type=\"checkbox\"\r\n role=\"checkbox\"\r\n value=\"{{ node.value }}\"\r\n [attr.disabled]=\"node.count === 0 ? true : null\"\r\n [attr.aria-disabled]=\"node.count === 0\"\r\n (keydown.enter)=\"selectTreeItem(node, parent, $event, true)\"\r\n [checked]=\"node.$selected || node.$selectedVisually\" />\r\n }\r\n @if (resolvedItemTemplate(); as tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tpl\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: node,\r\n field: field,\r\n selected: node.$selected || node.$selectedVisually || false,\r\n count: node.count,\r\n name: (treeItemName(node) | syslang) ?? '',\r\n searchText: searchText(),\r\n level: treeItemLevel(node),\r\n expanded: node.$opened ?? false,\r\n hasChildren: node.hasChildren ?? false\r\n }\" />\r\n } @else {\r\n @let icon = node.icon;\r\n @if (icon) {\r\n <FaIcon [faClass]=\"icon\" class=\"self-center justify-self-center\" />\r\n }\r\n <span\r\n [class]=\"\r\n cn(\r\n 'line-clamp-1 break-all text-ellipsis',\r\n quickFilter() && 'hover:underline'\r\n )\r\n \"\r\n [title]=\"\r\n quickFilter()\r\n ? ((isTreeItemFiltered(node, field)\r\n ? 'filters.removeFilter'\r\n : 'filters.addFilter'\r\n ) | transloco) +\r\n ': ' +\r\n (treeItemName(node) | syslang)\r\n : (treeItemName(node) | syslang)\r\n \"\r\n (click)=\"onTreeItemTextClick(node, parent, $event)\">\r\n @for (\r\n chunk of (treeItemName(node) | syslang) ?? \"\"\r\n | highlightWord: searchText() : 10;\r\n track $index\r\n ) {\r\n <span [class]=\"{ 'font-bold': chunk.match }\" aria-hidden=\"true\">{{\r\n chunk.text\r\n }}</span>\r\n }\r\n </span>\r\n @if (showCount() && node.count > 0) {\r\n <span class=\"ml-auto px-1 text-xs empty:hidden\" aria-hidden=\"true\">{{\r\n node.count\r\n }}</span>\r\n }\r\n }\r\n </a>\r\n @if (node.hasChildren && node.$opened) {\r\n <div role=\"group\">\r\n @for (child of node.items; track $index) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tpl\"\r\n [ngTemplateOutletContext]=\"{\r\n node: child,\r\n path: treeChildrenPath(node, path),\r\n field: field,\r\n tpl: tpl,\r\n parent: node\r\n }\">\r\n </ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-template>\r\n", styles: ["div[role=treeitem]:has(+div[role=treeitem]){margin-bottom:var(--agg-item-gap, 0)}div[role=treeitem]{display:block;-webkit-user-select:none;user-select:none}div[role=treeitem] a{padding-left:calc(var(--agg-tree-indent, .5rem) * var(--level, 0));line-height:var(--agg-item-height, inherit)}\n"] }]
14736
14761
  }], ctorParameters: () => [], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], showFiltersCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFiltersCount", required: false }] }], showCheckbox: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCheckbox", required: false }] }], expandedLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedLevel", required: false }] }], syncUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "syncUrl", required: false }] }], controlledQuery: [{ type: i0.Input, args: [{ isSignal: true, alias: "query", required: false }] }], controlledAggregation: [{ type: i0.Input, args: [{ isSignal: true, alias: "aggregation", required: false }] }], controlledSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }], onApply: [{ type: i0.Output, args: ["onApply"] }], onClear: [{ type: i0.Output, args: ["onClear"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], filtersChange: [{ type: i0.Output, args: ["filtersChange"] }], virtualItems: [{ type: i0.ViewChildren, args: ["virtualItem", { isSignal: true }] }], scrollElement: [{ type: i0.ViewChild, args: ["scrollElement", { isSignal: true }] }], itemDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => AggregationItemDirective), { isSignal: true }] }], itemTemplateInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], searchText: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchText", required: false }] }, { type: i0.Output, args: ["searchTextChange"] }] } });
14737
14762
 
14738
14763
  class AggregationListComponent {