@acorex/platform 21.0.0-next.8 → 21.0.0-next.83

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 (133) hide show
  1. package/contracts/README.md +3 -0
  2. package/fesm2022/acorex-platform-auth.mjs +201 -81
  3. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  4. package/fesm2022/acorex-platform-common-common-settings.provider-Ytey9uhY.mjs +177 -0
  5. package/fesm2022/acorex-platform-common-common-settings.provider-Ytey9uhY.mjs.map +1 -0
  6. package/fesm2022/acorex-platform-common.mjs +4490 -880
  7. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  8. package/fesm2022/acorex-platform-contracts.mjs +38 -0
  9. package/fesm2022/acorex-platform-contracts.mjs.map +1 -0
  10. package/fesm2022/acorex-platform-core.mjs +2612 -667
  11. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  12. package/fesm2022/acorex-platform-domain.mjs +557 -826
  13. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  14. package/fesm2022/acorex-platform-layout-builder.mjs +1255 -209
  15. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  16. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs +121 -0
  17. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +1 -0
  18. package/fesm2022/acorex-platform-layout-components.mjs +6486 -1915
  19. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  20. package/fesm2022/acorex-platform-layout-designer.mjs +612 -287
  21. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  22. package/fesm2022/acorex-platform-layout-entity-attachments-page.component-CwG6n_Yb.mjs +376 -0
  23. package/fesm2022/acorex-platform-layout-entity-attachments-page.component-CwG6n_Yb.mjs.map +1 -0
  24. package/fesm2022/acorex-platform-layout-entity-file-list-popup.component--IeMZLIr.mjs +100 -0
  25. package/fesm2022/acorex-platform-layout-entity-file-list-popup.component--IeMZLIr.mjs.map +1 -0
  26. package/fesm2022/acorex-platform-layout-entity.mjs +22502 -9964
  27. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  28. package/fesm2022/acorex-platform-layout-views.mjs +1360 -338
  29. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  30. package/fesm2022/acorex-platform-layout-widget-core.mjs +2226 -524
  31. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  32. package/fesm2022/{acorex-platform-layout-widgets-button-widget-designer.component-C3VoBb_b.mjs → acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs} +10 -10
  33. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs.map +1 -0
  34. package/fesm2022/{acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs → acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs} +6 -7
  35. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +1 -0
  36. package/fesm2022/{acorex-platform-layout-widgets-page-widget-designer.component-BtZMBxYp.mjs → acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs} +12 -12
  37. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs.map +1 -0
  38. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs +116 -0
  39. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs.map +1 -0
  40. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs} +6 -6
  41. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs.map +1 -0
  42. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs} +5 -5
  43. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs.map +1 -0
  44. package/fesm2022/{acorex-platform-layout-widgets-text-block-widget-designer.component-Df1BFkSa.mjs → acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs} +6 -6
  45. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs.map +1 -0
  46. package/fesm2022/acorex-platform-layout-widgets.mjs +18742 -16715
  47. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  48. package/fesm2022/acorex-platform-native.mjs +8 -7
  49. package/fesm2022/acorex-platform-native.mjs.map +1 -1
  50. package/fesm2022/acorex-platform-runtime.mjs +391 -166
  51. package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
  52. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-CWLfNqV0.mjs +160 -0
  53. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-CWLfNqV0.mjs.map +1 -0
  54. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-C7cT82K2.mjs +120 -0
  55. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-C7cT82K2.mjs.map +1 -0
  56. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs → acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs} +21 -28
  57. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs.map +1 -0
  58. package/fesm2022/acorex-platform-themes-default-error-401.component-B1nsdpTY.mjs +48 -0
  59. package/fesm2022/acorex-platform-themes-default-error-401.component-B1nsdpTY.mjs.map +1 -0
  60. package/fesm2022/acorex-platform-themes-default-error-404.component-D4UvRe8u.mjs +42 -0
  61. package/fesm2022/acorex-platform-themes-default-error-404.component-D4UvRe8u.mjs.map +1 -0
  62. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs +19 -0
  63. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs.map +1 -0
  64. package/fesm2022/acorex-platform-themes-default.mjs +2337 -94
  65. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  66. package/fesm2022/{acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs → acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs} +6 -6
  67. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs.map +1 -0
  68. package/fesm2022/{acorex-platform-themes-shared-icon-chooser-view.component-9W52W6Nu.mjs → acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs} +6 -6
  69. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs.map +1 -0
  70. package/fesm2022/{acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs → acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs} +52 -33
  71. package/fesm2022/acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs.map +1 -0
  72. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs +94 -0
  73. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs.map +1 -0
  74. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs +86 -0
  75. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs.map +1 -0
  76. package/fesm2022/acorex-platform-themes-shared.mjs +793 -612
  77. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  78. package/fesm2022/acorex-platform-workflow.mjs +997 -274
  79. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  80. package/fesm2022/acorex-platform.mjs.map +1 -1
  81. package/package.json +41 -35
  82. package/{auth/index.d.ts → types/acorex-platform-auth.d.ts} +40 -19
  83. package/types/acorex-platform-common.d.ts +3673 -0
  84. package/types/acorex-platform-contracts.d.ts +940 -0
  85. package/{core/index.d.ts → types/acorex-platform-core.d.ts} +1029 -170
  86. package/{domain/index.d.ts → types/acorex-platform-domain.d.ts} +744 -412
  87. package/{layout/builder/index.d.ts → types/acorex-platform-layout-builder.d.ts} +262 -55
  88. package/types/acorex-platform-layout-components.d.ts +3329 -0
  89. package/{layout/designer/index.d.ts → types/acorex-platform-layout-designer.d.ts} +96 -18
  90. package/types/acorex-platform-layout-entity.d.ts +4512 -0
  91. package/{layout/views/index.d.ts → types/acorex-platform-layout-views.d.ts} +334 -91
  92. package/{layout/widget-core/index.d.ts → types/acorex-platform-layout-widget-core.d.ts} +438 -162
  93. package/{layout/widgets/index.d.ts → types/acorex-platform-layout-widgets.d.ts} +1152 -507
  94. package/{native/index.d.ts → types/acorex-platform-native.d.ts} +0 -7
  95. package/types/acorex-platform-runtime.d.ts +571 -0
  96. package/{themes/default/index.d.ts → types/acorex-platform-themes-default.d.ts} +268 -11
  97. package/{themes/shared/index.d.ts → types/acorex-platform-themes-shared.d.ts} +30 -2
  98. package/{workflow/index.d.ts → types/acorex-platform-workflow.d.ts} +436 -748
  99. package/common/index.d.ts +0 -2470
  100. package/fesm2022/acorex-platform-common-common-settings.provider-zhqNP3xb.mjs +0 -71
  101. package/fesm2022/acorex-platform-common-common-settings.provider-zhqNP3xb.mjs.map +0 -1
  102. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-C3VoBb_b.mjs.map +0 -1
  103. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs +0 -135
  104. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs.map +0 -1
  105. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs.map +0 -1
  106. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-BtZMBxYp.mjs.map +0 -1
  107. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs.map +0 -1
  108. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs.map +0 -1
  109. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Df1BFkSa.mjs.map +0 -1
  110. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs +0 -157
  111. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs.map +0 -1
  112. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-D3qZa5fM.mjs +0 -1542
  113. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-D3qZa5fM.mjs.map +0 -1
  114. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs +0 -101
  115. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs.map +0 -1
  116. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs.map +0 -1
  117. package/fesm2022/acorex-platform-themes-default-error-401.component-cfREo88K.mjs +0 -31
  118. package/fesm2022/acorex-platform-themes-default-error-401.component-cfREo88K.mjs.map +0 -1
  119. package/fesm2022/acorex-platform-themes-default-error-404.component-CdCV5ZoA.mjs +0 -25
  120. package/fesm2022/acorex-platform-themes-default-error-404.component-CdCV5ZoA.mjs.map +0 -1
  121. package/fesm2022/acorex-platform-themes-default-error-offline.component-E7SzBcAt.mjs +0 -19
  122. package/fesm2022/acorex-platform-themes-default-error-offline.component-E7SzBcAt.mjs.map +0 -1
  123. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs.map +0 -1
  124. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-9W52W6Nu.mjs.map +0 -1
  125. package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs.map +0 -1
  126. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-Dz0cylyQ.mjs +0 -65
  127. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-Dz0cylyQ.mjs.map +0 -1
  128. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-DY0JtT1v.mjs +0 -64
  129. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-DY0JtT1v.mjs.map +0 -1
  130. package/layout/components/index.d.ts +0 -1670
  131. package/layout/entity/index.d.ts +0 -2294
  132. package/runtime/index.d.ts +0 -307
  133. /package/{index.d.ts → types/acorex-platform.d.ts} +0 -0
@@ -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, computed, input, HostListener } from '@angular/core';
4
+ import { inject, viewChild, afterNextRender, effect, ChangeDetectionStrategy, ViewEncapsulation, Component, signal, computed, Injectable, input, output, ViewContainerRef, Directive, DestroyRef, ElementRef, untracked } 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,22 +12,23 @@ 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 { AXPStickyDirective, AXPHomePageService, AXPCommonSettings, AXPSettingsService, AXPEntityCommandScope } from '@acorex/platform/common';
16
- import * as i8 from '@acorex/platform/layout/components';
17
- import { AXPComponentSlotModule, AXPThemeLayoutBlockComponent, AXPThemeLayoutActionsComponent, AXPThemeLayoutHeaderComponent, AXPThemeLayoutContainerComponent, AXPThemeLayoutListComponent, AXPThemeLayoutListItemComponent, AXPThemeLayoutStartSideComponent } from '@acorex/platform/layout/components';
15
+ import { AXPStickyDirective, AXPCommonSettings, AXPHomePageService, AXPSettingsService, axpNavigateAppPath, AXPEntityCommandScope, axpIsEntityDetailsViewRoute, AXPUnsavedChangesConfirmService, AXPUnsavedChangesPopstateService, createUnsavedChangesCanDeactivateGuard } from '@acorex/platform/common';
16
+ import * as i8 from '@acorex/platform/core';
17
+ import { AXPDeviceService, AXPComponentSlotModule, getSmart, AXPExpressionEvaluatorService, AXPContextStore, normalizeKeyboardShortcuts, AXPBroadcastEventService, AXPKeyboardShortcutRegistry, 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';
21
21
  import * as i3$1 from '@acorex/core/translation';
22
22
  import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
23
- import { AXPDeviceService, getChangedPaths, getSmart, AXPExpressionEvaluatorService, AXPBroadcastEventService } from '@acorex/platform/core';
23
+ import { AXPThemeLayoutBlockComponent, AXPThemeLayoutActionsComponent, AXPThemeLayoutHeaderComponent, AXPThemeLayoutContainerComponent, AXPPageComponentRegistryService, AXPThemeLayoutListComponent, AXPThemeLayoutListItemComponent, AXPThemeLayoutStartSideComponent } from '@acorex/platform/layout/components';
24
+ import { AXPStatusChipComponent } from '@acorex/platform/layout/widgets';
24
25
  import { AXPCommandService, AXPPolicyEngineService } from '@acorex/platform/runtime';
25
26
  import { AXPLayoutThemeService } from '@acorex/platform/themes/shared';
26
27
  import { AXPWorkflowService } from '@acorex/platform/workflow';
27
28
  import { AXToastService } from '@acorex/components/toast';
28
29
  import { AXFormatService, AXFormatModule } from '@acorex/core/format';
29
30
  import { AXPSessionService } from '@acorex/platform/auth';
30
- import { isNil, isEmpty, isEqual, cloneDeep } from 'lodash-es';
31
+ import { isEmpty, cloneDeep, get } from 'lodash-es';
31
32
  import { AXBasePageComponent } from '@acorex/components/page';
32
33
  import * as i6$1 from '@acorex/platform/layout/widget-core';
33
34
  import { AXPPageStatus, AXPWidgetContainerComponent, AXPWidgetCoreModule } from '@acorex/platform/layout/widget-core';
@@ -40,7 +41,6 @@ import { AXMenuModule } from '@acorex/components/menu';
40
41
  import { AXSearchBoxModule } from '@acorex/components/search-box';
41
42
  import { AXDateTimeModule } from '@acorex/core/date-time';
42
43
  import { AXFileModule } from '@acorex/core/file';
43
- import { AXResizableDirective } from '@acorex/cdk/resizable';
44
44
  import * as i7 from '@acorex/components/form';
45
45
  import { AXFormModule } from '@acorex/components/form';
46
46
  import * as i5$1 from '@acorex/components/tabs';
@@ -55,7 +55,7 @@ class AXPPageLayoutComponent {
55
55
  this.page = inject(AXPPageLayoutBase, { optional: true });
56
56
  this.layoutService = inject(AXPLayoutThemeService);
57
57
  this.deviceService = inject(AXPDeviceService);
58
- this.startSideDrawer = viewChild('startSideDrawer', ...(ngDevMode ? [{ debugName: "startSideDrawer" }] : []));
58
+ this.startSideDrawer = viewChild('startSideDrawer', ...(ngDevMode ? [{ debugName: "startSideDrawer" }] : /* istanbul ignore next */ []));
59
59
  this.workflow = inject(AXPWorkflowService);
60
60
  this.commandService = inject(AXPCommandService);
61
61
  this.#initialize = afterNextRender(async () => {
@@ -65,7 +65,7 @@ class AXPPageLayoutComponent {
65
65
  this.page?.title();
66
66
  this.page?.description();
67
67
  this.checkScrollableContent();
68
- }, ...(ngDevMode ? [{ debugName: "#effect" }] : []));
68
+ }, ...(ngDevMode ? [{ debugName: "#effect" }] : /* istanbul ignore next */ []));
69
69
  }
70
70
  #initialize;
71
71
  #effect;
@@ -97,6 +97,9 @@ class AXPPageLayoutComponent {
97
97
  async execute(command) {
98
98
  const reserved = ['navigate'];
99
99
  if (reserved.includes(command.name)) {
100
+ if (!(await this.canLeaveCurrentPage())) {
101
+ return;
102
+ }
100
103
  await this.workflow.execute(command.name, { options: command.options });
101
104
  return;
102
105
  }
@@ -111,14 +114,43 @@ class AXPPageLayoutComponent {
111
114
  event.stopPropagation();
112
115
  this.startSideDrawer()?.hide();
113
116
  }
114
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPPageLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
115
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", 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: "<div\n id=\"axp-drawer-start\"\n [mode]=\"deviceService.isSmall() ? 'overlay' : 'push'\"\n [transition]=\"250\"\n axDrawerItem\n [backDrop]=\"true\"\n (onBackdropClick)=\"handleBackdropClick($event)\"\n #startSideDrawer=\"axDrawerItem\"\n [backdropClass]=\"'ax-bg-darkest/75'\"\n [collapsed]=\"deviceService.isSmall()\"\n drawerLocation=\"start\"\n class=\"ax-z-50 ax-h-full\"\n>\n <ng-content select=\"axp-layout-start-side\"></ng-content>\n</div>\n<axp-layout-container id=\"axp-page-layout\" #container>\n <axp-layout-header\n id=\"axp-page-header\"\n *translate=\"let t\"\n #sticky=\"axpSticky\"\n [axpSticky]=\"'axp-is-sticky'\"\n [stickyOffset]=\"50\"\n [stickyParent]=\"container.hostElement\"\n >\n @if (page?.hasBackButton() && deviceService.isSmall()) {\n <ax-button\n id=\"axp-btn-back\"\n [look]=\"'blank'\"\n class=\"ax-sm ax-w-fit ax-ms-1\"\n color=\"secondary\"\n (click)=\"page?.onBackButtonClick()\"\n [text]=\"page?.backButton()?.title\"\n >\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 <!-------- Begin Title Bar -------->\n <axp-layout-title-bar id=\"axp-title-bar\">\n <!-------- Begin Title -------->\n <div class=\"ax-flex ax-flex-col ax-transition\">\n <!-- 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\n [attr.id]=\"'axp-breadcrumb-item-' + $index\"\n [active]=\"$last\"\n (click)=\"item.command ? execute(item.command) : null\"\n >\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 <div class=\"__title-container\">\n <!-- Title -->\n @if (page?.hasTitle()) {\n <axp-layout-title id=\"axp-page-title\"> {{ t(page?.title()) | async }}</axp-layout-title>\n }\n <!-- 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\n [attr.id]=\"'axp-btn-title-action-' + (sub.name || $index)\"\n [text]=\"(t(sub.title) | async)!\"\n [color]=\"sub.color\"\n [disabled]=\"sub.disabled\"\n (onClick)=\"handleActionClick(sub)\"\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 </ng-container>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-- 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\"\n >\n <i class=\"fa-solid fa-circle\"></i>\n {{ page?.badge()?.title }}\n </div>\n }\n </div>\n <!-- Description -->\n @if (page?.hasDescription()) {\n <axp-layout-description id=\"axp-page-description\">\n {{ t(page?.description()) | async }}</axp-layout-description\n >\n }\n </div>\n <!-------- Finish Title -------->\n <!--------------------------------------------------------------->\n <!-------- Page Actions -------->\n\n <axp-layout-actions id=\"axp-page-actions\" class=\"ax-shrink-0\">\n <axp-component-slot name=\"page-header-actions\"></axp-component-slot>\n <!--Primary Actions -->\n @if (page?.hasPrimaryActions()) {\n <!-- items -->\n @for (item of page?.primaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button\n [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\"\n [class.ax-sm]=\"deviceService.isSmall()\"\n [iconOnly]=\"deviceService.isSmall()\"\n [disabled]=\"item.disabled\"\n [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"item.color\"\n (onClick)=\"handleActionClick(item)\"\n >\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\n [attr.id]=\"'axp-btn-primary-' + (item.name || item.title) + '-' + (sub.name || sub.title)\"\n [text]=\"(t(sub.title) | async)!\"\n [color]=\"sub.color\"\n [disabled]=\"sub.disabled\"\n (onClick)=\"handleActionClick(sub)\"\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 <!-- Secondary Actions -->\n @if (page?.hasSecondaryActions()) {\n <ax-button\n id=\"axp-btn-secondary\"\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 (item of page?.secondaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button-item\n [attr.id]=\"'axp-btn-secondary-' + (item.name || item.title)\"\n [text]=\"(item.title | translate | async)!\"\n [color]=\"item.color\"\n [disabled]=\"item.disabled\"\n (onClick)=\"handleSecondaryActionClick(item)\"\n >\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 </axp-layout-actions>\n <!-- Finish Page Actions -->\n </axp-layout-title-bar>\n <!----- Finish Title Bar ----->\n <!--------------------------------------------------------------->\n <!-- Begin Navbar -->\n @if (!sticky.isSticky) {}\n <ng-content select=\"axp-page-toolbar\"></ng-content>\n <!-- Finish Navbar -->\n </axp-layout-header>\n <ng-content select=\"axp-page-content\"></ng-content>\n\n <axp-page-footer-container\n id=\"axp-page-footer-container\"\n [ngStyle]=\"{ display: tt.isEmpty() && prefixSlot.isEmpty() && suffixSlot.isEmpty() ? 'none' : 'block' }\"\n >\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</axp-layout-container>\n", styles: [".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 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 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;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{position:sticky;top:0;z-index:10;display:flex;flex-direction:column;align-items:flex-start;gap:0px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1));padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@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.--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.--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.--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-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:10;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:
117
+ /**
118
+ * Breadcrumbs and other in-page `navigate` commands bypass `routerLink`, so prompt here
119
+ * when the hosted page implements {@link AXPUnsavedChangesCanDeactivate}.
120
+ * A successful confirm sets `leaveConfirmed` for the router guard on the subsequent navigation.
121
+ */
122
+ async canLeaveCurrentPage() {
123
+ const page = this.page;
124
+ if (!page || typeof page.canDeactivate !== 'function') {
125
+ return true;
126
+ }
127
+ return page.canDeactivate();
128
+ }
129
+ //#region ---------------- Status Helpers ----------------
130
+ getEntityData() {
131
+ // Get entity data from page context if available
132
+ if (this.page && 'getEntityData' in this.page && typeof this.page.getEntityData === 'function') {
133
+ return this.page.getEntityData();
134
+ }
135
+ return null;
136
+ }
137
+ async handleStatusTransition(transition) {
138
+ // Convert status transition to command and execute
139
+ await this.execute({
140
+ name: 'update-status',
141
+ options: {
142
+ transition,
143
+ },
144
+ });
145
+ }
146
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
147
+ 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:
116
148
  //
117
149
  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:
118
150
  //
119
- AXPComponentSlotModule }, { kind: "directive", type: i8.AXPComponentSlotDirective, selector: "axp-component-slot", inputs: ["name", "host", "context"], exportAs: ["slot"] }, { 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: "component", type: AXPThemeLayoutActionsComponent, selector: "axp-layout-actions" }, { kind: "component", type: AXPThemeLayoutHeaderComponent, selector: "axp-layout-header" }, { kind: "directive", type: AXPStickyDirective, selector: "[axpSticky]", inputs: ["axpSticky", "stickyOffset", "stickyParent", "stickyTarget"], outputs: ["isStickyChange"], exportAs: ["axpSticky"] }, { kind: "component", type: AXPThemeLayoutContainerComponent, selector: "axp-layout-container" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
151
+ AXPComponentSlotModule }, { kind: "directive", type: i8.AXPComponentSlotDirective, selector: "axp-component-slot", inputs: ["name", "host", "context"], exportAs: ["slot"] }, { 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: "component", type: AXPThemeLayoutActionsComponent, selector: "axp-layout-actions" }, { kind: "component", type: AXPThemeLayoutHeaderComponent, selector: "axp-layout-header" }, { kind: "directive", type: AXPStickyDirective, selector: "[axpSticky]", inputs: ["axpSticky", "stickyOffset", "stickyParent", "stickyTarget"], outputs: ["isStickyChange"], exportAs: ["axpSticky"] }, { kind: "component", type: AXPThemeLayoutContainerComponent, selector: "axp-layout-container" }, { kind: "component", type: AXPStatusChipComponent, selector: "axp-status-chip", inputs: ["status", "value", "readonly", "availableTransitions", "definitionKey", "entityData"], outputs: ["openChange", "transitionExecuted", "transitionError"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
120
152
  }
121
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPPageLayoutComponent, decorators: [{
153
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageLayoutComponent, decorators: [{
122
154
  type: Component,
123
155
  args: [{ standalone: true, imports: [
124
156
  CommonModule,
@@ -139,9 +171,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
139
171
  AXPThemeLayoutHeaderComponent,
140
172
  AXPStickyDirective,
141
173
  AXPThemeLayoutContainerComponent,
142
- ], selector: 'axp-page-layout', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [AXDrawerContainerDirective], providers: [], template: "<div\n id=\"axp-drawer-start\"\n [mode]=\"deviceService.isSmall() ? 'overlay' : 'push'\"\n [transition]=\"250\"\n axDrawerItem\n [backDrop]=\"true\"\n (onBackdropClick)=\"handleBackdropClick($event)\"\n #startSideDrawer=\"axDrawerItem\"\n [backdropClass]=\"'ax-bg-darkest/75'\"\n [collapsed]=\"deviceService.isSmall()\"\n drawerLocation=\"start\"\n class=\"ax-z-50 ax-h-full\"\n>\n <ng-content select=\"axp-layout-start-side\"></ng-content>\n</div>\n<axp-layout-container id=\"axp-page-layout\" #container>\n <axp-layout-header\n id=\"axp-page-header\"\n *translate=\"let t\"\n #sticky=\"axpSticky\"\n [axpSticky]=\"'axp-is-sticky'\"\n [stickyOffset]=\"50\"\n [stickyParent]=\"container.hostElement\"\n >\n @if (page?.hasBackButton() && deviceService.isSmall()) {\n <ax-button\n id=\"axp-btn-back\"\n [look]=\"'blank'\"\n class=\"ax-sm ax-w-fit ax-ms-1\"\n color=\"secondary\"\n (click)=\"page?.onBackButtonClick()\"\n [text]=\"page?.backButton()?.title\"\n >\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 <!-------- Begin Title Bar -------->\n <axp-layout-title-bar id=\"axp-title-bar\">\n <!-------- Begin Title -------->\n <div class=\"ax-flex ax-flex-col ax-transition\">\n <!-- 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\n [attr.id]=\"'axp-breadcrumb-item-' + $index\"\n [active]=\"$last\"\n (click)=\"item.command ? execute(item.command) : null\"\n >\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 <div class=\"__title-container\">\n <!-- Title -->\n @if (page?.hasTitle()) {\n <axp-layout-title id=\"axp-page-title\"> {{ t(page?.title()) | async }}</axp-layout-title>\n }\n <!-- 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\n [attr.id]=\"'axp-btn-title-action-' + (sub.name || $index)\"\n [text]=\"(t(sub.title) | async)!\"\n [color]=\"sub.color\"\n [disabled]=\"sub.disabled\"\n (onClick)=\"handleActionClick(sub)\"\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 </ng-container>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n <!-- 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\"\n >\n <i class=\"fa-solid fa-circle\"></i>\n {{ page?.badge()?.title }}\n </div>\n }\n </div>\n <!-- Description -->\n @if (page?.hasDescription()) {\n <axp-layout-description id=\"axp-page-description\">\n {{ t(page?.description()) | async }}</axp-layout-description\n >\n }\n </div>\n <!-------- Finish Title -------->\n <!--------------------------------------------------------------->\n <!-------- Page Actions -------->\n\n <axp-layout-actions id=\"axp-page-actions\" class=\"ax-shrink-0\">\n <axp-component-slot name=\"page-header-actions\"></axp-component-slot>\n <!--Primary Actions -->\n @if (page?.hasPrimaryActions()) {\n <!-- items -->\n @for (item of page?.primaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button\n [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\"\n [class.ax-sm]=\"deviceService.isSmall()\"\n [iconOnly]=\"deviceService.isSmall()\"\n [disabled]=\"item.disabled\"\n [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"item.color\"\n (onClick)=\"handleActionClick(item)\"\n >\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\n [attr.id]=\"'axp-btn-primary-' + (item.name || item.title) + '-' + (sub.name || sub.title)\"\n [text]=\"(t(sub.title) | async)!\"\n [color]=\"sub.color\"\n [disabled]=\"sub.disabled\"\n (onClick)=\"handleActionClick(sub)\"\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 <!-- Secondary Actions -->\n @if (page?.hasSecondaryActions()) {\n <ax-button\n id=\"axp-btn-secondary\"\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 (item of page?.secondaryMenuItems(); track $index) {\n @if (item.visible != false) {\n <ax-button-item\n [attr.id]=\"'axp-btn-secondary-' + (item.name || item.title)\"\n [text]=\"(item.title | translate | async)!\"\n [color]=\"item.color\"\n [disabled]=\"item.disabled\"\n (onClick)=\"handleSecondaryActionClick(item)\"\n >\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 </axp-layout-actions>\n <!-- Finish Page Actions -->\n </axp-layout-title-bar>\n <!----- Finish Title Bar ----->\n <!--------------------------------------------------------------->\n <!-- Begin Navbar -->\n @if (!sticky.isSticky) {}\n <ng-content select=\"axp-page-toolbar\"></ng-content>\n <!-- Finish Navbar -->\n </axp-layout-header>\n <ng-content select=\"axp-page-content\"></ng-content>\n\n <axp-page-footer-container\n id=\"axp-page-footer-container\"\n [ngStyle]=\"{ display: tt.isEmpty() && prefixSlot.isEmpty() && suffixSlot.isEmpty() ? 'none' : 'block' }\"\n >\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</axp-layout-container>\n", styles: [".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 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 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;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{position:sticky;top:0;z-index:10;display:flex;flex-direction:column;align-items:flex-start;gap:0px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1));padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@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.--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.--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.--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-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:10;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"] }]
174
+ AXPStatusChipComponent,
175
+ ], 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"] }]
143
176
  }], propDecorators: { startSideDrawer: [{ type: i0.ViewChild, args: ['startSideDrawer', { isSignal: true }] }] } });
144
177
 
178
+ //#region ---- Page Unsaved Changes Utilities ----
179
+ /**
180
+ * Builds the standard "Not Saved" page badge when the global show-page-badge setting is enabled.
181
+ */
182
+ async function buildNotSavedPageBadge(translateService, settingsService) {
183
+ const showPageBadge = await settingsService.get(AXPCommonSettings.ShowPageBadge);
184
+ if (!showPageBadge) {
185
+ return null;
186
+ }
187
+ return {
188
+ title: await translateService.translateAsync('@general:terms.interface.save-status.not-saved.title'),
189
+ color: 'warning',
190
+ description: await translateService.translateAsync('@general:terms.interface.save-status.not-saved.description'),
191
+ };
192
+ }
193
+ /**
194
+ * Whether a command name represents a discard/revert action on a details sub-page.
195
+ */
196
+ function isDiscardCommand(commandName, rejectCommandName) {
197
+ if (!commandName) {
198
+ return false;
199
+ }
200
+ if (rejectCommandName && commandName === rejectCommandName) {
201
+ return true;
202
+ }
203
+ if (commandName === 'discard') {
204
+ return true;
205
+ }
206
+ return /:discard$/i.test(commandName) || commandName.endsWith('Discard');
207
+ }
208
+ //#endregion
209
+
145
210
  class AXPPageLayoutBaseComponent {
146
211
  constructor() {
147
212
  //#region ---------------- Services ----------------
@@ -152,26 +217,55 @@ class AXPPageLayoutBaseComponent {
152
217
  this.toastService = inject(AXToastService);
153
218
  this.homePageService = inject(AXPHomePageService);
154
219
  this.policyService = inject(AXPPolicyEngineService);
220
+ this.settingsService = inject(AXPSettingsService);
155
221
  //#endregion
156
222
  //#region ---------------- Signal to force recomputation ----------------
157
- this._updateTrigger = signal(0, ...(ngDevMode ? [{ debugName: "_updateTrigger" }] : []));
223
+ this._updateTrigger = signal(0, ...(ngDevMode ? [{ debugName: "_updateTrigger" }] : /* istanbul ignore next */ []));
158
224
  this.updateTrigger = this._updateTrigger.asReadonly();
159
225
  //#endregion
160
226
  //#region ---------------- Title ----------------
161
- this.title = signal('', ...(ngDevMode ? [{ debugName: "title" }] : []));
227
+ this.title = signal('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
228
+ this.titleIcon = signal(null, ...(ngDevMode ? [{ debugName: "titleIcon" }] : /* istanbul ignore next */ []));
162
229
  this.#titleEffect = effect(async () => {
163
230
  this.updateTrigger();
164
231
  this.title.set(await this.getPageTitle());
165
- }, ...(ngDevMode ? [{ debugName: "#titleEffect" }] : []));
166
- this.hasTitle = computed(() => this.title() !== '', ...(ngDevMode ? [{ debugName: "hasTitle" }] : []));
232
+ const icon = await this.getPageIcon();
233
+ this.titleIcon.set(icon);
234
+ }, ...(ngDevMode ? [{ debugName: "#titleEffect" }] : /* istanbul ignore next */ []));
235
+ this.hasTitle = computed(() => {
236
+ const value = this.title();
237
+ if (value === null || value === undefined) {
238
+ return false;
239
+ }
240
+ if (typeof value === 'string') {
241
+ return value.length > 0;
242
+ }
243
+ if (typeof value === 'object' && !Array.isArray(value)) {
244
+ return !isEmpty(value);
245
+ }
246
+ return false;
247
+ }, ...(ngDevMode ? [{ debugName: "hasTitle" }] : /* istanbul ignore next */ []));
248
+ this.hasTitleIcon = computed(() => this.titleIcon() !== null, ...(ngDevMode ? [{ debugName: "hasTitleIcon" }] : /* istanbul ignore next */ []));
167
249
  //#endregion
168
250
  //#region ---------------- Description ----------------
169
- this.description = signal(null, ...(ngDevMode ? [{ debugName: "description" }] : []));
170
- this.hasDescription = computed(() => !isNil(this.description()) && !isEmpty(this.description()), ...(ngDevMode ? [{ debugName: "hasDescription" }] : []));
251
+ this.description = signal(null, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
252
+ this.hasDescription = computed(() => {
253
+ const value = this.description();
254
+ if (value === null || value === undefined) {
255
+ return false;
256
+ }
257
+ if (typeof value === 'string') {
258
+ return value.length > 0;
259
+ }
260
+ if (typeof value === 'object' && !Array.isArray(value)) {
261
+ return !isEmpty(value);
262
+ }
263
+ return false;
264
+ }, ...(ngDevMode ? [{ debugName: "hasDescription" }] : /* istanbul ignore next */ []));
171
265
  this.#descriptionEffect = effect(async () => {
172
266
  this.updateTrigger();
173
267
  this.description.set(await this.getPageDescription());
174
- }, ...(ngDevMode ? [{ debugName: "#descriptionEffect" }] : []));
268
+ }, ...(ngDevMode ? [{ debugName: "#descriptionEffect" }] : /* istanbul ignore next */ []));
175
269
  //#endregion
176
270
  //#region ---------------- Breadcrumbs ----------------
177
271
  this.defaultBreadCrumbs = [
@@ -186,53 +280,61 @@ class AXPPageLayoutBaseComponent {
186
280
  },
187
281
  },
188
282
  ];
189
- this.breadcrumbs = signal(this.defaultBreadCrumbs, ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : []));
283
+ this.breadcrumbs = signal(this.defaultBreadCrumbs, ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : /* istanbul ignore next */ []));
190
284
  this.#breadcrumbsEffect = effect(async () => {
191
285
  this.updateTrigger();
192
286
  const breadCrumbs = await this.getPageBreadcrumbs();
193
287
  this.breadcrumbs.set([...this.defaultBreadCrumbs, ...breadCrumbs]);
194
- }, ...(ngDevMode ? [{ debugName: "#breadcrumbsEffect" }] : []));
195
- this.hasBreadcrumbs = computed(() => this.breadcrumbs().length > 1, ...(ngDevMode ? [{ debugName: "hasBreadcrumbs" }] : []));
288
+ }, ...(ngDevMode ? [{ debugName: "#breadcrumbsEffect" }] : /* istanbul ignore next */ []));
289
+ this.hasBreadcrumbs = computed(() => this.breadcrumbs().length > 1, ...(ngDevMode ? [{ debugName: "hasBreadcrumbs" }] : /* istanbul ignore next */ []));
196
290
  //#endregion
197
291
  //#region ---------------- Badge ----------------
198
- this.badge = signal(null, ...(ngDevMode ? [{ debugName: "badge" }] : []));
199
- this.hasBadge = computed(() => this.badge() !== null, ...(ngDevMode ? [{ debugName: "hasBadge" }] : []));
292
+ this.badge = signal(null, ...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
293
+ this.hasBadge = computed(() => this.badge() !== null, ...(ngDevMode ? [{ debugName: "hasBadge" }] : /* istanbul ignore next */ []));
200
294
  this.#badgeEffect = effect(async () => {
201
295
  this.updateTrigger();
202
296
  this.badge.set(await this.getPageBadge());
203
- }, ...(ngDevMode ? [{ debugName: "#badgeEffect" }] : []));
297
+ }, ...(ngDevMode ? [{ debugName: "#badgeEffect" }] : /* istanbul ignore next */ []));
298
+ //#endregion
299
+ //#region ---------------- Status ----------------
300
+ this.status = signal(null, ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
301
+ this.hasStatus = computed(() => this.status() !== null, ...(ngDevMode ? [{ debugName: "hasStatus" }] : /* istanbul ignore next */ []));
302
+ this.#statusEffect = effect(async () => {
303
+ this.updateTrigger();
304
+ this.status.set(await this.getPageStatus());
305
+ }, ...(ngDevMode ? [{ debugName: "#statusEffect" }] : /* istanbul ignore next */ []));
204
306
  //#endregion
205
307
  //#region ---------------- Layout ----------------
206
- this.layout = viewChild(AXPPageLayoutComponent, ...(ngDevMode ? [{ debugName: "layout" }] : []));
308
+ this.layout = viewChild(AXPPageLayoutComponent, ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
207
309
  //#endregion
208
310
  //#region ---------------- Actions ----------------
209
- this.primaryMenuItems = signal([], ...(ngDevMode ? [{ debugName: "primaryMenuItems" }] : []));
210
- this.hasPrimaryActions = computed(() => this.primaryMenuItems().filter(item => item.visible != false).length > 0, ...(ngDevMode ? [{ debugName: "hasPrimaryActions" }] : []));
311
+ this.primaryMenuItems = signal([], ...(ngDevMode ? [{ debugName: "primaryMenuItems" }] : /* istanbul ignore next */ []));
312
+ this.hasPrimaryActions = computed(() => this.primaryMenuItems().filter((item) => item.visible != false).length > 0, ...(ngDevMode ? [{ debugName: "hasPrimaryActions" }] : /* istanbul ignore next */ []));
211
313
  this.#primaryMenuItemsEffect = effect(async () => {
212
314
  this.updateTrigger();
213
315
  const items = await this.getPrimaryMenuItems();
214
316
  this.primaryMenuItems.set(items);
215
- }, ...(ngDevMode ? [{ debugName: "#primaryMenuItemsEffect" }] : []));
216
- this.secondaryMenuItems = signal([], ...(ngDevMode ? [{ debugName: "secondaryMenuItems" }] : []));
217
- this.hasSecondaryActions = computed(() => this.secondaryMenuItems().filter(item => item.visible != false).length > 0, ...(ngDevMode ? [{ debugName: "hasSecondaryActions" }] : []));
317
+ }, ...(ngDevMode ? [{ debugName: "#primaryMenuItemsEffect" }] : /* istanbul ignore next */ []));
318
+ this.secondaryMenuItems = signal([], ...(ngDevMode ? [{ debugName: "secondaryMenuItems" }] : /* istanbul ignore next */ []));
319
+ this.hasSecondaryActions = computed(() => this.secondaryMenuItems().filter((item) => item.visible != false).length > 0, ...(ngDevMode ? [{ debugName: "hasSecondaryActions" }] : /* istanbul ignore next */ []));
218
320
  this.#secondaryMenuItemsEffect = effect(async () => {
219
321
  this.updateTrigger();
220
322
  const items = await this.getSecondaryMenuItems();
221
323
  this.secondaryMenuItems.set(items);
222
- }, ...(ngDevMode ? [{ debugName: "#secondaryMenuItemsEffect" }] : []));
223
- this.hasActions = computed(() => this.hasPrimaryActions() || this.hasSecondaryActions(), ...(ngDevMode ? [{ debugName: "hasActions" }] : []));
224
- this.titleActions = signal([], ...(ngDevMode ? [{ debugName: "titleActions" }] : []));
225
- this.hasTitleActions = computed(() => this.titleActions().length > 0, ...(ngDevMode ? [{ debugName: "hasTitleActions" }] : []));
324
+ }, ...(ngDevMode ? [{ debugName: "#secondaryMenuItemsEffect" }] : /* istanbul ignore next */ []));
325
+ this.hasActions = computed(() => this.hasPrimaryActions() || this.hasSecondaryActions(), ...(ngDevMode ? [{ debugName: "hasActions" }] : /* istanbul ignore next */ []));
326
+ this.titleActions = signal([], ...(ngDevMode ? [{ debugName: "titleActions" }] : /* istanbul ignore next */ []));
327
+ this.hasTitleActions = computed(() => this.titleActions().length > 0, ...(ngDevMode ? [{ debugName: "hasTitleActions" }] : /* istanbul ignore next */ []));
226
328
  this.#titleActionsEffect = effect(async () => {
227
329
  this.updateTrigger();
228
330
  this.titleActions.set(await this.getTitleActions());
229
- }, ...(ngDevMode ? [{ debugName: "#titleActionsEffect" }] : []));
230
- this.backButton = signal(null, ...(ngDevMode ? [{ debugName: "backButton" }] : []));
231
- this.hasBackButton = computed(() => this.backButton() !== null, ...(ngDevMode ? [{ debugName: "hasBackButton" }] : []));
331
+ }, ...(ngDevMode ? [{ debugName: "#titleActionsEffect" }] : /* istanbul ignore next */ []));
332
+ this.backButton = signal(null, ...(ngDevMode ? [{ debugName: "backButton" }] : /* istanbul ignore next */ []));
333
+ this.hasBackButton = computed(() => this.backButton() !== null, ...(ngDevMode ? [{ debugName: "hasBackButton" }] : /* istanbul ignore next */ []));
232
334
  this.#backButtonEffect = effect(async () => {
233
335
  this.updateTrigger();
234
336
  this.backButton.set(await this.getBackButton());
235
- }, ...(ngDevMode ? [{ debugName: "#backButtonEffect" }] : []));
337
+ }, ...(ngDevMode ? [{ debugName: "#backButtonEffect" }] : /* istanbul ignore next */ []));
236
338
  }
237
339
  recompute() {
238
340
  this._updateTrigger.set(this._updateTrigger() + 1);
@@ -248,6 +350,9 @@ class AXPPageLayoutBaseComponent {
248
350
  getPageTitle() {
249
351
  return '';
250
352
  }
353
+ getPageIcon() {
354
+ return null;
355
+ }
251
356
  #descriptionEffect;
252
357
  getPageDescription() {
253
358
  return null;
@@ -257,7 +362,20 @@ class AXPPageLayoutBaseComponent {
257
362
  return [];
258
363
  }
259
364
  #badgeEffect;
260
- getPageBadge() {
365
+ hasUnsavedChanges() {
366
+ return false;
367
+ }
368
+ async getPageBadge() {
369
+ if (!this.hasUnsavedChanges()) {
370
+ return null;
371
+ }
372
+ return buildNotSavedPageBadge(this.translateService, this.settingsService);
373
+ }
374
+ async resolvePageBadge() {
375
+ return this.getPageBadge();
376
+ }
377
+ #statusEffect;
378
+ getPageStatus() {
261
379
  return null;
262
380
  }
263
381
  //TODO: Remove this after migration to the new layout
@@ -287,18 +405,26 @@ class AXPPageLayoutBaseComponent {
287
405
  //#endregion
288
406
  //#region ---------------- Handle Commands ----------------
289
407
  execute(command) { }
408
+ /**
409
+ * Optional partial context to merge into the create/update wizard when leaving a page step.
410
+ * Override when the page keeps edits in local state instead of the shared form context.
411
+ */
412
+ getWizardStepContext() {
413
+ return null;
414
+ }
290
415
  startSideToggle() {
291
416
  this.layout();
292
417
  }
293
418
  onBackButtonClick() { }
294
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPPageLayoutBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
295
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.12", type: AXPPageLayoutBaseComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "layout", first: true, predicate: AXPPageLayoutComponent, descendants: true, isSignal: true }], ngImport: i0, template: '', isInline: true }); }
419
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageLayoutBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
420
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.9", type: AXPPageLayoutBaseComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "layout", first: true, predicate: AXPPageLayoutComponent, descendants: true, isSignal: true }], ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
296
421
  }
297
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPPageLayoutBaseComponent, decorators: [{
422
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageLayoutBaseComponent, decorators: [{
298
423
  type: Component,
299
424
  args: [{
300
425
  standalone: true,
301
426
  template: '',
427
+ changeDetection: ChangeDetectionStrategy.OnPush,
302
428
  }]
303
429
  }], propDecorators: { layout: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPPageLayoutComponent), { isSignal: true }] }] } });
304
430
 
@@ -316,7 +442,7 @@ class AXPPopupLayoutComponent {
316
442
  this.#effect = effect(() => {
317
443
  this.popup?.title();
318
444
  this.checkScrollableContent();
319
- }, ...(ngDevMode ? [{ debugName: "#effect" }] : []));
445
+ }, ...(ngDevMode ? [{ debugName: "#effect" }] : /* istanbul ignore next */ []));
320
446
  }
321
447
  #initialize;
322
448
  #effect;
@@ -342,14 +468,14 @@ class AXPPopupLayoutComponent {
342
468
  e.component.hide();
343
469
  return false;
344
470
  }
345
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPPopupLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
346
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPPopupLayoutComponent, isStandalone: true, selector: "axp-popup-layout", ngImport: i0, template: "<axp-layout-container id=\"axp-popup-layout\" #container>\n <ng-content select=\"axp-page-content\"></ng-content>\n <axp-page-footer id=\"axp-popup-footer\" *translate=\"let t\">\n <ax-prefix> </ax-prefix>\n @if (popup.hasPrimaryActions()) {\n <ax-suffix>\n @for (item of popup.primaryMenuItems(); track $index) {\n <ax-button\n [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\"\n [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"item.color\"\n (onClick)=\"handleActionClick(item)\"\n >\n <ax-prefix>\n <i class=\"{{ item.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n </ax-suffix>\n }\n </axp-page-footer>\n</axp-layout-container>\n", styles: [".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-popup-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-popup-layout>axp-layout-container{position:relative;display:flex;width:100%;height:100%;flex-direction:column;overflow:auto;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-popup-layout>axp-layout-container>axp-layout-header{position:sticky;top:0;z-index:10;display:flex;flex-direction:column;align-items:flex-start;gap:0px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1));padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@media (min-width: 768px){axp-popup-layout>axp-layout-container>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-popup-layout>axp-layout-container>axp-page-content{display:flex;width:100%;flex:1 1 0%;flex-direction:column}axp-popup-layout>axp-layout-container>axp-page-footer{border-top-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1))}axp-popup-layout>axp-layout-container>axp-page-footer:is(.ax-dark *){--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-dark-surface),var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-dark-surface),var(--tw-bg-opacity, 1))}axp-popup-layout>axp-layout-container>axp-page-footer{position:sticky;bottom:0;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-popup-layout>axp-layout-container>axp-page-footer.--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: "ngmodule", type:
471
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPopupLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
472
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPPopupLayoutComponent, isStandalone: true, selector: "axp-popup-layout", ngImport: i0, template: "<axp-layout-container id=\"axp-popup-layout\" #container>\n <ng-content select=\"axp-page-content\"></ng-content>\n <axp-page-footer id=\"axp-popup-footer\" *translate=\"let t\">\n <ax-prefix> </ax-prefix>\n @if (popup.hasPrimaryActions()) {\n <ax-suffix>\n @for (item of popup.primaryMenuItems(); track $index) {\n <ax-button\n [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\"\n [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"item.color\"\n (onClick)=\"handleActionClick(item)\"\n >\n <ax-prefix>\n <i class=\"{{ item.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n </ax-suffix>\n }\n </axp-page-footer>\n</axp-layout-container>\n", styles: [".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-popup-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-popup-layout>axp-layout-container{position:relative;display:flex;width:100%;height:100%;flex-direction:column;overflow:auto;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-popup-layout>axp-layout-container>axp-layout-header{position:sticky;top:0;z-index:10;display:flex;flex-direction:column;align-items:flex-start;gap:0px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1));padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@media(min-width:768px){axp-popup-layout>axp-layout-container>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-popup-layout>axp-layout-container>axp-page-content{display:flex;width:100%;flex:1 1 0%;flex-direction:column}axp-popup-layout>axp-layout-container>axp-page-footer{border-top-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1))}axp-popup-layout>axp-layout-container>axp-page-footer:is(.ax-dark *){--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-dark-surface),var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-dark-surface),var(--tw-bg-opacity, 1))}axp-popup-layout>axp-layout-container>axp-page-footer{position:sticky;bottom:0;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-popup-layout>axp-layout-container>axp-page-footer.--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: "ngmodule", type:
347
473
  //
348
474
  AXCommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { 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: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { 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: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i3$1.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXDrawerModule }, { kind: "ngmodule", type: AXDrawerDirectiveModule }, { kind: "component", type:
349
475
  //
350
476
  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: "component", type: AXPThemeLayoutContainerComponent, selector: "axp-layout-container" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
351
477
  }
352
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPPopupLayoutComponent, decorators: [{
478
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPopupLayoutComponent, decorators: [{
353
479
  type: Component,
354
480
  args: [{ standalone: true, imports: [
355
481
  CommonModule,
@@ -366,7 +492,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
366
492
  //
367
493
  AXPThemeLayoutBlockComponent,
368
494
  AXPThemeLayoutContainerComponent,
369
- ], selector: 'axp-popup-layout', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<axp-layout-container id=\"axp-popup-layout\" #container>\n <ng-content select=\"axp-page-content\"></ng-content>\n <axp-page-footer id=\"axp-popup-footer\" *translate=\"let t\">\n <ax-prefix> </ax-prefix>\n @if (popup.hasPrimaryActions()) {\n <ax-suffix>\n @for (item of popup.primaryMenuItems(); track $index) {\n <ax-button\n [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\"\n [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"item.color\"\n (onClick)=\"handleActionClick(item)\"\n >\n <ax-prefix>\n <i class=\"{{ item.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n </ax-suffix>\n }\n </axp-page-footer>\n</axp-layout-container>\n", styles: [".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-popup-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-popup-layout>axp-layout-container{position:relative;display:flex;width:100%;height:100%;flex-direction:column;overflow:auto;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-popup-layout>axp-layout-container>axp-layout-header{position:sticky;top:0;z-index:10;display:flex;flex-direction:column;align-items:flex-start;gap:0px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1));padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@media (min-width: 768px){axp-popup-layout>axp-layout-container>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-popup-layout>axp-layout-container>axp-page-content{display:flex;width:100%;flex:1 1 0%;flex-direction:column}axp-popup-layout>axp-layout-container>axp-page-footer{border-top-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1))}axp-popup-layout>axp-layout-container>axp-page-footer:is(.ax-dark *){--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-dark-surface),var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-dark-surface),var(--tw-bg-opacity, 1))}axp-popup-layout>axp-layout-container>axp-page-footer{position:sticky;bottom:0;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-popup-layout>axp-layout-container>axp-page-footer.--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"] }]
495
+ ], selector: 'axp-popup-layout', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<axp-layout-container id=\"axp-popup-layout\" #container>\n <ng-content select=\"axp-page-content\"></ng-content>\n <axp-page-footer id=\"axp-popup-footer\" *translate=\"let t\">\n <ax-prefix> </ax-prefix>\n @if (popup.hasPrimaryActions()) {\n <ax-suffix>\n @for (item of popup.primaryMenuItems(); track $index) {\n <ax-button\n [attr.id]=\"'axp-btn-primary-' + (item.name || item.title)\"\n [text]=\"(t(item.title) | async)!\"\n [look]=\"'solid'\"\n [color]=\"item.color\"\n (onClick)=\"handleActionClick(item)\"\n >\n <ax-prefix>\n <i class=\"{{ item.icon }}\"></i>\n </ax-prefix>\n </ax-button>\n }\n </ax-suffix>\n }\n </axp-page-footer>\n</axp-layout-container>\n", styles: [".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-popup-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-popup-layout>axp-layout-container{position:relative;display:flex;width:100%;height:100%;flex-direction:column;overflow:auto;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-popup-layout>axp-layout-container>axp-layout-header{position:sticky;top:0;z-index:10;display:flex;flex-direction:column;align-items:flex-start;gap:0px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1));padding-top:.5rem;padding-bottom:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}@media(min-width:768px){axp-popup-layout>axp-layout-container>axp-layout-header{padding-top:1rem;padding-bottom:1rem}}axp-popup-layout>axp-layout-container>axp-page-content{display:flex;width:100%;flex:1 1 0%;flex-direction:column}axp-popup-layout>axp-layout-container>axp-page-footer{border-top-width:1px;--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-lightest-surface),var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-lightest-surface),var(--tw-bg-opacity, 1))}axp-popup-layout>axp-layout-container>axp-page-footer:is(.ax-dark *){--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-border-dark-surface),var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-dark-surface),var(--tw-bg-opacity, 1))}axp-popup-layout>axp-layout-container>axp-page-footer{position:sticky;bottom:0;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-popup-layout>axp-layout-container>axp-page-footer.--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"] }]
370
496
  }] });
371
497
 
372
498
  class AXPPopupLayoutBaseComponent extends AXBasePageComponent {
@@ -381,41 +507,41 @@ class AXPPopupLayoutBaseComponent extends AXBasePageComponent {
381
507
  this.homePageService = inject(AXPHomePageService);
382
508
  //#endregion
383
509
  //#region ---------------- Signal to force recomputation ----------------
384
- this._updateTrigger = signal(0, ...(ngDevMode ? [{ debugName: "_updateTrigger" }] : []));
510
+ this._updateTrigger = signal(0, ...(ngDevMode ? [{ debugName: "_updateTrigger" }] : /* istanbul ignore next */ []));
385
511
  this.updateTrigger = this._updateTrigger.asReadonly();
386
512
  //#endregion
387
513
  //#region ---------------- Title ----------------
388
- this.title = signal('', ...(ngDevMode ? [{ debugName: "title" }] : []));
514
+ this.title = signal('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
389
515
  this.#titleEffect = effect(async () => {
390
516
  this.updateTrigger();
391
517
  this.title.set(await this.getPopupTitle());
392
- }, ...(ngDevMode ? [{ debugName: "#titleEffect" }] : []));
393
- this.hasTitle = computed(() => this.title() !== '', ...(ngDevMode ? [{ debugName: "hasTitle" }] : []));
518
+ }, ...(ngDevMode ? [{ debugName: "#titleEffect" }] : /* istanbul ignore next */ []));
519
+ this.hasTitle = computed(() => this.title() !== '', ...(ngDevMode ? [{ debugName: "hasTitle" }] : /* istanbul ignore next */ []));
394
520
  //#endregion
395
521
  //#region ---------------- Layout ----------------
396
522
  // Placeholder for popup layout reference if needed
397
- this.layout = viewChild(AXPPopupLayoutComponent, ...(ngDevMode ? [{ debugName: "layout" }] : []));
523
+ this.layout = viewChild(AXPPopupLayoutComponent, ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
398
524
  //#endregion
399
525
  //#region ---------------- Actions ----------------
400
- this.primaryMenuItems = signal([], ...(ngDevMode ? [{ debugName: "primaryMenuItems" }] : []));
401
- this.hasPrimaryActions = computed(() => this.primaryMenuItems().length > 0, ...(ngDevMode ? [{ debugName: "hasPrimaryActions" }] : []));
526
+ this.primaryMenuItems = signal([], ...(ngDevMode ? [{ debugName: "primaryMenuItems" }] : /* istanbul ignore next */ []));
527
+ this.hasPrimaryActions = computed(() => this.primaryMenuItems().length > 0, ...(ngDevMode ? [{ debugName: "hasPrimaryActions" }] : /* istanbul ignore next */ []));
402
528
  this.#primaryMenuItemsEffect = effect(async () => {
403
529
  this.updateTrigger();
404
530
  this.primaryMenuItems.set(await this.getPrimaryMenuItems());
405
- }, ...(ngDevMode ? [{ debugName: "#primaryMenuItemsEffect" }] : []));
406
- this.secondaryMenuItems = signal([], ...(ngDevMode ? [{ debugName: "secondaryMenuItems" }] : []));
407
- this.hasSecondaryActions = computed(() => this.secondaryMenuItems().length > 0, ...(ngDevMode ? [{ debugName: "hasSecondaryActions" }] : []));
531
+ }, ...(ngDevMode ? [{ debugName: "#primaryMenuItemsEffect" }] : /* istanbul ignore next */ []));
532
+ this.secondaryMenuItems = signal([], ...(ngDevMode ? [{ debugName: "secondaryMenuItems" }] : /* istanbul ignore next */ []));
533
+ this.hasSecondaryActions = computed(() => this.secondaryMenuItems().length > 0, ...(ngDevMode ? [{ debugName: "hasSecondaryActions" }] : /* istanbul ignore next */ []));
408
534
  this.#secondaryMenuItemsEffect = effect(async () => {
409
535
  this.updateTrigger();
410
536
  this.secondaryMenuItems.set(await this.getSecondaryMenuItems());
411
- }, ...(ngDevMode ? [{ debugName: "#secondaryMenuItemsEffect" }] : []));
412
- this.hasActions = computed(() => this.hasPrimaryActions() || this.hasSecondaryActions(), ...(ngDevMode ? [{ debugName: "hasActions" }] : []));
413
- this.titleActions = signal([], ...(ngDevMode ? [{ debugName: "titleActions" }] : []));
414
- this.hasTitleActions = computed(() => this.titleActions().length > 0, ...(ngDevMode ? [{ debugName: "hasTitleActions" }] : []));
537
+ }, ...(ngDevMode ? [{ debugName: "#secondaryMenuItemsEffect" }] : /* istanbul ignore next */ []));
538
+ this.hasActions = computed(() => this.hasPrimaryActions() || this.hasSecondaryActions(), ...(ngDevMode ? [{ debugName: "hasActions" }] : /* istanbul ignore next */ []));
539
+ this.titleActions = signal([], ...(ngDevMode ? [{ debugName: "titleActions" }] : /* istanbul ignore next */ []));
540
+ this.hasTitleActions = computed(() => this.titleActions().length > 0, ...(ngDevMode ? [{ debugName: "hasTitleActions" }] : /* istanbul ignore next */ []));
415
541
  this.#titleActionsEffect = effect(async () => {
416
542
  this.updateTrigger();
417
543
  this.titleActions.set(await this.getTitleActions());
418
- }, ...(ngDevMode ? [{ debugName: "#titleActionsEffect" }] : []));
544
+ }, ...(ngDevMode ? [{ debugName: "#titleActionsEffect" }] : /* istanbul ignore next */ []));
419
545
  }
420
546
  recompute() {
421
547
  this._updateTrigger.set(this._updateTrigger() + 1);
@@ -447,17 +573,53 @@ class AXPPopupLayoutBaseComponent extends AXBasePageComponent {
447
573
  //#endregion
448
574
  //#region ---------------- Handle Commands ----------------
449
575
  execute(command) { }
450
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPPopupLayoutBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
451
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.12", type: AXPPopupLayoutBaseComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "layout", first: true, predicate: AXPPopupLayoutComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: '', isInline: true }); }
576
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPopupLayoutBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
577
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.9", type: AXPPopupLayoutBaseComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "layout", first: true, predicate: AXPPopupLayoutComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
452
578
  }
453
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPPopupLayoutBaseComponent, decorators: [{
579
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPopupLayoutBaseComponent, decorators: [{
454
580
  type: Component,
455
581
  args: [{
456
582
  standalone: true,
457
583
  template: '',
584
+ changeDetection: ChangeDetectionStrategy.OnPush,
458
585
  }]
459
586
  }], propDecorators: { layout: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPPopupLayoutComponent), { isSignal: true }] }] } });
460
587
 
588
+ //#region ---- Root-context widget expression resolution ----
589
+ /**
590
+ * Evaluates `{{ ... }}` strings inside `options.customFilterDefinitions` using `rootContext`
591
+ * (details adapter load data), so filter UI does not depend on widget-renderer contextService.
592
+ */
593
+ async function buildEvaluatedPageContentsForRootContext(currentPage, rootContext, evaluatorService) {
594
+ if (!currentPage) {
595
+ return { evaluatedPageContent: [], evaluatedTabContentsById: {} };
596
+ }
597
+ const scope = {
598
+ context: {
599
+ eval: (path) => getSmart(rootContext, path),
600
+ },
601
+ };
602
+ const resolveNodes = async (nodes) => {
603
+ if (!nodes?.length) {
604
+ return [];
605
+ }
606
+ const cloned = cloneDeep(nodes);
607
+ for (const node of cloned) {
608
+ const defs = node.options?.['customFilterDefinitions'];
609
+ if (Array.isArray(defs) && defs.length > 0) {
610
+ node.options['customFilterDefinitions'] = await evaluatorService.evaluate(defs, scope);
611
+ }
612
+ }
613
+ return cloned;
614
+ };
615
+ const evaluatedPageContent = await resolveNodes(currentPage.content);
616
+ const evaluatedTabContentsById = {};
617
+ for (const tab of currentPage.tabs ?? []) {
618
+ evaluatedTabContentsById[tab.id] = await resolveNodes(tab.content);
619
+ }
620
+ return { evaluatedPageContent, evaluatedTabContentsById };
621
+ }
622
+ //#endregion
461
623
  const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
462
624
  const state = {
463
625
  adapter: null,
@@ -469,8 +631,12 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
469
631
  currentPage: null,
470
632
  currentTab: null,
471
633
  pageSelectedRows: [],
472
- // Cache for rendered tabs per page to prevent re-rendering
473
- renderedTabsCache: {},
634
+ /** Page main column widgets with `customFilterDefinitions` evaluated against `rootContext` */
635
+ evaluatedPageContent: [],
636
+ /** Tab panel widgets keyed by tab id (same evaluation as `evaluatedPageContent`) */
637
+ evaluatedTabContentsById: {},
638
+ /** Dirty flag synced from {@link AXPWidgetContainerComponent.isFormDirty}. */
639
+ formDirty: false,
474
640
  };
475
641
  return state;
476
642
  }), withComputed((store, deviceService = inject(AXPDeviceService)) => ({
@@ -486,86 +652,148 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
486
652
  //
487
653
  isBusy: computed(() => store.status() == AXPPageStatus.Processing),
488
654
  isSaving: computed(() => store.status() == AXPPageStatus.Submitting),
489
- isDirty: computed(() => !isEqual(store.context(), store.previousContext())),
490
- changesCount: computed(() => getChangedPaths(store.context(), store.previousContext()).length),
655
+ isDirty: computed(() => {
656
+ if (store.currentPage()?.isReadonly) {
657
+ return false;
658
+ }
659
+ return store.formDirty();
660
+ }),
661
+ changesCount: computed(() => {
662
+ if (store.currentPage()?.isReadonly) {
663
+ return 0;
664
+ }
665
+ return store.formDirty() ? 1 : 0;
666
+ }),
491
667
  isLoaded: computed(() => store.adapter() != null),
492
668
  currentPageSelectedRows: computed(() => store.pageSelectedRows()),
493
- //
494
- // Rendered tabs for current page - prevents re-rendering on tab switch
495
- currentPageRenderedTabs: computed(() => {
496
- const currentPage = store.currentPage();
497
- if (!currentPage?.id) {
669
+ /** Evaluated widget nodes for the active tab only (avoids double-mount from keep-alive cache). */
670
+ activeTabContent: computed(() => {
671
+ const tab = store.currentTab();
672
+ if (!tab?.id) {
498
673
  return [];
499
674
  }
500
- const pageId = currentPage.id;
501
- const cache = store.renderedTabsCache();
502
- return cache[pageId] || [];
675
+ const evaluatedByTab = store.evaluatedTabContentsById();
676
+ return evaluatedByTab[tab.id] ?? [];
503
677
  }),
504
678
  })), withMethods((store, evaluatorService = inject(AXPExpressionEvaluatorService), router = inject(Router), route = inject(ActivatedRoute), deviceService = inject(AXPDeviceService), formatService = inject(AXFormatService), toastService = inject(AXToastService), translateService = inject(AXTranslationService), settingsService = inject(AXPSettingsService)) => {
505
- // Effect to automatically cache current tab when it changes
506
- effect(() => {
507
- const currentPage = store.currentPage();
508
- const currentTab = store.currentTab();
509
- if (currentPage?.id && currentTab?.id) {
510
- const pageId = currentPage.id;
511
- const tabId = currentTab.id;
512
- const cache = store.renderedTabsCache();
513
- const pageCache = cache[pageId] || [];
514
- // Check if tab is already in cache
515
- const isTabCached = pageCache.some((cached) => cached.tabId === tabId);
516
- if (!isTabCached) {
517
- // Add tab to cache for this page
518
- const newTabCache = {
519
- tabId: tabId,
520
- tab: currentTab,
521
- };
522
- const updatedPageCache = [...pageCache, newTabCache];
523
- // Update the cache immutably
524
- const updatedCache = {
525
- ...cache,
526
- [pageId]: updatedPageCache,
527
- };
679
+ const refreshEvaluatedPageContents = async (page) => {
680
+ const rootCtx = store.rootContext();
681
+ const { evaluatedPageContent, evaluatedTabContentsById } = await buildEvaluatedPageContentsForRootContext(page, rootCtx, evaluatorService);
682
+ patchState(store, {
683
+ evaluatedPageContent,
684
+ evaluatedTabContentsById,
685
+ });
686
+ };
687
+ // Sync sidebar page from route query params
688
+ effect((onCleanup) => {
689
+ if (!store.adapter()) {
690
+ return;
691
+ }
692
+ const subscription = route.queryParams.subscribe((params) => {
693
+ const pageId = params['page'];
694
+ const adapter = store.adapter();
695
+ if (!adapter) {
696
+ return;
697
+ }
698
+ let currentPage = null;
699
+ if (pageId) {
700
+ currentPage = adapter.pages.find((p) => p.id === pageId) ?? null;
701
+ }
702
+ else if (deviceService.isLarge() || adapter.pages.length === 1) {
703
+ currentPage = adapter.pages.find((p) => p.isPrimary) ?? adapter.pages[0];
704
+ }
705
+ const currentTab = currentPage?.tabs?.[0] ?? null;
706
+ if (store.currentPage()?.id !== currentPage?.id) {
707
+ // `load()` → `loadPage` owns initial hydration when both sides are still null.
708
+ if (store.currentPage() == null && currentPage == null) {
709
+ return;
710
+ }
528
711
  patchState(store, {
529
- renderedTabsCache: updatedCache,
712
+ currentPage,
713
+ currentTab,
530
714
  });
715
+ void refreshEvaluatedPageContents(currentPage);
531
716
  }
532
- }
717
+ });
718
+ onCleanup(() => subscription.unsubscribe());
533
719
  });
534
- // Create an effect to handle route changes
535
- effect(() => {
536
- if (store.adapter()) {
537
- route.queryParams.subscribe((params) => {
538
- const pageId = params['page'];
539
- const adapter = store.adapter();
540
- if (adapter) {
541
- // Find current page from query param or conditionally default to first page
542
- let currentPage = null;
543
- if (pageId) {
544
- const foundPage = adapter.pages.find((p) => p.id === pageId);
545
- if (foundPage) {
546
- currentPage = foundPage;
547
- }
548
- }
549
- else {
550
- // Only auto-select primary page if layout is large
551
- if (deviceService.isLarge() || adapter.pages.length == 1) {
552
- const primaryPage = adapter.pages.find((p) => p.isPrimary) ?? adapter.pages[0];
553
- currentPage = primaryPage;
554
- }
555
- }
556
- // Set current tab to first tab of the current page (internal state only)
557
- let currentTab = currentPage?.tabs?.[0] ?? null;
558
- // Only update if there's a change
559
- if (store.currentPage()?.id !== currentPage?.id) {
560
- patchState(store, {
561
- currentPage,
562
- currentTab,
563
- });
564
- }
565
- }
566
- });
720
+ /**
721
+ * Breadcrumb titles are rendered with `{{ t(item.title) | async }}`; values must resolve to primitives
722
+ * or `@` keys. Normalize MLS **before** evaluate/format **and** **after**, because `raw` and the evaluator
723
+ * output can both carry MLS maps or locale-shaped objects.
724
+ */
725
+ function applyLocaleIfMultilingual(value) {
726
+ if (value !== null &&
727
+ value !== undefined &&
728
+ typeof value === 'object' &&
729
+ !Array.isArray(value) &&
730
+ translateService.isValidMultiLanguageObject(value)) {
731
+ return translateService.resolve(value);
567
732
  }
568
- });
733
+ return value;
734
+ }
735
+ /** Post-eval: collapse MLS maps and plain locale objects after evaluate/format (avoids `[object Object]` in `t()`). */
736
+ function finalizeBreadcrumbTitleEvaluated(evaluated, fallback) {
737
+ const chosen = evaluated ?? fallback;
738
+ if (chosen !== null &&
739
+ chosen !== undefined &&
740
+ typeof chosen === 'object' &&
741
+ !Array.isArray(chosen) &&
742
+ translateService.isValidMultiLanguageObject(chosen)) {
743
+ return translateService.resolve(chosen);
744
+ }
745
+ if (typeof chosen === 'string') {
746
+ return chosen;
747
+ }
748
+ if (chosen !== null && chosen !== undefined && typeof chosen === 'object' && !Array.isArray(chosen)) {
749
+ return translateService.resolve(chosen);
750
+ }
751
+ if (typeof fallback === 'string') {
752
+ return fallback;
753
+ }
754
+ if (fallback !== null &&
755
+ fallback !== undefined &&
756
+ translateService.isValidMultiLanguageObject(fallback)) {
757
+ return translateService.resolve(fallback);
758
+ }
759
+ return translateService.resolve(fallback);
760
+ }
761
+ async function resolveBreadcrumbTitleFields(raw, evalScope, formatContext) {
762
+ /** Pre-eval: locale strip for recognizable MLS payloads before branching on expressions. */
763
+ const sourceAfterPreLocale = applyLocaleIfMultilingual(raw);
764
+ const isStructuredMlsObject = translateService.isValidMultiLanguageObject(raw) &&
765
+ typeof raw === 'object' &&
766
+ raw !== null &&
767
+ !Array.isArray(raw);
768
+ /** Full-string `{{ ... }}` uses `AXPExpressionEvaluatorService.isExpression` (aligned with evaluator API). */
769
+ let evaluated;
770
+ if (typeof sourceAfterPreLocale === 'string' && evaluatorService.isExpression(sourceAfterPreLocale)) {
771
+ evaluated = await evaluatorService.evaluate(sourceAfterPreLocale, evalScope);
772
+ }
773
+ else if (isStructuredMlsObject) {
774
+ evaluated = await evaluatorService.evaluate(raw, evalScope);
775
+ }
776
+ else if (typeof sourceAfterPreLocale === 'string') {
777
+ evaluated = await formatService.format(sourceAfterPreLocale, 'string', formatContext);
778
+ }
779
+ else {
780
+ evaluated = await formatService.format(raw, 'string', formatContext);
781
+ }
782
+ /** Post-eval: MLS-aware resolution again — evaluate may return MLS or map-like wrappers. */
783
+ return finalizeBreadcrumbTitleEvaluated(evaluated, raw);
784
+ }
785
+ /**
786
+ * Resolves MLS objects, evaluates format templates, or applies string formatting against page context (same semantics as legacy details layout header meta).
787
+ */
788
+ function convertToMultiLanguageString(value) {
789
+ if (!value || isEmpty(value)) {
790
+ return null;
791
+ }
792
+ if (translateService.isValidMultiLanguageObject(value)) {
793
+ return translateService.resolve(value);
794
+ }
795
+ return formatService.format(value, 'string', store.context()) ?? '';
796
+ }
569
797
  return {
570
798
  async loadAdapter(adapter) {
571
799
  patchState(store, { adapter });
@@ -614,13 +842,29 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
614
842
  }
615
843
  // Set current tab to first tab of the current page (internal state only)
616
844
  let currentTab = currentPage?.tabs?.[0] ?? null;
845
+ const rootCtx = store.rootContext();
846
+ const { evaluatedPageContent, evaluatedTabContentsById } = await buildEvaluatedPageContentsForRootContext(currentPage, rootCtx, evaluatorService);
617
847
  patchState(store, {
618
848
  previousContext: cloneDeep(context),
619
849
  context: cloneDeep(context),
620
850
  status: AXPPageStatus.Rendered,
621
851
  currentPage,
622
852
  currentTab,
853
+ evaluatedPageContent,
854
+ evaluatedTabContentsById,
855
+ formDirty: false,
623
856
  });
857
+ if (currentPage && axpIsEntityDetailsViewRoute(router)) {
858
+ const pageParam = route.snapshot.queryParamMap.get('page');
859
+ if (pageParam !== currentPage.id) {
860
+ router.navigate([], {
861
+ relativeTo: route,
862
+ queryParams: { page: currentPage.id },
863
+ queryParamsHandling: 'merge',
864
+ replaceUrl: true,
865
+ });
866
+ }
867
+ }
624
868
  },
625
869
  async load(adapter) {
626
870
  // Setup expression evaluator scope
@@ -644,34 +888,26 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
644
888
  context,
645
889
  });
646
890
  },
891
+ setFormDirty(dirty) {
892
+ if (store.formDirty() === dirty) {
893
+ return;
894
+ }
895
+ patchState(store, {
896
+ formDirty: dirty,
897
+ });
898
+ },
647
899
  updatePageSelectedRows(rows) {
648
900
  patchState(store, {
649
901
  pageSelectedRows: rows,
650
902
  });
651
903
  },
652
- //Current Page
653
- currentPageTitle() {
654
- const raw = store.currentPage()?.title;
655
- if (raw) {
656
- return formatService.format(raw, 'string', store.context());
657
- }
658
- else {
659
- return null;
660
- }
661
- },
662
- currentPageDescription() {
663
- const raw = store.currentPage()?.description;
664
- if (raw) {
665
- return formatService.format(raw, 'string', store.context());
666
- }
667
- else {
668
- return null;
669
- }
670
- },
671
904
  async currentPagePrimaryActions() {
672
- const raw = store.currentPage()?.actions?.filter((a) => a.priority == 'primary') ?? [];
673
- const acceptAction = store.currentPage()?.settings?.commands?.accept;
674
- const rejectAction = store.currentPage()?.settings?.commands?.reject;
905
+ // Use getActions() if available for reactive updates, otherwise fall back to static actions
906
+ const currentPage = store.currentPage();
907
+ const allActions = currentPage?.getActions ? await currentPage.getActions() : (currentPage?.actions ?? []);
908
+ const raw = allActions.filter((a) => a.priority == 'primary');
909
+ const acceptAction = currentPage?.settings?.commands?.accept;
910
+ const rejectAction = currentPage?.settings?.commands?.reject;
675
911
  if (rejectAction) {
676
912
  raw.push({
677
913
  priority: 'primary',
@@ -679,6 +915,7 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
679
915
  name: 'reject',
680
916
  title: rejectAction.title,
681
917
  color: rejectAction.color,
918
+ icon: rejectAction.icon,
682
919
  command: rejectAction.command,
683
920
  visible: rejectAction.visible,
684
921
  });
@@ -690,6 +927,7 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
690
927
  name: 'accept',
691
928
  title: acceptAction.title,
692
929
  color: acceptAction.color,
930
+ icon: acceptAction.icon,
693
931
  command: acceptAction.command,
694
932
  visible: acceptAction.visible,
695
933
  });
@@ -698,113 +936,146 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
698
936
  return processed;
699
937
  },
700
938
  async currentPageSecondaryActions() {
701
- const raw = store.currentPage()?.actions?.filter((a) => a.priority == 'secondary') ?? [];
939
+ const raw = store
940
+ .currentPage()
941
+ ?.actions?.filter((a) => a.priority == 'secondary' && a.zone == 'header' && a.scope == AXPEntityCommandScope.TypeLevel) ?? [];
702
942
  const processed = await evaluatorService.evaluate(raw, store.scope());
703
943
  return processed;
704
944
  },
705
945
  currentPageContent() {
706
- const content = store.currentPage()?.content;
707
- return content;
946
+ return store.evaluatedPageContent();
708
947
  },
709
948
  currentPageTabs() {
710
949
  return store.currentPage()?.tabs?.filter((tab) => tab.visible !== false);
711
950
  },
712
951
  setCurrentPage(page) {
713
- // Clear previous page cache if changing pages
714
952
  const previousPage = store.currentPage();
715
- if (previousPage?.id && previousPage.id !== page?.id) {
716
- this.clearPageTabCache(previousPage.id);
717
- }
718
953
  if (page) {
719
954
  const firstTab = page.tabs?.[0] ?? null;
955
+ const pageParam = route.snapshot.queryParamMap.get('page');
956
+ const isSamePage = previousPage?.id === page.id && pageParam === page.id;
720
957
  patchState(store, {
721
958
  currentPage: page,
722
959
  currentTab: firstTab,
960
+ ...(page.isReadonly ? { formDirty: false } : {}),
723
961
  });
724
- router.navigate([], {
725
- queryParams: {
726
- page: page.id,
727
- },
728
- queryParamsHandling: 'merge',
729
- });
962
+ if (!isSamePage && axpIsEntityDetailsViewRoute(router)) {
963
+ const queryParams = { page: page.id };
964
+ if (previousPage?.id && previousPage.id !== page.id) {
965
+ queryParams['filters'] = null;
966
+ }
967
+ router.navigate([], {
968
+ relativeTo: route,
969
+ queryParams,
970
+ queryParamsHandling: 'merge',
971
+ // Push history for desktop sidebar switches and mobile page-list picks.
972
+ replaceUrl: false,
973
+ });
974
+ }
975
+ void refreshEvaluatedPageContents(page);
730
976
  }
731
977
  else {
732
978
  patchState(store, {
733
979
  currentPage: null,
734
980
  currentTab: null,
981
+ evaluatedPageContent: [],
982
+ evaluatedTabContentsById: {},
735
983
  });
736
- // Remove page query parameter
737
- const currentParams = { ...route.snapshot.queryParams };
738
- delete currentParams['page'];
739
- router.navigate([], {
740
- queryParams: currentParams,
741
- });
984
+ if (axpIsEntityDetailsViewRoute(router)) {
985
+ const currentParams = { ...route.snapshot.queryParams };
986
+ delete currentParams['page'];
987
+ router.navigate([], {
988
+ relativeTo: route,
989
+ queryParams: currentParams,
990
+ replaceUrl: true,
991
+ });
992
+ }
742
993
  }
743
994
  },
744
- //Current Tab
745
995
  setCurrentTab(tab) {
746
996
  patchState(store, {
747
997
  currentTab: tab,
748
998
  });
749
- // Cache management is handled automatically by the effect
750
999
  },
751
- getCurrentTabContent() {
752
- return store.currentTab()?.content ?? [];
753
- },
754
- //#region ---- Rendered Tabs Management ----
755
- /**
756
- * Get content for a specific rendered tab
757
- */
758
- getRenderedTabContent(tabId) {
759
- const renderedTabs = store.currentPageRenderedTabs();
760
- const renderedTab = renderedTabs.find((cached) => cached.tabId === tabId);
761
- return renderedTab?.tab?.content ?? [];
1000
+ //#region ---- Page layout metadata (title, description, back button, badge, status) ----
1001
+ backButtonTitle() {
1002
+ return store.showPages() ? (store.adapter()?.label ?? '') : (store.adapter()?.title ?? '');
762
1003
  },
763
- /**
764
- * Clear cache when page changes to free memory
765
- */
766
- clearPageTabCache(pageId) {
767
- const cache = store.renderedTabsCache();
768
- const updatedCache = { ...cache };
769
- delete updatedCache[pageId];
770
- patchState(store, {
771
- renderedTabsCache: updatedCache,
772
- });
1004
+ async getPageTitle() {
1005
+ if (store.showPages()) {
1006
+ const raw = store.adapter()?.title;
1007
+ return convertToMultiLanguageString(raw) ?? '';
1008
+ }
1009
+ const raw = store.currentPage()?.title;
1010
+ return convertToMultiLanguageString(raw) ?? '';
773
1011
  },
774
- //#endregion
775
- title() {
776
- const raw = store.showPages() ? (store.adapter()?.title ?? '') : (store.adapter()?.label ?? '');
777
- return raw ? formatService.format(raw, 'string', store.rootContext()) : null;
1012
+ async getPageDescription() {
1013
+ if (store.showPages()) {
1014
+ const raw = store.adapter()?.description;
1015
+ return convertToMultiLanguageString(raw);
1016
+ }
1017
+ const raw = store.currentPage()?.description;
1018
+ return convertToMultiLanguageString(raw);
778
1019
  },
779
- backButtonTitle() {
780
- const raw = store.showPages() ? (store.adapter()?.label ?? '') : (store.adapter()?.title ?? '');
781
- return raw ? formatService.format(raw, 'string', store.rootContext()) : null;
1020
+ async getBackButton() {
1021
+ const adapter = store.adapter();
1022
+ if (!adapter) {
1023
+ return null;
1024
+ }
1025
+ if ((adapter.pages?.length ?? 0) > 1) {
1026
+ const titleRaw = (store.showPages() ? (adapter.label ?? '') : (adapter.title ?? ''));
1027
+ return { title: convertToMultiLanguageString(titleRaw) ?? '@general:terms.common.back' };
1028
+ }
1029
+ const label = (adapter.label ?? '');
1030
+ return { title: convertToMultiLanguageString(label) ?? '@general:terms.common.back' };
782
1031
  },
783
- description() {
784
- const raw = store.adapter()?.description;
785
- if (raw) {
786
- return formatService.format(raw, 'string', store.rootContext());
1032
+ async getPageBadge() {
1033
+ if (store.currentPage()?.isReadonly) {
1034
+ return null;
787
1035
  }
788
- else {
1036
+ const showPageBadge = await settingsService.get(AXPCommonSettings.ShowPageBadge);
1037
+ if (!showPageBadge) {
1038
+ return null;
1039
+ }
1040
+ const adapter = store.adapter();
1041
+ if (!adapter?.getPageBadge) {
1042
+ return null;
1043
+ }
1044
+ return adapter.getPageBadge(store.context(), store.isDirty());
1045
+ },
1046
+ async getPageStatus() {
1047
+ const adapter = store.adapter();
1048
+ if (!adapter?.getPageStatus) {
789
1049
  return null;
790
1050
  }
1051
+ return adapter.getPageStatus(store.context(), store.currentPage());
791
1052
  },
1053
+ //#endregion
792
1054
  async primaryActions() {
793
1055
  const raw = store.adapter()?.actions?.filter((a) => a.priority == 'primary') ?? [];
794
1056
  const processed = await evaluatorService.evaluate(raw, store.scope());
795
1057
  return processed;
796
1058
  },
797
1059
  async secondaryActions() {
798
- const raw = store.adapter()?.actions?.filter((a) => a.priority == 'secondary') ?? [];
1060
+ const raw = store
1061
+ .adapter()
1062
+ ?.actions?.filter((a) => a.priority == 'secondary' && a.scope == AXPEntityCommandScope.TypeLevel) ?? [];
799
1063
  const processed = await evaluatorService.evaluate(raw, store.scope());
800
1064
  return processed;
801
1065
  },
802
1066
  async breadcrumbs() {
1067
+ const rootContext = store.rootContext();
1068
+ const scope = {
1069
+ ...rootContext,
1070
+ context: {
1071
+ eval: (path) => get(rootContext, path),
1072
+ },
1073
+ };
803
1074
  const breadcrumbs = await Promise.all(store.adapter()?.breadcrumbs?.map(async (b) => {
804
- const raw = b?.title ?? '';
1075
+ const raw = (b?.title ?? '');
805
1076
  return {
806
1077
  ...b,
807
- title: formatService.format(raw, 'string', store.rootContext()),
1078
+ title: await resolveBreadcrumbTitleFields(raw, scope, rootContext),
808
1079
  };
809
1080
  }) ?? []);
810
1081
  // Add current page title as the last breadcrumb item
@@ -813,112 +1084,495 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
813
1084
  const primaryPage = pages.find((p) => p.isPrimary) ?? pages[0];
814
1085
  const isMainPage = primaryPage?.id === store.currentPage()?.id;
815
1086
  if (currentPageLabel && !isMainPage) {
816
- const processedCurrentPageTitle = formatService.format(currentPageLabel, 'string', store.context());
1087
+ const pageScope = {
1088
+ ...store.context(),
1089
+ context: {
1090
+ eval: (path) => get(store.context(), path),
1091
+ },
1092
+ };
817
1093
  breadcrumbs.push({
818
- title: processedCurrentPageTitle,
1094
+ title: await resolveBreadcrumbTitleFields(currentPageLabel, pageScope, store.context()),
819
1095
  });
820
1096
  }
821
1097
  return breadcrumbs;
822
1098
  },
1099
+ /** Aligns view-model context with the container after revert/commit (saved baseline). */
1100
+ applySavedState(context) {
1101
+ const snapshot = cloneDeep(context);
1102
+ patchState(store, {
1103
+ context: snapshot,
1104
+ previousContext: snapshot,
1105
+ formDirty: false,
1106
+ });
1107
+ },
823
1108
  async discard() {
824
1109
  patchState(store, {
825
- context: cloneDeep(store.previousContext()),
1110
+ formDirty: false,
826
1111
  });
827
1112
  },
828
- async save(command, form) {
1113
+ async save(command, form, liveContext) {
829
1114
  const formResult = await form.validate();
830
1115
  if (!formResult.result) {
831
- return;
1116
+ return false;
832
1117
  }
1118
+ const payload = liveContext ?? store.context();
833
1119
  patchState(store, {
834
1120
  status: AXPPageStatus.Submitting,
835
1121
  });
836
- const result = await store.currentPage()?.execute?.(command, store.context());
837
- const enableOperationToasts = await settingsService.get(AXPCommonSettings.EnableOperationToasts);
838
- if (result?.success) {
1122
+ try {
1123
+ const result = await store.currentPage()?.execute?.(command, payload);
1124
+ // Clear submitting before post-save refresh so the footer is not left disabled.
839
1125
  patchState(store, {
840
- previousContext: store.context(),
1126
+ status: AXPPageStatus.Rendered,
841
1127
  });
842
- // After successful save, force refresh the rootContext and reload the current page
843
- try {
844
- await this.loadPage(store.currentPage()?.id, true);
845
- }
846
- catch (error) {
847
- console.error('Failed to refresh page after save', error);
848
- }
849
- if (enableOperationToasts) {
850
- toastService.show({
851
- color: 'success',
852
- title: await translateService.translateAsync('@general:messages.generic.success.title'),
853
- content: await translateService.translateAsync('@general:messages.generic.success.description'),
854
- location: 'bottom-center',
855
- closeButton: true,
856
- timeOut: 3000,
857
- timeOutProgress: true,
1128
+ const enableOperationToasts = await settingsService.get(AXPCommonSettings.EnableOperationToasts);
1129
+ if (result?.success) {
1130
+ try {
1131
+ await this.loadPage(store.currentPage()?.id, true);
1132
+ }
1133
+ catch {
1134
+ //
1135
+ }
1136
+ patchState(store, {
1137
+ previousContext: store.context(),
1138
+ formDirty: false,
858
1139
  });
1140
+ if (enableOperationToasts) {
1141
+ toastService.show({
1142
+ color: 'success',
1143
+ title: await translateService.translateAsync('@general:messages.generic.success.title'),
1144
+ content: await translateService.translateAsync('@general:messages.generic.success.description'),
1145
+ location: 'bottom-center',
1146
+ closeButton: true,
1147
+ timeOut: 3000,
1148
+ timeOutProgress: true,
1149
+ });
1150
+ }
1151
+ patchState(store, {
1152
+ formDirty: false,
1153
+ });
1154
+ return true;
859
1155
  }
1156
+ const rawText = result?.message?.text;
1157
+ const errorText = rawText
1158
+ ? typeof rawText === 'string'
1159
+ ? rawText.startsWith('@')
1160
+ ? await translateService.translateAsync(rawText)
1161
+ : rawText
1162
+ : translateService.resolve(rawText)
1163
+ : await translateService.translateAsync('@general:messages.generic.error.description');
1164
+ toastService.show({
1165
+ color: 'danger',
1166
+ title: await translateService.translateAsync('@general:messages.generic.error.title'),
1167
+ content: errorText,
1168
+ location: 'bottom-center',
1169
+ closeButton: true,
1170
+ timeOut: 5000,
1171
+ timeOutProgress: true,
1172
+ });
1173
+ return false;
860
1174
  }
861
- else {
862
- if (enableOperationToasts) {
863
- toastService.show({
864
- color: 'danger',
865
- title: await translateService.translateAsync('@general:messages.generic.error.title'),
866
- content: result?.message?.text ||
867
- (await translateService.translateAsync('@general:messages.generic.error.description')),
868
- location: 'bottom-center',
869
- closeButton: true,
870
- timeOut: 3000,
871
- timeOutProgress: true,
1175
+ catch (error) {
1176
+ const errorText = error instanceof Error
1177
+ ? error.message
1178
+ : await translateService.translateAsync('@general:messages.generic.error.description');
1179
+ patchState(store, {
1180
+ status: AXPPageStatus.Rendered,
1181
+ });
1182
+ toastService.show({
1183
+ color: 'danger',
1184
+ title: await translateService.translateAsync('@general:messages.generic.error.title'),
1185
+ content: errorText,
1186
+ location: 'bottom-center',
1187
+ closeButton: true,
1188
+ timeOut: 5000,
1189
+ timeOutProgress: true,
1190
+ });
1191
+ return false;
1192
+ }
1193
+ finally {
1194
+ if (store.status() === AXPPageStatus.Submitting) {
1195
+ patchState(store, {
1196
+ status: AXPPageStatus.Rendered,
872
1197
  });
873
1198
  }
874
1199
  }
875
- patchState(store, {
876
- status: AXPPageStatus.Submitted,
877
- });
878
1200
  },
879
1201
  goToListPage() {
880
- if (store.adapter()?.exitUrl) {
881
- router.navigate([store.adapter()?.exitUrl]);
1202
+ const exitUrl = store.adapter()?.exitUrl;
1203
+ if (exitUrl) {
1204
+ void axpNavigateAppPath(router, exitUrl);
882
1205
  }
883
1206
  },
884
1207
  };
885
1208
  }));
886
1209
 
1210
+ /**
1211
+ * Registry of rendered page component instances by component key.
1212
+ * Used so page execute can delegate to the actual component instance in the view.
1213
+ */
1214
+ class AXPPageComponentInstanceRegistryService {
1215
+ constructor() {
1216
+ this.instances = new Map();
1217
+ }
1218
+ register(key, instance) {
1219
+ this.instances.set(key, instance);
1220
+ }
1221
+ unregister(key) {
1222
+ this.instances.delete(key);
1223
+ }
1224
+ get(key) {
1225
+ return this.instances.get(key) ?? null;
1226
+ }
1227
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageComponentInstanceRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1228
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageComponentInstanceRegistryService, providedIn: 'root' }); }
1229
+ }
1230
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageComponentInstanceRegistryService, decorators: [{
1231
+ type: Injectable,
1232
+ args: [{
1233
+ providedIn: 'root',
1234
+ }]
1235
+ }] });
1236
+
1237
+ //#region ---- Page Component Renderer Directive ----
1238
+ /**
1239
+ * Directive for rendering page components dynamically
1240
+ * Similar to component-slot pattern but specifically for page components
1241
+ */
1242
+ class AXPPageComponentRendererDirective {
1243
+ constructor() {
1244
+ this.componentKey = input.required(...(ngDevMode ? [{ debugName: "componentKey" }] : /* istanbul ignore next */ []));
1245
+ this.rootContext = input({}, ...(ngDevMode ? [{ debugName: "rootContext" }] : /* istanbul ignore next */ []));
1246
+ this.pageConfig = input(...(ngDevMode ? [undefined, { debugName: "pageConfig" }] : /* istanbul ignore next */ []));
1247
+ this.options = input({}, ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
1248
+ /** Emitted when the component instance is registered and ready */
1249
+ this.componentReady = output();
1250
+ this.viewContainerRef = inject(ViewContainerRef);
1251
+ this.pageComponentRegistry = inject(AXPPageComponentRegistryService);
1252
+ this.instanceRegistry = inject(AXPPageComponentInstanceRegistryService);
1253
+ this.contextStore = inject(AXPContextStore);
1254
+ this.componentRef = null;
1255
+ this.#contextEffect = effect(() => {
1256
+ const context = this.rootContext();
1257
+ if (this.componentRef && context) {
1258
+ this.componentRef.setInput('rootContext', context);
1259
+ }
1260
+ }, ...(ngDevMode ? [{ debugName: "#contextEffect" }] : /* istanbul ignore next */ []));
1261
+ this.#pageConfigEffect = effect(() => {
1262
+ const config = this.pageConfig();
1263
+ if (this.componentRef && config) {
1264
+ this.componentRef.setInput('pageConfig', config);
1265
+ }
1266
+ }, ...(ngDevMode ? [{ debugName: "#pageConfigEffect" }] : /* istanbul ignore next */ []));
1267
+ this.#optionsEffect = effect(() => {
1268
+ const options = this.options();
1269
+ if (this.componentRef && options) {
1270
+ this.componentRef.setInput('options', options);
1271
+ }
1272
+ }, ...(ngDevMode ? [{ debugName: "#optionsEffect" }] : /* istanbul ignore next */ []));
1273
+ }
1274
+ /** Returns the dynamically mounted page component instance, if loaded. */
1275
+ getMountedPageInstance() {
1276
+ return this.componentRef?.instance ?? null;
1277
+ }
1278
+ #contextEffect;
1279
+ #pageConfigEffect;
1280
+ #optionsEffect;
1281
+ async ngOnInit() {
1282
+ await this.loadComponent();
1283
+ }
1284
+ ngOnDestroy() {
1285
+ if (this.componentRef) {
1286
+ this.syncWizardStepContextBeforeTeardown();
1287
+ this.instanceRegistry.unregister(this.componentKey());
1288
+ this.componentRef.destroy();
1289
+ this.componentRef = null;
1290
+ }
1291
+ }
1292
+ /** Persists page edits into the shared form context before the step component is destroyed. */
1293
+ syncWizardStepContextBeforeTeardown() {
1294
+ const instance = this.componentRef?.instance;
1295
+ const partial = instance?.getWizardStepContext?.();
1296
+ if (!partial || typeof partial !== 'object') {
1297
+ return;
1298
+ }
1299
+ for (const [path, value] of Object.entries(partial)) {
1300
+ this.contextStore.update(path, value, { origin: 'system' });
1301
+ }
1302
+ }
1303
+ async loadComponent() {
1304
+ try {
1305
+ // Clear any existing component
1306
+ this.viewContainerRef.clear();
1307
+ // Get component loader from registry
1308
+ const loader = await this.pageComponentRegistry.find(this.componentKey());
1309
+ if (!loader) {
1310
+ console.error(`Component with key "${this.componentKey()}" not found in registry`);
1311
+ return;
1312
+ }
1313
+ // Load component type
1314
+ const ComponentType = await loader();
1315
+ // Create component instance
1316
+ this.componentRef = this.viewContainerRef.createComponent(ComponentType);
1317
+ this.instanceRegistry.register(this.componentKey(), this.componentRef.instance);
1318
+ const context = this.rootContext();
1319
+ if (context) {
1320
+ this.componentRef.setInput('rootContext', context);
1321
+ }
1322
+ const options = this.options();
1323
+ if (options) {
1324
+ this.componentRef.setInput('options', options);
1325
+ }
1326
+ const pageConfig = this.pageConfig();
1327
+ if (pageConfig) {
1328
+ this.componentRef.setInput('pageConfig', pageConfig);
1329
+ }
1330
+ // Notify that component is ready (allows parent to re-fetch actions)
1331
+ this.componentReady.emit(this.componentKey());
1332
+ }
1333
+ catch (error) {
1334
+ console.error(`Failed to load component "${this.componentKey()}":`, error);
1335
+ }
1336
+ }
1337
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageComponentRendererDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1338
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: AXPPageComponentRendererDirective, isStandalone: true, selector: "[axp-page-component-renderer]", inputs: { componentKey: { classPropertyName: "componentKey", publicName: "componentKey", isSignal: true, isRequired: true, transformFunction: null }, rootContext: { classPropertyName: "rootContext", publicName: "rootContext", isSignal: true, isRequired: false, transformFunction: null }, pageConfig: { classPropertyName: "pageConfig", publicName: "pageConfig", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { componentReady: "componentReady" }, ngImport: i0 }); }
1339
+ }
1340
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageComponentRendererDirective, decorators: [{
1341
+ type: Directive,
1342
+ args: [{
1343
+ selector: '[axp-page-component-renderer]',
1344
+ standalone: true,
1345
+ }]
1346
+ }], propDecorators: { componentKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentKey", required: true }] }], rootContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "rootContext", required: false }] }], pageConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageConfig", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], componentReady: [{ type: i0.Output, args: ["componentReady"] }] } });
1347
+
1348
+ //#region ---- Details View Action Shortcut Utilities ----
1349
+ /** Platform defaults for known entity detail commands when `shortcuts` is omitted on the action. */
1350
+ const DEFAULT_ENTITY_DETAIL_ACTION_SHORTCUTS = {
1351
+ 'delete-entity': ['ctrl+shift+delete'],
1352
+ };
1353
+ const DEFAULT_FOOTER_COMMAND_SHORTCUTS = {
1354
+ 'update-entity': ['ctrl+s'],
1355
+ discard: ['escape'],
1356
+ };
1357
+ /**
1358
+ * Returns the base workflow/command name from a composite entity action command id (`cmd&actionName`).
1359
+ */
1360
+ function getDetailsViewActionCommandBaseName(commandName) {
1361
+ if (!commandName) {
1362
+ return '';
1363
+ }
1364
+ return commandName.split('&')[0];
1365
+ }
1366
+ /**
1367
+ * Resolves keyboard shortcuts for a header entity action.
1368
+ * Explicit `shortcuts` wins; pass `[]` to disable. Otherwise known commands use platform defaults.
1369
+ */
1370
+ function resolveDetailsViewActionShortcuts(commandBaseName, explicit) {
1371
+ if (explicit !== undefined) {
1372
+ const chords = flattenDetailsViewActionShortcuts(explicit);
1373
+ return chords.length ? chords : undefined;
1374
+ }
1375
+ const defaults = DEFAULT_ENTITY_DETAIL_ACTION_SHORTCUTS[commandBaseName];
1376
+ return defaults?.length ? [...defaults] : undefined;
1377
+ }
1378
+ /**
1379
+ * Resolves save/discard footer command shortcuts from page settings.
1380
+ */
1381
+ function resolveDetailsViewFooterCommandShortcuts(commandName, explicit) {
1382
+ if (explicit !== undefined) {
1383
+ const chords = flattenDetailsViewActionShortcuts(explicit);
1384
+ return chords.length ? chords : undefined;
1385
+ }
1386
+ const defaults = DEFAULT_FOOTER_COMMAND_SHORTCUTS[commandName];
1387
+ return defaults?.length ? [...defaults] : undefined;
1388
+ }
1389
+ function flattenDetailsViewActionShortcuts(shortcuts) {
1390
+ const chords = normalizeKeyboardShortcuts(shortcuts).flatMap((shortcut) => shortcut.keys);
1391
+ return dedupeDetailsViewActionShortcuts(chords);
1392
+ }
1393
+ function dedupeDetailsViewActionShortcuts(shortcuts) {
1394
+ const seen = new Set();
1395
+ const result = [];
1396
+ for (const shortcut of shortcuts) {
1397
+ const token = shortcut.trim().toLowerCase();
1398
+ if (!token || seen.has(token)) {
1399
+ continue;
1400
+ }
1401
+ seen.add(token);
1402
+ result.push(shortcut.trim());
1403
+ }
1404
+ return result;
1405
+ }
1406
+ //#endregion
1407
+
887
1408
  class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
888
1409
  constructor() {
889
1410
  super(...arguments);
890
- this.adapter = input.required(...(ngDevMode ? [{ debugName: "adapter" }] : []));
1411
+ this.adapter = input.required(...(ngDevMode ? [{ debugName: "adapter" }] : /* istanbul ignore next */ []));
891
1412
  //
892
1413
  this.vm = inject(AXPLayoutDetailsViewViewModel);
893
1414
  this.router = inject(Router);
894
1415
  this.route = inject(ActivatedRoute);
895
1416
  this.eventService = inject(AXPBroadcastEventService);
896
1417
  this.deviceService = inject(AXPDeviceService);
1418
+ this.unsavedChangesConfirm = inject(AXPUnsavedChangesConfirmService);
1419
+ this.unsavedChangesPopstate = inject(AXPUnsavedChangesPopstateService);
1420
+ this.pageComponentInstanceRegistry = inject(AXPPageComponentInstanceRegistryService);
1421
+ this.shortcutRegistry = inject(AXPKeyboardShortcutRegistry);
1422
+ this.destroyRef = inject(DestroyRef);
1423
+ this.elementRef = inject((ElementRef));
1424
+ /** Prevents sidebar tab init events from pushing history before {@link ngOnInit} load completes. */
1425
+ this.detailsLayoutReady = false;
897
1426
  this.destroyed$ = new Subject();
898
- this.form = viewChild('form', ...(ngDevMode ? [{ debugName: "form" }] : []));
899
- this.widgetContainer = viewChild(AXPWidgetContainerComponent, ...(ngDevMode ? [{ debugName: "widgetContainer" }] : []));
900
- this.footerPrimaryActions = signal([], ...(ngDevMode ? [{ debugName: "footerPrimaryActions" }] : []));
901
- this.footerSecondaryActions = signal([], ...(ngDevMode ? [{ debugName: "footerSecondaryActions" }] : []));
902
- this.footerActions = computed(() => [...this.footerPrimaryActions(), ...this.footerSecondaryActions()], ...(ngDevMode ? [{ debugName: "footerActions" }] : []));
1427
+ this.footerActionsGeneration = 0;
1428
+ this.keyboardShortcutRegistrationGeneration = 0;
1429
+ /** Header actions with resolved shortcut chords, keyed by command name. */
1430
+ this.actionShortcutEntries = signal(new Map(), ...(ngDevMode ? [{ debugName: "actionShortcutEntries" }] : /* istanbul ignore next */ []));
1431
+ this.form = viewChild('form', ...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
1432
+ this.widgetContainer = viewChild(AXPWidgetContainerComponent, ...(ngDevMode ? [{ debugName: "widgetContainer" }] : /* istanbul ignore next */ []));
1433
+ this.sidebarTabs = viewChild('sidebarTabs', ...(ngDevMode ? [{ debugName: "sidebarTabs" }] : /* istanbul ignore next */ []));
1434
+ this.sidebarTabChangeSuppressed = false;
1435
+ /** Syncs the line indicator when the active page changes programmatically. */
1436
+ this.#sidebarTabsIndicatorEffect = effect(() => {
1437
+ const pages = this.vm.adapter()?.pages;
1438
+ const currentId = this.vm.currentPage()?.id;
1439
+ if (!pages?.length || !currentId) {
1440
+ return;
1441
+ }
1442
+ const index = pages.findIndex((page) => page.id === currentId);
1443
+ if (index < 0) {
1444
+ return;
1445
+ }
1446
+ untracked(() => queueMicrotask(() => {
1447
+ this.sidebarTabChangeSuppressed = true;
1448
+ try {
1449
+ this.sidebarTabs()?.select(index);
1450
+ }
1451
+ finally {
1452
+ this.sidebarTabChangeSuppressed = false;
1453
+ }
1454
+ }));
1455
+ }, ...(ngDevMode ? [{ debugName: "#sidebarTabsIndicatorEffect" }] : /* istanbul ignore next */ []));
1456
+ this.footerPrimaryActions = signal([], ...(ngDevMode ? [{ debugName: "footerPrimaryActions" }] : /* istanbul ignore next */ []));
1457
+ this.footerSecondaryActions = signal([], ...(ngDevMode ? [{ debugName: "footerSecondaryActions" }] : /* istanbul ignore next */ []));
1458
+ this.footerActions = computed(() => [...this.footerPrimaryActions(), ...this.footerSecondaryActions()], ...(ngDevMode ? [{ debugName: "footerActions" }] : /* istanbul ignore next */ []));
1459
+ this.rejectFooterCommand = computed(() => {
1460
+ if (this.vm.currentPage()?.isReadonly) {
1461
+ return null;
1462
+ }
1463
+ return this.vm.currentPage()?.settings?.commands?.reject ?? null;
1464
+ }, ...(ngDevMode ? [{ debugName: "rejectFooterCommand" }] : /* istanbul ignore next */ []));
1465
+ this.acceptFooterCommand = computed(() => {
1466
+ if (this.vm.currentPage()?.isReadonly) {
1467
+ return null;
1468
+ }
1469
+ return this.vm.currentPage()?.settings?.commands?.accept ?? null;
1470
+ }, ...(ngDevMode ? [{ debugName: "acceptFooterCommand" }] : /* istanbul ignore next */ []));
1471
+ this.hasSaveDiscardFooterCommands = computed(() => !!(this.rejectFooterCommand() || this.acceptFooterCommand()), ...(ngDevMode ? [{ debugName: "hasSaveDiscardFooterCommands" }] : /* istanbul ignore next */ []));
1472
+ /** Entity save/discard — driven live by widget/container dirty state, not evaluated action metadata. */
1473
+ this.showSaveDiscardFooter = computed(() => this.hasSaveDiscardFooterCommands() && this.liveFormIsDirty(), ...(ngDevMode ? [{ debugName: "showSaveDiscardFooter" }] : /* istanbul ignore next */ []));
1474
+ /** Live dirty flag for widget-based entity forms (not component-hosted pages). */
1475
+ this.liveFormIsDirty = computed(() => {
1476
+ if (this.vm.currentPage()?.isReadonly || this.getActivePageComponentKey()) {
1477
+ return false;
1478
+ }
1479
+ return this.widgetContainer()?.isFormDirty() ?? false;
1480
+ }, ...(ngDevMode ? [{ debugName: "liveFormIsDirty" }] : /* istanbul ignore next */ []));
903
1481
  this.hasVisibleFooterPrimaryActions = computed(() => {
904
- const primaryFooterActions = this.footerPrimaryActions();
905
- return primaryFooterActions.some((action) => action.visible != false);
906
- }, ...(ngDevMode ? [{ debugName: "hasVisibleFooterPrimaryActions" }] : []));
907
- this.hasVisibleFooterSecondaryActions = computed(() => {
908
- const secondaryFooterActions = this.footerSecondaryActions();
909
- return secondaryFooterActions.some((action) => action.visible != false);
910
- }, ...(ngDevMode ? [{ debugName: "hasVisibleFooterSecondaryActions" }] : []));
1482
+ if (this.showSaveDiscardFooter()) {
1483
+ return true;
1484
+ }
1485
+ return this.footerPrimaryActions().some((action) => !this.isSaveDiscardFooterAction(action) && this.isFooterActionVisible(action));
1486
+ }, ...(ngDevMode ? [{ debugName: "hasVisibleFooterPrimaryActions" }] : /* istanbul ignore next */ []));
1487
+ this.hasVisibleFooterSecondaryActions = computed(() => this.footerSecondaryActions().some((action) => this.isFooterActionVisible(action)), ...(ngDevMode ? [{ debugName: "hasVisibleFooterSecondaryActions" }] : /* istanbul ignore next */ []));
911
1488
  this.hasFooter = computed(() => {
912
1489
  return ((this.hasVisibleFooterPrimaryActions() || this.hasVisibleFooterSecondaryActions()) &&
913
1490
  !this.vm.currentPage()?.isReadonly);
914
- }, ...(ngDevMode ? [{ debugName: "hasFooter" }] : []));
915
- this.#FooterActionsEffect = effect(async () => {
1491
+ }, ...(ngDevMode ? [{ debugName: "hasFooter" }] : /* istanbul ignore next */ []));
1492
+ this.#formDirtyEffect = effect(() => {
1493
+ if (this.vm.currentPage()?.isReadonly || this.getActivePageComponentKey()) {
1494
+ return;
1495
+ }
1496
+ const isDirty = this.liveFormIsDirty();
1497
+ if (this.vm.formDirty() === isDirty) {
1498
+ return;
1499
+ }
1500
+ untracked(() => {
1501
+ this.vm.setFormDirty(isDirty);
1502
+ this.recompute();
1503
+ });
1504
+ }, ...(ngDevMode ? [{ debugName: "#formDirtyEffect" }] : /* istanbul ignore next */ []));
1505
+ /** Refresh title badge (Not Saved) when dirty state changes. */
1506
+ this.#headerBadgeEffect = effect(() => {
1507
+ this.liveFormIsDirty();
1508
+ this.vm.currentPage()?.id;
1509
+ this.isActivePageComponentDirty();
1510
+ untracked(() => this.recompute());
1511
+ }, ...(ngDevMode ? [{ debugName: "#headerBadgeEffect" }] : /* istanbul ignore next */ []));
1512
+ this.#FooterActionsEffect = effect(() => {
1513
+ const generation = ++this.footerActionsGeneration;
916
1514
  this.updateTrigger();
917
- const footerPrimaryActions = await this.getFooterPrimaryActions();
918
- const footerSecondaryActions = await this.getFooterSecondaryActions();
919
- this.footerPrimaryActions.set(footerPrimaryActions);
920
- this.footerSecondaryActions.set(footerSecondaryActions);
921
- }, ...(ngDevMode ? [{ debugName: "#FooterActionsEffect" }] : []));
1515
+ this.liveFormIsDirty();
1516
+ this.vm.isSaving();
1517
+ void this.refreshFooterActions(generation);
1518
+ }, ...(ngDevMode ? [{ debugName: "#FooterActionsEffect" }] : /* istanbul ignore next */ []));
1519
+ this.#keyboardShortcutsEffect = effect(() => {
1520
+ const generation = ++this.keyboardShortcutRegistrationGeneration;
1521
+ this.updateTrigger();
1522
+ this.liveFormIsDirty();
1523
+ this.vm.isSaving();
1524
+ this.vm.currentPage()?.id;
1525
+ untracked(() => void this.refreshKeyboardShortcutRegistrations(generation));
1526
+ }, ...(ngDevMode ? [{ debugName: "#keyboardShortcutsEffect" }] : /* istanbul ignore next */ []));
1527
+ }
1528
+ /** Save/discard use live {@link AXPLayoutDetailsViewViewModel.isDirty}; other actions use evaluated `visible`. */
1529
+ static isTruthyActionFlag(value) {
1530
+ if (value === true) {
1531
+ return true;
1532
+ }
1533
+ if (value === false || value == null) {
1534
+ return false;
1535
+ }
1536
+ if (typeof value === 'string') {
1537
+ const normalized = value.trim().toLowerCase();
1538
+ if (normalized === 'false' || normalized === '0' || normalized === '') {
1539
+ return false;
1540
+ }
1541
+ if (normalized === 'true') {
1542
+ return true;
1543
+ }
1544
+ // Unevaluated template expressions must not keep footer actions visible or disabled.
1545
+ if (normalized.startsWith('{{')) {
1546
+ return false;
1547
+ }
1548
+ return true;
1549
+ }
1550
+ return Boolean(value);
1551
+ }
1552
+ /** Syncs the line indicator when the active page changes programmatically. */
1553
+ #sidebarTabsIndicatorEffect;
1554
+ isSaveDiscardFooterAction(action) {
1555
+ const commandName = action.command?.name;
1556
+ const acceptCommand = this.vm.currentPage()?.settings?.commands?.accept?.command?.name;
1557
+ const rejectCommand = this.vm.currentPage()?.settings?.commands?.reject?.command?.name;
1558
+ return (action.name === 'accept' ||
1559
+ action.name === 'reject' ||
1560
+ commandName === 'update-entity' ||
1561
+ commandName === 'discard' ||
1562
+ (!!acceptCommand && commandName === acceptCommand) ||
1563
+ (!!rejectCommand && commandName === rejectCommand));
1564
+ }
1565
+ isFooterActionVisible(action) {
1566
+ if (this.isSaveDiscardFooterAction(action)) {
1567
+ return false;
1568
+ }
1569
+ return AXPLayoutDetailsViewComponent.isTruthyActionFlag(action.visible);
1570
+ }
1571
+ isFooterActionDisabled(action) {
1572
+ if (this.vm.isSaving()) {
1573
+ return true;
1574
+ }
1575
+ return AXPLayoutDetailsViewComponent.isTruthyActionFlag(action.disabled);
922
1576
  }
923
1577
  /**
924
1578
  * Append timestamp query param to trigger router to re-run guards/resolvers
@@ -927,16 +1581,24 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
927
1581
  const router = this.router;
928
1582
  const route = this.route;
929
1583
  const now = Date.now();
1584
+ this.unsavedChangesConfirm.markLeaveConfirmed();
930
1585
  await router.navigate([], {
931
1586
  relativeTo: route,
932
1587
  queryParams: { _ts: now },
933
1588
  queryParamsHandling: 'merge',
1589
+ replaceUrl: true,
934
1590
  });
935
1591
  }
936
1592
  async ngOnInit() {
937
1593
  await super.ngOnInit();
1594
+ this.unsavedChangesPopstate.registerSource({
1595
+ id: 'axp-layout-details-view',
1596
+ isDirty: () => this.shouldPromptLeave(),
1597
+ });
938
1598
  //
939
1599
  await this.vm.load(this.adapter());
1600
+ this.detailsLayoutReady = true;
1601
+ void this.refreshKeyboardShortcutRegistrations(++this.keyboardShortcutRegistrationGeneration);
940
1602
  this.eventService
941
1603
  //TODO: Use the constant from the entity module
942
1604
  .listen('entity:refresh-layout')
@@ -960,16 +1622,92 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
960
1622
  }
961
1623
  }
962
1624
  ngOnDestroy() {
1625
+ this.unsavedChangesPopstate.unregisterSource('axp-layout-details-view');
963
1626
  this.onSelectionChangeSubscription?.unsubscribe();
1627
+ ++this.keyboardShortcutRegistrationGeneration;
964
1628
  this.destroyed$.next();
965
1629
  this.destroyed$.complete();
966
1630
  }
1631
+ #formDirtyEffect;
1632
+ /** Refresh title badge (Not Saved) when dirty state changes. */
1633
+ #headerBadgeEffect;
967
1634
  #FooterActionsEffect;
1635
+ #keyboardShortcutsEffect;
1636
+ async refreshFooterActions(generation) {
1637
+ const [footerPrimaryActions, footerSecondaryActions] = await Promise.all([
1638
+ this.getFooterPrimaryActions(),
1639
+ this.getFooterSecondaryActions(),
1640
+ ]);
1641
+ if (generation !== this.footerActionsGeneration) {
1642
+ return;
1643
+ }
1644
+ this.footerPrimaryActions.set(footerPrimaryActions);
1645
+ this.footerSecondaryActions.set(footerSecondaryActions);
1646
+ }
968
1647
  handleOnContextChanged(e) {
969
- this.vm.updateContext(e.data);
1648
+ this.vm.setFormDirty(e.isFormDirty ?? false);
970
1649
  this.recompute();
971
1650
  }
972
- handleSelectPage(page) {
1651
+ getLiveFormContext() {
1652
+ const container = this.widgetContainer();
1653
+ return (container?.contextService.data() ?? this.vm.context());
1654
+ }
1655
+ async finalizeSave() {
1656
+ const container = this.widgetContainer();
1657
+ if (!container) {
1658
+ this.vm.setFormDirty(false);
1659
+ return;
1660
+ }
1661
+ const savedContext = this.vm.context();
1662
+ await container.replaceContext(savedContext);
1663
+ this.vm.applySavedState(container.contextService.data());
1664
+ }
1665
+ finalizeDiscard() {
1666
+ const container = this.widgetContainer();
1667
+ if (!container) {
1668
+ return;
1669
+ }
1670
+ container.revertAndSettle();
1671
+ this.vm.applySavedState(container.contextService.data());
1672
+ }
1673
+ /**
1674
+ * `ax-tabs` selects on click before we can confirm. Revert synchronously, then confirm + switch.
1675
+ */
1676
+ handleSidebarTabChanged(event) {
1677
+ if (!this.detailsLayoutReady || this.sidebarTabChangeSuppressed) {
1678
+ return;
1679
+ }
1680
+ const pages = this.vm.adapter()?.pages ?? [];
1681
+ const target = pages[event.index];
1682
+ const currentId = this.vm.currentPage()?.id;
1683
+ if (!target || target.id === currentId) {
1684
+ return;
1685
+ }
1686
+ const activeIndex = pages.findIndex((page) => page.id === currentId);
1687
+ if (activeIndex >= 0) {
1688
+ this.sidebarTabChangeSuppressed = true;
1689
+ try {
1690
+ this.sidebarTabs()?.select(activeIndex);
1691
+ }
1692
+ finally {
1693
+ this.sidebarTabChangeSuppressed = false;
1694
+ }
1695
+ }
1696
+ void this.completePageSwitch(target);
1697
+ }
1698
+ async handleSelectPage(page) {
1699
+ if (page.id === this.vm.currentPage()?.id) {
1700
+ return;
1701
+ }
1702
+ if (!(await this.confirmLeaveIfDirty())) {
1703
+ return;
1704
+ }
1705
+ this.vm.setCurrentPage(page);
1706
+ }
1707
+ async completePageSwitch(page) {
1708
+ if (!(await this.confirmLeaveIfDirty())) {
1709
+ return;
1710
+ }
973
1711
  this.vm.setCurrentPage(page);
974
1712
  }
975
1713
  async getAllPrimaryActions() {
@@ -988,7 +1726,9 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
988
1726
  return (await this.getAllPrimaryActions()).filter((a) => {
989
1727
  return (a.priority == 'primary' &&
990
1728
  ((a.scope == AXPEntityCommandScope.Selected && this.vm.currentPageSelectedRows().length) ||
991
- (a.scope == AXPEntityCommandScope.TypeLevel && !this.vm.currentPageSelectedRows().length)));
1729
+ ((a.scope == AXPEntityCommandScope.TypeLevel || !a.scope) &&
1730
+ a.zone != 'footer' &&
1731
+ !this.vm.currentPageSelectedRows().length)));
992
1732
  });
993
1733
  }
994
1734
  async getFooterPrimaryActions() {
@@ -1016,46 +1756,40 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1016
1756
  return (await this.vm.breadcrumbs()) ?? [];
1017
1757
  }
1018
1758
  async getPageTitle() {
1019
- if (this.vm.showPages()) {
1020
- return this.vm.title() || '';
1021
- }
1022
- else {
1023
- return this.vm.currentPageTitle() || '';
1024
- }
1759
+ return this.vm.getPageTitle();
1025
1760
  }
1026
1761
  async getPageDescription() {
1027
- if (this.vm.showPages()) {
1028
- return (await this.vm.description()) || '';
1029
- }
1030
- else {
1031
- return await this.vm.currentPageDescription();
1032
- }
1762
+ return this.vm.getPageDescription();
1033
1763
  }
1034
1764
  async getBackButton() {
1035
- if (this.vm.adapter()?.pages?.length > 1) {
1036
- return {
1037
- title: this.vm.backButtonTitle() ?? '',
1038
- };
1765
+ return this.vm.getBackButton();
1766
+ }
1767
+ async getPageBadge() {
1768
+ if (this.vm.currentPage()?.isReadonly) {
1769
+ return null;
1039
1770
  }
1040
- else {
1041
- return {
1042
- title: this.vm.adapter()?.label ?? '',
1043
- };
1771
+ const componentInstance = this.getActivePageComponentInstance();
1772
+ if (componentInstance) {
1773
+ return componentInstance.resolvePageBadge();
1044
1774
  }
1775
+ if (!this.liveFormIsDirty()) {
1776
+ return null;
1777
+ }
1778
+ return buildNotSavedPageBadge(this.translateService, this.settingsService);
1779
+ }
1780
+ async getPageStatus() {
1781
+ return this.vm.getPageStatus();
1782
+ }
1783
+ /**
1784
+ * Get entity data for status chip component
1785
+ */
1786
+ getEntityData() {
1787
+ return this.vm.context() ?? null;
1045
1788
  }
1046
- // override async getPageBadge(): Promise<AXPBadge | null> {
1047
- // if (this.vm.isDirty()) {
1048
- // return {
1049
- // title: await this.translateService.translateAsync('@general:terms.interface.save-status.not-saved.title'),
1050
- // color: 'warning',
1051
- // description: await this.translateService.translateAsync(
1052
- // '@general:terms.interface.save-status.not-saved.description',
1053
- // ),
1054
- // };
1055
- // }
1056
- // return null;
1057
- // }
1058
1789
  async onBackButtonClick() {
1790
+ if (!(await this.confirmLeaveIfDirty())) {
1791
+ return;
1792
+ }
1059
1793
  // When back button is clicked in small layout, go back to page list
1060
1794
  if (!this.vm.showPages() && this.vm.adapter()?.pages?.length > 1) {
1061
1795
  this.vm.setCurrentPage(null);
@@ -1064,6 +1798,59 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1064
1798
  this.vm.goToListPage();
1065
1799
  }
1066
1800
  }
1801
+ //#region ---- Leave Page Gate ----
1802
+ /**
1803
+ * Router guard hook — same unsaved-changes confirm as dialog builder {@link confirmCloseWhenDirty}.
1804
+ */
1805
+ async canDeactivate() {
1806
+ if (this.unsavedChangesConfirm.hasLeaveConfirmed()) {
1807
+ return true;
1808
+ }
1809
+ return this.confirmLeaveIfDirty();
1810
+ }
1811
+ /** Active entity component page instance, when the current details sub-page is component-based. */
1812
+ getActivePageComponentInstance() {
1813
+ const componentKey = this.getActivePageComponentKey();
1814
+ if (!componentKey) {
1815
+ return null;
1816
+ }
1817
+ return this.pageComponentInstanceRegistry.get(componentKey);
1818
+ }
1819
+ /** Component key for the current details sub-page, when content is component-based. */
1820
+ getActivePageComponentKey() {
1821
+ const content = this.vm.currentPage()?.content;
1822
+ if (!content?.length) {
1823
+ return null;
1824
+ }
1825
+ for (const item of content) {
1826
+ if (AXPLayoutDetailsViewComponent.isComponentPageContent(item)) {
1827
+ return item.componentKey;
1828
+ }
1829
+ }
1830
+ return null;
1831
+ }
1832
+ static isComponentPageContent(item) {
1833
+ return 'type' in item && item.type === 'component';
1834
+ }
1835
+ /** Whether the active component-based entity page has unsaved edits. */
1836
+ isActivePageComponentDirty() {
1837
+ return this.getActivePageComponentInstance()?.hasUnsavedChanges() ?? false;
1838
+ }
1839
+ /** Whether the current details page has user-origin unsaved edits (form or component page). */
1840
+ shouldPromptLeave() {
1841
+ if (this.vm.currentPage()?.isReadonly) {
1842
+ return false;
1843
+ }
1844
+ if (this.isActivePageComponentDirty()) {
1845
+ return true;
1846
+ }
1847
+ return this.liveFormIsDirty();
1848
+ }
1849
+ /** Single gate for leaving the page or switching details sub-pages when dirty. */
1850
+ confirmLeaveIfDirty() {
1851
+ return this.unsavedChangesConfirm.confirmIfDirty(this.shouldPromptLeave());
1852
+ }
1853
+ //#endregion
1067
1854
  //#region ---- Command Execution ----
1068
1855
  async execute(command) {
1069
1856
  if (!this.vm.adapter()) {
@@ -1072,15 +1859,36 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1072
1859
  const acceptCommand = this.vm.currentPage()?.settings?.commands?.accept?.command.name;
1073
1860
  const rejectCommand = this.vm.currentPage()?.settings?.commands?.reject?.command.name;
1074
1861
  if (command.name == acceptCommand) {
1075
- await this.vm.save(command, this.form());
1862
+ const saved = await this.vm.save(command, this.form(), this.getLiveFormContext());
1863
+ if (saved) {
1864
+ await this.finalizeSave();
1865
+ }
1076
1866
  this.recompute();
1077
1867
  return;
1078
1868
  }
1079
1869
  if (command.name == rejectCommand) {
1080
1870
  await this.vm.discard();
1871
+ this.finalizeDiscard();
1081
1872
  this.recompute();
1082
1873
  return;
1083
1874
  }
1875
+ // Handle status update command
1876
+ if (command.name === 'update-status') {
1877
+ const transition = command.options?.['transition'];
1878
+ if (transition?.toStatus?.name) {
1879
+ const status = await this.vm.getPageStatus();
1880
+ if (status?.dataPath) {
1881
+ // Update entity context with new status value
1882
+ const entity = this.vm.context();
1883
+ if (entity) {
1884
+ entity[status.dataPath] = transition.toStatus.name;
1885
+ this.vm.updateContext(entity);
1886
+ this.recompute();
1887
+ }
1888
+ }
1889
+ }
1890
+ return;
1891
+ }
1084
1892
  // Get all actions
1085
1893
  const [adapterPrimaryActions, adapterSecondaryActions, pagePrimaryActions, pageSecondaryActions] = await Promise.all([
1086
1894
  this.vm.primaryActions(),
@@ -1092,9 +1900,14 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1092
1900
  const adapterActions = [...adapterPrimaryActions, ...adapterSecondaryActions];
1093
1901
  // Combine current page actions (primary + secondary)
1094
1902
  const pageActions = [...pagePrimaryActions, ...pageSecondaryActions];
1095
- // Helper function to check if command exists in actions
1096
1903
  const commandExistsInActions = (actions, commandName) => {
1097
- return actions.some((action) => action.command?.name === commandName);
1904
+ const check = (list) => {
1905
+ if (!Array.isArray(list) || list.length === 0)
1906
+ return false;
1907
+ return list.some((action) => action?.command?.name === commandName ||
1908
+ (Array.isArray(action?.items) && check(action.items)));
1909
+ };
1910
+ return check(actions);
1098
1911
  };
1099
1912
  // Check if command exists in adapter actions first
1100
1913
  if (commandExistsInActions(adapterActions, command.name)) {
@@ -1105,35 +1918,240 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1105
1918
  await this.vm
1106
1919
  .currentPage()
1107
1920
  ?.execute?.(command, this.vm.pageSelectedRows().length ? this.vm.pageSelectedRows() : this.vm.context());
1921
+ await this.syncDirtyStateAfterPageComponentCommand(command);
1922
+ }
1923
+ }
1924
+ /**
1925
+ * After a component-based page command (e.g. custom discard/save), align view-model dirty
1926
+ * state and widget context with the hosted page when it no longer reports unsaved changes.
1927
+ */
1928
+ async syncDirtyStateAfterPageComponentCommand(command) {
1929
+ const rejectCommand = this.vm.currentPage()?.settings?.commands?.reject?.command?.name;
1930
+ await this.waitForComponentDirtySettle();
1931
+ if (!this.getActivePageComponentKey()) {
1932
+ return;
1933
+ }
1934
+ if (isDiscardCommand(command.name, rejectCommand)) {
1935
+ await this.vm.discard();
1936
+ this.finalizeDiscard();
1937
+ this.recompute();
1938
+ return;
1939
+ }
1940
+ if (!this.isActivePageComponentDirty()) {
1941
+ const container = this.widgetContainer();
1942
+ if (container) {
1943
+ await container.settleSavedBaseline();
1944
+ this.vm.applySavedState(container.contextService.data());
1945
+ }
1946
+ else {
1947
+ this.vm.setFormDirty(false);
1948
+ }
1949
+ }
1950
+ this.recompute();
1951
+ }
1952
+ /** Waits for builder/effect microtasks to finish after a component page command. */
1953
+ waitForComponentDirtySettle() {
1954
+ return new Promise((resolve) => {
1955
+ queueMicrotask(() => {
1956
+ requestAnimationFrame(() => resolve());
1957
+ });
1958
+ });
1959
+ }
1960
+ //#endregion
1961
+ //#region ---- Keyboard Shortcuts ----
1962
+ async refreshKeyboardShortcutRegistrations(generation) {
1963
+ const entries = await this.collectActionShortcutEntries();
1964
+ if (generation !== this.keyboardShortcutRegistrationGeneration || this.destroyed$.closed) {
1965
+ return;
1108
1966
  }
1967
+ this.actionShortcutEntries.set(entries);
1968
+ this.registerCoreKeyboardShortcuts();
1969
+ this.registerActionKeyboardShortcuts(entries);
1109
1970
  }
1110
- async handleKeyboardEvent(event) {
1111
- if (event.ctrlKey) {
1112
- switch (event.code) {
1113
- case 'KeyS':
1114
- event.preventDefault();
1115
- event.stopPropagation();
1116
- await this.execute({ name: this.vm.currentPage()?.settings?.commands?.accept?.command.name || 'save' });
1117
- break;
1971
+ async collectActionShortcutEntries() {
1972
+ const map = new Map();
1973
+ if (this.vm.showPages()) {
1974
+ return map;
1975
+ }
1976
+ const [primaryActions, secondaryActions] = await Promise.all([
1977
+ this.getAllPrimaryActions(),
1978
+ this.getAllSecondaryActions(),
1979
+ ]);
1980
+ for (const action of [...primaryActions, ...secondaryActions]) {
1981
+ if (action.zone !== 'header' || this.isSaveDiscardFooterAction(action)) {
1982
+ continue;
1118
1983
  }
1984
+ const commandName = action.command?.name;
1985
+ const command = action.command;
1986
+ if (!commandName || !command) {
1987
+ continue;
1988
+ }
1989
+ const commandBaseName = getDetailsViewActionCommandBaseName(commandName);
1990
+ const chords = resolveDetailsViewActionShortcuts(commandBaseName, action.shortcuts);
1991
+ if (!chords?.length) {
1992
+ continue;
1993
+ }
1994
+ map.set(commandName, {
1995
+ command,
1996
+ title: typeof action.title === 'string' ? action.title : '',
1997
+ chords,
1998
+ visible: this.isHeaderActionAvailable(action),
1999
+ disabled: AXPLayoutDetailsViewComponent.isTruthyActionFlag(action.disabled),
2000
+ });
1119
2001
  }
2002
+ return map;
2003
+ }
2004
+ isHeaderActionAvailable(action) {
2005
+ if (AXPLayoutDetailsViewComponent.isTruthyActionFlag(action.hidden)) {
2006
+ return false;
2007
+ }
2008
+ if (action.visible !== undefined && !AXPLayoutDetailsViewComponent.isTruthyActionFlag(action.visible)) {
2009
+ return false;
2010
+ }
2011
+ return true;
2012
+ }
2013
+ /** Whether save/discard core shortcuts are listed in the help dialog (page supports them). */
2014
+ isCoreSaveShortcutAvailable() {
2015
+ return !this.vm.currentPage()?.isReadonly && !!this.acceptFooterCommand();
1120
2016
  }
1121
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutDetailsViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1122
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPLayoutDetailsViewComponent, isStandalone: true, selector: "axp-layout-details-view", inputs: { adapter: { classPropertyName: "adapter", publicName: "adapter", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "document:keydown": "handleKeyboardEvent($event)" } }, providers: [
2017
+ isCoreDiscardShortcutAvailable() {
2018
+ return !this.vm.currentPage()?.isReadonly && !!this.rejectFooterCommand();
2019
+ }
2020
+ canExecuteSaveShortcut() {
2021
+ if (this.vm.currentPage()?.isReadonly || this.vm.isSaving()) {
2022
+ return false;
2023
+ }
2024
+ if (!this.acceptFooterCommand()) {
2025
+ return false;
2026
+ }
2027
+ return this.shouldPromptLeave();
2028
+ }
2029
+ canExecuteDiscardShortcut() {
2030
+ if (this.vm.currentPage()?.isReadonly || this.vm.isSaving()) {
2031
+ return false;
2032
+ }
2033
+ if (this.unsavedChangesConfirm.isConfirmPending()) {
2034
+ return false;
2035
+ }
2036
+ if (!this.rejectFooterCommand()) {
2037
+ return false;
2038
+ }
2039
+ return this.shouldPromptLeave();
2040
+ }
2041
+ async executeDiscardViaShortcut(rejectCommandName) {
2042
+ if (!this.canExecuteDiscardShortcut()) {
2043
+ return;
2044
+ }
2045
+ const confirmed = await this.unsavedChangesConfirm.confirmIfDirty(true, {
2046
+ title: '@general:messages.unsaved-changes.title',
2047
+ message: '@general:messages.discard-changes.message',
2048
+ approveLeaveOnConfirm: false,
2049
+ });
2050
+ if (!confirmed) {
2051
+ return;
2052
+ }
2053
+ await this.execute({ name: rejectCommandName });
2054
+ }
2055
+ isActionShortcutActive(entryId) {
2056
+ if (this.vm.currentPage()?.isReadonly || this.vm.isSaving()) {
2057
+ return false;
2058
+ }
2059
+ const entry = this.actionShortcutEntries().get(entryId);
2060
+ if (!entry) {
2061
+ return false;
2062
+ }
2063
+ return entry.visible && !entry.disabled;
2064
+ }
2065
+ registerCoreKeyboardShortcuts() {
2066
+ const accept = this.vm.currentPage()?.settings?.commands?.accept;
2067
+ const reject = this.vm.currentPage()?.settings?.commands?.reject;
2068
+ const acceptCommandName = accept?.command.name ?? 'update-entity';
2069
+ const rejectCommandName = reject?.command.name ?? 'discard';
2070
+ const saveKeys = resolveDetailsViewFooterCommandShortcuts(acceptCommandName, accept?.shortcuts);
2071
+ const discardKeys = resolveDetailsViewFooterCommandShortcuts(rejectCommandName, reject?.shortcuts);
2072
+ const shortcuts = [];
2073
+ if (saveKeys?.length && this.isCoreSaveShortcutAvailable()) {
2074
+ shortcuts.push({
2075
+ keys: saveKeys,
2076
+ title: accept?.title ?? '@general:actions.save.title',
2077
+ group: '@general:keyboard-shortcuts.groups.entity-details',
2078
+ allowInEditableFields: true,
2079
+ when: () => this.canExecuteSaveShortcut(),
2080
+ handler: () => {
2081
+ void this.execute({ name: acceptCommandName });
2082
+ },
2083
+ });
2084
+ }
2085
+ if (discardKeys?.length && this.isCoreDiscardShortcutAvailable()) {
2086
+ shortcuts.push({
2087
+ keys: discardKeys,
2088
+ title: reject?.title ?? '@general:actions.discard.title',
2089
+ group: '@general:keyboard-shortcuts.groups.entity-details',
2090
+ allowInEditableFields: true,
2091
+ when: () => this.canExecuteDiscardShortcut(),
2092
+ handler: () => {
2093
+ void this.executeDiscardViaShortcut(rejectCommandName);
2094
+ },
2095
+ });
2096
+ }
2097
+ if (shortcuts.length === 0) {
2098
+ return;
2099
+ }
2100
+ this.shortcutRegistry.register({
2101
+ owner: this.destroyRef,
2102
+ elementRef: this.elementRef,
2103
+ id: 'layout-details-view-core',
2104
+ priority: AXPKeyboardShortcutPriority.Page,
2105
+ scope: '@general:keyboard-shortcuts.groups.entity-details',
2106
+ shortcuts,
2107
+ });
2108
+ }
2109
+ registerActionKeyboardShortcuts(entries) {
2110
+ const shortcuts = [];
2111
+ for (const [entryId, entry] of entries) {
2112
+ for (const chord of entry.chords) {
2113
+ shortcuts.push({
2114
+ keys: [chord],
2115
+ title: entry.title,
2116
+ group: '@general:keyboard-shortcuts.groups.entity-details',
2117
+ when: () => this.isActionShortcutActive(entryId),
2118
+ handler: () => {
2119
+ if (!this.isActionShortcutActive(entryId)) {
2120
+ return;
2121
+ }
2122
+ void this.execute(entry.command);
2123
+ },
2124
+ });
2125
+ }
2126
+ }
2127
+ if (shortcuts.length === 0) {
2128
+ return;
2129
+ }
2130
+ this.shortcutRegistry.register({
2131
+ owner: this.destroyRef,
2132
+ elementRef: this.elementRef,
2133
+ id: 'layout-details-view-actions',
2134
+ priority: AXPKeyboardShortcutPriority.Page,
2135
+ scope: '@general:keyboard-shortcuts.groups.entity-details',
2136
+ shortcuts,
2137
+ });
2138
+ }
2139
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLayoutDetailsViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2140
+ 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: [
1123
2141
  {
1124
2142
  provide: AXPPageLayoutBase,
1125
2143
  useExisting: AXPLayoutDetailsViewComponent,
1126
2144
  },
1127
2145
  AXPLayoutDetailsViewViewModel,
1128
- ], viewQueries: [{ propertyName: "form", first: true, predicate: ["form"], descendants: true, isSignal: true }, { propertyName: "widgetContainer", first: true, predicate: AXPWidgetContainerComponent, 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 [axResizable]=\"true\">\n <axp-layout-header>\n <axp-layout-title>{{ t(vm.title()) | async }}</axp-layout-title>\n <axp-layout-description>{{ t(vm.description()) | async }}</axp-layout-description>\n </axp-layout-header>\n <axp-layout-content>\n <ax-tabs class=\"axp-vertical-tabs\" [look]=\"'with-line-color'\" [location]=\"'end'\" [fitParent]=\"true\">\n @for (item of vm.adapter()?.pages; track $index) {\n <ax-tab-item\n [text]=\"(formatService.format(item.label, 'string', vm.rootContext()) | translate | async)!\"\n (onClick)=\"handleSelectPage(item)\"\n [active]=\"vm.currentPage() == item\"\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 <ax-form class=\"ax-h-full ax-w-full\" #form>\n <axp-widgets-container [context]=\"vm.context()\" (onContextChanged)=\"handleOnContextChanged($event)\">\n <div class=\"ax-flex ax-flex-col ax-w-full ax-gap-4 ax-h-full\">\n @for (content of vm.currentPageContent(); track $index) {\n <ng-container axp-widget-renderer [node]=\"content\" [mode]=\"content.mode ?? 'view'\"></ng-container>\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() == tab\"\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 @for (renderedTab of vm.currentPageRenderedTabs(); track renderedTab.tabId) {\n <div [class]=\"renderedTab.tabId === vm.currentTab()?.id ? '' : 'ax-hidden'\">\n @for (content of vm.getRenderedTabContent(renderedTab.tabId); track $index) {\n <ng-container axp-widget-renderer [node]=\"content\" [mode]=\"content.mode ?? 'view'\">\n </ng-container>\n }\n </div>\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\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 (action.visible != false) {\n <ax-button-item\n [text]=\"(t(action.title) | async)!\"\n [color]=\"action.color\"\n [disabled]=\"action.disabled || vm.isSaving()\"\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 @for (action of footerPrimaryActions(); track $index) {\n @if (action.visible != false) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [disabled]=\"action.disabled || vm.isSaving()\"\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 (sub.visible != false) {\n <ax-button-item\n [text]=\"(t(sub.title) | async)!\"\n [color]=\"sub.color\"\n [disabled]=\"sub.disabled\"\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-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;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))}\n"], dependencies: [{ kind: "ngmodule", type:
2146
+ ], 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(vm.showPages() ? (vm.adapter()?.title ?? '') : (vm.adapter()?.label ?? ''), 'string', vm.rootContext())\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 <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 $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 </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:
1129
2147
  // Angular
1130
2148
  CommonModule }, { kind: "ngmodule", type:
1131
2149
  // ACoreX
1132
- 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: "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: "directive", type: AXResizableDirective, selector: "[axResizable]", inputs: ["axResizable", "minWidth", "maxWidth", "dblClickAction", "width", "defaultWidth"], outputs: ["axResizableChange", "minWidthChange", "maxWidthChange", "dblClickActionChange", "widthChange", "defaultWidthChange", "onResizingStarted", "onResizingEnded", "onResizingDblClick"] }, { kind: "component", type:
2150
+ 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: "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:
1133
2151
  //
1134
- 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"], outputs: ["onValidate", "updateOnChange"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
2152
+ 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 }); }
1135
2153
  }
1136
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutDetailsViewComponent, decorators: [{
2154
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLayoutDetailsViewComponent, decorators: [{
1137
2155
  type: Component,
1138
2156
  args: [{ selector: 'axp-layout-details-view', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1139
2157
  // Angular
@@ -1155,7 +2173,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
1155
2173
  AXDateTimeModule,
1156
2174
  AXSearchBoxModule,
1157
2175
  AXTabsModule,
1158
- AXResizableDirective,
1159
2176
  //
1160
2177
  AXPThemeLayoutListComponent,
1161
2178
  AXPThemeLayoutListItemComponent,
@@ -1165,21 +2182,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
1165
2182
  AXPThemeLayoutStartSideComponent,
1166
2183
  AXPThemeLayoutHeaderComponent,
1167
2184
  AXFormModule,
2185
+ AXPPageComponentRendererDirective,
1168
2186
  ], encapsulation: ViewEncapsulation.None, providers: [
1169
2187
  {
1170
2188
  provide: AXPPageLayoutBase,
1171
2189
  useExisting: AXPLayoutDetailsViewComponent,
1172
2190
  },
1173
2191
  AXPLayoutDetailsViewViewModel,
1174
- ], template: "<axp-page-layout *translate=\"let t\">\n @if (vm.adapter()?.pages?.length! > 1 && vm.isLarge()) {\n <axp-layout-start-side [axResizable]=\"true\">\n <axp-layout-header>\n <axp-layout-title>{{ t(vm.title()) | async }}</axp-layout-title>\n <axp-layout-description>{{ t(vm.description()) | async }}</axp-layout-description>\n </axp-layout-header>\n <axp-layout-content>\n <ax-tabs class=\"axp-vertical-tabs\" [look]=\"'with-line-color'\" [location]=\"'end'\" [fitParent]=\"true\">\n @for (item of vm.adapter()?.pages; track $index) {\n <ax-tab-item\n [text]=\"(formatService.format(item.label, 'string', vm.rootContext()) | translate | async)!\"\n (onClick)=\"handleSelectPage(item)\"\n [active]=\"vm.currentPage() == item\"\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 <ax-form class=\"ax-h-full ax-w-full\" #form>\n <axp-widgets-container [context]=\"vm.context()\" (onContextChanged)=\"handleOnContextChanged($event)\">\n <div class=\"ax-flex ax-flex-col ax-w-full ax-gap-4 ax-h-full\">\n @for (content of vm.currentPageContent(); track $index) {\n <ng-container axp-widget-renderer [node]=\"content\" [mode]=\"content.mode ?? 'view'\"></ng-container>\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() == tab\"\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 @for (renderedTab of vm.currentPageRenderedTabs(); track renderedTab.tabId) {\n <div [class]=\"renderedTab.tabId === vm.currentTab()?.id ? '' : 'ax-hidden'\">\n @for (content of vm.getRenderedTabContent(renderedTab.tabId); track $index) {\n <ng-container axp-widget-renderer [node]=\"content\" [mode]=\"content.mode ?? 'view'\">\n </ng-container>\n }\n </div>\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\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 (action.visible != false) {\n <ax-button-item\n [text]=\"(t(action.title) | async)!\"\n [color]=\"action.color\"\n [disabled]=\"action.disabled || vm.isSaving()\"\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 @for (action of footerPrimaryActions(); track $index) {\n @if (action.visible != false) {\n <ax-button\n [class.ax-sm]=\"deviceService.isSmall()\"\n [disabled]=\"action.disabled || vm.isSaving()\"\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 (sub.visible != false) {\n <ax-button-item\n [text]=\"(t(sub.title) | async)!\"\n [color]=\"sub.color\"\n [disabled]=\"sub.disabled\"\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-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;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))}\n"] }]
1175
- }], 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 }] }], handleKeyboardEvent: [{
1176
- type: HostListener,
1177
- args: ['document:keydown', ['$event']]
1178
- }] } });
2192
+ ], 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(vm.showPages() ? (vm.adapter()?.title ?? '') : (vm.adapter()?.label ?? ''), 'string', vm.rootContext())\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 <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 $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 </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"] }]
2193
+ }], 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 }] }] } });
2194
+
2195
+ //#region ---- Details View Can Deactivate Guard ----
2196
+ /**
2197
+ * Prompts for unsaved changes before leaving the entity details route (breadcrumbs, menu, back to list).
2198
+ */
2199
+ const axpDetailsViewCanDeactivateGuard = createUnsavedChangesCanDeactivateGuard();
2200
+ //#endregion
1179
2201
 
1180
2202
  /**
1181
2203
  * Generated bundle index. Do not edit.
1182
2204
  */
1183
2205
 
1184
- export { AXPLayoutDetailsViewComponent, AXPLayoutDetailsViewViewModel, AXPPageLayoutBase, AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPopupLayoutBase, AXPPopupLayoutBaseComponent, AXPPopupLayoutComponent };
2206
+ export { AXPLayoutDetailsViewComponent, AXPLayoutDetailsViewViewModel, AXPPageComponentInstanceRegistryService, AXPPageComponentRendererDirective, AXPPageLayoutBase, AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPopupLayoutBase, AXPPopupLayoutBaseComponent, AXPPopupLayoutComponent, axpDetailsViewCanDeactivateGuard, buildNotSavedPageBadge, getDetailsViewActionCommandBaseName, isDiscardCommand, resolveDetailsViewActionShortcuts, resolveDetailsViewFooterCommandShortcuts };
1185
2207
  //# sourceMappingURL=acorex-platform-layout-views.mjs.map