@acorex/platform 21.0.0-next.88 → 21.0.0-next.89

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 (52) hide show
  1. package/fesm2022/acorex-platform-auth.mjs +8 -2
  2. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-common-common-settings.provider-VfmZct9H.mjs → acorex-platform-common-common-settings.provider-DilV4dql.mjs} +15 -42
  4. package/fesm2022/acorex-platform-common-common-settings.provider-DilV4dql.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-common.mjs +3299 -3200
  6. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-core.mjs +621 -26
  8. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-layout-builder.mjs +98 -189
  10. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  11. package/fesm2022/{acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs → acorex-platform-layout-components-binding-expression-editor-popup.component-RttFwaw9.mjs} +17 -4
  12. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-RttFwaw9.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-layout-components.mjs +125 -26
  14. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  15. package/fesm2022/acorex-platform-layout-designer.mjs +4 -4
  16. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  17. package/fesm2022/acorex-platform-layout-entity-contracts.mjs +106 -12
  18. package/fesm2022/acorex-platform-layout-entity-contracts.mjs.map +1 -1
  19. package/fesm2022/acorex-platform-layout-entity.mjs +419 -147
  20. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-layout-views.mjs +851 -162
  22. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  23. package/fesm2022/acorex-platform-layout-widget-core.mjs +378 -103
  24. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  25. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-D4MOHEpI.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-CZc2zFlg.mjs} +2 -2
  26. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-D4MOHEpI.mjs.map → acorex-platform-layout-widgets-tabular-data-edit-popup.component-CZc2zFlg.mjs.map} +1 -1
  27. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-XWRUVoL4.mjs} +2 -2
  28. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs.map → acorex-platform-layout-widgets-tabular-data-view-popup.component-XWRUVoL4.mjs.map} +1 -1
  29. package/fesm2022/acorex-platform-layout-widgets.mjs +575 -239
  30. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  31. package/fesm2022/acorex-platform-themes-default.mjs +221 -24
  32. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  33. package/fesm2022/{acorex-platform-themes-shared-settings.provider-BUwPqwUS.mjs → acorex-platform-themes-shared-settings.provider-UyKdkeyk.mjs} +48 -1
  34. package/fesm2022/acorex-platform-themes-shared-settings.provider-UyKdkeyk.mjs.map +1 -0
  35. package/fesm2022/acorex-platform-themes-shared.mjs +103 -24
  36. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  37. package/package.json +1 -1
  38. package/types/acorex-platform-auth.d.ts +1 -0
  39. package/types/acorex-platform-common.d.ts +202 -151
  40. package/types/acorex-platform-core.d.ts +161 -6
  41. package/types/acorex-platform-layout-builder.d.ts +10 -20
  42. package/types/acorex-platform-layout-components.d.ts +14 -1
  43. package/types/acorex-platform-layout-entity-contracts.d.ts +27 -2
  44. package/types/acorex-platform-layout-entity.d.ts +61 -12
  45. package/types/acorex-platform-layout-views.d.ts +101 -19
  46. package/types/acorex-platform-layout-widget-core.d.ts +65 -9
  47. package/types/acorex-platform-layout-widgets.d.ts +48 -26
  48. package/types/acorex-platform-themes-default.d.ts +56 -5
  49. package/types/acorex-platform-themes-shared.d.ts +4 -0
  50. package/fesm2022/acorex-platform-common-common-settings.provider-VfmZct9H.mjs.map +0 -1
  51. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +0 -1
  52. package/fesm2022/acorex-platform-themes-shared-settings.provider-BUwPqwUS.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import * as i2 from '@angular/common';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { inject, viewChild, afterNextRender, effect, ChangeDetectionStrategy, ViewEncapsulation, Component, signal, untracked, computed, Injectable, input, output, ViewContainerRef, Directive, DestroyRef, ElementRef } from '@angular/core';
4
+ import { inject, viewChild, afterNextRender, effect, ChangeDetectionStrategy, ViewEncapsulation, Component, DestroyRef, signal, untracked, computed, InjectionToken, Injectable, input, output, ViewContainerRef, Directive, ElementRef } from '@angular/core';
5
5
  import { AXCommonModule } from '@acorex/cdk/common';
6
6
  import * as i4 from '@acorex/components/breadcrumbs';
7
7
  import { AXBreadcrumbsModule } from '@acorex/components/breadcrumbs';
@@ -12,9 +12,9 @@ import { AXDecoratorModule } from '@acorex/components/decorators';
12
12
  import * as i5 from '@acorex/components/dropdown';
13
13
  import { AXDropdownModule } from '@acorex/components/dropdown';
14
14
  import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
15
- import { AXPTabNavigationService, AXPStickyDirective, AXPCommonSettings, AXPHomePageService, AXPSettingsService, AXPTabPreviewService, AXPUnsavedChangesConfirmService, normalizeRouterUrl, AXP_HOME_TAB_KEY, axpResolveTabKey, axpIsEntityDetailsViewRoute, axpNavigateAppPath, AXPEntityCommandScope, AXPUnsavedChangesPopstateService, createUnsavedChangesCanDeactivateGuard } from '@acorex/platform/common';
15
+ import { AXPTabNavigationService, AXPStickyDirective, AXPCommonSettings, AXPHomePageService, AXPSettingsService, AXPTabPreviewService, AXPUnsavedChangesConfirmService, AXPBrowserTitleService, axpJoinTabTitleSegments, normalizeRouterUrl, AXP_HOME_TAB_KEY, axpResolveTabKey, axpIsEntityDetailsViewRoute, axpNavigateAppPath, AXPEntityCommandScope, AXPNotFoundError, AXP_NOT_FOUND_ROUTE, AXPUnsavedChangesPopstateService, AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE, createUnsavedChangesCanDeactivateGuard } from '@acorex/platform/common';
16
16
  import * as i8 from '@acorex/platform/core';
17
- import { AXPDeviceService, AXPComponentSlotModule, getSmart, AXPExpressionEvaluatorService, AXPContextEvalFactory, normalizeKeyboardShortcuts, AXPContextStore, AXPBroadcastEventService, AXPKeyboardShortcutRegistry, AXPKeyboardShortcutPriority } from '@acorex/platform/core';
17
+ import { AXPDeviceService, AXPComponentSlotModule, getSmart, AXPDebugService, OVERLAY_DETAILS_VIEW_TRACE_NS, AXPExpressionEvaluatorService, AXPContextEvalFactory, normalizeKeyboardShortcuts, AXPContextStore, AXPBroadcastEventService, AXPKeyboardShortcutRegistry, FORM_DIRTY_TRACE_NS, summarizeFormContextDirtyDiff, AXPKeyboardShortcutPriority } from '@acorex/platform/core';
18
18
  import * as i1 from '@acorex/cdk/drawer';
19
19
  import { AXDrawerDirectiveModule, AXDrawerContainerDirective } from '@acorex/cdk/drawer';
20
20
  import { AXDrawerModule } from '@acorex/components/drawer';
@@ -28,25 +28,25 @@ import { AXPWorkflowService } from '@acorex/platform/workflow';
28
28
  import { AXToastService } from '@acorex/components/toast';
29
29
  import { AXFormatService, AXFormatModule } from '@acorex/core/format';
30
30
  import { AXPSessionService } from '@acorex/platform/auth';
31
- import { Router, ActivatedRoute } from '@angular/router';
31
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
32
+ import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
32
33
  import { isEmpty, cloneDeep, get } from 'lodash-es';
34
+ import { filter } from 'rxjs/operators';
33
35
  import { AXBasePageComponent } from '@acorex/components/page';
34
- import * as i7 from '@acorex/platform/layout/widget-core';
36
+ import * as i6$1 from '@acorex/platform/layout/widget-core';
35
37
  import { AXPPageStatus, AXPWidgetContainerComponent, AXPWidgetCoreModule } from '@acorex/platform/layout/widget-core';
36
38
  import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
37
39
  import { AXBadgeModule } from '@acorex/components/badge';
38
40
  import { AXButtonGroupModule } from '@acorex/components/button-group';
39
- import * as i5$1 from '@acorex/components/loading';
40
- import { AXLoadingModule } from '@acorex/components/loading';
41
41
  import { AXMenuModule } from '@acorex/components/menu';
42
42
  import { AXSearchBoxModule } from '@acorex/components/search-box';
43
43
  import { AXDateTimeModule } from '@acorex/core/date-time';
44
44
  import { AXFileModule } from '@acorex/core/file';
45
- import * as i8$1 from '@acorex/components/form';
45
+ import * as i7 from '@acorex/components/form';
46
46
  import { AXFormModule } from '@acorex/components/form';
47
- import * as i6$1 from '@acorex/components/tabs';
47
+ import * as i5$1 from '@acorex/components/tabs';
48
48
  import { AXTabsModule } from '@acorex/components/tabs';
49
- import { Subject, takeUntil } from 'rxjs';
49
+ import { Subject, takeUntil, filter as filter$1 } from 'rxjs';
50
50
 
51
51
  class AXPPageLayoutBase {
52
52
  }
@@ -146,7 +146,7 @@ class AXPPageLayoutComponent {
146
146
  });
147
147
  }
148
148
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
149
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPPageLayoutComponent, isStandalone: true, selector: "axp-page-layout", providers: [], viewQueries: [{ propertyName: "startSideDrawer", first: true, predicate: ["startSideDrawer"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.AXDrawerContainerDirective }], ngImport: i0, template: "<!-------- Begin Start Side Drawer -------->\n<div id=\"axp-drawer-start\" [mode]=\"deviceService.isSmall() ? 'overlay' : 'push'\" [transition]=\"250\" axDrawerItem\n [backDrop]=\"true\" (onBackdropClick)=\"handleBackdropClick($event)\" #startSideDrawer=\"axDrawerItem\"\n [backdropClass]=\"'ax-bg-darkest/75'\" [collapsed]=\"deviceService.isSmall()\" drawerLocation=\"start\"\n class=\"ax-z-50 ax-h-full\">\n <ng-content select=\"axp-layout-start-side\"></ng-content>\n</div>\n<!-------- Finish Start Side Drawer -------->\n<!--------------------------------------------------------------->\n<!-------- Begin Main Layout Container -------->\n<axp-layout-container id=\"axp-page-layout\" #container>\n <!-------- Begin Page Header -------->\n <axp-layout-header id=\"axp-page-header\" *translate=\"let t\" #sticky=\"axpSticky\" [axpSticky]=\"'axp-is-sticky'\"\n [stickyOffset]=\"50\" [stickyParent]=\"container.hostElement\">\n <!-------- Begin Back Button (Mobile Only) -------->\n @if (page?.hasBackButton() && deviceService.isSmall()) {\n <ax-button id=\"axp-btn-back\" [look]=\"'blank'\" class=\"ax-sm ax-w-fit ax-ms-1\" color=\"secondary\"\n (click)=\"page?.onBackButtonClick()\" [text]=\"(page?.backButton()?.title | translate | async) ?? ''\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-chevron-left rtl:ax-rotate-180\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n <!-------- Finish Back Button -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Bar -------->\n <axp-layout-title-bar id=\"axp-title-bar\">\n <!-------- Begin Title Section -------->\n <div class=\"ax-flex ax-flex-col ax-transition ax-shrink-1 ax-min-w-0\">\n <!-------- Begin Breadcrumbs -------->\n @if (page?.hasBreadcrumbs() && !deviceService.isSmall()) {\n <ax-breadcrumbs id=\"axp-breadcrumb\" class=\"ax-mb-1\">\n @for (item of page?.breadcrumbs(); track $index) {\n <ax-breadcrumbs-item [attr.id]=\"'axp-breadcrumb-item-' + $index\" [active]=\"$last\"\n (click)=\"!$last && item.command ? execute(item.command) : null\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n {{ t(item.title) | async }}\n </ax-breadcrumbs-item>\n }\n <ng-template #divider>\n <i class=\"fa-regular fa-chevron-right rtl:ax-rotate-180 fa-sm\"></i>\n </ng-template>\n </ax-breadcrumbs>\n }\n <!-------- Finish Breadcrumbs -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Container -------->\n <div class=\"__title-container\">\n <!-------- Begin Page Title -------->\n @if (page?.hasTitle()) {\n <axp-layout-title id=\"axp-page-title\">\n @if (page?.hasTitleIcon()) {\n <ax-icon [icon]=\"page?.titleIcon()!\" class=\"ax-me-2\"></ax-icon>\n }\n {{ page?.title() | translate | async }}\n </axp-layout-title>\n }\n <!-------- Finish Page Title -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Actions -------->\n @if (page?.hasTitleActions()) {\n <ax-button id=\"axp-btn-title-actions\" [look]=\"'blank'\" class=\"ax-sm -ax-mx-2\">\n <ax-prefix>\n <i class=\"fa-solid fa-caret-down fa-fw\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of page?.titleActions(); track $index) {\n <ng-container>\n <ax-button-item [attr.id]=\"'axp-btn-title-action-' + (sub.name || $index)\"\n [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\" [disabled]=\"sub.disabled\"\n [selected]=\"sub.command?.metadata?.['isSelected']\" (onClick)=\"handleActionClick(sub)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n </ng-container>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-------- Finish Title Actions -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Status -------->\n\n @if (page?.hasStatus()) {\n <axp-status-chip [value]=\"page?.status()?.value ?? null\" [readonly]=\"page?.status()?.readonly || false\"\n [definitionKey]=\"page?.status()?.definitionKey ?? null\" [entityData]=\"getEntityData()\"\n (transitionExecuted)=\"handleStatusTransition($event)\" class=\"__title-status\"></axp-status-chip>\n }\n <!-------- Finish Page Status -------->\n\n <!-------- Begin Title Badge -------->\n @if (page?.hasBadge()) {\n <div\n id=\"axp-page-badge\"\n class=\"__title-badge --{{ page?.badge()?.color }}\"\n [attr.title]=\"page?.badge()?.description ?? page?.badge()?.title\"\n [attr.aria-label]=\"page?.badge()?.title\"\n >\n <i class=\"fa-solid fa-circle\" aria-hidden=\"true\"></i>\n <span class=\"__title-badge-label\">{{ page?.badge()?.title }}</span>\n </div>\n }\n <!-------- Finish Title Badge -------->\n\n </div>\n <!-------- Finish Title Container -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Description -------->\n @if (page?.hasDescription()) {\n <axp-layout-description id=\"axp-page-description\">\n {{ page?.description() | translate | async }}</axp-layout-description>\n }\n <!-------- Finish Page Description -------->\n </div>\n <!-------- Finish Title Section -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Actions -------->\n <axp-layout-actions id=\"axp-page-actions\" class=\"ax-shrink-0\">\n <axp-component-slot name=\"page-header-actions\"></axp-component-slot>\n <!-------- Begin Primary Actions -------->\n @if (page?.hasPrimaryActions()) {\n @for (item of page?.primaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\" [class.ax-sm]=\"deviceService.isSmall()\"\n [iconOnly]=\"deviceService.isSmall()\" [disabled]=\"item.disabled\" [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\" [color]=\"item.color\" (onClick)=\"handleActionClick(item)\">\n <ax-prefix>\n <i class=\"{{ item.icon }}\"></i>\n </ax-prefix>\n @if (item?.items) {\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of item?.items; track $index) {\n @if (sub.visible != false) {\n <ax-button-item [attr.id]=\"'axp-btn-primary-' + (item.name || item.title) + '-' + (sub.name || sub.title)\"\n [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\" [disabled]=\"sub.disabled\"\n (onClick)=\"handleActionClick(sub)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n }\n </ax-button>\n }\n }\n }\n <!-------- Finish Primary Actions -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Secondary Actions -------->\n @if (page?.hasSecondaryActions()) {\n <ax-button id=\"axp-btn-secondary\" [class.ax-sm]=\"deviceService.isSmall()\" [iconOnly]=\"deviceService.isSmall()\"\n [text]=\"'@general:terms.interface.actions' | translate | async\"\n [look]=\"deviceService.isSmall() ? 'blank' : 'solid'\" [color]=\"'default'\">\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (item of page?.secondaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button-item [attr.id]=\"'axp-btn-secondary-' + (item.name || item.title)\"\n [text]=\"(item.title | translate | async)!\" [color]=\"item.color\" [disabled]=\"item.disabled\"\n (onClick)=\"handleSecondaryActionClick(item)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-------- Finish Secondary Actions -------->\n </axp-layout-actions>\n <!-------- Finish Page Actions -------->\n </axp-layout-title-bar>\n <!-------- Finish Title Bar -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Toolbar / Navbar -------->\n @if (!sticky.isSticky) {}\n <ng-content select=\"axp-page-toolbar\"></ng-content>\n <!-------- Finish Page Toolbar / Navbar -------->\n </axp-layout-header>\n <!-------- Finish Page Header -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Content -------->\n <ng-content select=\"axp-page-content\"></ng-content>\n <!-------- Finish Page Content -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Footer -------->\n <axp-page-footer-container id=\"axp-page-footer-container\"\n [ngStyle]=\"{ display: tt.isEmpty() && prefixSlot.isEmpty() && suffixSlot.isEmpty() ? 'none' : 'block' }\">\n <axp-layout-container #tt>\n <ng-content select=\"axp-page-footer\"></ng-content>\n </axp-layout-container>\n <axp-page-footer id=\"axp-page-footer\">\n <axp-layout-prefix>\n <axp-component-slot name=\"page-footer-start\" #prefixSlot=\"slot\"></axp-component-slot>\n </axp-layout-prefix>\n <axp-layout-suffix>\n <axp-component-slot name=\"page-footer-end\" #suffixSlot=\"slot\"></axp-component-slot>\n </axp-layout-suffix>\n </axp-page-footer>\n </axp-page-footer-container>\n <!-------- Finish Page Footer -------->\n</axp-layout-container>\n<!-------- Finish Main Layout Container -------->", styles: ["@charset \"UTF-8\";.axp-status-icon{font-size:.875rem;line-height:1}.axp-status-chip{display:inline-flex}.axp-status-chip--primary{background-color:rgb(var(--ax-sys-color-primary-lighter-surface));color:rgb(var(--ax-sys-color-on-primary-lighter-surface))}.axp-status-icon--primary{color:rgb(var(--ax-sys-color-primary-dark-surface))}.axp-status-chip--secondary{background-color:rgb(var(--ax-sys-color-secondary-lighter-surface));color:rgb(var(--ax-sys-color-on-secondary-lighter-surface))}.axp-status-icon--secondary{color:rgb(var(--ax-sys-color-secondary-dark-surface))}.axp-status-chip--success{background-color:rgb(var(--ax-sys-color-success-lighter-surface));color:rgb(var(--ax-sys-color-on-success-lighter-surface))}.axp-status-icon--success{color:rgb(var(--ax-sys-color-success-dark-surface))}.axp-status-chip--warning{background-color:rgb(var(--ax-sys-color-warning-lighter-surface));color:rgb(var(--ax-sys-color-on-warning-lighter-surface))}.axp-status-icon--warning{color:rgb(var(--ax-sys-color-warning-dark-surface))}.axp-status-chip--danger{background-color:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.axp-status-icon--danger{color:rgb(var(--ax-sys-color-danger-dark-surface))}.axp-status-chip--info{background-color:rgb(var(--ax-sys-color-accent3-lighter-surface));color:rgb(var(--ax-sys-color-on-accent3-lighter-surface))}.axp-status-icon--info{color:rgb(var(--ax-sys-color-accent3-dark-surface))}.axp-status-chip--accent1{background-color:rgb(var(--ax-sys-color-accent1-lighter-surface));color:rgb(var(--ax-sys-color-on-accent1-lighter-surface))}.axp-status-icon--accent1{color:rgb(var(--ax-sys-color-accent1-dark-surface))}.axp-status-chip--accent2{background-color:rgb(var(--ax-sys-color-accent2-lighter-surface));color:rgb(var(--ax-sys-color-on-accent2-lighter-surface))}.axp-status-icon--accent2{color:rgb(var(--ax-sys-color-accent2-dark-surface))}.axp-status-chip--accent3{background-color:rgb(var(--ax-sys-color-accent3-lighter-surface));color:rgb(var(--ax-sys-color-on-accent3-lighter-surface))}.axp-status-icon--accent3{color:rgb(var(--ax-sys-color-accent3-dark-surface))}.axp-status-chip--neutral{background-color:rgb(var(--ax-sys-color-neutral-lighter-surface));color:rgb(var(--ax-sys-color-on-neutral-lighter-surface))}.axp-status-icon--neutral{color:rgb(var(--ax-sys-color-neutral-dark-surface))}axp-layout-title{display:block;width:100%;font-weight:600}axp-layout-description{display:block;width:100%;font-size:.875rem;line-height:1.25rem;opacity:.65}axp-layout-actions{display:flex;align-items:center;gap:.75rem}axp-layout-actions axp-layout-actions-primary{display:flex;align-items:center;gap:.75rem}axp-layout-footer,axp-layout-toolbar,axp-layout-header,axp-page-header,axp-page-footer,axp-page-toolbar{display:flex;width:100%;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.5rem}axp-layout-footer>axp-layout-prefix,axp-layout-footer>axp-layout-suffix,axp-layout-toolbar>axp-layout-prefix,axp-layout-toolbar>axp-layout-suffix,axp-layout-header>axp-layout-prefix,axp-layout-header>axp-layout-suffix,axp-page-header>axp-layout-prefix,axp-page-header>axp-layout-suffix,axp-page-footer>axp-layout-prefix,axp-page-footer>axp-layout-suffix,axp-page-toolbar>axp-layout-prefix,axp-page-toolbar>axp-layout-suffix{display:flex;flex-direction:row;align-items:center;gap:.5rem}axp-layout-footer>axp-layout-prefix,axp-layout-toolbar>axp-layout-prefix,axp-layout-header>axp-layout-prefix,axp-page-header>axp-layout-prefix,axp-page-footer>axp-layout-prefix,axp-page-toolbar>axp-layout-prefix{order:-9999}axp-layout-footer>axp-layout-suffix,axp-layout-toolbar>axp-layout-suffix,axp-layout-header>axp-layout-suffix,axp-page-header>axp-layout-suffix,axp-page-footer>axp-layout-suffix,axp-page-toolbar>axp-layout-suffix{order:9999;margin-inline-start:auto}axp-layout-list{display:flex;flex-direction:column}axp-layout-list>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse));border-style:dashed}axp-layout-list:focus{outline:none}axp-layout-list-group{display:flex;flex-direction:column;padding-top:.5rem;padding-bottom:.5rem}axp-layout-list-group>axp-layout-title{padding-bottom:.5rem;font-size:.875rem;line-height:1.25rem;font-weight:600}axp-layout-list-group>axp-layout-header{display:flex;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}axp-layout-list-item{margin-top:.25rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem;font-size:.875rem;line-height:1.25rem}axp-layout-list-item:focus{outline:none}axp-layout-list-item.axp-state-focused,axp-layout-list-item:hover{cursor:pointer;border-radius:.25rem;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-light-surface),var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1))}axp-layout-list-item>axp-layout-prefix{margin-inline-end:auto;display:flex;flex-direction:row;gap:.5rem}axp-layout-list-item>axp-layout-content{flex:1 1 0%}axp-layout-list-item>axp-layout-content axp-layout-description{margin-top:.25rem!important;font-size:.75rem!important;line-height:1rem!important}axp-layout-list-item>axp-layout-suffix{margin-inline-start:auto;display:flex;flex-direction:row;gap:.5rem}axp-layout-sections{display:flex;flex-direction:column;gap:1rem}axp-layout-sections axp-layout-section{display:block;border-radius:.375rem;border-width:1px;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-layout-sections axp-layout-section>axp-layout-footer,axp-layout-sections axp-layout-section>axp-layout-header{padding:.5rem 1rem}@media(min-width:1280px){axp-layout-sections axp-layout-section>axp-layout-footer,axp-layout-sections axp-layout-section>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-layout-sections axp-layout-section>axp-layout-header{display:flex;flex-direction:column;gap:0px;border-top-left-radius:.375rem;border-top-right-radius:.375rem;border-bottom-width:1px}axp-layout-sections axp-layout-section>axp-layout-header axp-layout-title{font-weight:700;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1))}axp-layout-sections axp-layout-section>axp-layout-header axp-layout-description{margin-top:.25rem;font-size:.875rem;line-height:1.25rem}axp-layout-sections axp-layout-section>axp-layout-footer{display:flex;align-items:center;justify-content:space-between;border-bottom-right-radius:.375rem;border-bottom-left-radius:.375rem;border-top-width:1px;padding:1rem}axp-layout-sections axp-layout-section>axp-layout-footer>axp-layout-suffix{margin-inline-start:auto;display:flex;gap:.5rem}axp-layout-sections axp-layout-section>axp-layout-footer{opacity:0;animation:fadeInDown .5s ease-out forwards}@keyframes fadeInDown{0%{opacity:0}to{opacity:1}}axp-page-layout{display:flex;width:100%;height:100%;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-dark-surface));color:rgb(var(--ax-sys-color-on-dark-surface));border-color:rgb(var(--ax-sys-color-border-dark-surface))}axp-page-layout axp-layout-start-side,axp-page-layout axp-layout-end-side{display:flex;min-height:100%;min-width:16rem;flex-direction:column;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout axp-layout-start-side:is(.ax-dark *),axp-page-layout axp-layout-end-side:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-darker-surface));color:rgb(var(--ax-sys-color-on-darker-surface));border-color:rgb(var(--ax-sys-color-border-darker-surface))}axp-page-layout axp-layout-start-side axp-layout-header,axp-page-layout axp-layout-end-side axp-layout-header{display:flex;flex-direction:column;gap:.5rem;padding:1rem}axp-page-layout axp-layout-start-side axp-layout-header>axp-layout-title,axp-page-layout axp-layout-end-side axp-layout-header>axp-layout-title{font-size:1.125rem;line-height:1.75rem;font-weight:500}axp-page-layout axp-layout-start-side>axp-layout-content,axp-page-layout axp-layout-end-side>axp-layout-content{flex:1 1 0%}axp-page-layout>axp-layout-container{position:relative;display:flex;width:100%;height:100%;flex-direction:column;overflow:auto}axp-page-layout>axp-layout-container>axp-layout-header{position:sticky;top:0;z-index:20;display:flex;flex-direction:column;align-items:flex-start;gap:0px;padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-dark-surface));color:rgb(var(--ax-sys-color-on-dark-surface));border-color:rgb(var(--ax-sys-color-border-dark-surface))}@media(min-width:768px){axp-page-layout>axp-layout-container>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-page-layout>axp-layout-container>axp-layout-header.axp-is-sticky{--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-border-opacity, 1));--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-page-layout>axp-layout-container>axp-layout-header ax-breadcrumbs ax-breadcrumbs-item{font-size:.75rem;line-height:1rem}axp-page-layout>axp-layout-container>axp-layout-header ax-breadcrumbs ax-breadcrumbs-item.ax-state-active .ax-breadcrumb-item-content{cursor:default;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1));opacity:.75}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar{display:flex;width:100%;align-items:center;justify-content:space-between;padding-left:1rem;padding-right:1rem}@media(min-width:1280px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar{border-width:0px}}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar ax-layout-nav-button{display:flex;align-items:center;justify-content:space-between}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container{display:flex;align-items:baseline;gap:.75rem}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container axp-layout-title{display:inline-block;width:fit-content;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1.25rem;line-height:1.75rem;font-weight:500;line-height:1}@media(min-width:1024px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container axp-layout-title{font-size:1.5rem;line-height:2rem}}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge{display:inline-flex;--tw-translate-y: -3px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));align-items:center;align-self:baseline;border-radius:.375rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:600;line-height:1}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge i{margin-inline-end:.25rem;line-height:1;font-size:.5rem}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--warning{background-color:rgb(var(--ax-sys-color-warning-lightest-surface));color:rgb(var(--ax-sys-color-on-warning-lightest-surface));border-color:rgb(var(--ax-sys-color-border-warning-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--warning i{color:rgb(var(--ax-sys-color-warning-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--danger{background-color:rgb(var(--ax-sys-color-danger-lightest-surface));color:rgb(var(--ax-sys-color-on-danger-lightest-surface));border-color:rgb(var(--ax-sys-color-border-danger-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--danger i{color:rgb(var(--ax-sys-color-danger-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--success{background-color:rgb(var(--ax-sys-color-success-lightest-surface));color:rgb(var(--ax-sys-color-on-success-lightest-surface));border-color:rgb(var(--ax-sys-color-border-success-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--success i{color:rgb(var(--ax-sys-color-success-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--primary{background-color:rgb(var(--ax-sys-color-primary-lightest-surface));color:rgb(var(--ax-sys-color-on-primary-lightest-surface));border-color:rgb(var(--ax-sys-color-border-primary-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--primary i{color:rgb(var(--ax-sys-color-primary-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--secondary i{color:rgb(var(--ax-sys-color-secondary-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--default i{color:rgb(var(--ax-sys-color-on-surface)/.45)}@media(max-width:600px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge{--tw-translate-y: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));background-color:transparent;padding:0;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge .__title-badge-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge i{margin:0;font-size:.625rem}}axp-page-layout>axp-layout-container>axp-layout-header axp-page-toolbar{margin-top:.5rem;padding-left:1rem;padding-right:1rem}axp-page-layout>axp-layout-container>axp-page-content{display:flex;width:100%;flex:1 1 0%;flex-direction:column;padding:.75rem 1rem}axp-page-layout>axp-layout-container>axp-page-content.--scrollable{padding-bottom:1rem}axp-page-layout>axp-layout-container>axp-page-footer-container{border-top-width:1px;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout>axp-layout-container>axp-page-footer-container:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axp-page-layout>axp-layout-container>axp-page-footer-container{position:sticky;bottom:0;z-index:20;padding:.75rem;--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}@keyframes ax-fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}axp-page-layout>axp-layout-container>axp-page-footer-container.--animated{animation:1s both ax-fadeInUp;transition-duration:.3s;transition-timing-function:cubic-bezier(0,0,.2,1);animation-duration:.3s;animation-timing-function:cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type:
149
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPPageLayoutComponent, isStandalone: true, selector: "axp-page-layout", providers: [], viewQueries: [{ propertyName: "startSideDrawer", first: true, predicate: ["startSideDrawer"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.AXDrawerContainerDirective }], ngImport: i0, template: "<!-------- Begin Start Side Drawer -------->\n<div id=\"axp-drawer-start\" [mode]=\"deviceService.isSmall() ? 'overlay' : 'push'\" [transition]=\"250\" axDrawerItem\n [backDrop]=\"true\" (onBackdropClick)=\"handleBackdropClick($event)\" #startSideDrawer=\"axDrawerItem\"\n [backdropClass]=\"'ax-bg-darkest/75'\" [collapsed]=\"deviceService.isSmall()\" drawerLocation=\"start\" class=\"ax-h-full\">\n <ng-content select=\"axp-layout-start-side\"></ng-content>\n</div>\n<!-------- Finish Start Side Drawer -------->\n<!--------------------------------------------------------------->\n<!-------- Begin Main Layout Container -------->\n<axp-layout-container id=\"axp-page-layout\" #container>\n <!-------- Begin Page Header -------->\n <axp-layout-header id=\"axp-page-header\" *translate=\"let t\" #sticky=\"axpSticky\" [axpSticky]=\"'axp-is-sticky'\"\n [stickyOffset]=\"50\" [stickyParent]=\"container.hostElement\">\n <!-------- Begin Back Button (Mobile Only) -------->\n @if (page?.hasBackButton() && deviceService.isSmall()) {\n <ax-button id=\"axp-btn-back\" [look]=\"'blank'\" class=\"ax-sm ax-w-fit ax-ms-1\" color=\"secondary\"\n (click)=\"page?.onBackButtonClick()\" [text]=\"(page?.backButton()?.title | translate | async) ?? ''\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-chevron-left rtl:ax-rotate-180\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n <!-------- Finish Back Button -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Bar -------->\n <axp-layout-title-bar id=\"axp-title-bar\">\n <!-------- Begin Title Section -------->\n <div class=\"ax-flex ax-flex-col ax-transition ax-shrink-1 ax-min-w-0\">\n <!-------- Begin Breadcrumbs -------->\n @if (page?.hasBreadcrumbs() && !deviceService.isSmall()) {\n <ax-breadcrumbs id=\"axp-breadcrumb\" class=\"ax-mb-1\">\n @for (item of page?.breadcrumbs(); track $index) {\n <ax-breadcrumbs-item [attr.id]=\"'axp-breadcrumb-item-' + $index\" [active]=\"$last\"\n (click)=\"!$last && item.command ? execute(item.command) : null\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n {{ t(item.title) | async }}\n </ax-breadcrumbs-item>\n }\n <ng-template #divider>\n <i class=\"fa-regular fa-chevron-right rtl:ax-rotate-180 fa-sm\"></i>\n </ng-template>\n </ax-breadcrumbs>\n }\n <!-------- Finish Breadcrumbs -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Container -------->\n <div class=\"__title-container\">\n <!-------- Begin Page Title -------->\n @if (page?.hasTitle()) {\n <axp-layout-title id=\"axp-page-title\">\n @if (page?.hasTitleIcon()) {\n <ax-icon [icon]=\"page?.titleIcon()!\" class=\"ax-me-2\"></ax-icon>\n }\n {{ page?.title() | translate | async }}\n </axp-layout-title>\n }\n <!-------- Finish Page Title -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Actions -------->\n @if (page?.hasTitleActions()) {\n <ax-button id=\"axp-btn-title-actions\" [look]=\"'blank'\" class=\"ax-sm -ax-mx-2\">\n <ax-prefix>\n <i class=\"fa-solid fa-caret-down fa-fw\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of page?.titleActions(); track $index) {\n <ng-container>\n <ax-button-item [attr.id]=\"'axp-btn-title-action-' + (sub.name || $index)\"\n [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\" [disabled]=\"sub.disabled\"\n [selected]=\"sub.command?.metadata?.['isSelected']\" (onClick)=\"handleActionClick(sub)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n </ng-container>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-------- Finish Title Actions -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Status -------->\n\n @if (page?.hasStatus()) {\n <axp-status-chip [value]=\"page?.status()?.value ?? null\" [readonly]=\"page?.status()?.readonly || false\"\n [definitionKey]=\"page?.status()?.definitionKey ?? null\" [entityData]=\"getEntityData()\"\n (transitionExecuted)=\"handleStatusTransition($event)\" class=\"__title-status\"></axp-status-chip>\n }\n <!-------- Finish Page Status -------->\n\n <!-------- Begin Title Badge -------->\n @if (page?.hasBadge()) {\n <div id=\"axp-page-badge\" class=\"__title-badge --{{ page?.badge()?.color }}\"\n [attr.title]=\"page?.badge()?.description ?? page?.badge()?.title\" [attr.aria-label]=\"page?.badge()?.title\">\n <i class=\"fa-solid fa-circle\" aria-hidden=\"true\"></i>\n <span class=\"__title-badge-label\">{{ page?.badge()?.title }}</span>\n </div>\n }\n <!-------- Finish Title Badge -------->\n\n </div>\n <!-------- Finish Title Container -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Description -------->\n @if (page?.hasDescription()) {\n <axp-layout-description id=\"axp-page-description\">\n {{ page?.description() | translate | async }}</axp-layout-description>\n }\n <!-------- Finish Page Description -------->\n </div>\n <!-------- Finish Title Section -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Actions -------->\n <axp-layout-actions id=\"axp-page-actions\" class=\"ax-shrink-0\">\n <axp-component-slot name=\"page-header-actions\"></axp-component-slot>\n <!-------- Begin Primary Actions -------->\n @if (page?.hasPrimaryActions()) {\n @for (item of page?.primaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\" [class.ax-sm]=\"deviceService.isSmall()\"\n [iconOnly]=\"deviceService.isSmall()\" [disabled]=\"item.disabled\" [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\" [color]=\"item.color\" (onClick)=\"handleActionClick(item)\">\n <ax-prefix>\n <i class=\"{{ item.icon }}\"></i>\n </ax-prefix>\n @if (item?.items) {\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of item?.items; track $index) {\n @if (sub.visible != false) {\n <ax-button-item [attr.id]=\"'axp-btn-primary-' + (item.name || item.title) + '-' + (sub.name || sub.title)\"\n [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\" [disabled]=\"sub.disabled\"\n (onClick)=\"handleActionClick(sub)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n }\n </ax-button>\n }\n }\n }\n <!-------- Finish Primary Actions -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Secondary Actions -------->\n @if (page?.hasSecondaryActions()) {\n <ax-button id=\"axp-btn-secondary\" [class.ax-sm]=\"deviceService.isSmall()\" [iconOnly]=\"deviceService.isSmall()\"\n [text]=\"'@general:terms.interface.actions' | translate | async\"\n [look]=\"deviceService.isSmall() ? 'blank' : 'solid'\" [color]=\"'default'\">\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (item of page?.secondaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button-item [attr.id]=\"'axp-btn-secondary-' + (item.name || item.title)\"\n [text]=\"(item.title | translate | async)!\" [color]=\"item.color\" [disabled]=\"item.disabled\"\n (onClick)=\"handleSecondaryActionClick(item)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-------- Finish Secondary Actions -------->\n </axp-layout-actions>\n <!-------- Finish Page Actions -------->\n </axp-layout-title-bar>\n <!-------- Finish Title Bar -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Toolbar / Navbar -------->\n @if (!sticky.isSticky) {}\n <ng-content select=\"axp-page-toolbar\"></ng-content>\n <!-------- Finish Page Toolbar / Navbar -------->\n </axp-layout-header>\n <!-------- Finish Page Header -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Content -------->\n <ng-content select=\"axp-page-content\"></ng-content>\n <!-------- Finish Page Content -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Footer -------->\n <axp-page-footer-container id=\"axp-page-footer-container\"\n [ngStyle]=\"{ display: tt.isEmpty() && prefixSlot.isEmpty() && suffixSlot.isEmpty() ? 'none' : 'block' }\">\n <axp-layout-container #tt>\n <ng-content select=\"axp-page-footer\"></ng-content>\n </axp-layout-container>\n <axp-page-footer id=\"axp-page-footer\">\n <axp-layout-prefix>\n <axp-component-slot name=\"page-footer-start\" #prefixSlot=\"slot\"></axp-component-slot>\n </axp-layout-prefix>\n <axp-layout-suffix>\n <axp-component-slot name=\"page-footer-end\" #suffixSlot=\"slot\"></axp-component-slot>\n </axp-layout-suffix>\n </axp-page-footer>\n </axp-page-footer-container>\n <!-------- Finish Page Footer -------->\n</axp-layout-container>\n<!-------- Finish Main Layout Container -------->", styles: ["@charset \"UTF-8\";.axp-status-icon{font-size:.875rem;line-height:1}.axp-status-chip{display:inline-flex}.axp-status-chip--primary{background-color:rgb(var(--ax-sys-color-primary-lighter-surface));color:rgb(var(--ax-sys-color-on-primary-lighter-surface))}.axp-status-icon--primary{color:rgb(var(--ax-sys-color-primary-dark-surface))}.axp-status-chip--secondary{background-color:rgb(var(--ax-sys-color-secondary-lighter-surface));color:rgb(var(--ax-sys-color-on-secondary-lighter-surface))}.axp-status-icon--secondary{color:rgb(var(--ax-sys-color-secondary-dark-surface))}.axp-status-chip--success{background-color:rgb(var(--ax-sys-color-success-lighter-surface));color:rgb(var(--ax-sys-color-on-success-lighter-surface))}.axp-status-icon--success{color:rgb(var(--ax-sys-color-success-dark-surface))}.axp-status-chip--warning{background-color:rgb(var(--ax-sys-color-warning-lighter-surface));color:rgb(var(--ax-sys-color-on-warning-lighter-surface))}.axp-status-icon--warning{color:rgb(var(--ax-sys-color-warning-dark-surface))}.axp-status-chip--danger{background-color:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.axp-status-icon--danger{color:rgb(var(--ax-sys-color-danger-dark-surface))}.axp-status-chip--info{background-color:rgb(var(--ax-sys-color-accent3-lighter-surface));color:rgb(var(--ax-sys-color-on-accent3-lighter-surface))}.axp-status-icon--info{color:rgb(var(--ax-sys-color-accent3-dark-surface))}.axp-status-chip--accent1{background-color:rgb(var(--ax-sys-color-accent1-lighter-surface));color:rgb(var(--ax-sys-color-on-accent1-lighter-surface))}.axp-status-icon--accent1{color:rgb(var(--ax-sys-color-accent1-dark-surface))}.axp-status-chip--accent2{background-color:rgb(var(--ax-sys-color-accent2-lighter-surface));color:rgb(var(--ax-sys-color-on-accent2-lighter-surface))}.axp-status-icon--accent2{color:rgb(var(--ax-sys-color-accent2-dark-surface))}.axp-status-chip--accent3{background-color:rgb(var(--ax-sys-color-accent3-lighter-surface));color:rgb(var(--ax-sys-color-on-accent3-lighter-surface))}.axp-status-icon--accent3{color:rgb(var(--ax-sys-color-accent3-dark-surface))}.axp-status-chip--neutral{background-color:rgb(var(--ax-sys-color-neutral-lighter-surface));color:rgb(var(--ax-sys-color-on-neutral-lighter-surface))}.axp-status-icon--neutral{color:rgb(var(--ax-sys-color-neutral-dark-surface))}axp-layout-title{display:block;width:100%;font-weight:600}axp-layout-description{display:block;width:100%;font-size:.875rem;line-height:1.25rem;opacity:.65}axp-layout-actions{display:flex;align-items:center;gap:.75rem}axp-layout-actions axp-layout-actions-primary{display:flex;align-items:center;gap:.75rem}axp-layout-footer,axp-layout-toolbar,axp-layout-header,axp-page-header,axp-page-footer,axp-page-toolbar{display:flex;width:100%;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.5rem}axp-layout-footer>axp-layout-prefix,axp-layout-footer>axp-layout-suffix,axp-layout-toolbar>axp-layout-prefix,axp-layout-toolbar>axp-layout-suffix,axp-layout-header>axp-layout-prefix,axp-layout-header>axp-layout-suffix,axp-page-header>axp-layout-prefix,axp-page-header>axp-layout-suffix,axp-page-footer>axp-layout-prefix,axp-page-footer>axp-layout-suffix,axp-page-toolbar>axp-layout-prefix,axp-page-toolbar>axp-layout-suffix{display:flex;flex-direction:row;align-items:center;gap:.5rem}axp-layout-footer>axp-layout-prefix,axp-layout-toolbar>axp-layout-prefix,axp-layout-header>axp-layout-prefix,axp-page-header>axp-layout-prefix,axp-page-footer>axp-layout-prefix,axp-page-toolbar>axp-layout-prefix{order:-9999}axp-layout-footer>axp-layout-suffix,axp-layout-toolbar>axp-layout-suffix,axp-layout-header>axp-layout-suffix,axp-page-header>axp-layout-suffix,axp-page-footer>axp-layout-suffix,axp-page-toolbar>axp-layout-suffix{order:9999;margin-inline-start:auto}axp-layout-list{display:flex;flex-direction:column}axp-layout-list>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse));border-style:dashed}axp-layout-list:focus{outline:none}axp-layout-list-group{display:flex;flex-direction:column;padding-top:.5rem;padding-bottom:.5rem}axp-layout-list-group>axp-layout-title{padding-bottom:.5rem;font-size:.875rem;line-height:1.25rem;font-weight:600}axp-layout-list-group>axp-layout-header{display:flex;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}axp-layout-list-item{margin-top:.25rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem;font-size:.875rem;line-height:1.25rem}axp-layout-list-item:focus{outline:none}axp-layout-list-item.axp-state-focused,axp-layout-list-item:hover{cursor:pointer;border-radius:.25rem;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-light-surface),var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1))}axp-layout-list-item>axp-layout-prefix{margin-inline-end:auto;display:flex;flex-direction:row;gap:.5rem}axp-layout-list-item>axp-layout-content{flex:1 1 0%}axp-layout-list-item>axp-layout-content axp-layout-description{margin-top:.25rem!important;font-size:.75rem!important;line-height:1rem!important}axp-layout-list-item>axp-layout-suffix{margin-inline-start:auto;display:flex;flex-direction:row;gap:.5rem}axp-layout-sections{display:flex;flex-direction:column;gap:1rem}axp-layout-sections axp-layout-section{display:block;border-radius:.375rem;border-width:1px;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-layout-sections axp-layout-section>axp-layout-footer,axp-layout-sections axp-layout-section>axp-layout-header{padding:.5rem 1rem}@media(min-width:1280px){axp-layout-sections axp-layout-section>axp-layout-footer,axp-layout-sections axp-layout-section>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-layout-sections axp-layout-section>axp-layout-header{display:flex;flex-direction:column;gap:0px;border-top-left-radius:.375rem;border-top-right-radius:.375rem;border-bottom-width:1px}axp-layout-sections axp-layout-section>axp-layout-header axp-layout-title{font-weight:700;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1))}axp-layout-sections axp-layout-section>axp-layout-header axp-layout-description{margin-top:.25rem;font-size:.875rem;line-height:1.25rem}axp-layout-sections axp-layout-section>axp-layout-footer{display:flex;align-items:center;justify-content:space-between;border-bottom-right-radius:.375rem;border-bottom-left-radius:.375rem;border-top-width:1px;padding:1rem}axp-layout-sections axp-layout-section>axp-layout-footer>axp-layout-suffix{margin-inline-start:auto;display:flex;gap:.5rem}axp-layout-sections axp-layout-section>axp-layout-footer{opacity:0;animation:fadeInDown .5s ease-out forwards}@keyframes fadeInDown{0%{opacity:0}to{opacity:1}}axp-page-layout{display:flex;width:100%;height:100%;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-dark-surface));color:rgb(var(--ax-sys-color-on-dark-surface));border-color:rgb(var(--ax-sys-color-border-dark-surface))}axp-page-layout axp-layout-start-side,axp-page-layout axp-layout-end-side{display:flex;min-height:100%;min-width:16rem;flex-direction:column;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout axp-layout-start-side:is(.ax-dark *),axp-page-layout axp-layout-end-side:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-darker-surface));color:rgb(var(--ax-sys-color-on-darker-surface));border-color:rgb(var(--ax-sys-color-border-darker-surface))}axp-page-layout axp-layout-start-side axp-layout-header,axp-page-layout axp-layout-end-side axp-layout-header{display:flex;flex-direction:column;gap:.5rem;padding:1rem}axp-page-layout axp-layout-start-side axp-layout-header>axp-layout-title,axp-page-layout axp-layout-end-side axp-layout-header>axp-layout-title{font-size:1.125rem;line-height:1.75rem;font-weight:500}axp-page-layout axp-layout-start-side>axp-layout-content,axp-page-layout axp-layout-end-side>axp-layout-content{flex:1 1 0%}axp-page-layout>axp-layout-container{position:relative;display:flex;width:100%;height:100%;flex-direction:column;overflow:auto}axp-page-layout>axp-layout-container>axp-layout-header{position:sticky;top:0;z-index:20;display:flex;flex-direction:column;align-items:flex-start;gap:0px;padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-dark-surface));color:rgb(var(--ax-sys-color-on-dark-surface));border-color:rgb(var(--ax-sys-color-border-dark-surface))}@media(min-width:768px){axp-page-layout>axp-layout-container>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-page-layout>axp-layout-container>axp-layout-header.axp-is-sticky{--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-border-opacity, 1));--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-page-layout>axp-layout-container>axp-layout-header ax-breadcrumbs ax-breadcrumbs-item{font-size:.75rem;line-height:1rem}axp-page-layout>axp-layout-container>axp-layout-header ax-breadcrumbs ax-breadcrumbs-item.ax-state-active .ax-breadcrumb-item-content{cursor:default;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1));opacity:.75}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar{display:flex;width:100%;align-items:center;justify-content:space-between;padding-left:1rem;padding-right:1rem}@media(min-width:1280px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar{border-width:0px}}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar ax-layout-nav-button{display:flex;align-items:center;justify-content:space-between}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container{display:flex;align-items:baseline;gap:.75rem}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container axp-layout-title{display:inline-block;width:fit-content;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1.25rem;line-height:1.75rem;font-weight:500;line-height:1}@media(min-width:1024px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container axp-layout-title{font-size:1.5rem;line-height:2rem}}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge{display:inline-flex;--tw-translate-y: -3px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));align-items:center;align-self:baseline;border-radius:.375rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:600;line-height:1}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge i{margin-inline-end:.25rem;line-height:1;font-size:.5rem}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--warning{background-color:rgb(var(--ax-sys-color-warning-lightest-surface));color:rgb(var(--ax-sys-color-on-warning-lightest-surface));border-color:rgb(var(--ax-sys-color-border-warning-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--warning i{color:rgb(var(--ax-sys-color-warning-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--danger{background-color:rgb(var(--ax-sys-color-danger-lightest-surface));color:rgb(var(--ax-sys-color-on-danger-lightest-surface));border-color:rgb(var(--ax-sys-color-border-danger-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--danger i{color:rgb(var(--ax-sys-color-danger-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--success{background-color:rgb(var(--ax-sys-color-success-lightest-surface));color:rgb(var(--ax-sys-color-on-success-lightest-surface));border-color:rgb(var(--ax-sys-color-border-success-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--success i{color:rgb(var(--ax-sys-color-success-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--primary{background-color:rgb(var(--ax-sys-color-primary-lightest-surface));color:rgb(var(--ax-sys-color-on-primary-lightest-surface));border-color:rgb(var(--ax-sys-color-border-primary-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--primary i{color:rgb(var(--ax-sys-color-primary-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--secondary i{color:rgb(var(--ax-sys-color-secondary-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--default i{color:rgb(var(--ax-sys-color-on-surface)/.45)}@media(max-width:600px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge{--tw-translate-y: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));background-color:transparent;padding:0;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge .__title-badge-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge i{margin:0;font-size:.625rem}}axp-page-layout>axp-layout-container>axp-layout-header axp-page-toolbar{margin-top:.5rem;padding-left:1rem;padding-right:1rem}axp-page-layout>axp-layout-container>axp-page-content{display:flex;width:100%;flex:1 1 0%;flex-direction:column;padding:.75rem 1rem}axp-page-layout>axp-layout-container>axp-page-content.--scrollable{padding-bottom:1rem}axp-page-layout>axp-layout-container>axp-page-footer-container{border-top-width:1px;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout>axp-layout-container>axp-page-footer-container:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axp-page-layout>axp-layout-container>axp-page-footer-container{position:sticky;bottom:0;z-index:20;padding:.75rem;--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}@keyframes ax-fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}axp-page-layout>axp-layout-container>axp-page-footer-container.--animated{animation:1s both ax-fadeInUp;transition-duration:.3s;transition-timing-function:cubic-bezier(0,0,.2,1);animation-duration:.3s;animation-timing-function:cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type:
150
150
  //
151
151
  AXCommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.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: AXBreadcrumbsModule }, { kind: "component", type: i4.AXBreadCrumbsComponent, selector: "ax-breadcrumbs" }, { kind: "component", type: i4.AXBreadCrumbsItemComponent, selector: "ax-breadcrumbs-item", inputs: ["disabled", "active"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i5.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i6.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i6.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i6.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i3$1.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXDrawerModule }, { kind: "ngmodule", type: AXDrawerDirectiveModule }, { kind: "directive", type: i1.AXDrawerItemDirective, selector: "[axDrawerItem]", inputs: ["location", "collapsed", "backDrop", "mode", "transition", "closeOnBackdropClick", "backdropClass", "singleOpenMode"], outputs: ["collapseStateChanged", "locationChange", "collapsedChange", "backDropChange", "modeChange", "transitionChange", "closeOnBackdropClickChange", "backdropClassChange", "onBackdropClick", "singleOpenModeChange"], exportAs: ["axDrawerItem"] }, { kind: "ngmodule", type:
152
152
  //
@@ -174,7 +174,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
174
174
  AXPStickyDirective,
175
175
  AXPThemeLayoutContainerComponent,
176
176
  AXPStatusChipComponent,
177
- ], selector: 'axp-page-layout', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [AXDrawerContainerDirective], providers: [], template: "<!-------- Begin Start Side Drawer -------->\n<div id=\"axp-drawer-start\" [mode]=\"deviceService.isSmall() ? 'overlay' : 'push'\" [transition]=\"250\" axDrawerItem\n [backDrop]=\"true\" (onBackdropClick)=\"handleBackdropClick($event)\" #startSideDrawer=\"axDrawerItem\"\n [backdropClass]=\"'ax-bg-darkest/75'\" [collapsed]=\"deviceService.isSmall()\" drawerLocation=\"start\"\n class=\"ax-z-50 ax-h-full\">\n <ng-content select=\"axp-layout-start-side\"></ng-content>\n</div>\n<!-------- Finish Start Side Drawer -------->\n<!--------------------------------------------------------------->\n<!-------- Begin Main Layout Container -------->\n<axp-layout-container id=\"axp-page-layout\" #container>\n <!-------- Begin Page Header -------->\n <axp-layout-header id=\"axp-page-header\" *translate=\"let t\" #sticky=\"axpSticky\" [axpSticky]=\"'axp-is-sticky'\"\n [stickyOffset]=\"50\" [stickyParent]=\"container.hostElement\">\n <!-------- Begin Back Button (Mobile Only) -------->\n @if (page?.hasBackButton() && deviceService.isSmall()) {\n <ax-button id=\"axp-btn-back\" [look]=\"'blank'\" class=\"ax-sm ax-w-fit ax-ms-1\" color=\"secondary\"\n (click)=\"page?.onBackButtonClick()\" [text]=\"(page?.backButton()?.title | translate | async) ?? ''\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-chevron-left rtl:ax-rotate-180\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n <!-------- Finish Back Button -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Bar -------->\n <axp-layout-title-bar id=\"axp-title-bar\">\n <!-------- Begin Title Section -------->\n <div class=\"ax-flex ax-flex-col ax-transition ax-shrink-1 ax-min-w-0\">\n <!-------- Begin Breadcrumbs -------->\n @if (page?.hasBreadcrumbs() && !deviceService.isSmall()) {\n <ax-breadcrumbs id=\"axp-breadcrumb\" class=\"ax-mb-1\">\n @for (item of page?.breadcrumbs(); track $index) {\n <ax-breadcrumbs-item [attr.id]=\"'axp-breadcrumb-item-' + $index\" [active]=\"$last\"\n (click)=\"!$last && item.command ? execute(item.command) : null\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n {{ t(item.title) | async }}\n </ax-breadcrumbs-item>\n }\n <ng-template #divider>\n <i class=\"fa-regular fa-chevron-right rtl:ax-rotate-180 fa-sm\"></i>\n </ng-template>\n </ax-breadcrumbs>\n }\n <!-------- Finish Breadcrumbs -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Container -------->\n <div class=\"__title-container\">\n <!-------- Begin Page Title -------->\n @if (page?.hasTitle()) {\n <axp-layout-title id=\"axp-page-title\">\n @if (page?.hasTitleIcon()) {\n <ax-icon [icon]=\"page?.titleIcon()!\" class=\"ax-me-2\"></ax-icon>\n }\n {{ page?.title() | translate | async }}\n </axp-layout-title>\n }\n <!-------- Finish Page Title -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Actions -------->\n @if (page?.hasTitleActions()) {\n <ax-button id=\"axp-btn-title-actions\" [look]=\"'blank'\" class=\"ax-sm -ax-mx-2\">\n <ax-prefix>\n <i class=\"fa-solid fa-caret-down fa-fw\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of page?.titleActions(); track $index) {\n <ng-container>\n <ax-button-item [attr.id]=\"'axp-btn-title-action-' + (sub.name || $index)\"\n [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\" [disabled]=\"sub.disabled\"\n [selected]=\"sub.command?.metadata?.['isSelected']\" (onClick)=\"handleActionClick(sub)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n </ng-container>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-------- Finish Title Actions -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Status -------->\n\n @if (page?.hasStatus()) {\n <axp-status-chip [value]=\"page?.status()?.value ?? null\" [readonly]=\"page?.status()?.readonly || false\"\n [definitionKey]=\"page?.status()?.definitionKey ?? null\" [entityData]=\"getEntityData()\"\n (transitionExecuted)=\"handleStatusTransition($event)\" class=\"__title-status\"></axp-status-chip>\n }\n <!-------- Finish Page Status -------->\n\n <!-------- Begin Title Badge -------->\n @if (page?.hasBadge()) {\n <div\n id=\"axp-page-badge\"\n class=\"__title-badge --{{ page?.badge()?.color }}\"\n [attr.title]=\"page?.badge()?.description ?? page?.badge()?.title\"\n [attr.aria-label]=\"page?.badge()?.title\"\n >\n <i class=\"fa-solid fa-circle\" aria-hidden=\"true\"></i>\n <span class=\"__title-badge-label\">{{ page?.badge()?.title }}</span>\n </div>\n }\n <!-------- Finish Title Badge -------->\n\n </div>\n <!-------- Finish Title Container -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Description -------->\n @if (page?.hasDescription()) {\n <axp-layout-description id=\"axp-page-description\">\n {{ page?.description() | translate | async }}</axp-layout-description>\n }\n <!-------- Finish Page Description -------->\n </div>\n <!-------- Finish Title Section -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Actions -------->\n <axp-layout-actions id=\"axp-page-actions\" class=\"ax-shrink-0\">\n <axp-component-slot name=\"page-header-actions\"></axp-component-slot>\n <!-------- Begin Primary Actions -------->\n @if (page?.hasPrimaryActions()) {\n @for (item of page?.primaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\" [class.ax-sm]=\"deviceService.isSmall()\"\n [iconOnly]=\"deviceService.isSmall()\" [disabled]=\"item.disabled\" [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\" [color]=\"item.color\" (onClick)=\"handleActionClick(item)\">\n <ax-prefix>\n <i class=\"{{ item.icon }}\"></i>\n </ax-prefix>\n @if (item?.items) {\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of item?.items; track $index) {\n @if (sub.visible != false) {\n <ax-button-item [attr.id]=\"'axp-btn-primary-' + (item.name || item.title) + '-' + (sub.name || sub.title)\"\n [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\" [disabled]=\"sub.disabled\"\n (onClick)=\"handleActionClick(sub)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n }\n </ax-button>\n }\n }\n }\n <!-------- Finish Primary Actions -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Secondary Actions -------->\n @if (page?.hasSecondaryActions()) {\n <ax-button id=\"axp-btn-secondary\" [class.ax-sm]=\"deviceService.isSmall()\" [iconOnly]=\"deviceService.isSmall()\"\n [text]=\"'@general:terms.interface.actions' | translate | async\"\n [look]=\"deviceService.isSmall() ? 'blank' : 'solid'\" [color]=\"'default'\">\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (item of page?.secondaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button-item [attr.id]=\"'axp-btn-secondary-' + (item.name || item.title)\"\n [text]=\"(item.title | translate | async)!\" [color]=\"item.color\" [disabled]=\"item.disabled\"\n (onClick)=\"handleSecondaryActionClick(item)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-------- Finish Secondary Actions -------->\n </axp-layout-actions>\n <!-------- Finish Page Actions -------->\n </axp-layout-title-bar>\n <!-------- Finish Title Bar -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Toolbar / Navbar -------->\n @if (!sticky.isSticky) {}\n <ng-content select=\"axp-page-toolbar\"></ng-content>\n <!-------- Finish Page Toolbar / Navbar -------->\n </axp-layout-header>\n <!-------- Finish Page Header -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Content -------->\n <ng-content select=\"axp-page-content\"></ng-content>\n <!-------- Finish Page Content -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Footer -------->\n <axp-page-footer-container id=\"axp-page-footer-container\"\n [ngStyle]=\"{ display: tt.isEmpty() && prefixSlot.isEmpty() && suffixSlot.isEmpty() ? 'none' : 'block' }\">\n <axp-layout-container #tt>\n <ng-content select=\"axp-page-footer\"></ng-content>\n </axp-layout-container>\n <axp-page-footer id=\"axp-page-footer\">\n <axp-layout-prefix>\n <axp-component-slot name=\"page-footer-start\" #prefixSlot=\"slot\"></axp-component-slot>\n </axp-layout-prefix>\n <axp-layout-suffix>\n <axp-component-slot name=\"page-footer-end\" #suffixSlot=\"slot\"></axp-component-slot>\n </axp-layout-suffix>\n </axp-page-footer>\n </axp-page-footer-container>\n <!-------- Finish Page Footer -------->\n</axp-layout-container>\n<!-------- Finish Main Layout Container -------->", styles: ["@charset \"UTF-8\";.axp-status-icon{font-size:.875rem;line-height:1}.axp-status-chip{display:inline-flex}.axp-status-chip--primary{background-color:rgb(var(--ax-sys-color-primary-lighter-surface));color:rgb(var(--ax-sys-color-on-primary-lighter-surface))}.axp-status-icon--primary{color:rgb(var(--ax-sys-color-primary-dark-surface))}.axp-status-chip--secondary{background-color:rgb(var(--ax-sys-color-secondary-lighter-surface));color:rgb(var(--ax-sys-color-on-secondary-lighter-surface))}.axp-status-icon--secondary{color:rgb(var(--ax-sys-color-secondary-dark-surface))}.axp-status-chip--success{background-color:rgb(var(--ax-sys-color-success-lighter-surface));color:rgb(var(--ax-sys-color-on-success-lighter-surface))}.axp-status-icon--success{color:rgb(var(--ax-sys-color-success-dark-surface))}.axp-status-chip--warning{background-color:rgb(var(--ax-sys-color-warning-lighter-surface));color:rgb(var(--ax-sys-color-on-warning-lighter-surface))}.axp-status-icon--warning{color:rgb(var(--ax-sys-color-warning-dark-surface))}.axp-status-chip--danger{background-color:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.axp-status-icon--danger{color:rgb(var(--ax-sys-color-danger-dark-surface))}.axp-status-chip--info{background-color:rgb(var(--ax-sys-color-accent3-lighter-surface));color:rgb(var(--ax-sys-color-on-accent3-lighter-surface))}.axp-status-icon--info{color:rgb(var(--ax-sys-color-accent3-dark-surface))}.axp-status-chip--accent1{background-color:rgb(var(--ax-sys-color-accent1-lighter-surface));color:rgb(var(--ax-sys-color-on-accent1-lighter-surface))}.axp-status-icon--accent1{color:rgb(var(--ax-sys-color-accent1-dark-surface))}.axp-status-chip--accent2{background-color:rgb(var(--ax-sys-color-accent2-lighter-surface));color:rgb(var(--ax-sys-color-on-accent2-lighter-surface))}.axp-status-icon--accent2{color:rgb(var(--ax-sys-color-accent2-dark-surface))}.axp-status-chip--accent3{background-color:rgb(var(--ax-sys-color-accent3-lighter-surface));color:rgb(var(--ax-sys-color-on-accent3-lighter-surface))}.axp-status-icon--accent3{color:rgb(var(--ax-sys-color-accent3-dark-surface))}.axp-status-chip--neutral{background-color:rgb(var(--ax-sys-color-neutral-lighter-surface));color:rgb(var(--ax-sys-color-on-neutral-lighter-surface))}.axp-status-icon--neutral{color:rgb(var(--ax-sys-color-neutral-dark-surface))}axp-layout-title{display:block;width:100%;font-weight:600}axp-layout-description{display:block;width:100%;font-size:.875rem;line-height:1.25rem;opacity:.65}axp-layout-actions{display:flex;align-items:center;gap:.75rem}axp-layout-actions axp-layout-actions-primary{display:flex;align-items:center;gap:.75rem}axp-layout-footer,axp-layout-toolbar,axp-layout-header,axp-page-header,axp-page-footer,axp-page-toolbar{display:flex;width:100%;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.5rem}axp-layout-footer>axp-layout-prefix,axp-layout-footer>axp-layout-suffix,axp-layout-toolbar>axp-layout-prefix,axp-layout-toolbar>axp-layout-suffix,axp-layout-header>axp-layout-prefix,axp-layout-header>axp-layout-suffix,axp-page-header>axp-layout-prefix,axp-page-header>axp-layout-suffix,axp-page-footer>axp-layout-prefix,axp-page-footer>axp-layout-suffix,axp-page-toolbar>axp-layout-prefix,axp-page-toolbar>axp-layout-suffix{display:flex;flex-direction:row;align-items:center;gap:.5rem}axp-layout-footer>axp-layout-prefix,axp-layout-toolbar>axp-layout-prefix,axp-layout-header>axp-layout-prefix,axp-page-header>axp-layout-prefix,axp-page-footer>axp-layout-prefix,axp-page-toolbar>axp-layout-prefix{order:-9999}axp-layout-footer>axp-layout-suffix,axp-layout-toolbar>axp-layout-suffix,axp-layout-header>axp-layout-suffix,axp-page-header>axp-layout-suffix,axp-page-footer>axp-layout-suffix,axp-page-toolbar>axp-layout-suffix{order:9999;margin-inline-start:auto}axp-layout-list{display:flex;flex-direction:column}axp-layout-list>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse));border-style:dashed}axp-layout-list:focus{outline:none}axp-layout-list-group{display:flex;flex-direction:column;padding-top:.5rem;padding-bottom:.5rem}axp-layout-list-group>axp-layout-title{padding-bottom:.5rem;font-size:.875rem;line-height:1.25rem;font-weight:600}axp-layout-list-group>axp-layout-header{display:flex;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}axp-layout-list-item{margin-top:.25rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem;font-size:.875rem;line-height:1.25rem}axp-layout-list-item:focus{outline:none}axp-layout-list-item.axp-state-focused,axp-layout-list-item:hover{cursor:pointer;border-radius:.25rem;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-light-surface),var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1))}axp-layout-list-item>axp-layout-prefix{margin-inline-end:auto;display:flex;flex-direction:row;gap:.5rem}axp-layout-list-item>axp-layout-content{flex:1 1 0%}axp-layout-list-item>axp-layout-content axp-layout-description{margin-top:.25rem!important;font-size:.75rem!important;line-height:1rem!important}axp-layout-list-item>axp-layout-suffix{margin-inline-start:auto;display:flex;flex-direction:row;gap:.5rem}axp-layout-sections{display:flex;flex-direction:column;gap:1rem}axp-layout-sections axp-layout-section{display:block;border-radius:.375rem;border-width:1px;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-layout-sections axp-layout-section>axp-layout-footer,axp-layout-sections axp-layout-section>axp-layout-header{padding:.5rem 1rem}@media(min-width:1280px){axp-layout-sections axp-layout-section>axp-layout-footer,axp-layout-sections axp-layout-section>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-layout-sections axp-layout-section>axp-layout-header{display:flex;flex-direction:column;gap:0px;border-top-left-radius:.375rem;border-top-right-radius:.375rem;border-bottom-width:1px}axp-layout-sections axp-layout-section>axp-layout-header axp-layout-title{font-weight:700;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1))}axp-layout-sections axp-layout-section>axp-layout-header axp-layout-description{margin-top:.25rem;font-size:.875rem;line-height:1.25rem}axp-layout-sections axp-layout-section>axp-layout-footer{display:flex;align-items:center;justify-content:space-between;border-bottom-right-radius:.375rem;border-bottom-left-radius:.375rem;border-top-width:1px;padding:1rem}axp-layout-sections axp-layout-section>axp-layout-footer>axp-layout-suffix{margin-inline-start:auto;display:flex;gap:.5rem}axp-layout-sections axp-layout-section>axp-layout-footer{opacity:0;animation:fadeInDown .5s ease-out forwards}@keyframes fadeInDown{0%{opacity:0}to{opacity:1}}axp-page-layout{display:flex;width:100%;height:100%;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-dark-surface));color:rgb(var(--ax-sys-color-on-dark-surface));border-color:rgb(var(--ax-sys-color-border-dark-surface))}axp-page-layout axp-layout-start-side,axp-page-layout axp-layout-end-side{display:flex;min-height:100%;min-width:16rem;flex-direction:column;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout axp-layout-start-side:is(.ax-dark *),axp-page-layout axp-layout-end-side:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-darker-surface));color:rgb(var(--ax-sys-color-on-darker-surface));border-color:rgb(var(--ax-sys-color-border-darker-surface))}axp-page-layout axp-layout-start-side axp-layout-header,axp-page-layout axp-layout-end-side axp-layout-header{display:flex;flex-direction:column;gap:.5rem;padding:1rem}axp-page-layout axp-layout-start-side axp-layout-header>axp-layout-title,axp-page-layout axp-layout-end-side axp-layout-header>axp-layout-title{font-size:1.125rem;line-height:1.75rem;font-weight:500}axp-page-layout axp-layout-start-side>axp-layout-content,axp-page-layout axp-layout-end-side>axp-layout-content{flex:1 1 0%}axp-page-layout>axp-layout-container{position:relative;display:flex;width:100%;height:100%;flex-direction:column;overflow:auto}axp-page-layout>axp-layout-container>axp-layout-header{position:sticky;top:0;z-index:20;display:flex;flex-direction:column;align-items:flex-start;gap:0px;padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-dark-surface));color:rgb(var(--ax-sys-color-on-dark-surface));border-color:rgb(var(--ax-sys-color-border-dark-surface))}@media(min-width:768px){axp-page-layout>axp-layout-container>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-page-layout>axp-layout-container>axp-layout-header.axp-is-sticky{--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-border-opacity, 1));--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-page-layout>axp-layout-container>axp-layout-header ax-breadcrumbs ax-breadcrumbs-item{font-size:.75rem;line-height:1rem}axp-page-layout>axp-layout-container>axp-layout-header ax-breadcrumbs ax-breadcrumbs-item.ax-state-active .ax-breadcrumb-item-content{cursor:default;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1));opacity:.75}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar{display:flex;width:100%;align-items:center;justify-content:space-between;padding-left:1rem;padding-right:1rem}@media(min-width:1280px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar{border-width:0px}}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar ax-layout-nav-button{display:flex;align-items:center;justify-content:space-between}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container{display:flex;align-items:baseline;gap:.75rem}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container axp-layout-title{display:inline-block;width:fit-content;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1.25rem;line-height:1.75rem;font-weight:500;line-height:1}@media(min-width:1024px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container axp-layout-title{font-size:1.5rem;line-height:2rem}}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge{display:inline-flex;--tw-translate-y: -3px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));align-items:center;align-self:baseline;border-radius:.375rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:600;line-height:1}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge i{margin-inline-end:.25rem;line-height:1;font-size:.5rem}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--warning{background-color:rgb(var(--ax-sys-color-warning-lightest-surface));color:rgb(var(--ax-sys-color-on-warning-lightest-surface));border-color:rgb(var(--ax-sys-color-border-warning-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--warning i{color:rgb(var(--ax-sys-color-warning-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--danger{background-color:rgb(var(--ax-sys-color-danger-lightest-surface));color:rgb(var(--ax-sys-color-on-danger-lightest-surface));border-color:rgb(var(--ax-sys-color-border-danger-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--danger i{color:rgb(var(--ax-sys-color-danger-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--success{background-color:rgb(var(--ax-sys-color-success-lightest-surface));color:rgb(var(--ax-sys-color-on-success-lightest-surface));border-color:rgb(var(--ax-sys-color-border-success-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--success i{color:rgb(var(--ax-sys-color-success-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--primary{background-color:rgb(var(--ax-sys-color-primary-lightest-surface));color:rgb(var(--ax-sys-color-on-primary-lightest-surface));border-color:rgb(var(--ax-sys-color-border-primary-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--primary i{color:rgb(var(--ax-sys-color-primary-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--secondary i{color:rgb(var(--ax-sys-color-secondary-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--default i{color:rgb(var(--ax-sys-color-on-surface)/.45)}@media(max-width:600px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge{--tw-translate-y: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));background-color:transparent;padding:0;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge .__title-badge-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge i{margin:0;font-size:.625rem}}axp-page-layout>axp-layout-container>axp-layout-header axp-page-toolbar{margin-top:.5rem;padding-left:1rem;padding-right:1rem}axp-page-layout>axp-layout-container>axp-page-content{display:flex;width:100%;flex:1 1 0%;flex-direction:column;padding:.75rem 1rem}axp-page-layout>axp-layout-container>axp-page-content.--scrollable{padding-bottom:1rem}axp-page-layout>axp-layout-container>axp-page-footer-container{border-top-width:1px;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout>axp-layout-container>axp-page-footer-container:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axp-page-layout>axp-layout-container>axp-page-footer-container{position:sticky;bottom:0;z-index:20;padding:.75rem;--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}@keyframes ax-fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}axp-page-layout>axp-layout-container>axp-page-footer-container.--animated{animation:1s both ax-fadeInUp;transition-duration:.3s;transition-timing-function:cubic-bezier(0,0,.2,1);animation-duration:.3s;animation-timing-function:cubic-bezier(0,0,.2,1)}\n"] }]
177
+ ], selector: 'axp-page-layout', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [AXDrawerContainerDirective], providers: [], template: "<!-------- Begin Start Side Drawer -------->\n<div id=\"axp-drawer-start\" [mode]=\"deviceService.isSmall() ? 'overlay' : 'push'\" [transition]=\"250\" axDrawerItem\n [backDrop]=\"true\" (onBackdropClick)=\"handleBackdropClick($event)\" #startSideDrawer=\"axDrawerItem\"\n [backdropClass]=\"'ax-bg-darkest/75'\" [collapsed]=\"deviceService.isSmall()\" drawerLocation=\"start\" class=\"ax-h-full\">\n <ng-content select=\"axp-layout-start-side\"></ng-content>\n</div>\n<!-------- Finish Start Side Drawer -------->\n<!--------------------------------------------------------------->\n<!-------- Begin Main Layout Container -------->\n<axp-layout-container id=\"axp-page-layout\" #container>\n <!-------- Begin Page Header -------->\n <axp-layout-header id=\"axp-page-header\" *translate=\"let t\" #sticky=\"axpSticky\" [axpSticky]=\"'axp-is-sticky'\"\n [stickyOffset]=\"50\" [stickyParent]=\"container.hostElement\">\n <!-------- Begin Back Button (Mobile Only) -------->\n @if (page?.hasBackButton() && deviceService.isSmall()) {\n <ax-button id=\"axp-btn-back\" [look]=\"'blank'\" class=\"ax-sm ax-w-fit ax-ms-1\" color=\"secondary\"\n (click)=\"page?.onBackButtonClick()\" [text]=\"(page?.backButton()?.title | translate | async) ?? ''\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-chevron-left rtl:ax-rotate-180\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n <!-------- Finish Back Button -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Bar -------->\n <axp-layout-title-bar id=\"axp-title-bar\">\n <!-------- Begin Title Section -------->\n <div class=\"ax-flex ax-flex-col ax-transition ax-shrink-1 ax-min-w-0\">\n <!-------- Begin Breadcrumbs -------->\n @if (page?.hasBreadcrumbs() && !deviceService.isSmall()) {\n <ax-breadcrumbs id=\"axp-breadcrumb\" class=\"ax-mb-1\">\n @for (item of page?.breadcrumbs(); track $index) {\n <ax-breadcrumbs-item [attr.id]=\"'axp-breadcrumb-item-' + $index\" [active]=\"$last\"\n (click)=\"!$last && item.command ? execute(item.command) : null\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n {{ t(item.title) | async }}\n </ax-breadcrumbs-item>\n }\n <ng-template #divider>\n <i class=\"fa-regular fa-chevron-right rtl:ax-rotate-180 fa-sm\"></i>\n </ng-template>\n </ax-breadcrumbs>\n }\n <!-------- Finish Breadcrumbs -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Container -------->\n <div class=\"__title-container\">\n <!-------- Begin Page Title -------->\n @if (page?.hasTitle()) {\n <axp-layout-title id=\"axp-page-title\">\n @if (page?.hasTitleIcon()) {\n <ax-icon [icon]=\"page?.titleIcon()!\" class=\"ax-me-2\"></ax-icon>\n }\n {{ page?.title() | translate | async }}\n </axp-layout-title>\n }\n <!-------- Finish Page Title -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Title Actions -------->\n @if (page?.hasTitleActions()) {\n <ax-button id=\"axp-btn-title-actions\" [look]=\"'blank'\" class=\"ax-sm -ax-mx-2\">\n <ax-prefix>\n <i class=\"fa-solid fa-caret-down fa-fw\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of page?.titleActions(); track $index) {\n <ng-container>\n <ax-button-item [attr.id]=\"'axp-btn-title-action-' + (sub.name || $index)\"\n [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\" [disabled]=\"sub.disabled\"\n [selected]=\"sub.command?.metadata?.['isSelected']\" (onClick)=\"handleActionClick(sub)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n </ng-container>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-------- Finish Title Actions -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Status -------->\n\n @if (page?.hasStatus()) {\n <axp-status-chip [value]=\"page?.status()?.value ?? null\" [readonly]=\"page?.status()?.readonly || false\"\n [definitionKey]=\"page?.status()?.definitionKey ?? null\" [entityData]=\"getEntityData()\"\n (transitionExecuted)=\"handleStatusTransition($event)\" class=\"__title-status\"></axp-status-chip>\n }\n <!-------- Finish Page Status -------->\n\n <!-------- Begin Title Badge -------->\n @if (page?.hasBadge()) {\n <div id=\"axp-page-badge\" class=\"__title-badge --{{ page?.badge()?.color }}\"\n [attr.title]=\"page?.badge()?.description ?? page?.badge()?.title\" [attr.aria-label]=\"page?.badge()?.title\">\n <i class=\"fa-solid fa-circle\" aria-hidden=\"true\"></i>\n <span class=\"__title-badge-label\">{{ page?.badge()?.title }}</span>\n </div>\n }\n <!-------- Finish Title Badge -------->\n\n </div>\n <!-------- Finish Title Container -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Description -------->\n @if (page?.hasDescription()) {\n <axp-layout-description id=\"axp-page-description\">\n {{ page?.description() | translate | async }}</axp-layout-description>\n }\n <!-------- Finish Page Description -------->\n </div>\n <!-------- Finish Title Section -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Actions -------->\n <axp-layout-actions id=\"axp-page-actions\" class=\"ax-shrink-0\">\n <axp-component-slot name=\"page-header-actions\"></axp-component-slot>\n <!-------- Begin Primary Actions -------->\n @if (page?.hasPrimaryActions()) {\n @for (item of page?.primaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\" [class.ax-sm]=\"deviceService.isSmall()\"\n [iconOnly]=\"deviceService.isSmall()\" [disabled]=\"item.disabled\" [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\" [color]=\"item.color\" (onClick)=\"handleActionClick(item)\">\n <ax-prefix>\n <i class=\"{{ item.icon }}\"></i>\n </ax-prefix>\n @if (item?.items) {\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of item?.items; track $index) {\n @if (sub.visible != false) {\n <ax-button-item [attr.id]=\"'axp-btn-primary-' + (item.name || item.title) + '-' + (sub.name || sub.title)\"\n [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\" [disabled]=\"sub.disabled\"\n (onClick)=\"handleActionClick(sub)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n }\n </ax-button>\n }\n }\n }\n <!-------- Finish Primary Actions -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Secondary Actions -------->\n @if (page?.hasSecondaryActions()) {\n <ax-button id=\"axp-btn-secondary\" [class.ax-sm]=\"deviceService.isSmall()\" [iconOnly]=\"deviceService.isSmall()\"\n [text]=\"'@general:terms.interface.actions' | translate | async\"\n [look]=\"deviceService.isSmall() ? 'blank' : 'solid'\" [color]=\"'default'\">\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (item of page?.secondaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button-item [attr.id]=\"'axp-btn-secondary-' + (item.name || item.title)\"\n [text]=\"(item.title | translate | async)!\" [color]=\"item.color\" [disabled]=\"item.disabled\"\n (onClick)=\"handleSecondaryActionClick(item)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-------- Finish Secondary Actions -------->\n </axp-layout-actions>\n <!-------- Finish Page Actions -------->\n </axp-layout-title-bar>\n <!-------- Finish Title Bar -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Toolbar / Navbar -------->\n @if (!sticky.isSticky) {}\n <ng-content select=\"axp-page-toolbar\"></ng-content>\n <!-------- Finish Page Toolbar / Navbar -------->\n </axp-layout-header>\n <!-------- Finish Page Header -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Content -------->\n <ng-content select=\"axp-page-content\"></ng-content>\n <!-------- Finish Page Content -------->\n <!--------------------------------------------------------------->\n <!-------- Begin Page Footer -------->\n <axp-page-footer-container id=\"axp-page-footer-container\"\n [ngStyle]=\"{ display: tt.isEmpty() && prefixSlot.isEmpty() && suffixSlot.isEmpty() ? 'none' : 'block' }\">\n <axp-layout-container #tt>\n <ng-content select=\"axp-page-footer\"></ng-content>\n </axp-layout-container>\n <axp-page-footer id=\"axp-page-footer\">\n <axp-layout-prefix>\n <axp-component-slot name=\"page-footer-start\" #prefixSlot=\"slot\"></axp-component-slot>\n </axp-layout-prefix>\n <axp-layout-suffix>\n <axp-component-slot name=\"page-footer-end\" #suffixSlot=\"slot\"></axp-component-slot>\n </axp-layout-suffix>\n </axp-page-footer>\n </axp-page-footer-container>\n <!-------- Finish Page Footer -------->\n</axp-layout-container>\n<!-------- Finish Main Layout Container -------->", styles: ["@charset \"UTF-8\";.axp-status-icon{font-size:.875rem;line-height:1}.axp-status-chip{display:inline-flex}.axp-status-chip--primary{background-color:rgb(var(--ax-sys-color-primary-lighter-surface));color:rgb(var(--ax-sys-color-on-primary-lighter-surface))}.axp-status-icon--primary{color:rgb(var(--ax-sys-color-primary-dark-surface))}.axp-status-chip--secondary{background-color:rgb(var(--ax-sys-color-secondary-lighter-surface));color:rgb(var(--ax-sys-color-on-secondary-lighter-surface))}.axp-status-icon--secondary{color:rgb(var(--ax-sys-color-secondary-dark-surface))}.axp-status-chip--success{background-color:rgb(var(--ax-sys-color-success-lighter-surface));color:rgb(var(--ax-sys-color-on-success-lighter-surface))}.axp-status-icon--success{color:rgb(var(--ax-sys-color-success-dark-surface))}.axp-status-chip--warning{background-color:rgb(var(--ax-sys-color-warning-lighter-surface));color:rgb(var(--ax-sys-color-on-warning-lighter-surface))}.axp-status-icon--warning{color:rgb(var(--ax-sys-color-warning-dark-surface))}.axp-status-chip--danger{background-color:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.axp-status-icon--danger{color:rgb(var(--ax-sys-color-danger-dark-surface))}.axp-status-chip--info{background-color:rgb(var(--ax-sys-color-accent3-lighter-surface));color:rgb(var(--ax-sys-color-on-accent3-lighter-surface))}.axp-status-icon--info{color:rgb(var(--ax-sys-color-accent3-dark-surface))}.axp-status-chip--accent1{background-color:rgb(var(--ax-sys-color-accent1-lighter-surface));color:rgb(var(--ax-sys-color-on-accent1-lighter-surface))}.axp-status-icon--accent1{color:rgb(var(--ax-sys-color-accent1-dark-surface))}.axp-status-chip--accent2{background-color:rgb(var(--ax-sys-color-accent2-lighter-surface));color:rgb(var(--ax-sys-color-on-accent2-lighter-surface))}.axp-status-icon--accent2{color:rgb(var(--ax-sys-color-accent2-dark-surface))}.axp-status-chip--accent3{background-color:rgb(var(--ax-sys-color-accent3-lighter-surface));color:rgb(var(--ax-sys-color-on-accent3-lighter-surface))}.axp-status-icon--accent3{color:rgb(var(--ax-sys-color-accent3-dark-surface))}.axp-status-chip--neutral{background-color:rgb(var(--ax-sys-color-neutral-lighter-surface));color:rgb(var(--ax-sys-color-on-neutral-lighter-surface))}.axp-status-icon--neutral{color:rgb(var(--ax-sys-color-neutral-dark-surface))}axp-layout-title{display:block;width:100%;font-weight:600}axp-layout-description{display:block;width:100%;font-size:.875rem;line-height:1.25rem;opacity:.65}axp-layout-actions{display:flex;align-items:center;gap:.75rem}axp-layout-actions axp-layout-actions-primary{display:flex;align-items:center;gap:.75rem}axp-layout-footer,axp-layout-toolbar,axp-layout-header,axp-page-header,axp-page-footer,axp-page-toolbar{display:flex;width:100%;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.5rem}axp-layout-footer>axp-layout-prefix,axp-layout-footer>axp-layout-suffix,axp-layout-toolbar>axp-layout-prefix,axp-layout-toolbar>axp-layout-suffix,axp-layout-header>axp-layout-prefix,axp-layout-header>axp-layout-suffix,axp-page-header>axp-layout-prefix,axp-page-header>axp-layout-suffix,axp-page-footer>axp-layout-prefix,axp-page-footer>axp-layout-suffix,axp-page-toolbar>axp-layout-prefix,axp-page-toolbar>axp-layout-suffix{display:flex;flex-direction:row;align-items:center;gap:.5rem}axp-layout-footer>axp-layout-prefix,axp-layout-toolbar>axp-layout-prefix,axp-layout-header>axp-layout-prefix,axp-page-header>axp-layout-prefix,axp-page-footer>axp-layout-prefix,axp-page-toolbar>axp-layout-prefix{order:-9999}axp-layout-footer>axp-layout-suffix,axp-layout-toolbar>axp-layout-suffix,axp-layout-header>axp-layout-suffix,axp-page-header>axp-layout-suffix,axp-page-footer>axp-layout-suffix,axp-page-toolbar>axp-layout-suffix{order:9999;margin-inline-start:auto}axp-layout-list{display:flex;flex-direction:column}axp-layout-list>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse));border-style:dashed}axp-layout-list:focus{outline:none}axp-layout-list-group{display:flex;flex-direction:column;padding-top:.5rem;padding-bottom:.5rem}axp-layout-list-group>axp-layout-title{padding-bottom:.5rem;font-size:.875rem;line-height:1.25rem;font-weight:600}axp-layout-list-group>axp-layout-header{display:flex;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}axp-layout-list-item{margin-top:.25rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem;font-size:.875rem;line-height:1.25rem}axp-layout-list-item:focus{outline:none}axp-layout-list-item.axp-state-focused,axp-layout-list-item:hover{cursor:pointer;border-radius:.25rem;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-light-surface),var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1))}axp-layout-list-item>axp-layout-prefix{margin-inline-end:auto;display:flex;flex-direction:row;gap:.5rem}axp-layout-list-item>axp-layout-content{flex:1 1 0%}axp-layout-list-item>axp-layout-content axp-layout-description{margin-top:.25rem!important;font-size:.75rem!important;line-height:1rem!important}axp-layout-list-item>axp-layout-suffix{margin-inline-start:auto;display:flex;flex-direction:row;gap:.5rem}axp-layout-sections{display:flex;flex-direction:column;gap:1rem}axp-layout-sections axp-layout-section{display:block;border-radius:.375rem;border-width:1px;--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-layout-sections axp-layout-section>axp-layout-footer,axp-layout-sections axp-layout-section>axp-layout-header{padding:.5rem 1rem}@media(min-width:1280px){axp-layout-sections axp-layout-section>axp-layout-footer,axp-layout-sections axp-layout-section>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-layout-sections axp-layout-section>axp-layout-header{display:flex;flex-direction:column;gap:0px;border-top-left-radius:.375rem;border-top-right-radius:.375rem;border-bottom-width:1px}axp-layout-sections axp-layout-section>axp-layout-header axp-layout-title{font-weight:700;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1))}axp-layout-sections axp-layout-section>axp-layout-header axp-layout-description{margin-top:.25rem;font-size:.875rem;line-height:1.25rem}axp-layout-sections axp-layout-section>axp-layout-footer{display:flex;align-items:center;justify-content:space-between;border-bottom-right-radius:.375rem;border-bottom-left-radius:.375rem;border-top-width:1px;padding:1rem}axp-layout-sections axp-layout-section>axp-layout-footer>axp-layout-suffix{margin-inline-start:auto;display:flex;gap:.5rem}axp-layout-sections axp-layout-section>axp-layout-footer{opacity:0;animation:fadeInDown .5s ease-out forwards}@keyframes fadeInDown{0%{opacity:0}to{opacity:1}}axp-page-layout{display:flex;width:100%;height:100%;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-dark-surface));color:rgb(var(--ax-sys-color-on-dark-surface));border-color:rgb(var(--ax-sys-color-border-dark-surface))}axp-page-layout axp-layout-start-side,axp-page-layout axp-layout-end-side{display:flex;min-height:100%;min-width:16rem;flex-direction:column;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout axp-layout-start-side:is(.ax-dark *),axp-page-layout axp-layout-end-side:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-darker-surface));color:rgb(var(--ax-sys-color-on-darker-surface));border-color:rgb(var(--ax-sys-color-border-darker-surface))}axp-page-layout axp-layout-start-side axp-layout-header,axp-page-layout axp-layout-end-side axp-layout-header{display:flex;flex-direction:column;gap:.5rem;padding:1rem}axp-page-layout axp-layout-start-side axp-layout-header>axp-layout-title,axp-page-layout axp-layout-end-side axp-layout-header>axp-layout-title{font-size:1.125rem;line-height:1.75rem;font-weight:500}axp-page-layout axp-layout-start-side>axp-layout-content,axp-page-layout axp-layout-end-side>axp-layout-content{flex:1 1 0%}axp-page-layout>axp-layout-container{position:relative;display:flex;width:100%;height:100%;flex-direction:column;overflow:auto}axp-page-layout>axp-layout-container>axp-layout-header{position:sticky;top:0;z-index:20;display:flex;flex-direction:column;align-items:flex-start;gap:0px;padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-dark-surface));color:rgb(var(--ax-sys-color-on-dark-surface));border-color:rgb(var(--ax-sys-color-border-dark-surface))}@media(min-width:768px){axp-page-layout>axp-layout-container>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-page-layout>axp-layout-container>axp-layout-header.axp-is-sticky{--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-border-opacity, 1));--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-page-layout>axp-layout-container>axp-layout-header ax-breadcrumbs ax-breadcrumbs-item{font-size:.75rem;line-height:1rem}axp-page-layout>axp-layout-container>axp-layout-header ax-breadcrumbs ax-breadcrumbs-item.ax-state-active .ax-breadcrumb-item-content{cursor:default;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-lightest-surface),var(--tw-text-opacity, 1));opacity:.75}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar{display:flex;width:100%;align-items:center;justify-content:space-between;padding-left:1rem;padding-right:1rem}@media(min-width:1280px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar{border-width:0px}}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar ax-layout-nav-button{display:flex;align-items:center;justify-content:space-between}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container{display:flex;align-items:baseline;gap:.75rem}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container axp-layout-title{display:inline-block;width:fit-content;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1.25rem;line-height:1.75rem;font-weight:500;line-height:1}@media(min-width:1024px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container axp-layout-title{font-size:1.5rem;line-height:2rem}}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge{display:inline-flex;--tw-translate-y: -3px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));align-items:center;align-self:baseline;border-radius:.375rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:600;line-height:1}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge i{margin-inline-end:.25rem;line-height:1;font-size:.5rem}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--warning{background-color:rgb(var(--ax-sys-color-warning-lightest-surface));color:rgb(var(--ax-sys-color-on-warning-lightest-surface));border-color:rgb(var(--ax-sys-color-border-warning-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--warning i{color:rgb(var(--ax-sys-color-warning-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--danger{background-color:rgb(var(--ax-sys-color-danger-lightest-surface));color:rgb(var(--ax-sys-color-on-danger-lightest-surface));border-color:rgb(var(--ax-sys-color-border-danger-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--danger i{color:rgb(var(--ax-sys-color-danger-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--success{background-color:rgb(var(--ax-sys-color-success-lightest-surface));color:rgb(var(--ax-sys-color-on-success-lightest-surface));border-color:rgb(var(--ax-sys-color-border-success-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--success i{color:rgb(var(--ax-sys-color-success-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--primary{background-color:rgb(var(--ax-sys-color-primary-lightest-surface));color:rgb(var(--ax-sys-color-on-primary-lightest-surface));border-color:rgb(var(--ax-sys-color-border-primary-lightest-surface))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--primary i{color:rgb(var(--ax-sys-color-primary-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--secondary i{color:rgb(var(--ax-sys-color-secondary-500))}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge.--default i{color:rgb(var(--ax-sys-color-on-surface)/.45)}@media(max-width:600px){axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge{--tw-translate-y: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));background-color:transparent;padding:0;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge .__title-badge-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}axp-page-layout>axp-layout-container>axp-layout-header axp-layout-title-bar .__title-container .__title-badge i{margin:0;font-size:.625rem}}axp-page-layout>axp-layout-container>axp-layout-header axp-page-toolbar{margin-top:.5rem;padding-left:1rem;padding-right:1rem}axp-page-layout>axp-layout-container>axp-page-content{display:flex;width:100%;flex:1 1 0%;flex-direction:column;padding:.75rem 1rem}axp-page-layout>axp-layout-container>axp-page-content.--scrollable{padding-bottom:1rem}axp-page-layout>axp-layout-container>axp-page-footer-container{border-top-width:1px;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-page-layout>axp-layout-container>axp-page-footer-container:is(.ax-dark *){background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axp-page-layout>axp-layout-container>axp-page-footer-container{position:sticky;bottom:0;z-index:20;padding:.75rem;--tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / .05);--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}@keyframes ax-fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}axp-page-layout>axp-layout-container>axp-page-footer-container.--animated{animation:1s both ax-fadeInUp;transition-duration:.3s;transition-timing-function:cubic-bezier(0,0,.2,1);animation-duration:.3s;animation-timing-function:cubic-bezier(0,0,.2,1)}\n"] }]
178
178
  }], propDecorators: { startSideDrawer: [{ type: i0.ViewChild, args: ['startSideDrawer', { isSignal: true }] }] } });
179
179
 
180
180
  //#region ---- Page Unsaved Changes Utilities ----
@@ -223,7 +223,9 @@ class AXPPageLayoutBaseComponent {
223
223
  this.tabNavigation = inject(AXPTabNavigationService);
224
224
  this.tabPreviewService = inject(AXPTabPreviewService);
225
225
  this.unsavedChangesConfirm = inject(AXPUnsavedChangesConfirmService);
226
+ this.browserTitleService = inject(AXPBrowserTitleService);
226
227
  this.router = inject(Router);
228
+ this.pageLayoutDestroyRef = inject(DestroyRef);
227
229
  //#endregion
228
230
  //#region ---------------- Signal to force recomputation ----------------
229
231
  this._updateTrigger = signal(0, ...(ngDevMode ? [{ debugName: "_updateTrigger" }] : /* istanbul ignore next */ []));
@@ -298,6 +300,19 @@ class AXPPageLayoutBaseComponent {
298
300
  return false;
299
301
  }, ...(ngDevMode ? [{ debugName: "hasTitle" }] : /* istanbul ignore next */ []));
300
302
  this.hasTitleIcon = computed(() => this.titleIcon() !== null, ...(ngDevMode ? [{ debugName: "hasTitleIcon" }] : /* istanbul ignore next */ []));
303
+ this.#browserTitleEffect = effect(() => {
304
+ if (this.tabNavigation.effectiveMode() === 'tabular') {
305
+ return;
306
+ }
307
+ if (!this.isActivePageForBrowserTitle()) {
308
+ return;
309
+ }
310
+ this.updateTrigger();
311
+ this.title();
312
+ untracked(() => {
313
+ void this.publishBrowserTitleIfActive();
314
+ });
315
+ }, ...(ngDevMode ? [{ debugName: "#browserTitleEffect" }] : /* istanbul ignore next */ []));
301
316
  //#endregion
302
317
  //#region ---------------- Description ----------------
303
318
  this.description = signal(null, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
@@ -340,16 +355,17 @@ class AXPPageLayoutBaseComponent {
340
355
  this.breadcrumbs.set(trail);
341
356
  if (this.tabNavigation.effectiveMode() === 'tabular') {
342
357
  const tabKey = this.pageTabKey();
343
- let tabTitle = await this.resolveBreadcrumbTabTitle(breadCrumbs);
358
+ const tabTitleSegments = await this.resolveBreadcrumbTabTitleSegments(breadCrumbs);
359
+ let tabTitle = tabTitleSegments.length ? axpJoinTabTitleSegments(tabTitleSegments) : null;
344
360
  if (!tabTitle) {
345
361
  tabTitle = await this.resolvePageTitleForTab();
346
362
  }
347
363
  if (tabKey && tabTitle) {
348
- this.tabNavigation.syncTabTitle(tabKey, tabTitle);
364
+ this.tabNavigation.syncTabTitle(tabKey, tabTitleSegments.length ? tabTitleSegments : tabTitle);
349
365
  }
350
366
  }
351
367
  }, ...(ngDevMode ? [{ debugName: "#breadcrumbsEffect" }] : /* istanbul ignore next */ []));
352
- this.hasBreadcrumbs = computed(() => this.breadcrumbs().length > 1 && this.tabNavigation.effectiveMode() !== 'tabular', ...(ngDevMode ? [{ debugName: "hasBreadcrumbs" }] : /* istanbul ignore next */ []));
368
+ this.hasBreadcrumbs = computed(() => this.breadcrumbs().length > 1, ...(ngDevMode ? [{ debugName: "hasBreadcrumbs" }] : /* istanbul ignore next */ []));
353
369
  //#endregion
354
370
  //#region ---------------- Badge ----------------
355
371
  this.badge = signal(null, ...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
@@ -409,6 +425,11 @@ class AXPPageLayoutBaseComponent {
409
425
  this.translateService.langChanges$.subscribe(() => {
410
426
  this.recompute();
411
427
  });
428
+ this.router.events
429
+ .pipe(filter((event) => event instanceof NavigationEnd), takeUntilDestroyed(this.pageLayoutDestroyRef))
430
+ .subscribe(() => {
431
+ void this.publishBrowserTitleIfActive();
432
+ });
412
433
  }
413
434
  /** Maps the home-page route to the pinned home tab key instead of a path-based key. */
414
435
  resolvePageTabKey() {
@@ -418,6 +439,10 @@ class AXPPageLayoutBaseComponent {
418
439
  }
419
440
  return axpResolveTabKey(this.router);
420
441
  }
442
+ /** Stable tab key for this cached page instance (tabular mode). */
443
+ getPageTabKey() {
444
+ return this.pageTabKey();
445
+ }
421
446
  //#endregion
422
447
  //#region ---------------- Tab Title Sync ----------------
423
448
  /** Refreshes tab title when this cached page becomes the active tab again. */
@@ -481,6 +506,33 @@ class AXPPageLayoutBaseComponent {
481
506
  getPageIcon() {
482
507
  return null;
483
508
  }
509
+ #browserTitleEffect;
510
+ /** Publishes the page title to the browser tab when this instance is the active route. */
511
+ async publishBrowserTitleIfActive() {
512
+ if (this.tabNavigation.effectiveMode() === 'tabular') {
513
+ return;
514
+ }
515
+ if (!this.isActivePageForBrowserTitle()) {
516
+ return;
517
+ }
518
+ const routeKey = this.pageTabKey();
519
+ if (!routeKey) {
520
+ return;
521
+ }
522
+ const pageTitle = await this.resolvePageTitleForTab();
523
+ if (!this.isActivePageForBrowserTitle()) {
524
+ return;
525
+ }
526
+ this.browserTitleService.setSimpleModePageTitle(pageTitle, routeKey);
527
+ }
528
+ /** True when this cached page instance matches the current router location. */
529
+ isActivePageForBrowserTitle() {
530
+ const pageKey = this.pageTabKey();
531
+ if (!pageKey) {
532
+ return false;
533
+ }
534
+ return pageKey === axpResolveTabKey(this.router);
535
+ }
484
536
  #descriptionEffect;
485
537
  getPageDescription() {
486
538
  return null;
@@ -489,8 +541,8 @@ class AXPPageLayoutBaseComponent {
489
541
  getPageBreadcrumbs() {
490
542
  return [];
491
543
  }
492
- /** Joins all page breadcrumbs (Home is excluded upstream) as the tab label. */
493
- async resolveBreadcrumbTabTitle(pageBreadcrumbs) {
544
+ /** Collects resolved breadcrumb labels (Home excluded upstream) for tab chrome. */
545
+ async resolveBreadcrumbTabTitleSegments(pageBreadcrumbs) {
494
546
  const segments = [];
495
547
  for (const item of pageBreadcrumbs) {
496
548
  const title = await this.resolveBreadcrumbItemTitle(item);
@@ -498,10 +550,15 @@ class AXPPageLayoutBaseComponent {
498
550
  segments.push(title);
499
551
  }
500
552
  }
553
+ return segments;
554
+ }
555
+ /** Joins breadcrumb segments as the stored tab title string. */
556
+ async resolveBreadcrumbTabTitle(pageBreadcrumbs) {
557
+ const segments = await this.resolveBreadcrumbTabTitleSegments(pageBreadcrumbs);
501
558
  if (!segments.length) {
502
559
  return null;
503
560
  }
504
- return segments.join(' - ');
561
+ return axpJoinTabTitleSegments(segments);
505
562
  }
506
563
  /** Resolves a breadcrumb label the same way as page chrome (`t(item.title)`). */
507
564
  async resolveBreadcrumbItemTitle(item) {
@@ -781,6 +838,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
781
838
  }]
782
839
  }], propDecorators: { layout: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPPopupLayoutComponent), { isSignal: true }] }] } });
783
840
 
841
+ const AXP_LAYOUT_DETAILS_VIEW_ADAPTER_LOADER = new InjectionToken('AXP_LAYOUT_DETAILS_VIEW_ADAPTER_LOADER');
842
+ //#endregion
843
+
844
+ /** Trace namespace for details-view page / URL sync diagnostics. */
845
+ const DETAILS_VIEW_PAGE_TRACE_NS = 'details-view-page';
846
+
784
847
  //#region ---- Root-context widget expression resolution ----
785
848
  /**
786
849
  * Evaluates `{{ ... }}` strings inside `options.customFilterDefinitions` using `rootContext`
@@ -820,10 +883,11 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
820
883
  const state = {
821
884
  adapter: null,
822
885
  rootContext: {},
886
+ savedContext: {},
823
887
  previousContext: {},
824
888
  context: {},
825
889
  scope: null,
826
- status: AXPPageStatus.Processing,
890
+ status: AXPPageStatus.Idle,
827
891
  currentPage: null,
828
892
  currentTab: null,
829
893
  pageSelectedRows: [],
@@ -848,6 +912,10 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
848
912
  //
849
913
  isBusy: computed(() => store.status() == AXPPageStatus.Processing),
850
914
  isSaving: computed(() => store.status() == AXPPageStatus.Submitting),
915
+ isOverlayBusy: computed(() => store.status() === AXPPageStatus.Processing || store.status() === AXPPageStatus.Submitting),
916
+ isPageReady: computed(() => store.adapter() != null &&
917
+ store.currentPage() != null &&
918
+ store.status() === AXPPageStatus.Rendered),
851
919
  isDirty: computed(() => {
852
920
  if (store.currentPage()?.isReadonly) {
853
921
  return false;
@@ -871,7 +939,7 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
871
939
  const evaluatedByTab = store.evaluatedTabContentsById();
872
940
  return evaluatedByTab[tab.id] ?? [];
873
941
  }),
874
- })), withMethods((store, evaluatorService = inject(AXPExpressionEvaluatorService), contextEvalFactory = inject(AXPContextEvalFactory), router = inject(Router), route = inject(ActivatedRoute), deviceService = inject(AXPDeviceService), formatService = inject(AXFormatService), toastService = inject(AXToastService), translateService = inject(AXTranslationService), settingsService = inject(AXPSettingsService)) => {
942
+ })), withMethods((store, evaluatorService = inject(AXPExpressionEvaluatorService), contextEvalFactory = inject(AXPContextEvalFactory), router = inject(Router), route = inject(ActivatedRoute), deviceService = inject(AXPDeviceService), formatService = inject(AXFormatService), toastService = inject(AXToastService), translateService = inject(AXTranslationService), settingsService = inject(AXPSettingsService), layout = inject(AXPLayoutThemeService), adapterLoader = inject(AXP_LAYOUT_DETAILS_VIEW_ADAPTER_LOADER)) => {
875
943
  const resolvePageFromId = (adapter, pageId) => {
876
944
  if (pageId) {
877
945
  return adapter.pages.find((p) => p.id === pageId) ?? null;
@@ -881,49 +949,140 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
881
949
  }
882
950
  return null;
883
951
  };
952
+ /** Serializes page activation so route sync and UI cannot run overlapping loads. */
953
+ let pageActivationChain = Promise.resolve();
954
+ /** Serializes route-driven adapter loads (initial navigation and layout refresh). */
955
+ let routeLoadChain = Promise.resolve();
956
+ /** `page` query param from the browser URL (reliable on hard refresh). */
957
+ const readPageQueryParam = () => {
958
+ const page = router.parseUrl(router.url).queryParams['page'];
959
+ return typeof page === 'string' && page.length > 0 ? page : null;
960
+ };
961
+ /** Snapshot of all page-query sources for trace logs. */
962
+ const pageQueryTraceContext = (extra = {}) => ({
963
+ routerUrl: router.url,
964
+ pageFromRouterUrl: readPageQueryParam(),
965
+ pageFromRouteSnapshot: route.snapshot.queryParamMap.get('page'),
966
+ pageFromRootSnapshot: router.routerState.snapshot.root.queryParams['page'] ?? null,
967
+ currentPageId: store.currentPage()?.id ?? null,
968
+ adapterPageIds: store.adapter()?.pages.map((p) => p.id) ?? [],
969
+ ...extra,
970
+ });
884
971
  /** Loads page data, context, and evaluated widgets for the target sidebar page. */
885
972
  const activatePageById = async (pageId, forceRefresh) => {
973
+ const activation = pageActivationChain.then(() => runPageActivation(pageId, forceRefresh));
974
+ pageActivationChain = activation.catch(() => undefined);
975
+ await activation;
976
+ };
977
+ const runPageActivation = async (pageId, forceRefresh) => {
886
978
  const adapter = store.adapter();
887
979
  if (!adapter) {
888
980
  return;
889
981
  }
890
- const queryParams = router.routerState.snapshot.root.queryParams;
891
- const targetPageId = pageId ?? queryParams['page'];
982
+ const targetPageId = pageId ?? readPageQueryParam() ?? undefined;
892
983
  const currentPage = resolvePageFromId(adapter, targetPageId);
984
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'runPageActivation', () => pageQueryTraceContext({
985
+ passedPageId: pageId ?? null,
986
+ targetPageId: targetPageId ?? null,
987
+ resolvedPageId: currentPage?.id ?? null,
988
+ forceRefresh: forceRefresh ?? false,
989
+ vmStatus: store.status(),
990
+ }));
893
991
  if (!forceRefresh && currentPage?.id === store.currentPage()?.id && store.status() === AXPPageStatus.Rendered) {
992
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'runPageActivation skipped (already rendered)', () => pageQueryTraceContext({
993
+ resolvedPageId: currentPage?.id ?? null,
994
+ }));
894
995
  return;
895
996
  }
997
+ const previousPageId = store.currentPage()?.id;
998
+ const isSidebarSwitch = previousPageId != null && previousPageId !== currentPage?.id;
999
+ if (isSidebarSwitch) {
1000
+ layout.setNavigationLoading(true);
1001
+ }
1002
+ const overlayAlreadyOn = layout.overlayTaskCount() > 0;
1003
+ if (!overlayAlreadyOn) {
1004
+ AXPDebugService.instance?.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'viewmodel', 'activatePage overlay ON', () => ({
1005
+ pageId: currentPage?.id,
1006
+ forceRefresh,
1007
+ isSidebarSwitch,
1008
+ }));
1009
+ layout.setOverlayLoading(true);
1010
+ }
1011
+ else {
1012
+ AXPDebugService.instance?.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'viewmodel', 'activatePage skipped overlay ON (task count > 0)', () => ({
1013
+ pageId: currentPage?.id,
1014
+ forceRefresh,
1015
+ isSidebarSwitch,
1016
+ taskCount: layout.overlayTaskCount(),
1017
+ }));
1018
+ }
896
1019
  patchState(store, {
897
1020
  status: AXPPageStatus.Processing,
898
1021
  });
899
- let context = {};
900
- if (currentPage) {
901
- const currentPageIndex = adapter.pages.findIndex((p) => p.id === currentPage.id);
902
- const loadResult = await adapter.pages[currentPageIndex]?.load?.({ forceRefresh });
903
- context = loadResult?.data ?? {};
904
- }
905
- const currentTab = currentPage?.tabs?.[0] ?? null;
906
- const rootCtx = store.rootContext();
907
- const { evaluatedPageContent, evaluatedTabContentsById } = await buildEvaluatedPageContentsForRootContext(currentPage, rootCtx, evaluatorService);
908
- patchState(store, {
909
- previousContext: cloneDeep(context),
910
- context: cloneDeep(context),
911
- status: AXPPageStatus.Rendered,
912
- currentPage,
913
- currentTab,
914
- evaluatedPageContent,
915
- evaluatedTabContentsById,
916
- formDirty: false,
917
- });
918
- if (currentPage && axpIsEntityDetailsViewRoute(router)) {
919
- const pageParam = route.snapshot.queryParamMap.get('page');
920
- if (pageParam !== currentPage.id) {
921
- router.navigate([], {
922
- relativeTo: route,
923
- queryParams: { page: currentPage.id },
924
- queryParamsHandling: 'merge',
925
- replaceUrl: true,
926
- });
1022
+ try {
1023
+ let context = {};
1024
+ if (currentPage) {
1025
+ const currentPageIndex = adapter.pages.findIndex((p) => p.id === currentPage.id);
1026
+ const pageLoad = adapter.pages[currentPageIndex]?.load;
1027
+ if (typeof pageLoad === 'function') {
1028
+ const loadResult = await pageLoad({ forceRefresh });
1029
+ context = loadResult?.data ?? {};
1030
+ }
1031
+ else {
1032
+ // Component/list sidebar pages have no `load`; keep entity root context so widget
1033
+ // state is not cleared (Change History, etc. use `rootContext` instead).
1034
+ context = cloneDeep(store.rootContext());
1035
+ }
1036
+ }
1037
+ const currentTab = currentPage?.tabs?.[0] ?? null;
1038
+ const shouldSyncRootContext = forceRefresh === true && currentPage?.isPrimary === true && !isEmpty(context);
1039
+ const rootCtx = shouldSyncRootContext
1040
+ ? context
1041
+ : store.rootContext();
1042
+ const { evaluatedPageContent, evaluatedTabContentsById } = await buildEvaluatedPageContentsForRootContext(currentPage, rootCtx, evaluatorService);
1043
+ patchState(store, {
1044
+ previousContext: cloneDeep(context),
1045
+ context: cloneDeep(context),
1046
+ savedContext: cloneDeep(context),
1047
+ ...(shouldSyncRootContext ? { rootContext: cloneDeep(context) } : {}),
1048
+ status: AXPPageStatus.Rendered,
1049
+ currentPage,
1050
+ currentTab,
1051
+ evaluatedPageContent,
1052
+ evaluatedTabContentsById,
1053
+ formDirty: false,
1054
+ });
1055
+ AXPDebugService.instance?.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'viewmodel', 'activatePage VM ready (Rendered)', () => ({
1056
+ pageId: currentPage?.id,
1057
+ forceRefresh,
1058
+ }));
1059
+ const urlPageParam = readPageQueryParam();
1060
+ if (currentPage && axpIsEntityDetailsViewRoute(router)) {
1061
+ if (!urlPageParam) {
1062
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'URL sync — add missing ?page=', () => pageQueryTraceContext({
1063
+ navigateToPageId: currentPage.id,
1064
+ }));
1065
+ router.navigate([], {
1066
+ relativeTo: route,
1067
+ queryParams: { page: currentPage.id },
1068
+ queryParamsHandling: 'merge',
1069
+ replaceUrl: true,
1070
+ });
1071
+ }
1072
+ else {
1073
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'URL sync — skipped (page already in URL)', () => pageQueryTraceContext({
1074
+ urlPageParam,
1075
+ resolvedPageId: currentPage.id,
1076
+ }));
1077
+ }
1078
+ }
1079
+ }
1080
+ finally {
1081
+ if (isSidebarSwitch) {
1082
+ layout.setNavigationLoading(false);
1083
+ }
1084
+ if (store.status() === AXPPageStatus.Processing) {
1085
+ patchState(store, { status: AXPPageStatus.Rendered });
927
1086
  }
928
1087
  }
929
1088
  };
@@ -937,16 +1096,33 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
937
1096
  if (!adapter) {
938
1097
  return;
939
1098
  }
1099
+ // `load()` → `loadPage()` owns the first activation while `currentPage` is still null.
1100
+ if (store.currentPage() == null) {
1101
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'queryParams effect — skipped (currentPage null)', () => pageQueryTraceContext({
1102
+ paramsPage: params['page'] ?? null,
1103
+ }));
1104
+ return;
1105
+ }
940
1106
  const pageId = params['page'];
941
- const targetPage = resolvePageFromId(adapter, pageId);
942
- if (store.currentPage()?.id === targetPage?.id) {
1107
+ if (!pageId) {
1108
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'queryParams effect — skipped (no page param)', () => pageQueryTraceContext({
1109
+ params,
1110
+ }));
943
1111
  return;
944
1112
  }
945
- // `load()` `activatePageById` owns initial hydration when both sides are still null.
946
- if (store.currentPage() == null && targetPage == null) {
1113
+ const targetPage = adapter.pages.find((p) => p.id === pageId);
1114
+ if (!targetPage || store.currentPage()?.id === targetPage.id) {
1115
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'queryParams effect — skipped (same or unknown page)', () => pageQueryTraceContext({
1116
+ paramsPage: pageId,
1117
+ targetPageFound: !!targetPage,
1118
+ }));
947
1119
  return;
948
1120
  }
949
- void activatePageById(targetPage?.id);
1121
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'queryParams effect — activatePageById', () => pageQueryTraceContext({
1122
+ paramsPage: pageId,
1123
+ activatePageId: targetPage.id,
1124
+ }));
1125
+ void activatePageById(targetPage.id);
950
1126
  });
951
1127
  onCleanup(() => subscription.unsubscribe());
952
1128
  });
@@ -1048,7 +1224,7 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1048
1224
  async loadPage(pageId, forceRefresh) {
1049
1225
  await activatePageById(pageId, forceRefresh);
1050
1226
  },
1051
- async load(adapter) {
1227
+ async load(adapter, forceRefresh, pageIdFromUrl) {
1052
1228
  const scope = {
1053
1229
  context: {
1054
1230
  ...contextEvalFactory.createLiveScope(() => store.context()),
@@ -1060,7 +1236,81 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1060
1236
  });
1061
1237
  //
1062
1238
  await this.loadAdapter(adapter);
1063
- await this.loadPage(undefined, true);
1239
+ const pageId = pageIdFromUrl ?? readPageQueryParam() ?? undefined;
1240
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'load — activate page', () => pageQueryTraceContext({
1241
+ pageIdFromUrl: pageIdFromUrl ?? null,
1242
+ resolvedPageId: pageId ?? null,
1243
+ forceRefresh: forceRefresh ?? false,
1244
+ }));
1245
+ await this.loadPage(pageId, forceRefresh);
1246
+ },
1247
+ async loadFromRoute(forceRefresh) {
1248
+ const run = async () => {
1249
+ const pageIdFromUrl = readPageQueryParam() ?? undefined;
1250
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'loadFromRoute start', () => pageQueryTraceContext({
1251
+ pageIdFromUrl: pageIdFromUrl ?? null,
1252
+ forceRefresh: forceRefresh ?? false,
1253
+ }));
1254
+ const moduleName = route.parent?.snapshot.paramMap.get('module');
1255
+ const entityName = route.snapshot.paramMap.get('entity');
1256
+ const id = route.snapshot.paramMap.get('id');
1257
+ if (!moduleName || !entityName || !id) {
1258
+ return;
1259
+ }
1260
+ layout.setNavigationLoading(true);
1261
+ if (layout.overlayTaskCount() === 0) {
1262
+ AXPDebugService.instance?.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'viewmodel', 'loadFromRoute overlay ON', () => ({
1263
+ moduleName,
1264
+ entityName,
1265
+ id,
1266
+ forceRefresh,
1267
+ }));
1268
+ layout.setOverlayLoading(true);
1269
+ }
1270
+ else {
1271
+ AXPDebugService.instance?.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'viewmodel', 'loadFromRoute skipped overlay ON (task count > 0)', () => ({
1272
+ moduleName,
1273
+ entityName,
1274
+ id,
1275
+ forceRefresh,
1276
+ taskCount: layout.overlayTaskCount(),
1277
+ }));
1278
+ }
1279
+ try {
1280
+ if (forceRefresh) {
1281
+ patchState(store, {
1282
+ currentPage: null,
1283
+ status: AXPPageStatus.Idle,
1284
+ });
1285
+ }
1286
+ const adapter = await adapterLoader.load({ moduleName, entityName, id });
1287
+ AXPDebugService.instance?.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'viewmodel', 'adapter loaded (overlay still ON — details-view releases)', () => ({
1288
+ moduleName,
1289
+ entityName,
1290
+ id,
1291
+ }));
1292
+ await this.load(adapter, forceRefresh, pageIdFromUrl);
1293
+ }
1294
+ catch (error) {
1295
+ AXPDebugService.instance?.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'viewmodel', 'loadFromRoute overlay OFF (error)', () => ({
1296
+ moduleName,
1297
+ entityName,
1298
+ id,
1299
+ }));
1300
+ layout.setOverlayLoading(false);
1301
+ if (error instanceof AXPNotFoundError) {
1302
+ void router.navigateByUrl(AXP_NOT_FOUND_ROUTE);
1303
+ return;
1304
+ }
1305
+ throw error;
1306
+ }
1307
+ finally {
1308
+ layout.setNavigationLoading(false);
1309
+ }
1310
+ };
1311
+ const load = routeLoadChain.then(run);
1312
+ routeLoadChain = load.catch(() => undefined);
1313
+ await load;
1064
1314
  },
1065
1315
  updateContext(context) {
1066
1316
  patchState(store, {
@@ -1129,10 +1379,23 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1129
1379
  },
1130
1380
  setCurrentPage(page) {
1131
1381
  const previousPage = store.currentPage();
1382
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'setCurrentPage', () => pageQueryTraceContext({
1383
+ requestedPageId: page?.id ?? null,
1384
+ previousPageId: previousPage?.id ?? null,
1385
+ }));
1132
1386
  if (page) {
1133
- const pageParam = route.snapshot.queryParamMap.get('page');
1387
+ if (!previousPage) {
1388
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'setCurrentPage — ignored (initial load in progress)', () => pageQueryTraceContext({
1389
+ requestedPageId: page.id,
1390
+ }));
1391
+ return;
1392
+ }
1393
+ const pageParam = readPageQueryParam();
1134
1394
  const isSamePage = previousPage?.id === page.id && pageParam === page.id;
1135
1395
  if (!isSamePage && axpIsEntityDetailsViewRoute(router)) {
1396
+ AXPDebugService.instance?.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'viewmodel', 'setCurrentPage — navigate', () => pageQueryTraceContext({
1397
+ navigateToPageId: page.id,
1398
+ }));
1136
1399
  const queryParams = { page: page.id };
1137
1400
  if (previousPage?.id && previousPage.id !== page.id) {
1138
1401
  queryParams['filters'] = null;
@@ -1144,6 +1407,7 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1144
1407
  // Push history for desktop sidebar switches and mobile page-list picks.
1145
1408
  replaceUrl: false,
1146
1409
  });
1410
+ return;
1147
1411
  }
1148
1412
  void activatePageById(page.id);
1149
1413
  }
@@ -1274,13 +1538,16 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1274
1538
  const snapshot = cloneDeep(context);
1275
1539
  patchState(store, {
1276
1540
  context: snapshot,
1541
+ savedContext: snapshot,
1277
1542
  previousContext: snapshot,
1278
1543
  formDirty: false,
1279
1544
  });
1280
1545
  },
1281
1546
  async discard() {
1547
+ const saved = cloneDeep(store.savedContext());
1282
1548
  patchState(store, {
1283
- context: cloneDeep(store.previousContext()),
1549
+ context: saved,
1550
+ previousContext: saved,
1284
1551
  formDirty: false,
1285
1552
  });
1286
1553
  },
@@ -1295,10 +1562,6 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1295
1562
  });
1296
1563
  try {
1297
1564
  const result = await store.currentPage()?.execute?.(command, payload);
1298
- // Clear submitting before post-save refresh so the footer is not left disabled.
1299
- patchState(store, {
1300
- status: AXPPageStatus.Rendered,
1301
- });
1302
1565
  const enableOperationToasts = await settingsService.get(AXPCommonSettings.EnableOperationToasts);
1303
1566
  if (result?.success) {
1304
1567
  try {
@@ -1309,6 +1572,7 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1309
1572
  }
1310
1573
  patchState(store, {
1311
1574
  previousContext: store.context(),
1575
+ savedContext: cloneDeep(store.context()),
1312
1576
  formDirty: false,
1313
1577
  });
1314
1578
  if (enableOperationToasts) {
@@ -1322,9 +1586,6 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1322
1586
  timeOutProgress: true,
1323
1587
  });
1324
1588
  }
1325
- patchState(store, {
1326
- formDirty: false,
1327
- });
1328
1589
  return true;
1329
1590
  }
1330
1591
  const rawText = result?.message?.text;
@@ -1350,9 +1611,6 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1350
1611
  const errorText = error instanceof Error
1351
1612
  ? error.message
1352
1613
  : await translateService.translateAsync('@general:messages.generic.error.description');
1353
- patchState(store, {
1354
- status: AXPPageStatus.Rendered,
1355
- });
1356
1614
  toastService.show({
1357
1615
  color: 'danger',
1358
1616
  title: await translateService.translateAsync('@general:messages.generic.error.title'),
@@ -1365,17 +1623,15 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1365
1623
  return false;
1366
1624
  }
1367
1625
  finally {
1368
- if (store.status() === AXPPageStatus.Submitting) {
1369
- patchState(store, {
1370
- status: AXPPageStatus.Rendered,
1371
- });
1372
- }
1626
+ patchState(store, {
1627
+ status: AXPPageStatus.Rendered,
1628
+ });
1373
1629
  }
1374
1630
  },
1375
- goToListPage() {
1631
+ async goToListPage() {
1376
1632
  const exitUrl = store.adapter()?.exitUrl;
1377
1633
  if (exitUrl) {
1378
- void axpNavigateAppPath(router, exitUrl);
1634
+ await axpNavigateAppPath(router, exitUrl);
1379
1635
  }
1380
1636
  },
1381
1637
  };
@@ -1390,6 +1646,8 @@ const DEFAULT_FOOTER_COMMAND_SHORTCUTS = {
1390
1646
  'update-entity': ['ctrl+s'],
1391
1647
  discard: ['escape'],
1392
1648
  };
1649
+ const SAVE_FOOTER_COMMAND_SUFFIX = ':Save';
1650
+ const DISCARD_FOOTER_COMMAND_SUFFIX = ':Discard';
1393
1651
  /**
1394
1652
  * Returns the base workflow/command name from a composite entity action command id (`cmd&actionName`).
1395
1653
  */
@@ -1420,7 +1678,34 @@ function resolveDetailsViewFooterCommandShortcuts(commandName, explicit) {
1420
1678
  return chords.length ? chords : undefined;
1421
1679
  }
1422
1680
  const defaults = DEFAULT_FOOTER_COMMAND_SHORTCUTS[commandName];
1423
- return defaults?.length ? [...defaults] : undefined;
1681
+ if (defaults?.length) {
1682
+ return [...defaults];
1683
+ }
1684
+ return resolvePageFooterActionDefaultShortcuts(commandName);
1685
+ }
1686
+ /**
1687
+ * Platform defaults for component-page footer save/discard commands (e.g. `MetaDataBuilder:Save`).
1688
+ */
1689
+ function resolvePageFooterActionDefaultShortcuts(commandName) {
1690
+ if (isSaveFooterCommand(commandName)) {
1691
+ return [...DEFAULT_FOOTER_COMMAND_SHORTCUTS['update-entity']];
1692
+ }
1693
+ if (isDiscardFooterCommand(commandName)) {
1694
+ return [...DEFAULT_FOOTER_COMMAND_SHORTCUTS['discard']];
1695
+ }
1696
+ return undefined;
1697
+ }
1698
+ function isSaveFooterCommand(commandName) {
1699
+ return commandName === 'update-entity' || commandName.endsWith(SAVE_FOOTER_COMMAND_SUFFIX);
1700
+ }
1701
+ function isDiscardFooterCommand(commandName) {
1702
+ return commandName === 'discard' || commandName.endsWith(DISCARD_FOOTER_COMMAND_SUFFIX);
1703
+ }
1704
+ /**
1705
+ * Resolves keyboard shortcuts for a footer action on entity detail sub-pages.
1706
+ */
1707
+ function resolvePageFooterActionShortcuts(commandName, explicit) {
1708
+ return resolveDetailsViewFooterCommandShortcuts(commandName, explicit);
1424
1709
  }
1425
1710
  function flattenDetailsViewActionShortcuts(shortcuts) {
1426
1711
  const chords = normalizeKeyboardShortcuts(shortcuts).flatMap((shortcut) => shortcut.keys);
@@ -1582,7 +1867,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1582
1867
  class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1583
1868
  constructor() {
1584
1869
  super(...arguments);
1585
- this.adapter = input.required(...(ngDevMode ? [{ debugName: "adapter" }] : /* istanbul ignore next */ []));
1586
1870
  //
1587
1871
  this.vm = inject(AXPLayoutDetailsViewViewModel);
1588
1872
  this.route = inject(ActivatedRoute);
@@ -1591,13 +1875,21 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1591
1875
  this.unsavedChangesPopstate = inject(AXPUnsavedChangesPopstateService);
1592
1876
  this.pageComponentInstanceRegistry = inject(AXPPageComponentInstanceRegistryService);
1593
1877
  this.shortcutRegistry = inject(AXPKeyboardShortcutRegistry);
1878
+ this.workflowService = inject(AXPWorkflowService);
1594
1879
  this.destroyRef = inject(DestroyRef);
1595
1880
  this.elementRef = inject((ElementRef));
1596
- /** Prevents sidebar tab init events from pushing history before {@link ngOnInit} load completes. */
1597
- this.detailsLayoutReady = false;
1881
+ this.debug = inject(AXPDebugService);
1882
+ /** Prevents sidebar tab init events from pushing history before the first page activation completes. */
1883
+ this.detailsLayoutReady = signal(false, ...(ngDevMode ? [{ debugName: "detailsLayoutReady" }] : /* istanbul ignore next */ []));
1598
1884
  this.destroyed$ = new Subject();
1599
1885
  this.footerActionsGeneration = 0;
1600
1886
  this.keyboardShortcutRegistrationGeneration = 0;
1887
+ /** Page id the overlay release logic is bound to; reset on sidebar/page switch. */
1888
+ this.overlayTargetPageId = null;
1889
+ /** After a page switch, wait for widget registry to clear before accepting remounted widgets. */
1890
+ this.overlaySawZeroWidgetsAfterPageChange = false;
1891
+ /** Cancels in-flight overlay release when the page changes. */
1892
+ this.overlayReleaseGeneration = 0;
1601
1893
  /** Header actions with resolved shortcut chords, keyed by command name. */
1602
1894
  this.actionShortcutEntries = signal(new Map(), ...(ngDevMode ? [{ debugName: "actionShortcutEntries" }] : /* istanbul ignore next */ []));
1603
1895
  this.form = viewChild('form', ...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
@@ -1616,6 +1908,11 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1616
1908
  return;
1617
1909
  }
1618
1910
  untracked(() => queueMicrotask(() => {
1911
+ this.debug.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'details-view', 'sidebarTabs select (sync indicator)', () => ({
1912
+ currentPageId: currentId,
1913
+ tabIndex: index,
1914
+ routerUrl: this.router.url,
1915
+ }));
1619
1916
  this.sidebarTabChangeSuppressed = true;
1620
1917
  try {
1621
1918
  this.sidebarTabs()?.select(index);
@@ -1625,6 +1922,114 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1625
1922
  }
1626
1923
  }));
1627
1924
  }, ...(ngDevMode ? [{ debugName: "#sidebarTabsIndicatorEffect" }] : /* istanbul ignore next */ []));
1925
+ /** Clears the page overlay reactively once VM + widget hydration are both idle. */
1926
+ this.#overlayReleaseEffect = effect(() => {
1927
+ const showPages = this.vm.showPages();
1928
+ const pageId = this.vm.currentPage()?.id;
1929
+ const isVmBusy = this.vm.isOverlayBusy();
1930
+ const isPageReady = this.vm.isPageReady();
1931
+ const container = this.widgetContainer();
1932
+ this.vm.currentPageContent();
1933
+ this.vm.activeTabContent();
1934
+ this.vm.context();
1935
+ container?.builderService.registeredWidgetsCount();
1936
+ container?.builderService.isHydrating();
1937
+ container?.isBusy();
1938
+ container?.isWidgetsReady();
1939
+ const widgetCount = container?.builderService.registeredWidgetsCount() ?? 0;
1940
+ const widgetsBusy = container?.isBusy() ?? false;
1941
+ const widgetsReady = container?.isWidgetsReady() ?? false;
1942
+ untracked(() => {
1943
+ const widgetSnapshot = container?.builderService.getWidgetStateSnapshot();
1944
+ if (pageId !== this.overlayTargetPageId) {
1945
+ const isInitialOverlayBind = this.overlayTargetPageId == null;
1946
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'page bind changed', () => ({
1947
+ pageId,
1948
+ previousPageId: this.overlayTargetPageId,
1949
+ isInitialOverlayBind,
1950
+ overlayReleaseGeneration: this.overlayReleaseGeneration + 1,
1951
+ }));
1952
+ this.overlayTargetPageId = pageId ?? null;
1953
+ // First bind: widgets mount without a prior page registry. Sidebar switch: require clear first.
1954
+ this.overlaySawZeroWidgetsAfterPageChange = isInitialOverlayBind;
1955
+ this.overlayReleaseGeneration += 1;
1956
+ this.overlayReleasePromise = undefined;
1957
+ this.clearOverlayFallback();
1958
+ }
1959
+ if (showPages) {
1960
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'showPages — release overlay', () => ({ isVmBusy }));
1961
+ this.overlayReleaseGeneration += 1;
1962
+ this.overlayReleasePromise = undefined;
1963
+ this.clearOverlayFallback();
1964
+ if (!isVmBusy) {
1965
+ this.clearPageOverlay('showPages — release overlay');
1966
+ }
1967
+ return;
1968
+ }
1969
+ if (isVmBusy || !isPageReady || !pageId) {
1970
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'waiting on VM', () => ({
1971
+ pageId,
1972
+ isVmBusy,
1973
+ isPageReady,
1974
+ }));
1975
+ this.overlayReleaseGeneration += 1;
1976
+ this.overlayReleasePromise = undefined;
1977
+ this.clearOverlayFallback();
1978
+ return;
1979
+ }
1980
+ if (this.getActivePageComponentKey()) {
1981
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'component page — release overlay', () => ({
1982
+ componentKey: this.getActivePageComponentKey(),
1983
+ }));
1984
+ this.overlayReleaseGeneration += 1;
1985
+ this.overlayReleasePromise = undefined;
1986
+ this.clearOverlayFallback();
1987
+ this.clearPageOverlay('component page — release overlay');
1988
+ return;
1989
+ }
1990
+ if (!this.pageHasWidgetNodes()) {
1991
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'no widget nodes — release overlay', () => ({ pageId }));
1992
+ this.overlayReleaseGeneration += 1;
1993
+ this.overlayReleasePromise = undefined;
1994
+ this.clearOverlayFallback();
1995
+ this.clearPageOverlay('no widget nodes — release overlay');
1996
+ return;
1997
+ }
1998
+ if (widgetCount === 0) {
1999
+ this.overlaySawZeroWidgetsAfterPageChange = true;
2000
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'widget registry cleared (remount gate open)', () => ({ pageId }));
2001
+ }
2002
+ if (!this.overlaySawZeroWidgetsAfterPageChange) {
2003
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'blocked: remount gate (await widgetCount=0)', () => ({
2004
+ pageId,
2005
+ widgetCount,
2006
+ ...widgetSnapshot,
2007
+ }));
2008
+ this.scheduleOverlayFallback();
2009
+ return;
2010
+ }
2011
+ if (!widgetsReady || widgetsBusy) {
2012
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'blocked: widgets not ready', () => ({
2013
+ pageId,
2014
+ widgetsReady,
2015
+ widgetsBusy,
2016
+ overlaySawZero: this.overlaySawZeroWidgetsAfterPageChange,
2017
+ releaseInFlight: !!this.overlayReleasePromise,
2018
+ ...widgetSnapshot,
2019
+ hydratingWidgets: widgetSnapshot?.widgets?.filter((w) => w.isHydrating).map((w) => w.id),
2020
+ renderingWidgets: widgetSnapshot?.widgets?.filter((w) => w.status === 'rendering').map((w) => w.id),
2021
+ }));
2022
+ this.scheduleOverlayFallback();
2023
+ return;
2024
+ }
2025
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'request overlay release', () => ({
2026
+ pageId,
2027
+ overlayReleaseGeneration: this.overlayReleaseGeneration,
2028
+ ...widgetSnapshot,
2029
+ }));
2030
+ void this.requestOverlayRelease(pageId);
2031
+ });
2032
+ }, ...(ngDevMode ? [{ debugName: "#overlayReleaseEffect" }] : /* istanbul ignore next */ []));
1628
2033
  this.footerPrimaryActions = signal([], ...(ngDevMode ? [{ debugName: "footerPrimaryActions" }] : /* istanbul ignore next */ []));
1629
2034
  this.footerSecondaryActions = signal([], ...(ngDevMode ? [{ debugName: "footerSecondaryActions" }] : /* istanbul ignore next */ []));
1630
2035
  this.footerActions = computed(() => [...this.footerPrimaryActions(), ...this.footerSecondaryActions()], ...(ngDevMode ? [{ debugName: "footerActions" }] : /* istanbul ignore next */ []));
@@ -1648,7 +2053,14 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1648
2053
  if (this.vm.currentPage()?.isReadonly || this.getActivePageComponentKey()) {
1649
2054
  return false;
1650
2055
  }
1651
- return this.widgetContainer()?.isFormDirty() ?? false;
2056
+ if (this.vm.isOverlayBusy()) {
2057
+ return false;
2058
+ }
2059
+ const container = this.widgetContainer();
2060
+ if (!container?.isSavedCommitted()) {
2061
+ return false;
2062
+ }
2063
+ return container.isFormDirty();
1652
2064
  }, ...(ngDevMode ? [{ debugName: "liveFormIsDirty" }] : /* istanbul ignore next */ []));
1653
2065
  this.hasVisibleFooterPrimaryActions = computed(() => {
1654
2066
  if (this.showSaveDiscardFooter()) {
@@ -1665,11 +2077,25 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1665
2077
  if (this.vm.currentPage()?.isReadonly || this.getActivePageComponentKey()) {
1666
2078
  return;
1667
2079
  }
1668
- const isDirty = this.liveFormIsDirty();
2080
+ if (this.vm.isOverlayBusy()) {
2081
+ return;
2082
+ }
2083
+ const container = this.widgetContainer();
2084
+ if (!container?.isSavedCommitted()) {
2085
+ if (this.vm.formDirty()) {
2086
+ untracked(() => this.vm.setFormDirty(false));
2087
+ }
2088
+ return;
2089
+ }
2090
+ const isDirty = container.isFormDirty();
1669
2091
  if (this.vm.formDirty() === isDirty) {
1670
2092
  return;
1671
2093
  }
1672
2094
  untracked(() => {
2095
+ this.debug.trace(FORM_DIRTY_TRACE_NS, 'details-view', 'formDirty effect', () => ({
2096
+ isDirty,
2097
+ vmFormDirty: this.vm.formDirty(),
2098
+ }));
1673
2099
  this.vm.setFormDirty(isDirty);
1674
2100
  this.recompute();
1675
2101
  });
@@ -1685,18 +2111,21 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1685
2111
  const generation = ++this.footerActionsGeneration;
1686
2112
  this.updateTrigger();
1687
2113
  this.liveFormIsDirty();
1688
- this.vm.isSaving();
2114
+ this.vm.isOverlayBusy();
1689
2115
  void this.refreshFooterActions(generation);
1690
2116
  }, ...(ngDevMode ? [{ debugName: "#FooterActionsEffect" }] : /* istanbul ignore next */ []));
1691
2117
  this.#keyboardShortcutsEffect = effect(() => {
1692
2118
  const generation = ++this.keyboardShortcutRegistrationGeneration;
1693
2119
  this.updateTrigger();
1694
2120
  this.liveFormIsDirty();
1695
- this.vm.isSaving();
2121
+ this.isActivePageComponentDirty();
2122
+ this.vm.isOverlayBusy();
1696
2123
  this.vm.currentPage()?.id;
1697
2124
  untracked(() => void this.refreshKeyboardShortcutRegistrations(generation));
1698
2125
  }, ...(ngDevMode ? [{ debugName: "#keyboardShortcutsEffect" }] : /* istanbul ignore next */ []));
1699
2126
  }
2127
+ /** Safety cap when widget ready detection does not settle. */
2128
+ static { this.overlayMaxWaitMs = 30_000; }
1700
2129
  /** Save/discard use live {@link AXPLayoutDetailsViewViewModel.isDirty}; other actions use evaluated `visible`. */
1701
2130
  static isTruthyActionFlag(value) {
1702
2131
  if (value === true) {
@@ -1723,6 +2152,8 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1723
2152
  }
1724
2153
  /** Syncs the line indicator when the active page changes programmatically. */
1725
2154
  #sidebarTabsIndicatorEffect;
2155
+ /** Clears the page overlay reactively once VM + widget hydration are both idle. */
2156
+ #overlayReleaseEffect;
1726
2157
  isSaveDiscardFooterAction(action) {
1727
2158
  const commandName = action.command?.name;
1728
2159
  const acceptCommand = this.vm.currentPage()?.settings?.commands?.accept?.command?.name;
@@ -1741,35 +2172,43 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1741
2172
  return AXPLayoutDetailsViewComponent.isTruthyActionFlag(action.visible);
1742
2173
  }
1743
2174
  isFooterActionDisabled(action) {
1744
- if (this.vm.isSaving()) {
2175
+ if (this.vm.isOverlayBusy()) {
1745
2176
  return true;
1746
2177
  }
1747
2178
  return AXPLayoutDetailsViewComponent.isTruthyActionFlag(action.disabled);
1748
2179
  }
1749
2180
  /**
1750
- * Append timestamp query param to trigger router to re-run guards/resolvers
2181
+ * Re-fetches the entity adapter and reloads the active page.
1751
2182
  */
1752
2183
  async refreshLayout() {
1753
- const router = this.router;
1754
- const route = this.route;
1755
- const now = Date.now();
1756
2184
  this.unsavedChangesConfirm.markLeaveConfirmed();
1757
- await router.navigate([], {
1758
- relativeTo: route,
1759
- queryParams: { _ts: now },
1760
- queryParamsHandling: 'merge',
1761
- replaceUrl: true,
1762
- });
2185
+ this.detailsLayoutReady.set(false);
2186
+ try {
2187
+ await this.vm.loadFromRoute(true);
2188
+ }
2189
+ finally {
2190
+ this.detailsLayoutReady.set(true);
2191
+ }
1763
2192
  }
1764
2193
  async ngOnInit() {
1765
2194
  await super.ngOnInit();
2195
+ this.debug.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'details-view', 'ngOnInit — before loadFromRoute', () => ({
2196
+ routerUrl: this.router.url,
2197
+ pageFromRouterUrl: this.router.parseUrl(this.router.url).queryParams['page'] ?? null,
2198
+ pageFromRouteSnapshot: this.route.snapshot.queryParamMap.get('page'),
2199
+ }));
1766
2200
  this.unsavedChangesPopstate.registerSource({
1767
2201
  id: 'axp-layout-details-view',
1768
- isDirty: () => this.shouldPromptLeave(),
2202
+ isDirty: () => this.hasUnsavedChanges(),
1769
2203
  });
2204
+ this.destroyRef.onDestroy(() => this.unsavedChangesPopstate.unregisterSource('axp-layout-details-view'));
1770
2205
  //
1771
- await this.vm.load(this.adapter());
1772
- this.detailsLayoutReady = true;
2206
+ await this.vm.loadFromRoute();
2207
+ this.debug.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'details-view', 'ngOnInit — after loadFromRoute', () => ({
2208
+ routerUrl: this.router.url,
2209
+ currentPageId: this.vm.currentPage()?.id ?? null,
2210
+ }));
2211
+ this.detailsLayoutReady.set(true);
1773
2212
  void this.refreshKeyboardShortcutRegistrations(++this.keyboardShortcutRegistrationGeneration);
1774
2213
  this.eventService
1775
2214
  //TODO: Use the constant from the entity module
@@ -1780,6 +2219,37 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1780
2219
  this.refreshLayout();
1781
2220
  }
1782
2221
  });
2222
+ this.workflowService.events$
2223
+ .pipe(filter$1((event) => event.type === AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE), takeUntil(this.destroyed$))
2224
+ .subscribe((event) => {
2225
+ void this.handleEntityDeleted(event.payload);
2226
+ });
2227
+ }
2228
+ /** Navigates to {@link AXPLayoutDetailsViewAdapter.exitUrl} when the open record was deleted. */
2229
+ async handleEntityDeleted(payload) {
2230
+ if (!payload?.entity || !payload.ids?.length) {
2231
+ return;
2232
+ }
2233
+ const adapterName = this.vm.adapter()?.name;
2234
+ const recordId = this.vm.context()?.['id'];
2235
+ if (!adapterName || recordId == null) {
2236
+ return;
2237
+ }
2238
+ const deletedIds = payload.ids.map((id) => String(id));
2239
+ if (payload.entity !== adapterName || !deletedIds.includes(String(recordId))) {
2240
+ return;
2241
+ }
2242
+ this.unsavedChangesConfirm.markLeaveConfirmed();
2243
+ if (this.tabNavigation.effectiveMode() === 'tabular') {
2244
+ const tabKey = this.getPageTabKey();
2245
+ await this.vm.goToListPage();
2246
+ if (tabKey) {
2247
+ this.unsavedChangesConfirm.markLeaveConfirmed();
2248
+ await this.tabNavigation.closeTab(tabKey);
2249
+ }
2250
+ return;
2251
+ }
2252
+ await this.vm.goToListPage();
1783
2253
  }
1784
2254
  async ngAfterViewInit() {
1785
2255
  const listWidget = (await this.widgetContainer()?.find('page-list_table'));
@@ -1794,9 +2264,12 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1794
2264
  }
1795
2265
  }
1796
2266
  ngOnDestroy() {
1797
- this.unsavedChangesPopstate.unregisterSource('axp-layout-details-view');
1798
2267
  this.onSelectionChangeSubscription?.unsubscribe();
1799
2268
  ++this.keyboardShortcutRegistrationGeneration;
2269
+ this.clearOverlayFallback();
2270
+ this.overlayReleaseGeneration += 1;
2271
+ this.overlayReleasePromise = undefined;
2272
+ this.clearPageOverlay('ngOnDestroy');
1800
2273
  this.destroyed$.next();
1801
2274
  this.destroyed$.complete();
1802
2275
  }
@@ -1817,28 +2290,171 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1817
2290
  this.footerSecondaryActions.set(footerSecondaryActions);
1818
2291
  }
1819
2292
  handleOnContextChanged(e) {
1820
- this.vm.setFormDirty(e.isFormDirty ?? false);
2293
+ if (!this.vm.currentPage()?.isReadonly &&
2294
+ !this.getActivePageComponentKey() &&
2295
+ this.widgetContainer()?.isSavedCommitted()) {
2296
+ const isDirty = e.isFormDirty ?? false;
2297
+ const container = this.widgetContainer();
2298
+ this.debug.trace(FORM_DIRTY_TRACE_NS, 'details-view', 'handleOnContextChanged', () => ({
2299
+ isFormDirty: isDirty,
2300
+ vmFormDirty: this.vm.formDirty(),
2301
+ changePath: e.path,
2302
+ changeOrigin: e.origin,
2303
+ userEditedSinceCommit: container?.contextService.hasUserEditedSinceCommit(),
2304
+ dirtyPaths: container
2305
+ ? summarizeFormContextDirtyDiff(container.contextService.data(), container.contextService.saved())
2306
+ : [],
2307
+ }));
2308
+ if (this.vm.formDirty() !== isDirty) {
2309
+ this.vm.setFormDirty(isDirty);
2310
+ }
2311
+ }
1821
2312
  this.recompute();
1822
2313
  }
1823
2314
  getLiveFormContext() {
1824
2315
  const container = this.widgetContainer();
1825
2316
  return (container?.contextService.data() ?? this.vm.context());
1826
2317
  }
2318
+ /** Whether the active page renders widget nodes (not only hosted components). */
2319
+ pageHasWidgetNodes() {
2320
+ const pageWidgets = this.vm.currentPageContent();
2321
+ if (pageWidgets.some((item) => !('type' in item && item.type === 'component'))) {
2322
+ return true;
2323
+ }
2324
+ return this.vm.activeTabContent().length > 0;
2325
+ }
2326
+ /** Clears all overlay loading tasks once the page (or hosted view) is ready. */
2327
+ clearPageOverlay(reason) {
2328
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', reason, () => ({
2329
+ taskCount: this.layoutService.overlayTaskCount(),
2330
+ }));
2331
+ this.layoutService.clearOverlayLoading();
2332
+ }
2333
+ scheduleOverlayFallback() {
2334
+ if (this.overlayFallbackTimer) {
2335
+ return;
2336
+ }
2337
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'schedule fallback timer', () => ({
2338
+ timeoutMs: AXPLayoutDetailsViewComponent.overlayMaxWaitMs,
2339
+ pageId: this.overlayTargetPageId,
2340
+ }));
2341
+ this.overlayFallbackTimer = setTimeout(() => {
2342
+ this.overlayFallbackTimer = undefined;
2343
+ const isOverlayLoading = this.layoutService.isOverlayLoading();
2344
+ const isVmBusy = this.vm.isOverlayBusy();
2345
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'fallback timer fired', () => ({
2346
+ isOverlayLoading,
2347
+ isVmBusy,
2348
+ pageId: this.overlayTargetPageId,
2349
+ }));
2350
+ if (!isOverlayLoading) {
2351
+ return;
2352
+ }
2353
+ if (!isVmBusy) {
2354
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'fallback forcing overlay off', () => ({
2355
+ taskCount: this.layoutService.overlayTaskCount(),
2356
+ }));
2357
+ this.clearPageOverlay('fallback forcing overlay off');
2358
+ }
2359
+ }, AXPLayoutDetailsViewComponent.overlayMaxWaitMs);
2360
+ }
2361
+ clearOverlayFallback() {
2362
+ if (this.overlayFallbackTimer) {
2363
+ clearTimeout(this.overlayFallbackTimer);
2364
+ this.overlayFallbackTimer = undefined;
2365
+ }
2366
+ }
2367
+ /**
2368
+ * Hides overlay after the widget container reports continuous idle (same gate as saved baseline).
2369
+ */
2370
+ requestOverlayRelease(pageId) {
2371
+ if (this.overlayReleasePromise) {
2372
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'release skipped — already in flight', () => ({ pageId }));
2373
+ return;
2374
+ }
2375
+ const generation = this.overlayReleaseGeneration;
2376
+ const container = this.widgetContainer();
2377
+ if (!container) {
2378
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'release skipped — no container', () => ({ pageId }));
2379
+ this.scheduleOverlayFallback();
2380
+ return;
2381
+ }
2382
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'waitUntilSettled started', () => ({ pageId, generation }));
2383
+ this.overlayReleasePromise = container
2384
+ .waitUntilSettled()
2385
+ .then(() => {
2386
+ const latest = this.widgetContainer();
2387
+ const snapshot = latest?.builderService.getWidgetStateSnapshot();
2388
+ if (generation !== this.overlayReleaseGeneration) {
2389
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'release aborted — generation mismatch', () => ({
2390
+ pageId,
2391
+ generation,
2392
+ currentGeneration: this.overlayReleaseGeneration,
2393
+ }));
2394
+ return;
2395
+ }
2396
+ if (pageId !== this.overlayTargetPageId || pageId !== this.vm.currentPage()?.id) {
2397
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'release aborted — page changed', () => ({
2398
+ pageId,
2399
+ overlayTargetPageId: this.overlayTargetPageId,
2400
+ currentPageId: this.vm.currentPage()?.id,
2401
+ }));
2402
+ return;
2403
+ }
2404
+ if (this.vm.isOverlayBusy()) {
2405
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'release aborted — VM still busy', () => ({ pageId }));
2406
+ return;
2407
+ }
2408
+ if (!latest?.isWidgetsReady() || latest.isBusy()) {
2409
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'release aborted — widgets not ready after settle', () => ({
2410
+ pageId,
2411
+ widgetsReady: latest?.isWidgetsReady(),
2412
+ widgetsBusy: latest?.isBusy(),
2413
+ ...snapshot,
2414
+ }));
2415
+ return;
2416
+ }
2417
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'release overlay OFF', () => ({
2418
+ pageId,
2419
+ generation,
2420
+ taskCount: this.layoutService.overlayTaskCount(),
2421
+ ...snapshot,
2422
+ }));
2423
+ this.clearOverlayFallback();
2424
+ this.clearPageOverlay('widgets settled — release overlay');
2425
+ })
2426
+ .finally(() => {
2427
+ this.overlayReleasePromise = undefined;
2428
+ });
2429
+ }
1827
2430
  async finalizeSave() {
1828
2431
  const container = this.widgetContainer();
1829
2432
  if (!container) {
1830
2433
  this.vm.setFormDirty(false);
1831
2434
  return;
1832
2435
  }
1833
- const savedContext = this.vm.context();
1834
- await container.replaceContext(savedContext);
1835
- this.vm.applySavedState(container.contextService.data());
2436
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'finalizeSave overlay ON');
2437
+ this.layoutService.setOverlayLoading(true);
2438
+ try {
2439
+ const savedContext = this.vm.context();
2440
+ await container.replaceContext(savedContext);
2441
+ this.vm.applySavedState(container.contextService.data());
2442
+ if (!this.getActivePageComponentKey()) {
2443
+ await container.settleSavedBaseline();
2444
+ }
2445
+ }
2446
+ finally {
2447
+ this.debug.trace(OVERLAY_DETAILS_VIEW_TRACE_NS, 'details-view', 'finalizeSave overlay OFF');
2448
+ this.layoutService.setOverlayLoading(false);
2449
+ }
1836
2450
  }
1837
2451
  finalizeDiscard() {
2452
+ this.debug.trace(FORM_DIRTY_TRACE_NS, 'details-view', 'finalizeDiscard');
1838
2453
  const container = this.widgetContainer();
1839
2454
  if (container) {
1840
2455
  container.revertAndSettle();
1841
- this.vm.applySavedState(container.contextService.data());
2456
+ const saved = container.contextService.saved();
2457
+ this.vm.applySavedState(saved);
1842
2458
  return;
1843
2459
  }
1844
2460
  void this.vm.discard();
@@ -1852,15 +2468,21 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1852
2468
  * `ax-tabs` selects on click before we can confirm. Revert synchronously, then confirm + switch.
1853
2469
  */
1854
2470
  handleSidebarTabChanged(event) {
1855
- if (!this.detailsLayoutReady || this.sidebarTabChangeSuppressed) {
2471
+ if (!this.detailsLayoutReady() || this.sidebarTabChangeSuppressed) {
1856
2472
  return;
1857
2473
  }
1858
2474
  const pages = this.vm.adapter()?.pages ?? [];
1859
2475
  const target = pages[event.index];
1860
2476
  const currentId = this.vm.currentPage()?.id;
1861
- if (!target || target.id === currentId) {
2477
+ if (!currentId || !target || target.id === currentId) {
1862
2478
  return;
1863
2479
  }
2480
+ this.debug.trace(DETAILS_VIEW_PAGE_TRACE_NS, 'details-view', 'handleSidebarTabChanged', () => ({
2481
+ routerUrl: this.router.url,
2482
+ targetPageId: target.id,
2483
+ currentPageId: currentId ?? null,
2484
+ tabIndex: event.index,
2485
+ }));
1864
2486
  const activeIndex = pages.findIndex((page) => page.id === currentId);
1865
2487
  if (activeIndex >= 0) {
1866
2488
  this.sidebarTabChangeSuppressed = true;
@@ -1943,13 +2565,7 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1943
2565
  return this.vm.getBackButton();
1944
2566
  }
1945
2567
  hasUnsavedChanges() {
1946
- if (this.vm.currentPage()?.isReadonly) {
1947
- return false;
1948
- }
1949
- if (this.isActivePageComponentDirty()) {
1950
- return true;
1951
- }
1952
- return this.liveFormIsDirty();
2568
+ return this.shouldPromptLeave();
1953
2569
  }
1954
2570
  async getPageBadge() {
1955
2571
  if (this.vm.currentPage()?.isReadonly) {
@@ -1997,6 +2613,9 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1997
2613
  }
1998
2614
  /** Background tab close — confirm without discarding (the cached instance is destroyed). */
1999
2615
  onBeforeTabClose() {
2616
+ if (this.unsavedChangesConfirm.hasLeaveConfirmed()) {
2617
+ return Promise.resolve(true);
2618
+ }
2000
2619
  return this.unsavedChangesConfirm.confirmIfDirty(this.shouldPromptLeave(), {
2001
2620
  approveLeaveOnConfirm: false,
2002
2621
  });
@@ -2035,6 +2654,23 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2035
2654
  isActivePageComponentDirty() {
2036
2655
  return this.getActivePageComponentInstance()?.hasUnsavedChanges() ?? false;
2037
2656
  }
2657
+ /**
2658
+ * Widget-form dirty state for leave guards (popstate, canDeactivate).
2659
+ * Unlike {@link liveFormIsDirty}, does not suppress dirty while overlay is busy.
2660
+ */
2661
+ hasWidgetFormUnsavedChanges() {
2662
+ if (this.getActivePageComponentKey()) {
2663
+ return false;
2664
+ }
2665
+ const container = this.widgetContainer();
2666
+ if (!container) {
2667
+ return this.vm.formDirty();
2668
+ }
2669
+ if (container.isSavedCommitted()) {
2670
+ return container.isFormDirty();
2671
+ }
2672
+ return container.contextService.hasUserEditedSinceCommit() || this.vm.formDirty();
2673
+ }
2038
2674
  /** Whether the current details page has user-origin unsaved edits (form or component page). */
2039
2675
  shouldPromptLeave() {
2040
2676
  if (this.vm.currentPage()?.isReadonly) {
@@ -2043,7 +2679,7 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2043
2679
  if (this.isActivePageComponentDirty()) {
2044
2680
  return true;
2045
2681
  }
2046
- return this.liveFormIsDirty();
2682
+ return this.hasWidgetFormUnsavedChanges();
2047
2683
  }
2048
2684
  /** Single gate for leaving the page or switching details sub-pages when dirty. */
2049
2685
  async confirmLeaveIfDirty() {
@@ -2168,17 +2804,59 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2168
2804
  this.registerCoreKeyboardShortcuts();
2169
2805
  this.registerActionKeyboardShortcuts(entries);
2170
2806
  }
2807
+ /** i18n scope label for the active details sub-page shortcut group in the help dialog. */
2808
+ getKeyboardShortcutScope() {
2809
+ const page = this.vm.currentPage();
2810
+ if (page?.isPrimary) {
2811
+ return '@general:keyboard-shortcuts.groups.entity-details';
2812
+ }
2813
+ const label = page?.label;
2814
+ if (typeof label === 'string' && label.length > 0) {
2815
+ return label;
2816
+ }
2817
+ return page?.id ?? '@general:keyboard-shortcuts.groups.entity-details';
2818
+ }
2819
+ /** Primary overview page backed by the entity widget form (not a component-hosted sub-page). */
2820
+ isWidgetFormPrimaryPage() {
2821
+ return !!this.vm.currentPage()?.isPrimary && !this.getActivePageComponentKey();
2822
+ }
2823
+ registerDetailsViewShortcutScope(id, shortcuts) {
2824
+ const scope = this.getKeyboardShortcutScope();
2825
+ this.shortcutRegistry.register({
2826
+ owner: this.destroyRef,
2827
+ elementRef: this.elementRef,
2828
+ id,
2829
+ priority: AXPKeyboardShortcutPriority.Page,
2830
+ scope,
2831
+ shortcuts,
2832
+ });
2833
+ }
2171
2834
  async collectActionShortcutEntries() {
2172
2835
  const map = new Map();
2173
2836
  if (this.vm.showPages()) {
2174
2837
  return map;
2175
2838
  }
2176
- const [primaryActions, secondaryActions] = await Promise.all([
2177
- this.getAllPrimaryActions(),
2178
- this.getAllSecondaryActions(),
2839
+ const includeAdapterActions = this.isWidgetFormPrimaryPage();
2840
+ const [adapterPrimaryActions, adapterSecondaryActions, pagePrimaryActions, pageSecondaryActions] = await Promise.all([
2841
+ includeAdapterActions ? this.vm.primaryActions() : Promise.resolve([]),
2842
+ includeAdapterActions ? this.vm.secondaryActions() : Promise.resolve([]),
2843
+ this.vm.currentPagePrimaryActions(),
2844
+ this.vm.currentPageSecondaryActions(),
2179
2845
  ]);
2180
- for (const action of [...primaryActions, ...secondaryActions]) {
2181
- if (action.zone !== 'header' || this.isSaveDiscardFooterAction(action)) {
2846
+ for (const action of [
2847
+ ...adapterPrimaryActions,
2848
+ ...adapterSecondaryActions,
2849
+ ...pagePrimaryActions,
2850
+ ...pageSecondaryActions,
2851
+ ]) {
2852
+ const zone = action.zone ?? 'header';
2853
+ if (zone !== 'header' && zone !== 'footer') {
2854
+ continue;
2855
+ }
2856
+ if (zone === 'footer' && this.isWidgetFormPrimaryPage() && this.isSaveDiscardFooterAction(action)) {
2857
+ continue;
2858
+ }
2859
+ if (zone === 'header' && this.isSaveDiscardFooterAction(action)) {
2182
2860
  continue;
2183
2861
  }
2184
2862
  const commandName = action.command?.name;
@@ -2187,7 +2865,9 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2187
2865
  continue;
2188
2866
  }
2189
2867
  const commandBaseName = getDetailsViewActionCommandBaseName(commandName);
2190
- const chords = resolveDetailsViewActionShortcuts(commandBaseName, action.shortcuts);
2868
+ const chords = zone === 'footer'
2869
+ ? resolvePageFooterActionShortcuts(commandBaseName, action.shortcuts)
2870
+ : resolveDetailsViewActionShortcuts(commandBaseName, action.shortcuts);
2191
2871
  if (!chords?.length) {
2192
2872
  continue;
2193
2873
  }
@@ -2195,13 +2875,13 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2195
2875
  command,
2196
2876
  title: typeof action.title === 'string' ? action.title : '',
2197
2877
  chords,
2198
- visible: this.isHeaderActionAvailable(action),
2878
+ visible: this.isShortcutActionAvailable(action),
2199
2879
  disabled: AXPLayoutDetailsViewComponent.isTruthyActionFlag(action.disabled),
2200
2880
  });
2201
2881
  }
2202
2882
  return map;
2203
2883
  }
2204
- isHeaderActionAvailable(action) {
2884
+ isShortcutActionAvailable(action) {
2205
2885
  if (AXPLayoutDetailsViewComponent.isTruthyActionFlag(action.hidden)) {
2206
2886
  return false;
2207
2887
  }
@@ -2210,15 +2890,15 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2210
2890
  }
2211
2891
  return true;
2212
2892
  }
2213
- /** Whether save/discard core shortcuts are listed in the help dialog (page supports them). */
2893
+ /** Whether save/discard core shortcuts are listed in the help dialog (widget overview page only). */
2214
2894
  isCoreSaveShortcutAvailable() {
2215
- return !this.vm.currentPage()?.isReadonly && !!this.acceptFooterCommand();
2895
+ return this.isWidgetFormPrimaryPage() && !this.vm.currentPage()?.isReadonly && !!this.acceptFooterCommand();
2216
2896
  }
2217
2897
  isCoreDiscardShortcutAvailable() {
2218
- return !this.vm.currentPage()?.isReadonly && !!this.rejectFooterCommand();
2898
+ return this.isWidgetFormPrimaryPage() && !this.vm.currentPage()?.isReadonly && !!this.rejectFooterCommand();
2219
2899
  }
2220
2900
  canExecuteSaveShortcut() {
2221
- if (this.vm.currentPage()?.isReadonly || this.vm.isSaving()) {
2901
+ if (this.vm.currentPage()?.isReadonly || this.vm.isOverlayBusy()) {
2222
2902
  return false;
2223
2903
  }
2224
2904
  if (!this.acceptFooterCommand()) {
@@ -2227,7 +2907,7 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2227
2907
  return this.shouldPromptLeave();
2228
2908
  }
2229
2909
  canExecuteDiscardShortcut() {
2230
- if (this.vm.currentPage()?.isReadonly || this.vm.isSaving()) {
2910
+ if (this.vm.currentPage()?.isReadonly || this.vm.isOverlayBusy()) {
2231
2911
  return false;
2232
2912
  }
2233
2913
  if (this.unsavedChangesConfirm.isConfirmPending()) {
@@ -2252,8 +2932,31 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2252
2932
  }
2253
2933
  await this.execute({ name: rejectCommandName });
2254
2934
  }
2935
+ async executeActionShortcut(entry) {
2936
+ const commandName = entry.command.name;
2937
+ if (isDiscardFooterCommand(commandName)) {
2938
+ if (this.vm.currentPage()?.isReadonly || this.vm.isOverlayBusy()) {
2939
+ return;
2940
+ }
2941
+ if (this.unsavedChangesConfirm.isConfirmPending()) {
2942
+ return;
2943
+ }
2944
+ if (!this.shouldPromptLeave()) {
2945
+ return;
2946
+ }
2947
+ const confirmed = await this.unsavedChangesConfirm.confirmIfDirty(true, {
2948
+ title: '@general:messages.unsaved-changes.title',
2949
+ message: '@general:messages.discard-changes.message',
2950
+ approveLeaveOnConfirm: false,
2951
+ });
2952
+ if (!confirmed) {
2953
+ return;
2954
+ }
2955
+ }
2956
+ await this.execute(entry.command);
2957
+ }
2255
2958
  isActionShortcutActive(entryId) {
2256
- if (this.vm.currentPage()?.isReadonly || this.vm.isSaving()) {
2959
+ if (this.vm.currentPage()?.isReadonly || this.vm.isOverlayBusy()) {
2257
2960
  return false;
2258
2961
  }
2259
2962
  const entry = this.actionShortcutEntries().get(entryId);
@@ -2263,18 +2966,23 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2263
2966
  return entry.visible && !entry.disabled;
2264
2967
  }
2265
2968
  registerCoreKeyboardShortcuts() {
2969
+ if (!this.isWidgetFormPrimaryPage()) {
2970
+ this.registerDetailsViewShortcutScope('layout-details-view-core', []);
2971
+ return;
2972
+ }
2266
2973
  const accept = this.vm.currentPage()?.settings?.commands?.accept;
2267
2974
  const reject = this.vm.currentPage()?.settings?.commands?.reject;
2268
2975
  const acceptCommandName = accept?.command.name ?? 'update-entity';
2269
2976
  const rejectCommandName = reject?.command.name ?? 'discard';
2270
2977
  const saveKeys = resolveDetailsViewFooterCommandShortcuts(acceptCommandName, accept?.shortcuts);
2271
2978
  const discardKeys = resolveDetailsViewFooterCommandShortcuts(rejectCommandName, reject?.shortcuts);
2979
+ const scope = this.getKeyboardShortcutScope();
2272
2980
  const shortcuts = [];
2273
2981
  if (saveKeys?.length && this.isCoreSaveShortcutAvailable()) {
2274
2982
  shortcuts.push({
2275
2983
  keys: saveKeys,
2276
2984
  title: accept?.title ?? '@general:actions.save.title',
2277
- group: '@general:keyboard-shortcuts.groups.entity-details',
2985
+ group: scope,
2278
2986
  allowInEditableFields: true,
2279
2987
  when: () => this.canExecuteSaveShortcut(),
2280
2988
  handler: () => {
@@ -2286,7 +2994,7 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2286
2994
  shortcuts.push({
2287
2995
  keys: discardKeys,
2288
2996
  title: reject?.title ?? '@general:actions.discard.title',
2289
- group: '@general:keyboard-shortcuts.groups.entity-details',
2997
+ group: scope,
2290
2998
  allowInEditableFields: true,
2291
2999
  when: () => this.canExecuteDiscardShortcut(),
2292
3000
  handler: () => {
@@ -2294,62 +3002,44 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2294
3002
  },
2295
3003
  });
2296
3004
  }
2297
- if (shortcuts.length === 0) {
2298
- return;
2299
- }
2300
- this.shortcutRegistry.register({
2301
- owner: this.destroyRef,
2302
- elementRef: this.elementRef,
2303
- id: 'layout-details-view-core',
2304
- priority: AXPKeyboardShortcutPriority.Page,
2305
- scope: '@general:keyboard-shortcuts.groups.entity-details',
2306
- shortcuts,
2307
- });
3005
+ this.registerDetailsViewShortcutScope('layout-details-view-core', shortcuts);
2308
3006
  }
2309
3007
  registerActionKeyboardShortcuts(entries) {
3008
+ const scope = this.getKeyboardShortcutScope();
2310
3009
  const shortcuts = [];
2311
3010
  for (const [entryId, entry] of entries) {
2312
3011
  for (const chord of entry.chords) {
2313
3012
  shortcuts.push({
2314
3013
  keys: [chord],
2315
3014
  title: entry.title,
2316
- group: '@general:keyboard-shortcuts.groups.entity-details',
3015
+ group: scope,
3016
+ allowInEditableFields: entry.command.name ? isSaveFooterCommand(entry.command.name) || isDiscardFooterCommand(entry.command.name) : false,
2317
3017
  when: () => this.isActionShortcutActive(entryId),
2318
3018
  handler: () => {
2319
3019
  if (!this.isActionShortcutActive(entryId)) {
2320
3020
  return;
2321
3021
  }
2322
- void this.execute(entry.command);
3022
+ void this.executeActionShortcut(entry);
2323
3023
  },
2324
3024
  });
2325
3025
  }
2326
3026
  }
2327
- if (shortcuts.length === 0) {
2328
- return;
2329
- }
2330
- this.shortcutRegistry.register({
2331
- owner: this.destroyRef,
2332
- elementRef: this.elementRef,
2333
- id: 'layout-details-view-actions',
2334
- priority: AXPKeyboardShortcutPriority.Page,
2335
- scope: '@general:keyboard-shortcuts.groups.entity-details',
2336
- shortcuts,
2337
- });
3027
+ this.registerDetailsViewShortcutScope('layout-details-view-actions', shortcuts);
2338
3028
  }
2339
3029
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLayoutDetailsViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2340
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLayoutDetailsViewComponent, isStandalone: true, selector: "axp-layout-details-view", inputs: { adapter: { classPropertyName: "adapter", publicName: "adapter", isSignal: true, isRequired: true, transformFunction: null } }, providers: [
3030
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLayoutDetailsViewComponent, isStandalone: true, selector: "axp-layout-details-view", providers: [
2341
3031
  {
2342
3032
  provide: AXPPageLayoutBase,
2343
3033
  useExisting: AXPLayoutDetailsViewComponent,
2344
3034
  },
2345
3035
  AXPLayoutDetailsViewViewModel,
2346
- ], viewQueries: [{ propertyName: "form", first: true, predicate: ["form"], descendants: true, isSignal: true }, { propertyName: "widgetContainer", first: true, predicate: AXPWidgetContainerComponent, descendants: true, isSignal: true }, { propertyName: "sidebarTabs", first: true, predicate: ["sidebarTabs"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<axp-page-layout *translate=\"let t\">\n @if (vm.adapter()?.pages?.length! > 1 && vm.isLarge()) {\n <axp-layout-start-side>\n <axp-layout-header>\n <axp-layout-title>{{\n formatService.format(\n vm.showPages() ? (vm.adapter()?.title ?? '') : (vm.adapter()?.label ?? ''),\n 'string',\n vm.rootContext()\n )\n | translate\n | async\n }}</axp-layout-title>\n <axp-layout-description>{{\n formatService.format(vm.adapter()?.description ?? '', 'string', vm.rootContext()) | translate | async\n }}</axp-layout-description>\n </axp-layout-header>\n <axp-layout-content>\n <ax-tabs\n #sidebarTabs\n class=\"axp-vertical-tabs\"\n [look]=\"'with-line-color'\"\n [location]=\"'end'\"\n [fitParent]=\"true\"\n (onActiveTabChanged)=\"handleSidebarTabChanged($event)\"\n >\n @for (item of vm.adapter()?.pages; track item.id) {\n <ax-tab-item\n [key]=\"item.id\"\n [text]=\"(formatService.format(item.label, 'string', vm.rootContext()) | translate | async)!\"\n [active]=\"vm.currentPage()?.id === item.id\"\n >\n <ax-prefix>\n <ax-icon icon=\"far ${{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n }\n </ax-tabs>\n </axp-layout-content>\n </axp-layout-start-side>\n }\n <!-- Content Section -->\n <axp-page-content class=\"ax-flex ax-flex-row ax-gap-4\">\n @if (vm.showPages()) {\n <axp-layout-list class=\"ax-w-full\">\n @for (item of vm.adapter()?.pages; track $index) {\n <axp-layout-list-item (click)=\"handleSelectPage(item)\">\n <axp-layout-prefix>\n <ax-icon icon=\"far ${{ item.icon }}\" class=\"ax-text-gray-500\"></ax-icon>\n </axp-layout-prefix>\n <axp-layout-content>\n <a class=\"ax-font-semibold\">{{\n formatService.format(item.label, 'string', vm.rootContext()) | translate | async\n }}</a>\n </axp-layout-content>\n <axp-layout-suffix>\n <ax-icon icon=\" far fa-chevron-right\" class=\"ax-text-gray-400\"></ax-icon>\n </axp-layout-suffix>\n </axp-layout-list-item>\n }\n </axp-layout-list>\n } @else {\n @if (vm.isBusy()) {\n <div class=\"ax-flex ax-h-full ax-w-full ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n } @else {\n <ax-form class=\"ax-h-full ax-w-full\" #form>\n <axp-widgets-container\n #widgetsContainerRef\n [context]=\"vm.context()\"\n (onContextChanged)=\"handleOnContextChanged($event)\"\n >\n <div class=\"ax-flex ax-flex-col ax-w-full ax-gap-4 ax-h-full\">\n @for (item of vm.currentPageContent(); track pageContentTrackKey($any(item), $index)) {\n @if ('type' in item && item.type === 'component') {\n <!-- Component-based content -->\n <div\n axp-page-component-renderer\n [componentKey]=\"$any(item).componentKey\"\n [rootContext]=\"vm.rootContext()\"\n [pageConfig]=\"$any(item).pageConfig\"\n [options]=\"$any(item).options\"\n (componentReady)=\"recompute()\"\n ></div>\n } @else {\n <!-- Widget-based content -->\n <ng-container axp-widget-renderer [node]=\"$any(item)\" [mode]=\"$any(item).mode ?? 'view'\"></ng-container>\n }\n }\n @if (vm.currentPage()?.tabs?.length) {\n <div class=\"axp-horizontal-tabs\">\n <ax-tabs [location]=\"'bottom'\" [fitParent]=\"false\" look=\"classic\">\n @for (tab of vm.currentPageTabs(); track $index) {\n <ax-tab-item\n (onClick)=\"vm.setCurrentTab(tab)\"\n [text]=\"(tab.title | translate | async)!\"\n [active]=\"vm.currentTab()?.id === tab.id\"\n >\n <ax-prefix>\n <ax-icon icon=\"far ${{ tab.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n }\n </ax-tabs>\n <div class=\"content\">\n @if (vm.currentTab()) {\n @for (content of vm.activeTabContent(); track content.name) {\n <ng-container axp-widget-renderer [node]=\"content\" [mode]=\"content.mode ?? 'view'\">\n </ng-container>\n }\n }\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n </ax-form>\n }\n }\n </axp-page-content>\n\n <!-- Footer Section -->\n @if (hasFooter()) {\n <axp-page-footer class=\"--animated\">\n <axp-layout-suffix>\n <!-- secondary footer actions -->\n @if (hasVisibleFooterSecondaryActions()) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [iconOnly]=\"deviceService.isSmall()\"\n [text]=\"'@general:terms.interface.actions' | translate | async\"\n [look]=\"deviceService.isSmall() ? 'blank' : 'solid'\"\n [color]=\"'default'\"\n >\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (action of footerSecondaryActions(); track $index) {\n @if (isFooterActionVisible(action)) {\n <ax-button-item\n [text]=\"(t(action.title) | async)!\"\n [color]=\"action.color\"\n [disabled]=\"isFooterActionDisabled(action)\"\n (onClick)=\"execute(action.command!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ action.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (action.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n\n @if (hasVisibleFooterPrimaryActions()) {\n @if (showSaveDiscardFooter()) {\n @if (rejectFooterCommand(); as reject) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [disabled]=\"vm.isSaving()\"\n [text]=\"(t(reject.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"reject.color\"\n (onClick)=\"execute(reject.command)\"\n >\n <ax-prefix>\n <i class=\"{{ reject.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n @if (acceptFooterCommand(); as accept) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [disabled]=\"vm.isSaving()\"\n [text]=\"(t(accept.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"accept.color\"\n (onClick)=\"execute(accept.command)\"\n >\n <ax-prefix>\n <i class=\"{{ accept.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n }\n @for (action of footerPrimaryActions(); track $index) {\n @if (isFooterActionVisible(action)) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [disabled]=\"isFooterActionDisabled(action)\"\n [text]=\"(t(action.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"action.color\"\n (onClick)=\"execute(action.command!)\"\n >\n <ax-prefix>\n <i class=\"{{ action.icon }}\"></i>\n </ax-prefix>\n @if (action?.items) {\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of action?.items; track $index) {\n @if (isFooterActionVisible(sub)) {\n <ax-button-item\n [text]=\"(t(sub.title) | async)!\"\n [color]=\"sub.color\"\n [disabled]=\"isFooterActionDisabled(sub)\"\n (onClick)=\"execute(sub.command!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n }\n </ax-button>\n }\n }\n }\n </axp-layout-suffix>\n </axp-page-footer>\n }\n</axp-page-layout>\n", styles: ["axp-layout-details-view .axp-vertical-tabs{--ax-comp-tabs-default-border-radius: 0}axp-layout-details-view .axp-vertical-tabs ax-tab-item{margin-top:0!important;margin-bottom:0!important;padding-top:.75rem!important;padding-bottom:.75rem!important;font-weight:600!important}axp-layout-details-view .axp-vertical-tabs ax-tab-item>div{display:flex!important;align-items:center!important}axp-layout-details-view .axp-vertical-tabs ax-tab-item>div .ax-tab-item-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-layout-details-view .axp-horizontal-tabs{display:flex;width:100%;flex-direction:column}axp-layout-details-view .axp-horizontal-tabs .content{margin-top:1rem;margin-bottom:1rem;display:block;width:100%}axp-layout-details-view axp-layout-section axp-layout-content{display:flex;width:100%;flex-direction:column}axp-layout-details-view axp-layout-section axp-layout-content>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse));border-style:dashed;--tw-divide-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-divide-opacity, 1))}axp-layout-details-view axp-layout-section axp-layout-content .--item-container{align-items:center;gap:1rem;padding:1rem}@media(min-width:1024px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:1.5rem;padding-right:1.5rem}}@media(min-width:1280px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:2rem;padding-right:2rem}}@media(min-width:1536px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:2.5rem;padding-right:2.5rem}}axp-layout-details-view axp-layout-section axp-layout-content .--item-container{display:grid;grid-template-columns:repeat(12,minmax(0,1fr))}axp-layout-details-view axp-layout-section axp-layout-content .--item-container axp-layout-description{margin-top:.5rem!important;font-size:.75rem!important;line-height:1rem!important}axp-layout-details-view axp-page-content ax-form form{height:100%}axp-layout-details-view axp-layout-start-side{border-inline-end-width:1px}\n"], dependencies: [{ kind: "ngmodule", type:
3036
+ ], viewQueries: [{ propertyName: "form", first: true, predicate: ["form"], descendants: true, isSignal: true }, { propertyName: "widgetContainer", first: true, predicate: AXPWidgetContainerComponent, descendants: true, isSignal: true }, { propertyName: "sidebarTabs", first: true, predicate: ["sidebarTabs"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<axp-page-layout *translate=\"let t\">\n @if (vm.adapter()?.pages?.length! > 1 && vm.isLarge()) {\n <axp-layout-start-side>\n <axp-layout-header>\n <axp-layout-title>{{\n formatService.format(\n vm.showPages() ? (vm.adapter()?.title ?? '') : (vm.adapter()?.label ?? ''),\n 'string',\n vm.rootContext()\n )\n | translate\n | async\n }}</axp-layout-title>\n <axp-layout-description>{{\n formatService.format(vm.adapter()?.description ?? '', 'string', vm.rootContext()) | translate | async\n }}</axp-layout-description>\n </axp-layout-header>\n <axp-layout-content>\n <ax-tabs #sidebarTabs class=\"axp-vertical-tabs\" [look]=\"'with-line-color'\" [location]=\"'end'\" [fitParent]=\"true\"\n (onActiveTabChanged)=\"handleSidebarTabChanged($event)\">\n @for (item of vm.adapter()?.pages; track item.id) {\n <ax-tab-item [key]=\"item.id\"\n [text]=\"(formatService.format(item.label, 'string', vm.rootContext()) | translate | async)!\"\n [active]=\"vm.currentPage()?.id === item.id\">\n <ax-prefix>\n <ax-icon icon=\"far ${{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n }\n </ax-tabs>\n </axp-layout-content>\n </axp-layout-start-side>\n }\n <!-- Content Section -->\n <axp-page-content class=\"ax-flex ax-flex-row ax-gap-4\">\n @if (vm.showPages()) {\n <axp-layout-list class=\"ax-w-full\">\n @for (item of vm.adapter()?.pages; track $index) {\n <axp-layout-list-item (click)=\"handleSelectPage(item)\">\n <axp-layout-prefix>\n <ax-icon icon=\"far ${{ item.icon }}\" class=\"ax-text-gray-500\"></ax-icon>\n </axp-layout-prefix>\n <axp-layout-content>\n <a class=\"ax-font-semibold\">{{\n formatService.format(item.label, 'string', vm.rootContext()) | translate | async\n }}</a>\n </axp-layout-content>\n <axp-layout-suffix>\n <ax-icon icon=\" far fa-chevron-right\" class=\"ax-text-gray-400\"></ax-icon>\n </axp-layout-suffix>\n </axp-layout-list-item>\n }\n </axp-layout-list>\n } @else {\n <ax-form class=\"ax-h-full ax-w-full\" #form>\n <axp-widgets-container #widgetsContainerRef [context]=\"vm.context()\"\n (onContextChanged)=\"handleOnContextChanged($event)\">\n <div class=\"ax-flex ax-flex-col ax-w-full ax-gap-4 ax-h-full\">\n @for (item of vm.currentPageContent(); track pageContentTrackKey($any(item), $index)) {\n @if ('type' in item && item.type === 'component') {\n <!-- Component-based content -->\n <div axp-page-component-renderer [componentKey]=\"$any(item).componentKey\" [rootContext]=\"vm.rootContext()\"\n [pageConfig]=\"$any(item).pageConfig\" [options]=\"$any(item).options\" (componentReady)=\"recompute()\"></div>\n } @else {\n <!-- Widget-based content -->\n <ng-container axp-widget-renderer [node]=\"$any(item)\" [mode]=\"$any(item).mode ?? 'view'\"></ng-container>\n }\n }\n @if (vm.currentPage()?.tabs?.length) {\n <div class=\"axp-horizontal-tabs\">\n <ax-tabs [location]=\"'bottom'\" [fitParent]=\"false\" look=\"classic\">\n @for (tab of vm.currentPageTabs(); track $index) {\n <ax-tab-item (onClick)=\"vm.setCurrentTab(tab)\" [text]=\"(tab.title | translate | async)!\"\n [active]=\"vm.currentTab()?.id === tab.id\">\n <ax-prefix>\n <ax-icon icon=\"far ${{ tab.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n }\n </ax-tabs>\n <div class=\"content\">\n @if (vm.currentTab()) {\n @for (content of vm.activeTabContent(); track content.name) {\n <ng-container axp-widget-renderer [node]=\"content\" [mode]=\"content.mode ?? 'view'\">\n </ng-container>\n }\n }\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n </ax-form>\n }\n </axp-page-content>\n\n <!-- Footer Section -->\n @if (hasFooter()) {\n <axp-page-footer class=\"--animated\">\n <axp-layout-suffix>\n <!-- secondary footer actions -->\n @if (hasVisibleFooterSecondaryActions()) {\n <ax-button [class.ax-sm]=\"deviceService.isSmall()\" [iconOnly]=\"deviceService.isSmall()\"\n [text]=\"'@general:terms.interface.actions' | translate | async\"\n [look]=\"deviceService.isSmall() ? 'blank' : 'solid'\" [color]=\"'default'\">\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (action of footerSecondaryActions(); track $index) {\n @if (isFooterActionVisible(action)) {\n <ax-button-item [text]=\"(t(action.title) | async)!\" [color]=\"action.color\"\n [disabled]=\"isFooterActionDisabled(action)\" (onClick)=\"execute(action.command!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ action.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (action.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n\n @if (hasVisibleFooterPrimaryActions()) {\n @if (showSaveDiscardFooter()) {\n @if (rejectFooterCommand(); as reject) {\n <ax-button [class.ax-sm]=\"deviceService.isSmall()\" [disabled]=\"vm.isOverlayBusy()\"\n [text]=\"(t(reject.title) | async)!\" [look]=\"'solid'\" [color]=\"reject.color\" (onClick)=\"execute(reject.command)\">\n <ax-prefix>\n <i class=\"{{ reject.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n @if (acceptFooterCommand(); as accept) {\n <ax-button [class.ax-sm]=\"deviceService.isSmall()\" [disabled]=\"vm.isOverlayBusy()\"\n [text]=\"(t(accept.title) | async)!\" [look]=\"'solid'\" [color]=\"accept.color\" (onClick)=\"execute(accept.command)\">\n <ax-prefix>\n <i class=\"{{ accept.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n }\n @for (action of footerPrimaryActions(); track $index) {\n @if (isFooterActionVisible(action)) {\n <ax-button [class.ax-sm]=\"deviceService.isSmall()\" [disabled]=\"isFooterActionDisabled(action)\"\n [text]=\"(t(action.title) | async)!\" [look]=\"'solid'\" [color]=\"action.color\"\n (onClick)=\"execute(action.command!)\">\n <ax-prefix>\n <i class=\"{{ action.icon }}\"></i>\n </ax-prefix>\n @if (action?.items) {\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of action?.items; track $index) {\n @if (isFooterActionVisible(sub)) {\n <ax-button-item [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\"\n [disabled]=\"isFooterActionDisabled(sub)\" (onClick)=\"execute(sub.command!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n }\n </ax-button>\n }\n }\n }\n </axp-layout-suffix>\n </axp-page-footer>\n }\n</axp-page-layout>", styles: ["axp-layout-details-view .axp-vertical-tabs{--ax-comp-tabs-default-border-radius: 0}axp-layout-details-view .axp-vertical-tabs ax-tab-item{margin-top:0!important;margin-bottom:0!important;padding-top:.75rem!important;padding-bottom:.75rem!important;font-weight:600!important}axp-layout-details-view .axp-vertical-tabs ax-tab-item>div{display:flex!important;align-items:center!important}axp-layout-details-view .axp-vertical-tabs ax-tab-item>div .ax-tab-item-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-layout-details-view .axp-horizontal-tabs{display:flex;width:100%;flex-direction:column}axp-layout-details-view .axp-horizontal-tabs .content{margin-top:1rem;margin-bottom:1rem;display:block;width:100%}axp-layout-details-view axp-layout-section axp-layout-content{display:flex;width:100%;flex-direction:column}axp-layout-details-view axp-layout-section axp-layout-content>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse));border-style:dashed;--tw-divide-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-divide-opacity, 1))}axp-layout-details-view axp-layout-section axp-layout-content .--item-container{align-items:center;gap:1rem;padding:1rem}@media(min-width:1024px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:1.5rem;padding-right:1.5rem}}@media(min-width:1280px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:2rem;padding-right:2rem}}@media(min-width:1536px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:2.5rem;padding-right:2.5rem}}axp-layout-details-view axp-layout-section axp-layout-content .--item-container{display:grid;grid-template-columns:repeat(12,minmax(0,1fr))}axp-layout-details-view axp-layout-section axp-layout-content .--item-container axp-layout-description{margin-top:.5rem!important;font-size:.75rem!important;line-height:1rem!important}axp-layout-details-view axp-page-content ax-form form{height:100%}axp-layout-details-view axp-layout-start-side{border-inline-end-width:1px}\n"], dependencies: [{ kind: "ngmodule", type:
2347
3037
  // Angular
2348
3038
  CommonModule }, { kind: "ngmodule", type:
2349
3039
  // ACoreX
2350
- AXMenuModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i6.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i6.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i6.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i5.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i3$1.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.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: AXLoadingModule }, { kind: "component", type: i5$1.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXFileModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i6$1.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i6$1.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "component", type:
3040
+ AXMenuModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i6.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i6.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i6.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i5.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i3$1.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.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: AXBreadcrumbsModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXFileModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i5$1.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i5$1.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "component", type:
2351
3041
  //
2352
- AXPThemeLayoutListComponent, selector: "axp-layout-list" }, { kind: "component", type: AXPThemeLayoutListItemComponent, selector: "axp-layout-list-item" }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i7.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i7.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "component", type: AXPThemeLayoutStartSideComponent, selector: "axp-layout-page-start-side, axp-layout-start-side" }, { kind: "component", type: AXPThemeLayoutHeaderComponent, selector: "axp-layout-header" }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i8$1.AXFormComponent, selector: "ax-form", inputs: ["disabled", "readonly", "labelMode", "look", "messageStyle", "updateOn", "inUserInteractionActive"], outputs: ["onValidate", "updateOnChange"] }, { kind: "directive", type: AXPPageComponentRendererDirective, selector: "[axp-page-component-renderer]", inputs: ["componentKey", "rootContext", "pageConfig", "options"], outputs: ["componentReady"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
3042
+ AXPThemeLayoutListComponent, selector: "axp-layout-list" }, { kind: "component", type: AXPThemeLayoutListItemComponent, selector: "axp-layout-list-item" }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i6$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i6$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "component", type: AXPThemeLayoutStartSideComponent, selector: "axp-layout-page-start-side, axp-layout-start-side" }, { kind: "component", type: AXPThemeLayoutHeaderComponent, selector: "axp-layout-header" }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i7.AXFormComponent, selector: "ax-form", inputs: ["disabled", "readonly", "labelMode", "look", "messageStyle", "updateOn", "inUserInteractionActive"], outputs: ["onValidate", "updateOnChange"] }, { kind: "directive", type: AXPPageComponentRendererDirective, selector: "[axp-page-component-renderer]", inputs: ["componentKey", "rootContext", "pageConfig", "options"], outputs: ["componentReady"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
2353
3043
  }
2354
3044
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLayoutDetailsViewComponent, decorators: [{
2355
3045
  type: Component,
@@ -2364,7 +3054,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2364
3054
  AXDropdownModule,
2365
3055
  AXTranslationModule,
2366
3056
  AXDecoratorModule,
2367
- AXLoadingModule,
2368
3057
  AXBreadcrumbsModule,
2369
3058
  AXBadgeModule,
2370
3059
  AXSearchBoxModule,
@@ -2389,8 +3078,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2389
3078
  useExisting: AXPLayoutDetailsViewComponent,
2390
3079
  },
2391
3080
  AXPLayoutDetailsViewViewModel,
2392
- ], template: "<axp-page-layout *translate=\"let t\">\n @if (vm.adapter()?.pages?.length! > 1 && vm.isLarge()) {\n <axp-layout-start-side>\n <axp-layout-header>\n <axp-layout-title>{{\n formatService.format(\n vm.showPages() ? (vm.adapter()?.title ?? '') : (vm.adapter()?.label ?? ''),\n 'string',\n vm.rootContext()\n )\n | translate\n | async\n }}</axp-layout-title>\n <axp-layout-description>{{\n formatService.format(vm.adapter()?.description ?? '', 'string', vm.rootContext()) | translate | async\n }}</axp-layout-description>\n </axp-layout-header>\n <axp-layout-content>\n <ax-tabs\n #sidebarTabs\n class=\"axp-vertical-tabs\"\n [look]=\"'with-line-color'\"\n [location]=\"'end'\"\n [fitParent]=\"true\"\n (onActiveTabChanged)=\"handleSidebarTabChanged($event)\"\n >\n @for (item of vm.adapter()?.pages; track item.id) {\n <ax-tab-item\n [key]=\"item.id\"\n [text]=\"(formatService.format(item.label, 'string', vm.rootContext()) | translate | async)!\"\n [active]=\"vm.currentPage()?.id === item.id\"\n >\n <ax-prefix>\n <ax-icon icon=\"far ${{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n }\n </ax-tabs>\n </axp-layout-content>\n </axp-layout-start-side>\n }\n <!-- Content Section -->\n <axp-page-content class=\"ax-flex ax-flex-row ax-gap-4\">\n @if (vm.showPages()) {\n <axp-layout-list class=\"ax-w-full\">\n @for (item of vm.adapter()?.pages; track $index) {\n <axp-layout-list-item (click)=\"handleSelectPage(item)\">\n <axp-layout-prefix>\n <ax-icon icon=\"far ${{ item.icon }}\" class=\"ax-text-gray-500\"></ax-icon>\n </axp-layout-prefix>\n <axp-layout-content>\n <a class=\"ax-font-semibold\">{{\n formatService.format(item.label, 'string', vm.rootContext()) | translate | async\n }}</a>\n </axp-layout-content>\n <axp-layout-suffix>\n <ax-icon icon=\" far fa-chevron-right\" class=\"ax-text-gray-400\"></ax-icon>\n </axp-layout-suffix>\n </axp-layout-list-item>\n }\n </axp-layout-list>\n } @else {\n @if (vm.isBusy()) {\n <div class=\"ax-flex ax-h-full ax-w-full ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n } @else {\n <ax-form class=\"ax-h-full ax-w-full\" #form>\n <axp-widgets-container\n #widgetsContainerRef\n [context]=\"vm.context()\"\n (onContextChanged)=\"handleOnContextChanged($event)\"\n >\n <div class=\"ax-flex ax-flex-col ax-w-full ax-gap-4 ax-h-full\">\n @for (item of vm.currentPageContent(); track pageContentTrackKey($any(item), $index)) {\n @if ('type' in item && item.type === 'component') {\n <!-- Component-based content -->\n <div\n axp-page-component-renderer\n [componentKey]=\"$any(item).componentKey\"\n [rootContext]=\"vm.rootContext()\"\n [pageConfig]=\"$any(item).pageConfig\"\n [options]=\"$any(item).options\"\n (componentReady)=\"recompute()\"\n ></div>\n } @else {\n <!-- Widget-based content -->\n <ng-container axp-widget-renderer [node]=\"$any(item)\" [mode]=\"$any(item).mode ?? 'view'\"></ng-container>\n }\n }\n @if (vm.currentPage()?.tabs?.length) {\n <div class=\"axp-horizontal-tabs\">\n <ax-tabs [location]=\"'bottom'\" [fitParent]=\"false\" look=\"classic\">\n @for (tab of vm.currentPageTabs(); track $index) {\n <ax-tab-item\n (onClick)=\"vm.setCurrentTab(tab)\"\n [text]=\"(tab.title | translate | async)!\"\n [active]=\"vm.currentTab()?.id === tab.id\"\n >\n <ax-prefix>\n <ax-icon icon=\"far ${{ tab.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n }\n </ax-tabs>\n <div class=\"content\">\n @if (vm.currentTab()) {\n @for (content of vm.activeTabContent(); track content.name) {\n <ng-container axp-widget-renderer [node]=\"content\" [mode]=\"content.mode ?? 'view'\">\n </ng-container>\n }\n }\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n </ax-form>\n }\n }\n </axp-page-content>\n\n <!-- Footer Section -->\n @if (hasFooter()) {\n <axp-page-footer class=\"--animated\">\n <axp-layout-suffix>\n <!-- secondary footer actions -->\n @if (hasVisibleFooterSecondaryActions()) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [iconOnly]=\"deviceService.isSmall()\"\n [text]=\"'@general:terms.interface.actions' | translate | async\"\n [look]=\"deviceService.isSmall() ? 'blank' : 'solid'\"\n [color]=\"'default'\"\n >\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (action of footerSecondaryActions(); track $index) {\n @if (isFooterActionVisible(action)) {\n <ax-button-item\n [text]=\"(t(action.title) | async)!\"\n [color]=\"action.color\"\n [disabled]=\"isFooterActionDisabled(action)\"\n (onClick)=\"execute(action.command!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ action.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (action.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n\n @if (hasVisibleFooterPrimaryActions()) {\n @if (showSaveDiscardFooter()) {\n @if (rejectFooterCommand(); as reject) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [disabled]=\"vm.isSaving()\"\n [text]=\"(t(reject.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"reject.color\"\n (onClick)=\"execute(reject.command)\"\n >\n <ax-prefix>\n <i class=\"{{ reject.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n @if (acceptFooterCommand(); as accept) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [disabled]=\"vm.isSaving()\"\n [text]=\"(t(accept.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"accept.color\"\n (onClick)=\"execute(accept.command)\"\n >\n <ax-prefix>\n <i class=\"{{ accept.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n }\n @for (action of footerPrimaryActions(); track $index) {\n @if (isFooterActionVisible(action)) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [disabled]=\"isFooterActionDisabled(action)\"\n [text]=\"(t(action.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"action.color\"\n (onClick)=\"execute(action.command!)\"\n >\n <ax-prefix>\n <i class=\"{{ action.icon }}\"></i>\n </ax-prefix>\n @if (action?.items) {\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of action?.items; track $index) {\n @if (isFooterActionVisible(sub)) {\n <ax-button-item\n [text]=\"(t(sub.title) | async)!\"\n [color]=\"sub.color\"\n [disabled]=\"isFooterActionDisabled(sub)\"\n (onClick)=\"execute(sub.command!)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n }\n </ax-button>\n }\n }\n }\n </axp-layout-suffix>\n </axp-page-footer>\n }\n</axp-page-layout>\n", styles: ["axp-layout-details-view .axp-vertical-tabs{--ax-comp-tabs-default-border-radius: 0}axp-layout-details-view .axp-vertical-tabs ax-tab-item{margin-top:0!important;margin-bottom:0!important;padding-top:.75rem!important;padding-bottom:.75rem!important;font-weight:600!important}axp-layout-details-view .axp-vertical-tabs ax-tab-item>div{display:flex!important;align-items:center!important}axp-layout-details-view .axp-vertical-tabs ax-tab-item>div .ax-tab-item-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-layout-details-view .axp-horizontal-tabs{display:flex;width:100%;flex-direction:column}axp-layout-details-view .axp-horizontal-tabs .content{margin-top:1rem;margin-bottom:1rem;display:block;width:100%}axp-layout-details-view axp-layout-section axp-layout-content{display:flex;width:100%;flex-direction:column}axp-layout-details-view axp-layout-section axp-layout-content>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse));border-style:dashed;--tw-divide-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-divide-opacity, 1))}axp-layout-details-view axp-layout-section axp-layout-content .--item-container{align-items:center;gap:1rem;padding:1rem}@media(min-width:1024px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:1.5rem;padding-right:1.5rem}}@media(min-width:1280px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:2rem;padding-right:2rem}}@media(min-width:1536px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:2.5rem;padding-right:2.5rem}}axp-layout-details-view axp-layout-section axp-layout-content .--item-container{display:grid;grid-template-columns:repeat(12,minmax(0,1fr))}axp-layout-details-view axp-layout-section axp-layout-content .--item-container axp-layout-description{margin-top:.5rem!important;font-size:.75rem!important;line-height:1rem!important}axp-layout-details-view axp-page-content ax-form form{height:100%}axp-layout-details-view axp-layout-start-side{border-inline-end-width:1px}\n"] }]
2393
- }], propDecorators: { adapter: [{ type: i0.Input, args: [{ isSignal: true, alias: "adapter", required: true }] }], form: [{ type: i0.ViewChild, args: ['form', { isSignal: true }] }], widgetContainer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPWidgetContainerComponent), { isSignal: true }] }], sidebarTabs: [{ type: i0.ViewChild, args: ['sidebarTabs', { isSignal: true }] }] } });
3081
+ ], template: "<axp-page-layout *translate=\"let t\">\n @if (vm.adapter()?.pages?.length! > 1 && vm.isLarge()) {\n <axp-layout-start-side>\n <axp-layout-header>\n <axp-layout-title>{{\n formatService.format(\n vm.showPages() ? (vm.adapter()?.title ?? '') : (vm.adapter()?.label ?? ''),\n 'string',\n vm.rootContext()\n )\n | translate\n | async\n }}</axp-layout-title>\n <axp-layout-description>{{\n formatService.format(vm.adapter()?.description ?? '', 'string', vm.rootContext()) | translate | async\n }}</axp-layout-description>\n </axp-layout-header>\n <axp-layout-content>\n <ax-tabs #sidebarTabs class=\"axp-vertical-tabs\" [look]=\"'with-line-color'\" [location]=\"'end'\" [fitParent]=\"true\"\n (onActiveTabChanged)=\"handleSidebarTabChanged($event)\">\n @for (item of vm.adapter()?.pages; track item.id) {\n <ax-tab-item [key]=\"item.id\"\n [text]=\"(formatService.format(item.label, 'string', vm.rootContext()) | translate | async)!\"\n [active]=\"vm.currentPage()?.id === item.id\">\n <ax-prefix>\n <ax-icon icon=\"far ${{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n }\n </ax-tabs>\n </axp-layout-content>\n </axp-layout-start-side>\n }\n <!-- Content Section -->\n <axp-page-content class=\"ax-flex ax-flex-row ax-gap-4\">\n @if (vm.showPages()) {\n <axp-layout-list class=\"ax-w-full\">\n @for (item of vm.adapter()?.pages; track $index) {\n <axp-layout-list-item (click)=\"handleSelectPage(item)\">\n <axp-layout-prefix>\n <ax-icon icon=\"far ${{ item.icon }}\" class=\"ax-text-gray-500\"></ax-icon>\n </axp-layout-prefix>\n <axp-layout-content>\n <a class=\"ax-font-semibold\">{{\n formatService.format(item.label, 'string', vm.rootContext()) | translate | async\n }}</a>\n </axp-layout-content>\n <axp-layout-suffix>\n <ax-icon icon=\" far fa-chevron-right\" class=\"ax-text-gray-400\"></ax-icon>\n </axp-layout-suffix>\n </axp-layout-list-item>\n }\n </axp-layout-list>\n } @else {\n <ax-form class=\"ax-h-full ax-w-full\" #form>\n <axp-widgets-container #widgetsContainerRef [context]=\"vm.context()\"\n (onContextChanged)=\"handleOnContextChanged($event)\">\n <div class=\"ax-flex ax-flex-col ax-w-full ax-gap-4 ax-h-full\">\n @for (item of vm.currentPageContent(); track pageContentTrackKey($any(item), $index)) {\n @if ('type' in item && item.type === 'component') {\n <!-- Component-based content -->\n <div axp-page-component-renderer [componentKey]=\"$any(item).componentKey\" [rootContext]=\"vm.rootContext()\"\n [pageConfig]=\"$any(item).pageConfig\" [options]=\"$any(item).options\" (componentReady)=\"recompute()\"></div>\n } @else {\n <!-- Widget-based content -->\n <ng-container axp-widget-renderer [node]=\"$any(item)\" [mode]=\"$any(item).mode ?? 'view'\"></ng-container>\n }\n }\n @if (vm.currentPage()?.tabs?.length) {\n <div class=\"axp-horizontal-tabs\">\n <ax-tabs [location]=\"'bottom'\" [fitParent]=\"false\" look=\"classic\">\n @for (tab of vm.currentPageTabs(); track $index) {\n <ax-tab-item (onClick)=\"vm.setCurrentTab(tab)\" [text]=\"(tab.title | translate | async)!\"\n [active]=\"vm.currentTab()?.id === tab.id\">\n <ax-prefix>\n <ax-icon icon=\"far ${{ tab.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n }\n </ax-tabs>\n <div class=\"content\">\n @if (vm.currentTab()) {\n @for (content of vm.activeTabContent(); track content.name) {\n <ng-container axp-widget-renderer [node]=\"content\" [mode]=\"content.mode ?? 'view'\">\n </ng-container>\n }\n }\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n </ax-form>\n }\n </axp-page-content>\n\n <!-- Footer Section -->\n @if (hasFooter()) {\n <axp-page-footer class=\"--animated\">\n <axp-layout-suffix>\n <!-- secondary footer actions -->\n @if (hasVisibleFooterSecondaryActions()) {\n <ax-button [class.ax-sm]=\"deviceService.isSmall()\" [iconOnly]=\"deviceService.isSmall()\"\n [text]=\"'@general:terms.interface.actions' | translate | async\"\n [look]=\"deviceService.isSmall() ? 'blank' : 'solid'\" [color]=\"'default'\">\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (action of footerSecondaryActions(); track $index) {\n @if (isFooterActionVisible(action)) {\n <ax-button-item [text]=\"(t(action.title) | async)!\" [color]=\"action.color\"\n [disabled]=\"isFooterActionDisabled(action)\" (onClick)=\"execute(action.command!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ action.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (action.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n\n @if (hasVisibleFooterPrimaryActions()) {\n @if (showSaveDiscardFooter()) {\n @if (rejectFooterCommand(); as reject) {\n <ax-button [class.ax-sm]=\"deviceService.isSmall()\" [disabled]=\"vm.isOverlayBusy()\"\n [text]=\"(t(reject.title) | async)!\" [look]=\"'solid'\" [color]=\"reject.color\" (onClick)=\"execute(reject.command)\">\n <ax-prefix>\n <i class=\"{{ reject.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n @if (acceptFooterCommand(); as accept) {\n <ax-button [class.ax-sm]=\"deviceService.isSmall()\" [disabled]=\"vm.isOverlayBusy()\"\n [text]=\"(t(accept.title) | async)!\" [look]=\"'solid'\" [color]=\"accept.color\" (onClick)=\"execute(accept.command)\">\n <ax-prefix>\n <i class=\"{{ accept.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n }\n @for (action of footerPrimaryActions(); track $index) {\n @if (isFooterActionVisible(action)) {\n <ax-button [class.ax-sm]=\"deviceService.isSmall()\" [disabled]=\"isFooterActionDisabled(action)\"\n [text]=\"(t(action.title) | async)!\" [look]=\"'solid'\" [color]=\"action.color\"\n (onClick)=\"execute(action.command!)\">\n <ax-prefix>\n <i class=\"{{ action.icon }}\"></i>\n </ax-prefix>\n @if (action?.items) {\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n @for (sub of action?.items; track $index) {\n @if (isFooterActionVisible(sub)) {\n <ax-button-item [text]=\"(t(sub.title) | async)!\" [color]=\"sub.color\"\n [disabled]=\"isFooterActionDisabled(sub)\" (onClick)=\"execute(sub.command!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ sub.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (sub.break) {\n <ax-divider></ax-divider>\n }\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n }\n </ax-button>\n }\n }\n }\n </axp-layout-suffix>\n </axp-page-footer>\n }\n</axp-page-layout>", styles: ["axp-layout-details-view .axp-vertical-tabs{--ax-comp-tabs-default-border-radius: 0}axp-layout-details-view .axp-vertical-tabs ax-tab-item{margin-top:0!important;margin-bottom:0!important;padding-top:.75rem!important;padding-bottom:.75rem!important;font-weight:600!important}axp-layout-details-view .axp-vertical-tabs ax-tab-item>div{display:flex!important;align-items:center!important}axp-layout-details-view .axp-vertical-tabs ax-tab-item>div .ax-tab-item-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}axp-layout-details-view .axp-horizontal-tabs{display:flex;width:100%;flex-direction:column}axp-layout-details-view .axp-horizontal-tabs .content{margin-top:1rem;margin-bottom:1rem;display:block;width:100%}axp-layout-details-view axp-layout-section axp-layout-content{display:flex;width:100%;flex-direction:column}axp-layout-details-view axp-layout-section axp-layout-content>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse));border-style:dashed;--tw-divide-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-divide-opacity, 1))}axp-layout-details-view axp-layout-section axp-layout-content .--item-container{align-items:center;gap:1rem;padding:1rem}@media(min-width:1024px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:1.5rem;padding-right:1.5rem}}@media(min-width:1280px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:2rem;padding-right:2rem}}@media(min-width:1536px){axp-layout-details-view axp-layout-section axp-layout-content .--item-container{padding-left:2.5rem;padding-right:2.5rem}}axp-layout-details-view axp-layout-section axp-layout-content .--item-container{display:grid;grid-template-columns:repeat(12,minmax(0,1fr))}axp-layout-details-view axp-layout-section axp-layout-content .--item-container axp-layout-description{margin-top:.5rem!important;font-size:.75rem!important;line-height:1rem!important}axp-layout-details-view axp-page-content ax-form form{height:100%}axp-layout-details-view axp-layout-start-side{border-inline-end-width:1px}\n"] }]
3082
+ }], propDecorators: { form: [{ type: i0.ViewChild, args: ['form', { isSignal: true }] }], widgetContainer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPWidgetContainerComponent), { isSignal: true }] }], sidebarTabs: [{ type: i0.ViewChild, args: ['sidebarTabs', { isSignal: true }] }] } });
2394
3083
 
2395
3084
  //#region ---- Details View Can Deactivate Guard ----
2396
3085
  /**
@@ -2403,5 +3092,5 @@ const axpDetailsViewCanDeactivateGuard = createUnsavedChangesCanDeactivateGuard(
2403
3092
  * Generated bundle index. Do not edit.
2404
3093
  */
2405
3094
 
2406
- export { AXPLayoutDetailsViewComponent, AXPLayoutDetailsViewViewModel, AXPPageComponentInstanceRegistryService, AXPPageComponentRendererDirective, AXPPageLayoutBase, AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPopupLayoutBase, AXPPopupLayoutBaseComponent, AXPPopupLayoutComponent, axpDetailsViewCanDeactivateGuard, buildNotSavedPageBadge, getDetailsViewActionCommandBaseName, isDiscardCommand, resolveDetailsViewActionShortcuts, resolveDetailsViewFooterCommandShortcuts };
3095
+ export { AXPLayoutDetailsViewComponent, AXPLayoutDetailsViewViewModel, AXPPageComponentInstanceRegistryService, AXPPageComponentRendererDirective, AXPPageLayoutBase, AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPopupLayoutBase, AXPPopupLayoutBaseComponent, AXPPopupLayoutComponent, AXP_LAYOUT_DETAILS_VIEW_ADAPTER_LOADER, axpDetailsViewCanDeactivateGuard, buildNotSavedPageBadge, getDetailsViewActionCommandBaseName, isDiscardCommand, isDiscardFooterCommand, isSaveFooterCommand, resolveDetailsViewActionShortcuts, resolveDetailsViewFooterCommandShortcuts, resolvePageFooterActionDefaultShortcuts, resolvePageFooterActionShortcuts };
2407
3096
  //# sourceMappingURL=acorex-platform-layout-views.mjs.map