@acorex/platform 21.0.0-next.70 → 21.0.0-next.72

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 (55) hide show
  1. package/fesm2022/acorex-platform-auth.mjs +10 -2
  2. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-common-common-settings.provider-Bi1RYif5.mjs → acorex-platform-common-common-settings.provider-Ytey9uhY.mjs} +15 -1
  4. package/fesm2022/acorex-platform-common-common-settings.provider-Ytey9uhY.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-common.mjs +3798 -1674
  6. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-core.mjs +1362 -97
  8. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-layout-builder.mjs +446 -44
  10. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-layout-components.mjs +149 -109
  12. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  13. package/fesm2022/acorex-platform-layout-designer.mjs +199 -126
  14. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  15. package/fesm2022/{acorex-platform-layout-entity-attachments-page.component-D8iQnT-R.mjs → acorex-platform-layout-entity-attachments-page.component-B0EkdqvH.mjs} +6 -1
  16. package/fesm2022/acorex-platform-layout-entity-attachments-page.component-B0EkdqvH.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-layout-entity.mjs +823 -594
  18. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  19. package/fesm2022/acorex-platform-layout-views.mjs +845 -218
  20. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-layout-widget-core.mjs +122 -33
  22. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  23. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-BcpRkpJp.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs} +2 -2
  24. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-BcpRkpJp.mjs.map → acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs.map} +1 -1
  25. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-DQtK4lxl.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs} +2 -2
  26. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-DQtK4lxl.mjs.map → acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs.map} +1 -1
  27. package/fesm2022/acorex-platform-layout-widgets.mjs +312 -676
  28. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  29. package/fesm2022/acorex-platform-themes-default-error-401.component-B1nsdpTY.mjs +48 -0
  30. package/fesm2022/acorex-platform-themes-default-error-401.component-B1nsdpTY.mjs.map +1 -0
  31. package/fesm2022/acorex-platform-themes-default-error-404.component-D4UvRe8u.mjs +42 -0
  32. package/fesm2022/acorex-platform-themes-default-error-404.component-D4UvRe8u.mjs.map +1 -0
  33. package/fesm2022/acorex-platform-themes-default.mjs +89 -46
  34. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  35. package/fesm2022/acorex-platform-themes-shared.mjs +50 -30
  36. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  37. package/package.json +1 -1
  38. package/types/acorex-platform-auth.d.ts +2 -0
  39. package/types/acorex-platform-common.d.ts +899 -256
  40. package/types/acorex-platform-core.d.ts +394 -60
  41. package/types/acorex-platform-layout-builder.d.ts +78 -13
  42. package/types/acorex-platform-layout-components.d.ts +30 -24
  43. package/types/acorex-platform-layout-entity.d.ts +93 -44
  44. package/types/acorex-platform-layout-views.d.ts +162 -42
  45. package/types/acorex-platform-layout-widget-core.d.ts +60 -33
  46. package/types/acorex-platform-layout-widgets.d.ts +48 -20
  47. package/types/acorex-platform-themes-default.d.ts +38 -8
  48. package/types/acorex-platform-themes-shared.d.ts +6 -0
  49. package/types/acorex-platform-workflow.d.ts +1 -1
  50. package/fesm2022/acorex-platform-common-common-settings.provider-Bi1RYif5.mjs.map +0 -1
  51. package/fesm2022/acorex-platform-layout-entity-attachments-page.component-D8iQnT-R.mjs.map +0 -1
  52. package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs +0 -31
  53. package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs.map +0 -1
  54. package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs +0 -25
  55. package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs.map +0 -1
@@ -6,7 +6,7 @@ import { AXClickEvent } from '@acorex/cdk/common';
6
6
  import * as i1 from '@acorex/cdk/drawer';
7
7
  import { AXDrawerItemDirective } from '@acorex/cdk/drawer';
8
8
  import * as _acorex_platform_core from '@acorex/platform/core';
9
- import { AXPActionMenuItem, AXPBreadcrumbItem, AXPMultiLanguageString, AXPBadge, AXPPageStatus, AXPBackButton, AXPExecuteCommand, AXPDeviceService, AXPExecuteCommandResult, AXPExpressionEvaluatorScope, AXPBroadcastEventService, AXPContextChangeEvent } from '@acorex/platform/core';
9
+ import { AXPActionMenuItem, AXPBreadcrumbItem, AXPMultiLanguageString, AXPBadge, AXPPageStatus, AXPBackButton, AXPExecuteCommand, AXPDeviceService, AXPKeyboardShortcut, AXPExecuteCommandResult, AXPExpressionEvaluatorScope, AXPBroadcastEventService, AXPContextChangeEvent, AXPKeyboardShortcutChord } from '@acorex/platform/core';
10
10
  import { AXPCommandService, AXPPolicyEngineService } from '@acorex/platform/runtime';
11
11
  import { AXPWorkflowService } from '@acorex/platform/workflow';
12
12
  import * as _acorex_core_translation from '@acorex/core/translation';
@@ -14,12 +14,14 @@ import { AXTranslationService } from '@acorex/core/translation';
14
14
  import { AXToastService } from '@acorex/components/toast';
15
15
  import { AXFormatService } from '@acorex/core/format';
16
16
  import { AXPSessionService } from '@acorex/platform/auth';
17
- import { AXPHomePageService, AXPEntityCommandScope } from '@acorex/platform/common';
17
+ import { AXPHomePageService, AXPSettingsService, AXPEntityCommandScope } from '@acorex/platform/common';
18
18
  import { AXBasePageComponent } from '@acorex/components/page';
19
19
  import * as _acorex_platform_layout_widget_core from '@acorex/platform/layout/widget-core';
20
20
  import { AXPWidgetNode, AXPPageStatus as AXPPageStatus$1, AXPWidgetContainerComponent } from '@acorex/platform/layout/widget-core';
21
21
  import * as _acorex_platform_layout_views from '@acorex/platform/layout/views';
22
22
  import { AXFormComponent } from '@acorex/components/form';
23
+ import { AXTabStripChangedEvent } from '@acorex/components/tabs';
24
+ import * as _angular_router from '@angular/router';
23
25
  import { Router, ActivatedRoute } from '@angular/router';
24
26
 
25
27
  declare abstract class AXPPageLayoutBase {
@@ -47,6 +49,10 @@ declare abstract class AXPPageLayoutBase {
47
49
  abstract onBackButtonClick: () => void | Promise<void>;
48
50
  abstract startSideToggle: () => void | Promise<void>;
49
51
  abstract execute: (command: AXPExecuteCommand) => void | Promise<void>;
52
+ /** Whether the page has user-origin edits that are not yet persisted. */
53
+ abstract hasUnsavedChanges(): boolean;
54
+ /** Resolves the page title badge (used by host layouts for nested entity pages). */
55
+ abstract resolvePageBadge(): AXPBadge | null | Promise<AXPBadge | null>;
50
56
  }
51
57
 
52
58
  declare class AXPPageLayoutComponent {
@@ -65,6 +71,7 @@ declare class AXPPageLayoutComponent {
65
71
  overlayLoadingTaskCount: _angular_core.Signal<number>;
66
72
  navigationLoadingTaskCount: _angular_core.Signal<number>;
67
73
  sideMenuState: _angular_core.Signal<_acorex_platform_themes_shared.AXPSideMenuState>;
74
+ overlaySideMenuOpen: _angular_core.Signal<boolean>;
68
75
  sideMenuWidth: _angular_core.Signal<number>;
69
76
  sideMenuCompactWidth: _angular_core.Signal<number>;
70
77
  menuVerticalMode: _angular_core.Signal<_acorex_platform_themes_shared.AXPMenuVerticalMode>;
@@ -77,6 +84,7 @@ declare class AXPPageLayoutComponent {
77
84
  isOverlayLoading: _angular_core.Signal<boolean>;
78
85
  isNavigationLoading: _angular_core.Signal<boolean>;
79
86
  isMenuHorizontal: _angular_core.Signal<boolean>;
87
+ effectiveMenuVerticalMode: _angular_core.Signal<_acorex_platform_themes_shared.AXPMenuVerticalMode>;
80
88
  sideMenuDrawerWidth: _angular_core.Signal<number>;
81
89
  changeThemeMode: (theme: _acorex_platform_themes_shared.AXPThemeMode) => void;
82
90
  openSideMenu: () => void;
@@ -101,6 +109,7 @@ declare class AXPPageLayoutComponent {
101
109
  overlayLoadingTaskCount: number;
102
110
  navigationLoadingTaskCount: number;
103
111
  sideMenuState: _acorex_platform_themes_shared.AXPSideMenuState;
112
+ overlaySideMenuOpen: boolean;
104
113
  sideMenuWidth: number;
105
114
  sideMenuCompactWidth: number;
106
115
  menuVerticalMode: _acorex_platform_themes_shared.AXPMenuVerticalMode;
@@ -118,6 +127,12 @@ declare class AXPPageLayoutComponent {
118
127
  protected handleBackdropClick(e: AXClickEvent): boolean;
119
128
  protected execute(command: AXPExecuteCommand): Promise<void>;
120
129
  protected handleOnBackdropClick(event: MouseEvent): void;
130
+ /**
131
+ * Breadcrumbs and other in-page `navigate` commands bypass `routerLink`, so prompt here
132
+ * when the hosted page implements {@link AXPUnsavedChangesCanDeactivate}.
133
+ * A successful confirm sets `leaveConfirmed` for the router guard on the subsequent navigation.
134
+ */
135
+ private canLeaveCurrentPage;
121
136
  protected getEntityData(): Record<string, any> | null;
122
137
  protected handleStatusTransition(transition: any): Promise<void>;
123
138
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXPPageLayoutComponent, never>;
@@ -139,6 +154,7 @@ declare abstract class AXPPageLayoutBaseComponent implements AXPPageLayoutBase {
139
154
  overlayLoadingTaskCount: _angular_core.Signal<number>;
140
155
  navigationLoadingTaskCount: _angular_core.Signal<number>;
141
156
  sideMenuState: _angular_core.Signal<_acorex_platform_themes_shared.AXPSideMenuState>;
157
+ overlaySideMenuOpen: _angular_core.Signal<boolean>;
142
158
  sideMenuWidth: _angular_core.Signal<number>;
143
159
  sideMenuCompactWidth: _angular_core.Signal<number>;
144
160
  menuVerticalMode: _angular_core.Signal<_acorex_platform_themes_shared.AXPMenuVerticalMode>;
@@ -151,6 +167,7 @@ declare abstract class AXPPageLayoutBaseComponent implements AXPPageLayoutBase {
151
167
  isOverlayLoading: _angular_core.Signal<boolean>;
152
168
  isNavigationLoading: _angular_core.Signal<boolean>;
153
169
  isMenuHorizontal: _angular_core.Signal<boolean>;
170
+ effectiveMenuVerticalMode: _angular_core.Signal<_acorex_platform_themes_shared.AXPMenuVerticalMode>;
154
171
  sideMenuDrawerWidth: _angular_core.Signal<number>;
155
172
  changeThemeMode: (theme: _acorex_platform_themes_shared.AXPThemeMode) => void;
156
173
  openSideMenu: () => void;
@@ -175,6 +192,7 @@ declare abstract class AXPPageLayoutBaseComponent implements AXPPageLayoutBase {
175
192
  overlayLoadingTaskCount: number;
176
193
  navigationLoadingTaskCount: number;
177
194
  sideMenuState: _acorex_platform_themes_shared.AXPSideMenuState;
195
+ overlaySideMenuOpen: boolean;
178
196
  sideMenuWidth: number;
179
197
  sideMenuCompactWidth: number;
180
198
  menuVerticalMode: _acorex_platform_themes_shared.AXPMenuVerticalMode;
@@ -187,6 +205,7 @@ declare abstract class AXPPageLayoutBaseComponent implements AXPPageLayoutBase {
187
205
  protected readonly toastService: AXToastService;
188
206
  protected readonly homePageService: AXPHomePageService;
189
207
  protected readonly policyService: AXPPolicyEngineService;
208
+ protected readonly settingsService: AXPSettingsService;
190
209
  private _updateTrigger;
191
210
  protected updateTrigger: _angular_core.Signal<number>;
192
211
  protected recompute(): void;
@@ -206,7 +225,9 @@ declare abstract class AXPPageLayoutBaseComponent implements AXPPageLayoutBase {
206
225
  protected getPageBreadcrumbs(): AXPBreadcrumbItem[] | Promise<AXPBreadcrumbItem[]>;
207
226
  badge: _angular_core.WritableSignal<AXPBadge | null>;
208
227
  hasBadge: _angular_core.Signal<boolean>;
209
- protected getPageBadge(): AXPBadge | null | Promise<AXPBadge | null>;
228
+ hasUnsavedChanges(): boolean;
229
+ protected getPageBadge(): Promise<AXPBadge | null>;
230
+ resolvePageBadge(): Promise<AXPBadge | null>;
210
231
  status: _angular_core.WritableSignal<AXPPageStatus | null>;
211
232
  hasStatus: _angular_core.Signal<boolean>;
212
233
  protected getPageStatus(): AXPPageStatus | null | Promise<AXPPageStatus | null>;
@@ -238,6 +259,15 @@ declare abstract class AXPPageLayoutBaseComponent implements AXPPageLayoutBase {
238
259
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXPPageLayoutBaseComponent, "ng-component", never, {}, {}, never, never, true, never>;
239
260
  }
240
261
 
262
+ /**
263
+ * Builds the standard "Not Saved" page badge when the global show-page-badge setting is enabled.
264
+ */
265
+ declare function buildNotSavedPageBadge(translateService: AXTranslationService, settingsService: AXPSettingsService): Promise<AXPBadge | null>;
266
+ /**
267
+ * Whether a command name represents a discard/revert action on a details sub-page.
268
+ */
269
+ declare function isDiscardCommand(commandName: string, rejectCommandName?: string | null): boolean;
270
+
241
271
  declare abstract class AXPPopupLayoutBase {
242
272
  abstract primaryMenuItems: Signal<AXPActionMenuItem[]>;
243
273
  abstract secondaryMenuItems: Signal<AXPActionMenuItem[]>;
@@ -267,6 +297,7 @@ declare class AXPPopupLayoutComponent {
267
297
  overlayLoadingTaskCount: _angular_core.Signal<number>;
268
298
  navigationLoadingTaskCount: _angular_core.Signal<number>;
269
299
  sideMenuState: _angular_core.Signal<_acorex_platform_themes_shared.AXPSideMenuState>;
300
+ overlaySideMenuOpen: _angular_core.Signal<boolean>;
270
301
  sideMenuWidth: _angular_core.Signal<number>;
271
302
  sideMenuCompactWidth: _angular_core.Signal<number>;
272
303
  menuVerticalMode: _angular_core.Signal<_acorex_platform_themes_shared.AXPMenuVerticalMode>;
@@ -279,6 +310,7 @@ declare class AXPPopupLayoutComponent {
279
310
  isOverlayLoading: _angular_core.Signal<boolean>;
280
311
  isNavigationLoading: _angular_core.Signal<boolean>;
281
312
  isMenuHorizontal: _angular_core.Signal<boolean>;
313
+ effectiveMenuVerticalMode: _angular_core.Signal<_acorex_platform_themes_shared.AXPMenuVerticalMode>;
282
314
  sideMenuDrawerWidth: _angular_core.Signal<number>;
283
315
  changeThemeMode: (theme: _acorex_platform_themes_shared.AXPThemeMode) => void;
284
316
  openSideMenu: () => void;
@@ -303,6 +335,7 @@ declare class AXPPopupLayoutComponent {
303
335
  overlayLoadingTaskCount: number;
304
336
  navigationLoadingTaskCount: number;
305
337
  sideMenuState: _acorex_platform_themes_shared.AXPSideMenuState;
338
+ overlaySideMenuOpen: boolean;
306
339
  sideMenuWidth: number;
307
340
  sideMenuCompactWidth: number;
308
341
  menuVerticalMode: _acorex_platform_themes_shared.AXPMenuVerticalMode;
@@ -333,6 +366,7 @@ declare abstract class AXPPopupLayoutBaseComponent extends AXBasePageComponent {
333
366
  overlayLoadingTaskCount: _angular_core.Signal<number>;
334
367
  navigationLoadingTaskCount: _angular_core.Signal<number>;
335
368
  sideMenuState: _angular_core.Signal<_acorex_platform_themes_shared.AXPSideMenuState>;
369
+ overlaySideMenuOpen: _angular_core.Signal<boolean>;
336
370
  sideMenuWidth: _angular_core.Signal<number>;
337
371
  sideMenuCompactWidth: _angular_core.Signal<number>;
338
372
  menuVerticalMode: _angular_core.Signal<_acorex_platform_themes_shared.AXPMenuVerticalMode>;
@@ -345,6 +379,7 @@ declare abstract class AXPPopupLayoutBaseComponent extends AXBasePageComponent {
345
379
  isOverlayLoading: _angular_core.Signal<boolean>;
346
380
  isNavigationLoading: _angular_core.Signal<boolean>;
347
381
  isMenuHorizontal: _angular_core.Signal<boolean>;
382
+ effectiveMenuVerticalMode: _angular_core.Signal<_acorex_platform_themes_shared.AXPMenuVerticalMode>;
348
383
  sideMenuDrawerWidth: _angular_core.Signal<number>;
349
384
  changeThemeMode: (theme: _acorex_platform_themes_shared.AXPThemeMode) => void;
350
385
  openSideMenu: () => void;
@@ -369,6 +404,7 @@ declare abstract class AXPPopupLayoutBaseComponent extends AXBasePageComponent {
369
404
  overlayLoadingTaskCount: number;
370
405
  navigationLoadingTaskCount: number;
371
406
  sideMenuState: _acorex_platform_themes_shared.AXPSideMenuState;
407
+ overlaySideMenuOpen: boolean;
372
408
  sideMenuWidth: number;
373
409
  sideMenuCompactWidth: number;
374
410
  menuVerticalMode: _acorex_platform_themes_shared.AXPMenuVerticalMode;
@@ -451,6 +487,7 @@ interface AXPLayoutDetailsViewPage {
451
487
  color: string;
452
488
  visible?: string | boolean;
453
489
  command: AXPExecuteCommand;
490
+ shortcuts?: AXPKeyboardShortcut[];
454
491
  };
455
492
  reject?: {
456
493
  title: string;
@@ -458,6 +495,7 @@ interface AXPLayoutDetailsViewPage {
458
495
  color: string;
459
496
  visible?: string | boolean;
460
497
  command: AXPExecuteCommand;
498
+ shortcuts?: AXPKeyboardShortcut[];
461
499
  };
462
500
  };
463
501
  };
@@ -490,12 +528,9 @@ declare const AXPLayoutDetailsViewViewModel: _angular_core.Type<{
490
528
  currentPage: _angular_core.Signal<AXPLayoutDetailsViewPage | null>;
491
529
  currentTab: _angular_core.Signal<AXPLayoutDetailsViewTabItem | null>;
492
530
  pageSelectedRows: _angular_core.Signal<any[]>;
493
- renderedTabsCache: _angular_core.Signal<Record<string, {
494
- tabId: string;
495
- tab: AXPLayoutDetailsViewTabItem;
496
- }[]>>;
497
531
  evaluatedPageContent: _angular_core.Signal<AXPWidgetNode[]>;
498
532
  evaluatedTabContentsById: _angular_core.Signal<Record<string, AXPWidgetNode[]>>;
533
+ formDirty: _angular_core.Signal<boolean>;
499
534
  icon: _angular_core.Signal<string | null>;
500
535
  content: _angular_core.Signal<_acorex_platform_layout_views.AXPPageContentItem[]>;
501
536
  showPages: _angular_core.Signal<boolean>;
@@ -503,17 +538,15 @@ declare const AXPLayoutDetailsViewViewModel: _angular_core.Type<{
503
538
  isBusy: _angular_core.Signal<boolean>;
504
539
  isSaving: _angular_core.Signal<boolean>;
505
540
  isDirty: _angular_core.Signal<boolean>;
506
- changesCount: _angular_core.Signal<number>;
541
+ changesCount: _angular_core.Signal<1 | 0>;
507
542
  isLoaded: _angular_core.Signal<boolean>;
508
543
  currentPageSelectedRows: _angular_core.Signal<any[]>;
509
- currentPageRenderedTabs: _angular_core.Signal<{
510
- tabId: string;
511
- tab: AXPLayoutDetailsViewTabItem;
512
- }[]>;
544
+ activeTabContent: _angular_core.Signal<AXPWidgetNode[]>;
513
545
  loadAdapter: (adapter: AXPLayoutDetailsViewAdapter) => Promise<void>;
514
546
  loadPage: (pageId?: string, forceRefresh?: boolean) => Promise<void>;
515
547
  load: (adapter: AXPLayoutDetailsViewAdapter) => Promise<void>;
516
548
  updateContext: (context: any) => void;
549
+ setFormDirty: (dirty: boolean) => void;
517
550
  updatePageSelectedRows: (rows: any[]) => void;
518
551
  currentPagePrimaryActions: () => Promise<any>;
519
552
  currentPageSecondaryActions: () => Promise<any>;
@@ -521,9 +554,6 @@ declare const AXPLayoutDetailsViewViewModel: _angular_core.Type<{
521
554
  currentPageTabs: () => AXPLayoutDetailsViewTabItem[] | undefined;
522
555
  setCurrentPage: (page: AXPLayoutDetailsViewPage | null) => void;
523
556
  setCurrentTab: (tab: AXPLayoutDetailsViewTabItem) => void;
524
- getCurrentTabContent: () => AXPWidgetNode[];
525
- getRenderedTabContent: (tabId: string) => AXPWidgetNode[];
526
- clearPageTabCache: (pageId: string) => void;
527
557
  backButtonTitle: () => _acorex_core_translation.AXMultiLanguageString;
528
558
  getPageTitle: () => Promise<AXPMultiLanguageString>;
529
559
  getPageDescription: () => Promise<AXPMultiLanguageString | null>;
@@ -538,8 +568,9 @@ declare const AXPLayoutDetailsViewViewModel: _angular_core.Type<{
538
568
  icon?: string;
539
569
  command?: AXPExecuteCommand;
540
570
  }[]>;
571
+ applySavedState: (context: Record<string, unknown>) => void;
541
572
  discard: () => Promise<void>;
542
- save: (command: AXPExecuteCommand, form: AXFormComponent) => Promise<void>;
573
+ save: (command: AXPExecuteCommand, form: AXFormComponent, liveContext?: Record<string, unknown>) => Promise<boolean>;
543
574
  goToListPage: () => void;
544
575
  } & _ngrx_signals.StateSource<{
545
576
  adapter: AXPLayoutDetailsViewAdapter | null;
@@ -551,12 +582,9 @@ declare const AXPLayoutDetailsViewViewModel: _angular_core.Type<{
551
582
  currentPage: AXPLayoutDetailsViewPage | null;
552
583
  currentTab: AXPLayoutDetailsViewTabItem | null;
553
584
  pageSelectedRows: any[];
554
- renderedTabsCache: Record<string, Array<{
555
- tabId: string;
556
- tab: AXPLayoutDetailsViewTabItem;
557
- }>>;
558
585
  evaluatedPageContent: AXPWidgetNode[];
559
586
  evaluatedTabContentsById: Record<string, AXPWidgetNode[]>;
587
+ formDirty: boolean;
560
588
  }>>;
561
589
 
562
590
  declare class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent implements OnInit, OnDestroy {
@@ -572,30 +600,25 @@ declare class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent i
572
600
  currentPage: _angular_core.Signal<AXPLayoutDetailsViewPage | null>;
573
601
  currentTab: _angular_core.Signal<_acorex_platform_layout_views.AXPLayoutDetailsViewTabItem | null>;
574
602
  pageSelectedRows: _angular_core.Signal<any[]>;
575
- renderedTabsCache: _angular_core.Signal<Record<string, {
576
- tabId: string;
577
- tab: _acorex_platform_layout_views.AXPLayoutDetailsViewTabItem;
578
- }[]>>;
579
603
  evaluatedPageContent: _angular_core.Signal<_acorex_platform_layout_widget_core.AXPWidgetNode[]>;
580
604
  evaluatedTabContentsById: _angular_core.Signal<Record<string, _acorex_platform_layout_widget_core.AXPWidgetNode[]>>;
605
+ formDirty: _angular_core.Signal<boolean>;
581
606
  icon: _angular_core.Signal<string | null>;
582
- content: _angular_core.Signal<_acorex_platform_layout_views.AXPPageContentItem[]>;
607
+ content: _angular_core.Signal<AXPPageContentItem[]>;
583
608
  showPages: _angular_core.Signal<boolean>;
584
609
  isLarge: _angular_core.Signal<boolean>;
585
610
  isBusy: _angular_core.Signal<boolean>;
586
611
  isSaving: _angular_core.Signal<boolean>;
587
612
  isDirty: _angular_core.Signal<boolean>;
588
- changesCount: _angular_core.Signal<number>;
613
+ changesCount: _angular_core.Signal<1 | 0>;
589
614
  isLoaded: _angular_core.Signal<boolean>;
590
615
  currentPageSelectedRows: _angular_core.Signal<any[]>;
591
- currentPageRenderedTabs: _angular_core.Signal<{
592
- tabId: string;
593
- tab: _acorex_platform_layout_views.AXPLayoutDetailsViewTabItem;
594
- }[]>;
616
+ activeTabContent: _angular_core.Signal<_acorex_platform_layout_widget_core.AXPWidgetNode[]>;
595
617
  loadAdapter: (adapter: AXPLayoutDetailsViewAdapter) => Promise<void>;
596
618
  loadPage: (pageId?: string, forceRefresh?: boolean) => Promise<void>;
597
619
  load: (adapter: AXPLayoutDetailsViewAdapter) => Promise<void>;
598
620
  updateContext: (context: any) => void;
621
+ setFormDirty: (dirty: boolean) => void;
599
622
  updatePageSelectedRows: (rows: any[]) => void;
600
623
  currentPagePrimaryActions: () => Promise<any>;
601
624
  currentPageSecondaryActions: () => Promise<any>;
@@ -603,9 +626,6 @@ declare class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent i
603
626
  currentPageTabs: () => _acorex_platform_layout_views.AXPLayoutDetailsViewTabItem[] | undefined;
604
627
  setCurrentPage: (page: AXPLayoutDetailsViewPage | null) => void;
605
628
  setCurrentTab: (tab: _acorex_platform_layout_views.AXPLayoutDetailsViewTabItem) => void;
606
- getCurrentTabContent: () => _acorex_platform_layout_widget_core.AXPWidgetNode[];
607
- getRenderedTabContent: (tabId: string) => _acorex_platform_layout_widget_core.AXPWidgetNode[];
608
- clearPageTabCache: (pageId: string) => void;
609
629
  backButtonTitle: () => _acorex_core_translation.AXMultiLanguageString;
610
630
  getPageTitle: () => Promise<AXPMultiLanguageString>;
611
631
  getPageDescription: () => Promise<AXPMultiLanguageString | null>;
@@ -620,8 +640,9 @@ declare class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent i
620
640
  icon?: string;
621
641
  command?: AXPExecuteCommand;
622
642
  }[]>;
643
+ applySavedState: (context: Record<string, unknown>) => void;
623
644
  discard: () => Promise<void>;
624
- save: (command: AXPExecuteCommand, form: AXFormComponent) => Promise<void>;
645
+ save: (command: AXPExecuteCommand, form: AXFormComponent, liveContext?: Record<string, unknown>) => Promise<boolean>;
625
646
  goToListPage: () => void;
626
647
  } & _ngrx_signals.StateSource<{
627
648
  adapter: AXPLayoutDetailsViewAdapter | null;
@@ -633,26 +654,63 @@ declare class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent i
633
654
  currentPage: AXPLayoutDetailsViewPage | null;
634
655
  currentTab: _acorex_platform_layout_views.AXPLayoutDetailsViewTabItem | null;
635
656
  pageSelectedRows: any[];
636
- renderedTabsCache: Record<string, Array<{
637
- tabId: string;
638
- tab: _acorex_platform_layout_views.AXPLayoutDetailsViewTabItem;
639
- }>>;
640
657
  evaluatedPageContent: _acorex_platform_layout_widget_core.AXPWidgetNode[];
641
658
  evaluatedTabContentsById: Record<string, _acorex_platform_layout_widget_core.AXPWidgetNode[]>;
659
+ formDirty: boolean;
642
660
  }>;
643
661
  protected router: Router;
644
662
  protected route: ActivatedRoute;
645
663
  protected eventService: AXPBroadcastEventService;
646
664
  protected deviceService: AXPDeviceService;
665
+ private readonly unsavedChangesConfirm;
666
+ private readonly unsavedChangesPopstate;
667
+ private readonly pageComponentInstanceRegistry;
668
+ private readonly shortcutRegistry;
669
+ private readonly destroyRef;
670
+ private readonly elementRef;
647
671
  private onSelectionChangeSubscription?;
672
+ /** Prevents sidebar tab init events from pushing history before {@link ngOnInit} load completes. */
673
+ private detailsLayoutReady;
648
674
  private readonly destroyed$;
675
+ private footerActionsGeneration;
676
+ private keyboardShortcutRegistrationGeneration;
677
+ /** Header actions with resolved shortcut chords, keyed by command name. */
678
+ private readonly actionShortcutEntries;
679
+ /** Save/discard use live {@link AXPLayoutDetailsViewViewModel.isDirty}; other actions use evaluated `visible`. */
680
+ private static isTruthyActionFlag;
649
681
  protected form: _angular_core.Signal<AXFormComponent | undefined>;
650
682
  protected widgetContainer: _angular_core.Signal<AXPWidgetContainerComponent | undefined>;
683
+ private readonly sidebarTabs;
684
+ private sidebarTabChangeSuppressed;
651
685
  protected footerPrimaryActions: _angular_core.WritableSignal<AXPActionMenuItem[]>;
652
686
  protected footerSecondaryActions: _angular_core.WritableSignal<AXPActionMenuItem[]>;
653
687
  protected footerActions: _angular_core.Signal<AXPActionMenuItem[]>;
688
+ protected rejectFooterCommand: _angular_core.Signal<{
689
+ title: string;
690
+ icon?: string;
691
+ color: string;
692
+ visible?: string | boolean;
693
+ command: AXPExecuteCommand;
694
+ shortcuts?: _acorex_platform_core.AXPKeyboardShortcut[];
695
+ } | null>;
696
+ protected acceptFooterCommand: _angular_core.Signal<{
697
+ title: string;
698
+ icon?: string;
699
+ color: string;
700
+ visible?: string | boolean;
701
+ command: AXPExecuteCommand;
702
+ shortcuts?: _acorex_platform_core.AXPKeyboardShortcut[];
703
+ } | null>;
704
+ protected hasSaveDiscardFooterCommands: _angular_core.Signal<boolean>;
705
+ /** Entity save/discard — driven live by widget/container dirty state, not evaluated action metadata. */
706
+ protected showSaveDiscardFooter: _angular_core.Signal<boolean>;
707
+ /** Live dirty flag for widget-based entity forms (not component-hosted pages). */
708
+ protected liveFormIsDirty: _angular_core.Signal<boolean>;
654
709
  protected hasVisibleFooterPrimaryActions: _angular_core.Signal<boolean>;
655
710
  protected hasVisibleFooterSecondaryActions: _angular_core.Signal<boolean>;
711
+ protected isSaveDiscardFooterAction(action: AXPActionMenuItem): boolean;
712
+ protected isFooterActionVisible(action: AXPActionMenuItem): boolean;
713
+ protected isFooterActionDisabled(action: AXPActionMenuItem): boolean;
656
714
  protected hasFooter: _angular_core.Signal<boolean>;
657
715
  /**
658
716
  * Append timestamp query param to trigger router to re-run guards/resolvers
@@ -661,8 +719,17 @@ declare class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent i
661
719
  ngOnInit(): Promise<void>;
662
720
  ngAfterViewInit(): Promise<void>;
663
721
  ngOnDestroy(): void;
722
+ private refreshFooterActions;
664
723
  protected handleOnContextChanged(e: AXPContextChangeEvent): void;
665
- protected handleSelectPage(page: AXPLayoutDetailsViewPage): void;
724
+ private getLiveFormContext;
725
+ private finalizeSave;
726
+ private finalizeDiscard;
727
+ /**
728
+ * `ax-tabs` selects on click before we can confirm. Revert synchronously, then confirm + switch.
729
+ */
730
+ protected handleSidebarTabChanged(event: AXTabStripChangedEvent): void;
731
+ protected handleSelectPage(page: AXPLayoutDetailsViewPage): Promise<void>;
732
+ private completePageSwitch;
666
733
  protected getAllPrimaryActions(): Promise<AXPLayoutDetailsViewAction[]>;
667
734
  getPrimaryMenuItems(): Promise<AXPActionMenuItem[]>;
668
735
  protected getFooterPrimaryActions(): Promise<AXPActionMenuItem[]>;
@@ -680,12 +747,65 @@ declare class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent i
680
747
  */
681
748
  getEntityData(): Record<string, any> | null;
682
749
  onBackButtonClick(): Promise<void>;
750
+ /**
751
+ * Router guard hook — same unsaved-changes confirm as dialog builder {@link confirmCloseWhenDirty}.
752
+ */
753
+ canDeactivate(): Promise<boolean>;
754
+ /** Active entity component page instance, when the current details sub-page is component-based. */
755
+ private getActivePageComponentInstance;
756
+ /** Component key for the current details sub-page, when content is component-based. */
757
+ private getActivePageComponentKey;
758
+ private static isComponentPageContent;
759
+ /** Whether the active component-based entity page has unsaved edits. */
760
+ private isActivePageComponentDirty;
761
+ /** Whether the current details page has user-origin unsaved edits (form or component page). */
762
+ private shouldPromptLeave;
763
+ /** Single gate for leaving the page or switching details sub-pages when dirty. */
764
+ private confirmLeaveIfDirty;
683
765
  execute(command: AXPExecuteCommand): Promise<void>;
684
- protected handleKeyboardEvent(event: KeyboardEvent): Promise<void>;
766
+ /**
767
+ * After a component-based page command (e.g. custom discard/save), align view-model dirty
768
+ * state and widget context with the hosted page when it no longer reports unsaved changes.
769
+ */
770
+ private syncDirtyStateAfterPageComponentCommand;
771
+ /** Waits for builder/effect microtasks to finish after a component page command. */
772
+ private waitForComponentDirtySettle;
773
+ private refreshKeyboardShortcutRegistrations;
774
+ private collectActionShortcutEntries;
775
+ private isHeaderActionAvailable;
776
+ /** Whether save/discard core shortcuts are listed in the help dialog (page supports them). */
777
+ private isCoreSaveShortcutAvailable;
778
+ private isCoreDiscardShortcutAvailable;
779
+ private canExecuteSaveShortcut;
780
+ private canExecuteDiscardShortcut;
781
+ private executeDiscardViaShortcut;
782
+ private isActionShortcutActive;
783
+ private registerCoreKeyboardShortcuts;
784
+ private registerActionKeyboardShortcuts;
685
785
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXPLayoutDetailsViewComponent, never>;
686
786
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXPLayoutDetailsViewComponent, "axp-layout-details-view", never, { "adapter": { "alias": "adapter"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
687
787
  }
688
788
 
789
+ type AXPDetailsViewActionShortcut = AXPKeyboardShortcutChord;
790
+ /**
791
+ * Returns the base workflow/command name from a composite entity action command id (`cmd&actionName`).
792
+ */
793
+ declare function getDetailsViewActionCommandBaseName(commandName: string | undefined): string;
794
+ /**
795
+ * Resolves keyboard shortcuts for a header entity action.
796
+ * Explicit `shortcuts` wins; pass `[]` to disable. Otherwise known commands use platform defaults.
797
+ */
798
+ declare function resolveDetailsViewActionShortcuts(commandBaseName: string, explicit?: readonly AXPKeyboardShortcut[]): AXPDetailsViewActionShortcut[] | undefined;
799
+ /**
800
+ * Resolves save/discard footer command shortcuts from page settings.
801
+ */
802
+ declare function resolveDetailsViewFooterCommandShortcuts(commandName: string, explicit?: readonly AXPKeyboardShortcut[]): AXPDetailsViewActionShortcut[] | undefined;
803
+
804
+ /**
805
+ * Prompts for unsaved changes before leaving the entity details route (breadcrumbs, menu, back to list).
806
+ */
807
+ declare const axpDetailsViewCanDeactivateGuard: _angular_router.CanDeactivateFn<AXPLayoutDetailsViewComponent>;
808
+
689
809
  /**
690
810
  * Registry of rendered page component instances by component key.
691
811
  * Used so page execute can delegate to the actual component instance in the view.
@@ -727,5 +847,5 @@ declare class AXPPageComponentRendererDirective implements OnInit, OnDestroy {
727
847
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<AXPPageComponentRendererDirective, "[axp-page-component-renderer]", never, { "componentKey": { "alias": "componentKey"; "required": true; "isSignal": true; }; "rootContext": { "alias": "rootContext"; "required": false; "isSignal": true; }; "pageConfig": { "alias": "pageConfig"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; }, { "componentReady": "componentReady"; }, never, never, true, never>;
728
848
  }
729
849
 
730
- export { AXPLayoutDetailsViewComponent, AXPLayoutDetailsViewViewModel, AXPPageComponentInstanceRegistryService, AXPPageComponentRendererDirective, AXPPageLayoutBase, AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPopupLayoutBase, AXPPopupLayoutBaseComponent, AXPPopupLayoutComponent };
731
- export type { AXPLayoutDetailsViewAction, AXPLayoutDetailsViewAdapter, AXPLayoutDetailsViewPage, AXPLayoutDetailsViewTabItem, AXPPageContentItem };
850
+ export { AXPLayoutDetailsViewComponent, AXPLayoutDetailsViewViewModel, AXPPageComponentInstanceRegistryService, AXPPageComponentRendererDirective, AXPPageLayoutBase, AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPopupLayoutBase, AXPPopupLayoutBaseComponent, AXPPopupLayoutComponent, axpDetailsViewCanDeactivateGuard, buildNotSavedPageBadge, getDetailsViewActionCommandBaseName, isDiscardCommand, resolveDetailsViewActionShortcuts, resolveDetailsViewFooterCommandShortcuts };
851
+ export type { AXPDetailsViewActionShortcut, AXPLayoutDetailsViewAction, AXPLayoutDetailsViewAdapter, AXPLayoutDetailsViewPage, AXPLayoutDetailsViewTabItem, AXPPageContentItem };