@acorex-platform/framework-client 0.0.10 → 0.0.15

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 (119) hide show
  1. package/fesm2022/acorex-platform-framework-client-auth.mjs +285 -50
  2. package/fesm2022/acorex-platform-framework-client-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-CbzOYCnI.mjs → acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs} +55 -36
  4. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs +29 -0
  6. package/fesm2022/acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-framework-client-common.mjs +1576 -408
  8. package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-framework-client-core.mjs +561 -25
  10. package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs +154 -42
  12. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs.map +1 -1
  13. package/fesm2022/{acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CWVU3wXL.mjs → acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CjnQ9hAJ.mjs} +7 -7
  14. package/fesm2022/acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CjnQ9hAJ.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-fFen8w8M.mjs +77 -0
  16. package/fesm2022/acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-fFen8w8M.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-framework-client-layout-components.mjs +2378 -1274
  18. package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
  19. package/fesm2022/acorex-platform-framework-client-layout-designer.mjs +92 -84
  20. package/fesm2022/acorex-platform-framework-client-layout-designer.mjs.map +1 -1
  21. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-CxBxxpmA.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-BzUM-JMC.mjs} +3 -3
  22. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-CxBxxpmA.mjs.map → acorex-platform-framework-client-layout-entity-attachments-page.component-BzUM-JMC.mjs.map} +1 -1
  23. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-l0JAHKIH.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-Ci_CTFtq.mjs} +6 -6
  24. package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-Ci_CTFtq.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-framework-client-layout-entity-gallery-page.component-DmiB__JR.mjs +256 -0
  26. package/fesm2022/acorex-platform-framework-client-layout-entity-gallery-page.component-DmiB__JR.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +17599 -17114
  28. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs.map +1 -1
  29. package/fesm2022/acorex-platform-framework-client-layout-views.mjs +120 -70
  30. package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
  31. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +302 -263
  32. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
  33. package/fesm2022/{acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CpkWwygb.mjs → acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CIwpAXbL.mjs} +2 -2
  34. package/fesm2022/acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CIwpAXbL.mjs.map +1 -0
  35. package/fesm2022/{acorex-platform-framework-client-layout-widgets-image-preview.popup-C_EPAvCU.mjs → acorex-platform-framework-client-layout-widgets-image-preview.popup-CazpERbX.mjs} +3 -3
  36. package/fesm2022/acorex-platform-framework-client-layout-widgets-image-preview.popup-CazpERbX.mjs.map +1 -0
  37. package/fesm2022/{acorex-platform-framework-client-layout-widgets-page-widget-designer.component-CmtTq2Mt.mjs → acorex-platform-framework-client-layout-widgets-page-widget-designer.component-DKkJi40s.mjs} +5 -5
  38. package/fesm2022/{acorex-platform-framework-client-layout-widgets-page-widget-designer.component-CmtTq2Mt.mjs.map → acorex-platform-framework-client-layout-widgets-page-widget-designer.component-DKkJi40s.mjs.map} +1 -1
  39. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DSx0E3NV.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DtYZfA79.mjs} +3 -3
  40. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DSx0E3NV.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DtYZfA79.mjs.map} +1 -1
  41. package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-DdfcGV1C.mjs → acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-nMUtxAyy.mjs} +10 -10
  42. package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-nMUtxAyy.mjs.map +1 -0
  43. package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-CntopmDS.mjs → acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-DvUSZ4hJ.mjs} +5 -5
  44. package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-DvUSZ4hJ.mjs.map +1 -0
  45. package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BihIfkZW.mjs +61 -0
  46. package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BihIfkZW.mjs.map +1 -0
  47. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +2218 -1504
  48. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs.map +1 -1
  49. package/fesm2022/acorex-platform-framework-client-realtime.mjs +227 -0
  50. package/fesm2022/acorex-platform-framework-client-realtime.mjs.map +1 -0
  51. package/fesm2022/acorex-platform-framework-client-runtime.mjs +201 -13
  52. package/fesm2022/acorex-platform-framework-client-runtime.mjs.map +1 -1
  53. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-QIFX11dh.mjs +158 -0
  54. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-QIFX11dh.mjs.map +1 -0
  55. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BBdellyL.mjs +119 -0
  56. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BBdellyL.mjs.map +1 -0
  57. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-single-view.component-D1a7UI71.mjs → acorex-platform-framework-client-themes-default-entity-master-single-view.component-CIf1VWNW.mjs} +5 -6
  58. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-CIf1VWNW.mjs.map +1 -0
  59. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-C_czT_JC.mjs +48 -0
  60. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-C_czT_JC.mjs.map +1 -0
  61. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-C2Wu0YtF.mjs +42 -0
  62. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-C2Wu0YtF.mjs.map +1 -0
  63. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DRz-kVsT.mjs +19 -0
  64. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DRz-kVsT.mjs.map +1 -0
  65. package/fesm2022/acorex-platform-framework-client-themes-default.mjs +123 -96
  66. package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
  67. package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-column.component-CXSGiTCK.mjs → acorex-platform-framework-client-themes-shared-icon-chooser-column.component-Ci_oH7NE.mjs} +3 -3
  68. package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-column.component-Ci_oH7NE.mjs.map +1 -0
  69. package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-view.component-BY5clQ1J.mjs → acorex-platform-framework-client-themes-shared-icon-chooser-view.component-Lb1G2Xz7.mjs} +3 -3
  70. package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-view.component-Lb1G2Xz7.mjs.map +1 -0
  71. package/fesm2022/{acorex-platform-framework-client-themes-shared-settings.provider-DEL2YOTP.mjs → acorex-platform-framework-client-themes-shared-settings.provider-D2XPkc71.mjs} +11 -2
  72. package/fesm2022/acorex-platform-framework-client-themes-shared-settings.provider-D2XPkc71.mjs.map +1 -0
  73. package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-BXl8u4Yp.mjs → acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-D4ubvFYf.mjs} +7 -7
  74. package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-D4ubvFYf.mjs.map +1 -0
  75. package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-i2sOOkVj.mjs → acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-Br8j_BF_.mjs} +7 -7
  76. package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-Br8j_BF_.mjs.map +1 -0
  77. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +124 -112
  78. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
  79. package/fesm2022/acorex-platform-framework-client-workflow.mjs +26 -483
  80. package/fesm2022/acorex-platform-framework-client-workflow.mjs.map +1 -1
  81. package/package.json +14 -9
  82. package/types/acorex-platform-framework-client-auth.d.ts +76 -5
  83. package/types/acorex-platform-framework-client-common.d.ts +499 -129
  84. package/types/acorex-platform-framework-client-core.d.ts +291 -10
  85. package/types/acorex-platform-framework-client-layout-builder.d.ts +81 -31
  86. package/types/acorex-platform-framework-client-layout-components.d.ts +295 -41
  87. package/types/acorex-platform-framework-client-layout-entity.d.ts +1895 -1743
  88. package/types/acorex-platform-framework-client-layout-views.d.ts +8 -18
  89. package/types/acorex-platform-framework-client-layout-widget-core.d.ts +20 -35
  90. package/types/acorex-platform-framework-client-layout-widgets.d.ts +167 -33
  91. package/types/acorex-platform-framework-client-realtime.d.ts +100 -0
  92. package/types/acorex-platform-framework-client-runtime.d.ts +60 -2
  93. package/types/acorex-platform-framework-client-themes-default.d.ts +4 -48
  94. package/types/acorex-platform-framework-client-workflow.d.ts +16 -127
  95. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-CbzOYCnI.mjs.map +0 -1
  96. package/fesm2022/acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CWVU3wXL.mjs.map +0 -1
  97. package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-l0JAHKIH.mjs.map +0 -1
  98. package/fesm2022/acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CpkWwygb.mjs.map +0 -1
  99. package/fesm2022/acorex-platform-framework-client-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +0 -1
  100. package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-DdfcGV1C.mjs.map +0 -1
  101. package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-CntopmDS.mjs.map +0 -1
  102. package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-B5kSWxGk.mjs +0 -34
  103. package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-B5kSWxGk.mjs.map +0 -1
  104. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DnTHwsDJ.mjs +0 -160
  105. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DnTHwsDJ.mjs.map +0 -1
  106. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BpR9g6QS.mjs +0 -121
  107. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BpR9g6QS.mjs.map +0 -1
  108. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-D1a7UI71.mjs.map +0 -1
  109. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-D--_MIar.mjs +0 -48
  110. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-D--_MIar.mjs.map +0 -1
  111. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-Byyqk8pH.mjs +0 -42
  112. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-Byyqk8pH.mjs.map +0 -1
  113. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DR6G8gPC.mjs +0 -19
  114. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DR6G8gPC.mjs.map +0 -1
  115. package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-column.component-CXSGiTCK.mjs.map +0 -1
  116. package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-view.component-BY5clQ1J.mjs.map +0 -1
  117. package/fesm2022/acorex-platform-framework-client-themes-shared-settings.provider-DEL2YOTP.mjs.map +0 -1
  118. package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-BXl8u4Yp.mjs.map +0 -1
  119. package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-i2sOOkVj.mjs.map +0 -1
@@ -2,13 +2,13 @@ import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, Injectable, Injector, signal, DestroyRef, makeEnvironmentProviders, NgModule, computed, input, output, ViewEncapsulation, ChangeDetectionStrategy, Component, viewChild, effect, untracked, ErrorHandler, EventEmitter, Input, Output, Directive, Inject, runInInjectionContext, model, linkedSignal, afterNextRender } from '@angular/core';
3
3
  import { Router, NavigationEnd, NavigationStart, ROUTES, RedirectCommand, RouterModule } from '@angular/router';
4
4
  import { AXPSessionService, AXPSessionStatus, AXPAuthGuard } from '@acorex-platform/framework-client/auth';
5
- import { combineLatest, map, distinctUntilChanged, Subject, ReplaySubject, firstValueFrom, filter, take, merge as merge$1, first, switchMap, from } from 'rxjs';
5
+ import { combineLatest, map, distinctUntilChanged, Subject, ReplaySubject, firstValueFrom, filter, take, merge as merge$1, first, switchMap, from, debounceTime } from 'rxjs';
6
6
  import { unwrapValueProperty, coerceUnknownToDate, coerceUnknownToFiniteNumber, coerceUnknownToBoolean, coerceUnknownToTrimmedString, AXPPlatformScope, AXPRegionalSetting, AXPWidgetsCatalog, AXPKeyboardShortcutPriority, AXPSystemActionType, isLocaleStringMap } from '@acorex-platform/framework-shared/core';
7
7
  import * as i3$1 from '@acorex-platform/framework-client/core';
8
- import { AXPDebugService, AXPBroadcastEventService, objectKeyValueTransforms, AXPDataGenerator, AXPKeyboardShortcutRegistry, normalizeKeyboardShortcuts, AXPDeviceService, chordToKbdItemKeys, hasForegroundOverlayLayer, AXPExpressionEvaluatorService, AXPContextEvalFactory, AXPModuleManifestModule, AXPComponentSlotModule, AXPAppStartUpProvider, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXPHookService } from '@acorex-platform/framework-client/core';
8
+ import { AXPDebugService, AXPBroadcastEventService, AXP_SETTINGS_DEFINITION_DIALOG_OPENER, objectKeyValueTransforms, AXPDataGenerator, AXPKeyboardShortcutRegistry, normalizeKeyboardShortcuts, AXPDeviceService, chordToKbdItemKeys, hasForegroundOverlayLayer, AXPExpressionEvaluatorService, AXPContextEvalFactory, AXPModuleManifestModule, AXPComponentSlotModule, AXPAppStartUpProvider, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_LOGO_IMAGE_SRC_RESOLVER, AXPHookService } from '@acorex-platform/framework-client/core';
9
9
  export { AXPDebugService } from '@acorex-platform/framework-client/core';
10
- import { merge, sortBy, isString, toString, defaultTo, isEmpty, cloneDeep, get, isNumber, isNil, isObject, isPlainObject, omit } from 'lodash-es';
11
- import { AXPQueryService, AXPCommandService, AXPCommandExecutor } from '@acorex-platform/framework-client/runtime';
10
+ import { merge, sortBy, isString, toString, defaultTo, isEmpty, cloneDeep, get, isNumber, isNil, isObject, isPlainObject, omit, uniq } from 'lodash-es';
11
+ import { AXPQueryService, AXPCommandService, provideCommandSetups } from '@acorex-platform/framework-client/runtime';
12
12
  import Dexie from 'dexie';
13
13
  import { AXCalendarService, AXDateTimeModule } from '@acorex/core/date-time';
14
14
  import { AXDialogService } from '@acorex/components/dialog';
@@ -26,17 +26,18 @@ import { AXButtonModule } from '@acorex/components/button';
26
26
  import * as i3 from '@acorex/components/progress-bar';
27
27
  import { AXProgressBarModule } from '@acorex/components/progress-bar';
28
28
  import { filter as filter$1 } from 'rxjs/operators';
29
- import * as i4$2 from '@acorex-platform/framework-client/workflow';
30
- import { AXPWorkflowService, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowError, AXPWorkflowModule } from '@acorex-platform/framework-client/workflow';
31
29
  import { signalStore, withState, withMethods, patchState, withHooks } from '@ngrx/signals';
32
30
  import { AXPopupService, AXPopupModule } from '@acorex/components/popup';
33
- import { AXToastService, AXToastModule } from '@acorex/components/toast';
31
+ import { AXToastModule, AXToastService } from '@acorex/components/toast';
34
32
  import * as i2$1 from '@acorex/core/format';
35
33
  import { AXFormatService } from '@acorex/core/format';
34
+ import { HttpErrorResponse } from '@angular/common/http';
36
35
  import { AXKBDComponent, AXKBDItemComponent } from '@acorex/components/kbd';
37
36
  import { AXDataSource } from '@acorex/cdk/common';
38
37
  import { normalizeEntityDisplayTemplate, sanitizeResolvedEntityDisplayTitle, resolveEntityModifyRecordTitleTemplate, isMeaningfulEntityDisplayTitle, isUnresolvedEntityDisplayTemplate, ENTITY_ROW_POPUP_TITLE_OPTION, ENTITY_ROW_TITLE_TEMPLATE_OPTION, ENTITY_LAYOUT_SINGLE_TITLE_PATH, buildEntitySearchTitleContext, resolveEntityRowTitleTemplate } from '@acorex-platform/framework-shared/entity';
39
- import { AXFileService } from '@acorex/core/file';
38
+ import * as i1$1 from '@acorex/core/file';
39
+ import { getFileExtension, resolveFileTypeExtension, resolveFileTypeOpen, runFileTypeOpen, AX_FILE_TYPE_METADATA_PURPOSE, getFileTypePurposes, AXFileTypeRegistryService, AXFileModule } from '@acorex/core/file';
40
+ export { AX_FILE_TYPE_METADATA_PURPOSE, filterFileTypesByPurpose, getFileTypePurposes } from '@acorex/core/file';
40
41
  import { AXCheckBoxModule } from '@acorex/components/check-box';
41
42
  import * as i6 from '@acorex/components/color-box';
42
43
  import { AXColorBoxModule } from '@acorex/components/color-box';
@@ -46,8 +47,10 @@ import * as i2$2 from '@acorex/components/number-box';
46
47
  import { AXNumberBoxModule } from '@acorex/components/number-box';
47
48
  import { AXBasePageComponent } from '@acorex/components/page';
48
49
  import { AXTextBoxModule } from '@acorex/components/text-box';
49
- import * as i1$1 from '@angular/forms';
50
+ import * as i1$2 from '@angular/forms';
50
51
  import { FormsModule } from '@angular/forms';
52
+ import { defineCommand, AXP_COMMAND_DEFINITION_CATEGORY_PLATFORM } from '@acorex-platform/framework-shared/runtime';
53
+ import { createWorkFlowEvent } from '@acorex-platform/framework-client/workflow';
51
54
 
52
55
  //#region ---- Datasource keys ----
53
56
  /** Platform common datasource registry names. */
@@ -372,6 +375,29 @@ const AXP_HOME_PAGE_DEFAULT_KEY = new InjectionToken('AXP_HOME_PAGE_DEFAULT_KEY'
372
375
  factory: () => 'home'
373
376
  });
374
377
 
378
+ /** Strict descendants allowed to override a setting owned at `scope`. */
379
+ const AXP_SETTING_SCOPE_DESCENDANTS = {
380
+ P: ['T', 'U'],
381
+ T: ['U'],
382
+ U: [],
383
+ };
384
+ function normalizeOverridableAt(ownerScope, overridableAt) {
385
+ const scopes = overridableAt ?? [];
386
+ const allowed = AXP_SETTING_SCOPE_DESCENDANTS[ownerScope];
387
+ for (const scope of scopes) {
388
+ if (!allowed.includes(scope)) {
389
+ throw new Error(`Setting at scope "${ownerScope}" cannot be overridable at "${scope}". Allowed: [${allowed.join(', ')}].`);
390
+ }
391
+ }
392
+ return scopes;
393
+ }
394
+ function isSettingVisibleOnScope(setting, pageScope) {
395
+ if (setting.scope === pageScope) {
396
+ return true;
397
+ }
398
+ return (setting.overridableAt ?? []).includes(pageScope);
399
+ }
400
+
375
401
  var AXPCommonSettings;
376
402
  (function (AXPCommonSettings) {
377
403
  AXPCommonSettings["EnableOperationToasts"] = "Common:Setting:Notifications.EnableOperationToasts";
@@ -387,6 +413,8 @@ var AXPCommonSettings;
387
413
  AXPCommonSettings["EntityListPersistenceMode"] = "Common:Setting:Entity.ListPersistenceMode";
388
414
  AXPCommonSettings["NavigationMode"] = "Common:Setting:Navigation.Mode";
389
415
  AXPCommonSettings["MaxOpenTabs"] = "Common:Setting:Navigation.MaxOpenTabs";
416
+ /** When true with entity list quick-search input, filters emit {@link AXP_QUERY_QUICK_SEARCH_FIELD} instead of inline OR. */
417
+ AXPCommonSettings["QuickSearchEnabled"] = "Common:Setting:Entity.QuickSearchEnabled";
390
418
  })(AXPCommonSettings || (AXPCommonSettings = {}));
391
419
 
392
420
  class AXPSettingDefinitionProviderContext {
@@ -478,6 +506,7 @@ class AXPSettingDefinitionSectionBuilder {
478
506
  this.section = section;
479
507
  }
480
508
  addSetting(setting) {
509
+ const scope = setting.scope ?? 'P';
481
510
  const newSetting = {
482
511
  name: setting.key,
483
512
  title: setting.title,
@@ -485,10 +514,11 @@ class AXPSettingDefinitionSectionBuilder {
485
514
  searchTagKeys: setting.searchTagKeys,
486
515
  isRequired: setting.isRequired ?? false,
487
516
  isInherited: setting.isInherited ?? false,
517
+ overridableAt: normalizeOverridableAt(scope, setting.overridableAt),
488
518
  isEncrypted: setting.isEncrypted ?? false,
489
519
  requiresPageRefresh: setting.requiresPageRefresh ?? false,
490
520
  defaultValue: setting.defaultValue,
491
- scope: setting.scope ?? 'P',
521
+ scope,
492
522
  layout: setting.widget.layout,
493
523
  widget: {
494
524
  type: setting.widget.type,
@@ -506,6 +536,13 @@ class AXPSettingDefinitionSectionBuilder {
506
536
  this.section.settings.push(newSetting);
507
537
  return this;
508
538
  }
539
+ addAction(action) {
540
+ if (!this.section.actions) {
541
+ this.section.actions = [];
542
+ }
543
+ this.section.actions.push(action);
544
+ return this;
545
+ }
509
546
  endSection() {
510
547
  return this.groupBuilder;
511
548
  }
@@ -517,28 +554,48 @@ class AXPSettingDefinitionProviderService {
517
554
  constructor() {
518
555
  this.providers = inject(AXP_SETTING_DEFINITION_PROVIDER, { optional: true });
519
556
  this.cache = null;
557
+ this.loadPromise = null;
520
558
  }
521
559
  async load() {
560
+ if (this.cache) {
561
+ return;
562
+ }
563
+ if (!this.loadPromise) {
564
+ this.loadPromise = this.loadDefinitions().finally(() => {
565
+ this.loadPromise = null;
566
+ });
567
+ }
568
+ await this.loadPromise;
569
+ }
570
+ async loadDefinitions() {
522
571
  if (this.cache) {
523
572
  return;
524
573
  }
525
574
  const context = new AXPSettingDefinitionProviderContext();
526
- // Load providers from DI tokens
527
- if (Array.isArray(this.providers)) {
528
- for (const provider of this.providers) {
575
+ // Load providers from DI tokens — isolate failures so one provider cannot block bootstrap.
576
+ const providerList = this.normalizeProviders(this.providers);
577
+ for (const provider of providerList) {
578
+ try {
529
579
  if (provider instanceof Promise) {
530
- // If provider is a promise, resolve it
531
580
  const resolvedProvider = await provider;
532
581
  await resolvedProvider.provide(context);
533
582
  }
534
583
  else {
535
- // If provider is a direct instance, use it directly
536
584
  await provider.provide(context);
537
585
  }
538
586
  }
587
+ catch (error) {
588
+ console.warn('Setting definition provider failed; continuing with remaining providers', error);
589
+ }
539
590
  }
540
591
  this.cache = context.getGroups();
541
592
  }
593
+ normalizeProviders(providers) {
594
+ if (!providers) {
595
+ return [];
596
+ }
597
+ return Array.isArray(providers) ? providers : [providers];
598
+ }
542
599
  async reload() {
543
600
  this.cache = null;
544
601
  await this.load();
@@ -551,30 +608,14 @@ class AXPSettingDefinitionProviderService {
551
608
  if (!this.cache) {
552
609
  return [];
553
610
  }
554
- const scopeOrder = ['P', 'T', 'U']; // Scopes hierarchy in ascending order
555
611
  const filterByScope = (groups, currentScope) => {
556
- const currentScopeIndex = scopeOrder.indexOf(currentScope);
557
612
  return groups
558
613
  .map((group) => ({
559
614
  ...group,
560
615
  sections: group.sections
561
616
  .map((section) => ({
562
617
  ...section,
563
- settings: section.settings.filter((setting) => {
564
- const settingScopeIndex = scopeOrder.indexOf(setting.scope);
565
- // Include settings where:
566
- // 1. The scope matches the requested scope.
567
- if (setting.scope === currentScope)
568
- return true;
569
- // 2. The setting scope is higher (closer to 'U') and is inherited.
570
- if (setting.isInherited &&
571
- settingScopeIndex > currentScopeIndex // Higher scope
572
- ) {
573
- return true;
574
- }
575
- // 3. Exclude settings with a lower or irrelevant scope.
576
- return false;
577
- }),
618
+ settings: section.settings.filter((setting) => isSettingVisibleOnScope(setting, currentScope)),
578
619
  }))
579
620
  .filter((section) => section.settings.length > 0), // Keep only sections with settings
580
621
  groups: filterByScope(group.groups, currentScope), // Recursively filter nested groups
@@ -664,6 +705,53 @@ class AXPSettingDefinitionProviderService {
664
705
  findGroup(scope, groupName) {
665
706
  return this.searchRecursive(this.getList(scope), groupName, []); // Initialize with an empty breadcrumb
666
707
  }
708
+ async findSection(scope, sectionName, groupName) {
709
+ await this.load();
710
+ return this.searchSectionRecursive(this.getList(scope), sectionName, groupName);
711
+ }
712
+ async collectSettingsByKeys(scope, keys) {
713
+ if (!keys.length) {
714
+ return [];
715
+ }
716
+ await this.load();
717
+ const keySet = new Set(keys);
718
+ const found = new Map();
719
+ const walk = (groups) => {
720
+ for (const group of groups) {
721
+ for (const section of group.sections) {
722
+ for (const setting of section.settings) {
723
+ if (keySet.has(setting.name) && !found.has(setting.name)) {
724
+ found.set(setting.name, setting);
725
+ }
726
+ }
727
+ }
728
+ walk(group.groups);
729
+ }
730
+ };
731
+ walk(this.getList(scope));
732
+ return keys.map((key) => found.get(key)).filter((setting) => !!setting);
733
+ }
734
+ searchSectionRecursive(groups, sectionName, groupName) {
735
+ for (const group of groups) {
736
+ if (groupName && group.name !== groupName) {
737
+ const nested = this.searchSectionRecursive(group.groups, sectionName, groupName);
738
+ if (nested) {
739
+ return nested;
740
+ }
741
+ continue;
742
+ }
743
+ for (const section of group.sections) {
744
+ if (section.name === sectionName) {
745
+ return { group, section };
746
+ }
747
+ }
748
+ const nested = this.searchSectionRecursive(group.groups, sectionName, groupName);
749
+ if (nested) {
750
+ return nested;
751
+ }
752
+ }
753
+ return null;
754
+ }
667
755
  searchRecursive(groups, groupName, breadcrumb) {
668
756
  for (const group of groups) {
669
757
  const currentBreadcrumb = [
@@ -807,7 +895,6 @@ function coerceAXPSettingRawValue(raw, kind) {
807
895
  //#endregion
808
896
 
809
897
  const AXP_SETTINGS_SYNC_KEYS = new InjectionToken('AXP_SETTINGS_SYNC_KEYS');
810
- //#endregion
811
898
 
812
899
  //#region ---- Settings bulk sync (query + command) ----
813
900
  class AXPSettingsBulkSyncService {
@@ -888,9 +975,13 @@ function traceSettingsLocalPersist(scope, payload) {
888
975
  keys: payload.keys,
889
976
  dirtyKeyCount: payload.dirtyKeyCount,
890
977
  flush: payload.flush,
891
- note: payload.flush
892
- ? 'IndexedDB updated — ServerSync flush runs immediately (flush: true)'
893
- : 'IndexedDB updated — dirty keys queued; ServerSync runs after debounce',
978
+ note: scope === AXPPlatformScope.User
979
+ ? payload.flush
980
+ ? 'IndexedDB updated — ServerSync flush runs immediately (flush: true)'
981
+ : 'IndexedDB updated — dirty keys queued; ServerSync runs after debounce'
982
+ : payload.flush
983
+ ? 'In-memory snapshot updated — ServerSync flush runs immediately (flush: true)'
984
+ : 'In-memory snapshot updated — dirty keys queued; ServerSync runs after debounce',
894
985
  }));
895
986
  }
896
987
  //#endregion
@@ -1040,9 +1131,20 @@ function createEmptyScopedSettingsSnapshot(id, scope) {
1040
1131
  retryAttempt: 0,
1041
1132
  };
1042
1133
  }
1134
+ /** Only user-scoped settings are persisted in IndexedDB; platform/tenant stay in memory. */
1135
+ function shouldPersistSettingsInIndexedDb(scope) {
1136
+ return scope === AXPPlatformScope.User;
1137
+ }
1138
+ /** Removes legacy platform/tenant rows written before user-only IndexedDB persistence. */
1139
+ async function purgeNonUserScopedSettingsSnapshots() {
1140
+ await axpSettingsIndexedDb.scoped_snapshots
1141
+ .where('scope')
1142
+ .anyOf([AXPPlatformScope.Platform, AXPPlatformScope.Tenant])
1143
+ .delete();
1144
+ }
1043
1145
  //#endregion
1044
1146
 
1045
- //#region ---- IndexedDB + bulk API setting value provider ----
1147
+ //#region ---- Scoped settings provider (IndexedDB for user scope only) ----
1046
1148
  class AXPIndexedDbSettingValueProvider {
1047
1149
  constructor(_scope, injector) {
1048
1150
  this._scope = _scope;
@@ -1075,7 +1177,9 @@ class AXPIndexedDbSettingValueProvider {
1075
1177
  return;
1076
1178
  }
1077
1179
  if (status === AXPSessionStatus.Authorized || status === AXPSessionStatus.Authenticated) {
1078
- this.tryBindSessionContext();
1180
+ if (this.canSyncScopeWithServer()) {
1181
+ this.tryBindSessionContext();
1182
+ }
1079
1183
  }
1080
1184
  });
1081
1185
  if (this._scope === AXPPlatformScope.User) {
@@ -1160,7 +1264,7 @@ class AXPIndexedDbSettingValueProvider {
1160
1264
  await this.revalidateNow();
1161
1265
  }
1162
1266
  async revalidateIfNeeded() {
1163
- if (!this.snapshotId) {
1267
+ if (!this.snapshotId || !this.canSyncScopeWithServer()) {
1164
1268
  return;
1165
1269
  }
1166
1270
  if (!this.snapshot) {
@@ -1184,13 +1288,15 @@ class AXPIndexedDbSettingValueProvider {
1184
1288
  if (!expectedSnapshotId) {
1185
1289
  return;
1186
1290
  }
1187
- const existing = await axpSettingsIndexedDb.scoped_snapshots.get(expectedSnapshotId);
1291
+ const existing = shouldPersistSettingsInIndexedDb(this._scope)
1292
+ ? await axpSettingsIndexedDb.scoped_snapshots.get(expectedSnapshotId)
1293
+ : undefined;
1188
1294
  if (this.snapshotId !== expectedSnapshotId) {
1189
1295
  return;
1190
1296
  }
1191
1297
  this.snapshot = existing ?? createEmptyScopedSettingsSnapshot(expectedSnapshotId, this._scope);
1192
1298
  const needsInitialSync = isEmpty(this.snapshot.values);
1193
- if (needsInitialSync || this.shouldRevalidate(this.snapshot)) {
1299
+ if (this.canSyncScopeWithServer() && (needsInitialSync || this.shouldRevalidate(this.snapshot))) {
1194
1300
  await this.revalidateNow();
1195
1301
  }
1196
1302
  this.hydrated = true;
@@ -1237,6 +1343,9 @@ class AXPIndexedDbSettingValueProvider {
1237
1343
  if (this._scope === AXPPlatformScope.Platform) {
1238
1344
  return;
1239
1345
  }
1346
+ if (!this.canSyncScopeWithServer()) {
1347
+ return;
1348
+ }
1240
1349
  if (this._scope === AXPPlatformScope.User && (!this.sessionService.user?.id || !this.sessionService.tenant?.id)) {
1241
1350
  return;
1242
1351
  }
@@ -1269,12 +1378,24 @@ class AXPIndexedDbSettingValueProvider {
1269
1378
  await this.persistSnapshotRecord(this.snapshot);
1270
1379
  }
1271
1380
  async persistSnapshotRecord(snapshot) {
1381
+ if (!shouldPersistSettingsInIndexedDb(snapshot.scope)) {
1382
+ return;
1383
+ }
1272
1384
  await axpSettingsIndexedDb.scoped_snapshots.put(snapshot);
1273
1385
  }
1274
1386
  toSettingValues(values) {
1275
1387
  return Object.entries(values).map(([key, value]) => ({ key, value }));
1276
1388
  }
1277
1389
  //#endregion
1390
+ //#region ---- Server sync eligibility ----
1391
+ /** Platform settings are public; tenant/user bulk sync requires a Bearer token. */
1392
+ canSyncScopeWithServer() {
1393
+ if (this._scope === AXPPlatformScope.Platform) {
1394
+ return true;
1395
+ }
1396
+ return Boolean(this.sessionService.getToken());
1397
+ }
1398
+ //#endregion
1278
1399
  //#region ---- Revalidation ----
1279
1400
  shouldRevalidate(record) {
1280
1401
  const ttl = AXP_SETTINGS_SYNC_TTL_MS[this._scope];
@@ -1304,7 +1425,7 @@ class AXPIndexedDbSettingValueProvider {
1304
1425
  }
1305
1426
  async doRevalidate() {
1306
1427
  const snapshot = this.snapshot;
1307
- if (!snapshot) {
1428
+ if (!snapshot || !this.canSyncScopeWithServer()) {
1308
1429
  return;
1309
1430
  }
1310
1431
  try {
@@ -1384,7 +1505,7 @@ class AXPIndexedDbSettingValueProvider {
1384
1505
  }
1385
1506
  async doFlush() {
1386
1507
  const snapshot = this.snapshot;
1387
- if (!snapshot || isEmpty(snapshot.dirty)) {
1508
+ if (!snapshot || isEmpty(snapshot.dirty) || !this.canSyncScopeWithServer()) {
1388
1509
  return;
1389
1510
  }
1390
1511
  const payload = { ...snapshot.dirty };
@@ -1461,6 +1582,7 @@ class AXPIndexedDbSettingValueProvider {
1461
1582
 
1462
1583
  //#region ---- Provider factories ----
1463
1584
  function createIndexedDbSettingValueProviders(injector) {
1585
+ void purgeNonUserScopedSettingsSnapshots();
1464
1586
  return [
1465
1587
  new AXPIndexedDbSettingValueProvider(AXPPlatformScope.Platform, injector),
1466
1588
  new AXPIndexedDbSettingValueProvider(AXPPlatformScope.Tenant, injector),
@@ -1589,6 +1711,9 @@ class AXPSettingsService {
1589
1711
  this.clearScopedCache(AXPPlatformScope.User);
1590
1712
  return;
1591
1713
  }
1714
+ if (!this.shouldLoadProvider(AXPPlatformScope.User)) {
1715
+ return;
1716
+ }
1592
1717
  await this.reload(AXPPlatformScope.User, 'session-user-changed');
1593
1718
  });
1594
1719
  this.sessionService.tenant$
@@ -1602,6 +1727,9 @@ class AXPSettingsService {
1602
1727
  this.clearScopedCache(AXPPlatformScope.Tenant);
1603
1728
  return;
1604
1729
  }
1730
+ if (!this.shouldLoadProvider(AXPPlatformScope.Tenant)) {
1731
+ return;
1732
+ }
1605
1733
  await this.reload(AXPPlatformScope.Tenant, 'session-tenant-changed');
1606
1734
  });
1607
1735
  if (typeof document !== 'undefined') {
@@ -1709,11 +1837,14 @@ class AXPSettingsService {
1709
1837
  throw error;
1710
1838
  }
1711
1839
  }
1712
- /** Platform always; tenant when selected; user when authenticated with tenant. */
1840
+ /** Platform always; tenant/user only when a Bearer token is present. */
1713
1841
  shouldLoadProvider(scope) {
1714
1842
  if (scope === AXPPlatformScope.Platform) {
1715
1843
  return true;
1716
1844
  }
1845
+ if (!this.sessionService.getToken()) {
1846
+ return false;
1847
+ }
1717
1848
  if (scope === AXPPlatformScope.Tenant) {
1718
1849
  return !!this.sessionService.tenant?.id;
1719
1850
  }
@@ -1754,6 +1885,24 @@ class AXPSettingsService {
1754
1885
  }
1755
1886
  return cloneDeep(effective);
1756
1887
  }
1888
+ /**
1889
+ * Synchronous read from the in-memory scope cache (User → Tenant → Platform).
1890
+ * Returns `undefined` when the key is not cached yet (e.g. before {@link load} completes).
1891
+ */
1892
+ peekCached(key) {
1893
+ const scopeOrder = [AXPPlatformScope.User, AXPPlatformScope.Tenant, AXPPlatformScope.Platform];
1894
+ for (const scope of scopeOrder) {
1895
+ const scopeCache = this.scopedSettingsCache.get(scope);
1896
+ if (!scopeCache?.has(key)) {
1897
+ continue;
1898
+ }
1899
+ const value = scopeCache.get(key);
1900
+ if (value !== undefined && value !== null) {
1901
+ return value;
1902
+ }
1903
+ }
1904
+ return undefined;
1905
+ }
1757
1906
  /**
1758
1907
  * Inherited settings at tenant/user scope may match the definition default while still being an explicit
1759
1908
  * override of a different parent value (e.g. tenant enables lock while platform default is disabled).
@@ -1833,6 +1982,51 @@ class AXPSettingsService {
1833
1982
  }
1834
1983
  return new ScopedSettingService(this, provider, this.scopedSettingsCache.get(scope), (s) => this.shouldLoadProvider(s));
1835
1984
  }
1985
+ /**
1986
+ * Opens a dialog to quick-edit a settings definition section using canonical widgets.
1987
+ */
1988
+ async showSectionPopup(options) {
1989
+ const definitionService = this.injector.get(AXPSettingDefinitionProviderService);
1990
+ const lookup = await definitionService.findSection(options.scope, options.section, options.group);
1991
+ if (!lookup) {
1992
+ return false;
1993
+ }
1994
+ const opener = this.injector.get(AXP_SETTINGS_DEFINITION_DIALOG_OPENER);
1995
+ const { openSettingsDefinitionDialog } = await import('./acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs');
1996
+ return openSettingsDefinitionDialog(this, opener, {
1997
+ scope: options.scope,
1998
+ sections: [lookup.section],
1999
+ title: options.title ?? lookup.section.title,
2000
+ description: options.description ?? lookup.section.description,
2001
+ size: options.size,
2002
+ });
2003
+ }
2004
+ /**
2005
+ * Opens a dialog to quick-edit one or more settings by key using their canonical widget definitions.
2006
+ */
2007
+ async showSettingsPopup(options) {
2008
+ const definitionService = this.injector.get(AXPSettingDefinitionProviderService);
2009
+ const settings = await definitionService.collectSettingsByKeys(options.scope, options.keys);
2010
+ if (!settings.length) {
2011
+ return false;
2012
+ }
2013
+ const opener = this.injector.get(AXP_SETTINGS_DEFINITION_DIALOG_OPENER);
2014
+ const { openSettingsDefinitionDialog } = await import('./acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs');
2015
+ return openSettingsDefinitionDialog(this, opener, {
2016
+ scope: options.scope,
2017
+ sections: [
2018
+ {
2019
+ name: 'quick-edit',
2020
+ title: options.title ?? '@settings-management:module.menus.root.title',
2021
+ description: options.description,
2022
+ settings,
2023
+ },
2024
+ ],
2025
+ title: options.title ?? '@settings-management:module.menus.root.title',
2026
+ description: options.description,
2027
+ size: options.size,
2028
+ });
2029
+ }
1836
2030
  /** Applies remote values into the in-memory scope cache and notifies listeners. */
1837
2031
  syncScopeCache(scope, values) {
1838
2032
  const scopeCache = this.scopedSettingsCache.get(scope);
@@ -2580,6 +2774,8 @@ function createUnsavedChangesCanDeactivateGuard() {
2580
2774
  }
2581
2775
  //#endregion
2582
2776
 
2777
+ //#endregion
2778
+
2583
2779
  var AXPHomePageSettings;
2584
2780
  (function (AXPHomePageSettings) {
2585
2781
  AXPHomePageSettings["UserHomePath"] = "Common:Setting:Startup.HomePage";
@@ -2730,6 +2926,17 @@ function provideDynamicHomePage() {
2730
2926
  ]);
2731
2927
  }
2732
2928
 
2929
+ //#region ---- Experience settings group ----
2930
+ /** Root Settings nav group for startup, widgets, notifications, and entity UX preferences. */
2931
+ const AXP_EXPERIENCE_SETTINGS_GROUP = 'experience';
2932
+ const AXP_EXPERIENCE_SETTINGS_SECTIONS = {
2933
+ Startup: 'startup',
2934
+ Widgets: 'widgets',
2935
+ Notifications: 'notifications',
2936
+ Entity: 'entity',
2937
+ };
2938
+ //#endregion
2939
+
2733
2940
  const I18N = '@general:settings';
2734
2941
  class AXPHomePageSettingProvider {
2735
2942
  constructor(injector) {
@@ -2742,16 +2949,14 @@ class AXPHomePageSettingProvider {
2742
2949
  if (list.length === 0) {
2743
2950
  return;
2744
2951
  }
2745
- // Define the 'General Settings' group
2746
2952
  context
2747
- .addGroup('general', `${I18N}.general.nav-title`, `${I18N}.general.description`, 'fa-light fa-palette', `${I18N}.general.title`, 1)
2748
- // Add the 'Startup' section
2749
- .addSection('startup', `${I18N}.general.startup.title`, `${I18N}.general.startup.description`)
2750
- // Add the 'Home Page' setting
2953
+ .addGroup(AXP_EXPERIENCE_SETTINGS_GROUP, `${I18N}.experience.nav-title`, `${I18N}.experience.description`, 'fa-light fa-wand-magic-sparkles', `${I18N}.experience.title`, 1)
2954
+ .addSection(AXP_EXPERIENCE_SETTINGS_SECTIONS.Startup, `${I18N}.experience.startup.title`, `${I18N}.experience.startup.description`)
2751
2955
  .addSetting({
2752
2956
  key: AXPHomePageSettings.UserHomePath,
2753
- title: `${I18N}.general.startup.home-page.title`,
2957
+ title: `${I18N}.experience.startup.home-page.title`,
2754
2958
  scope: AXPPlatformScope.User,
2959
+ overridableAt: [],
2755
2960
  isInherited: true,
2756
2961
  defaultValue: this.defaultHomePageKey || list[0].id,
2757
2962
  valueTransforms: objectKeyValueTransforms('id'),
@@ -2763,11 +2968,11 @@ class AXPHomePageSettingProvider {
2763
2968
  dataSource: list,
2764
2969
  },
2765
2970
  },
2766
- description: `${I18N}.general.startup.home-page.description`,
2971
+ description: `${I18N}.experience.startup.home-page.description`,
2767
2972
  })
2768
- // End the 'Startup' section
2769
2973
  .endSection()
2770
- // End the 'General Settings' group
2974
+ .addSection(AXP_EXPERIENCE_SETTINGS_SECTIONS.Widgets, `${I18N}.experience.widgets.title`, `${I18N}.experience.widgets.description`)
2975
+ .endSection()
2771
2976
  .endGroup();
2772
2977
  }
2773
2978
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageSettingProvider, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -3687,11 +3892,11 @@ class AXPBackgroundOperationItemComponent {
3687
3892
  return this.pendingAction() === action;
3688
3893
  }
3689
3894
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3690
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationItemComponent, isStandalone: true, selector: "axp-background-operation-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { actionCompleted: "actionCompleted", itemClicked: "itemClicked" }, ngImport: i0, template: "<article\n class=\"operation-item\"\n [class]=\"statusClass()\"\n [class.--clickable]=\"isClickable()\"\n (click)=\"onItemClick()\"\n>\n <div class=\"operation-item__body\">\n <div class=\"operation-item__header\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__summary\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n\n @if (showMetaRow()) {\n <div class=\"operation-item__meta\">\n <div class=\"operation-item__meta-content\">\n @if (data().statusText) {\n <p class=\"operation-item__status-text\">{{ data().statusText }}</p>\n }\n\n @if (data().currentStep) {\n <span class=\"operation-item__step\">\n {{ '@general:background-operation.step' | translate | async }} {{ data().currentStep }}\n </span>\n }\n </div>\n\n @if (actions().length > 0) {\n <footer class=\"operation-item__actions\" (click)=\"$event.stopPropagation()\">\n @for (action of actions(); track action) {\n <ax-button\n class=\"ax-xs\"\n [look]=\"actionButtonLook(action)\"\n [color]=\"actionButtonColor(action)\"\n [text]=\"(actionLabelKey(action) | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled(action) || isActionLoading(action)\"\n (onClick)=\"onAction(action)\"\n ></ax-button>\n }\n </footer>\n }\n </div>\n }\n\n @if (showProgressBar()) {\n <ax-progress-bar\n [progress]=\"progressValue()\"\n [mode]=\"progressMode()\"\n [color]=\"progressColor()\"\n [style.height.px]=\"4\"\n ></ax-progress-bar>\n }\n\n @if (showError()) {\n <p class=\"operation-item__error\" role=\"alert\">{{ data().error!.message }}</p>\n }\n </div>\n </div>\n </div>\n</article>\n", styles: ["axp-background-operation-item{display:block}.operation-item{position:relative;overflow:hidden;border-radius:.375rem;border-width:1px;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;animation-duration:.2s;border-color:rgb(var(--ax-sys-color-border-lighter-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.operation-item.--clickable{cursor:pointer}@media(hover:hover){.operation-item.--clickable:hover{border-color:rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface))}}.operation-item.--failed{border-color:rgb(var(--ax-sys-color-border-danger-surface))}.operation-item__body{display:flex;flex-direction:column;gap:.5rem;padding:.75rem}.operation-item__header{display:flex;align-items:center;gap:.75rem}.operation-item__status-icon{margin-top:.125rem;flex-shrink:0;font-size:1.5rem;line-height:2rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500))}.operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500))}.operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500))}.operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500))}.operation-item__summary{display:flex;min-width:0px;flex:1 1 0%;flex-direction:column;gap:.25rem}.operation-item__title{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;text-align:start;font-size:.875rem;line-height:1.25rem;font-weight:500;line-height:1.375;color:rgb(var(--ax-sys-color-on-surface))}.operation-item__meta{display:flex;align-items:center;justify-content:space-between;gap:.5rem}.operation-item__meta-content{display:flex;min-width:0px;flex:1 1 0%;flex-direction:column;gap:.125rem}.operation-item__status-text{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;text-align:start;font-size:.75rem;line-height:1rem;line-height:1.625;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__step{display:inline-block;font-size:.6875rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__error{margin:0;border-radius:.375rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;line-height:1.625;background:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.operation-item__actions{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:.25rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.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: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXProgressBarModule }, { kind: "component", type: i3.AXProgressBarComponent, selector: "ax-progress-bar", inputs: ["color", "mode", "progress", "height"], outputs: ["ValueChange", "sizeChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
3895
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationItemComponent, isStandalone: true, selector: "axp-background-operation-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { actionCompleted: "actionCompleted", itemClicked: "itemClicked" }, ngImport: i0, template: "<article\n class=\"operation-item\"\n [class]=\"statusClass()\"\n [class.--clickable]=\"isClickable()\"\n (click)=\"onItemClick()\"\n>\n <div class=\"operation-item__body\">\n <div class=\"operation-item__header\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__summary\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n\n @if (showMetaRow()) {\n <div class=\"operation-item__meta\">\n <div class=\"operation-item__meta-content\">\n @if (data().statusText) {\n <p class=\"operation-item__status-text\">\n {{ data().statusText }}\n </p>\n }\n\n @if (data().currentStep) {\n <span class=\"operation-item__step\">\n {{\n '@general:background-operation.step' | translate | async\n }}\n {{ data().currentStep }}\n </span>\n }\n </div>\n\n @if (actions().length > 0) {\n <footer\n class=\"operation-item__actions\"\n (click)=\"$event.stopPropagation()\"\n >\n @for (action of actions(); track action) {\n <ax-button\n class=\"ax-sm\"\n [look]=\"actionButtonLook(action)\"\n [color]=\"actionButtonColor(action)\"\n [text]=\"(actionLabelKey(action) | translate | async) ?? ''\"\n [disabled]=\"\n isActionDisabled(action) || isActionLoading(action)\n \"\n (onClick)=\"onAction(action)\"\n ></ax-button>\n }\n </footer>\n }\n </div>\n }\n\n @if (showProgressBar()) {\n <ax-progress-bar\n [progress]=\"progressValue()\"\n [mode]=\"progressMode()\"\n [color]=\"progressColor()\"\n [style.height.px]=\"4\"\n ></ax-progress-bar>\n }\n\n @if (showError()) {\n <p class=\"operation-item__error\" role=\"alert\">\n {{ data().error!.message }}\n </p>\n }\n </div>\n </div>\n </div>\n</article>\n", styles: ["@layer properties;axp-background-operation-item{display:block}.operation-item{position:relative;overflow:hidden;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s;border-color:rgb(var(--ax-sys-color-border-lighter-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.operation-item.--clickable{cursor:pointer}@media(hover:hover){.operation-item.--clickable:hover{border-color:rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface))}}.operation-item.--failed{border-color:rgb(var(--ax-sys-color-border-danger-surface))}.operation-item__body{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.operation-item__header{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.operation-item__status-icon{margin-top:calc(var(--spacing, .25rem) * .5);flex-shrink:0;font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500))}.operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500))}.operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500))}.operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500))}.operation-item__summary{display:flex;min-width:0;flex:1;flex-direction:column;gap:var(--spacing, .25rem)}.operation-item__title{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;text-align:start;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgb(var(--ax-sys-color-on-surface))}.operation-item__meta{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.operation-item__meta-content{display:flex;min-width:0;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}.operation-item__status-text{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;text-align:start;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__step{display:inline-block;font-size:.6875rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__error{margin:0;border-radius:var(--radius-md, .375rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:var(--spacing, .25rem);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);background:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.operation-item__actions{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--spacing, .25rem)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-duration: initial;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.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: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXProgressBarModule }, { kind: "component", type: i3.AXProgressBarComponent, selector: "ax-progress-bar", inputs: ["color", "mode", "progress", "height"], outputs: ["ValueChange", "sizeChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
3691
3896
  }
3692
3897
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationItemComponent, decorators: [{
3693
3898
  type: Component,
3694
- args: [{ selector: 'axp-background-operation-item', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXButtonModule, AXDecoratorModule, AXProgressBarModule, AXTranslationModule], template: "<article\n class=\"operation-item\"\n [class]=\"statusClass()\"\n [class.--clickable]=\"isClickable()\"\n (click)=\"onItemClick()\"\n>\n <div class=\"operation-item__body\">\n <div class=\"operation-item__header\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__summary\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n\n @if (showMetaRow()) {\n <div class=\"operation-item__meta\">\n <div class=\"operation-item__meta-content\">\n @if (data().statusText) {\n <p class=\"operation-item__status-text\">{{ data().statusText }}</p>\n }\n\n @if (data().currentStep) {\n <span class=\"operation-item__step\">\n {{ '@general:background-operation.step' | translate | async }} {{ data().currentStep }}\n </span>\n }\n </div>\n\n @if (actions().length > 0) {\n <footer class=\"operation-item__actions\" (click)=\"$event.stopPropagation()\">\n @for (action of actions(); track action) {\n <ax-button\n class=\"ax-xs\"\n [look]=\"actionButtonLook(action)\"\n [color]=\"actionButtonColor(action)\"\n [text]=\"(actionLabelKey(action) | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled(action) || isActionLoading(action)\"\n (onClick)=\"onAction(action)\"\n ></ax-button>\n }\n </footer>\n }\n </div>\n }\n\n @if (showProgressBar()) {\n <ax-progress-bar\n [progress]=\"progressValue()\"\n [mode]=\"progressMode()\"\n [color]=\"progressColor()\"\n [style.height.px]=\"4\"\n ></ax-progress-bar>\n }\n\n @if (showError()) {\n <p class=\"operation-item__error\" role=\"alert\">{{ data().error!.message }}</p>\n }\n </div>\n </div>\n </div>\n</article>\n", styles: ["axp-background-operation-item{display:block}.operation-item{position:relative;overflow:hidden;border-radius:.375rem;border-width:1px;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;animation-duration:.2s;border-color:rgb(var(--ax-sys-color-border-lighter-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.operation-item.--clickable{cursor:pointer}@media(hover:hover){.operation-item.--clickable:hover{border-color:rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface))}}.operation-item.--failed{border-color:rgb(var(--ax-sys-color-border-danger-surface))}.operation-item__body{display:flex;flex-direction:column;gap:.5rem;padding:.75rem}.operation-item__header{display:flex;align-items:center;gap:.75rem}.operation-item__status-icon{margin-top:.125rem;flex-shrink:0;font-size:1.5rem;line-height:2rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500))}.operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500))}.operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500))}.operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500))}.operation-item__summary{display:flex;min-width:0px;flex:1 1 0%;flex-direction:column;gap:.25rem}.operation-item__title{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;text-align:start;font-size:.875rem;line-height:1.25rem;font-weight:500;line-height:1.375;color:rgb(var(--ax-sys-color-on-surface))}.operation-item__meta{display:flex;align-items:center;justify-content:space-between;gap:.5rem}.operation-item__meta-content{display:flex;min-width:0px;flex:1 1 0%;flex-direction:column;gap:.125rem}.operation-item__status-text{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;text-align:start;font-size:.75rem;line-height:1rem;line-height:1.625;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__step{display:inline-block;font-size:.6875rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__error{margin:0;border-radius:.375rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;line-height:1.625;background:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.operation-item__actions{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:.25rem}\n"] }]
3899
+ args: [{ selector: 'axp-background-operation-item', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXButtonModule, AXDecoratorModule, AXProgressBarModule, AXTranslationModule], template: "<article\n class=\"operation-item\"\n [class]=\"statusClass()\"\n [class.--clickable]=\"isClickable()\"\n (click)=\"onItemClick()\"\n>\n <div class=\"operation-item__body\">\n <div class=\"operation-item__header\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__summary\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n\n @if (showMetaRow()) {\n <div class=\"operation-item__meta\">\n <div class=\"operation-item__meta-content\">\n @if (data().statusText) {\n <p class=\"operation-item__status-text\">\n {{ data().statusText }}\n </p>\n }\n\n @if (data().currentStep) {\n <span class=\"operation-item__step\">\n {{\n '@general:background-operation.step' | translate | async\n }}\n {{ data().currentStep }}\n </span>\n }\n </div>\n\n @if (actions().length > 0) {\n <footer\n class=\"operation-item__actions\"\n (click)=\"$event.stopPropagation()\"\n >\n @for (action of actions(); track action) {\n <ax-button\n class=\"ax-sm\"\n [look]=\"actionButtonLook(action)\"\n [color]=\"actionButtonColor(action)\"\n [text]=\"(actionLabelKey(action) | translate | async) ?? ''\"\n [disabled]=\"\n isActionDisabled(action) || isActionLoading(action)\n \"\n (onClick)=\"onAction(action)\"\n ></ax-button>\n }\n </footer>\n }\n </div>\n }\n\n @if (showProgressBar()) {\n <ax-progress-bar\n [progress]=\"progressValue()\"\n [mode]=\"progressMode()\"\n [color]=\"progressColor()\"\n [style.height.px]=\"4\"\n ></ax-progress-bar>\n }\n\n @if (showError()) {\n <p class=\"operation-item__error\" role=\"alert\">\n {{ data().error!.message }}\n </p>\n }\n </div>\n </div>\n </div>\n</article>\n", styles: ["@layer properties;axp-background-operation-item{display:block}.operation-item{position:relative;overflow:hidden;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s;border-color:rgb(var(--ax-sys-color-border-lighter-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.operation-item.--clickable{cursor:pointer}@media(hover:hover){.operation-item.--clickable:hover{border-color:rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface))}}.operation-item.--failed{border-color:rgb(var(--ax-sys-color-border-danger-surface))}.operation-item__body{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.operation-item__header{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.operation-item__status-icon{margin-top:calc(var(--spacing, .25rem) * .5);flex-shrink:0;font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500))}.operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500))}.operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500))}.operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500))}.operation-item__summary{display:flex;min-width:0;flex:1;flex-direction:column;gap:var(--spacing, .25rem)}.operation-item__title{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;text-align:start;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgb(var(--ax-sys-color-on-surface))}.operation-item__meta{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.operation-item__meta-content{display:flex;min-width:0;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}.operation-item__status-text{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;text-align:start;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__step{display:inline-block;font-size:.6875rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__error{margin:0;border-radius:var(--radius-md, .375rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:var(--spacing, .25rem);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);background:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.operation-item__actions{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--spacing, .25rem)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-duration: initial;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"] }]
3695
3900
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], actionCompleted: [{ type: i0.Output, args: ["actionCompleted"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
3696
3901
 
3697
3902
  //#region ---- Imports ----
@@ -3728,11 +3933,11 @@ class AXPBackgroundOperationPanelComponent {
3728
3933
  }), ...(ngDevMode ? [{ debugName: "visibleOperations" }] : /* istanbul ignore next */ []));
3729
3934
  }
3730
3935
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3731
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationPanelComponent, isStandalone: true, selector: "axp-background-operation-panel", outputs: { onActiveCountChange: "onActiveCountChange", onClosePopover: "onClosePopover" }, ngImport: i0, template: "<div class=\"operation-panel\">\n <header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">{{ '@general:background-operation.panel.title' | translate | async }}</h2>\n </header>\n\n <div class=\"operation-panel__list\">\n @if (visibleOperations().length === 0) {\n <div class=\"operation-panel__empty\">\n <i class=\"fa-regular fa-list-check\"></i>\n <span class=\"ax-text-sm\">{{ '@general:background-operation.empty.all' | translate | async }}</span>\n </div>\n } @else {\n @for (operation of visibleOperations(); track operation.id) {\n <axp-background-operation-item\n [data]=\"operation\"\n (actionCompleted)=\"onActiveCountChange.emit(operationService.activeCount())\"\n (itemClicked)=\"onClosePopover.emit()\"\n ></axp-background-operation-item>\n }\n }\n </div>\n</div>\n", styles: ["axp-background-operation-panel{display:block}.operation-panel__header{display:flex;align-items:center;justify-content:space-between;border-bottom-width:1px;padding:.75rem 1rem;border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.operation-panel__title{margin:0;font-size:1rem;line-height:1.5rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface))}.operation-panel__list{display:flex;max-height:50vh;flex-direction:column;gap:.75rem;overflow-y:auto;padding:1rem}@media(min-width:768px){.operation-panel__list{width:32rem}}.operation-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2.5rem 1.5rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-panel__empty i{font-size:1.5rem;line-height:2rem;opacity:.6}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPBackgroundOperationItemComponent, selector: "axp-background-operation-item", inputs: ["data"], outputs: ["actionCompleted", "itemClicked"] }, { kind: "pipe", type: i4$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
3936
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationPanelComponent, isStandalone: true, selector: "axp-background-operation-panel", outputs: { onActiveCountChange: "onActiveCountChange", onClosePopover: "onClosePopover" }, ngImport: i0, template: "<div class=\"operation-panel\">\n <header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">{{ '@general:background-operation.panel.title' | translate | async }}</h2>\n </header>\n\n <div class=\"operation-panel__list\">\n @if (visibleOperations().length === 0) {\n <div class=\"operation-panel__empty\">\n <i class=\"fa-regular fa-list-check\"></i>\n <span class=\"text-sm\">{{ '@general:background-operation.empty.all' | translate | async }}</span>\n </div>\n } @else {\n @for (operation of visibleOperations(); track operation.id) {\n <axp-background-operation-item\n [data]=\"operation\"\n (actionCompleted)=\"onActiveCountChange.emit(operationService.activeCount())\"\n (itemClicked)=\"onClosePopover.emit()\"\n ></axp-background-operation-item>\n }\n }\n </div>\n</div>\n", styles: ["@layer properties;axp-background-operation-panel{display:block}.operation-panel__header{display:flex;align-items:center;justify-content:space-between;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.operation-panel__title{margin:0;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgb(var(--ax-sys-color-on-surface))}.operation-panel__list{display:flex;max-height:50vh;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);overflow-y:auto;padding:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.operation-panel__list{width:32rem}}.operation-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 6);padding-block:calc(var(--spacing, .25rem) * 10);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-panel__empty i{font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));opacity:60%}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPBackgroundOperationItemComponent, selector: "axp-background-operation-item", inputs: ["data"], outputs: ["actionCompleted", "itemClicked"] }, { kind: "pipe", type: i4$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
3732
3937
  }
3733
3938
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationPanelComponent, decorators: [{
3734
3939
  type: Component,
3735
- args: [{ selector: 'axp-background-operation-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXTranslationModule, AXPBackgroundOperationItemComponent], template: "<div class=\"operation-panel\">\n <header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">{{ '@general:background-operation.panel.title' | translate | async }}</h2>\n </header>\n\n <div class=\"operation-panel__list\">\n @if (visibleOperations().length === 0) {\n <div class=\"operation-panel__empty\">\n <i class=\"fa-regular fa-list-check\"></i>\n <span class=\"ax-text-sm\">{{ '@general:background-operation.empty.all' | translate | async }}</span>\n </div>\n } @else {\n @for (operation of visibleOperations(); track operation.id) {\n <axp-background-operation-item\n [data]=\"operation\"\n (actionCompleted)=\"onActiveCountChange.emit(operationService.activeCount())\"\n (itemClicked)=\"onClosePopover.emit()\"\n ></axp-background-operation-item>\n }\n }\n </div>\n</div>\n", styles: ["axp-background-operation-panel{display:block}.operation-panel__header{display:flex;align-items:center;justify-content:space-between;border-bottom-width:1px;padding:.75rem 1rem;border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.operation-panel__title{margin:0;font-size:1rem;line-height:1.5rem;font-weight:600;color:rgb(var(--ax-sys-color-on-surface))}.operation-panel__list{display:flex;max-height:50vh;flex-direction:column;gap:.75rem;overflow-y:auto;padding:1rem}@media(min-width:768px){.operation-panel__list{width:32rem}}.operation-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2.5rem 1.5rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-panel__empty i{font-size:1.5rem;line-height:2rem;opacity:.6}\n"] }]
3940
+ args: [{ selector: 'axp-background-operation-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXTranslationModule, AXPBackgroundOperationItemComponent], template: "<div class=\"operation-panel\">\n <header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">{{ '@general:background-operation.panel.title' | translate | async }}</h2>\n </header>\n\n <div class=\"operation-panel__list\">\n @if (visibleOperations().length === 0) {\n <div class=\"operation-panel__empty\">\n <i class=\"fa-regular fa-list-check\"></i>\n <span class=\"text-sm\">{{ '@general:background-operation.empty.all' | translate | async }}</span>\n </div>\n } @else {\n @for (operation of visibleOperations(); track operation.id) {\n <axp-background-operation-item\n [data]=\"operation\"\n (actionCompleted)=\"onActiveCountChange.emit(operationService.activeCount())\"\n (itemClicked)=\"onClosePopover.emit()\"\n ></axp-background-operation-item>\n }\n }\n </div>\n</div>\n", styles: ["@layer properties;axp-background-operation-panel{display:block}.operation-panel__header{display:flex;align-items:center;justify-content:space-between;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.operation-panel__title{margin:0;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgb(var(--ax-sys-color-on-surface))}.operation-panel__list{display:flex;max-height:50vh;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);overflow-y:auto;padding:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.operation-panel__list{width:32rem}}.operation-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 6);padding-block:calc(var(--spacing, .25rem) * 10);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-panel__empty i{font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));opacity:60%}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"] }]
3736
3941
  }], propDecorators: { onActiveCountChange: [{ type: i0.Output, args: ["onActiveCountChange"] }], onClosePopover: [{ type: i0.Output, args: ["onClosePopover"] }] } });
3737
3942
 
3738
3943
  //#region ---- Imports ----
@@ -3771,13 +3976,31 @@ class AXPBackgroundOperationSlotComponent {
3771
3976
  this.popover()?.close();
3772
3977
  }
3773
3978
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3774
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationSlotComponent, isStandalone: true, selector: "axp-background-operation-slot", viewQueries: [{ propertyName: "popover", first: true, predicate: AXPopoverComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (showSlot()) {\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger>\n <ax-icon class=\"operation-slot__icon\">\n @if (slotShowsFailureOnly()) {\n <i class=\"fa-light fa-circle-exclamation\"></i>\n } @else {\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n }\n </ax-icon>\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate: { params: slotLabelParams() } | async }}\n </span>\n </button>\n\n <ax-popover [target]=\"operationTrigger\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"ax-bg-lightest ax-rounded-md ax-w-full\">\n <axp-background-operation-panel (onClosePopover)=\"closePopover()\"></axp-background-operation-panel>\n </div>\n </ax-popover>\n}\n", styles: ["axp-background-operation-slot{display:inline-flex}.operation-slot__trigger{display:inline-flex;cursor:pointer;align-items:center;gap:.375rem;border-width:0px;background-color:transparent;padding:0;color:rgb(var(--ax-sys-color-primary-600))}@media(hover:hover){.operation-slot__trigger:hover{color:rgb(var(--ax-sys-color-primary-700))}}.operation-slot__icon{font-size:.875rem;line-height:1.25rem}.operation-slot__text{font-size:.875rem;line-height:1.25rem;font-weight:500}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXPBackgroundOperationPanelComponent, selector: "axp-background-operation-panel", outputs: ["onActiveCountChange", "onClosePopover"] }, { kind: "pipe", type: i4$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
3979
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationSlotComponent, isStandalone: true, selector: "axp-background-operation-slot", viewQueries: [{ propertyName: "popover", first: true, predicate: AXPopoverComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (showSlot()) {\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger>\n <ax-icon class=\"operation-slot__icon\">\n @if (slotShowsFailureOnly()) {\n <i class=\"fa-light fa-circle-exclamation\"></i>\n } @else {\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n }\n </ax-icon>\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate: { params: slotLabelParams() } | async }}\n </span>\n </button>\n\n <ax-popover [target]=\"operationTrigger\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"bg-lightest rounded-md w-full\">\n <axp-background-operation-panel (onClosePopover)=\"closePopover()\"></axp-background-operation-panel>\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;axp-background-operation-slot{display:inline-flex}.operation-slot__trigger{display:inline-flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding:0;color:rgb(var(--ax-sys-color-primary-600))}@media(hover:hover){.operation-slot__trigger:hover{color:rgb(var(--ax-sys-color-primary-700))}}.operation-slot__icon{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}.operation-slot__text{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXPBackgroundOperationPanelComponent, selector: "axp-background-operation-panel", outputs: ["onActiveCountChange", "onClosePopover"] }, { kind: "pipe", type: i4$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
3775
3980
  }
3776
3981
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationSlotComponent, decorators: [{
3777
3982
  type: Component,
3778
- args: [{ selector: 'axp-background-operation-slot', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXDecoratorModule, AXTranslationModule, AXPopoverModule, AXPBackgroundOperationPanelComponent], template: "@if (showSlot()) {\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger>\n <ax-icon class=\"operation-slot__icon\">\n @if (slotShowsFailureOnly()) {\n <i class=\"fa-light fa-circle-exclamation\"></i>\n } @else {\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n }\n </ax-icon>\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate: { params: slotLabelParams() } | async }}\n </span>\n </button>\n\n <ax-popover [target]=\"operationTrigger\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"ax-bg-lightest ax-rounded-md ax-w-full\">\n <axp-background-operation-panel (onClosePopover)=\"closePopover()\"></axp-background-operation-panel>\n </div>\n </ax-popover>\n}\n", styles: ["axp-background-operation-slot{display:inline-flex}.operation-slot__trigger{display:inline-flex;cursor:pointer;align-items:center;gap:.375rem;border-width:0px;background-color:transparent;padding:0;color:rgb(var(--ax-sys-color-primary-600))}@media(hover:hover){.operation-slot__trigger:hover{color:rgb(var(--ax-sys-color-primary-700))}}.operation-slot__icon{font-size:.875rem;line-height:1.25rem}.operation-slot__text{font-size:.875rem;line-height:1.25rem;font-weight:500}\n"] }]
3983
+ args: [{ selector: 'axp-background-operation-slot', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXDecoratorModule, AXTranslationModule, AXPopoverModule, AXPBackgroundOperationPanelComponent], template: "@if (showSlot()) {\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger>\n <ax-icon class=\"operation-slot__icon\">\n @if (slotShowsFailureOnly()) {\n <i class=\"fa-light fa-circle-exclamation\"></i>\n } @else {\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n }\n </ax-icon>\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate: { params: slotLabelParams() } | async }}\n </span>\n </button>\n\n <ax-popover [target]=\"operationTrigger\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"bg-lightest rounded-md w-full\">\n <axp-background-operation-panel (onClosePopover)=\"closePopover()\"></axp-background-operation-panel>\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;axp-background-operation-slot{display:inline-flex}.operation-slot__trigger{display:inline-flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding:0;color:rgb(var(--ax-sys-color-primary-600))}@media(hover:hover){.operation-slot__trigger:hover{color:rgb(var(--ax-sys-color-primary-700))}}.operation-slot__icon{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}.operation-slot__text{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"] }]
3779
3984
  }], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPopoverComponent), { isSignal: true }] }] } });
3780
3985
 
3986
+ const ENVIRONMENT = new InjectionToken('ENVIRONMENT');
3987
+ const AXP_PLATFORM_CONFIG_TOKEN = new InjectionToken('AXP_PLATFORM_CONFIG_TOKEN', {
3988
+ providedIn: 'root',
3989
+ factory: () => {
3990
+ return AXPPlatformDefaultConfigs;
3991
+ },
3992
+ });
3993
+ const AXPPlatformDefaultConfigs = {
3994
+ copyright: 'ACoreX @ 2026',
3995
+ title: 'ACoreX Platform',
3996
+ network: {
3997
+ timeOut: 5000,
3998
+ },
3999
+ };
4000
+ function configPlatform(config = AXPPlatformDefaultConfigs) {
4001
+ return merge(AXPPlatformDefaultConfigs, config);
4002
+ }
4003
+
3781
4004
  //#endregion
3782
4005
  //#region ---- App Path Navigation ----
3783
4006
  /**
@@ -3841,17 +4064,20 @@ function axpReplaceEntityListRouteQueryParams(router, queryParams) {
3841
4064
  if (!axpIsEntityListPath(url)) {
3842
4065
  return;
3843
4066
  }
4067
+ const parsed = router.parseUrl(url);
3844
4068
  const pathOnly = url.split('?')[0].split('#')[0];
3845
4069
  const { segments } = axpParseAppPath(pathOnly);
4070
+ const mergedQueryParams = { ...parsed.queryParams, ...queryParams };
3846
4071
  void router.navigate(segments, {
3847
- queryParams,
3848
- queryParamsHandling: 'merge',
4072
+ queryParams: mergedQueryParams,
3849
4073
  replaceUrl: true,
3850
4074
  });
3851
4075
  }
3852
4076
  //#endregion
3853
4077
 
3854
4078
  const DEFAULT_TRAILING_SEGMENTS = ['list', 'view', 'edit', 'create'];
4079
+ /** Query params managed by entity list UI; ignored when matching generic (no-query) menu paths. */
4080
+ const ENTITY_LIST_UI_QUERY_KEYS = new Set(['view']);
3855
4081
  //#region ---- Entity Route Helpers ----
3856
4082
  /**
3857
4083
  * Parses `/{app}/m/{module}/e/{entity}/...` routes into a stable entity key.
@@ -3872,15 +4098,89 @@ function axpParseEntityRouteKey(segments) {
3872
4098
  function axpEntityRouteKeysEqual(left, right) {
3873
4099
  return left.app === right.app && left.module === right.module && left.entity === right.entity;
3874
4100
  }
4101
+ function axpParseQueryString(queryString) {
4102
+ return new URLSearchParams(queryString);
4103
+ }
4104
+ function axpMenuDeclaredNavigationParams(queryString) {
4105
+ const params = axpParseQueryString(queryString);
4106
+ const navigationParams = new URLSearchParams();
4107
+ params.forEach((value, key) => {
4108
+ if (!ENTITY_LIST_UI_QUERY_KEYS.has(key)) {
4109
+ navigationParams.append(key, value);
4110
+ }
4111
+ });
4112
+ return navigationParams;
4113
+ }
4114
+ function axpMenuHasDeclaredNavigationParams(itemQueryString) {
4115
+ return axpMenuDeclaredNavigationParams(itemQueryString).toString().length > 0;
4116
+ }
4117
+ /**
4118
+ * True when every navigation query param declared on the menu path equals the current URL.
4119
+ */
4120
+ function axpMenuDeclaredQueryParamsMatch(itemQueryString, currentQueryString) {
4121
+ const itemParams = axpMenuDeclaredNavigationParams(itemQueryString);
4122
+ const declaredPairs = [];
4123
+ itemParams.forEach((value, key) => {
4124
+ declaredPairs.push([key, value]);
4125
+ });
4126
+ if (declaredPairs.length === 0) {
4127
+ return axpGenericEntityListMenuQueryParamsMatch(currentQueryString);
4128
+ }
4129
+ const currentParams = axpParseQueryString(currentQueryString);
4130
+ return declaredPairs.every(([key, value]) => currentParams.get(key) === value);
4131
+ }
4132
+ /**
4133
+ * Generic entity list menu items (no declared query params) match only when the URL has no
4134
+ * navigation query params beyond UI-managed keys such as `view`.
4135
+ */
4136
+ function axpGenericEntityListMenuQueryParamsMatch(currentQueryString) {
4137
+ const currentParams = axpParseQueryString(currentQueryString);
4138
+ let hasNavigationParam = false;
4139
+ currentParams.forEach((_value, key) => {
4140
+ if (!ENTITY_LIST_UI_QUERY_KEYS.has(key)) {
4141
+ hasNavigationParam = true;
4142
+ }
4143
+ });
4144
+ return !hasNavigationParam;
4145
+ }
4146
+ /**
4147
+ * Counts declared menu query params that match the current URL (for best-match selection).
4148
+ */
4149
+ function axpMenuQueryParamSpecificity(itemPath, currentPath) {
4150
+ const itemQueryString = itemPath.split('#')[0].split('?')[1] ?? '';
4151
+ const currentQueryString = currentPath.split('#')[0].split('?')[1] ?? '';
4152
+ const itemParams = axpMenuDeclaredNavigationParams(itemQueryString);
4153
+ const currentParams = axpParseQueryString(currentQueryString);
4154
+ let specificity = 0;
4155
+ itemParams.forEach((value, key) => {
4156
+ if (currentParams.get(key) === value) {
4157
+ specificity++;
4158
+ }
4159
+ });
4160
+ return specificity;
4161
+ }
3875
4162
  /**
3876
4163
  * Matches entity list menu entries against list/detail/create/edit routes for the same entity.
3877
4164
  */
3878
- function axpTryMatchEntityMenuRoute(itemSegments, pathSegments, currentBase) {
4165
+ function axpTryMatchEntityMenuRoute(itemSegments, pathSegments, currentBase, itemQueryString, currentQueryString) {
3879
4166
  const menuEntity = axpParseEntityRouteKey(itemSegments);
3880
4167
  const currentEntity = axpParseEntityRouteKey(pathSegments);
3881
4168
  if (!menuEntity || !currentEntity || !axpEntityRouteKeysEqual(menuEntity, currentEntity)) {
3882
4169
  return null;
3883
4170
  }
4171
+ const itemHasDeclaredParams = axpMenuHasDeclaredNavigationParams(itemQueryString);
4172
+ if (itemHasDeclaredParams) {
4173
+ if (!axpIsEntityListPath(currentBase)) {
4174
+ return { isMatch: false, isPartial: false };
4175
+ }
4176
+ if (!axpMenuDeclaredQueryParamsMatch(itemQueryString, currentQueryString)) {
4177
+ return { isMatch: false, isPartial: false };
4178
+ }
4179
+ return { isMatch: true, isPartial: false };
4180
+ }
4181
+ if (axpIsEntityListPath(currentBase) && !axpGenericEntityListMenuQueryParamsMatch(currentQueryString)) {
4182
+ return { isMatch: false, isPartial: false };
4183
+ }
3884
4184
  const isPartial = pathSegments.length > menuEntity.entityEndIndex ||
3885
4185
  axpIsEntityDetailsPath(currentBase) ||
3886
4186
  !axpIsEntityListPath(currentBase);
@@ -3895,10 +4195,10 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
3895
4195
  const itemNoHash = itemPath.split('#')[0];
3896
4196
  const currentNoHash = currentPath.split('#')[0];
3897
4197
  const [itemBase, itemQueryString = ''] = itemNoHash.split('?');
3898
- const [currentBase] = currentNoHash.split('?');
4198
+ const [currentBase, currentQueryString = ''] = currentNoHash.split('?');
3899
4199
  const itemSegments = itemBase.split('/').filter((segment) => segment.length > 0);
3900
4200
  const pathSegments = currentBase.split('/').filter((segment) => segment.length > 0);
3901
- const entityMatch = axpTryMatchEntityMenuRoute(itemSegments, pathSegments, `/${currentBase}`);
4201
+ const entityMatch = axpTryMatchEntityMenuRoute(itemSegments, pathSegments, `/${currentBase}`, itemQueryString, currentQueryString);
3902
4202
  if (entityMatch) {
3903
4203
  return entityMatch;
3904
4204
  }
@@ -3923,8 +4223,8 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
3923
4223
  }
3924
4224
  const isPartialMatch = effectiveMenuLength < pathLength;
3925
4225
  const isExactMatch = effectiveMenuLength === pathLength;
3926
- const itemParams = new URLSearchParams(itemQueryString);
3927
- const currentParams = new URLSearchParams(currentNoHash.split('?')[1] ?? '');
4226
+ const itemParams = axpParseQueryString(itemQueryString);
4227
+ const currentParams = axpParseQueryString(currentQueryString);
3928
4228
  let queryMatches = true;
3929
4229
  const itemParamPairs = [];
3930
4230
  itemParams.forEach((value, key) => {
@@ -3949,6 +4249,7 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
3949
4249
  function axpFindMenuItemByRoute(items, currentPath, trailingSegmentsToIgnore = DEFAULT_TRAILING_SEGMENTS) {
3950
4250
  let bestMatch = null;
3951
4251
  let bestEffectiveLength = -1;
4252
+ let bestQuerySpecificity = -1;
3952
4253
  const visit = (menuItems, ancestors) => {
3953
4254
  for (const item of menuItems) {
3954
4255
  if (item.children?.length) {
@@ -3973,8 +4274,11 @@ function axpFindMenuItemByRoute(items, currentPath, trailingSegmentsToIgnore = D
3973
4274
  if (menuEntity) {
3974
4275
  effectiveMenuLength = menuEntity.entityEndIndex;
3975
4276
  }
3976
- if (effectiveMenuLength > bestEffectiveLength) {
4277
+ const querySpecificity = axpMenuQueryParamSpecificity(item.path, currentPath);
4278
+ if (effectiveMenuLength > bestEffectiveLength ||
4279
+ (effectiveMenuLength === bestEffectiveLength && querySpecificity > bestQuerySpecificity)) {
3977
4280
  bestEffectiveLength = effectiveMenuLength;
4281
+ bestQuerySpecificity = querySpecificity;
3978
4282
  bestMatch = { item, ancestors, isPartialMatch: matchResult.isPartial };
3979
4283
  }
3980
4284
  }
@@ -4334,6 +4638,8 @@ class AXPMenuProviderService {
4334
4638
  */
4335
4639
  this.menuReloadSubject = new Subject();
4336
4640
  this.menuReload$ = this.menuReloadSubject.asObservable();
4641
+ /** Serializes menu builds so pending queues are not corrupted by concurrent items() calls. */
4642
+ this.itemsBuildLock = Promise.resolve();
4337
4643
  }
4338
4644
  //#endregion
4339
4645
  //#region ---- Public API ----
@@ -4341,22 +4647,37 @@ class AXPMenuProviderService {
4341
4647
  * Get menu items with middlewares applied (for end-user display)
4342
4648
  */
4343
4649
  async items() {
4344
- // Return cached items if available
4345
4650
  if (this.cache) {
4346
4651
  return this.cache;
4347
4652
  }
4653
+ let releaseLock;
4654
+ const previousBuild = this.itemsBuildLock;
4655
+ this.itemsBuildLock = new Promise((resolve) => {
4656
+ releaseLock = resolve;
4657
+ });
4658
+ await previousBuild;
4659
+ try {
4660
+ if (this.cache) {
4661
+ return this.cache;
4662
+ }
4663
+ return await this.buildItems();
4664
+ }
4665
+ finally {
4666
+ releaseLock();
4667
+ }
4668
+ }
4669
+ async buildItems() {
4670
+ this.resetPendingOperations();
4348
4671
  const items = [];
4349
4672
  const context = this.createMenuProviderContext(items);
4350
4673
  // Load providers from DI tokens
4351
4674
  if (Array.isArray(this.providers)) {
4352
4675
  for (const provider of this.providers) {
4353
4676
  if (provider instanceof Promise) {
4354
- // If provider is a promise, resolve it
4355
4677
  const resolvedProvider = await provider;
4356
4678
  await resolvedProvider.provide(context);
4357
4679
  }
4358
4680
  else {
4359
- // If provider is a direct instance, use it directly
4360
4681
  await provider.provide(context);
4361
4682
  }
4362
4683
  // Apply pending operations after each provider so subsequent providers
@@ -4379,6 +4700,7 @@ class AXPMenuProviderService {
4379
4700
  * Used by menu management pages to show original items before customization
4380
4701
  */
4381
4702
  async rawItems() {
4703
+ this.resetPendingOperations();
4382
4704
  const items = [];
4383
4705
  const context = this.createMenuProviderContext(items);
4384
4706
  // Load providers from DI tokens
@@ -4409,16 +4731,19 @@ class AXPMenuProviderService {
4409
4731
  */
4410
4732
  clearCache() {
4411
4733
  this.cache = null;
4734
+ this.resetPendingOperations();
4735
+ // Notify subscribers that menu should be reloaded
4736
+ this.menuReloadSubject.next();
4737
+ }
4738
+ //#endregion
4739
+ //#region ---- Private Methods ----
4740
+ resetPendingOperations() {
4412
4741
  this.pendingInserts = [];
4413
4742
  this.pendingRemovals = [];
4414
4743
  this.pendingUpdates = [];
4415
4744
  this.pendingAdditions = [];
4416
4745
  this.pendingMoves = [];
4417
- // Notify subscribers that menu should be reloaded
4418
- this.menuReloadSubject.next();
4419
4746
  }
4420
- //#endregion
4421
- //#region ---- Private Methods ----
4422
4747
  /**
4423
4748
  * Apply middlewares in priority order using the enhanced context API
4424
4749
  */
@@ -4562,17 +4887,29 @@ class AXPMenuProviderService {
4562
4887
  Object.assign(foundItem, updatedItem);
4563
4888
  }
4564
4889
  }
4565
- for (const { target, newItems } of this.pendingAdditions) {
4566
- const foundItemInfo = this.findItemWithParent(items, target);
4567
- const { foundItem } = foundItemInfo;
4568
- if (!foundItem) {
4569
- console.warn(`Target "${target}" not found, nothing to add items to.`);
4570
- }
4571
- else {
4890
+ this.applyPendingAdditions(items);
4891
+ for (const move of this.pendingMoves) {
4892
+ this.applyPendingMove(items, move.source, move.destination, move.position);
4893
+ }
4894
+ this.resetPendingOperations();
4895
+ }
4896
+ /**
4897
+ * Applies queued child additions in multiple passes so a provider can create a parent shell
4898
+ * and attach children in the same provide() call (parent is created in an earlier pass).
4899
+ */
4900
+ applyPendingAdditions(items) {
4901
+ const maxPasses = 32;
4902
+ for (let pass = 0; pass < maxPasses && this.pendingAdditions.length > 0; pass++) {
4903
+ const remaining = [];
4904
+ for (const { target, newItems } of this.pendingAdditions) {
4905
+ const foundItem = this.findItemWithParent(items, target).foundItem;
4906
+ if (!foundItem) {
4907
+ remaining.push({ target, newItems });
4908
+ continue;
4909
+ }
4572
4910
  if (!foundItem.children) {
4573
4911
  foundItem.children = [];
4574
4912
  }
4575
- // Check for duplicates by name and merge or add
4576
4913
  for (const newItem of newItems) {
4577
4914
  if (newItem.name) {
4578
4915
  const existingChild = this.findItemByName(foundItem.children, newItem.name);
@@ -4588,16 +4925,14 @@ class AXPMenuProviderService {
4588
4925
  }
4589
4926
  }
4590
4927
  }
4928
+ if (remaining.length === this.pendingAdditions.length) {
4929
+ for (const { target } of remaining) {
4930
+ console.warn(`Target "${target}" not found, nothing to add items to.`);
4931
+ }
4932
+ break;
4933
+ }
4934
+ this.pendingAdditions = remaining;
4591
4935
  }
4592
- for (const move of this.pendingMoves) {
4593
- this.applyPendingMove(items, move.source, move.destination, move.position);
4594
- }
4595
- // Clear pending operations after applying them
4596
- this.pendingInserts = [];
4597
- this.pendingRemovals = [];
4598
- this.pendingUpdates = [];
4599
- this.pendingAdditions = [];
4600
- this.pendingMoves = [];
4601
4936
  }
4602
4937
  findItemWithParent(items, target, parentItems = items) {
4603
4938
  for (const item of items) {
@@ -4967,7 +5302,7 @@ withState((router = inject(Router)) => {
4967
5302
  };
4968
5303
  }),
4969
5304
  // Methods for State Management
4970
- withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowService), commandExecutor = inject(AXPCommandExecutor)) => {
5305
+ withMethods((store, router = inject(Router), commandService = inject(AXPCommandService)) => {
4971
5306
  return {
4972
5307
  setMenuItems(items) {
4973
5308
  patchState(store, { items: items });
@@ -4983,19 +5318,13 @@ withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowServic
4983
5318
  },
4984
5319
  executeCommand(item) {
4985
5320
  if (item.path) {
4986
- workflow.execute('navigate', {
4987
- type: 'router',
4988
- options: { path: item.path },
4989
- });
5321
+ void commandService.execute('navigate', { path: item.path });
4990
5322
  patchState(store, { selectedMenuItem: { item, isFullMatch: true } });
4991
5323
  }
4992
5324
  if (item.command) {
4993
5325
  const command = item.command;
4994
- if (workflow.exists(command?.name)) {
4995
- workflow.execute(command.name, command.options);
4996
- }
4997
- else {
4998
- commandExecutor.execute(command.name, command.options);
5326
+ if (commandService.exists(command?.name)) {
5327
+ void commandService.execute(command.name, command.options ?? {});
4999
5328
  }
5000
5329
  }
5001
5330
  },
@@ -5016,8 +5345,9 @@ withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowServic
5016
5345
  return findParent(item, selectedItem);
5017
5346
  },
5018
5347
  };
5019
- }), withHooks((store, menuProviderService = inject(AXPMenuProviderService), menuKeyboardShortcuts = inject(AXPMenuKeyboardShortcutService), router = inject(Router)) => {
5348
+ }), withHooks((store, menuProviderService = inject(AXPMenuProviderService), menuKeyboardShortcuts = inject(AXPMenuKeyboardShortcutService), router = inject(Router), sessionService = inject(AXPSessionService)) => {
5020
5349
  let reloadSubscription;
5350
+ let accessPolicySubscription;
5021
5351
  const applyMenuItems = (items) => {
5022
5352
  patchState(store, { items });
5023
5353
  menuKeyboardShortcuts.sync(items);
@@ -5025,20 +5355,39 @@ withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowServic
5025
5355
  };
5026
5356
  return {
5027
5357
  onInit() {
5028
- // Load initial menu items
5029
- (async () => {
5030
- applyMenuItems(await menuProviderService.items());
5031
- })();
5032
5358
  // Subscribe to menu reload events
5033
- reloadSubscription = menuProviderService.menuReload$.subscribe(async () => {
5034
- applyMenuItems(await menuProviderService.items());
5359
+ reloadSubscription = menuProviderService.menuReload$.subscribe(() => {
5360
+ void (async () => {
5361
+ applyMenuItems(await menuProviderService.items());
5362
+ })();
5363
+ });
5364
+ // Rebuild menu only after the session is Authorized and access policy data is ready.
5365
+ // Permissions/features load while status is still Authenticated; rebuilding then caches a
5366
+ // tree without common menu shells and module providers fail with "Target ... not found".
5367
+ accessPolicySubscription = combineLatest([
5368
+ sessionService.isAuthorized$,
5369
+ sessionService.permissions$,
5370
+ sessionService.features$,
5371
+ ])
5372
+ .pipe(filter(([isAuthorized]) => isAuthorized), map(([, permissions, features]) => {
5373
+ const applicationId = sessionService.application?.id ?? '';
5374
+ return `${applicationId}:${permissions.length}:${features.length}`;
5375
+ }), distinctUntilChanged())
5376
+ .subscribe(() => {
5377
+ menuProviderService.clearCache();
5035
5378
  });
5379
+ // Initial load: clear cache once after session is ready; menuReload$ performs the build.
5380
+ void (async () => {
5381
+ const authorized = await firstValueFrom(sessionService.isAuthorizedWithLoading$);
5382
+ if (!authorized) {
5383
+ return;
5384
+ }
5385
+ menuProviderService.clearCache();
5386
+ })();
5036
5387
  },
5037
5388
  onDestroy() {
5038
- // Clean up subscription
5039
- if (reloadSubscription) {
5040
- reloadSubscription.unsubscribe();
5041
- }
5389
+ reloadSubscription?.unsubscribe();
5390
+ accessPolicySubscription?.unsubscribe();
5042
5391
  },
5043
5392
  };
5044
5393
  }));
@@ -6140,6 +6489,7 @@ class AXPBrowserTitleService {
6140
6489
  this.tabNavigation = inject(AXPTabNavigationService);
6141
6490
  this.menuService = inject(AXPMenuService);
6142
6491
  this.sessionService = inject(AXPSessionService);
6492
+ this.platformConfig = inject(AXP_PLATFORM_CONFIG_TOKEN);
6143
6493
  this.router = inject(Router);
6144
6494
  this.destroyRef = inject(DestroyRef);
6145
6495
  //#endregion
@@ -6235,11 +6585,15 @@ class AXPBrowserTitleService {
6235
6585
  }
6236
6586
  async resolveApplicationTitle() {
6237
6587
  const application = this.sessionService.application;
6238
- const raw = application?.title?.trim() || application?.name?.trim() || '';
6239
- if (!raw) {
6588
+ const sessionTitle = application?.title?.trim() || application?.name?.trim() || '';
6589
+ if (sessionTitle) {
6590
+ return (await this.resolveLocalizedText(sessionTitle)) ?? sessionTitle;
6591
+ }
6592
+ const platformTitle = this.platformConfig.title?.trim() || '';
6593
+ if (!platformTitle) {
6240
6594
  return '';
6241
6595
  }
6242
- return (await this.resolveLocalizedText(raw)) ?? raw;
6596
+ return (await this.resolveLocalizedText(platformTitle)) ?? platformTitle;
6243
6597
  }
6244
6598
  async resolveLocalizedText(value) {
6245
6599
  const trimmed = value.trim();
@@ -6257,7 +6611,7 @@ class AXPBrowserTitleService {
6257
6611
  if (route && app) {
6258
6612
  return `${route} | ${app}`;
6259
6613
  }
6260
- return route || app || 'ACoreX';
6614
+ return route || app;
6261
6615
  }
6262
6616
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBrowserTitleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6263
6617
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBrowserTitleService, providedIn: 'root' }); }
@@ -6333,6 +6687,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
6333
6687
  type: Injectable
6334
6688
  }] });
6335
6689
 
6690
+ /**
6691
+ * Best-effort plain string for thrown {@link Error} messages from command results (no i18n lookup).
6692
+ */
6693
+ function commandMessageTextForError(value) {
6694
+ if (value == null) {
6695
+ return '';
6696
+ }
6697
+ if (typeof value === 'string') {
6698
+ return value;
6699
+ }
6700
+ if (typeof value === 'object' && !Array.isArray(value)) {
6701
+ const values = Object.values(value);
6702
+ const first = values.find((v) => typeof v === 'string' && v.length > 0);
6703
+ return first ?? '';
6704
+ }
6705
+ return String(value);
6706
+ }
6707
+
6336
6708
  class AXPErrorHandlerRegistryService {
6337
6709
  constructor(injector) {
6338
6710
  this.injector = injector;
@@ -6360,35 +6732,120 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
6360
6732
  }]
6361
6733
  }], ctorParameters: () => [{ type: i0.Injector }] });
6362
6734
 
6363
- class AXPGlobalErrorHandler extends ErrorHandler {
6364
- constructor(injector, registry) {
6365
- super();
6366
- this.injector = injector;
6367
- this.registry = registry;
6735
+ function readBodyRecord(body) {
6736
+ if (body == null || typeof body !== 'object' || Array.isArray(body)) {
6737
+ return null;
6368
6738
  }
6369
- handleError(error) {
6370
- const handleErrorRecursively = (index, error) => {
6371
- const errorHandlers = this.registry.handlers;
6372
- if (index < errorHandlers.length) {
6373
- errorHandlers[index].handleError(error, (err) => {
6374
- handleErrorRecursively(index + 1, err);
6375
- });
6376
- }
6377
- else {
6378
- super.handleError(error); // Fallback to default handler
6379
- }
6380
- };
6381
- if (error.message?.startsWith('NG0100')) {
6382
- //ignore it
6383
- return;
6384
- }
6385
- handleErrorRecursively(0, error);
6739
+ return body;
6740
+ }
6741
+ function readPayload(body) {
6742
+ const record = readBodyRecord(body);
6743
+ if (!record) {
6744
+ return null;
6386
6745
  }
6387
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, deps: [{ token: i0.Injector }, { token: AXPErrorHandlerRegistryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
6388
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, providedIn: 'root' }); }
6746
+ const message = record['message'];
6747
+ if (readBodyRecord(message)) {
6748
+ return readBodyRecord(message);
6749
+ }
6750
+ const nestedError = record['error'];
6751
+ if (readBodyRecord(nestedError)) {
6752
+ return readBodyRecord(nestedError);
6753
+ }
6754
+ return record;
6389
6755
  }
6390
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, decorators: [{
6391
- type: Injectable,
6756
+ function readStringParam(value) {
6757
+ return typeof value === 'string' && value.trim() ? value : undefined;
6758
+ }
6759
+ function extractHttpErrorBodyMessage(error) {
6760
+ const payload = readPayload(error.error);
6761
+ if (!payload) {
6762
+ return '';
6763
+ }
6764
+ const message = payload['message'];
6765
+ if (typeof message === 'string') {
6766
+ return message;
6767
+ }
6768
+ if (Array.isArray(message)) {
6769
+ return message.map(String).join(', ');
6770
+ }
6771
+ return '';
6772
+ }
6773
+ /**
6774
+ * Extracts structured API error details from an HTTP failure.
6775
+ */
6776
+ function extractHttpRequestErrorInfo(error) {
6777
+ if (!(error instanceof HttpErrorResponse)) {
6778
+ return null;
6779
+ }
6780
+ const payload = readPayload(error.error);
6781
+ if (!payload) {
6782
+ const fallbackMessage = error.message?.trim();
6783
+ return fallbackMessage ? { message: fallbackMessage } : null;
6784
+ }
6785
+ const code = readStringParam(payload['code']);
6786
+ const params = {};
6787
+ const jobId = readStringParam(payload['jobId']);
6788
+ const status = readStringParam(payload['status']);
6789
+ const scheduleId = readStringParam(payload['scheduleId']);
6790
+ if (jobId) {
6791
+ params['jobId'] = jobId;
6792
+ }
6793
+ if (status) {
6794
+ params['status'] = status;
6795
+ }
6796
+ if (scheduleId) {
6797
+ params['scheduleId'] = scheduleId;
6798
+ }
6799
+ const message = extractHttpErrorBodyMessage(error);
6800
+ if (!code && !message) {
6801
+ return null;
6802
+ }
6803
+ return {
6804
+ message,
6805
+ ...(code ? { code } : {}),
6806
+ ...(Object.keys(params).length > 0 ? { params } : {}),
6807
+ };
6808
+ }
6809
+ /**
6810
+ * Resolves a user-facing error string from HTTP failures and thrown errors.
6811
+ */
6812
+ function formatRequestError(error, fallback) {
6813
+ const httpInfo = extractHttpRequestErrorInfo(error);
6814
+ if (httpInfo) {
6815
+ return httpInfo.message || fallback;
6816
+ }
6817
+ return error instanceof Error ? error.message : fallback;
6818
+ }
6819
+
6820
+ class AXPGlobalErrorHandler extends ErrorHandler {
6821
+ constructor(injector, registry) {
6822
+ super();
6823
+ this.injector = injector;
6824
+ this.registry = registry;
6825
+ }
6826
+ handleError(error) {
6827
+ const handleErrorRecursively = (index, error) => {
6828
+ const errorHandlers = this.registry.handlers;
6829
+ if (index < errorHandlers.length) {
6830
+ errorHandlers[index].handleError(error, (err) => {
6831
+ handleErrorRecursively(index + 1, err);
6832
+ });
6833
+ }
6834
+ else {
6835
+ super.handleError(error); // Fallback to default handler
6836
+ }
6837
+ };
6838
+ if (error.message?.startsWith('NG0100')) {
6839
+ //ignore it
6840
+ return;
6841
+ }
6842
+ handleErrorRecursively(0, error);
6843
+ }
6844
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, deps: [{ token: i0.Injector }, { token: AXPErrorHandlerRegistryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
6845
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, providedIn: 'root' }); }
6846
+ }
6847
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, decorators: [{
6848
+ type: Injectable,
6392
6849
  args: [{ providedIn: 'root' }]
6393
6850
  }], ctorParameters: () => [{ type: i0.Injector }, { type: AXPErrorHandlerRegistryService }] });
6394
6851
 
@@ -6571,6 +7028,165 @@ async function resolveStoredImageDisplayUrl(value, download) {
6571
7028
  }
6572
7029
  //#endregion
6573
7030
 
7031
+ //#region ---- Logo image src resolver (file storage) ----
7032
+ class AXPLogoImageSrcResolverService {
7033
+ constructor(fileStorage) {
7034
+ this.fileStorage = fileStorage;
7035
+ }
7036
+ async resolve(src) {
7037
+ const trimmed = src?.trim();
7038
+ if (!trimmed) {
7039
+ return undefined;
7040
+ }
7041
+ if (!isStoredImageFileId(trimmed)) {
7042
+ return trimmed;
7043
+ }
7044
+ try {
7045
+ const displayUrl = await resolveStoredImageDisplayUrl(trimmed, (fileId) => this.fileStorage.download(fileId));
7046
+ return displayUrl || undefined;
7047
+ }
7048
+ catch {
7049
+ return undefined;
7050
+ }
7051
+ }
7052
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLogoImageSrcResolverService, deps: [{ token: AXPFileStorageService }], target: i0.ɵɵFactoryTarget.Injectable }); }
7053
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLogoImageSrcResolverService, providedIn: 'root' }); }
7054
+ }
7055
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLogoImageSrcResolverService, decorators: [{
7056
+ type: Injectable,
7057
+ args: [{ providedIn: 'root' }]
7058
+ }], ctorParameters: () => [{ type: AXPFileStorageService }] });
7059
+
7060
+ //#region ---- Document → file list item ----
7061
+ function normalizeFileIdSource(value) {
7062
+ return {
7063
+ kind: 'fileId',
7064
+ value: normalizeStoredImageRef(value) ?? value,
7065
+ };
7066
+ }
7067
+ function resolveSourceFromRaw(raw) {
7068
+ if (raw == null) {
7069
+ return undefined;
7070
+ }
7071
+ if (typeof raw === 'string') {
7072
+ return normalizeFileIdSource(raw);
7073
+ }
7074
+ if (typeof raw !== 'object') {
7075
+ return undefined;
7076
+ }
7077
+ const item = raw;
7078
+ if (item.source?.kind === 'fileId' && typeof item.source.value === 'string') {
7079
+ return normalizeFileIdSource(item.source.value);
7080
+ }
7081
+ if (item.source?.kind === 'blob' || item.source?.kind === 'url') {
7082
+ return item.source;
7083
+ }
7084
+ if (typeof item.source?.value === 'string') {
7085
+ const value = item.source.value;
7086
+ if (value.startsWith('blob:') || value.startsWith('data:') || value.startsWith('http')) {
7087
+ return { kind: 'url', value };
7088
+ }
7089
+ return normalizeFileIdSource(value);
7090
+ }
7091
+ if (typeof item.id === 'string' && item.id) {
7092
+ return normalizeFileIdSource(item.id);
7093
+ }
7094
+ return undefined;
7095
+ }
7096
+ /**
7097
+ * Normalizes a drive document or explorer node into an {@link AXPFileListItem}
7098
+ * with a resolvable `source` for the gallery / media viewer.
7099
+ */
7100
+ function normalizeDocumentToFileListItem(doc) {
7101
+ const raw = doc.fileInfo ?? doc.fileId;
7102
+ const source = resolveSourceFromRaw(raw);
7103
+ const rawItem = typeof raw === 'object' && raw != null ? raw : undefined;
7104
+ const rawItemId = typeof rawItem?.id === 'string' ? rawItem.id : undefined;
7105
+ const sourceFileId = source?.kind === 'fileId' && typeof source.value === 'string' ? source.value : undefined;
7106
+ return {
7107
+ id: doc.id ?? rawItemId ?? sourceFileId ?? '',
7108
+ name: doc.name,
7109
+ size: rawItem?.size ?? doc.size ?? 0,
7110
+ status: rawItem?.status ?? 'attached',
7111
+ source,
7112
+ title: rawItem?.title,
7113
+ description: rawItem?.description,
7114
+ readOnly: rawItem?.readOnly,
7115
+ meta: rawItem?.meta,
7116
+ };
7117
+ }
7118
+ //#endregion
7119
+
7120
+ //#region ---- Media viewer type resolution ----
7121
+ /** Extensions supported by {@link AXMediaViewerData} (`image` | `audio` | `pdf` | `video`). */
7122
+ const GALLERY_MEDIA_EXTENSIONS = [
7123
+ 'jpg',
7124
+ 'jpeg',
7125
+ 'png',
7126
+ 'gif',
7127
+ 'bmp',
7128
+ 'webp',
7129
+ 'svg',
7130
+ 'pdf',
7131
+ 'mp4',
7132
+ 'webm',
7133
+ 'mov',
7134
+ 'm4v',
7135
+ 'avi',
7136
+ 'mkv',
7137
+ 'wmv',
7138
+ 'mp3',
7139
+ 'wav',
7140
+ 'ogg',
7141
+ 'oga',
7142
+ 'm4a',
7143
+ 'flac',
7144
+ 'aac',
7145
+ 'wma',
7146
+ 'weba',
7147
+ ];
7148
+ const IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']);
7149
+ const PDF_EXTENSIONS = new Set(['pdf']);
7150
+ const VIDEO_EXTENSIONS = new Set(['mp4', 'webm', 'mov', 'm4v', 'avi', 'mkv', 'wmv']);
7151
+ const AUDIO_EXTENSIONS = new Set(['mp3', 'wav', 'ogg', 'oga', 'm4a', 'flac', 'aac', 'wma', 'weba']);
7152
+ const GALLERY_EXTENSION_SET = new Set(GALLERY_MEDIA_EXTENSIONS);
7153
+ /** Returns the lowercase extension from a file name, or `undefined` when missing. */
7154
+ function extractFileExtension(fileName) {
7155
+ if (!fileName) {
7156
+ return undefined;
7157
+ }
7158
+ const ext = fileName.split('.').pop()?.toLowerCase();
7159
+ return ext && ext !== fileName.toLowerCase() ? ext : undefined;
7160
+ }
7161
+ /** Maps a file name extension to the media-viewer `type` discriminator. */
7162
+ function resolveMediaViewerType(fileName) {
7163
+ const ext = extractFileExtension(fileName);
7164
+ if (!ext) {
7165
+ return 'image';
7166
+ }
7167
+ if (PDF_EXTENSIONS.has(ext)) {
7168
+ return 'pdf';
7169
+ }
7170
+ if (VIDEO_EXTENSIONS.has(ext)) {
7171
+ return 'video';
7172
+ }
7173
+ if (AUDIO_EXTENSIONS.has(ext)) {
7174
+ return 'audio';
7175
+ }
7176
+ if (IMAGE_EXTENSIONS.has(ext)) {
7177
+ return 'image';
7178
+ }
7179
+ return 'image';
7180
+ }
7181
+ /** Whether the extension can be rendered in the gallery / media viewer. */
7182
+ function isGalleryMediaExtension(extension) {
7183
+ if (!extension) {
7184
+ return false;
7185
+ }
7186
+ return GALLERY_EXTENSION_SET.has(extension.toLowerCase());
7187
+ }
7188
+ //#endregion
7189
+
6574
7190
  class AXPKeyboardShortcutsHelpComponent {
6575
7191
  constructor() {
6576
7192
  //#region ---- Services & Dependencies ----
@@ -6633,7 +7249,7 @@ class AXPKeyboardShortcutsHelpComponent {
6633
7249
  }
6634
7250
  </div>
6635
7251
  </div>
6636
- `, isInline: true, styles: [".axp-keyboard-shortcuts-help{display:flex;max-height:75vh;min-height:0px;flex-direction:column;overflow-y:auto}.axp-keyboard-shortcuts-help .__body{min-height:0px;flex:1 1 0%;padding:1rem}.axp-keyboard-shortcuts-help .__empty{margin:0;padding:2rem .5rem;text-align:center;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(115 115 115 / var(--tw-text-opacity, 1))}.axp-keyboard-shortcuts-help .__section:not(:first-child){margin-top:1.5rem}.axp-keyboard-shortcuts-help .__heading{margin:0;margin-bottom:.5rem;padding-left:.25rem;padding-right:.25rem;font-size:.9375rem;font-weight:600;line-height:1.375;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-surface),var(--tw-text-opacity, 1))}.axp-keyboard-shortcuts-help .__list{display:flex;flex-direction:column}.axp-keyboard-shortcuts-help .__row{display:flex;min-height:2rem;align-items:center;justify-content:space-between;gap:2rem;padding:.25rem}.axp-keyboard-shortcuts-help .__action{min-width:0px;flex:1 1 0%;font-size:.875rem;line-height:1.25rem;line-height:1.375;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-surface),var(--tw-text-opacity, 1))}.axp-keyboard-shortcuts-help .__keys{display:flex;flex-shrink:0;align-items:center;justify-content:flex-end;gap:.5rem}.axp-keyboard-shortcuts-help .__or{-webkit-user-select:none;user-select:none;padding-left:.125rem;padding-right:.125rem;font-size:.8125rem;font-weight:400;--tw-text-opacity: 1;color:rgb(115 115 115 / var(--tw-text-opacity, 1))}.axp-keyboard-shortcuts-help ax-kbd{gap:.25rem}.axp-keyboard-shortcuts-help ax-kbd ax-kbd-item kbd.ax-solid{height:1.5rem;min-width:1.5rem;font-size:.75rem;line-height:1rem}\n"], dependencies: [{ kind: "component", type: AXKBDComponent, selector: "ax-kbd", inputs: ["look"] }, { kind: "component", type: AXKBDItemComponent, selector: "ax-kbd-item", inputs: ["keys", "join", "look"], outputs: ["lookChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
7252
+ `, isInline: true, styles: ["@layer properties;.axp-keyboard-shortcuts-help{display:flex;max-height:75vh;min-height:0;flex-direction:column;overflow-y:auto}.axp-keyboard-shortcuts-help .__body{min-height:0;flex:1;padding:calc(var(--spacing, .25rem) * 4)}.axp-keyboard-shortcuts-help .__empty{margin:0;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 8);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-500, oklch(55.6% 0 0))}.axp-keyboard-shortcuts-help .__section:not(:first-child){margin-top:calc(var(--spacing, .25rem) * 6)}.axp-keyboard-shortcuts-help .__heading{margin:0;margin-bottom:calc(var(--spacing, .25rem) * 2);padding-inline:var(--spacing, .25rem);font-size:.9375rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-on-surface))}.axp-keyboard-shortcuts-help .__list{display:flex;flex-direction:column}.axp-keyboard-shortcuts-help .__row{display:flex;min-height:calc(var(--spacing, .25rem) * 8);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 8);padding-inline:var(--spacing, .25rem);padding-block:var(--spacing, .25rem)}.axp-keyboard-shortcuts-help .__action{min-width:0;flex:1;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);color:rgba(var(--ax-sys-color-on-surface))}.axp-keyboard-shortcuts-help .__keys{display:flex;flex-shrink:0;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 2)}.axp-keyboard-shortcuts-help .__or{padding-inline:calc(var(--spacing, .25rem) * .5);font-size:.8125rem;--tw-font-weight: var(--font-weight-normal, 400);font-weight:var(--font-weight-normal, 400);color:var(--color-neutral-500, oklch(55.6% 0 0));-webkit-user-select:none;user-select:none}.axp-keyboard-shortcuts-help ax-kbd{gap:var(--spacing, .25rem)}.axp-keyboard-shortcuts-help ax-kbd ax-kbd-item kbd.ax-solid{height:calc(var(--spacing, .25rem) * 6);min-width:calc(var(--spacing, .25rem) * 6);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXKBDComponent, selector: "ax-kbd", inputs: ["look"] }, { kind: "component", type: AXKBDItemComponent, selector: "ax-kbd-item", inputs: ["keys", "join", "look"], outputs: ["lookChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6637
7253
  }
6638
7254
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPKeyboardShortcutsHelpComponent, decorators: [{
6639
7255
  type: Component,
@@ -6676,7 +7292,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
6676
7292
  }
6677
7293
  </div>
6678
7294
  </div>
6679
- `, styles: [".axp-keyboard-shortcuts-help{display:flex;max-height:75vh;min-height:0px;flex-direction:column;overflow-y:auto}.axp-keyboard-shortcuts-help .__body{min-height:0px;flex:1 1 0%;padding:1rem}.axp-keyboard-shortcuts-help .__empty{margin:0;padding:2rem .5rem;text-align:center;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(115 115 115 / var(--tw-text-opacity, 1))}.axp-keyboard-shortcuts-help .__section:not(:first-child){margin-top:1.5rem}.axp-keyboard-shortcuts-help .__heading{margin:0;margin-bottom:.5rem;padding-left:.25rem;padding-right:.25rem;font-size:.9375rem;font-weight:600;line-height:1.375;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-surface),var(--tw-text-opacity, 1))}.axp-keyboard-shortcuts-help .__list{display:flex;flex-direction:column}.axp-keyboard-shortcuts-help .__row{display:flex;min-height:2rem;align-items:center;justify-content:space-between;gap:2rem;padding:.25rem}.axp-keyboard-shortcuts-help .__action{min-width:0px;flex:1 1 0%;font-size:.875rem;line-height:1.25rem;line-height:1.375;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-on-surface),var(--tw-text-opacity, 1))}.axp-keyboard-shortcuts-help .__keys{display:flex;flex-shrink:0;align-items:center;justify-content:flex-end;gap:.5rem}.axp-keyboard-shortcuts-help .__or{-webkit-user-select:none;user-select:none;padding-left:.125rem;padding-right:.125rem;font-size:.8125rem;font-weight:400;--tw-text-opacity: 1;color:rgb(115 115 115 / var(--tw-text-opacity, 1))}.axp-keyboard-shortcuts-help ax-kbd{gap:.25rem}.axp-keyboard-shortcuts-help ax-kbd ax-kbd-item kbd.ax-solid{height:1.5rem;min-width:1.5rem;font-size:.75rem;line-height:1rem}\n"] }]
7295
+ `, styles: ["@layer properties;.axp-keyboard-shortcuts-help{display:flex;max-height:75vh;min-height:0;flex-direction:column;overflow-y:auto}.axp-keyboard-shortcuts-help .__body{min-height:0;flex:1;padding:calc(var(--spacing, .25rem) * 4)}.axp-keyboard-shortcuts-help .__empty{margin:0;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 8);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-500, oklch(55.6% 0 0))}.axp-keyboard-shortcuts-help .__section:not(:first-child){margin-top:calc(var(--spacing, .25rem) * 6)}.axp-keyboard-shortcuts-help .__heading{margin:0;margin-bottom:calc(var(--spacing, .25rem) * 2);padding-inline:var(--spacing, .25rem);font-size:.9375rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-on-surface))}.axp-keyboard-shortcuts-help .__list{display:flex;flex-direction:column}.axp-keyboard-shortcuts-help .__row{display:flex;min-height:calc(var(--spacing, .25rem) * 8);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 8);padding-inline:var(--spacing, .25rem);padding-block:var(--spacing, .25rem)}.axp-keyboard-shortcuts-help .__action{min-width:0;flex:1;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);color:rgba(var(--ax-sys-color-on-surface))}.axp-keyboard-shortcuts-help .__keys{display:flex;flex-shrink:0;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 2)}.axp-keyboard-shortcuts-help .__or{padding-inline:calc(var(--spacing, .25rem) * .5);font-size:.8125rem;--tw-font-weight: var(--font-weight-normal, 400);font-weight:var(--font-weight-normal, 400);color:var(--color-neutral-500, oklch(55.6% 0 0));-webkit-user-select:none;user-select:none}.axp-keyboard-shortcuts-help ax-kbd{gap:var(--spacing, .25rem)}.axp-keyboard-shortcuts-help ax-kbd ax-kbd-item kbd.ax-solid{height:calc(var(--spacing, .25rem) * 6);min-width:calc(var(--spacing, .25rem) * 6);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"] }]
6680
7296
  }] });
6681
7297
 
6682
7298
  var keyboardShortcutsHelp_component = /*#__PURE__*/Object.freeze({
@@ -7850,14 +8466,14 @@ class AXPMenuSearchProvider {
7850
8466
  class AXPFooterTextSlotComponent {
7851
8467
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFooterTextSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7852
8468
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: AXPFooterTextSlotComponent, isStandalone: true, selector: "ng-component", inputs: { text: "text" }, ngImport: i0, template: `
7853
- <small class="ax-text-sm" [innerHTML]="text"></small>
8469
+ <small class="text-sm" [innerHTML]="text"></small>
7854
8470
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7855
8471
  }
7856
8472
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFooterTextSlotComponent, decorators: [{
7857
8473
  type: Component,
7858
8474
  args: [{
7859
8475
  template: `
7860
- <small class="ax-text-sm" [innerHTML]="text"></small>
8476
+ <small class="text-sm" [innerHTML]="text"></small>
7861
8477
  `,
7862
8478
  standalone: true,
7863
8479
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -7873,7 +8489,7 @@ class AXPNavBarSlotComponent {
7873
8489
  }
7874
8490
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavBarSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7875
8491
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPNavBarSlotComponent, isStandalone: true, selector: "ng-component", inputs: { items: "items" }, ngImport: i0, template: `
7876
- <div class="ax-flex ax-items-center ax-justify-between ax-gap-5">
8492
+ <div class="flex items-center justify-between gap-5">
7877
8493
  @for (link of items; track link) {
7878
8494
  <a (click)="handleCommand(link.command)" >{{ link.text }}</a>
7879
8495
  }
@@ -7884,7 +8500,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
7884
8500
  type: Component,
7885
8501
  args: [{
7886
8502
  template: `
7887
- <div class="ax-flex ax-items-center ax-justify-between ax-gap-5">
8503
+ <div class="flex items-center justify-between gap-5">
7888
8504
  @for (link of items; track link) {
7889
8505
  <a (click)="handleCommand(link.command)" >{{ link.text }}</a>
7890
8506
  }
@@ -7986,153 +8602,26 @@ class AXPTokenEvaluatorScopeProvider {
7986
8602
  }
7987
8603
  }
7988
8604
 
7989
- //TODO Loading, Redirect, Drawer, Show toast
7990
- const AXPRedirectEvent = createWorkFlowEvent('Redirect Event Fired');
7991
- const AXPRefreshEvent = createWorkFlowEvent('Refresh Event Fired');
7992
- const AXPReloadEvent = createWorkFlowEvent('Reload Event Fired');
7993
- class AXPWorkflowNavigateAction extends AXPWorkflowAction {
8605
+ //#region ---- Query params expression scope ----
8606
+ /**
8607
+ * Exposes URL query parameters in expression strings, e.g.
8608
+ * `{{ queryParams.get('view') }}`.
8609
+ */
8610
+ class AXPQueryParamsEvaluatorScopeProvider {
7994
8611
  constructor() {
7995
- super(...arguments);
7996
8612
  this.router = inject(Router);
7997
- this.tabNavigation = inject(AXPTabNavigationService);
7998
- }
7999
- async execute(context) {
8000
- const payload = context.getVariable('payload');
8001
- if (Array.isArray(payload.commands)) {
8002
- await this.router.navigate(payload.commands, payload.extras);
8003
- return;
8004
- }
8005
- const path = payload.commands;
8006
- if (!path) {
8007
- return;
8008
- }
8009
- if (path.toLowerCase().startsWith('http') || payload.target === 'blank') {
8010
- window.open(path, '_blank');
8011
- return;
8012
- }
8013
- await this.tabNavigation.navigate(path, payload.extras);
8014
- }
8015
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowNavigateAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
8016
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowNavigateAction }); }
8017
- }
8018
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowNavigateAction, decorators: [{
8019
- type: Injectable
8020
- }] });
8021
- class AXPDialogConfirmAction extends AXPWorkflowAction {
8022
- constructor() {
8023
- super(...arguments);
8024
- this.dialogService = inject(AXDialogService);
8025
- this.translationService = inject(AXTranslationService);
8026
- this.defaultAction = 'cancel';
8027
- }
8028
- async execute(context) {
8029
- console.log('AXPDialogConfirmAction', this.title, this.message, this.type);
8030
- context.setOutput('result', false);
8031
- const dialogResult = await this.dialogService.confirm(await this.translationService.translateAsync(this.title), await this.translationService.translateAsync(this.message), (await this.translationService.translateAsync(this.type)), 'horizontal', false, 'cancel');
8032
- context.setOutput('result', dialogResult.result);
8033
- }
8034
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDialogConfirmAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
8035
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDialogConfirmAction }); }
8036
- }
8037
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDialogConfirmAction, decorators: [{
8038
- type: Injectable
8039
- }] });
8040
- class AXPToastAction extends AXPWorkflowAction {
8041
- constructor() {
8042
- super(...arguments);
8043
- this.toastService = inject(AXToastService);
8044
- this.translationService = inject(AXTranslationService);
8045
- this.settingsService = inject(AXPSettingsService);
8046
- }
8047
- async execute(context) {
8048
- const showResult = await this.settingsService.get(AXPCommonSettings.EnableOperationToasts);
8049
- if (showResult) {
8050
- this.toastService.show({
8051
- color: this.color,
8052
- title: await this.translationService.translateAsync(this.title),
8053
- content: await this.translationService.translateAsync(this.content),
8054
- closeButton: true,
8055
- timeOut: 3000,
8056
- timeOutProgress: true,
8057
- });
8058
- }
8059
8613
  }
8060
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPToastAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
8061
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPToastAction }); }
8062
- }
8063
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPToastAction, decorators: [{
8064
- type: Injectable
8065
- }] });
8066
- class AXPReloadAction extends AXPWorkflowAction {
8067
- async execute(context) {
8068
- this.dispatch(AXPReloadEvent({ entity: context.getVariable('entity'), meta: context.getVariable('meta') }));
8614
+ async provide(context) {
8615
+ context.addScope('queryParams', {
8616
+ get: (key) => {
8617
+ const value = this.router.parseUrl(this.router.url).queryParamMap.get(key);
8618
+ return value ?? undefined;
8619
+ },
8620
+ });
8069
8621
  }
8070
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPReloadAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
8071
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPReloadAction }); }
8072
8622
  }
8073
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPReloadAction, decorators: [{
8074
- type: Injectable
8075
- }] });
8076
-
8077
- //#region ---- Entity Workflow Events ----
8078
- /** Workflow event type dispatched after a successful entity delete. */
8079
- const AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE = '[Entity] Deleted';
8080
8623
  //#endregion
8081
8624
 
8082
- class AXPWorkflowRouterNavigateAction extends AXPWorkflowAction {
8083
- constructor() {
8084
- super(...arguments);
8085
- this.tabNavigation = inject(AXPTabNavigationService);
8086
- }
8087
- async execute(context) {
8088
- const command = context.getVariable();
8089
- const path = command.options.path;
8090
- if (!path) {
8091
- console.error('Path is required for navigate workflow');
8092
- return;
8093
- }
8094
- if (path?.toLowerCase()?.startsWith('http') || command.options?.extras?.target === 'blank') {
8095
- window.open(path, '_blank');
8096
- }
8097
- else {
8098
- await this.tabNavigation.navigate(path, command.options.extras);
8099
- }
8100
- }
8101
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRouterNavigateAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
8102
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRouterNavigateAction }); }
8103
- }
8104
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRouterNavigateAction, decorators: [{
8105
- type: Injectable
8106
- }] });
8107
- const AXPNavigateWorkflow = {
8108
- startStepId: 'start',
8109
- steps: {
8110
- start: {
8111
- action: 'navigate-router',
8112
- },
8113
- },
8114
- };
8115
-
8116
- class AXMWorkflowErrorHandler {
8117
- constructor() {
8118
- this.dialog = inject(AXDialogService);
8119
- }
8120
- handleError(error, next) {
8121
- if (error instanceof AXPWorkflowError) {
8122
- this.dialog.alert("Somthing is wrong!", error.inner ? error.inner.message : error.message, 'danger');
8123
- next(error);
8124
- }
8125
- else {
8126
- next(error);
8127
- }
8128
- }
8129
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkflowErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
8130
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkflowErrorHandler }); }
8131
- }
8132
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkflowErrorHandler, decorators: [{
8133
- type: Injectable
8134
- }] });
8135
-
8136
8625
  class AXPCommonModule {
8137
8626
  static forRoot(configs) {
8138
8627
  return {
@@ -8176,7 +8665,7 @@ class AXPCommonModule {
8176
8665
  });
8177
8666
  }
8178
8667
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, deps: [{ token: 'AXPCommonModuleFactory' }, { token: AXPKeyboardShortcutsHelpService }, { token: i2$1.AXFormatterRegistryService }], target: i0.ɵɵFactoryTarget.NgModule }); }
8179
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, imports: [i3$1.AXPComponentSlotModule, i4$2.AXPWorkflowModule, AXPopupModule,
8668
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, imports: [i3$1.AXPComponentSlotModule, AXPopupModule,
8180
8669
  AXDateTimeModule,
8181
8670
  AXToastModule,
8182
8671
  AXPModuleManifestModule], exports: [RouterModule] }); }
@@ -8219,10 +8708,19 @@ class AXPCommonModule {
8219
8708
  useClass: AXPFileStorageEvaluatorScopeProvider,
8220
8709
  multi: true,
8221
8710
  },
8711
+ {
8712
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
8713
+ useClass: AXPQueryParamsEvaluatorScopeProvider,
8714
+ multi: true,
8715
+ },
8222
8716
  {
8223
8717
  provide: AXP_SETTINGS_CACHE_SYNC,
8224
8718
  useExisting: AXPSettingsService,
8225
8719
  },
8720
+ {
8721
+ provide: AXP_LOGO_IMAGE_SRC_RESOLVER,
8722
+ useExisting: AXPLogoImageSrcResolverService,
8723
+ },
8226
8724
  {
8227
8725
  provide: AXP_SETTING_VALUE_PROVIDER,
8228
8726
  useFactory: createIndexedDbSettingValueProviders,
@@ -8232,11 +8730,17 @@ class AXPCommonModule {
8232
8730
  provide: AXP_SETTING_DEFINITION_PROVIDER,
8233
8731
  useFactory: async () => {
8234
8732
  const injector = inject(Injector);
8235
- const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-CbzOYCnI.mjs')).AXPCommonSettingProvider;
8733
+ const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs')).AXPCommonSettingProvider;
8236
8734
  return new provider(injector);
8237
8735
  },
8238
8736
  multi: true,
8239
8737
  },
8738
+ provideCommandSetups([
8739
+ {
8740
+ key: 'navigate',
8741
+ command: () => Promise.resolve().then(function () { return navigate_command; }).then((c) => c.AXPNavigateCommand),
8742
+ },
8743
+ ]),
8240
8744
  ], imports: [AXPComponentSlotModule.forChild({
8241
8745
  'root-footer-end': [
8242
8746
  {
@@ -8245,17 +8749,6 @@ class AXPCommonModule {
8245
8749
  },
8246
8750
  ],
8247
8751
  }),
8248
- AXPWorkflowModule.forChild({
8249
- actions: {
8250
- 'navigate-router': AXPWorkflowRouterNavigateAction,
8251
- 'show-prompt-dialog': AXPDialogConfirmAction,
8252
- 'show-toast': AXPToastAction,
8253
- reload: AXPReloadAction,
8254
- },
8255
- workflows: {
8256
- navigate: AXPNavigateWorkflow,
8257
- },
8258
- }),
8259
8752
  AXPopupModule,
8260
8753
  AXDateTimeModule,
8261
8754
  AXToastModule,
@@ -8273,17 +8766,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
8273
8766
  },
8274
8767
  ],
8275
8768
  }),
8276
- AXPWorkflowModule.forChild({
8277
- actions: {
8278
- 'navigate-router': AXPWorkflowRouterNavigateAction,
8279
- 'show-prompt-dialog': AXPDialogConfirmAction,
8280
- 'show-toast': AXPToastAction,
8281
- reload: AXPReloadAction,
8282
- },
8283
- workflows: {
8284
- navigate: AXPNavigateWorkflow,
8285
- },
8286
- }),
8287
8769
  AXPopupModule,
8288
8770
  AXDateTimeModule,
8289
8771
  AXToastModule,
@@ -8329,10 +8811,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
8329
8811
  useClass: AXPFileStorageEvaluatorScopeProvider,
8330
8812
  multi: true,
8331
8813
  },
8814
+ {
8815
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
8816
+ useClass: AXPQueryParamsEvaluatorScopeProvider,
8817
+ multi: true,
8818
+ },
8332
8819
  {
8333
8820
  provide: AXP_SETTINGS_CACHE_SYNC,
8334
8821
  useExisting: AXPSettingsService,
8335
8822
  },
8823
+ {
8824
+ provide: AXP_LOGO_IMAGE_SRC_RESOLVER,
8825
+ useExisting: AXPLogoImageSrcResolverService,
8826
+ },
8336
8827
  {
8337
8828
  provide: AXP_SETTING_VALUE_PROVIDER,
8338
8829
  useFactory: createIndexedDbSettingValueProviders,
@@ -8342,11 +8833,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
8342
8833
  provide: AXP_SETTING_DEFINITION_PROVIDER,
8343
8834
  useFactory: async () => {
8344
8835
  const injector = inject(Injector);
8345
- const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-CbzOYCnI.mjs')).AXPCommonSettingProvider;
8836
+ const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs')).AXPCommonSettingProvider;
8346
8837
  return new provider(injector);
8347
8838
  },
8348
8839
  multi: true,
8349
8840
  },
8841
+ provideCommandSetups([
8842
+ {
8843
+ key: 'navigate',
8844
+ command: () => Promise.resolve().then(function () { return navigate_command; }).then((c) => c.AXPNavigateCommand),
8845
+ },
8846
+ ]),
8350
8847
  ],
8351
8848
  }]
8352
8849
  }], ctorParameters: () => [{ type: undefined, decorators: [{
@@ -8354,24 +8851,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
8354
8851
  args: ['AXPCommonModuleFactory']
8355
8852
  }] }, { type: AXPKeyboardShortcutsHelpService }, { type: i2$1.AXFormatterRegistryService }] });
8356
8853
 
8357
- const ENVIRONMENT = new InjectionToken('ENVIRONMENT');
8358
- const AXP_PLATFORM_CONFIG_TOKEN = new InjectionToken('AXP_PLATFORM_CONFIG_TOKEN', {
8359
- providedIn: 'root',
8360
- factory: () => {
8361
- return AXPPlatformDefaultConfigs;
8362
- },
8363
- });
8364
- const AXPPlatformDefaultConfigs = {
8365
- copyright: 'ACoreX @ 2026',
8366
- title: 'ACoreX Platform',
8367
- network: {
8368
- timeOut: 5000,
8369
- },
8370
- };
8371
- function configPlatform(config = AXPPlatformDefaultConfigs) {
8372
- return merge(AXPPlatformDefaultConfigs, config);
8373
- }
8374
-
8375
8854
  /**
8376
8855
  * Resolves post-create list behavior from user settings and optional action overrides.
8377
8856
  */
@@ -8387,6 +8866,49 @@ async function resolveEntityCreateListBehavior(settingsService, options) {
8387
8866
 
8388
8867
  const AXP_ROOT_CONFIG_TOKEN = new InjectionToken('AXP_ROOT_CONFIG_TOKEN');
8389
8868
 
8869
+ /**
8870
+ * Opens the native file picker and always settles — including when the user cancels.
8871
+ * `AXFileService.choose()` can hang on cancel because no `change` event fires.
8872
+ */
8873
+ function chooseSystemFiles(options = {}) {
8874
+ const document = inject(DOCUMENT);
8875
+ const accept = options.accept ?? '';
8876
+ const multiple = options.multiple ?? false;
8877
+ return new Promise((resolve) => {
8878
+ const input = document.createElement('input');
8879
+ input.type = 'file';
8880
+ input.accept = accept;
8881
+ input.multiple = multiple;
8882
+ input.style.display = 'none';
8883
+ document.body.appendChild(input);
8884
+ let settled = false;
8885
+ const settle = (files) => {
8886
+ if (settled) {
8887
+ return;
8888
+ }
8889
+ settled = true;
8890
+ cleanup();
8891
+ resolve(files);
8892
+ };
8893
+ const cleanup = () => {
8894
+ input.removeEventListener('change', onChange);
8895
+ window.removeEventListener('focus', onWindowFocus);
8896
+ input.remove();
8897
+ };
8898
+ const onChange = () => {
8899
+ settle(Array.from(input.files ?? []));
8900
+ };
8901
+ const onWindowFocus = () => {
8902
+ // Allow `change` to fire first when the user confirms a selection.
8903
+ window.setTimeout(() => settle([]), 300);
8904
+ };
8905
+ input.addEventListener('change', onChange);
8906
+ window.addEventListener('focus', onWindowFocus, { once: true });
8907
+ input.click();
8908
+ });
8909
+ }
8910
+ //#endregion
8911
+
8390
8912
  //#endregion
8391
8913
  //#region ---- Injection Token ----
8392
8914
  /**
@@ -8507,7 +9029,6 @@ const UploadFromComputerActionProvider = {
8507
9029
  key: 'file-uploader.actions',
8508
9030
  priority: 1, // Higher priority than upload-from-drive to show first
8509
9031
  execute: (payload) => {
8510
- const fileService = inject(AXFileService);
8511
9032
  // Capture widget options for use in the action
8512
9033
  const widgetOptions = payload.options;
8513
9034
  payload.actions = [
@@ -8519,7 +9040,7 @@ const UploadFromComputerActionProvider = {
8519
9040
  icon: 'fa-light fa-file-arrow-up',
8520
9041
  run: async (capabilities) => {
8521
9042
  // Open file picker with widget options
8522
- const files = await fileService.choose({
9043
+ const files = await chooseSystemFiles({
8523
9044
  multiple: widgetOptions?.multiple ?? true,
8524
9045
  accept: widgetOptions?.accept,
8525
9046
  });
@@ -8552,17 +9073,17 @@ class AXPFileTypeProviderService {
8552
9073
  constructor() {
8553
9074
  this.providers = inject(AXP_FILE_TYPE_INFO_PROVIDER, { optional: true });
8554
9075
  }
8555
- async items() {
9076
+ async items(purpose) {
8556
9077
  const items = [];
8557
9078
  if (Array.isArray(this.providers)) {
8558
9079
  for (const provider of this.providers) {
8559
- items.push(...(await provider.items()));
9080
+ items.push(...(await provider.items(purpose)));
8560
9081
  }
8561
9082
  }
8562
9083
  return items;
8563
9084
  }
8564
- async get(name) {
8565
- return (await this.items()).find((c) => c.name == name);
9085
+ async get(name, purpose) {
9086
+ return (await this.items(purpose)).find((c) => c.name == name);
8566
9087
  }
8567
9088
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileTypeProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
8568
9089
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileTypeProviderService, providedIn: 'root' }); }
@@ -8572,27 +9093,437 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
8572
9093
  args: [{ providedIn: 'root' }]
8573
9094
  }] });
8574
9095
 
8575
- const AXP_INTEGRATION_PROVIDER = new InjectionToken('AXP_INTEGRATION_PROVIDER', {
8576
- providedIn: 'root',
8577
- factory: () => [],
8578
- });
8579
- const AXP_INTEGRATION_RUNTIME_PROVIDER = new InjectionToken('AXP_INTEGRATION_RUNTIME_PROVIDER', {
8580
- providedIn: 'root',
8581
- factory: () => [],
8582
- });
8583
- //#endregion
9096
+ /** Default catalog purposes for document-management (excludes conversation). */
9097
+ const AXP_DOCUMENT_FILE_TYPE_PURPOSES = ['system', 'document'];
9098
+ function normalizeDocumentFileTypePurposes(purpose) {
9099
+ if (!purpose) {
9100
+ return [...AXP_DOCUMENT_FILE_TYPE_PURPOSES];
9101
+ }
9102
+ return Array.isArray(purpose) ? purpose : [purpose];
9103
+ }
8584
9104
 
8585
- //#region ---- Integration provider context ----
8586
- class AXPIntegrationProviderContext {
8587
- constructor() {
8588
- //#region ---- State ----
8589
- this.definitions = new Map();
8590
- //#endregion
9105
+ const DEFAULT_ICON = 'fa-solid fa-file';
9106
+ const DEFAULT_TYPE_NAME = 'file';
9107
+ /**
9108
+ * Picks the best file name for extension-based icon lookup in the explorer.
9109
+ * Document display names may omit the extension while `fileId.name` retains it.
9110
+ */
9111
+ function resolveExplorerFileDisplayName(nodeName, fileId) {
9112
+ if (nodeName.includes('.')) {
9113
+ return nodeName;
8591
9114
  }
8592
- //#endregion
8593
- //#region ---- Builder API ----
8594
- /**
8595
- * Registers a provider definition. Throws when duplicate ids are registered.
9115
+ if (fileId != null && typeof fileId === 'object' && fileId.name?.includes('.')) {
9116
+ return fileId.name;
9117
+ }
9118
+ return nodeName;
9119
+ }
9120
+ /**
9121
+ * Resolves explorer / list icon and logical file type from the ACoreX file-type catalog.
9122
+ * Matches the file name extension against each catalog entry's `extensions`, then falls back
9123
+ * to the parent type icon (`video`, `audio`, `file`, …).
9124
+ */
9125
+ function resolveFileTypeDisplay(fileName, catalog) {
9126
+ const extension = (getFileExtension(fileName) ?? '').toLowerCase();
9127
+ if (!extension || catalog.length === 0) {
9128
+ return { icon: DEFAULT_ICON, typeName: DEFAULT_TYPE_NAME, extension };
9129
+ }
9130
+ for (const type of catalog) {
9131
+ const match = (type.extensions ?? []).find((ext) => ext.name?.toLowerCase() === extension);
9132
+ if (match) {
9133
+ return {
9134
+ icon: match.icon || type.icon || DEFAULT_ICON,
9135
+ typeName: type.name,
9136
+ extension,
9137
+ };
9138
+ }
9139
+ }
9140
+ return { icon: DEFAULT_ICON, typeName: DEFAULT_TYPE_NAME, extension };
9141
+ }
9142
+ //#endregion
9143
+
9144
+ //#region ---- File type open (catalog → AX registry) ----
9145
+ function createFileTypeOpenContext(injector, platformId) {
9146
+ return {
9147
+ injector,
9148
+ platformId,
9149
+ readAsDataUrl: (file) => new Promise((resolve, reject) => {
9150
+ const reader = new FileReader();
9151
+ reader.onload = () => resolve(reader.result);
9152
+ reader.onerror = () => reject(reader.error);
9153
+ reader.readAsDataURL(file);
9154
+ }),
9155
+ };
9156
+ }
9157
+ function buildFileTypeExtensionHint(fileName, payload) {
9158
+ if (payload instanceof File) {
9159
+ return {
9160
+ file: payload,
9161
+ extensionName: getFileExtension(payload.name) || getFileExtension(fileName) || undefined,
9162
+ };
9163
+ }
9164
+ const extensionName = getFileExtension(fileName) || undefined;
9165
+ if (!payload || typeof payload !== 'object') {
9166
+ return { extensionName };
9167
+ }
9168
+ const record = payload;
9169
+ const itemName = typeof record['name'] === 'string' ? record['name'] : fileName;
9170
+ const resolvedExtension = getFileExtension(itemName) || extensionName;
9171
+ const source = record['source'];
9172
+ if (source?.kind === 'blob' && source.value instanceof Blob) {
9173
+ return {
9174
+ extensionName: resolvedExtension,
9175
+ mimeType: source.value.type || undefined,
9176
+ };
9177
+ }
9178
+ return { extensionName: resolvedExtension };
9179
+ }
9180
+ /**
9181
+ * Returns whether the catalog-resolved file type has an `open` handler on the matched
9182
+ * extension or its parent type (extension-first, per {@link resolveFileTypeOpen}).
9183
+ */
9184
+ async function hasFileTypeOpenHandler(options) {
9185
+ const display = resolveFileTypeDisplay(options.fileName, options.catalog);
9186
+ const fileType = await options.fileService.getFileType(display.typeName);
9187
+ if (!fileType) {
9188
+ return false;
9189
+ }
9190
+ const extension = resolveFileTypeExtension(fileType, buildFileTypeExtensionHint(options.fileName, options.payload));
9191
+ return typeof resolveFileTypeOpen(fileType, extension) === 'function';
9192
+ }
9193
+ /**
9194
+ * Resolves extension → parent `open` and runs it when present.
9195
+ * Returns `true` when a handler ran; `false` when none exists (caller should download).
9196
+ */
9197
+ async function tryOpenFileByCatalogType(options) {
9198
+ const display = resolveFileTypeDisplay(options.fileName, options.catalog);
9199
+ const fileType = await options.fileService.getFileType(display.typeName);
9200
+ if (!fileType) {
9201
+ return false;
9202
+ }
9203
+ const extension = resolveFileTypeExtension(fileType, buildFileTypeExtensionHint(options.fileName, options.payload));
9204
+ if (!resolveFileTypeOpen(fileType, extension)) {
9205
+ return false;
9206
+ }
9207
+ const result = await runFileTypeOpen(fileType, options.openContext, options.payload, extension);
9208
+ return result !== false;
9209
+ }
9210
+ //#endregion
9211
+
9212
+ //#region ---- ACoreX file type bridge ----
9213
+ function mapExtension(ext) {
9214
+ return {
9215
+ name: ext.name,
9216
+ title: ext.title ?? ext.name,
9217
+ icon: ext.icon,
9218
+ };
9219
+ }
9220
+ function mapFileType(type) {
9221
+ return {
9222
+ name: type.name,
9223
+ title: type.title ?? type.name,
9224
+ icon: type.icon,
9225
+ metadata: type.metadata ?? { [AX_FILE_TYPE_METADATA_PURPOSE]: getFileTypePurposes(type) },
9226
+ extensions: (type.extensions ?? []).map(mapExtension),
9227
+ };
9228
+ }
9229
+ /**
9230
+ * Bridges {@link AXFileTypeRegistryService} into the platform {@link AXPFileTypeInfoProvider} token.
9231
+ * Excludes conversation-purpose types by default.
9232
+ */
9233
+ class AXPAcorexFileTypeBridgeProvider {
9234
+ constructor() {
9235
+ this.registry = inject(AXFileTypeRegistryService);
9236
+ }
9237
+ async items(purpose) {
9238
+ const types = await this.registry.getTypes({
9239
+ purpose: normalizeDocumentFileTypePurposes(purpose),
9240
+ });
9241
+ return types.map(mapFileType);
9242
+ }
9243
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeBridgeProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
9244
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeBridgeProvider }); }
9245
+ }
9246
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeBridgeProvider, decorators: [{
9247
+ type: Injectable
9248
+ }] });
9249
+
9250
+ //#region ---- ACoreX file type module ----
9251
+ /**
9252
+ * Registers ACoreX built-in file types (image, video, audio, file, document) and exposes them
9253
+ * through the platform {@link AXP_FILE_TYPE_INFO_PROVIDER} token.
9254
+ */
9255
+ class AXPAcorexFileTypeModule {
9256
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
9257
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeModule, imports: [i1$1.AXFileModule] }); }
9258
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeModule, providers: [
9259
+ {
9260
+ provide: AXP_FILE_TYPE_INFO_PROVIDER,
9261
+ useClass: AXPAcorexFileTypeBridgeProvider,
9262
+ multi: true,
9263
+ },
9264
+ ], imports: [AXFileModule.forRoot()] }); }
9265
+ }
9266
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeModule, decorators: [{
9267
+ type: NgModule,
9268
+ args: [{
9269
+ imports: [AXFileModule.forRoot()],
9270
+ providers: [
9271
+ {
9272
+ provide: AXP_FILE_TYPE_INFO_PROVIDER,
9273
+ useClass: AXPAcorexFileTypeBridgeProvider,
9274
+ multi: true,
9275
+ },
9276
+ ],
9277
+ }]
9278
+ }] });
9279
+
9280
+ //#region ---- Shared in-app inbox types ----
9281
+ //#endregion
9282
+
9283
+ //#region ---- Shared in-app inbox helpers ----
9284
+ function isInAppInboxUnread(readAt) {
9285
+ return readAt == null;
9286
+ }
9287
+ function isInAppInboxUnseen(seenAt) {
9288
+ return seenAt == null;
9289
+ }
9290
+ function getInAppInboxPriorityClass(priority) {
9291
+ return priority ?? 'Notice';
9292
+ }
9293
+ function normalizeInAppInboxItem(item) {
9294
+ return {
9295
+ id: String(item.id),
9296
+ title: item.title ?? '',
9297
+ body: item.body ?? '',
9298
+ createdAt: item.createdAt ? new Date(item.createdAt) : new Date(),
9299
+ seenAt: item.seenAt ? new Date(item.seenAt) : item.seenAt ?? null,
9300
+ readAt: item.readAt ? new Date(item.readAt) : item.readAt ?? null,
9301
+ sender: item.sender,
9302
+ priority: item.priority ?? 'Notice',
9303
+ isPinned: item.isPinned ?? false,
9304
+ category: item.category,
9305
+ };
9306
+ }
9307
+ //#endregion
9308
+
9309
+ //#region ---- In-app inbox data port ----
9310
+ const AXP_IN_APP_INBOX_PORT = new InjectionToken('AXP_IN_APP_INBOX_PORT');
9311
+ //#endregion
9312
+
9313
+ //#region ---- In-app inbox configuration tokens ----
9314
+ const AXP_IN_APP_INBOX_CONFIG = new InjectionToken('AXP_IN_APP_INBOX_CONFIG');
9315
+ const AXP_IN_APP_INBOX_I18N = new InjectionToken('AXP_IN_APP_INBOX_I18N');
9316
+ //#endregion
9317
+
9318
+ //#region ---- In-app inbox realtime events ----
9319
+ class AXPInAppInboxRealtimeService {
9320
+ constructor() {
9321
+ this.changedSubject = new Subject();
9322
+ this.changed$ = this.changedSubject.asObservable();
9323
+ }
9324
+ notifyChanged(event) {
9325
+ this.changedSubject.next(event);
9326
+ }
9327
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxRealtimeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
9328
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxRealtimeService, providedIn: 'root' }); }
9329
+ }
9330
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxRealtimeService, decorators: [{
9331
+ type: Injectable,
9332
+ args: [{
9333
+ providedIn: 'root',
9334
+ }]
9335
+ }] });
9336
+
9337
+ //#region ---- Shared in-app inbox connector ----
9338
+ class AXPInAppInboxConnectorService {
9339
+ constructor() {
9340
+ this.port = inject(AXP_IN_APP_INBOX_PORT);
9341
+ this.realtime = inject(AXPInAppInboxRealtimeService);
9342
+ this.destroyRef = inject(DestroyRef);
9343
+ this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
9344
+ this.pageLoading = signal(false, ...(ngDevMode ? [{ debugName: "pageLoading" }] : /* istanbul ignore next */ []));
9345
+ this.error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
9346
+ this.items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
9347
+ this.totalCount = signal(0, ...(ngDevMode ? [{ debugName: "totalCount" }] : /* istanbul ignore next */ []));
9348
+ this.pageItems = signal([], ...(ngDevMode ? [{ debugName: "pageItems" }] : /* istanbul ignore next */ []));
9349
+ this.pageTotalCount = signal(0, ...(ngDevMode ? [{ debugName: "pageTotalCount" }] : /* istanbul ignore next */ []));
9350
+ this.capabilities = this.port.capabilities;
9351
+ this.loading = computed(() => this.isLoading(), ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
9352
+ this.pageLoadingState = computed(() => this.pageLoading(), ...(ngDevMode ? [{ debugName: "pageLoadingState" }] : /* istanbul ignore next */ []));
9353
+ this.errorMessage = computed(() => this.error(), ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
9354
+ this.inboxList = computed(() => this.items(), ...(ngDevMode ? [{ debugName: "inboxList" }] : /* istanbul ignore next */ []));
9355
+ this.total = computed(() => this.totalCount(), ...(ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []));
9356
+ this.pagedInboxList = computed(() => this.pageItems(), ...(ngDevMode ? [{ debugName: "pagedInboxList" }] : /* istanbul ignore next */ []));
9357
+ this.pagedTotal = computed(() => this.pageTotalCount(), ...(ngDevMode ? [{ debugName: "pagedTotal" }] : /* istanbul ignore next */ []));
9358
+ this.unreadCount = computed(() => this.items().filter((item) => isInAppInboxUnread(item.readAt)).length, ...(ngDevMode ? [{ debugName: "unreadCount" }] : /* istanbul ignore next */ []));
9359
+ void this.refresh();
9360
+ this.realtime.changed$
9361
+ .pipe(filter((event) => event.type !== 'seen' && event.type !== 'read'), debounceTime(100), takeUntilDestroyed(this.destroyRef))
9362
+ .subscribe(() => {
9363
+ if (!this.isLoading()) {
9364
+ void this.refresh();
9365
+ }
9366
+ });
9367
+ this.realtime.changed$
9368
+ .pipe(filter((event) => event.type === 'seen' || event.type === 'read'), takeUntilDestroyed(this.destroyRef))
9369
+ .subscribe((event) => this.syncEngagement(event.ids, event.type));
9370
+ }
9371
+ async refresh() {
9372
+ try {
9373
+ this.isLoading.set(true);
9374
+ this.error.set(null);
9375
+ const response = await this.port.loadInbox({ skip: 0, take: 1000 });
9376
+ const items = response.items.map((item) => normalizeInAppInboxItem(item));
9377
+ this.items.set(items);
9378
+ this.totalCount.set(response.total);
9379
+ return { items, total: response.total };
9380
+ }
9381
+ catch (err) {
9382
+ this.error.set(err instanceof Error ? err.message : 'Failed to load inbox');
9383
+ this.items.set([]);
9384
+ this.totalCount.set(0);
9385
+ return { items: [], total: 0 };
9386
+ }
9387
+ finally {
9388
+ this.isLoading.set(false);
9389
+ }
9390
+ }
9391
+ async loadPage(skip, take) {
9392
+ try {
9393
+ this.pageLoading.set(true);
9394
+ this.error.set(null);
9395
+ const result = await this.port.loadInbox({ skip, take });
9396
+ const items = result.items.map((item) => normalizeInAppInboxItem(item));
9397
+ this.pageItems.set(items);
9398
+ this.pageTotalCount.set(result.total);
9399
+ return { items, total: result.total };
9400
+ }
9401
+ catch (err) {
9402
+ this.error.set(err instanceof Error ? err.message : 'Failed to load inbox page');
9403
+ this.pageItems.set([]);
9404
+ this.pageTotalCount.set(0);
9405
+ return { items: [], total: 0 };
9406
+ }
9407
+ finally {
9408
+ this.pageLoading.set(false);
9409
+ }
9410
+ }
9411
+ async markUnseenAsSeen() {
9412
+ if (!this.port.capabilities.seenTracking) {
9413
+ return;
9414
+ }
9415
+ const unseenIds = this.items()
9416
+ .filter((item) => isInAppInboxUnseen(item.seenAt))
9417
+ .map((item) => item.id);
9418
+ if (unseenIds.length === 0) {
9419
+ return;
9420
+ }
9421
+ await this.port.markSeen(unseenIds);
9422
+ this.realtime.notifyChanged({ type: 'seen', ids: unseenIds });
9423
+ }
9424
+ async markAsRead(ids) {
9425
+ if (ids.length === 0 || !this.port.capabilities.readTracking) {
9426
+ return;
9427
+ }
9428
+ await this.port.markRead(ids);
9429
+ this.realtime.notifyChanged({ type: 'read', ids });
9430
+ }
9431
+ async markAllAsRead() {
9432
+ if (!this.port.capabilities.readTracking) {
9433
+ return;
9434
+ }
9435
+ await this.port.markAllRead();
9436
+ const readAt = new Date();
9437
+ const patchAll = (list) => list.map((item) => isInAppInboxUnread(item.readAt)
9438
+ ? { ...item, readAt, seenAt: item.seenAt ?? readAt }
9439
+ : item);
9440
+ this.items.update(patchAll);
9441
+ this.pageItems.update(patchAll);
9442
+ }
9443
+ async togglePin(id) {
9444
+ if (!this.port.capabilities.pinSupport || !this.port.togglePin) {
9445
+ return;
9446
+ }
9447
+ await this.port.togglePin(id);
9448
+ await this.refresh();
9449
+ }
9450
+ syncEngagement(ids, kind) {
9451
+ if (!ids?.length) {
9452
+ return;
9453
+ }
9454
+ const idSet = new Set(ids);
9455
+ const now = new Date();
9456
+ const patch = (list) => list.map((item) => {
9457
+ if (!idSet.has(item.id)) {
9458
+ return item;
9459
+ }
9460
+ if (kind === 'seen') {
9461
+ return item.seenAt ? item : { ...item, seenAt: now };
9462
+ }
9463
+ return {
9464
+ ...item,
9465
+ seenAt: item.seenAt ?? now,
9466
+ readAt: item.readAt ?? now,
9467
+ };
9468
+ });
9469
+ this.items.update(patch);
9470
+ this.pageItems.update(patch);
9471
+ }
9472
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
9473
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxConnectorService, providedIn: 'root' }); }
9474
+ }
9475
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxConnectorService, decorators: [{
9476
+ type: Injectable,
9477
+ args: [{
9478
+ providedIn: 'root',
9479
+ }]
9480
+ }], ctorParameters: () => [] });
9481
+
9482
+ const AXP_INTEGRATION_PROVIDER = new InjectionToken('AXP_INTEGRATION_PROVIDER', {
9483
+ providedIn: 'root',
9484
+ factory: () => [],
9485
+ });
9486
+ const AXP_INTEGRATION_RUNTIME_PROVIDER = new InjectionToken('AXP_INTEGRATION_RUNTIME_PROVIDER', {
9487
+ providedIn: 'root',
9488
+ factory: () => [],
9489
+ });
9490
+ //#endregion
9491
+
9492
+ const AXP_INTEGRATION_DOMAIN_PROVIDER = new InjectionToken('AXP_INTEGRATION_DOMAIN_PROVIDER', {
9493
+ providedIn: 'root',
9494
+ factory: () => [],
9495
+ });
9496
+ //#endregion
9497
+
9498
+ //#region ---- Integration domain context ----
9499
+ class AXPIntegrationDomainProviderContext {
9500
+ constructor() {
9501
+ this.definitions = new Map();
9502
+ }
9503
+ register(definition) {
9504
+ // Idempotent: multiple extensions (e.g. Telegram + WhatsApp) may register the same domain.
9505
+ if (this.definitions.has(definition.id)) {
9506
+ return;
9507
+ }
9508
+ this.definitions.set(definition.id, definition);
9509
+ }
9510
+ getDefinitions() {
9511
+ return this.definitions;
9512
+ }
9513
+ }
9514
+ //#endregion
9515
+
9516
+ //#region ---- Integration provider context ----
9517
+ class AXPIntegrationProviderContext {
9518
+ constructor() {
9519
+ //#region ---- State ----
9520
+ this.definitions = new Map();
9521
+ //#endregion
9522
+ }
9523
+ //#endregion
9524
+ //#region ---- Builder API ----
9525
+ /**
9526
+ * Registers a provider definition. Throws when duplicate ids are registered.
8596
9527
  */
8597
9528
  register(definition) {
8598
9529
  if (this.definitions.has(definition.id)) {
@@ -8608,49 +9539,125 @@ class AXPIntegrationProviderContext {
8608
9539
  }
8609
9540
  //#endregion
8610
9541
 
8611
- //#region ---- Integration provider registry ----
8612
- class AXPIntegrationProviderRegistryService {
9542
+ //#region ---- Integration domain registry ----
9543
+ class AXPIntegrationDomainRegistryService {
8613
9544
  constructor() {
8614
- //#region ---- Dependencies ----
8615
- this.providers = inject(AXP_INTEGRATION_PROVIDER, { optional: true });
8616
- //#endregion
8617
- //#region ---- State ----
8618
- this.cache = null;
9545
+ this.domainProviders = inject(AXP_INTEGRATION_DOMAIN_PROVIDER, { optional: true });
9546
+ this.integrationProviders = inject(AXP_INTEGRATION_PROVIDER, { optional: true });
9547
+ this.domainCache = null;
9548
+ this.providerCache = null;
8619
9549
  }
8620
- //#endregion
8621
- //#region ---- Public API ----
8622
- async list() {
8623
- const map = await this.load();
9550
+ async listDomains() {
9551
+ const map = await this.loadDomains();
9552
+ return Array.from(map.values()).sort((a, b) => defaultTo(a.sortOrder, 100) - defaultTo(b.sortOrder, 100));
9553
+ }
9554
+ async getDomain(id) {
9555
+ const map = await this.loadDomains();
9556
+ return map.get(id) ?? null;
9557
+ }
9558
+ async getDomainOrThrow(id) {
9559
+ const domain = await this.getDomain(id);
9560
+ if (!domain) {
9561
+ throw new Error(`[AXPIntegrationDomainRegistry] Unknown integration domain '${id}'.`);
9562
+ }
9563
+ return domain;
9564
+ }
9565
+ async listProviders() {
9566
+ const map = await this.loadProviders();
8624
9567
  return Array.from(map.values());
8625
9568
  }
8626
- async get(id) {
8627
- const map = await this.load();
9569
+ async listProvidersByDomain(domainId) {
9570
+ const providers = await this.listProviders();
9571
+ return providers.filter((provider) => provider.domainId === domainId);
9572
+ }
9573
+ async getProvider(id) {
9574
+ const map = await this.loadProviders();
8628
9575
  return map.get(id) ?? null;
8629
9576
  }
8630
- async getOrThrow(id) {
8631
- const definition = await this.get(id);
8632
- if (!definition) {
8633
- throw new Error(`[AXPIntegrationProviderRegistry] Unknown integration provider '${id}'.`);
9577
+ async getProviderOrThrow(id) {
9578
+ const provider = await this.getProvider(id);
9579
+ if (!provider) {
9580
+ throw new Error(`[AXPIntegrationDomainRegistry] Unknown integration provider '${id}'.`);
8634
9581
  }
8635
- return definition;
9582
+ return provider;
8636
9583
  }
8637
9584
  clearCache() {
8638
- this.cache = null;
9585
+ this.domainCache = null;
9586
+ this.providerCache = null;
8639
9587
  }
8640
- //#endregion
8641
- //#region ---- Private Methods ----
8642
- async load() {
8643
- if (this.cache) {
8644
- return this.cache;
9588
+ normalizeProviders(providers) {
9589
+ if (!providers) {
9590
+ return [];
9591
+ }
9592
+ return Array.isArray(providers) ? providers : [providers];
9593
+ }
9594
+ async loadDomains() {
9595
+ if (this.domainCache) {
9596
+ return this.domainCache;
9597
+ }
9598
+ const context = new AXPIntegrationDomainProviderContext();
9599
+ for (const provider of this.normalizeProviders(this.domainProviders)) {
9600
+ const resolved = provider instanceof Promise ? await provider : provider;
9601
+ await resolved.provide(context);
8645
9602
  }
9603
+ this.domainCache = new Map(context.getDefinitions());
9604
+ return this.domainCache;
9605
+ }
9606
+ async loadProviders() {
9607
+ if (this.providerCache) {
9608
+ return this.providerCache;
9609
+ }
9610
+ const domains = await this.loadDomains();
8646
9611
  const context = new AXPIntegrationProviderContext();
8647
- const providerList = this.providers ?? [];
8648
- for (const provider of providerList) {
9612
+ for (const provider of this.normalizeProviders(this.integrationProviders)) {
8649
9613
  const resolved = provider instanceof Promise ? await provider : provider;
8650
9614
  await resolved.provide(context);
8651
9615
  }
8652
- this.cache = new Map(context.getDefinitions());
8653
- return this.cache;
9616
+ const resolvedProviders = new Map();
9617
+ for (const definition of context.getDefinitions().values()) {
9618
+ resolvedProviders.set(definition.id, this.resolveProviderDefinition(definition, domains));
9619
+ }
9620
+ this.providerCache = resolvedProviders;
9621
+ return this.providerCache;
9622
+ }
9623
+ resolveProviderDefinition(definition, domains) {
9624
+ const domain = domains.get(definition.domainId);
9625
+ if (!domain) {
9626
+ throw new Error(`[AXPIntegrationDomainRegistry] Provider '${definition.id}' references unknown domain '${definition.domainId}'.`);
9627
+ }
9628
+ const domainCapabilities = defaultTo(domain.capabilities, []);
9629
+ const providerCapabilities = defaultTo(definition.capabilities, []);
9630
+ return {
9631
+ ...definition,
9632
+ category: domain.category,
9633
+ capabilities: uniq([...domainCapabilities, ...providerCapabilities]),
9634
+ };
9635
+ }
9636
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
9637
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryService, providedIn: 'root' }); }
9638
+ }
9639
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryService, decorators: [{
9640
+ type: Injectable,
9641
+ args: [{ providedIn: 'root' }]
9642
+ }] });
9643
+
9644
+ //#region ---- Integration provider registry ----
9645
+ /** @deprecated Use {@link AXPIntegrationDomainRegistryService} for domain-aware provider access. */
9646
+ class AXPIntegrationProviderRegistryService {
9647
+ constructor() {
9648
+ this.domainRegistry = inject(AXPIntegrationDomainRegistryService);
9649
+ }
9650
+ async list() {
9651
+ return this.domainRegistry.listProviders();
9652
+ }
9653
+ async get(id) {
9654
+ return this.domainRegistry.getProvider(id);
9655
+ }
9656
+ async getOrThrow(id) {
9657
+ return this.domainRegistry.getProviderOrThrow(id);
9658
+ }
9659
+ clearCache() {
9660
+ this.domainRegistry.clearCache();
8654
9661
  }
8655
9662
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationProviderRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
8656
9663
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationProviderRegistryService, providedIn: 'root' }); }
@@ -8659,6 +9666,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
8659
9666
  type: Injectable,
8660
9667
  args: [{ providedIn: 'root' }]
8661
9668
  }] });
9669
+ /** Convenience alias for domain listing. */
9670
+ class AXPIntegrationDomainRegistryFacade {
9671
+ constructor() {
9672
+ this.domainRegistry = inject(AXPIntegrationDomainRegistryService);
9673
+ }
9674
+ listDomains() {
9675
+ return this.domainRegistry.listDomains();
9676
+ }
9677
+ listProvidersByDomain(domainId) {
9678
+ return this.domainRegistry.listProvidersByDomain(domainId);
9679
+ }
9680
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
9681
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryFacade, providedIn: 'root' }); }
9682
+ }
9683
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryFacade, decorators: [{
9684
+ type: Injectable,
9685
+ args: [{ providedIn: 'root' }]
9686
+ }] });
8662
9687
 
8663
9688
  const AXP_INTEGRATION_SECRET_STORE = new InjectionToken('AXP_INTEGRATION_SECRET_STORE');
8664
9689
  class AXPIntegrationRuntimeService {
@@ -8860,7 +9885,7 @@ class AXPStatusDefinitionProviderService {
8860
9885
  // Execute the command
8861
9886
  const result = await this.commandService.execute(commandName, commandOptions);
8862
9887
  if (!result?.success) {
8863
- const text = this.commandMessageTextForError(result?.message?.text);
9888
+ const text = commandMessageTextForError(result?.message?.text);
8864
9889
  throw new Error(text || 'Failed to execute status transition command');
8865
9890
  }
8866
9891
  }
@@ -8871,23 +9896,6 @@ class AXPStatusDefinitionProviderService {
8871
9896
  isValidTransition(provider, from, to) {
8872
9897
  return provider.transitions.some((transition) => transition.from === from && transition.to === to);
8873
9898
  }
8874
- /**
8875
- * Best-effort plain string for {@link Error} messages (no i18n lookup).
8876
- */
8877
- commandMessageTextForError(value) {
8878
- if (value == null) {
8879
- return '';
8880
- }
8881
- if (typeof value === 'string') {
8882
- return value;
8883
- }
8884
- if (typeof value === 'object' && !Array.isArray(value)) {
8885
- const values = Object.values(value);
8886
- const first = values.find((v) => typeof v === 'string' && v.length > 0);
8887
- return first ?? '';
8888
- }
8889
- return String(value);
8890
- }
8891
9899
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStatusDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
8892
9900
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStatusDefinitionProviderService, providedIn: 'root' }); }
8893
9901
  }
@@ -8899,6 +9907,76 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
8899
9907
  //#region ---- Types ----
8900
9908
  //#endregion
8901
9909
 
9910
+ //#endregion
9911
+ //#region ---- Constants ----
9912
+ const SESSION_KEY_PREFIX = 'axp-entity-list-return:';
9913
+ //#endregion
9914
+ //#region ---- Route Parsing ----
9915
+ /** Parses an entity master list route (`.../m/{module}/e/{entity}/list`). */
9916
+ function axpParseEntityListRoute(url) {
9917
+ const path = url.split('?')[0].split('#')[0];
9918
+ const match = path.match(/\/m\/([^/]+)\/e\/([^/]+)\/list$/);
9919
+ if (!match) {
9920
+ return null;
9921
+ }
9922
+ return {
9923
+ module: decodeURIComponent(match[1]),
9924
+ entity: decodeURIComponent(match[2]),
9925
+ };
9926
+ }
9927
+ /** Parses an entity details route (`.../m/{module}/e/{entity}/{id}/view`). */
9928
+ function axpParseEntityDetailsRoute(url) {
9929
+ const path = url.split('?')[0].split('#')[0];
9930
+ const match = path.match(/\/m\/([^/]+)\/e\/([^/]+)\/([^/]+)\/view$/);
9931
+ if (!match) {
9932
+ return null;
9933
+ }
9934
+ return {
9935
+ module: decodeURIComponent(match[1]),
9936
+ entity: decodeURIComponent(match[2]),
9937
+ id: decodeURIComponent(match[3]),
9938
+ };
9939
+ }
9940
+ //#endregion
9941
+ //#region ---- Session Storage ----
9942
+ function buildStorageKey(module, entity) {
9943
+ return `${SESSION_KEY_PREFIX}${module}.${entity}`;
9944
+ }
9945
+ /** Persists the last list URL (including query params) used before opening entity details. */
9946
+ function axpSaveEntityListReturnUrl(module, entity, url) {
9947
+ if (!axpIsEntityListPath(url)) {
9948
+ return;
9949
+ }
9950
+ const parsed = axpParseEntityListRoute(url);
9951
+ if (!parsed || parsed.module !== module || parsed.entity !== entity) {
9952
+ return;
9953
+ }
9954
+ try {
9955
+ sessionStorage.setItem(buildStorageKey(module, entity), normalizeRouterUrl(url));
9956
+ }
9957
+ catch {
9958
+ // sessionStorage may be unavailable
9959
+ }
9960
+ }
9961
+ /** Returns the stored list URL for the entity, or the provided fallback path. */
9962
+ function axpGetEntityListReturnUrl(module, entity, fallbackPath) {
9963
+ try {
9964
+ const stored = sessionStorage.getItem(buildStorageKey(module, entity));
9965
+ if (!stored || !axpIsEntityListPath(stored)) {
9966
+ return fallbackPath;
9967
+ }
9968
+ const parsed = axpParseEntityListRoute(stored);
9969
+ if (parsed?.module === module && parsed.entity === entity) {
9970
+ return stored;
9971
+ }
9972
+ }
9973
+ catch {
9974
+ // sessionStorage may be unavailable
9975
+ }
9976
+ return fallbackPath;
9977
+ }
9978
+ //#endregion
9979
+
8902
9980
  class AXPClipBoardService {
8903
9981
  constructor() {
8904
9982
  //#region ---- Services & Dependencies ----
@@ -9252,9 +10330,9 @@ class AXMOrgChartPrintPage extends AXBasePageComponent {
9252
10330
  });
9253
10331
  }
9254
10332
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMOrgChartPrintPage, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
9255
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: AXMOrgChartPrintPage, isStandalone: true, selector: "ng-component", inputs: { bgcolor: { classPropertyName: "bgcolor", publicName: "bgcolor", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { bgcolor: "bgcolorChange", width: "widthChange", height: "heightChange", quality: "qualityChange", scale: "scaleChange" }, usesInheritance: true, ngImport: i0, template: ` <div class="ax-grid ax-grid-cols-[auto_18rem] ax-gap-4 ax-justify-center ax-p-4 ax-items-center">
10333
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: AXMOrgChartPrintPage, isStandalone: true, selector: "ng-component", inputs: { bgcolor: { classPropertyName: "bgcolor", publicName: "bgcolor", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { bgcolor: "bgcolorChange", width: "widthChange", height: "heightChange", quality: "qualityChange", scale: "scaleChange" }, usesInheritance: true, ngImport: i0, template: ` <div class="grid grid-cols-[auto_18rem] gap-4 justify-center p-4 items-center">
9256
10334
  <ax-label>Resolution (px)</ax-label>
9257
- <div class="ax-flex ax-gap-2 ax-items-center">
10335
+ <div class="flex gap-2 items-center">
9258
10336
  <ax-number-box
9259
10337
  [changeOnScroll]="true"
9260
10338
  [decimals]="4"
@@ -9301,14 +10379,14 @@ class AXMOrgChartPrintPage extends AXBasePageComponent {
9301
10379
  <ax-icon class="fa-solid fa-print"> </ax-icon>
9302
10380
  </ax-button>
9303
10381
  </ax-suffix>
9304
- </ax-footer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "ngmodule", type: AXNumberBoxModule }, { kind: "component", type: i2$2.AXNumberBoxComponent, selector: "ax-number-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "minValue", "maxValue", "showSpinButtons", "thousandsSeparator", "decimals", "changeOnScroll", "step"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "thousandsSeparatorChange"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "ngmodule", type: AXLabelModule }, { kind: "component", type: i3$2.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i4.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: AXButtonModule }, { kind: "component", type: i1.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: AXColorBoxModule }, { kind: "component", type: i6.AXColorBoxComponent, selector: "ax-color-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "showBadge", "showValue", "showClearButton", "showIcon"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed"] }] }); }
10382
+ </ax-footer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "ngmodule", type: AXNumberBoxModule }, { kind: "component", type: i2$2.AXNumberBoxComponent, selector: "ax-number-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "minValue", "maxValue", "showSpinButtons", "thousandsSeparator", "decimals", "changeOnScroll", "step"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "thousandsSeparatorChange"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "ngmodule", type: AXLabelModule }, { kind: "component", type: i3$2.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i4.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: AXButtonModule }, { kind: "component", type: i1.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: AXColorBoxModule }, { kind: "component", type: i6.AXColorBoxComponent, selector: "ax-color-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "showBadge", "showValue", "showClearButton", "showIcon"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed"] }] }); }
9305
10383
  }
9306
10384
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMOrgChartPrintPage, decorators: [{
9307
10385
  type: Component,
9308
10386
  args: [{
9309
- template: ` <div class="ax-grid ax-grid-cols-[auto_18rem] ax-gap-4 ax-justify-center ax-p-4 ax-items-center">
10387
+ template: ` <div class="grid grid-cols-[auto_18rem] gap-4 justify-center p-4 items-center">
9310
10388
  <ax-label>Resolution (px)</ax-label>
9311
- <div class="ax-flex ax-gap-2 ax-items-center">
10389
+ <div class="flex gap-2 items-center">
9312
10390
  <ax-number-box
9313
10391
  [changeOnScroll]="true"
9314
10392
  [decimals]="4"
@@ -9459,9 +10537,99 @@ class AXPVersioningService {
9459
10537
  }
9460
10538
  //#endregion
9461
10539
 
10540
+ //#endregion
10541
+ //#region ---- Helpers ----
10542
+ function axpResolveNavigatePath(input) {
10543
+ if (!input) {
10544
+ return undefined;
10545
+ }
10546
+ if (typeof input.options?.path === 'string') {
10547
+ return input.options.path;
10548
+ }
10549
+ if (typeof input.path === 'string') {
10550
+ return input.path;
10551
+ }
10552
+ return undefined;
10553
+ }
10554
+ function axpResolveNavigateExtras(input) {
10555
+ return input?.options?.extras;
10556
+ }
10557
+ //#endregion
10558
+ //#region ---- Navigate Command ----
10559
+ class AXPNavigateCommand {
10560
+ constructor() {
10561
+ this.tabNavigation = inject(AXPTabNavigationService);
10562
+ }
10563
+ async execute(input = {}) {
10564
+ const path = axpResolveNavigatePath(input);
10565
+ if (!path) {
10566
+ console.error('Path is required for navigate command');
10567
+ return {
10568
+ success: false,
10569
+ message: {
10570
+ text: 'Path is required for navigate command',
10571
+ },
10572
+ };
10573
+ }
10574
+ const extras = axpResolveNavigateExtras(input);
10575
+ if (path.toLowerCase().startsWith('http') || extras?.target === 'blank') {
10576
+ window.open(path, '_blank');
10577
+ }
10578
+ else {
10579
+ await this.tabNavigation.navigate(path, extras);
10580
+ }
10581
+ return { success: true };
10582
+ }
10583
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavigateCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
10584
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavigateCommand, providedIn: 'root' }); }
10585
+ }
10586
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavigateCommand, decorators: [{
10587
+ type: Injectable,
10588
+ args: [{ providedIn: 'root' }]
10589
+ }] });
10590
+
10591
+ var navigate_command = /*#__PURE__*/Object.freeze({
10592
+ __proto__: null,
10593
+ AXPNavigateCommand: AXPNavigateCommand,
10594
+ axpResolveNavigatePath: axpResolveNavigatePath
10595
+ });
10596
+
10597
+ /**
10598
+ * Build-time only. Do not import from Angular modules.
10599
+ */
10600
+ const axpNavigateCommandDefinition = defineCommand({
10601
+ key: 'navigate',
10602
+ title: 'Navigate',
10603
+ description: 'AXPNavigateCommand resolves a router path from input.path or input.options.path, opens external URLs in a new tab, otherwise navigates via AXPTabNavigationService.',
10604
+ executionMode: 'frontend',
10605
+ inputs: [
10606
+ {
10607
+ name: 'path',
10608
+ title: 'Path',
10609
+ description: 'Router path or absolute URL (AXPNavigateCommandInput.path or input.options.path).',
10610
+ interface: { name: 'text-editor' },
10611
+ validations: [{ rule: 'required' }],
10612
+ },
10613
+ ],
10614
+ outcomes: {
10615
+ mode: 'static',
10616
+ values: ['success', 'failure'],
10617
+ },
10618
+ ai: {
10619
+ tags: ['navigation', 'router'],
10620
+ },
10621
+ categories: [AXP_COMMAND_DEFINITION_CATEGORY_PLATFORM],
10622
+ });
10623
+
10624
+ const AXP_ENTITY_DELETED_EVENT_TYPE = '[Entity] Deleted';
10625
+
10626
+ const AXPRedirectEvent = createWorkFlowEvent('Redirect Event Fired');
10627
+ const AXPRefreshEvent = createWorkFlowEvent('Refresh Event Fired');
10628
+ const AXPReloadEvent = createWorkFlowEvent('Reload Event Fired');
10629
+
9462
10630
  /**
9463
10631
  * Generated bundle index. Do not edit.
9464
10632
  */
9465
10633
 
9466
- export { ALL_DEFAULT_OPERATORS, AXMWorkflowErrorHandler, AXPAppVersionService, AXPBackgroundOperationCompletionService, AXPBackgroundOperationEntityStoreService, AXPBackgroundOperationHandler, AXPBackgroundOperationNotificationService, AXPBackgroundOperationProvider, AXPBackgroundOperationRootConfig, AXPBackgroundOperationService, AXPBackgroundOperationSlotComponent, AXPBrowserTitleService, AXPCleanNestedFilters, AXPClipBoardService, AXPCommonModule, AXPCommonSettings, AXPCustomOperatorService, AXPCustomOperatorServiceImpl, AXPDataProvider, AXPDefaultMultiLanguageConfigService, AXPDialogConfirmAction, AXPErrorHandlerRegistryService, AXPExportService, AXPFileActionsService, AXPFileStorageEvaluatorScopeProvider, AXPFileStorageService, AXPFileTypeProviderService, AXPFilterOperatorMiddlewareService, AXPFilterOperatorMiddlewareServiceImpl, AXPFooterTextSlotComponent, AXPGlobalErrorHandler, AXPHomePageModule, AXPHomePageService, AXPIndexedDbSettingValueProvider, AXPIntegrationOAuthService, AXPIntegrationProviderContext, AXPIntegrationProviderRegistryService, AXPIntegrationRuntimeService, AXPKeyboardShortcutsHelpComponent, AXPKeyboardShortcutsHelpService, AXPLockService, AXPMenuItemsDataSourceDefinition, AXPMenuKeyboardShortcutService, AXPMenuMiddlewareRegistry, AXPMenuProviderService, AXPMenuRouteAccessService, AXPMenuRouteGuard, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateWorkflow, AXPNotFoundCatchAllRoute, AXPNotFoundError, AXPOutputContractTranscriptSegmentService, AXPPlatformCommonDataSourceKeys, AXPPlatformDefaultConfigs, AXPRedirectEvent, AXPRefreshEvent, AXPRegionalCalendarService, AXPReloadAction, AXPReloadEvent, AXPSearchCommandProvider, AXPSearchDefinitionActionBuilder, AXPSearchDefinitionBuilder, AXPSearchDefinitionProviderContext, AXPSearchDefinitionProviderService, AXPSearchService, AXPSettingDefaultValuesAggregatorService, AXPSettingDefinitionGroupBuilder, AXPSettingDefinitionProviderContext, AXPSettingDefinitionProviderService, AXPSettingDefinitionSectionBuilder, AXPSettingsBulkSyncService, AXPSettingsEvaluatorScopeProvider, AXPSettingsIndexedDb, AXPSettingsService, AXPStatusDefinitionProviderService, AXPStickyDirective, AXPTabNavigationService, AXPTabPreviewService, AXPTabRouteCacheRegistry, AXPToastAction, AXPTokenDefinitionService, AXPTokenEvaluatorScopeProvider, AXPTranslateFormatter, AXPUnsavedChangesConfirmService, AXPUnsavedChangesPopstateService, AXPVersioningService, AXPWorkflowNavigateAction, AXPWorkflowRouterNavigateAction, AXP_AGENT_OUTPUT_CONTRACT_DEFAULT_STRUCTURED_RETRIES, AXP_APP_VERSION_PROVIDER, AXP_BACKGROUND_OPERATION_ENTITY_STORAGE, AXP_BACKGROUND_OPERATION_HANDLERS, AXP_BACKGROUND_OPERATION_PROVIDERS, AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE, AXP_FILE_ACTION_PROVIDER, AXP_FILE_TYPE_INFO_PROVIDER, AXP_HOME_PAGES, AXP_HOME_PAGE_DEFAULT_KEY, AXP_HOME_TAB_KEY, AXP_INTEGRATION_CONNECTION_ESTABLISHED, AXP_INTEGRATION_OAUTH_SERVICE, AXP_INTEGRATION_PROVIDER, AXP_INTEGRATION_RUNTIME_PROVIDER, AXP_INTEGRATION_SECRET_STORE, AXP_IN_APP_NOTIFICATION_SERVICE, AXP_LOCALE_MANAGEMENT_PORT, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER, AXP_NOT_FOUND_CATCH_ALL_ROUTE, AXP_NOT_FOUND_ROUTE, AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER, AXP_PLATFORM_CONFIG_TOKEN, AXP_PROTECTED_ROUTE_GUARDS, AXP_ROOT_CONFIG_TOKEN, AXP_SEARCH_DEFINITION_LAZY_RESOLVER, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SETTINGS_CACHE_SYNC, AXP_SETTINGS_SYNC_DEBOUNCE_MS, AXP_SETTINGS_SYNC_KEYS, AXP_SETTINGS_SYNC_RETRY_BACKOFF_MS, AXP_SETTINGS_SYNC_TTL_MS, AXP_SETTING_DEFAULT_VALUES_PROVIDERS, AXP_SETTING_DEFINITION_PROVIDER, AXP_SETTING_VALUE_PROVIDER, AXP_STATUS_PROVIDERS, AXP_TAB_BREADCRUMB_JOIN_SEPARATOR, AXP_TAB_ROUTE_DATA_KEY, AXP_TOKEN_DEFINITION_PROVIDER, AXP_UNAUTHORIZED_ROUTE, AXVChangeType, BETWEEN_OPER, BOOLEAN_OPERATORS, CONTAINS_OPER, DATE_OPERATORS, DEFAULT_DATE_FILTER_PRESETS, DEFAULT_MULTILANGUAGE_FIELD_NAMES, ENDS_WITH_OPER, ENVIRONMENT, EQ_OPER, GTE_OPER, GT_OPER, IN_OPER, IS_EMPTY_OPER, IS_NOT_EMPTY_OPER, LTE_OPER, LT_OPER, MULTILANGUAGE_CAPABLE_WIDGET_TYPES, NOT_CONTAINS_OPER, NOT_EQ_OPER, NUMBER_OPERATORS, SETTINGS_TRACE_NS, SETTINGS_TRACE_TITLE, STARTS_WITH_OPER, STRING_OPERATORS, UploadFromComputerActionProvider, applyDateFilterPreset, axpBackgroundOperationCapabilities, axpBackgroundOperationDisplayTime, axpBackgroundOperationEntityName, axpBackgroundOperationEstimateEndDate, axpBackgroundOperationFailurePolicy, axpBackgroundOperationFromEntityModel, axpBackgroundOperationRemainingMs, axpBackgroundOperationToEntityModel, axpBuildBackgroundOperation, axpBuildTabKey, axpCoerceBackgroundOperationDate, axpCreateBackgroundOperationId, axpFallbackTabTitle, axpFindMenuItemByRoute, axpGetLeafRouteSnapshot, axpHasTabScope, axpIsActiveBackgroundOperationStatus, axpIsCompletedBackgroundOperationStatus, axpIsEntityDetailsPath, axpIsEntityDetailsViewRoute, axpIsEntityListPath, axpIsEntityListRoute, axpIsEntityRecordNotFound, axpIsTabEligibleUrl, axpJoinTabTitleSegments, axpMenuPathsMatch, axpNavigateAppPath, axpParseAppPath, axpPathFromSnapshot, axpRedirectToNotFound, axpRedirectToUnauthorized, axpReplaceEntityListRouteQueryParams, axpResolveTabKey, axpResolveTabKeyFromRouteConfig, axpResolveTabKeyFromSnapshot, axpResolveTabTitleParts, axpSettingsIndexedDb, backgroundOperationEntityFactory, buildScopedSettingsSnapshotId, coerceAXPSettingRawValue, coerceAXPSettingRawValueByKind, configPlatform, createBackgroundOperationStore, createDefaultSettingValueProviders, createEmptyScopedSettingsSnapshot, createEntityCommandOptions, createEntityRowExpressionScope, createEntitySearchCommand, createIndexedDbSettingValueProviders, createMenuContext, createMenuMiddleware, createUnsavedChangesCanDeactivateGuard, downloadGraphicFromElement, evaluateEntityDisplayTemplate, findManualPresetIdByOperation, formatEntityRowDisplayTitle, inferSettingCoercionKind, isStoredImageFileId, normalizePositiveNumberOption, normalizeRouterUrl, normalizeStoredImageRef, peelSettingValueKey, printGraphicFromElement, provideDynamicHomePage, provideMenuMiddleware, resolveDateFilterPresets, resolveEntityCreateListBehavior, resolveEntityModifyPopupTitle, resolveEntityRowDisplayText, resolveEntityRowDisplayTitle, resolveEntityRowDisplayTitleFromColumnContext, resolveEntitySearchTitleFallback, resolveGraphicElementSize, resolveGraphicPrintContent, resolveQueryMatchingDisplayText, resolveSearchDisplayTemplate, resolveSearchableText, resolveStoredImageDisplayUrl, searchInRecordValues, searchInSearchableValue, serializeSvgElement, shouldApplyDefaultMultiLanguageToEntityProperty, shouldApplyDefaultMultiLanguageToWidgetNode, shouldApplyDefaultMultiLanguageToWidgetProperty, traceSettingsAppStartupLoadComplete, traceSettingsAppStartupLoadStarted, traceSettingsClientTool, traceSettingsFlush, traceSettingsLocalPersist, traceSettingsPageLoadComplete, traceSettingsPageLoadStarted, traceSettingsPageRouteLoad, traceSettingsRetryScheduled, traceSettingsRevalidateFailed, traceSettingsServerApiCall, traceSettingsServiceLoadComplete, traceSettingsServiceLoadFailed, traceSettingsServiceLoadStarted, traceSettingsServiceReload, traceSettingsSyncFailed, triggerBrowserDownload, withDefaultMultiLanguageOnWidgetNodeTree, withDefaultMultiLanguageOnWidgetProperty };
10634
+ export { ALL_DEFAULT_OPERATORS, AXPAcorexFileTypeBridgeProvider, AXPAcorexFileTypeModule, AXPAppVersionService, AXPBackgroundOperationCompletionService, AXPBackgroundOperationEntityStoreService, AXPBackgroundOperationHandler, AXPBackgroundOperationNotificationService, AXPBackgroundOperationProvider, AXPBackgroundOperationRootConfig, AXPBackgroundOperationService, AXPBackgroundOperationSlotComponent, AXPBrowserTitleService, AXPCleanNestedFilters, AXPClipBoardService, AXPCommonModule, AXPCommonSettings, AXPCustomOperatorService, AXPCustomOperatorServiceImpl, AXPDataProvider, AXPDefaultMultiLanguageConfigService, AXPErrorHandlerRegistryService, AXPExportService, AXPFileActionsService, AXPFileStorageEvaluatorScopeProvider, AXPFileStorageService, AXPFileTypeProviderService, AXPFilterOperatorMiddlewareService, AXPFilterOperatorMiddlewareServiceImpl, AXPFooterTextSlotComponent, AXPGlobalErrorHandler, AXPHomePageModule, AXPHomePageService, AXPInAppInboxConnectorService, AXPInAppInboxRealtimeService, AXPIndexedDbSettingValueProvider, AXPIntegrationDomainProviderContext, AXPIntegrationDomainRegistryFacade, AXPIntegrationDomainRegistryService, AXPIntegrationOAuthService, AXPIntegrationProviderContext, AXPIntegrationProviderRegistryService, AXPIntegrationRuntimeService, AXPKeyboardShortcutsHelpComponent, AXPKeyboardShortcutsHelpService, AXPLockService, AXPLogoImageSrcResolverService, AXPMenuItemsDataSourceDefinition, AXPMenuKeyboardShortcutService, AXPMenuMiddlewareRegistry, AXPMenuProviderService, AXPMenuRouteAccessService, AXPMenuRouteGuard, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateCommand, AXPNotFoundCatchAllRoute, AXPNotFoundError, AXPOutputContractTranscriptSegmentService, AXPPlatformCommonDataSourceKeys, AXPPlatformDefaultConfigs, AXPQueryParamsEvaluatorScopeProvider, AXPRedirectEvent, AXPRefreshEvent, AXPRegionalCalendarService, AXPReloadEvent, AXPSearchCommandProvider, AXPSearchDefinitionActionBuilder, AXPSearchDefinitionBuilder, AXPSearchDefinitionProviderContext, AXPSearchDefinitionProviderService, AXPSearchService, AXPSettingDefaultValuesAggregatorService, AXPSettingDefinitionGroupBuilder, AXPSettingDefinitionProviderContext, AXPSettingDefinitionProviderService, AXPSettingDefinitionSectionBuilder, AXPSettingsBulkSyncService, AXPSettingsEvaluatorScopeProvider, AXPSettingsIndexedDb, AXPSettingsService, AXPStatusDefinitionProviderService, AXPStickyDirective, AXPTabNavigationService, AXPTabPreviewService, AXPTabRouteCacheRegistry, AXPTokenDefinitionService, AXPTokenEvaluatorScopeProvider, AXPTranslateFormatter, AXPUnsavedChangesConfirmService, AXPUnsavedChangesPopstateService, AXPVersioningService, AXP_AGENT_OUTPUT_CONTRACT_DEFAULT_STRUCTURED_RETRIES, AXP_APP_VERSION_PROVIDER, AXP_BACKGROUND_OPERATION_ENTITY_STORAGE, AXP_BACKGROUND_OPERATION_HANDLERS, AXP_BACKGROUND_OPERATION_PROVIDERS, AXP_DOCUMENT_FILE_TYPE_PURPOSES, AXP_ENTITY_DELETED_EVENT_TYPE, AXP_EXPERIENCE_SETTINGS_GROUP, AXP_EXPERIENCE_SETTINGS_SECTIONS, AXP_FILE_ACTION_PROVIDER, AXP_FILE_TYPE_INFO_PROVIDER, AXP_HOME_PAGES, AXP_HOME_PAGE_DEFAULT_KEY, AXP_HOME_TAB_KEY, AXP_INTEGRATION_CONNECTION_ESTABLISHED, AXP_INTEGRATION_DOMAIN_PROVIDER, AXP_INTEGRATION_OAUTH_SERVICE, AXP_INTEGRATION_PROVIDER, AXP_INTEGRATION_RUNTIME_PROVIDER, AXP_INTEGRATION_SECRET_STORE, AXP_IN_APP_INBOX_CONFIG, AXP_IN_APP_INBOX_I18N, AXP_IN_APP_INBOX_PORT, AXP_IN_APP_NOTIFICATION_SERVICE, AXP_LOCALE_MANAGEMENT_PORT, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER, AXP_NOT_FOUND_CATCH_ALL_ROUTE, AXP_NOT_FOUND_ROUTE, AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER, AXP_PLATFORM_CONFIG_TOKEN, AXP_PROTECTED_ROUTE_GUARDS, AXP_ROOT_CONFIG_TOKEN, AXP_SEARCH_DEFINITION_LAZY_RESOLVER, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SETTINGS_CACHE_SYNC, AXP_SETTINGS_SYNC_DEBOUNCE_MS, AXP_SETTINGS_SYNC_KEYS, AXP_SETTINGS_SYNC_RETRY_BACKOFF_MS, AXP_SETTINGS_SYNC_TTL_MS, AXP_SETTING_DEFAULT_VALUES_PROVIDERS, AXP_SETTING_DEFINITION_PROVIDER, AXP_SETTING_SCOPE_DESCENDANTS, AXP_SETTING_VALUE_PROVIDER, AXP_STATUS_PROVIDERS, AXP_TAB_BREADCRUMB_JOIN_SEPARATOR, AXP_TAB_ROUTE_DATA_KEY, AXP_TOKEN_DEFINITION_PROVIDER, AXP_UNAUTHORIZED_ROUTE, AXVChangeType, BETWEEN_OPER, BOOLEAN_OPERATORS, CONTAINS_OPER, DATE_OPERATORS, DEFAULT_DATE_FILTER_PRESETS, DEFAULT_MULTILANGUAGE_FIELD_NAMES, ENDS_WITH_OPER, ENVIRONMENT, EQ_OPER, GALLERY_MEDIA_EXTENSIONS, GTE_OPER, GT_OPER, IN_OPER, IS_EMPTY_OPER, IS_NOT_EMPTY_OPER, LTE_OPER, LT_OPER, MULTILANGUAGE_CAPABLE_WIDGET_TYPES, NOT_CONTAINS_OPER, NOT_EQ_OPER, NUMBER_OPERATORS, SETTINGS_TRACE_NS, SETTINGS_TRACE_TITLE, STARTS_WITH_OPER, STRING_OPERATORS, UploadFromComputerActionProvider, applyDateFilterPreset, axpBackgroundOperationCapabilities, axpBackgroundOperationDisplayTime, axpBackgroundOperationEntityName, axpBackgroundOperationEstimateEndDate, axpBackgroundOperationFailurePolicy, axpBackgroundOperationFromEntityModel, axpBackgroundOperationRemainingMs, axpBackgroundOperationToEntityModel, axpBuildBackgroundOperation, axpBuildTabKey, axpCoerceBackgroundOperationDate, axpCreateBackgroundOperationId, axpFallbackTabTitle, axpFindMenuItemByRoute, axpGetEntityListReturnUrl, axpGetLeafRouteSnapshot, axpHasTabScope, axpIsActiveBackgroundOperationStatus, axpIsCompletedBackgroundOperationStatus, axpIsEntityDetailsPath, axpIsEntityDetailsViewRoute, axpIsEntityListPath, axpIsEntityListRoute, axpIsEntityRecordNotFound, axpIsTabEligibleUrl, axpJoinTabTitleSegments, axpMenuPathsMatch, axpNavigateAppPath, axpNavigateCommandDefinition, axpParseAppPath, axpParseEntityDetailsRoute, axpParseEntityListRoute, axpPathFromSnapshot, axpRedirectToNotFound, axpRedirectToUnauthorized, axpReplaceEntityListRouteQueryParams, axpResolveNavigatePath, axpResolveTabKey, axpResolveTabKeyFromRouteConfig, axpResolveTabKeyFromSnapshot, axpResolveTabTitleParts, axpSaveEntityListReturnUrl, axpSettingsIndexedDb, backgroundOperationEntityFactory, buildScopedSettingsSnapshotId, chooseSystemFiles, coerceAXPSettingRawValue, coerceAXPSettingRawValueByKind, commandMessageTextForError, configPlatform, createBackgroundOperationStore, createDefaultSettingValueProviders, createEmptyScopedSettingsSnapshot, createEntityCommandOptions, createEntityRowExpressionScope, createEntitySearchCommand, createFileTypeOpenContext, createIndexedDbSettingValueProviders, createMenuContext, createMenuMiddleware, createUnsavedChangesCanDeactivateGuard, downloadGraphicFromElement, evaluateEntityDisplayTemplate, extractFileExtension, extractHttpRequestErrorInfo, findManualPresetIdByOperation, formatEntityRowDisplayTitle, formatRequestError, getInAppInboxPriorityClass, hasFileTypeOpenHandler, inferSettingCoercionKind, isGalleryMediaExtension, isInAppInboxUnread, isInAppInboxUnseen, isSettingVisibleOnScope, isStoredImageFileId, normalizeDocumentFileTypePurposes, normalizeDocumentToFileListItem, normalizeInAppInboxItem, normalizeOverridableAt, normalizePositiveNumberOption, normalizeRouterUrl, normalizeStoredImageRef, peelSettingValueKey, printGraphicFromElement, provideDynamicHomePage, provideMenuMiddleware, purgeNonUserScopedSettingsSnapshots, resolveDateFilterPresets, resolveEntityCreateListBehavior, resolveEntityModifyPopupTitle, resolveEntityRowDisplayText, resolveEntityRowDisplayTitle, resolveEntityRowDisplayTitleFromColumnContext, resolveEntitySearchTitleFallback, resolveExplorerFileDisplayName, resolveFileTypeDisplay, resolveGraphicElementSize, resolveGraphicPrintContent, resolveMediaViewerType, resolveQueryMatchingDisplayText, resolveSearchDisplayTemplate, resolveSearchableText, resolveStoredImageDisplayUrl, searchInRecordValues, searchInSearchableValue, serializeSvgElement, shouldApplyDefaultMultiLanguageToEntityProperty, shouldApplyDefaultMultiLanguageToWidgetNode, shouldApplyDefaultMultiLanguageToWidgetProperty, shouldPersistSettingsInIndexedDb, traceSettingsAppStartupLoadComplete, traceSettingsAppStartupLoadStarted, traceSettingsClientTool, traceSettingsFlush, traceSettingsLocalPersist, traceSettingsPageLoadComplete, traceSettingsPageLoadStarted, traceSettingsPageRouteLoad, traceSettingsRetryScheduled, traceSettingsRevalidateFailed, traceSettingsServerApiCall, traceSettingsServiceLoadComplete, traceSettingsServiceLoadFailed, traceSettingsServiceLoadStarted, traceSettingsServiceReload, traceSettingsSyncFailed, triggerBrowserDownload, tryOpenFileByCatalogType, withDefaultMultiLanguageOnWidgetNodeTree, withDefaultMultiLanguageOnWidgetProperty };
9467
10635
  //# sourceMappingURL=acorex-platform-framework-client-common.mjs.map