@acorex/platform 21.0.0-next.2 → 21.0.0-next.3

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 (69) hide show
  1. package/auth/index.d.ts +97 -238
  2. package/common/index.d.ts +778 -213
  3. package/core/index.d.ts +562 -433
  4. package/fesm2022/acorex-platform-auth.mjs +160 -200
  5. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  6. package/fesm2022/acorex-platform-common.mjs +1012 -125
  7. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  8. package/fesm2022/acorex-platform-core.mjs +685 -400
  9. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  10. package/fesm2022/acorex-platform-domain.mjs +54 -11
  11. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  12. package/fesm2022/acorex-platform-layout-builder.mjs +412 -270
  13. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  14. package/fesm2022/acorex-platform-layout-components.mjs +2112 -3153
  15. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  16. package/fesm2022/acorex-platform-layout-designer.mjs +7 -7
  17. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  18. package/fesm2022/acorex-platform-layout-entity.mjs +756 -648
  19. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  20. package/fesm2022/acorex-platform-layout-views.mjs +4 -4
  21. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  22. package/fesm2022/acorex-platform-layout-widget-core.mjs +248 -174
  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-tabular-data-edit-popup.component-m8rHZP8L.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs} +2 -2
  27. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs.map +1 -0
  28. package/fesm2022/acorex-platform-layout-widgets.mjs +3058 -1038
  29. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  30. package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-mARj77Mr.mjs → acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs} +26 -5
  31. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs.map +1 -0
  32. package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs → acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs} +4 -5
  33. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs.map +1 -0
  34. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs +101 -0
  35. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs.map +1 -0
  36. 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
  37. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs.map +1 -0
  38. package/fesm2022/acorex-platform-themes-default.mjs +166 -30
  39. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  40. package/fesm2022/acorex-platform-themes-shared.mjs +27 -27
  41. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  42. package/layout/builder/index.d.ts +4 -1
  43. package/layout/components/index.d.ts +405 -327
  44. package/layout/designer/index.d.ts +3 -3
  45. package/layout/entity/index.d.ts +163 -108
  46. package/layout/widget-core/index.d.ts +39 -49
  47. package/layout/widgets/index.d.ts +368 -54
  48. package/package.json +5 -5
  49. package/themes/default/index.d.ts +15 -2
  50. package/themes/shared/index.d.ts +10 -10
  51. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs +0 -50
  52. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs.map +0 -1
  53. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs +0 -42
  54. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs.map +0 -1
  55. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs +0 -55
  56. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs.map +0 -1
  57. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs +0 -50
  58. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs.map +0 -1
  59. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs +0 -48
  60. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs.map +0 -1
  61. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs +0 -42
  62. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs.map +0 -1
  63. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-D0y-9nE5.mjs.map +0 -1
  64. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-m8rHZP8L.mjs.map +0 -1
  65. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-mARj77Mr.mjs.map +0 -1
  66. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs.map +0 -1
  67. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs +0 -101
  68. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs.map +0 -1
  69. 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;
@@ -328,8 +332,6 @@ const AXPWidgetsCatalog = {
328
332
  advancedGridItem: 'advanced-grid-item-layout',
329
333
  grid: 'grid-layout',
330
334
  gridItem: 'grid-item-layout',
331
- // gridRow: 'grid-row-layout',
332
- widgetSelector: 'widget-selector',
333
335
  template: 'template',
334
336
  templateDesigner: 'template-designer',
335
337
  cronJob: 'cron-job',
@@ -391,8 +393,9 @@ const AXPWidgetsCatalog = {
391
393
  editorJs: 'editor-js-editor',
392
394
  documentUploader: 'document-uploader',
393
395
  signatureList: 'signature-list',
394
- status: 'status-widget',
395
396
  stepWizard: 'step-wizard',
397
+ progressBar: 'progress-bar-editor',
398
+ rate: 'rate-picker-editor'
396
399
  };
397
400
 
398
401
  function cloneProperty(property, values) {
@@ -596,7 +599,8 @@ class AXPValueWidgetComponent extends AXPLayoutBaseWidgetComponent {
596
599
  this._isValueWidget = this.config.properties?.some((c) => c.name == 'path') ?? false;
597
600
  if (this.isValueWidget()) {
598
601
  this.detectFullPath();
599
- 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())) {
600
604
  this.setValue(this.defaultValue);
601
605
  }
602
606
  }
@@ -1212,8 +1216,14 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1212
1216
  super(...arguments);
1213
1217
  this.widgetRegistery = inject(AXPWidgetRegistryService);
1214
1218
  this.grid = inject(AXBaseDataTable);
1219
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
1215
1220
  this.mergedOptions = signal({}, ...(ngDevMode ? [{ debugName: "mergedOptions" }] : []));
1216
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
1217
1227
  this.injector = inject(Injector);
1218
1228
  this.cdr = inject(ChangeDetectorRef);
1219
1229
  }
@@ -1259,6 +1269,8 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1259
1269
  }, {});
1260
1270
  //
1261
1271
  this.mergedOptions.set(merge(props, this.node.options) || {});
1272
+ // Check if options contain expressions (performance optimization)
1273
+ this.hasExpressions = this.checkForExpressions(this.mergedOptions());
1262
1274
  const tokenValue = {
1263
1275
  path: this.node.path,
1264
1276
  options: this.mergedOptions(),
@@ -1276,12 +1288,164 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1276
1288
  this.allowResizing = this.mergedOptions().allowResizing || true;
1277
1289
  this.cdr.detectChanges();
1278
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
1279
1358
  getInputs(data) {
1280
1359
  return {
1281
- rawValue: getSmart(data, this.node.path),
1360
+ rawValue: get(data, this.node.path),
1282
1361
  rowData: data,
1283
1362
  };
1284
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
+ }
1285
1449
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetColumnRendererComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1286
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: [
1287
1451
  AXPWidgetCoreService,
@@ -1309,9 +1473,9 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1309
1473
  }
1310
1474
  </div>
1311
1475
  }
1312
- @if (component && widgetInjector && row?.data) {
1476
+ @if (component && row?.data) {
1313
1477
  <ng-container
1314
- *ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
1478
+ *ngComponentOutlet="component; injector: getRowInjector(row.data); inputs: getInputs(row.data)"
1315
1479
  ></ng-container>
1316
1480
  }
1317
1481
  </div>
@@ -1346,9 +1510,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
1346
1510
  }
1347
1511
  </div>
1348
1512
  }
1349
- @if (component && widgetInjector && row?.data) {
1513
+ @if (component && row?.data) {
1350
1514
  <ng-container
1351
- *ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
1515
+ *ngComponentOutlet="component; injector: getRowInjector(row.data); inputs: getInputs(row.data)"
1352
1516
  ></ng-container>
1353
1517
  }
1354
1518
  </div>
@@ -1472,6 +1636,7 @@ class AXPWidgetRendererDirective {
1472
1636
  this.options = this._options.asReadonly();
1473
1637
  this.onOptionsChanged = output();
1474
1638
  this.onValueChanged = output();
1639
+ this.onLoad = output();
1475
1640
  //#region ---- Public API ----
1476
1641
  /**
1477
1642
  * Signal that emits the component reference when it's ready
@@ -1496,6 +1661,7 @@ class AXPWidgetRendererDirective {
1496
1661
  this.renderTimeoutId = null;
1497
1662
  this.hasInitialRender = false;
1498
1663
  this.onContextChanged = new Subject();
1664
+ this.onLoadEvent = new Subject();
1499
1665
  //#region ---- Performance Optimization Properties ----
1500
1666
  this.contextUpdateQueue = new Set();
1501
1667
  this.contextUpdateTimeout = null;
@@ -1514,14 +1680,33 @@ class AXPWidgetRendererDirective {
1514
1680
  const changed = this.contextService.changeEvent();
1515
1681
  // Don't trigger re-render during initial setup
1516
1682
  if (!this.hasInitialRender) {
1517
- 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) {
1518
1691
  this.preRenderContextQueue.add(changed.path);
1519
1692
  // console.log(`📝 [${this.node().type}] Buffered pre-render context change: ${changed.path}`);
1520
1693
  }
1521
1694
  return;
1522
1695
  }
1523
1696
  // CRITICAL PERFORMANCE FIX: Only respond to relevant context changes
1524
- 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)) {
1525
1710
  // console.log(`🎯 [${this.node().type}] Context change detected: ${changed.path}`);
1526
1711
  this.queueContextUpdate(changed.path);
1527
1712
  }
@@ -1679,7 +1864,7 @@ class AXPWidgetRendererDirective {
1679
1864
  let match;
1680
1865
  while ((match = contextEvalRegex.exec(expressionValue)) !== null) {
1681
1866
  const evalPath = match[1];
1682
- // 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')
1683
1868
  const normalizePath = (p) => {
1684
1869
  if (!p)
1685
1870
  return p;
@@ -1869,6 +2054,7 @@ class AXPWidgetRendererDirective {
1869
2054
  if (this.componentRef) {
1870
2055
  this.componentRef.destroy();
1871
2056
  }
2057
+ this.onLoadEvent.complete();
1872
2058
  }
1873
2059
  async loadComponent() {
1874
2060
  if (this.isLoading()) {
@@ -1916,7 +2102,17 @@ class AXPWidgetRendererDirective {
1916
2102
  // Register expressions from widget defaults and node options to cover related-entity cases
1917
2103
  this.preprocessAndInitialOptions(cloneDeep(widget?.options));
1918
2104
  this.preprocessAndInitialOptions(cloneDeep(this.node().options));
1919
- 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
+ }
1920
2116
  //
1921
2117
  this._options.update((val) => ({ ...val, ...this.mergedOptions() }));
1922
2118
  // Evaluate default value
@@ -1980,13 +2176,33 @@ class AXPWidgetRendererDirective {
1980
2176
  await this.updateVisibility();
1981
2177
  // Process any buffered pre-render context changes now that the component is ready
1982
2178
  if (this.preRenderContextQueue.size > 0) {
1983
- // console.log(
1984
- // `🚀 [${this.node().type}] Processing ${this.preRenderContextQueue.size} buffered pre-render changes`,
1985
- // );
1986
- this.preRenderContextQueue.forEach((p) => this.contextUpdateQueue.add(p));
1987
- this.preRenderContextQueue.clear();
1988
- 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
+ }
1989
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);
1990
2206
  }
1991
2207
  catch (error) {
1992
2208
  // console.error('Error loading component:', error);
@@ -2258,6 +2474,9 @@ class AXPWidgetRendererDirective {
2258
2474
  }));
2259
2475
  },
2260
2476
  from: (event) => get(this.instance.api(), event),
2477
+ load: () => {
2478
+ return this.onLoadEvent.asObservable();
2479
+ },
2261
2480
  };
2262
2481
  }
2263
2482
  getWidgetScope() {
@@ -2276,6 +2495,10 @@ class AXPWidgetRendererDirective {
2276
2495
  if (refresh && typeof refresh === 'function') {
2277
2496
  refresh.bind(this.instance)();
2278
2497
  }
2498
+ else {
2499
+ this.updateOptionsBasedOnContext();
2500
+ this.applyOptions();
2501
+ }
2279
2502
  },
2280
2503
  output: (name) => {
2281
2504
  this.instance.output(name);
@@ -2364,7 +2587,7 @@ class AXPWidgetRendererDirective {
2364
2587
  }
2365
2588
  }
2366
2589
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetRendererDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2367
- 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: [
2368
2591
  {
2369
2592
  provide: AXUnsubscriber,
2370
2593
  },
@@ -2382,7 +2605,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
2382
2605
  ],
2383
2606
  standalone: false,
2384
2607
  }]
2385
- }], 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"] }] } });
2386
2609
 
2387
2610
  const COMPONENTS = [AXPWidgetContainerComponent, AXPWidgetColumnRendererComponent, AXPWidgetRendererDirective];
2388
2611
  class AXPWidgetCoreModule {
@@ -2658,158 +2881,9 @@ var AXPWidgetGroupEnum;
2658
2881
  AXPWidgetGroupEnum["UtilityWidget"] = "utility-widget";
2659
2882
  })(AXPWidgetGroupEnum || (AXPWidgetGroupEnum = {}));
2660
2883
 
2661
- class AXPWidgetStandaloneRendererHostComponent {
2662
- constructor() {
2663
- this.mode = 'edit';
2664
- }
2665
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetStandaloneRendererHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2666
- 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: `
2667
- <axp-widgets-container [context]="context" [functions]="functions">
2668
- <ng-container axp-widget-renderer [mode]="mode" [node]="node"></ng-container>
2669
- </axp-widgets-container>
2670
- `, 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"] }] }); }
2671
- }
2672
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetStandaloneRendererHostComponent, decorators: [{
2673
- type: Component,
2674
- args: [{
2675
- selector: 'axp-widget-standalone-renderer-host',
2676
- template: `
2677
- <axp-widgets-container [context]="context" [functions]="functions">
2678
- <ng-container axp-widget-renderer [mode]="mode" [node]="node"></ng-container>
2679
- </axp-widgets-container>
2680
- `,
2681
- standalone: true,
2682
- imports: [AXPWidgetCoreModule]
2683
- }]
2684
- }], propDecorators: { mode: [{
2685
- type: Input
2686
- }], node: [{
2687
- type: Input
2688
- }], context: [{
2689
- type: Input
2690
- }], functions: [{
2691
- type: Input
2692
- }] } });
2693
-
2694
- const LAYOUT_WIDGET_RENDER_ENGINE = new InjectionToken('LAYOUT_WIDGET_RENDER_ENGINE');
2695
- class WidgetCoreRendererEngine {
2696
- constructor(appRef, env) {
2697
- this.appRef = appRef;
2698
- this.env = env;
2699
- }
2700
- render(node, target, context, mode = 'edit') {
2701
- const compRef = createComponent(AXPWidgetStandaloneRendererHostComponent, { environmentInjector: this.env });
2702
- compRef.setInput('mode', mode);
2703
- compRef.setInput('node', node);
2704
- if (context) {
2705
- compRef.setInput('context', context);
2706
- }
2707
- this.appRef.attachView(compRef.hostView);
2708
- target.appendChild(compRef.location.nativeElement);
2709
- return {
2710
- element: compRef.location.nativeElement,
2711
- destroy: () => {
2712
- try {
2713
- this.appRef.detachView(compRef.hostView);
2714
- }
2715
- catch { }
2716
- compRef.destroy();
2717
- },
2718
- };
2719
- }
2720
- 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 }); }
2721
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: WidgetCoreRendererEngine, providedIn: 'root' }); }
2722
- }
2723
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: WidgetCoreRendererEngine, decorators: [{
2724
- type: Injectable,
2725
- args: [{ providedIn: 'root' }]
2726
- }], ctorParameters: () => [{ type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }] });
2727
- class SimpleDomRendererEngine {
2728
- render(node, target) {
2729
- const element = this.createElement(node);
2730
- target.appendChild(element);
2731
- return {
2732
- element,
2733
- destroy: () => {
2734
- if (element.parentElement) {
2735
- element.parentElement.removeChild(element);
2736
- }
2737
- },
2738
- };
2739
- }
2740
- createElement(node) {
2741
- const container = document.createElement('div');
2742
- container.className = `axp-widget axp-widget-${node.type}`;
2743
- switch (String(node.type)) {
2744
- case 'text-block-layout':
2745
- case 'static-text':
2746
- this.renderText(container, node);
2747
- break;
2748
- case 'tag':
2749
- this.renderTag(container, node);
2750
- break;
2751
- case 'text-editor':
2752
- this.renderTextBox(container, node);
2753
- break;
2754
- default:
2755
- this.renderGeneric(container, node);
2756
- break;
2757
- }
2758
- return container;
2759
- }
2760
- renderText(container, node) {
2761
- const anyNode = node;
2762
- const content = (anyNode.options && (anyNode.options.content || anyNode.options.label)) || '';
2763
- container.innerHTML = typeof content === 'string' ? content : String(content);
2764
- }
2765
- renderTag(container, node) {
2766
- const label = node.options?.label || 'Tag';
2767
- const tone = node.options?.tone || 'primary';
2768
- container.innerHTML = `<span class="tag tag-${tone}" style="
2769
- display: inline-block;
2770
- padding: 4px 12px;
2771
- border-radius: 12px;
2772
- font-size: 12px;
2773
- font-weight: 500;
2774
- background: ${tone === 'success' ? '#d4edda' : '#cce5ff'};
2775
- color: ${tone === 'success' ? '#155724' : '#004085'};
2776
- border: 1px solid ${tone === 'success' ? '#c3e6cb' : '#b8daff'};
2777
- ">${label}</span>`;
2778
- }
2779
- renderTextBox(container, node) {
2780
- const placeholder = node.options?.placeholder || '';
2781
- const input = document.createElement('input');
2782
- input.type = 'text';
2783
- input.placeholder = placeholder;
2784
- input.style.cssText = `
2785
- width: 100%;
2786
- padding: 8px 12px;
2787
- border: 1px solid #ddd;
2788
- border-radius: 4px;
2789
- font-size: 14px;
2790
- `;
2791
- container.appendChild(input);
2792
- }
2793
- renderGeneric(container, node) {
2794
- const anyNode = node;
2795
- if (anyNode.options?.content) {
2796
- container.innerHTML = anyNode.options.content;
2797
- }
2798
- else {
2799
- container.textContent = `[${String(node.type)}]`;
2800
- }
2801
- }
2802
- }
2803
- function provideWidgetCoreRenderer() {
2804
- return [{ provide: LAYOUT_WIDGET_RENDER_ENGINE, useClass: WidgetCoreRendererEngine }];
2805
- }
2806
- function provideSimpleDomRenderer() {
2807
- return [{ provide: LAYOUT_WIDGET_RENDER_ENGINE, useClass: SimpleDomRendererEngine }];
2808
- }
2809
-
2810
2884
  /**
2811
2885
  * Generated bundle index. Do not edit.
2812
2886
  */
2813
2887
 
2814
- 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 };
2815
2889
  //# sourceMappingURL=acorex-platform-layout-widget-core.mjs.map