@acorex-platform/framework-client 2.0.0-next.3 → 2.0.0-next.30

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 (81) hide show
  1. package/fesm2022/acorex-platform-framework-client-auth.mjs +8 -9
  2. package/fesm2022/acorex-platform-framework-client-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-ChU2tvyt.mjs → acorex-platform-framework-client-common-common-settings.provider-Biu0_ryw.mjs} +35 -2
  4. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-Biu0_ryw.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-framework-client-common.mjs +1382 -538
  6. package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-framework-client-core.mjs +7 -2
  8. package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs +20 -0
  10. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-framework-client-layout-components.mjs +520 -142
  12. package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
  13. package/fesm2022/{acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-DaOvPoNI.mjs → acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-DmkFxSuJ.mjs} +1084 -223
  14. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-DmkFxSuJ.mjs.map +1 -0
  15. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-BU7KEfyF.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-BV5WLQVo.mjs} +2 -2
  16. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-BU7KEfyF.mjs.map → acorex-platform-framework-client-layout-entity-attachments-page.component-BV5WLQVo.mjs.map} +1 -1
  17. package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-Boq0MUFK.mjs → acorex-platform-framework-client-layout-entity-bulk-entity.command-O8zdiHRH.mjs} +2 -2
  18. package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-Boq0MUFK.mjs.map → acorex-platform-framework-client-layout-entity-bulk-entity.command-O8zdiHRH.mjs.map} +1 -1
  19. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-CMoFkzhf.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-B3-0gJTQ.mjs} +4 -4
  20. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-CMoFkzhf.mjs.map → acorex-platform-framework-client-layout-entity-file-list-popup.component-B3-0gJTQ.mjs.map} +1 -1
  21. package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-Bre8friL.mjs → acorex-platform-framework-client-layout-entity-gallery-page.component-CjfLUBPZ.mjs} +2 -2
  22. package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-Bre8friL.mjs.map → acorex-platform-framework-client-layout-entity-gallery-page.component-CjfLUBPZ.mjs.map} +1 -1
  23. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +1 -1
  24. package/fesm2022/acorex-platform-framework-client-layout-views.mjs +94 -17
  25. package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
  26. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +285 -184
  27. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
  28. package/fesm2022/{acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-1UJh0Qj4.mjs → acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-CpmGqDUE.mjs} +1167 -265
  29. package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-CpmGqDUE.mjs.map +1 -0
  30. package/fesm2022/acorex-platform-framework-client-layout-widgets-filter-default-operators-widget-edit.component-DOEn58--.mjs +103 -0
  31. package/fesm2022/acorex-platform-framework-client-layout-widgets-filter-default-operators-widget-edit.component-DOEn58--.mjs.map +1 -0
  32. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-SHCgo4UC.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-XgjDH9Oc.mjs} +3 -3
  33. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-SHCgo4UC.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-XgjDH9Oc.mjs.map} +1 -1
  34. package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BYsrp8LT.mjs → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-DDczHmAA.mjs} +2 -2
  35. package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BYsrp8LT.mjs.map → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-DDczHmAA.mjs.map} +1 -1
  36. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +1 -1
  37. package/fesm2022/acorex-platform-framework-client-realtime.mjs +49 -7
  38. package/fesm2022/acorex-platform-framework-client-realtime.mjs.map +1 -1
  39. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-create-view.component-DwCoz2Du.mjs → acorex-platform-framework-client-themes-default-entity-master-create-view.component-DPU6jTDk.mjs} +8 -2
  40. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DPU6jTDk.mjs.map +1 -0
  41. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BCyFK60f.mjs → acorex-platform-framework-client-themes-default-entity-master-modify-view.component-CLdQJ8e8.mjs} +8 -2
  42. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-CLdQJ8e8.mjs.map +1 -0
  43. package/fesm2022/{acorex-platform-framework-client-themes-default-error-401.component-1lfBpY_d.mjs → acorex-platform-framework-client-themes-default-error-401.component-DszlyIaw.mjs} +5 -11
  44. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-DszlyIaw.mjs.map +1 -0
  45. package/fesm2022/{acorex-platform-framework-client-themes-default-error-404.component-BeWyRCJr.mjs → acorex-platform-framework-client-themes-default-error-404.component-BusKNAit.mjs} +5 -11
  46. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-BusKNAit.mjs.map +1 -0
  47. package/fesm2022/{acorex-platform-framework-client-themes-default-error-offline.component-PvveUj5c.mjs → acorex-platform-framework-client-themes-default-error-offline.component-Abf14p44.mjs} +15 -4
  48. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-Abf14p44.mjs.map +1 -0
  49. package/fesm2022/acorex-platform-framework-client-themes-default-error-page-go-home-B9VmB9Vt.mjs +19 -0
  50. package/fesm2022/acorex-platform-framework-client-themes-default-error-page-go-home-B9VmB9Vt.mjs.map +1 -0
  51. package/fesm2022/acorex-platform-framework-client-themes-default.mjs +306 -129
  52. package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
  53. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +11 -5
  54. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
  55. package/i18n/en-AU/general.json +32 -4
  56. package/i18n/en-AU/layout.json +2 -1
  57. package/i18n/en-AU/platform-layout-widgets.json +7 -1
  58. package/i18n/en-US/general.json +32 -4
  59. package/i18n/en-US/layout.json +2 -1
  60. package/i18n/en-US/platform-layout-widgets.json +7 -1
  61. package/i18n/fa-IR/general.json +32 -4
  62. package/i18n/fa-IR/layout.json +2 -1
  63. package/i18n/fa-IR/platform-layout-widgets.json +7 -1
  64. package/package.json +6 -6
  65. package/types/acorex-platform-framework-client-auth.d.ts +21 -11
  66. package/types/acorex-platform-framework-client-common.d.ts +230 -14
  67. package/types/acorex-platform-framework-client-layout-components.d.ts +47 -6
  68. package/types/acorex-platform-framework-client-layout-entity.d.ts +187 -35
  69. package/types/acorex-platform-framework-client-layout-views.d.ts +15 -0
  70. package/types/acorex-platform-framework-client-layout-widget-core.d.ts +64 -14
  71. package/types/acorex-platform-framework-client-layout-widgets.d.ts +145 -9
  72. package/types/acorex-platform-framework-client-realtime.d.ts +5 -0
  73. package/types/acorex-platform-framework-client-themes-default.d.ts +16 -5
  74. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-ChU2tvyt.mjs.map +0 -1
  75. package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-DaOvPoNI.mjs.map +0 -1
  76. package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-1UJh0Qj4.mjs.map +0 -1
  77. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DwCoz2Du.mjs.map +0 -1
  78. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BCyFK60f.mjs.map +0 -1
  79. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-1lfBpY_d.mjs.map +0 -1
  80. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-BeWyRCJr.mjs.map +0 -1
  81. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-PvveUj5c.mjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, signal, computed, effect, untracked, Injectable, inject, ElementRef, DestroyRef, PLATFORM_ID, EventEmitter, Injector, ChangeDetectorRef, ViewChild, Input, Output, ChangeDetectionStrategy, Component, input, output, ViewContainerRef, Directive, NgModule } from '@angular/core';
3
- import { AXPContextStore, AXPDeviceService, AXPExpressionEvaluatorService, AXPDebugService, FORM_DIRTY_TRACE_NS, OVERLAY_WIDGET_SETTLE_TRACE_NS } from '@acorex-platform/framework-client/core';
3
+ import { AXPContextStore, AXPExpressionEvaluatorService, AXPDeviceService, AXPDebugService, FORM_DIRTY_TRACE_NS, OVERLAY_WIDGET_SETTLE_TRACE_NS } from '@acorex-platform/framework-client/core';
4
4
  import { AXPPageStatus, AXPWidgetStatus, AXP_WIDGET_TOKEN, AXP_WIDGET_COLUMN_TOKEN, layoutProfileMediumFromRenderMode, resolveLayoutProfile, createStringProperty, createBooleanProperty, createSelectProperty, createNumberProperty, cloneProperty } from '@acorex-platform/framework-shared/widget-core';
5
- import { cloneDeep, set, get, isEqual, isNil, isUndefined, isObjectLike, merge, sum, isEmpty, isString } from 'lodash-es';
5
+ import { cloneDeep, get, isEqual, set, isNil, isUndefined, isObjectLike, merge, sum, isEmpty, isString } from 'lodash-es';
6
6
  import { AXPWidgetsList, isSelectionValueEqual, isFormValueEqual, runtimeQueryPayloadData, runtimeQueryCollectionData, extractValue, axpGridItemPlacementClassMap, getSmart, summarizeFormContextDirtyDiff, AXPWidgetsCatalog } from '@acorex-platform/framework-shared/core';
7
7
  import { ENTITY_GET_BY_ID_DEFAULT } from '@acorex-platform/framework-shared/runtime';
8
8
  export { AXP_WIDGETS_ACTION_CATEGORY, AXP_WIDGETS_ACTION_SUB_CONTROLS, AXP_WIDGETS_ADVANCE_CATEGORY, AXP_WIDGETS_ADVANCE_SUB_DATA, AXP_WIDGETS_ADVANCE_SUB_INPUT, AXP_WIDGETS_ADVANCE_SUB_MEDIA, AXP_WIDGETS_ADVANCE_SUB_TOOLS, AXP_WIDGETS_AI_CATEGORY, AXP_WIDGETS_CATEGORIES, AXP_WIDGETS_EDITOR_CATEGORY, AXP_WIDGETS_EDITOR_SUB_CHOICE, AXP_WIDGETS_EDITOR_SUB_COMPOSITE, AXP_WIDGETS_EDITOR_SUB_CONFIG, AXP_WIDGETS_EDITOR_SUB_DATETIME, AXP_WIDGETS_EDITOR_SUB_NUMERIC, AXP_WIDGETS_EDITOR_SUB_RICH, AXP_WIDGETS_EDITOR_SUB_TEXT_INPUTS, AXP_WIDGETS_EDITOR_SUB_VISUAL, AXP_WIDGETS_LAYOUT_CATEGORY, AXP_WIDGETS_LAYOUT_SUB_GRID, AXP_WIDGETS_LAYOUT_SUB_LISTS, AXP_WIDGETS_LAYOUT_SUB_SHELL, AXP_WIDGETS_LAYOUT_SUB_SURFACES, AXP_WIDGETS_LAYOUT_SUB_TABS, AXP_WIDGETS_LAYOUT_SUB_UTILITY, normalizeWidgetCategories } from '@acorex-platform/framework-shared/runtime';
@@ -402,6 +402,83 @@ class AXPWidgetSerializationHelper {
402
402
  }
403
403
  //#endregion
404
404
 
405
+ //#endregion
406
+ //#region ----- Helpers -----
407
+ function isBlankExposeValue(value) {
408
+ if (value == null) {
409
+ return true;
410
+ }
411
+ if (typeof value === 'string') {
412
+ return value.trim() === '';
413
+ }
414
+ if (Array.isArray(value)) {
415
+ return value.length === 0;
416
+ }
417
+ return false;
418
+ }
419
+ function readExposeMapping(entry) {
420
+ if (typeof entry === 'string') {
421
+ const path = entry.trim();
422
+ if (!path) {
423
+ return null;
424
+ }
425
+ return { source: path, target: path };
426
+ }
427
+ const source = entry?.source?.trim() ?? '';
428
+ const target = entry?.target?.trim() ?? '';
429
+ if (!source || !target) {
430
+ return null;
431
+ }
432
+ return { source, target };
433
+ }
434
+ /** True when writing `target` would replace this widget's own value or its parent object. */
435
+ function exposeTargetTouchesWidget(target, widgetPath) {
436
+ if (!widgetPath) {
437
+ return false;
438
+ }
439
+ if (target === widgetPath) {
440
+ return true;
441
+ }
442
+ if (widgetPath.startsWith(`${target}.`) || widgetPath.startsWith(`${target}[`)) {
443
+ return true;
444
+ }
445
+ if (target.startsWith(`${widgetPath}.`) || target.startsWith(`${widgetPath}[`)) {
446
+ return true;
447
+ }
448
+ return false;
449
+ }
450
+ //#endregion
451
+ //#region ----- Resolve -----
452
+ /**
453
+ * Leaf writes for opening a form. Skips empty sources, the widget's own path,
454
+ * and targets that already hold a different value.
455
+ */
456
+ function resolveWidgetExposeHydrateWrites(input) {
457
+ const items = input.items.filter((item) => item != null);
458
+ if (!items.length || !input.expose?.length) {
459
+ return [];
460
+ }
461
+ const writes = [];
462
+ for (const entry of input.expose) {
463
+ const mapping = readExposeMapping(entry);
464
+ if (!mapping || exposeTargetTouchesWidget(mapping.target, input.widgetPath)) {
465
+ continue;
466
+ }
467
+ const sources = items.map((item) => get(item, mapping.source));
468
+ if (sources.some((value) => isBlankExposeValue(value))) {
469
+ continue;
470
+ }
471
+ const nextValue = input.multiple ? sources : sources[0];
472
+ const current = input.readTarget(mapping.target);
473
+ if (isEqual(current, nextValue) || !isBlankExposeValue(current)) {
474
+ continue;
475
+ }
476
+ writes.push({ path: mapping.target, value: nextValue });
477
+ }
478
+ return writes;
479
+ }
480
+ //#endregion
481
+
405
482
  class AXPWidgetCoreElement {
406
483
  api() {
407
484
  return {};
@@ -601,6 +678,103 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
601
678
  type: Injectable
602
679
  }], ctorParameters: () => [] });
603
680
 
681
+ //#region ----- Authored rules -----
682
+ function collectAuthoredValidationRules(validationsRaw) {
683
+ if (validationsRaw == null) {
684
+ return [];
685
+ }
686
+ const values = Array.isArray(validationsRaw)
687
+ ? validationsRaw
688
+ : Object.values(validationsRaw);
689
+ const rules = [];
690
+ for (const item of values) {
691
+ if (item == null || typeof item !== 'object') {
692
+ continue;
693
+ }
694
+ const candidate = item;
695
+ if (typeof candidate.rule !== 'string' || candidate.rule.length === 0) {
696
+ continue;
697
+ }
698
+ rules.push({
699
+ rule: candidate.rule,
700
+ message: candidate.message,
701
+ options: candidate.options,
702
+ disabled: candidate.disabled,
703
+ });
704
+ }
705
+ return rules;
706
+ }
707
+ //#endregion
708
+ //#region ----- Disabled resolution -----
709
+ function assumedValidationDisabled(disabled, isExpression) {
710
+ if (disabled === true) {
711
+ return true;
712
+ }
713
+ return typeof disabled === 'string' && isExpression(disabled);
714
+ }
715
+ function resolveValidationContextPath(path, parentPath) {
716
+ if (!path.startsWith('>')) {
717
+ return path;
718
+ }
719
+ const rest = path.slice(1);
720
+ return parentPath ? `${parentPath}.${rest}` : rest;
721
+ }
722
+ function validationExpressionScope(readPath) {
723
+ return {
724
+ context: {
725
+ eval: (path) => readPath(path),
726
+ },
727
+ };
728
+ }
729
+ async function resolveValidationDisabledFlags(rules, isExpression, evaluate) {
730
+ return Promise.all(rules.map(async (rule) => {
731
+ const disabled = rule.disabled;
732
+ if (typeof disabled === 'boolean') {
733
+ return disabled;
734
+ }
735
+ if (typeof disabled !== 'string' || !isExpression(disabled)) {
736
+ return false;
737
+ }
738
+ try {
739
+ return (await evaluate(disabled)) === true;
740
+ }
741
+ catch {
742
+ return false;
743
+ }
744
+ }));
745
+ }
746
+ //#endregion
747
+ async function isRequiredRuleActive(disabledSources, isExpression, evaluate) {
748
+ if (disabledSources.length === 0) {
749
+ return false;
750
+ }
751
+ const flags = await resolveValidationDisabledFlags(disabledSources.map((disabled) => ({ rule: 'required', disabled })), isExpression, evaluate);
752
+ return flags.some((disabled) => disabled !== true);
753
+ }
754
+ /**
755
+ * Live required indicator: a `required` rule counts only while its `disabled` flag is not true.
756
+ * Expression `disabled` stays off until the expression resolves.
757
+ */
758
+ function syncRequiredIndicator(args) {
759
+ const required = signal(false, /* @ts-ignore */
760
+ ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
761
+ let generation = 0;
762
+ effect(() => {
763
+ const rules = args.nodes().flatMap((node) => collectAuthoredValidationRules(node.options?.['validations']));
764
+ args.trackContext();
765
+ const generationId = ++generation;
766
+ required.set(rules.some((rule) => rule.rule === 'required' && !assumedValidationDisabled(rule.disabled, args.isExpression)));
767
+ void resolveValidationDisabledFlags(rules, args.isExpression, args.evaluate).then((flags) => {
768
+ if (generationId !== generation) {
769
+ return;
770
+ }
771
+ required.set(rules.some((rule, index) => rule.rule === 'required' && flags[index] !== true));
772
+ });
773
+ });
774
+ return required.asReadonly();
775
+ }
776
+ //#endregion
777
+
604
778
  //#region ----- Imports -----
605
779
  //#endregion
606
780
  //#region ----- Constants -----
@@ -1086,30 +1260,52 @@ class AXPValueWidgetComponent extends AXPLayoutBaseWidgetComponent {
1086
1260
  ...(ngDevMode ? [{ debugName: "fullPath" }] : /* istanbul ignore next */ []));
1087
1261
  this.parentPath = signal(null, /* @ts-ignore */
1088
1262
  ...(ngDevMode ? [{ debugName: "parentPath" }] : /* istanbul ignore next */ []));
1263
+ this.validationExpressionEvaluator = inject(AXPExpressionEvaluatorService);
1264
+ this.validationDisabledByIndex = signal([], /* @ts-ignore */
1265
+ ...(ngDevMode ? [{ debugName: "validationDisabledByIndex" }] : /* istanbul ignore next */ []));
1266
+ this.validationDisabledGeneration = 0;
1267
+ this.#syncValidationDisabled = effect(() => {
1268
+ const rules = collectAuthoredValidationRules(this.options()['validations']);
1269
+ this.contextService.data();
1270
+ const parent = this.parentPath();
1271
+ const generation = ++this.validationDisabledGeneration;
1272
+ void resolveValidationDisabledFlags(rules, (value) => this.validationExpressionEvaluator.isExpression(value), (expression) => this.validationExpressionEvaluator.evaluate(expression, validationExpressionScope((path) => this.contextService.getValue(resolveValidationContextPath(path, parent))))).then((flags) => {
1273
+ if (generation !== this.validationDisabledGeneration) {
1274
+ return;
1275
+ }
1276
+ const current = this.validationDisabledByIndex();
1277
+ if (current.length === flags.length && current.every((flag, index) => flag === flags[index])) {
1278
+ return;
1279
+ }
1280
+ this.validationDisabledByIndex.set(flags);
1281
+ });
1282
+ }, /* @ts-ignore */
1283
+ ...(ngDevMode ? [{ debugName: "#syncValidationDisabled" }] : /* istanbul ignore next */ []));
1089
1284
  this.getValue = computed(() => {
1090
1285
  return this.fullPath() ? this.extractValue(this.fullPath()) : null;
1091
1286
  }, { ...(ngDevMode ? { debugName: "getValue" } : /* istanbul ignore next */ {}), equal: isEqual });
1092
- this.validationRules = computed(() => {
1093
- const validationsRaw = this.options()['validations'];
1094
- if (validationsRaw == null) {
1095
- return [];
1096
- }
1097
- return Object.values(this.options()['validations'])
1098
- .filter((c) => c != null)
1099
- .map((c) => ({
1100
- rule: c.rule,
1101
- message: c.message,
1102
- options: c.options,
1287
+ this.validationRulesWithDisabled = computed(() => {
1288
+ const rules = collectAuthoredValidationRules(this.options()['validations']);
1289
+ const flags = this.validationDisabledByIndex();
1290
+ const isExpression = (value) => this.validationExpressionEvaluator.isExpression(value);
1291
+ return rules.map((rule, index) => ({
1292
+ rule: rule.rule,
1293
+ message: rule.message,
1294
+ options: rule.options,
1295
+ disabled: flags[index] ?? assumedValidationDisabled(rule.disabled, isExpression),
1103
1296
  }));
1104
1297
  }, /* @ts-ignore */
1298
+ ...(ngDevMode ? [{ debugName: "validationRulesWithDisabled" }] : /* istanbul ignore next */ []));
1299
+ this.validationRules = computed(() => this.validationRulesWithDisabled(), /* @ts-ignore */
1105
1300
  ...(ngDevMode ? [{ debugName: "validationRules" }] : /* istanbul ignore next */ []));
1106
- this.hasRequiredValidation = computed(() => this.validationRules().some((rule) => rule.rule === 'required'), /* @ts-ignore */
1301
+ this.hasRequiredValidation = computed(() => this.validationRules().some((rule) => rule.rule === 'required' && rule.disabled !== true), /* @ts-ignore */
1107
1302
  ...(ngDevMode ? [{ debugName: "hasRequiredValidation" }] : /* istanbul ignore next */ []));
1108
1303
  this.hasClearButton = computed(() => this.resolveClearButtonOption('hasClearButton'), /* @ts-ignore */
1109
1304
  ...(ngDevMode ? [{ debugName: "hasClearButton" }] : /* istanbul ignore next */ []));
1110
1305
  this.clearButton = computed(() => this.resolveClearButtonOption('clearButton'), /* @ts-ignore */
1111
1306
  ...(ngDevMode ? [{ debugName: "clearButton" }] : /* istanbul ignore next */ []));
1112
1307
  }
1308
+ #syncValidationDisabled;
1113
1309
  ngOnInit() {
1114
1310
  this._isValueWidget = this.config.properties?.some((c) => c.name == 'path') ?? false;
1115
1311
  if (this.isValueWidget()) {
@@ -2038,6 +2234,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
2038
2234
  type: Injectable
2039
2235
  }] });
2040
2236
 
2237
+ const AXP_WIDGET_COLUMN_AUTO_FIT = new InjectionToken('AXP_WIDGET_COLUMN_AUTO_FIT');
2238
+
2041
2239
  //#region ---- Imports ----
2042
2240
  /**
2043
2241
  * Injection token for widget definition providers.
@@ -2123,8 +2321,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
2123
2321
  }]
2124
2322
  }] });
2125
2323
 
2126
- const AXP_WIDGET_COLUMN_AUTO_FIT = new InjectionToken('AXP_WIDGET_COLUMN_AUTO_FIT');
2127
-
2128
2324
  class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2129
2325
  constructor() {
2130
2326
  super(...arguments);
@@ -2200,6 +2396,9 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2200
2396
  this.loadingRow.set(row);
2201
2397
  await this.grid.expandRow(row);
2202
2398
  this.loadingRow.set(null);
2399
+ this.contentAutoFitSettled = false;
2400
+ this.contentAutoFitShouldSettle = false;
2401
+ this.scheduleContentAutoFit();
2203
2402
  // if (row.data?.__meta__?.expanded === undefined) {
2204
2403
  // this.width = `${parseInt(this.width as string) + 24}px`;
2205
2404
  // }
@@ -2256,9 +2455,7 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2256
2455
  return this.normalizeColumnAlignment(align);
2257
2456
  }
2258
2457
  if (typeof align === 'object' && !Array.isArray(align)) {
2259
- const raw = side === 'header'
2260
- ? align.header
2261
- : align.cell;
2458
+ const raw = side === 'header' ? align.header : align.cell;
2262
2459
  return this.normalizeColumnAlignment(raw);
2263
2460
  }
2264
2461
  return 'start';
@@ -2314,12 +2511,7 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2314
2511
  },
2315
2512
  ],
2316
2513
  });
2317
- this.width =
2318
- this.mergedOptions().width === 'auto'
2319
- ? 'auto'
2320
- : this.customWidth
2321
- ? this.customWidth
2322
- : (this.mergedOptions().width ?? '200px');
2514
+ this.width = this.mergedOptions().width === 'auto' ? 'auto' : this.customWidth ? this.customWidth : (this.mergedOptions().width ?? '200px');
2323
2515
  this.allowResizing = this.mergedOptions().allowResizing !== false;
2324
2516
  this.allowSorting = this.sortEnabled;
2325
2517
  this.syncAutoWidthIntent();
@@ -2383,9 +2575,7 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2383
2575
  return;
2384
2576
  }
2385
2577
  this.bandLocaleWatchStarted = true;
2386
- this.translation.langChanges$
2387
- .pipe(takeUntilDestroyed(this.destroyRef))
2388
- .subscribe(() => {
2578
+ this.translation.langChanges$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
2389
2579
  if (this.isBand && this.bandCaptionI18nKey) {
2390
2580
  this.resolveBandCaption();
2391
2581
  }
@@ -2396,8 +2586,7 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2396
2586
  return;
2397
2587
  }
2398
2588
  this.caption = text;
2399
- const topLevel = this.grid
2400
- .topLevelColumnsList;
2589
+ const topLevel = this.grid.topLevelColumnsList;
2401
2590
  if (topLevel) {
2402
2591
  topLevel.set([...topLevel()]);
2403
2592
  }
@@ -2429,9 +2618,7 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2429
2618
  // Use a hash of key properties instead of full JSON.stringify
2430
2619
  // This is much faster for large objects
2431
2620
  const keyProps = ['id', 'code', 'name', 'title'];
2432
- const keyValues = keyProps
2433
- .map((prop) => data?.[prop])
2434
- .filter((v) => v != null);
2621
+ const keyValues = keyProps.map((prop) => data?.[prop]).filter((v) => v != null);
2435
2622
  if (keyValues.length > 0) {
2436
2623
  return `row-${keyValues.join('-')}`;
2437
2624
  }
@@ -2482,7 +2669,8 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2482
2669
  if (!isPlatformBrowser(this.platformId) || !this.autoWidthColumn || this.contentAutoFitSettled) {
2483
2670
  return;
2484
2671
  }
2485
- this.contentAutoFitShouldSettle = this.contentAutoFitShouldSettle || request?.settle === true;
2672
+ const allowSettle = this.expandHandler !== true;
2673
+ this.contentAutoFitShouldSettle = this.contentAutoFitShouldSettle || (request?.settle === true && allowSettle);
2486
2674
  if (this.contentAutoFitTimer != null) {
2487
2675
  clearTimeout(this.contentAutoFitTimer);
2488
2676
  }
@@ -2654,23 +2842,13 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2654
2842
  [class.flex]="!sortEnabled"
2655
2843
  [class.items-center]="!sortEnabled"
2656
2844
  [class.axp-widget-column-header--sortable]="sortEnabled"
2657
- [class.axp-widget-column-header--sort-at-start]="
2658
- sortEnabled && getHeaderTextAlign() === 'end'
2659
- "
2660
- [class.axp-widget-column-header--sort-active]="
2661
- headerSortDirection === 'asc' || headerSortDirection === 'desc'
2662
- "
2845
+ [class.axp-widget-column-header--sort-at-start]="sortEnabled && getHeaderTextAlign() === 'end'"
2846
+ [class.axp-widget-column-header--sort-active]="headerSortDirection === 'asc' || headerSortDirection === 'desc'"
2663
2847
  [class.gap-1]="!sortEnabled"
2664
- [style.justify-content]="
2665
- sortEnabled ? 'flex-start' : getHeaderJustifyContent()
2666
- "
2848
+ [style.justify-content]="sortEnabled ? 'flex-start' : getHeaderJustifyContent()"
2667
2849
  (click)="onHeaderClick($event)"
2668
2850
  >
2669
- <span
2670
- class="axp-widget-column-header__caption truncate"
2671
- [class.axp-widget-column-header__caption--with-sort]="sortEnabled"
2672
- [style.text-align]="sortEnabled ? getHeaderTextAlign() : null"
2673
- >
2851
+ <span class="axp-widget-column-header__caption truncate" [class.axp-widget-column-header__caption--with-sort]="sortEnabled" [style.text-align]="sortEnabled ? getHeaderTextAlign() : null">
2674
2852
  @if (isBand) {
2675
2853
  {{ caption }}
2676
2854
  } @else {
@@ -2680,84 +2858,40 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
2680
2858
  @if (sortEnabled) {
2681
2859
  <span class="axp-widget-column-header__sort">
2682
2860
  @if (headerSortPriority !== undefined && headerSortPriority > 1) {
2683
- <span
2684
- class="axp-widget-column-header__sort-priority text-xs opacity-70"
2685
- >{{ headerSortPriority }}</span
2686
- >
2861
+ <span class="axp-widget-column-header__sort-priority text-xs opacity-70">{{ headerSortPriority }}</span>
2687
2862
  }
2688
- <i
2689
- class="fa-solid fa-arrow-up-long text-neutral-400"
2690
- [class.text-primary]="headerSortDirection === 'asc'"
2691
- ></i>
2692
- <i
2693
- class="fa-solid fa-arrow-down-long text-neutral-400"
2694
- [class.text-primary]="headerSortDirection === 'desc'"
2695
- ></i>
2863
+ <i class="fa-solid fa-arrow-up-long text-neutral-400" [class.text-primary]="headerSortDirection === 'asc'"></i>
2864
+ <i class="fa-solid fa-arrow-down-long text-neutral-400" [class.text-primary]="headerSortDirection === 'desc'"></i>
2696
2865
  </span>
2697
2866
  }
2698
2867
  </div>
2699
2868
  </ng-template>
2700
2869
  <ng-template #cell let-row>
2701
2870
  @if (expandHandler) {
2702
- <div
2703
- class="ax-data-table-nested-indent w-full"
2704
- [attr.data-level]="row.data?.__meta__?.level || 0"
2705
- >
2871
+ <div class="ax-data-table-nested-indent w-full" [attr.data-level]="row.data?.__meta__?.level || 0">
2706
2872
  @if (hasExpandableRow(row)) {
2707
- <div
2708
- (click)="handleExpandRow(row, $event)"
2709
- class="ax-expand-handler"
2710
- id="ax-expand-handler-container"
2711
- >
2873
+ <div (click)="handleExpandRow(row, $event)" class="ax-expand-handler" id="ax-expand-handler-container">
2712
2874
  @if (loadingRow() === row) {
2713
- <i
2714
- class="fas fa-spinner-third animate-twSpin animate-infinite"
2715
- ></i>
2875
+ <i class="fas fa-spinner-third animate-twSpin animate-infinite"></i>
2716
2876
  } @else {
2717
2877
  @if (row.data?.__meta__?.expanded) {
2718
- <i
2719
- [class]="
2720
- customCollapseIcon ||
2721
- 'far fa-minus-square text-md opacity-75'
2722
- "
2723
- ></i>
2878
+ <i [class]="customCollapseIcon || 'far fa-minus-square text-md opacity-75'"></i>
2724
2879
  } @else {
2725
- <i
2726
- [class]="
2727
- customExpandIcon || 'far fa-plus-square text-md opacity-75'
2728
- "
2729
- ></i>
2880
+ <i [class]="customExpandIcon || 'far fa-plus-square text-md opacity-75'"></i>
2730
2881
  }
2731
2882
  }
2732
2883
  </div>
2733
2884
  }
2734
2885
  @if (component && row?.data) {
2735
2886
  <div class="ax-data-table-cell-text min-w-0 flex-1">
2736
- <ng-container
2737
- *ngComponentOutlet="
2738
- component;
2739
- injector: getRowInjector(row.data);
2740
- inputs: getInputs(row.data)
2741
- "
2742
- ></ng-container>
2887
+ <ng-container *ngComponentOutlet="component; injector: getRowInjector(row.data); inputs: getInputs(row.data)"></ng-container>
2743
2888
  </div>
2744
2889
  }
2745
2890
  </div>
2746
2891
  } @else {
2747
- <div
2748
- class="w-full min-w-0 max-w-full"
2749
- [class.flex]="getCellUseFlexLayout()"
2750
- [class.items-center]="getCellUseFlexLayout()"
2751
- [style.justify-content]="getCellJustifyContent()"
2752
- >
2892
+ <div class="w-full min-w-0 max-w-full" [class.flex]="getCellUseFlexLayout()" [class.items-center]="getCellUseFlexLayout()" [style.justify-content]="getCellJustifyContent()">
2753
2893
  @if (component && row?.data) {
2754
- <ng-container
2755
- *ngComponentOutlet="
2756
- component;
2757
- injector: getRowInjector(row.data);
2758
- inputs: getInputs(row.data)
2759
- "
2760
- ></ng-container>
2894
+ <ng-container *ngComponentOutlet="component; injector: getRowInjector(row.data); inputs: getInputs(row.data)"></ng-container>
2761
2895
  }
2762
2896
  </div>
2763
2897
  }
@@ -2775,23 +2909,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
2775
2909
  [class.flex]="!sortEnabled"
2776
2910
  [class.items-center]="!sortEnabled"
2777
2911
  [class.axp-widget-column-header--sortable]="sortEnabled"
2778
- [class.axp-widget-column-header--sort-at-start]="
2779
- sortEnabled && getHeaderTextAlign() === 'end'
2780
- "
2781
- [class.axp-widget-column-header--sort-active]="
2782
- headerSortDirection === 'asc' || headerSortDirection === 'desc'
2783
- "
2912
+ [class.axp-widget-column-header--sort-at-start]="sortEnabled && getHeaderTextAlign() === 'end'"
2913
+ [class.axp-widget-column-header--sort-active]="headerSortDirection === 'asc' || headerSortDirection === 'desc'"
2784
2914
  [class.gap-1]="!sortEnabled"
2785
- [style.justify-content]="
2786
- sortEnabled ? 'flex-start' : getHeaderJustifyContent()
2787
- "
2915
+ [style.justify-content]="sortEnabled ? 'flex-start' : getHeaderJustifyContent()"
2788
2916
  (click)="onHeaderClick($event)"
2789
2917
  >
2790
- <span
2791
- class="axp-widget-column-header__caption truncate"
2792
- [class.axp-widget-column-header__caption--with-sort]="sortEnabled"
2793
- [style.text-align]="sortEnabled ? getHeaderTextAlign() : null"
2794
- >
2918
+ <span class="axp-widget-column-header__caption truncate" [class.axp-widget-column-header__caption--with-sort]="sortEnabled" [style.text-align]="sortEnabled ? getHeaderTextAlign() : null">
2795
2919
  @if (isBand) {
2796
2920
  {{ caption }}
2797
2921
  } @else {
@@ -2801,84 +2925,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
2801
2925
  @if (sortEnabled) {
2802
2926
  <span class="axp-widget-column-header__sort">
2803
2927
  @if (headerSortPriority !== undefined && headerSortPriority > 1) {
2804
- <span
2805
- class="axp-widget-column-header__sort-priority text-xs opacity-70"
2806
- >{{ headerSortPriority }}</span
2807
- >
2928
+ <span class="axp-widget-column-header__sort-priority text-xs opacity-70">{{ headerSortPriority }}</span>
2808
2929
  }
2809
- <i
2810
- class="fa-solid fa-arrow-up-long text-neutral-400"
2811
- [class.text-primary]="headerSortDirection === 'asc'"
2812
- ></i>
2813
- <i
2814
- class="fa-solid fa-arrow-down-long text-neutral-400"
2815
- [class.text-primary]="headerSortDirection === 'desc'"
2816
- ></i>
2930
+ <i class="fa-solid fa-arrow-up-long text-neutral-400" [class.text-primary]="headerSortDirection === 'asc'"></i>
2931
+ <i class="fa-solid fa-arrow-down-long text-neutral-400" [class.text-primary]="headerSortDirection === 'desc'"></i>
2817
2932
  </span>
2818
2933
  }
2819
2934
  </div>
2820
2935
  </ng-template>
2821
2936
  <ng-template #cell let-row>
2822
2937
  @if (expandHandler) {
2823
- <div
2824
- class="ax-data-table-nested-indent w-full"
2825
- [attr.data-level]="row.data?.__meta__?.level || 0"
2826
- >
2938
+ <div class="ax-data-table-nested-indent w-full" [attr.data-level]="row.data?.__meta__?.level || 0">
2827
2939
  @if (hasExpandableRow(row)) {
2828
- <div
2829
- (click)="handleExpandRow(row, $event)"
2830
- class="ax-expand-handler"
2831
- id="ax-expand-handler-container"
2832
- >
2940
+ <div (click)="handleExpandRow(row, $event)" class="ax-expand-handler" id="ax-expand-handler-container">
2833
2941
  @if (loadingRow() === row) {
2834
- <i
2835
- class="fas fa-spinner-third animate-twSpin animate-infinite"
2836
- ></i>
2942
+ <i class="fas fa-spinner-third animate-twSpin animate-infinite"></i>
2837
2943
  } @else {
2838
2944
  @if (row.data?.__meta__?.expanded) {
2839
- <i
2840
- [class]="
2841
- customCollapseIcon ||
2842
- 'far fa-minus-square text-md opacity-75'
2843
- "
2844
- ></i>
2945
+ <i [class]="customCollapseIcon || 'far fa-minus-square text-md opacity-75'"></i>
2845
2946
  } @else {
2846
- <i
2847
- [class]="
2848
- customExpandIcon || 'far fa-plus-square text-md opacity-75'
2849
- "
2850
- ></i>
2947
+ <i [class]="customExpandIcon || 'far fa-plus-square text-md opacity-75'"></i>
2851
2948
  }
2852
2949
  }
2853
2950
  </div>
2854
2951
  }
2855
2952
  @if (component && row?.data) {
2856
2953
  <div class="ax-data-table-cell-text min-w-0 flex-1">
2857
- <ng-container
2858
- *ngComponentOutlet="
2859
- component;
2860
- injector: getRowInjector(row.data);
2861
- inputs: getInputs(row.data)
2862
- "
2863
- ></ng-container>
2954
+ <ng-container *ngComponentOutlet="component; injector: getRowInjector(row.data); inputs: getInputs(row.data)"></ng-container>
2864
2955
  </div>
2865
2956
  }
2866
2957
  </div>
2867
2958
  } @else {
2868
- <div
2869
- class="w-full min-w-0 max-w-full"
2870
- [class.flex]="getCellUseFlexLayout()"
2871
- [class.items-center]="getCellUseFlexLayout()"
2872
- [style.justify-content]="getCellJustifyContent()"
2873
- >
2959
+ <div class="w-full min-w-0 max-w-full" [class.flex]="getCellUseFlexLayout()" [class.items-center]="getCellUseFlexLayout()" [style.justify-content]="getCellJustifyContent()">
2874
2960
  @if (component && row?.data) {
2875
- <ng-container
2876
- *ngComponentOutlet="
2877
- component;
2878
- injector: getRowInjector(row.data);
2879
- inputs: getInputs(row.data)
2880
- "
2881
- ></ng-container>
2961
+ <ng-container *ngComponentOutlet="component; injector: getRowInjector(row.data); inputs: getInputs(row.data)"></ng-container>
2882
2962
  }
2883
2963
  </div>
2884
2964
  }
@@ -3346,7 +3426,8 @@ class AXPWidgetRendererDirective {
3346
3426
  this.onContextChanged = new Subject();
3347
3427
  this.onLoadEvent = new Subject();
3348
3428
  //#region ---- Performance Optimization Properties ----
3349
- this.contextUpdateQueue = new Set();
3429
+ /** Path → whether `onContextChanged` (triggers) should fire. Hydrate writes stay false. */
3430
+ this.contextUpdateQueue = new Map();
3350
3431
  this.contextUpdateTimeout = null;
3351
3432
  this.CONTEXT_UPDATE_DEBOUNCE_MS = 4; // ~250fps for large forms
3352
3433
  // Removed visibility detection - not needed for current implementation
@@ -3358,7 +3439,8 @@ class AXPWidgetRendererDirective {
3358
3439
  // Expression result tracking
3359
3440
  this.lastExpressionResults = new Map();
3360
3441
  // Buffer for context changes that happen before initial render completes
3361
- this.preRenderContextQueue = new Set();
3442
+ /** Path → whether buffered pre-render changes should fire triggers. `*` marks a full context init. */
3443
+ this.preRenderContextQueue = new Map();
3362
3444
  /**
3363
3445
  * Last context {@link AXPContextChangeEvent} handled by this renderer.
3364
3446
  * Prevents re-queueing when the effect re-runs while `lastChange` in the store is unchanged
@@ -3373,11 +3455,11 @@ class AXPWidgetRendererDirective {
3373
3455
  if (changed.state === 'initiated' && (!changed.path || changed.path === '')) {
3374
3456
  // Mark that we need to re-evaluate all expressions when initial render completes
3375
3457
  // This handles the case where context is set before/during widget initialization
3376
- this.preRenderContextQueue.add('*'); // Use '*' as a marker for full context initialization
3458
+ this.rememberQueuedPath(this.preRenderContextQueue, '*', true);
3377
3459
  // console.log(`📝 [${this.node().type}] Buffered initial context set`);
3378
3460
  }
3379
3461
  else if (changed.path) {
3380
- this.preRenderContextQueue.add(changed.path);
3462
+ this.rememberQueuedPath(this.preRenderContextQueue, changed.path, changed.origin !== 'hydrate');
3381
3463
  // console.log(`📝 [${this.node().type}] Buffered pre-render context change: ${changed.path}`);
3382
3464
  }
3383
3465
  return;
@@ -3397,7 +3479,7 @@ class AXPWidgetRendererDirective {
3397
3479
  else if (changed.path && this.isRelevantContextChange(changed.path)) {
3398
3480
  const changedPath = changed.path;
3399
3481
  if (this.markContextChangeHandled(changed)) {
3400
- this.queueContextUpdate(changedPath);
3482
+ this.queueContextUpdate(changedPath, changed.origin !== 'hydrate');
3401
3483
  }
3402
3484
  }
3403
3485
  await this.updateVisibility();
@@ -3455,10 +3537,13 @@ class AXPWidgetRendererDirective {
3455
3537
  this.lastProcessedContextChangeRef = changed;
3456
3538
  return true;
3457
3539
  }
3458
- queueContextUpdate(path) {
3540
+ rememberQueuedPath(queue, path, notifyTriggers) {
3541
+ queue.set(path, (queue.get(path) ?? false) || notifyTriggers);
3542
+ }
3543
+ queueContextUpdate(path, notifyTriggers = true) {
3459
3544
  if (path) {
3460
3545
  // console.log(`🔄 [${this.node().type}] Queueing context update for path: ${path}`);
3461
- this.contextUpdateQueue.add(path);
3546
+ this.rememberQueuedPath(this.contextUpdateQueue, path, notifyTriggers);
3462
3547
  // Clear existing timeout
3463
3548
  if (this.contextUpdateTimeout) {
3464
3549
  clearTimeout(this.contextUpdateTimeout);
@@ -3474,8 +3559,10 @@ class AXPWidgetRendererDirective {
3474
3559
  if (this.contextUpdateQueue.size === 0)
3475
3560
  return;
3476
3561
  const startTime = performance.now();
3477
- const paths = Array.from(this.contextUpdateQueue);
3562
+ const queued = Array.from(this.contextUpdateQueue.entries());
3478
3563
  this.contextUpdateQueue.clear();
3564
+ const paths = queued.map(([path]) => path);
3565
+ const triggerPaths = queued.filter(([, notifyTriggers]) => notifyTriggers).map(([path]) => path);
3479
3566
  // console.log(`📊 [${this.node().type}] Processing ${paths.length} paths:`, paths);
3480
3567
  // Clear expression cache only if changed paths affect this widget's expressions
3481
3568
  const shouldClearCache = paths.some((path) => this.isPathAffectingExpressions(path));
@@ -3499,8 +3586,7 @@ class AXPWidgetRendererDirective {
3499
3586
  await this.updateVisibility();
3500
3587
  }
3501
3588
  const visibilityTime = performance.now() - visibilityStartTime;
3502
- // Emit context changes
3503
- paths.forEach((path) => {
3589
+ triggerPaths.forEach((path) => {
3504
3590
  this.onContextChanged.next({ path });
3505
3591
  });
3506
3592
  const totalTime = performance.now() - startTime;
@@ -3895,6 +3981,12 @@ class AXPWidgetRendererDirective {
3895
3981
  // Evaluate default value (skip when path already has a real value, e.g. edit forms).
3896
3982
  // Still evaluate when the path holds the unevaluated expression string itself.
3897
3983
  let defaultValue = this.node().defaultValue;
3984
+ if (defaultValue === undefined || defaultValue === null || defaultValue === '') {
3985
+ const fromOptions = this.node().options?.defaultValue;
3986
+ if (fromOptions !== undefined && fromOptions !== null && fromOptions !== '') {
3987
+ defaultValue = fromOptions;
3988
+ }
3989
+ }
3898
3990
  const defaultValuePath = this.node().path;
3899
3991
  if (typeof defaultValue === 'string' && this.expressionEvaluator.isExpression(defaultValue)) {
3900
3992
  const existing = defaultValuePath ? this.contextService.getValue(defaultValuePath) : undefined;
@@ -3980,7 +4072,9 @@ class AXPWidgetRendererDirective {
3980
4072
  // console.log(
3981
4073
  // `🚀 [${this.node().type}] Processing ${this.preRenderContextQueue.size} buffered pre-render changes`,
3982
4074
  // );
3983
- this.preRenderContextQueue.forEach((p) => this.contextUpdateQueue.add(p));
4075
+ this.preRenderContextQueue.forEach((notifyTriggers, path) => {
4076
+ this.rememberQueuedPath(this.contextUpdateQueue, path, notifyTriggers);
4077
+ });
3984
4078
  this.preRenderContextQueue.clear();
3985
4079
  await this.processBatchedUpdates();
3986
4080
  }
@@ -5112,6 +5206,13 @@ const AXP_ALLOW_SEARCH_PROPERTY = createBooleanProperty({
5112
5206
  group: AXP_BEHAVIOR_PROPERTY_GROUP,
5113
5207
  defaultValue: false,
5114
5208
  });
5209
+ const AXP_PREFETCH_PROPERTY = createBooleanProperty({
5210
+ name: 'prefetch',
5211
+ title: 'Prefetch',
5212
+ path: 'options.prefetch',
5213
+ group: AXP_BEHAVIOR_PROPERTY_GROUP,
5214
+ defaultValue: false,
5215
+ });
5115
5216
  const AXP_HAS_COPY_ICON_PROPERTY = createBooleanProperty({
5116
5217
  name: 'hasCopyIcon',
5117
5218
  title: 'Copy Icon',
@@ -6005,5 +6106,5 @@ const AXP_CALLBACK_VALIDATION_PROPERTY = {
6005
6106
  * Generated bundle index. Do not edit.
6006
6107
  */
6007
6108
 
6008
- export { AXPBaseWidgetComponent, AXPBlockBaseLayoutWidgetComponent, AXPBoxModelLayoutWidgetComponent, AXPColumnTruncatedTextComponent, AXPColumnWidgetComponent, AXPDataListWidgetComponent, AXPFlexBaseLayoutWidgetComponent, AXPFlexItemBaseLayoutWidgetComponent, AXPGridBaseLayoutWidgetComponent, AXPGridItemBaseLayoutWidgetComponent, AXPInlineBaseLayoutWidgetComponent, AXPLayoutBaseWidgetComponent, AXPPropertyEditorHelper, AXPTableBaseLayoutWidgetComponent, AXPTableItemBaseLayoutWidgetComponent, AXPTableItemOpsBaseLayoutWidgetComponent, AXPValueWidgetComponent, AXPWidgetColumnCellComponent, AXPWidgetColumnRendererComponent, AXPWidgetContainerComponent, AXPWidgetCoreElement, AXPWidgetCoreModule, AXPWidgetCoreService, AXPWidgetRegistryService, AXPWidgetRendererDirective, AXPWidgetSerializationHelper, AXP_ALLOW_CLEAR_PROPERTY, AXP_ALLOW_MULTIPLE_PROPERTY, AXP_ALLOW_SEARCH_PROPERTY, AXP_ANIMATION_PROPERTY_GROUP, AXP_APPEARANCE_PROPERTY_GROUP, AXP_BEHAVIOR_PROPERTY_GROUP, AXP_BETWEEN_VALIDATION_PROPERTY, AXP_BG_COLOR_PROPERTY, AXP_BOX_MODEL_PROPERTY_GROUP, AXP_CALLBACK_VALIDATION_PROPERTY, AXP_COLOR_PROPERTY, AXP_CONTENT_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DATA_PROPERTY_GROUP, AXP_DATA_SOURCE_OPTIONS_PROPERTY, AXP_DATE_DEPTH_PROPERTY, AXP_DATE_FORMAT_PROPERTY, AXP_DATE_RANGE_LIMIT_PROPERTY, AXP_DEFAULT_ROW_COUNT_PROPERTY, AXP_DESCRIPTION_PROPERTY, AXP_DIRECTION_PROPERTY, AXP_DISABLED_PROPERTY, AXP_DOWNLOADABLE_PROPERTY, AXP_EMPTY_SPACING_BOX, AXP_EQUAL_VALIDATION_PROPERTY, AXP_FALSY_TEXT_PROPERTY, AXP_FIT_LINE_COUNT_PROPERTY, AXP_FONT_SIZE_PROPERTY, AXP_GREATER_THAN_VALIDATION_PROPERTY, AXP_HAS_CLEAR_BUTTON_PROPERTY, AXP_HAS_COPY_ICON_PROPERTY, AXP_HAS_EYE_ICON_PROPERTY, AXP_HAS_ICON_PROPERTY, AXP_HAS_LABEL_PROPERTY, AXP_ICON_PROPERTY, AXP_IS_LOADING_PROPERTY, AXP_LABEL_PROPERTY, AXP_LAYOUT_ADVANCED_GRID_PROPERTY, AXP_LAYOUT_BORDER_PROPERTY, AXP_LAYOUT_COLUMNS_PROPERTY, AXP_LAYOUT_DIRECTION_PROPERTY, AXP_LAYOUT_FLEX_ITEM_PROPERTY, AXP_LAYOUT_FLEX_PROPERTY, AXP_LAYOUT_FLEX_PROPERTY_GROUP, AXP_LAYOUT_GAP_PROPERTY, AXP_LAYOUT_GRID_ITEM_PROPERTY, AXP_LAYOUT_GRID_PROPERTIES, AXP_LAYOUT_GRID_PROPERTY, AXP_LAYOUT_GRID_PROPERTY_GROUP, AXP_LAYOUT_GRID_ROW_PROPERTIES, AXP_LAYOUT_PROFILE, AXP_LAYOUT_ROWS_PROPERTY, AXP_LAYOUT_SHOW_HEADER_PROPERTY, AXP_LAYOUT_SPACING_PROPERTY, AXP_LAYOUT_TABLE_PROPERTY_GROUP, AXP_LESS_THAN_VALIDATION_PROPERTY, AXP_LOCAL_DATA_SOURCES_OPTION, AXP_LOCAL_DATA_SOURCE_PREFIX, AXP_LOCAL_DATA_SOURCE_STORE, AXP_MAX_LENGTH_VALIDATION_PROPERTY, AXP_MAX_LINE_COUNT_PROPERTY, AXP_MIN_LENGTH_VALIDATION_PROPERTY, AXP_MIN_LINE_COUNT_PROPERTY, AXP_MULTI_LANGUAGE_PROPERTY, AXP_NAME_PROPERTY, AXP_NUMBER_SEPARATOR_PROPERTY, AXP_PLACEHOLDER_PROPERTY, AXP_QUERY_OPTIONS_PROPERTY, AXP_READONLY_PROPERTY, AXP_REGULAR_EXPRESSION_VALIDATION_PROPERTY, AXP_REQUIRED_VALIDATION_PROPERTY, AXP_SHOW_PASSWORD_PROPERTY, AXP_SPIN_BUTTON_PROPERTY, AXP_STYLE_COLOR_PROPERTY, AXP_STYLE_LOOK_PROPERTY, AXP_STYLING_PROPERTY_GROUP, AXP_TABLE_COLUMNS_PROPERTY, AXP_TABLE_COLUMN_ALIGNMENT_PROPERTIES, AXP_TABLE_COLUMN_CELL_ALIGN_PROPERTY, AXP_TABLE_COLUMN_HEADER_ALIGN_PROPERTY, AXP_TABLE_COLUMN_HEIGHT_PROPERTY, AXP_TABLE_COLUMN_WIDTH_PROPERTY, AXP_TABLE_ITEM_COLSPAN_PROPERTY, AXP_TABLE_ITEM_ROWSPAN_PROPERTY, AXP_TEXT_ALIGN_PROPERTY, AXP_TEXT_FIELD_PROPERTY, AXP_TEXT_PROPERTY, AXP_THEME_PROPERTY, AXP_TITLE_PROPERTY, AXP_TRIGGERS_PROPERTY, AXP_TRIGGERS_PROPERTY_GROUP, AXP_TRULY_TEXT_PROPERTY, AXP_VALIDATION_PROPERTY_GROUP, AXP_VALUE_FIELD_PROPERTY, AXP_VERTICAL_ALIGN_PROPERTY, AXP_WIDGET_DEFINITION_PROVIDER, AXP_WIDGET_PROPERTY_GROUP, LOCAL_DATA_SOURCE_SHEET_BUFFER_ROWS, LOCAL_DATA_SOURCE_SHEET_MIN_ROWS, WIDGET_CASCADE_TRACE_NS, booleanDefaultProperty, buildLocalDataSourceListRows, buildQuerySelectorNode, buildQueryTabsNode, buildWidgetRegistryMapFromProviders, coerceGridProfile, coerceSpacingProfile, createDefaultLocalDataSourceColumns, createQueryOptionsProperty, createReadonlyLocalDataSourceStore, createWritableLocalDataSourceStore, ensureLocalDataSourceRowValues, findNonEmptyBreakpoints, isFlatSpacingBox, isLocalDataSourceRef, isLocalDataSourceRowEmpty, largeTextDefaultProperty, layoutSizeFromDevice, mapAXPPropertyToWidgetProperty, numberDefaultProperty, numberMaxValueProperty, numberMinValueProperty, padLocalDataSourceSheetRows, parseLocalDataSourceId, plainTextDefaultProperty, readLocalDataSourcesFromNode, resolveWidgetModeComponent, richTextDefaultProperty, selectEditorDefaultValueProperty, selectionListEditorDefaultValueProperty, spacingBoxOrEmpty, toLocalDataSourceRef, toLocalDataSourceSheet };
6109
+ export { AXPBaseWidgetComponent, AXPBlockBaseLayoutWidgetComponent, AXPBoxModelLayoutWidgetComponent, AXPColumnTruncatedTextComponent, AXPColumnWidgetComponent, AXPDataListWidgetComponent, AXPFlexBaseLayoutWidgetComponent, AXPFlexItemBaseLayoutWidgetComponent, AXPGridBaseLayoutWidgetComponent, AXPGridItemBaseLayoutWidgetComponent, AXPInlineBaseLayoutWidgetComponent, AXPLayoutBaseWidgetComponent, AXPPropertyEditorHelper, AXPTableBaseLayoutWidgetComponent, AXPTableItemBaseLayoutWidgetComponent, AXPTableItemOpsBaseLayoutWidgetComponent, AXPValueWidgetComponent, AXPWidgetColumnCellComponent, AXPWidgetColumnRendererComponent, AXPWidgetContainerComponent, AXPWidgetCoreElement, AXPWidgetCoreModule, AXPWidgetCoreService, AXPWidgetRegistryService, AXPWidgetRendererDirective, AXPWidgetSerializationHelper, AXP_ALLOW_CLEAR_PROPERTY, AXP_ALLOW_MULTIPLE_PROPERTY, AXP_ALLOW_SEARCH_PROPERTY, AXP_ANIMATION_PROPERTY_GROUP, AXP_APPEARANCE_PROPERTY_GROUP, AXP_BEHAVIOR_PROPERTY_GROUP, AXP_BETWEEN_VALIDATION_PROPERTY, AXP_BG_COLOR_PROPERTY, AXP_BOX_MODEL_PROPERTY_GROUP, AXP_CALLBACK_VALIDATION_PROPERTY, AXP_COLOR_PROPERTY, AXP_CONTENT_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DATA_PROPERTY_GROUP, AXP_DATA_SOURCE_OPTIONS_PROPERTY, AXP_DATE_DEPTH_PROPERTY, AXP_DATE_FORMAT_PROPERTY, AXP_DATE_RANGE_LIMIT_PROPERTY, AXP_DEFAULT_ROW_COUNT_PROPERTY, AXP_DESCRIPTION_PROPERTY, AXP_DIRECTION_PROPERTY, AXP_DISABLED_PROPERTY, AXP_DOWNLOADABLE_PROPERTY, AXP_EMPTY_SPACING_BOX, AXP_EQUAL_VALIDATION_PROPERTY, AXP_FALSY_TEXT_PROPERTY, AXP_FIT_LINE_COUNT_PROPERTY, AXP_FONT_SIZE_PROPERTY, AXP_GREATER_THAN_VALIDATION_PROPERTY, AXP_HAS_CLEAR_BUTTON_PROPERTY, AXP_HAS_COPY_ICON_PROPERTY, AXP_HAS_EYE_ICON_PROPERTY, AXP_HAS_ICON_PROPERTY, AXP_HAS_LABEL_PROPERTY, AXP_ICON_PROPERTY, AXP_IS_LOADING_PROPERTY, AXP_LABEL_PROPERTY, AXP_LAYOUT_ADVANCED_GRID_PROPERTY, AXP_LAYOUT_BORDER_PROPERTY, AXP_LAYOUT_COLUMNS_PROPERTY, AXP_LAYOUT_DIRECTION_PROPERTY, AXP_LAYOUT_FLEX_ITEM_PROPERTY, AXP_LAYOUT_FLEX_PROPERTY, AXP_LAYOUT_FLEX_PROPERTY_GROUP, AXP_LAYOUT_GAP_PROPERTY, AXP_LAYOUT_GRID_ITEM_PROPERTY, AXP_LAYOUT_GRID_PROPERTIES, AXP_LAYOUT_GRID_PROPERTY, AXP_LAYOUT_GRID_PROPERTY_GROUP, AXP_LAYOUT_GRID_ROW_PROPERTIES, AXP_LAYOUT_PROFILE, AXP_LAYOUT_ROWS_PROPERTY, AXP_LAYOUT_SHOW_HEADER_PROPERTY, AXP_LAYOUT_SPACING_PROPERTY, AXP_LAYOUT_TABLE_PROPERTY_GROUP, AXP_LESS_THAN_VALIDATION_PROPERTY, AXP_LOCAL_DATA_SOURCES_OPTION, AXP_LOCAL_DATA_SOURCE_PREFIX, AXP_LOCAL_DATA_SOURCE_STORE, AXP_MAX_LENGTH_VALIDATION_PROPERTY, AXP_MAX_LINE_COUNT_PROPERTY, AXP_MIN_LENGTH_VALIDATION_PROPERTY, AXP_MIN_LINE_COUNT_PROPERTY, AXP_MULTI_LANGUAGE_PROPERTY, AXP_NAME_PROPERTY, AXP_NUMBER_SEPARATOR_PROPERTY, AXP_PLACEHOLDER_PROPERTY, AXP_PREFETCH_PROPERTY, AXP_QUERY_OPTIONS_PROPERTY, AXP_READONLY_PROPERTY, AXP_REGULAR_EXPRESSION_VALIDATION_PROPERTY, AXP_REQUIRED_VALIDATION_PROPERTY, AXP_SHOW_PASSWORD_PROPERTY, AXP_SPIN_BUTTON_PROPERTY, AXP_STYLE_COLOR_PROPERTY, AXP_STYLE_LOOK_PROPERTY, AXP_STYLING_PROPERTY_GROUP, AXP_TABLE_COLUMNS_PROPERTY, AXP_TABLE_COLUMN_ALIGNMENT_PROPERTIES, AXP_TABLE_COLUMN_CELL_ALIGN_PROPERTY, AXP_TABLE_COLUMN_HEADER_ALIGN_PROPERTY, AXP_TABLE_COLUMN_HEIGHT_PROPERTY, AXP_TABLE_COLUMN_WIDTH_PROPERTY, AXP_TABLE_ITEM_COLSPAN_PROPERTY, AXP_TABLE_ITEM_ROWSPAN_PROPERTY, AXP_TEXT_ALIGN_PROPERTY, AXP_TEXT_FIELD_PROPERTY, AXP_TEXT_PROPERTY, AXP_THEME_PROPERTY, AXP_TITLE_PROPERTY, AXP_TRIGGERS_PROPERTY, AXP_TRIGGERS_PROPERTY_GROUP, AXP_TRULY_TEXT_PROPERTY, AXP_VALIDATION_PROPERTY_GROUP, AXP_VALUE_FIELD_PROPERTY, AXP_VERTICAL_ALIGN_PROPERTY, AXP_WIDGET_DEFINITION_PROVIDER, AXP_WIDGET_PROPERTY_GROUP, LOCAL_DATA_SOURCE_SHEET_BUFFER_ROWS, LOCAL_DATA_SOURCE_SHEET_MIN_ROWS, WIDGET_CASCADE_TRACE_NS, assumedValidationDisabled, booleanDefaultProperty, buildLocalDataSourceListRows, buildQuerySelectorNode, buildQueryTabsNode, buildWidgetRegistryMapFromProviders, coerceGridProfile, coerceSpacingProfile, collectAuthoredValidationRules, createDefaultLocalDataSourceColumns, createQueryOptionsProperty, createReadonlyLocalDataSourceStore, createWritableLocalDataSourceStore, ensureLocalDataSourceRowValues, findNonEmptyBreakpoints, isFlatSpacingBox, isLocalDataSourceRef, isLocalDataSourceRowEmpty, isRequiredRuleActive, largeTextDefaultProperty, layoutSizeFromDevice, mapAXPPropertyToWidgetProperty, numberDefaultProperty, numberMaxValueProperty, numberMinValueProperty, padLocalDataSourceSheetRows, parseLocalDataSourceId, plainTextDefaultProperty, readLocalDataSourcesFromNode, resolveValidationContextPath, resolveValidationDisabledFlags, resolveWidgetExposeHydrateWrites, resolveWidgetModeComponent, richTextDefaultProperty, selectEditorDefaultValueProperty, selectionListEditorDefaultValueProperty, spacingBoxOrEmpty, syncRequiredIndicator, toLocalDataSourceRef, toLocalDataSourceSheet, validationExpressionScope };
6009
6110
  //# sourceMappingURL=acorex-platform-framework-client-layout-widget-core.mjs.map