@acorex-platform/framework-client 0.0.30 → 0.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-CLm2BVk-.mjs → acorex-platform-framework-client-common-common-settings.provider-CzBr0cRi.mjs} +23 -2
  2. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-CzBr0cRi.mjs.map +1 -0
  3. package/fesm2022/acorex-platform-framework-client-common.mjs +673 -110
  4. package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
  5. package/fesm2022/acorex-platform-framework-client-core.mjs +76 -7
  6. package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs +3 -6
  8. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-framework-client-layout-components.mjs +505 -111
  10. package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
  11. package/fesm2022/{acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-CJemNxCu.mjs → acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-D1prdDvf.mjs} +3404 -2157
  12. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-D1prdDvf.mjs.map +1 -0
  13. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-DQXGk8nF.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-CeVGNzup.mjs} +2 -2
  14. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-DQXGk8nF.mjs.map → acorex-platform-framework-client-layout-entity-attachments-page.component-CeVGNzup.mjs.map} +1 -1
  15. package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-DSLUUXfQ.mjs → acorex-platform-framework-client-layout-entity-bulk-entity.command-CFScb-L4.mjs} +43 -15
  16. package/fesm2022/acorex-platform-framework-client-layout-entity-bulk-entity.command-CFScb-L4.mjs.map +1 -0
  17. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-p0hxDb0W.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-B3__csKW.mjs} +3 -3
  18. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-p0hxDb0W.mjs.map → acorex-platform-framework-client-layout-entity-file-list-popup.component-B3__csKW.mjs.map} +1 -1
  19. package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-uf51NO5m.mjs → acorex-platform-framework-client-layout-entity-gallery-page.component-B17l6mbm.mjs} +2 -2
  20. package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-uf51NO5m.mjs.map → acorex-platform-framework-client-layout-entity-gallery-page.component-B17l6mbm.mjs.map} +1 -1
  21. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +1 -1
  22. package/fesm2022/acorex-platform-framework-client-layout-views.mjs +37 -6
  23. package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
  24. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +148 -130
  25. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
  26. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-3CO4xJB3.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-4mX8aYzA.mjs} +3 -3
  27. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-3CO4xJB3.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-4mX8aYzA.mjs.map} +1 -1
  28. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +1214 -860
  29. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs.map +1 -1
  30. package/fesm2022/acorex-platform-framework-client-realtime.mjs +70 -5
  31. package/fesm2022/acorex-platform-framework-client-realtime.mjs.map +1 -1
  32. package/fesm2022/acorex-platform-framework-client-runtime.mjs +121 -6
  33. package/fesm2022/acorex-platform-framework-client-runtime.mjs.map +1 -1
  34. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-single-view.component-C2Abf7Lb.mjs → acorex-platform-framework-client-themes-default-entity-master-single-view.component-DCpl6AXq.mjs} +51 -12
  35. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-DCpl6AXq.mjs.map +1 -0
  36. package/fesm2022/acorex-platform-framework-client-themes-default.mjs +770 -679
  37. package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
  38. package/fesm2022/{acorex-platform-framework-client-themes-shared-settings.provider-D2XPkc71.mjs → acorex-platform-framework-client-themes-shared-settings.provider-CpsAIsxj.mjs} +76 -1
  39. package/fesm2022/acorex-platform-framework-client-themes-shared-settings.provider-CpsAIsxj.mjs.map +1 -0
  40. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +345 -54
  41. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
  42. package/package.json +7 -7
  43. package/types/acorex-platform-framework-client-common.d.ts +137 -9
  44. package/types/acorex-platform-framework-client-core.d.ts +4 -1
  45. package/types/acorex-platform-framework-client-layout-components.d.ts +141 -22
  46. package/types/acorex-platform-framework-client-layout-entity.d.ts +532 -255
  47. package/types/acorex-platform-framework-client-layout-views.d.ts +48 -0
  48. package/types/acorex-platform-framework-client-layout-widget-core.d.ts +2 -2
  49. package/types/acorex-platform-framework-client-layout-widgets.d.ts +143 -92
  50. package/types/acorex-platform-framework-client-realtime.d.ts +39 -2
  51. package/types/acorex-platform-framework-client-runtime.d.ts +56 -5
  52. package/types/acorex-platform-framework-client-themes-default.d.ts +144 -14
  53. package/types/acorex-platform-framework-client-themes-shared.d.ts +36 -3
  54. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-CLm2BVk-.mjs.map +0 -1
  55. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-CJemNxCu.mjs.map +0 -1
  56. package/fesm2022/acorex-platform-framework-client-layout-entity-bulk-entity.command-DSLUUXfQ.mjs.map +0 -1
  57. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-C2Abf7Lb.mjs.map +0 -1
  58. package/fesm2022/acorex-platform-framework-client-themes-shared-settings.provider-D2XPkc71.mjs.map +0 -1
@@ -1,38 +1,43 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, Injectable, Injector, signal, ApplicationRef, 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';
2
+ import { InjectionToken, inject, Injectable, Injector, signal, ApplicationRef, DestroyRef, makeEnvironmentProviders, NgModule, computed, input, ChangeDetectionStrategy, ViewEncapsulation, Component, output, effect, viewChild, afterNextRender, untracked, ErrorHandler, EventEmitter, Input, Output, Directive, Inject, runInInjectionContext, model, linkedSignal } from '@angular/core';
3
3
  import * as i4$2 from '@angular/router';
4
4
  import { Router, NavigationEnd, NavigationStart, ROUTES, RedirectCommand, UrlTree, RouterModule } from '@angular/router';
5
5
  import { AXPSessionService, AXPSessionStatus, AXPUnauthenticatedError, AXPAuthGuard, commandMessageTextForError } from '@acorex-platform/framework-client/auth';
6
6
  export { commandMessageTextForError } from '@acorex-platform/framework-client/auth';
7
7
  import { combineLatest, map, distinctUntilChanged, Subject, ReplaySubject, firstValueFrom, filter, take, timer, timeout, switchMap, from, of } from 'rxjs';
8
- import { unwrapValueProperty, isLocaleStringMap, coerceUnknownToDate, coerceUnknownToFiniteNumber, coerceUnknownToBoolean, coerceUnknownToTrimmedString, AXPPlatformScope, runtimeQueryPayloadData, runtimeCommandPayloadData, AXPRegionalSetting, AXPWidgetsCatalog, resolveMultiLanguageString, coerceUnknownToMultiLanguageString, AXPKeyboardShortcutPriority, AXP_PLATFORM_ERROR_CODES, AXPRequestError, mapUnknownToAXPErrorBody, AXPSystemActionType, runtimeQueryCollectionData } from '@acorex-platform/framework-shared/core';
9
- import * as i3$1 from '@acorex-platform/framework-client/core';
8
+ import { unwrapValueProperty, isLocaleStringMap, coerceUnknownToDate, coerceUnknownToFiniteNumber, coerceUnknownToBoolean, coerceUnknownToTrimmedString, AXPPlatformScope, runtimeQueryPayloadData, runtimeCommandPayloadData, AXPRegionalSetting, AXPWidgetsCatalog, axpResolveUserNotificationDelivery, resolveMultiLanguageString, coerceUnknownToMultiLanguageString, AXPKeyboardShortcutPriority, AXP_PLATFORM_ERROR_CODES, AXPRequestError, mapUnknownToAXPErrorBody, AXPSystemActionType, runtimeQueryCollectionData, createRandomUuid } from '@acorex-platform/framework-shared/core';
9
+ import * as i3$2 from '@acorex-platform/framework-client/core';
10
10
  import { AXPDebugService, AXPBroadcastEventService, AXP_SETTINGS_DEFINITION_DIALOG_OPENER, objectKeyValueTransforms, AXPDataGenerator, AXPKeyboardShortcutRegistry, normalizeKeyboardShortcuts, AXPDeviceService, chordToKbdItemKeys, hasForegroundOverlayLayer, AXPExpressionEvaluatorService, AXPContextEvalFactory, AXPModuleManifestModule, AXPComponentSlotModule, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_LOGO_IMAGE_SRC_RESOLVER, AXPHookService } from '@acorex-platform/framework-client/core';
11
11
  export { AXPDebugService } from '@acorex-platform/framework-client/core';
12
12
  import { merge, sortBy, isString, toString, isPlainObject, defaultTo, isEmpty, cloneDeep, get, isNumber, isNil, isObject, omit, uniq } from 'lodash-es';
13
13
  import { AXPQueryService, AXPCommandService, provideCommandSetups } from '@acorex-platform/framework-client/runtime';
14
14
  import Dexie from 'dexie';
15
15
  import { AXDialogService } from '@acorex/components/dialog';
16
- import * as i5 from '@acorex/core/translation';
16
+ import * as i6 from '@acorex/core/translation';
17
17
  import { AXTranslationService, AXTranslationModule, translateSync, resolveMultiLanguageString as resolveMultiLanguageString$1 } from '@acorex/core/translation';
18
18
  import { AXCalendarService, AXDateTimeModule } from '@acorex/core/date-time';
19
- import * as i4$1 from '@angular/common';
19
+ import * as i4 from '@angular/common';
20
20
  import { Location, CommonModule, DOCUMENT, AsyncPipe } from '@angular/common';
21
21
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
22
- import * as i4 from '@acorex/components/decorators';
22
+ import * as i4$1 from '@acorex/components/badge';
23
+ import { AXBadgeModule } from '@acorex/components/badge';
24
+ import * as i2 from '@acorex/components/decorators';
23
25
  import { AXDecoratorModule } from '@acorex/components/decorators';
24
- import * as i2 from '@acorex/components/popover';
26
+ import * as i3$1 from '@acorex/components/popover';
25
27
  import { AXPopoverComponent, AXPopoverModule } from '@acorex/components/popover';
26
28
  import * as i1 from '@acorex/components/button';
27
29
  import { AXButtonModule } from '@acorex/components/button';
30
+ import * as i2$2 from '@acorex/components/tabs';
31
+ import { AXTabsModule } from '@acorex/components/tabs';
28
32
  import * as i3 from '@acorex/components/progress-bar';
29
33
  import { AXProgressBarModule } from '@acorex/components/progress-bar';
34
+ import * as i2$1 from '@acorex/core/format';
35
+ import { AXFormatModule, AXFormatService } from '@acorex/core/format';
36
+ import { AXNotificationService, AXNotificationModule } from '@acorex/components/notification';
30
37
  import { filter as filter$1 } from 'rxjs/operators';
31
38
  import { signalStore, withState, withMethods, patchState, withHooks } from '@ngrx/signals';
32
39
  import { AXPopupService, AXPopupModule } from '@acorex/components/popup';
33
40
  import { AXToastModule, AXToastService } from '@acorex/components/toast';
34
- import * as i2$1 from '@acorex/core/format';
35
- import { AXFormatService } from '@acorex/core/format';
36
41
  import { HttpErrorResponse } from '@angular/common/http';
37
42
  import { AXKBDComponent, AXKBDItemComponent } from '@acorex/components/kbd';
38
43
  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';
@@ -40,11 +45,11 @@ import * as i1$1 from '@acorex/core/file';
40
45
  import { getFileExtension, resolveFileTypeExtension, resolveFileTypeOpen, runFileTypeOpen, AX_FILE_TYPE_METADATA_PURPOSE, getFileTypePurposes, AXFileTypeRegistryService, AXFileModule } from '@acorex/core/file';
41
46
  export { AX_FILE_TYPE_METADATA_PURPOSE, filterFileTypesByPurpose, getFileTypePurposes } from '@acorex/core/file';
42
47
  import { AXCheckBoxModule } from '@acorex/components/check-box';
43
- import * as i6 from '@acorex/components/color-box';
48
+ import * as i6$1 from '@acorex/components/color-box';
44
49
  import { AXColorBoxModule } from '@acorex/components/color-box';
45
- import * as i3$2 from '@acorex/components/label';
50
+ import * as i3$3 from '@acorex/components/label';
46
51
  import { AXLabelModule } from '@acorex/components/label';
47
- import * as i2$2 from '@acorex/components/number-box';
52
+ import * as i2$3 from '@acorex/components/number-box';
48
53
  import { AXNumberBoxModule } from '@acorex/components/number-box';
49
54
  import { AXBasePageComponent } from '@acorex/components/page';
50
55
  import { AXTextBoxModule } from '@acorex/components/text-box';
@@ -408,6 +413,8 @@ var AXPCommonSettings;
408
413
  AXPCommonSettings["AllowWorkingOffline"] = "Common:Setting:Offline.AllowWorkingOffline";
409
414
  AXPCommonSettings["ShowRowIndexColumn"] = "Common:Setting:Entity.ShowRowIndexColumn";
410
415
  AXPCommonSettings["EntityListPersistenceMode"] = "Common:Setting:Entity.ListPersistenceMode";
416
+ /** User default for entity master-list presentation (`table` | `card` | `row`). */
417
+ AXPCommonSettings["EntityListDisplayMode"] = "Common:Setting:Entity.ListDisplayMode";
411
418
  AXPCommonSettings["NavigationMode"] = "Common:Setting:Navigation.Mode";
412
419
  AXPCommonSettings["MaxOpenTabs"] = "Common:Setting:Navigation.MaxOpenTabs";
413
420
  /** When true with entity list quick-search input, filters emit {@link AXP_QUERY_QUICK_SEARCH_FIELD} instead of inline OR. */
@@ -427,6 +434,8 @@ const AXP_RUNTIME_QUERY_CACHE_DEFAULTS = {
427
434
  enabled: true,
428
435
  ttlMs: 2_000,
429
436
  };
437
+ /** Default entity list presentation when the user has not chosen a layout. */
438
+ const AXP_ENTITY_LIST_DISPLAY_MODE_DEFAULT = 'table';
430
439
 
431
440
  class AXPSettingDefinitionProviderContext {
432
441
  constructor() {
@@ -3881,6 +3890,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
3881
3890
  const AXP_IN_APP_NOTIFICATION_SERVICE = new InjectionToken('AXP_IN_APP_NOTIFICATION_SERVICE');
3882
3891
  //#endregion
3883
3892
 
3893
+ //#region ---- Imports ----
3894
+ const AXP_USER_NOTIFICATION_SERVICE = new InjectionToken('AXP_USER_NOTIFICATION_SERVICE');
3895
+ //#endregion
3896
+
3884
3897
  //#region ---- Imports ----
3885
3898
  //#endregion
3886
3899
  //#region ---- Service ----
@@ -3889,11 +3902,11 @@ const AXP_IN_APP_NOTIFICATION_SERVICE = new InjectionToken('AXP_IN_APP_NOTIFICAT
3889
3902
  */
3890
3903
  class AXPBackgroundOperationNotificationService {
3891
3904
  constructor() {
3892
- this.inAppNotificationService = inject(AXP_IN_APP_NOTIFICATION_SERVICE, { optional: true });
3905
+ this.userNotificationService = inject(AXP_USER_NOTIFICATION_SERVICE);
3893
3906
  this.sessionService = inject(AXPSessionService);
3894
3907
  }
3895
3908
  async notify(operation) {
3896
- if (!this.inAppNotificationService || !this.shouldNotify(operation)) {
3909
+ if (!this.shouldNotify(operation)) {
3897
3910
  return;
3898
3911
  }
3899
3912
  const userId = this.sessionService.user?.id;
@@ -3902,18 +3915,18 @@ class AXPBackgroundOperationNotificationService {
3902
3915
  }
3903
3916
  const body = this.resolveBody(operation);
3904
3917
  const { icon, priority } = this.resolveTemplate(operation);
3905
- const request = {
3906
- id: `notif-bg-op-${operation.id}-${operation.status}`,
3918
+ await this.userNotificationService.notify({
3919
+ correlationId: `notif-bg-op-${operation.id}-${operation.status}`,
3920
+ idempotencyKey: `notif-bg-op-${operation.id}-${operation.status}`,
3907
3921
  name: operation.title,
3908
3922
  title: operation.title,
3909
3923
  body,
3910
3924
  icon,
3911
- priority,
3912
- receiver: {
3913
- id: userId,
3914
- type: 'user',
3915
- fullName: get(this.sessionService.user, 'title'),
3916
- username: get(this.sessionService.user, 'name'),
3925
+ recipientUserId: userId,
3926
+ delivery: {
3927
+ inbox: {
3928
+ priority,
3929
+ },
3917
3930
  },
3918
3931
  data: {
3919
3932
  backgroundOperationId: operation.id,
@@ -3921,8 +3934,7 @@ class AXPBackgroundOperationNotificationService {
3921
3934
  status: operation.status,
3922
3935
  ...(operation.data ?? {}),
3923
3936
  },
3924
- };
3925
- await this.inAppNotificationService.create(request);
3937
+ });
3926
3938
  }
3927
3939
  //#region ---- Helpers ----
3928
3940
  shouldNotify(operation) {
@@ -4004,9 +4016,10 @@ function axpBackgroundOperationDisplayTime(operation) {
4004
4016
  }
4005
4017
  /**
4006
4018
  * Remaining duration in milliseconds for ETA display.
4019
+ * Prefers progress-rate extrapolation; falls back to an explicit estimate budget only.
4007
4020
  */
4008
4021
  function axpBackgroundOperationRemainingMs(operation) {
4009
- if (!operation.capabilities.supportsEstimate || !isNumber(operation.estimatedDurationMs)) {
4022
+ if (!operation.capabilities.supportsEstimate) {
4010
4023
  return null;
4011
4024
  }
4012
4025
  const { estimatedDurationMs, progress, startedAt, status } = operation;
@@ -4016,10 +4029,16 @@ function axpBackgroundOperationRemainingMs(operation) {
4016
4029
  if (isNumber(progress) && progress >= 100) {
4017
4030
  return 0;
4018
4031
  }
4019
- if (isNumber(progress) && progress > 0) {
4020
- return Math.max(0, Math.round((estimatedDurationMs * (100 - progress)) / 100));
4021
- }
4022
4032
  const started = axpCoerceBackgroundOperationDate(startedAt);
4033
+ if (isNumber(progress) && progress > 0 && started) {
4034
+ const elapsed = Date.now() - started.getTime();
4035
+ if (elapsed > 0) {
4036
+ return Math.max(0, Math.round((elapsed * (100 - progress)) / progress));
4037
+ }
4038
+ }
4039
+ if (!isNumber(estimatedDurationMs) || estimatedDurationMs <= 0) {
4040
+ return null;
4041
+ }
4023
4042
  if (started) {
4024
4043
  const elapsed = Date.now() - started.getTime();
4025
4044
  return Math.max(0, estimatedDurationMs - elapsed);
@@ -4036,6 +4055,47 @@ function axpBackgroundOperationEstimateEndDate(operation) {
4036
4055
  }
4037
4056
  return new Date(Date.now() + remainingMs);
4038
4057
  }
4058
+ function axpBackgroundOperationDurationMs(operation) {
4059
+ const started = axpCoerceBackgroundOperationDate(operation.startedAt) ??
4060
+ axpCoerceBackgroundOperationDate(operation.createdAt);
4061
+ const completed = axpCoerceBackgroundOperationDate(operation.completedAt);
4062
+ if (!started || !completed) {
4063
+ return null;
4064
+ }
4065
+ return Math.max(0, completed.getTime() - started.getTime());
4066
+ }
4067
+ function axpBackgroundOperationStatusTextParams(operation) {
4068
+ const statusText = operation.statusText?.trim() ?? '';
4069
+ const step = operation.currentStep?.trim();
4070
+ if (!statusText.startsWith('@')) {
4071
+ return {};
4072
+ }
4073
+ if (statusText.includes('layout-line-multiple')) {
4074
+ const count = Number.parseInt(step ?? '', 10);
4075
+ return { count: Number.isFinite(count) ? count : 0 };
4076
+ }
4077
+ if (step && (statusText.includes('layout-line-single') || statusText.includes('progress.layout'))) {
4078
+ return { layout: step };
4079
+ }
4080
+ return {};
4081
+ }
4082
+ function axpIsBackgroundOperationI18nText(value) {
4083
+ return !!value?.trim().startsWith('@');
4084
+ }
4085
+ function axpFormatBackgroundOperationDurationMs(ms) {
4086
+ const totalSeconds = Math.max(1, Math.round(ms / 1000));
4087
+ if (totalSeconds < 60) {
4088
+ return `${totalSeconds}s`;
4089
+ }
4090
+ const minutes = Math.floor(totalSeconds / 60);
4091
+ const seconds = totalSeconds % 60;
4092
+ if (minutes < 60) {
4093
+ return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
4094
+ }
4095
+ const hours = Math.floor(minutes / 60);
4096
+ const remainingMinutes = minutes % 60;
4097
+ return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
4098
+ }
4039
4099
  function axpBackgroundOperationCapabilities(partial = {}) {
4040
4100
  return {
4041
4101
  cancellable: partial.cancellable ?? false,
@@ -4045,6 +4105,7 @@ function axpBackgroundOperationCapabilities(partial = {}) {
4045
4105
  supportsProgress: partial.supportsProgress ?? false,
4046
4106
  supportsEstimate: partial.supportsEstimate ?? false,
4047
4107
  clickable: partial.clickable ?? false,
4108
+ keepInTrayAfterComplete: partial.keepInTrayAfterComplete ?? false,
4048
4109
  notifyOnComplete: partial.notifyOnComplete ?? true,
4049
4110
  notifyOnFailed: partial.notifyOnFailed ?? true,
4050
4111
  };
@@ -4063,6 +4124,26 @@ function axpIsActiveBackgroundOperationStatus(status) {
4063
4124
  function axpIsCompletedBackgroundOperationStatus(status) {
4064
4125
  return status === 'completed' || status === 'cancelled';
4065
4126
  }
4127
+ function axpIsTrayVisibleBackgroundOperation(operation) {
4128
+ if (axpIsActiveBackgroundOperationStatus(operation.status)) {
4129
+ return true;
4130
+ }
4131
+ if (operation.status === 'failed') {
4132
+ return true;
4133
+ }
4134
+ if (operation.capabilities.keepInTrayAfterComplete === true &&
4135
+ axpIsCompletedBackgroundOperationStatus(operation.status)) {
4136
+ return true;
4137
+ }
4138
+ return false;
4139
+ }
4140
+ function axpIsInProgressPanelBackgroundOperation(operation) {
4141
+ return axpIsActiveBackgroundOperationStatus(operation.status);
4142
+ }
4143
+ function axpIsCompletedPanelBackgroundOperation(operation) {
4144
+ return (axpIsTrayVisibleBackgroundOperation(operation) &&
4145
+ !axpIsActiveBackgroundOperationStatus(operation.status));
4146
+ }
4066
4147
  //#endregion
4067
4148
 
4068
4149
  //#region ---- Imports ----
@@ -4498,6 +4579,11 @@ class AXPBackgroundOperationService {
4498
4579
  ...(ngDevMode ? [{ debugName: "activeCount" }] : /* istanbul ignore next */ []));
4499
4580
  this.failedCount = computed(() => this.operations().filter((operation) => operation.status === 'failed').length, /* @ts-ignore */
4500
4581
  ...(ngDevMode ? [{ debugName: "failedCount" }] : /* istanbul ignore next */ []));
4582
+ this.trayVisibleCount = computed(() => this.operations().filter((operation) => axpIsTrayVisibleBackgroundOperation(operation)).length, /* @ts-ignore */
4583
+ ...(ngDevMode ? [{ debugName: "trayVisibleCount" }] : /* istanbul ignore next */ []));
4584
+ this.retainedCompletedCount = computed(() => this.operations().filter((operation) => operation.capabilities.keepInTrayAfterComplete === true &&
4585
+ axpIsCompletedBackgroundOperationStatus(operation.status)).length, /* @ts-ignore */
4586
+ ...(ngDevMode ? [{ debugName: "retainedCompletedCount" }] : /* istanbul ignore next */ []));
4501
4587
  }
4502
4588
  //#endregion
4503
4589
  //#region ---- Queries ----
@@ -4516,6 +4602,10 @@ class AXPBackgroundOperationService {
4516
4602
  if (capabilities.retryable && status === 'failed') {
4517
4603
  actions.push('retry');
4518
4604
  }
4605
+ if (capabilities.keepInTrayAfterComplete === true &&
4606
+ (status === 'completed' || status === 'failed' || status === 'cancelled')) {
4607
+ actions.push('dismiss');
4608
+ }
4519
4609
  return actions;
4520
4610
  }
4521
4611
  //#endregion
@@ -4560,10 +4650,43 @@ class AXPBackgroundOperationService {
4560
4650
  }
4561
4651
  await this.run(() => provider.cancel(operationId));
4562
4652
  }
4653
+ /**
4654
+ * Dismiss many completed rows. Groups by provider and prefers {@link AXPBackgroundOperationProvider.dismissMany}.
4655
+ */
4656
+ async dismissMany(operationIds) {
4657
+ const ids = [...new Set(operationIds.map((id) => id?.trim()).filter(Boolean))];
4658
+ if (ids.length === 0) {
4659
+ return;
4660
+ }
4661
+ const byProvider = new Map();
4662
+ for (const operationId of ids) {
4663
+ const { provider } = this.resolveOperation(operationId);
4664
+ const group = byProvider.get(provider.key) ?? [];
4665
+ group.push(operationId);
4666
+ byProvider.set(provider.key, group);
4667
+ }
4668
+ for (const [providerKey, providerIds] of byProvider) {
4669
+ const provider = this.resolveProvider(providerKey);
4670
+ if (provider.dismissMany) {
4671
+ await this.run(() => provider.dismissMany(providerIds));
4672
+ continue;
4673
+ }
4674
+ for (const operationId of providerIds) {
4675
+ await this.dismiss(operationId);
4676
+ }
4677
+ }
4678
+ }
4563
4679
  hasClickHandler(operation) {
4564
4680
  return (operation.capabilities.clickable &&
4565
4681
  this.handlers.some((handler) => handler.providerKey === operation.providerKey));
4566
4682
  }
4683
+ getCta(operation) {
4684
+ const handler = this.resolveHandler(operation.providerKey);
4685
+ if (!handler?.resolveCta) {
4686
+ return null;
4687
+ }
4688
+ return handler.resolveCta(operation);
4689
+ }
4567
4690
  async executeCommand(operationId, command) {
4568
4691
  const { operation } = this.resolveOperation(operationId);
4569
4692
  const handler = this.resolveHandler(operation.providerKey);
@@ -4634,25 +4757,65 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
4634
4757
  args: [{ providedIn: 'root' }]
4635
4758
  }] });
4636
4759
 
4637
- //#region ---- Imports ----
4760
+ //#region ----- Imports -----
4638
4761
  //#endregion
4639
- //#region ---- Component ----
4762
+ //#region ----- Component -----
4763
+ class AXPStateMessageComponent {
4764
+ constructor() {
4765
+ this.mode = input('empty', /* @ts-ignore */
4766
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
4767
+ this.icon = input('', /* @ts-ignore */
4768
+ ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
4769
+ this.title = input('', /* @ts-ignore */
4770
+ ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
4771
+ this.description = input('', /* @ts-ignore */
4772
+ ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
4773
+ this.titleParams = input({}, /* @ts-ignore */
4774
+ ...(ngDevMode ? [{ debugName: "titleParams" }] : /* istanbul ignore next */ []));
4775
+ this.descriptionParams = input({}, /* @ts-ignore */
4776
+ ...(ngDevMode ? [{ debugName: "descriptionParams" }] : /* istanbul ignore next */ []));
4777
+ this.look = input('default', /* @ts-ignore */
4778
+ ...(ngDevMode ? [{ debugName: "look" }] : /* istanbul ignore next */ []));
4779
+ }
4780
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPStateMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4781
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPStateMessageComponent, isStandalone: true, selector: "axp-state-message", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, titleParams: { classPropertyName: "titleParams", publicName: "titleParams", isSignal: true, isRequired: false, transformFunction: null }, descriptionParams: { classPropertyName: "descriptionParams", publicName: "descriptionParams", isSignal: true, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"axp-state-message\" [attr.data-mode]=\"mode()\" [attr.data-look]=\"look()\">\n @if (icon()) {\n <!-- ----- Empty / status icon ----- -->\n <div class=\"__icon\">\n <i [class]=\"icon()\"></i>\n </div>\n }\n <div class=\"__content\">\n @if (title()) {\n <!-- ----- Translated title ----- -->\n <h3 class=\"__title\">{{ title() | translate: { params: titleParams() } | async }}</h3>\n }\n @if (description()) {\n <!-- ----- Translated description ----- -->\n <p class=\"__description\">{{ description() | translate: { params: descriptionParams() } | async }}</p>\n }\n <div class=\"__actions\">\n <ng-content select=\"[slot=actions]\"></ng-content>\n </div>\n </div>\n</div>\n", styles: ["@layer properties;.axp-state-message{display:flex;height:100%;flex-direction:column;align-items:center;justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center}.axp-state-message .__icon{margin-bottom:calc(var(--spacing, .25rem) * 4)}.axp-state-message .__icon i{opacity:74%;display:block;font-size:1rem;font-weight:400;line-height:1.625rem;font-size:var(--text-4xl, 2.25rem);line-height:var(--tw-leading, var(--text-4xl--line-height, calc(2.5 / 2.25)))}.axp-state-message .__content{max-width:var(--container-md, 28rem)}.axp-state-message .__title{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-lg, 1.125rem);line-height:var(--tw-leading, var(--text-lg--line-height, calc(1.75 / 1.125)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.axp-state-message .__description{margin-bottom:calc(var(--spacing, .25rem) * 4);opacity:74%;display:block;font-size:1rem;font-weight:400;line-height:1.625rem;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}.axp-state-message .__actions{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.axp-state-message[data-mode=empty] .__icon i{color:var(--color-gray-400, oklch(70.7% .022 261.325))}.axp-state-message[data-mode=error] .__icon i{color:var(--color-red-500, oklch(63.7% .237 25.331))}.axp-state-message[data-mode=error] .__title{color:var(--color-red-600, oklch(57.7% .245 27.325))}.axp-state-message[data-mode=loading] .__icon i{color:var(--color-blue-500, oklch(62.3% .214 259.815))}.axp-state-message[data-mode=loading] .__title{color:var(--color-blue-600, oklch(54.6% .245 262.881))}.axp-state-message[data-mode=warning] .__icon i{color:var(--color-orange-500, oklch(70.5% .213 47.604))}.axp-state-message[data-mode=warning] .__title{color:var(--color-orange-600, oklch(64.6% .222 41.116))}.axp-state-message[data-mode=info] .__icon i{color:var(--color-blue-500, oklch(62.3% .214 259.815))}.axp-state-message[data-mode=info] .__title{color:var(--color-blue-600, oklch(54.6% .245 262.881))}.axp-state-message[data-mode=success] .__icon i{color:var(--color-green-500, oklch(72.3% .219 149.579))}.axp-state-message[data-mode=success] .__title{color:var(--color-green-600, oklch(62.7% .194 149.214))}.axp-state-message[data-look=compact]{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 6)}.axp-state-message[data-look=compact] .__icon{margin-bottom:calc(var(--spacing, .25rem) * 2)}.axp-state-message[data-look=compact] .__icon i{font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)))}.axp-state-message[data-look=compact] .__title{margin-bottom:var(--spacing, .25rem);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}.axp-state-message[data-look=compact] .__description{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}.axp-state-message[data-look=minimal]{padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 4)}.axp-state-message[data-look=minimal] .__icon{margin-bottom:var(--spacing, .25rem)}.axp-state-message[data-look=minimal] .__icon i{font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}.axp-state-message[data-look=minimal] .__title{margin-bottom:var(--spacing, .25rem);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}.axp-state-message[data-look=minimal] .__description{margin-bottom:var(--spacing, .25rem);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}@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-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4782
+ }
4783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPStateMessageComponent, decorators: [{
4784
+ type: Component,
4785
+ args: [{ selector: 'axp-state-message', imports: [CommonModule, AXTranslationModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"axp-state-message\" [attr.data-mode]=\"mode()\" [attr.data-look]=\"look()\">\n @if (icon()) {\n <!-- ----- Empty / status icon ----- -->\n <div class=\"__icon\">\n <i [class]=\"icon()\"></i>\n </div>\n }\n <div class=\"__content\">\n @if (title()) {\n <!-- ----- Translated title ----- -->\n <h3 class=\"__title\">{{ title() | translate: { params: titleParams() } | async }}</h3>\n }\n @if (description()) {\n <!-- ----- Translated description ----- -->\n <p class=\"__description\">{{ description() | translate: { params: descriptionParams() } | async }}</p>\n }\n <div class=\"__actions\">\n <ng-content select=\"[slot=actions]\"></ng-content>\n </div>\n </div>\n</div>\n", styles: ["@layer properties;.axp-state-message{display:flex;height:100%;flex-direction:column;align-items:center;justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center}.axp-state-message .__icon{margin-bottom:calc(var(--spacing, .25rem) * 4)}.axp-state-message .__icon i{opacity:74%;display:block;font-size:1rem;font-weight:400;line-height:1.625rem;font-size:var(--text-4xl, 2.25rem);line-height:var(--tw-leading, var(--text-4xl--line-height, calc(2.5 / 2.25)))}.axp-state-message .__content{max-width:var(--container-md, 28rem)}.axp-state-message .__title{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-lg, 1.125rem);line-height:var(--tw-leading, var(--text-lg--line-height, calc(1.75 / 1.125)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}.axp-state-message .__description{margin-bottom:calc(var(--spacing, .25rem) * 4);opacity:74%;display:block;font-size:1rem;font-weight:400;line-height:1.625rem;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}.axp-state-message .__actions{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.axp-state-message[data-mode=empty] .__icon i{color:var(--color-gray-400, oklch(70.7% .022 261.325))}.axp-state-message[data-mode=error] .__icon i{color:var(--color-red-500, oklch(63.7% .237 25.331))}.axp-state-message[data-mode=error] .__title{color:var(--color-red-600, oklch(57.7% .245 27.325))}.axp-state-message[data-mode=loading] .__icon i{color:var(--color-blue-500, oklch(62.3% .214 259.815))}.axp-state-message[data-mode=loading] .__title{color:var(--color-blue-600, oklch(54.6% .245 262.881))}.axp-state-message[data-mode=warning] .__icon i{color:var(--color-orange-500, oklch(70.5% .213 47.604))}.axp-state-message[data-mode=warning] .__title{color:var(--color-orange-600, oklch(64.6% .222 41.116))}.axp-state-message[data-mode=info] .__icon i{color:var(--color-blue-500, oklch(62.3% .214 259.815))}.axp-state-message[data-mode=info] .__title{color:var(--color-blue-600, oklch(54.6% .245 262.881))}.axp-state-message[data-mode=success] .__icon i{color:var(--color-green-500, oklch(72.3% .219 149.579))}.axp-state-message[data-mode=success] .__title{color:var(--color-green-600, oklch(62.7% .194 149.214))}.axp-state-message[data-look=compact]{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 6)}.axp-state-message[data-look=compact] .__icon{margin-bottom:calc(var(--spacing, .25rem) * 2)}.axp-state-message[data-look=compact] .__icon i{font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)))}.axp-state-message[data-look=compact] .__title{margin-bottom:var(--spacing, .25rem);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}.axp-state-message[data-look=compact] .__description{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}.axp-state-message[data-look=minimal]{padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 4)}.axp-state-message[data-look=minimal] .__icon{margin-bottom:var(--spacing, .25rem)}.axp-state-message[data-look=minimal] .__icon i{font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}.axp-state-message[data-look=minimal] .__title{margin-bottom:var(--spacing, .25rem);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}.axp-state-message[data-look=minimal] .__description{margin-bottom:var(--spacing, .25rem);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}@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-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
4786
+ }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], titleParams: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleParams", required: false }] }], descriptionParams: [{ type: i0.Input, args: [{ isSignal: true, alias: "descriptionParams", required: false }] }], look: [{ type: i0.Input, args: [{ isSignal: true, alias: "look", required: false }] }] } });
4787
+
4788
+ //#region ----- Imports -----
4789
+ //#endregion
4790
+ //#region ----- Component -----
4640
4791
  class AXPBackgroundOperationItemComponent {
4792
+ //#endregion
4793
+ //#region ----- Lifecycle -----
4641
4794
  constructor() {
4642
- //#region ---- Services & Dependencies ----
4795
+ //#region ----- Services & Dependencies -----
4643
4796
  this.operationService = inject(AXPBackgroundOperationService);
4797
+ this.translateService = inject(AXTranslationService);
4644
4798
  //#endregion
4645
- //#region ---- Inputs & Outputs ----
4799
+ //#region ----- Inputs & Outputs -----
4646
4800
  this.data = input.required(/* @ts-ignore */
4647
4801
  ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
4802
+ this.tabKey = input.required(/* @ts-ignore */
4803
+ ...(ngDevMode ? [{ debugName: "tabKey" }] : /* istanbul ignore next */ []));
4648
4804
  this.actionCompleted = output();
4649
4805
  this.itemClicked = output();
4650
4806
  //#endregion
4651
- //#region ---- State ----
4807
+ //#region ----- State -----
4652
4808
  this.pendingAction = signal(null, /* @ts-ignore */
4653
4809
  ...(ngDevMode ? [{ debugName: "pendingAction" }] : /* istanbul ignore next */ []));
4810
+ this.ctaDisplayText = signal('', /* @ts-ignore */
4811
+ ...(ngDevMode ? [{ debugName: "ctaDisplayText" }] : /* istanbul ignore next */ []));
4812
+ this.ctaTextRequestId = 0;
4654
4813
  //#endregion
4655
- //#region ---- Computed ----
4814
+ //#region ----- Computed -----
4815
+ this.isInProgressTab = computed(() => this.tabKey() === 'in-progress', /* @ts-ignore */
4816
+ ...(ngDevMode ? [{ debugName: "isInProgressTab" }] : /* istanbul ignore next */ []));
4817
+ this.isCompletedTab = computed(() => this.tabKey() === 'completed', /* @ts-ignore */
4818
+ ...(ngDevMode ? [{ debugName: "isCompletedTab" }] : /* istanbul ignore next */ []));
4656
4819
  this.statusClass = computed(() => `--${this.data().status}`, /* @ts-ignore */
4657
4820
  ...(ngDevMode ? [{ debugName: "statusClass" }] : /* istanbul ignore next */ []));
4658
4821
  this.statusIcon = computed(() => {
@@ -4689,12 +4852,14 @@ class AXPBackgroundOperationItemComponent {
4689
4852
  ...(ngDevMode ? [{ debugName: "progressColor" }] : /* istanbul ignore next */ []));
4690
4853
  this.showProgressBar = computed(() => {
4691
4854
  const operation = this.data();
4692
- return axpIsActiveBackgroundOperationStatus(operation.status);
4855
+ return (this.isInProgressTab() &&
4856
+ operation.capabilities.supportsProgress === true &&
4857
+ axpIsActiveBackgroundOperationStatus(operation.status));
4693
4858
  }, /* @ts-ignore */
4694
4859
  ...(ngDevMode ? [{ debugName: "showProgressBar" }] : /* istanbul ignore next */ []));
4695
4860
  this.isIndeterminateProgress = computed(() => {
4696
4861
  const operation = this.data();
4697
- return !isNumber(operation.progress) && !operation.currentStep;
4862
+ return operation.capabilities.supportsProgress === true && !isNumber(operation.progress);
4698
4863
  }, /* @ts-ignore */
4699
4864
  ...(ngDevMode ? [{ debugName: "isIndeterminateProgress" }] : /* istanbul ignore next */ []));
4700
4865
  this.progressMode = computed(() => this.isIndeterminateProgress() ? 'indeterminate' : 'determinate', /* @ts-ignore */
@@ -4707,54 +4872,168 @@ class AXPBackgroundOperationItemComponent {
4707
4872
  return 0;
4708
4873
  }, /* @ts-ignore */
4709
4874
  ...(ngDevMode ? [{ debugName: "progressValue" }] : /* istanbul ignore next */ []));
4710
- this.isClickable = computed(() => this.operationService.hasClickHandler(this.data()), /* @ts-ignore */
4711
- ...(ngDevMode ? [{ debugName: "isClickable" }] : /* istanbul ignore next */ []));
4875
+ this.showProgressPercent = computed(() => this.showProgressBar() && !this.isIndeterminateProgress(), /* @ts-ignore */
4876
+ ...(ngDevMode ? [{ debugName: "showProgressPercent" }] : /* istanbul ignore next */ []));
4712
4877
  this.showError = computed(() => this.data().status === 'failed' && !!this.data().error?.message, /* @ts-ignore */
4713
4878
  ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
4714
4879
  this.actions = computed(() => this.operationService.getAvailableActions(this.data()), /* @ts-ignore */
4715
4880
  ...(ngDevMode ? [{ debugName: "actions" }] : /* istanbul ignore next */ []));
4716
- this.showMetaRow = computed(() => {
4881
+ this.cta = computed(() => this.isCompletedTab() ? this.operationService.getCta(this.data()) : null, /* @ts-ignore */
4882
+ ...(ngDevMode ? [{ debugName: "cta" }] : /* istanbul ignore next */ []));
4883
+ this.showCancelButton = computed(() => this.isInProgressTab() && this.data().capabilities.cancellable && this.actions().includes('cancel'), /* @ts-ignore */
4884
+ ...(ngDevMode ? [{ debugName: "showCancelButton" }] : /* istanbul ignore next */ []));
4885
+ this.showPauseButton = computed(() => this.isInProgressTab() &&
4886
+ !this.showCancelButton() &&
4887
+ this.data().capabilities.pausable &&
4888
+ this.actions().includes('pause'), /* @ts-ignore */
4889
+ ...(ngDevMode ? [{ debugName: "showPauseButton" }] : /* istanbul ignore next */ []));
4890
+ this.showResumeButton = computed(() => this.isInProgressTab() && this.data().capabilities.resumable && this.actions().includes('resume'), /* @ts-ignore */
4891
+ ...(ngDevMode ? [{ debugName: "showResumeButton" }] : /* istanbul ignore next */ []));
4892
+ this.showDismissButton = computed(() => this.isCompletedTab() && this.actions().includes('dismiss'), /* @ts-ignore */
4893
+ ...(ngDevMode ? [{ debugName: "showDismissButton" }] : /* istanbul ignore next */ []));
4894
+ this.showActionColumn = computed(() => this.showCancelButton() || this.showPauseButton() || this.showResumeButton(), /* @ts-ignore */
4895
+ ...(ngDevMode ? [{ debugName: "showActionColumn" }] : /* istanbul ignore next */ []));
4896
+ this.showCompletedActionRow = computed(() => this.isCompletedTab() && (this.cta() !== null || this.showDismissButton()), /* @ts-ignore */
4897
+ ...(ngDevMode ? [{ debugName: "showCompletedActionRow" }] : /* istanbul ignore next */ []));
4898
+ this.statusTextKey = computed(() => {
4899
+ const statusText = this.data().statusText?.trim();
4900
+ return axpIsBackgroundOperationI18nText(statusText) ? statusText : null;
4901
+ }, /* @ts-ignore */
4902
+ ...(ngDevMode ? [{ debugName: "statusTextKey" }] : /* istanbul ignore next */ []));
4903
+ this.statusTextParams = computed(() => axpBackgroundOperationStatusTextParams(this.data()), /* @ts-ignore */
4904
+ ...(ngDevMode ? [{ debugName: "statusTextParams" }] : /* istanbul ignore next */ []));
4905
+ this.plainStatusText = computed(() => {
4906
+ const statusText = this.data().statusText?.trim();
4907
+ if (!statusText || axpIsBackgroundOperationI18nText(statusText)) {
4908
+ return null;
4909
+ }
4910
+ return statusText;
4911
+ }, /* @ts-ignore */
4912
+ ...(ngDevMode ? [{ debugName: "plainStatusText" }] : /* istanbul ignore next */ []));
4913
+ this.errorMessageKey = computed(() => {
4914
+ const message = this.data().error?.message?.trim();
4915
+ return axpIsBackgroundOperationI18nText(message) ? message : null;
4916
+ }, /* @ts-ignore */
4917
+ ...(ngDevMode ? [{ debugName: "errorMessageKey" }] : /* istanbul ignore next */ []));
4918
+ this.plainErrorMessage = computed(() => {
4919
+ const message = this.data().error?.message?.trim();
4920
+ if (!message || axpIsBackgroundOperationI18nText(message)) {
4921
+ return null;
4922
+ }
4923
+ return message;
4924
+ }, /* @ts-ignore */
4925
+ ...(ngDevMode ? [{ debugName: "plainErrorMessage" }] : /* istanbul ignore next */ []));
4926
+ this.showStepLine = computed(() => {
4717
4927
  const operation = this.data();
4718
- return (!!operation.statusText ||
4719
- !!operation.currentStep ||
4720
- this.actions().length > 0);
4928
+ if (!operation.currentStep?.trim()) {
4929
+ return false;
4930
+ }
4931
+ const statusText = operation.statusText?.trim() ?? '';
4932
+ return !(statusText.includes('layout-line-single') ||
4933
+ statusText.includes('progress.layout'));
4721
4934
  }, /* @ts-ignore */
4722
- ...(ngDevMode ? [{ debugName: "showMetaRow" }] : /* istanbul ignore next */ []));
4935
+ ...(ngDevMode ? [{ debugName: "showStepLine" }] : /* istanbul ignore next */ []));
4936
+ this.displayTime = computed(() => {
4937
+ const operation = this.data();
4938
+ const completedAt = axpCoerceBackgroundOperationDate(operation.completedAt);
4939
+ if (completedAt && !axpIsInProgressPanelBackgroundOperation(operation)) {
4940
+ return completedAt;
4941
+ }
4942
+ return axpBackgroundOperationDisplayTime(operation) ?? operation.createdAt;
4943
+ }, /* @ts-ignore */
4944
+ ...(ngDevMode ? [{ debugName: "displayTime" }] : /* istanbul ignore next */ []));
4945
+ this.showDate = computed(() => !!this.displayTime(), /* @ts-ignore */
4946
+ ...(ngDevMode ? [{ debugName: "showDate" }] : /* istanbul ignore next */ []));
4947
+ /** Absolute timestamp for locale-aware `format` pipe (`datetime` / `short`). */
4948
+ this.timingDatetime = computed(() => {
4949
+ const operation = this.data();
4950
+ if (axpIsActiveBackgroundOperationStatus(operation.status)) {
4951
+ return (axpBackgroundOperationDisplayTime(operation) ??
4952
+ axpCoerceBackgroundOperationDate(operation.createdAt));
4953
+ }
4954
+ return axpCoerceBackgroundOperationDate(operation.completedAt);
4955
+ }, /* @ts-ignore */
4956
+ ...(ngDevMode ? [{ debugName: "timingDatetime" }] : /* istanbul ignore next */ []));
4957
+ this.timingDuration = computed(() => {
4958
+ const operation = this.data();
4959
+ if (axpIsActiveBackgroundOperationStatus(operation.status)) {
4960
+ if (operation.capabilities.supportsEstimate !== true) {
4961
+ return null;
4962
+ }
4963
+ const remainingMs = axpBackgroundOperationRemainingMs(operation);
4964
+ return remainingMs !== null ? axpFormatBackgroundOperationDurationMs(remainingMs) : null;
4965
+ }
4966
+ const durationMs = axpBackgroundOperationDurationMs(operation);
4967
+ return durationMs !== null ? axpFormatBackgroundOperationDurationMs(durationMs) : null;
4968
+ }, /* @ts-ignore */
4969
+ ...(ngDevMode ? [{ debugName: "timingDuration" }] : /* istanbul ignore next */ []));
4970
+ this.showCompletedSummaryLine = computed(() => {
4971
+ if (!this.isCompletedTab()) {
4972
+ return false;
4973
+ }
4974
+ return !!this.statusTextKey() || !!this.plainStatusText() || !!this.timingDatetime();
4975
+ }, /* @ts-ignore */
4976
+ ...(ngDevMode ? [{ debugName: "showCompletedSummaryLine" }] : /* istanbul ignore next */ []));
4977
+ this.showEstimateLine = computed(() => this.isInProgressTab() &&
4978
+ this.data().capabilities.supportsEstimate === true &&
4979
+ !!this.timingDuration(), /* @ts-ignore */
4980
+ ...(ngDevMode ? [{ debugName: "showEstimateLine" }] : /* istanbul ignore next */ []));
4981
+ effect(() => {
4982
+ const cta = this.cta();
4983
+ const requestId = ++this.ctaTextRequestId;
4984
+ if (!cta) {
4985
+ this.ctaDisplayText.set('');
4986
+ return;
4987
+ }
4988
+ if (axpIsBackgroundOperationI18nText(cta.text)) {
4989
+ void this.translateService.translateAsync(cta.text).then((text) => {
4990
+ if (requestId === this.ctaTextRequestId) {
4991
+ this.ctaDisplayText.set(text);
4992
+ }
4993
+ });
4994
+ return;
4995
+ }
4996
+ this.ctaDisplayText.set(cta.text);
4997
+ });
4723
4998
  }
4724
4999
  //#endregion
4725
- //#region ---- Action presentation ----
5000
+ //#region ----- Action presentation -----
4726
5001
  actionLabelKey(action) {
4727
5002
  return `@general:background-operation.actions.${action}`;
4728
5003
  }
4729
- actionButtonLook(action) {
4730
- if (action === 'dismiss') {
4731
- return 'blank';
5004
+ isCtaDisabled(cta) {
5005
+ const pending = this.pendingAction();
5006
+ if (cta.command.name === 'click') {
5007
+ return pending !== null && pending !== 'click';
4732
5008
  }
4733
- return 'twotone';
4734
- }
4735
- actionButtonColor(action) {
4736
- switch (action) {
4737
- case 'cancel':
4738
- return 'danger';
4739
- case 'resume':
4740
- case 'retry':
4741
- return 'primary';
4742
- default:
4743
- return 'default';
5009
+ if (this.isBackgroundActionKey(cta.command.name)) {
5010
+ return this.isActionDisabled(cta.command.name) || this.isActionLoading(cta.command.name);
4744
5011
  }
5012
+ return pending !== null;
4745
5013
  }
4746
5014
  //#endregion
4747
- //#region ---- Event Handlers ----
4748
- async onItemClick() {
4749
- if (!this.isClickable()) {
5015
+ //#region ----- Event Handlers -----
5016
+ async onCtaClick(cta) {
5017
+ if (this.pendingAction()) {
4750
5018
  return;
4751
5019
  }
4752
- try {
4753
- await this.operationService.executeClick(this.data().id);
4754
- this.itemClicked.emit();
5020
+ if (cta.command.name === 'click') {
5021
+ this.pendingAction.set('click');
5022
+ try {
5023
+ await this.operationService.executeClick(this.data().id);
5024
+ this.itemClicked.emit();
5025
+ this.actionCompleted.emit();
5026
+ }
5027
+ catch (error) {
5028
+ console.error('Background operation CTA failed:', error);
5029
+ }
5030
+ finally {
5031
+ this.pendingAction.set(null);
5032
+ }
5033
+ return;
4755
5034
  }
4756
- catch (error) {
4757
- console.error('Background operation click failed:', error);
5035
+ if (this.isBackgroundActionKey(cta.command.name)) {
5036
+ await this.onAction(cta.command.name);
4758
5037
  }
4759
5038
  }
4760
5039
  async onAction(action) {
@@ -4780,17 +5059,29 @@ class AXPBackgroundOperationItemComponent {
4780
5059
  isActionLoading(action) {
4781
5060
  return this.pendingAction() === action;
4782
5061
  }
5062
+ //#endregion
5063
+ //#region ----- Helpers -----
5064
+ isBackgroundActionKey(value) {
5065
+ return value === 'cancel' || value === 'pause' || value === 'resume' || value === 'retry' || value === 'dismiss';
5066
+ }
4783
5067
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPBackgroundOperationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4784
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 .operation-item__body{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.operation-item .operation-item__header{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.operation-item .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 .operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500))}.operation-item .operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500))}.operation-item .operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500))}.operation-item .operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500))}.operation-item .operation-item__summary{display:flex;min-width:0px;flex:1;flex-direction:column;gap:var(--spacing, .25rem)}.operation-item .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 .operation-item__meta{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.operation-item .operation-item__meta-content{display:flex;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}.operation-item .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 .operation-item__step{display:inline-block;font-size:.6875rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item .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 .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.3 | 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 }); }
5068
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPBackgroundOperationItemComponent, isStandalone: true, selector: "axp-background-operation-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, tabKey: { classPropertyName: "tabKey", publicName: "tabKey", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { actionCompleted: "actionCompleted", itemClicked: "itemClicked" }, ngImport: i0, template: "<article class=\"operation-item\" [class]=\"statusClass()\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__content\">\n <div class=\"operation-item__headline\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n </div>\n\n @if (isCompletedTab()) {\n @if (showCompletedSummaryLine()) {\n <!-- ----- Status merged with finished time and duration ----- -->\n <p class=\"operation-item__status-text\">\n @if (statusTextKey(); as key) {\n <span>{{ key | translate: { params: statusTextParams() } | async }}</span>\n } @else if (plainStatusText()) {\n <span>{{ plainStatusText() }}</span>\n }\n @if (timingDatetime(); as finishedAt) {\n @if (statusTextKey() || plainStatusText()) {\n <span class=\"operation-item__status-separator\" aria-hidden=\"true\"> \u00B7 </span>\n }\n <!--->\n <!-- ----- Locale-aware finished datetime via format pipe ----- -->\n @if ((finishedAt | format: 'datetime' : 'short' | async); as datetime) {\n <span>{{\n '@general:background-operation.timing.finished-at'\n | translate: { params: { datetime } }\n | async\n }}</span>\n }\n <!--->\n <!-- ----- Compact duration when available ----- -->\n @if (timingDuration(); as duration) {\n <span class=\"operation-item__status-separator\" aria-hidden=\"true\"> \u00B7 </span>\n <span>{{\n '@general:background-operation.timing.duration'\n | translate: { params: { duration } }\n | async\n }}</span>\n }\n }\n </p>\n }\n } @else {\n @if (statusTextKey(); as key) {\n <p class=\"operation-item__status-text\">\n {{ key | translate: { params: statusTextParams() } | async }}\n </p>\n } @else if (plainStatusText()) {\n <p class=\"operation-item__status-text\">\n {{ plainStatusText() }}\n </p>\n }\n }\n\n @if (showStepLine()) {\n <span class=\"operation-item__step\">\n {{ '@general:background-operation.step' | translate | async }}\n {{ data().currentStep }}\n </span>\n }\n\n @if (timingDatetime(); as startedAt) {\n <!--->\n <!-- ----- Started time and estimate for in-progress tasks ----- -->\n @if (isInProgressTab()) {\n <div class=\"operation-item__timing\">\n <!-- ----- Locale-aware started datetime via format pipe ----- -->\n @if ((startedAt | format: 'datetime' : 'short' | async); as datetime) {\n <span>\n {{\n '@general:background-operation.timing.started-at'\n | translate: { params: { datetime } }\n | async\n }}\n </span>\n }\n <!--->\n <!-- ----- ETA when the task type supports estimates ----- -->\n @if (showEstimateLine()) {\n <span>\n {{\n '@general:background-operation.timing.estimate'\n | translate: { params: { estimate: timingDuration()! } }\n | async\n }}\n </span>\n }\n </div>\n }\n }\n\n @if (showCompletedActionRow()) {\n <div class=\"ax-xs operation-item__footer-actions\">\n @if (cta(); as primaryCta) {\n <!-- ----- Handler-defined CTA on completed tab ----- -->\n <ax-button\n class=\"operation-item__action-btn\"\n look=\"solid\"\n [color]=\"primaryCta.color ?? 'primary'\"\n [text]=\"ctaDisplayText()\"\n [disabled]=\"isCtaDisabled(primaryCta)\"\n (onClick)=\"onCtaClick(primaryCta)\"\n >\n @if (primaryCta.icon) {\n <ax-prefix>\n <ax-icon><i [class]=\"primaryCta.icon\"></i></ax-icon>\n </ax-prefix>\n }\n </ax-button>\n }\n @if (showDismissButton()) {\n <!-- ----- Close / dismiss completed rows ----- -->\n <ax-button\n class=\"operation-item__action-btn\"\n look=\"solid\"\n color=\"default\"\n [text]=\"(actionLabelKey('dismiss') | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled('dismiss') || isActionLoading('dismiss')\"\n (onClick)=\"onAction('dismiss')\"\n ></ax-button>\n }\n </div>\n }\n\n @if (showProgressBar()) {\n <div class=\"operation-item__progress-row\">\n @if (showProgressPercent()) {\n <span class=\"operation-item__progress-label\">\n {{\n '@general:background-operation.progress-percent'\n | translate: { params: { percent: progressValue() } }\n | async\n }}\n </span>\n }\n <ax-progress-bar\n class=\"operation-item__progress\"\n [progress]=\"progressValue()\"\n [mode]=\"progressMode()\"\n [color]=\"progressColor()\"\n [style.height.px]=\"4\"\n ></ax-progress-bar>\n </div>\n }\n\n @if (showError()) {\n @if (errorMessageKey(); as errorKey) {\n <p class=\"operation-item__error\" role=\"alert\">\n {{ errorKey | translate | async }}\n </p>\n } @else if (plainErrorMessage()) {\n <p class=\"operation-item__error\" role=\"alert\">\n {{ plainErrorMessage() }}\n </p>\n }\n }\n </div>\n\n @if (showDate() || showActionColumn()) {\n <div class=\"operation-item__aside\">\n @if (showDate()) {\n <span class=\"operation-item__time\">{{ displayTime() | format: 'timeleft' | async }}</span>\n }\n @if (showActionColumn()) {\n <div class=\"operation-item__actions\" (click)=\"$event.stopPropagation()\">\n @if (isInProgressTab()) {\n @if (showCancelButton()) {\n <!-- ----- Cancel for in-progress cancellable tasks ----- -->\n <ax-button\n class=\"ax-xs operation-item__action-btn\"\n look=\"outline\"\n color=\"danger\"\n [text]=\"(actionLabelKey('cancel') | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled('cancel') || isActionLoading('cancel')\"\n (onClick)=\"onAction('cancel')\"\n ></ax-button>\n }\n @if (showPauseButton()) {\n <!-- ----- Pause when supported and no cancel is shown ----- -->\n <ax-button\n class=\"ax-xs operation-item__action-btn\"\n look=\"outline\"\n color=\"default\"\n [text]=\"(actionLabelKey('pause') | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled('pause') || isActionLoading('pause')\"\n (onClick)=\"onAction('pause')\"\n ></ax-button>\n }\n @if (showResumeButton()) {\n <!-- ----- Resume for paused tasks ----- -->\n <ax-button\n class=\"ax-xs operation-item__action-btn\"\n look=\"outline\"\n color=\"primary\"\n [text]=\"(actionLabelKey('resume') | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled('resume') || isActionLoading('resume')\"\n (onClick)=\"onAction('resume')\"\n ></ax-button>\n }\n }\n </div>\n }\n </div>\n }\n</article>\n", styles: ["@layer properties;axp-background-operation-item{display:block;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-background-operation-item:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0px}.operation-item{position:relative;display:flex;align-items:flex-start;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);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: .15s;transition-duration:.15s}.operation-item.--failed{background:rgb(var(--ax-sys-color-danger-lightest-surface) / .35)}.operation-item__status-icon{margin-top:calc(var(--spacing, .25rem) * .5);display:flex;width:calc(var(--spacing, .25rem) * 12);height:calc(var(--spacing, .25rem) * 12);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1;color:rgb(var(--ax-sys-color-on-surface-variant));border-color:rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500));border-color:rgb(var(--ax-sys-color-border-primary-light-surface));background:rgb(var(--ax-sys-color-primary-lightest-surface))}.operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500));border-color:rgb(var(--ax-sys-color-border-warning-light-surface));background:rgb(var(--ax-sys-color-warning-lightest-surface))}.operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500));border-color:rgb(var(--ax-sys-color-border-success-light-surface));background:rgb(var(--ax-sys-color-success-lightest-surface))}.operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500));border-color:rgb(var(--ax-sys-color-border-danger-light-surface));background:rgb(var(--ax-sys-color-danger-lightest-surface))}.operation-item__content{display:flex;min-width:0px;flex:1;flex-direction:column;gap:var(--spacing, .25rem);text-align:start}.operation-item__headline{min-width:0px}.operation-item__title{margin:0;min-width:0px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;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__aside{position:relative;flex-shrink:0;align-self:stretch;min-width:3.5rem}.operation-item__time{position:relative;z-index:1;padding-top:calc(var(--spacing, .25rem) * .5);text-align:end;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));white-space:nowrap;color:rgb(var(--ax-sys-color-on-surface-variant))}.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-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--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:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__timing{display:flex;flex-wrap:wrap;column-gap:calc(var(--spacing, .25rem) * 2);row-gap:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__progress-row{margin-top:var(--spacing, .25rem);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.operation-item__progress-label{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__progress{min-width:0px;flex:1}.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__status-separator{white-space:pre}.operation-item__footer-actions{margin-top:var(--spacing, .25rem);display:flex;flex-wrap:wrap;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.operation-item__actions{position:absolute;top:50%;right:0;display:flex;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);flex-direction:column;align-items:flex-end;gap:var(--spacing, .25rem)}.operation-item__action-btn{white-space:nowrap}@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;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@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;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.3.3 | 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: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.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: AXProgressBarModule }, { kind: "component", type: i3.AXProgressBarComponent, selector: "ax-progress-bar", inputs: ["color", "mode", "progress", "height"], outputs: ["ValueChange", "sizeChange"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i2$1.AXFormatPipe, name: "format" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4785
5069
  }
4786
5070
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPBackgroundOperationItemComponent, decorators: [{
4787
5071
  type: Component,
4788
- 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 .operation-item__body{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.operation-item .operation-item__header{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.operation-item .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 .operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500))}.operation-item .operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500))}.operation-item .operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500))}.operation-item .operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500))}.operation-item .operation-item__summary{display:flex;min-width:0px;flex:1;flex-direction:column;gap:var(--spacing, .25rem)}.operation-item .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 .operation-item__meta{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.operation-item .operation-item__meta-content{display:flex;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}.operation-item .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 .operation-item__step{display:inline-block;font-size:.6875rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item .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 .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.3 | MIT License | https://tailwindcss.com */\n"] }]
4789
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], actionCompleted: [{ type: i0.Output, args: ["actionCompleted"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
5072
+ args: [{ selector: 'axp-background-operation-item', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
5073
+ CommonModule,
5074
+ AXButtonModule,
5075
+ AXDecoratorModule,
5076
+ AXProgressBarModule,
5077
+ AXFormatModule,
5078
+ AXTranslationModule,
5079
+ ], template: "<article class=\"operation-item\" [class]=\"statusClass()\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__content\">\n <div class=\"operation-item__headline\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n </div>\n\n @if (isCompletedTab()) {\n @if (showCompletedSummaryLine()) {\n <!-- ----- Status merged with finished time and duration ----- -->\n <p class=\"operation-item__status-text\">\n @if (statusTextKey(); as key) {\n <span>{{ key | translate: { params: statusTextParams() } | async }}</span>\n } @else if (plainStatusText()) {\n <span>{{ plainStatusText() }}</span>\n }\n @if (timingDatetime(); as finishedAt) {\n @if (statusTextKey() || plainStatusText()) {\n <span class=\"operation-item__status-separator\" aria-hidden=\"true\"> \u00B7 </span>\n }\n <!--->\n <!-- ----- Locale-aware finished datetime via format pipe ----- -->\n @if ((finishedAt | format: 'datetime' : 'short' | async); as datetime) {\n <span>{{\n '@general:background-operation.timing.finished-at'\n | translate: { params: { datetime } }\n | async\n }}</span>\n }\n <!--->\n <!-- ----- Compact duration when available ----- -->\n @if (timingDuration(); as duration) {\n <span class=\"operation-item__status-separator\" aria-hidden=\"true\"> \u00B7 </span>\n <span>{{\n '@general:background-operation.timing.duration'\n | translate: { params: { duration } }\n | async\n }}</span>\n }\n }\n </p>\n }\n } @else {\n @if (statusTextKey(); as key) {\n <p class=\"operation-item__status-text\">\n {{ key | translate: { params: statusTextParams() } | async }}\n </p>\n } @else if (plainStatusText()) {\n <p class=\"operation-item__status-text\">\n {{ plainStatusText() }}\n </p>\n }\n }\n\n @if (showStepLine()) {\n <span class=\"operation-item__step\">\n {{ '@general:background-operation.step' | translate | async }}\n {{ data().currentStep }}\n </span>\n }\n\n @if (timingDatetime(); as startedAt) {\n <!--->\n <!-- ----- Started time and estimate for in-progress tasks ----- -->\n @if (isInProgressTab()) {\n <div class=\"operation-item__timing\">\n <!-- ----- Locale-aware started datetime via format pipe ----- -->\n @if ((startedAt | format: 'datetime' : 'short' | async); as datetime) {\n <span>\n {{\n '@general:background-operation.timing.started-at'\n | translate: { params: { datetime } }\n | async\n }}\n </span>\n }\n <!--->\n <!-- ----- ETA when the task type supports estimates ----- -->\n @if (showEstimateLine()) {\n <span>\n {{\n '@general:background-operation.timing.estimate'\n | translate: { params: { estimate: timingDuration()! } }\n | async\n }}\n </span>\n }\n </div>\n }\n }\n\n @if (showCompletedActionRow()) {\n <div class=\"ax-xs operation-item__footer-actions\">\n @if (cta(); as primaryCta) {\n <!-- ----- Handler-defined CTA on completed tab ----- -->\n <ax-button\n class=\"operation-item__action-btn\"\n look=\"solid\"\n [color]=\"primaryCta.color ?? 'primary'\"\n [text]=\"ctaDisplayText()\"\n [disabled]=\"isCtaDisabled(primaryCta)\"\n (onClick)=\"onCtaClick(primaryCta)\"\n >\n @if (primaryCta.icon) {\n <ax-prefix>\n <ax-icon><i [class]=\"primaryCta.icon\"></i></ax-icon>\n </ax-prefix>\n }\n </ax-button>\n }\n @if (showDismissButton()) {\n <!-- ----- Close / dismiss completed rows ----- -->\n <ax-button\n class=\"operation-item__action-btn\"\n look=\"solid\"\n color=\"default\"\n [text]=\"(actionLabelKey('dismiss') | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled('dismiss') || isActionLoading('dismiss')\"\n (onClick)=\"onAction('dismiss')\"\n ></ax-button>\n }\n </div>\n }\n\n @if (showProgressBar()) {\n <div class=\"operation-item__progress-row\">\n @if (showProgressPercent()) {\n <span class=\"operation-item__progress-label\">\n {{\n '@general:background-operation.progress-percent'\n | translate: { params: { percent: progressValue() } }\n | async\n }}\n </span>\n }\n <ax-progress-bar\n class=\"operation-item__progress\"\n [progress]=\"progressValue()\"\n [mode]=\"progressMode()\"\n [color]=\"progressColor()\"\n [style.height.px]=\"4\"\n ></ax-progress-bar>\n </div>\n }\n\n @if (showError()) {\n @if (errorMessageKey(); as errorKey) {\n <p class=\"operation-item__error\" role=\"alert\">\n {{ errorKey | translate | async }}\n </p>\n } @else if (plainErrorMessage()) {\n <p class=\"operation-item__error\" role=\"alert\">\n {{ plainErrorMessage() }}\n </p>\n }\n }\n </div>\n\n @if (showDate() || showActionColumn()) {\n <div class=\"operation-item__aside\">\n @if (showDate()) {\n <span class=\"operation-item__time\">{{ displayTime() | format: 'timeleft' | async }}</span>\n }\n @if (showActionColumn()) {\n <div class=\"operation-item__actions\" (click)=\"$event.stopPropagation()\">\n @if (isInProgressTab()) {\n @if (showCancelButton()) {\n <!-- ----- Cancel for in-progress cancellable tasks ----- -->\n <ax-button\n class=\"ax-xs operation-item__action-btn\"\n look=\"outline\"\n color=\"danger\"\n [text]=\"(actionLabelKey('cancel') | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled('cancel') || isActionLoading('cancel')\"\n (onClick)=\"onAction('cancel')\"\n ></ax-button>\n }\n @if (showPauseButton()) {\n <!-- ----- Pause when supported and no cancel is shown ----- -->\n <ax-button\n class=\"ax-xs operation-item__action-btn\"\n look=\"outline\"\n color=\"default\"\n [text]=\"(actionLabelKey('pause') | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled('pause') || isActionLoading('pause')\"\n (onClick)=\"onAction('pause')\"\n ></ax-button>\n }\n @if (showResumeButton()) {\n <!-- ----- Resume for paused tasks ----- -->\n <ax-button\n class=\"ax-xs operation-item__action-btn\"\n look=\"outline\"\n color=\"primary\"\n [text]=\"(actionLabelKey('resume') | translate | async) ?? ''\"\n [disabled]=\"isActionDisabled('resume') || isActionLoading('resume')\"\n (onClick)=\"onAction('resume')\"\n ></ax-button>\n }\n }\n </div>\n }\n </div>\n }\n</article>\n", styles: ["@layer properties;axp-background-operation-item{display:block;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgb(var(--ax-sys-color-border-lightest-surface))}axp-background-operation-item:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0px}.operation-item{position:relative;display:flex;align-items:flex-start;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);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: .15s;transition-duration:.15s}.operation-item.--failed{background:rgb(var(--ax-sys-color-danger-lightest-surface) / .35)}.operation-item__status-icon{margin-top:calc(var(--spacing, .25rem) * .5);display:flex;width:calc(var(--spacing, .25rem) * 12);height:calc(var(--spacing, .25rem) * 12);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1;color:rgb(var(--ax-sys-color-on-surface-variant));border-color:rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500));border-color:rgb(var(--ax-sys-color-border-primary-light-surface));background:rgb(var(--ax-sys-color-primary-lightest-surface))}.operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500));border-color:rgb(var(--ax-sys-color-border-warning-light-surface));background:rgb(var(--ax-sys-color-warning-lightest-surface))}.operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500));border-color:rgb(var(--ax-sys-color-border-success-light-surface));background:rgb(var(--ax-sys-color-success-lightest-surface))}.operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500));border-color:rgb(var(--ax-sys-color-border-danger-light-surface));background:rgb(var(--ax-sys-color-danger-lightest-surface))}.operation-item__content{display:flex;min-width:0px;flex:1;flex-direction:column;gap:var(--spacing, .25rem);text-align:start}.operation-item__headline{min-width:0px}.operation-item__title{margin:0;min-width:0px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;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__aside{position:relative;flex-shrink:0;align-self:stretch;min-width:3.5rem}.operation-item__time{position:relative;z-index:1;padding-top:calc(var(--spacing, .25rem) * .5);text-align:end;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));white-space:nowrap;color:rgb(var(--ax-sys-color-on-surface-variant))}.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-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--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:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__timing{display:flex;flex-wrap:wrap;column-gap:calc(var(--spacing, .25rem) * 2);row-gap:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__progress-row{margin-top:var(--spacing, .25rem);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.operation-item__progress-label{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__progress{min-width:0px;flex:1}.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__status-separator{white-space:pre}.operation-item__footer-actions{margin-top:var(--spacing, .25rem);display:flex;flex-wrap:wrap;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.operation-item__actions{position:absolute;top:50%;right:0;display:flex;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);flex-direction:column;align-items:flex-end;gap:var(--spacing, .25rem)}.operation-item__action-btn{white-space:nowrap}@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;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@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;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
5080
+ }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], tabKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabKey", required: true }] }], actionCompleted: [{ type: i0.Output, args: ["actionCompleted"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
4790
5081
 
4791
- //#region ---- Imports ----
5082
+ //#region ----- Imports -----
4792
5083
  //#endregion
4793
- //#region ---- Sort priority ----
5084
+ //#region ----- Sort priority -----
4794
5085
  const STATUS_SORT_PRIORITY = {
4795
5086
  running: 0,
4796
5087
  queued: 1,
@@ -4799,36 +5090,163 @@ const STATUS_SORT_PRIORITY = {
4799
5090
  completed: 4,
4800
5091
  cancelled: 5,
4801
5092
  };
5093
+ function sortBackgroundOperations(left, right) {
5094
+ const priorityDiff = STATUS_SORT_PRIORITY[left.status] - STATUS_SORT_PRIORITY[right.status];
5095
+ if (priorityDiff !== 0) {
5096
+ return priorityDiff;
5097
+ }
5098
+ return right.createdAt.getTime() - left.createdAt.getTime();
5099
+ }
4802
5100
  //#endregion
4803
- //#region ---- Component ----
5101
+ //#region ----- Component -----
4804
5102
  class AXPBackgroundOperationPanelComponent {
4805
5103
  constructor() {
4806
- //#region ---- Outputs ----
5104
+ //#region ----- Outputs -----
4807
5105
  this.onActiveCountChange = output();
4808
5106
  this.onClosePopover = output();
4809
5107
  //#endregion
4810
- //#region ---- Services & Dependencies ----
5108
+ //#region ----- Services & Dependencies -----
4811
5109
  this.operationService = inject(AXPBackgroundOperationService);
5110
+ this.injector = inject(Injector);
4812
5111
  //#endregion
4813
- //#region ---- Computed ----
4814
- this.visibleOperations = computed(() => [...this.operationService.operations()]
4815
- .filter((operation) => axpIsActiveBackgroundOperationStatus(operation.status) || operation.status === 'failed')
4816
- .sort((left, right) => {
4817
- const priorityDiff = STATUS_SORT_PRIORITY[left.status] - STATUS_SORT_PRIORITY[right.status];
4818
- if (priorityDiff !== 0) {
4819
- return priorityDiff;
5112
+ //#region ----- View Queries -----
5113
+ this.tabsHost = viewChild('tabsHost', /* @ts-ignore */
5114
+ ...(ngDevMode ? [{ debugName: "tabsHost" }] : /* istanbul ignore next */ []));
5115
+ //#endregion
5116
+ //#region ----- State -----
5117
+ this.activeTab = signal('in-progress', /* @ts-ignore */
5118
+ ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
5119
+ this.bulkActionPending = signal(false, /* @ts-ignore */
5120
+ ...(ngDevMode ? [{ debugName: "bulkActionPending" }] : /* istanbul ignore next */ []));
5121
+ //#endregion
5122
+ //#region ----- Computed -----
5123
+ this.inProgressOperations = computed(() => [...this.operationService.operations()]
5124
+ .filter((operation) => axpIsTrayVisibleBackgroundOperation(operation) &&
5125
+ axpIsInProgressPanelBackgroundOperation(operation))
5126
+ .sort(sortBackgroundOperations), /* @ts-ignore */
5127
+ ...(ngDevMode ? [{ debugName: "inProgressOperations" }] : /* istanbul ignore next */ []));
5128
+ this.completedOperations = computed(() => [...this.operationService.operations()]
5129
+ .filter((operation) => axpIsCompletedPanelBackgroundOperation(operation))
5130
+ .sort(sortBackgroundOperations), /* @ts-ignore */
5131
+ ...(ngDevMode ? [{ debugName: "completedOperations" }] : /* istanbul ignore next */ []));
5132
+ this.cancellableInProgressOperations = computed(() => this.inProgressOperations().filter((operation) => this.operationService.getAvailableActions(operation).includes('cancel')), /* @ts-ignore */
5133
+ ...(ngDevMode ? [{ debugName: "cancellableInProgressOperations" }] : /* istanbul ignore next */ []));
5134
+ this.dismissibleCompletedOperations = computed(() => this.completedOperations().filter((operation) => this.operationService.getAvailableActions(operation).includes('dismiss')), /* @ts-ignore */
5135
+ ...(ngDevMode ? [{ debugName: "dismissibleCompletedOperations" }] : /* istanbul ignore next */ []));
5136
+ this.showCancelAllButton = computed(() => this.activeTab() === 'in-progress' && this.cancellableInProgressOperations().length > 1, /* @ts-ignore */
5137
+ ...(ngDevMode ? [{ debugName: "showCancelAllButton" }] : /* istanbul ignore next */ []));
5138
+ this.showDismissAllButton = computed(() => this.activeTab() === 'completed' && this.dismissibleCompletedOperations().length > 1, /* @ts-ignore */
5139
+ ...(ngDevMode ? [{ debugName: "showDismissAllButton" }] : /* istanbul ignore next */ []));
5140
+ this.showCloseButton = computed(() => !this.showCancelAllButton() && !this.showDismissAllButton(), /* @ts-ignore */
5141
+ ...(ngDevMode ? [{ debugName: "showCloseButton" }] : /* istanbul ignore next */ []));
5142
+ this.tabItems = computed(() => [
5143
+ {
5144
+ key: 'in-progress',
5145
+ labelKey: '@general:background-operation.tabs.in-progress',
5146
+ count: this.inProgressOperations().length,
5147
+ },
5148
+ {
5149
+ key: 'completed',
5150
+ labelKey: '@general:background-operation.tabs.completed',
5151
+ count: this.completedOperations().length,
5152
+ },
5153
+ ], /* @ts-ignore */
5154
+ ...(ngDevMode ? [{ debugName: "tabItems" }] : /* istanbul ignore next */ []));
5155
+ }
5156
+ //#endregion
5157
+ //#region ----- Event Handlers -----
5158
+ /**
5159
+ * Pick In Progress when any running tasks exist; otherwise Completed.
5160
+ * Must call `ax-tabs.select` — `[active]` alone does not switch tab content.
5161
+ */
5162
+ syncDefaultTab() {
5163
+ const tab = this.inProgressOperations().length > 0 ? 'in-progress' : 'completed';
5164
+ this.activeTab.set(tab);
5165
+ const index = this.tabItems().findIndex((item) => item.key === tab);
5166
+ if (index < 0) {
5167
+ return;
5168
+ }
5169
+ afterNextRender(() => {
5170
+ this.tabsHost()?.select(index);
5171
+ }, { injector: this.injector });
5172
+ }
5173
+ handleTabChange(event) {
5174
+ const tab = this.tabItems()[event.index];
5175
+ if (tab) {
5176
+ this.activeTab.set(tab.key);
5177
+ }
5178
+ }
5179
+ getOperations(tab) {
5180
+ return tab === 'in-progress' ? this.inProgressOperations() : this.completedOperations();
5181
+ }
5182
+ emptyStateForTab(tab) {
5183
+ if (tab === 'in-progress') {
5184
+ return {
5185
+ icon: 'fa-regular fa-clock',
5186
+ titleKey: '@general:background-operation.empty.in-progress',
5187
+ descriptionKey: '@general:background-operation.empty.in-progress-description',
5188
+ };
5189
+ }
5190
+ return {
5191
+ icon: 'fa-regular fa-circle-check',
5192
+ titleKey: '@general:background-operation.empty.completed',
5193
+ descriptionKey: '@general:background-operation.empty.completed-description',
5194
+ };
5195
+ }
5196
+ onItemActionCompleted() {
5197
+ this.onActiveCountChange.emit(this.operationService.activeCount());
5198
+ }
5199
+ async onCancelAll() {
5200
+ if (this.bulkActionPending()) {
5201
+ return;
5202
+ }
5203
+ this.bulkActionPending.set(true);
5204
+ try {
5205
+ for (const operation of this.cancellableInProgressOperations()) {
5206
+ await this.operationService.runAction(operation.id, 'cancel');
4820
5207
  }
4821
- return right.createdAt.getTime() - left.createdAt.getTime();
4822
- }), /* @ts-ignore */
4823
- ...(ngDevMode ? [{ debugName: "visibleOperations" }] : /* istanbul ignore next */ []));
5208
+ this.onItemActionCompleted();
5209
+ }
5210
+ catch (error) {
5211
+ console.error('Background operation cancel-all failed:', error);
5212
+ }
5213
+ finally {
5214
+ this.bulkActionPending.set(false);
5215
+ }
5216
+ }
5217
+ async onDismissAll() {
5218
+ if (this.bulkActionPending()) {
5219
+ return;
5220
+ }
5221
+ this.bulkActionPending.set(true);
5222
+ try {
5223
+ const ids = this.dismissibleCompletedOperations().map((operation) => operation.id);
5224
+ await this.operationService.dismissMany(ids);
5225
+ this.onItemActionCompleted();
5226
+ }
5227
+ catch (error) {
5228
+ console.error('Background operation dismiss-all failed:', error);
5229
+ }
5230
+ finally {
5231
+ this.bulkActionPending.set(false);
5232
+ }
4824
5233
  }
4825
5234
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPBackgroundOperationPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4826
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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.3 | 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 }); }
5235
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPBackgroundOperationPanelComponent, isStandalone: true, selector: "axp-background-operation-panel", outputs: { onActiveCountChange: "onActiveCountChange", onClosePopover: "onClosePopover" }, viewQueries: [{ propertyName: "tabsHost", first: true, predicate: ["tabsHost"], descendants: true, isSignal: true }], ngImport: i0, template: "<header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">\n {{ '@general:background-operation.panel.title' | translate | async }}\n </h2>\n @if (showCancelAllButton()) {\n <!-- ----- Cancel all cancellable in-progress tasks ----- -->\n <ax-button\n class=\"ax-xs operation-panel__header-action\"\n look=\"blank\"\n color=\"danger\"\n [text]=\"('@general:background-operation.actions.cancel-all' | translate | async) ?? ''\"\n [disabled]=\"bulkActionPending() || operationService.loading()\"\n (onClick)=\"onCancelAll()\"\n ></ax-button>\n }\n @if (showDismissAllButton()) {\n <!-- ----- Dismiss all dismissible completed tasks ----- -->\n <ax-button\n class=\"ax-xs operation-panel__header-action\"\n look=\"blank\"\n color=\"default\"\n [text]=\"('@general:background-operation.actions.dismiss-all' | translate | async) ?? ''\"\n [disabled]=\"bulkActionPending() || operationService.loading()\"\n (onClick)=\"onDismissAll()\"\n ></ax-button>\n }\n <ax-button class=\"ax-xs operation-panel__header-action\" look=\"blank\" [iconOnly]=\"true\" (onClick)=\"onClosePopover.emit()\">\n <ax-icon><i class=\"fa-light fa-xmark \" aria-hidden=\"true\"></i></ax-icon>\n </ax-button>\n</header>\n\n<ax-tabs\n #tabsHost\n [content]=\"tabContent\"\n [look]=\"'with-line'\"\n location=\"bottom\"\n (onActiveTabChanged)=\"handleTabChange($event)\"\n>\n @for (tab of tabItems(); track tab.key) {\n <ax-tab-item [text]=\"(tab.labelKey | translate | async) ?? ''\" [active]=\"activeTab() === tab.key\">\n <ax-suffix>\n @if (tab.count > 0) {\n <ax-badge [color]=\"activeTab() === tab.key ? 'primary' : 'ghost'\" [text]=\"tab.count.toString()\"></ax-badge>\n }\n </ax-suffix>\n <ax-content>\n <div class=\"operation-panel__list\">\n @if (getOperations(tab.key).length === 0) {\n @if (emptyStateForTab(tab.key); as emptyState) {\n <axp-state-message [icon]=\"emptyState.icon\" [title]=\"emptyState.titleKey\" [description]=\"emptyState.descriptionKey\" />\n }\n } @else {\n @for (operation of getOperations(tab.key); track operation.id) {\n <axp-background-operation-item [data]=\"operation\" [tabKey]=\"tab.key\" (actionCompleted)=\"onItemActionCompleted()\" (itemClicked)=\"onClosePopover.emit()\"></axp-background-operation-item>\n }\n }\n </div>\n </ax-content>\n </ax-tab-item>\n }\n</ax-tabs>\n\n<ng-template [axTabContent] #tabContent=\"axTabContent\"></ng-template>\n", styles: ["@layer properties;axp-background-operation-panel{display:block;min-height:calc(var(--spacing, .25rem) * 80);width:100%;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-primary-500));background-color:rgba(var(--ax-sys-color-lightest-surface))}@media(width>=48rem){axp-background-operation-panel{width:32rem}}axp-background-operation-panel ax-tabs{padding-inline:calc(var(--spacing, .25rem) * 2)}axp-background-operation-panel .operation-panel__header{display:flex;align-items:center;justify-content:space-between;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;background-color:var(--color-primary);color:var(--color-on-primary);border-color:var(--color-border-primary);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3)}axp-background-operation-panel .operation-panel__title{margin:0;min-width:0px;flex:1;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)}axp-background-operation-panel .operation-panel__header-action{flex-shrink:0}axp-background-operation-panel .operation-panel__header-action .ax-blank-interactive{color:var(--color-white, #fff)!important}axp-background-operation-panel .operation-panel__header-action .ax-blank-interactive:hover{color:rgba(var(--ax-sys-color-primary-500))!important}axp-background-operation-panel .operation-panel__list{display:flex;max-height:50vh;flex-direction:column;overflow-y:auto}@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.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { 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: AXTabsModule }, { kind: "component", type: i2$2.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i2$2.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "directive", type: i2$2.AXTabContentDirective, selector: "[axTabContent]", inputs: ["axTabContent"], exportAs: ["axTabContent"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.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: AXBadgeModule }, { kind: "component", type: i4$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXPBackgroundOperationItemComponent, selector: "axp-background-operation-item", inputs: ["data", "tabKey"], outputs: ["actionCompleted", "itemClicked"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4827
5236
  }
4828
5237
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPBackgroundOperationPanelComponent, decorators: [{
4829
5238
  type: Component,
4830
- 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.3 | MIT License | https://tailwindcss.com */\n"] }]
4831
- }], propDecorators: { onActiveCountChange: [{ type: i0.Output, args: ["onActiveCountChange"] }], onClosePopover: [{ type: i0.Output, args: ["onClosePopover"] }] } });
5239
+ args: [{ selector: 'axp-background-operation-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
5240
+ CommonModule,
5241
+ AXTranslationModule,
5242
+ AXButtonModule,
5243
+ AXTabsModule,
5244
+ AXDecoratorModule,
5245
+ AXBadgeModule,
5246
+ AXPStateMessageComponent,
5247
+ AXPBackgroundOperationItemComponent,
5248
+ ], template: "<header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">\n {{ '@general:background-operation.panel.title' | translate | async }}\n </h2>\n @if (showCancelAllButton()) {\n <!-- ----- Cancel all cancellable in-progress tasks ----- -->\n <ax-button\n class=\"ax-xs operation-panel__header-action\"\n look=\"blank\"\n color=\"danger\"\n [text]=\"('@general:background-operation.actions.cancel-all' | translate | async) ?? ''\"\n [disabled]=\"bulkActionPending() || operationService.loading()\"\n (onClick)=\"onCancelAll()\"\n ></ax-button>\n }\n @if (showDismissAllButton()) {\n <!-- ----- Dismiss all dismissible completed tasks ----- -->\n <ax-button\n class=\"ax-xs operation-panel__header-action\"\n look=\"blank\"\n color=\"default\"\n [text]=\"('@general:background-operation.actions.dismiss-all' | translate | async) ?? ''\"\n [disabled]=\"bulkActionPending() || operationService.loading()\"\n (onClick)=\"onDismissAll()\"\n ></ax-button>\n }\n <ax-button class=\"ax-xs operation-panel__header-action\" look=\"blank\" [iconOnly]=\"true\" (onClick)=\"onClosePopover.emit()\">\n <ax-icon><i class=\"fa-light fa-xmark \" aria-hidden=\"true\"></i></ax-icon>\n </ax-button>\n</header>\n\n<ax-tabs\n #tabsHost\n [content]=\"tabContent\"\n [look]=\"'with-line'\"\n location=\"bottom\"\n (onActiveTabChanged)=\"handleTabChange($event)\"\n>\n @for (tab of tabItems(); track tab.key) {\n <ax-tab-item [text]=\"(tab.labelKey | translate | async) ?? ''\" [active]=\"activeTab() === tab.key\">\n <ax-suffix>\n @if (tab.count > 0) {\n <ax-badge [color]=\"activeTab() === tab.key ? 'primary' : 'ghost'\" [text]=\"tab.count.toString()\"></ax-badge>\n }\n </ax-suffix>\n <ax-content>\n <div class=\"operation-panel__list\">\n @if (getOperations(tab.key).length === 0) {\n @if (emptyStateForTab(tab.key); as emptyState) {\n <axp-state-message [icon]=\"emptyState.icon\" [title]=\"emptyState.titleKey\" [description]=\"emptyState.descriptionKey\" />\n }\n } @else {\n @for (operation of getOperations(tab.key); track operation.id) {\n <axp-background-operation-item [data]=\"operation\" [tabKey]=\"tab.key\" (actionCompleted)=\"onItemActionCompleted()\" (itemClicked)=\"onClosePopover.emit()\"></axp-background-operation-item>\n }\n }\n </div>\n </ax-content>\n </ax-tab-item>\n }\n</ax-tabs>\n\n<ng-template [axTabContent] #tabContent=\"axTabContent\"></ng-template>\n", styles: ["@layer properties;axp-background-operation-panel{display:block;min-height:calc(var(--spacing, .25rem) * 80);width:100%;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-primary-500));background-color:rgba(var(--ax-sys-color-lightest-surface))}@media(width>=48rem){axp-background-operation-panel{width:32rem}}axp-background-operation-panel ax-tabs{padding-inline:calc(var(--spacing, .25rem) * 2)}axp-background-operation-panel .operation-panel__header{display:flex;align-items:center;justify-content:space-between;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;background-color:var(--color-primary);color:var(--color-on-primary);border-color:var(--color-border-primary);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3)}axp-background-operation-panel .operation-panel__title{margin:0;min-width:0px;flex:1;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)}axp-background-operation-panel .operation-panel__header-action{flex-shrink:0}axp-background-operation-panel .operation-panel__header-action .ax-blank-interactive{color:var(--color-white, #fff)!important}axp-background-operation-panel .operation-panel__header-action .ax-blank-interactive:hover{color:rgba(var(--ax-sys-color-primary-500))!important}axp-background-operation-panel .operation-panel__list{display:flex;max-height:50vh;flex-direction:column;overflow-y:auto}@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.3 | MIT License | https://tailwindcss.com */\n"] }]
5249
+ }], propDecorators: { onActiveCountChange: [{ type: i0.Output, args: ["onActiveCountChange"] }], onClosePopover: [{ type: i0.Output, args: ["onClosePopover"] }], tabsHost: [{ type: i0.ViewChild, args: ['tabsHost', { isSignal: true }] }] } });
4832
5250
 
4833
5251
  //#region ---- Imports ----
4834
5252
  //#endregion
@@ -4845,39 +5263,181 @@ class AXPBackgroundOperationSlotComponent {
4845
5263
  //#region ---- Computed ----
4846
5264
  this.activeCount = this.operationService.activeCount;
4847
5265
  this.failedCount = this.operationService.failedCount;
4848
- this.showSlot = computed(() => this.activeCount() > 0 || this.failedCount() > 0, /* @ts-ignore */
5266
+ this.showSlot = computed(() => this.operationService.trayVisibleCount() > 0, /* @ts-ignore */
4849
5267
  ...(ngDevMode ? [{ debugName: "showSlot" }] : /* istanbul ignore next */ []));
4850
- this.slotShowsFailureOnly = computed(() => this.activeCount() === 0 && this.failedCount() > 0, /* @ts-ignore */
5268
+ this.slotShowsFailureOnly = computed(() => this.operationService.activeCount() === 0 && this.operationService.failedCount() > 0, /* @ts-ignore */
4851
5269
  ...(ngDevMode ? [{ debugName: "slotShowsFailureOnly" }] : /* istanbul ignore next */ []));
5270
+ this.slotShowsRetainedOnly = computed(() => this.operationService.activeCount() === 0 &&
5271
+ this.operationService.failedCount() === 0 &&
5272
+ this.operationService.retainedCompletedCount() > 0, /* @ts-ignore */
5273
+ ...(ngDevMode ? [{ debugName: "slotShowsRetainedOnly" }] : /* istanbul ignore next */ []));
4852
5274
  this.slotLabelKey = computed(() => {
4853
5275
  if (this.slotShowsFailureOnly()) {
4854
- return this.failedCount() === 1
4855
- ? '@general:background-operation.slot.failed-single'
4856
- : '@general:background-operation.slot.failed-multiple';
5276
+ return '@general:background-operation.slot.failed';
4857
5277
  }
4858
- return this.activeCount() === 1
4859
- ? '@general:background-operation.slot.single'
4860
- : '@general:background-operation.slot.multiple';
5278
+ if (this.slotShowsRetainedOnly()) {
5279
+ return '@general:background-operation.slot.completed';
5280
+ }
5281
+ return '@general:background-operation.slot.in-progress';
4861
5282
  }, /* @ts-ignore */
4862
5283
  ...(ngDevMode ? [{ debugName: "slotLabelKey" }] : /* istanbul ignore next */ []));
4863
- this.slotLabelParams = computed(() => ({
4864
- count: this.slotShowsFailureOnly() ? this.failedCount() : this.activeCount(),
4865
- }), /* @ts-ignore */
4866
- ...(ngDevMode ? [{ debugName: "slotLabelParams" }] : /* istanbul ignore next */ []));
5284
+ this.badgeDisplay = computed(() => {
5285
+ const total = this.slotShowsFailureOnly()
5286
+ ? this.failedCount()
5287
+ : this.slotShowsRetainedOnly()
5288
+ ? this.operationService.retainedCompletedCount()
5289
+ : this.activeCount();
5290
+ if (total <= 0) {
5291
+ return '';
5292
+ }
5293
+ return total > 50 ? '50+' : total.toString();
5294
+ }, /* @ts-ignore */
5295
+ ...(ngDevMode ? [{ debugName: "badgeDisplay" }] : /* istanbul ignore next */ []));
4867
5296
  }
4868
5297
  //#endregion
4869
5298
  //#region ---- Event Handlers ----
5299
+ onTriggerClick(panel) {
5300
+ // Sync before open: popover toggles on the same click; skip when closing.
5301
+ if (!this.popover()?.isOpen) {
5302
+ panel.syncDefaultTab();
5303
+ }
5304
+ }
5305
+ onPopoverOpened(panel) {
5306
+ panel.syncDefaultTab();
5307
+ }
4870
5308
  closePopover() {
4871
5309
  this.popover()?.close();
4872
5310
  }
4873
5311
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPBackgroundOperationSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4874
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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.3 | 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", "visualContextScope", "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 }); }
5312
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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 <!-- ----- Footer tray trigger ----- -->\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger (click)=\"onTriggerClick(panel)\">\n @if (badgeDisplay()) {\n <!-- ----- Count badge ----- -->\n <ax-badge class=\"operation-slot__badge\" [class.--xs]=\"badgeDisplay().length > 2\" color=\"danger\" [text]=\"badgeDisplay()\"></ax-badge>\n }\n @if (slotShowsFailureOnly()) {\n <!-- ----- Failed tasks ----- -->\n <ax-icon class=\"operation-slot__icon\">\n <i class=\"fa-light fa-circle-exclamation\"></i>\n </ax-icon>\n }\n <!--->\n <!-- ----- In-progress spinner (no icon for completed) ----- -->\n @else if (!slotShowsRetainedOnly()) {\n <ax-icon class=\"operation-slot__icon\">\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n </ax-icon>\n }\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate | async }}\n </span>\n </button>\n\n <ax-popover\n [target]=\"operationTrigger\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n [adaptivityEnabled]=\"true\"\n (onOpened)=\"onPopoverOpened(panel)\"\n >\n <axp-background-operation-panel\n #panel\n (onClosePopover)=\"closePopover()\"\n ></axp-background-operation-panel>\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-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:var(--spacing, .25rem);color:var(--color-text-default);--ax-sys-size: ax-sm;--ax-sys-size-base: calc(var(--ax-sys-size-md) - var(--ax-sys-size-step));--spacing: calc(var(--ax-sys-spacing-base) - .25 * var(--ax-sys-padding-step));--ax-sys-border-radius: var(--ax-sys-border-radius-base);--text-xs: calc(var(--ax-sys-text-xs-base) * 11 / 12);--text-sm: calc(var(--ax-sys-text-sm-base) * 6 / 7);--text-base: calc(var(--ax-sys-body-font-size) * .875);--text-lg: calc(var(--ax-sys-text-lg-base) * 8 / 9);--text-xl: calc(var(--ax-sys-text-xl-base) * .9);--leading-3: calc(var(--ax-sys-leading-3-base) * 7 / 6);--leading-4: var(--ax-sys-leading-4-base);--leading-5: calc(var(--ax-sys-leading-5-base) * .9);--leading-6: calc(var(--ax-sys-leading-6-base) * 11 / 12)}@media(hover:hover){.operation-slot__trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}}.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)}.operation-slot__badge{flex-shrink:0}@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.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i3$1.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "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.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4875
5313
  }
4876
5314
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPBackgroundOperationSlotComponent, decorators: [{
4877
5315
  type: Component,
4878
- 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.3 | MIT License | https://tailwindcss.com */\n"] }]
5316
+ args: [{ selector: 'axp-background-operation-slot', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXBadgeModule, AXDecoratorModule, AXTranslationModule, AXPopoverModule, AXPBackgroundOperationPanelComponent], template: "@if (showSlot()) {\n <!-- ----- Footer tray trigger ----- -->\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger (click)=\"onTriggerClick(panel)\">\n @if (badgeDisplay()) {\n <!-- ----- Count badge ----- -->\n <ax-badge class=\"operation-slot__badge\" [class.--xs]=\"badgeDisplay().length > 2\" color=\"danger\" [text]=\"badgeDisplay()\"></ax-badge>\n }\n @if (slotShowsFailureOnly()) {\n <!-- ----- Failed tasks ----- -->\n <ax-icon class=\"operation-slot__icon\">\n <i class=\"fa-light fa-circle-exclamation\"></i>\n </ax-icon>\n }\n <!--->\n <!-- ----- In-progress spinner (no icon for completed) ----- -->\n @else if (!slotShowsRetainedOnly()) {\n <ax-icon class=\"operation-slot__icon\">\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n </ax-icon>\n }\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate | async }}\n </span>\n </button>\n\n <ax-popover\n [target]=\"operationTrigger\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n [adaptivityEnabled]=\"true\"\n (onOpened)=\"onPopoverOpened(panel)\"\n >\n <axp-background-operation-panel\n #panel\n (onClosePopover)=\"closePopover()\"\n ></axp-background-operation-panel>\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-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:var(--spacing, .25rem);color:var(--color-text-default);--ax-sys-size: ax-sm;--ax-sys-size-base: calc(var(--ax-sys-size-md) - var(--ax-sys-size-step));--spacing: calc(var(--ax-sys-spacing-base) - .25 * var(--ax-sys-padding-step));--ax-sys-border-radius: var(--ax-sys-border-radius-base);--text-xs: calc(var(--ax-sys-text-xs-base) * 11 / 12);--text-sm: calc(var(--ax-sys-text-sm-base) * 6 / 7);--text-base: calc(var(--ax-sys-body-font-size) * .875);--text-lg: calc(var(--ax-sys-text-lg-base) * 8 / 9);--text-xl: calc(var(--ax-sys-text-xl-base) * .9);--leading-3: calc(var(--ax-sys-leading-3-base) * 7 / 6);--leading-4: var(--ax-sys-leading-4-base);--leading-5: calc(var(--ax-sys-leading-5-base) * .9);--leading-6: calc(var(--ax-sys-leading-6-base) * 11 / 12)}@media(hover:hover){.operation-slot__trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}}.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)}.operation-slot__badge{flex-shrink:0}@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.3 | MIT License | https://tailwindcss.com */\n"] }]
4879
5317
  }], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPopoverComponent), { isSignal: true }] }] } });
4880
5318
 
5319
+ //#region ---- Imports ----
5320
+ //#endregion
5321
+ //#region ---- Service ----
5322
+ /**
5323
+ * Delivers {@link AXPUserNotificationRequest} to configured channels (toast overlay, in-app inbox).
5324
+ * Inbox persistence is delegated to {@link AXP_IN_APP_NOTIFICATION_SERVICE} when registered.
5325
+ */
5326
+ class AXPUserNotificationService {
5327
+ constructor() {
5328
+ //#region ----- Dependencies -----
5329
+ this.toastService = inject(AXNotificationService);
5330
+ this.inAppNotificationService = inject(AXP_IN_APP_NOTIFICATION_SERVICE, { optional: true });
5331
+ this.sessionService = inject(AXPSessionService);
5332
+ //#endregion
5333
+ //#region ----- State -----
5334
+ this.recentToastCorrelationIds = new Map();
5335
+ }
5336
+ static { this.TOAST_DEDUPE_MS = 15_000; }
5337
+ //#endregion
5338
+ //#region ----- API -----
5339
+ async notify(request) {
5340
+ const { toast, inbox } = axpResolveUserNotificationDelivery(request.delivery);
5341
+ if (toast) {
5342
+ this.deliverToast(request, toast);
5343
+ }
5344
+ if (inbox) {
5345
+ await this.deliverInbox(request, inbox);
5346
+ }
5347
+ }
5348
+ //#endregion
5349
+ //#region ----- Toast -----
5350
+ deliverToast(request, options) {
5351
+ const correlationId = request.correlationId.trim();
5352
+ if (correlationId && this.isDuplicateToast(correlationId)) {
5353
+ return;
5354
+ }
5355
+ const actions = request.toastActions ?? [];
5356
+ const showActions = options.showActions !== false && actions.length > 0;
5357
+ const ref = this.toastService.show({
5358
+ color: options.color ?? 'primary',
5359
+ location: options.location ?? 'bottom-center',
5360
+ closeButton: options.closeButton ?? true,
5361
+ timeOut: options.timeOut ?? 3_000,
5362
+ timeOutProgress: options.timeOutProgress ?? true,
5363
+ icon: request.icon,
5364
+ title: request.title,
5365
+ content: request.body,
5366
+ ...(showActions
5367
+ ? {
5368
+ buttons: actions.map((action) => ({
5369
+ text: action.text,
5370
+ color: action.color ?? 'primary',
5371
+ onClick: (event) => {
5372
+ if (event) {
5373
+ event.handled = true;
5374
+ }
5375
+ ref.close();
5376
+ void action.onClick?.();
5377
+ },
5378
+ })),
5379
+ }
5380
+ : {}),
5381
+ });
5382
+ }
5383
+ //#endregion
5384
+ //#region ----- Inbox -----
5385
+ async deliverInbox(request, options) {
5386
+ if (!this.inAppNotificationService) {
5387
+ return;
5388
+ }
5389
+ const recipientUserId = request.recipientUserId?.trim() || this.sessionService.user?.id?.trim();
5390
+ if (!recipientUserId) {
5391
+ return;
5392
+ }
5393
+ const priority = (options.priority ?? 'Notice');
5394
+ await this.inAppNotificationService.create({
5395
+ id: request.idempotencyKey?.trim() || request.correlationId.trim(),
5396
+ name: request.name?.trim() || request.title,
5397
+ title: request.title,
5398
+ body: request.body,
5399
+ icon: request.icon ?? 'fa-light fa-bell',
5400
+ priority,
5401
+ receiver: {
5402
+ id: recipientUserId,
5403
+ type: 'user',
5404
+ fullName: get(this.sessionService.user, 'title'),
5405
+ username: get(this.sessionService.user, 'name'),
5406
+ },
5407
+ data: {
5408
+ correlationId: request.correlationId,
5409
+ definitionKey: options.definitionKey,
5410
+ actions: options.actions,
5411
+ ...(request.data ?? {}),
5412
+ },
5413
+ });
5414
+ }
5415
+ //#endregion
5416
+ //#region ----- Helpers -----
5417
+ isDuplicateToast(correlationId) {
5418
+ const now = Date.now();
5419
+ const previous = this.recentToastCorrelationIds.get(correlationId);
5420
+ if (previous !== undefined && now - previous < AXPUserNotificationService.TOAST_DEDUPE_MS) {
5421
+ return true;
5422
+ }
5423
+ this.recentToastCorrelationIds.set(correlationId, now);
5424
+ return false;
5425
+ }
5426
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPUserNotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5427
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPUserNotificationService, providedIn: 'root' }); }
5428
+ }
5429
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPUserNotificationService, decorators: [{
5430
+ type: Injectable,
5431
+ args: [{ providedIn: 'root' }]
5432
+ }] });
5433
+
5434
+ function provideAXPUserNotificationService() {
5435
+ return {
5436
+ provide: AXP_USER_NOTIFICATION_SERVICE,
5437
+ useExisting: AXPUserNotificationService,
5438
+ };
5439
+ }
5440
+
4881
5441
  const ENVIRONMENT = new InjectionToken('ENVIRONMENT');
4882
5442
  const AXP_PLATFORM_CONFIG_TOKEN = new InjectionToken('AXP_PLATFORM_CONFIG_TOKEN', {
4883
5443
  providedIn: 'root',
@@ -8558,7 +9118,7 @@ class AXPKeyboardShortcutsHelpComponent {
8558
9118
  }
8559
9119
  </div>
8560
9120
  </div>
8561
- `, isInline: true, styles: ["@layer properties;.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;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 none))}.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:0px;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 none));-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.3 | 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 }); }
9121
+ `, isInline: true, styles: ["@layer properties;.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;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 none))}.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:0px;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 none));-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.3 | 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: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
8562
9122
  }
8563
9123
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPKeyboardShortcutsHelpComponent, decorators: [{
8564
9124
  type: Component,
@@ -9962,11 +10522,13 @@ class AXPCommonModule {
9962
10522
  });
9963
10523
  }
9964
10524
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPCommonModule, deps: [{ token: 'AXPCommonModuleFactory' }, { token: AXPKeyboardShortcutsHelpService }, { token: i2$1.AXFormatterRegistryService }], target: i0.ɵɵFactoryTarget.NgModule }); }
9965
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXPCommonModule, imports: [i3$1.AXPComponentSlotModule, AXPopupModule,
10525
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXPCommonModule, imports: [i3$2.AXPComponentSlotModule, AXPopupModule,
9966
10526
  AXDateTimeModule,
9967
10527
  AXToastModule,
10528
+ AXNotificationModule,
9968
10529
  AXPModuleManifestModule, i4$2.RouterModule], exports: [RouterModule] }); }
9969
10530
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPCommonModule, providers: [
10531
+ provideAXPUserNotificationService(),
9970
10532
  {
9971
10533
  provide: ErrorHandler,
9972
10534
  useClass: AXPGlobalErrorHandler,
@@ -10031,7 +10593,7 @@ class AXPCommonModule {
10031
10593
  provide: AXP_SETTING_DEFINITION_PROVIDER,
10032
10594
  useFactory: async () => {
10033
10595
  const injector = inject(Injector);
10034
- const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-CLm2BVk-.mjs')).AXPCommonSettingProvider;
10596
+ const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-CzBr0cRi.mjs')).AXPCommonSettingProvider;
10035
10597
  return new provider(injector);
10036
10598
  },
10037
10599
  multi: true,
@@ -10053,6 +10615,7 @@ class AXPCommonModule {
10053
10615
  AXPopupModule,
10054
10616
  AXDateTimeModule,
10055
10617
  AXToastModule,
10618
+ AXNotificationModule,
10056
10619
  AXPModuleManifestModule,
10057
10620
  RouterModule.forChild([]), RouterModule] }); }
10058
10621
  }
@@ -10071,11 +10634,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
10071
10634
  AXPopupModule,
10072
10635
  AXDateTimeModule,
10073
10636
  AXToastModule,
10637
+ AXNotificationModule,
10074
10638
  AXPModuleManifestModule,
10075
10639
  RouterModule.forChild([]),
10076
10640
  ],
10077
10641
  exports: [RouterModule],
10078
10642
  providers: [
10643
+ provideAXPUserNotificationService(),
10079
10644
  {
10080
10645
  provide: ErrorHandler,
10081
10646
  useClass: AXPGlobalErrorHandler,
@@ -10140,7 +10705,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
10140
10705
  provide: AXP_SETTING_DEFINITION_PROVIDER,
10141
10706
  useFactory: async () => {
10142
10707
  const injector = inject(Injector);
10143
- const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-CLm2BVk-.mjs')).AXPCommonSettingProvider;
10708
+ const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-CzBr0cRi.mjs')).AXPCommonSettingProvider;
10144
10709
  return new provider(injector);
10145
10710
  },
10146
10711
  multi: true,
@@ -10961,9 +11526,7 @@ class AXPLocalEntityEngine {
10961
11526
  constructor() {
10962
11527
  this.sessionService = inject(AXPSessionService);
10963
11528
  this.destroyRef = inject(DestroyRef);
10964
- this.originId = typeof crypto !== 'undefined' && 'randomUUID' in crypto
10965
- ? crypto.randomUUID()
10966
- : `local-entity-${Date.now()}-${Math.random().toString(36).slice(2)}`;
11529
+ this.originId = createRandomUuid();
10967
11530
  this.buckets = new Map();
10968
11531
  this.userKeySignal = signal(null, /* @ts-ignore */
10969
11532
  ...(ngDevMode ? [{ debugName: "userKeySignal" }] : /* istanbul ignore next */ []));
@@ -12108,7 +12671,7 @@ class AXMOrgChartPrintPage extends AXBasePageComponent {
12108
12671
  <ax-icon class="fa-solid fa-print"> </ax-icon>
12109
12672
  </ax-button>
12110
12673
  </ax-suffix>
12111
- </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"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
12674
+ </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$3.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$3.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.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$1.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"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
12112
12675
  }
12113
12676
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartPrintPage, decorators: [{
12114
12677
  type: Component,
@@ -12421,5 +12984,5 @@ const axpNavigateCommandDefinition = defineCommand({
12421
12984
  * Generated bundle index. Do not edit.
12422
12985
  */
12423
12986
 
12424
- 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, AXPFileChooserSettings, AXPFileStorageEvaluatorScopeProvider, AXPFileStorageService, AXPFileTypeProviderService, AXPFilterOperatorMiddlewareService, AXPFilterOperatorMiddlewareServiceImpl, AXPFooterTextSlotComponent, AXPGlobalErrorHandler, AXPHomePageModule, AXPHomePageService, AXPIndexedDbSettingValueProvider, AXPIntegrationDomainProviderContext, AXPIntegrationDomainRegistryFacade, AXPIntegrationDomainRegistryService, AXPIntegrationOAuthService, AXPIntegrationProviderContext, AXPIntegrationProviderRegistryService, AXPIntegrationRuntimeService, AXPKeyboardShortcutsHelpComponent, AXPKeyboardShortcutsHelpService, AXPLocalEntityEngine, AXPLocalEntityIndexedDb, AXPLocalEntityRealtimeBridge, AXPLockService, AXPLogoImageSrcResolverService, AXPMenuKeyboardShortcutService, AXPMenuMiddlewareRegistry, AXPMenuProviderService, AXPMenuRouteAccessService, AXPMenuRouteGuard, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateCommand, AXPNetworkConnectivityService, AXPNotFoundCatchAllRoute, AXPNotFoundError, AXPOutputContractTranscriptSegmentService, AXPPlatformBrandingService, AXPPlatformDefaultConfigs, AXPPlatformSettingsLoadState, AXPPlatformSettingsOfflineBootstrapService, AXPQueryEvaluatorScopeProvider, AXPQueryParamsEvaluatorScopeProvider, AXPRegionalCalendarService, 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_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_CONNECTION_LIFECYCLE, AXP_INTEGRATION_DOMAIN_PROVIDER, 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_LOCAL_ENTITY_BROADCAST_CHANNEL, AXP_LOCAL_ENTITY_DEFAULT_MAX_ITEMS, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER, AXP_NOT_FOUND_CATCH_ALL_ROUTE, AXP_NOT_FOUND_ROUTE, AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER, AXP_PLATFORM_BRANDING_SETTING_KEYS, AXP_PLATFORM_CONFIG_TOKEN, AXP_PROTECTED_ROUTE_GUARDS, AXP_ROOT_CONFIG_TOKEN, AXP_RUNTIME_QUERY_CACHE_DEFAULTS, 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, AX_FILE_TYPE_METADATA_SUPPORT_BY_FILE_VIEWER, 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, axpInterpolateNavigatePath, axpIsActiveBackgroundOperationStatus, axpIsCompletedBackgroundOperationStatus, axpIsEntityDetailsPath, axpIsEntityDetailsViewRoute, axpIsEntityListPath, axpIsEntityListRoute, axpIsEntityRecordNotFound, axpIsTabEligibleUrl, axpJoinTabTitleSegments, axpLocalEntityCanServeListLocally, axpLocalEntityHotListRequest, axpLocalEntityIndexedDb, axpLocalEntityRecordId, axpLocalEntitySortAt, axpLocalEntityToPayload, axpMenuPathsMatch, axpNavigateAppPath, axpNavigateCommandDefinition, axpParseAppPath, axpParseEntityDetailsRoute, axpParseEntityListRoute, axpPathFromSnapshot, axpPlatformSettingsAvailableGuard, axpRedirectToNotFound, axpRedirectToUnauthorized, axpReplaceEntityListRouteQueryParams, axpResolveNavigatePath, axpResolveTabKey, axpResolveTabKeyFromRouteConfig, axpResolveTabKeyFromSnapshot, axpResolveTabTitleParts, axpSaveEntityListReturnUrl, axpSettingsIndexedDb, backgroundOperationEntityFactory, buildFileStorageDownloadUrl, buildLocalEntityMetaId, buildLocalEntityStorageId, buildScopedSettingsSnapshotId, chooseSystemFiles, coerceAXPSettingRawValue, coerceAXPSettingRawValueByKind, configPlatform, createBackgroundOperationStore, createDefaultSettingValueProviders, createEmptyScopedSettingsSnapshot, createEntityCommandOptions, createEntityRowExpressionScope, createEntitySearchCommand, createFileTypeOpenContext, createIndexedDbSettingValueProviders, createMenuContext, createMenuMiddleware, createUnsavedChangesCanDeactivateGuard, downloadGraphicFromElement, evaluateEntityDisplayTemplate, extractFileExtension, extractHttpRequestErrorInfo, extractRequestErrorInfo, findManualPresetIdByOperation, formatEntityRowDisplayTitle, formatRequestError, hasFileTypeOpenHandler, hydrateSettingsValuesFromIndexedDb, inferSettingCoercionKind, isFileNameShownInViewer, isFileTypeShownInViewer, isGalleryMediaExtension, isOneWaySettingsIndexedDbCache, isSettingKeyCacheable, isSettingVisibleOnScope, isStoredImageFileId, normalizeAvailableLanguageCodes, normalizeDocumentFileTypePurposes, normalizeDocumentToFileListItem, normalizeOverridableAt, normalizePositiveNumberOption, normalizeRouterUrl, normalizeStoredImageRef, peelSettingValueKey, platformErrorI18nKey, primaryLanguageSubtag, printGraphicFromElement, projectSettingsValuesForIndexedDb, provideDynamicHomePage, provideMenuMiddleware, purgeLegacyTenantScopedSettingsSnapshots, resolveDateFilterPresets, resolveEffectiveAvailableLanguageCodes, resolveEntityCreateListBehavior, resolveEntityModifyPopupTitle, resolveEntityRowDisplayText, resolveEntityRowDisplayTitle, resolveEntityRowDisplayTitleFromColumnContext, resolveEntitySearchTitleFallback, resolveExplorerFileDisplayName, resolveFileTypeDisplay, resolveGraphicElementSize, resolveGraphicPrintContent, resolveMediaViewerType, resolveQueryMatchingDisplayText, resolveSearchDisplayTemplate, resolveSearchableText, resolveStoredImageDisplayUrl, searchInRecordValues, searchInSearchableValue, serializeSvgElement, shouldApplyDefaultMultiLanguageToEntityProperty, shouldApplyDefaultMultiLanguageToWidgetNode, shouldApplyDefaultMultiLanguageToWidgetProperty, shouldPersistSettingsInIndexedDb, stripAccidentalNestedSettingParents, throwIfCommandFailed, toAXPRequestError, toExecuteCommandFailureResult, traceSettingsAppStartupLoadComplete, traceSettingsAppStartupLoadStarted, traceSettingsClientTool, traceSettingsFlush, traceSettingsLocalPersist, traceSettingsPageLoadComplete, traceSettingsPageLoadStarted, traceSettingsPageRouteLoad, traceSettingsRetryScheduled, traceSettingsRevalidateFailed, traceSettingsServerApiCall, traceSettingsServiceLoadComplete, traceSettingsServiceLoadFailed, traceSettingsServiceLoadStarted, traceSettingsServiceReload, traceSettingsSyncFailed, triggerBrowserDownload, tryOpenFileByCatalogType, withDefaultMultiLanguageOnWidgetNodeTree, withDefaultMultiLanguageOnWidgetProperty };
12987
+ 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, AXPFileChooserSettings, AXPFileStorageEvaluatorScopeProvider, AXPFileStorageService, AXPFileTypeProviderService, AXPFilterOperatorMiddlewareService, AXPFilterOperatorMiddlewareServiceImpl, AXPFooterTextSlotComponent, AXPGlobalErrorHandler, AXPHomePageModule, AXPHomePageService, AXPIndexedDbSettingValueProvider, AXPIntegrationDomainProviderContext, AXPIntegrationDomainRegistryFacade, AXPIntegrationDomainRegistryService, AXPIntegrationOAuthService, AXPIntegrationProviderContext, AXPIntegrationProviderRegistryService, AXPIntegrationRuntimeService, AXPKeyboardShortcutsHelpComponent, AXPKeyboardShortcutsHelpService, AXPLocalEntityEngine, AXPLocalEntityIndexedDb, AXPLocalEntityRealtimeBridge, AXPLockService, AXPLogoImageSrcResolverService, AXPMenuKeyboardShortcutService, AXPMenuMiddlewareRegistry, AXPMenuProviderService, AXPMenuRouteAccessService, AXPMenuRouteGuard, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateCommand, AXPNetworkConnectivityService, AXPNotFoundCatchAllRoute, AXPNotFoundError, AXPOutputContractTranscriptSegmentService, AXPPlatformBrandingService, AXPPlatformDefaultConfigs, AXPPlatformSettingsLoadState, AXPPlatformSettingsOfflineBootstrapService, AXPQueryEvaluatorScopeProvider, AXPQueryParamsEvaluatorScopeProvider, AXPRegionalCalendarService, AXPSearchCommandProvider, AXPSearchDefinitionActionBuilder, AXPSearchDefinitionBuilder, AXPSearchDefinitionProviderContext, AXPSearchDefinitionProviderService, AXPSearchService, AXPSettingDefaultValuesAggregatorService, AXPSettingDefinitionGroupBuilder, AXPSettingDefinitionProviderContext, AXPSettingDefinitionProviderService, AXPSettingDefinitionSectionBuilder, AXPSettingsBulkSyncService, AXPSettingsEvaluatorScopeProvider, AXPSettingsIndexedDb, AXPSettingsService, AXPStateMessageComponent, AXPStatusDefinitionProviderService, AXPStickyDirective, AXPTabNavigationService, AXPTabPreviewService, AXPTabRouteCacheRegistry, AXPTokenDefinitionService, AXPTokenEvaluatorScopeProvider, AXPTranslateFormatter, AXPUnsavedChangesConfirmService, AXPUnsavedChangesPopstateService, AXPUserNotificationService, 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_LIST_DISPLAY_MODE_DEFAULT, 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_CONNECTION_LIFECYCLE, AXP_INTEGRATION_DOMAIN_PROVIDER, 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_LOCAL_ENTITY_BROADCAST_CHANNEL, AXP_LOCAL_ENTITY_DEFAULT_MAX_ITEMS, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER, AXP_NOT_FOUND_CATCH_ALL_ROUTE, AXP_NOT_FOUND_ROUTE, AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER, AXP_PLATFORM_BRANDING_SETTING_KEYS, AXP_PLATFORM_CONFIG_TOKEN, AXP_PROTECTED_ROUTE_GUARDS, AXP_ROOT_CONFIG_TOKEN, AXP_RUNTIME_QUERY_CACHE_DEFAULTS, 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, AXP_USER_NOTIFICATION_SERVICE, AXVChangeType, AX_FILE_TYPE_METADATA_SUPPORT_BY_FILE_VIEWER, 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, axpBackgroundOperationDurationMs, axpBackgroundOperationEntityName, axpBackgroundOperationEstimateEndDate, axpBackgroundOperationFailurePolicy, axpBackgroundOperationFromEntityModel, axpBackgroundOperationRemainingMs, axpBackgroundOperationStatusTextParams, axpBackgroundOperationToEntityModel, axpBuildBackgroundOperation, axpBuildTabKey, axpCoerceBackgroundOperationDate, axpCreateBackgroundOperationId, axpFallbackTabTitle, axpFindMenuItemByRoute, axpFormatBackgroundOperationDurationMs, axpGetEntityListReturnUrl, axpGetLeafRouteSnapshot, axpHasTabScope, axpInterpolateNavigatePath, axpIsActiveBackgroundOperationStatus, axpIsBackgroundOperationI18nText, axpIsCompletedBackgroundOperationStatus, axpIsCompletedPanelBackgroundOperation, axpIsEntityDetailsPath, axpIsEntityDetailsViewRoute, axpIsEntityListPath, axpIsEntityListRoute, axpIsEntityRecordNotFound, axpIsInProgressPanelBackgroundOperation, axpIsTabEligibleUrl, axpIsTrayVisibleBackgroundOperation, axpJoinTabTitleSegments, axpLocalEntityCanServeListLocally, axpLocalEntityHotListRequest, axpLocalEntityIndexedDb, axpLocalEntityRecordId, axpLocalEntitySortAt, axpLocalEntityToPayload, axpMenuPathsMatch, axpNavigateAppPath, axpNavigateCommandDefinition, axpParseAppPath, axpParseEntityDetailsRoute, axpParseEntityListRoute, axpPathFromSnapshot, axpPlatformSettingsAvailableGuard, axpRedirectToNotFound, axpRedirectToUnauthorized, axpReplaceEntityListRouteQueryParams, axpResolveNavigatePath, axpResolveTabKey, axpResolveTabKeyFromRouteConfig, axpResolveTabKeyFromSnapshot, axpResolveTabTitleParts, axpSaveEntityListReturnUrl, axpSettingsIndexedDb, backgroundOperationEntityFactory, buildFileStorageDownloadUrl, buildLocalEntityMetaId, buildLocalEntityStorageId, buildScopedSettingsSnapshotId, chooseSystemFiles, coerceAXPSettingRawValue, coerceAXPSettingRawValueByKind, configPlatform, createBackgroundOperationStore, createDefaultSettingValueProviders, createEmptyScopedSettingsSnapshot, createEntityCommandOptions, createEntityRowExpressionScope, createEntitySearchCommand, createFileTypeOpenContext, createIndexedDbSettingValueProviders, createMenuContext, createMenuMiddleware, createUnsavedChangesCanDeactivateGuard, downloadGraphicFromElement, evaluateEntityDisplayTemplate, extractFileExtension, extractHttpRequestErrorInfo, extractRequestErrorInfo, findManualPresetIdByOperation, formatEntityRowDisplayTitle, formatRequestError, hasFileTypeOpenHandler, hydrateSettingsValuesFromIndexedDb, inferSettingCoercionKind, isFileNameShownInViewer, isFileTypeShownInViewer, isGalleryMediaExtension, isOneWaySettingsIndexedDbCache, isSettingKeyCacheable, isSettingVisibleOnScope, isStoredImageFileId, normalizeAvailableLanguageCodes, normalizeDocumentFileTypePurposes, normalizeDocumentToFileListItem, normalizeOverridableAt, normalizePositiveNumberOption, normalizeRouterUrl, normalizeStoredImageRef, peelSettingValueKey, platformErrorI18nKey, primaryLanguageSubtag, printGraphicFromElement, projectSettingsValuesForIndexedDb, provideAXPUserNotificationService, provideDynamicHomePage, provideMenuMiddleware, purgeLegacyTenantScopedSettingsSnapshots, resolveDateFilterPresets, resolveEffectiveAvailableLanguageCodes, resolveEntityCreateListBehavior, resolveEntityModifyPopupTitle, resolveEntityRowDisplayText, resolveEntityRowDisplayTitle, resolveEntityRowDisplayTitleFromColumnContext, resolveEntitySearchTitleFallback, resolveExplorerFileDisplayName, resolveFileTypeDisplay, resolveGraphicElementSize, resolveGraphicPrintContent, resolveMediaViewerType, resolveQueryMatchingDisplayText, resolveSearchDisplayTemplate, resolveSearchableText, resolveStoredImageDisplayUrl, searchInRecordValues, searchInSearchableValue, serializeSvgElement, shouldApplyDefaultMultiLanguageToEntityProperty, shouldApplyDefaultMultiLanguageToWidgetNode, shouldApplyDefaultMultiLanguageToWidgetProperty, shouldPersistSettingsInIndexedDb, stripAccidentalNestedSettingParents, throwIfCommandFailed, toAXPRequestError, toExecuteCommandFailureResult, traceSettingsAppStartupLoadComplete, traceSettingsAppStartupLoadStarted, traceSettingsClientTool, traceSettingsFlush, traceSettingsLocalPersist, traceSettingsPageLoadComplete, traceSettingsPageLoadStarted, traceSettingsPageRouteLoad, traceSettingsRetryScheduled, traceSettingsRevalidateFailed, traceSettingsServerApiCall, traceSettingsServiceLoadComplete, traceSettingsServiceLoadFailed, traceSettingsServiceLoadStarted, traceSettingsServiceReload, traceSettingsSyncFailed, triggerBrowserDownload, tryOpenFileByCatalogType, withDefaultMultiLanguageOnWidgetNodeTree, withDefaultMultiLanguageOnWidgetProperty };
12425
12988
  //# sourceMappingURL=acorex-platform-framework-client-common.mjs.map