@acorex/platform 21.0.0-next.3 → 21.0.0-next.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 (117) hide show
  1. package/fesm2022/acorex-platform-auth.mjs +295 -45
  2. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-common-common-settings.provider-zhqNP3xb.mjs → acorex-platform-common-common-settings.provider-G9XcXXOG.mjs} +60 -4
  4. package/fesm2022/acorex-platform-common-common-settings.provider-G9XcXXOG.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-common.mjs +960 -319
  6. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-core.mjs +1352 -832
  8. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-domain.mjs +554 -826
  10. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-layout-builder.mjs +530 -154
  12. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  13. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs +121 -0
  14. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-layout-components.mjs +5969 -2347
  16. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  17. package/fesm2022/acorex-platform-layout-designer.mjs +169 -154
  18. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  19. package/fesm2022/acorex-platform-layout-entity.mjs +15380 -9274
  20. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-layout-views.mjs +393 -110
  22. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  23. package/fesm2022/acorex-platform-layout-widget-core.mjs +511 -450
  24. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  25. package/fesm2022/{acorex-platform-layout-widgets-button-widget-designer.component-C3VoBb_b.mjs → acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs} +10 -10
  26. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs.map +1 -0
  27. package/fesm2022/{acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs → acorex-platform-layout-widgets-file-list-popup.component-9uCkMxcc.mjs} +39 -16
  28. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-9uCkMxcc.mjs.map +1 -0
  29. package/fesm2022/{acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs → acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs} +6 -7
  30. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +1 -0
  31. package/fesm2022/{acorex-platform-layout-widgets-page-widget-designer.component-BtZMBxYp.mjs → acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs} +12 -12
  32. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs.map +1 -0
  33. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGQqY5Mw.mjs +111 -0
  34. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGQqY5Mw.mjs.map +1 -0
  35. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-DmzNTYiS.mjs} +6 -6
  36. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DmzNTYiS.mjs.map +1 -0
  37. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-BNG_588B.mjs} +5 -5
  38. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-BNG_588B.mjs.map +1 -0
  39. package/fesm2022/{acorex-platform-layout-widgets-text-block-widget-designer.component-Df1BFkSa.mjs → acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs} +6 -6
  40. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs.map +1 -0
  41. package/fesm2022/acorex-platform-layout-widgets.mjs +7865 -4026
  42. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  43. package/fesm2022/acorex-platform-native.mjs +8 -7
  44. package/fesm2022/acorex-platform-native.mjs.map +1 -1
  45. package/fesm2022/acorex-platform-runtime.mjs +220 -169
  46. package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
  47. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cvvr4HnL.mjs +160 -0
  48. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cvvr4HnL.mjs.map +1 -0
  49. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-TYoLN1Jq.mjs +120 -0
  50. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-TYoLN1Jq.mjs.map +1 -0
  51. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs → acorex-platform-themes-default-entity-master-single-view.component-C2z5Lq9y.mjs} +18 -25
  52. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-C2z5Lq9y.mjs.map +1 -0
  53. package/fesm2022/{acorex-platform-themes-default-error-401.component-cfREo88K.mjs → acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs} +4 -4
  54. package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs.map +1 -0
  55. package/fesm2022/{acorex-platform-themes-default-error-404.component-CdCV5ZoA.mjs → acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs} +4 -4
  56. package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs.map +1 -0
  57. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs +19 -0
  58. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs.map +1 -0
  59. package/fesm2022/acorex-platform-themes-default.mjs +1717 -66
  60. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  61. package/fesm2022/{acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs → acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs} +6 -6
  62. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs.map +1 -0
  63. package/fesm2022/{acorex-platform-themes-shared-icon-chooser-view.component-9W52W6Nu.mjs → acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs} +6 -6
  64. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs.map +1 -0
  65. package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs.map +1 -1
  66. package/fesm2022/{acorex-platform-themes-shared-theme-color-chooser-column.component-DTnfRy5f.mjs → acorex-platform-themes-shared-theme-color-chooser-column.component-CHfrTtol.mjs} +11 -11
  67. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-CHfrTtol.mjs.map +1 -0
  68. package/fesm2022/{acorex-platform-themes-shared-theme-color-chooser-view.component-DY0JtT1v.mjs → acorex-platform-themes-shared-theme-color-chooser-view.component-BSmvnUVq.mjs} +9 -9
  69. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BSmvnUVq.mjs.map +1 -0
  70. package/fesm2022/acorex-platform-themes-shared.mjs +563 -561
  71. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  72. package/fesm2022/acorex-platform-workflow.mjs +1735 -1750
  73. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  74. package/fesm2022/acorex-platform.mjs.map +1 -1
  75. package/package.json +31 -31
  76. package/{auth/index.d.ts → types/acorex-platform-auth.d.ts} +247 -10
  77. package/{common/index.d.ts → types/acorex-platform-common.d.ts} +492 -31
  78. package/{core/index.d.ts → types/acorex-platform-core.d.ts} +606 -392
  79. package/{domain/index.d.ts → types/acorex-platform-domain.d.ts} +719 -413
  80. package/{layout/builder/index.d.ts → types/acorex-platform-layout-builder.d.ts} +128 -56
  81. package/types/acorex-platform-layout-components.d.ts +2927 -0
  82. package/{layout/designer/index.d.ts → types/acorex-platform-layout-designer.d.ts} +9 -3
  83. package/{layout/entity/index.d.ts → types/acorex-platform-layout-entity.d.ts} +1133 -237
  84. package/{layout/views/index.d.ts → types/acorex-platform-layout-views.d.ts} +90 -31
  85. package/{layout/widget-core/index.d.ts → types/acorex-platform-layout-widget-core.d.ts} +206 -102
  86. package/{layout/widgets/index.d.ts → types/acorex-platform-layout-widgets.d.ts} +942 -137
  87. package/{native/index.d.ts → types/acorex-platform-native.d.ts} +0 -7
  88. package/{runtime/index.d.ts → types/acorex-platform-runtime.d.ts} +237 -74
  89. package/{themes/default/index.d.ts → types/acorex-platform-themes-default.d.ts} +113 -5
  90. package/{themes/shared/index.d.ts → types/acorex-platform-themes-shared.d.ts} +1 -1
  91. package/types/acorex-platform-workflow.d.ts +1806 -0
  92. package/fesm2022/acorex-platform-common-common-settings.provider-zhqNP3xb.mjs.map +0 -1
  93. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-C3VoBb_b.mjs.map +0 -1
  94. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs.map +0 -1
  95. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs.map +0 -1
  96. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-BtZMBxYp.mjs.map +0 -1
  97. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs.map +0 -1
  98. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs.map +0 -1
  99. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Df1BFkSa.mjs.map +0 -1
  100. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs +0 -157
  101. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs.map +0 -1
  102. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs +0 -1542
  103. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs.map +0 -1
  104. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs +0 -101
  105. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs.map +0 -1
  106. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs.map +0 -1
  107. package/fesm2022/acorex-platform-themes-default-error-401.component-cfREo88K.mjs.map +0 -1
  108. package/fesm2022/acorex-platform-themes-default-error-404.component-CdCV5ZoA.mjs.map +0 -1
  109. package/fesm2022/acorex-platform-themes-default-error-offline.component-E7SzBcAt.mjs +0 -19
  110. package/fesm2022/acorex-platform-themes-default-error-offline.component-E7SzBcAt.mjs.map +0 -1
  111. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs.map +0 -1
  112. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-9W52W6Nu.mjs.map +0 -1
  113. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-DTnfRy5f.mjs.map +0 -1
  114. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-DY0JtT1v.mjs.map +0 -1
  115. package/layout/components/index.d.ts +0 -1669
  116. package/workflow/index.d.ts +0 -2443
  117. /package/{index.d.ts → types/acorex-platform.d.ts} +0 -0
@@ -1,10 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, Injectable, computed, input, effect, Directive, EventEmitter, HostListener, Output, ViewContainerRef, ElementRef, signal, output, DestroyRef, Renderer2, untracked, Injector, runInInjectionContext, provideAppInitializer, NgModule, Pipe } from '@angular/core';
2
+ import { InjectionToken, inject, Injectable, Directive, computed, Injector, ChangeDetectionStrategy, Component, input, ElementRef, ViewContainerRef, signal, effect, runInInjectionContext, Optional, Inject, NgModule, EventEmitter, HostListener, Output, provideAppInitializer, ChangeDetectorRef, Pipe } from '@angular/core';
3
+ import { get, isPlainObject, set, isNil, isEmpty, isArray, merge, isObjectLike, transform, isEqual, differenceWith, union, cloneDeep, has, sortBy, isUndefined, endsWith, startsWith, includes, lte, gte, lt, gt, orderBy } from 'lodash-es';
3
4
  import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
4
- import { get, isPlainObject, set, isArray, merge, isNil, isObjectLike, transform, isEmpty, isEqual, differenceWith, union, cloneDeep, isUndefined, endsWith, startsWith, includes, lte, gte, lt, gt, orderBy } from 'lodash-es';
5
- import { Subject, interval, fromEvent } from 'rxjs';
5
+ import * as i1 from '@acorex/components/skeleton';
6
+ import { AXSkeletonModule } from '@acorex/components/skeleton';
7
+ import { Subject, merge as merge$1, of, interval, fromEvent } from 'rxjs';
8
+ import { AXDataSource } from '@acorex/cdk/common';
9
+ import { AXTranslationService } from '@acorex/core/translation';
10
+ import { map, distinctUntilChanged, startWith, debounceTime } from 'rxjs/operators';
6
11
  import { AXCalendarService } from '@acorex/core/date-time';
7
- import { startWith, map, debounceTime } from 'rxjs/operators';
8
12
 
9
13
  const AXP_ACTIVITY_LOG_PROVIDER = new InjectionToken('AXP_ACTIVITY_LOGS_PROVIDER');
10
14
  class AXPActivityLogService {
@@ -17,10 +21,10 @@ class AXPActivityLogService {
17
21
  async getHistoryByIds(refId, refType, ids) {
18
22
  return (await Promise.all(this.providers?.map((p) => p.getHistoryByIds(refId, refType, ids)) ?? [])).flat();
19
23
  }
20
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPActivityLogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
21
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPActivityLogService, providedIn: 'root' }); }
24
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityLogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
25
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityLogService, providedIn: 'root' }); }
22
26
  }
23
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPActivityLogService, decorators: [{
27
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityLogService, decorators: [{
24
28
  type: Injectable,
25
29
  args: [{ providedIn: 'root' }]
26
30
  }] });
@@ -170,10 +174,10 @@ class AXPColorPaletteService {
170
174
  const uniquePalettes = allPalettes.filter((palette, index, self) => index === self.findIndex((p) => p.name === palette.name));
171
175
  this.cache = uniquePalettes;
172
176
  }
173
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPColorPaletteService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
174
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPColorPaletteService, providedIn: 'root' }); }
177
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColorPaletteService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
178
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColorPaletteService, providedIn: 'root' }); }
175
179
  }
176
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPColorPaletteService, decorators: [{
180
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColorPaletteService, decorators: [{
177
181
  type: Injectable,
178
182
  args: [{
179
183
  providedIn: 'root',
@@ -288,13 +292,241 @@ class AXPDefaultColorPalettesProvider extends AXPColorPaletteProvider {
288
292
  },
289
293
  ];
290
294
  }
291
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDefaultColorPalettesProvider, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
292
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDefaultColorPalettesProvider }); }
295
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultColorPalettesProvider, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
296
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultColorPalettesProvider }); }
293
297
  }
294
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDefaultColorPalettesProvider, decorators: [{
298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultColorPalettesProvider, decorators: [{
295
299
  type: Injectable
296
300
  }] });
297
301
 
302
+ //#region ---- Column Width Provider ----
303
+ /**
304
+ * Injection token for column width providers
305
+ * Use this to register multiple column width providers with multi: true
306
+ *
307
+ * @example
308
+ * ```typescript
309
+ * providers: [
310
+ * {
311
+ * provide: AXP_COLUMN_WIDTH_PROVIDER,
312
+ * useValue: {
313
+ * matchers: [
314
+ * { name: 'title', width: '300px', priority: 10 },
315
+ * { widgetType: /text-box/i, width: '200px' }
316
+ * ],
317
+ * priority: 150
318
+ * },
319
+ * multi: true
320
+ * }
321
+ * ]
322
+ * ```
323
+ */
324
+ const AXP_COLUMN_WIDTH_PROVIDER = new InjectionToken('AXP_COLUMN_WIDTH_PROVIDER');
325
+ //#endregion
326
+
327
+ //#region ---- Column Width Service ----
328
+ /**
329
+ * Service for resolving column widths based on registered providers
330
+ * Supports matching by column name (priority) and widget type (fallback)
331
+ * Uses multi-provider pattern for extensibility
332
+ */
333
+ class AXPColumnWidthService {
334
+ constructor() {
335
+ //#region ---- Services & Dependencies ----
336
+ this.providers = inject(AXP_COLUMN_WIDTH_PROVIDER, {
337
+ optional: true,
338
+ }) ?? [];
339
+ }
340
+ //#region ---- Public Methods ----
341
+ /**
342
+ * Resolve width for a column based on registered providers
343
+ * Only returns a width if column doesn't already have one set
344
+ *
345
+ * @param column Column to resolve width for
346
+ * @returns Resolved width string (normalized) or undefined if no match or column already has width
347
+ */
348
+ resolveWidth(column) {
349
+ // If column already has a width set, don't override
350
+ const existingWidth = column.width || column.options?.width;
351
+ if (existingWidth) {
352
+ return undefined;
353
+ }
354
+ // Get widget type from column (support both widget.type and showAs.type)
355
+ const widgetType = column.widget?.type || column.showAs?.type;
356
+ // Collect all matchers from all providers
357
+ const allMatchers = this.collectMatchers();
358
+ // Try name-based matches first (higher priority)
359
+ const nameMatch = this.findNameMatch(column.name, allMatchers);
360
+ if (nameMatch) {
361
+ return this.normalizeWidth(nameMatch.width);
362
+ }
363
+ // Fallback to widget-type matches (case-insensitive)
364
+ if (widgetType) {
365
+ const widgetMatch = this.findWidgetTypeMatch(widgetType, allMatchers);
366
+ if (widgetMatch) {
367
+ return this.normalizeWidth(widgetMatch.width);
368
+ }
369
+ }
370
+ return undefined;
371
+ }
372
+ /**
373
+ * Apply resolved width to a column (mutates the column)
374
+ * Only applies if column doesn't already have a width
375
+ *
376
+ * @param column Column to apply width to
377
+ * @returns true if width was applied, false if column already had width or no match found
378
+ */
379
+ applyWidth(column) {
380
+ const width = this.resolveWidth(column);
381
+ if (!width) {
382
+ return false;
383
+ }
384
+ // Apply to the appropriate property
385
+ if (column.options) {
386
+ column.options.width = width;
387
+ }
388
+ else {
389
+ column.width = width;
390
+ }
391
+ return true;
392
+ }
393
+ //#endregion
394
+ //#region ---- Private Methods ----
395
+ /**
396
+ * Collect all matchers from all providers, sorted by provider priority and matcher priority
397
+ */
398
+ collectMatchers() {
399
+ const allMatchers = [];
400
+ for (const provider of this.providers) {
401
+ const providerPriority = provider.priority ?? 100;
402
+ for (const matcher of provider.matchers) {
403
+ allMatchers.push({
404
+ matcher,
405
+ providerPriority,
406
+ });
407
+ }
408
+ }
409
+ // Sort by provider priority (descending), then by matcher priority (descending)
410
+ allMatchers.sort((a, b) => {
411
+ if (a.providerPriority !== b.providerPriority) {
412
+ return b.providerPriority - a.providerPriority; // Higher priority first
413
+ }
414
+ const priorityA = a.matcher.priority ?? 0;
415
+ const priorityB = b.matcher.priority ?? 0;
416
+ return priorityB - priorityA; // Higher priority first
417
+ });
418
+ return allMatchers;
419
+ }
420
+ /**
421
+ * Find first matching matcher by column name
422
+ * Name matches take precedence over widget type matches
423
+ */
424
+ findNameMatch(columnName, allMatchers) {
425
+ for (const { matcher } of allMatchers) {
426
+ if (!matcher.name) {
427
+ continue; // Skip if no name matcher
428
+ }
429
+ if (typeof matcher.name === 'string') {
430
+ // Exact string match (case-sensitive for names)
431
+ if (matcher.name === columnName) {
432
+ return matcher;
433
+ }
434
+ }
435
+ else if (matcher.name instanceof RegExp) {
436
+ // RegExp match
437
+ if (matcher.name.test(columnName)) {
438
+ return matcher;
439
+ }
440
+ }
441
+ }
442
+ return undefined;
443
+ }
444
+ /**
445
+ * Find first matching matcher by widget type (case-insensitive)
446
+ */
447
+ findWidgetTypeMatch(widgetType, allMatchers) {
448
+ const widgetTypeLower = widgetType.toLowerCase();
449
+ for (const { matcher } of allMatchers) {
450
+ if (!matcher.widgetType) {
451
+ continue; // Skip if no widget type matcher
452
+ }
453
+ if (typeof matcher.widgetType === 'string') {
454
+ // Case-insensitive string match
455
+ if (matcher.widgetType.toLowerCase() === widgetTypeLower) {
456
+ return matcher;
457
+ }
458
+ }
459
+ else if (matcher.widgetType instanceof RegExp) {
460
+ // RegExp match (should already be case-insensitive if needed, but we'll test case-insensitively)
461
+ // Create a new regex with case-insensitive flag if not already present
462
+ let regex = matcher.widgetType;
463
+ if (!regex.flags.includes('i')) {
464
+ regex = new RegExp(regex.source, regex.flags + 'i');
465
+ }
466
+ if (regex.test(widgetType)) {
467
+ return matcher;
468
+ }
469
+ }
470
+ }
471
+ return undefined;
472
+ }
473
+ /**
474
+ * Normalize width value to string format
475
+ * Numbers are converted to pixels (e.g., 150 -> '150px')
476
+ * Strings are preserved as-is (supports any CSS unit)
477
+ */
478
+ normalizeWidth(width) {
479
+ if (typeof width === 'number') {
480
+ return `${width}px`;
481
+ }
482
+ return width;
483
+ }
484
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColumnWidthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
485
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColumnWidthService, providedIn: 'root' }); }
486
+ }
487
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColumnWidthService, decorators: [{
488
+ type: Injectable,
489
+ args: [{
490
+ providedIn: 'root',
491
+ }]
492
+ }] });
493
+
494
+ //#region ---- Column Width Types ----
495
+ //#endregion
496
+
497
+ //#region ---- Default Column Width Provider ----
498
+ /**
499
+ * Default column width configuration
500
+ * Migrated from DEFAULT_COLUMN_WIDTHS in column-width.middleware.ts
501
+ * Provides sensible defaults for common column names
502
+ */
503
+ const defaultColumnWidthProvider = {
504
+ priority: 100,
505
+ matchers: [
506
+ // Priority: name-based matches (higher priority = more specific)
507
+ { name: 'code', width: '150px', priority: 10 },
508
+ { name: 'name', width: '250px', priority: 10 },
509
+ { name: 'title', width: '250px', priority: 10 },
510
+ { name: 'description', width: '350px', priority: 10 },
511
+ { name: 'note', width: '350px', priority: 10 },
512
+ { name: 'notes', width: '350px', priority: 10 },
513
+ { name: 'content', width: '500px', priority: 10 },
514
+ { name: 'level', width: '100px', priority: 10 },
515
+ { name: 'order', width: '100px', priority: 10 },
516
+ { name: 'phones', width: '300px', priority: 10 },
517
+ { name: 'emails', width: '300px', priority: 10 },
518
+ ],
519
+ };
520
+ //#endregion
521
+
522
+ class AXPComponentSlot {
523
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
524
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: AXPComponentSlot, isStandalone: true, ngImport: i0 }); }
525
+ }
526
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlot, decorators: [{
527
+ type: Directive
528
+ }] });
529
+
298
530
  function extractNestedFieldsWildcard(obj, basePath, fields) {
299
531
  const result = {};
300
532
  if (fields.length === 1 && fields[0] === '*') {
@@ -313,7 +545,41 @@ function setSmart(obj, smartPath, value) {
313
545
  const lastPart = pathParts[pathParts.length - 1];
314
546
  const fieldMatch = lastPart.match(/^\{(.+)\}$/);
315
547
  if (!fieldMatch) {
548
+ // Fix: If value is undefined and we're setting a nested property,
549
+ // check if the parent object exists and if setting this would result in
550
+ // all properties being undefined. If so, set the parent to null instead.
551
+ if (isNil(value) && pathParts.length > 1) {
552
+ const parentPath = pathParts.slice(0, -1).join('.');
553
+ const parentObj = get(obj, parentPath);
554
+ // If parent is already null/undefined, don't recreate the object structure
555
+ if (isNil(parentObj)) {
556
+ return obj;
557
+ }
558
+ // Check if parent is a plain object (not array, not null)
559
+ if (isPlainObject(parentObj)) {
560
+ const existingKeys = Object.keys(parentObj);
561
+ // Check if all existing properties are null/undefined using lodash
562
+ const allNil = isEmpty(existingKeys) || existingKeys.every((key) => isNil(parentObj[key]));
563
+ if (allNil) {
564
+ // Set parent to null instead of creating/keeping an object with all undefined properties
565
+ set(obj, parentPath, null);
566
+ return obj;
567
+ }
568
+ }
569
+ }
316
570
  set(obj, smartPath, value);
571
+ // After setting, check again if parent should be null using lodash
572
+ if (isNil(value) && pathParts.length > 1) {
573
+ const parentPath = pathParts.slice(0, -1).join('.');
574
+ const parentObj = get(obj, parentPath);
575
+ if (isPlainObject(parentObj)) {
576
+ // Use lodash to check if all properties are null/undefined
577
+ const allNil = Object.keys(parentObj).every((key) => isNil(parentObj[key]));
578
+ if (allNil) {
579
+ set(obj, parentPath, null);
580
+ }
581
+ }
582
+ }
317
583
  return obj;
318
584
  }
319
585
  const fields = fieldMatch[1].split(',').map((f) => f.trim());
@@ -525,9 +791,10 @@ function getEnumValues(enumType) {
525
791
 
526
792
  class AXPContextChangeEvent {
527
793
  }
528
- const AXPContextStore = signalStore({
529
- providedIn: 'root',
530
- },
794
+ //#endregion
795
+ //#region ---- Context signal store ----
796
+ // Shared reactive context: root injector has a default instance; widget/layout trees
797
+ const AXPContextStore = signalStore(
531
798
  // Initial State
532
799
  withState(() => ({
533
800
  data: {}, // Shared context data
@@ -577,7 +844,7 @@ withMethods((store) => ({
577
844
  lastChange: changeEvent,
578
845
  });
579
846
  },
580
- patch(context) {
847
+ patch(context, skipDirtyTracking = false) {
581
848
  const currentData = cloneDeep(store.data());
582
849
  // Update the value and prepare the change event
583
850
  const updatedData = { ...currentData, ...context };
@@ -587,7 +854,7 @@ withMethods((store) => ({
587
854
  };
588
855
  // Patch the state
589
856
  patchState(store, {
590
- previousSnapshot: store.snapshot(), // Save the previous state
857
+ ...(skipDirtyTracking ? {} : { previousSnapshot: store.snapshot() }),
591
858
  data: updatedData,
592
859
  state: 'changed',
593
860
  lastChange: changeEvent,
@@ -635,107 +902,527 @@ withMethods((store) => ({
635
902
  getValue(path) {
636
903
  return getSmart(store.data(), path);
637
904
  },
905
+ // Check if a path exists in the context
906
+ hasValue(path) {
907
+ return has(store.data(), path);
908
+ },
638
909
  })));
910
+ //#endregion
639
911
 
640
- class AXPDataGenerator {
641
- static uuid() {
642
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
643
- const random = (Math.random() * 16) | 0;
644
- const value = char === 'x' ? random : (random & 0x3) | 0x8;
645
- return value.toString(16);
646
- });
912
+ class AXPExpressionEvaluatorScopeProviderContext {
913
+ constructor() {
914
+ this.scopes = {};
647
915
  }
648
- static number(...args) {
649
- let min = 0;
650
- let max = 100;
651
- if (args.length == 1)
652
- max = args[0];
653
- if (args.length == 2) {
654
- min = args[0];
655
- max = args[1];
656
- }
657
- return Math.floor(Math.random() * (max - min + 1)) + min;
916
+ addScope(namespace, functions) {
917
+ this.scopes[namespace] = { ...this.scopes[namespace], ...functions };
658
918
  }
659
- static date(...args) {
660
- let start = new Date(2000, 0, 1);
661
- let end = new Date();
662
- if (args.length === 1) {
663
- start = args[0];
664
- }
665
- else if (args.length === 2) {
666
- start = args[0];
667
- end = args[1];
668
- }
669
- const startTime = start.getTime();
670
- const endTime = end.getTime();
671
- return new Date(startTime + Math.random() * (endTime - startTime));
919
+ getScopes() {
920
+ return this.scopes;
672
921
  }
673
- static array(length = 5, generator) {
674
- return Array.from({ length }, generator);
922
+ }
923
+ const AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER = new InjectionToken('AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER');
924
+ class AXPExpressionEvaluatorScopeProviderService {
925
+ constructor() {
926
+ this.injector = inject(Injector);
927
+ this.cache = null;
675
928
  }
676
- static pick(...args) {
677
- if (args.length < 1) {
678
- throw new Error('Invalid parameters');
679
- }
680
- const items = args[0];
681
- const count = args[1] ?? 1;
682
- if (count < 1) {
683
- throw new Error('Count must be at least 1');
684
- }
685
- // If the count is greater than the number of items, just return a shuffled copy of the array
686
- if (count >= items.length) {
687
- return [...items].sort(() => Math.random() - 0.5);
688
- }
689
- // Shuffle the array and slice the first 'count' elements
690
- const shuffled = items.slice();
691
- for (let i = shuffled.length - 1; i > 0; i--) {
692
- const j = Math.floor(Math.random() * (i + 1));
693
- [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; // Swap elements
929
+ async load() {
930
+ if (this.cache)
931
+ return;
932
+ const raw = this.injector.get(AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, [], { optional: true });
933
+ const providers = Array.isArray(raw)
934
+ ? raw
935
+ : typeof raw === 'function'
936
+ ? raw()
937
+ : [];
938
+ const context = new AXPExpressionEvaluatorScopeProviderContext();
939
+ for (const provider of providers) {
940
+ await provider.provide(context);
694
941
  }
695
- return count == 1 ? shuffled.slice(0, count)[0] : shuffled.slice(0, count);
942
+ this.cache = context.getScopes();
696
943
  }
697
- static string(length = 10) {
698
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
699
- return Array.from({ length }, () => chars.charAt(Math.floor(Math.random() * chars.length))).join('');
944
+ async getScopesAsync() {
945
+ await this.load();
946
+ return this.cache || {};
700
947
  }
701
- static boolean() {
702
- return Math.random() >= 0.5;
948
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
949
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, providedIn: 'root' }); }
950
+ }
951
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, decorators: [{
952
+ type: Injectable,
953
+ args: [{ providedIn: 'root' }]
954
+ }] });
955
+
956
+ class AXPExpressionEvaluatorService {
957
+ constructor() {
958
+ // Memoization cache for compiled expressions
959
+ this.expressionCache = new Map();
960
+ this.providerService = inject(AXPExpressionEvaluatorScopeProviderService);
703
961
  }
704
- static item(array = []) {
705
- return array.length > 0 ? array[Math.floor(Math.random() * array.length)] : undefined;
962
+ getOrCompileFunction(expression) {
963
+ if (!this.expressionCache.has(expression)) {
964
+ // Check if expression contains multiple statements (has semicolons or newlines)
965
+ const hasMultipleStatements = expression.includes(';') || expression.includes('\n');
966
+ let fn;
967
+ if (hasMultipleStatements) {
968
+ // For multiple statements, execute them in sequence and return the last expression
969
+ fn = new Function('scope', `with (scope) { return (async function() { ${expression} })(); }`);
970
+ }
971
+ else {
972
+ // For single expressions, use return
973
+ fn = new Function('scope', `with (scope) { return (async function() { return ${expression}; })(); }`);
974
+ }
975
+ this.expressionCache.set(expression, fn);
976
+ }
977
+ return this.expressionCache.get(expression);
706
978
  }
707
- static color(format = 'hex') {
708
- // Generate HSL values with safe ranges for good contrast
709
- const h = Math.floor(Math.random() * 360);
710
- const s = Math.floor(Math.random() * 20) + 60; // 60% - 80%
711
- const l = Math.floor(Math.random() * 20) + 40; // 40% - 60%
712
- if (format === 'hsl') {
713
- return `hsl(${h}, ${s}%, ${l}%)`;
979
+ async getMergedScope(userScope) {
980
+ const pluginScopes = await this.providerService.getScopesAsync();
981
+ // Merge pluginScopes and userScope (userScope takes precedence)
982
+ return { ...pluginScopes, ...userScope };
983
+ }
984
+ async evaluate(source, scope = {}) {
985
+ try {
986
+ const mergedScope = await this.getMergedScope(scope);
987
+ if (typeof source === 'string' && source.includes('{{')) {
988
+ return await this.evaluateStringExpression(source, mergedScope);
989
+ }
990
+ else if (Array.isArray(source)) {
991
+ const evaluatedArray = [];
992
+ for (const item of source) {
993
+ evaluatedArray.push(await this.evaluate(item, mergedScope));
994
+ }
995
+ return evaluatedArray;
996
+ }
997
+ else if (typeof source === 'object' && source !== null) {
998
+ const evaluatedObject = {};
999
+ for (const key in source) {
1000
+ if (source.hasOwnProperty(key)) {
1001
+ evaluatedObject[key] = await this.evaluate(source[key], mergedScope);
1002
+ }
1003
+ }
1004
+ return evaluatedObject;
1005
+ }
1006
+ else {
1007
+ return source;
1008
+ }
714
1009
  }
715
- // Convert HSL to RGB
716
- const { r, g, b } = this.hslToRgb(h, s / 100, l / 100);
717
- if (format === 'rgb') {
718
- return `rgb(${r}, ${g}, ${b})`;
1010
+ catch (error) {
1011
+ console.error('Expression evaluator - Error evaluating expression:', source, error);
1012
+ return false;
719
1013
  }
720
- // Convert RGB to HEX
721
- const toHex = (val) => val.toString(16).padStart(2, '0');
722
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
723
1014
  }
724
- //TODO: move or read from utils
725
- static hslToRgb(h, s, l) {
726
- const c = (1 - Math.abs(2 * l - 1)) * s;
727
- const x = c * (1 - Math.abs((h / 60) % 2 - 1));
728
- const m = l - c / 2;
729
- let r = 0, g = 0, b = 0;
730
- if (h < 60)
731
- [r, g, b] = [c, x, 0];
732
- else if (h < 120)
733
- [r, g, b] = [x, c, 0];
734
- else if (h < 180)
735
- [r, g, b] = [0, c, x];
736
- else if (h < 240)
737
- [r, g, b] = [0, x, c];
738
- else if (h < 300)
1015
+ async evaluateStringExpression(templateExpression, scope) {
1016
+ // Check if the input is exactly a single {{ ... }} expression (handle multiline)
1017
+ const exactMatch = templateExpression.match(/^\s*\{\{\s*([\s\S]*?)\s*\}\}\s*$/);
1018
+ if (exactMatch) {
1019
+ const expression = exactMatch[1];
1020
+ const sandbox = this.getOrCompileFunction(expression);
1021
+ const result = await sandbox(scope);
1022
+ return result;
1023
+ }
1024
+ // Otherwise, interpolate all {{ ... }} expressions in the string
1025
+ const regex = /\{\{\s*([\s\S]*?)\s*\}\}/g;
1026
+ // Collect all matches and their positions
1027
+ const matches = [];
1028
+ let match;
1029
+ while ((match = regex.exec(templateExpression)) !== null) {
1030
+ matches.push({
1031
+ expression: match[1],
1032
+ start: match.index,
1033
+ end: regex.lastIndex,
1034
+ raw: match[0],
1035
+ });
1036
+ }
1037
+ // Evaluate all expressions in parallel
1038
+ const values = await Promise.all(matches.map((m) => {
1039
+ const sandbox = this.getOrCompileFunction(m.expression);
1040
+ return sandbox(scope);
1041
+ }));
1042
+ // Reconstruct the string with evaluated values
1043
+ let result = '';
1044
+ let lastIndex = 0;
1045
+ matches.forEach((m, i) => {
1046
+ result += templateExpression.slice(lastIndex, m.start);
1047
+ const value = values[i];
1048
+ result += value !== undefined && value !== null ? value : '';
1049
+ lastIndex = m.end;
1050
+ });
1051
+ result += templateExpression.slice(lastIndex);
1052
+ return result;
1053
+ }
1054
+ isExpression(expression) {
1055
+ if (typeof expression === 'string') {
1056
+ return expression.trim().startsWith('{{') && expression.trim().endsWith('}}');
1057
+ }
1058
+ return false;
1059
+ }
1060
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1061
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorService, providedIn: 'root' }); }
1062
+ }
1063
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorService, decorators: [{
1064
+ type: Injectable,
1065
+ args: [{ providedIn: 'root' }]
1066
+ }] });
1067
+
1068
+ class AXPComponentSlotPlaceholderComponent {
1069
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotPlaceholderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1070
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: AXPComponentSlotPlaceholderComponent, isStandalone: true, selector: "axp-component-slot-placeholder", ngImport: i0, template: `<div>
1071
+ <ax-skeleton class="ax-w-full ax-h-10 ax-rounded-md"></ax-skeleton>
1072
+ </div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1073
+ }
1074
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotPlaceholderComponent, decorators: [{
1075
+ type: Component,
1076
+ args: [{
1077
+ selector: 'axp-component-slot-placeholder',
1078
+ template: `<div>
1079
+ <ax-skeleton class="ax-w-full ax-h-10 ax-rounded-md"></ax-skeleton>
1080
+ </div>`,
1081
+ changeDetection: ChangeDetectionStrategy.OnPush,
1082
+ imports: [AXSkeletonModule],
1083
+ standalone: true,
1084
+ }]
1085
+ }] });
1086
+
1087
+ class AXPComponentSlotRegistryService {
1088
+ constructor() {
1089
+ this.registry = new Map();
1090
+ }
1091
+ register(slotName, config) {
1092
+ let configs = this.registry.get(slotName) || [];
1093
+ // Check if the component is already registered in this slot
1094
+ const isDuplicate = configs.some(existingConfig => existingConfig.name === config.name);
1095
+ if (!isDuplicate) {
1096
+ configs = [...configs, config]; // Add the new configuration
1097
+ this.registry.set(slotName, configs);
1098
+ }
1099
+ }
1100
+ get(slotName) {
1101
+ return this.registry.get(slotName) || [];
1102
+ }
1103
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1104
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotRegistryService, providedIn: 'root' }); }
1105
+ }
1106
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotRegistryService, decorators: [{
1107
+ type: Injectable,
1108
+ args: [{
1109
+ providedIn: 'root'
1110
+ }]
1111
+ }] });
1112
+
1113
+ class AXPComponentSlotDirective {
1114
+ constructor() {
1115
+ this.name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
1116
+ this.host = input(...(ngDevMode ? [undefined, { debugName: "host" }] : /* istanbul ignore next */ []));
1117
+ this.context = input(...(ngDevMode ? [undefined, { debugName: "context" }] : /* istanbul ignore next */ []));
1118
+ this.elementRef = inject(ElementRef);
1119
+ this.registryService = inject(AXPComponentSlotRegistryService);
1120
+ this.injector = inject(Injector);
1121
+ this.evaluator = inject(AXPExpressionEvaluatorService);
1122
+ this.viewContainerRef = inject(ViewContainerRef);
1123
+ this.contextStore = inject(AXPContextStore);
1124
+ this.isEmpty = computed(() => this._viewCount() === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
1125
+ // Create a signal to store the count of children
1126
+ this._viewCount = signal(0, ...(ngDevMode ? [{ debugName: "_viewCount" }] : /* istanbul ignore next */ []));
1127
+ // Track component references for updates
1128
+ this.componentRefs = [];
1129
+ // Track placeholder references for replacement
1130
+ this.placeholderRefs = new Map();
1131
+ // Watch for context changes and update component instances
1132
+ effect(() => {
1133
+ const currentContext = this.context();
1134
+ const currentHost = this.host();
1135
+ // Update all component references with new context and host
1136
+ this.componentRefs.forEach((componentRef) => {
1137
+ if (componentRef.instance) {
1138
+ Object.assign(componentRef.instance, {
1139
+ host: currentHost,
1140
+ context: currentContext,
1141
+ });
1142
+ }
1143
+ });
1144
+ });
1145
+ }
1146
+ async ngOnInit() {
1147
+ await this.loadComponents();
1148
+ // Update the signal after loading
1149
+ this._viewCount.set(this.viewContainerRef.length);
1150
+ }
1151
+ async loadComponents() {
1152
+ this.viewContainerRef.clear();
1153
+ // Clear previous component references
1154
+ this.componentRefs = [];
1155
+ this.placeholderRefs.clear();
1156
+ const configs = sortBy(this.registryService.get(this.name()), (c) => c.priority ?? 0);
1157
+ if (!configs) {
1158
+ console.error(`No component found for slot ${this.name()}`);
1159
+ return;
1160
+ }
1161
+ // Evaluate conditions and check features in parallel for performance
1162
+ const results = await Promise.all(configs.map(async (c) => {
1163
+ // Check condition if provided
1164
+ const conditionPassed = c.condition ? await this.evaluateCondition(c.condition) : true;
1165
+ // Check features if provided
1166
+ // const featuresPassed =
1167
+ // c.features && c.features.length > 0 ? this.sessionService.isFeatureEnabled(...c.features) : true;
1168
+ return {
1169
+ config: c,
1170
+ // visible: conditionPassed && featuresPassed,
1171
+ visible: conditionPassed,
1172
+ };
1173
+ }));
1174
+ // Filter visible components while preserving priority order
1175
+ const slots = results.filter((r) => r.visible).map((r) => r.config);
1176
+ // Create skeleton placeholders immediately in priority order
1177
+ slots.forEach((config, index) => {
1178
+ const placeholderRef = this.viewContainerRef.createComponent(AXPComponentSlotPlaceholderComponent);
1179
+ this.placeholderRefs.set(index, placeholderRef);
1180
+ });
1181
+ // Load all components in parallel and replace placeholders as they become ready
1182
+ const loadPromises = slots.map(async (config, index) => {
1183
+ let component;
1184
+ let options = {};
1185
+ // load component
1186
+ if (typeof config.loadComponent === 'function') {
1187
+ await runInInjectionContext(this.injector, async () => {
1188
+ component = await config.loadComponent?.();
1189
+ });
1190
+ }
1191
+ else if (config.component) {
1192
+ component = config.component;
1193
+ }
1194
+ // load options
1195
+ if (typeof config.options === 'function') {
1196
+ await runInInjectionContext(this.injector, async () => {
1197
+ const fun = config.options;
1198
+ options = await fun();
1199
+ });
1200
+ }
1201
+ else if (config.options) {
1202
+ options = await this.evaluator.evaluate(config.options, {});
1203
+ }
1204
+ // Replace placeholder with actual component as soon as it's ready
1205
+ if (!component) {
1206
+ console.warn(`Component failed to load for slot ${this.name()} at index ${index}`);
1207
+ // Remove placeholder if component failed to load
1208
+ const placeholderRef = this.placeholderRefs.get(index);
1209
+ if (placeholderRef) {
1210
+ placeholderRef.destroy();
1211
+ this.placeholderRefs.delete(index);
1212
+ }
1213
+ return;
1214
+ }
1215
+ // Get the placeholder reference at this index
1216
+ const placeholderRef = this.placeholderRefs.get(index);
1217
+ if (!placeholderRef) {
1218
+ console.warn(`Placeholder not found for index ${index}`);
1219
+ return;
1220
+ }
1221
+ // Get the index of the placeholder in the view container
1222
+ const placeholderIndex = this.viewContainerRef.indexOf(placeholderRef.hostView);
1223
+ // Remove the placeholder
1224
+ placeholderRef.destroy();
1225
+ this.placeholderRefs.delete(index);
1226
+ // Create the actual component at the same position
1227
+ const componentRef = this.viewContainerRef.createComponent(component, { index: placeholderIndex });
1228
+ // Store the component reference for future updates
1229
+ this.componentRefs.push(componentRef);
1230
+ Object.assign(componentRef.instance, {
1231
+ host: this.host(),
1232
+ context: this.context(),
1233
+ ...options,
1234
+ });
1235
+ });
1236
+ // Wait for all components to finish loading (they render as they become ready)
1237
+ await Promise.all(loadPromises);
1238
+ }
1239
+ async evaluateCondition(condition) {
1240
+ if (typeof condition === 'string') {
1241
+ const result = await this.evaluator.evaluate(condition, {});
1242
+ return result;
1243
+ }
1244
+ return condition(this.contextStore.data());
1245
+ //return condition(this.context());
1246
+ }
1247
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1248
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: AXPComponentSlotDirective, isStandalone: false, selector: "axp-component-slot", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, host: { classPropertyName: "host", publicName: "host", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["slot"], ngImport: i0 }); }
1249
+ }
1250
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotDirective, decorators: [{
1251
+ type: Directive,
1252
+ args: [{
1253
+ selector: 'axp-component-slot',
1254
+ standalone: false,
1255
+ exportAs: 'slot',
1256
+ }]
1257
+ }], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], host: [{ type: i0.Input, args: [{ isSignal: true, alias: "host", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }] } });
1258
+
1259
+ class AXPComponentSlotModule {
1260
+ static forRoot(configs) {
1261
+ return {
1262
+ ngModule: AXPComponentSlotModule,
1263
+ providers: [
1264
+ {
1265
+ provide: 'AXPComponentSlotModuleFactory',
1266
+ useFactory: (registry) => () => {
1267
+ if (configs) {
1268
+ for (const [key, value] of Object.entries(configs)) {
1269
+ value.forEach(v => {
1270
+ registry.register(key, v);
1271
+ });
1272
+ }
1273
+ }
1274
+ },
1275
+ deps: [AXPComponentSlotRegistryService],
1276
+ multi: true
1277
+ }
1278
+ ]
1279
+ };
1280
+ }
1281
+ static forChild(configs) {
1282
+ return {
1283
+ ngModule: AXPComponentSlotModule,
1284
+ providers: [
1285
+ {
1286
+ provide: 'AXPComponentSlotModuleFactory',
1287
+ useFactory: (registry) => () => {
1288
+ if (configs) {
1289
+ for (const [key, value] of Object.entries(configs)) {
1290
+ value.forEach(v => {
1291
+ registry.register(key, v);
1292
+ });
1293
+ }
1294
+ }
1295
+ },
1296
+ deps: [AXPComponentSlotRegistryService],
1297
+ multi: true
1298
+ }
1299
+ ]
1300
+ };
1301
+ }
1302
+ /**
1303
+ * @ignore
1304
+ */
1305
+ constructor(instances) {
1306
+ instances?.forEach(f => {
1307
+ f();
1308
+ });
1309
+ }
1310
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotModule, deps: [{ token: 'AXPComponentSlotModuleFactory', optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
1311
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotModule, declarations: [AXPComponentSlotDirective], exports: [AXPComponentSlotDirective] }); }
1312
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotModule }); }
1313
+ }
1314
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotModule, decorators: [{
1315
+ type: NgModule,
1316
+ args: [{
1317
+ declarations: [AXPComponentSlotDirective],
1318
+ exports: [AXPComponentSlotDirective]
1319
+ }]
1320
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
1321
+ type: Optional
1322
+ }, {
1323
+ type: Inject,
1324
+ args: ['AXPComponentSlotModuleFactory']
1325
+ }] }] });
1326
+
1327
+ class AXPDataGenerator {
1328
+ static uuid() {
1329
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
1330
+ const random = (Math.random() * 16) | 0;
1331
+ const value = char === 'x' ? random : (random & 0x3) | 0x8;
1332
+ return value.toString(16);
1333
+ });
1334
+ }
1335
+ static number(...args) {
1336
+ let min = 0;
1337
+ let max = 100;
1338
+ if (args.length == 1)
1339
+ max = args[0];
1340
+ if (args.length == 2) {
1341
+ min = args[0];
1342
+ max = args[1];
1343
+ }
1344
+ return Math.floor(Math.random() * (max - min + 1)) + min;
1345
+ }
1346
+ static date(...args) {
1347
+ let start = new Date(2000, 0, 1);
1348
+ let end = new Date();
1349
+ if (args.length === 1) {
1350
+ start = args[0];
1351
+ }
1352
+ else if (args.length === 2) {
1353
+ start = args[0];
1354
+ end = args[1];
1355
+ }
1356
+ const startTime = start.getTime();
1357
+ const endTime = end.getTime();
1358
+ return new Date(startTime + Math.random() * (endTime - startTime));
1359
+ }
1360
+ static array(length = 5, generator) {
1361
+ return Array.from({ length }, generator);
1362
+ }
1363
+ static pick(...args) {
1364
+ if (args.length < 1) {
1365
+ throw new Error('Invalid parameters');
1366
+ }
1367
+ const items = args[0];
1368
+ const count = args[1] ?? 1;
1369
+ if (count < 1) {
1370
+ throw new Error('Count must be at least 1');
1371
+ }
1372
+ // If the count is greater than the number of items, just return a shuffled copy of the array
1373
+ if (count >= items.length) {
1374
+ return [...items].sort(() => Math.random() - 0.5);
1375
+ }
1376
+ // Shuffle the array and slice the first 'count' elements
1377
+ const shuffled = items.slice();
1378
+ for (let i = shuffled.length - 1; i > 0; i--) {
1379
+ const j = Math.floor(Math.random() * (i + 1));
1380
+ [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; // Swap elements
1381
+ }
1382
+ return count == 1 ? shuffled.slice(0, count)[0] : shuffled.slice(0, count);
1383
+ }
1384
+ static string(length = 10) {
1385
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1386
+ return Array.from({ length }, () => chars.charAt(Math.floor(Math.random() * chars.length))).join('');
1387
+ }
1388
+ static boolean() {
1389
+ return Math.random() >= 0.5;
1390
+ }
1391
+ static item(array = []) {
1392
+ return array.length > 0 ? array[Math.floor(Math.random() * array.length)] : undefined;
1393
+ }
1394
+ static color(format = 'hex') {
1395
+ // Generate HSL values with safe ranges for good contrast
1396
+ const h = Math.floor(Math.random() * 360);
1397
+ const s = Math.floor(Math.random() * 20) + 60; // 60% - 80%
1398
+ const l = Math.floor(Math.random() * 20) + 40; // 40% - 60%
1399
+ if (format === 'hsl') {
1400
+ return `hsl(${h}, ${s}%, ${l}%)`;
1401
+ }
1402
+ // Convert HSL to RGB
1403
+ const { r, g, b } = this.hslToRgb(h, s / 100, l / 100);
1404
+ if (format === 'rgb') {
1405
+ return `rgb(${r}, ${g}, ${b})`;
1406
+ }
1407
+ // Convert RGB to HEX
1408
+ const toHex = (val) => val.toString(16).padStart(2, '0');
1409
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
1410
+ }
1411
+ //TODO: move or read from utils
1412
+ static hslToRgb(h, s, l) {
1413
+ const c = (1 - Math.abs(2 * l - 1)) * s;
1414
+ const x = c * (1 - Math.abs((h / 60) % 2 - 1));
1415
+ const m = l - c / 2;
1416
+ let r = 0, g = 0, b = 0;
1417
+ if (h < 60)
1418
+ [r, g, b] = [c, x, 0];
1419
+ else if (h < 120)
1420
+ [r, g, b] = [x, c, 0];
1421
+ else if (h < 180)
1422
+ [r, g, b] = [0, c, x];
1423
+ else if (h < 240)
1424
+ [r, g, b] = [0, x, c];
1425
+ else if (h < 300)
739
1426
  [r, g, b] = [x, 0, c];
740
1427
  else
741
1428
  [r, g, b] = [c, 0, x];
@@ -822,203 +1509,54 @@ function objectKeyValueTransforms(keyName) {
822
1509
  };
823
1510
  }
824
1511
 
825
- //#region ---- Imports ----
826
- //#endregion
827
- //#region ---- Provider Registry Service ----
828
- /**
829
- * Registry service for dynamically loaded module providers.
830
- * Stores provider instances that are loaded conditionally based on access control.
831
- */
832
- class AXPModuleProviderRegistry {
833
- constructor() {
834
- //#region ---- Fields ----
835
- this.permissionProviders = [];
836
- this.menuProviders = [];
837
- this.entityProviders = [];
838
- this.settingProviders = [];
839
- this.searchProviders = [];
840
- this.featureProviders = [];
841
- this.datasourceProviders = [];
842
- }
843
- //#endregion
844
- //#region ---- Public Methods ----
845
- /**
846
- * Register a permission provider.
847
- */
848
- registerPermissionProvider(provider) {
849
- this.permissionProviders.push(provider);
850
- }
851
- /**
852
- * Get all registered permission providers.
853
- */
854
- getPermissionProviders() {
855
- return [...this.permissionProviders];
856
- }
857
- /**
858
- * Register a menu provider.
859
- */
860
- registerMenuProvider(provider) {
861
- this.menuProviders.push(provider);
862
- }
863
- /**
864
- * Get all registered menu providers.
865
- */
866
- getMenuProviders() {
867
- return [...this.menuProviders];
868
- }
869
- /**
870
- * Register an entity provider.
871
- */
872
- registerEntityProvider(provider) {
873
- this.entityProviders.push(provider);
874
- }
875
- /**
876
- * Get all registered entity providers.
877
- */
878
- getEntityProviders() {
879
- return [...this.entityProviders];
880
- }
881
- /**
882
- * Register a settings provider.
883
- */
884
- registerSettingProvider(provider) {
885
- this.settingProviders.push(provider);
886
- }
887
- /**
888
- * Get all registered settings providers.
889
- */
890
- getSettingProviders() {
891
- return [...this.settingProviders];
892
- }
893
- /**
894
- * Register a search provider.
895
- */
896
- registerSearchProvider(provider) {
897
- this.searchProviders.push(provider);
898
- }
899
- /**
900
- * Get all registered search providers.
901
- */
902
- getSearchProviders() {
903
- return [...this.searchProviders];
904
- }
905
- /**
906
- * Register a feature provider.
907
- */
908
- registerFeatureProvider(provider) {
909
- this.featureProviders.push(provider);
910
- }
911
- /**
912
- * Get all registered feature providers.
913
- */
914
- getFeatureProviders() {
915
- return [...this.featureProviders];
916
- }
917
- /**
918
- * Register a datasource provider.
919
- */
920
- registerDatasourceProvider(provider) {
921
- this.datasourceProviders.push(provider);
922
- }
923
- /**
924
- * Get all registered datasource providers.
925
- */
926
- getDatasourceProviders() {
927
- return [...this.datasourceProviders];
928
- }
929
- /**
930
- * Clear all registered providers.
931
- * Useful for testing or re-initialization.
932
- */
933
- clear() {
934
- this.permissionProviders.length = 0;
935
- this.menuProviders.length = 0;
936
- this.entityProviders.length = 0;
937
- this.settingProviders.length = 0;
938
- this.searchProviders.length = 0;
939
- this.featureProviders.length = 0;
940
- this.datasourceProviders.length = 0;
941
- }
942
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleProviderRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
943
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleProviderRegistry, providedIn: 'root' }); }
944
- }
945
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleProviderRegistry, decorators: [{
946
- type: Injectable,
947
- args: [{ providedIn: 'root' }]
948
- }] });
949
-
950
1512
  const AXP_DATASOURCE_DEFINITION_PROVIDER = new InjectionToken('AXP_DATASOURCE_TYPE_PROVIDER');
951
1513
  class AXPDataSourceDefinitionProviderService {
952
1514
  constructor() {
953
1515
  this.providers = inject(AXP_DATASOURCE_DEFINITION_PROVIDER, { optional: true });
954
- this.providerRegistry = inject(AXPModuleProviderRegistry);
955
1516
  }
956
1517
  async items() {
957
1518
  const items = [];
958
- // Load from DI tokens (backward compatibility)
1519
+ // Load from DI tokens; resolve lazy providers (provideLazyProvider uses useFactory that returns Promise<T>)
959
1520
  if (Array.isArray(this.providers)) {
960
- for (const provider of this.providers) {
961
- set(provider, '__parent__', this);
962
- items.push(...(await provider.items()));
1521
+ for (const raw of this.providers) {
1522
+ const provider = await Promise.resolve(raw);
1523
+ if (provider && typeof provider.items === 'function') {
1524
+ set(provider, '__parent__', this);
1525
+ items.push(...(await provider.items()));
1526
+ }
963
1527
  }
964
1528
  }
965
- // Load from registry (manifest-based, conditionally loaded)
966
- const registryProviders = this.providerRegistry.getDatasourceProviders();
967
- for (const provider of registryProviders) {
968
- set(provider, '__parent__', this);
969
- items.push(...(await provider.items()));
970
- }
971
1529
  return items;
972
1530
  }
973
1531
  async get(name) {
974
1532
  return (await this.items()).find((c) => c.name == name);
975
1533
  }
976
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDataSourceDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
977
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDataSourceDefinitionProviderService, providedIn: 'root' }); }
1534
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSourceDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1535
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSourceDefinitionProviderService, providedIn: 'root' }); }
978
1536
  }
979
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDataSourceDefinitionProviderService, decorators: [{
1537
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSourceDefinitionProviderService, decorators: [{
980
1538
  type: Injectable,
981
1539
  args: [{ providedIn: 'root' }]
982
1540
  }] });
983
1541
 
984
- class AXPElementDataDirective {
985
- constructor(elementRef) {
986
- this.elementRef = elementRef;
987
- this.data = input(null, ...(ngDevMode ? [{ debugName: "data", alias: 'axp-data' }] : [{ alias: 'axp-data' }]));
988
- this.path = input('__data__', ...(ngDevMode ? [{ debugName: "path", alias: 'axp-data-path' }] : [{ alias: 'axp-data-path' }]));
989
- // Effect to update element data when inputs change
990
- this.updateEffect = effect(() => {
991
- const currentData = this.data();
992
- const currentPath = this.path();
993
- set(this.elementRef.nativeElement, currentPath, currentData);
994
- }, ...(ngDevMode ? [{ debugName: "updateEffect" }] : []));
995
- }
996
- ngOnInit() {
997
- // Initial data setup
998
- set(this.elementRef.nativeElement, this.path(), this.data());
999
- }
1000
- /**
1001
- * Get data from the element
1002
- */
1003
- getData() {
1004
- return get(this.elementRef.nativeElement, this.path());
1005
- }
1006
- /**
1007
- * Update data at runtime
1008
- */
1009
- setData(data) {
1010
- set(this.elementRef.nativeElement, this.path(), data);
1542
+ // src/app/directives/grid-layout.directive.ts
1543
+ class AXPContentCheckerDirective {
1544
+ constructor() {
1545
+ this.viewContainerRef = inject(ViewContainerRef);
1546
+ this.elementRef = inject((ElementRef));
1547
+ this.isEmpty = computed(() => this.viewContainerRef.length === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
1011
1548
  }
1012
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPElementDataDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
1013
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.12", type: AXPElementDataDirective, isStandalone: true, selector: "[axp-data]", inputs: { data: { classPropertyName: "data", publicName: "axp-data", isSignal: true, isRequired: false, transformFunction: null }, path: { classPropertyName: "path", publicName: "axp-data-path", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
1549
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPContentCheckerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1550
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: AXPContentCheckerDirective, isStandalone: true, selector: "[axp-content-checker]", exportAs: ["checker"], ngImport: i0 }); }
1014
1551
  }
1015
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPElementDataDirective, decorators: [{
1552
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPContentCheckerDirective, decorators: [{
1016
1553
  type: Directive,
1017
1554
  args: [{
1018
- selector: '[axp-data]',
1019
- standalone: true
1555
+ selector: '[axp-content-checker]',
1556
+ standalone: true,
1557
+ exportAs: 'checker'
1020
1558
  }]
1021
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-data", required: false }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-data-path", required: false }] }] } });
1559
+ }] });
1022
1560
 
1023
1561
  class AXPDblClickDirective {
1024
1562
  constructor() {
@@ -1041,30 +1579,69 @@ class AXPDblClickDirective {
1041
1579
  }
1042
1580
  this.lastTap = currentTime;
1043
1581
  }
1044
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDblClickDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1045
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.12", type: AXPDblClickDirective, isStandalone: true, selector: "[onDblClick]", outputs: { onDblClick: "onDblClick" }, host: { listeners: { "dblclick": "handleOnDblClick($event)", "touchend": "onTouchEnd($event)" } }, ngImport: i0 }); }
1582
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDblClickDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1583
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: AXPDblClickDirective, isStandalone: true, selector: "[onDblClick]", outputs: { onDblClick: "onDblClick" }, host: { listeners: { "dblclick": "handleOnDblClick($event)", "touchend": "onTouchEnd($event)" } }, ngImport: i0 }); }
1046
1584
  }
1047
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDblClickDirective, decorators: [{
1585
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDblClickDirective, decorators: [{
1048
1586
  type: Directive,
1049
1587
  args: [{
1050
1588
  selector: '[onDblClick]'
1051
1589
  }]
1052
- }], propDecorators: { onDblClick: [{
1053
- type: Output
1054
- }], handleOnDblClick: [{
1055
- type: HostListener,
1056
- args: ['dblclick', ['$event']]
1057
- }], onTouchEnd: [{
1058
- type: HostListener,
1059
- args: ['touchend', ['$event']]
1060
- }] } });
1590
+ }], propDecorators: { onDblClick: [{
1591
+ type: Output
1592
+ }], handleOnDblClick: [{
1593
+ type: HostListener,
1594
+ args: ['dblclick', ['$event']]
1595
+ }], onTouchEnd: [{
1596
+ type: HostListener,
1597
+ args: ['touchend', ['$event']]
1598
+ }] } });
1599
+
1600
+ class AXPElementDataDirective {
1601
+ constructor(elementRef) {
1602
+ this.elementRef = elementRef;
1603
+ this.data = input(null, { ...(ngDevMode ? { debugName: "data" } : /* istanbul ignore next */ {}), alias: 'axp-data' });
1604
+ this.path = input('__data__', { ...(ngDevMode ? { debugName: "path" } : /* istanbul ignore next */ {}), alias: 'axp-data-path' });
1605
+ // Effect to update element data when inputs change
1606
+ this.updateEffect = effect(() => {
1607
+ const currentData = this.data();
1608
+ const currentPath = this.path();
1609
+ set(this.elementRef.nativeElement, currentPath, currentData);
1610
+ }, ...(ngDevMode ? [{ debugName: "updateEffect" }] : /* istanbul ignore next */ []));
1611
+ }
1612
+ ngOnInit() {
1613
+ // Initial data setup
1614
+ set(this.elementRef.nativeElement, this.path(), this.data());
1615
+ }
1616
+ /**
1617
+ * Get data from the element
1618
+ */
1619
+ getData() {
1620
+ return get(this.elementRef.nativeElement, this.path());
1621
+ }
1622
+ /**
1623
+ * Update data at runtime
1624
+ */
1625
+ setData(data) {
1626
+ set(this.elementRef.nativeElement, this.path(), data);
1627
+ }
1628
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPElementDataDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
1629
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: AXPElementDataDirective, isStandalone: true, selector: "[axp-data]", inputs: { data: { classPropertyName: "data", publicName: "axp-data", isSignal: true, isRequired: false, transformFunction: null }, path: { classPropertyName: "path", publicName: "axp-data-path", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
1630
+ }
1631
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPElementDataDirective, decorators: [{
1632
+ type: Directive,
1633
+ args: [{
1634
+ selector: '[axp-data]',
1635
+ standalone: true
1636
+ }]
1637
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-data", required: false }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-data-path", required: false }] }] } });
1061
1638
 
1062
1639
  // src/app/directives/grid-layout.directive.ts
1063
1640
  class AXPGridLayoutDirective {
1064
1641
  constructor(el, renderer) {
1065
1642
  this.el = el;
1066
1643
  this.renderer = renderer;
1067
- this.options = input.required(...(ngDevMode ? [{ debugName: "options", alias: 'axp-grid-layout' }] : [{ alias: 'axp-grid-layout' }]));
1644
+ this.options = input.required({ ...(ngDevMode ? { debugName: "options" } : /* istanbul ignore next */ {}), alias: 'axp-grid-layout' });
1068
1645
  }
1069
1646
  ngOnChanges(changes) {
1070
1647
  if (changes['options']) {
@@ -1108,10 +1685,10 @@ class AXPGridLayoutDirective {
1108
1685
  }
1109
1686
  });
1110
1687
  }
1111
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPGridLayoutDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive }); }
1112
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.12", type: AXPGridLayoutDirective, isStandalone: true, selector: "[axp-grid-layout]", inputs: { options: { classPropertyName: "options", publicName: "axp-grid-layout", isSignal: true, isRequired: true, transformFunction: null } }, usesOnChanges: true, ngImport: i0 }); }
1688
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGridLayoutDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive }); }
1689
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: AXPGridLayoutDirective, isStandalone: true, selector: "[axp-grid-layout]", inputs: { options: { classPropertyName: "options", publicName: "axp-grid-layout", isSignal: true, isRequired: true, transformFunction: null } }, usesOnChanges: true, ngImport: i0 }); }
1113
1690
  }
1114
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPGridLayoutDirective, decorators: [{
1691
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGridLayoutDirective, decorators: [{
1115
1692
  type: Directive,
1116
1693
  args: [{
1117
1694
  selector: '[axp-grid-layout]',
@@ -1119,222 +1696,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
1119
1696
  }]
1120
1697
  }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-grid-layout", required: true }] }] } });
1121
1698
 
1122
- // src/app/directives/grid-layout.directive.ts
1123
- class AXPContentCheckerDirective {
1124
- constructor() {
1125
- this.viewContainerRef = inject(ViewContainerRef);
1126
- this.elementRef = inject((ElementRef));
1127
- this.isEmpty = computed(() => this.viewContainerRef.length === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : []));
1128
- }
1129
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPContentCheckerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1130
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.12", type: AXPContentCheckerDirective, isStandalone: true, selector: "[axp-content-checker]", exportAs: ["checker"], ngImport: i0 }); }
1131
- }
1132
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPContentCheckerDirective, decorators: [{
1133
- type: Directive,
1134
- args: [{
1135
- selector: '[axp-content-checker]',
1136
- standalone: true,
1137
- exportAs: 'checker'
1138
- }]
1139
- }] });
1140
-
1141
- //#region ---- Imports ----
1142
- //#endregion
1143
- //#region ---- Directive ----
1144
- /**
1145
- * Fullscreen directive that provides CSS-based fullscreen functionality
1146
- * Usage: <element axFullscreen #fullscreen="axFullscreen"></element>
1147
- * Then: fullscreen.toggle() or fullscreen.enter() or fullscreen.exit()
1148
- */
1149
- class AXFullscreenDirective {
1150
- constructor(elementRef) {
1151
- this.elementRef = elementRef;
1152
- //#region ---- Properties ----
1153
- /**
1154
- * Current fullscreen state
1155
- */
1156
- this.isFullscreenState = signal(false, ...(ngDevMode ? [{ debugName: "isFullscreenState" }] : []));
1157
- /**
1158
- * Original element styles to restore
1159
- */
1160
- this.originalStyles = {};
1161
- /**
1162
- * Original parent element reference
1163
- */
1164
- this.originalParent = null;
1165
- /**
1166
- * Fullscreen container element
1167
- */
1168
- this.fullscreenContainer = null;
1169
- /**
1170
- * Fullscreen change event
1171
- */
1172
- this.fullscreenChange = output();
1173
- //#endregion
1174
- //#region ---- Constructor ----
1175
- this.destroyRef = inject(DestroyRef);
1176
- this.renderer = inject(Renderer2);
1177
- // Sync state changes to output
1178
- effect(() => {
1179
- const isFullscreen = this.isFullscreenState();
1180
- untracked(() => {
1181
- this.fullscreenChange.emit(isFullscreen);
1182
- });
1183
- });
1184
- }
1185
- //#endregion
1186
- //#region ---- Public API ----
1187
- /**
1188
- * Toggle fullscreen state
1189
- */
1190
- async toggle() {
1191
- if (this.isFullscreenState()) {
1192
- await this.exit();
1193
- }
1194
- else {
1195
- await this.enter();
1196
- }
1197
- }
1198
- /**
1199
- * Enter fullscreen mode using CSS
1200
- */
1201
- async enter() {
1202
- if (this.isFullscreenState()) {
1203
- return;
1204
- }
1205
- const element = this.elementRef.nativeElement;
1206
- try {
1207
- // Store original styles and parent
1208
- this.storeOriginalStyles(element);
1209
- this.originalParent = element.parentElement;
1210
- // Create fullscreen container
1211
- this.fullscreenContainer = this.renderer.createElement('div');
1212
- this.renderer.setStyle(this.fullscreenContainer, 'position', 'fixed');
1213
- this.renderer.setStyle(this.fullscreenContainer, 'top', '0');
1214
- this.renderer.setStyle(this.fullscreenContainer, 'left', '0');
1215
- this.renderer.setStyle(this.fullscreenContainer, 'width', '100vw');
1216
- this.renderer.setStyle(this.fullscreenContainer, 'height', '100vh');
1217
- this.renderer.setStyle(this.fullscreenContainer, 'z-index', '9999');
1218
- this.renderer.setStyle(this.fullscreenContainer, 'background-color', '#ffffff');
1219
- this.renderer.setStyle(this.fullscreenContainer, 'overflow', 'auto');
1220
- // Move element to container
1221
- this.renderer.appendChild(this.fullscreenContainer, element);
1222
- // Apply fullscreen styles to element
1223
- this.renderer.setStyle(element, 'position', 'relative');
1224
- this.renderer.setStyle(element, 'width', '100%');
1225
- this.renderer.setStyle(element, 'height', '100%');
1226
- this.renderer.setStyle(element, 'margin', '0');
1227
- this.renderer.setStyle(element, 'padding', '0');
1228
- // Append container to body
1229
- this.renderer.appendChild(document.body, this.fullscreenContainer);
1230
- // Prevent body scroll
1231
- this.renderer.setStyle(document.body, 'overflow', 'hidden');
1232
- this.isFullscreenState.set(true);
1233
- }
1234
- catch (error) {
1235
- console.error('Error entering fullscreen:', error);
1236
- this.restoreOriginalStyles(element);
1237
- }
1238
- }
1239
- /**
1240
- * Exit fullscreen mode
1241
- */
1242
- async exit() {
1243
- if (!this.isFullscreenState()) {
1244
- return;
1245
- }
1246
- const element = this.elementRef.nativeElement;
1247
- try {
1248
- // Restore body scroll
1249
- this.renderer.removeStyle(document.body, 'overflow');
1250
- // Move element back to original parent
1251
- if (this.fullscreenContainer && this.originalParent) {
1252
- this.renderer.removeChild(this.fullscreenContainer, element);
1253
- this.renderer.appendChild(this.originalParent, element);
1254
- // Remove container
1255
- this.renderer.removeChild(document.body, this.fullscreenContainer);
1256
- this.fullscreenContainer = null;
1257
- }
1258
- // Restore original styles
1259
- this.restoreOriginalStyles(element);
1260
- this.isFullscreenState.set(false);
1261
- }
1262
- catch (error) {
1263
- console.error('Error exiting fullscreen:', error);
1264
- }
1265
- }
1266
- /**
1267
- * Check if currently in fullscreen mode
1268
- */
1269
- isFullscreen() {
1270
- return this.isFullscreenState();
1271
- }
1272
- //#endregion
1273
- //#region ---- Private Methods ----
1274
- /**
1275
- * Store original element styles
1276
- */
1277
- storeOriginalStyles(element) {
1278
- const computedStyle = window.getComputedStyle(element);
1279
- this.originalStyles = {
1280
- position: computedStyle.position,
1281
- top: computedStyle.top,
1282
- left: computedStyle.left,
1283
- width: computedStyle.width,
1284
- height: computedStyle.height,
1285
- zIndex: computedStyle.zIndex,
1286
- backgroundColor: computedStyle.backgroundColor,
1287
- margin: computedStyle.margin,
1288
- padding: computedStyle.padding,
1289
- };
1290
- }
1291
- /**
1292
- * Restore original element styles
1293
- */
1294
- restoreOriginalStyles(element) {
1295
- if (!this.originalStyles) {
1296
- return;
1297
- }
1298
- // Restore each style property
1299
- Object.entries(this.originalStyles).forEach(([key, value]) => {
1300
- const styleKey = this.camelToKebabCase(key);
1301
- if (value) {
1302
- this.renderer.setStyle(element, styleKey, value);
1303
- }
1304
- else {
1305
- this.renderer.removeStyle(element, styleKey);
1306
- }
1307
- });
1308
- this.originalStyles = {};
1309
- }
1310
- /**
1311
- * Convert camelCase to kebab-case for CSS properties
1312
- */
1313
- camelToKebabCase(str) {
1314
- return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
1315
- }
1316
- //#endregion
1317
- //#region ---- Lifecycle ----
1318
- ngOnDestroy() {
1319
- // Exit fullscreen if still active
1320
- if (this.isFullscreenState()) {
1321
- this.exit().catch(() => {
1322
- // Ignore errors during cleanup
1323
- });
1324
- }
1325
- }
1326
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXFullscreenDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
1327
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.12", type: AXFullscreenDirective, isStandalone: true, selector: "[axFullscreen]", outputs: { fullscreenChange: "fullscreenChange" }, exportAs: ["axFullscreen"], ngImport: i0 }); }
1328
- }
1329
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXFullscreenDirective, decorators: [{
1330
- type: Directive,
1331
- args: [{
1332
- selector: '[axFullscreen]',
1333
- standalone: true,
1334
- exportAs: 'axFullscreen',
1335
- }]
1336
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { fullscreenChange: [{ type: i0.Output, args: ["fullscreenChange"] }] } });
1337
-
1338
1699
  const AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER = new InjectionToken('AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER');
1339
1700
 
1340
1701
  //#region ---- Imports ----
@@ -1471,10 +1832,10 @@ class AXPDistributedEventListenerService {
1471
1832
  this.listenersByKey.clear();
1472
1833
  this.providersLoaded = false;
1473
1834
  }
1474
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDistributedEventListenerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1475
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDistributedEventListenerService, providedIn: 'root' }); }
1835
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDistributedEventListenerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1836
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDistributedEventListenerService, providedIn: 'root' }); }
1476
1837
  }
1477
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDistributedEventListenerService, decorators: [{
1838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDistributedEventListenerService, decorators: [{
1478
1839
  type: Injectable,
1479
1840
  args: [{
1480
1841
  providedIn: 'root',
@@ -1565,200 +1926,48 @@ class AXPBroadcastEventService {
1565
1926
  }
1566
1927
  else {
1567
1928
  reject(new Error(`Timeout: No response received for event '${type}' after ${options.retries} attempts.`));
1568
- }
1569
- }
1570
- }, options.timeout);
1571
- });
1572
- };
1573
- return attemptRequest(0);
1574
- }
1575
- /**
1576
- * Respond to a request
1577
- */
1578
- respondToRequest(requestId, response) {
1579
- if (!requestId) {
1580
- console.warn('Invalid requestId. Cannot send response.');
1581
- return;
1582
- }
1583
- this.channel.postMessage({ requestId, response });
1584
- }
1585
- /**
1586
- * Cleanup when the service is destroyed
1587
- */
1588
- ngOnDestroy() {
1589
- this.channel.close();
1590
- // Complete all subjects
1591
- this.eventSubjects.forEach((subject) => subject.complete());
1592
- this.eventSubjects.clear();
1593
- // Reject all pending requests to avoid dangling promises
1594
- this.pendingRequests.forEach((resolve, requestId) => {
1595
- resolve(Promise.reject(new Error(`Service destroyed. Request ${requestId} was not completed.`)));
1596
- });
1597
- this.pendingRequests.clear();
1598
- // Cleanup multi-tab event history
1599
- this.multiTabEventHistory.clear();
1600
- }
1601
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPBroadcastEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1602
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPBroadcastEventService, providedIn: 'root' }); }
1603
- }
1604
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPBroadcastEventService, decorators: [{
1605
- type: Injectable,
1606
- args: [{
1607
- providedIn: 'root',
1608
- }]
1609
- }], ctorParameters: () => [] });
1610
-
1611
- class AXPExpressionEvaluatorScopeProviderContext {
1612
- constructor() {
1613
- this.scopes = {};
1614
- }
1615
- addScope(namespace, functions) {
1616
- this.scopes[namespace] = { ...this.scopes[namespace], ...functions };
1617
- }
1618
- getScopes() {
1619
- return this.scopes;
1620
- }
1621
- }
1622
- const AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER = new InjectionToken('AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER');
1623
- class AXPExpressionEvaluatorScopeProviderService {
1624
- constructor() {
1625
- this.providers = inject(AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, { optional: true });
1626
- this.cache = null;
1627
- }
1628
- async load() {
1629
- if (this.cache)
1630
- return;
1631
- const context = new AXPExpressionEvaluatorScopeProviderContext();
1632
- if (Array.isArray(this.providers)) {
1633
- for (const provider of this.providers) {
1634
- await provider.provide(context);
1635
- }
1636
- }
1637
- this.cache = context.getScopes();
1638
- }
1639
- async getScopesAsync() {
1640
- await this.load();
1641
- return this.cache || {};
1642
- }
1643
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1644
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, providedIn: 'root' }); }
1645
- }
1646
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, decorators: [{
1647
- type: Injectable,
1648
- args: [{ providedIn: 'root' }]
1649
- }] });
1650
-
1651
- class AXPExpressionEvaluatorService {
1652
- constructor() {
1653
- // Memoization cache for compiled expressions
1654
- this.expressionCache = new Map();
1655
- this.providerService = inject(AXPExpressionEvaluatorScopeProviderService);
1656
- }
1657
- getOrCompileFunction(expression) {
1658
- if (!this.expressionCache.has(expression)) {
1659
- // Check if expression contains multiple statements (has semicolons or newlines)
1660
- const hasMultipleStatements = expression.includes(';') || expression.includes('\n');
1661
- let fn;
1662
- if (hasMultipleStatements) {
1663
- // For multiple statements, execute them in sequence and return the last expression
1664
- fn = new Function('scope', `with (scope) { return (async function() { ${expression} })(); }`);
1665
- }
1666
- else {
1667
- // For single expressions, use return
1668
- fn = new Function('scope', `with (scope) { return (async function() { return ${expression}; })(); }`);
1669
- }
1670
- this.expressionCache.set(expression, fn);
1671
- }
1672
- return this.expressionCache.get(expression);
1673
- }
1674
- async getMergedScope(userScope) {
1675
- const pluginScopes = await this.providerService.getScopesAsync();
1676
- // Merge pluginScopes and userScope (userScope takes precedence)
1677
- return { ...pluginScopes, ...userScope };
1678
- }
1679
- async evaluate(source, scope = {}) {
1680
- try {
1681
- const mergedScope = await this.getMergedScope(scope);
1682
- if (typeof source === 'string' && source.includes('{{')) {
1683
- return await this.evaluateStringExpression(source, mergedScope);
1684
- }
1685
- else if (Array.isArray(source)) {
1686
- const evaluatedArray = [];
1687
- for (const item of source) {
1688
- evaluatedArray.push(await this.evaluate(item, mergedScope));
1689
- }
1690
- return evaluatedArray;
1691
- }
1692
- else if (typeof source === 'object' && source !== null) {
1693
- const evaluatedObject = {};
1694
- for (const key in source) {
1695
- if (source.hasOwnProperty(key)) {
1696
- evaluatedObject[key] = await this.evaluate(source[key], mergedScope);
1697
- }
1698
- }
1699
- return evaluatedObject;
1700
- }
1701
- else {
1702
- return source;
1703
- }
1704
- }
1705
- catch (error) {
1706
- console.error('Expression evaluator - Error evaluating expression:', source, error);
1707
- return false;
1708
- }
1709
- }
1710
- async evaluateStringExpression(templateExpression, scope) {
1711
- // Check if the input is exactly a single {{ ... }} expression (handle multiline)
1712
- const exactMatch = templateExpression.match(/^\s*\{\{\s*([\s\S]*?)\s*\}\}\s*$/);
1713
- if (exactMatch) {
1714
- const expression = exactMatch[1];
1715
- const sandbox = this.getOrCompileFunction(expression);
1716
- const result = await sandbox(scope);
1717
- return result;
1718
- }
1719
- // Otherwise, interpolate all {{ ... }} expressions in the string
1720
- const regex = /\{\{\s*([\s\S]*?)\s*\}\}/g;
1721
- // Collect all matches and their positions
1722
- const matches = [];
1723
- let match;
1724
- while ((match = regex.exec(templateExpression)) !== null) {
1725
- matches.push({
1726
- expression: match[1],
1727
- start: match.index,
1728
- end: regex.lastIndex,
1729
- raw: match[0],
1929
+ }
1930
+ }
1931
+ }, options.timeout);
1730
1932
  });
1731
- }
1732
- // Evaluate all expressions in parallel
1733
- const values = await Promise.all(matches.map((m) => {
1734
- const sandbox = this.getOrCompileFunction(m.expression);
1735
- return sandbox(scope);
1736
- }));
1737
- // Reconstruct the string with evaluated values
1738
- let result = '';
1739
- let lastIndex = 0;
1740
- matches.forEach((m, i) => {
1741
- result += templateExpression.slice(lastIndex, m.start);
1742
- const value = values[i];
1743
- result += value !== undefined && value !== null ? value : '';
1744
- lastIndex = m.end;
1745
- });
1746
- result += templateExpression.slice(lastIndex);
1747
- return result;
1933
+ };
1934
+ return attemptRequest(0);
1748
1935
  }
1749
- isExpression(expression) {
1750
- if (typeof expression === 'string') {
1751
- return expression.includes('{{');
1936
+ /**
1937
+ * Respond to a request
1938
+ */
1939
+ respondToRequest(requestId, response) {
1940
+ if (!requestId) {
1941
+ console.warn('Invalid requestId. Cannot send response.');
1942
+ return;
1752
1943
  }
1753
- return false;
1944
+ this.channel.postMessage({ requestId, response });
1945
+ }
1946
+ /**
1947
+ * Cleanup when the service is destroyed
1948
+ */
1949
+ ngOnDestroy() {
1950
+ this.channel.close();
1951
+ // Complete all subjects
1952
+ this.eventSubjects.forEach((subject) => subject.complete());
1953
+ this.eventSubjects.clear();
1954
+ // Reject all pending requests to avoid dangling promises
1955
+ this.pendingRequests.forEach((resolve, requestId) => {
1956
+ resolve(Promise.reject(new Error(`Service destroyed. Request ${requestId} was not completed.`)));
1957
+ });
1958
+ this.pendingRequests.clear();
1959
+ // Cleanup multi-tab event history
1960
+ this.multiTabEventHistory.clear();
1754
1961
  }
1755
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1756
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorService, providedIn: 'root' }); }
1962
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBroadcastEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1963
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBroadcastEventService, providedIn: 'root' }); }
1757
1964
  }
1758
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorService, decorators: [{
1965
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBroadcastEventService, decorators: [{
1759
1966
  type: Injectable,
1760
- args: [{ providedIn: 'root' }]
1761
- }] });
1967
+ args: [{
1968
+ providedIn: 'root',
1969
+ }]
1970
+ }], ctorParameters: () => [] });
1762
1971
 
1763
1972
  class AXPHookService {
1764
1973
  constructor() {
@@ -1806,10 +2015,10 @@ class AXPHookService {
1806
2015
  }
1807
2016
  return data;
1808
2017
  }
1809
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPHookService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1810
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPHookService, providedIn: 'root' }); }
2018
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHookService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2019
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHookService, providedIn: 'root' }); }
1811
2020
  }
1812
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPHookService, decorators: [{
2021
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHookService, decorators: [{
1813
2022
  type: Injectable,
1814
2023
  args: [{ providedIn: 'root' }]
1815
2024
  }] });
@@ -1818,21 +2027,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
1818
2027
  //#endregion
1819
2028
 
1820
2029
  //#region ---- Provider Interfaces ----
1821
- /**
1822
- * Injection token for edition service.
1823
- * Modules should provide their implementation using this token.
1824
- */
1825
- const AXP_EDITION_SERVICE = new InjectionToken('AXP_EDITION_SERVICE', {
1826
- providedIn: 'root',
1827
- factory: () => {
1828
- return null;
1829
- },
1830
- });
1831
- /**
1832
- * Injection token for module provider loader.
1833
- * Implementation: @acorex/platform/auth
1834
- */
1835
- const AXP_MODULE_PROVIDER_LOADER = new InjectionToken('AXP_MODULE_PROVIDER_LOADER');
1836
2030
  /**
1837
2031
  * Injection token for session service.
1838
2032
  * Implementation: @acorex/platform/auth
@@ -1845,6 +2039,41 @@ const AXP_SESSION_SERVICE = new InjectionToken('AXP_SESSION_SERVICE');
1845
2039
  const AXP_MODULE_MANIFEST_PROVIDER = new InjectionToken('AXP_MODULE_MANIFEST_PROVIDER');
1846
2040
  //#endregion
1847
2041
 
2042
+ //#region ---- Imports ----
2043
+ //#endregion
2044
+ //#region ---- Feature Definition Provider Interface ----
2045
+ /**
2046
+ * Context for feature definition providers.
2047
+ * Allows providers to add additional feature definitions dynamically.
2048
+ */
2049
+ class AXPFeatureDefinitionProviderContext {
2050
+ constructor() {
2051
+ this.features = new Map();
2052
+ }
2053
+ /**
2054
+ * Add a feature definition.
2055
+ * @param key Full feature key (ModuleName:FeatureKey format with colon separator)
2056
+ * @param definition Feature definition
2057
+ */
2058
+ addFeature(key, definition) {
2059
+ this.features.set(key, definition);
2060
+ }
2061
+ /**
2062
+ * Get all feature definitions.
2063
+ */
2064
+ getFeatures() {
2065
+ return this.features;
2066
+ }
2067
+ }
2068
+ /**
2069
+ * Injection token for feature definition providers.
2070
+ */
2071
+ const AXP_FEATURE_DEFINITION_PROVIDER = new InjectionToken('AXP_FEATURE_DEFINITION_PROVIDER', {
2072
+ providedIn: 'root',
2073
+ factory: () => [],
2074
+ });
2075
+ //#endregion
2076
+
1848
2077
  //#region ---- Imports ----
1849
2078
  //#endregion
1850
2079
  //#region ---- Registry Service ----
@@ -1910,6 +2139,8 @@ class AXPModuleManifestRegistry {
1910
2139
  }
1911
2140
  });
1912
2141
  await Promise.all(registerPromises);
2142
+ // Load and register features from all feature definition providers
2143
+ await this.loadFeatureDefinitions();
1913
2144
  this.isInitialized = true;
1914
2145
  }
1915
2146
  //#endregion
@@ -1946,6 +2177,53 @@ class AXPModuleManifestRegistry {
1946
2177
  has(moduleName) {
1947
2178
  return this.manifests.has(moduleName);
1948
2179
  }
2180
+ /**
2181
+ * Load feature definitions from all registered feature definition providers.
2182
+ * Features are automatically associated with modules based on the module name in the feature key.
2183
+ */
2184
+ async loadFeatureDefinitions() {
2185
+ try {
2186
+ const featureProviders = this.injector.get(AXP_FEATURE_DEFINITION_PROVIDER, []);
2187
+ if (!featureProviders || featureProviders.length === 0) {
2188
+ return;
2189
+ }
2190
+ const context = new AXPFeatureDefinitionProviderContext();
2191
+ // Call all providers to collect features
2192
+ for (const provider of featureProviders) {
2193
+ if (provider instanceof Promise) {
2194
+ // If provider is a promise, resolve it
2195
+ const resolvedProvider = await provider;
2196
+ await resolvedProvider.provide(context);
2197
+ }
2198
+ else {
2199
+ // If provider is a direct instance, use it directly
2200
+ await provider.provide(context);
2201
+ }
2202
+ }
2203
+ // Register all features and associate them with their modules
2204
+ const features = context.getFeatures();
2205
+ for (const [key, definition] of features.entries()) {
2206
+ // Extract module name from key (format: ModuleName:FeatureKey)
2207
+ const [moduleName, ...keyParts] = key.split(':');
2208
+ const shortKey = keyParts.join(':');
2209
+ // Verify that the module exists
2210
+ if (!this.has(moduleName)) {
2211
+ console.warn(`Feature '${key}' references unknown module '${moduleName}'. Skipping.`);
2212
+ continue;
2213
+ }
2214
+ // Register feature definition
2215
+ this.registerFeatureDefinition({
2216
+ ...definition,
2217
+ name: key,
2218
+ module: moduleName,
2219
+ key: shortKey,
2220
+ });
2221
+ }
2222
+ }
2223
+ catch (error) {
2224
+ console.error('Failed to load feature definitions:', error);
2225
+ }
2226
+ }
1949
2227
  //#endregion
1950
2228
  //#region ---- Feature Definition Management ----
1951
2229
  /**
@@ -1982,7 +2260,7 @@ class AXPModuleManifestRegistry {
1982
2260
  }
1983
2261
  /**
1984
2262
  * Register a feature definition dynamically (e.g., from feature definition provider).
1985
- * Used to add features that are defined at runtime via featuresProvider.
2263
+ * Used to add features that are defined at runtime via AXP_FEATURE_DEFINITION_PROVIDER.
1986
2264
  */
1987
2265
  registerFeatureDefinition(definition) {
1988
2266
  this.featureDefinitions.set(definition.name, definition);
@@ -1992,40 +2270,113 @@ class AXPModuleManifestRegistry {
1992
2270
  /**
1993
2271
  * Check if module dependencies are satisfied.
1994
2272
  * Returns array of missing dependencies.
2273
+ * Dependencies can be module names or feature keys (ModuleName.FeatureKey format).
1995
2274
  */
1996
2275
  checkDependencies(moduleName) {
1997
2276
  const manifest = this.get(moduleName);
1998
- if (!manifest?.dependencies) {
2277
+ if (!manifest?.dependencies || manifest.dependencies.length === 0) {
1999
2278
  return { missingModules: [], missingFeatures: [] };
2000
2279
  }
2001
2280
  const missingModules = [];
2002
2281
  const missingFeatures = [];
2003
- // Check module dependencies
2004
- if (manifest.dependencies.modules) {
2005
- for (const depModule of manifest.dependencies.modules) {
2006
- if (!this.has(depModule)) {
2007
- missingModules.push(depModule);
2282
+ for (const dependency of manifest.dependencies) {
2283
+ // If dependency contains a dot, it's a feature (ModuleName.FeatureKey)
2284
+ if (dependency.includes('.')) {
2285
+ // Convert dependency format (ModuleName.FeatureKey) to feature name format (ModuleName:Feature:FeatureKey)
2286
+ const [moduleName, featureKey] = dependency.split('.');
2287
+ const featureName = `${moduleName}:Feature:${featureKey}`;
2288
+ if (!this.isFeatureDefined(featureName)) {
2289
+ missingFeatures.push(dependency);
2008
2290
  }
2009
2291
  }
2010
- }
2011
- // Check feature dependencies
2012
- if (manifest.dependencies.features) {
2013
- for (const featureName of manifest.dependencies.features) {
2014
- if (!this.isFeatureDefined(featureName)) {
2015
- missingFeatures.push(featureName);
2292
+ else {
2293
+ // Otherwise, it's a module name
2294
+ if (!this.has(dependency)) {
2295
+ missingModules.push(dependency);
2016
2296
  }
2017
2297
  }
2018
2298
  }
2019
2299
  return { missingModules, missingFeatures };
2020
2300
  }
2021
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleManifestRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2022
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleManifestRegistry, providedIn: 'root' }); }
2301
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2302
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestRegistry, providedIn: 'root' }); }
2023
2303
  }
2024
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleManifestRegistry, decorators: [{
2304
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestRegistry, decorators: [{
2025
2305
  type: Injectable,
2026
2306
  args: [{ providedIn: 'root' }]
2027
2307
  }] });
2028
2308
 
2309
+ //#region ---- Imports ----
2310
+ //#endregion
2311
+ //#region ---- Module manifests data source ----
2312
+ /**
2313
+ * Registered module manifests for select widgets via dataSource name {@link MODULE_MANIFESTS_DATASOURCE_NAME}.
2314
+ */
2315
+ const MODULE_MANIFESTS_DATASOURCE_NAME = 'platform-module-manifests';
2316
+ /**
2317
+ * Data source definition for module names/titles from {@link AXPModuleManifestRegistry}.
2318
+ */
2319
+ class AXPModuleManifestsDataSourceDefinition {
2320
+ constructor() {
2321
+ //#region ---- Services & Dependencies ----
2322
+ this.manifestRegistry = inject(AXPModuleManifestRegistry);
2323
+ //#endregion
2324
+ }
2325
+ //#endregion
2326
+ //#region ---- Public API ----
2327
+ async items() {
2328
+ return [
2329
+ {
2330
+ name: MODULE_MANIFESTS_DATASOURCE_NAME,
2331
+ title: 'Module manifests',
2332
+ source: () => new AXDataSource({
2333
+ key: 'id',
2334
+ load: async () => {
2335
+ await this.manifestRegistry.initialize();
2336
+ const list = this.manifestRegistry.getAll().map((m) => ({
2337
+ id: m.name,
2338
+ title: m.title || m.name,
2339
+ }));
2340
+ return { items: list, total: list.length };
2341
+ },
2342
+ byKey: async (key) => {
2343
+ await this.manifestRegistry.initialize();
2344
+ const m = this.manifestRegistry.getAll().find((x) => x.name === key);
2345
+ return m ? { id: m.name, title: m.title || m.name } : undefined;
2346
+ },
2347
+ pageSize: 1000,
2348
+ }),
2349
+ columns: [
2350
+ {
2351
+ name: 'id',
2352
+ title: 'ID',
2353
+ datatype: 'string',
2354
+ type: 'text-editor',
2355
+ },
2356
+ {
2357
+ name: 'title',
2358
+ title: 'Title',
2359
+ datatype: 'string',
2360
+ type: 'text-editor',
2361
+ },
2362
+ ],
2363
+ filters: [
2364
+ {
2365
+ field: 'title',
2366
+ title: 'Title',
2367
+ operator: { type: 'equal' },
2368
+ widget: { type: 'text-editor' },
2369
+ filterType: { advance: true, inline: true },
2370
+ },
2371
+ ],
2372
+ textField: { name: 'title', title: 'Title' },
2373
+ valueField: { name: 'id', title: 'ID' },
2374
+ },
2375
+ ];
2376
+ }
2377
+ }
2378
+ //#endregion
2379
+
2029
2380
  class AXPAppStartUpService {
2030
2381
  constructor() {
2031
2382
  this.tasks = [];
@@ -2045,10 +2396,10 @@ class AXPAppStartUpService {
2045
2396
  loadingText.innerHTML = status;
2046
2397
  }
2047
2398
  }
2048
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPAppStartUpService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2049
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPAppStartUpService, providedIn: 'root' }); }
2399
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppStartUpService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2400
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppStartUpService, providedIn: 'root' }); }
2050
2401
  }
2051
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPAppStartUpService, decorators: [{
2402
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppStartUpService, decorators: [{
2052
2403
  type: Injectable,
2053
2404
  args: [{
2054
2405
  providedIn: 'root',
@@ -2066,17 +2417,16 @@ const AXPAppStartUpProvider = provideAppInitializer(() => {
2066
2417
  //#endregion
2067
2418
  //#region ---- Module ----
2068
2419
  /**
2069
- * Module for managing module manifests and providers initialization.
2070
- * Handles the registration of manifest and module provider startup tasks.
2420
+ * Module for managing module manifests initialization.
2421
+ * Handles the registration of manifest startup tasks.
2071
2422
  */
2072
2423
  class AXPModuleManifestModule {
2073
2424
  /**
2074
2425
  * @ignore
2075
- * Initializes module manifest and provider tasks on module construction.
2426
+ * Initializes module manifest tasks on module construction.
2076
2427
  */
2077
2428
  constructor(appInitService, injector) {
2078
2429
  const manifestRegistry = injector.get(AXPModuleManifestRegistry);
2079
- const moduleProviderLoader = injector.get(AXP_MODULE_PROVIDER_LOADER);
2080
2430
  // Register manifest initialization task
2081
2431
  appInitService.registerTask({
2082
2432
  name: 'ModuleManifests',
@@ -2086,97 +2436,204 @@ class AXPModuleManifestModule {
2086
2436
  await manifestRegistry.initialize();
2087
2437
  },
2088
2438
  });
2089
- // Register module provider tasks
2090
- appInitService.registerTask({
2091
- name: 'RequiredModuleProviders',
2092
- statusText: 'Loading required modules...',
2093
- priority: 1.5,
2094
- run: async () => {
2095
- await moduleProviderLoader.loadRequiredModules();
2096
- },
2097
- });
2098
- appInitService.registerTask({
2099
- name: 'ModuleProviders',
2100
- statusText: 'Loading module providers...',
2101
- priority: 3,
2102
- run: async () => {
2103
- await moduleProviderLoader.loadProvidersIfReady();
2104
- },
2105
- });
2106
2439
  }
2107
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleManifestModule, deps: [{ token: AXPAppStartUpService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
2108
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleManifestModule }); }
2109
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleManifestModule }); }
2440
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestModule, deps: [{ token: AXPAppStartUpService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
2441
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestModule }); }
2442
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestModule }); }
2110
2443
  }
2111
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPModuleManifestModule, decorators: [{
2444
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestModule, decorators: [{
2112
2445
  type: NgModule,
2113
2446
  args: [{
2114
2447
  providers: [],
2115
2448
  }]
2116
2449
  }], ctorParameters: () => [{ type: AXPAppStartUpService }, { type: i0.Injector }] });
2117
2450
 
2118
- //#region ---- Imports ----
2451
+ //#region ---- Imports ----
2119
2452
  //#endregion
2120
- //#region ---- Feature Definition Provider Interface ----
2453
+ //#region ---- Public API ----
2454
+ const LOCALE_KEY_REGEX = /^(\*-\*|[a-z]{2}-[A-Z]{2})$/;
2121
2455
  /**
2122
- * Context for feature definition providers.
2123
- * Allows providers to add additional feature definitions dynamically.
2456
+ * Checks whether value is a valid locale map (`xx-XX` or `*-*` keys, string values).
2124
2457
  */
2125
- class AXPFeatureDefinitionProviderContext {
2126
- constructor() {
2127
- this.features = new Map();
2458
+ function isValidMultiLanguageObject(value) {
2459
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
2460
+ return false;
2128
2461
  }
2129
- /**
2130
- * Add a feature definition.
2131
- * @param key Full feature key (ModuleName:FeatureKey format with colon separator)
2132
- * @param definition Feature definition
2133
- */
2134
- addFeature(key, definition) {
2135
- this.features.set(key, definition);
2462
+ const entries = Object.entries(value);
2463
+ if (!entries.length) {
2464
+ return false;
2136
2465
  }
2137
- /**
2138
- * Get all feature definitions.
2139
- */
2140
- getFeatures() {
2141
- return this.features;
2466
+ return entries.every(([key, entryValue]) => LOCALE_KEY_REGEX.test(key) && typeof entryValue === 'string');
2467
+ }
2468
+ /**
2469
+ * Resolves {@link AXPMultiLanguageString} to a single string for the given locale.
2470
+ * Fallback order: `currentLocale` → `en-US` → first map value.
2471
+ */
2472
+ function resolveMultiLanguageString(content, currentLocale) {
2473
+ if (content == null || content === '') {
2474
+ return '';
2142
2475
  }
2476
+ if (typeof content === 'string') {
2477
+ return content;
2478
+ }
2479
+ if (!isValidMultiLanguageObject(content)) {
2480
+ return String(content);
2481
+ }
2482
+ const record = content;
2483
+ const pick = record[currentLocale] ??
2484
+ record['en-US'] ??
2485
+ Object.values(record).find((v) => v != null);
2486
+ if (pick == null || pick === '') {
2487
+ return '';
2488
+ }
2489
+ if (typeof pick === 'string') {
2490
+ return pick;
2491
+ }
2492
+ return String(pick);
2143
2493
  }
2144
2494
  /**
2145
- * Injection token for feature definition providers.
2495
+ * Creates an {@link AXPMultiLanguageString} with `en-US` and `fa-IR` entries.
2496
+ * Use for seed data, tests, and demos that supply English and Persian copy explicitly.
2146
2497
  */
2147
- const AXP_FEATURE_DEFINITION_PROVIDER = new InjectionToken('AXP_FEATURE_DEFINITION_PROVIDER', {
2148
- providedIn: 'root',
2149
- factory: () => [],
2150
- });
2498
+ function createMultiLanguageString(enUs, faIr) {
2499
+ return { 'en-US': enUs, 'fa-IR': faIr };
2500
+ }
2501
+ /**
2502
+ * True when there is no displayable text in any locale (plain string or ML map).
2503
+ * Pure helper for predicates (e.g. default section detection); prefer widgets / pipes for display.
2504
+ */
2505
+ function isEffectivelyEmptyLocalizedValue(value) {
2506
+ if (value == null)
2507
+ return true;
2508
+ if (typeof value === 'string')
2509
+ return value.trim() === '';
2510
+ if (typeof value !== 'object' || Array.isArray(value))
2511
+ return false;
2512
+ const record = value;
2513
+ return Object.values(record).every((v) => v == null || String(v).trim() === '');
2514
+ }
2151
2515
  //#endregion
2152
2516
 
2153
- //#region ---- Imports ----
2517
+ //#region ---- Imports ----
2154
2518
  //#endregion
2155
- //#region ---- Default Implementation ----
2519
+ //#region ---- AXPMultiLanguageStringResolverService ----
2156
2520
  /**
2157
- * Default implementation of module access control service.
2158
- * Checks if module is enabled in edition.modulesAndFeatures.modules.
2521
+ * Resolves {@link AXPMultiLanguageString} using the active app locale, and exposes
2522
+ * {@link currentLocale$} for code that prefers an observable (e.g. manual subscriptions).
2523
+ * Templates usually use {@link AXPResolveMultiLanguageStringPipe} instead.
2159
2524
  */
2160
- class DefaultModuleAccessControlService {
2161
- checkAccess(manifest, context) {
2162
- // Check if module is enabled in edition
2163
- const enabledModules = context.edition.modulesAndFeatures?.modules || [];
2164
- return enabledModules.includes(manifest.name);
2525
+ class AXPMultiLanguageStringResolverService {
2526
+ constructor() {
2527
+ //#region ---- Services & Dependencies ----
2528
+ this.translation = inject(AXTranslationService);
2529
+ //#endregion
2530
+ //#region ---- Locale stream ----
2531
+ /**
2532
+ * Emits the active locale on subscribe and whenever the language changes.
2533
+ */
2534
+ this.currentLocale$ = merge$1(of(this.translation.getActiveLang()), this.translation.langChanges$).pipe(map(() => this.translation.getActiveLang()), distinctUntilChanged());
2535
+ }
2536
+ //#endregion
2537
+ //#region ---- Resolve ----
2538
+ /**
2539
+ * Resolves multi-language content for an optional locale (defaults to active).
2540
+ */
2541
+ resolve(content, locale) {
2542
+ if (content && typeof content === 'object' && !isValidMultiLanguageObject(content)) {
2543
+ return '';
2544
+ }
2545
+ return resolveMultiLanguageString(content, locale ?? this.translation.getActiveLang());
2546
+ }
2547
+ /**
2548
+ * Checks if a value is a valid multi-language object map.
2549
+ * Key format must be `xx-XX` (e.g. en-US, fa-IR) or fallback `*-*`.
2550
+ * All values must be strings.
2551
+ */
2552
+ isValidMultiLanguageObject(value) {
2553
+ return isValidMultiLanguageObject(value);
2554
+ }
2555
+ /**
2556
+ * Normalizes multi-language content to a locale map for editors (e.g. multi-language popup `values`).
2557
+ * If `content` is already a locale-to-string map, returns a shallow copy.
2558
+ * If it is a plain string or empty, wraps it as `{ [activeLocale]: text }`.
2559
+ */
2560
+ toLocaleMap(content, activeLocale) {
2561
+ if (this.isValidMultiLanguageObject(content)) {
2562
+ return { ...content };
2563
+ }
2564
+ const txt = typeof content === 'string' ? content : '';
2565
+ return { [activeLocale]: txt };
2165
2566
  }
2166
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: DefaultModuleAccessControlService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2167
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: DefaultModuleAccessControlService, providedIn: 'root' }); }
2567
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMultiLanguageStringResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2568
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMultiLanguageStringResolverService, providedIn: 'root' }); }
2168
2569
  }
2169
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: DefaultModuleAccessControlService, decorators: [{
2570
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMultiLanguageStringResolverService, decorators: [{
2170
2571
  type: Injectable,
2171
2572
  args: [{ providedIn: 'root' }]
2172
2573
  }] });
2574
+
2575
+ //#region ---- Imports ----
2576
+ //#endregion
2577
+ //#region ---- AXPResolveMultiLanguageStringPipe ----
2578
+ /**
2579
+ * Resolves {@link AXPMultiLanguageString} via {@link AXPMultiLanguageStringResolverService}.
2580
+ * Impure and subscribes to {@link AXPMultiLanguageStringResolverService#currentLocale$} so
2581
+ * OnPush hosts (e.g. grid cells) still refresh when the language changes.
2582
+ *
2583
+ * Optional second argument: explicit locale (e.g. from a host `locale` input). When omitted or null/empty,
2584
+ * the active language is used.
2585
+ *
2586
+ * @example
2587
+ * ```html
2588
+ * {{ value | axpResolveMultiLanguageString }}
2589
+ * {{ value | axpResolveMultiLanguageString: locale() }}
2590
+ * ```
2591
+ */
2592
+ class AXPResolveMultiLanguageStringPipe {
2593
+ constructor() {
2594
+ this.resolver = inject(AXPMultiLanguageStringResolverService);
2595
+ this.cdr = inject(ChangeDetectorRef);
2596
+ this.localeSubscription = this.resolver.currentLocale$.subscribe(() => this.cdr.markForCheck());
2597
+ }
2598
+ transform(value, locale) {
2599
+ const explicitLocale = locale != null && locale !== '' ? locale : undefined;
2600
+ return this.resolver.resolve(value, explicitLocale);
2601
+ }
2602
+ ngOnDestroy() {
2603
+ this.localeSubscription.unsubscribe();
2604
+ }
2605
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPResolveMultiLanguageStringPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2606
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPResolveMultiLanguageStringPipe, isStandalone: true, name: "axpResolveMultiLanguageString", pure: false }); }
2607
+ }
2608
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPResolveMultiLanguageStringPipe, decorators: [{
2609
+ type: Pipe,
2610
+ args: [{
2611
+ name: 'axpResolveMultiLanguageString',
2612
+ standalone: true,
2613
+ pure: false,
2614
+ }]
2615
+ }] });
2616
+
2617
+ //#region ---- Imports ----
2173
2618
  //#endregion
2174
- //#region ---- Injection Token ----
2619
+ //#region ---- Compare & sort ----
2620
+ const DEFAULT_COLLATOR_OPTIONS = { sensitivity: 'base' };
2621
+ /**
2622
+ * Locale-aware comparison of {@link AXPMultiLanguageString} values (plain string, `@scope:key`, or locale map).
2623
+ * Resolves each side with {@link resolveMultiLanguageString} for `locale`, then compares with `String#localeCompare`.
2624
+ */
2625
+ function compareMultiLanguageStrings(a, b, locale, collatorOptions = DEFAULT_COLLATOR_OPTIONS) {
2626
+ const sa = resolveMultiLanguageString(a ?? '', locale);
2627
+ const sb = resolveMultiLanguageString(b ?? '', locale);
2628
+ return sa.localeCompare(sb, locale, collatorOptions);
2629
+ }
2175
2630
  /**
2176
- * Injection token for module access control service.
2177
- * If not provided, DefaultModuleAccessControlService will be used as fallback.
2631
+ * Stable sort copy: orders items by resolved string for `getValue(item)` using the active `locale`.
2178
2632
  */
2179
- const AXP_MODULE_ACCESS_CONTROL_SERVICE = new InjectionToken('AXP_MODULE_ACCESS_CONTROL_SERVICE');
2633
+ function sortByMultiLanguageString(items, getValue, locale, collatorOptions) {
2634
+ return [...items].sort((x, y) => compareMultiLanguageStrings(getValue(x), getValue(y), locale, collatorOptions));
2635
+ }
2636
+ //#endregion
2180
2637
 
2181
2638
  //#region ---- Tag Types ----
2182
2639
  //#endregion
@@ -2329,10 +2786,10 @@ class AXPTagService {
2329
2786
  const uniqueTags = allTags.filter((tag, index, self) => index === self.findIndex((t) => t.title.toLowerCase() === tag.title.toLowerCase()));
2330
2787
  this.cache = uniqueTags;
2331
2788
  }
2332
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPTagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2333
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPTagService, providedIn: 'root' }); }
2789
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2790
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTagService, providedIn: 'root' }); }
2334
2791
  }
2335
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPTagService, decorators: [{
2792
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTagService, decorators: [{
2336
2793
  type: Injectable,
2337
2794
  args: [{
2338
2795
  providedIn: 'root',
@@ -3264,6 +3721,9 @@ function getNestedKeys(obj, prefix = '') {
3264
3721
  return keys;
3265
3722
  }
3266
3723
 
3724
+ //#region ---- Imports ----
3725
+ //#endregion
3726
+
3267
3727
  function applySystemActionDefault(action, type) {
3268
3728
  const systemAction = getSystemActions(type);
3269
3729
  return {
@@ -3295,8 +3755,6 @@ class AXPIconLogoConfig {
3295
3755
 
3296
3756
  var AXPPlatformScope;
3297
3757
  (function (AXPPlatformScope) {
3298
- AXPPlatformScope["Environment"] = "C";
3299
- AXPPlatformScope["Global"] = "G";
3300
3758
  AXPPlatformScope["Platform"] = "P";
3301
3759
  AXPPlatformScope["Tenant"] = "T";
3302
3760
  AXPPlatformScope["User"] = "U";
@@ -3304,8 +3762,6 @@ var AXPPlatformScope;
3304
3762
  ;
3305
3763
  function resolvePlatformScopeKey(name) {
3306
3764
  const scopeMap = {
3307
- environment: AXPPlatformScope.Environment,
3308
- global: AXPPlatformScope.Global,
3309
3765
  platform: AXPPlatformScope.Platform,
3310
3766
  tenant: AXPPlatformScope.Tenant,
3311
3767
  user: AXPPlatformScope.User,
@@ -3314,8 +3770,6 @@ function resolvePlatformScopeKey(name) {
3314
3770
  }
3315
3771
  function resolvePlatformScopeName(scope) {
3316
3772
  const scopeMap = {
3317
- C: 'environment',
3318
- G: 'global',
3319
3773
  P: 'platform',
3320
3774
  T: 'tenant',
3321
3775
  U: 'user',
@@ -3335,7 +3789,7 @@ var AXPExportTemplateToken;
3335
3789
  class AXPCountdownPipe {
3336
3790
  constructor() {
3337
3791
  this.calendarService = inject(AXCalendarService);
3338
- this.countdownSignal = signal(this.setupTimer(), ...(ngDevMode ? [{ debugName: "countdownSignal" }] : []));
3792
+ this.countdownSignal = signal(this.setupTimer(), ...(ngDevMode ? [{ debugName: "countdownSignal" }] : /* istanbul ignore next */ []));
3339
3793
  this.targetDate = 0;
3340
3794
  this.prevValue = 0;
3341
3795
  }
@@ -3364,10 +3818,10 @@ class AXPCountdownPipe {
3364
3818
  updateTargetDate(value) {
3365
3819
  this.targetDate = new Date(value).getTime();
3366
3820
  }
3367
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPCountdownPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3368
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: AXPCountdownPipe, isStandalone: true, name: "countdown", pure: false }); }
3821
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCountdownPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3822
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPCountdownPipe, isStandalone: true, name: "countdown", pure: false }); }
3369
3823
  }
3370
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPCountdownPipe, decorators: [{
3824
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCountdownPipe, decorators: [{
3371
3825
  type: Pipe,
3372
3826
  args: [{
3373
3827
  name: 'countdown',
@@ -3650,45 +4104,45 @@ class AXPDeviceService {
3650
4104
  /**
3651
4105
  * Current screen size (Small, Medium, Large)
3652
4106
  */
3653
- this.screenSize = signal(getScreenSize(), ...(ngDevMode ? [{ debugName: "screenSize" }] : []));
4107
+ this.screenSize = signal(getScreenSize(), ...(ngDevMode ? [{ debugName: "screenSize" }] : /* istanbul ignore next */ []));
3654
4108
  /**
3655
4109
  * Current device type (Mobile, Tablet, Desktop)
3656
4110
  */
3657
- this.deviceType = signal(getDeviceType(), ...(ngDevMode ? [{ debugName: "deviceType" }] : []));
4111
+ this.deviceType = signal(getDeviceType(), ...(ngDevMode ? [{ debugName: "deviceType" }] : /* istanbul ignore next */ []));
3658
4112
  /**
3659
4113
  * Whether the device supports touch input
3660
4114
  */
3661
- this.isTouchDevice = signal(isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchDevice" }] : []));
4115
+ this.isTouchDevice = signal(isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchDevice" }] : /* istanbul ignore next */ []));
3662
4116
  //#endregion
3663
4117
  //#region ---- Computed Signals ----
3664
4118
  /**
3665
4119
  * Whether the screen size is Small
3666
4120
  */
3667
- this.isSmall = computed(() => this.screenSize() === AXPScreenSize.Small, ...(ngDevMode ? [{ debugName: "isSmall" }] : []));
4121
+ this.isSmall = computed(() => this.screenSize() === AXPScreenSize.Small, ...(ngDevMode ? [{ debugName: "isSmall" }] : /* istanbul ignore next */ []));
3668
4122
  /**
3669
4123
  * Whether the screen size is Medium
3670
4124
  */
3671
- this.isMedium = computed(() => this.screenSize() === AXPScreenSize.Medium, ...(ngDevMode ? [{ debugName: "isMedium" }] : []));
4125
+ this.isMedium = computed(() => this.screenSize() === AXPScreenSize.Medium, ...(ngDevMode ? [{ debugName: "isMedium" }] : /* istanbul ignore next */ []));
3672
4126
  /**
3673
4127
  * Whether the screen size is Large
3674
4128
  */
3675
- this.isLarge = computed(() => this.screenSize() === AXPScreenSize.Large, ...(ngDevMode ? [{ debugName: "isLarge" }] : []));
4129
+ this.isLarge = computed(() => this.screenSize() === AXPScreenSize.Large, ...(ngDevMode ? [{ debugName: "isLarge" }] : /* istanbul ignore next */ []));
3676
4130
  /**
3677
4131
  * Whether the device is Mobile
3678
4132
  */
3679
- this.isMobileDevice = computed(() => this.deviceType() === AXPDeviceType.Mobile, ...(ngDevMode ? [{ debugName: "isMobileDevice" }] : []));
4133
+ this.isMobileDevice = computed(() => this.deviceType() === AXPDeviceType.Mobile, ...(ngDevMode ? [{ debugName: "isMobileDevice" }] : /* istanbul ignore next */ []));
3680
4134
  /**
3681
4135
  * Whether the device is Tablet
3682
4136
  */
3683
- this.isTabletDevice = computed(() => this.deviceType() === AXPDeviceType.Tablet, ...(ngDevMode ? [{ debugName: "isTabletDevice" }] : []));
4137
+ this.isTabletDevice = computed(() => this.deviceType() === AXPDeviceType.Tablet, ...(ngDevMode ? [{ debugName: "isTabletDevice" }] : /* istanbul ignore next */ []));
3684
4138
  /**
3685
4139
  * Whether the device is Desktop
3686
4140
  */
3687
- this.isDesktopDevice = computed(() => this.deviceType() === AXPDeviceType.Desktop, ...(ngDevMode ? [{ debugName: "isDesktopDevice" }] : []));
4141
+ this.isDesktopDevice = computed(() => this.deviceType() === AXPDeviceType.Desktop, ...(ngDevMode ? [{ debugName: "isDesktopDevice" }] : /* istanbul ignore next */ []));
3688
4142
  /**
3689
4143
  * Whether the device supports touch (alias for isTouchDevice)
3690
4144
  */
3691
- this.isTouchScreen = computed(() => this.isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchScreen" }] : []));
4145
+ this.isTouchScreen = computed(() => this.isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchScreen" }] : /* istanbul ignore next */ []));
3692
4146
  //#endregion
3693
4147
  //#region ---- Private Properties ----
3694
4148
  this._resizeListener = null;
@@ -3754,10 +4208,10 @@ class AXPDeviceService {
3754
4208
  destroy() {
3755
4209
  this._removeResizeListener();
3756
4210
  }
3757
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDeviceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3758
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDeviceService, providedIn: 'root' }); }
4211
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDeviceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4212
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDeviceService, providedIn: 'root' }); }
3759
4213
  }
3760
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPDeviceService, decorators: [{
4214
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDeviceService, decorators: [{
3761
4215
  type: Injectable,
3762
4216
  args: [{
3763
4217
  providedIn: 'root',
@@ -3861,21 +4315,87 @@ class AXHighlightService {
3861
4315
  resultHTML += '</span>';
3862
4316
  return resultHTML;
3863
4317
  }
3864
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXHighlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3865
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXHighlightService, providedIn: 'root' }); }
4318
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXHighlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4319
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXHighlightService, providedIn: 'root' }); }
3866
4320
  }
3867
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXHighlightService, decorators: [{
4321
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXHighlightService, decorators: [{
3868
4322
  type: Injectable,
3869
4323
  args: [{
3870
4324
  providedIn: 'root',
3871
4325
  }]
3872
4326
  }], ctorParameters: () => [] });
3873
4327
 
4328
+ /**
4329
+ * Creates a provider instance within an injection context.
4330
+ * Handles dynamic import, injector resolution, and provider instantiation.
4331
+ *
4332
+ * @param loader - Function that returns a promise resolving to the provider class
4333
+ * @returns Promise that resolves to the provider instance
4334
+ *
4335
+ * @example
4336
+ * ```typescript
4337
+ * useFactory: () => createProviderWithInjectionContext(() =>
4338
+ * import('./settings.provider').then(m => m.AXMSettingProvider)
4339
+ * )
4340
+ * ```
4341
+ */
4342
+ async function createProviderWithInjectionContext(loader) {
4343
+ const injector = inject(Injector);
4344
+ const ProviderClass = await loader();
4345
+ return runInInjectionContext(injector, () => new ProviderClass());
4346
+ }
4347
+ /**
4348
+ * Creates a provider configuration for lazy-loaded providers with injection context.
4349
+ * Simplifies provider registration in NgModule providers array.
4350
+ *
4351
+ * @param token - The injection token to provide
4352
+ * @param loader - Function that returns a promise resolving to the provider class
4353
+ * @param multi - Optional. Whether the provider is a multi-provider (array of values). Defaults to `true`. Pass `false` for a single provider.
4354
+ * @returns Provider configuration object
4355
+ *
4356
+ * @example
4357
+ * ```typescript
4358
+ * // Multi-provider (default)
4359
+ * provideLazyProvider(
4360
+ * AXP_DATASOURCE_DEFINITION_PROVIDER,
4361
+ * () => import('./datasource.provider').then(m => m.AXMDataSourceProvider)
4362
+ * )
4363
+ *
4364
+ * // Single provider
4365
+ * provideLazyProvider(
4366
+ * SOME_TOKEN,
4367
+ * () => import('./my.provider').then(m => m.MyProvider),
4368
+ * false
4369
+ * )
4370
+ * ```
4371
+ */
4372
+ function provideLazyProvider(token, loader, multi = true) {
4373
+ return {
4374
+ provide: token,
4375
+ useFactory: () => createProviderWithInjectionContext(loader),
4376
+ multi,
4377
+ };
4378
+ }
4379
+
3874
4380
  function extractTextFromHtml(value) {
3875
4381
  const div = document.createElement('div');
3876
4382
  div.innerHTML = value;
3877
4383
  return div.textContent || div.innerText || '';
3878
4384
  }
4385
+ /**
4386
+ * True when the string likely contains HTML markup (e.g. `<p>`, `<ul>`), as opposed to plain text.
4387
+ * Used to choose innerHTML vs text interpolation for multilingual fields.
4388
+ */
4389
+ function containsHtmlMarkup(value) {
4390
+ if (value == null) {
4391
+ return false;
4392
+ }
4393
+ const t = value.trim();
4394
+ if (!t) {
4395
+ return false;
4396
+ }
4397
+ return /<\/?[a-z][\s\S]*?>/i.test(t);
4398
+ }
3879
4399
  /**
3880
4400
  * Generate kebab-case group name from title
3881
4401
  */
@@ -3893,5 +4413,5 @@ function generateKebabCase(title) {
3893
4413
  * Generated bundle index. Do not edit.
3894
4414
  */
3895
4415
 
3896
- export { AXFullscreenDirective, AXHighlightService, AXPActivityLogProvider, AXPActivityLogService, AXPAppStartUpProvider, AXPAppStartUpService, AXPBroadcastEventService, AXPColorPaletteProvider, AXPColorPaletteService, AXPComponentLogoConfig, AXPContentCheckerDirective, AXPContextChangeEvent, AXPContextStore, AXPCountdownPipe, AXPDataGenerator, AXPDataSourceDefinitionProviderService, AXPDblClickDirective, AXPDefaultColorPalettesProvider, AXPDeviceService, AXPDeviceType, AXPDistributedEventListenerService, AXPElementDataDirective, AXPExportTemplateToken, AXPExpressionEvaluatorScopeProviderContext, AXPExpressionEvaluatorScopeProviderService, AXPExpressionEvaluatorService, AXPFeatureDefinitionProviderContext, AXPGridLayoutDirective, AXPHookService, AXPIconLogoConfig, AXPImageUrlLogoConfig, AXPModuleManifestModule, AXPModuleManifestRegistry, AXPModuleProviderRegistry, AXPPlatformScope, AXPScreenSize, AXPSystemActionType, AXPSystemActions, AXPTagProvider, AXPTagService, AXP_ACTIVITY_LOG_PROVIDER, AXP_COLOR_PALETTE_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXP_EDITION_SERVICE, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER, AXP_MODULE_ACCESS_CONTROL_SERVICE, AXP_MODULE_MANIFEST_PROVIDER, AXP_MODULE_PROVIDER_LOADER, AXP_SESSION_SERVICE, AXP_TAG_PROVIDER, DefaultModuleAccessControlService, applyFilterArray, applyPagination, applyQueryArray, applySortArray, applySystemActionDefault, cleanDeep, extractNestedFieldsWildcard, extractTextFromHtml, extractValue, generateKebabCase, getActionButton, getChangedPaths, getDetailedChanges, getEnumValues, getNestedKeys, getSmart, getSystemActions, objectKeyValueTransforms, resolveActionLook, resolvePlatformScopeKey, resolvePlatformScopeName, setSmart };
4416
+ export { AXHighlightService, AXPActivityLogProvider, AXPActivityLogService, AXPAppStartUpProvider, AXPAppStartUpService, AXPBroadcastEventService, AXPColorPaletteProvider, AXPColorPaletteService, AXPColumnWidthService, AXPComponentLogoConfig, AXPComponentSlot, AXPComponentSlotDirective, AXPComponentSlotModule, AXPComponentSlotRegistryService, AXPContentCheckerDirective, AXPContextChangeEvent, AXPContextStore, AXPCountdownPipe, AXPDataGenerator, AXPDataSourceDefinitionProviderService, AXPDblClickDirective, AXPDefaultColorPalettesProvider, AXPDeviceService, AXPDeviceType, AXPDistributedEventListenerService, AXPElementDataDirective, AXPExportTemplateToken, AXPExpressionEvaluatorScopeProviderContext, AXPExpressionEvaluatorScopeProviderService, AXPExpressionEvaluatorService, AXPFeatureDefinitionProviderContext, AXPGridLayoutDirective, AXPHookService, AXPIconLogoConfig, AXPImageUrlLogoConfig, AXPModuleManifestModule, AXPModuleManifestRegistry, AXPModuleManifestsDataSourceDefinition, AXPMultiLanguageStringResolverService, AXPPlatformScope, AXPResolveMultiLanguageStringPipe, AXPScreenSize, AXPSystemActionType, AXPSystemActions, AXPTagProvider, AXPTagService, AXP_ACTIVITY_LOG_PROVIDER, AXP_COLOR_PALETTE_PROVIDER, AXP_COLUMN_WIDTH_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER, AXP_SESSION_SERVICE, AXP_TAG_PROVIDER, MODULE_MANIFESTS_DATASOURCE_NAME, applyFilterArray, applyPagination, applyQueryArray, applySortArray, applySystemActionDefault, cleanDeep, compareMultiLanguageStrings, containsHtmlMarkup, createMultiLanguageString, createProviderWithInjectionContext, defaultColumnWidthProvider, extractNestedFieldsWildcard, extractTextFromHtml, extractValue, generateKebabCase, getActionButton, getChangedPaths, getDetailedChanges, getEnumValues, getNestedKeys, getSmart, getSystemActions, isEffectivelyEmptyLocalizedValue, isValidMultiLanguageObject, objectKeyValueTransforms, provideLazyProvider, resolveActionLook, resolveMultiLanguageString, resolvePlatformScopeKey, resolvePlatformScopeName, setSmart, sortByMultiLanguageString };
3897
4417
  //# sourceMappingURL=acorex-platform-core.mjs.map