@acorex-platform/framework-client 2.0.0-next.2 → 2.0.0-next.20

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.
Files changed (58) hide show
  1. package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-ChU2tvyt.mjs → acorex-platform-framework-client-common-common-settings.provider-Cyr1DaiD.mjs} +19 -2
  2. package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-ChU2tvyt.mjs.map → acorex-platform-framework-client-common-common-settings.provider-Cyr1DaiD.mjs.map} +1 -1
  3. package/fesm2022/acorex-platform-framework-client-common.mjs +416 -191
  4. package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
  5. package/fesm2022/acorex-platform-framework-client-core.mjs +7 -2
  6. package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-framework-client-layout-components.mjs +329 -114
  8. package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
  9. package/fesm2022/{acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-CA19c8sx.mjs → acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-uEA2EE9v.mjs} +706 -200
  10. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-uEA2EE9v.mjs.map +1 -0
  11. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-Dxp4kGsa.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-i9bfszKb.mjs} +2 -2
  12. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-Dxp4kGsa.mjs.map → acorex-platform-framework-client-layout-entity-attachments-page.component-i9bfszKb.mjs.map} +1 -1
  13. package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-fnICGK0s.mjs → acorex-platform-framework-client-layout-entity-bulk-entity.command-Ej4_qrGa.mjs} +2 -2
  14. package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-fnICGK0s.mjs.map → acorex-platform-framework-client-layout-entity-bulk-entity.command-Ej4_qrGa.mjs.map} +1 -1
  15. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-BxTbTlUr.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-BbYsgq32.mjs} +4 -4
  16. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-BxTbTlUr.mjs.map → acorex-platform-framework-client-layout-entity-file-list-popup.component-BbYsgq32.mjs.map} +1 -1
  17. package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-D0WZheYu.mjs → acorex-platform-framework-client-layout-entity-gallery-page.component-CWc-6CZ8.mjs} +2 -2
  18. package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-D0WZheYu.mjs.map → acorex-platform-framework-client-layout-entity-gallery-page.component-CWc-6CZ8.mjs.map} +1 -1
  19. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +1 -1
  20. package/fesm2022/acorex-platform-framework-client-layout-views.mjs +71 -10
  21. package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
  22. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +279 -184
  23. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
  24. package/fesm2022/{acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-1UJh0Qj4.mjs → acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-DZMgisgf.mjs} +183 -102
  25. package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-DZMgisgf.mjs.map +1 -0
  26. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-SHCgo4UC.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-BejeCu5q.mjs} +3 -3
  27. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-SHCgo4UC.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-BejeCu5q.mjs.map} +1 -1
  28. package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BYsrp8LT.mjs → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-C2XsTtkl.mjs} +2 -2
  29. package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BYsrp8LT.mjs.map → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-C2XsTtkl.mjs.map} +1 -1
  30. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +1 -1
  31. package/fesm2022/acorex-platform-framework-client-realtime.mjs +49 -7
  32. package/fesm2022/acorex-platform-framework-client-realtime.mjs.map +1 -1
  33. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-create-view.component-DwCoz2Du.mjs → acorex-platform-framework-client-themes-default-entity-master-create-view.component-DPU6jTDk.mjs} +8 -2
  34. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DPU6jTDk.mjs.map +1 -0
  35. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BCyFK60f.mjs → acorex-platform-framework-client-themes-default-entity-master-modify-view.component-CLdQJ8e8.mjs} +8 -2
  36. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-CLdQJ8e8.mjs.map +1 -0
  37. package/fesm2022/acorex-platform-framework-client-themes-default.mjs +42 -17
  38. package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
  39. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +1 -1
  40. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
  41. package/i18n/en-AU/general.json +16 -4
  42. package/i18n/en-AU/layout.json +2 -1
  43. package/i18n/en-US/general.json +16 -4
  44. package/i18n/en-US/layout.json +2 -1
  45. package/i18n/fa-IR/general.json +16 -4
  46. package/i18n/fa-IR/layout.json +2 -1
  47. package/package.json +6 -6
  48. package/types/acorex-platform-framework-client-common.d.ts +67 -7
  49. package/types/acorex-platform-framework-client-layout-components.d.ts +35 -4
  50. package/types/acorex-platform-framework-client-layout-entity.d.ts +83 -31
  51. package/types/acorex-platform-framework-client-layout-views.d.ts +15 -0
  52. package/types/acorex-platform-framework-client-layout-widget-core.d.ts +64 -14
  53. package/types/acorex-platform-framework-client-layout-widgets.d.ts +24 -1
  54. package/types/acorex-platform-framework-client-realtime.d.ts +5 -0
  55. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-CA19c8sx.mjs.map +0 -1
  56. package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-1UJh0Qj4.mjs.map +0 -1
  57. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DwCoz2Du.mjs.map +0 -1
  58. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BCyFK60f.mjs.map +0 -1
@@ -3,7 +3,7 @@ import { AXLocaleService } from '@acorex/core/locale';
3
3
  import * as i1$2 from '@acorex/components/button';
4
4
  import { AXButtonModule } from '@acorex/components/button';
5
5
  import * as i1$6 from '@acorex/cdk/common';
6
- import { AXCommonModule } from '@acorex/cdk/common';
6
+ import { AXCommonModule, AXDataSource } from '@acorex/cdk/common';
7
7
  import * as i2$1 from '@acorex/components/decorators';
8
8
  import { AXDecoratorModule } from '@acorex/components/decorators';
9
9
  import * as i3 from '@acorex/core/translation';
@@ -14,12 +14,12 @@ import * as i4$3 from '@acorex/core/format';
14
14
  import { AXFormatService, AXFormatModule } from '@acorex/core/format';
15
15
  import { AXPLayoutRendererComponent, AXPDialogOpener, AXPLayoutBuilderService, resolveLayoutBuilderDialogResult } from '@acorex-platform/framework-client/layout/builder';
16
16
  import * as i1 from '@angular/common';
17
- import { CommonModule, NgTemplateOutlet, AsyncPipe, isPlatformBrowser, NgComponentOutlet, DOCUMENT } from '@angular/common';
17
+ import { CommonModule, NgTemplateOutlet, AsyncPipe, isPlatformBrowser, DOCUMENT, NgComponentOutlet } from '@angular/common';
18
18
  import * as i0 from '@angular/core';
19
19
  import { inject, input, signal, effect, ViewEncapsulation, ChangeDetectionStrategy, Component, output, computed, linkedSignal, InjectionToken, Injector, Injectable, Directive, viewChild, contentChild, ElementRef, afterNextRender, model, EventEmitter, forwardRef, ViewChild, Output, Input, untracked, DestroyRef, PLATFORM_ID, createComponent, EnvironmentInjector, runInInjectionContext, ApplicationRef, makeEnvironmentProviders, viewChildren, ViewChildren, TemplateRef, contentChildren } from '@angular/core';
20
20
  import { AXAccordionCdkModule } from '@acorex/cdk/accordion';
21
21
  import { AXTagModule } from '@acorex/components/tag';
22
- import { AXPSettingsService, AXPStateMessageComponent, AXPFileChooserSettings, normalizeStoredImageRef, extractFileExtension, AXPFileStorageService, AXPFileTypeProviderService, resolveFileTypeDisplay, AXPCommonSettings, coerceAXPSettingRawValueByKind, AXPFilterOperatorMiddlewareService, ALL_DEFAULT_OPERATORS, withDefaultMultiLanguageOnWidgetProperty, AXPDefaultMultiLanguageConfigService, resolveSearchableText, isStoredImageFileId, resolveStoredImageDisplayUrl } from '@acorex-platform/framework-client/common';
22
+ import { AXPSettingsService, AXPStateMessageComponent, openSystemFileDialog, AXPFileChooserSettings, normalizeStoredImageRef, extractFileExtension, AXPFileStorageService, AXPFileTypeProviderService, resolveFileTypeDisplay, AXPCommonSettings, coerceAXPSettingRawValueByKind, AXPFilterOperatorMiddlewareService, ALL_DEFAULT_OPERATORS, withDefaultMultiLanguageOnWidgetProperty, AXPDefaultMultiLanguageConfigService, resolveSearchableText, isStoredImageFileId, resolveStoredImageDisplayUrl, AXPUserStatusFeatureService } from '@acorex-platform/framework-client/common';
23
23
  export { AXPFileChooserSettings, AXPStateMessageComponent } from '@acorex-platform/framework-client/common';
24
24
  import * as i1$1 from '@acorex/components/avatar';
25
25
  import { AXAvatarModule } from '@acorex/components/avatar';
@@ -65,8 +65,8 @@ import { AXPopupService } from '@acorex/components/popup';
65
65
  import { moveItemInArray as moveItemInArray$1, AXDragDirective, AXDragHandleDirective, AXDropListDirective } from '@acorex/cdk/drag-drop';
66
66
  import { normalizeEntityListUserStylingRules, AXP_ENTITY_LIST_RECORD_STYLING_TARGET, createEntityListStylingCondition, isEntityListRecordStylingTarget, resolveEntityListFilterQueryField, resolveEntityListFilterContextField, isCustomQueryView } from '@acorex-platform/framework-shared/entity';
67
67
  import { AXLookupComponent } from '@acorex/components/lookup';
68
- import { DomSanitizer } from '@angular/platform-browser';
69
68
  import { AXToastService } from '@acorex/components/toast';
69
+ import { DomSanitizer } from '@angular/platform-browser';
70
70
  import { getFileExtension, AXFileService } from '@acorex/core/file';
71
71
  import { AXDialogService } from '@acorex/components/dialog';
72
72
  import { resolveFileViewerFileType, AXFileViewerContainerComponent, AXFileViewerService, AXFileViewerGalleryService } from '@acorex/components/file-viewer';
@@ -1490,7 +1490,7 @@ class AXPColorChooserComponent {
1490
1490
  this.dropdownWidth.set(`${Math.max(hostWidth, POPOVER_MIN_WIDTH_PX)}px`);
1491
1491
  }
1492
1492
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPColorChooserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1493
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPColorChooserComponent, isStandalone: true, selector: "axp-color-chooser", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: false, transformFunction: null }, selectedClass: { classPropertyName: "selectedClass", publicName: "selectedClass", isSignal: true, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, allowClear: { classPropertyName: "allowClear", publicName: "allowClear", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { classSelected: "classSelected" }, host: { listeners: { "click": "hostClickListener()" }, classAttribute: "axp-color-chooser" }, viewQueries: [{ propertyName: "paletteDropdown", first: true, predicate: ["paletteDropdown"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"__root\" [class.__disabled]=\"disabled()\" [class.__readonly]=\"readonly()\">\n @if (usePopover()) {\n <!-- ----- Same shell as ax-select-box: dropdown-box + input slot + panel ----- -->\n <ax-dropdown-box\n #paletteDropdown\n [disabled]=\"disabled()\"\n [popoverWidth]=\"dropdownWidth()\"\n (onOpened)=\"handleDropdownOpened()\"\n (onClosed)=\"handleDropdownClosed()\"\n >\n <ng-container input>\n <div class=\"ax-editor ax-content ax-input\">\n <ng-container *ngTemplateOutlet=\"selectedItem\"></ng-container>\n </div>\n @if (allowClear() && hasSelection() && isInteractive()) {\n <button\n type=\"button\"\n class=\"ax-general-button-icon\"\n tabindex=\"-1\"\n (click)=\"handleClear($event)\"\n >\n <span class=\"ax-icon ax-icon-close\"></span>\n </button>\n }\n <button type=\"button\" class=\"ax-general-button-icon\" [disabled]=\"!isInteractive()\" tabindex=\"-1\">\n <span\n class=\"ax-icon\"\n [class.ax-icon-chevron-down]=\"!dropdownOpen()\"\n [class.ax-icon-chevron-up]=\"dropdownOpen()\"\n ></span>\n </button>\n </ng-container>\n <ng-container panel>\n <div class=\"__popover\" [style.min-width]=\"dropdownWidth()\">\n <ng-container *ngTemplateOutlet=\"paletteGroups; context: { showTitles: true }\"></ng-container>\n </div>\n </ng-container>\n </ax-dropdown-box>\n }\n <!-- ----- Single named row stays inline at select height ----- -->\n @else {\n <ng-container *ngTemplateOutlet=\"paletteGroups; context: { showTitles: false }\"></ng-container>\n <!-- ----- Clear under the single inline strip ----- -->\n @if (allowClear()) {\n <button\n type=\"button\"\n class=\"__clear\"\n [class.__selected]=\"selectedClass() == null\"\n [disabled]=\"!isInteractive()\"\n (click)=\"handleClear($event)\"\n >\n <span class=\"ax-icon ax-icon-close\"></span>\n </button>\n }\n }\n</div>\n\n<ng-template #selectedItem>\n @if (selectedSwatch(); as swatch) {\n <!-- ----- Selected value as a surface-colored pill ----- -->\n <div class=\"__selected-item {{ swatch.className }}\">\n <span class=\"__selected-text\">\n <!-- ----- Group title before the selected variant ----- -->\n @if (selectedGroup()?.title; as groupTitle) {\n {{ groupTitle | translate | async }}\n <span class=\"__trigger-sep\">\u00B7</span>\n }\n {{ displayLabel(swatch.label) | translate | async }}\n </span>\n </div>\n }\n <!-- ----- Empty state uses the same control height as a select ----- -->\n @else {\n <div class=\"ax-placeholder\">\n {{ '@platform-layout-widgets:widgets.color-chooser.placeholder' | translate | async }}\n </div>\n }\n</ng-template>\n\n<ng-template #paletteGroups let-showTitles=\"showTitles\">\n <div class=\"__groups\" [class.__look-strip]=\"look() === 'strip'\" [class.__look-swatches]=\"look() === 'swatches'\">\n @for (group of resolvedGroups(); track group.id) {\n <div class=\"__group\">\n <!-- ----- Named row title inside the dropdown list ----- -->\n @if (showTitles && group.title) {\n <div class=\"__group-title\">{{ group.title | translate | async }}</div>\n }\n <!-- ----- Coolors bar: thin columns, hover expands and shows the label ----- -->\n <div class=\"__strip\" role=\"listbox\">\n @for (swatch of group.swatches; track swatch.className) {\n <button\n type=\"button\"\n class=\"__column {{ swatch.className }}\"\n [class.__selected]=\"isSelected(swatch.className)\"\n [disabled]=\"!isInteractive()\"\n [attr.aria-label]=\"displayLabel(swatch.label)\"\n [attr.aria-selected]=\"isSelected(swatch.className)\"\n (click)=\"handleSelect(swatch)\"\n >\n <span class=\"__label\">{{ displayLabel(swatch.label) | translate | async }}</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;min-height:var(--ax-sys-size-base, 2.5rem);width:100%}:host ax-dropdown-box{width:100%}:host .ax-editor-container{padding-block:0}:host .ax-content{display:flex;min-height:var(--ax-sys-size-base, 2.5rem);min-width:0;flex:1;cursor:pointer;align-items:center;outline:none;-webkit-user-select:none;user-select:none}.__root{display:flex;flex-direction:column;gap:.5rem}.__selected-item{display:inline-flex;align-items:center;max-width:100%;min-height:1.5rem;padding-inline:.5rem;border-radius:.375rem}.__selected-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__placeholder{opacity:.65}.__trigger-sep{margin-inline:.25rem}.__popover{box-sizing:border-box;width:100%;max-height:min(24rem,70vh);overflow:auto;padding:.75rem}.__groups{display:flex;flex-direction:column;gap:.75rem;min-width:0}.__group-title{font-size:.75rem;font-weight:500;color:rgb(var(--ax-sys-color-on-lighter-surface))}.__strip{display:flex;flex-wrap:nowrap;align-items:stretch;width:100%;height:var(--ax-sys-size-base, 2.5rem);overflow:hidden;border-radius:.5rem}.__column{position:relative;flex:1 1 0;min-width:0;margin:0;padding:0;border:0;border-radius:0;appearance:none;cursor:pointer;transition:flex .22s ease}.__label{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;font-size:var(--ax-sys-text-xs-base, .75rem);font-weight:600;letter-spacing:.04em;white-space:nowrap;opacity:0;transition:opacity .16s ease}.__look-strip .__column.__selected,.__look-strip .__column:hover:not(:disabled),.__look-strip .__column:focus-visible:not(:disabled){flex:4 1 0}.__look-strip .__column.__selected .__label,.__look-strip .__column:hover:not(:disabled) .__label,.__look-strip .__column:focus-visible:not(:disabled) .__label{opacity:1}.__look-strip .__strip:has(.__column:hover:not(.__selected)) .__column.__selected:not(:hover),.__look-strip .__strip:has(.__column:focus-visible:not(.__selected)) .__column.__selected:not(:focus-visible){flex:1 1 0}.__look-strip .__strip:has(.__column:hover:not(.__selected)) .__column.__selected:not(:hover) .__label,.__look-strip .__strip:has(.__column:focus-visible:not(.__selected)) .__column.__selected:not(:focus-visible) .__label{opacity:0}.__column.__selected{box-shadow:inset 0 0 0 2px rgb(var(--ax-sys-color-on-lighter-surface) / .4)}.__column:disabled{cursor:not-allowed}.__clear{align-self:flex-start;display:inline-flex;height:1.75rem;width:1.75rem;align-items:center;justify-content:center;border-radius:999px;border:1px dashed rgb(var(--ax-sys-color-border-lighter-surface));background:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));font-size:.75rem}.__clear.__selected,.__clear:focus-visible:not(:disabled){outline:2px solid rgb(var(--ax-sys-color-primary));outline-offset:2px}.__clear:disabled{cursor:not-allowed;opacity:.5}.__look-swatches .__strip{height:auto;flex-wrap:wrap;gap:.25rem;overflow:visible;border-radius:0}.__look-swatches .__column{flex:0 0 2rem;width:2rem;height:2rem;min-width:2rem;border-radius:.375rem;transition:transform .16s ease}.__look-swatches .__label{display:none}.__look-swatches .__column:hover:not(:disabled),.__look-swatches .__column:focus-visible:not(:disabled){flex:0 0 2rem;transform:scale(1.08)}.__disabled .__column,.__readonly .__column,.__disabled .__clear,.__readonly .__clear,.__disabled .ax-content,.__readonly .ax-content{cursor:default}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i5.AXDropdownBoxComponent, selector: "ax-dropdown-box", inputs: ["disabled", "look", "hasInput", "popoverWidth"], outputs: ["disabledChange", "onBlur", "onFocus", "onClick", "onOpened", "onClosed"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1493
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPColorChooserComponent, isStandalone: true, selector: "axp-color-chooser", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: false, transformFunction: null }, selectedClass: { classPropertyName: "selectedClass", publicName: "selectedClass", isSignal: true, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, allowClear: { classPropertyName: "allowClear", publicName: "allowClear", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { classSelected: "classSelected" }, host: { listeners: { "click": "hostClickListener()" }, classAttribute: "axp-color-chooser" }, viewQueries: [{ propertyName: "paletteDropdown", first: true, predicate: ["paletteDropdown"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"__root\" [class.__disabled]=\"disabled()\" [class.__readonly]=\"readonly()\">\n @if (usePopover()) {\n <!-- ----- Same shell as ax-select-box: dropdown-box + input slot + panel ----- -->\n <ax-dropdown-box\n #paletteDropdown\n [disabled]=\"disabled()\"\n [popoverWidth]=\"dropdownWidth()\"\n (onOpened)=\"handleDropdownOpened()\"\n (onClosed)=\"handleDropdownClosed()\"\n >\n <ng-container input>\n <div class=\"ax-editor ax-content ax-input\">\n <ng-container *ngTemplateOutlet=\"selectedItem\"></ng-container>\n </div>\n @if (allowClear() && hasSelection() && isInteractive()) {\n <button\n type=\"button\"\n class=\"ax-general-button-icon\"\n tabindex=\"-1\"\n (click)=\"handleClear($event)\"\n >\n <span class=\"ax-icon ax-icon-close\"></span>\n </button>\n }\n <button type=\"button\" class=\"ax-general-button-icon\" [disabled]=\"!isInteractive()\" tabindex=\"-1\">\n <span\n class=\"ax-icon\"\n [class.ax-icon-chevron-down]=\"!dropdownOpen()\"\n [class.ax-icon-chevron-up]=\"dropdownOpen()\"\n ></span>\n </button>\n </ng-container>\n <ng-container panel>\n <div class=\"__popover\" [style.min-width]=\"dropdownWidth()\">\n <ng-container *ngTemplateOutlet=\"paletteGroups; context: { showTitles: true }\"></ng-container>\n </div>\n </ng-container>\n </ax-dropdown-box>\n }\n <!-- ----- Single named row stays inline at select height ----- -->\n @else {\n <ng-container *ngTemplateOutlet=\"paletteGroups; context: { showTitles: false }\"></ng-container>\n <!-- ----- Clear under the single inline strip ----- -->\n @if (allowClear()) {\n <button\n type=\"button\"\n class=\"__clear\"\n [class.__selected]=\"selectedClass() == null\"\n [disabled]=\"!isInteractive()\"\n (click)=\"handleClear($event)\"\n >\n <span class=\"ax-icon ax-icon-close\"></span>\n </button>\n }\n }\n</div>\n\n<ng-template #selectedItem>\n @if (selectedSwatch(); as swatch) {\n <!-- ----- Selected value as a surface-colored pill ----- -->\n <div class=\"__selected-item {{ swatch.className }}\">\n <span class=\"__selected-text\">\n <!-- ----- Group title before the selected variant ----- -->\n @if (selectedGroup()?.title; as groupTitle) {\n {{ groupTitle | translate | async }}\n <span class=\"__trigger-sep\">\u00B7</span>\n }\n {{ displayLabel(swatch.label) | translate | async }}\n </span>\n </div>\n }\n <!-- ----- Empty state uses the same control height as a select ----- -->\n @else {\n <div class=\"ax-placeholder\">\n {{ '@platform-layout-widgets:widgets.color-chooser.placeholder' | translate | async }}\n </div>\n }\n</ng-template>\n\n<ng-template #paletteGroups let-showTitles=\"showTitles\">\n <div class=\"__groups\" [class.__look-strip]=\"look() === 'strip'\" [class.__look-swatches]=\"look() === 'swatches'\">\n @for (group of resolvedGroups(); track group.id) {\n <div class=\"__group\">\n <!-- ----- Named row title inside the dropdown list ----- -->\n @if (showTitles && group.title) {\n <div class=\"__group-title\">{{ group.title | translate | async }}</div>\n }\n <!-- ----- Coolors bar: thin columns, hover expands and shows the label ----- -->\n <div class=\"__strip\" role=\"listbox\">\n @for (swatch of group.swatches; track swatch.className) {\n <button\n type=\"button\"\n class=\"__column {{ swatch.className }}\"\n [class.__selected]=\"isSelected(swatch.className)\"\n [disabled]=\"!isInteractive()\"\n [attr.aria-label]=\"displayLabel(swatch.label)\"\n [attr.aria-selected]=\"isSelected(swatch.className)\"\n (click)=\"handleSelect(swatch)\"\n >\n <span class=\"__label\">{{ displayLabel(swatch.label) | translate | async }}</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;min-height:var(--ax-sys-size-base, 2.5rem);width:100%}:host ax-dropdown-box{width:100%}:host .ax-editor-container{padding-block:0}:host .ax-content{display:flex;min-height:var(--ax-sys-size-base, 2.5rem);min-width:0;flex:1;cursor:pointer;align-items:center;outline:none;-webkit-user-select:none;user-select:none}.__root{display:flex;flex-direction:column;gap:.5rem}.__selected-item{display:inline-flex;align-items:center;max-width:100%;min-height:1.5rem;padding-inline:.5rem;border-radius:.375rem}.__selected-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__placeholder{opacity:.65}.__trigger-sep{margin-inline:.25rem}.__popover{box-sizing:border-box;width:100%;max-height:min(24rem,70vh);overflow:auto;padding:.75rem}.__groups{display:flex;flex-direction:column;gap:.75rem;min-width:0}.__group-title{font-size:.75rem;font-weight:500;color:rgb(var(--ax-sys-color-on-lighter-surface))}.__strip{display:flex;flex-wrap:nowrap;align-items:stretch;width:100%;height:var(--ax-sys-size-base, 2.5rem);overflow:hidden;border-radius:.5rem}.__column{position:relative;flex:1 1 0;min-width:0;margin:0;padding:0;border:0;border-radius:0;appearance:none;cursor:pointer;transition:flex .22s ease}.__label{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;font-size:var(--ax-sys-text-xs-base, .75rem);font-weight:600;letter-spacing:.04em;white-space:nowrap;opacity:0;transition:opacity .16s ease}.__look-strip .__column.__selected,.__look-strip .__column:hover:not(:disabled),.__look-strip .__column:focus-visible:not(:disabled){flex:4 1 0}.__look-strip .__column.__selected .__label,.__look-strip .__column:hover:not(:disabled) .__label,.__look-strip .__column:focus-visible:not(:disabled) .__label{opacity:1}.__look-strip .__strip:has(.__column:hover:not(.__selected)) .__column.__selected:not(:hover),.__look-strip .__strip:has(.__column:focus-visible:not(.__selected)) .__column.__selected:not(:focus-visible){flex:1 1 0}.__look-strip .__strip:has(.__column:hover:not(.__selected)) .__column.__selected:not(:hover) .__label,.__look-strip .__strip:has(.__column:focus-visible:not(.__selected)) .__column.__selected:not(:focus-visible) .__label{opacity:0}.__column.__selected{box-shadow:inset 0 0 0 2px rgb(var(--ax-sys-color-on-lighter-surface) / .4)}.__column:disabled{cursor:not-allowed}.__clear{align-self:flex-start;display:inline-flex;height:1.75rem;width:1.75rem;align-items:center;justify-content:center;border-radius:999px;border:1px dashed rgb(var(--ax-sys-color-border-lighter-surface));background:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));font-size:.75rem}.__clear.__selected,.__clear:focus-visible:not(:disabled){outline:2px solid rgb(var(--ax-sys-color-primary));outline-offset:2px}.__clear:disabled{cursor:not-allowed;opacity:.5}.__look-swatches .__strip{height:auto;flex-wrap:wrap;gap:.25rem;overflow:visible;border-radius:0}.__look-swatches .__column{flex:0 0 2rem;width:2rem;height:2rem;min-width:2rem;border-radius:.375rem;transition:transform .16s ease}.__look-swatches .__label{display:none}.__look-swatches .__column:hover:not(:disabled),.__look-swatches .__column:focus-visible:not(:disabled){flex:0 0 2rem;transform:scale(1.08)}.__disabled .__column,.__readonly .__column,.__disabled .__clear,.__readonly .__clear,.__disabled .ax-content,.__readonly .ax-content{cursor:default}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i5.AXDropdownBoxComponent, selector: "ax-dropdown-box", inputs: ["disabled", "look", "hasInput", "popoverWidth", "popoverAnchor"], outputs: ["disabledChange", "onBlur", "onFocus", "onClick", "onOpened", "onClosed"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1494
1494
  }
1495
1495
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPColorChooserComponent, decorators: [{
1496
1496
  type: Component,
@@ -1696,7 +1696,7 @@ class AXPColumnItemListComponent {
1696
1696
  </div>
1697
1697
  </div>
1698
1698
  </ax-popover>
1699
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i1$3.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2$2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1699
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i1$3.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2$2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "restoreFocusOnClose", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1700
1700
  }
1701
1701
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPColumnItemListComponent, decorators: [{
1702
1702
  type: Component,
@@ -3486,7 +3486,7 @@ class AXPConditionBuilderConditionComponent {
3486
3486
  }
3487
3487
  }
3488
3488
  onContextChange(event) {
3489
- if (event.state !== 'changed' || event.origin === 'system') {
3489
+ if (event.state !== 'changed' || event.origin === 'system' || event.origin === 'hydrate') {
3490
3490
  return;
3491
3491
  }
3492
3492
  const filterData = event.data?.filter;
@@ -3511,7 +3511,7 @@ class AXPConditionBuilderConditionComponent {
3511
3511
  this.removeItem.emit(this.item().id ?? '');
3512
3512
  }
3513
3513
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPConditionBuilderConditionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3514
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPConditionBuilderConditionComponent, isStandalone: true, selector: "axp-condition-builder-condition", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, filterDefinitions: { classPropertyName: "filterDefinitions", publicName: "filterDefinitions", isSignal: true, isRequired: false, transformFunction: null }, onResolveWidget: { classPropertyName: "onResolveWidget", publicName: "onResolveWidget", isSignal: true, isRequired: false, transformFunction: null }, showFillByUser: { classPropertyName: "showFillByUser", publicName: "showFillByUser", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, operationsLook: { classPropertyName: "operationsLook", publicName: "operationsLook", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemChange: "itemChange", removeItem: "removeItem" }, ngImport: i0, template: "<div class=\"__condition-row\" [class.__condition-row--comfortable]=\"!compact()\">\n <div class=\"__item-content\">\n <!-- Field Selector -->\n <div class=\"__field-selector\">\n <ax-lookup\n mode=\"drop-down-list\"\n [class.ax-sm]=\"compact()\"\n [dataSource]=\"availableFields()\"\n [ngModel]=\"selectedFieldValue()\"\n (onValueChanged)=\"onFieldChange($event)\"\n valueField=\"value\"\n textField=\"text\"\n [searchable]=\"false\"\n [placeholder]=\"('@data-management:metadata-definitions.components.query-builder.condition.select-field' | translate | async) || 'Select a field'\"\n [look]=\"'outline'\">\n </ax-lookup>\n </div>\n\n <!-- Filter Widget (Operator + Value) -->\n <div class=\"__operator-selector\">\n @if (filterHostKeys().length) {\n <!-- ----- Operator and value for the selected field ----- -->\n @for (hostKey of filterHostKeys(); track hostKey) {\n <axp-widgets-container\n class=\"__filter-widget-container\"\n [context]=\"context()\"\n (onContextChanged)=\"onContextChange($event)\">\n <ng-container axp-widget-renderer [node]=\"filterNode()\" [mode]=\"'edit'\">\n </ng-container>\n </axp-widgets-container>\n }\n }\n <!-- ----- Prompt until a field is chosen ----- -->\n @else {\n <div class=\"__filter-placeholder\">\n <span class=\"__placeholder-text\">{{\n ('@data-management:metadata-definitions.components.query-builder.condition.select-field-first' | translate | async) || 'Select a field first'\n }}</span>\n </div>\n }\n </div>\n\n <!-- Fill By User (optional) -->\n @if (showFillByUser()) {\n <div class=\"__fill-by-user\">\n <ax-check-box\n class=\"text-xs\"\n [ngModel]=\"$safeNavigationMigration(selectedField()?.isParametric)\"\n (ngModelChange)=\"onFillByUserChange($event)\">\n <ax-label>\n {{ '@data-management:metadata-definitions.components.query-builder.condition.fill-by-user' | translate | async }}\n </ax-label>\n </ax-check-box>\n </div>\n }\n </div>\n</div>\n", styles: ["@layer properties;.__condition-row{display:flex;width:100%;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.__condition-row .__item-content{display:flex;flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);display:grid;grid-template-columns:1fr 1fr;gap:.75rem}.__condition-row .__item-content .__field-selector{min-width:0px}.__condition-row .__item-content .__field-selector ax-lookup{width:100%}.__condition-row .__item-content .__operator-selector{min-width:0px}.__condition-row .__item-content .__operator-selector .__filter-widget-container{width:100%}.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep .axp-widgets-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep ax-lookup{min-width:140px}.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep axp-filter-operations.axp-filter-operations--select{min-width:9rem}.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep ax-text-box,.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep ax-number-box,.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep ax-date-time-box{flex:1}.__condition-row .__item-content .__operator-selector .__filter-placeholder{display:flex;align-items:center;justify-content:center;border-radius:.25rem;border-style:var(--tw-border-style);--tw-border-style: dashed;border-style:dashed;background-color:var(--color-lightest);color:var(--color-on-lightest);border-color:var(--color-border-lightest);padding:calc(var(--spacing, .25rem) * 3);border-color:rgba(var(--ax-sys-color-border-lighter-surface),1);border-width:1px}.__condition-row .__item-content .__operator-selector .__filter-placeholder .__placeholder-text{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-500, oklch(55.6% 0 none));font-style:italic}.__condition-row .__item-content .__fill-by-user{grid-column:1 / -1}.__condition-row.__condition-row--comfortable .__field-selector ax-lookup,.__condition-row.__condition-row--comfortable .__filter-placeholder{min-height:var(--ax-sys-size-base, 2.5rem)}.__condition-row.__condition-row--comfortable .__filter-placeholder{justify-content:flex-start;padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:0px}.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep ax-text-box,.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep ax-number-box,.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep ax-date-time-box,.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep ax-lookup,.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep .ax-editor-container{min-height:var(--ax-sys-size-base, 2.5rem)}@media(max-width:768px){.__condition-row{flex-direction:column;align-items:stretch}.__condition-row .__item-content{grid-template-columns:1fr}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXLookupComponent, selector: "ax-lookup", inputs: ["name", "mode", "dataSource", "treeDataSource", "valueField", "textField", "disabledField", "columns", "treeParentField", "hasChildrenField", "searchable", "adaptivityEnabled", "caption", "alternate", "searchPlaceholder", "placeholder", "disabled", "readonly", "look", "itemHeight", "maxVisibleItems", "treeSelectionBehavior", "highlightSearch", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "value", "valueItems"], outputs: ["lookChange", "valueChange", "onValueChanged", "onSelectionChanged", "onFocus", "onBlur", "onItemClick", "onItemSelected", "onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i2$3.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "component", type: i3$4.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$5.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1$5.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3514
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPConditionBuilderConditionComponent, isStandalone: true, selector: "axp-condition-builder-condition", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, filterDefinitions: { classPropertyName: "filterDefinitions", publicName: "filterDefinitions", isSignal: true, isRequired: false, transformFunction: null }, onResolveWidget: { classPropertyName: "onResolveWidget", publicName: "onResolveWidget", isSignal: true, isRequired: false, transformFunction: null }, showFillByUser: { classPropertyName: "showFillByUser", publicName: "showFillByUser", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, operationsLook: { classPropertyName: "operationsLook", publicName: "operationsLook", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemChange: "itemChange", removeItem: "removeItem" }, ngImport: i0, template: "<div class=\"__condition-row\" [class.__condition-row--comfortable]=\"!compact()\">\n <div class=\"__item-content\">\n <!-- Field Selector -->\n <div class=\"__field-selector\">\n <ax-lookup\n mode=\"drop-down-list\"\n [class.ax-sm]=\"compact()\"\n [dataSource]=\"availableFields()\"\n [ngModel]=\"selectedFieldValue()\"\n (onValueChanged)=\"onFieldChange($event)\"\n valueField=\"value\"\n textField=\"text\"\n [searchable]=\"false\"\n [placeholder]=\"('@data-management:metadata-definitions.components.query-builder.condition.select-field' | translate | async) || 'Select a field'\"\n [look]=\"'outline'\">\n </ax-lookup>\n </div>\n\n <!-- Filter Widget (Operator + Value) -->\n <div class=\"__operator-selector\">\n @if (filterHostKeys().length) {\n <!-- ----- Operator and value for the selected field ----- -->\n @for (hostKey of filterHostKeys(); track hostKey) {\n <axp-widgets-container\n class=\"__filter-widget-container\"\n [context]=\"context()\"\n (onContextChanged)=\"onContextChange($event)\">\n <ng-container axp-widget-renderer [node]=\"filterNode()\" [mode]=\"'edit'\">\n </ng-container>\n </axp-widgets-container>\n }\n }\n <!-- ----- Prompt until a field is chosen ----- -->\n @else {\n <div class=\"__filter-placeholder\">\n <span class=\"__placeholder-text\">{{\n ('@data-management:metadata-definitions.components.query-builder.condition.select-field-first' | translate | async) || 'Select a field first'\n }}</span>\n </div>\n }\n </div>\n\n <!-- Fill By User (optional) -->\n @if (showFillByUser()) {\n <div class=\"__fill-by-user\">\n <ax-check-box\n class=\"text-xs\"\n [ngModel]=\"$safeNavigationMigration(selectedField()?.isParametric)\"\n (ngModelChange)=\"onFillByUserChange($event)\">\n <ax-label>\n {{ '@data-management:metadata-definitions.components.query-builder.condition.fill-by-user' | translate | async }}\n </ax-label>\n </ax-check-box>\n </div>\n }\n </div>\n</div>\n", styles: ["@layer properties;.__condition-row{display:flex;width:100%;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.__condition-row .__item-content{display:flex;flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);display:grid;grid-template-columns:1fr 1fr;gap:.75rem}.__condition-row .__item-content .__field-selector{min-width:0px}.__condition-row .__item-content .__field-selector ax-lookup{width:100%}.__condition-row .__item-content .__operator-selector{min-width:0px}.__condition-row .__item-content .__operator-selector .__filter-widget-container{width:100%}.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep .axp-widgets-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep ax-lookup{min-width:140px}.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep axp-filter-operations.axp-filter-operations--select{min-width:9rem}.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep ax-text-box,.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep ax-number-box,.__condition-row .__item-content .__operator-selector .__filter-widget-container ::ng-deep ax-date-time-box{flex:1}.__condition-row .__item-content .__operator-selector .__filter-placeholder{display:flex;align-items:center;justify-content:center;border-radius:.25rem;border-style:var(--tw-border-style);--tw-border-style: dashed;border-style:dashed;background-color:var(--color-lightest);color:var(--color-on-lightest);border-color:var(--color-border-lightest);padding:calc(var(--spacing, .25rem) * 3);border-color:rgba(var(--ax-sys-color-border-lighter-surface),1);border-width:1px}.__condition-row .__item-content .__operator-selector .__filter-placeholder .__placeholder-text{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-500, oklch(55.6% 0 none));font-style:italic}.__condition-row .__item-content .__fill-by-user{grid-column:1 / -1}.__condition-row.__condition-row--comfortable .__field-selector ax-lookup,.__condition-row.__condition-row--comfortable .__filter-placeholder{min-height:var(--ax-sys-size-base, 2.5rem)}.__condition-row.__condition-row--comfortable .__filter-placeholder{justify-content:flex-start;padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:0px}.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep ax-text-box,.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep ax-number-box,.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep ax-date-time-box,.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep ax-lookup,.__condition-row.__condition-row--comfortable .__operator-selector ::ng-deep .ax-editor-container{min-height:var(--ax-sys-size-base, 2.5rem)}@media(max-width:768px){.__condition-row{flex-direction:column;align-items:stretch}.__condition-row .__item-content{grid-template-columns:1fr}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXLookupComponent, selector: "ax-lookup", inputs: ["name", "mode", "dataSource", "treeDataSource", "valueField", "textField", "disabledField", "columns", "treeParentField", "hasChildrenField", "searchable", "adaptivityEnabled", "caption", "alternate", "searchPlaceholder", "placeholder", "disabled", "readonly", "look", "itemHeight", "maxVisibleItems", "treeSelectionBehavior", "highlightSearch", "allowSelectAll", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "value", "valueItems", "prefetch"], outputs: ["lookChange", "valueChange", "onValueChanged", "onSelectionChanged", "onFocus", "onBlur", "onItemClick", "onItemSelected", "onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i2$3.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "component", type: i3$4.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$5.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1$5.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3515
3515
  }
3516
3516
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPConditionBuilderConditionComponent, decorators: [{
3517
3517
  type: Component,
@@ -4066,7 +4066,7 @@ class AXPFileProviderMenuComponent {
4066
4066
  </ax-button-item-list>
4067
4067
  </div>
4068
4068
  </ax-popover>
4069
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2$2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPFileProviderIconComponent, selector: "axp-file-provider-icon", inputs: ["icon"] }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4069
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2$2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "restoreFocusOnClose", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPFileProviderIconComponent, selector: "axp-file-provider-icon", inputs: ["icon"] }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4070
4070
  }
4071
4071
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPFileProviderMenuComponent, decorators: [{
4072
4072
  type: Component,
@@ -4264,36 +4264,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
4264
4264
  args: [{ providedIn: 'root' }]
4265
4265
  }] });
4266
4266
 
4267
- //#region ---- Rejection notifications ----
4268
- async function notifyFileAcceptRejections(rejected, deps) {
4269
- if (rejected.length === 0) {
4270
- return;
4271
- }
4272
- const { translateService, toastService, maxFileSize } = deps;
4273
- const errorTitle = await translateService.translateAsync('@general:messages.error.title');
4274
- const typeRejections = rejected.filter((entry) => entry.reason === 'type');
4275
- const sizeRejections = rejected.filter((entry) => entry.reason === 'size');
4276
- if (typeRejections.length === 1) {
4277
- const content = await translateService.translateAsync('@general:widgets.file-uploader.validation.file-type-not-allowed', { params: { fileName: typeRejections[0].file.name } });
4278
- toastService.show({ color: 'danger', title: errorTitle, content });
4279
- return;
4280
- }
4281
- if (typeRejections.length > 1) {
4282
- const content = await translateService.translateAsync('@general:widgets.file-uploader.validation.file-type-not-allowed-summary', { params: { count: typeRejections.length } });
4283
- toastService.show({ color: 'danger', title: errorTitle, content });
4284
- return;
4285
- }
4286
- if (sizeRejections.length === 1) {
4287
- const maxMb = Math.round((maxFileSize / (1024 * 1024)) * 10) / 10;
4288
- const content = await translateService.translateAsync('@general:widgets.file-uploader.validation.file-size-exceeds-limit', { params: { fileName: sizeRejections[0].file.name, maxSizeMb: maxMb } });
4289
- toastService.show({ color: 'danger', title: errorTitle, content });
4290
- return;
4291
- }
4292
- const content = await translateService.translateAsync('@general:widgets.file-uploader.validation.files-rejected-summary', { params: { count: rejected.length } });
4293
- toastService.show({ color: 'danger', title: errorTitle, content });
4294
- }
4295
- //#endregion
4296
-
4297
4267
  //#endregion
4298
4268
  //#region ---- Validation ----
4299
4269
  function isUnrestrictedFileAccept(accept) {
@@ -4478,6 +4448,36 @@ function matchesCategoryByExtension(fileName, category) {
4478
4448
  }
4479
4449
  //#endregion
4480
4450
 
4451
+ //#region ---- Rejection notifications ----
4452
+ async function notifyFileAcceptRejections(rejected, deps) {
4453
+ if (rejected.length === 0) {
4454
+ return;
4455
+ }
4456
+ const { translateService, toastService, maxFileSize } = deps;
4457
+ const errorTitle = await translateService.translateAsync('@general:messages.generic.error.title');
4458
+ const typeRejections = rejected.filter((entry) => entry.reason === 'type');
4459
+ const sizeRejections = rejected.filter((entry) => entry.reason === 'size');
4460
+ if (typeRejections.length === 1) {
4461
+ const content = await translateService.translateAsync('@general:widgets.file-uploader.validation.file-type-not-allowed', { params: { fileName: typeRejections[0].file.name } });
4462
+ toastService.show({ color: 'danger', title: errorTitle, content });
4463
+ }
4464
+ else if (typeRejections.length > 1) {
4465
+ const content = await translateService.translateAsync('@general:widgets.file-uploader.validation.file-type-not-allowed-summary', { params: { count: typeRejections.length } });
4466
+ toastService.show({ color: 'danger', title: errorTitle, content });
4467
+ }
4468
+ if (sizeRejections.length === 1) {
4469
+ const maxSize = formatMaxFileSizeForDisplay(maxFileSize);
4470
+ const content = await translateService.translateAsync('@general:widgets.file-uploader.validation.file-size-exceeds-limit', { params: { fileName: sizeRejections[0].file.name, maxSize } });
4471
+ toastService.show({ color: 'danger', title: errorTitle, content });
4472
+ return;
4473
+ }
4474
+ if (sizeRejections.length > 1) {
4475
+ const content = await translateService.translateAsync('@general:widgets.file-uploader.validation.files-rejected-summary', { params: { count: sizeRejections.length } });
4476
+ toastService.show({ color: 'danger', title: errorTitle, content });
4477
+ }
4478
+ }
4479
+ //#endregion
4480
+
4481
4481
  //#region ---- Accept resolution ----
4482
4482
  const ZIP_ACCEPT_TOKENS = '.zip,application/zip';
4483
4483
  /**
@@ -4503,7 +4503,8 @@ function resolveFileChooserAccept(accept, promptZipOnMultiple) {
4503
4503
  //#endregion
4504
4504
 
4505
4505
  //#region ---- Chooser result validation ----
4506
- function fileFromListItem(item) {
4506
+ /** Blob-backed chooser item as a {@link File}. Drive and file-id items return undefined. */
4507
+ function resolveChooserItemFile(item) {
4507
4508
  const source = item.source;
4508
4509
  if (source?.kind !== 'blob' || source.value == null) {
4509
4510
  return undefined;
@@ -4512,7 +4513,8 @@ function fileFromListItem(item) {
4512
4513
  return source.value;
4513
4514
  }
4514
4515
  if (source.value instanceof Blob) {
4515
- return new File([source.value], item.name, {
4516
+ const name = item.name?.trim() || 'file';
4517
+ return new File([source.value], name, {
4516
4518
  type: source.value.type ?? '',
4517
4519
  });
4518
4520
  }
@@ -4525,30 +4527,38 @@ function validateFileChooserItems(items, options) {
4525
4527
  const accept = options['accept'];
4526
4528
  const maxFileSize = defaultTo(options['maxFileSize'], 0);
4527
4529
  const passthrough = [];
4528
- const blobItems = [];
4529
- const blobFiles = [];
4530
+ const blobEntries = [];
4530
4531
  for (const item of items) {
4531
- const file = fileFromListItem(item);
4532
+ const file = resolveChooserItemFile(item);
4532
4533
  if (file) {
4533
- blobItems.push(item);
4534
- blobFiles.push(file);
4534
+ blobEntries.push({ item, file });
4535
4535
  continue;
4536
4536
  }
4537
4537
  passthrough.push(item);
4538
4538
  }
4539
- const namedAccepted = passthrough.filter((item) => isUnrestrictedFileAccept(accept) || fileNameMatchesAccept(item.name ?? '', accept));
4540
- const namedRejected = passthrough
4541
- .filter((item) => !namedAccepted.includes(item))
4542
- .map((item) => ({
4543
- file: new File([], item.name ?? 'file', { type: '' }),
4544
- reason: 'type',
4545
- }));
4546
- if (!blobFiles.length) {
4539
+ const namedAccepted = [];
4540
+ const namedRejected = [];
4541
+ for (const item of passthrough) {
4542
+ const placeholder = new File([], item.name ?? 'file', { type: '' });
4543
+ const typeOk = isUnrestrictedFileAccept(accept) || fileNameMatchesAccept(item.name ?? '', accept);
4544
+ if (!typeOk) {
4545
+ namedRejected.push({ file: placeholder, reason: 'type' });
4546
+ continue;
4547
+ }
4548
+ if (maxFileSize > 0 && (item.size ?? 0) > maxFileSize) {
4549
+ namedRejected.push({ file: placeholder, reason: 'size' });
4550
+ continue;
4551
+ }
4552
+ namedAccepted.push(item);
4553
+ }
4554
+ if (!blobEntries.length) {
4547
4555
  return { accepted: namedAccepted, rejected: namedRejected };
4548
4556
  }
4549
- const { accepted, rejected } = filterFilesByAcceptAndMaxSize(blobFiles, accept, maxFileSize);
4557
+ const { accepted, rejected } = filterFilesByAcceptAndMaxSize(blobEntries.map((entry) => entry.file), accept, maxFileSize);
4550
4558
  const acceptedSet = new Set(accepted);
4551
- const acceptedItems = blobItems.filter((item) => acceptedSet.has(fileFromListItem(item)));
4559
+ const acceptedItems = blobEntries
4560
+ .filter((entry) => acceptedSet.has(entry.file))
4561
+ .map((entry) => entry.item);
4552
4562
  return {
4553
4563
  accepted: [...namedAccepted, ...acceptedItems],
4554
4564
  rejected: [...namedRejected, ...rejected],
@@ -4564,9 +4574,7 @@ const AXPFileChooserHookKeys = {
4564
4574
 
4565
4575
  //#region ---- File chooser tokens ----
4566
4576
  /**
4567
-
4568
4577
  * Multi token for file chooser providers (system disk, drive, external systems).
4569
-
4570
4578
  */
4571
4579
  const AXP_FILE_CHOOSER_PROVIDERS = new InjectionToken('AXP_FILE_CHOOSER_PROVIDERS');
4572
4580
  //#endregion
@@ -4578,14 +4586,37 @@ const AXP_SYSTEM_FILE_CHOOSER_PROVIDER = {
4578
4586
  order: 1,
4579
4587
  choose: async (context) => {
4580
4588
  const fileService = inject(AXFileService);
4589
+ const documentRef = inject(DOCUMENT);
4590
+ const translateService = inject(AXTranslationService);
4591
+ const toastService = inject(AXToastService);
4581
4592
  const multiple = Boolean(context.options['multiple']);
4582
4593
  const fileType = context.options['fileType'];
4583
- const accept = context.options['accept'];
4584
- const files = await fileService.choose({
4585
- fileType,
4586
- accept,
4587
- multiple,
4588
- });
4594
+ const acceptOption = context.options['accept'];
4595
+ const maxFileSizeOption = context.options['maxFileSize'];
4596
+ const maxFileSize = typeof maxFileSizeOption === 'number' ? maxFileSizeOption : 0;
4597
+ const accept = fileType
4598
+ ? (acceptOption ?? (await fileService.getAcceptAttribute(fileType)))
4599
+ : (acceptOption ?? '');
4600
+ const picked = await openSystemFileDialog(documentRef, { accept, multiple });
4601
+ if (!picked.length) {
4602
+ return undefined;
4603
+ }
4604
+ let files = picked;
4605
+ if (fileType) {
4606
+ const validation = await fileService.validateMany(picked, fileType);
4607
+ files = validation.accepted;
4608
+ if (validation.rejected.length > 0) {
4609
+ const rejected = validation.rejected.map((entry) => ({
4610
+ file: entry.file,
4611
+ reason: catalogRejectionReason(entry.errors, maxFileSize),
4612
+ }));
4613
+ await notifyFileAcceptRejections(rejected, {
4614
+ translateService,
4615
+ toastService,
4616
+ maxFileSize,
4617
+ });
4618
+ }
4619
+ }
4589
4620
  if (!files.length) {
4590
4621
  return undefined;
4591
4622
  }
@@ -4602,9 +4633,13 @@ const AXP_SYSTEM_FILE_CHOOSER_PROVIDER = {
4602
4633
  if (!multiple) {
4603
4634
  return next.slice(0, 1);
4604
4635
  }
4605
- return [...context.items, ...next];
4636
+ return [...(context.items ?? []), ...next];
4606
4637
  },
4607
4638
  };
4639
+ function catalogRejectionReason(errors, maxFileSize) {
4640
+ const failedForSize = errors.some((error) => (error.rule ?? '').toLowerCase().includes('size'));
4641
+ return failedForSize && maxFileSize > 0 ? 'size' : 'type';
4642
+ }
4608
4643
  //#endregion
4609
4644
 
4610
4645
  //#region ---- File chooser platform settings ----
@@ -4960,13 +4995,18 @@ class AXPFileChooserService {
4960
4995
  if (!items?.length) {
4961
4996
  return items;
4962
4997
  }
4998
+ const previousItems = new Set(context.items ?? []);
4999
+ const incoming = items.filter((item) => !previousItems.has(item));
5000
+ if (incoming.length === 0) {
5001
+ return items;
5002
+ }
4963
5003
  const maxFileSize = defaultTo(context.options['maxFileSize'], 0);
4964
5004
  const promptZipOnMultiple = (await this.settingsService.get(AXPFileChooserSettings.PromptZipOnMultiple)) ?? false;
4965
5005
  const validationOptions = {
4966
5006
  ...context.options,
4967
5007
  accept: resolveFileChooserAccept(context.options['accept'], promptZipOnMultiple),
4968
5008
  };
4969
- const { accepted, rejected } = validateFileChooserItems(items, validationOptions);
5009
+ const { accepted, rejected } = validateFileChooserItems(incoming, validationOptions);
4970
5010
  if (rejected.length > 0) {
4971
5011
  await notifyFileAcceptRejections(rejected, {
4972
5012
  translateService: this.translateService,
@@ -4974,7 +5014,14 @@ class AXPFileChooserService {
4974
5014
  maxFileSize,
4975
5015
  });
4976
5016
  }
4977
- return accepted.length > 0 ? accepted : undefined;
5017
+ if (accepted.length === 0) {
5018
+ return undefined;
5019
+ }
5020
+ if (previousItems.size === 0) {
5021
+ return accepted;
5022
+ }
5023
+ const acceptedIncoming = new Set(accepted);
5024
+ return items.filter((item) => previousItems.has(item) || acceptedIncoming.has(item));
4978
5025
  }
4979
5026
  async runAfterChosenHook(providerKey, context, items) {
4980
5027
  if (!items?.length) {
@@ -5004,6 +5051,8 @@ class AXPFileChooserDirective {
5004
5051
  constructor() {
5005
5052
  //#region ---- Services & Dependencies ----
5006
5053
  this.chooserService = inject(AXPFileChooserService);
5054
+ this.toastService = inject(AXToastService);
5055
+ this.translateService = inject(AXTranslationService);
5007
5056
  this.elementRef = inject(ElementRef);
5008
5057
  this.envInjector = inject(EnvironmentInjector);
5009
5058
  this.appRef = inject(ApplicationRef);
@@ -5064,10 +5113,16 @@ class AXPFileChooserDirective {
5064
5113
  ...this.context(),
5065
5114
  items: this.items(),
5066
5115
  });
5067
- if (result) {
5116
+ if (result?.length) {
5068
5117
  this.items.set(result);
5069
5118
  }
5070
5119
  }
5120
+ catch (error) {
5121
+ console.error('[AXPFileChooserDirective] choose failed', error);
5122
+ const title = await this.translateService.translateAsync('@general:messages.generic.error.title');
5123
+ const content = await this.translateService.translateAsync('@layout:components.file-chooser.messages.choose-failed');
5124
+ this.toastService.show({ color: 'danger', title, content });
5125
+ }
5071
5126
  finally {
5072
5127
  this.busy.set(false);
5073
5128
  }
@@ -5101,30 +5156,38 @@ async function compressImageFile(file, quality = 0.7, maxDimension = 1920) {
5101
5156
  if (!file.type.startsWith('image/') || file.type === 'image/svg+xml') {
5102
5157
  return file;
5103
5158
  }
5104
- const bitmap = await createImageBitmap(file);
5105
- const scale = Math.min(1, maxDimension / Math.max(bitmap.width, bitmap.height));
5106
- const width = Math.max(1, Math.round(bitmap.width * scale));
5107
- const height = Math.max(1, Math.round(bitmap.height * scale));
5108
- const canvas = document.createElement('canvas');
5109
- canvas.width = width;
5110
- canvas.height = height;
5111
- const context = canvas.getContext('2d');
5112
- if (!context) {
5113
- bitmap.close();
5114
- return file;
5159
+ let bitmap;
5160
+ try {
5161
+ bitmap = await createImageBitmap(file);
5162
+ const longestSide = Math.max(bitmap.width, bitmap.height);
5163
+ const scale = longestSide > 0 ? Math.min(1, maxDimension / longestSide) : 1;
5164
+ const width = Math.max(1, Math.round(bitmap.width * scale));
5165
+ const height = Math.max(1, Math.round(bitmap.height * scale));
5166
+ const canvas = document.createElement('canvas');
5167
+ canvas.width = width;
5168
+ canvas.height = height;
5169
+ const context = canvas.getContext('2d');
5170
+ if (!context) {
5171
+ return file;
5172
+ }
5173
+ context.drawImage(bitmap, 0, 0, width, height);
5174
+ const mimeType = file.type === 'image/png' ? 'image/png' : 'image/jpeg';
5175
+ const blob = await new Promise((resolve) => {
5176
+ canvas.toBlob(resolve, mimeType, quality);
5177
+ });
5178
+ if (!blob || blob.size >= file.size) {
5179
+ return file;
5180
+ }
5181
+ const extension = mimeType === 'image/png' ? 'png' : 'jpg';
5182
+ const baseName = file.name.includes('.') ? file.name.slice(0, file.name.lastIndexOf('.')) : file.name;
5183
+ return new File([blob], `${baseName}.${extension}`, { type: mimeType, lastModified: Date.now() });
5115
5184
  }
5116
- context.drawImage(bitmap, 0, 0, width, height);
5117
- bitmap.close();
5118
- const mimeType = file.type === 'image/png' ? 'image/png' : 'image/jpeg';
5119
- const blob = await new Promise((resolve) => {
5120
- canvas.toBlob(resolve, mimeType, quality);
5121
- });
5122
- if (!blob || blob.size >= file.size) {
5185
+ catch {
5123
5186
  return file;
5124
5187
  }
5125
- const extension = mimeType === 'image/png' ? 'png' : 'jpg';
5126
- const baseName = file.name.includes('.') ? file.name.slice(0, file.name.lastIndexOf('.')) : file.name;
5127
- return new File([blob], `${baseName}.${extension}`, { type: mimeType, lastModified: Date.now() });
5188
+ finally {
5189
+ bitmap?.close();
5190
+ }
5128
5191
  }
5129
5192
  /**
5130
5193
  * Builds a store-only ZIP archive (no compression) from the given files.
@@ -5136,9 +5199,10 @@ async function createZipArchive(files, archiveName = 'archive.zip') {
5136
5199
  })));
5137
5200
  const chunks = [];
5138
5201
  const centralDirectory = [];
5202
+ const usedNames = new Set();
5139
5203
  let offset = 0;
5140
5204
  for (const entry of entries) {
5141
- const nameBytes = new TextEncoder().encode(entry.name);
5205
+ const nameBytes = new TextEncoder().encode(uniqueZipEntryName(entry.name, usedNames));
5142
5206
  const crc = crc32(entry.data);
5143
5207
  const localHeader = buildLocalFileHeader(nameBytes, entry.data.length, crc);
5144
5208
  chunks.push(localHeader, nameBytes, entry.data);
@@ -5157,10 +5221,32 @@ async function createZipArchive(files, archiveName = 'archive.zip') {
5157
5221
  }
5158
5222
  return new File([archive], archiveName, { type: 'application/zip', lastModified: Date.now() });
5159
5223
  }
5224
+ const ZIP_VERSION_NEEDED = 20;
5225
+ const ZIP_UTF8_FLAG = 0x0800;
5226
+ function uniqueZipEntryName(name, used) {
5227
+ const baseName = name || 'file';
5228
+ if (!used.has(baseName)) {
5229
+ used.add(baseName);
5230
+ return baseName;
5231
+ }
5232
+ const dot = baseName.lastIndexOf('.');
5233
+ const stem = dot > 0 ? baseName.slice(0, dot) : baseName;
5234
+ const extension = dot > 0 ? baseName.slice(dot) : '';
5235
+ let index = 2;
5236
+ let candidate = `${stem} (${index})${extension}`;
5237
+ while (used.has(candidate)) {
5238
+ index += 1;
5239
+ candidate = `${stem} (${index})${extension}`;
5240
+ }
5241
+ used.add(candidate);
5242
+ return candidate;
5243
+ }
5160
5244
  function buildLocalFileHeader(nameBytes, size, crc) {
5161
5245
  const header = new Uint8Array(30);
5162
5246
  const view = new DataView(header.buffer);
5163
5247
  view.setUint32(0, 0x04034b50, true);
5248
+ view.setUint16(4, ZIP_VERSION_NEEDED, true);
5249
+ view.setUint16(6, ZIP_UTF8_FLAG, true);
5164
5250
  view.setUint16(8, 0, true);
5165
5251
  view.setUint16(10, 0, true);
5166
5252
  view.setUint32(14, crc, true);
@@ -5174,6 +5260,9 @@ function buildCentralDirectoryHeader(nameBytes, size, crc, offset) {
5174
5260
  const header = new Uint8Array(46);
5175
5261
  const view = new DataView(header.buffer);
5176
5262
  view.setUint32(0, 0x02014b50, true);
5263
+ view.setUint16(4, ZIP_VERSION_NEEDED, true);
5264
+ view.setUint16(6, ZIP_VERSION_NEEDED, true);
5265
+ view.setUint16(8, ZIP_UTF8_FLAG, true);
5177
5266
  view.setUint16(10, 0, true);
5178
5267
  view.setUint16(12, 0, true);
5179
5268
  view.setUint32(16, crc, true);
@@ -5783,21 +5872,44 @@ const AXP_SYSTEM_FILE_UPLOADER_PROVIDER = {
5783
5872
  icon: 'fa-light fa-file-arrow-up',
5784
5873
  order: 1,
5785
5874
  upload: async (context) => {
5875
+ const fileStorage = inject(AXPFileStorageService);
5876
+ const translateService = inject(AXTranslationService);
5877
+ const toastService = inject(AXToastService);
5786
5878
  const multiple = Boolean(context.options['multiple']);
5787
- const maxFileSize = defaultTo(context.options['maxFileSize'], 10 * 1024 * 1024);
5879
+ const maxFileSizeOption = context.options['maxFileSize'];
5880
+ // Omitted maxFileSize keeps the historical 10 MB cap. Zero or negative means no limit.
5881
+ const maxFileSize = typeof maxFileSizeOption === 'number' ? maxFileSizeOption : 10 * 1024 * 1024;
5788
5882
  const refId = defaultTo(context.options['refId'], 'temp');
5789
5883
  const refType = defaultTo(context.options['refType'], 'file-uploader');
5790
5884
  const category = defaultTo(context.options['category'], 'attachment');
5791
- const chosen = context.chosen.filter((item) => (item.size ?? 0) <= maxFileSize &&
5792
- item.source?.kind === 'blob' &&
5793
- item.source.value instanceof File);
5794
- if (isEmpty(chosen)) {
5885
+ const chosen = Array.isArray(context.chosen) ? context.chosen : [];
5886
+ const rejected = [];
5887
+ const uploadable = [];
5888
+ for (const item of chosen) {
5889
+ const file = resolveChooserItemFile(item);
5890
+ if (!file) {
5891
+ continue;
5892
+ }
5893
+ const comparableSize = Math.max(item.size ?? 0, file.size);
5894
+ if (maxFileSize > 0 && comparableSize > maxFileSize) {
5895
+ rejected.push({ file, reason: 'size' });
5896
+ continue;
5897
+ }
5898
+ uploadable.push({ item, file });
5899
+ }
5900
+ if (rejected.length > 0) {
5901
+ await notifyFileAcceptRejections(rejected, {
5902
+ translateService,
5903
+ toastService,
5904
+ maxFileSize,
5905
+ });
5906
+ }
5907
+ const queue = multiple ? uploadable : uploadable.slice(0, 1);
5908
+ if (queue.length === 0) {
5795
5909
  return undefined;
5796
5910
  }
5797
- const fileStorage = inject(AXPFileStorageService);
5798
5911
  const uploaded = [];
5799
- for (const item of chosen) {
5800
- const file = item.source.value;
5912
+ for (const { item, file } of queue) {
5801
5913
  const info = await fileStorage.save({
5802
5914
  file,
5803
5915
  name: item.name,
@@ -5820,7 +5932,7 @@ const AXP_SYSTEM_FILE_UPLOADER_PROVIDER = {
5820
5932
  if (!multiple) {
5821
5933
  return uploaded.slice(0, 1);
5822
5934
  }
5823
- return [...context.items, ...uploaded];
5935
+ return [...(context.items ?? []), ...uploaded];
5824
5936
  },
5825
5937
  };
5826
5938
  //#endregion
@@ -5898,6 +6010,8 @@ class AXPFileUploaderDirective {
5898
6010
  constructor() {
5899
6011
  //#region ---- Services & Dependencies ----
5900
6012
  this.uploaderService = inject(AXPFileUploaderService);
6013
+ this.toastService = inject(AXToastService);
6014
+ this.translateService = inject(AXTranslationService);
5901
6015
  this.elementRef = inject(ElementRef);
5902
6016
  this.envInjector = inject(EnvironmentInjector);
5903
6017
  this.appRef = inject(ApplicationRef);
@@ -5962,6 +6076,12 @@ class AXPFileUploaderDirective {
5962
6076
  this.uploaded.set(result);
5963
6077
  }
5964
6078
  }
6079
+ catch (error) {
6080
+ console.error('[AXPFileUploaderDirective] upload failed', error);
6081
+ const title = await this.translateService.translateAsync('@general:messages.generic.error.title');
6082
+ const content = await this.translateService.translateAsync('@general:widgets.file-uploader.messages.upload-failed');
6083
+ this.toastService.show({ color: 'danger', title, content });
6084
+ }
5965
6085
  finally {
5966
6086
  this.busy.set(false);
5967
6087
  }
@@ -7887,7 +8007,7 @@ class AXPQueryFiltersComponent {
7887
8007
  */
7888
8008
  #focusEffect;
7889
8009
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPQueryFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7890
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPQueryFiltersComponent, isStandalone: true, selector: "axp-query-filters", inputs: { filtersDefinitions: { classPropertyName: "filtersDefinitions", publicName: "filtersDefinitions", isSignal: true, isRequired: false, transformFunction: null }, initialFilters: { classPropertyName: "initialFilters", publicName: "initialFilters", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, quickSearch: { classPropertyName: "quickSearch", publicName: "quickSearch", isSignal: true, isRequired: false, transformFunction: null }, sortPresets: { classPropertyName: "sortPresets", publicName: "sortPresets", isSignal: true, isRequired: false, transformFunction: null }, activeSortPresetName: { classPropertyName: "activeSortPresetName", publicName: "activeSortPresetName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFiltersChanged: "onFiltersChanged", onSortPresetSelected: "onSortPresetSelected" }, viewQueries: [{ propertyName: "tagBox", first: true, predicate: ["tagBox"], descendants: true, isSignal: true }, { propertyName: "mobileFilterTrigger", first: true, predicate: ["mobileFilterTrigger"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "widgetsContainer", first: true, predicate: AXPWidgetContainerComponent, descendants: true, isSignal: true }, { propertyName: "widgetRenderers", predicate: AXPWidgetRendererDirective, descendants: true, isSignal: true }, { propertyName: "popover", first: true, predicate: ["popover"], descendants: true, isSignal: true }, { propertyName: "listItems", predicate: ["caseItem"], descendants: true }], ngImport: i0, template: "<div\n class=\"flex w-full min-w-0 items-center gap-2 px-1.5 py-1\"\n [class.axp-query-filters__bar--toggle-collapsed]=\"deviceService.isSmall() && mobileModeToggleCollapsed() && !mobileSearchOpen()\"\n (keydown.control.space)=\"openFilterPopover()\"\n>\n @if (deviceService.isSmall()) {\n <!-- ----- Inline search replaces the chip row ----- -->\n @if (mobileSearchOpen()) {\n <div id=\"axp-query-filters-mobile-search\" class=\"axp-query-filters__mobile-search\">\n <ax-search-box\n class=\"ax-sm\"\n [value]=\"mobileSearchText()\"\n [delayTime]=\"300\"\n [placeholder]=\"('@general:terms.interface.filter.search-placeholder' | translate | async) ?? ''\"\n (onValueChanged)=\"handleMobileSearchChanged($event)\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </div>\n }\n <!-- ----- Compact pill row instead of the desktop tag-box toolbar ----- -->\n @else {\n <div\n #mobileFilterTrigger\n class=\"axp-query-filters__mobile-row\"\n [class.axp-query-filters__chips--panning]=\"isChipsPanning()\"\n (wheel)=\"handleChipsWheel($event)\"\n (pointerdown)=\"handleChipsPointerDown($event)\"\n (scroll)=\"handleMobileChipsScroll($event)\"\n >\n @for (chip of mobileFilterChips(); track chip.id) {\n <!--->\n <!-- ----- Applied filter chip keeps the field title, with a primary border ----- -->\n @if (chip.kind === 'applied') {\n <div\n class=\"axp-query-filters__mobile-chip axp-query-filters__mobile-chip--applied\"\n [class.axp-query-filters__mobile-chip--search]=\"chip.tag.field === 'all'\"\n (click)=\"handleTagClick(chip.tag, $event)\"\n >\n <span class=\"axp-query-filters__mobile-chip-text\">{{ mobileChipLabel(chip.tag) }}</span>\n <!--->\n <!-- ----- Remove this applied filter ----- -->\n @if (!chip.tag.readOnly) {\n <button class=\"axp-query-filters__chip-remove\" (click)=\"handleRemoveTag($event, chip.tagIndex)\" type=\"button\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n }\n </div>\n }\n <!-- ----- Unused filter field as an outline chip ----- -->\n @else if (chip.kind === 'available') {\n <div\n class=\"axp-query-filters__mobile-chip axp-query-filters__mobile-chip--available\"\n [class.axp-query-filters__mobile-chip--disabled]=\"isFilterDisabled(chip.definition)\"\n [attr.aria-disabled]=\"isFilterDisabled(chip.definition) ? 'true' : null\"\n (click)=\"openMobileAvailableFilter(chip.definition, $event)\"\n >\n <span class=\"axp-query-filters__mobile-chip-text\">{{ chip.definition.title | translate | async }}</span>\n <ax-icon class=\"fa-light fa-angle-down axp-query-filters__mobile-chip-caret\"></ax-icon>\n </div>\n }\n }\n @for (preset of sortPresets(); track preset.name) {\n <!--------------------------------------------------------------->\n <!-- ----- Sort preset pill in the same row as advance filters ----- -->\n <div\n class=\"axp-query-filters__mobile-chip\"\n [class.axp-query-filters__mobile-chip--applied]=\"isMobileSortPresetActive(preset)\"\n [class.axp-query-filters__mobile-chip--available]=\"!isMobileSortPresetActive(preset)\"\n [attr.aria-pressed]=\"isMobileSortPresetActive(preset)\"\n (click)=\"applyMobileSortPreset(preset, $event)\"\n >\n <span class=\"axp-query-filters__mobile-chip-text\">{{ preset.title | translate | async }}</span>\n <!--------------------------------------------------------------->\n <!-- ----- Custom icon when the recipe does not use a direction arrow ----- -->\n @if (preset.icon) {\n <ax-icon [class]=\"preset.icon + ' axp-query-filters__mobile-chip-caret'\"></ax-icon>\n }\n <!--------------------------------------------------------------->\n <!-- ----- Descending hint when the first sort is descending ----- -->\n @else if (mobileSortPresetDir(preset) === 'desc') {\n <ax-icon class=\"fa-solid fa-arrow-down-long axp-query-filters__mobile-chip-caret\"></ax-icon>\n }\n <!--------------------------------------------------------------->\n <!-- ----- Ascending hint when the first sort is ascending ----- -->\n @else if (mobileSortPresetDir(preset) === 'asc') {\n <ax-icon class=\"fa-solid fa-arrow-up-long axp-query-filters__mobile-chip-caret\"></ax-icon>\n }\n </div>\n }\n </div>\n }\n <div\n class=\"axp-query-filters__mode-toggle\"\n [class.axp-query-filters__mode-toggle--collapsed]=\"mobileModeToggleCollapsed() && !mobileSearchOpen()\"\n [attr.aria-hidden]=\"mobileModeToggleCollapsed() && !mobileSearchOpen()\"\n [attr.inert]=\"mobileModeToggleCollapsed() && !mobileSearchOpen() ? true : null\"\n role=\"tablist\"\n [attr.aria-label]=\"('@general:terms.interface.filter.title' | translate | async) ?? ''\"\n >\n <div class=\"axp-query-filters__mode-toggle-inner\">\n <button\n type=\"button\"\n role=\"tab\"\n class=\"axp-query-filters__mode-toggle-btn\"\n [class.axp-query-filters__mode-toggle-btn--active]=\"!mobileSearchOpen()\"\n [disabled]=\"isMobileFilterModeLocked()\"\n [attr.aria-selected]=\"!mobileSearchOpen()\"\n [attr.aria-label]=\"('@general:terms.interface.filter.title' | translate | async) ?? ''\"\n (click)=\"setMobileSearchOpen(false)\"\n >\n <ax-icon class=\"fa-light fa-filter\"></ax-icon>\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n class=\"axp-query-filters__mode-toggle-btn\"\n [class.axp-query-filters__mode-toggle-btn--active]=\"mobileSearchOpen()\"\n [disabled]=\"isMobileSearchModeLocked()\"\n [attr.aria-selected]=\"mobileSearchOpen()\"\n [attr.aria-label]=\"('@general:actions.search.title' | translate | async) ?? ''\"\n (click)=\"setMobileSearchOpen(true)\"\n >\n <ax-icon class=\"fa-light fa-magnifying-glass\"></ax-icon>\n </button>\n </div>\n </div>\n } @else {\n <!-- ----- Root AND/OR when more than one visible chip, including All ----- -->\n @if (isAdvanced() && hasMultipleFilterGroups()) {\n <ax-button-group\n class=\"axp-query-filters__logic-toggle ax-sm shrink-0\"\n [selection]=\"'single'\"\n [look]=\"'outline'\"\n [color]=\"'primary'\"\n >\n <ax-button-group-item [text]=\"('@general:terms.interface.filter.chip-logic-and' | translate | async) ?? ''\" [selected]=\"rootLogic() === 'and'\" (onClick)=\"setRootLogic('and')\"></ax-button-group-item>\n <ax-button-group-item [text]=\"('@general:terms.interface.filter.chip-logic-or' | translate | async) ?? ''\" [selected]=\"rootLogic() === 'or'\" (onClick)=\"setRootLogic('or')\"></ax-button-group-item>\n </ax-button-group>\n }\n <!-- ----- Filter picker when root AND/OR is hidden ----- -->\n @else {\n <ax-button (keydown)=\"handleButtonKeyDown($event)\" (onClick)=\"isAdvanced() ? openNewFilterGroup() : openFilterPopover()\" #filterButton [look]=\"'blank'\">\n <ax-icon class=\"far fa-bars-filter cursor-pointer\"></ax-icon>\n </ax-button>\n }\n }\n <div\n class=\"axp-query-filters__chips min-w-0\"\n [class.flex-1]=\"!deviceService.isSmall()\"\n [class.hidden]=\"deviceService.isSmall()\"\n [class.axp-query-filters__chips--panning]=\"isChipsPanning()\"\n (click)=\"handleTagBoxClick($event)\"\n (wheel)=\"handleChipsWheel($event)\"\n (pointerdown)=\"handleChipsPointerDown($event)\"\n >\n <ax-tag-box\n #tagBoxComponent\n [ngModel]=\"asyncTags()\"\n (onValueChanged)=\"handleSelectFilters($event)\"\n [textField]=\"'query'\"\n [valueField]=\"'id'\"\n [readonly]=\"filtersDefinitions().length === 0\"\n [look]=\"'none'\"\n [readonlyField]=\"'readOnly'\"\n [tagTemplate]=\"tagTemplate\"\n (onKeyDown)=\"handleKeyDown($event)\"\n [addOnEnter]=\"false\"\n [allowDuplicateValues]=\"true\"\n [placeholder]=\"(filtersDefinitions().length === 0 ? '@general:terms.interface.filter.no-filter-definitions' : '@general:terms.interface.filter.placeholder') | translate | async\"\n #tagBox\n >\n <ax-suffix class=\"hidden shrink-0 whitespace-nowrap md:flex text-gray-500\">\n <ax-kbd look=\"blank\">\n <ax-kbd-item [keys]=\"filterFocusShortcutKeys\"></ax-kbd-item>\n </ax-kbd>\n </ax-suffix>\n </ax-tag-box>\n </div>\n\n <ng-template #tagTemplate let-item let-index=\"index\">\n <div class=\"axp-query-filters__chip\" [class.axp-query-filters__chip--active]=\"item.id === activeChipId()\" [class.axp-query-filters__chip--search]=\"item.field === 'all'\" (click)=\"handleTagClick(item, $event)\">\n <!-- ----- Quick search chip keeps a single text label ----- -->\n @if (item.chipMode === 'search') {\n <span class=\"axp-query-filters__chip-text\">{{ item.query }}</span>\n } @else if (item.chipMode === 'summary') {\n <!-- ----- Summary chip when more than two conditions ----- -->\n @if (item.titleLabel) {\n <span class=\"axp-query-filters__chip-title\">{{ item.titleLabel }}:</span>\n }\n <span class=\"axp-query-filters__chip-text\">{{ item.summaryText }}</span>\n } @else {\n <!-- ----- One or two conditions: field + operator + quoted value ----- -->\n @if (item.titleLabel && !item.mixed) {\n <span class=\"axp-query-filters__chip-title\">{{ item.titleLabel }}</span>\n }\n @for (cond of item.chipConditions; track $index) {\n <!--->\n <!-- ----- Logic connector between conditions ----- -->\n @if ($index > 0) {\n <span class=\"axp-query-filters__chip-logic\">{{ item.logicLabel }}</span>\n }\n <!--->\n <!-- ----- Field title on mixed-field chips ----- -->\n @if (item.mixed && cond.title) {\n <span class=\"axp-query-filters__chip-title\">{{ cond.title }}</span>\n }\n <span class=\"axp-query-filters__chip-operator\">{{ cond.operator }}</span>\n <!--->\n <!-- ----- Quoted value badge when the operator has a display value ----- -->\n @if (cond.value) {\n <span class=\"axp-query-filters__chip-value\">'{{ cond.value }}'</span>\n }\n }\n }\n @if (!item.readOnly) {\n <button class=\"axp-query-filters__chip-remove\" (click)=\"handleRemoveTag($event, index)\" type=\"button\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n }\n </div>\n </ng-template>\n</div>\n\n<ax-popover [offsetY]=\"activeFilter() ? -30 : 0\" [openOn]=\"'toggle'\" (onOpened)=\"onPopoverOpened($event)\" [closeOn]=\"'clickOut'\" (onClosed)=\"handlePopoverClosed($event)\" [adaptivityEnabled]=\"true\" #popover>\n <div class=\"axp-query-filters__popover md:min-w-72 w-full rounded-md md:max-h-[min(32rem,80vh)] lg:w-[520px] md:overflow-auto\">\n <axp-widgets-container #widgetsContainer [context]=\"context()\" (onContextChanged)=\"onContextChanged($event)\">\n @if (activeFilter()) {\n <div class=\"flex flex-col lightest-surface shadow-md\" (keydown.enter)=\"onEnterKeyPressed($event)\">\n <ax-header class=\"axp-query-filters__editor-header border-b border-border-light px-4 py-2\">\n <div class=\"flex min-w-0 items-center gap-2 font-semibold\">\n <!--->\n <!-- ----- Field icon when the group is a single field ----- -->\n @if (!isMixedEditingGroup() && activeFilter()?.icon) {\n <ax-icon class=\"w-5 shrink-0\" [class]=\"'fa-light ' + activeFilter()!.icon\"></ax-icon>\n }\n <span class=\"min-w-0 truncate\">\n {{ isMixedEditingGroup() ? ('@general:terms.interface.filter.filter-group' | translate | async) : ('@general:terms.interface.filter.filter-on' | translate: { params: { title: activeFilterTitle() } } | async) }}\n </span>\n </div>\n <!--->\n <!-- ----- Condition logic AND/OR stays on desktop ----- -->\n @if (!deviceService.isSmall()) {\n <ax-button-group class=\"axp-query-filters__logic-toggle ax-sm shrink-0\" [selection]=\"'single'\" [look]=\"'outline'\" [color]=\"'primary'\">\n <ax-button-group-item [text]=\"('@general:terms.interface.filter.logic-and-all' | translate | async) ?? ''\" [selected]=\"editingLogic() === 'and'\" (onClick)=\"setEditingLogic('and')\"></ax-button-group-item>\n <ax-button-group-item [text]=\"('@general:terms.interface.filter.logic-or-any' | translate | async) ?? ''\" [selected]=\"editingLogic() === 'or'\" (onClick)=\"setEditingLogic('or')\"></ax-button-group-item>\n </ax-button-group>\n }\n </ax-header>\n <ax-content class=\"p-4\">\n @for (condition of editingConditions(); track condition.id; let i = $index) {\n <!--->\n <!-- ----- Numbered condition row with the field widget ----- -->\n @if (i > 0 && !deviceService.isSmall()) {\n <div class=\"axp-query-filters__logic-split\">\n <span class=\"axp-query-filters__logic-split-label\">{{ (editingLogic() === 'or' ? '@general:terms.interface.filter.chip-logic-or' : '@general:terms.interface.filter.chip-logic-and') | translate | async }}</span>\n </div>\n }\n <div class=\"axp-query-filters__condition\">\n <div class=\"axp-query-filters__condition-head\">\n <div class=\"axp-query-filters__condition-heading\">\n <!--->\n <!-- ----- Field picker for mixed-field groups in advanced mode ----- -->\n @if (isAdvanced()) {\n <ax-dropdown-button class=\"ax-sm\" [text]=\"(getConditionDefinition(condition.field)?.title | translate | async) ?? ''\" [mode]=\"'dropdown'\" [look]=\"'outline'\">\n <ax-button-item-list>\n @for (def of advancedFieldOptions(); track def.field) {\n <ax-button-item [text]=\"(def.title | translate | async) ?? ''\" [selected]=\"condition.field === def.field\" [disabled]=\"isFilterDisabled(def)\" (onClick)=\"setConditionField(condition.id, def.field ?? '')\"></ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-button>\n }\n <!--->\n <!-- ----- Active operator for this condition ----- -->\n @if (getConditionOperatorKey(condition.id); as operatorKey) {\n <ax-badge [text]=\"(operatorKey | translate | async) || ''\"></ax-badge>\n }\n </div>\n <button type=\"button\" class=\"axp-query-filters__condition-remove\" (click)=\"handleRemoveCondition(condition.id)\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n </div>\n <ng-container\n axp-widget-renderer\n [node]=\"{\n type: getConditionWidget(condition)?.type || 'text-editor',\n path: resolveEditingConditionContextField(condition.id),\n options: $safeNavigationMigration(getConditionWidget(condition)?.options),\n }\"\n [mode]=\"'edit'\"\n ></ng-container>\n </div>\n }\n <!--->\n <!-- ----- Extra conditions stay on desktop ----- -->\n @if (!deviceService.isSmall()) {\n <button type=\"button\" class=\"axp-query-filters__add-condition\" (click)=\"handleAddCondition()\">\n <ax-icon class=\"fa-light fa-plus\"></ax-icon>\n <span>{{ (isAdvanced() ? '@general:terms.interface.filter.add-condition-generic' : '@general:terms.interface.filter.add-condition') | translate: { params: { title: activeFilterTitle() } } | async }}</span>\n </button>\n }\n </ax-content>\n <ax-footer class=\"border-t flex justify-end gap-2 border-border-light w-full px-4 py-2\">\n <ax-button class=\"ax-sm\" [look]=\"'blank'\" [text]=\"'@general:actions.cancel.title' | translate | async\" (onClick)=\"handleCancelFilter()\"></ax-button>\n <ax-button class=\"ax-sm\" [color]=\"'primary'\" [disabled]=\"!canApplyFilter()\" [text]=\"'@general:terms.interface.filter.apply-filter' | translate | async\" (onClick)=\"handleApplyFilter()\"></ax-button>\n </ax-footer>\n </div>\n } @else {\n <!-- ----- Field picker when no filter is being edited ----- -->\n <div class=\"flex flex-col lightest-surface\">\n <div axListNavigation #list=\"axListNavigation\" class=\"axp-list-items border-none\">\n @for (field of filterFields(); track field.field) {\n <div\n axListNavigationItem\n #caseItem=\"axListNavigationItem\"\n [class.axp-state-focused]=\"caseItem.isActive() && !isFilterDisabled(field)\"\n [class.axp-query-filters__advance-item--disabled]=\"isFilterDisabled(field)\"\n [attr.aria-disabled]=\"isFilterDisabled(field) ? 'true' : null\"\n [attr.tabindex]=\"isFilterDisabled(field) ? -1 : 0\"\n (click)=\"handleSelectField(field)\"\n (keydown)=\"handleFieldKeyDown($event, field)\"\n >\n <div class=\"flex items-center gap-2\">\n <ax-icon class=\"axp-query-filters__field-icon\" [ngClass]=\"'fa-light ' + field.icon\"></ax-icon>\n <span class=\"leading-none\">{{ field.title | translate | async }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </axp-widgets-container>\n </div>\n</ax-popover>\n", styles: ["@layer properties;axp-query-filters{display:block;width:100%;min-width:0px;overflow:hidden}axp-query-filters>.flex{min-width:0px;flex-wrap:nowrap}axp-query-filters ax-tag-box{width:100%;min-width:0px}axp-query-filters ax-tag-box .editor-container,axp-query-filters ax-tag-box .ax-editor-container{display:flex;width:100%;min-width:0px;flex-wrap:nowrap;align-items:center;background-color:transparent;min-height:2.25rem}axp-query-filters ax-tag-box .ax-tags-container{display:flex;flex:1 1 0%;min-width:0;flex-wrap:nowrap!important;overflow-x:auto;overflow-y:hidden}axp-query-filters ax-tag-box ax-suffix{flex-shrink:0;white-space:nowrap}axp-query-filters>.flex>ax-button button{min-height:var(--ax-sys-size-base);height:var(--ax-sys-size-base);padding-block:0}.axp-query-filters__chips,axp-query-filters ax-tag-box .ax-tags-container{scrollbar-width:none;-ms-overflow-style:none}:is(.axp-query-filters__chips,axp-query-filters ax-tag-box .ax-tags-container)::-webkit-scrollbar{display:none;width:0;height:0;background:transparent}.axp-query-filters__chips{min-width:0px;cursor:grab;overflow-x:auto;overflow-y:hidden}.axp-query-filters__chips.axp-query-filters__chips--panning,.axp-query-filters__chips.axp-query-filters__chips--panning *{cursor:grabbing;-webkit-user-select:none;user-select:none}.axp-query-filters__chip{display:inline-flex;flex-shrink:0;cursor:pointer;align-items:center;gap:var(--spacing, .25rem);border-radius:var(--radius-md, .375rem);background-color:var(--color-surface);color:var(--color-on-surface);border-color:var(--color-border-surface);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * .5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));white-space:nowrap}.axp-query-filters__chip:hover{background-color:rgba(var(--ax-sys-color-darkest-surface))}.axp-query-filters__chip--search,.axp-query-filters__chip--active{background-color:rgba(var(--ax-sys-color-primary-surface));color:var(--color-white, #fff)}:is(.axp-query-filters__chip--search,.axp-query-filters__chip--active):hover{background-color:rgba(var(--ax-sys-color-primary-surface))}.axp-query-filters__chip-title{flex-shrink:0;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.axp-query-filters__chip-text,.axp-query-filters__chip-operator{min-width:0px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axp-query-filters__chip-logic{flex-shrink:0;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}.axp-query-filters__chip--active .axp-query-filters__chip-logic,.axp-query-filters__chip--search .axp-query-filters__chip-logic{color:var(--color-white, #fff)}.axp-query-filters__chip-value{display:inline-flex;max-width:12rem;flex-shrink:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:.25rem;background-color:rgba(var(--ax-sys-color-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: calc(var(--spacing, .25rem) * 5);line-height:calc(var(--spacing, .25rem) * 5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.axp-query-filters__chip--active .axp-query-filters__chip-value,.axp-query-filters__chip--search .axp-query-filters__chip-value{background-color:color-mix(in srgb,#fff 20%,transparent);color:var(--color-white, #fff)}@supports (color: color-mix(in lab,red,red)){.axp-query-filters__chip--active .axp-query-filters__chip-value,.axp-query-filters__chip--search .axp-query-filters__chip-value{background-color:color-mix(in oklab,var(--color-white, #fff) 20%,transparent)}}.axp-query-filters__chip-remove{display:inline-flex;flex-shrink:0;cursor:pointer;align-items:center;justify-content:center;opacity:70%}.axp-query-filters__chip-remove:hover{opacity:100%}.axp-query-filters__mode-toggle{flex:0 0 auto;max-width:6rem;overflow:visible;transition:max-width .32s cubic-bezier(.32,.72,0,1)}.axp-query-filters__mode-toggle--collapsed{max-width:0;pointer-events:none}.axp-query-filters__mode-toggle-inner{position:relative;z-index:10;margin-inline-start:var(--spacing, .25rem);display:inline-flex;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;background-color:var(--color-lightest);color:var(--color-on-lightest);border-color:var(--color-border-lightest);border-color:rgba(var(--ax-sys-color-light-surface));--tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);width:max-content;transform:translate(0);transition:transform .32s cubic-bezier(.32,.72,0,1),margin .32s cubic-bezier(.32,.72,0,1)}.axp-query-filters__mode-toggle--collapsed .axp-query-filters__mode-toggle-inner{margin-inline-start:0;transform:translate(5rem)}[dir=rtl] .axp-query-filters__mode-toggle--collapsed .axp-query-filters__mode-toggle-inner{transform:translate(-5rem)}.axp-query-filters__mode-toggle-btn{display:inline-flex;align-items:center;justify-content:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));width:1.875rem;height:1.625rem}.axp-query-filters__mode-toggle-btn:first-child{border-start-start-radius:calc(infinity * 1px);border-end-start-radius:calc(infinity * 1px)}.axp-query-filters__mode-toggle-btn:last-child{border-start-end-radius:calc(infinity * 1px);border-end-end-radius:calc(infinity * 1px)}.axp-query-filters__mode-toggle-btn--active{background-color:rgba(var(--ax-sys-color-primary-surface));color:var(--color-white, #fff)}.axp-query-filters__mode-toggle-btn:disabled:not(.axp-query-filters__mode-toggle-btn--active){cursor:not-allowed;opacity:40%}.axp-query-filters__mobile-search{min-width:0px;flex:1}.axp-query-filters__mobile-search ax-search-box,.axp-query-filters__mobile-search ax-search-box .ax-editor,.axp-query-filters__mobile-search ax-search-box .ax-editor-container,.axp-query-filters__mobile-search ax-search-box .editor-container{min-height:1.875rem;height:1.875rem}.axp-query-filters__mobile-search ax-search-box input{min-height:1.875rem;height:1.875rem;font-size:.8125rem;line-height:1.125rem}.axp-query-filters__mobile-row{display:flex;min-width:0px;flex:1;flex-wrap:nowrap;align-items:center;gap:var(--spacing, .25rem);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.axp-query-filters__mobile-row::-webkit-scrollbar{display:none;width:0;height:0;background:transparent}.axp-query-filters__mobile-chip{display:inline-flex;flex-shrink:0;cursor:pointer;align-items:center;gap:var(--spacing, .25rem);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;background-color:var(--color-surface);color:var(--color-on-surface);border-color:var(--color-border-surface);border-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * .5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);white-space:nowrap}.axp-query-filters__mobile-chip--available{cursor:pointer;background-color:transparent}.axp-query-filters__mobile-chip--disabled{cursor:not-allowed;opacity:50%}.axp-query-filters__mobile-chip--applied{border-color:rgba(var(--ax-sys-color-primary-surface));background-color:transparent;color:rgba(var(--ax-sys-color-primary-surface))}.axp-query-filters__mobile-chip-text{max-width:10rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axp-query-filters__mobile-chip-caret{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}.axp-query-filters__editor-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3)}.axp-query-filters__logic-toggle ax-button-group-item.ax-state-selected ax-button button,.axp-query-filters__logic-toggle ax-button button.ax-state-selected{background-image:none;box-shadow:none;background-color:rgba(var(--ax-sys-color-primary-surface));color:var(--color-white, #fff)}.axp-query-filters__logic-toggle ax-button>button{min-height:2rem;height:2rem;padding-inline:.5rem;padding-block:0;font-size:.8125rem;line-height:1.125rem;font-weight:600}@media(max-width:600px){axp-query-filters{overflow:hidden}axp-query-filters>.flex{gap:.5rem;padding-block:0;padding-inline:.125rem;overflow:hidden}axp-query-filters>.flex.axp-query-filters__bar--toggle-collapsed{gap:0}.axp-query-filters__logic-toggle{flex-wrap:nowrap}.axp-query-filters__chip{gap:.375rem;padding-inline:.625rem;padding-block:.25rem;font-size:.8125rem}.axp-query-filters__chip-value{max-width:none;font-size:.8125rem}}.axp-query-filters__condition{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axp-query-filters__condition-head{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.axp-query-filters__condition-heading{display:flex;min-width:0px;flex-wrap:wrap;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.axp-query-filters__condition-title{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-text-default));text-transform:uppercase}@supports (color: color-mix(in lab,red,red)){.axp-query-filters__condition-title{color:color-mix(in oklab,rgba(var(--ax-sys-color-text-default)) 80%,transparent)}}.axp-query-filters__condition-remove{display:inline-flex;cursor:pointer;align-items:center;justify-content:center;color:rgba(var(--ax-sys-color-text-default))}@supports (color: color-mix(in lab,red,red)){.axp-query-filters__condition-remove{color:color-mix(in oklab,rgba(var(--ax-sys-color-text-default)) 80%,transparent)}}.axp-query-filters__condition-remove:hover{color:rgba(var(--ax-sys-color-danger-surface))}.axp-query-filters__logic-split{position:relative;margin-block:calc(var(--spacing, .25rem) * 3);display:flex;align-items:center;justify-content:center}.axp-query-filters__logic-split:before,.axp-query-filters__logic-split:after{content:\"\";height:1px;flex:1;background-color:rgba(var(--ax-sys-color-border-light-surface))}.axp-query-filters__logic-split-label{margin-inline:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * .5);font-size:10px;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}.axp-query-filters__add-condition{margin-top:calc(var(--spacing, .25rem) * 3);display:inline-flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-primary-surface))}.axp-query-filters__add-condition:hover{text-decoration-line:underline}.axp-list-items{display:flex;min-width:calc(var(--spacing, .25rem) * 40);flex-direction:column;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;background-color:var(--color-lightest);color:var(--color-on-lightest);border-color:var(--color-border-lightest);padding-block:calc(var(--spacing, .25rem) * 4);--tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.axp-list-items>div{min-width:calc(var(--spacing, .25rem) * 28);cursor:pointer;padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 2);text-align:start}.axp-list-items>div:focus{outline:none}.axp-list-items>div.axp-state-focused,.axp-list-items>div:hover{background-color:var(--color-surface);color:var(--color-on-surface);border-color:var(--color-border-surface)}.axp-list-items>div.axp-query-filters__advance-item--disabled{cursor:not-allowed;opacity:50%}.axp-list-items>div.axp-query-filters__advance-item--disabled.axp-state-focused,.axp-list-items>div.axp-query-filters__advance-item--disabled:hover{background-color:transparent}.axp-query-filters__field-icon{display:inline-flex;height:calc(var(--spacing, .25rem) * 4);width:calc(var(--spacing, .25rem) * 5);flex-shrink:0;align-items:center;justify-content:center;--tw-leading: 1;line-height:1}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-tracking: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i1$2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "component", type: i4$2.AXButtonGroupComponent, selector: "ax-button-group", inputs: ["disabled", "fitParent", "color", "look", "class", "selection"], outputs: ["onBlur", "onFocus", "disabledChange", "colorChange", "lookChange", "onClick", "selectionChange", "selectedButtonChange"] }, { kind: "component", type: i4$2.AXButtonGroupItemComponent, selector: "ax-button-group-item", inputs: ["disabled", "color", "text", "class", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange", "classChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: i6.AXDropdownButtonComponent, selector: "ax-dropdown-button", inputs: ["disabled", "size", "text", "selected", "color", "look", "type", "mode", "iconOnly"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "lookChange", "colorChange", "disabledChange"] }, { kind: "component", type: AXKBDComponent, selector: "ax-kbd", inputs: ["look"] }, { kind: "component", type: AXKBDItemComponent, selector: "ax-kbd-item", inputs: ["keys", "join", "look"], outputs: ["lookChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2$2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i3$2.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSelectionListModule }, { kind: "ngmodule", type: AXTagBoxModule }, { kind: "component", type: i9.AXTagBoxComponent, selector: "ax-tag-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "allowNull", "type", "look", "addOnComma", "addOnEnter", "valueField", "textField", "readonlyField", "allowDuplicateValues", "tagTemplate"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onTagClick", "onTagDblClick", "onTagContextMenu"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$5.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1$5.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXListNavigationModule }, { kind: "directive", type: i11.AXListNavigationDirective, selector: "[axListNavigation]", inputs: ["orientation"], outputs: ["onNavigationChanged", "onKeypress"], exportAs: ["axListNavigation"] }, { kind: "directive", type: i11.AXListNavigationItemDirective, selector: "[axListNavigationItem]", outputs: ["onKeypress"], exportAs: ["axListNavigationItem"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i1$3.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
8010
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPQueryFiltersComponent, isStandalone: true, selector: "axp-query-filters", inputs: { filtersDefinitions: { classPropertyName: "filtersDefinitions", publicName: "filtersDefinitions", isSignal: true, isRequired: false, transformFunction: null }, initialFilters: { classPropertyName: "initialFilters", publicName: "initialFilters", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, quickSearch: { classPropertyName: "quickSearch", publicName: "quickSearch", isSignal: true, isRequired: false, transformFunction: null }, sortPresets: { classPropertyName: "sortPresets", publicName: "sortPresets", isSignal: true, isRequired: false, transformFunction: null }, activeSortPresetName: { classPropertyName: "activeSortPresetName", publicName: "activeSortPresetName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFiltersChanged: "onFiltersChanged", onSortPresetSelected: "onSortPresetSelected" }, viewQueries: [{ propertyName: "tagBox", first: true, predicate: ["tagBox"], descendants: true, isSignal: true }, { propertyName: "mobileFilterTrigger", first: true, predicate: ["mobileFilterTrigger"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "widgetsContainer", first: true, predicate: AXPWidgetContainerComponent, descendants: true, isSignal: true }, { propertyName: "widgetRenderers", predicate: AXPWidgetRendererDirective, descendants: true, isSignal: true }, { propertyName: "popover", first: true, predicate: ["popover"], descendants: true, isSignal: true }, { propertyName: "listItems", predicate: ["caseItem"], descendants: true }], ngImport: i0, template: "<div\n class=\"flex w-full min-w-0 items-center gap-2 px-1.5 py-1\"\n [class.axp-query-filters__bar--toggle-collapsed]=\"deviceService.isSmall() && mobileModeToggleCollapsed() && !mobileSearchOpen()\"\n (keydown.control.space)=\"openFilterPopover()\"\n>\n @if (deviceService.isSmall()) {\n <!-- ----- Inline search replaces the chip row ----- -->\n @if (mobileSearchOpen()) {\n <div id=\"axp-query-filters-mobile-search\" class=\"axp-query-filters__mobile-search\">\n <ax-search-box\n class=\"ax-sm\"\n [value]=\"mobileSearchText()\"\n [delayTime]=\"300\"\n [placeholder]=\"('@general:terms.interface.filter.search-placeholder' | translate | async) ?? ''\"\n (onValueChanged)=\"handleMobileSearchChanged($event)\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </div>\n }\n <!-- ----- Compact pill row instead of the desktop tag-box toolbar ----- -->\n @else {\n <div\n #mobileFilterTrigger\n class=\"axp-query-filters__mobile-row\"\n [class.axp-query-filters__chips--panning]=\"isChipsPanning()\"\n (wheel)=\"handleChipsWheel($event)\"\n (pointerdown)=\"handleChipsPointerDown($event)\"\n (scroll)=\"handleMobileChipsScroll($event)\"\n >\n @for (chip of mobileFilterChips(); track chip.id) {\n <!--->\n <!-- ----- Applied filter chip keeps the field title, with a primary border ----- -->\n @if (chip.kind === 'applied') {\n <div\n class=\"axp-query-filters__mobile-chip axp-query-filters__mobile-chip--applied\"\n [class.axp-query-filters__mobile-chip--search]=\"chip.tag.field === 'all'\"\n (click)=\"handleTagClick(chip.tag, $event)\"\n >\n <span class=\"axp-query-filters__mobile-chip-text\">{{ mobileChipLabel(chip.tag) }}</span>\n <!--->\n <!-- ----- Remove this applied filter ----- -->\n @if (!chip.tag.readOnly) {\n <button class=\"axp-query-filters__chip-remove\" (click)=\"handleRemoveTag($event, chip.tagIndex)\" type=\"button\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n }\n </div>\n }\n <!-- ----- Unused filter field as an outline chip ----- -->\n @else if (chip.kind === 'available') {\n <div\n class=\"axp-query-filters__mobile-chip axp-query-filters__mobile-chip--available\"\n [class.axp-query-filters__mobile-chip--disabled]=\"isFilterDisabled(chip.definition)\"\n [attr.aria-disabled]=\"isFilterDisabled(chip.definition) ? 'true' : null\"\n (click)=\"openMobileAvailableFilter(chip.definition, $event)\"\n >\n <span class=\"axp-query-filters__mobile-chip-text\">{{ chip.definition.title | translate | async }}</span>\n <ax-icon class=\"fa-light fa-angle-down axp-query-filters__mobile-chip-caret\"></ax-icon>\n </div>\n }\n }\n @for (preset of sortPresets(); track preset.name) {\n <!--------------------------------------------------------------->\n <!-- ----- Sort preset pill in the same row as advance filters ----- -->\n <div\n class=\"axp-query-filters__mobile-chip\"\n [class.axp-query-filters__mobile-chip--applied]=\"isMobileSortPresetActive(preset)\"\n [class.axp-query-filters__mobile-chip--available]=\"!isMobileSortPresetActive(preset)\"\n [attr.aria-pressed]=\"isMobileSortPresetActive(preset)\"\n (click)=\"applyMobileSortPreset(preset, $event)\"\n >\n <span class=\"axp-query-filters__mobile-chip-text\">{{ preset.title | translate | async }}</span>\n <!--------------------------------------------------------------->\n <!-- ----- Custom icon when the recipe does not use a direction arrow ----- -->\n @if (preset.icon) {\n <ax-icon [class]=\"preset.icon + ' axp-query-filters__mobile-chip-caret'\"></ax-icon>\n }\n <!--------------------------------------------------------------->\n <!-- ----- Descending hint when the first sort is descending ----- -->\n @else if (mobileSortPresetDir(preset) === 'desc') {\n <ax-icon class=\"fa-solid fa-arrow-down-long axp-query-filters__mobile-chip-caret\"></ax-icon>\n }\n <!--------------------------------------------------------------->\n <!-- ----- Ascending hint when the first sort is ascending ----- -->\n @else if (mobileSortPresetDir(preset) === 'asc') {\n <ax-icon class=\"fa-solid fa-arrow-up-long axp-query-filters__mobile-chip-caret\"></ax-icon>\n }\n </div>\n }\n </div>\n }\n <div\n class=\"axp-query-filters__mode-toggle\"\n [class.axp-query-filters__mode-toggle--collapsed]=\"mobileModeToggleCollapsed() && !mobileSearchOpen()\"\n [attr.aria-hidden]=\"mobileModeToggleCollapsed() && !mobileSearchOpen()\"\n [attr.inert]=\"mobileModeToggleCollapsed() && !mobileSearchOpen() ? true : null\"\n role=\"tablist\"\n [attr.aria-label]=\"('@general:terms.interface.filter.title' | translate | async) ?? ''\"\n >\n <div class=\"axp-query-filters__mode-toggle-inner\">\n <button\n type=\"button\"\n role=\"tab\"\n class=\"axp-query-filters__mode-toggle-btn\"\n [class.axp-query-filters__mode-toggle-btn--active]=\"!mobileSearchOpen()\"\n [disabled]=\"isMobileFilterModeLocked()\"\n [attr.aria-selected]=\"!mobileSearchOpen()\"\n [attr.aria-label]=\"('@general:terms.interface.filter.title' | translate | async) ?? ''\"\n (click)=\"setMobileSearchOpen(false)\"\n >\n <ax-icon class=\"fa-light fa-filter\"></ax-icon>\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n class=\"axp-query-filters__mode-toggle-btn\"\n [class.axp-query-filters__mode-toggle-btn--active]=\"mobileSearchOpen()\"\n [disabled]=\"isMobileSearchModeLocked()\"\n [attr.aria-selected]=\"mobileSearchOpen()\"\n [attr.aria-label]=\"('@general:actions.search.title' | translate | async) ?? ''\"\n (click)=\"setMobileSearchOpen(true)\"\n >\n <ax-icon class=\"fa-light fa-magnifying-glass\"></ax-icon>\n </button>\n </div>\n </div>\n } @else {\n <!-- ----- Root AND/OR when more than one visible chip, including All ----- -->\n @if (isAdvanced() && hasMultipleFilterGroups()) {\n <ax-button-group\n class=\"axp-query-filters__logic-toggle ax-sm shrink-0\"\n [selection]=\"'single'\"\n [look]=\"'outline'\"\n [color]=\"'primary'\"\n >\n <ax-button-group-item [text]=\"('@general:terms.interface.filter.chip-logic-and' | translate | async) ?? ''\" [selected]=\"rootLogic() === 'and'\" (onClick)=\"setRootLogic('and')\"></ax-button-group-item>\n <ax-button-group-item [text]=\"('@general:terms.interface.filter.chip-logic-or' | translate | async) ?? ''\" [selected]=\"rootLogic() === 'or'\" (onClick)=\"setRootLogic('or')\"></ax-button-group-item>\n </ax-button-group>\n }\n <!-- ----- Filter picker when root AND/OR is hidden ----- -->\n @else {\n <ax-button (keydown)=\"handleButtonKeyDown($event)\" (onClick)=\"isAdvanced() ? openNewFilterGroup() : openFilterPopover()\" #filterButton [look]=\"'blank'\">\n <ax-icon class=\"far fa-bars-filter cursor-pointer\"></ax-icon>\n </ax-button>\n }\n }\n <div\n class=\"axp-query-filters__chips min-w-0\"\n [class.flex-1]=\"!deviceService.isSmall()\"\n [class.hidden]=\"deviceService.isSmall()\"\n [class.axp-query-filters__chips--panning]=\"isChipsPanning()\"\n (click)=\"handleTagBoxClick($event)\"\n (wheel)=\"handleChipsWheel($event)\"\n (pointerdown)=\"handleChipsPointerDown($event)\"\n >\n <ax-tag-box\n #tagBoxComponent\n [ngModel]=\"asyncTags()\"\n (onValueChanged)=\"handleSelectFilters($event)\"\n [textField]=\"'query'\"\n [valueField]=\"'id'\"\n [readonly]=\"filtersDefinitions().length === 0\"\n [look]=\"'none'\"\n [readonlyField]=\"'readOnly'\"\n [tagTemplate]=\"tagTemplate\"\n (onKeyDown)=\"handleKeyDown($event)\"\n [addOnEnter]=\"false\"\n [allowDuplicateValues]=\"true\"\n [placeholder]=\"(filtersDefinitions().length === 0 ? '@general:terms.interface.filter.no-filter-definitions' : '@general:terms.interface.filter.placeholder') | translate | async\"\n #tagBox\n >\n <ax-suffix class=\"hidden shrink-0 whitespace-nowrap md:flex text-gray-500\">\n <ax-kbd look=\"blank\">\n <ax-kbd-item [keys]=\"filterFocusShortcutKeys\"></ax-kbd-item>\n </ax-kbd>\n </ax-suffix>\n </ax-tag-box>\n </div>\n\n <ng-template #tagTemplate let-item let-index=\"index\">\n <div class=\"axp-query-filters__chip\" [class.axp-query-filters__chip--active]=\"item.id === activeChipId()\" [class.axp-query-filters__chip--search]=\"item.field === 'all'\" (click)=\"handleTagClick(item, $event)\">\n <!-- ----- Quick search chip keeps a single text label ----- -->\n @if (item.chipMode === 'search') {\n <span class=\"axp-query-filters__chip-text\">{{ item.query }}</span>\n } @else if (item.chipMode === 'summary') {\n <!-- ----- Summary chip when more than two conditions ----- -->\n @if (item.titleLabel) {\n <span class=\"axp-query-filters__chip-title\">{{ item.titleLabel }}:</span>\n }\n <span class=\"axp-query-filters__chip-text\">{{ item.summaryText }}</span>\n } @else {\n <!-- ----- One or two conditions: field + operator + quoted value ----- -->\n @if (item.titleLabel && !item.mixed) {\n <span class=\"axp-query-filters__chip-title\">{{ item.titleLabel }}</span>\n }\n @for (cond of item.chipConditions; track $index) {\n <!--->\n <!-- ----- Logic connector between conditions ----- -->\n @if ($index > 0) {\n <span class=\"axp-query-filters__chip-logic\">{{ item.logicLabel }}</span>\n }\n <!--->\n <!-- ----- Field title on mixed-field chips ----- -->\n @if (item.mixed && cond.title) {\n <span class=\"axp-query-filters__chip-title\">{{ cond.title }}</span>\n }\n <span class=\"axp-query-filters__chip-operator\">{{ cond.operator }}</span>\n <!--->\n <!-- ----- Quoted value badge when the operator has a display value ----- -->\n @if (cond.value) {\n <span class=\"axp-query-filters__chip-value\">'{{ cond.value }}'</span>\n }\n }\n }\n @if (!item.readOnly) {\n <button class=\"axp-query-filters__chip-remove\" (click)=\"handleRemoveTag($event, index)\" type=\"button\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n }\n </div>\n </ng-template>\n</div>\n\n<ax-popover [offsetY]=\"activeFilter() ? -30 : 0\" [openOn]=\"'toggle'\" (onOpened)=\"onPopoverOpened($event)\" [closeOn]=\"'clickOut'\" (onClosed)=\"handlePopoverClosed($event)\" [adaptivityEnabled]=\"true\" #popover>\n <div class=\"axp-query-filters__popover md:min-w-72 w-full rounded-md md:max-h-[min(32rem,80vh)] lg:w-[520px] md:overflow-auto\">\n <axp-widgets-container #widgetsContainer [context]=\"context()\" (onContextChanged)=\"onContextChanged($event)\">\n @if (activeFilter()) {\n <div class=\"flex flex-col lightest-surface shadow-md\" (keydown.enter)=\"onEnterKeyPressed($event)\">\n <ax-header class=\"axp-query-filters__editor-header border-b border-border-light px-4 py-2\">\n <div class=\"flex min-w-0 items-center gap-2 font-semibold\">\n <!--->\n <!-- ----- Field icon when the group is a single field ----- -->\n @if (!isMixedEditingGroup() && activeFilter()?.icon) {\n <ax-icon class=\"w-5 shrink-0\" [class]=\"'fa-light ' + activeFilter()!.icon\"></ax-icon>\n }\n <span class=\"min-w-0 truncate\">\n {{ isMixedEditingGroup() ? ('@general:terms.interface.filter.filter-group' | translate | async) : ('@general:terms.interface.filter.filter-on' | translate: { params: { title: activeFilterTitle() } } | async) }}\n </span>\n </div>\n <!--->\n <!-- ----- Condition logic AND/OR stays on desktop ----- -->\n @if (!deviceService.isSmall()) {\n <ax-button-group class=\"axp-query-filters__logic-toggle ax-sm shrink-0\" [selection]=\"'single'\" [look]=\"'outline'\" [color]=\"'primary'\">\n <ax-button-group-item [text]=\"('@general:terms.interface.filter.logic-and-all' | translate | async) ?? ''\" [selected]=\"editingLogic() === 'and'\" (onClick)=\"setEditingLogic('and')\"></ax-button-group-item>\n <ax-button-group-item [text]=\"('@general:terms.interface.filter.logic-or-any' | translate | async) ?? ''\" [selected]=\"editingLogic() === 'or'\" (onClick)=\"setEditingLogic('or')\"></ax-button-group-item>\n </ax-button-group>\n }\n </ax-header>\n <ax-content class=\"p-4\">\n @for (condition of editingConditions(); track condition.id; let i = $index) {\n <!--->\n <!-- ----- Numbered condition row with the field widget ----- -->\n @if (i > 0 && !deviceService.isSmall()) {\n <div class=\"axp-query-filters__logic-split\">\n <span class=\"axp-query-filters__logic-split-label\">{{ (editingLogic() === 'or' ? '@general:terms.interface.filter.chip-logic-or' : '@general:terms.interface.filter.chip-logic-and') | translate | async }}</span>\n </div>\n }\n <div class=\"axp-query-filters__condition\">\n <div class=\"axp-query-filters__condition-head\">\n <div class=\"axp-query-filters__condition-heading\">\n <!--->\n <!-- ----- Field picker for mixed-field groups in advanced mode ----- -->\n @if (isAdvanced()) {\n <ax-dropdown-button class=\"ax-sm\" [text]=\"(getConditionDefinition(condition.field)?.title | translate | async) ?? ''\" [mode]=\"'dropdown'\" [look]=\"'outline'\">\n <ax-button-item-list>\n @for (def of advancedFieldOptions(); track def.field) {\n <ax-button-item [text]=\"(def.title | translate | async) ?? ''\" [selected]=\"condition.field === def.field\" [disabled]=\"isFilterDisabled(def)\" (onClick)=\"setConditionField(condition.id, def.field ?? '')\"></ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-button>\n }\n <!--->\n <!-- ----- Active operator for this condition ----- -->\n @if (getConditionOperatorKey(condition.id); as operatorKey) {\n <ax-badge [text]=\"(operatorKey | translate | async) || ''\"></ax-badge>\n }\n </div>\n <button type=\"button\" class=\"axp-query-filters__condition-remove\" (click)=\"handleRemoveCondition(condition.id)\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n </div>\n <ng-container\n axp-widget-renderer\n [node]=\"{\n type: getConditionWidget(condition)?.type || 'text-editor',\n path: resolveEditingConditionContextField(condition.id),\n options: $safeNavigationMigration(getConditionWidget(condition)?.options),\n }\"\n [mode]=\"'edit'\"\n ></ng-container>\n </div>\n }\n <!--->\n <!-- ----- Extra conditions stay on desktop ----- -->\n @if (!deviceService.isSmall()) {\n <button type=\"button\" class=\"axp-query-filters__add-condition\" (click)=\"handleAddCondition()\">\n <ax-icon class=\"fa-light fa-plus\"></ax-icon>\n <span>{{ (isAdvanced() ? '@general:terms.interface.filter.add-condition-generic' : '@general:terms.interface.filter.add-condition') | translate: { params: { title: activeFilterTitle() } } | async }}</span>\n </button>\n }\n </ax-content>\n <ax-footer class=\"border-t flex justify-end gap-2 border-border-light w-full px-4 py-2\">\n <ax-button class=\"ax-sm\" [look]=\"'blank'\" [text]=\"'@general:actions.cancel.title' | translate | async\" (onClick)=\"handleCancelFilter()\"></ax-button>\n <ax-button class=\"ax-sm\" [color]=\"'primary'\" [disabled]=\"!canApplyFilter()\" [text]=\"'@general:terms.interface.filter.apply-filter' | translate | async\" (onClick)=\"handleApplyFilter()\"></ax-button>\n </ax-footer>\n </div>\n } @else {\n <!-- ----- Field picker when no filter is being edited ----- -->\n <div class=\"flex flex-col lightest-surface\">\n <div axListNavigation #list=\"axListNavigation\" class=\"axp-list-items border-none\">\n @for (field of filterFields(); track field.field) {\n <div\n axListNavigationItem\n #caseItem=\"axListNavigationItem\"\n [class.axp-state-focused]=\"caseItem.isActive() && !isFilterDisabled(field)\"\n [class.axp-query-filters__advance-item--disabled]=\"isFilterDisabled(field)\"\n [attr.aria-disabled]=\"isFilterDisabled(field) ? 'true' : null\"\n [attr.tabindex]=\"isFilterDisabled(field) ? -1 : 0\"\n (click)=\"handleSelectField(field)\"\n (keydown)=\"handleFieldKeyDown($event, field)\"\n >\n <div class=\"flex items-center gap-2\">\n <ax-icon class=\"axp-query-filters__field-icon\" [ngClass]=\"'fa-light ' + field.icon\"></ax-icon>\n <span class=\"leading-none\">{{ field.title | translate | async }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </axp-widgets-container>\n </div>\n</ax-popover>\n", styles: ["@layer properties;axp-query-filters{display:block;width:100%;min-width:0px;overflow:hidden}axp-query-filters>.flex{min-width:0px;flex-wrap:nowrap}axp-query-filters ax-tag-box{width:100%;min-width:0px}axp-query-filters ax-tag-box .editor-container,axp-query-filters ax-tag-box .ax-editor-container{display:flex;width:100%;min-width:0px;flex-wrap:nowrap;align-items:center;background-color:transparent;min-height:2.25rem}axp-query-filters ax-tag-box .ax-tags-container{display:flex;flex:1 1 0%;min-width:0;flex-wrap:nowrap!important;overflow-x:auto;overflow-y:hidden}axp-query-filters ax-tag-box ax-suffix{flex-shrink:0;white-space:nowrap}axp-query-filters>.flex>ax-button button{min-height:var(--ax-sys-size-base);height:var(--ax-sys-size-base);padding-block:0}.axp-query-filters__chips,axp-query-filters ax-tag-box .ax-tags-container{scrollbar-width:none;-ms-overflow-style:none}:is(.axp-query-filters__chips,axp-query-filters ax-tag-box .ax-tags-container)::-webkit-scrollbar{display:none;width:0;height:0;background:transparent}.axp-query-filters__chips{min-width:0px;cursor:grab;overflow-x:auto;overflow-y:hidden}.axp-query-filters__chips.axp-query-filters__chips--panning,.axp-query-filters__chips.axp-query-filters__chips--panning *{cursor:grabbing;-webkit-user-select:none;user-select:none}.axp-query-filters__chip{display:inline-flex;flex-shrink:0;cursor:pointer;align-items:center;gap:var(--spacing, .25rem);border-radius:var(--radius-md, .375rem);background-color:var(--color-surface);color:var(--color-on-surface);border-color:var(--color-border-surface);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * .5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));white-space:nowrap}.axp-query-filters__chip:hover{background-color:rgba(var(--ax-sys-color-darkest-surface))}.axp-query-filters__chip--search,.axp-query-filters__chip--active{background-color:rgba(var(--ax-sys-color-primary-surface));color:var(--color-white, #fff)}:is(.axp-query-filters__chip--search,.axp-query-filters__chip--active):hover{background-color:rgba(var(--ax-sys-color-primary-surface))}.axp-query-filters__chip-title{flex-shrink:0;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.axp-query-filters__chip-text,.axp-query-filters__chip-operator{min-width:0px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axp-query-filters__chip-logic{flex-shrink:0;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}.axp-query-filters__chip--active .axp-query-filters__chip-logic,.axp-query-filters__chip--search .axp-query-filters__chip-logic{color:var(--color-white, #fff)}.axp-query-filters__chip-value{display:inline-flex;max-width:12rem;flex-shrink:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:.25rem;background-color:rgba(var(--ax-sys-color-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: calc(var(--spacing, .25rem) * 5);line-height:calc(var(--spacing, .25rem) * 5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.axp-query-filters__chip--active .axp-query-filters__chip-value,.axp-query-filters__chip--search .axp-query-filters__chip-value{background-color:color-mix(in srgb,#fff 20%,transparent);color:var(--color-white, #fff)}@supports (color: color-mix(in lab,red,red)){.axp-query-filters__chip--active .axp-query-filters__chip-value,.axp-query-filters__chip--search .axp-query-filters__chip-value{background-color:color-mix(in oklab,var(--color-white, #fff) 20%,transparent)}}.axp-query-filters__chip-remove{display:inline-flex;flex-shrink:0;cursor:pointer;align-items:center;justify-content:center;opacity:70%}.axp-query-filters__chip-remove:hover{opacity:100%}.axp-query-filters__mode-toggle{flex:0 0 auto;max-width:6rem;overflow:visible;transition:max-width .32s cubic-bezier(.32,.72,0,1)}.axp-query-filters__mode-toggle--collapsed{max-width:0;pointer-events:none}.axp-query-filters__mode-toggle-inner{position:relative;z-index:10;margin-inline-start:var(--spacing, .25rem);display:inline-flex;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;background-color:var(--color-lightest);color:var(--color-on-lightest);border-color:var(--color-border-lightest);border-color:rgba(var(--ax-sys-color-light-surface));--tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);width:max-content;transform:translate(0);transition:transform .32s cubic-bezier(.32,.72,0,1),margin .32s cubic-bezier(.32,.72,0,1)}.axp-query-filters__mode-toggle--collapsed .axp-query-filters__mode-toggle-inner{margin-inline-start:0;transform:translate(5rem)}[dir=rtl] .axp-query-filters__mode-toggle--collapsed .axp-query-filters__mode-toggle-inner{transform:translate(-5rem)}.axp-query-filters__mode-toggle-btn{display:inline-flex;align-items:center;justify-content:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));width:1.875rem;height:1.625rem}.axp-query-filters__mode-toggle-btn:first-child{border-start-start-radius:calc(infinity * 1px);border-end-start-radius:calc(infinity * 1px)}.axp-query-filters__mode-toggle-btn:last-child{border-start-end-radius:calc(infinity * 1px);border-end-end-radius:calc(infinity * 1px)}.axp-query-filters__mode-toggle-btn--active{background-color:rgba(var(--ax-sys-color-primary-surface));color:var(--color-white, #fff)}.axp-query-filters__mode-toggle-btn:disabled:not(.axp-query-filters__mode-toggle-btn--active){cursor:not-allowed;opacity:40%}.axp-query-filters__mobile-search{min-width:0px;flex:1}.axp-query-filters__mobile-search ax-search-box,.axp-query-filters__mobile-search ax-search-box .ax-editor,.axp-query-filters__mobile-search ax-search-box .ax-editor-container,.axp-query-filters__mobile-search ax-search-box .editor-container{min-height:1.875rem;height:1.875rem}.axp-query-filters__mobile-search ax-search-box input{min-height:1.875rem;height:1.875rem;font-size:.8125rem;line-height:1.125rem}.axp-query-filters__mobile-row{display:flex;min-width:0px;flex:1;flex-wrap:nowrap;align-items:center;gap:var(--spacing, .25rem);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.axp-query-filters__mobile-row::-webkit-scrollbar{display:none;width:0;height:0;background:transparent}.axp-query-filters__mobile-chip{display:inline-flex;flex-shrink:0;cursor:pointer;align-items:center;gap:var(--spacing, .25rem);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;background-color:var(--color-surface);color:var(--color-on-surface);border-color:var(--color-border-surface);border-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * .5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);white-space:nowrap}.axp-query-filters__mobile-chip--available{cursor:pointer;background-color:transparent}.axp-query-filters__mobile-chip--disabled{cursor:not-allowed;opacity:50%}.axp-query-filters__mobile-chip--applied{border-color:rgba(var(--ax-sys-color-primary-surface));background-color:transparent;color:rgba(var(--ax-sys-color-primary-surface))}.axp-query-filters__mobile-chip-text{max-width:10rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.axp-query-filters__mobile-chip-caret{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}.axp-query-filters__editor-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3)}.axp-query-filters__logic-toggle ax-button-group-item.ax-state-selected ax-button button,.axp-query-filters__logic-toggle ax-button button.ax-state-selected{background-image:none;box-shadow:none;background-color:rgba(var(--ax-sys-color-primary-surface));color:var(--color-white, #fff)}.axp-query-filters__logic-toggle ax-button>button{min-height:2rem;height:2rem;padding-inline:.5rem;padding-block:0;font-size:.8125rem;line-height:1.125rem;font-weight:600}@media(max-width:600px){axp-query-filters{overflow:hidden}axp-query-filters>.flex{gap:.5rem;padding-block:0;padding-inline:.125rem;overflow:hidden}axp-query-filters>.flex.axp-query-filters__bar--toggle-collapsed{gap:0}.axp-query-filters__logic-toggle{flex-wrap:nowrap}.axp-query-filters__chip{gap:.375rem;padding-inline:.625rem;padding-block:.25rem;font-size:.8125rem}.axp-query-filters__chip-value{max-width:none;font-size:.8125rem}}.axp-query-filters__condition{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axp-query-filters__condition-head{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.axp-query-filters__condition-heading{display:flex;min-width:0px;flex-wrap:wrap;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.axp-query-filters__condition-title{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-text-default));text-transform:uppercase}@supports (color: color-mix(in lab,red,red)){.axp-query-filters__condition-title{color:color-mix(in oklab,rgba(var(--ax-sys-color-text-default)) 80%,transparent)}}.axp-query-filters__condition-remove{display:inline-flex;cursor:pointer;align-items:center;justify-content:center;color:rgba(var(--ax-sys-color-text-default))}@supports (color: color-mix(in lab,red,red)){.axp-query-filters__condition-remove{color:color-mix(in oklab,rgba(var(--ax-sys-color-text-default)) 80%,transparent)}}.axp-query-filters__condition-remove:hover{color:rgba(var(--ax-sys-color-danger-surface))}.axp-query-filters__logic-split{position:relative;margin-block:calc(var(--spacing, .25rem) * 3);display:flex;align-items:center;justify-content:center}.axp-query-filters__logic-split:before,.axp-query-filters__logic-split:after{content:\"\";height:1px;flex:1;background-color:rgba(var(--ax-sys-color-border-light-surface))}.axp-query-filters__logic-split-label{margin-inline:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * .5);font-size:10px;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}.axp-query-filters__add-condition{margin-top:calc(var(--spacing, .25rem) * 3);display:inline-flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-primary-surface))}.axp-query-filters__add-condition:hover{text-decoration-line:underline}.axp-list-items{display:flex;min-width:calc(var(--spacing, .25rem) * 40);flex-direction:column;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;background-color:var(--color-lightest);color:var(--color-on-lightest);border-color:var(--color-border-lightest);padding-block:calc(var(--spacing, .25rem) * 4);--tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.axp-list-items>div{min-width:calc(var(--spacing, .25rem) * 28);cursor:pointer;padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 2);text-align:start}.axp-list-items>div:focus{outline:none}.axp-list-items>div.axp-state-focused,.axp-list-items>div:hover{background-color:var(--color-surface);color:var(--color-on-surface);border-color:var(--color-border-surface)}.axp-list-items>div.axp-query-filters__advance-item--disabled{cursor:not-allowed;opacity:50%}.axp-list-items>div.axp-query-filters__advance-item--disabled.axp-state-focused,.axp-list-items>div.axp-query-filters__advance-item--disabled:hover{background-color:transparent}.axp-query-filters__field-icon{display:inline-flex;height:calc(var(--spacing, .25rem) * 4);width:calc(var(--spacing, .25rem) * 5);flex-shrink:0;align-items:center;justify-content:center;--tw-leading: 1;line-height:1}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-tracking: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i1$2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "component", type: i4$2.AXButtonGroupComponent, selector: "ax-button-group", inputs: ["disabled", "fitParent", "color", "look", "class", "selection"], outputs: ["onBlur", "onFocus", "disabledChange", "colorChange", "lookChange", "onClick", "selectionChange", "selectedButtonChange"] }, { kind: "component", type: i4$2.AXButtonGroupItemComponent, selector: "ax-button-group-item", inputs: ["disabled", "color", "text", "class", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange", "classChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: i6.AXDropdownButtonComponent, selector: "ax-dropdown-button", inputs: ["disabled", "size", "text", "selected", "color", "look", "type", "mode", "iconOnly"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "lookChange", "colorChange", "disabledChange"] }, { kind: "component", type: AXKBDComponent, selector: "ax-kbd", inputs: ["look"] }, { kind: "component", type: AXKBDItemComponent, selector: "ax-kbd-item", inputs: ["keys", "join", "look"], outputs: ["lookChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2$2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "restoreFocusOnClose", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i3$2.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSelectionListModule }, { kind: "ngmodule", type: AXTagBoxModule }, { kind: "component", type: i9.AXTagBoxComponent, selector: "ax-tag-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "allowNull", "type", "look", "addOnComma", "addOnEnter", "valueField", "textField", "readonlyField", "allowDuplicateValues", "tagTemplate"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onTagClick", "onTagDblClick", "onTagContextMenu"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1$5.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1$5.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXListNavigationModule }, { kind: "directive", type: i11.AXListNavigationDirective, selector: "[axListNavigation]", inputs: ["orientation"], outputs: ["onNavigationChanged", "onKeypress"], exportAs: ["axListNavigation"] }, { kind: "directive", type: i11.AXListNavigationItemDirective, selector: "[axListNavigationItem]", outputs: ["onKeypress"], exportAs: ["axListNavigationItem"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i1$3.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
7891
8011
  }
7892
8012
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPQueryFiltersComponent, decorators: [{
7893
8013
  type: Component,
@@ -8704,7 +8824,8 @@ class AXPPropertyViewerComponent {
8704
8824
  this.context.set(event.data);
8705
8825
  const isHydration = event.state === 'initiated' ||
8706
8826
  event.state === 'restored' ||
8707
- event.origin === 'system';
8827
+ event.origin === 'system' ||
8828
+ event.origin === 'hydrate';
8708
8829
  this.onChanged.emit({
8709
8830
  values: this.context(),
8710
8831
  mode: isHydration ? 'init' : 'update',
@@ -9197,6 +9318,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
9197
9318
  }]
9198
9319
  }] });
9199
9320
 
9321
+ /**
9322
+ * Fixed virtual-scroll row. The lookup paints a "loading" placeholder for any
9323
+ * index that is still a hole, so this must match the option template exactly.
9324
+ */
9325
+ const ITEM_CONFIGURATOR_OPTION_HEIGHT = 56;
9326
+ /** One page covers the whole catalog so search/reopen never leaves unloaded holes. */
9327
+ const ITEM_CONFIGURATOR_PAGE_SIZE = 500;
9328
+ const ITEM_CONFIGURATOR_FALLBACK_ICON = 'fa-light fa-puzzle-piece';
9200
9329
  //#endregion
9201
9330
  //#region ---- Component ----
9202
9331
  /**
@@ -9204,6 +9333,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
9204
9333
  * Bound state: {@link selectedItemId} and {@link values} (context returned from the viewer). Not tied to {@link AXPWidgetNode}.
9205
9334
  */
9206
9335
  class AXPItemConfiguratorComponent {
9336
+ /**
9337
+ * Visible order follows the translated title. Sorting the raw `@scope:key`
9338
+ * puts the list in key order (PPE, Test Sheet, Address, …).
9339
+ */
9340
+ async rowsInDisplayOrder() {
9341
+ const locale = this.translationService.getActiveLang();
9342
+ const labeled = await Promise.all(this.availableItems().map(async (row) => ({
9343
+ row,
9344
+ label: await this.displayLabel(row.title),
9345
+ })));
9346
+ labeled.sort((a, b) => a.label.localeCompare(b.label, locale, { sensitivity: 'base' }));
9347
+ return labeled.map((entry) => entry.row);
9348
+ }
9349
+ async filterRows(rows, needle) {
9350
+ const locale = this.translationService.getActiveLang();
9351
+ const matched = [];
9352
+ for (const row of rows) {
9353
+ const title = (await this.displayLabel(row.title)).toLocaleLowerCase(locale);
9354
+ const description = (await this.displayLabel(row.description)).toLocaleLowerCase(locale);
9355
+ if (title.includes(needle) || description.includes(needle)) {
9356
+ matched.push(row);
9357
+ }
9358
+ }
9359
+ return matched;
9360
+ }
9361
+ async displayLabel(value) {
9362
+ if (value == null || value === '') {
9363
+ return '';
9364
+ }
9365
+ const translated = await this.translationService.translateAsync(value);
9366
+ return translated.trim();
9367
+ }
9207
9368
  enterEditMode() {
9208
9369
  if (this.readonly()) {
9209
9370
  return;
@@ -9251,17 +9412,17 @@ class AXPItemConfiguratorComponent {
9251
9412
  if (!id) {
9252
9413
  continue;
9253
9414
  }
9254
- const title = resolveSearchableText(row.title, locale, this.translationService).trim() || id;
9415
+ const sortText = resolveSearchableText(row.title, locale, this.translationService).trim() || id;
9255
9416
  list.push({
9256
9417
  value: id,
9257
- text: title,
9418
+ text: typeof row.title === 'string' ? row.title : sortText,
9419
+ title: row.title,
9258
9420
  icon: row.icon,
9259
- description: row.description != null
9260
- ? resolveSearchableText(row.description, locale, this.translationService)
9261
- : undefined,
9421
+ description: row.description,
9422
+ sortText,
9262
9423
  });
9263
9424
  }
9264
- return list.sort((a, b) => compareMultiLanguageStrings(a.text, b.text, locale));
9425
+ return list.sort((a, b) => compareMultiLanguageStrings(a.sortText, b.sortText, locale));
9265
9426
  }, /* @ts-ignore */
9266
9427
  ...(ngDevMode ? [{ debugName: "availableItems" }] : /* istanbul ignore next */ []));
9267
9428
  this.selectedListItem = computed(() => {
@@ -9317,8 +9478,41 @@ class AXPItemConfiguratorComponent {
9317
9478
  ...(ngDevMode ? [{ debugName: "isConfigured" }] : /* istanbul ignore next */ []));
9318
9479
  this.visibleHeaderActions = computed(() => (this.headerActions() ?? []).filter((a) => a != null && a.visible !== false && !a.items?.length), /* @ts-ignore */
9319
9480
  ...(ngDevMode ? [{ debugName: "visibleHeaderActions" }] : /* istanbul ignore next */ []));
9481
+ this.optionRowHeight = ITEM_CONFIGURATOR_OPTION_HEIGHT;
9482
+ this.optionMaxVisibleRows = 8;
9483
+ this.fallbackIcon = ITEM_CONFIGURATOR_FALLBACK_ICON;
9484
+ /**
9485
+ * Owned datasource (not a raw array). The lookup wraps arrays at page size 20;
9486
+ * after a search the virtual list keeps a scroll offset into unloaded pages and
9487
+ * stays on the loading placeholder. One page fills every row.
9488
+ */
9489
+ this.itemDataSource = new AXDataSource({
9490
+ key: 'value',
9491
+ pageSize: ITEM_CONFIGURATOR_PAGE_SIZE,
9492
+ load: async (query) => {
9493
+ const rows = await this.rowsInDisplayOrder();
9494
+ const needle = readLookupFilterText(query.filter);
9495
+ const matched = needle ? await this.filterRows(rows, needle) : rows;
9496
+ const skip = query.skip ?? 0;
9497
+ const take = query.take ?? matched.length;
9498
+ return {
9499
+ items: matched.slice(skip, skip + take),
9500
+ total: matched.length,
9501
+ };
9502
+ },
9503
+ byKey: (key) => this.availableItems().find((row) => row.value == key) ?? {
9504
+ value: String(key ?? ''),
9505
+ text: String(key ?? ''),
9506
+ title: String(key ?? ''),
9507
+ sortText: String(key ?? ''),
9508
+ },
9509
+ });
9320
9510
  this.itemLookup = viewChild(AXLookupComponent, /* @ts-ignore */
9321
9511
  ...(ngDevMode ? [{ debugName: "itemLookup" }] : /* istanbul ignore next */ []));
9512
+ effect(() => {
9513
+ this.availableItems();
9514
+ untracked(() => this.itemDataSource.refresh());
9515
+ });
9322
9516
  effect(() => {
9323
9517
  if (!this.isEditMode()) {
9324
9518
  return;
@@ -9424,7 +9618,7 @@ class AXPItemConfiguratorComponent {
9424
9618
  return action.disabled === true;
9425
9619
  }
9426
9620
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPItemConfiguratorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9427
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPItemConfiguratorComponent, isStandalone: true, selector: "axp-item-configurator", inputs: { selectedItemId: { classPropertyName: "selectedItemId", publicName: "selectedItemId", isSignal: true, isRequired: false, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, headerActions: { classPropertyName: "headerActions", publicName: "headerActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedItemId: "selectedItemIdChange", values: "valuesChange" }, viewQueries: [{ propertyName: "itemLookup", first: true, predicate: AXLookupComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Item selector & info container -->\n<div class=\"__item-container\">\n @if (isEditMode()) {\n <div class=\"__item-selector\">\n <ax-lookup\n #itemLookup\n mode=\"drop-down-list\"\n [ngModel]=\"selectedItemId()\"\n [dataSource]=\"availableItems()\"\n [placeholder]=\"\n ('@general:actions.select.title' | translate | async) ?? ''\n \"\n [readonly]=\"readonly()\"\n (onValueChanged)=\"onSelectionChange($event)\"\n valueField=\"value\"\n textField=\"text\"\n [searchable]=\"true\"\n [itemTemplate]=\"itemTemplate\"\n [itemHeight]=\"72\"\n [selectedTemplate]=\"selectedTemplate\"\n (onClosed)=\"exitEditMode()\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-lookup>\n </div>\n }\n\n @if (!isEditMode()) {\n @if (selectedItemId() && currentItemConfig(); as config) {\n <div class=\"__item-info\">\n <div\n class=\"__item-header\"\n [class.__editable]=\"!readonly()\"\n (click)=\"enterEditMode()\"\n >\n <div>\n @if (config.icon) {\n <i [class]=\"config.icon\"></i>\n }\n <div>\n <span>\n {{ config.title | translate | async }}\n </span>\n @if (config.description) {\n <p>\n {{ (config.description | translate | async) ?? '' }}\n </p>\n }\n </div>\n </div>\n\n <div class=\"__action-buttons\" (click)=\"$event.stopPropagation()\">\n @if (config.hasProperties) {\n <ax-button\n [disabled]=\"!canConfigure() || readonly()\"\n [title]=\"\n ('@general:actions.configure.title' | translate | async) ?? ''\n \"\n look=\"blank\"\n [color]=\"isConfigured() ? 'primary' : 'default'\"\n size=\"sm\"\n (onClick)=\"openConfigureDialog()\"\n >\n <ax-icon icon=\"fa-solid fa-cog\"></ax-icon>\n </ax-button>\n }\n @for (\n action of visibleHeaderActions();\n track action.name ?? $index\n ) {\n <ax-button\n look=\"blank\"\n size=\"sm\"\n [color]=\"action.color ?? 'default'\"\n [disabled]=\"readonly() || isHeaderActionDisabled(action)\"\n [title]=\"(action.title | translate | async) ?? ''\"\n [class.icon-only]=\"action.iconOnly === true\"\n (onClick)=\"onHeaderActionClick(action)\"\n >\n @if (action.icon) {\n <ax-icon [icon]=\"action.icon\"></ax-icon>\n }\n @if (action.iconOnly !== true) {\n <span>{{ (action.title | translate | async) ?? '' }}</span>\n }\n </ax-button>\n }\n </div>\n </div>\n </div>\n } @else {\n <div\n class=\"__item-empty\"\n [class.__editable]=\"!readonly()\"\n (click)=\"enterEditMode()\"\n >\n <i class=\"fa-solid fa-puzzle-piece\"></i>\n <span>\n {{\n ('@general:widgets.widget-configurator.select-widget-type'\n | translate\n | async) ?? 'Select an item type'\n }}\n </span>\n </div>\n }\n }\n\n <ng-template #itemTemplate let-item>\n <div class=\"__item-template flex w-full items-center gap-3 p-2\">\n @if (item.icon) {\n <i [class]=\"item.icon + 'text-base w-5 text-center'\"></i>\n }\n <div class=\"flex flex-col gap-1 flex-1 min-w-0\">\n <div class=\"text-sm font-medium\">\n {{ item.text | translate | async }}\n </div>\n @if (item.description) {\n <div class=\"text-xs text-neutral-600\">\n {{ item.description | translate | async }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #selectedTemplate let-item>\n <div class=\"__selected-template\">\n @if (item?.icon) {\n <i [class]=\"item.icon\"></i>\n }\n <span>\n {{ $safeNavigationMigration(item?.text) | translate | async }}\n </span>\n </div>\n </ng-template>\n</div>\n", styles: ["@layer properties;axp-item-configurator{display:flex;flex-direction:column}axp-item-configurator .__item-selector{display:flex;flex-direction:column}axp-item-configurator .__item-selector ax-lookup{width:100%}axp-item-configurator .__item-info{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3)}axp-item-configurator .__item-info .__item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5)}axp-item-configurator .__item-info .__item-header.__editable{cursor:pointer}axp-item-configurator .__item-info .__item-header.__editable:hover{border-radius:var(--radius-md, .375rem);background-color:rgba(var(--ax-sys-color-lighter-surface))}axp-item-configurator .__item-info .__item-header:not(.__editable){cursor:not-allowed}axp-item-configurator .__item-info .__item-header>div:first-child{display:flex;flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__item-info .__item-header>div:first-child i{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));flex-shrink:0}axp-item-configurator .__item-info .__item-header>div:first-child>div{display:flex;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}axp-item-configurator .__item-info .__item-header>div:first-child>div>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-item-configurator .__item-info .__item-header>div:first-child>div>p{margin:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:var(--color-neutral-600, oklch(43.9% 0 none))}axp-item-configurator .__item-info .__action-buttons{display:flex;align-items:center;gap:var(--spacing, .25rem);flex-shrink:0}axp-item-configurator .__item-empty{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__item-empty.__editable{cursor:pointer}axp-item-configurator .__item-empty.__editable:hover{border-radius:var(--radius-md, .375rem);background-color:rgba(var(--ax-sys-color-lighter-surface))}axp-item-configurator .__item-empty:not(.__editable){cursor:not-allowed}axp-item-configurator .__item-empty>i{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:var(--color-neutral-400, oklch(70.8% 0 none))}axp-item-configurator .__item-empty>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-600, oklch(43.9% 0 none))}axp-item-configurator .__item-template>i{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center}axp-item-configurator .__item-template>div>div:first-child{flex-shrink:0}axp-item-configurator .__item-template>div>div:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-item-configurator .__selected-template{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__selected-template>i{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axp-item-configurator .__selected-template>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}axp-item-configurator :host([readonly]){pointer-events:none;opacity:.7}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXLookupComponent, selector: "ax-lookup", inputs: ["name", "mode", "dataSource", "treeDataSource", "valueField", "textField", "disabledField", "columns", "treeParentField", "hasChildrenField", "searchable", "adaptivityEnabled", "caption", "alternate", "searchPlaceholder", "placeholder", "disabled", "readonly", "look", "itemHeight", "maxVisibleItems", "treeSelectionBehavior", "highlightSearch", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "value", "valueItems"], outputs: ["lookChange", "valueChange", "onValueChanged", "onSelectionChanged", "onFocus", "onBlur", "onItemClick", "onItemSelected", "onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
9621
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPItemConfiguratorComponent, isStandalone: true, selector: "axp-item-configurator", inputs: { selectedItemId: { classPropertyName: "selectedItemId", publicName: "selectedItemId", isSignal: true, isRequired: false, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, headerActions: { classPropertyName: "headerActions", publicName: "headerActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedItemId: "selectedItemIdChange", values: "valuesChange" }, viewQueries: [{ propertyName: "itemLookup", first: true, predicate: AXLookupComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Item selector & info container -->\n<div class=\"__item-container\">\n @if (isEditMode()) {\n <div class=\"__item-selector\">\n <ax-lookup\n #itemLookup\n mode=\"drop-down-list\"\n [ngModel]=\"selectedItemId()\"\n [dataSource]=\"itemDataSource\"\n [placeholder]=\"\n ('@general:actions.select.title' | translate | async) ?? ''\n \"\n [readonly]=\"readonly()\"\n (onValueChanged)=\"onSelectionChange($event)\"\n valueField=\"value\"\n textField=\"text\"\n [searchable]=\"true\"\n [itemTemplate]=\"itemTemplate\"\n [loadingTemplate]=\"loadingTemplate\"\n [itemHeight]=\"optionRowHeight\"\n [maxVisibleItems]=\"optionMaxVisibleRows\"\n [selectedTemplate]=\"selectedTemplate\"\n (onClosed)=\"exitEditMode()\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-lookup>\n </div>\n }\n\n @if (!isEditMode()) {\n @if (selectedItemId() && currentItemConfig(); as config) {\n <div class=\"__item-info\">\n <div\n class=\"__item-header\"\n [class.__editable]=\"!readonly()\"\n (click)=\"enterEditMode()\"\n >\n <div>\n @if (config.icon) {\n <ax-icon [icon]=\"config.icon\"></ax-icon>\n }\n <div>\n <span>\n {{ config.title | translate | async }}\n </span>\n @if (config.description) {\n <p>\n {{ (config.description | translate | async) ?? '' }}\n </p>\n }\n </div>\n </div>\n\n <div class=\"__action-buttons\" (click)=\"$event.stopPropagation()\">\n @if (config.hasProperties) {\n <ax-button\n [disabled]=\"!canConfigure() || readonly()\"\n [title]=\"\n ('@general:actions.configure.title' | translate | async) ?? ''\n \"\n look=\"blank\"\n [color]=\"isConfigured() ? 'primary' : 'default'\"\n size=\"sm\"\n (onClick)=\"openConfigureDialog()\"\n >\n <ax-icon icon=\"fa-solid fa-cog\"></ax-icon>\n </ax-button>\n }\n @for (\n action of visibleHeaderActions();\n track action.name ?? $index\n ) {\n <ax-button\n look=\"blank\"\n size=\"sm\"\n [color]=\"action.color ?? 'default'\"\n [disabled]=\"readonly() || isHeaderActionDisabled(action)\"\n [title]=\"(action.title | translate | async) ?? ''\"\n [class.icon-only]=\"action.iconOnly === true\"\n (onClick)=\"onHeaderActionClick(action)\"\n >\n @if (action.icon) {\n <ax-icon [icon]=\"action.icon\"></ax-icon>\n }\n @if (action.iconOnly !== true) {\n <span>{{ (action.title | translate | async) ?? '' }}</span>\n }\n </ax-button>\n }\n </div>\n </div>\n </div>\n } @else {\n <div\n class=\"__item-empty\"\n [class.__editable]=\"!readonly()\"\n (click)=\"enterEditMode()\"\n >\n <i class=\"fa-solid fa-puzzle-piece\"></i>\n <span>\n {{\n ('@general:widgets.widget-configurator.select-widget-type'\n | translate\n | async) ?? 'Select an item type'\n }}\n </span>\n </div>\n }\n }\n\n <ng-template #itemTemplate let-item>\n @let title = (item.title | translate | async) ?? '';\n @let description = (item.description | translate | async) ?? '';\n <div class=\"axp-item-configurator-option\">\n <ax-icon [icon]=\"item.icon || fallbackIcon\"></ax-icon>\n <div class=\"axp-item-configurator-option__text\">\n <span class=\"axp-item-configurator-option__title\">\n {{ title }}\n </span>\n <!-- ----- One-line description under the title ----- -->\n @if (item.description) {\n <span class=\"axp-item-configurator-option__description\">\n {{ description }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #loadingTemplate>\n <div class=\"axp-item-configurator-option axp-item-configurator-option--loading\">\n <span class=\"axp-item-configurator-option__icon-slot\"></span>\n <span class=\"axp-item-configurator-option__bar\"></span>\n </div>\n </ng-template>\n\n <ng-template #selectedTemplate let-item>\n <div class=\"__selected-template\">\n @if (item?.icon) {\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n }\n <span>\n {{ (item?.title | translate | async) ?? '' }}\n </span>\n </div>\n </ng-template>\n</div>\n", styles: ["@layer properties;axp-item-configurator{display:flex;flex-direction:column}axp-item-configurator .__item-selector{display:flex;flex-direction:column}axp-item-configurator .__item-selector ax-lookup{width:100%}axp-item-configurator .__item-info{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3)}axp-item-configurator .__item-info .__item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5)}axp-item-configurator .__item-info .__item-header.__editable{cursor:pointer}axp-item-configurator .__item-info .__item-header.__editable:hover{border-radius:var(--radius-md, .375rem);background-color:rgba(var(--ax-sys-color-lighter-surface))}axp-item-configurator .__item-info .__item-header:not(.__editable){cursor:not-allowed}axp-item-configurator .__item-info .__item-header>div:first-child{display:flex;flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__item-info .__item-header>div:first-child ax-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));flex-shrink:0}axp-item-configurator .__item-info .__item-header>div:first-child>div{display:flex;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}axp-item-configurator .__item-info .__item-header>div:first-child>div>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-item-configurator .__item-info .__item-header>div:first-child>div>p{margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);color:var(--color-neutral-600, oklch(43.9% 0 none))}axp-item-configurator .__item-info .__action-buttons{display:flex;align-items:center;gap:var(--spacing, .25rem);flex-shrink:0}axp-item-configurator .__item-empty{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__item-empty.__editable{cursor:pointer}axp-item-configurator .__item-empty.__editable:hover{border-radius:var(--radius-md, .375rem);background-color:rgba(var(--ax-sys-color-lighter-surface))}axp-item-configurator .__item-empty:not(.__editable){cursor:not-allowed}axp-item-configurator .__item-empty>i{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:var(--color-neutral-400, oklch(70.8% 0 none))}axp-item-configurator .__item-empty>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-600, oklch(43.9% 0 none))}axp-item-configurator .__selected-template{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__selected-template>ax-icon{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axp-item-configurator .__selected-template>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}axp-item-configurator :host([readonly]){pointer-events:none;opacity:.7}.ax-lookup-viewport:has(.axp-item-configurator-option){min-height:224px;overflow-y:scroll;scrollbar-gutter:stable}.ax-lookup-option-host:has(.axp-item-configurator-option){overflow:hidden}.axp-item-configurator-option{box-sizing:border-box;display:flex;align-items:center;gap:.625rem;width:100%;height:100%;min-width:0;overflow:hidden;padding-inline:.75rem}.axp-item-configurator-option>ax-icon{flex-shrink:0;width:1.125rem;font-size:1rem;line-height:1;text-align:center}.axp-item-configurator-option__text{display:flex;min-width:0;flex:1;flex-direction:column;justify-content:center;gap:.125rem;line-height:1.25}.axp-item-configurator-option__title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;font-weight:500;line-height:1.25}.axp-item-configurator-option__description{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--color-neutral-600, oklch(43.9% 0 none));font-size:.75rem;line-height:1.25}.axp-item-configurator-option--loading{gap:.5rem}.axp-item-configurator-option__icon-slot,.axp-item-configurator-option__bar{display:block;border-radius:.25rem;background:currentColor}@supports (color: color-mix(in lab,red,red)){.axp-item-configurator-option__icon-slot,.axp-item-configurator-option__bar{background:color-mix(in srgb,currentColor 12%,transparent)}}.axp-item-configurator-option__icon-slot{width:1rem;height:1rem;flex-shrink:0}.axp-item-configurator-option__bar{height:.5rem;width:40%}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXLookupComponent, selector: "ax-lookup", inputs: ["name", "mode", "dataSource", "treeDataSource", "valueField", "textField", "disabledField", "columns", "treeParentField", "hasChildrenField", "searchable", "adaptivityEnabled", "caption", "alternate", "searchPlaceholder", "placeholder", "disabled", "readonly", "look", "itemHeight", "maxVisibleItems", "treeSelectionBehavior", "highlightSearch", "allowSelectAll", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "value", "valueItems", "prefetch"], outputs: ["lookChange", "valueChange", "onValueChanged", "onSelectionChanged", "onFocus", "onBlur", "onItemClick", "onItemSelected", "onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
9428
9622
  }
9429
9623
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPItemConfiguratorComponent, decorators: [{
9430
9624
  type: Component,
@@ -9436,7 +9630,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
9436
9630
  AXLookupComponent,
9437
9631
  AXDecoratorModule,
9438
9632
  AXTranslationModule,
9439
- ], template: "<!-- Item selector & info container -->\n<div class=\"__item-container\">\n @if (isEditMode()) {\n <div class=\"__item-selector\">\n <ax-lookup\n #itemLookup\n mode=\"drop-down-list\"\n [ngModel]=\"selectedItemId()\"\n [dataSource]=\"availableItems()\"\n [placeholder]=\"\n ('@general:actions.select.title' | translate | async) ?? ''\n \"\n [readonly]=\"readonly()\"\n (onValueChanged)=\"onSelectionChange($event)\"\n valueField=\"value\"\n textField=\"text\"\n [searchable]=\"true\"\n [itemTemplate]=\"itemTemplate\"\n [itemHeight]=\"72\"\n [selectedTemplate]=\"selectedTemplate\"\n (onClosed)=\"exitEditMode()\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-lookup>\n </div>\n }\n\n @if (!isEditMode()) {\n @if (selectedItemId() && currentItemConfig(); as config) {\n <div class=\"__item-info\">\n <div\n class=\"__item-header\"\n [class.__editable]=\"!readonly()\"\n (click)=\"enterEditMode()\"\n >\n <div>\n @if (config.icon) {\n <i [class]=\"config.icon\"></i>\n }\n <div>\n <span>\n {{ config.title | translate | async }}\n </span>\n @if (config.description) {\n <p>\n {{ (config.description | translate | async) ?? '' }}\n </p>\n }\n </div>\n </div>\n\n <div class=\"__action-buttons\" (click)=\"$event.stopPropagation()\">\n @if (config.hasProperties) {\n <ax-button\n [disabled]=\"!canConfigure() || readonly()\"\n [title]=\"\n ('@general:actions.configure.title' | translate | async) ?? ''\n \"\n look=\"blank\"\n [color]=\"isConfigured() ? 'primary' : 'default'\"\n size=\"sm\"\n (onClick)=\"openConfigureDialog()\"\n >\n <ax-icon icon=\"fa-solid fa-cog\"></ax-icon>\n </ax-button>\n }\n @for (\n action of visibleHeaderActions();\n track action.name ?? $index\n ) {\n <ax-button\n look=\"blank\"\n size=\"sm\"\n [color]=\"action.color ?? 'default'\"\n [disabled]=\"readonly() || isHeaderActionDisabled(action)\"\n [title]=\"(action.title | translate | async) ?? ''\"\n [class.icon-only]=\"action.iconOnly === true\"\n (onClick)=\"onHeaderActionClick(action)\"\n >\n @if (action.icon) {\n <ax-icon [icon]=\"action.icon\"></ax-icon>\n }\n @if (action.iconOnly !== true) {\n <span>{{ (action.title | translate | async) ?? '' }}</span>\n }\n </ax-button>\n }\n </div>\n </div>\n </div>\n } @else {\n <div\n class=\"__item-empty\"\n [class.__editable]=\"!readonly()\"\n (click)=\"enterEditMode()\"\n >\n <i class=\"fa-solid fa-puzzle-piece\"></i>\n <span>\n {{\n ('@general:widgets.widget-configurator.select-widget-type'\n | translate\n | async) ?? 'Select an item type'\n }}\n </span>\n </div>\n }\n }\n\n <ng-template #itemTemplate let-item>\n <div class=\"__item-template flex w-full items-center gap-3 p-2\">\n @if (item.icon) {\n <i [class]=\"item.icon + 'text-base w-5 text-center'\"></i>\n }\n <div class=\"flex flex-col gap-1 flex-1 min-w-0\">\n <div class=\"text-sm font-medium\">\n {{ item.text | translate | async }}\n </div>\n @if (item.description) {\n <div class=\"text-xs text-neutral-600\">\n {{ item.description | translate | async }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #selectedTemplate let-item>\n <div class=\"__selected-template\">\n @if (item?.icon) {\n <i [class]=\"item.icon\"></i>\n }\n <span>\n {{ $safeNavigationMigration(item?.text) | translate | async }}\n </span>\n </div>\n </ng-template>\n</div>\n", styles: ["@layer properties;axp-item-configurator{display:flex;flex-direction:column}axp-item-configurator .__item-selector{display:flex;flex-direction:column}axp-item-configurator .__item-selector ax-lookup{width:100%}axp-item-configurator .__item-info{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3)}axp-item-configurator .__item-info .__item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5)}axp-item-configurator .__item-info .__item-header.__editable{cursor:pointer}axp-item-configurator .__item-info .__item-header.__editable:hover{border-radius:var(--radius-md, .375rem);background-color:rgba(var(--ax-sys-color-lighter-surface))}axp-item-configurator .__item-info .__item-header:not(.__editable){cursor:not-allowed}axp-item-configurator .__item-info .__item-header>div:first-child{display:flex;flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__item-info .__item-header>div:first-child i{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));flex-shrink:0}axp-item-configurator .__item-info .__item-header>div:first-child>div{display:flex;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}axp-item-configurator .__item-info .__item-header>div:first-child>div>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-item-configurator .__item-info .__item-header>div:first-child>div>p{margin:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:var(--color-neutral-600, oklch(43.9% 0 none))}axp-item-configurator .__item-info .__action-buttons{display:flex;align-items:center;gap:var(--spacing, .25rem);flex-shrink:0}axp-item-configurator .__item-empty{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__item-empty.__editable{cursor:pointer}axp-item-configurator .__item-empty.__editable:hover{border-radius:var(--radius-md, .375rem);background-color:rgba(var(--ax-sys-color-lighter-surface))}axp-item-configurator .__item-empty:not(.__editable){cursor:not-allowed}axp-item-configurator .__item-empty>i{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:var(--color-neutral-400, oklch(70.8% 0 none))}axp-item-configurator .__item-empty>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-600, oklch(43.9% 0 none))}axp-item-configurator .__item-template>i{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center}axp-item-configurator .__item-template>div>div:first-child{flex-shrink:0}axp-item-configurator .__item-template>div>div:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-item-configurator .__selected-template{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__selected-template>i{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axp-item-configurator .__selected-template>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}axp-item-configurator :host([readonly]){pointer-events:none;opacity:.7}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
9633
+ ], template: "<!-- Item selector & info container -->\n<div class=\"__item-container\">\n @if (isEditMode()) {\n <div class=\"__item-selector\">\n <ax-lookup\n #itemLookup\n mode=\"drop-down-list\"\n [ngModel]=\"selectedItemId()\"\n [dataSource]=\"itemDataSource\"\n [placeholder]=\"\n ('@general:actions.select.title' | translate | async) ?? ''\n \"\n [readonly]=\"readonly()\"\n (onValueChanged)=\"onSelectionChange($event)\"\n valueField=\"value\"\n textField=\"text\"\n [searchable]=\"true\"\n [itemTemplate]=\"itemTemplate\"\n [loadingTemplate]=\"loadingTemplate\"\n [itemHeight]=\"optionRowHeight\"\n [maxVisibleItems]=\"optionMaxVisibleRows\"\n [selectedTemplate]=\"selectedTemplate\"\n (onClosed)=\"exitEditMode()\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-lookup>\n </div>\n }\n\n @if (!isEditMode()) {\n @if (selectedItemId() && currentItemConfig(); as config) {\n <div class=\"__item-info\">\n <div\n class=\"__item-header\"\n [class.__editable]=\"!readonly()\"\n (click)=\"enterEditMode()\"\n >\n <div>\n @if (config.icon) {\n <ax-icon [icon]=\"config.icon\"></ax-icon>\n }\n <div>\n <span>\n {{ config.title | translate | async }}\n </span>\n @if (config.description) {\n <p>\n {{ (config.description | translate | async) ?? '' }}\n </p>\n }\n </div>\n </div>\n\n <div class=\"__action-buttons\" (click)=\"$event.stopPropagation()\">\n @if (config.hasProperties) {\n <ax-button\n [disabled]=\"!canConfigure() || readonly()\"\n [title]=\"\n ('@general:actions.configure.title' | translate | async) ?? ''\n \"\n look=\"blank\"\n [color]=\"isConfigured() ? 'primary' : 'default'\"\n size=\"sm\"\n (onClick)=\"openConfigureDialog()\"\n >\n <ax-icon icon=\"fa-solid fa-cog\"></ax-icon>\n </ax-button>\n }\n @for (\n action of visibleHeaderActions();\n track action.name ?? $index\n ) {\n <ax-button\n look=\"blank\"\n size=\"sm\"\n [color]=\"action.color ?? 'default'\"\n [disabled]=\"readonly() || isHeaderActionDisabled(action)\"\n [title]=\"(action.title | translate | async) ?? ''\"\n [class.icon-only]=\"action.iconOnly === true\"\n (onClick)=\"onHeaderActionClick(action)\"\n >\n @if (action.icon) {\n <ax-icon [icon]=\"action.icon\"></ax-icon>\n }\n @if (action.iconOnly !== true) {\n <span>{{ (action.title | translate | async) ?? '' }}</span>\n }\n </ax-button>\n }\n </div>\n </div>\n </div>\n } @else {\n <div\n class=\"__item-empty\"\n [class.__editable]=\"!readonly()\"\n (click)=\"enterEditMode()\"\n >\n <i class=\"fa-solid fa-puzzle-piece\"></i>\n <span>\n {{\n ('@general:widgets.widget-configurator.select-widget-type'\n | translate\n | async) ?? 'Select an item type'\n }}\n </span>\n </div>\n }\n }\n\n <ng-template #itemTemplate let-item>\n @let title = (item.title | translate | async) ?? '';\n @let description = (item.description | translate | async) ?? '';\n <div class=\"axp-item-configurator-option\">\n <ax-icon [icon]=\"item.icon || fallbackIcon\"></ax-icon>\n <div class=\"axp-item-configurator-option__text\">\n <span class=\"axp-item-configurator-option__title\">\n {{ title }}\n </span>\n <!-- ----- One-line description under the title ----- -->\n @if (item.description) {\n <span class=\"axp-item-configurator-option__description\">\n {{ description }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #loadingTemplate>\n <div class=\"axp-item-configurator-option axp-item-configurator-option--loading\">\n <span class=\"axp-item-configurator-option__icon-slot\"></span>\n <span class=\"axp-item-configurator-option__bar\"></span>\n </div>\n </ng-template>\n\n <ng-template #selectedTemplate let-item>\n <div class=\"__selected-template\">\n @if (item?.icon) {\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n }\n <span>\n {{ (item?.title | translate | async) ?? '' }}\n </span>\n </div>\n </ng-template>\n</div>\n", styles: ["@layer properties;axp-item-configurator{display:flex;flex-direction:column}axp-item-configurator .__item-selector{display:flex;flex-direction:column}axp-item-configurator .__item-selector ax-lookup{width:100%}axp-item-configurator .__item-info{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3)}axp-item-configurator .__item-info .__item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5)}axp-item-configurator .__item-info .__item-header.__editable{cursor:pointer}axp-item-configurator .__item-info .__item-header.__editable:hover{border-radius:var(--radius-md, .375rem);background-color:rgba(var(--ax-sys-color-lighter-surface))}axp-item-configurator .__item-info .__item-header:not(.__editable){cursor:not-allowed}axp-item-configurator .__item-info .__item-header>div:first-child{display:flex;flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__item-info .__item-header>div:first-child ax-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));flex-shrink:0}axp-item-configurator .__item-info .__item-header>div:first-child>div{display:flex;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}axp-item-configurator .__item-info .__item-header>div:first-child>div>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-item-configurator .__item-info .__item-header>div:first-child>div>p{margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);color:var(--color-neutral-600, oklch(43.9% 0 none))}axp-item-configurator .__item-info .__action-buttons{display:flex;align-items:center;gap:var(--spacing, .25rem);flex-shrink:0}axp-item-configurator .__item-empty{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__item-empty.__editable{cursor:pointer}axp-item-configurator .__item-empty.__editable:hover{border-radius:var(--radius-md, .375rem);background-color:rgba(var(--ax-sys-color-lighter-surface))}axp-item-configurator .__item-empty:not(.__editable){cursor:not-allowed}axp-item-configurator .__item-empty>i{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:var(--color-neutral-400, oklch(70.8% 0 none))}axp-item-configurator .__item-empty>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-600, oklch(43.9% 0 none))}axp-item-configurator .__selected-template{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}axp-item-configurator .__selected-template>ax-icon{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axp-item-configurator .__selected-template>span{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}axp-item-configurator :host([readonly]){pointer-events:none;opacity:.7}.ax-lookup-viewport:has(.axp-item-configurator-option){min-height:224px;overflow-y:scroll;scrollbar-gutter:stable}.ax-lookup-option-host:has(.axp-item-configurator-option){overflow:hidden}.axp-item-configurator-option{box-sizing:border-box;display:flex;align-items:center;gap:.625rem;width:100%;height:100%;min-width:0;overflow:hidden;padding-inline:.75rem}.axp-item-configurator-option>ax-icon{flex-shrink:0;width:1.125rem;font-size:1rem;line-height:1;text-align:center}.axp-item-configurator-option__text{display:flex;min-width:0;flex:1;flex-direction:column;justify-content:center;gap:.125rem;line-height:1.25}.axp-item-configurator-option__title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;font-weight:500;line-height:1.25}.axp-item-configurator-option__description{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--color-neutral-600, oklch(43.9% 0 none));font-size:.75rem;line-height:1.25}.axp-item-configurator-option--loading{gap:.5rem}.axp-item-configurator-option__icon-slot,.axp-item-configurator-option__bar{display:block;border-radius:.25rem;background:currentColor}@supports (color: color-mix(in lab,red,red)){.axp-item-configurator-option__icon-slot,.axp-item-configurator-option__bar{background:color-mix(in srgb,currentColor 12%,transparent)}}.axp-item-configurator-option__icon-slot{width:1rem;height:1rem;flex-shrink:0}.axp-item-configurator-option__bar{height:.5rem;width:40%}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
9440
9634
  }], ctorParameters: () => [], propDecorators: { selectedItemId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemId", required: false }] }, { type: i0.Output, args: ["selectedItemIdChange"] }], values: [{ type: i0.Input, args: [{ isSignal: true, alias: "values", required: false }] }, { type: i0.Output, args: ["valuesChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], headerActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerActions", required: false }] }], itemLookup: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXLookupComponent), { isSignal: true }] }] } });
9441
9635
  //#region ---- Helpers ----
9442
9636
  function isPropertyDefinitionArray(value) {
@@ -9457,6 +9651,24 @@ function extractOptionsPatchFromPropertyViewerValues(values) {
9457
9651
  }
9458
9652
  return values;
9459
9653
  }
9654
+ function readLookupFilterText(filter) {
9655
+ if (!filter || typeof filter !== 'object') {
9656
+ return '';
9657
+ }
9658
+ const candidate = filter;
9659
+ if (candidate.operator?.type === 'contains' && candidate.value != null) {
9660
+ return String(candidate.value).trim().toLocaleLowerCase();
9661
+ }
9662
+ if (Array.isArray(candidate.filters)) {
9663
+ for (const nested of candidate.filters) {
9664
+ const text = readLookupFilterText(nested);
9665
+ if (text) {
9666
+ return text;
9667
+ }
9668
+ }
9669
+ }
9670
+ return '';
9671
+ }
9460
9672
 
9461
9673
  //#region ----- Imports -----
9462
9674
  //#endregion
@@ -15142,6 +15354,7 @@ class AXPUserAvatarComponent {
15142
15354
  this.sessionService = inject(AXPSessionService);
15143
15355
  this.fileStorage = inject(AXPFileStorageService);
15144
15356
  this.presenceService = inject(AXPUserPresenceService, { optional: true });
15357
+ this.userStatus = inject(AXPUserStatusFeatureService);
15145
15358
  this.resolveGeneration = 0;
15146
15359
  this.lastResolvedRef = null;
15147
15360
  this.userInfo = signal(null, /* @ts-ignore */
@@ -15189,13 +15402,14 @@ class AXPUserAvatarComponent {
15189
15402
  ...(ngDevMode ? [{ debugName: "isAway" }] : /* istanbul ignore next */ []));
15190
15403
  this.isBusy = computed(() => this.presenceStatus() === 'busy', /* @ts-ignore */
15191
15404
  ...(ngDevMode ? [{ debugName: "isBusy" }] : /* istanbul ignore next */ []));
15192
- this.showPresenceDot = computed(() => this.showPresence() &&
15405
+ this.showPresenceDot = computed(() => this.userStatus.enabled() &&
15406
+ this.showPresence() &&
15193
15407
  isWatchablePresenceUserId(String(this.userId() ?? '')) &&
15194
15408
  this.presenceStatus() !== null, /* @ts-ignore */
15195
15409
  ...(ngDevMode ? [{ debugName: "showPresenceDot" }] : /* istanbul ignore next */ []));
15196
15410
  effect((onCleanup) => {
15197
15411
  const id = String(this.userId() ?? '').trim();
15198
- const showPresence = this.showPresence();
15412
+ const showPresence = this.showPresence() && this.userStatus.enabled();
15199
15413
  void this.displayName();
15200
15414
  void this.displayAvatar();
15201
15415
  if (!id) {
@@ -15461,6 +15675,7 @@ class AXPUserCardComponent {
15461
15675
  //#region ----- Services & Dependencies -----
15462
15676
  this.avatarService = inject(AXPUserAvatarService);
15463
15677
  this.presenceService = inject(AXPUserPresenceService, { optional: true });
15678
+ this.userStatus = inject(AXPUserStatusFeatureService);
15464
15679
  this.formatService = inject(AXFormatService);
15465
15680
  this.settingsService = inject(AXPSettingsService);
15466
15681
  this.translation = inject(AXTranslationService);
@@ -15517,7 +15732,7 @@ class AXPUserCardComponent {
15517
15732
  }
15518
15733
  }, /* @ts-ignore */
15519
15734
  ...(ngDevMode ? [{ debugName: "presenceLabelKey" }] : /* istanbul ignore next */ []));
15520
- this.showPresence = computed(() => isWatchablePresenceUserId(this.userId()), /* @ts-ignore */
15735
+ this.showPresence = computed(() => this.userStatus.enabled() && isWatchablePresenceUserId(this.userId()), /* @ts-ignore */
15521
15736
  ...(ngDevMode ? [{ debugName: "showPresence" }] : /* istanbul ignore next */ []));
15522
15737
  this.tooltipDisabled = computed(() => !this.tooltipText(), /* @ts-ignore */
15523
15738
  ...(ngDevMode ? [{ debugName: "tooltipDisabled" }] : /* istanbul ignore next */ []));
@@ -15545,7 +15760,7 @@ class AXPUserCardComponent {
15545
15760
  this.subscriptions.add(this.avatarService.getUserInfo$(userId).subscribe((data) => {
15546
15761
  this.identity.set(data);
15547
15762
  }));
15548
- if (this.presenceService && isWatchablePresenceUserId(userId)) {
15763
+ if (this.userStatus.enabled() && this.presenceService && isWatchablePresenceUserId(userId)) {
15549
15764
  this.presenceService.watch(userId);
15550
15765
  this.watchedUserId = userId;
15551
15766
  this.presence.set(this.presenceService.get(userId) ?? { userId, status: 'offline' });
@@ -16927,5 +17142,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
16927
17142
  * Generated bundle index. Do not edit.
16928
17143
  */
16929
17144
 
16930
- export { AXPActivityLogComponent, AXPAvatarComponent, AXPCategoryTreeComponent, AXPColorChooserComponent, AXPColorPalettePickerComponent, AXPColumnItemListComponent, AXPCompareViewComponent, AXPConditionBuilderComponent, AXPConditionBuilderConditionComponent, AXPDataSelectorComponent, AXPDataSelectorService, AXPDragDropListComponent, AXPEntityListStylingDialogService, AXPEntityListStylingPopupComponent, AXPExpressionFieldDefinitions, AXPFileChooserCompressImagesHook, AXPFileChooserDirective, AXPFileChooserHookKeys, AXPFileChooserService, AXPFileChooserZipFilesHook, AXPFileUploaderDirective, AXPFileUploaderHookKeys, AXPFileUploaderService, AXPFileViewerComponent, AXPFileViewerFallbackContentComponent, AXPFileViewerService, AXPImageEditorPopupComponent, AXPImageEditorService, AXPInfiniteScrollDirective, AXPItemConfiguratorComponent, AXPLayoutFloatingZoomBarComponent, AXPLayoutSideDetailPanelComponent, AXPLayoutSideDetailPanelSectionDirective, AXPLocalDataSourceEditorDialogService, AXPMarkdownTemplateDirective, AXPMarkdownViewerComponent, AXPMenuBadgeHelper, AXPMenuCustomizerComponent, AXPMenuCustomizerService, AXPOutcomeResultsViewerComponent, AXPPageComponentRegistryService, AXPPreloadFiltersComponent, AXPPropertyViewerComponent, AXPPropertyViewerPopupComponent, AXPPropertyViewerService, AXPQueryColumnsComponent, AXPQueryFiltersComponent, AXPQuerySortsComponent, AXPQueryViewSaveButtonComponent, AXPQueryViewSaveDialogService, AXPQueryViewTabsComponent, AXPQueryViewsComponent, AXPRepeaterRowsLayoutComponent, AXPResourceAppointmentBoardProvider, AXPResourceAppointmentComponent, AXPResourceAppointmentService, AXPSectionItemsBuilderComponent, AXPSignatureEditorService, AXPSpreadsheetComponent, AXPStandardSectionItemsBuilderComponent, AXPStopwatchComponent, AXPTableColumnsEditorComponent, AXPTableColumnsEditorPopupComponent, AXPTableColumnsEditorService, AXPTableDataEditorComponent, AXPTableDataEditorPopupComponent, AXPTableDataEditorService, AXPTaskBadgeDirective, AXPTaskBadgeProvider, AXPTaskBadgeService, AXPTemplateViewerComponent, AXPTemplateViewerService, AXPTextCommandColumnComponent, AXPThemeLayoutActionsComponent, AXPThemeLayoutBlockComponent, AXPThemeLayoutContainerComponent, AXPThemeLayoutEndSideComponent, AXPThemeLayoutFooterComponent, AXPThemeLayoutHeaderComponent, AXPThemeLayoutListComponent, AXPThemeLayoutListItemComponent, AXPThemeLayoutListItemsGroupComponent, AXPThemeLayoutPageHeaderComponent, AXPThemeLayoutPagePrimaryActionsComponent, AXPThemeLayoutPageSecondaryActionsComponent, AXPThemeLayoutSectionComponent, AXPThemeLayoutStartSideComponent, AXPThemeLayoutToolbarComponent, AXPUserAvatarComponent, AXPUserAvatarService, AXPUserCardComponent, AXPUserCardDirective, AXPUserCardService, AXPVirtualKeypadComponent, AXPWidgetFieldConfiguratorComponent, AXPWidgetItemComponent, AXPWidgetPropertyViewerComponent, AXPWidgetPropertyViewerPopupComponent, AXPWidgetPropertyViewerService, AXP_EXPRESSION_LOGIC_DEFINITIONS, AXP_EXPRESSION_OPERATION_DEFINITIONS, AXP_FILE_CHOOSER_DEFAULT_ZIP_ARCHIVE_NAME, AXP_FILE_CHOOSER_HOOK_PROVIDERS, AXP_FILE_CHOOSER_OPTION_KEYS, AXP_FILE_CHOOSER_PROVIDERS, AXP_FILE_UPLOADER_PROVIDERS, AXP_IMAGE_FILE_CHOOSER_ACCEPT, AXP_INFINITE_SCROLL_DEFAULT_ROOT_MARGIN, AXP_MENU_CUSTOMIZER_SERVICE, AXP_PAGE_COMPONENT_PROVIDER, AXP_PAGE_LAYOUT_ELEMENT_ID, AXP_PROFILE_PHOTO_GRAVATAR_SOURCE_KEY, AXP_RESOURCE_APPOINTMENT_PROVIDER, AXP_SIGNATURE_PROVIDER, AXP_SPREADSHEET_COLUMN_WIDGET_TYPES, AXP_SYSTEM_FILE_CHOOSER_PROVIDER, AXP_SYSTEM_FILE_UPLOADER_PROVIDER, AXP_TASK_BADGE_PROVIDERS, AXP_USER_AVATAR_PROVIDER, PROPERTY_VIEWER_EXPRESSION_EDITOR_MIN_LINES, SPREADSHEET_COLUMN_NAME_PATH, SPREADSHEET_COLUMN_TITLE_PATH, STANDARD_SECTION_ITEMS_SECTION_TABS, USER_CARD_HOVER_OPEN_DELAY_MS, USER_CARD_ITEMS_HOOK, USER_CARD_ITEMS_SKELETON_DELAY_MS, asSpreadsheetColumnTitle, buildEntityListStylingRulesLayout, buildFileChooserOptions, buildGravatarAvatarUrl, buildPropertyViewerInitialContextFromProperties, buildPropertyViewerTabsFromProperties, buildTableColumnsEditorLayout, compressImageFile, createAttachedFileProviderMenu, createZipArchive, fetchGravatarImageFile, fileListItemToFileViewerItem, fileListItemToImageFile, fileMatchesAccept, fileNameMatchesAccept, filterFileProvidersByContext, filterFilesByAcceptAndMaxSize, formatAcceptForDisplay, formatMaxFileSizeForDisplay, getFieldDefinitions, getLogicDefinition, getOperationDefinition, isPropertyBindingExpressionFormValue, isUnrestrictedFileAccept, mapFileListToViewerItems, md5Hex, mergeInfiniteScrollPage, mergeObjectsReplacingArrays, normalizeFileViewerBoundValue, normalizeSpreadsheetColumnName, notifyFileAcceptRejections, observeInfiniteScroll, pickImageFileViaFileChooser, pickProfilePhotoImageFile, preparePropertyForViewer, preparePropertyViewerTabs, provideFileChooserHooks, readSpreadsheetColumnIdentity, readSpreadsheetColumnWidth, registerFieldDefinitions, resolveExcludedFileProviderKeys, resolveFileChooserAccept, resolveFileChooserExtension, resolveFileListItemUrl, resolveFileUploaderEmptyStateDescription, resolveInfiniteScrollRoot, sortUserCardActions, sortUserCardRows, spreadsheetColumnIdentityProperties, toSpreadsheetColumnWidget, validateFileChooserItems, visibleUserCardActions, withValidationsOnEditorNode };
17145
+ export { AXPActivityLogComponent, AXPAvatarComponent, AXPCategoryTreeComponent, AXPColorChooserComponent, AXPColorPalettePickerComponent, AXPColumnItemListComponent, AXPCompareViewComponent, AXPConditionBuilderComponent, AXPConditionBuilderConditionComponent, AXPDataSelectorComponent, AXPDataSelectorService, AXPDragDropListComponent, AXPEntityListStylingDialogService, AXPEntityListStylingPopupComponent, AXPExpressionFieldDefinitions, AXPFileChooserCompressImagesHook, AXPFileChooserDirective, AXPFileChooserHookKeys, AXPFileChooserService, AXPFileChooserZipFilesHook, AXPFileUploaderDirective, AXPFileUploaderHookKeys, AXPFileUploaderService, AXPFileViewerComponent, AXPFileViewerFallbackContentComponent, AXPFileViewerService, AXPImageEditorPopupComponent, AXPImageEditorService, AXPInfiniteScrollDirective, AXPItemConfiguratorComponent, AXPLayoutFloatingZoomBarComponent, AXPLayoutSideDetailPanelComponent, AXPLayoutSideDetailPanelSectionDirective, AXPLocalDataSourceEditorDialogService, AXPMarkdownTemplateDirective, AXPMarkdownViewerComponent, AXPMenuBadgeHelper, AXPMenuCustomizerComponent, AXPMenuCustomizerService, AXPOutcomeResultsViewerComponent, AXPPageComponentRegistryService, AXPPreloadFiltersComponent, AXPPropertyViewerComponent, AXPPropertyViewerPopupComponent, AXPPropertyViewerService, AXPQueryColumnsComponent, AXPQueryFiltersComponent, AXPQuerySortsComponent, AXPQueryViewSaveButtonComponent, AXPQueryViewSaveDialogService, AXPQueryViewTabsComponent, AXPQueryViewsComponent, AXPRepeaterRowsLayoutComponent, AXPResourceAppointmentBoardProvider, AXPResourceAppointmentComponent, AXPResourceAppointmentService, AXPSectionItemsBuilderComponent, AXPSignatureEditorService, AXPSpreadsheetComponent, AXPStandardSectionItemsBuilderComponent, AXPStopwatchComponent, AXPTableColumnsEditorComponent, AXPTableColumnsEditorPopupComponent, AXPTableColumnsEditorService, AXPTableDataEditorComponent, AXPTableDataEditorPopupComponent, AXPTableDataEditorService, AXPTaskBadgeDirective, AXPTaskBadgeProvider, AXPTaskBadgeService, AXPTemplateViewerComponent, AXPTemplateViewerService, AXPTextCommandColumnComponent, AXPThemeLayoutActionsComponent, AXPThemeLayoutBlockComponent, AXPThemeLayoutContainerComponent, AXPThemeLayoutEndSideComponent, AXPThemeLayoutFooterComponent, AXPThemeLayoutHeaderComponent, AXPThemeLayoutListComponent, AXPThemeLayoutListItemComponent, AXPThemeLayoutListItemsGroupComponent, AXPThemeLayoutPageHeaderComponent, AXPThemeLayoutPagePrimaryActionsComponent, AXPThemeLayoutPageSecondaryActionsComponent, AXPThemeLayoutSectionComponent, AXPThemeLayoutStartSideComponent, AXPThemeLayoutToolbarComponent, AXPUserAvatarComponent, AXPUserAvatarService, AXPUserCardComponent, AXPUserCardDirective, AXPUserCardService, AXPVirtualKeypadComponent, AXPWidgetFieldConfiguratorComponent, AXPWidgetItemComponent, AXPWidgetPropertyViewerComponent, AXPWidgetPropertyViewerPopupComponent, AXPWidgetPropertyViewerService, AXP_EXPRESSION_LOGIC_DEFINITIONS, AXP_EXPRESSION_OPERATION_DEFINITIONS, AXP_FILE_CHOOSER_DEFAULT_ZIP_ARCHIVE_NAME, AXP_FILE_CHOOSER_HOOK_PROVIDERS, AXP_FILE_CHOOSER_OPTION_KEYS, AXP_FILE_CHOOSER_PROVIDERS, AXP_FILE_UPLOADER_PROVIDERS, AXP_IMAGE_FILE_CHOOSER_ACCEPT, AXP_INFINITE_SCROLL_DEFAULT_ROOT_MARGIN, AXP_MENU_CUSTOMIZER_SERVICE, AXP_PAGE_COMPONENT_PROVIDER, AXP_PAGE_LAYOUT_ELEMENT_ID, AXP_PROFILE_PHOTO_GRAVATAR_SOURCE_KEY, AXP_RESOURCE_APPOINTMENT_PROVIDER, AXP_SIGNATURE_PROVIDER, AXP_SPREADSHEET_COLUMN_WIDGET_TYPES, AXP_SYSTEM_FILE_CHOOSER_PROVIDER, AXP_SYSTEM_FILE_UPLOADER_PROVIDER, AXP_TASK_BADGE_PROVIDERS, AXP_USER_AVATAR_PROVIDER, PROPERTY_VIEWER_EXPRESSION_EDITOR_MIN_LINES, SPREADSHEET_COLUMN_NAME_PATH, SPREADSHEET_COLUMN_TITLE_PATH, STANDARD_SECTION_ITEMS_SECTION_TABS, USER_CARD_HOVER_OPEN_DELAY_MS, USER_CARD_ITEMS_HOOK, USER_CARD_ITEMS_SKELETON_DELAY_MS, asSpreadsheetColumnTitle, buildEntityListStylingRulesLayout, buildFileChooserOptions, buildGravatarAvatarUrl, buildPropertyViewerInitialContextFromProperties, buildPropertyViewerTabsFromProperties, buildTableColumnsEditorLayout, compressImageFile, createAttachedFileProviderMenu, createZipArchive, fetchGravatarImageFile, fileListItemToFileViewerItem, fileListItemToImageFile, fileMatchesAccept, fileNameMatchesAccept, filterFileProvidersByContext, filterFilesByAcceptAndMaxSize, formatAcceptForDisplay, formatMaxFileSizeForDisplay, getFieldDefinitions, getLogicDefinition, getOperationDefinition, isPropertyBindingExpressionFormValue, isUnrestrictedFileAccept, mapFileListToViewerItems, md5Hex, mergeInfiniteScrollPage, mergeObjectsReplacingArrays, normalizeFileViewerBoundValue, normalizeSpreadsheetColumnName, notifyFileAcceptRejections, observeInfiniteScroll, pickImageFileViaFileChooser, pickProfilePhotoImageFile, preparePropertyForViewer, preparePropertyViewerTabs, provideFileChooserHooks, readSpreadsheetColumnIdentity, readSpreadsheetColumnWidth, registerFieldDefinitions, resolveChooserItemFile, resolveExcludedFileProviderKeys, resolveFileChooserAccept, resolveFileChooserExtension, resolveFileListItemUrl, resolveFileUploaderEmptyStateDescription, resolveInfiniteScrollRoot, sortUserCardActions, sortUserCardRows, spreadsheetColumnIdentityProperties, toSpreadsheetColumnWidget, validateFileChooserItems, visibleUserCardActions, withValidationsOnEditorNode };
16931
17146
  //# sourceMappingURL=acorex-platform-framework-client-layout-components.mjs.map