@acorex/platform 20.6.0-next.9 → 21.0.0-next.1

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 (88) hide show
  1. package/auth/index.d.ts +91 -12
  2. package/common/index.d.ts +615 -44
  3. package/core/index.d.ts +718 -422
  4. package/fesm2022/acorex-platform-auth.mjs +152 -39
  5. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  6. package/fesm2022/acorex-platform-common.mjs +1009 -112
  7. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  8. package/fesm2022/acorex-platform-core.mjs +887 -408
  9. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  10. package/fesm2022/acorex-platform-domain.mjs +99 -11
  11. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  12. package/fesm2022/acorex-platform-layout-builder.mjs +555 -492
  13. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  14. package/fesm2022/acorex-platform-layout-components.mjs +2446 -2733
  15. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  16. package/fesm2022/acorex-platform-layout-designer.mjs +9 -9
  17. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  18. package/fesm2022/acorex-platform-layout-entity.mjs +9708 -4721
  19. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  20. package/fesm2022/acorex-platform-layout-views.mjs +32 -26
  21. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  22. package/fesm2022/acorex-platform-layout-widget-core.mjs +252 -182
  23. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  24. package/fesm2022/{acorex-platform-layout-widgets-file-list-popup.component-D0y-9nE5.mjs → acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs} +2 -2
  25. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs.map +1 -0
  26. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs +30 -0
  27. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs.map +1 -0
  28. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-C1l2KSDa.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs} +2 -2
  29. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs.map +1 -0
  30. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-D-31ej0C.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs} +2 -2
  31. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs.map +1 -0
  32. package/fesm2022/acorex-platform-layout-widgets.mjs +9791 -6928
  33. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  34. package/fesm2022/acorex-platform-runtime.mjs +79 -3
  35. package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
  36. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs +157 -0
  37. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs.map +1 -0
  38. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs +1542 -0
  39. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs.map +1 -0
  40. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs +101 -0
  41. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs.map +1 -0
  42. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-B_P0a5KW.mjs → acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs} +3 -3
  43. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs.map +1 -0
  44. package/fesm2022/acorex-platform-themes-default.mjs +282 -43
  45. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  46. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs +55 -0
  47. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs.map +1 -0
  48. package/fesm2022/acorex-platform-themes-shared.mjs +42 -137
  49. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  50. package/fesm2022/acorex-platform-workflow.mjs +658 -45
  51. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  52. package/layout/builder/index.d.ts +10 -34
  53. package/layout/components/index.d.ts +694 -375
  54. package/layout/designer/index.d.ts +4 -4
  55. package/layout/entity/index.d.ts +802 -183
  56. package/layout/views/index.d.ts +5 -58
  57. package/layout/widget-core/index.d.ts +63 -75
  58. package/layout/widgets/README.md +0 -1
  59. package/layout/widgets/index.d.ts +493 -129
  60. package/package.json +1 -1
  61. package/runtime/index.d.ts +36 -8
  62. package/themes/default/index.d.ts +44 -75
  63. package/themes/shared/index.d.ts +11 -49
  64. package/workflow/index.d.ts +401 -90
  65. package/fesm2022/acorex-platform-layout-entity-create-entity.command-DGeylNSY.mjs +0 -52
  66. package/fesm2022/acorex-platform-layout-entity-create-entity.command-DGeylNSY.mjs.map +0 -1
  67. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs +0 -50
  68. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs.map +0 -1
  69. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs +0 -42
  70. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs.map +0 -1
  71. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs +0 -55
  72. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs.map +0 -1
  73. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs +0 -50
  74. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs.map +0 -1
  75. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs +0 -48
  76. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs.map +0 -1
  77. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs +0 -42
  78. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs.map +0 -1
  79. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-D0y-9nE5.mjs.map +0 -1
  80. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-C1l2KSDa.mjs.map +0 -1
  81. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-D-31ej0C.mjs.map +0 -1
  82. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-WbPPqDON.mjs +0 -115
  83. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-WbPPqDON.mjs.map +0 -1
  84. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-CD7rJIMh.mjs +0 -803
  85. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-CD7rJIMh.mjs.map +0 -1
  86. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs +0 -101
  87. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs.map +0 -1
  88. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-B_P0a5KW.mjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { computed, signal, Injectable, InjectionToken, inject, ElementRef, effect, untracked, Injector, ChangeDetectorRef, ViewChild, Input, ChangeDetectionStrategy, Component, EventEmitter, Output, input, output, ViewContainerRef, Directive, Optional, Inject, NgModule, createComponent } from '@angular/core';
2
+ import { computed, signal, Injectable, InjectionToken, inject, ElementRef, effect, untracked, Injector, ChangeDetectorRef, ViewChild, Input, ChangeDetectionStrategy, Component, EventEmitter, Output, input, output, ViewContainerRef, Directive, Optional, Inject, NgModule } from '@angular/core';
3
3
  import { convertArrayToDataSource, AXDataSource } from '@acorex/cdk/common';
4
- import { setSmart, AXPDataSourceDefinitionProviderService, extractValue, getSmart, AXPExpressionEvaluatorService } from '@acorex/platform/core';
5
- import { cloneDeep, isEqual, get, set, merge, isNil, isUndefined, isObjectLike, sum, isEmpty, isString } from 'lodash-es';
4
+ import { setSmart, AXPDataSourceDefinitionProviderService, extractValue, AXPExpressionEvaluatorService, getSmart } from '@acorex/platform/core';
5
+ import { cloneDeep, isEqual, has, get, set, merge, isNil, isUndefined, isObjectLike, sum, isEmpty, isString } from 'lodash-es';
6
6
  import { Subject, BehaviorSubject, filter } from 'rxjs';
7
7
  import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
8
8
  import * as i1$1 from '@acorex/components/skeleton';
@@ -125,6 +125,10 @@ withMethods((store) => ({
125
125
  getValue(path) {
126
126
  return get(store.data(), path);
127
127
  },
128
+ // Check if a path exists in the context
129
+ hasValue(path) {
130
+ return has(store.data(), path);
131
+ },
128
132
  })));
129
133
 
130
134
  var AXPPageStatus;
@@ -291,7 +295,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
291
295
  const AXPWidgetsCatalog = {
292
296
  timeDuration: 'time-duration',
293
297
  timeDurationFilter: 'time-duration-filter',
294
- tagable: 'tagable-editor',
295
298
  checkbox: 'checkbox-editor',
296
299
  color: 'color-editor',
297
300
  connectedLists: 'connected-lists-editor',
@@ -329,8 +332,6 @@ const AXPWidgetsCatalog = {
329
332
  advancedGridItem: 'advanced-grid-item-layout',
330
333
  grid: 'grid-layout',
331
334
  gridItem: 'grid-item-layout',
332
- // gridRow: 'grid-row-layout',
333
- widgetSelector: 'widget-selector',
334
335
  template: 'template',
335
336
  templateDesigner: 'template-designer',
336
337
  cronJob: 'cron-job',
@@ -392,8 +393,9 @@ const AXPWidgetsCatalog = {
392
393
  editorJs: 'editor-js-editor',
393
394
  documentUploader: 'document-uploader',
394
395
  signatureList: 'signature-list',
395
- status: 'status-widget',
396
396
  stepWizard: 'step-wizard',
397
+ progressBar: 'progress-bar-editor',
398
+ rate: 'rate-picker-editor'
397
399
  };
398
400
 
399
401
  function cloneProperty(property, values) {
@@ -597,7 +599,8 @@ class AXPValueWidgetComponent extends AXPLayoutBaseWidgetComponent {
597
599
  this._isValueWidget = this.config.properties?.some((c) => c.name == 'path') ?? false;
598
600
  if (this.isValueWidget()) {
599
601
  this.detectFullPath();
600
- if (!isNil(this.defaultValue) && isNil(this.getValue())) {
602
+ // Set defaultValue if it exists and the path doesn't exist in context
603
+ if (!isNil(this.defaultValue) && this.fullPath() && !this.contextService.hasValue(this.fullPath())) {
601
604
  this.setValue(this.defaultValue);
602
605
  }
603
606
  }
@@ -679,14 +682,10 @@ class AXPDataListWidgetComponent extends AXPValueWidgetComponent {
679
682
  this.dataService = inject(AXPDataSourceDefinitionProviderService);
680
683
  this.textField = computed(() => this.options()['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
681
684
  this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
682
- this.textTemplate = computed(() => (this.options()['textTemplate'] ?? '').replaceAll('{', '{{').replaceAll('}', '}}'), ...(ngDevMode ? [{ debugName: "textTemplate" }] : []));
685
+ this.textTemplate = computed(() => isNil(this.options()['textTemplate'])
686
+ ? undefined
687
+ : this.options()['textTemplate'].replace(/{/g, '{{').replace(/}/g, '}}'), ...(ngDevMode ? [{ debugName: "textTemplate" }] : []));
683
688
  this.dataSource = signal(convertArrayToDataSource([]), ...(ngDevMode ? [{ debugName: "dataSource" }] : []));
684
- this.isReady = computed(() => {
685
- const key = this.dataSource().config?.key;
686
- const valueField = this.valueField();
687
- const result = key == valueField;
688
- return result;
689
- }, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
690
689
  this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
691
690
  //#region ---- DataSource Loading Effect ----
692
691
  /**
@@ -1217,8 +1216,14 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1217
1216
  super(...arguments);
1218
1217
  this.widgetRegistery = inject(AXPWidgetRegistryService);
1219
1218
  this.grid = inject(AXBaseDataTable);
1219
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
1220
1220
  this.mergedOptions = signal({}, ...(ngDevMode ? [{ debugName: "mergedOptions" }] : []));
1221
1221
  this.loadingRow = signal(null, ...(ngDevMode ? [{ debugName: "loadingRow" }] : []));
1222
+ this.rowInjectorsCache = new Map();
1223
+ this.hasExpressions = false;
1224
+ this.pendingEvaluations = new Set();
1225
+ this.changeDetectionScheduled = false;
1226
+ this.MAX_CACHE_SIZE = 1000; // Limit cache size to prevent memory leaks
1222
1227
  this.injector = inject(Injector);
1223
1228
  this.cdr = inject(ChangeDetectorRef);
1224
1229
  }
@@ -1264,6 +1269,8 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1264
1269
  }, {});
1265
1270
  //
1266
1271
  this.mergedOptions.set(merge(props, this.node.options) || {});
1272
+ // Check if options contain expressions (performance optimization)
1273
+ this.hasExpressions = this.checkForExpressions(this.mergedOptions());
1267
1274
  const tokenValue = {
1268
1275
  path: this.node.path,
1269
1276
  options: this.mergedOptions(),
@@ -1281,12 +1288,164 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1281
1288
  this.allowResizing = this.mergedOptions().allowResizing || true;
1282
1289
  this.cdr.detectChanges();
1283
1290
  }
1291
+ //#region ---- Performance Optimization Methods ----
1292
+ /**
1293
+ * Check if options contain any expressions that need evaluation
1294
+ */
1295
+ checkForExpressions(obj) {
1296
+ if (typeof obj === 'string') {
1297
+ return this.expressionEvaluator.isExpression(obj);
1298
+ }
1299
+ if (Array.isArray(obj)) {
1300
+ return obj.some((item) => this.checkForExpressions(item));
1301
+ }
1302
+ if (obj && typeof obj === 'object') {
1303
+ return Object.values(obj).some((value) => this.checkForExpressions(value));
1304
+ }
1305
+ return false;
1306
+ }
1307
+ /**
1308
+ * Get cache key for row data - optimized to avoid JSON.stringify when possible
1309
+ */
1310
+ getCacheKey(data) {
1311
+ if (data?.id) {
1312
+ return `row-${data.id}`;
1313
+ }
1314
+ // Use a hash of key properties instead of full JSON.stringify
1315
+ // This is much faster for large objects
1316
+ const keyProps = ['id', 'code', 'name', 'title'];
1317
+ const keyValues = keyProps.map((prop) => data?.[prop]).filter((v) => v != null);
1318
+ if (keyValues.length > 0) {
1319
+ return `row-${keyValues.join('-')}`;
1320
+ }
1321
+ // Fallback to JSON.stringify only if no key properties exist
1322
+ // But limit the stringified size to prevent performance issues
1323
+ try {
1324
+ const str = JSON.stringify(data);
1325
+ return str.length > 1000 ? `row-${str.substring(0, 1000)}` : `row-${str}`;
1326
+ }
1327
+ catch {
1328
+ // If JSON.stringify fails, use a simple hash
1329
+ return `row-${Object.keys(data || {}).length}`;
1330
+ }
1331
+ }
1332
+ /**
1333
+ * Schedule change detection (debounced to batch multiple updates)
1334
+ */
1335
+ scheduleChangeDetection() {
1336
+ if (this.changeDetectionScheduled) {
1337
+ return;
1338
+ }
1339
+ this.changeDetectionScheduled = true;
1340
+ // Use requestAnimationFrame for better performance
1341
+ requestAnimationFrame(() => {
1342
+ this.cdr.detectChanges();
1343
+ this.changeDetectionScheduled = false;
1344
+ });
1345
+ }
1346
+ /**
1347
+ * Limit cache size using simple FIFO eviction
1348
+ */
1349
+ evictCacheIfNeeded() {
1350
+ if (this.rowInjectorsCache.size >= this.MAX_CACHE_SIZE) {
1351
+ // Remove oldest entries (first 25% of cache)
1352
+ const entriesToRemove = Math.floor(this.MAX_CACHE_SIZE * 0.25);
1353
+ const keysToRemove = Array.from(this.rowInjectorsCache.keys()).slice(0, entriesToRemove);
1354
+ keysToRemove.forEach((key) => this.rowInjectorsCache.delete(key));
1355
+ }
1356
+ }
1357
+ //#endregion
1284
1358
  getInputs(data) {
1285
1359
  return {
1286
- rawValue: getSmart(data, this.node.path),
1360
+ rawValue: get(data, this.node.path),
1287
1361
  rowData: data,
1288
1362
  };
1289
1363
  }
1364
+ getRowInjector(data) {
1365
+ // Optimized cache key generation
1366
+ const cacheKey = this.getCacheKey(data);
1367
+ // Check if we have a cached injector for this row
1368
+ let rowInjector = this.rowInjectorsCache.get(cacheKey);
1369
+ if (!rowInjector) {
1370
+ // If no expressions in options, use original options directly (performance optimization)
1371
+ if (!this.hasExpressions) {
1372
+ const tokenValue = {
1373
+ path: this.node.path,
1374
+ options: this.mergedOptions(),
1375
+ };
1376
+ rowInjector = Injector.create({
1377
+ parent: this.injector,
1378
+ providers: [
1379
+ {
1380
+ provide: AXP_WIDGET_COLUMN_TOKEN,
1381
+ useValue: tokenValue,
1382
+ },
1383
+ ],
1384
+ });
1385
+ this.evictCacheIfNeeded();
1386
+ this.rowInjectorsCache.set(cacheKey, rowInjector);
1387
+ return rowInjector;
1388
+ }
1389
+ // Check if evaluation is already pending for this row
1390
+ if (!this.pendingEvaluations.has(cacheKey)) {
1391
+ this.pendingEvaluations.add(cacheKey);
1392
+ // Evaluate expressions in options based on row data
1393
+ const scope = {
1394
+ ...(data ?? {}),
1395
+ context: {
1396
+ eval: (path) => {
1397
+ return getSmart(data, path);
1398
+ },
1399
+ },
1400
+ };
1401
+ // Start async evaluation - will update injector when complete
1402
+ this.expressionEvaluator.evaluate(this.mergedOptions(), scope).then((evaluatedOptions) => {
1403
+ // Create injector with evaluated options
1404
+ const tokenValue = {
1405
+ path: this.node.path,
1406
+ options: evaluatedOptions,
1407
+ };
1408
+ const newInjector = Injector.create({
1409
+ parent: this.injector,
1410
+ providers: [
1411
+ {
1412
+ provide: AXP_WIDGET_COLUMN_TOKEN,
1413
+ useValue: tokenValue,
1414
+ },
1415
+ ],
1416
+ });
1417
+ // Replace cached injector to force component recreation on next render
1418
+ this.rowInjectorsCache.delete(cacheKey);
1419
+ this.evictCacheIfNeeded();
1420
+ this.rowInjectorsCache.set(cacheKey, newInjector);
1421
+ this.pendingEvaluations.delete(cacheKey);
1422
+ // Schedule batched change detection (performance optimization)
1423
+ this.scheduleChangeDetection();
1424
+ }).catch(() => {
1425
+ // If evaluation fails, keep using the fallback injector
1426
+ this.pendingEvaluations.delete(cacheKey);
1427
+ });
1428
+ }
1429
+ // Create injector with original options as fallback (will be updated when evaluation completes)
1430
+ const tokenValue = {
1431
+ path: this.node.path,
1432
+ options: this.mergedOptions(),
1433
+ };
1434
+ rowInjector = Injector.create({
1435
+ parent: this.injector,
1436
+ providers: [
1437
+ {
1438
+ provide: AXP_WIDGET_COLUMN_TOKEN,
1439
+ useValue: tokenValue,
1440
+ },
1441
+ ],
1442
+ });
1443
+ // Cache the initial injector
1444
+ this.evictCacheIfNeeded();
1445
+ this.rowInjectorsCache.set(cacheKey, rowInjector);
1446
+ }
1447
+ return rowInjector;
1448
+ }
1290
1449
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetColumnRendererComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1291
1450
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPWidgetColumnRendererComponent, isStandalone: false, selector: "axp-widget-column-renderer", inputs: { caption: "caption", customExpandIcon: "customExpandIcon", customCollapseIcon: "customCollapseIcon", customWidth: "customWidth", node: "node", footerTemplate: "footerTemplate", expandHandler: "expandHandler", cellTemplate: "cellTemplate", headerTemplate: "headerTemplate" }, providers: [
1292
1451
  AXPWidgetCoreService,
@@ -1314,9 +1473,9 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1314
1473
  }
1315
1474
  </div>
1316
1475
  }
1317
- @if (component && widgetInjector && row?.data) {
1476
+ @if (component && row?.data) {
1318
1477
  <ng-container
1319
- *ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
1478
+ *ngComponentOutlet="component; injector: getRowInjector(row.data); inputs: getInputs(row.data)"
1320
1479
  ></ng-container>
1321
1480
  }
1322
1481
  </div>
@@ -1351,9 +1510,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
1351
1510
  }
1352
1511
  </div>
1353
1512
  }
1354
- @if (component && widgetInjector && row?.data) {
1513
+ @if (component && row?.data) {
1355
1514
  <ng-container
1356
- *ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
1515
+ *ngComponentOutlet="component; injector: getRowInjector(row.data); inputs: getInputs(row.data)"
1357
1516
  ></ng-container>
1358
1517
  }
1359
1518
  </div>
@@ -1477,6 +1636,7 @@ class AXPWidgetRendererDirective {
1477
1636
  this.options = this._options.asReadonly();
1478
1637
  this.onOptionsChanged = output();
1479
1638
  this.onValueChanged = output();
1639
+ this.onLoad = output();
1480
1640
  //#region ---- Public API ----
1481
1641
  /**
1482
1642
  * Signal that emits the component reference when it's ready
@@ -1501,6 +1661,7 @@ class AXPWidgetRendererDirective {
1501
1661
  this.renderTimeoutId = null;
1502
1662
  this.hasInitialRender = false;
1503
1663
  this.onContextChanged = new Subject();
1664
+ this.onLoadEvent = new Subject();
1504
1665
  //#region ---- Performance Optimization Properties ----
1505
1666
  this.contextUpdateQueue = new Set();
1506
1667
  this.contextUpdateTimeout = null;
@@ -1519,14 +1680,33 @@ class AXPWidgetRendererDirective {
1519
1680
  const changed = this.contextService.changeEvent();
1520
1681
  // Don't trigger re-render during initial setup
1521
1682
  if (!this.hasInitialRender) {
1522
- if (changed.path) {
1683
+ // Handle initial context set (state: 'initiated' with empty path means full context update)
1684
+ if (changed.state === 'initiated' && (!changed.path || changed.path === '')) {
1685
+ // Mark that we need to re-evaluate all expressions when initial render completes
1686
+ // This handles the case where context is set before/during widget initialization
1687
+ this.preRenderContextQueue.add('*'); // Use '*' as a marker for full context initialization
1688
+ // console.log(`📝 [${this.node().type}] Buffered initial context set`);
1689
+ }
1690
+ else if (changed.path) {
1523
1691
  this.preRenderContextQueue.add(changed.path);
1524
1692
  // console.log(`📝 [${this.node().type}] Buffered pre-render context change: ${changed.path}`);
1525
1693
  }
1526
1694
  return;
1527
1695
  }
1528
1696
  // CRITICAL PERFORMANCE FIX: Only respond to relevant context changes
1529
- if (changed.path && this.isRelevantContextChange(changed.path)) {
1697
+ // Handle initial context set (full context update)
1698
+ if (changed.state === 'initiated' && (!changed.path || changed.path === '')) {
1699
+ // Full context initialization - trigger re-evaluation of all expressions
1700
+ // console.log(`🎯 [${this.node().type}] Initial context set detected - triggering full re-evaluation`);
1701
+ this.clearExpressionCache();
1702
+ if (this.expressionEvaluators.size > 0) {
1703
+ await this.updateOptionsBasedOnContext();
1704
+ this.applyOptions();
1705
+ }
1706
+ await this.updateVisibility();
1707
+ await this.updateValueBasedOnFormula();
1708
+ }
1709
+ else if (changed.path && this.isRelevantContextChange(changed.path)) {
1530
1710
  // console.log(`🎯 [${this.node().type}] Context change detected: ${changed.path}`);
1531
1711
  this.queueContextUpdate(changed.path);
1532
1712
  }
@@ -1684,7 +1864,7 @@ class AXPWidgetRendererDirective {
1684
1864
  let match;
1685
1865
  while ((match = contextEvalRegex.exec(expressionValue)) !== null) {
1686
1866
  const evalPath = match[1];
1687
- // Normalize Id-suffixed segments to dot-id form (e.g., 'typeId' -> 'type.id', 'party.typeId' -> 'party.type.id')
1867
+ // Normalize Id-suffixed segments to dot-id form (e.g., 'typeId' -> 'type.id', 'person.typeId' -> 'person.type.id')
1688
1868
  const normalizePath = (p) => {
1689
1869
  if (!p)
1690
1870
  return p;
@@ -1874,6 +2054,7 @@ class AXPWidgetRendererDirective {
1874
2054
  if (this.componentRef) {
1875
2055
  this.componentRef.destroy();
1876
2056
  }
2057
+ this.onLoadEvent.complete();
1877
2058
  }
1878
2059
  async loadComponent() {
1879
2060
  if (this.isLoading()) {
@@ -1921,7 +2102,17 @@ class AXPWidgetRendererDirective {
1921
2102
  // Register expressions from widget defaults and node options to cover related-entity cases
1922
2103
  this.preprocessAndInitialOptions(cloneDeep(widget?.options));
1923
2104
  this.preprocessAndInitialOptions(cloneDeep(this.node().options));
1924
- await this.updateOptionsBasedOnContext();
2105
+ // Check if context is available before evaluating expressions
2106
+ // If context is empty, expressions will be re-evaluated after initial render
2107
+ const contextData = this.contextService.data();
2108
+ const hasContextData = contextData && Object.keys(contextData).length > 0;
2109
+ if (hasContextData) {
2110
+ await this.updateOptionsBasedOnContext();
2111
+ }
2112
+ else {
2113
+ // Context not yet available - expressions will be evaluated after initial render
2114
+ // when context is set (handled by the effect and preRenderContextQueue)
2115
+ }
1925
2116
  //
1926
2117
  this._options.update((val) => ({ ...val, ...this.mergedOptions() }));
1927
2118
  // Evaluate default value
@@ -1985,13 +2176,33 @@ class AXPWidgetRendererDirective {
1985
2176
  await this.updateVisibility();
1986
2177
  // Process any buffered pre-render context changes now that the component is ready
1987
2178
  if (this.preRenderContextQueue.size > 0) {
1988
- // console.log(
1989
- // `🚀 [${this.node().type}] Processing ${this.preRenderContextQueue.size} buffered pre-render changes`,
1990
- // );
1991
- this.preRenderContextQueue.forEach((p) => this.contextUpdateQueue.add(p));
1992
- this.preRenderContextQueue.clear();
1993
- await this.processBatchedUpdates();
2179
+ // Check if we have a full context initialization marker
2180
+ const hasFullContextInit = this.preRenderContextQueue.has('*');
2181
+ if (hasFullContextInit) {
2182
+ // Full context was initialized - clear cache and re-evaluate all expressions
2183
+ // console.log(`🚀 [${this.node().type}] Processing initial context set - full re-evaluation`);
2184
+ this.clearExpressionCache();
2185
+ this.preRenderContextQueue.clear();
2186
+ // Re-evaluate all expressions since context is now available
2187
+ if (this.expressionEvaluators.size > 0) {
2188
+ await this.updateOptionsBasedOnContext();
2189
+ this.applyOptions();
2190
+ }
2191
+ await this.updateVisibility();
2192
+ }
2193
+ else {
2194
+ // console.log(
2195
+ // `🚀 [${this.node().type}] Processing ${this.preRenderContextQueue.size} buffered pre-render changes`,
2196
+ // );
2197
+ this.preRenderContextQueue.forEach((p) => this.contextUpdateQueue.add(p));
2198
+ this.preRenderContextQueue.clear();
2199
+ await this.processBatchedUpdates();
2200
+ }
1994
2201
  }
2202
+ // Emit load event after widget is fully loaded
2203
+ const loadEvent = { sender: this, widget: this.instance };
2204
+ this.onLoadEvent.next(loadEvent);
2205
+ this.onLoad.emit(loadEvent);
1995
2206
  }
1996
2207
  catch (error) {
1997
2208
  // console.error('Error loading component:', error);
@@ -2263,6 +2474,9 @@ class AXPWidgetRendererDirective {
2263
2474
  }));
2264
2475
  },
2265
2476
  from: (event) => get(this.instance.api(), event),
2477
+ load: () => {
2478
+ return this.onLoadEvent.asObservable();
2479
+ },
2266
2480
  };
2267
2481
  }
2268
2482
  getWidgetScope() {
@@ -2281,6 +2495,10 @@ class AXPWidgetRendererDirective {
2281
2495
  if (refresh && typeof refresh === 'function') {
2282
2496
  refresh.bind(this.instance)();
2283
2497
  }
2498
+ else {
2499
+ this.updateOptionsBasedOnContext();
2500
+ this.applyOptions();
2501
+ }
2284
2502
  },
2285
2503
  output: (name) => {
2286
2504
  this.instance.output(name);
@@ -2369,7 +2587,7 @@ class AXPWidgetRendererDirective {
2369
2587
  }
2370
2588
  }
2371
2589
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetRendererDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2372
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.12", type: AXPWidgetRendererDirective, isStandalone: false, selector: "[axp-widget-renderer]", inputs: { parentNode: { classPropertyName: "parentNode", publicName: "parentNode", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onOptionsChanged: "onOptionsChanged", onValueChanged: "onValueChanged" }, providers: [
2590
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.12", type: AXPWidgetRendererDirective, isStandalone: false, selector: "[axp-widget-renderer]", inputs: { parentNode: { classPropertyName: "parentNode", publicName: "parentNode", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onOptionsChanged: "onOptionsChanged", onValueChanged: "onValueChanged", onLoad: "onLoad" }, providers: [
2373
2591
  {
2374
2592
  provide: AXUnsubscriber,
2375
2593
  },
@@ -2387,7 +2605,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
2387
2605
  ],
2388
2606
  standalone: false,
2389
2607
  }]
2390
- }], ctorParameters: () => [], propDecorators: { parentNode: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentNode", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: true }] }], node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }], onOptionsChanged: [{ type: i0.Output, args: ["onOptionsChanged"] }], onValueChanged: [{ type: i0.Output, args: ["onValueChanged"] }] } });
2608
+ }], ctorParameters: () => [], propDecorators: { parentNode: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentNode", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: true }] }], node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }], onOptionsChanged: [{ type: i0.Output, args: ["onOptionsChanged"] }], onValueChanged: [{ type: i0.Output, args: ["onValueChanged"] }], onLoad: [{ type: i0.Output, args: ["onLoad"] }] } });
2391
2609
 
2392
2610
  const COMPONENTS = [AXPWidgetContainerComponent, AXPWidgetColumnRendererComponent, AXPWidgetRendererDirective];
2393
2611
  class AXPWidgetCoreModule {
@@ -2660,160 +2878,12 @@ var AXPWidgetGroupEnum;
2660
2878
  AXPWidgetGroupEnum["MetaData"] = "meta-data";
2661
2879
  AXPWidgetGroupEnum["SettingWidget"] = "setting-widget";
2662
2880
  AXPWidgetGroupEnum["EntityWidget"] = "entity-widget";
2881
+ AXPWidgetGroupEnum["UtilityWidget"] = "utility-widget";
2663
2882
  })(AXPWidgetGroupEnum || (AXPWidgetGroupEnum = {}));
2664
2883
 
2665
- class AXPWidgetStandaloneRendererHostComponent {
2666
- constructor() {
2667
- this.mode = 'edit';
2668
- }
2669
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetStandaloneRendererHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2670
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.12", type: AXPWidgetStandaloneRendererHostComponent, isStandalone: true, selector: "axp-widget-standalone-renderer-host", inputs: { mode: "mode", node: "node", context: "context", functions: "functions" }, ngImport: i0, template: `
2671
- <axp-widgets-container [context]="context" [functions]="functions">
2672
- <ng-container axp-widget-renderer [mode]="mode" [node]="node"></ng-container>
2673
- </axp-widgets-container>
2674
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }] }); }
2675
- }
2676
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetStandaloneRendererHostComponent, decorators: [{
2677
- type: Component,
2678
- args: [{
2679
- selector: 'axp-widget-standalone-renderer-host',
2680
- template: `
2681
- <axp-widgets-container [context]="context" [functions]="functions">
2682
- <ng-container axp-widget-renderer [mode]="mode" [node]="node"></ng-container>
2683
- </axp-widgets-container>
2684
- `,
2685
- standalone: true,
2686
- imports: [AXPWidgetCoreModule]
2687
- }]
2688
- }], propDecorators: { mode: [{
2689
- type: Input
2690
- }], node: [{
2691
- type: Input
2692
- }], context: [{
2693
- type: Input
2694
- }], functions: [{
2695
- type: Input
2696
- }] } });
2697
-
2698
- const LAYOUT_WIDGET_RENDER_ENGINE = new InjectionToken('LAYOUT_WIDGET_RENDER_ENGINE');
2699
- class WidgetCoreRendererEngine {
2700
- constructor(appRef, env) {
2701
- this.appRef = appRef;
2702
- this.env = env;
2703
- }
2704
- render(node, target, context, mode = 'edit') {
2705
- const compRef = createComponent(AXPWidgetStandaloneRendererHostComponent, { environmentInjector: this.env });
2706
- compRef.setInput('mode', mode);
2707
- compRef.setInput('node', node);
2708
- if (context) {
2709
- compRef.setInput('context', context);
2710
- }
2711
- this.appRef.attachView(compRef.hostView);
2712
- target.appendChild(compRef.location.nativeElement);
2713
- return {
2714
- element: compRef.location.nativeElement,
2715
- destroy: () => {
2716
- try {
2717
- this.appRef.detachView(compRef.hostView);
2718
- }
2719
- catch { }
2720
- compRef.destroy();
2721
- },
2722
- };
2723
- }
2724
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: WidgetCoreRendererEngine, deps: [{ token: i0.ApplicationRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable }); }
2725
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: WidgetCoreRendererEngine, providedIn: 'root' }); }
2726
- }
2727
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: WidgetCoreRendererEngine, decorators: [{
2728
- type: Injectable,
2729
- args: [{ providedIn: 'root' }]
2730
- }], ctorParameters: () => [{ type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }] });
2731
- class SimpleDomRendererEngine {
2732
- render(node, target) {
2733
- const element = this.createElement(node);
2734
- target.appendChild(element);
2735
- return {
2736
- element,
2737
- destroy: () => {
2738
- if (element.parentElement) {
2739
- element.parentElement.removeChild(element);
2740
- }
2741
- },
2742
- };
2743
- }
2744
- createElement(node) {
2745
- const container = document.createElement('div');
2746
- container.className = `axp-widget axp-widget-${node.type}`;
2747
- switch (String(node.type)) {
2748
- case 'text-block-layout':
2749
- case 'static-text':
2750
- this.renderText(container, node);
2751
- break;
2752
- case 'tag':
2753
- this.renderTag(container, node);
2754
- break;
2755
- case 'text-editor':
2756
- this.renderTextBox(container, node);
2757
- break;
2758
- default:
2759
- this.renderGeneric(container, node);
2760
- break;
2761
- }
2762
- return container;
2763
- }
2764
- renderText(container, node) {
2765
- const anyNode = node;
2766
- const content = (anyNode.options && (anyNode.options.content || anyNode.options.label)) || '';
2767
- container.innerHTML = typeof content === 'string' ? content : String(content);
2768
- }
2769
- renderTag(container, node) {
2770
- const label = node.options?.label || 'Tag';
2771
- const tone = node.options?.tone || 'primary';
2772
- container.innerHTML = `<span class="tag tag-${tone}" style="
2773
- display: inline-block;
2774
- padding: 4px 12px;
2775
- border-radius: 12px;
2776
- font-size: 12px;
2777
- font-weight: 500;
2778
- background: ${tone === 'success' ? '#d4edda' : '#cce5ff'};
2779
- color: ${tone === 'success' ? '#155724' : '#004085'};
2780
- border: 1px solid ${tone === 'success' ? '#c3e6cb' : '#b8daff'};
2781
- ">${label}</span>`;
2782
- }
2783
- renderTextBox(container, node) {
2784
- const placeholder = node.options?.placeholder || '';
2785
- const input = document.createElement('input');
2786
- input.type = 'text';
2787
- input.placeholder = placeholder;
2788
- input.style.cssText = `
2789
- width: 100%;
2790
- padding: 8px 12px;
2791
- border: 1px solid #ddd;
2792
- border-radius: 4px;
2793
- font-size: 14px;
2794
- `;
2795
- container.appendChild(input);
2796
- }
2797
- renderGeneric(container, node) {
2798
- const anyNode = node;
2799
- if (anyNode.options?.content) {
2800
- container.innerHTML = anyNode.options.content;
2801
- }
2802
- else {
2803
- container.textContent = `[${String(node.type)}]`;
2804
- }
2805
- }
2806
- }
2807
- function provideWidgetCoreRenderer() {
2808
- return [{ provide: LAYOUT_WIDGET_RENDER_ENGINE, useClass: WidgetCoreRendererEngine }];
2809
- }
2810
- function provideSimpleDomRenderer() {
2811
- return [{ provide: LAYOUT_WIDGET_RENDER_ENGINE, useClass: SimpleDomRendererEngine }];
2812
- }
2813
-
2814
2884
  /**
2815
2885
  * Generated bundle index. Do not edit.
2816
2886
  */
2817
2887
 
2818
- export { AXPBaseWidgetComponent, AXPBlockBaseLayoutWidgetComponent, AXPBoxModelLayoutWidgetComponent, AXPColumnWidgetComponent, AXPDataListWidgetComponent, AXPFlexBaseLayoutWidgetComponent, AXPFlexItemBaseLayoutWidgetComponent, AXPGridBaseLayoutWidgetComponent, AXPGridItemBaseLayoutWidgetComponent, AXPInlineBaseLayoutWidgetComponent, AXPLayoutBaseWidgetComponent, AXPPageStatus, AXPPropertyEditorHelper, AXPTableBaseLayoutWidgetComponent, AXPTableItemBaseLayoutWidgetComponent, AXPTableItemOpsBaseLayoutWidgetComponent, AXPValueWidgetComponent, AXPWidgetColumnRendererComponent, AXPWidgetContainerComponent, AXPWidgetCoreContextChangeEvent, AXPWidgetCoreContextStore, AXPWidgetCoreElement, AXPWidgetCoreModule, AXPWidgetCoreService, AXPWidgetGroupEnum, AXPWidgetRegistryService, AXPWidgetRendererDirective, AXPWidgetStandaloneRendererHostComponent, AXPWidgetStatus, AXPWidgetsCatalog, AXP_WIDGETS_ACTION_CATEGORY, AXP_WIDGETS_ADVANCE_CATEGORY, AXP_WIDGETS_CATEGORIES, AXP_WIDGETS_EDITOR_CATEGORY, AXP_WIDGETS_LAYOUT_CATEGORY, AXP_WIDGET_COLUMN_TOKEN, AXP_WIDGET_TOKEN, LAYOUT_WIDGET_RENDER_ENGINE, SimpleDomRendererEngine, WidgetCoreRendererEngine, cloneProperty, createBooleanProperty, createNumberProperty, createSelectProperty, createStringProperty, findNonEmptyBreakpoints, provideSimpleDomRenderer, provideWidgetCoreRenderer };
2888
+ export { AXPBaseWidgetComponent, AXPBlockBaseLayoutWidgetComponent, AXPBoxModelLayoutWidgetComponent, AXPColumnWidgetComponent, AXPDataListWidgetComponent, AXPFlexBaseLayoutWidgetComponent, AXPFlexItemBaseLayoutWidgetComponent, AXPGridBaseLayoutWidgetComponent, AXPGridItemBaseLayoutWidgetComponent, AXPInlineBaseLayoutWidgetComponent, AXPLayoutBaseWidgetComponent, AXPPageStatus, AXPPropertyEditorHelper, AXPTableBaseLayoutWidgetComponent, AXPTableItemBaseLayoutWidgetComponent, AXPTableItemOpsBaseLayoutWidgetComponent, AXPValueWidgetComponent, AXPWidgetColumnRendererComponent, AXPWidgetContainerComponent, AXPWidgetCoreContextChangeEvent, AXPWidgetCoreContextStore, AXPWidgetCoreElement, AXPWidgetCoreModule, AXPWidgetCoreService, AXPWidgetGroupEnum, AXPWidgetRegistryService, AXPWidgetRendererDirective, AXPWidgetStatus, AXPWidgetsCatalog, AXP_WIDGETS_ACTION_CATEGORY, AXP_WIDGETS_ADVANCE_CATEGORY, AXP_WIDGETS_CATEGORIES, AXP_WIDGETS_EDITOR_CATEGORY, AXP_WIDGETS_LAYOUT_CATEGORY, AXP_WIDGET_COLUMN_TOKEN, AXP_WIDGET_TOKEN, cloneProperty, createBooleanProperty, createNumberProperty, createSelectProperty, createStringProperty, findNonEmptyBreakpoints };
2819
2889
  //# sourceMappingURL=acorex-platform-layout-widget-core.mjs.map