@acorex/platform 0.0.0-ACOREX

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 (116) hide show
  1. package/README.md +7 -0
  2. package/auth/README.md +3 -0
  3. package/common/README.md +3 -0
  4. package/core/README.md +4 -0
  5. package/fesm2022/acorex-platform-auth.mjs +1362 -0
  6. package/fesm2022/acorex-platform-auth.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-common-common-settings.provider-G9XcXXOG.mjs +127 -0
  8. package/fesm2022/acorex-platform-common-common-settings.provider-G9XcXXOG.mjs.map +1 -0
  9. package/fesm2022/acorex-platform-common.mjs +4601 -0
  10. package/fesm2022/acorex-platform-common.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-core.mjs +4374 -0
  12. package/fesm2022/acorex-platform-core.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-domain.mjs +3234 -0
  14. package/fesm2022/acorex-platform-domain.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-layout-builder.mjs +2847 -0
  16. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs +121 -0
  18. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +1 -0
  19. package/fesm2022/acorex-platform-layout-components.mjs +8583 -0
  20. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -0
  21. package/fesm2022/acorex-platform-layout-designer.mjs +2474 -0
  22. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -0
  23. package/fesm2022/acorex-platform-layout-entity.mjs +19150 -0
  24. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-layout-views.mjs +1468 -0
  26. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-layout-widget-core.mjs +2950 -0
  28. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -0
  29. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs +72 -0
  30. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs.map +1 -0
  31. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-9uCkMxcc.mjs +158 -0
  32. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-9uCkMxcc.mjs.map +1 -0
  33. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs +29 -0
  34. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +1 -0
  35. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs +172 -0
  36. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs.map +1 -0
  37. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGQqY5Mw.mjs +111 -0
  38. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGQqY5Mw.mjs.map +1 -0
  39. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DmzNTYiS.mjs +274 -0
  40. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DmzNTYiS.mjs.map +1 -0
  41. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-BNG_588B.mjs +64 -0
  42. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-BNG_588B.mjs.map +1 -0
  43. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs +34 -0
  44. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs.map +1 -0
  45. package/fesm2022/acorex-platform-layout-widgets.mjs +29791 -0
  46. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -0
  47. package/fesm2022/acorex-platform-native.mjs +155 -0
  48. package/fesm2022/acorex-platform-native.mjs.map +1 -0
  49. package/fesm2022/acorex-platform-runtime-catalog-command-definition.mjs +20 -0
  50. package/fesm2022/acorex-platform-runtime-catalog-command-definition.mjs.map +1 -0
  51. package/fesm2022/acorex-platform-runtime-catalog-query-definition.mjs +20 -0
  52. package/fesm2022/acorex-platform-runtime-catalog-query-definition.mjs.map +1 -0
  53. package/fesm2022/acorex-platform-runtime.mjs +899 -0
  54. package/fesm2022/acorex-platform-runtime.mjs.map +1 -0
  55. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cvvr4HnL.mjs +160 -0
  56. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cvvr4HnL.mjs.map +1 -0
  57. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-TYoLN1Jq.mjs +120 -0
  58. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-TYoLN1Jq.mjs.map +1 -0
  59. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-C2z5Lq9y.mjs +237 -0
  60. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-C2z5Lq9y.mjs.map +1 -0
  61. package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs +31 -0
  62. package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs.map +1 -0
  63. package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs +25 -0
  64. package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs.map +1 -0
  65. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs +19 -0
  66. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs.map +1 -0
  67. package/fesm2022/acorex-platform-themes-default.mjs +2589 -0
  68. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -0
  69. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs +55 -0
  70. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs.map +1 -0
  71. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs +57 -0
  72. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs.map +1 -0
  73. package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs +168 -0
  74. package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs.map +1 -0
  75. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-CHfrTtol.mjs +65 -0
  76. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-CHfrTtol.mjs.map +1 -0
  77. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BSmvnUVq.mjs +64 -0
  78. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BSmvnUVq.mjs.map +1 -0
  79. package/fesm2022/acorex-platform-themes-shared.mjs +2125 -0
  80. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -0
  81. package/fesm2022/acorex-platform-workflow.mjs +2501 -0
  82. package/fesm2022/acorex-platform-workflow.mjs.map +1 -0
  83. package/fesm2022/acorex-platform.mjs +6 -0
  84. package/fesm2022/acorex-platform.mjs.map +1 -0
  85. package/layout/builder/README.md +1578 -0
  86. package/layout/components/README.md +3 -0
  87. package/layout/designer/README.md +4 -0
  88. package/layout/entity/README.md +4 -0
  89. package/layout/views/README.md +3 -0
  90. package/layout/widget-core/README.md +4 -0
  91. package/layout/widgets/README.md +3 -0
  92. package/native/README.md +4 -0
  93. package/package.json +103 -0
  94. package/runtime/README.md +3 -0
  95. package/themes/default/README.md +3 -0
  96. package/themes/shared/README.md +3 -0
  97. package/types/acorex-platform-auth.d.ts +680 -0
  98. package/types/acorex-platform-common.d.ts +2926 -0
  99. package/types/acorex-platform-core.d.ts +2896 -0
  100. package/types/acorex-platform-domain.d.ts +2353 -0
  101. package/types/acorex-platform-layout-builder.d.ts +926 -0
  102. package/types/acorex-platform-layout-components.d.ts +2903 -0
  103. package/types/acorex-platform-layout-designer.d.ts +422 -0
  104. package/types/acorex-platform-layout-entity.d.ts +3189 -0
  105. package/types/acorex-platform-layout-views.d.ts +667 -0
  106. package/types/acorex-platform-layout-widget-core.d.ts +1086 -0
  107. package/types/acorex-platform-layout-widgets.d.ts +5478 -0
  108. package/types/acorex-platform-native.d.ts +28 -0
  109. package/types/acorex-platform-runtime-catalog-command-definition.d.ts +137 -0
  110. package/types/acorex-platform-runtime-catalog-query-definition.d.ts +125 -0
  111. package/types/acorex-platform-runtime.d.ts +470 -0
  112. package/types/acorex-platform-themes-default.d.ts +573 -0
  113. package/types/acorex-platform-themes-shared.d.ts +170 -0
  114. package/types/acorex-platform-workflow.d.ts +1806 -0
  115. package/types/acorex-platform.d.ts +2 -0
  116. package/workflow/README.md +4 -0
@@ -0,0 +1,4374 @@
1
+ import * as i0 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';
4
+ import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
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';
11
+ import { AXCalendarService } from '@acorex/core/date-time';
12
+
13
+ const AXP_ACTIVITY_LOG_PROVIDER = new InjectionToken('AXP_ACTIVITY_LOGS_PROVIDER');
14
+ class AXPActivityLogService {
15
+ constructor() {
16
+ this.providers = inject(AXP_ACTIVITY_LOG_PROVIDER, { optional: true });
17
+ }
18
+ async getHistory(refId, refType, options) {
19
+ return (await Promise.all(this.providers?.map((p) => p.getHistory(refId, refType, options)) ?? [])).flat();
20
+ }
21
+ async getHistoryByIds(refId, refType, ids) {
22
+ return (await Promise.all(this.providers?.map((p) => p.getHistoryByIds(refId, refType, ids)) ?? [])).flat();
23
+ }
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' }); }
26
+ }
27
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityLogService, decorators: [{
28
+ type: Injectable,
29
+ args: [{ providedIn: 'root' }]
30
+ }] });
31
+
32
+ class AXPActivityLogProvider {
33
+ }
34
+
35
+ //#region ---- Color Palette Provider ----
36
+ /**
37
+ * Abstract class for color palette providers
38
+ * Implement this to provide palettes from different sources (system, app, module, etc.)
39
+ */
40
+ class AXPColorPaletteProvider {
41
+ }
42
+ /**
43
+ * Injection token for color palette providers
44
+ * Use this to register multiple palette providers
45
+ */
46
+ const AXP_COLOR_PALETTE_PROVIDER = new InjectionToken('AXP_COLOR_PALETTE_PROVIDER');
47
+ //#endregion
48
+
49
+ //#region ---- Color Palette Service ----
50
+ /**
51
+ * Service for managing color palettes from multiple providers
52
+ * Aggregates palettes from all registered providers
53
+ */
54
+ class AXPColorPaletteService {
55
+ constructor() {
56
+ //#region ---- Dependencies ----
57
+ this.providers = inject(AXP_COLOR_PALETTE_PROVIDER, { optional: true }) ?? [];
58
+ //#endregion
59
+ //#region ---- State ----
60
+ this.cache = null;
61
+ }
62
+ //#endregion
63
+ //#region ---- Public API ----
64
+ /**
65
+ * Get all palettes from all providers
66
+ * @param options Filter options
67
+ * @returns Promise of palettes
68
+ */
69
+ async getPalettes(options) {
70
+ if (!this.cache) {
71
+ await this.loadPalettes();
72
+ }
73
+ let palettes = this.cache;
74
+ // Apply category filter
75
+ if (options?.category) {
76
+ palettes = palettes.filter((palette) => palette.category === options.category);
77
+ }
78
+ // Apply search filter
79
+ if (options?.search) {
80
+ const searchLower = options.search.toLowerCase();
81
+ palettes = palettes.filter((palette) => palette.name.toLowerCase().includes(searchLower) ||
82
+ palette.title.toLowerCase().includes(searchLower) ||
83
+ palette.description?.toLowerCase().includes(searchLower));
84
+ }
85
+ return palettes;
86
+ }
87
+ /**
88
+ * Get a palette by name
89
+ * @param name The unique name of the palette
90
+ * @returns Promise of palette or undefined if not found
91
+ */
92
+ async getPalette(name) {
93
+ if (!this.cache) {
94
+ await this.loadPalettes();
95
+ }
96
+ return this.cache.find((p) => p.name === name);
97
+ }
98
+ /**
99
+ * Get palettes by category
100
+ * @param category The category to filter by
101
+ * @returns Promise of palettes in the specified category
102
+ */
103
+ async getByCategory(category) {
104
+ return this.getPalettes({ category });
105
+ }
106
+ /**
107
+ * Check if a palette exists
108
+ * @param name The unique name of the palette
109
+ * @returns Promise of true if the palette exists
110
+ */
111
+ async has(name) {
112
+ const palette = await this.getPalette(name);
113
+ return palette !== undefined;
114
+ }
115
+ /**
116
+ * Reload palettes from all providers
117
+ */
118
+ async reload() {
119
+ this.cache = null;
120
+ await this.loadPalettes();
121
+ }
122
+ /**
123
+ * Get the default palette (material-design) or fallback colors
124
+ * @returns Promise of default palette, never returns undefined
125
+ */
126
+ async getDefaultPalette() {
127
+ const defaultPalette = await this.getPalette('material-design');
128
+ if (defaultPalette) {
129
+ return defaultPalette;
130
+ }
131
+ // Fallback to hardcoded material design colors if provider fails
132
+ return {
133
+ name: 'material-design',
134
+ title: 'Material Design',
135
+ category: 'material',
136
+ description: 'Google Material Design color palette',
137
+ colors: [
138
+ '#F44336', // Red
139
+ '#E91E63', // Pink
140
+ '#9C27B0', // Purple
141
+ '#673AB7', // Deep Purple
142
+ '#3F51B5', // Indigo
143
+ '#2196F3', // Blue
144
+ '#03A9F4', // Light Blue
145
+ '#00BCD4', // Cyan
146
+ '#009688', // Teal
147
+ '#4CAF50', // Green
148
+ '#8BC34A', // Light Green
149
+ '#CDDC39', // Lime
150
+ '#FFEB3B', // Yellow
151
+ '#FFC107', // Amber
152
+ '#FF9800', // Orange
153
+ '#FF5722', // Deep Orange
154
+ ],
155
+ };
156
+ }
157
+ //#endregion
158
+ //#region ---- Private Methods ----
159
+ /**
160
+ * Load palettes from all providers
161
+ */
162
+ async loadPalettes() {
163
+ const allPalettes = [];
164
+ for (const provider of this.providers) {
165
+ try {
166
+ const palettes = await provider.provide();
167
+ allPalettes.push(...palettes);
168
+ }
169
+ catch (error) {
170
+ console.error(`Error loading palettes from provider ${provider.name}:`, error);
171
+ }
172
+ }
173
+ // Remove duplicates based on name
174
+ const uniquePalettes = allPalettes.filter((palette, index, self) => index === self.findIndex((p) => p.name === palette.name));
175
+ this.cache = uniquePalettes;
176
+ }
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' }); }
179
+ }
180
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColorPaletteService, decorators: [{
181
+ type: Injectable,
182
+ args: [{
183
+ providedIn: 'root',
184
+ }]
185
+ }] });
186
+
187
+ //#region ---- Color Palette Types ----
188
+ //#endregion
189
+
190
+ //#region ---- Default System Palettes Provider ----
191
+ /**
192
+ * Default system color palette provider
193
+ * Provides built-in color palettes
194
+ */
195
+ class AXPDefaultColorPalettesProvider extends AXPColorPaletteProvider {
196
+ constructor() {
197
+ super(...arguments);
198
+ this.name = 'system';
199
+ }
200
+ async provide() {
201
+ return [
202
+ {
203
+ name: 'material-design',
204
+ title: 'Material Design',
205
+ category: 'material',
206
+ description: 'Google Material Design color palette',
207
+ colors: [
208
+ '#F44336', // Red
209
+ '#E91E63', // Pink
210
+ '#9C27B0', // Purple
211
+ '#673AB7', // Deep Purple
212
+ '#3F51B5', // Indigo
213
+ '#2196F3', // Blue
214
+ '#03A9F4', // Light Blue
215
+ '#00BCD4', // Cyan
216
+ '#009688', // Teal
217
+ '#4CAF50', // Green
218
+ '#8BC34A', // Light Green
219
+ '#CDDC39', // Lime
220
+ '#FFEB3B', // Yellow
221
+ '#FFC107', // Amber
222
+ '#FF9800', // Orange
223
+ '#FF5722', // Deep Orange
224
+ ],
225
+ },
226
+ {
227
+ name: 'pastel',
228
+ title: 'Pastel Colors',
229
+ category: 'theme',
230
+ description: 'Soft pastel color palette',
231
+ colors: [
232
+ '#FFB3BA', // Light Pink
233
+ '#FFDFBA', // Light Peach
234
+ '#FFFFBA', // Light Yellow
235
+ '#BAFFC9', // Light Green
236
+ '#BAE1FF', // Light Blue
237
+ '#E0BBE4', // Light Purple
238
+ '#FFDFD3', // Light Coral
239
+ '#D4F1F4', // Light Cyan
240
+ ],
241
+ },
242
+ {
243
+ name: 'vibrant',
244
+ title: 'Vibrant Colors',
245
+ category: 'theme',
246
+ description: 'Bold and vibrant color palette',
247
+ colors: [
248
+ '#FF6B6B', // Vibrant Red
249
+ '#4ECDC4', // Vibrant Teal
250
+ '#45B7D1', // Vibrant Blue
251
+ '#FFA07A', // Vibrant Salmon
252
+ '#98D8C8', // Vibrant Mint
253
+ '#F7DC6F', // Vibrant Yellow
254
+ '#BB8FCE', // Vibrant Purple
255
+ '#85C1E2', // Vibrant Sky Blue
256
+ ],
257
+ },
258
+ {
259
+ name: 'earth-tones',
260
+ title: 'Earth Tones',
261
+ category: 'theme',
262
+ description: 'Natural earth tone color palette',
263
+ colors: [
264
+ '#8B4513', // Saddle Brown
265
+ '#A0522D', // Sienna
266
+ '#D2691E', // Chocolate
267
+ '#CD853F', // Peru
268
+ '#DEB887', // Burlywood
269
+ '#F5DEB3', // Wheat
270
+ '#556B2F', // Dark Olive Green
271
+ '#6B8E23', // Olive Drab
272
+ ],
273
+ },
274
+ {
275
+ name: 'monochrome',
276
+ title: 'Monochrome',
277
+ category: 'theme',
278
+ description: 'Grayscale color palette',
279
+ colors: [
280
+ '#000000', // Black
281
+ '#262626', // Very Dark Gray
282
+ '#404040', // Dark Gray
283
+ '#595959', // Medium Dark Gray
284
+ '#737373', // Medium Gray
285
+ '#8C8C8C', // Light Medium Gray
286
+ '#A6A6A6', // Light Gray
287
+ '#BFBFBF', // Very Light Gray
288
+ '#D9D9D9', // Lighter Gray
289
+ '#F2F2F2', // Almost White
290
+ '#FFFFFF', // White
291
+ ],
292
+ },
293
+ ];
294
+ }
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 }); }
297
+ }
298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultColorPalettesProvider, decorators: [{
299
+ type: Injectable
300
+ }] });
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
+
530
+ function extractNestedFieldsWildcard(obj, basePath, fields) {
531
+ const result = {};
532
+ if (fields.length === 1 && fields[0] === '*') {
533
+ const fullObj = get(obj, basePath);
534
+ return isPlainObject(fullObj) ? fullObj : {};
535
+ }
536
+ for (const field of fields) {
537
+ const fullPath = basePath ? `${basePath}.${field}` : field;
538
+ const value = get(obj, fullPath);
539
+ set(result, field, value);
540
+ }
541
+ return result;
542
+ }
543
+ function setSmart(obj, smartPath, value) {
544
+ const pathParts = smartPath.split('.');
545
+ const lastPart = pathParts[pathParts.length - 1];
546
+ const fieldMatch = lastPart.match(/^\{(.+)\}$/);
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
+ }
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
+ }
583
+ return obj;
584
+ }
585
+ const fields = fieldMatch[1].split(',').map((f) => f.trim());
586
+ const basePath = pathParts.slice(0, -1).join('.');
587
+ const [arrayKey, ...restPath] = basePath.split('.');
588
+ // Make sure the array exists
589
+ if (!obj[arrayKey])
590
+ obj[arrayKey] = [];
591
+ // 🟡 Case A: value is array (normal set)
592
+ if (isArray(value)) {
593
+ for (let i = 0; i < value.length; i++) {
594
+ const item = value[i];
595
+ const targetItem = obj[arrayKey][i] ?? {};
596
+ const nested = {};
597
+ if (restPath.length > 0) {
598
+ const picked = extractNestedFieldsWildcard(item, restPath.join('.'), fields);
599
+ set(nested, restPath.join('.'), picked);
600
+ }
601
+ else {
602
+ const picked = extractNestedFieldsWildcard(item, '', fields);
603
+ Object.assign(nested, picked);
604
+ }
605
+ obj[arrayKey][i] = merge({}, targetItem, nested);
606
+ }
607
+ }
608
+ // 🟢 Case B: value is a single value → broadcast
609
+ else {
610
+ for (let i = 0; i < obj[arrayKey].length; i++) {
611
+ const targetItem = obj[arrayKey][i] ?? {};
612
+ const nested = {};
613
+ if (restPath.length > 0) {
614
+ for (const field of fields) {
615
+ set(nested, `${restPath.join('.')}.${field}`, value);
616
+ }
617
+ }
618
+ else {
619
+ for (const field of fields) {
620
+ set(nested, field, value);
621
+ }
622
+ }
623
+ obj[arrayKey][i] = merge({}, targetItem, nested);
624
+ }
625
+ }
626
+ return obj;
627
+ }
628
+ function extractFieldsFromPath(obj, basePath, fields) {
629
+ if (fields.length === 1 && fields[0] === '*') {
630
+ const fullObj = basePath ? get(obj, basePath) : obj;
631
+ return isPlainObject(fullObj) ? fullObj : {};
632
+ }
633
+ const result = {};
634
+ for (const field of fields) {
635
+ const fullPath = basePath ? `${basePath}.${field}` : field;
636
+ const val = get(obj, fullPath);
637
+ if (val !== undefined) {
638
+ result[field] = val;
639
+ }
640
+ }
641
+ return result;
642
+ }
643
+ function getSmart(obj, smartPath) {
644
+ const pathParts = smartPath.split('.');
645
+ const lastPart = pathParts[pathParts.length - 1];
646
+ const fieldMatch = lastPart.match(/^\{(.+)\}$/);
647
+ // Simple get (no fields)
648
+ if (!fieldMatch) {
649
+ return get(obj, smartPath);
650
+ }
651
+ const fields = fieldMatch[1].split(',').map((f) => f.trim());
652
+ const basePath = pathParts.slice(0, -1).join('.');
653
+ const items = get(obj, basePath);
654
+ if (!isArray(items))
655
+ return [];
656
+ const nestedPath = basePath.includes('.') ? basePath.split('.').slice(1).join('.') : '';
657
+ return items.map((item) => {
658
+ return extractFieldsFromPath(item, nestedPath, fields);
659
+ });
660
+ }
661
+ function extractValue(value, key = 'id') {
662
+ if (isNil(value)) {
663
+ return null;
664
+ }
665
+ return isObjectLike(value) ? get(value, key) : value;
666
+ }
667
+ function cleanDeep(obj) {
668
+ return transform(obj, (result, value, key) => {
669
+ if (isObjectLike(value)) {
670
+ const cleaned = cleanDeep(value);
671
+ if (!isEmpty(cleaned)) {
672
+ result[key] = cleaned;
673
+ }
674
+ }
675
+ else if (!isNil(value) && // not null or undefined
676
+ !(typeof value === 'string' && value.trim() === '') && // not empty string
677
+ !(Array.isArray(value) && value.length === 0) // not empty array
678
+ ) {
679
+ result[key] = value;
680
+ }
681
+ });
682
+ }
683
+ function getDeepChanges(obj1, obj2) {
684
+ const changes = [];
685
+ function walk(o1, o2, currentPath = []) {
686
+ // If both values are deeply equal, skip
687
+ if (isEqual(o1, o2))
688
+ return;
689
+ const isObj1Nil = o1 === null || o1 === undefined;
690
+ const isObj2Nil = o2 === null || o2 === undefined;
691
+ // If obj1 is null/undefined and obj2 is not, treat entire obj2 as added
692
+ if (isObj1Nil && !isObj2Nil) {
693
+ if (isPlainObject(o2)) {
694
+ for (const key of Object.keys(o2)) {
695
+ walk(undefined, o2[key], [...currentPath, key]);
696
+ }
697
+ }
698
+ else if (Array.isArray(o2)) {
699
+ changes.push({
700
+ path: currentPath.join('.'),
701
+ oldValue: undefined,
702
+ newValue: o2,
703
+ arrayDiff: {
704
+ added: o2,
705
+ removed: [],
706
+ },
707
+ });
708
+ }
709
+ else {
710
+ changes.push({
711
+ path: currentPath.join('.'),
712
+ oldValue: undefined,
713
+ newValue: o2,
714
+ });
715
+ }
716
+ return;
717
+ }
718
+ // If obj2 is null/undefined and obj1 is not, treat entire obj1 as removed
719
+ if (!isObj1Nil && isObj2Nil) {
720
+ if (isPlainObject(o1)) {
721
+ for (const key of Object.keys(o1)) {
722
+ walk(o1[key], undefined, [...currentPath, key]);
723
+ }
724
+ }
725
+ else if (Array.isArray(o1)) {
726
+ changes.push({
727
+ path: currentPath.join('.'),
728
+ oldValue: o1,
729
+ newValue: undefined,
730
+ arrayDiff: {
731
+ added: [],
732
+ removed: o1,
733
+ },
734
+ });
735
+ }
736
+ else {
737
+ changes.push({
738
+ path: currentPath.join('.'),
739
+ oldValue: o1,
740
+ newValue: undefined,
741
+ });
742
+ }
743
+ return;
744
+ }
745
+ // If both are arrays, compare items
746
+ if (Array.isArray(o1) && Array.isArray(o2)) {
747
+ if (!isEqual(o1, o2)) {
748
+ const added = differenceWith(o2, o1, isEqual);
749
+ const removed = differenceWith(o1, o2, isEqual);
750
+ changes.push({
751
+ path: currentPath.join('.'),
752
+ oldValue: o1,
753
+ newValue: o2,
754
+ arrayDiff: {
755
+ added,
756
+ removed,
757
+ },
758
+ });
759
+ }
760
+ return;
761
+ }
762
+ // If both are plain objects, walk each key
763
+ if (isPlainObject(o1) && isPlainObject(o2)) {
764
+ const allKeys = union(Object.keys(o1), Object.keys(o2));
765
+ for (const key of allKeys) {
766
+ walk(o1[key], o2[key], [...currentPath, key]);
767
+ }
768
+ return;
769
+ }
770
+ // Primitive values or mismatched types
771
+ changes.push({
772
+ path: currentPath.join('.'),
773
+ oldValue: o1,
774
+ newValue: o2,
775
+ });
776
+ }
777
+ walk(obj1, obj2);
778
+ return changes;
779
+ }
780
+ // Method 1: Returns only changed paths
781
+ function getChangedPaths(obj1, obj2) {
782
+ return getDeepChanges(obj1, obj2).map((change) => change.path);
783
+ }
784
+ // Method 2: Returns full change entries
785
+ function getDetailedChanges(obj1, obj2) {
786
+ return getDeepChanges(obj1, obj2);
787
+ }
788
+ function getEnumValues(enumType) {
789
+ return Object.entries(enumType).map(([key, value]) => ({ id: value, title: key }));
790
+ }
791
+
792
+ class AXPContextChangeEvent {
793
+ }
794
+ //#endregion
795
+ //#region ---- Context signal store ----
796
+ // Shared reactive context: root injector has a default instance; widget/layout trees
797
+ const AXPContextStore = signalStore(
798
+ // Initial State
799
+ withState(() => ({
800
+ data: {}, // Shared context data
801
+ state: 'initiated', // Current state
802
+ initialSnapshot: {}, // Snapshot of the first initialized state
803
+ previousSnapshot: {}, // Snapshot of the previous state
804
+ lastChange: {
805
+ state: 'initiated',
806
+ }, // Last change event
807
+ })),
808
+ // Computed Signals
809
+ withComputed(({ data, state, lastChange, initialSnapshot, previousSnapshot }) => ({
810
+ isChanged: computed(() => state() === 'changed'),
811
+ isReset: computed(() => state() === 'restored'),
812
+ isInitiated: computed(() => state() === 'initiated'),
813
+ isEmpty: computed(() => Object.keys(data()).length === 0),
814
+ isDirty: computed(() => !isEqual(data(), previousSnapshot())),
815
+ snapshot: computed(() => cloneDeep(data())), // Current data snapshot
816
+ initial: computed(() => cloneDeep(initialSnapshot())), // Initial snapshot
817
+ previous: computed(() => cloneDeep(previousSnapshot())), // Previous snapshot
818
+ changeEvent: computed(() => lastChange()), // Reactive last change event
819
+ })),
820
+ // Methods for State Management
821
+ withMethods((store) => ({
822
+ // Update a specific value
823
+ update(path, value) {
824
+ const currentData = cloneDeep(store.data());
825
+ const oldValue = getSmart(currentData, path);
826
+ // Skip if the value hasn't changed
827
+ if (isEqual(oldValue, value)) {
828
+ return;
829
+ }
830
+ // Update the value and prepare the change event
831
+ const updatedData = setSmart(currentData, path, value);
832
+ const changeEvent = {
833
+ oldValue,
834
+ newValue: value,
835
+ path,
836
+ state: 'changed',
837
+ data: updatedData,
838
+ };
839
+ // Patch the state
840
+ patchState(store, {
841
+ previousSnapshot: store.snapshot(), // Save the previous state
842
+ data: updatedData,
843
+ state: 'changed',
844
+ lastChange: changeEvent,
845
+ });
846
+ },
847
+ patch(context, skipDirtyTracking = false) {
848
+ const currentData = cloneDeep(store.data());
849
+ // Update the value and prepare the change event
850
+ const updatedData = { ...currentData, ...context };
851
+ const changeEvent = {
852
+ state: 'patch',
853
+ data: updatedData,
854
+ };
855
+ // Patch the state
856
+ patchState(store, {
857
+ ...(skipDirtyTracking ? {} : { previousSnapshot: store.snapshot() }),
858
+ data: updatedData,
859
+ state: 'changed',
860
+ lastChange: changeEvent,
861
+ });
862
+ },
863
+ // Reset to the initial state
864
+ reset() {
865
+ const initialData = store.initial();
866
+ const changeEvent = {
867
+ oldValue: cloneDeep(store.data()), // Current data becomes old value
868
+ newValue: cloneDeep(initialData), // Reset to the initial state
869
+ path: '',
870
+ state: 'restored',
871
+ data: initialData,
872
+ };
873
+ patchState(store, {
874
+ previousSnapshot: store.snapshot(), // Save the previous state
875
+ data: initialData,
876
+ state: 'restored',
877
+ lastChange: changeEvent,
878
+ });
879
+ },
880
+ // Initialize the state
881
+ set(initialData) {
882
+ const currentData = store.data();
883
+ if (isEqual(currentData, initialData)) {
884
+ return; // Skip if the current state matches the initial state
885
+ }
886
+ const changeEvent = {
887
+ oldValue: null,
888
+ newValue: cloneDeep(initialData),
889
+ path: '',
890
+ state: 'initiated',
891
+ data: initialData,
892
+ };
893
+ patchState(store, {
894
+ initialSnapshot: cloneDeep(initialData), // Save the initial state
895
+ previousSnapshot: store.snapshot(), // Save the current state as the previous
896
+ data: initialData,
897
+ state: 'initiated',
898
+ lastChange: changeEvent,
899
+ });
900
+ },
901
+ // Get a specific value
902
+ getValue(path) {
903
+ return getSmart(store.data(), path);
904
+ },
905
+ // Check if a path exists in the context
906
+ hasValue(path) {
907
+ return has(store.data(), path);
908
+ },
909
+ })));
910
+ //#endregion
911
+
912
+ class AXPExpressionEvaluatorScopeProviderContext {
913
+ constructor() {
914
+ this.scopes = {};
915
+ }
916
+ addScope(namespace, functions) {
917
+ this.scopes[namespace] = { ...this.scopes[namespace], ...functions };
918
+ }
919
+ getScopes() {
920
+ return this.scopes;
921
+ }
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;
928
+ }
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);
941
+ }
942
+ this.cache = context.getScopes();
943
+ }
944
+ async getScopesAsync() {
945
+ await this.load();
946
+ return this.cache || {};
947
+ }
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);
961
+ }
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);
978
+ }
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
+ }
1009
+ }
1010
+ catch (error) {
1011
+ console.error('Expression evaluator - Error evaluating expression:', source, error);
1012
+ return false;
1013
+ }
1014
+ }
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)
1426
+ [r, g, b] = [x, 0, c];
1427
+ else
1428
+ [r, g, b] = [c, 0, x];
1429
+ return {
1430
+ r: Math.round((r + m) * 255),
1431
+ g: Math.round((g + m) * 255),
1432
+ b: Math.round((b + m) * 255)
1433
+ };
1434
+ }
1435
+ static alphanumeric(length = 10) {
1436
+ const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
1437
+ return Array.from({ length }, () => chars.charAt(Math.floor(Math.random() * chars.length))).join('');
1438
+ }
1439
+ static alphabet(length = 10) {
1440
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
1441
+ return Array.from({ length }, () => chars.charAt(Math.floor(Math.random() * chars.length))).join('');
1442
+ }
1443
+ static phone() {
1444
+ const areaCode = this.number(100, 999);
1445
+ const exchangeCode = this.number(100, 999);
1446
+ const lineNumber = this.number(1000, 9999);
1447
+ return `${areaCode}-${exchangeCode}-${lineNumber}`;
1448
+ }
1449
+ static firstName() {
1450
+ const firstNames = ['John', 'Allen', 'Jak', 'Rose', 'Kate', 'Liam', 'Olivia', 'Noah', 'Emma', 'Ava'];
1451
+ return this.pick(firstNames);
1452
+ }
1453
+ static lastName() {
1454
+ const lastNames = ['Gates', 'Jonsen', 'Smith', 'Ford', 'Jakson', 'Brown', 'Johnson', 'Williams', 'Jones', 'Garcia'];
1455
+ return this.pick(lastNames);
1456
+ }
1457
+ static email(...args) {
1458
+ const domains = ['gmail.com', 'yahoo.com', 'outlook.com', 'example.com'];
1459
+ const domain = this.pick(domains);
1460
+ const separator = this.pick(['.', '_', '']);
1461
+ const randomSuffix = this.boolean() ? this.number(1, 99).toString() : '';
1462
+ if (args.length === 2) {
1463
+ const firstName = args[0].toLowerCase();
1464
+ const lastName = args[1].toLowerCase();
1465
+ return `${firstName}${separator}${lastName}${randomSuffix}@${domain}`;
1466
+ }
1467
+ else {
1468
+ const firstName = this.firstName().toLowerCase();
1469
+ const lastName = this.lastName().toLowerCase();
1470
+ return `${firstName}${separator}${lastName}${randomSuffix}@${domain}`;
1471
+ }
1472
+ }
1473
+ static country() {
1474
+ const countries = ['USA', 'Canada', 'Mexico', 'Germany', 'France', 'Japan', 'Australia'];
1475
+ return this.pick(countries);
1476
+ }
1477
+ static city() {
1478
+ const cities = ['Los Angeles', 'Toronto', 'Vancouver', 'Berlin', 'Paris', 'Tokyo', 'Sydney'];
1479
+ return this.pick(cities);
1480
+ }
1481
+ static state() {
1482
+ const states = ['NY', 'CA', 'TX', 'ON', 'BC', 'NSW', 'BER', 'IDF', 'TYO'];
1483
+ return this.pick(states);
1484
+ }
1485
+ static address() {
1486
+ const streets = ['Main St', 'High St', 'Maple Ave', 'Oak St', 'Pine St', 'Cedar St'];
1487
+ const streetNumber = this.number(100, 9999);
1488
+ const street = this.pick(streets);
1489
+ const city = this.city();
1490
+ const state = this.state();
1491
+ const zip = this.number(10000, 99999);
1492
+ const country = this.country();
1493
+ return `${streetNumber} ${street}, ${city}, ${state} ${zip}, ${country}`;
1494
+ }
1495
+ static avatar() {
1496
+ return `https://avatar.iran.liara.run/public/${this.pick([35, 22, 16, 6, 31])}`;
1497
+ //return `https://i.pravatar.cc/300?u=${this.uuid()}`;
1498
+ }
1499
+ }
1500
+
1501
+ function objectKeyValueTransforms(keyName) {
1502
+ return {
1503
+ getter: (value) => {
1504
+ return extractValue(value, keyName);
1505
+ },
1506
+ setter: (value) => {
1507
+ return extractValue(value, keyName);
1508
+ },
1509
+ };
1510
+ }
1511
+
1512
+ const AXP_DATASOURCE_DEFINITION_PROVIDER = new InjectionToken('AXP_DATASOURCE_TYPE_PROVIDER');
1513
+ class AXPDataSourceDefinitionProviderService {
1514
+ constructor() {
1515
+ this.providers = inject(AXP_DATASOURCE_DEFINITION_PROVIDER, { optional: true });
1516
+ }
1517
+ async items() {
1518
+ const items = [];
1519
+ // Load from DI tokens; resolve lazy providers (provideLazyProvider uses useFactory that returns Promise<T>)
1520
+ if (Array.isArray(this.providers)) {
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
+ }
1527
+ }
1528
+ }
1529
+ return items;
1530
+ }
1531
+ async get(name) {
1532
+ return (await this.items()).find((c) => c.name == name);
1533
+ }
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' }); }
1536
+ }
1537
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSourceDefinitionProviderService, decorators: [{
1538
+ type: Injectable,
1539
+ args: [{ providedIn: 'root' }]
1540
+ }] });
1541
+
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 */ []));
1548
+ }
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 }); }
1551
+ }
1552
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPContentCheckerDirective, decorators: [{
1553
+ type: Directive,
1554
+ args: [{
1555
+ selector: '[axp-content-checker]',
1556
+ standalone: true,
1557
+ exportAs: 'checker'
1558
+ }]
1559
+ }] });
1560
+
1561
+ class AXPDblClickDirective {
1562
+ constructor() {
1563
+ this.onDblClick = new EventEmitter();
1564
+ this.lastTap = 0;
1565
+ this.doubleTapThreshold = 300; // milliseconds
1566
+ }
1567
+ // Listen for the native dblclick event (desktop)
1568
+ handleOnDblClick(event) {
1569
+ this.onDblClick.emit(event);
1570
+ }
1571
+ // Listen for touchend events (mobile)
1572
+ onTouchEnd(event) {
1573
+ const currentTime = new Date().getTime();
1574
+ const tapGap = currentTime - this.lastTap;
1575
+ if (tapGap > 0 && tapGap < this.doubleTapThreshold) {
1576
+ // Detected a double-tap
1577
+ this.onDblClick.emit(event);
1578
+ event.preventDefault(); // Optionally prevent further default actions
1579
+ }
1580
+ this.lastTap = currentTime;
1581
+ }
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 }); }
1584
+ }
1585
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDblClickDirective, decorators: [{
1586
+ type: Directive,
1587
+ args: [{
1588
+ selector: '[onDblClick]'
1589
+ }]
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 }] }] } });
1638
+
1639
+ // src/app/directives/grid-layout.directive.ts
1640
+ class AXPGridLayoutDirective {
1641
+ constructor(el, renderer) {
1642
+ this.el = el;
1643
+ this.renderer = renderer;
1644
+ this.options = input.required({ ...(ngDevMode ? { debugName: "options" } : /* istanbul ignore next */ {}), alias: 'axp-grid-layout' });
1645
+ }
1646
+ ngOnChanges(changes) {
1647
+ if (changes['options']) {
1648
+ this.applyTailwindClasses();
1649
+ }
1650
+ }
1651
+ applyTailwindClasses() {
1652
+ const placement = this.options()?.positions;
1653
+ if (!placement)
1654
+ return;
1655
+ // Clear existing grid classes
1656
+ this.clearClasses();
1657
+ // Apply new grid classes based on the input options
1658
+ this.setClasses(placement.sm, '');
1659
+ this.setClasses(placement.md, 'md:');
1660
+ this.setClasses(placement.lg, 'lg:');
1661
+ this.setClasses(placement.xl, 'xl:');
1662
+ this.setClasses(placement.xxl, '2xl:');
1663
+ }
1664
+ setClasses(placement, prefix) {
1665
+ if (placement == null)
1666
+ return;
1667
+ const colStart = placement.colStart ? `${prefix}ax-col-start-${placement.colStart}` : '';
1668
+ const colEnd = placement.colEnd ? `${prefix}ax-col-end-${placement.colEnd}` : '';
1669
+ const colSpan = placement.colSpan ? `${prefix}ax-col-span-${placement.colSpan}` : '';
1670
+ const rowStart = placement.rowStart ? `${prefix}ax-row-start-${placement.rowStart}` : '';
1671
+ const rowEnd = placement.rowEnd ? `${prefix}ax-row-end-${placement.rowEnd}` : '';
1672
+ const rowSpan = placement.rowSpan ? `${prefix}ax-row-span-${placement.rowSpan}` : '';
1673
+ const order = placement.order ? `${prefix}ax-order-${placement.order}` : ''; // Handling order
1674
+ [colStart, colEnd, colSpan, rowStart, rowEnd, rowSpan, order].forEach(cls => {
1675
+ if (cls) {
1676
+ this.renderer.addClass(this.el.nativeElement, cls);
1677
+ }
1678
+ });
1679
+ }
1680
+ clearClasses() {
1681
+ const currentClasses = this.el.nativeElement.className.split(' ');
1682
+ currentClasses.forEach((className) => {
1683
+ if (className.startsWith('ax-col-') || className.startsWith('ax-row-') || className.startsWith('ax-order-')) {
1684
+ this.renderer.removeClass(this.el.nativeElement, className);
1685
+ }
1686
+ });
1687
+ }
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 }); }
1690
+ }
1691
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGridLayoutDirective, decorators: [{
1692
+ type: Directive,
1693
+ args: [{
1694
+ selector: '[axp-grid-layout]',
1695
+ standalone: true,
1696
+ }]
1697
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-grid-layout", required: true }] }] } });
1698
+
1699
+ const AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER = new InjectionToken('AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER');
1700
+
1701
+ //#region ---- Imports ----
1702
+ //#endregion
1703
+ class AXPDistributedEventListenerService {
1704
+ constructor() {
1705
+ //#region ---- Providers & Caches ----
1706
+ this.listenerProviders = inject(AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, { optional: true }) || [];
1707
+ this.injector = inject(Injector);
1708
+ /** Cache for listeners by key. */
1709
+ this.listenersByKey = new Map();
1710
+ /** Flag to track if providers have been loaded */
1711
+ this.providersLoaded = false;
1712
+ }
1713
+ //#endregion
1714
+ //#region ---- Public API ----
1715
+ /**
1716
+ * Dispatches an event to all registered listeners for the given key.
1717
+ * @param key The event key.
1718
+ * @param data The event data to pass to listeners.
1719
+ */
1720
+ async dispatch(key, data) {
1721
+ const providers = await this.resolveProviders();
1722
+ const matched = providers.filter(p => p.key === key);
1723
+ if (!matched.length) {
1724
+ return;
1725
+ }
1726
+ for (const provider of matched) {
1727
+ try {
1728
+ await Promise.resolve(runInInjectionContext(this.injector, () => provider.execute(data)));
1729
+ }
1730
+ catch (err) {
1731
+ console.error(`[AXPDistributedEventListenerService] Provider for key='${key}' failed`, err);
1732
+ }
1733
+ }
1734
+ }
1735
+ /**
1736
+ * Dispatch with async response (first matching provider, with retry/timeout)
1737
+ */
1738
+ async dispatchAsync(key, data, options = {
1739
+ timeout: 60_000,
1740
+ retries: 3,
1741
+ retryDelay: 1000,
1742
+ }) {
1743
+ const providers = await this.resolveProviders();
1744
+ const matched = providers.filter(p => p.key === key);
1745
+ if (!matched.length) {
1746
+ throw new Error(`No provider found for key='${key}'`);
1747
+ }
1748
+ const attempt = (n) => {
1749
+ return new Promise((resolve, reject) => {
1750
+ let finished = false;
1751
+ const timer = setTimeout(() => {
1752
+ if (!finished) {
1753
+ if (n < options.retries) {
1754
+ resolve(attempt(n + 1));
1755
+ }
1756
+ else {
1757
+ reject(new Error(`Timeout: no response for key='${key}' after ${options.retries} attempts.`));
1758
+ }
1759
+ }
1760
+ }, options.timeout);
1761
+ try {
1762
+ const provider = matched[0];
1763
+ const result = runInInjectionContext(this.injector, () => provider.execute(data));
1764
+ Promise.resolve(result)
1765
+ .then((r) => {
1766
+ finished = true;
1767
+ clearTimeout(timer);
1768
+ resolve(r);
1769
+ })
1770
+ .catch(err => {
1771
+ finished = true;
1772
+ clearTimeout(timer);
1773
+ reject(err);
1774
+ });
1775
+ }
1776
+ catch (err) {
1777
+ clearTimeout(timer);
1778
+ reject(err);
1779
+ }
1780
+ });
1781
+ };
1782
+ return attempt(0);
1783
+ }
1784
+ /**
1785
+ * Resolve all providers (handle both direct provider and Promise<provider>)
1786
+ */
1787
+ async resolveProviders() {
1788
+ return Promise.all(this.listenerProviders.map(p => p instanceof Promise ? p : Promise.resolve(p)));
1789
+ }
1790
+ /**
1791
+ * Returns all listeners for a specific event key.
1792
+ * @param key The event key.
1793
+ * @returns Array of listeners for the key.
1794
+ */
1795
+ async getListeners(key) {
1796
+ await this.ensureProvidersLoaded();
1797
+ return this.listenersByKey.get(key) || [];
1798
+ }
1799
+ /**
1800
+ * Returns all registered event keys.
1801
+ * @returns Array of all event keys that have listeners.
1802
+ */
1803
+ async getRegisteredKeys() {
1804
+ await this.ensureProvidersLoaded();
1805
+ return Array.from(this.listenersByKey.keys());
1806
+ }
1807
+ //#endregion
1808
+ //#region ---- Private Methods ----
1809
+ /**
1810
+ * Ensures that all providers have been loaded and cached.
1811
+ */
1812
+ async ensureProvidersLoaded() {
1813
+ if (this.providersLoaded) {
1814
+ return;
1815
+ }
1816
+ // Resolve all providers
1817
+ const resolvedProviders = await Promise.all(this.listenerProviders);
1818
+ // Group listeners by key
1819
+ for (const provider of resolvedProviders) {
1820
+ if (provider) {
1821
+ const existingListeners = this.listenersByKey.get(provider.key) || [];
1822
+ existingListeners.push(provider);
1823
+ this.listenersByKey.set(provider.key, existingListeners);
1824
+ }
1825
+ }
1826
+ this.providersLoaded = true;
1827
+ }
1828
+ //#endregion
1829
+ //#region ---- Cache Management ----
1830
+ /** Clears the listeners cache and forces reload on next access. */
1831
+ clearListenersCache() {
1832
+ this.listenersByKey.clear();
1833
+ this.providersLoaded = false;
1834
+ }
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' }); }
1837
+ }
1838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDistributedEventListenerService, decorators: [{
1839
+ type: Injectable,
1840
+ args: [{
1841
+ providedIn: 'root',
1842
+ }]
1843
+ }] });
1844
+
1845
+ class AXPBroadcastEventService {
1846
+ constructor() {
1847
+ this.eventSubjects = new Map();
1848
+ this.pendingRequests = new Map();
1849
+ this.multiTabEventHistory = new Set(); // Prevent duplicate processing of the same event
1850
+ this.instanceId = AXPDataGenerator.uuid();
1851
+ this.channel = new BroadcastChannel('platform_global_events');
1852
+ // Handle incoming messages
1853
+ this.channel.onmessage = (event) => {
1854
+ const { type, payload, requestId, response, sourceId } = event.data;
1855
+ // Prevent processing the same event multiple times (multi-tab synchronization)
1856
+ if (requestId && this.multiTabEventHistory.has(requestId)) {
1857
+ return;
1858
+ }
1859
+ if (requestId) {
1860
+ this.multiTabEventHistory.add(requestId); // Store processed requestId
1861
+ setTimeout(() => this.multiTabEventHistory.delete(requestId), 10000); // Cleanup after 10 sec
1862
+ }
1863
+ // Handle responses to pending requests
1864
+ if (requestId && !isUndefined(response) && this.pendingRequests.has(requestId)) {
1865
+ this.pendingRequests.get(requestId)(response);
1866
+ this.pendingRequests.delete(requestId);
1867
+ return;
1868
+ }
1869
+ // Handle normal broadcast events
1870
+ // Ignore events originating from this same instance to avoid double-delivery
1871
+ if (sourceId && sourceId === this.instanceId) {
1872
+ return;
1873
+ }
1874
+ if (type && this.eventSubjects.has(type)) {
1875
+ this.eventSubjects.get(type).next({ data: payload, requestId });
1876
+ }
1877
+ };
1878
+ }
1879
+ /**
1880
+ * Publish an event without expecting a response
1881
+ */
1882
+ publish(type, payload) {
1883
+ this.channel.postMessage({ type, payload, sourceId: this.instanceId });
1884
+ // Local echo so same-tab listeners receive the event as well
1885
+ if (this.eventSubjects.has(type)) {
1886
+ this.eventSubjects.get(type).next({ data: payload });
1887
+ }
1888
+ }
1889
+ /**
1890
+ * Subscribe to an event
1891
+ */
1892
+ listen(type) {
1893
+ if (!this.eventSubjects.has(type)) {
1894
+ this.eventSubjects.set(type, new Subject());
1895
+ }
1896
+ return this.eventSubjects.get(type).asObservable();
1897
+ }
1898
+ /**
1899
+ * Unsubscribe from an event
1900
+ */
1901
+ unsubscribe(type) {
1902
+ if (this.eventSubjects.has(type)) {
1903
+ this.eventSubjects.get(type).complete();
1904
+ this.eventSubjects.delete(type);
1905
+ }
1906
+ }
1907
+ /**
1908
+ * Send a message and wait for a response with retry logic
1909
+ */
1910
+ async sendAndWaitForResponse(type, payload, options = {
1911
+ timeout: 60 * 60 * 1000,
1912
+ retries: 3,
1913
+ retryDelay: 1000,
1914
+ }) {
1915
+ const requestId = AXPDataGenerator.uuid();
1916
+ const attemptRequest = (attempt) => {
1917
+ return new Promise((resolve, reject) => {
1918
+ this.pendingRequests.set(requestId, resolve);
1919
+ this.channel.postMessage({ type, payload, requestId });
1920
+ setTimeout(() => {
1921
+ if (this.pendingRequests.has(requestId)) {
1922
+ this.pendingRequests.delete(requestId);
1923
+ if (attempt < options.retries) {
1924
+ console.warn(`Retrying request '${type}' (${attempt + 1}/${options.retries})...`);
1925
+ resolve(attemptRequest(attempt + 1)); // Retry request
1926
+ }
1927
+ else {
1928
+ reject(new Error(`Timeout: No response received for event '${type}' after ${options.retries} attempts.`));
1929
+ }
1930
+ }
1931
+ }, options.timeout);
1932
+ });
1933
+ };
1934
+ return attemptRequest(0);
1935
+ }
1936
+ /**
1937
+ * Respond to a request
1938
+ */
1939
+ respondToRequest(requestId, response) {
1940
+ if (!requestId) {
1941
+ console.warn('Invalid requestId. Cannot send response.');
1942
+ return;
1943
+ }
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();
1961
+ }
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' }); }
1964
+ }
1965
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBroadcastEventService, decorators: [{
1966
+ type: Injectable,
1967
+ args: [{
1968
+ providedIn: 'root',
1969
+ }]
1970
+ }], ctorParameters: () => [] });
1971
+
1972
+ class AXPHookService {
1973
+ constructor() {
1974
+ this.listenerProviders = inject(AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, { optional: true }) || [];
1975
+ this.injector = inject(Injector);
1976
+ }
1977
+ /**
1978
+ * Resolve all providers (handle both direct providers and Promise<provider>)
1979
+ */
1980
+ async resolveProviders() {
1981
+ return Promise.all(this.listenerProviders.map(p => p instanceof Promise ? p : Promise.resolve(p)));
1982
+ }
1983
+ /**
1984
+ * Fire sync hooks (fire-and-forget).
1985
+ * All providers with the given key will be executed.
1986
+ * Execution is not awaited.
1987
+ */
1988
+ fire(key, data) {
1989
+ this.resolveProviders().then(providers => {
1990
+ providers
1991
+ .filter(p => p.key === key)
1992
+ .sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0))
1993
+ .forEach(p => {
1994
+ try {
1995
+ runInInjectionContext(this.injector, () => p.execute(data));
1996
+ }
1997
+ catch (err) {
1998
+ console.error(`[AXPHookService] Hook '${key}' failed`, err);
1999
+ }
2000
+ });
2001
+ });
2002
+ }
2003
+ /**
2004
+ * Run async hooks sequentially (waterfall).
2005
+ * The output of each hook is passed as input to the next hook.
2006
+ * Returns the final merged data after all hooks are executed.
2007
+ */
2008
+ async runAsync(key, initialData) {
2009
+ const providers = (await this.resolveProviders())
2010
+ .filter(p => p.key === key)
2011
+ .sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
2012
+ let data = initialData;
2013
+ for (const p of providers) {
2014
+ data = await Promise.resolve(runInInjectionContext(this.injector, () => p.execute(data)));
2015
+ }
2016
+ return data;
2017
+ }
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' }); }
2020
+ }
2021
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHookService, decorators: [{
2022
+ type: Injectable,
2023
+ args: [{ providedIn: 'root' }]
2024
+ }] });
2025
+
2026
+ //#region ---- Imports ----
2027
+ //#endregion
2028
+
2029
+ //#region ---- Provider Interfaces ----
2030
+ /**
2031
+ * Injection token for session service.
2032
+ * Implementation: @acorex/platform/auth
2033
+ */
2034
+ const AXP_SESSION_SERVICE = new InjectionToken('AXP_SESSION_SERVICE');
2035
+ /**
2036
+ * Injection token for module manifest providers.
2037
+ * Modules register their manifest providers using this token.
2038
+ */
2039
+ const AXP_MODULE_MANIFEST_PROVIDER = new InjectionToken('AXP_MODULE_MANIFEST_PROVIDER');
2040
+ //#endregion
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
+
2077
+ //#region ---- Imports ----
2078
+ //#endregion
2079
+ //#region ---- Registry Service ----
2080
+ /**
2081
+ * Registry service for module manifests.
2082
+ * Collects and manages all registered module manifests.
2083
+ */
2084
+ class AXPModuleManifestRegistry {
2085
+ constructor() {
2086
+ //#region ---- Fields ----
2087
+ this.manifests = new Map();
2088
+ this.featureDefinitions = new Map();
2089
+ this.injector = inject(Injector);
2090
+ this.initializationPromise = null;
2091
+ this.isInitialized = false;
2092
+ }
2093
+ //#endregion
2094
+ //#region ---- Initialization ----
2095
+ /**
2096
+ * Initialize registry by loading all manifest providers.
2097
+ * Should be called during app startup.
2098
+ * Safe to call multiple times - will only initialize once.
2099
+ */
2100
+ async initialize() {
2101
+ // If already initialized, return immediately
2102
+ if (this.isInitialized) {
2103
+ return;
2104
+ }
2105
+ // If initialization is in progress, wait for it
2106
+ if (this.initializationPromise) {
2107
+ return this.initializationPromise;
2108
+ }
2109
+ // Start initialization
2110
+ this.initializationPromise = this._doInitialize();
2111
+ await this.initializationPromise;
2112
+ }
2113
+ /**
2114
+ * Internal initialization logic.
2115
+ */
2116
+ async _doInitialize() {
2117
+ // Get manifests from injector (using useValue, they are provided directly)
2118
+ let manifests;
2119
+ try {
2120
+ const injectedManifests = this.injector.get(AXP_MODULE_MANIFEST_PROVIDER, []);
2121
+ manifests = Array.isArray(injectedManifests) ? injectedManifests : injectedManifests ? [injectedManifests] : [];
2122
+ }
2123
+ catch (error) {
2124
+ console.error('Failed to get manifest providers from injector:', error);
2125
+ manifests = [];
2126
+ }
2127
+ // Register all manifests directly
2128
+ const registerPromises = manifests.map(async (manifest) => {
2129
+ try {
2130
+ // Validate manifest
2131
+ if (!manifest) {
2132
+ console.error('Invalid manifest:', manifest);
2133
+ return;
2134
+ }
2135
+ await this.register(manifest);
2136
+ }
2137
+ catch (error) {
2138
+ console.error(`Failed to register manifest:`, error);
2139
+ }
2140
+ });
2141
+ await Promise.all(registerPromises);
2142
+ // Load and register features from all feature definition providers
2143
+ await this.loadFeatureDefinitions();
2144
+ this.isInitialized = true;
2145
+ }
2146
+ //#endregion
2147
+ //#region ---- Manifest Management ----
2148
+ /**
2149
+ * Register a module manifest.
2150
+ */
2151
+ async register(manifest) {
2152
+ // Validate manifest
2153
+ if (!manifest.name) {
2154
+ throw new Error('Manifest must have a name');
2155
+ }
2156
+ if (!manifest.version) {
2157
+ throw new Error(`Manifest for module '${manifest.name}' must have a version`);
2158
+ }
2159
+ // Register manifest
2160
+ this.manifests.set(manifest.name, manifest);
2161
+ }
2162
+ /**
2163
+ * Get manifest for a module.
2164
+ */
2165
+ get(moduleName) {
2166
+ return this.manifests.get(moduleName);
2167
+ }
2168
+ /**
2169
+ * Get all registered manifests.
2170
+ */
2171
+ getAll() {
2172
+ return Array.from(this.manifests.values());
2173
+ }
2174
+ /**
2175
+ * Check if a module manifest is registered.
2176
+ */
2177
+ has(moduleName) {
2178
+ return this.manifests.has(moduleName);
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
+ }
2227
+ //#endregion
2228
+ //#region ---- Feature Definition Management ----
2229
+ /**
2230
+ * Get all feature definitions from all manifests.
2231
+ */
2232
+ getAllFeatureDefinitions() {
2233
+ return Array.from(this.featureDefinitions.values());
2234
+ }
2235
+ /**
2236
+ * Get feature definition by full name.
2237
+ */
2238
+ getFeatureDefinition(featureName) {
2239
+ return this.featureDefinitions.get(featureName);
2240
+ }
2241
+ /**
2242
+ * Check if a feature is defined in any manifest.
2243
+ */
2244
+ isFeatureDefined(featureName) {
2245
+ return this.featureDefinitions.has(featureName);
2246
+ }
2247
+ /**
2248
+ * Get default value for a feature.
2249
+ * Returns undefined if feature is not defined.
2250
+ */
2251
+ getFeatureDefault(featureName) {
2252
+ const definition = this.getFeatureDefinition(featureName);
2253
+ return definition?.defaultValue;
2254
+ }
2255
+ /**
2256
+ * Get all feature definitions for a specific module.
2257
+ */
2258
+ getModuleFeatures(moduleName) {
2259
+ return Array.from(this.featureDefinitions.values()).filter((def) => def.module === moduleName);
2260
+ }
2261
+ /**
2262
+ * Register a feature definition dynamically (e.g., from feature definition provider).
2263
+ * Used to add features that are defined at runtime via AXP_FEATURE_DEFINITION_PROVIDER.
2264
+ */
2265
+ registerFeatureDefinition(definition) {
2266
+ this.featureDefinitions.set(definition.name, definition);
2267
+ }
2268
+ //#endregion
2269
+ //#region ---- Dependency Checking ----
2270
+ /**
2271
+ * Check if module dependencies are satisfied.
2272
+ * Returns array of missing dependencies.
2273
+ * Dependencies can be module names or feature keys (ModuleName.FeatureKey format).
2274
+ */
2275
+ checkDependencies(moduleName) {
2276
+ const manifest = this.get(moduleName);
2277
+ if (!manifest?.dependencies || manifest.dependencies.length === 0) {
2278
+ return { missingModules: [], missingFeatures: [] };
2279
+ }
2280
+ const missingModules = [];
2281
+ const missingFeatures = [];
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);
2290
+ }
2291
+ }
2292
+ else {
2293
+ // Otherwise, it's a module name
2294
+ if (!this.has(dependency)) {
2295
+ missingModules.push(dependency);
2296
+ }
2297
+ }
2298
+ }
2299
+ return { missingModules, missingFeatures };
2300
+ }
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' }); }
2303
+ }
2304
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestRegistry, decorators: [{
2305
+ type: Injectable,
2306
+ args: [{ providedIn: 'root' }]
2307
+ }] });
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
+
2380
+ class AXPAppStartUpService {
2381
+ constructor() {
2382
+ this.tasks = [];
2383
+ }
2384
+ registerTask(task) {
2385
+ this.tasks.push(task);
2386
+ }
2387
+ async runAllTasks() {
2388
+ for (const task of this.tasks.sort((a, b) => a.priority - b.priority)) {
2389
+ this.updateStatus(task.statusText);
2390
+ await task.run();
2391
+ }
2392
+ }
2393
+ updateStatus(status) {
2394
+ const loadingText = document.querySelector('#loadingText');
2395
+ if (loadingText) {
2396
+ loadingText.innerHTML = status;
2397
+ }
2398
+ }
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' }); }
2401
+ }
2402
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppStartUpService, decorators: [{
2403
+ type: Injectable,
2404
+ args: [{
2405
+ providedIn: 'root',
2406
+ }]
2407
+ }] });
2408
+ function initAppFactory(appInitService) {
2409
+ return () => appInitService.runAllTasks();
2410
+ }
2411
+ const AXPAppStartUpProvider = provideAppInitializer(() => {
2412
+ const initializerFn = initAppFactory(inject(AXPAppStartUpService));
2413
+ return initializerFn();
2414
+ });
2415
+
2416
+ //#region ---- Imports ----
2417
+ //#endregion
2418
+ //#region ---- Module ----
2419
+ /**
2420
+ * Module for managing module manifests initialization.
2421
+ * Handles the registration of manifest startup tasks.
2422
+ */
2423
+ class AXPModuleManifestModule {
2424
+ /**
2425
+ * @ignore
2426
+ * Initializes module manifest tasks on module construction.
2427
+ */
2428
+ constructor(appInitService, injector) {
2429
+ const manifestRegistry = injector.get(AXPModuleManifestRegistry);
2430
+ // Register manifest initialization task
2431
+ appInitService.registerTask({
2432
+ name: 'ModuleManifests',
2433
+ statusText: 'Loading module manifests...',
2434
+ priority: 1, // Load early, before features/permissions
2435
+ run: async () => {
2436
+ await manifestRegistry.initialize();
2437
+ },
2438
+ });
2439
+ }
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 }); }
2443
+ }
2444
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestModule, decorators: [{
2445
+ type: NgModule,
2446
+ args: [{
2447
+ providers: [],
2448
+ }]
2449
+ }], ctorParameters: () => [{ type: AXPAppStartUpService }, { type: i0.Injector }] });
2450
+
2451
+ //#region ---- Imports ----
2452
+ //#endregion
2453
+ //#region ---- Public API ----
2454
+ /**
2455
+ * Resolves {@link AXPMultiLanguageString} to a single string for the given locale.
2456
+ * Fallback order: `currentLocale` → `en-US` → first map value.
2457
+ */
2458
+ function resolveMultiLanguageString(content, currentLocale) {
2459
+ if (content == null || content === '') {
2460
+ return '';
2461
+ }
2462
+ if (typeof content === 'string') {
2463
+ return content;
2464
+ }
2465
+ if (typeof content !== 'object' || Array.isArray(content)) {
2466
+ return String(content);
2467
+ }
2468
+ const record = content;
2469
+ const pick = record[currentLocale] ??
2470
+ record['en-US'] ??
2471
+ Object.values(record).find((v) => v != null);
2472
+ if (pick == null || pick === '') {
2473
+ return '';
2474
+ }
2475
+ if (typeof pick === 'string') {
2476
+ return pick;
2477
+ }
2478
+ if (typeof pick === 'object' && pick !== null && !Array.isArray(pick)) {
2479
+ return resolveMultiLanguageString(pick, currentLocale);
2480
+ }
2481
+ return String(pick);
2482
+ }
2483
+ /**
2484
+ * Creates an {@link AXPMultiLanguageString} with `en-US` and `fa-IR` entries.
2485
+ * Use for seed data, tests, and demos that supply English and Persian copy explicitly.
2486
+ */
2487
+ function createMultiLanguageString(enUs, faIr) {
2488
+ return { 'en-US': enUs, 'fa-IR': faIr };
2489
+ }
2490
+ /**
2491
+ * True when there is no displayable text in any locale (plain string or ML map).
2492
+ * Pure helper for predicates (e.g. default section detection); prefer widgets / pipes for display.
2493
+ */
2494
+ function isEffectivelyEmptyLocalizedValue(value) {
2495
+ if (value == null)
2496
+ return true;
2497
+ if (typeof value === 'string')
2498
+ return value.trim() === '';
2499
+ if (typeof value !== 'object' || Array.isArray(value))
2500
+ return false;
2501
+ const record = value;
2502
+ return Object.values(record).every((v) => v == null || String(v).trim() === '');
2503
+ }
2504
+ //#endregion
2505
+
2506
+ //#region ---- Imports ----
2507
+ //#endregion
2508
+ //#region ---- AXPMultiLanguageStringResolverService ----
2509
+ /**
2510
+ * Resolves {@link AXPMultiLanguageString} using the active app locale, and exposes
2511
+ * {@link currentLocale$} for code that prefers an observable (e.g. manual subscriptions).
2512
+ * Templates usually use {@link AXPResolveMultiLanguageStringPipe} instead.
2513
+ */
2514
+ class AXPMultiLanguageStringResolverService {
2515
+ constructor() {
2516
+ //#region ---- Services & Dependencies ----
2517
+ this.translation = inject(AXTranslationService);
2518
+ //#endregion
2519
+ //#region ---- Locale stream ----
2520
+ /**
2521
+ * Emits the active locale on subscribe and whenever the language changes.
2522
+ */
2523
+ this.currentLocale$ = merge$1(of(this.translation.getActiveLang()), this.translation.langChanges$).pipe(map(() => this.translation.getActiveLang()), distinctUntilChanged());
2524
+ }
2525
+ //#endregion
2526
+ //#region ---- Resolve ----
2527
+ /**
2528
+ * Resolves multi-language content for an optional locale (defaults to active).
2529
+ */
2530
+ resolve(content, locale) {
2531
+ return resolveMultiLanguageString(content, locale ?? this.translation.getActiveLang());
2532
+ }
2533
+ /**
2534
+ * Normalizes multi-language content to a locale map for editors (e.g. multi-language popup `values`).
2535
+ * If `content` is already a locale-to-string map, returns a shallow copy.
2536
+ * If it is a plain string or empty, wraps it as `{ [activeLocale]: text }`.
2537
+ */
2538
+ toLocaleMap(content, activeLocale) {
2539
+ if (content && typeof content === 'object' && !Array.isArray(content)) {
2540
+ return { ...content };
2541
+ }
2542
+ const txt = typeof content === 'string' ? content : '';
2543
+ return { [activeLocale]: txt };
2544
+ }
2545
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMultiLanguageStringResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2546
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMultiLanguageStringResolverService, providedIn: 'root' }); }
2547
+ }
2548
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMultiLanguageStringResolverService, decorators: [{
2549
+ type: Injectable,
2550
+ args: [{ providedIn: 'root' }]
2551
+ }] });
2552
+
2553
+ //#region ---- Imports ----
2554
+ //#endregion
2555
+ //#region ---- AXPResolveMultiLanguageStringPipe ----
2556
+ /**
2557
+ * Resolves {@link AXPMultiLanguageString} via {@link AXPMultiLanguageStringResolverService}.
2558
+ * Impure and subscribes to {@link AXPMultiLanguageStringResolverService#currentLocale$} so
2559
+ * OnPush hosts (e.g. grid cells) still refresh when the language changes.
2560
+ *
2561
+ * Optional second argument: explicit locale (e.g. from a host `locale` input). When omitted or null/empty,
2562
+ * the active language is used.
2563
+ *
2564
+ * @example
2565
+ * ```html
2566
+ * {{ value | axpResolveMultiLanguageString }}
2567
+ * {{ value | axpResolveMultiLanguageString: locale() }}
2568
+ * ```
2569
+ */
2570
+ class AXPResolveMultiLanguageStringPipe {
2571
+ constructor() {
2572
+ this.resolver = inject(AXPMultiLanguageStringResolverService);
2573
+ this.cdr = inject(ChangeDetectorRef);
2574
+ this.localeSubscription = this.resolver.currentLocale$.subscribe(() => this.cdr.markForCheck());
2575
+ }
2576
+ transform(value, locale) {
2577
+ const explicitLocale = locale != null && locale !== '' ? locale : undefined;
2578
+ return this.resolver.resolve(value, explicitLocale);
2579
+ }
2580
+ ngOnDestroy() {
2581
+ this.localeSubscription.unsubscribe();
2582
+ }
2583
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPResolveMultiLanguageStringPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2584
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPResolveMultiLanguageStringPipe, isStandalone: true, name: "axpResolveMultiLanguageString", pure: false }); }
2585
+ }
2586
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPResolveMultiLanguageStringPipe, decorators: [{
2587
+ type: Pipe,
2588
+ args: [{
2589
+ name: 'axpResolveMultiLanguageString',
2590
+ standalone: true,
2591
+ pure: false,
2592
+ }]
2593
+ }] });
2594
+
2595
+ //#region ---- Tag Types ----
2596
+ //#endregion
2597
+
2598
+ //#region ---- Tag Provider ----
2599
+ /**
2600
+ * Abstract class for tag providers
2601
+ * Implement this to provide tags from different sources (system, tenant, user, etc.)
2602
+ */
2603
+ class AXPTagProvider {
2604
+ /**
2605
+ * Create a new tag (optional - not all providers support creation)
2606
+ * @param tag Tag to create
2607
+ * @returns Created tag with id
2608
+ */
2609
+ async create(tag) {
2610
+ throw new Error(`Provider ${this.name} does not support tag creation`);
2611
+ }
2612
+ /**
2613
+ * Update an existing tag (optional)
2614
+ * @param tag Tag to update
2615
+ * @returns Updated tag
2616
+ */
2617
+ async update(tag) {
2618
+ throw new Error(`Provider ${this.name} does not support tag updates`);
2619
+ }
2620
+ /**
2621
+ * Delete a tag (optional)
2622
+ * @param id Tag id to delete
2623
+ */
2624
+ async delete(id) {
2625
+ throw new Error(`Provider ${this.name} does not support tag deletion`);
2626
+ }
2627
+ }
2628
+ /**
2629
+ * Injection token for tag providers
2630
+ * Use this to register multiple tag providers
2631
+ */
2632
+ const AXP_TAG_PROVIDER = new InjectionToken('AXP_TAG_PROVIDER');
2633
+ //#endregion
2634
+
2635
+ //#region ---- Tag Service ----
2636
+ /**
2637
+ * Service for managing tags from multiple providers
2638
+ * Aggregates tags from all registered providers
2639
+ */
2640
+ class AXPTagService {
2641
+ constructor() {
2642
+ //#region ---- Dependencies ----
2643
+ this.providers = inject(AXP_TAG_PROVIDER, { optional: true }) ?? [];
2644
+ //#endregion
2645
+ //#region ---- State ----
2646
+ this.cache = null;
2647
+ }
2648
+ //#endregion
2649
+ //#region ---- Public API ----
2650
+ /**
2651
+ * Get all tags from all providers
2652
+ * @param options Filter options
2653
+ * @returns Promise of tags
2654
+ */
2655
+ async getTags(options) {
2656
+ if (!this.cache) {
2657
+ await this.loadTags();
2658
+ }
2659
+ let tags = this.cache;
2660
+ // Apply scope filter
2661
+ if (options?.scope && options.scope.length > 0) {
2662
+ tags = tags.filter((tag) => tag.scope && options.scope.includes(tag.scope));
2663
+ }
2664
+ // Apply search filter
2665
+ if (options?.search) {
2666
+ const searchLower = options.search.toLowerCase();
2667
+ tags = tags.filter((tag) => tag.title.toLowerCase().includes(searchLower) ||
2668
+ tag.description?.toLowerCase().includes(searchLower));
2669
+ }
2670
+ return tags;
2671
+ }
2672
+ /**
2673
+ * Create a new tag using the appropriate provider
2674
+ * @param tag Tag to create
2675
+ * @param providerName Provider to use (defaults to first writable provider)
2676
+ * @returns Created tag
2677
+ */
2678
+ async createTag(tag, providerName) {
2679
+ const provider = providerName
2680
+ ? this.providers.find((p) => p.name === providerName)
2681
+ : this.providers.find((p) => p.create);
2682
+ if (!provider || !provider.create) {
2683
+ throw new Error('No writable tag provider available');
2684
+ }
2685
+ const createdTag = await provider.create(tag);
2686
+ // Invalidate cache
2687
+ this.cache = null;
2688
+ return createdTag;
2689
+ }
2690
+ /**
2691
+ * Update an existing tag
2692
+ * @param tag Tag to update
2693
+ * @returns Updated tag
2694
+ */
2695
+ async updateTag(tag) {
2696
+ const provider = this.providers.find((p) => p.name === tag.scope && p.update);
2697
+ if (!provider || !provider.update) {
2698
+ throw new Error(`No provider found for updating tag with scope: ${tag.scope}`);
2699
+ }
2700
+ const updatedTag = await provider.update(tag);
2701
+ // Invalidate cache
2702
+ this.cache = null;
2703
+ return updatedTag;
2704
+ }
2705
+ /**
2706
+ * Delete a tag
2707
+ * @param tagId Tag id to delete
2708
+ * @param scope Tag scope
2709
+ */
2710
+ async deleteTag(tagId, scope) {
2711
+ const provider = this.providers.find((p) => p.name === scope && p.delete);
2712
+ if (!provider || !provider.delete) {
2713
+ throw new Error(`No provider found for deleting tag with scope: ${scope}`);
2714
+ }
2715
+ await provider.delete(tagId);
2716
+ // Invalidate cache
2717
+ this.cache = null;
2718
+ }
2719
+ /**
2720
+ * Reload tags from all providers
2721
+ */
2722
+ async reload() {
2723
+ this.cache = null;
2724
+ await this.loadTags();
2725
+ }
2726
+ //#endregion
2727
+ //#region ---- Private Methods ----
2728
+ /**
2729
+ * Load tags from all providers
2730
+ */
2731
+ async loadTags() {
2732
+ const allTags = [];
2733
+ for (const provider of this.providers) {
2734
+ try {
2735
+ const tags = await provider.provide();
2736
+ allTags.push(...tags);
2737
+ }
2738
+ catch (error) {
2739
+ console.error(`Error loading tags from provider ${provider.name}:`, error);
2740
+ }
2741
+ }
2742
+ // Remove duplicates based on title (case-insensitive)
2743
+ const uniqueTags = allTags.filter((tag, index, self) => index === self.findIndex((t) => t.title.toLowerCase() === tag.title.toLowerCase()));
2744
+ this.cache = uniqueTags;
2745
+ }
2746
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2747
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTagService, providedIn: 'root' }); }
2748
+ }
2749
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTagService, decorators: [{
2750
+ type: Injectable,
2751
+ args: [{
2752
+ providedIn: 'root',
2753
+ }]
2754
+ }] });
2755
+
2756
+ /**
2757
+ * Additional suggested generic actions for future consideration:
2758
+ *
2759
+ * Data & Content Actions:
2760
+ * - Search = 'search' - Search functionality
2761
+ * - Filter = 'filter' - Apply filters
2762
+ * - Sort = 'sort' - Sort data
2763
+ * - Group = 'group' - Group data
2764
+ * - Expand = 'expand' - Expand details
2765
+ * - Collapse = 'collapse' - Collapse details
2766
+ * - Pin = 'pin' - Pin to favorites
2767
+ * - Bookmark = 'bookmark' - Bookmark item
2768
+ * - Favorite = 'favorite' - Mark as favorite
2769
+ * - Star = 'star' - Star rating
2770
+ *
2771
+ * Workflow Actions:
2772
+ * - Start = 'start' - Start process/workflow
2773
+ * - Stop = 'stop' - Stop process
2774
+ * - Pause = 'pause' - Pause process
2775
+ * - Resume = 'resume' - Resume process
2776
+ * - Cancel = 'cancel' - Cancel operation
2777
+ * - Complete = 'complete' - Mark as complete
2778
+ * - Close = 'close' - Close item
2779
+ * - Reopen = 'reopen' - Reopen closed item
2780
+ * - Forward = 'forward' - Forward to next step
2781
+ * - Back = 'back' - Go back
2782
+ *
2783
+ * Communication Actions:
2784
+ * - Reply = 'reply' - Reply to message
2785
+ * - Forward = 'forward' - Forward message
2786
+ * - Notify = 'notify' - Send notification
2787
+ * - Invite = 'invite' - Invite user
2788
+ * - Join = 'join' - Join group/meeting
2789
+ * - Leave = 'leave' - Leave group/meeting
2790
+ *
2791
+ * Security Actions:
2792
+ * - Login = 'login' - User login
2793
+ * - Logout = 'logout' - User logout
2794
+ * - Block = 'block' - Block user/content
2795
+ * - Unblock = 'unblock' - Unblock user/content
2796
+ * - Ban = 'ban' - Ban user
2797
+ * - Unban = 'unban' - Unban user
2798
+ * - Verify = 'verify' - Verify identity
2799
+ * - Authenticate = 'authenticate' - Authenticate
2800
+ *
2801
+ * File & Media Actions:
2802
+ * - Open = 'open' - Open file
2803
+ * - Save = 'save' - Save file
2804
+ * - SaveAs = 'save-as' - Save as new file
2805
+ * - Attach = 'attach' - Attach file
2806
+ * - Detach = 'detach' - Detach file
2807
+ * - Compress = 'compress' - Compress files
2808
+ * - Extract = 'extract' - Extract archive
2809
+ * - Convert = 'convert' - Convert format
2810
+ * - Crop = 'crop' - Crop image
2811
+ * - Resize = 'resize' - Resize image
2812
+ *
2813
+ * System Actions:
2814
+ * - Sync = 'sync' - Synchronize data
2815
+ * - Backup = 'backup' - Create backup
2816
+ * - Restore = 'restore' - Restore from backup
2817
+ * - Reset = 'reset' - Reset to defaults
2818
+ * - Clear = 'clear' - Clear data
2819
+ * - Optimize = 'optimize' - Optimize performance
2820
+ * - Update = 'update' - Update system
2821
+ * - Install = 'install' - Install component
2822
+ * - Uninstall = 'uninstall' - Uninstall component
2823
+ * - Enable = 'enable' - Enable feature
2824
+ * - Disable = 'disable' - Disable feature
2825
+ *
2826
+ * Analytics & Monitoring:
2827
+ * - Monitor = 'monitor' - Monitor activity
2828
+ * - Track = 'track' - Track progress
2829
+ * - Analyze = 'analyze' - Analyze data
2830
+ * - Debug = 'debug' - Debug issue
2831
+ * - Log = 'log' - View logs
2832
+ * - Alert = 'alert' - Set alert
2833
+ * - Dashboard = 'dashboard' - View dashboard
2834
+ * - Metrics = 'metrics' - View metrics
2835
+ *
2836
+ * Collaboration Actions:
2837
+ * - Collaborate = 'collaborate' - Start collaboration
2838
+ * - Share = 'share' - Share content
2839
+ * - Comment = 'comment' - Add comment
2840
+ * - Like = 'like' - Like content
2841
+ * - Follow = 'follow' - Follow user/content
2842
+ * - Subscribe = 'subscribe' - Subscribe to updates
2843
+ * - Unsubscribe = 'unsubscribe' - Unsubscribe
2844
+ * - Rate = 'rate' - Rate content
2845
+ * - Review = 'review' - Review content
2846
+ * - Recommend = 'recommend' - Recommend content
2847
+ */
2848
+ var AXPSystemActionType;
2849
+ (function (AXPSystemActionType) {
2850
+ AXPSystemActionType["View"] = "view";
2851
+ AXPSystemActionType["Create"] = "create";
2852
+ AXPSystemActionType["Update"] = "update";
2853
+ AXPSystemActionType["Delete"] = "delete";
2854
+ AXPSystemActionType["Approve"] = "approve";
2855
+ AXPSystemActionType["Reject"] = "reject";
2856
+ AXPSystemActionType["Submit"] = "submit";
2857
+ AXPSystemActionType["Export"] = "export";
2858
+ AXPSystemActionType["Import"] = "import";
2859
+ AXPSystemActionType["Print"] = "print";
2860
+ AXPSystemActionType["Assign"] = "assign";
2861
+ AXPSystemActionType["Lock"] = "lock";
2862
+ AXPSystemActionType["Unlock"] = "unlock";
2863
+ AXPSystemActionType["Share"] = "share";
2864
+ AXPSystemActionType["Configure"] = "configure";
2865
+ AXPSystemActionType["Reorder"] = "reorder";
2866
+ AXPSystemActionType["Preview"] = "preview";
2867
+ AXPSystemActionType["Duplicate"] = "duplicate";
2868
+ AXPSystemActionType["Archive"] = "archive";
2869
+ AXPSystemActionType["Publish"] = "publish";
2870
+ AXPSystemActionType["Unpublish"] = "unpublish";
2871
+ AXPSystemActionType["Upload"] = "upload";
2872
+ AXPSystemActionType["Download"] = "download";
2873
+ AXPSystemActionType["Copy"] = "copy";
2874
+ AXPSystemActionType["Move"] = "move";
2875
+ AXPSystemActionType["Rename"] = "rename";
2876
+ AXPSystemActionType["Restore"] = "restore";
2877
+ AXPSystemActionType["Manage"] = "manage";
2878
+ AXPSystemActionType["Info"] = "info";
2879
+ AXPSystemActionType["Confirm"] = "confirm";
2880
+ AXPSystemActionType["Design"] = "design";
2881
+ AXPSystemActionType["VersionHistory"] = "version-history";
2882
+ AXPSystemActionType["Compare"] = "compare";
2883
+ AXPSystemActionType["Comments"] = "comments";
2884
+ AXPSystemActionType["Sign"] = "sign";
2885
+ AXPSystemActionType["Setup"] = "setup";
2886
+ AXPSystemActionType["Send"] = "send";
2887
+ AXPSystemActionType["Report"] = "report";
2888
+ AXPSystemActionType["Sent"] = "sent";
2889
+ AXPSystemActionType["Review"] = "review";
2890
+ AXPSystemActionType["Generate"] = "generate";
2891
+ AXPSystemActionType["Refresh"] = "refresh";
2892
+ AXPSystemActionType["Reload"] = "reload";
2893
+ AXPSystemActionType["Search"] = "search";
2894
+ AXPSystemActionType["Filter"] = "filter";
2895
+ AXPSystemActionType["Sort"] = "sort";
2896
+ AXPSystemActionType["Start"] = "start";
2897
+ AXPSystemActionType["Stop"] = "stop";
2898
+ AXPSystemActionType["Pause"] = "pause";
2899
+ AXPSystemActionType["Cancel"] = "cancel";
2900
+ AXPSystemActionType["Close"] = "close";
2901
+ AXPSystemActionType["Complete"] = "complete";
2902
+ AXPSystemActionType["Save"] = "save";
2903
+ AXPSystemActionType["SaveAs"] = "save-as";
2904
+ AXPSystemActionType["Sync"] = "sync";
2905
+ AXPSystemActionType["Reset"] = "reset";
2906
+ AXPSystemActionType["Clear"] = "clear";
2907
+ AXPSystemActionType["Distribution"] = "distribution";
2908
+ })(AXPSystemActionType || (AXPSystemActionType = {}));
2909
+ const i18n = (key) => `@general:actions.${key}`;
2910
+ const AXPSystemActions = Object.freeze({
2911
+ View: {
2912
+ key: AXPSystemActionType.View,
2913
+ title: i18n('view.title'),
2914
+ icon: 'fa-light fa-eye',
2915
+ color: 'primary',
2916
+ descriptions: {
2917
+ title: i18n('view.title'),
2918
+ tooltip: i18n('view.description'),
2919
+ permission: i18n('view.permission'),
2920
+ audit: i18n('view.audit')
2921
+ }
2922
+ },
2923
+ Create: {
2924
+ key: AXPSystemActionType.Create,
2925
+ title: i18n('create.title'),
2926
+ icon: 'fa-light fa-plus',
2927
+ color: 'primary',
2928
+ descriptions: {
2929
+ title: i18n('create.title'),
2930
+ tooltip: i18n('create.description'),
2931
+ permission: i18n('create.permission'),
2932
+ audit: i18n('create.audit')
2933
+ }
2934
+ },
2935
+ Edit: {
2936
+ key: AXPSystemActionType.Update,
2937
+ title: i18n('edit.title'),
2938
+ icon: 'fa-light fa-pen',
2939
+ color: 'default',
2940
+ descriptions: {
2941
+ title: i18n('edit.title'),
2942
+ tooltip: i18n('edit.description'),
2943
+ permission: i18n('edit.permission'),
2944
+ audit: i18n('edit.audit')
2945
+ }
2946
+ },
2947
+ Delete: {
2948
+ key: AXPSystemActionType.Delete,
2949
+ title: i18n('delete.title'),
2950
+ icon: 'fa-light fa-trash',
2951
+ color: 'danger',
2952
+ critical: true,
2953
+ descriptions: {
2954
+ title: i18n('delete.title'),
2955
+ tooltip: i18n('delete.description'),
2956
+ permission: i18n('delete.permission'),
2957
+ audit: i18n('delete.audit')
2958
+ }
2959
+ },
2960
+ Approve: {
2961
+ key: AXPSystemActionType.Approve,
2962
+ title: i18n('approve.title'),
2963
+ icon: 'fa-light fa-circle-check',
2964
+ color: 'success',
2965
+ critical: true,
2966
+ descriptions: {
2967
+ title: i18n('approve.title'),
2968
+ tooltip: i18n('approve.description'),
2969
+ permission: i18n('approve.permission'),
2970
+ audit: i18n('approve.audit')
2971
+ }
2972
+ },
2973
+ Submit: {
2974
+ key: AXPSystemActionType.Submit,
2975
+ title: i18n('submit.title'),
2976
+ icon: 'fa-light fa-paper-plane',
2977
+ color: 'primary',
2978
+ descriptions: {
2979
+ title: i18n('submit.title'),
2980
+ tooltip: i18n('submit.description'),
2981
+ permission: i18n('submit.permission'),
2982
+ audit: i18n('submit.audit')
2983
+ }
2984
+ },
2985
+ Reject: {
2986
+ key: AXPSystemActionType.Reject,
2987
+ title: i18n('reject.title'),
2988
+ icon: 'fa-light fa-ban',
2989
+ color: 'danger',
2990
+ critical: true,
2991
+ descriptions: {
2992
+ title: i18n('reject.title'),
2993
+ tooltip: i18n('reject.description'),
2994
+ permission: i18n('reject.permission'),
2995
+ audit: i18n('reject.audit')
2996
+ }
2997
+ },
2998
+ Export: {
2999
+ key: AXPSystemActionType.Export,
3000
+ title: i18n('export.title'),
3001
+ icon: 'fa-light fa-download',
3002
+ color: 'default',
3003
+ descriptions: {
3004
+ title: i18n('export.title'),
3005
+ tooltip: i18n('export.description'),
3006
+ permission: i18n('export.permission'),
3007
+ audit: i18n('export.audit')
3008
+ }
3009
+ },
3010
+ Import: {
3011
+ key: AXPSystemActionType.Import,
3012
+ title: i18n('import.title'),
3013
+ icon: 'fa-light fa-upload',
3014
+ color: 'default',
3015
+ descriptions: {
3016
+ title: i18n('import.title'),
3017
+ tooltip: i18n('import.description'),
3018
+ permission: i18n('import.permission'),
3019
+ audit: i18n('import.audit')
3020
+ }
3021
+ },
3022
+ Print: {
3023
+ key: AXPSystemActionType.Print,
3024
+ title: i18n('print.title'),
3025
+ icon: 'fa-light fa-print',
3026
+ color: 'default',
3027
+ descriptions: {
3028
+ title: i18n('print.title'),
3029
+ tooltip: i18n('print.description'),
3030
+ permission: i18n('print.permission'),
3031
+ audit: i18n('print.audit')
3032
+ }
3033
+ },
3034
+ Duplicate: {
3035
+ key: AXPSystemActionType.Duplicate,
3036
+ title: i18n('duplicate.title'),
3037
+ icon: 'fa-light fa-clone',
3038
+ color: 'warning',
3039
+ descriptions: {
3040
+ title: i18n('duplicate.title'),
3041
+ tooltip: i18n('duplicate.description'),
3042
+ permission: i18n('duplicate.permission'),
3043
+ audit: i18n('duplicate.audit')
3044
+ }
3045
+ },
3046
+ Archive: {
3047
+ key: AXPSystemActionType.Archive,
3048
+ title: i18n('archive.title'),
3049
+ icon: 'fa-light fa-box-archive',
3050
+ color: 'default',
3051
+ descriptions: {
3052
+ title: i18n('archive.title'),
3053
+ tooltip: i18n('archive.description'),
3054
+ permission: i18n('archive.permission'),
3055
+ audit: i18n('archive.audit')
3056
+ }
3057
+ },
3058
+ Restore: {
3059
+ key: AXPSystemActionType.Restore,
3060
+ title: i18n('restore.title'),
3061
+ icon: 'fa-light fa-arrow-rotate-left',
3062
+ color: 'default',
3063
+ descriptions: {
3064
+ title: i18n('restore.title'),
3065
+ tooltip: i18n('restore.description'),
3066
+ permission: i18n('restore.permission'),
3067
+ audit: i18n('restore.audit')
3068
+ }
3069
+ },
3070
+ Assign: {
3071
+ key: AXPSystemActionType.Assign,
3072
+ title: i18n('assign.title'),
3073
+ icon: 'fa-light fa-user-plus',
3074
+ color: 'primary',
3075
+ descriptions: {
3076
+ title: i18n('assign.title'),
3077
+ tooltip: i18n('assign.description'),
3078
+ permission: i18n('assign.permission'),
3079
+ audit: i18n('assign.audit')
3080
+ }
3081
+ },
3082
+ Lock: {
3083
+ key: AXPSystemActionType.Lock,
3084
+ title: i18n('lock.title'),
3085
+ icon: 'fa-light fa-lock',
3086
+ color: 'warning',
3087
+ descriptions: {
3088
+ title: i18n('lock.title'),
3089
+ tooltip: i18n('lock.description'),
3090
+ permission: i18n('lock.permission'),
3091
+ audit: i18n('lock.audit')
3092
+ }
3093
+ },
3094
+ Unlock: {
3095
+ key: AXPSystemActionType.Unlock,
3096
+ title: i18n('unlock.title'),
3097
+ icon: 'fa-light fa-unlock',
3098
+ color: 'success',
3099
+ descriptions: {
3100
+ title: i18n('unlock.title'),
3101
+ tooltip: i18n('unlock.description'),
3102
+ permission: i18n('unlock.permission'),
3103
+ audit: i18n('unlock.audit')
3104
+ }
3105
+ },
3106
+ Share: {
3107
+ key: AXPSystemActionType.Share,
3108
+ title: i18n('share.title'),
3109
+ icon: 'fa-light fa-share-nodes',
3110
+ color: 'info',
3111
+ descriptions: {
3112
+ title: i18n('share.title'),
3113
+ tooltip: i18n('share.description'),
3114
+ permission: i18n('share.permission'),
3115
+ audit: i18n('share.audit')
3116
+ }
3117
+ },
3118
+ Configure: {
3119
+ key: AXPSystemActionType.Configure,
3120
+ title: i18n('configure.title'),
3121
+ icon: 'fa-light fa-sliders',
3122
+ color: 'primary',
3123
+ descriptions: {
3124
+ title: i18n('configure.title'),
3125
+ tooltip: i18n('configure.description'),
3126
+ permission: i18n('configure.permission'),
3127
+ audit: i18n('configure.audit')
3128
+ }
3129
+ },
3130
+ Reorder: {
3131
+ key: AXPSystemActionType.Reorder,
3132
+ title: i18n('reorder.title'),
3133
+ icon: 'fa-light fa-arrow-down-up-across-line',
3134
+ color: 'default',
3135
+ descriptions: {
3136
+ title: i18n('reorder.title'),
3137
+ tooltip: i18n('reorder.description'),
3138
+ permission: i18n('reorder.permission'),
3139
+ audit: i18n('reorder.audit')
3140
+ }
3141
+ },
3142
+ Preview: {
3143
+ key: AXPSystemActionType.Preview,
3144
+ title: i18n('preview.title'),
3145
+ icon: 'fa-light fa-magnifying-glass',
3146
+ color: 'default',
3147
+ descriptions: {
3148
+ title: i18n('preview.title'),
3149
+ tooltip: i18n('preview.description'),
3150
+ permission: i18n('preview.permission'),
3151
+ audit: i18n('preview.audit')
3152
+ }
3153
+ },
3154
+ Publish: {
3155
+ key: AXPSystemActionType.Publish,
3156
+ title: i18n('publish.title'),
3157
+ icon: 'fa-light fa-globe',
3158
+ color: 'success',
3159
+ descriptions: {
3160
+ title: i18n('publish.title'),
3161
+ tooltip: i18n('publish.description'),
3162
+ permission: i18n('publish.permission'),
3163
+ audit: i18n('publish.audit')
3164
+ }
3165
+ },
3166
+ Unpublish: {
3167
+ key: AXPSystemActionType.Unpublish,
3168
+ title: i18n('unpublish.title'),
3169
+ icon: 'fa-light fa-globe-slash',
3170
+ color: 'danger',
3171
+ descriptions: {
3172
+ title: i18n('unpublish.title'),
3173
+ tooltip: i18n('unpublish.description'),
3174
+ permission: i18n('unpublish.permission'),
3175
+ audit: i18n('unpublish.audit')
3176
+ }
3177
+ },
3178
+ Upload: {
3179
+ key: AXPSystemActionType.Upload,
3180
+ title: i18n('upload.title'),
3181
+ icon: 'fa-light fa-upload',
3182
+ color: 'default',
3183
+ descriptions: {
3184
+ title: i18n('upload.title'),
3185
+ tooltip: i18n('upload.description'),
3186
+ permission: i18n('upload.permission'),
3187
+ audit: i18n('upload.audit')
3188
+ }
3189
+ },
3190
+ Download: {
3191
+ key: AXPSystemActionType.Download,
3192
+ title: i18n('download.title'),
3193
+ icon: 'fa-light fa-download',
3194
+ color: 'default',
3195
+ descriptions: {
3196
+ title: i18n('download.title'),
3197
+ tooltip: i18n('download.description'),
3198
+ permission: i18n('download.permission'),
3199
+ audit: i18n('download.audit')
3200
+ }
3201
+ },
3202
+ Copy: {
3203
+ key: AXPSystemActionType.Copy,
3204
+ title: i18n('copy.title'),
3205
+ icon: 'fa-light fa-copy',
3206
+ color: 'default',
3207
+ descriptions: {
3208
+ title: i18n('copy.title'),
3209
+ tooltip: i18n('copy.description'),
3210
+ permission: i18n('copy.permission'),
3211
+ audit: i18n('copy.audit')
3212
+ }
3213
+ },
3214
+ Move: {
3215
+ key: AXPSystemActionType.Move,
3216
+ title: i18n('move.title'),
3217
+ icon: 'fa-light fa-arrow-right-arrow-left',
3218
+ color: 'default',
3219
+ descriptions: {
3220
+ title: i18n('move.title'),
3221
+ tooltip: i18n('move.description'),
3222
+ permission: i18n('move.permission'),
3223
+ audit: i18n('move.audit')
3224
+ }
3225
+ },
3226
+ Rename: {
3227
+ key: AXPSystemActionType.Rename,
3228
+ title: i18n('rename.title'),
3229
+ icon: 'fa-light fa-pen',
3230
+ color: 'default',
3231
+ descriptions: {
3232
+ title: i18n('rename.title'),
3233
+ tooltip: i18n('rename.description'),
3234
+ permission: i18n('rename.permission'),
3235
+ audit: i18n('rename.audit')
3236
+ }
3237
+ },
3238
+ Manage: {
3239
+ key: AXPSystemActionType.Manage,
3240
+ title: i18n('manage.title'),
3241
+ icon: 'fa-light fa-gear',
3242
+ color: 'default',
3243
+ descriptions: {
3244
+ title: i18n('manage.title'),
3245
+ tooltip: i18n('manage.description'),
3246
+ permission: i18n('manage.permission'),
3247
+ audit: i18n('manage.audit')
3248
+ }
3249
+ },
3250
+ Info: {
3251
+ key: AXPSystemActionType.Info,
3252
+ title: i18n('info.title'),
3253
+ icon: 'fa-light fa-info',
3254
+ color: 'default',
3255
+ descriptions: {
3256
+ title: i18n('info.title'),
3257
+ tooltip: i18n('info.description'),
3258
+ permission: i18n('info.permission'),
3259
+ audit: i18n('info.audit')
3260
+ }
3261
+ },
3262
+ Confirm: {
3263
+ key: AXPSystemActionType.Confirm,
3264
+ title: i18n('confirm.title'),
3265
+ icon: 'fa-light fa-check',
3266
+ color: 'success',
3267
+ descriptions: {
3268
+ title: i18n('confirm.title'),
3269
+ tooltip: i18n('confirm.description'),
3270
+ permission: i18n('confirm.permission'),
3271
+ audit: i18n('confirm.audit')
3272
+ }
3273
+ },
3274
+ Design: {
3275
+ key: AXPSystemActionType.Design,
3276
+ title: i18n('design.title'),
3277
+ icon: 'fa-light fa-paintbrush',
3278
+ color: 'default',
3279
+ descriptions: {
3280
+ title: i18n('design.title'),
3281
+ tooltip: i18n('design.description'),
3282
+ permission: i18n('design.permission'),
3283
+ audit: i18n('design.audit')
3284
+ }
3285
+ },
3286
+ VersionHistory: {
3287
+ key: AXPSystemActionType.VersionHistory,
3288
+ title: i18n('version-history.title'),
3289
+ icon: 'fa-light fa-history',
3290
+ color: 'default',
3291
+ descriptions: {
3292
+ title: i18n('version-history.title'),
3293
+ tooltip: i18n('version-history.description'),
3294
+ permission: i18n('version-history.permission'),
3295
+ audit: i18n('version-history.audit')
3296
+ }
3297
+ },
3298
+ Compare: {
3299
+ key: AXPSystemActionType.Compare,
3300
+ title: i18n('compare.title'),
3301
+ icon: 'fa-light fa-code-compare',
3302
+ color: 'default',
3303
+ descriptions: {
3304
+ title: i18n('compare.title'),
3305
+ tooltip: i18n('compare.description'),
3306
+ permission: i18n('compare.permission'),
3307
+ audit: i18n('compare.audit')
3308
+ }
3309
+ },
3310
+ Comments: {
3311
+ key: AXPSystemActionType.Comments,
3312
+ title: i18n('comments.title'),
3313
+ icon: 'fa-light fa-comments',
3314
+ color: 'default',
3315
+ descriptions: {
3316
+ title: i18n('comments.title'),
3317
+ tooltip: i18n('comments.description'),
3318
+ permission: i18n('comments.permission'),
3319
+ audit: i18n('comments.audit')
3320
+ }
3321
+ },
3322
+ Sign: {
3323
+ key: AXPSystemActionType.Sign,
3324
+ title: i18n('sign.title'),
3325
+ icon: 'fa-light fa-signature',
3326
+ color: 'default',
3327
+ descriptions: {
3328
+ title: i18n('sign.title'),
3329
+ tooltip: i18n('sign.description'),
3330
+ permission: i18n('sign.permission'),
3331
+ audit: i18n('sign.audit')
3332
+ }
3333
+ },
3334
+ Setup: {
3335
+ key: AXPSystemActionType.Setup,
3336
+ title: i18n('setup.title'),
3337
+ icon: 'fa-light fa-cog',
3338
+ color: 'default',
3339
+ descriptions: {
3340
+ title: i18n('setup.title'),
3341
+ tooltip: i18n('setup.description'),
3342
+ permission: i18n('setup.permission'),
3343
+ audit: i18n('setup.audit')
3344
+ }
3345
+ },
3346
+ Send: {
3347
+ key: AXPSystemActionType.Send,
3348
+ title: i18n('send.title'),
3349
+ icon: 'fa-light fa-envelope',
3350
+ color: 'default',
3351
+ descriptions: {
3352
+ title: i18n('send.title'),
3353
+ tooltip: i18n('send.description'),
3354
+ permission: i18n('send.permission'),
3355
+ audit: i18n('send.audit')
3356
+ }
3357
+ },
3358
+ Report: {
3359
+ key: AXPSystemActionType.Report,
3360
+ title: i18n('report.title'),
3361
+ icon: 'fa-light fa-chart-line',
3362
+ color: 'default',
3363
+ descriptions: {
3364
+ title: i18n('report.title'),
3365
+ tooltip: i18n('report.description'),
3366
+ permission: i18n('report.permission'),
3367
+ audit: i18n('report.audit')
3368
+ }
3369
+ },
3370
+ Sent: {
3371
+ key: AXPSystemActionType.Sent,
3372
+ title: i18n('sent.title'),
3373
+ icon: 'fa-light fa-paper-plane',
3374
+ color: 'default',
3375
+ descriptions: {
3376
+ title: i18n('sent.title'),
3377
+ tooltip: i18n('sent.description'),
3378
+ permission: i18n('sent.permission'),
3379
+ audit: i18n('sent.audit')
3380
+ }
3381
+ },
3382
+ Review: {
3383
+ key: AXPSystemActionType.Review,
3384
+ title: i18n('review.title'),
3385
+ icon: 'fa-light fa-eye',
3386
+ color: 'default',
3387
+ descriptions: {
3388
+ title: i18n('review.title'),
3389
+ tooltip: i18n('review.description'),
3390
+ permission: i18n('review.permission'),
3391
+ audit: i18n('review.audit')
3392
+ }
3393
+ },
3394
+ Generate: {
3395
+ key: AXPSystemActionType.Generate,
3396
+ title: i18n('generate.title'),
3397
+ icon: 'fa-light fa-wand-magic-sparkles',
3398
+ color: 'primary',
3399
+ descriptions: {
3400
+ title: i18n('generate.title'),
3401
+ tooltip: i18n('generate.description'),
3402
+ permission: i18n('generate.permission'),
3403
+ audit: i18n('generate.audit')
3404
+ }
3405
+ },
3406
+ Refresh: {
3407
+ key: AXPSystemActionType.Refresh,
3408
+ title: i18n('refresh.title'),
3409
+ icon: 'fa-light fa-arrows-rotate',
3410
+ color: 'default',
3411
+ descriptions: {
3412
+ title: i18n('refresh.title'),
3413
+ tooltip: i18n('refresh.description'),
3414
+ permission: i18n('refresh.permission'),
3415
+ audit: i18n('refresh.audit')
3416
+ }
3417
+ },
3418
+ Reload: {
3419
+ key: AXPSystemActionType.Reload,
3420
+ title: i18n('reload.title'),
3421
+ icon: 'fa-light fa-arrows-rotate',
3422
+ color: 'default',
3423
+ descriptions: {
3424
+ title: i18n('reload.title'),
3425
+ tooltip: i18n('reload.description'),
3426
+ permission: i18n('reload.permission'),
3427
+ audit: i18n('reload.audit')
3428
+ }
3429
+ },
3430
+ Search: {
3431
+ key: AXPSystemActionType.Search,
3432
+ title: i18n('search.title'),
3433
+ icon: 'fa-light fa-magnifying-glass',
3434
+ color: 'default',
3435
+ descriptions: {
3436
+ title: i18n('search.title'),
3437
+ tooltip: i18n('search.description'),
3438
+ permission: i18n('search.permission'),
3439
+ audit: i18n('search.audit')
3440
+ }
3441
+ },
3442
+ Filter: {
3443
+ key: AXPSystemActionType.Filter,
3444
+ title: i18n('filter.title'),
3445
+ icon: 'fa-light fa-filter',
3446
+ color: 'default',
3447
+ descriptions: {
3448
+ title: i18n('filter.title'),
3449
+ tooltip: i18n('filter.description'),
3450
+ permission: i18n('filter.permission'),
3451
+ audit: i18n('filter.audit')
3452
+ }
3453
+ },
3454
+ Sort: {
3455
+ key: AXPSystemActionType.Sort,
3456
+ title: i18n('sort.title'),
3457
+ icon: 'fa-light fa-arrow-down-up-across-line',
3458
+ color: 'default',
3459
+ descriptions: {
3460
+ title: i18n('sort.title'),
3461
+ tooltip: i18n('sort.description'),
3462
+ permission: i18n('sort.permission'),
3463
+ audit: i18n('sort.audit')
3464
+ }
3465
+ },
3466
+ Start: {
3467
+ key: AXPSystemActionType.Start,
3468
+ title: i18n('start.title'),
3469
+ icon: 'fa-light fa-play',
3470
+ color: 'success',
3471
+ descriptions: {
3472
+ title: i18n('start.title'),
3473
+ tooltip: i18n('start.description'),
3474
+ permission: i18n('start.permission'),
3475
+ audit: i18n('start.audit')
3476
+ }
3477
+ },
3478
+ Stop: {
3479
+ key: AXPSystemActionType.Stop,
3480
+ title: i18n('stop.title'),
3481
+ icon: 'fa-light fa-stop',
3482
+ color: 'danger',
3483
+ critical: true,
3484
+ descriptions: {
3485
+ title: i18n('stop.title'),
3486
+ tooltip: i18n('stop.description'),
3487
+ permission: i18n('stop.permission'),
3488
+ audit: i18n('stop.audit')
3489
+ }
3490
+ },
3491
+ Pause: {
3492
+ key: AXPSystemActionType.Pause,
3493
+ title: i18n('pause.title'),
3494
+ icon: 'fa-light fa-pause',
3495
+ color: 'warning',
3496
+ descriptions: {
3497
+ title: i18n('pause.title'),
3498
+ tooltip: i18n('pause.description'),
3499
+ permission: i18n('pause.permission'),
3500
+ audit: i18n('pause.audit')
3501
+ }
3502
+ },
3503
+ Cancel: {
3504
+ key: AXPSystemActionType.Cancel,
3505
+ title: i18n('cancel.title'),
3506
+ icon: 'fa-light fa-xmark',
3507
+ critical: true,
3508
+ descriptions: {
3509
+ title: i18n('cancel.title'),
3510
+ tooltip: i18n('cancel.description'),
3511
+ permission: i18n('cancel.permission'),
3512
+ audit: i18n('cancel.audit')
3513
+ }
3514
+ },
3515
+ Close: {
3516
+ key: AXPSystemActionType.Close,
3517
+ title: i18n('close.title'),
3518
+ icon: 'fa-light fa-xmark',
3519
+ color: 'default',
3520
+ descriptions: {
3521
+ title: i18n('close.title'),
3522
+ tooltip: i18n('close.description'),
3523
+ permission: i18n('close.permission'),
3524
+ audit: i18n('close.audit')
3525
+ }
3526
+ },
3527
+ Complete: {
3528
+ key: AXPSystemActionType.Complete,
3529
+ title: i18n('complete.title'),
3530
+ icon: 'fa-light fa-check',
3531
+ color: 'success',
3532
+ descriptions: {
3533
+ title: i18n('complete.title'),
3534
+ tooltip: i18n('complete.description'),
3535
+ permission: i18n('complete.permission'),
3536
+ audit: i18n('complete.audit')
3537
+ }
3538
+ },
3539
+ Save: {
3540
+ key: AXPSystemActionType.Save,
3541
+ title: i18n('save.title'),
3542
+ icon: 'fa-light fa-floppy-disk',
3543
+ color: 'primary',
3544
+ descriptions: {
3545
+ title: i18n('save.title'),
3546
+ tooltip: i18n('save.description'),
3547
+ permission: i18n('save.permission'),
3548
+ audit: i18n('save.audit')
3549
+ }
3550
+ },
3551
+ SaveAs: {
3552
+ key: AXPSystemActionType.SaveAs,
3553
+ title: i18n('save-as.title'),
3554
+ icon: 'fa-light fa-floppy-disk',
3555
+ color: 'default',
3556
+ descriptions: {
3557
+ title: i18n('save-as.title'),
3558
+ tooltip: i18n('save-as.description'),
3559
+ permission: i18n('save-as.permission'),
3560
+ audit: i18n('save-as.audit')
3561
+ }
3562
+ },
3563
+ Sync: {
3564
+ key: AXPSystemActionType.Sync,
3565
+ title: i18n('sync.title'),
3566
+ icon: 'fa-light fa-arrows-rotate',
3567
+ color: 'default',
3568
+ descriptions: {
3569
+ title: i18n('sync.title'),
3570
+ tooltip: i18n('sync.description'),
3571
+ permission: i18n('sync.permission'),
3572
+ audit: i18n('sync.audit')
3573
+ }
3574
+ },
3575
+ Reset: {
3576
+ key: AXPSystemActionType.Reset,
3577
+ title: i18n('reset.title'),
3578
+ icon: 'fa-light fa-arrow-rotate-left',
3579
+ color: 'warning',
3580
+ critical: true,
3581
+ descriptions: {
3582
+ title: i18n('reset.title'),
3583
+ tooltip: i18n('reset.description'),
3584
+ permission: i18n('reset.permission'),
3585
+ audit: i18n('reset.audit')
3586
+ }
3587
+ },
3588
+ Clear: {
3589
+ key: AXPSystemActionType.Clear,
3590
+ title: i18n('clear.title'),
3591
+ icon: 'fa-light fa-eraser',
3592
+ color: 'default',
3593
+ descriptions: {
3594
+ title: i18n('clear.title'),
3595
+ tooltip: i18n('clear.description'),
3596
+ permission: i18n('clear.permission'),
3597
+ audit: i18n('clear.audit')
3598
+ }
3599
+ },
3600
+ Distribution: {
3601
+ key: AXPSystemActionType.Distribution,
3602
+ title: i18n('distribution.title'),
3603
+ icon: 'fa-light fa-share-nodes',
3604
+ color: 'default',
3605
+ descriptions: {
3606
+ title: i18n('distribution.title'),
3607
+ tooltip: i18n('distribution.description'),
3608
+ permission: i18n('distribution.permission'),
3609
+ audit: i18n('distribution.audit')
3610
+ }
3611
+ },
3612
+ });
3613
+ function getSystemActions(type) {
3614
+ return Object.values(AXPSystemActions).find(action => action.key === type);
3615
+ }
3616
+ /**
3617
+ * Resolves the visual appearance (color and icon) for entity actions
3618
+ * using the system actions from the core module.
3619
+ */
3620
+ function resolveActionLook(actionType) {
3621
+ // Try to get system action first
3622
+ const systemActionType = actionType;
3623
+ if (systemActionType) {
3624
+ const systemAction = getSystemActions(systemActionType);
3625
+ if (systemAction) {
3626
+ return {
3627
+ color: (systemAction.color || 'default'),
3628
+ icon: systemAction.icon || ''
3629
+ };
3630
+ }
3631
+ }
3632
+ // Fallback for unknown actions
3633
+ return {
3634
+ color: 'default',
3635
+ icon: ''
3636
+ };
3637
+ }
3638
+ /**
3639
+ * Resolves the title, description, icon and color for button actions
3640
+ * using the system actions from the core module.
3641
+ * @param actionType
3642
+ * @returns
3643
+ */
3644
+ function getActionButton(actionType) {
3645
+ const systemActionType = actionType;
3646
+ if (systemActionType) {
3647
+ const systemAction = getSystemActions(systemActionType);
3648
+ if (systemAction) {
3649
+ return {
3650
+ name: actionType,
3651
+ icon: systemAction.icon || '',
3652
+ color: systemAction.color || 'default',
3653
+ title: systemAction.title,
3654
+ description: systemAction.descriptions.title
3655
+ };
3656
+ }
3657
+ }
3658
+ // Fallback for unknown actions
3659
+ return {
3660
+ name: actionType,
3661
+ title: actionType,
3662
+ description: `Perform ${actionType} action`,
3663
+ icon: '',
3664
+ color: 'default'
3665
+ };
3666
+ }
3667
+
3668
+ function getNestedKeys(obj, prefix = '') {
3669
+ let keys = [];
3670
+ for (const key in obj) {
3671
+ if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
3672
+ keys = [...keys, ...getNestedKeys(obj[key], prefix + key + '.')];
3673
+ }
3674
+ else {
3675
+ keys.push(prefix + key);
3676
+ }
3677
+ }
3678
+ return keys;
3679
+ }
3680
+
3681
+ //#region ---- Imports ----
3682
+ //#endregion
3683
+
3684
+ function applySystemActionDefault(action, type) {
3685
+ const systemAction = getSystemActions(type);
3686
+ return {
3687
+ name: systemAction.key,
3688
+ title: systemAction.title,
3689
+ icon: systemAction.icon,
3690
+ color: systemAction.color,
3691
+ };
3692
+ }
3693
+
3694
+ class AXPImageUrlLogoConfig {
3695
+ constructor(url, width, height) {
3696
+ this.url = url;
3697
+ this.width = width;
3698
+ this.height = height;
3699
+ }
3700
+ }
3701
+ class AXPComponentLogoConfig {
3702
+ constructor(component) {
3703
+ this.component = component;
3704
+ }
3705
+ }
3706
+ class AXPIconLogoConfig {
3707
+ constructor(icon, color) {
3708
+ this.icon = icon;
3709
+ this.color = color;
3710
+ }
3711
+ }
3712
+
3713
+ var AXPPlatformScope;
3714
+ (function (AXPPlatformScope) {
3715
+ AXPPlatformScope["Platform"] = "P";
3716
+ AXPPlatformScope["Tenant"] = "T";
3717
+ AXPPlatformScope["User"] = "U";
3718
+ })(AXPPlatformScope || (AXPPlatformScope = {}));
3719
+ ;
3720
+ function resolvePlatformScopeKey(name) {
3721
+ const scopeMap = {
3722
+ platform: AXPPlatformScope.Platform,
3723
+ tenant: AXPPlatformScope.Tenant,
3724
+ user: AXPPlatformScope.User,
3725
+ };
3726
+ return scopeMap[name.toLowerCase()] ?? AXPPlatformScope.User;
3727
+ }
3728
+ function resolvePlatformScopeName(scope) {
3729
+ const scopeMap = {
3730
+ P: 'platform',
3731
+ T: 'tenant',
3732
+ U: 'user',
3733
+ };
3734
+ return scopeMap[scope] ?? 'user';
3735
+ }
3736
+
3737
+ var AXPExportTemplateToken;
3738
+ (function (AXPExportTemplateToken) {
3739
+ AXPExportTemplateToken["Date"] = "{date}";
3740
+ AXPExportTemplateToken["Time"] = "{time}";
3741
+ AXPExportTemplateToken["User"] = "{user}";
3742
+ AXPExportTemplateToken["ReportTitle"] = "{title}";
3743
+ AXPExportTemplateToken["UUID"] = "{uuid}";
3744
+ })(AXPExportTemplateToken || (AXPExportTemplateToken = {}));
3745
+
3746
+ class AXPCountdownPipe {
3747
+ constructor() {
3748
+ this.calendarService = inject(AXCalendarService);
3749
+ this.countdownSignal = signal(this.setupTimer(), ...(ngDevMode ? [{ debugName: "countdownSignal" }] : /* istanbul ignore next */ []));
3750
+ this.targetDate = 0;
3751
+ this.prevValue = 0;
3752
+ }
3753
+ transform(value) {
3754
+ if (this.prevValue != value) {
3755
+ this.prevValue = value;
3756
+ const expireTime = this.calendarService.calendar.add(new Date(), 'second', value).date;
3757
+ this.updateTargetDate(expireTime.toISOString());
3758
+ }
3759
+ return this.countdownSignal();
3760
+ }
3761
+ setupTimer() {
3762
+ return interval(1000).pipe(startWith(0), map(() => {
3763
+ const diff = this.targetDate - new Date().getTime();
3764
+ if (diff < 0) {
3765
+ return "Time's up!";
3766
+ }
3767
+ const times = [86400, 3600, 60, 1].map((seconds) => Math.floor((diff / 1000 / seconds) % (seconds === 1 ? 60 : 24)));
3768
+ const labels = ['d', 'h', 'm', 's'];
3769
+ return times
3770
+ .map((t, i) => (t > 0 || i === 3 ? `${t}${labels[i]}` : ''))
3771
+ .join(' ')
3772
+ .trim();
3773
+ }));
3774
+ }
3775
+ updateTargetDate(value) {
3776
+ this.targetDate = new Date(value).getTime();
3777
+ }
3778
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCountdownPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3779
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPCountdownPipe, isStandalone: true, name: "countdown", pure: false }); }
3780
+ }
3781
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCountdownPipe, decorators: [{
3782
+ type: Pipe,
3783
+ args: [{
3784
+ name: 'countdown',
3785
+ pure: false,
3786
+ standalone: true,
3787
+ }]
3788
+ }] });
3789
+
3790
+ const loggingEnabled = false; // Set to true to enable logging, false to disable
3791
+ function applyCondition(item, condition) {
3792
+ const rawValue = condition.field ? get(item, condition.field) : null;
3793
+ const itemValue = typeof rawValue === 'string' ? rawValue.toLowerCase() : rawValue;
3794
+ const conditionValue = typeof condition.value === 'string' ? condition.value.toLowerCase() : condition.value;
3795
+ // Conditional Logging for debugging
3796
+ if (loggingEnabled) {
3797
+ console.log('Condition:', condition);
3798
+ console.log('Item Value:', itemValue);
3799
+ console.log('Condition Value:', conditionValue);
3800
+ }
3801
+ let result;
3802
+ const valueToCompare = isNil(condition.field) || condition.field === '' ? conditionValue : itemValue;
3803
+ const conditionType = condition?.operator?.type;
3804
+ if (!conditionType) {
3805
+ return true;
3806
+ }
3807
+ const op = String(conditionType);
3808
+ switch (op) {
3809
+ case 'equal':
3810
+ case 'eq':
3811
+ result = isEqual(valueToCompare, conditionValue);
3812
+ if (loggingEnabled) {
3813
+ console.log('Equal check result:', result);
3814
+ }
3815
+ break;
3816
+ case 'notEqual':
3817
+ case 'ne':
3818
+ case 'neq':
3819
+ result = !isEqual(valueToCompare, conditionValue);
3820
+ if (loggingEnabled) {
3821
+ console.log('Not equal check result:', result);
3822
+ }
3823
+ break;
3824
+ case 'greaterThan':
3825
+ case 'gt':
3826
+ result = gt(valueToCompare, conditionValue);
3827
+ if (loggingEnabled) {
3828
+ console.log('Greater than check result:', result);
3829
+ }
3830
+ break;
3831
+ case 'lessThan':
3832
+ case 'lt':
3833
+ result = lt(valueToCompare, conditionValue);
3834
+ if (loggingEnabled) {
3835
+ console.log('Less than check result:', result);
3836
+ }
3837
+ break;
3838
+ case 'greaterThanOrEqual':
3839
+ case 'gte':
3840
+ result = gte(valueToCompare, conditionValue);
3841
+ if (loggingEnabled) {
3842
+ console.log('Greater than or equal check result:', result);
3843
+ }
3844
+ break;
3845
+ case 'lessThanOrEqual':
3846
+ case 'lte':
3847
+ result = lte(valueToCompare, conditionValue);
3848
+ if (loggingEnabled) {
3849
+ console.log('Less than or equal check result:', result);
3850
+ }
3851
+ break;
3852
+ case 'contains':
3853
+ if (typeof valueToCompare === 'string') {
3854
+ result = includes(valueToCompare, conditionValue);
3855
+ }
3856
+ else if (Array.isArray(valueToCompare)) {
3857
+ result = includes(valueToCompare.map((val) => val.toString().toLowerCase()), conditionValue);
3858
+ }
3859
+ else {
3860
+ result = false;
3861
+ }
3862
+ if (loggingEnabled) {
3863
+ console.log('Contains check result:', result);
3864
+ }
3865
+ break;
3866
+ case 'in':
3867
+ if (Array.isArray(conditionValue)) {
3868
+ if (typeof valueToCompare === 'string') {
3869
+ result = conditionValue.some(val => typeof val === 'string' ? val.toLowerCase() === valueToCompare : val === valueToCompare);
3870
+ }
3871
+ else if (Array.isArray(valueToCompare)) {
3872
+ result = valueToCompare.some(val => conditionValue.some(condVal => typeof val === 'string' && typeof condVal === 'string'
3873
+ ? val.toLowerCase() === condVal.toLowerCase()
3874
+ : val === condVal));
3875
+ }
3876
+ else {
3877
+ result = conditionValue.includes(valueToCompare);
3878
+ }
3879
+ }
3880
+ else {
3881
+ result = false;
3882
+ }
3883
+ if (loggingEnabled) {
3884
+ console.log('In check result:', result);
3885
+ }
3886
+ break;
3887
+ case 'notContains':
3888
+ if (typeof valueToCompare === 'string') {
3889
+ result = !includes(valueToCompare, conditionValue);
3890
+ }
3891
+ else if (Array.isArray(valueToCompare)) {
3892
+ result = !includes(valueToCompare.map((val) => val.toString().toLowerCase()), conditionValue);
3893
+ }
3894
+ else {
3895
+ result = false;
3896
+ }
3897
+ if (loggingEnabled) {
3898
+ console.log('Not contains check result:', result);
3899
+ }
3900
+ break;
3901
+ case 'startsWith':
3902
+ result = typeof valueToCompare === 'string' && startsWith(valueToCompare, conditionValue);
3903
+ if (loggingEnabled) {
3904
+ console.log('Starts with check result:', result);
3905
+ }
3906
+ break;
3907
+ case 'endsWith':
3908
+ result = typeof valueToCompare === 'string' && endsWith(valueToCompare, conditionValue);
3909
+ if (loggingEnabled) {
3910
+ console.log('Ends with check result:', result);
3911
+ }
3912
+ break;
3913
+ case 'isEmpty':
3914
+ result = isEmpty(valueToCompare);
3915
+ if (loggingEnabled) {
3916
+ console.log('Is empty check result:', result);
3917
+ }
3918
+ break;
3919
+ case 'isNull':
3920
+ result = isNil(valueToCompare);
3921
+ if (loggingEnabled) {
3922
+ console.log('Is null check result:', result);
3923
+ }
3924
+ break;
3925
+ case 'isNotEmpty':
3926
+ result = !isEmpty(valueToCompare);
3927
+ if (loggingEnabled) {
3928
+ console.log('Is not empty check result:', result);
3929
+ }
3930
+ break;
3931
+ case 'between':
3932
+ result = !isNil(valueToCompare) && valueToCompare >= condition.value.from && valueToCompare <= condition.value.to;
3933
+ if (loggingEnabled) {
3934
+ console.log('Between check result:', result);
3935
+ }
3936
+ break;
3937
+ default:
3938
+ result = true;
3939
+ if (loggingEnabled) {
3940
+ console.log('Default case, returning true');
3941
+ }
3942
+ }
3943
+ // Apply negative flag if present on operator (invert the result)
3944
+ const isNegative = !!condition?.operator?.negative;
3945
+ return isNegative ? !result : result;
3946
+ }
3947
+ function applyFilterArray(dataArray, filters, logic = 'and') {
3948
+ if (filters && filters.length) {
3949
+ return dataArray.filter((item) => {
3950
+ if (logic === 'and') {
3951
+ return filters.every((f) => {
3952
+ return f.filters ? applyFilterArray([item], f.filters, f.logic).length > 0 : applyCondition(item, f);
3953
+ });
3954
+ }
3955
+ else {
3956
+ // logic === 'or'
3957
+ return filters.some((f) => {
3958
+ return f.filters ? applyFilterArray([item], f.filters, f.logic).length > 0 : applyCondition(item, f);
3959
+ });
3960
+ }
3961
+ });
3962
+ }
3963
+ else {
3964
+ return dataArray;
3965
+ }
3966
+ }
3967
+ function applySortArray(dataArray, sorts) {
3968
+ if (sorts && sorts.length > 0) {
3969
+ const sortFields = sorts.map((s) => s.field);
3970
+ const sortOrders = sorts.map((s) => s.dir);
3971
+ return orderBy(dataArray, sortFields, sortOrders);
3972
+ }
3973
+ else
3974
+ return dataArray;
3975
+ }
3976
+ function applyPagination(dataArray, skip, take) {
3977
+ return dataArray.slice(skip, skip + take);
3978
+ }
3979
+ async function applyQueryArray(dataArray, query) {
3980
+ let result = [...dataArray];
3981
+ // Apply filtering
3982
+ if (query.filter) {
3983
+ result = applyFilterArray(result, [query.filter], query.filter.logic ?? 'and');
3984
+ }
3985
+ // Store total count before pagination
3986
+ const total = result.length;
3987
+ // Apply sorting
3988
+ if (query.sort && query.sort.length > 0) {
3989
+ result = applySortArray(result, query.sort);
3990
+ }
3991
+ // Apply pagination
3992
+ result = applyPagination(result, query.skip, query.take);
3993
+ return {
3994
+ items: result,
3995
+ total,
3996
+ };
3997
+ }
3998
+
3999
+ //#region ---- Type Definitions ----
4000
+ /**
4001
+ * Screen Size Enum
4002
+ */
4003
+ var AXPScreenSize;
4004
+ (function (AXPScreenSize) {
4005
+ AXPScreenSize["Small"] = "small";
4006
+ AXPScreenSize["Medium"] = "medium";
4007
+ AXPScreenSize["Large"] = "large";
4008
+ })(AXPScreenSize || (AXPScreenSize = {}));
4009
+ /**
4010
+ * Device Type Enum
4011
+ */
4012
+ var AXPDeviceType;
4013
+ (function (AXPDeviceType) {
4014
+ AXPDeviceType["Mobile"] = "mobile";
4015
+ AXPDeviceType["Tablet"] = "tablet";
4016
+ AXPDeviceType["Desktop"] = "desktop";
4017
+ })(AXPDeviceType || (AXPDeviceType = {}));
4018
+ //#endregion
4019
+ //#region ---- Helper Functions ----
4020
+ /**
4021
+ * Get the initial screen size based on window width
4022
+ */
4023
+ const getScreenSize = () => {
4024
+ const width = window.innerWidth;
4025
+ if (width <= 600)
4026
+ return AXPScreenSize.Small;
4027
+ if (width <= 1024)
4028
+ return AXPScreenSize.Medium;
4029
+ return AXPScreenSize.Large;
4030
+ };
4031
+ /**
4032
+ * Determine device type based on viewport width
4033
+ */
4034
+ const getDeviceType = () => {
4035
+ const width = window.innerWidth;
4036
+ if (width <= 600) {
4037
+ return AXPDeviceType.Mobile;
4038
+ }
4039
+ else if (width <= 1024) {
4040
+ return AXPDeviceType.Tablet;
4041
+ }
4042
+ return AXPDeviceType.Desktop;
4043
+ };
4044
+ /**
4045
+ * Determine if the device supports touch
4046
+ */
4047
+ const isTouchDevice = () => {
4048
+ return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
4049
+ };
4050
+ //#endregion
4051
+ //#region ---- Device Service ----
4052
+ /**
4053
+ * Injectable service that provides reactive device and screen size information.
4054
+ * Monitors window resize events and updates signals accordingly.
4055
+ */
4056
+ class AXPDeviceService {
4057
+ //#endregion
4058
+ //#region ---- Constructor & Lifecycle ----
4059
+ constructor() {
4060
+ //#region ---- State Signals ----
4061
+ /**
4062
+ * Current screen size (Small, Medium, Large)
4063
+ */
4064
+ this.screenSize = signal(getScreenSize(), ...(ngDevMode ? [{ debugName: "screenSize" }] : /* istanbul ignore next */ []));
4065
+ /**
4066
+ * Current device type (Mobile, Tablet, Desktop)
4067
+ */
4068
+ this.deviceType = signal(getDeviceType(), ...(ngDevMode ? [{ debugName: "deviceType" }] : /* istanbul ignore next */ []));
4069
+ /**
4070
+ * Whether the device supports touch input
4071
+ */
4072
+ this.isTouchDevice = signal(isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchDevice" }] : /* istanbul ignore next */ []));
4073
+ //#endregion
4074
+ //#region ---- Computed Signals ----
4075
+ /**
4076
+ * Whether the screen size is Small
4077
+ */
4078
+ this.isSmall = computed(() => this.screenSize() === AXPScreenSize.Small, ...(ngDevMode ? [{ debugName: "isSmall" }] : /* istanbul ignore next */ []));
4079
+ /**
4080
+ * Whether the screen size is Medium
4081
+ */
4082
+ this.isMedium = computed(() => this.screenSize() === AXPScreenSize.Medium, ...(ngDevMode ? [{ debugName: "isMedium" }] : /* istanbul ignore next */ []));
4083
+ /**
4084
+ * Whether the screen size is Large
4085
+ */
4086
+ this.isLarge = computed(() => this.screenSize() === AXPScreenSize.Large, ...(ngDevMode ? [{ debugName: "isLarge" }] : /* istanbul ignore next */ []));
4087
+ /**
4088
+ * Whether the device is Mobile
4089
+ */
4090
+ this.isMobileDevice = computed(() => this.deviceType() === AXPDeviceType.Mobile, ...(ngDevMode ? [{ debugName: "isMobileDevice" }] : /* istanbul ignore next */ []));
4091
+ /**
4092
+ * Whether the device is Tablet
4093
+ */
4094
+ this.isTabletDevice = computed(() => this.deviceType() === AXPDeviceType.Tablet, ...(ngDevMode ? [{ debugName: "isTabletDevice" }] : /* istanbul ignore next */ []));
4095
+ /**
4096
+ * Whether the device is Desktop
4097
+ */
4098
+ this.isDesktopDevice = computed(() => this.deviceType() === AXPDeviceType.Desktop, ...(ngDevMode ? [{ debugName: "isDesktopDevice" }] : /* istanbul ignore next */ []));
4099
+ /**
4100
+ * Whether the device supports touch (alias for isTouchDevice)
4101
+ */
4102
+ this.isTouchScreen = computed(() => this.isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchScreen" }] : /* istanbul ignore next */ []));
4103
+ //#endregion
4104
+ //#region ---- Private Properties ----
4105
+ this._resizeListener = null;
4106
+ this._setupResizeListener();
4107
+ }
4108
+ //#endregion
4109
+ //#region ---- Private Methods ----
4110
+ /**
4111
+ * Update screen size and device type based on window width
4112
+ */
4113
+ _updateScreenSize() {
4114
+ const width = window.innerWidth;
4115
+ let newScreenSize;
4116
+ if (width <= 600) {
4117
+ newScreenSize = AXPScreenSize.Small;
4118
+ }
4119
+ else if (width <= 1024) {
4120
+ newScreenSize = AXPScreenSize.Medium;
4121
+ }
4122
+ else {
4123
+ newScreenSize = AXPScreenSize.Large;
4124
+ }
4125
+ // Determine device type based on width to keep it reactive to devtools emulation
4126
+ let newDeviceType;
4127
+ if (width <= 600) {
4128
+ newDeviceType = AXPDeviceType.Mobile;
4129
+ }
4130
+ else if (width <= 1024) {
4131
+ newDeviceType = AXPDeviceType.Tablet;
4132
+ }
4133
+ else {
4134
+ newDeviceType = AXPDeviceType.Desktop;
4135
+ }
4136
+ if (newScreenSize !== this.screenSize() || newDeviceType !== this.deviceType()) {
4137
+ this.screenSize.set(newScreenSize);
4138
+ this.deviceType.set(newDeviceType);
4139
+ }
4140
+ }
4141
+ /**
4142
+ * Set up event listener for window resize
4143
+ */
4144
+ _setupResizeListener() {
4145
+ this._resizeListener = fromEvent(window, 'resize')
4146
+ .pipe(debounceTime(250)) // 250ms debounce delay
4147
+ .subscribe(() => {
4148
+ this._updateScreenSize();
4149
+ });
4150
+ }
4151
+ /**
4152
+ * Remove event listener for window resize
4153
+ */
4154
+ _removeResizeListener() {
4155
+ if (this._resizeListener) {
4156
+ this._resizeListener.unsubscribe();
4157
+ this._resizeListener = null;
4158
+ }
4159
+ }
4160
+ //#endregion
4161
+ //#region ---- Public Methods ----
4162
+ /**
4163
+ * Clean up resources when service is destroyed
4164
+ */
4165
+ destroy() {
4166
+ this._removeResizeListener();
4167
+ }
4168
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDeviceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4169
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDeviceService, providedIn: 'root' }); }
4170
+ }
4171
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDeviceService, decorators: [{
4172
+ type: Injectable,
4173
+ args: [{
4174
+ providedIn: 'root',
4175
+ }]
4176
+ }], ctorParameters: () => [] });
4177
+
4178
+ /**
4179
+ * Service for applying and resetting text highlighting within specified HTML elements.
4180
+ */
4181
+ class AXHighlightService {
4182
+ constructor() { }
4183
+ /**
4184
+ * Highlights all occurrences of a search value within the elements matching the provided query selector.
4185
+ *
4186
+ * @param querySelector - CSS selector to identify target elements.
4187
+ * @param searchValue - Text to search and highlight.
4188
+ */
4189
+ highlight(querySelector, searchValue) {
4190
+ this.clear();
4191
+ if (!querySelector || !searchValue) {
4192
+ return;
4193
+ }
4194
+ this.querySelector = querySelector;
4195
+ this.searchValue = searchValue;
4196
+ const elements = document.querySelectorAll(querySelector);
4197
+ elements.forEach((element) => {
4198
+ this.applyHighlight(element);
4199
+ });
4200
+ }
4201
+ /**
4202
+ * Resets all highlighted text within the elements matching the previously used query selector.
4203
+ */
4204
+ clear() {
4205
+ const elements = document.querySelectorAll(`${this.querySelector} .ax-highlight-text`);
4206
+ elements.forEach((element) => {
4207
+ let combinedText = '';
4208
+ element.querySelectorAll('span').forEach((span) => {
4209
+ combinedText += span.textContent;
4210
+ });
4211
+ const mergedSpan = document.createElement('span');
4212
+ mergedSpan.textContent = combinedText;
4213
+ element?.parentNode?.replaceChild(mergedSpan, element);
4214
+ });
4215
+ }
4216
+ /**
4217
+ * Applies highlighting to a specific element by matching text against the search value.
4218
+ *
4219
+ * @param element - The HTML element to apply highlights to.
4220
+ */
4221
+ applyHighlight(element) {
4222
+ const searchRegex = new RegExp(`(${this.searchValue})`, 'gi');
4223
+ this.recursivelyHighlight(element, searchRegex);
4224
+ }
4225
+ /**
4226
+ * Recursively applies highlighting to text nodes within an element.
4227
+ *
4228
+ * @param element - The current node being processed.
4229
+ * @param searchRegex - Regular expression for matching text to highlight.
4230
+ */
4231
+ recursivelyHighlight(element, searchRegex) {
4232
+ const childNodes = Array.from(element.childNodes);
4233
+ childNodes.forEach((node) => {
4234
+ if (node.nodeType === Node.TEXT_NODE) {
4235
+ const textContent = node.textContent || '';
4236
+ if (textContent.match(searchRegex)) {
4237
+ const highlightedHTML = this.createHighlightedHTML(textContent, searchRegex);
4238
+ const tempContainer = document.createElement('div');
4239
+ tempContainer.innerHTML = highlightedHTML;
4240
+ const fragment = document.createDocumentFragment();
4241
+ Array.from(tempContainer.childNodes).forEach((child) => fragment.appendChild(child));
4242
+ node.replaceWith(fragment);
4243
+ }
4244
+ }
4245
+ else if (node.nodeType === Node.ELEMENT_NODE) {
4246
+ this.recursivelyHighlight(node, searchRegex);
4247
+ }
4248
+ });
4249
+ }
4250
+ /**
4251
+ * Generates the HTML structure for highlighted text.
4252
+ *
4253
+ * @param textContent - The original text content to process.
4254
+ * @param searchRegex - Regular expression for matching text to highlight.
4255
+ * @returns A string of HTML with highlighted portions wrapped in span elements.
4256
+ */
4257
+ createHighlightedHTML(textContent, searchRegex) {
4258
+ let parts = [];
4259
+ let match;
4260
+ let lastIndex = 0;
4261
+ let resultHTML = '<span class="ax-highlight-text">';
4262
+ while ((match = searchRegex.exec(textContent)) !== null) {
4263
+ if (match.index > lastIndex) {
4264
+ resultHTML += `<span>${textContent.slice(lastIndex, match.index)}</span>`;
4265
+ }
4266
+ resultHTML += `<span class="ax-highlight">${match[0]}</span>`;
4267
+ lastIndex = searchRegex.lastIndex;
4268
+ }
4269
+ if (lastIndex < textContent.length) {
4270
+ resultHTML += `<span>${textContent.slice(lastIndex)}</span>`;
4271
+ }
4272
+ resultHTML += '</span>';
4273
+ return resultHTML;
4274
+ }
4275
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXHighlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4276
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXHighlightService, providedIn: 'root' }); }
4277
+ }
4278
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXHighlightService, decorators: [{
4279
+ type: Injectable,
4280
+ args: [{
4281
+ providedIn: 'root',
4282
+ }]
4283
+ }], ctorParameters: () => [] });
4284
+
4285
+ /**
4286
+ * Creates a provider instance within an injection context.
4287
+ * Handles dynamic import, injector resolution, and provider instantiation.
4288
+ *
4289
+ * @param loader - Function that returns a promise resolving to the provider class
4290
+ * @returns Promise that resolves to the provider instance
4291
+ *
4292
+ * @example
4293
+ * ```typescript
4294
+ * useFactory: () => createProviderWithInjectionContext(() =>
4295
+ * import('./settings.provider').then(m => m.AXMSettingProvider)
4296
+ * )
4297
+ * ```
4298
+ */
4299
+ async function createProviderWithInjectionContext(loader) {
4300
+ const injector = inject(Injector);
4301
+ const ProviderClass = await loader();
4302
+ return runInInjectionContext(injector, () => new ProviderClass());
4303
+ }
4304
+ /**
4305
+ * Creates a provider configuration for lazy-loaded providers with injection context.
4306
+ * Simplifies provider registration in NgModule providers array.
4307
+ *
4308
+ * @param token - The injection token to provide
4309
+ * @param loader - Function that returns a promise resolving to the provider class
4310
+ * @param multi - Optional. Whether the provider is a multi-provider (array of values). Defaults to `true`. Pass `false` for a single provider.
4311
+ * @returns Provider configuration object
4312
+ *
4313
+ * @example
4314
+ * ```typescript
4315
+ * // Multi-provider (default)
4316
+ * provideLazyProvider(
4317
+ * AXP_DATASOURCE_DEFINITION_PROVIDER,
4318
+ * () => import('./datasource.provider').then(m => m.AXMDataSourceProvider)
4319
+ * )
4320
+ *
4321
+ * // Single provider
4322
+ * provideLazyProvider(
4323
+ * SOME_TOKEN,
4324
+ * () => import('./my.provider').then(m => m.MyProvider),
4325
+ * false
4326
+ * )
4327
+ * ```
4328
+ */
4329
+ function provideLazyProvider(token, loader, multi = true) {
4330
+ return {
4331
+ provide: token,
4332
+ useFactory: () => createProviderWithInjectionContext(loader),
4333
+ multi,
4334
+ };
4335
+ }
4336
+
4337
+ function extractTextFromHtml(value) {
4338
+ const div = document.createElement('div');
4339
+ div.innerHTML = value;
4340
+ return div.textContent || div.innerText || '';
4341
+ }
4342
+ /**
4343
+ * True when the string likely contains HTML markup (e.g. `<p>`, `<ul>`), as opposed to plain text.
4344
+ * Used to choose innerHTML vs text interpolation for multilingual fields.
4345
+ */
4346
+ function containsHtmlMarkup(value) {
4347
+ if (value == null) {
4348
+ return false;
4349
+ }
4350
+ const t = value.trim();
4351
+ if (!t) {
4352
+ return false;
4353
+ }
4354
+ return /<\/?[a-z][\s\S]*?>/i.test(t);
4355
+ }
4356
+ /**
4357
+ * Generate kebab-case group name from title
4358
+ */
4359
+ function generateKebabCase(title) {
4360
+ return title
4361
+ .toLowerCase()
4362
+ .trim()
4363
+ .replace(/[^a-z0-9\s-]/g, '') // Remove special characters
4364
+ .replace(/\s+/g, '-') // Replace spaces with hyphens
4365
+ .replace(/-+/g, '-') // Replace multiple hyphens with single
4366
+ .replace(/^-+|-+$/g, ''); // Remove leading/trailing hyphens
4367
+ }
4368
+
4369
+ /**
4370
+ * Generated bundle index. Do not edit.
4371
+ */
4372
+
4373
+ 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, containsHtmlMarkup, createMultiLanguageString, createProviderWithInjectionContext, defaultColumnWidthProvider, extractNestedFieldsWildcard, extractTextFromHtml, extractValue, generateKebabCase, getActionButton, getChangedPaths, getDetailedChanges, getEnumValues, getNestedKeys, getSmart, getSystemActions, isEffectivelyEmptyLocalizedValue, objectKeyValueTransforms, provideLazyProvider, resolveActionLook, resolveMultiLanguageString, resolvePlatformScopeKey, resolvePlatformScopeName, setSmart };
4374
+ //# sourceMappingURL=acorex-platform-core.mjs.map