@acorex/platform 20.3.0-next.1 → 20.3.0-next.11

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 (119) hide show
  1. package/common/index.d.ts +125 -12
  2. package/core/index.d.ts +656 -100
  3. package/fesm2022/acorex-platform-auth.mjs +20 -20
  4. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  5. package/fesm2022/acorex-platform-common.mjs +120 -148
  6. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-core.mjs +885 -261
  8. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-domain.mjs +16 -16
  10. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-layout-builder.mjs +1615 -662
  12. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  13. package/fesm2022/acorex-platform-layout-components.mjs +3327 -157
  14. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  15. package/fesm2022/acorex-platform-layout-designer.mjs +172 -210
  16. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  17. package/fesm2022/acorex-platform-layout-entity-create-entity.command-764ie8R8.mjs +52 -0
  18. package/fesm2022/acorex-platform-layout-entity-create-entity.command-764ie8R8.mjs.map +1 -0
  19. package/fesm2022/acorex-platform-layout-entity.mjs +4522 -1643
  20. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-layout-views.mjs +398 -89
  22. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  23. package/fesm2022/acorex-platform-native.mjs +7 -7
  24. package/fesm2022/acorex-platform-native.mjs.map +1 -1
  25. package/fesm2022/acorex-platform-runtime.mjs +40 -40
  26. package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
  27. package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-hHXxHlFG.mjs → acorex-platform-themes-default-entity-master-create-view.component-Ct-ri59W.mjs} +7 -7
  28. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Ct-ri59W.mjs.map +1 -0
  29. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-7BB4LdjK.mjs +706 -0
  30. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-7BB4LdjK.mjs.map +1 -0
  31. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BDJR088o.mjs +101 -0
  32. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BDJR088o.mjs.map +1 -0
  33. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-BExtm1JE.mjs +244 -0
  34. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-BExtm1JE.mjs.map +1 -0
  35. package/fesm2022/{acorex-platform-themes-default-error-401.component-D4glpFvU.mjs → acorex-platform-themes-default-error-401.component-DrO1PEOH.mjs} +4 -4
  36. package/fesm2022/{acorex-platform-themes-default-error-401.component-D4glpFvU.mjs.map → acorex-platform-themes-default-error-401.component-DrO1PEOH.mjs.map} +1 -1
  37. package/fesm2022/{acorex-platform-themes-default-error-404.component-BvGeDMjo.mjs → acorex-platform-themes-default-error-404.component-DqVq0oHX.mjs} +4 -4
  38. package/fesm2022/{acorex-platform-themes-default-error-404.component-BvGeDMjo.mjs.map → acorex-platform-themes-default-error-404.component-DqVq0oHX.mjs.map} +1 -1
  39. package/fesm2022/{acorex-platform-themes-default-error-offline.component-BINy-Zo3.mjs → acorex-platform-themes-default-error-offline.component-Bt2PTL7_.mjs} +4 -4
  40. package/fesm2022/{acorex-platform-themes-default-error-offline.component-BINy-Zo3.mjs.map → acorex-platform-themes-default-error-offline.component-Bt2PTL7_.mjs.map} +1 -1
  41. package/fesm2022/acorex-platform-themes-default.mjs +64 -509
  42. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  43. package/fesm2022/{acorex-platform-themes-shared-icon-chooser-view.component-C833prGO.mjs → acorex-platform-themes-shared-icon-chooser-view.component-BgEh06Tn.mjs} +24 -14
  44. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BgEh06Tn.mjs.map +1 -0
  45. package/fesm2022/{acorex-platform-themes-shared-settings.provider-CXiRmniv.mjs → acorex-platform-themes-shared-settings.provider-CLUKU4y0.mjs} +2 -2
  46. package/fesm2022/acorex-platform-themes-shared-settings.provider-CLUKU4y0.mjs.map +1 -0
  47. package/fesm2022/{acorex-platform-themes-shared-color-chooser-column.component-DjKLg513.mjs → acorex-platform-themes-shared-theme-color-chooser-column.component-AeOQxjbS.mjs} +23 -8
  48. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-AeOQxjbS.mjs.map +1 -0
  49. package/fesm2022/{acorex-platform-themes-shared-color-chooser-view.component-DE0wO98F.mjs → acorex-platform-themes-shared-theme-color-chooser-view.component-DEVzRd6-.mjs} +23 -8
  50. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-DEVzRd6-.mjs.map +1 -0
  51. package/fesm2022/acorex-platform-themes-shared.mjs +250 -85
  52. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  53. package/fesm2022/{acorex-platform-widgets-button-widget-designer.component-lNF95FJv.mjs → acorex-platform-widgets-button-widget-designer.component-DSaD9Fwc.mjs} +7 -7
  54. package/fesm2022/acorex-platform-widgets-button-widget-designer.component-DSaD9Fwc.mjs.map +1 -0
  55. package/fesm2022/acorex-platform-widgets-extra-properties-schema-widget-edit.component-D9mf08rU.mjs +50 -0
  56. package/fesm2022/acorex-platform-widgets-extra-properties-schema-widget-edit.component-D9mf08rU.mjs.map +1 -0
  57. package/fesm2022/acorex-platform-widgets-extra-properties-schema-widget-view.component-D6GQ-eyr.mjs +42 -0
  58. package/fesm2022/acorex-platform-widgets-extra-properties-schema-widget-view.component-D6GQ-eyr.mjs.map +1 -0
  59. package/fesm2022/acorex-platform-widgets-extra-properties-values-widget-edit.component-DVbIdVZ6.mjs +55 -0
  60. package/fesm2022/acorex-platform-widgets-extra-properties-values-widget-edit.component-DVbIdVZ6.mjs.map +1 -0
  61. package/fesm2022/acorex-platform-widgets-extra-properties-values-widget-view.component-D-aM64Hu.mjs +50 -0
  62. package/fesm2022/acorex-platform-widgets-extra-properties-values-widget-view.component-D-aM64Hu.mjs.map +1 -0
  63. package/fesm2022/acorex-platform-widgets-extra-properties-widget-edit.component-em2-aU8E.mjs +48 -0
  64. package/fesm2022/acorex-platform-widgets-extra-properties-widget-edit.component-em2-aU8E.mjs.map +1 -0
  65. package/fesm2022/acorex-platform-widgets-extra-properties-widget-view.component-BeuIofdr.mjs +42 -0
  66. package/fesm2022/acorex-platform-widgets-extra-properties-widget-view.component-BeuIofdr.mjs.map +1 -0
  67. package/fesm2022/{acorex-platform-widgets-file-list-popup.component-DFbPO0ud.mjs → acorex-platform-widgets-file-list-popup.component-Cmtq2bBV.mjs} +72 -7
  68. package/fesm2022/acorex-platform-widgets-file-list-popup.component-Cmtq2bBV.mjs.map +1 -0
  69. package/fesm2022/{acorex-platform-widgets-page-widget-designer.component-DRsLkulH.mjs → acorex-platform-widgets-page-widget-designer.component-B-ZEi2yd.mjs} +79 -69
  70. package/fesm2022/acorex-platform-widgets-page-widget-designer.component-B-ZEi2yd.mjs.map +1 -0
  71. package/fesm2022/{acorex-platform-widgets-tabular-data-edit-popup.component-nLZYiPnF.mjs → acorex-platform-widgets-tabular-data-edit-popup.component-CMqq_iOj.mjs} +13 -13
  72. package/fesm2022/acorex-platform-widgets-tabular-data-edit-popup.component-CMqq_iOj.mjs.map +1 -0
  73. package/fesm2022/{acorex-platform-widgets-tabular-data-view-popup.component-D6kiasYM.mjs → acorex-platform-widgets-tabular-data-view-popup.component-CRpjdiNz.mjs} +8 -7
  74. package/fesm2022/acorex-platform-widgets-tabular-data-view-popup.component-CRpjdiNz.mjs.map +1 -0
  75. package/fesm2022/{acorex-platform-widgets-text-block-widget-designer.component-CCMQtH3e.mjs → acorex-platform-widgets-text-block-widget-designer.component-DeSmBqMa.mjs} +9 -14
  76. package/fesm2022/acorex-platform-widgets-text-block-widget-designer.component-DeSmBqMa.mjs.map +1 -0
  77. package/fesm2022/acorex-platform-widgets.mjs +9152 -7181
  78. package/fesm2022/acorex-platform-widgets.mjs.map +1 -1
  79. package/fesm2022/acorex-platform-workflow.mjs +28 -25
  80. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  81. package/layout/builder/index.d.ts +419 -185
  82. package/layout/components/index.d.ts +1129 -24
  83. package/layout/designer/index.d.ts +20 -49
  84. package/layout/entity/index.d.ts +424 -332
  85. package/layout/views/index.d.ts +129 -22
  86. package/package.json +23 -37
  87. package/widgets/index.d.ts +1908 -783
  88. package/workflow/index.d.ts +4 -1
  89. package/fesm2022/acorex-platform-themes-default-create-entity-view.component-SY0oMDoH.mjs +0 -22
  90. package/fesm2022/acorex-platform-themes-default-create-entity-view.component-SY0oMDoH.mjs.map +0 -1
  91. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-hHXxHlFG.mjs.map +0 -1
  92. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-hf4QOz_4.mjs +0 -665
  93. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-hf4QOz_4.mjs.map +0 -1
  94. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-DC3MrDtI.mjs +0 -108
  95. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-DC3MrDtI.mjs.map +0 -1
  96. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-Bb90PeHq.mjs +0 -236
  97. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-Bb90PeHq.mjs.map +0 -1
  98. package/fesm2022/acorex-platform-themes-shared-color-chooser-column.component-DjKLg513.mjs.map +0 -1
  99. package/fesm2022/acorex-platform-themes-shared-color-chooser-view.component-DE0wO98F.mjs.map +0 -1
  100. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-C833prGO.mjs.map +0 -1
  101. package/fesm2022/acorex-platform-themes-shared-settings.provider-CXiRmniv.mjs.map +0 -1
  102. package/fesm2022/acorex-platform-widgets-button-widget-designer.component-lNF95FJv.mjs.map +0 -1
  103. package/fesm2022/acorex-platform-widgets-checkbox-widget-column.component-BNBOATPB.mjs +0 -85
  104. package/fesm2022/acorex-platform-widgets-checkbox-widget-column.component-BNBOATPB.mjs.map +0 -1
  105. package/fesm2022/acorex-platform-widgets-checkbox-widget-designer.component-BI18uzNZ.mjs +0 -55
  106. package/fesm2022/acorex-platform-widgets-checkbox-widget-designer.component-BI18uzNZ.mjs.map +0 -1
  107. package/fesm2022/acorex-platform-widgets-checkbox-widget-view.component-C6-QPsnb.mjs +0 -76
  108. package/fesm2022/acorex-platform-widgets-checkbox-widget-view.component-C6-QPsnb.mjs.map +0 -1
  109. package/fesm2022/acorex-platform-widgets-color-box-widget-designer.component-pYOQv5g8.mjs +0 -55
  110. package/fesm2022/acorex-platform-widgets-color-box-widget-designer.component-pYOQv5g8.mjs.map +0 -1
  111. package/fesm2022/acorex-platform-widgets-file-list-popup.component-DFbPO0ud.mjs.map +0 -1
  112. package/fesm2022/acorex-platform-widgets-file-rename-popup.component-DA_CgIvm.mjs +0 -211
  113. package/fesm2022/acorex-platform-widgets-file-rename-popup.component-DA_CgIvm.mjs.map +0 -1
  114. package/fesm2022/acorex-platform-widgets-page-widget-designer.component-DRsLkulH.mjs.map +0 -1
  115. package/fesm2022/acorex-platform-widgets-rich-text-popup.component-CM_v-cL4.mjs +0 -40
  116. package/fesm2022/acorex-platform-widgets-rich-text-popup.component-CM_v-cL4.mjs.map +0 -1
  117. package/fesm2022/acorex-platform-widgets-tabular-data-edit-popup.component-nLZYiPnF.mjs.map +0 -1
  118. package/fesm2022/acorex-platform-widgets-tabular-data-view-popup.component-D6kiasYM.mjs.map +0 -1
  119. package/fesm2022/acorex-platform-widgets-text-block-widget-designer.component-CCMQtH3e.mjs.map +0 -1
@@ -1,18 +1,19 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, computed, Injectable, InjectionToken, inject, ElementRef, effect, Injector, ChangeDetectorRef, ViewChild, Input, ChangeDetectionStrategy, Component, EventEmitter, Output, input, output, ViewContainerRef, Directive, Optional, Inject, NgModule } from '@angular/core';
3
+ import { convertArrayToDataSource, AXDataSource } from '@acorex/cdk/common';
4
+ import { setSmart, AXPDataSourceDefinitionProviderService, extractValue, getSmart, AXPExpressionEvaluatorService } from '@acorex/platform/core';
5
+ import { set, cloneDeep, isEqual, get, merge, isNil, isUndefined, isObjectLike, sum, isEmpty, isString } from 'lodash-es';
6
+ import { Subject, BehaviorSubject, filter } from 'rxjs';
7
+ import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
1
8
  import * as i1$1 from '@acorex/components/skeleton';
2
9
  import { AXSkeletonModule } from '@acorex/components/skeleton';
10
+ import * as i2 from '@acorex/core/translation';
11
+ import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
3
12
  import { PortalModule } from '@angular/cdk/portal';
4
13
  import * as i1 from '@angular/common';
5
14
  import { CommonModule } from '@angular/common';
6
- import * as i0 from '@angular/core';
7
- import { signal, computed, Injectable, InjectionToken, inject, Injector, ChangeDetectorRef, ViewChild, Input, ChangeDetectionStrategy, Component, EventEmitter, effect, Output, input, output, ViewContainerRef, Directive, Optional, Inject, NgModule, ElementRef } from '@angular/core';
8
15
  import { AXDataTableColumnComponent, AXBaseDataTable } from '@acorex/components/data-table';
9
- import { set, merge, cloneDeep, isNil, isEqual, get, sum, isEmpty, isString, isUndefined, isObjectLike } from 'lodash-es';
10
- import { Subject, filter, BehaviorSubject } from 'rxjs';
11
- import { getSmart, setSmart, AXPExpressionEvaluatorService, AXPDataSourceDefinitionProviderService, extractValue } from '@acorex/platform/core';
12
- import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
13
- import { AXTranslationService } from '@acorex/core/translation';
14
16
  import { AXUnsubscriber } from '@acorex/core/utils';
15
- import { convertArrayToDataSource, AXDataSource } from '@acorex/cdk/common';
16
17
 
17
18
  var AXPPageStatus;
18
19
  (function (AXPPageStatus) {
@@ -54,6 +55,7 @@ class AXPLayoutBuilderService {
54
55
  this.functions$ = signal({}, ...(ngDevMode ? [{ debugName: "functions$" }] : []));
55
56
  this.onRefresh = new Subject();
56
57
  this.widgets = new Map();
58
+ this.onWidgetRegistered = new Subject();
57
59
  this.status$ = signal(AXPPageStatus.Rendering, ...(ngDevMode ? [{ debugName: "status$" }] : []));
58
60
  this.status = this.status$.asReadonly();
59
61
  this.isBusy = computed(() => {
@@ -70,7 +72,7 @@ class AXPLayoutBuilderService {
70
72
  this.status$.update(() => this.detectStatus());
71
73
  }
72
74
  detectStatus() {
73
- const statuses = Array.from(this.widgets.values()).map(c => c.status());
75
+ const statuses = Array.from(this.widgets.values()).map((c) => c.status());
74
76
  // Rendering statuses
75
77
  if (statuses.some((status) => status === AXPWidgetStatus.Rendering)) {
76
78
  return AXPPageStatus.Rendering;
@@ -116,55 +118,164 @@ class AXPLayoutBuilderService {
116
118
  }
117
119
  registerWidget(id, widget) {
118
120
  this.widgets.set(id, widget);
121
+ this.onWidgetRegistered.next({ id, widget });
119
122
  }
120
123
  getWidget(id) {
121
124
  return this.widgets.get(id);
122
125
  }
123
- ngOnDestroy() {
126
+ /**
127
+ * Waits until a widget with the given id is registered, then resolves with it.
128
+ * If the widget is already registered, resolves immediately.
129
+ * Optionally accepts a timeout (in ms) after which it resolves with undefined.
130
+ */
131
+ async waitForWidget(id, timeoutMs) {
132
+ const existing = this.widgets.get(id);
133
+ if (existing) {
134
+ return existing;
135
+ }
136
+ return new Promise((resolve) => {
137
+ let resolved = false;
138
+ let timer = null;
139
+ const sub = this.onWidgetRegistered.subscribe(({ id: registeredId, widget }) => {
140
+ if (registeredId === id && !resolved) {
141
+ resolved = true;
142
+ sub.unsubscribe();
143
+ if (timer) {
144
+ clearTimeout(timer);
145
+ }
146
+ resolve(widget);
147
+ }
148
+ });
149
+ if (timeoutMs != null && timeoutMs > 0) {
150
+ timer = setTimeout(() => {
151
+ if (!resolved) {
152
+ resolved = true;
153
+ sub.unsubscribe();
154
+ resolve(undefined);
155
+ }
156
+ }, timeoutMs);
157
+ }
158
+ });
124
159
  }
125
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutBuilderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
126
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutBuilderService }); }
160
+ ngOnDestroy() { }
161
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
162
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderService }); }
127
163
  }
128
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutBuilderService, decorators: [{
164
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderService, decorators: [{
129
165
  type: Injectable
130
166
  }] });
131
167
 
132
- class AXPWidgetRegistryService {
133
- /**
134
- *
135
- */
136
- constructor() {
137
- this.types = new Map();
138
- AXPWidgetRegistryService.instance = this;
139
- }
140
- register(widget) {
141
- this.types.set(widget.name, widget);
142
- }
143
- extend(parentName, widget) {
144
- const parentWidget = this.resolve(parentName);
145
- const newWidget = merge({}, parentWidget, widget);
146
- newWidget.name = widget.name;
147
- this.register(newWidget);
148
- }
149
- resolve(name) {
150
- const widget = this.types.get(name);
151
- if (!widget) {
152
- throw new Error(`Widget with name "${name}" does not exist.`);
153
- }
154
- return widget;
155
- }
156
- all() {
157
- return Array.from(this.types.values());
158
- }
159
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
160
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetRegistryService, providedIn: 'root' }); }
168
+ class AXPLayoutContextChangeEvent {
161
169
  }
162
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetRegistryService, decorators: [{
163
- type: Injectable,
164
- args: [{
165
- providedIn: 'root',
166
- }]
167
- }], ctorParameters: () => [] });
170
+ const AXPLayoutBuilderContextStore = signalStore(
171
+ // Initial State
172
+ withState(() => ({
173
+ data: {}, // Shared context data
174
+ state: 'initiated', // Current state
175
+ initialSnapshot: {}, // Snapshot of the first initialized state
176
+ previousSnapshot: {}, // Snapshot of the previous state
177
+ lastChange: {
178
+ state: 'initiated',
179
+ }, // Last change event
180
+ })),
181
+ // Computed Signals
182
+ withComputed(({ data, state, lastChange, initialSnapshot, previousSnapshot }) => ({
183
+ isChanged: computed(() => state() === 'changed'),
184
+ isReset: computed(() => state() === 'restored'),
185
+ isInitiated: computed(() => state() === 'initiated'),
186
+ isEmpty: computed(() => Object.keys(data()).length === 0),
187
+ isDirty: computed(() => !isEqual(data(), previousSnapshot())),
188
+ snapshot: computed(() => cloneDeep(data())), // Current data snapshot
189
+ initial: computed(() => cloneDeep(initialSnapshot())), // Initial snapshot
190
+ previous: computed(() => cloneDeep(previousSnapshot())), // Previous snapshot
191
+ changeEvent: computed(() => lastChange()), // Reactive last change event
192
+ })),
193
+ // Methods for State Management
194
+ withMethods((store) => ({
195
+ // Update a specific value
196
+ update(path, value) {
197
+ const currentData = cloneDeep(store.data());
198
+ const oldValue = get(currentData, path);
199
+ // Skip if the value hasn't changed
200
+ if (isEqual(oldValue, value)) {
201
+ return;
202
+ }
203
+ // Update the value and prepare the change event
204
+ const updatedData = setSmart(currentData, path, value);
205
+ const changeEvent = {
206
+ oldValue,
207
+ newValue: value,
208
+ path,
209
+ state: 'changed',
210
+ data: updatedData,
211
+ };
212
+ // Patch the state
213
+ patchState(store, {
214
+ previousSnapshot: store.snapshot(), // Save the previous state
215
+ data: updatedData,
216
+ state: 'changed',
217
+ lastChange: changeEvent,
218
+ });
219
+ },
220
+ patch(context) {
221
+ const currentData = cloneDeep(store.data());
222
+ // Update the value and prepare the change event
223
+ const updatedData = { ...currentData, ...context };
224
+ const changeEvent = {
225
+ state: 'patch',
226
+ data: updatedData,
227
+ };
228
+ // Patch the state
229
+ patchState(store, {
230
+ previousSnapshot: store.snapshot(), // Save the previous state
231
+ data: updatedData,
232
+ state: 'changed',
233
+ lastChange: changeEvent,
234
+ });
235
+ },
236
+ // Reset to the initial state
237
+ reset() {
238
+ const initialData = store.initial();
239
+ const changeEvent = {
240
+ oldValue: cloneDeep(store.data()), // Current data becomes old value
241
+ newValue: cloneDeep(initialData), // Reset to the initial state
242
+ path: '',
243
+ state: 'restored',
244
+ data: initialData,
245
+ };
246
+ patchState(store, {
247
+ previousSnapshot: store.snapshot(), // Save the previous state
248
+ data: initialData,
249
+ state: 'restored',
250
+ lastChange: changeEvent,
251
+ });
252
+ },
253
+ // Initialize the state
254
+ set(initialData) {
255
+ const currentData = store.data();
256
+ if (isEqual(currentData, initialData)) {
257
+ return; // Skip if the current state matches the initial state
258
+ }
259
+ const changeEvent = {
260
+ oldValue: null,
261
+ newValue: cloneDeep(initialData),
262
+ path: '',
263
+ state: 'initiated',
264
+ data: initialData,
265
+ };
266
+ patchState(store, {
267
+ initialSnapshot: cloneDeep(initialData), // Save the initial state
268
+ previousSnapshot: store.snapshot(), // Save the current state as the previous
269
+ data: initialData,
270
+ state: 'initiated',
271
+ lastChange: changeEvent,
272
+ });
273
+ },
274
+ // Get a specific value
275
+ getValue(path) {
276
+ return get(store.data(), path);
277
+ },
278
+ })));
168
279
 
169
280
  const AXPWidgetsCatalog = {
170
281
  timeDuration: 'time-duration',
@@ -173,13 +284,10 @@ const AXPWidgetsCatalog = {
173
284
  color: 'color-editor',
174
285
  contact: 'contact-editor',
175
286
  dateTime: 'date-time-editor',
176
- email: 'email-editor',
177
287
  largeText: 'large-text-editor',
178
- link: 'link-editor',
179
288
  number: 'number-editor',
180
289
  numberUnit: 'number-unit-editor',
181
290
  password: 'password-editor',
182
- phone: 'phone-editor',
183
291
  richText: 'rich-text-editor',
184
292
  select: 'select-editor',
185
293
  selectionList: 'selection-list-editor',
@@ -194,6 +302,7 @@ const AXPWidgetsCatalog = {
194
302
  fileTypeExtension: 'file-type-extension',
195
303
  map: 'map',
196
304
  imageMarker: 'image-marker',
305
+ image: 'image',
197
306
  gallery: 'gallery',
198
307
  signature: 'signature',
199
308
  buttonAction: 'button-action',
@@ -205,7 +314,7 @@ const AXPWidgetsCatalog = {
205
314
  advancedGridItem: 'advanced-grid-item-layout',
206
315
  grid: 'grid-layout',
207
316
  gridItem: 'grid-item-layout',
208
- gridRow: 'grid-row-layout',
317
+ // gridRow: 'grid-row-layout',
209
318
  widgetSelector: 'widget-selector',
210
319
  template: 'template',
211
320
  templateDesigner: 'template-designer',
@@ -214,6 +323,9 @@ const AXPWidgetsCatalog = {
214
323
  direction: 'direction',
215
324
  border: 'border',
216
325
  flexLayout: 'flex-layout',
326
+ flexItem: 'flex-item-layout',
327
+ tableLayout: 'table-layout',
328
+ tableItem: 'table-item-layout',
217
329
  avatar: 'avatar',
218
330
  themePaletteChooser: 'theme-palette-chooser',
219
331
  themeModeChooser: 'theme-mode-chooser',
@@ -221,8 +333,9 @@ const AXPWidgetsCatalog = {
221
333
  fontStyleChooser: 'font-style-chooser',
222
334
  fontSizeChooser: 'font-size-chooser',
223
335
  iconChooser: 'icon-chooser',
224
- colorChooser: 'color-chooser',
336
+ themeColorChooser: 'theme-color-chooser',
225
337
  gridOptions: 'grid-options',
338
+ gridItemOptions: 'grid-item-options',
226
339
  advancedGridOptions: 'advanced-grid-options',
227
340
  stringFilter: 'string-filter',
228
341
  numberFilter: 'number-filter',
@@ -230,6 +343,7 @@ const AXPWidgetsCatalog = {
230
343
  booleanFilter: 'boolean-filter',
231
344
  lookupFilter: 'lookup-filter',
232
345
  flexOptions: 'flex-options',
346
+ flexItemOptions: 'flex-item-options',
233
347
  selectFilter: 'select-filter',
234
348
  requiredValidation: 'required-validation',
235
349
  regularExpressionValidation: 'regular-expression-validation',
@@ -254,8 +368,12 @@ const AXPWidgetsCatalog = {
254
368
  templateEditor: 'template-box-editor',
255
369
  panel: 'panel',
256
370
  notification: 'notification',
257
- taskList: 'task-list',
371
+ taskBoard: 'task-board',
258
372
  comment: 'comment',
373
+ list: 'list',
374
+ listToolbar: 'list-toolbar',
375
+ entityList: 'entity-list',
376
+ documentUploader: 'document-uploader',
259
377
  };
260
378
 
261
379
  function cloneProperty(property, values) {
@@ -340,63 +458,764 @@ function createSelectProperty(ctor) {
340
458
  const AXP_WIDGET_TOKEN = new InjectionToken('AXP_WIDGET_TOKEN');
341
459
  const AXP_WIDGET_COLUMN_TOKEN = new InjectionToken('AXP_WIDGET_COLUMN_TOKEN');
342
460
 
343
- class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
461
+ class AXPBaseWidgetComponent extends AXPLayoutElement {
344
462
  constructor() {
345
463
  super(...arguments);
346
- this.widgetRegistery = inject(AXPWidgetRegistryService);
347
- this.grid = inject(AXBaseDataTable);
348
- this.mergedOptions = signal({}, ...(ngDevMode ? [{ debugName: "mergedOptions" }] : []));
349
- this.loadingRow = signal(null, ...(ngDevMode ? [{ debugName: "loadingRow" }] : []));
350
- this.injector = inject(Injector);
351
- this.cdr = inject(ChangeDetectorRef);
464
+ this.token = inject(AXP_WIDGET_TOKEN);
465
+ this.host = inject(ElementRef).nativeElement;
466
+ this.layoutService = inject(AXPLayoutBuilderService);
467
+ this.contextService = inject(AXPLayoutBuilderContextStore);
468
+ this.config = this.token.config;
469
+ this.node = this.token.node;
470
+ this.name = this.token.node.name;
471
+ this.component = this;
472
+ this._options = signal(this.token.options ?? {}, ...(ngDevMode ? [{ debugName: "_options" }] : []));
473
+ this.options = this._options.asReadonly();
474
+ this.onOptionsChanged = new Subject();
475
+ this._status = signal(AXPWidgetStatus.Rendering, ...(ngDevMode ? [{ debugName: "_status" }] : []));
476
+ this.status = this._status.asReadonly();
477
+ this.onStatusChanged = new BehaviorSubject(this._status());
478
+ this.#statusEffect = effect(() => {
479
+ this.onStatusChanged.next(this.status());
480
+ }, ...(ngDevMode ? [{ debugName: "#statusEffect" }] : []));
481
+ this.isBusy = computed(() => [AXPWidgetStatus.Rendering, AXPWidgetStatus.Processing].includes(this.status()), ...(ngDevMode ? [{ debugName: "isBusy" }] : []));
482
+ this._children = signal(this.token.node.children ?? [], ...(ngDevMode ? [{ debugName: "_children" }] : []));
483
+ this.children = this._children.asReadonly();
352
484
  }
353
- get node() {
354
- return this._node;
485
+ get id() {
486
+ return this._id;
355
487
  }
356
- set node(v) {
357
- this._node = v;
488
+ #statusEffect;
489
+ outputs() {
490
+ return [];
358
491
  }
359
- get renderFooterTemplate() {
360
- return this.footerTemplate ?? this._contentFooterTemplate;
492
+ ngOnInit() {
493
+ if (get(this.node, '__meta__.added')) {
494
+ this.onAdded();
495
+ }
496
+ this.setStatus(AXPWidgetStatus.Rendered);
361
497
  }
362
- get renderCellTemplate() {
363
- return this.cellTemplate ?? this._contentCellTemplate;
498
+ setStatus(status) {
499
+ this._status.set(status);
500
+ this.layoutService.updateStatus();
364
501
  }
365
- async handleExpandRow(row) {
366
- this.loadingRow.set(row);
367
- await this.grid.expandRow(row);
368
- this.loadingRow.set(null);
369
- // if (row.data?.__meta__?.expanded === undefined) {
370
- // this.width = `${parseInt(this.width as string) + 24}px`;
371
- // }
502
+ setOptions(values) {
503
+ const oldValue = this.options();
504
+ const value = cloneDeep(values);
505
+ this._options.set({ ...oldValue, ...value });
506
+ this.onOptionsChanged.next({ sender: this });
372
507
  }
373
- get renderHeaderTemplate() {
374
- return this.headerTemplate ?? this._contentHeaderTemplate;
508
+ output(name) {
509
+ const outputs = this.outputs().map((c) => (typeof c == 'string' ? { name: c, value: c } : c));
510
+ if (outputs.some((c) => c.name == name)) {
511
+ const opt = get(this, name);
512
+ if (typeof opt == 'function') {
513
+ return opt();
514
+ }
515
+ return opt;
516
+ }
517
+ return null;
375
518
  }
376
- get loadingEnabled() {
377
- return true;
519
+ call(name, ...args) {
520
+ const fn = get(this, name);
521
+ if (fn && typeof fn == 'function') {
522
+ fn.bind(this)(...args);
523
+ }
378
524
  }
379
- get name() {
380
- return `col-${this.node.path}`;
525
+ setChildren(children) {
526
+ this._children.set([...children]);
381
527
  }
382
- async ngOnInit() {
383
- const widget = this.widgetRegistery.resolve(this.node.type);
384
- const mode = 'column';
385
- this.component = await widget?.components[mode]?.component();
386
- //
387
- const props = widget?.components[mode]?.properties
388
- ?.filter((c) => c.schema.defaultValue)
389
- .map((c) => ({ [c.name]: c.schema.defaultValue }))
390
- .reduce((acc, curr) => {
391
- return { ...acc, ...curr };
392
- }, {});
393
- //
394
- this.mergedOptions.set(merge(props, this.node.options) || {});
395
- const tokenValue = {
396
- path: this.node.path,
397
- options: this.mergedOptions(),
398
- };
399
- this.widgetInjector = Injector.create({
528
+ onAdded() { }
529
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBaseWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
530
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBaseWidgetComponent }); }
531
+ }
532
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBaseWidgetComponent, decorators: [{
533
+ type: Injectable
534
+ }] });
535
+ class AXPLayoutBaseWidgetComponent extends AXPBaseWidgetComponent {
536
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBaseWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
537
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBaseWidgetComponent }); }
538
+ }
539
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBaseWidgetComponent, decorators: [{
540
+ type: Injectable
541
+ }] });
542
+ class AXPValueWidgetComponent extends AXPLayoutBaseWidgetComponent {
543
+ constructor() {
544
+ super(...arguments);
545
+ this.path = this.token.node.path;
546
+ this.defaultValue = this.token.defaultValue ?? this.token.node.defaultValue;
547
+ this._isValueWidget = false;
548
+ this.isValueWidget = () => this._isValueWidget;
549
+ this.onValueChanged = new Subject();
550
+ this.fullPath = signal(null, ...(ngDevMode ? [{ debugName: "fullPath" }] : []));
551
+ this.parentPath = signal(null, ...(ngDevMode ? [{ debugName: "parentPath" }] : []));
552
+ this.getValue = computed(() => {
553
+ return this.fullPath() ? this.extractValue(this.fullPath()) : null;
554
+ }, ...(ngDevMode ? [{ debugName: "getValue", equal: isEqual }] : [{ equal: isEqual }]));
555
+ this.validationRules = computed(() => {
556
+ const validationsRaw = this.options()['validations'];
557
+ if (validationsRaw == null) {
558
+ return [];
559
+ }
560
+ return Object.values(this.options()['validations'])
561
+ .filter((c) => c != null)
562
+ .map((c) => ({
563
+ rule: c.rule,
564
+ message: c.message,
565
+ options: c.options,
566
+ }));
567
+ }, ...(ngDevMode ? [{ debugName: "validationRules" }] : []));
568
+ }
569
+ ngOnInit() {
570
+ this._isValueWidget = this.config.properties?.some((c) => c.name == 'path') ?? false;
571
+ if (this.isValueWidget()) {
572
+ this.detectFullPath();
573
+ if (!isNil(this.defaultValue) && isNil(this.getValue())) {
574
+ this.setValue(this.defaultValue);
575
+ }
576
+ }
577
+ //
578
+ super.ngOnInit();
579
+ }
580
+ extractValue(path) {
581
+ const rawValue = this.contextService.getValue(path);
582
+ if (this.node.valueTransforms?.getter) {
583
+ return this.node.valueTransforms?.getter(rawValue);
584
+ }
585
+ return rawValue;
586
+ }
587
+ setValue(value) {
588
+ if (this.node.valueTransforms?.setter) {
589
+ value = this.node.valueTransforms?.setter(value);
590
+ }
591
+ const oldValue = this.getValue();
592
+ value = isUndefined(value) ? null : value;
593
+ if (isNil(value) && isNil(oldValue)) {
594
+ return;
595
+ }
596
+ if (isEqual(oldValue, value)) {
597
+ return;
598
+ }
599
+ if (this.fullPath()) {
600
+ this.contextService.update(this.fullPath(), value);
601
+ this.onValueChanged.next({ sender: this });
602
+ }
603
+ }
604
+ detectFullPath() {
605
+ const sections = [];
606
+ const ids = [];
607
+ //
608
+ let parent = this;
609
+ //
610
+ while (parent) {
611
+ const isValueWidget = parent instanceof AXPValueWidgetComponent && parent.isValueWidget();
612
+ const valueParent = parent;
613
+ const path = valueParent.path ?? (isValueWidget ? valueParent.name : null);
614
+ const id = valueParent.name;
615
+ //
616
+ if (path) {
617
+ sections.push(path);
618
+ }
619
+ if (parent.index != null && isValueWidget) {
620
+ sections.push(`[${parent.index}]`);
621
+ }
622
+ if (id) {
623
+ ids.push(id);
624
+ if (parent.index != null) {
625
+ ids.push(`${parent.index}`);
626
+ }
627
+ }
628
+ parent = parent.parent;
629
+ }
630
+ //
631
+ this.fullPath.set(sections.reverse().join('.'));
632
+ this.parentPath.set(sections.slice(0, sections.length - 1).join('.'));
633
+ this._id = this.name || this.parent ? ids.reverse().join('_') : null;
634
+ if (this._id) {
635
+ this.layoutService.registerWidget(this._id, this);
636
+ }
637
+ }
638
+ handleValueChanged(e) {
639
+ if (e.isUserInteraction) {
640
+ this.setValue(e.value);
641
+ }
642
+ }
643
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPValueWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
644
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPValueWidgetComponent }); }
645
+ }
646
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPValueWidgetComponent, decorators: [{
647
+ type: Injectable
648
+ }] });
649
+ class AXPDataListWidgetComponent extends AXPValueWidgetComponent {
650
+ constructor() {
651
+ super(...arguments);
652
+ this.dataService = inject(AXPDataSourceDefinitionProviderService);
653
+ this.textField = computed(() => this.options()['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
654
+ this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
655
+ this.dataSource = signal(convertArrayToDataSource([]), ...(ngDevMode ? [{ debugName: "dataSource" }] : []));
656
+ this.isReady = computed(() => {
657
+ const key = this.dataSource().config?.key;
658
+ const valueField = this.valueField();
659
+ const result = key == valueField;
660
+ return result;
661
+ }, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
662
+ this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
663
+ this.rf = effect(async () => {
664
+ const rawValue = this.options()['dataSource'];
665
+ // static datasource class
666
+ if (rawValue instanceof AXDataSource) {
667
+ this.dataSource.set(rawValue);
668
+ }
669
+ // static array datasource
670
+ else if (Array.isArray(rawValue)) {
671
+ const ds = new AXDataSource({
672
+ key: this.valueField(),
673
+ pageSize: 10,
674
+ load: async (e) => {
675
+ const raw = this.options()['dataSource'];
676
+ return {
677
+ items: raw,
678
+ total: raw.length,
679
+ };
680
+ },
681
+ byKey: (key) => {
682
+ const raw = this.options()['dataSource'];
683
+ const item = raw.filter((c) => c[this.valueField()] == key);
684
+ return Promise.resolve(item[0]);
685
+ },
686
+ });
687
+ this.dataSource.set(ds);
688
+ }
689
+ // resolve data source by name
690
+ else if (rawValue && (typeof rawValue == 'string' || typeof rawValue == 'object')) {
691
+ const id = typeof rawValue == 'object' ? rawValue['id'] : rawValue;
692
+ const c = await this.dataService.get(id);
693
+ if (this.mode == 'designer' && c?.samples?.length) {
694
+ this.dataSource.set(convertArrayToDataSource(c.samples, {
695
+ key: this.valueField(),
696
+ pageSize: 500,
697
+ }));
698
+ }
699
+ else {
700
+ const ds = c?.source();
701
+ if (ds && ds instanceof Promise) {
702
+ const d = await ds;
703
+ this.dataSource.set(d);
704
+ }
705
+ else if (ds) {
706
+ this.dataSource.set(ds);
707
+ }
708
+ // empty datasource
709
+ else {
710
+ this.dataSource.set(convertArrayToDataSource([]));
711
+ }
712
+ }
713
+ }
714
+ // empty datasource
715
+ else {
716
+ this.dataSource.set(convertArrayToDataSource([]));
717
+ }
718
+ }, ...(ngDevMode ? [{ debugName: "rf" }] : []));
719
+ this.effect2 = effect(async () => {
720
+ const value = this.getValue();
721
+ const items = [];
722
+ if (Array.isArray(value)) {
723
+ items.push(...(await Promise.all(value.map((item) => this.extractItem(item)))));
724
+ }
725
+ else {
726
+ items.push(await this.extractItem(value));
727
+ }
728
+ this.selectedItems.set(items.filter((c) => c != null));
729
+ }, ...(ngDevMode ? [{ debugName: "effect2" }] : []));
730
+ }
731
+ async extractItem(item) {
732
+ if (isNil(item)) {
733
+ return null;
734
+ }
735
+ if (isObjectLike(item) && get(item, this.textField()) != null) {
736
+ return item;
737
+ }
738
+ const key = extractValue(item, this.valueField());
739
+ const ds = this.dataSource();
740
+ if (ds.config?.byKey) {
741
+ const found = await ds.config?.byKey(key);
742
+ if (found) {
743
+ return found;
744
+ }
745
+ }
746
+ return isObjectLike(item)
747
+ ? item
748
+ : {
749
+ [this.valueField()]: item,
750
+ [this.textField()]: item,
751
+ };
752
+ }
753
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPDataListWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
754
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPDataListWidgetComponent }); }
755
+ }
756
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPDataListWidgetComponent, decorators: [{
757
+ type: Injectable
758
+ }] });
759
+ class AXPColumnWidgetComponent {
760
+ constructor() {
761
+ this.token = inject(AXP_WIDGET_COLUMN_TOKEN);
762
+ this.path = this.token.path;
763
+ this.options = this.token.options ?? {};
764
+ this.rawValue = null;
765
+ this.nullText = this.options['nullText'];
766
+ this.nullValue = this.options['nullValue'];
767
+ this.value = computed(() => {
768
+ if (isNil(this.rawValue) && !isNil(this.nullValue)) {
769
+ return this.nullValue;
770
+ }
771
+ return this.rawValue;
772
+ }, ...(ngDevMode ? [{ debugName: "value" }] : []));
773
+ }
774
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPColumnWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
775
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPColumnWidgetComponent }); }
776
+ }
777
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPColumnWidgetComponent, decorators: [{
778
+ type: Injectable
779
+ }] });
780
+
781
+ class AXPBoxModelLayoutWidgetComponent extends AXPLayoutBaseWidgetComponent {
782
+ constructor() {
783
+ super(...arguments);
784
+ this.hostBoxStyle = computed(() => {
785
+ const options = this.options();
786
+ const style = {};
787
+ const spacing = options?.['spacing'];
788
+ const border = options?.['border'];
789
+ const backgroundColor = options?.['backgroundColor'];
790
+ const direction = options?.['direction'];
791
+ const overflow = options?.['overflow'];
792
+ const overflowX = options?.['overflowX'];
793
+ const overflowY = options?.['overflowY'];
794
+ style['background-color'] = backgroundColor ?? '';
795
+ style['padding'] = spacing?.padding ?? '';
796
+ style['margin'] = spacing?.margin ?? '';
797
+ style['border-radius'] = border?.radius ?? '';
798
+ style['border-width'] = border?.width ?? '';
799
+ style['border-color'] = border?.color ?? '';
800
+ style['border-style'] = border?.style ?? '';
801
+ style['overflow'] = overflow ?? '';
802
+ style['overflow-x'] = overflowX ?? '';
803
+ style['overflow-y'] = overflowY ?? '';
804
+ style['direction'] = direction ?? '';
805
+ return style;
806
+ }, ...(ngDevMode ? [{ debugName: "hostBoxStyle" }] : []));
807
+ this.blockStyle = computed(() => {
808
+ const options = this.options();
809
+ const style = { ...this.hostBoxStyle() };
810
+ const width = options?.['width'];
811
+ const minWidth = options?.['minWidth'];
812
+ const maxWidth = options?.['maxWidth'];
813
+ const height = options?.['height'];
814
+ const minHeight = options?.['minHeight'];
815
+ const maxHeight = options?.['maxHeight'];
816
+ style['min-width'] = minWidth ?? '';
817
+ style['width'] = width ?? '';
818
+ style['max-width'] = maxWidth ?? '';
819
+ style['min-height'] = minHeight ?? '';
820
+ style['height'] = height ?? '';
821
+ style['max-height'] = maxHeight ?? '';
822
+ return style;
823
+ }, ...(ngDevMode ? [{ debugName: "blockStyle" }] : []));
824
+ this.inlineStyle = computed(() => {
825
+ return { ...this.hostBoxStyle() };
826
+ }, ...(ngDevMode ? [{ debugName: "inlineStyle" }] : []));
827
+ this.blockClass = computed(() => {
828
+ return {
829
+ 'ax-block': true,
830
+ 'ax-w-full': true,
831
+ // 'ax-widget-outline': true,
832
+ };
833
+ }, ...(ngDevMode ? [{ debugName: "blockClass" }] : []));
834
+ this.inlineClass = computed(() => {
835
+ return {
836
+ 'ax-inline-block': true,
837
+ };
838
+ }, ...(ngDevMode ? [{ debugName: "inlineClass" }] : []));
839
+ }
840
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBoxModelLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
841
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBoxModelLayoutWidgetComponent }); }
842
+ }
843
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBoxModelLayoutWidgetComponent, decorators: [{
844
+ type: Injectable
845
+ }] });
846
+
847
+ class AXPBlockBaseLayoutWidgetComponent extends AXPBoxModelLayoutWidgetComponent {
848
+ constructor() {
849
+ super(...arguments);
850
+ this.hostClass = computed(() => this.blockClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
851
+ this.hostStyle = computed(() => this.blockStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
852
+ }
853
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBlockBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
854
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBlockBaseLayoutWidgetComponent }); }
855
+ }
856
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPBlockBaseLayoutWidgetComponent, decorators: [{
857
+ type: Injectable
858
+ }] });
859
+
860
+ class AXPFlexBaseLayoutWidgetComponent extends AXPBlockBaseLayoutWidgetComponent {
861
+ constructor() {
862
+ super(...arguments);
863
+ this.flex = computed(() => this.options(), ...(ngDevMode ? [{ debugName: "flex" }] : []));
864
+ this.hostFlexStyle = computed(() => {
865
+ const blockStyle = this.blockStyle();
866
+ const style = { ...blockStyle };
867
+ const flex = this.flex();
868
+ if (isNil(flex?.flexDirection)) {
869
+ style['flex-direction'] = '';
870
+ }
871
+ else {
872
+ style['flex-direction'] = flex.flexDirection;
873
+ }
874
+ if (isNil(flex?.flexWrap)) {
875
+ style['flex-wrap'] = '';
876
+ }
877
+ else {
878
+ style['flex-wrap'] = flex.flexWrap;
879
+ }
880
+ //TODO NEED TO FIX LATER
881
+ style['overflow'] = flex?.flexWrap === 'nowrap' ? 'auto' : '';
882
+ //END
883
+ if (isNil(flex?.justifyContent)) {
884
+ style['justify-content'] = '';
885
+ }
886
+ else {
887
+ style['justify-content'] = flex.justifyContent;
888
+ }
889
+ if (isNil(flex?.alignItems)) {
890
+ style['align-items'] = '';
891
+ }
892
+ else {
893
+ style['align-items'] = flex.alignItems;
894
+ }
895
+ if (isNil(flex?.gap)) {
896
+ style['gap'] = '';
897
+ }
898
+ else {
899
+ style['gap'] = flex.gap;
900
+ }
901
+ return style;
902
+ }, ...(ngDevMode ? [{ debugName: "hostFlexStyle" }] : []));
903
+ this.hostFlexClass = computed(() => {
904
+ return {
905
+ ...this.blockClass(),
906
+ 'ax-flex': true,
907
+ 'ax-h-full': true,
908
+ };
909
+ }, ...(ngDevMode ? [{ debugName: "hostFlexClass" }] : []));
910
+ this.hostClass = computed(() => {
911
+ return this.hostFlexClass();
912
+ }, ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
913
+ this.hostStyle = computed(() => {
914
+ return this.hostFlexStyle();
915
+ }, ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
916
+ }
917
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
918
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexBaseLayoutWidgetComponent }); }
919
+ }
920
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexBaseLayoutWidgetComponent, decorators: [{
921
+ type: Injectable
922
+ }] });
923
+
924
+ class AXPInlineBaseLayoutWidgetComponent extends AXPBoxModelLayoutWidgetComponent {
925
+ constructor() {
926
+ super(...arguments);
927
+ this.hostClass = computed(() => this.inlineClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
928
+ this.hostStyle = computed(() => this.inlineStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
929
+ }
930
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPInlineBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
931
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPInlineBaseLayoutWidgetComponent }); }
932
+ }
933
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPInlineBaseLayoutWidgetComponent, decorators: [{
934
+ type: Injectable
935
+ }] });
936
+
937
+ class AXPFlexItemBaseLayoutWidgetComponent extends AXPInlineBaseLayoutWidgetComponent {
938
+ constructor() {
939
+ super(...arguments);
940
+ this.flexItem = computed(() => this.options(), ...(ngDevMode ? [{ debugName: "flexItem" }] : []));
941
+ this.hostFlexItemStyle = computed(() => {
942
+ const inlineStyle = this.blockStyle();
943
+ const style = { ...inlineStyle };
944
+ const fi = this.flexItem();
945
+ if (isNil(fi?.order)) {
946
+ style['order'] = '';
947
+ }
948
+ else {
949
+ style['order'] = fi.order;
950
+ }
951
+ if (isNil(fi?.grow)) {
952
+ style['flex-grow'] = '';
953
+ }
954
+ else {
955
+ style['flex-grow'] = fi.grow;
956
+ }
957
+ if (isNil(fi?.shrink)) {
958
+ style['flex-shrink'] = '';
959
+ }
960
+ else {
961
+ style['flex-shrink'] = fi.shrink;
962
+ }
963
+ if (isNil(fi?.basis)) {
964
+ style['flex-basis'] = '';
965
+ }
966
+ else {
967
+ style['flex-basis'] = fi.basis;
968
+ }
969
+ if (isNil(fi?.alignSelf)) {
970
+ style['align-self'] = '';
971
+ }
972
+ else {
973
+ style['align-self'] = fi.alignSelf;
974
+ }
975
+ return style;
976
+ }, ...(ngDevMode ? [{ debugName: "hostFlexItemStyle" }] : []));
977
+ this.hostFlexItemClass = computed(() => {
978
+ return {
979
+ ...this.blockClass(),
980
+ };
981
+ }, ...(ngDevMode ? [{ debugName: "hostFlexItemClass" }] : []));
982
+ this.hostClass = computed(() => {
983
+ return this.hostFlexItemClass();
984
+ }, ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
985
+ this.hostStyle = computed(() => {
986
+ return this.hostFlexItemStyle();
987
+ }, ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
988
+ }
989
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexItemBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
990
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexItemBaseLayoutWidgetComponent }); }
991
+ }
992
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPFlexItemBaseLayoutWidgetComponent, decorators: [{
993
+ type: Injectable
994
+ }] });
995
+
996
+ class AXPGridBaseLayoutWidgetComponent extends AXPBlockBaseLayoutWidgetComponent {
997
+ constructor() {
998
+ super(...arguments);
999
+ this.grid = computed(() => this.options()?.['grid'], ...(ngDevMode ? [{ debugName: "grid" }] : []));
1000
+ this.hostGridStyle = computed(() => {
1001
+ const style = { ...this.inlineStyle() };
1002
+ const g = this.grid()?.default;
1003
+ if (g?.gap)
1004
+ style['gap'] = g.gap;
1005
+ return style;
1006
+ }, ...(ngDevMode ? [{ debugName: "hostGridStyle" }] : []));
1007
+ this.hostGridClass = computed(() => {
1008
+ const cls = {
1009
+ ...this.inlineClass(),
1010
+ 'ax-grid': true,
1011
+ };
1012
+ const g = this.grid()?.default;
1013
+ if (g?.columns)
1014
+ cls[`lg:ax-grid-cols-${g.columns}`] = true;
1015
+ if (g?.rows)
1016
+ cls[`lg:ax-grid-rows-${g.rows}`] = true;
1017
+ if (g?.justifyItems)
1018
+ cls[`lg:ax-justify-items-${g.justifyItems}`] = true;
1019
+ if (g?.alignItems)
1020
+ cls[`lg:ax-align-items-${g.alignItems}`] = true;
1021
+ if (g?.autoFlow)
1022
+ cls[`lg:ax-grid-flow-${g.autoFlow}`] = true;
1023
+ return cls;
1024
+ }, ...(ngDevMode ? [{ debugName: "hostGridClass" }] : []));
1025
+ this.hostClass = computed(() => this.hostGridClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
1026
+ this.hostStyle = computed(() => this.hostGridStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
1027
+ }
1028
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1029
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridBaseLayoutWidgetComponent }); }
1030
+ }
1031
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridBaseLayoutWidgetComponent, decorators: [{
1032
+ type: Injectable
1033
+ }] });
1034
+
1035
+ class AXPGridItemBaseLayoutWidgetComponent extends AXPFlexBaseLayoutWidgetComponent {
1036
+ constructor() {
1037
+ super(...arguments);
1038
+ this.gridItem = computed(() => this.options(), ...(ngDevMode ? [{ debugName: "gridItem" }] : []));
1039
+ this.hostGridItemStyle = computed(() => {
1040
+ const style = { ...this.hostFlexStyle() };
1041
+ const g = this.gridItem();
1042
+ if (g?.alignSelf)
1043
+ style['align-self'] = g.alignSelf;
1044
+ if (g?.justifySelf)
1045
+ style['justify-self'] = g.justifySelf;
1046
+ return style;
1047
+ }, ...(ngDevMode ? [{ debugName: "hostGridItemStyle" }] : []));
1048
+ this.hostGridItemClass = computed(() => {
1049
+ const cls = { ...this.hostFlexClass() };
1050
+ const g = this.gridItem();
1051
+ if (g?.colSpan)
1052
+ cls[`lg:ax-col-span-${g.colSpan}`] = true;
1053
+ if (g?.colStart)
1054
+ cls[`lg:ax-col-start-${g.colStart}`] = true;
1055
+ if (g?.colEnd)
1056
+ cls[`lg:ax-col-end-${g.colEnd}`] = true;
1057
+ if (g?.rowSpan)
1058
+ cls[`lg:ax-row-span-${g.rowSpan}`] = true;
1059
+ if (g?.rowStart)
1060
+ cls[`lg:ax-row-start-${g.rowStart}`] = true;
1061
+ if (g?.rowEnd)
1062
+ cls[`lg:ax-row-end-${g.rowEnd}`] = true;
1063
+ return cls;
1064
+ }, ...(ngDevMode ? [{ debugName: "hostGridItemClass" }] : []));
1065
+ this.hostClass = computed(() => this.hostGridItemClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
1066
+ this.hostStyle = computed(() => this.hostGridItemStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
1067
+ }
1068
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridItemBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1069
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridItemBaseLayoutWidgetComponent }); }
1070
+ }
1071
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPGridItemBaseLayoutWidgetComponent, decorators: [{
1072
+ type: Injectable
1073
+ }] });
1074
+
1075
+ class AXPTableBaseLayoutWidgetComponent extends AXPBlockBaseLayoutWidgetComponent {
1076
+ constructor() {
1077
+ super(...arguments);
1078
+ this.hostTableClass = computed(() => ({
1079
+ ...this.blockClass(),
1080
+ }), ...(ngDevMode ? [{ debugName: "hostTableClass" }] : []));
1081
+ this.hostTableStyle = computed(() => {
1082
+ const style = { ...this.blockStyle() };
1083
+ style['overflow-x'] = 'auto';
1084
+ return style;
1085
+ }, ...(ngDevMode ? [{ debugName: "hostTableStyle" }] : []));
1086
+ this.hostClass = computed(() => this.hostTableClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
1087
+ this.hostStyle = computed(() => this.hostTableStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
1088
+ }
1089
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1090
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableBaseLayoutWidgetComponent }); }
1091
+ }
1092
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableBaseLayoutWidgetComponent, decorators: [{
1093
+ type: Injectable
1094
+ }] });
1095
+
1096
+ class AXPTableItemOpsBaseLayoutWidgetComponent extends AXPBlockBaseLayoutWidgetComponent {
1097
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemOpsBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1098
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemOpsBaseLayoutWidgetComponent }); }
1099
+ }
1100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemOpsBaseLayoutWidgetComponent, decorators: [{
1101
+ type: Injectable
1102
+ }] });
1103
+
1104
+ class AXPTableItemBaseLayoutWidgetComponent extends AXPTableItemOpsBaseLayoutWidgetComponent {
1105
+ constructor() {
1106
+ super(...arguments);
1107
+ this.colSpan = computed(() => {
1108
+ const v = this.options()?.colSpan;
1109
+ return v ? Math.max(1, v) : 1;
1110
+ }, ...(ngDevMode ? [{ debugName: "colSpan" }] : []));
1111
+ this.rowSpan = computed(() => {
1112
+ const v = this.options()?.rowSpan;
1113
+ return v ? Math.max(1, v) : 1;
1114
+ }, ...(ngDevMode ? [{ debugName: "rowSpan" }] : []));
1115
+ this.hostClass = computed(() => this.blockClass(), ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
1116
+ this.hostStyle = computed(() => this.blockStyle(), ...(ngDevMode ? [{ debugName: "hostStyle" }] : []));
1117
+ }
1118
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemBaseLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1119
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemBaseLayoutWidgetComponent }); }
1120
+ }
1121
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPTableItemBaseLayoutWidgetComponent, decorators: [{
1122
+ type: Injectable
1123
+ }] });
1124
+
1125
+ class AXPWidgetRegistryService {
1126
+ /**
1127
+ *
1128
+ */
1129
+ constructor() {
1130
+ this.types = new Map();
1131
+ AXPWidgetRegistryService.instance = this;
1132
+ }
1133
+ register(widget) {
1134
+ this.types.set(widget.name, widget);
1135
+ }
1136
+ extend(parentName, widget) {
1137
+ const parentWidget = this.resolve(parentName);
1138
+ const newWidget = merge({}, parentWidget, widget);
1139
+ newWidget.name = widget.name;
1140
+ this.register(newWidget);
1141
+ }
1142
+ resolve(name) {
1143
+ const widget = this.types.get(name);
1144
+ if (!widget) {
1145
+ throw new Error(`Widget with name "${name}" does not exist.`);
1146
+ }
1147
+ return widget;
1148
+ }
1149
+ all() {
1150
+ return Array.from(this.types.values());
1151
+ }
1152
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1153
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetRegistryService, providedIn: 'root' }); }
1154
+ }
1155
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetRegistryService, decorators: [{
1156
+ type: Injectable,
1157
+ args: [{
1158
+ providedIn: 'root',
1159
+ }]
1160
+ }], ctorParameters: () => [] });
1161
+
1162
+ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
1163
+ constructor() {
1164
+ super(...arguments);
1165
+ this.widgetRegistery = inject(AXPWidgetRegistryService);
1166
+ this.grid = inject(AXBaseDataTable);
1167
+ this.mergedOptions = signal({}, ...(ngDevMode ? [{ debugName: "mergedOptions" }] : []));
1168
+ this.loadingRow = signal(null, ...(ngDevMode ? [{ debugName: "loadingRow" }] : []));
1169
+ this.injector = inject(Injector);
1170
+ this.cdr = inject(ChangeDetectorRef);
1171
+ }
1172
+ get node() {
1173
+ return this._node;
1174
+ }
1175
+ set node(v) {
1176
+ this._node = v;
1177
+ }
1178
+ get renderFooterTemplate() {
1179
+ return this.footerTemplate ?? this._contentFooterTemplate;
1180
+ }
1181
+ get renderCellTemplate() {
1182
+ return this.cellTemplate ?? this._contentCellTemplate;
1183
+ }
1184
+ async handleExpandRow(row) {
1185
+ this.loadingRow.set(row);
1186
+ await this.grid.expandRow(row);
1187
+ this.loadingRow.set(null);
1188
+ // if (row.data?.__meta__?.expanded === undefined) {
1189
+ // this.width = `${parseInt(this.width as string) + 24}px`;
1190
+ // }
1191
+ }
1192
+ get renderHeaderTemplate() {
1193
+ return this.headerTemplate ?? this._contentHeaderTemplate;
1194
+ }
1195
+ get loadingEnabled() {
1196
+ return true;
1197
+ }
1198
+ get name() {
1199
+ return `col-${this.node.path}`;
1200
+ }
1201
+ async ngOnInit() {
1202
+ const widget = this.widgetRegistery.resolve(this.node.type);
1203
+ const mode = 'column';
1204
+ this.component = await widget?.components[mode]?.component();
1205
+ //
1206
+ const props = widget?.components[mode]?.properties
1207
+ ?.filter((c) => c.schema.defaultValue)
1208
+ .map((c) => ({ [c.name]: c.schema.defaultValue }))
1209
+ .reduce((acc, curr) => {
1210
+ return { ...acc, ...curr };
1211
+ }, {});
1212
+ //
1213
+ this.mergedOptions.set(merge(props, this.node.options) || {});
1214
+ const tokenValue = {
1215
+ path: this.node.path,
1216
+ options: this.mergedOptions(),
1217
+ };
1218
+ this.widgetInjector = Injector.create({
400
1219
  parent: this.injector,
401
1220
  providers: [
402
1221
  {
@@ -405,78 +1224,84 @@ class AXPWidgetColumnRendererComponent extends AXDataTableColumnComponent {
405
1224
  },
406
1225
  ],
407
1226
  });
408
- this.width = this.customWidth ? this.customWidth : this.mergedOptions().width ?? '200px';
1227
+ this.width = this.customWidth ? this.customWidth : (this.mergedOptions().width ?? '200px');
409
1228
  this.allowResizing = this.mergedOptions().allowResizing || true;
410
1229
  this.cdr.detectChanges();
411
1230
  }
412
1231
  getInputs(data) {
413
1232
  return {
414
1233
  rawValue: getSmart(data, this.node.path),
415
- rowData: data
1234
+ rowData: data,
416
1235
  };
417
1236
  }
418
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetColumnRendererComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
419
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", 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: [
1237
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetColumnRendererComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1238
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", 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: [
420
1239
  AXPLayoutBuilderService,
421
1240
  { provide: AXDataTableColumnComponent, useExisting: AXPWidgetColumnRendererComponent },
422
1241
  ], viewQueries: [{ propertyName: "_contentFooterTemplate", first: true, predicate: ["footer"], descendants: true }, { propertyName: "_contentCellTemplate", first: true, predicate: ["cell"], descendants: true }, { propertyName: "_contentHeaderTemplate", first: true, predicate: ["header"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
423
- <ng-template #header>{{ caption }}</ng-template>
1242
+ <ng-template #header>{{ caption | translate | async }}</ng-template>
424
1243
  <ng-template #cell let-row>
425
1244
  <div class="ax-flex ax-gap-2 ax-items-center">
426
1245
  @if (expandHandler) {
427
- <div
428
- (click)="handleExpandRow(row)"
429
- class="ax-expand-handler"
430
- [class.ax-invisible]="row.data.hasChild === false"
431
- id="ax-expand-handler-container"
432
- [style.padding-inline-start.rem]="row.data?.__meta__?.level * 2"
433
- >
434
- @if (loadingRow() === row) {
435
- <i class="fas fa-spinner-third ax-animate-twSpin ax-animate-infinite"></i>
436
- } @else { @if (row.data?.__meta__?.expanded) {
437
- <i [class]="customCollapseIcon || 'far fa-minus-square ax-text-md ax-opacity-75'"></i>
438
- } @else {
439
- <i [class]="customExpandIcon || 'far fa-plus-square ax-text-md ax-opacity-75'"></i>
440
- } }
441
- </div>
442
- } @if(component && widgetInjector && row?.data) {
443
- <ng-container
444
- *ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
445
- ></ng-container>
1246
+ <div
1247
+ (click)="handleExpandRow(row)"
1248
+ class="ax-expand-handler"
1249
+ [class.ax-invisible]="row.data.hasChild === false"
1250
+ id="ax-expand-handler-container"
1251
+ [style.padding-inline-start.rem]="row.data?.__meta__?.level * 2"
1252
+ >
1253
+ @if (loadingRow() === row) {
1254
+ <i class="fas fa-spinner-third ax-animate-twSpin ax-animate-infinite"></i>
1255
+ } @else {
1256
+ @if (row.data?.__meta__?.expanded) {
1257
+ <i [class]="customCollapseIcon || 'far fa-minus-square ax-text-md ax-opacity-75'"></i>
1258
+ } @else {
1259
+ <i [class]="customExpandIcon || 'far fa-plus-square ax-text-md ax-opacity-75'"></i>
1260
+ }
1261
+ }
1262
+ </div>
1263
+ }
1264
+ @if (component && widgetInjector && row?.data) {
1265
+ <ng-container
1266
+ *ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
1267
+ ></ng-container>
446
1268
  }
447
1269
  </div>
448
1270
  </ng-template>
449
1271
  <ng-template #footer></ng-template>
450
- `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1272
+ `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
451
1273
  }
452
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetColumnRendererComponent, decorators: [{
1274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetColumnRendererComponent, decorators: [{
453
1275
  type: Component,
454
1276
  args: [{
455
1277
  selector: 'axp-widget-column-renderer',
456
1278
  template: `
457
- <ng-template #header>{{ caption }}</ng-template>
1279
+ <ng-template #header>{{ caption | translate | async }}</ng-template>
458
1280
  <ng-template #cell let-row>
459
1281
  <div class="ax-flex ax-gap-2 ax-items-center">
460
1282
  @if (expandHandler) {
461
- <div
462
- (click)="handleExpandRow(row)"
463
- class="ax-expand-handler"
464
- [class.ax-invisible]="row.data.hasChild === false"
465
- id="ax-expand-handler-container"
466
- [style.padding-inline-start.rem]="row.data?.__meta__?.level * 2"
467
- >
468
- @if (loadingRow() === row) {
469
- <i class="fas fa-spinner-third ax-animate-twSpin ax-animate-infinite"></i>
470
- } @else { @if (row.data?.__meta__?.expanded) {
471
- <i [class]="customCollapseIcon || 'far fa-minus-square ax-text-md ax-opacity-75'"></i>
472
- } @else {
473
- <i [class]="customExpandIcon || 'far fa-plus-square ax-text-md ax-opacity-75'"></i>
474
- } }
475
- </div>
476
- } @if(component && widgetInjector && row?.data) {
477
- <ng-container
478
- *ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
479
- ></ng-container>
1283
+ <div
1284
+ (click)="handleExpandRow(row)"
1285
+ class="ax-expand-handler"
1286
+ [class.ax-invisible]="row.data.hasChild === false"
1287
+ id="ax-expand-handler-container"
1288
+ [style.padding-inline-start.rem]="row.data?.__meta__?.level * 2"
1289
+ >
1290
+ @if (loadingRow() === row) {
1291
+ <i class="fas fa-spinner-third ax-animate-twSpin ax-animate-infinite"></i>
1292
+ } @else {
1293
+ @if (row.data?.__meta__?.expanded) {
1294
+ <i [class]="customCollapseIcon || 'far fa-minus-square ax-text-md ax-opacity-75'"></i>
1295
+ } @else {
1296
+ <i [class]="customExpandIcon || 'far fa-plus-square ax-text-md ax-opacity-75'"></i>
1297
+ }
1298
+ }
1299
+ </div>
1300
+ }
1301
+ @if (component && widgetInjector && row?.data) {
1302
+ <ng-container
1303
+ *ngComponentOutlet="component; injector: widgetInjector; inputs: getInputs(row.data)"
1304
+ ></ng-container>
480
1305
  }
481
1306
  </div>
482
1307
  </ng-template>
@@ -509,126 +1334,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
509
1334
  }], cellTemplate: [{
510
1335
  type: Input
511
1336
  }], _contentCellTemplate: [{
512
- type: ViewChild,
513
- args: ['cell']
514
- }], headerTemplate: [{
515
- type: Input
516
- }], _contentHeaderTemplate: [{
517
- type: ViewChild,
518
- args: ['header']
519
- }] } });
520
-
521
- class AXPLayoutContextChangeEvent {
522
- }
523
- const AXPLayoutBuilderContextStore = signalStore(
524
- // Initial State
525
- withState(() => ({
526
- data: {}, // Shared context data
527
- state: 'initiated', // Current state
528
- initialSnapshot: {}, // Snapshot of the first initialized state
529
- previousSnapshot: {}, // Snapshot of the previous state
530
- lastChange: {
531
- state: 'initiated',
532
- }, // Last change event
533
- })),
534
- // Computed Signals
535
- withComputed(({ data, state, lastChange, initialSnapshot, previousSnapshot }) => ({
536
- isChanged: computed(() => state() === 'changed'),
537
- isReset: computed(() => state() === 'restored'),
538
- isInitiated: computed(() => state() === 'initiated'),
539
- isEmpty: computed(() => Object.keys(data()).length === 0),
540
- isDirty: computed(() => !isEqual(data(), previousSnapshot())),
541
- snapshot: computed(() => cloneDeep(data())), // Current data snapshot
542
- initial: computed(() => cloneDeep(initialSnapshot())), // Initial snapshot
543
- previous: computed(() => cloneDeep(previousSnapshot())), // Previous snapshot
544
- changeEvent: computed(() => lastChange()), // Reactive last change event
545
- })),
546
- // Methods for State Management
547
- withMethods((store) => ({
548
- // Update a specific value
549
- update(path, value) {
550
- const currentData = cloneDeep(store.data());
551
- const oldValue = get(currentData, path);
552
- // Skip if the value hasn't changed
553
- if (isEqual(oldValue, value)) {
554
- return;
555
- }
556
- // Update the value and prepare the change event
557
- const updatedData = setSmart(currentData, path, value);
558
- const changeEvent = {
559
- oldValue,
560
- newValue: value,
561
- path,
562
- state: 'changed',
563
- data: updatedData,
564
- };
565
- // Patch the state
566
- patchState(store, {
567
- previousSnapshot: store.snapshot(), // Save the previous state
568
- data: updatedData,
569
- state: 'changed',
570
- lastChange: changeEvent,
571
- });
572
- },
573
- patch(context) {
574
- const currentData = cloneDeep(store.data());
575
- // Update the value and prepare the change event
576
- const updatedData = { ...currentData, ...context };
577
- const changeEvent = {
578
- state: 'patch',
579
- data: updatedData,
580
- };
581
- // Patch the state
582
- patchState(store, {
583
- previousSnapshot: store.snapshot(), // Save the previous state
584
- data: updatedData,
585
- state: 'changed',
586
- lastChange: changeEvent,
587
- });
588
- },
589
- // Reset to the initial state
590
- reset() {
591
- const initialData = store.initial();
592
- const changeEvent = {
593
- oldValue: cloneDeep(store.data()), // Current data becomes old value
594
- newValue: cloneDeep(initialData), // Reset to the initial state
595
- path: '',
596
- state: 'restored',
597
- data: initialData,
598
- };
599
- patchState(store, {
600
- previousSnapshot: store.snapshot(), // Save the previous state
601
- data: initialData,
602
- state: 'restored',
603
- lastChange: changeEvent,
604
- });
605
- },
606
- // Initialize the state
607
- set(initialData) {
608
- const currentData = store.data();
609
- if (isEqual(currentData, initialData)) {
610
- return; // Skip if the current state matches the initial state
611
- }
612
- const changeEvent = {
613
- oldValue: null,
614
- newValue: cloneDeep(initialData),
615
- path: '',
616
- state: 'initiated',
617
- data: initialData,
618
- };
619
- patchState(store, {
620
- initialSnapshot: cloneDeep(initialData), // Save the initial state
621
- previousSnapshot: store.snapshot(), // Save the current state as the previous
622
- data: initialData,
623
- state: 'initiated',
624
- lastChange: changeEvent,
625
- });
626
- },
627
- // Get a specific value
628
- getValue(path) {
629
- return get(store.data(), path);
630
- },
631
- })));
1337
+ type: ViewChild,
1338
+ args: ['cell']
1339
+ }], headerTemplate: [{
1340
+ type: Input
1341
+ }], _contentHeaderTemplate: [{
1342
+ type: ViewChild,
1343
+ args: ['header']
1344
+ }] } });
632
1345
 
633
1346
  class AXPWidgetContainerComponent {
634
1347
  set context(value) {
@@ -653,10 +1366,16 @@ class AXPWidgetContainerComponent {
653
1366
  }
654
1367
  });
655
1368
  }
656
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
657
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: AXPWidgetContainerComponent, isStandalone: false, selector: "axp-widgets-container", inputs: { context: "context", functions: "functions" }, outputs: { onContextChanged: "onContextChanged" }, host: { styleAttribute: "display: contents;" }, providers: [AXPLayoutBuilderService, AXPLayoutBuilderContextStore], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1369
+ refresh() {
1370
+ this.builderService.refresh();
1371
+ }
1372
+ find(name) {
1373
+ return this.builderService.waitForWidget(name);
1374
+ }
1375
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1376
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: AXPWidgetContainerComponent, isStandalone: false, selector: "axp-widgets-container", inputs: { context: "context", functions: "functions" }, outputs: { onContextChanged: "onContextChanged" }, host: { styleAttribute: "display: contents;" }, providers: [AXPLayoutBuilderService, AXPLayoutBuilderContextStore], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
658
1377
  }
659
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetContainerComponent, decorators: [{
1378
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetContainerComponent, decorators: [{
660
1379
  type: Component,
661
1380
  args: [{
662
1381
  selector: 'axp-widgets-container',
@@ -675,12 +1394,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
675
1394
  }] } });
676
1395
 
677
1396
  class AXPWidgetPlaceholderComponent {
678
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetPlaceholderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
679
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: AXPWidgetPlaceholderComponent, isStandalone: true, selector: "axp-widget-placeholder", ngImport: i0, template: `<div>
1397
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetPlaceholderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1398
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: AXPWidgetPlaceholderComponent, isStandalone: true, selector: "axp-widget-placeholder", ngImport: i0, template: `<div>
680
1399
  <ax-skeleton class="ax-w-full ax-h-10 ax-rounded-md"></ax-skeleton>
681
1400
  </div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i1$1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
682
1401
  }
683
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetPlaceholderComponent, decorators: [{
1402
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetPlaceholderComponent, decorators: [{
684
1403
  type: Component,
685
1404
  args: [{
686
1405
  selector: 'axp-widget-placeholder',
@@ -694,6 +1413,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
694
1413
  }] });
695
1414
 
696
1415
  class AXPWidgetRendererDirective {
1416
+ //#endregion
697
1417
  //#endregion
698
1418
  constructor() {
699
1419
  this.parentNode = input(...(ngDevMode ? [undefined, { debugName: "parentNode" }] : []));
@@ -720,29 +1440,314 @@ class AXPWidgetRendererDirective {
720
1440
  this.renderTimeoutId = null;
721
1441
  this.hasInitialRender = false;
722
1442
  this.onContextChanged = new Subject();
1443
+ //#region ---- Performance Optimization Properties ----
1444
+ this.contextUpdateQueue = new Set();
1445
+ this.contextUpdateTimeout = null;
1446
+ this.CONTEXT_UPDATE_DEBOUNCE_MS = 4; // ~250fps for large forms
1447
+ // Removed visibility detection - not needed for current implementation
1448
+ // Expression result caching
1449
+ this.expressionCache = new Map();
1450
+ this.EXPRESSION_CACHE_TTL = 500; // Cache for 500ms (increased for better hit rate)
1451
+ // Options change tracking
1452
+ this.lastAppliedOptions = null;
1453
+ // Expression result tracking
1454
+ this.lastExpressionResults = new Map();
1455
+ // Buffer for context changes that happen before initial render completes
1456
+ this.preRenderContextQueue = new Set();
723
1457
  effect(async () => {
724
1458
  const changed = this.contextService.changeEvent();
725
1459
  // Don't trigger re-render during initial setup
726
1460
  if (!this.hasInitialRender) {
1461
+ if (changed.path) {
1462
+ this.preRenderContextQueue.add(changed.path);
1463
+ // console.log(`📝 [${this.node().type}] Buffered pre-render context change: ${changed.path}`);
1464
+ }
727
1465
  return;
728
1466
  }
729
- if ((await this.updateOptionsBasedOnContext()) > 0) {
730
- this.applyOptions();
731
- }
732
- if (this.checkFormulaForUpdate(this.node().formula, changed.path)) {
733
- await this.updateValueBasedOnFormula();
734
- }
735
- //
736
- if (changed.path) {
737
- this.onContextChanged.next({ path: changed.path });
1467
+ // CRITICAL PERFORMANCE FIX: Only respond to relevant context changes
1468
+ if (changed.path && this.isRelevantContextChange(changed.path)) {
1469
+ // console.log(`🎯 [${this.node().type}] Context change detected: ${changed.path}`);
1470
+ this.queueContextUpdate(changed.path);
738
1471
  }
739
1472
  });
740
1473
  this.builderService.onRefresh.pipe(this.unsubscriber.takeUntilDestroy).subscribe(async () => {
741
- if ((await this.updateOptionsBasedOnContext()) > 0) {
742
- this.applyOptions();
1474
+ await this.processBatchedUpdates();
1475
+ });
1476
+ }
1477
+ //#region ---- Expression Caching Methods ----
1478
+ getCachedExpressionResult(expressionKey) {
1479
+ const cached = this.expressionCache.get(expressionKey);
1480
+ if (cached && performance.now() - cached.timestamp < this.EXPRESSION_CACHE_TTL) {
1481
+ // console.log(`💾 [${this.node().type}] Using cached expression result for '${expressionKey}'`);
1482
+ return cached.value;
1483
+ }
1484
+ return null;
1485
+ }
1486
+ setCachedExpressionResult(expressionKey, value) {
1487
+ this.expressionCache.set(expressionKey, {
1488
+ value,
1489
+ timestamp: performance.now(),
1490
+ });
1491
+ }
1492
+ clearExpressionCache() {
1493
+ this.expressionCache.clear();
1494
+ }
1495
+ isPathAffectingExpressions(changedPath) {
1496
+ // console.log(
1497
+ // `🔍 [${this.node().type}] Checking if path '${changedPath}' affects expressions. Expression count: ${this.expressionEvaluators.size}`,
1498
+ // );
1499
+ // If widget has no expressions, no need to clear cache
1500
+ if (this.expressionEvaluators.size === 0) {
1501
+ // console.log(`🔍 [${this.node().type}] Path '${changedPath}' - no expressions, keeping cache`);
1502
+ return false;
1503
+ }
1504
+ // Use the same logic as hasExpressionDependency to check for actual dependencies
1505
+ if (this.hasExpressionDependency(changedPath)) {
1506
+ // console.log(`🔍 [${this.node().type}] Path '${changedPath}' affects expressions - clearing cache`);
1507
+ return true;
1508
+ }
1509
+ // console.log(`🔍 [${this.node().type}] Path '${changedPath}' does not affect expressions - keeping cache`);
1510
+ return false;
1511
+ }
1512
+ //#endregion
1513
+ //#region ---- Context Batching Methods ----
1514
+ queueContextUpdate(path) {
1515
+ if (path) {
1516
+ // console.log(`🔄 [${this.node().type}] Queueing context update for path: ${path}`);
1517
+ this.contextUpdateQueue.add(path);
1518
+ // Clear existing timeout
1519
+ if (this.contextUpdateTimeout) {
1520
+ clearTimeout(this.contextUpdateTimeout);
743
1521
  }
1522
+ // Debounce updates
1523
+ this.contextUpdateTimeout = setTimeout(() => {
1524
+ // console.log(`⚡ [${this.node().type}] Processing batched updates for ${this.contextUpdateQueue.size} paths`);
1525
+ this.processBatchedUpdates();
1526
+ }, this.CONTEXT_UPDATE_DEBOUNCE_MS);
1527
+ }
1528
+ }
1529
+ async processBatchedUpdates() {
1530
+ if (this.contextUpdateQueue.size === 0)
1531
+ return;
1532
+ const startTime = performance.now();
1533
+ const paths = Array.from(this.contextUpdateQueue);
1534
+ this.contextUpdateQueue.clear();
1535
+ // console.log(`📊 [${this.node().type}] Processing ${paths.length} paths:`, paths);
1536
+ // Clear expression cache only if changed paths affect this widget's expressions
1537
+ const shouldClearCache = paths.some((path) => this.isPathAffectingExpressions(path));
1538
+ if (shouldClearCache) {
1539
+ // console.log(`🗑️ [${this.node().type}] Clearing expression cache due to expression-affecting path change`);
1540
+ this.clearExpressionCache();
1541
+ }
1542
+ // Process updates in batches
1543
+ const optionsStartTime = performance.now();
1544
+ const hasOptionsUpdate = await this.updateOptionsBasedOnContext();
1545
+ const optionsTime = performance.now() - optionsStartTime;
1546
+ if (typeof hasOptionsUpdate === 'number' && hasOptionsUpdate > 0) {
1547
+ // console.log(`🔧 [${this.node().type}] Options updated (${optionsTime.toFixed(2)}ms)`);
1548
+ this.applyOptions();
1549
+ }
1550
+ // Check formulas for any of the changed paths
1551
+ const formulaStartTime = performance.now();
1552
+ const formulaNeedsUpdate = paths.some((path) => this.checkFormulaForUpdate(this.node().formula, path));
1553
+ if (formulaNeedsUpdate) {
1554
+ // console.log(`🧮 [${this.node().type}] Formula needs update`);
1555
+ await this.updateValueBasedOnFormula();
1556
+ }
1557
+ const formulaTime = performance.now() - formulaStartTime;
1558
+ // Emit context changes
1559
+ paths.forEach((path) => {
1560
+ this.onContextChanged.next({ path });
744
1561
  });
1562
+ const totalTime = performance.now() - startTime;
1563
+ // console.log(
1564
+ // `✅ [${this.node().type}] Batch processing completed in ${totalTime.toFixed(2)}ms (options: ${optionsTime.toFixed(2)}ms, formula: ${formulaTime.toFixed(2)}ms)`,
1565
+ // );
1566
+ }
1567
+ //#endregion
1568
+ //#region ---- Context Relevance Filtering ----
1569
+ isRelevantContextChange(changedPath) {
1570
+ const node = this.node();
1571
+ // 1. Direct path match - widget's own field
1572
+ if (node.path === changedPath) {
1573
+ return true;
1574
+ }
1575
+ // 2. Parent path match - widget is inside the changed container
1576
+ if (node.path && changedPath.startsWith(node.path + '.')) {
1577
+ return true;
1578
+ }
1579
+ // 3. Child path match - changed field is inside this widget's container
1580
+ if (node.path && node.path.startsWith(changedPath + '.')) {
1581
+ return true;
1582
+ }
1583
+ // 4. Expression dependency check - if widget has expressions that depend on this path
1584
+ if (this.hasExpressionDependency(changedPath)) {
1585
+ return true;
1586
+ }
1587
+ // 5. Formula dependency check - if widget's formula depends on this path
1588
+ if (node.formula && this.checkFormulaForUpdate(node.formula, changedPath)) {
1589
+ return true;
1590
+ }
1591
+ // 6. Trigger dependency check - if widget has triggers that depend on this path
1592
+ if (this.hasTriggerDependency(changedPath)) {
1593
+ return true;
1594
+ }
1595
+ return false;
1596
+ }
1597
+ hasExpressionDependency(changedPath) {
1598
+ // Check if any cached expressions depend on the changed path
1599
+ for (const [path, evaluator] of this.expressionEvaluators) {
1600
+ // Check if the expression path itself contains the changed path
1601
+ if (path.includes(changedPath)) {
1602
+ return true;
1603
+ }
1604
+ // Parse the actual expression content to check for context.eval() calls
1605
+ // We need to get the original expression string to analyze it
1606
+ const node = this.node();
1607
+ const expressionValue = this.getExpressionValueFromNode(node, path);
1608
+ if (expressionValue && typeof expressionValue === 'string') {
1609
+ // Look for context.eval() calls that reference the changed path
1610
+ const contextEvalRegex = /context\.eval\(['"]([^'\"]+)['"]\)/g;
1611
+ let match;
1612
+ while ((match = contextEvalRegex.exec(expressionValue)) !== null) {
1613
+ const evalPath = match[1];
1614
+ // Normalize Id-suffixed segments to dot-id form (e.g., 'typeId' -> 'type.id', 'party.typeId' -> 'party.type.id')
1615
+ const normalizePath = (p) => {
1616
+ if (!p)
1617
+ return p;
1618
+ const parts = p.split('.');
1619
+ const last = parts[parts.length - 1];
1620
+ if (last && last.endsWith('Id')) {
1621
+ parts.splice(parts.length - 1, 1, last.slice(0, -2), 'id');
1622
+ }
1623
+ return parts.join('.');
1624
+ };
1625
+ const isSegmentSuffix = (a, b) => {
1626
+ if (!a || !b)
1627
+ return false;
1628
+ const pa = a.split('.');
1629
+ const pb = b.split('.');
1630
+ if (pb.length > pa.length)
1631
+ return false;
1632
+ for (let i = 1; i <= pb.length; i++) {
1633
+ if (pa[pa.length - i] !== pb[pb.length - i])
1634
+ return false;
1635
+ }
1636
+ return true;
1637
+ };
1638
+ const evalNorm = normalizePath(evalPath);
1639
+ const changedNorm = normalizePath(changedPath);
1640
+ // Debug log for dependency check
1641
+ // console.log(
1642
+ // `🧭 [${this.node().type}] dep-check expr='${path}', changed='${changedPath}', eval='${evalPath}', evalNorm='${evalNorm}', changedNorm='${changedNorm}'`,
1643
+ // );
1644
+ // Generic direct and hierarchical dependency checks (raw and normalized)
1645
+ const rawMatch = evalPath === changedPath ||
1646
+ evalPath.startsWith(changedPath + '.') ||
1647
+ changedPath.startsWith(evalPath + '.') ||
1648
+ isSegmentSuffix(evalPath, changedPath) ||
1649
+ isSegmentSuffix(changedPath, evalPath);
1650
+ const normMatch = evalNorm === changedNorm ||
1651
+ evalNorm.startsWith(changedNorm + '.') ||
1652
+ changedNorm.startsWith(evalNorm + '.') ||
1653
+ isSegmentSuffix(evalNorm, changedNorm) ||
1654
+ isSegmentSuffix(changedNorm, evalNorm);
1655
+ if (rawMatch || normMatch) {
1656
+ // console.log(
1657
+ // `🔍 [${this.node().type}] Expression '${path}' depends on '${changedPath}' via context.eval('${evalPath}') (generic match)`,
1658
+ // );
1659
+ return true;
1660
+ }
1661
+ // Check for path aliases/mappings (e.g., typeId.id <-> type.id)
1662
+ if (this.isPathAlias(evalPath, changedPath)) {
1663
+ // console.log(
1664
+ // `🔍 [${this.node().type}] Expression '${path}' depends on '${changedPath}' via context.eval('${evalPath}') (path alias)`,
1665
+ // );
1666
+ return true;
1667
+ }
1668
+ }
1669
+ }
1670
+ }
1671
+ return false;
1672
+ }
1673
+ isPathAlias(evalPath, changedPath) {
1674
+ // Dynamic path alias detection based on 'Id' suffix pattern
1675
+ // Examples: typeId.id <-> type.id, categoryId.name <-> category.name
1676
+ // Check if evalPath ends with 'Id' and has a property
1677
+ if (evalPath.endsWith('Id') && evalPath.includes('.')) {
1678
+ const basePath = evalPath.substring(0, evalPath.lastIndexOf('Id'));
1679
+ const property = evalPath.substring(evalPath.lastIndexOf('.') + 1);
1680
+ const mappedPath = `${basePath}.${property}`;
1681
+ if (changedPath === mappedPath) {
1682
+ // console.log(`🔍 [${this.node().type}] Path alias detected: '${evalPath}' <-> '${changedPath}'`);
1683
+ return true;
1684
+ }
1685
+ }
1686
+ // Check if changedPath ends with 'Id' and has a property
1687
+ if (changedPath.endsWith('Id') && changedPath.includes('.')) {
1688
+ const basePath = changedPath.substring(0, changedPath.lastIndexOf('Id'));
1689
+ const property = changedPath.substring(changedPath.lastIndexOf('.') + 1);
1690
+ const mappedPath = `${basePath}.${property}`;
1691
+ if (evalPath === mappedPath) {
1692
+ // console.log(`🔍 [${this.node().type}] Path alias detected: '${evalPath}' <-> '${changedPath}'`);
1693
+ return true;
1694
+ }
1695
+ }
1696
+ // Check for direct 'Id' suffix mapping (e.g., typeId <-> type.id)
1697
+ if (evalPath.endsWith('Id') && !evalPath.includes('.')) {
1698
+ const basePath = evalPath.substring(0, evalPath.lastIndexOf('Id'));
1699
+ const mappedPath = `${basePath}.id`;
1700
+ if (changedPath === mappedPath) {
1701
+ // console.log(`🔍 [${this.node().type}] Path alias detected: '${evalPath}' <-> '${changedPath}'`);
1702
+ return true;
1703
+ }
1704
+ }
1705
+ if (changedPath.endsWith('Id') && !changedPath.includes('.')) {
1706
+ const basePath = changedPath.substring(0, changedPath.lastIndexOf('Id'));
1707
+ const mappedPath = `${basePath}.id`;
1708
+ if (evalPath === mappedPath) {
1709
+ // console.log(`🔍 [${this.node().type}] Path alias detected: '${evalPath}' <-> '${changedPath}'`);
1710
+ return true;
1711
+ }
1712
+ }
1713
+ return false;
745
1714
  }
1715
+ getExpressionValueFromNode(node, path) {
1716
+ try {
1717
+ // Navigate through the node structure to find the expression value
1718
+ const pathParts = path.split('.');
1719
+ let current = node.options || {};
1720
+ // Navigate through the path parts
1721
+ for (const part of pathParts) {
1722
+ if (current && typeof current === 'object' && part in current) {
1723
+ current = current[part];
1724
+ }
1725
+ else {
1726
+ return null;
1727
+ }
1728
+ }
1729
+ return typeof current === 'string' ? current : null;
1730
+ }
1731
+ catch (error) {
1732
+ // console.error('Error extracting expression value from node:', error);
1733
+ return null;
1734
+ }
1735
+ }
1736
+ hasTriggerDependency(changedPath) {
1737
+ const node = this.node();
1738
+ const triggers = node.triggers || node.options?.['triggers'] || this.mergedOptions()?.triggers;
1739
+ if (!triggers)
1740
+ return false;
1741
+ // Check if any trigger event depends on the changed path
1742
+ for (const trigger of triggers) {
1743
+ if (trigger.event && trigger.event.includes(changedPath)) {
1744
+ return true;
1745
+ }
1746
+ }
1747
+ return false;
1748
+ }
1749
+ //#endregion
1750
+ // Removed visibility detection methods - not needed for current implementation
746
1751
  // Detect input changes
747
1752
  ngOnChanges(changes) {
748
1753
  if (changes['mode'] || changes['node']) {
@@ -768,6 +1773,9 @@ class AXPWidgetRendererDirective {
768
1773
  if (this.renderTimeoutId) {
769
1774
  clearTimeout(this.renderTimeoutId);
770
1775
  }
1776
+ if (this.contextUpdateTimeout) {
1777
+ clearTimeout(this.contextUpdateTimeout);
1778
+ }
771
1779
  if (this.componentRef) {
772
1780
  this.componentRef.destroy();
773
1781
  }
@@ -786,8 +1794,10 @@ class AXPWidgetRendererDirective {
786
1794
  //
787
1795
  const widget = this.widgetRegistery.resolve(this.node().type);
788
1796
  //
789
- const propertiesToProcess = [...(widget?.properties ?? []), ...(widget?.components[this.mode()]?.properties ?? [])]
790
- ?.filter((c) => c.schema.defaultValue != null);
1797
+ const propertiesToProcess = [
1798
+ ...(widget?.properties ?? []),
1799
+ ...(widget?.components[this.mode()]?.properties ?? []),
1800
+ ]?.filter((c) => c.schema.defaultValue != null);
791
1801
  // Process default values (evaluate expressions if needed)
792
1802
  const props = {};
793
1803
  for (const property of propertiesToProcess) {
@@ -799,7 +1809,7 @@ class AXPWidgetRendererDirective {
799
1809
  props[property.name] = evaluatedValue;
800
1810
  }
801
1811
  catch (error) {
802
- console.error(`Error evaluating default value expression for property ${property.name}:`, error);
1812
+ // console.error(`Error evaluating default value expression for property ${property.name}:`, error);
803
1813
  props[property.name] = cloneDeep(defaultValue); // Fallback to original value
804
1814
  }
805
1815
  }
@@ -810,6 +1820,9 @@ class AXPWidgetRendererDirective {
810
1820
  }
811
1821
  //
812
1822
  this.mergedOptions.set(merge(props, widget?.options, this.node().options) || {});
1823
+ this.expressionEvaluators.clear();
1824
+ // Register expressions from widget defaults and node options to cover related-entity cases
1825
+ this.preprocessAndInitialOptions(cloneDeep(widget?.options));
813
1826
  this.preprocessAndInitialOptions(cloneDeep(this.node().options));
814
1827
  await this.updateOptionsBasedOnContext();
815
1828
  //
@@ -840,7 +1853,7 @@ class AXPWidgetRendererDirective {
840
1853
  //
841
1854
  const com = await widget?.components[this.mode()]?.component();
842
1855
  if (!com) {
843
- console.error(`${this.node().type} widget component not found with mode: ${this.mode()}`);
1856
+ // console.error(`${this.node().type} widget component not found with mode: ${this.mode()}`);
844
1857
  return;
845
1858
  }
846
1859
  this.componentRef = this.viewContainerRef.createComponent(com, { injector: token });
@@ -862,9 +1875,24 @@ class AXPWidgetRendererDirective {
862
1875
  loadingRef.destroy();
863
1876
  // Mark that initial render is complete
864
1877
  this.hasInitialRender = true;
1878
+ // Re-evaluate expressions after initial render to catch late-arriving related context
1879
+ if (this.expressionEvaluators.size > 0) {
1880
+ // console.log(`🔄 [${this.node().type}] Re-evaluating expressions after initial render`);
1881
+ await this.updateOptionsBasedOnContext();
1882
+ this.applyOptions();
1883
+ }
1884
+ // Process any buffered pre-render context changes now that the component is ready
1885
+ if (this.preRenderContextQueue.size > 0) {
1886
+ // console.log(
1887
+ // `🚀 [${this.node().type}] Processing ${this.preRenderContextQueue.size} buffered pre-render changes`,
1888
+ // );
1889
+ this.preRenderContextQueue.forEach((p) => this.contextUpdateQueue.add(p));
1890
+ this.preRenderContextQueue.clear();
1891
+ await this.processBatchedUpdates();
1892
+ }
865
1893
  }
866
1894
  catch (error) {
867
- console.error('Error loading component:', error);
1895
+ // console.error('Error loading component:', error);
868
1896
  }
869
1897
  finally {
870
1898
  this.isLoading.set(false);
@@ -873,9 +1901,26 @@ class AXPWidgetRendererDirective {
873
1901
  applyOptions() {
874
1902
  if (!this.instance)
875
1903
  return;
876
- this._options.update((val) => ({ ...val, ...this.mergedOptions() }));
877
- this.instance.setOptions(this.mergedOptions());
1904
+ const currentOptions = this.mergedOptions();
1905
+ // Check if options have actually changed
1906
+ if (this.hasOptionsChanged(currentOptions)) {
1907
+ // console.log('applyOptions', this.node().path, '- options changed');
1908
+ this._options.update((val) => ({ ...val, ...currentOptions }));
1909
+ this.instance.setOptions(currentOptions);
1910
+ this.lastAppliedOptions = cloneDeep(currentOptions); // Deep clone using Lodash
1911
+ }
1912
+ else {
1913
+ // console.log('applyOptions', this.node().path, '- no changes, skipping');
1914
+ }
878
1915
  }
1916
+ hasOptionsChanged(newOptions) {
1917
+ if (!this.lastAppliedOptions) {
1918
+ return true; // First time, always apply
1919
+ }
1920
+ // Deep comparison of options using Lodash isEqual
1921
+ return !isEqual(newOptions, this.lastAppliedOptions);
1922
+ }
1923
+ // Removed deepCloneValue method - now using Lodash cloneDeep
879
1924
  checkFormulaForUpdate(formula, path) {
880
1925
  if (formula) {
881
1926
  const regex = /context\.eval\('([^']+)'\)/g;
@@ -893,7 +1938,7 @@ class AXPWidgetRendererDirective {
893
1938
  Object.entries(obj).forEach(([key, value]) => {
894
1939
  const currentPath = pathPrefix ? `${pathPrefix}.${key}` : key;
895
1940
  // CRITICAL FIX: Skip trigger actions during options processing
896
- //
1941
+ //
897
1942
  // PROBLEM: Trigger actions were being evaluated immediately during widget setup/options processing,
898
1943
  // causing them to execute before the actual trigger event occurred. This meant triggers would fire
899
1944
  // during initialization instead of when the specified context path actually changed.
@@ -934,24 +1979,64 @@ class AXPWidgetRendererDirective {
934
1979
  });
935
1980
  }
936
1981
  async updateOptionsBasedOnContext() {
1982
+ // Early return if no expressions to evaluate
1983
+ if (this.expressionEvaluators.size === 0) {
1984
+ return 0;
1985
+ }
1986
+ // console.log(`🔍 [${this.node().type}] Evaluating ${this.expressionEvaluators.size} expressions`);
937
1987
  const updatePromises = Array.from(this.expressionEvaluators).map(async ([path, evaluator]) => {
1988
+ // Check cache first
1989
+ const cachedValue = this.getCachedExpressionResult(path);
1990
+ if (cachedValue !== null) {
1991
+ // console.log(`💾 [${this.node().type}] Using cached expression result for '${path}'`);
1992
+ return { path, newValue: cachedValue, fromCache: true };
1993
+ }
1994
+ // Evaluate expression if not cached
1995
+ const evalStartTime = performance.now();
938
1996
  const newValue = await evaluator();
939
- return { path, newValue };
1997
+ const evalTime = performance.now() - evalStartTime;
1998
+ // Check if result has actually changed using Lodash isEqual
1999
+ const lastValue = this.lastExpressionResults.get(path);
2000
+ const hasChanged = !isEqual(newValue, lastValue);
2001
+ if (hasChanged) {
2002
+ // console.log(
2003
+ // `📝 [${this.node().type}] Expression '${path}' evaluated in ${evalTime.toFixed(2)}ms - value changed`,
2004
+ // );
2005
+ // Cache the result and track it
2006
+ this.setCachedExpressionResult(path, newValue);
2007
+ this.lastExpressionResults.set(path, cloneDeep(newValue));
2008
+ return { path, newValue, fromCache: false, hasChanged: true };
2009
+ }
2010
+ else {
2011
+ // console.log(
2012
+ // `📝 [${this.node().type}] Expression '${path}' evaluated in ${evalTime.toFixed(2)}ms - value unchanged, skipping update`,
2013
+ // );
2014
+ // Cache the result but don't update
2015
+ this.setCachedExpressionResult(path, newValue);
2016
+ this.lastExpressionResults.set(path, cloneDeep(newValue));
2017
+ return { path, newValue, fromCache: false, hasChanged: false };
2018
+ }
940
2019
  });
941
2020
  // Wait for all evaluators to complete
942
2021
  const updates = await Promise.all(updatePromises);
943
- // Apply updates to mergedOptions
944
- if (updates.length > 0) {
2022
+ // Filter updates to only include those that have actually changed
2023
+ const changedUpdates = updates.filter((update) => update.hasChanged !== false);
2024
+ // Apply updates to mergedOptions only for changed values
2025
+ if (changedUpdates.length > 0) {
945
2026
  this.mergedOptions.update((o) => {
946
2027
  const updatedOptions = { ...o };
947
- updates.forEach(({ path, newValue }) => {
948
- // Set the new value in the updatedOptions object by path
949
- set(updatedOptions, path, newValue); // Assuming 'set' can handle paths like 'property.subproperty'
2028
+ changedUpdates.forEach(({ path, newValue }) => {
2029
+ set(updatedOptions, path, newValue);
950
2030
  });
951
2031
  return updatedOptions;
952
2032
  });
953
2033
  }
954
- return updates.length;
2034
+ const cacheHits = updates.filter((update) => update.fromCache).length;
2035
+ const skippedUpdates = updates.length - changedUpdates.length;
2036
+ // console.log(
2037
+ // `📋 [${this.node().type}] Applied ${changedUpdates.length} expression updates (${cacheHits} cache hits, ${skippedUpdates} skipped)`,
2038
+ // );
2039
+ return changedUpdates.length;
955
2040
  }
956
2041
  async updateValueBasedOnFormula() {
957
2042
  if (this.node().formula) {
@@ -965,7 +2050,7 @@ class AXPWidgetRendererDirective {
965
2050
  return await this.expressionEvaluator.evaluate(templateExpression, scope);
966
2051
  }
967
2052
  catch (error) {
968
- console.error('Error evaluating expression:', error);
2053
+ // console.error('Error evaluating expression:', error);
969
2054
  return false;
970
2055
  }
971
2056
  }
@@ -1101,7 +2186,7 @@ class AXPWidgetRendererDirective {
1101
2186
  }
1102
2187
  }
1103
2188
  catch (error) {
1104
- console.error('Error assigning trigger:', error);
2189
+ // console.error('Error assigning trigger:', error);
1105
2190
  }
1106
2191
  }
1107
2192
  }
@@ -1118,7 +2203,7 @@ class AXPWidgetRendererDirective {
1118
2203
  }
1119
2204
  }
1120
2205
  catch (error) {
1121
- console.error('Error evaluating trigger expression:', error);
2206
+ // console.error('Error evaluating trigger expression:', error);
1122
2207
  return null;
1123
2208
  }
1124
2209
  }
@@ -1128,17 +2213,17 @@ class AXPWidgetRendererDirective {
1128
2213
  await this.expressionEvaluator.evaluate(templateExpression, scope);
1129
2214
  }
1130
2215
  catch (error) {
1131
- console.error('Error evaluating action expression:', templateExpression, error);
2216
+ // console.error('Error evaluating action expression:', templateExpression, error);
1132
2217
  }
1133
2218
  }
1134
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetRendererDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1135
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.6", 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: [
2219
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetRendererDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2220
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.8", 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: [
1136
2221
  {
1137
2222
  provide: AXUnsubscriber,
1138
2223
  },
1139
2224
  ], exportAs: ["widgetRenderer"], usesOnChanges: true, ngImport: i0 }); }
1140
2225
  }
1141
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPWidgetRendererDirective, decorators: [{
2226
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPWidgetRendererDirective, decorators: [{
1142
2227
  type: Directive,
1143
2228
  args: [{
1144
2229
  selector: '[axp-widget-renderer]',
@@ -1180,386 +2265,254 @@ class AXPLayoutBuilderModule {
1180
2265
  await Promise.all(config?.widgets?.map((w) => Promise.resolve(registry.register(w))) || []);
1181
2266
  await Promise.all(config?.extendedWidgets?.map((ew) => Promise.resolve(registry.extend(ew.parentName, ew.widget))) || []);
1182
2267
  },
1183
- deps: [AXPWidgetRegistryService],
1184
- multi: true,
1185
- },
1186
- ],
1187
- };
1188
- }
1189
- /**
1190
- * @ignore
1191
- */
1192
- constructor(instances) {
1193
- instances?.forEach((f) => {
1194
- f();
1195
- });
1196
- }
1197
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutBuilderModule, deps: [{ token: 'AXPLayoutBuilderModuleFactory', optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
1198
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutBuilderModule, declarations: [AXPWidgetContainerComponent, AXPWidgetColumnRendererComponent, AXPWidgetRendererDirective], imports: [CommonModule, PortalModule, AXSkeletonModule, CommonModule], exports: [AXPWidgetContainerComponent, AXPWidgetColumnRendererComponent, AXPWidgetRendererDirective] }); }
1199
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutBuilderModule, imports: [CommonModule, PortalModule, AXSkeletonModule, CommonModule] }); }
1200
- }
1201
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutBuilderModule, decorators: [{
1202
- type: NgModule,
1203
- args: [{
1204
- imports: [CommonModule, PortalModule, AXSkeletonModule, CommonModule],
1205
- exports: [...COMPONENTS],
1206
- declarations: [...COMPONENTS],
1207
- }]
1208
- }], ctorParameters: () => [{ type: undefined, decorators: [{
1209
- type: Optional
1210
- }, {
1211
- type: Inject,
1212
- args: ['AXPLayoutBuilderModuleFactory']
1213
- }] }] });
1214
-
1215
- const AXP_WIDGETS_LAYOUT_CATEGORY = {
1216
- name: 'layout',
1217
- order: 1,
1218
- title: 'Layout',
1219
- };
1220
- const AXP_WIDGETS_EDITOR_CATEGORY = {
1221
- name: 'editor',
1222
- order: 2,
1223
- title: 'Editors',
1224
- };
1225
- const AXP_WIDGETS_ACTION_CATEGORY = {
1226
- name: 'action',
1227
- order: 3,
1228
- title: 'Action',
1229
- };
1230
- const AXP_WIDGETS_ADVANCE_CATEGORY = {
1231
- name: 'advance',
1232
- order: 4,
1233
- title: 'Advance',
1234
- };
1235
- const AXP_WIDGETS_CATEGORIES = [
1236
- AXP_WIDGETS_LAYOUT_CATEGORY,
1237
- AXP_WIDGETS_EDITOR_CATEGORY,
1238
- AXP_WIDGETS_ACTION_CATEGORY,
1239
- AXP_WIDGETS_ADVANCE_CATEGORY,
1240
- ];
1241
-
1242
- var AXPWidgetGroupEnum;
1243
- (function (AXPWidgetGroupEnum) {
1244
- AXPWidgetGroupEnum["FormElement"] = "form-element";
1245
- AXPWidgetGroupEnum["DashboardWidget"] = "dashboard-widget";
1246
- AXPWidgetGroupEnum["FormTemplate"] = "form-template";
1247
- AXPWidgetGroupEnum["PropertyEditor"] = "property-editor";
1248
- AXPWidgetGroupEnum["MetaData"] = "meta-data";
1249
- AXPWidgetGroupEnum["SettingWidget"] = "setting-widget";
1250
- AXPWidgetGroupEnum["EntityWidget"] = "entity-widget";
1251
- })(AXPWidgetGroupEnum || (AXPWidgetGroupEnum = {}));
1252
-
1253
- class AXPBaseWidgetComponent extends AXPLayoutElement {
1254
- constructor() {
1255
- super(...arguments);
1256
- this.token = inject(AXP_WIDGET_TOKEN);
1257
- this.host = inject(ElementRef).nativeElement;
1258
- this.layoutService = inject(AXPLayoutBuilderService);
1259
- this.contextService = inject(AXPLayoutBuilderContextStore);
1260
- this.config = this.token.config;
1261
- this.node = this.token.node;
1262
- this.name = this.token.node.name;
1263
- this._options = signal(this.token.options ?? {}, ...(ngDevMode ? [{ debugName: "_options" }] : []));
1264
- this.options = this._options.asReadonly();
1265
- this.onOptionsChanged = new Subject();
1266
- this._status = signal(AXPWidgetStatus.Rendering, ...(ngDevMode ? [{ debugName: "_status" }] : []));
1267
- this.status = this._status.asReadonly();
1268
- this.onStatusChanged = new BehaviorSubject(this._status());
1269
- this.#statusEffect = effect(() => {
1270
- this.onStatusChanged.next(this.status());
1271
- }, ...(ngDevMode ? [{ debugName: "#statusEffect" }] : []));
1272
- this.isBusy = computed(() => [AXPWidgetStatus.Rendering, AXPWidgetStatus.Processing].includes(this.status()), ...(ngDevMode ? [{ debugName: "isBusy" }] : []));
1273
- this._children = signal(this.token.node.children ?? [], ...(ngDevMode ? [{ debugName: "_children" }] : []));
1274
- this.children = this._children.asReadonly();
1275
- }
1276
- get id() {
1277
- return this._id;
1278
- }
1279
- #statusEffect;
1280
- outputs() {
1281
- return [];
1282
- }
1283
- ngOnInit() {
1284
- if (get(this.node, '__meta__.added')) {
1285
- this.onAdded();
1286
- }
1287
- this.setStatus(AXPWidgetStatus.Rendered);
1288
- }
1289
- setStatus(status) {
1290
- this._status.set(status);
1291
- this.layoutService.updateStatus();
1292
- }
1293
- setOptions(values) {
1294
- this._options.set({ ...this.options(), ...values });
1295
- this.onOptionsChanged.next({ sender: this });
1296
- }
1297
- output(name) {
1298
- const outputs = this.outputs().map((c) => (typeof c == 'string' ? { name: c, value: c } : c));
1299
- if (outputs.some((c) => c.name == name)) {
1300
- const opt = get(this, name);
1301
- if (typeof opt == 'function') {
1302
- return opt();
1303
- }
1304
- return opt;
1305
- }
1306
- return null;
1307
- }
1308
- call(name, ...args) {
1309
- const fn = get(this, name);
1310
- if (fn && typeof fn == 'function') {
1311
- fn.bind(this)(...args);
1312
- }
1313
- }
1314
- setChildren(children) {
1315
- this._children.set([...children]);
1316
- }
1317
- onAdded() { }
1318
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPBaseWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1319
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPBaseWidgetComponent }); }
1320
- }
1321
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPBaseWidgetComponent, decorators: [{
1322
- type: Injectable
1323
- }] });
1324
- class AXPLayoutWidgetComponent extends AXPBaseWidgetComponent {
1325
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1326
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutWidgetComponent }); }
1327
- }
1328
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutWidgetComponent, decorators: [{
1329
- type: Injectable
1330
- }] });
1331
- class AXPValueWidgetComponent extends AXPLayoutWidgetComponent {
1332
- constructor() {
1333
- super(...arguments);
1334
- this.path = this.token.node.path;
1335
- this.defaultValue = this.token.defaultValue ?? this.token.node.defaultValue;
1336
- this._isValueWidget = false;
1337
- this.isValueWidget = () => this._isValueWidget;
1338
- this.onValueChanged = new Subject();
1339
- this.fullPath = signal(null, ...(ngDevMode ? [{ debugName: "fullPath" }] : []));
1340
- this.parentPath = signal(null, ...(ngDevMode ? [{ debugName: "parentPath" }] : []));
1341
- this.getValue = computed(() => {
1342
- return this.fullPath() ? this.extractValue(this.fullPath()) : null;
1343
- }, ...(ngDevMode ? [{ debugName: "getValue", equal: isEqual }] : [{ equal: isEqual }]));
1344
- this.validationRules = computed(() => {
1345
- const validationsRaw = this.options()['validations'];
1346
- if (validationsRaw == null) {
1347
- return [];
1348
- }
1349
- return Object.values(this.options()['validations'])
1350
- .filter((c) => c != null)
1351
- .map((c) => ({
1352
- rule: c.rule,
1353
- message: c.message,
1354
- options: c.options,
1355
- }));
1356
- }, ...(ngDevMode ? [{ debugName: "validationRules" }] : []));
2268
+ deps: [AXPWidgetRegistryService],
2269
+ multi: true,
2270
+ },
2271
+ ],
2272
+ };
1357
2273
  }
1358
- ngOnInit() {
1359
- this._isValueWidget = this.config.properties?.some((c) => c.name == 'path') ?? false;
1360
- if (this.isValueWidget()) {
1361
- this.detectFullPath();
1362
- if (!isNil(this.defaultValue) && isNil(this.getValue())) {
1363
- this.setValue(this.defaultValue);
1364
- }
1365
- }
1366
- //
1367
- super.ngOnInit();
2274
+ /**
2275
+ * @ignore
2276
+ */
2277
+ constructor(instances) {
2278
+ instances?.forEach((f) => {
2279
+ f();
2280
+ });
1368
2281
  }
1369
- extractValue(path) {
1370
- const rawValue = this.contextService.getValue(path);
1371
- if (this.node.valueTransforms?.getter) {
1372
- return this.node.valueTransforms?.getter(rawValue);
2282
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderModule, deps: [{ token: 'AXPLayoutBuilderModuleFactory', optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
2283
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderModule, declarations: [AXPWidgetContainerComponent, AXPWidgetColumnRendererComponent, AXPWidgetRendererDirective], imports: [CommonModule, PortalModule, AXSkeletonModule, CommonModule, AXTranslationModule], exports: [AXPWidgetContainerComponent, AXPWidgetColumnRendererComponent, AXPWidgetRendererDirective] }); }
2284
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderModule, imports: [CommonModule, PortalModule, AXSkeletonModule, CommonModule, AXTranslationModule] }); }
2285
+ }
2286
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: AXPLayoutBuilderModule, decorators: [{
2287
+ type: NgModule,
2288
+ args: [{
2289
+ imports: [CommonModule, PortalModule, AXSkeletonModule, CommonModule, AXTranslationModule],
2290
+ exports: [...COMPONENTS],
2291
+ declarations: [...COMPONENTS],
2292
+ }]
2293
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
2294
+ type: Optional
2295
+ }, {
2296
+ type: Inject,
2297
+ args: ['AXPLayoutBuilderModuleFactory']
2298
+ }] }] });
2299
+
2300
+ class AXPPropertyEditorHelper {
2301
+ static expandShorthand(values) {
2302
+ switch (values.length) {
2303
+ case 1:
2304
+ return [values[0], values[0], values[0], values[0]];
2305
+ case 2:
2306
+ return [values[0], values[1], values[0], values[1]];
2307
+ case 3:
2308
+ return [values[0], values[1], values[2], values[1]];
2309
+ case 4:
2310
+ return values;
2311
+ default:
2312
+ throw new Error(`Invalid shorthand value count. Input: ${values}`);
1373
2313
  }
1374
- return rawValue;
1375
2314
  }
1376
- setValue(value) {
1377
- if (this.node.valueTransforms?.setter) {
1378
- value = this.node.valueTransforms?.setter(value);
1379
- }
1380
- const oldValue = this.getValue();
1381
- value = isUndefined(value) ? null : value;
1382
- if (isNil(value) && isNil(oldValue)) {
1383
- return;
2315
+ static condenseShorthand(values) {
2316
+ if (values.length !== 4) {
2317
+ throw new Error('Expected 4 values for condensation.');
1384
2318
  }
1385
- if (isEqual(oldValue, value)) {
1386
- return;
2319
+ if (values[0] === values[1] && values[1] === values[2] && values[2] === values[3]) {
2320
+ return `${values[0]}`;
1387
2321
  }
1388
- if (this.fullPath()) {
1389
- this.contextService.update(this.fullPath(), value);
1390
- this.onValueChanged.next({ sender: this });
2322
+ else if (values[0] === values[2] && values[1] === values[3]) {
2323
+ return `${values[0]} ${values[1]}`;
1391
2324
  }
1392
- }
1393
- detectFullPath() {
1394
- const sections = [];
1395
- const ids = [];
1396
- //
1397
- let parent = this;
1398
- //
1399
- while (parent) {
1400
- const isValueWidget = parent instanceof AXPValueWidgetComponent && parent.isValueWidget();
1401
- const valueParent = parent;
1402
- const path = valueParent.path ?? (isValueWidget ? valueParent.name : null);
1403
- const id = valueParent.name;
1404
- //
1405
- if (path) {
1406
- sections.push(path);
1407
- }
1408
- if (parent.index != null && isValueWidget) {
1409
- sections.push(`[${parent.index}]`);
1410
- }
1411
- if (id) {
1412
- ids.push(id);
1413
- if (parent.index != null) {
1414
- ids.push(`${parent.index}`);
1415
- }
1416
- }
1417
- parent = parent.parent;
2325
+ else if (values[1] === values[3]) {
2326
+ return `${values[0]} ${values[1]} ${values[2]}`;
1418
2327
  }
1419
- //
1420
- this.fullPath.set(sections.reverse().join('.'));
1421
- this.parentPath.set(sections.slice(0, sections.length - 1).join('.'));
1422
- this._id = this.name || this.parent ? ids.reverse().join('_') : null;
1423
- if (this._id) {
1424
- this.layoutService.registerWidget(this._id, this);
2328
+ else {
2329
+ return `${values[0]} ${values[1]} ${values[2]} ${values[3]}`;
1425
2330
  }
1426
2331
  }
1427
- handleValueChanged(e) {
1428
- if (e.isUserInteraction) {
1429
- this.setValue(e.value);
1430
- }
2332
+ static parseSides(input) {
2333
+ const values = this.expandShorthand(input.match(/(?:rgb\([^)]+\)|[^ ]+)/g)?.map((value) => value.trim()) || []);
2334
+ return { top: values[0], right: values[1], bottom: values[2], left: values[3] };
1431
2335
  }
1432
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPValueWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1433
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPValueWidgetComponent }); }
1434
- }
1435
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPValueWidgetComponent, decorators: [{
1436
- type: Injectable
1437
- }] });
1438
- class AXPDataListWidgetComponent extends AXPValueWidgetComponent {
1439
- constructor() {
1440
- super(...arguments);
1441
- this.dataService = inject(AXPDataSourceDefinitionProviderService);
1442
- this.textField = computed(() => this.options()['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
1443
- this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
1444
- this.dataSource = signal(convertArrayToDataSource([]), ...(ngDevMode ? [{ debugName: "dataSource" }] : []));
1445
- this.isReady = computed(() => {
1446
- const key = this.dataSource().config?.key;
1447
- const valueField = this.valueField();
1448
- const result = key == valueField;
1449
- return result;
1450
- }, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
1451
- this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
1452
- this.rf = effect(async () => {
1453
- const rawValue = this.options()['dataSource'];
1454
- // static datasource class
1455
- if (rawValue instanceof AXDataSource) {
1456
- this.dataSource.set(rawValue);
1457
- }
1458
- // static array datasource
1459
- else if (Array.isArray(rawValue)) {
1460
- const ds = new AXDataSource({
1461
- key: this.valueField(),
1462
- pageSize: 10,
1463
- load: async (e) => {
1464
- const raw = this.options()['dataSource'];
1465
- return {
1466
- items: raw,
1467
- total: raw.length,
1468
- };
1469
- },
1470
- byKey: (key) => {
1471
- const raw = this.options()['dataSource'];
1472
- const item = raw.filter((c) => c[this.valueField()] == key);
1473
- return Promise.resolve(item[0]);
1474
- },
1475
- });
1476
- this.dataSource.set(ds);
1477
- }
1478
- // resolve data source by name
1479
- else if (rawValue && (typeof rawValue == 'string' || typeof rawValue == 'object')) {
1480
- const id = typeof rawValue == 'object' ? rawValue['id'] : rawValue;
1481
- const c = await this.dataService.get(id);
1482
- if (this.mode == 'designer' && c?.samples?.length) {
1483
- this.dataSource.set(convertArrayToDataSource(c.samples, {
1484
- key: this.valueField(),
1485
- pageSize: 500,
1486
- }));
1487
- }
1488
- else {
1489
- const ds = c?.source();
1490
- if (ds && ds instanceof Promise) {
1491
- const d = await ds;
1492
- this.dataSource.set(d);
1493
- }
1494
- else if (ds) {
1495
- this.dataSource.set(ds);
1496
- }
1497
- // empty datasource
1498
- else {
1499
- this.dataSource.set(convertArrayToDataSource([]));
1500
- }
1501
- }
1502
- }
1503
- // empty datasource
1504
- else {
1505
- this.dataSource.set(convertArrayToDataSource([]));
1506
- }
1507
- }, ...(ngDevMode ? [{ debugName: "rf" }] : []));
1508
- this.effect2 = effect(async () => {
1509
- const value = this.getValue();
1510
- const items = [];
1511
- if (Array.isArray(value)) {
1512
- items.push(...await Promise.all(value.map((item) => this.extractItem(item))));
1513
- }
1514
- else {
1515
- items.push(await this.extractItem(value));
1516
- }
1517
- this.selectedItems.set(items.filter((c) => c != null));
1518
- }, ...(ngDevMode ? [{ debugName: "effect2" }] : []));
2336
+ static parseSidesWithUnits(input) {
2337
+ const values = this.expandShorthand(input.match(/(?:rgb\([^)]+\)|[^ ]+)/g)?.map((value) => value.trim()) || []);
2338
+ return {
2339
+ top: AXPPropertyEditorHelper.getValueWithUnit(values[0]).value,
2340
+ right: AXPPropertyEditorHelper.getValueWithUnit(values[1]).value,
2341
+ bottom: AXPPropertyEditorHelper.getValueWithUnit(values[2]).value,
2342
+ left: AXPPropertyEditorHelper.getValueWithUnit(values[3]).value,
2343
+ };
1519
2344
  }
1520
- async extractItem(item) {
1521
- if (isNil(item)) {
1522
- return null;
1523
- }
1524
- if (isObjectLike(item) && get(item, this.textField()) != null) {
1525
- return item;
2345
+ static parseCorners(input) {
2346
+ const values = this.expandShorthand(input.split(' ').map((value) => value.trim()));
2347
+ return {
2348
+ 'top-left': AXPPropertyEditorHelper.getValueWithUnit(values[0]).value,
2349
+ 'top-right': AXPPropertyEditorHelper.getValueWithUnit(values[1]).value,
2350
+ 'bottom-left': AXPPropertyEditorHelper.getValueWithUnit(values[2]).value,
2351
+ 'bottom-right': AXPPropertyEditorHelper.getValueWithUnit(values[3]).value,
2352
+ };
2353
+ }
2354
+ static parseSpacingBox(input) {
2355
+ return {
2356
+ margin: this.parseSidesWithUnits(input.margin),
2357
+ padding: this.parseSidesWithUnits(input.padding),
2358
+ };
2359
+ }
2360
+ static parseBorderBox(input) {
2361
+ return {
2362
+ width: this.parseSidesWithUnits(input.width),
2363
+ radius: this.parseCorners(input.radius),
2364
+ color: this.parseSides(input.color),
2365
+ style: this.parseSides(input.style),
2366
+ };
2367
+ }
2368
+ static parseSpacingBoxReverse(input, units) {
2369
+ const format = (value, unit) => `${value}${unit}`;
2370
+ return {
2371
+ margin: AXPPropertyEditorHelper.condenseShorthand([
2372
+ format(input.margin.top, units.margin.top),
2373
+ format(input.margin.right, units.margin.right),
2374
+ format(input.margin.bottom, units.margin.bottom),
2375
+ format(input.margin.left, units.margin.left),
2376
+ ]),
2377
+ padding: AXPPropertyEditorHelper.condenseShorthand([
2378
+ format(input.padding.top, units.padding.top),
2379
+ format(input.padding.right, units.padding.right),
2380
+ format(input.padding.bottom, units.padding.bottom),
2381
+ format(input.padding.left, units.padding.left),
2382
+ ]),
2383
+ };
2384
+ }
2385
+ static parseBorderBoxReverse(input, units) {
2386
+ const format = (value, unit) => `${value}${unit}`;
2387
+ return {
2388
+ width: AXPPropertyEditorHelper.condenseShorthand([
2389
+ format(input.width.top, units.width.top),
2390
+ format(input.width.right, units.width.right),
2391
+ format(input.width.bottom, units.width.bottom),
2392
+ format(input.width.left, units.width.left),
2393
+ ]),
2394
+ radius: AXPPropertyEditorHelper.condenseShorthand([
2395
+ format(input.radius['top-left'], units.radius['top-left']),
2396
+ format(input.radius['top-right'], units.radius['top-right']),
2397
+ format(input.radius['bottom-right'], units.radius['bottom-right']),
2398
+ format(input.radius['bottom-left'], units.radius['bottom-left']),
2399
+ ]),
2400
+ color: AXPPropertyEditorHelper.condenseShorthand([
2401
+ `${input.color.top}${units.color.top}`,
2402
+ `${input.color.right}${units.color.right}`,
2403
+ `${input.color.bottom}${units.color.bottom}`,
2404
+ `${input.color.left}${units.color.left}`,
2405
+ ]),
2406
+ style: AXPPropertyEditorHelper.condenseShorthand([
2407
+ `${input.style.top}${units.style.top}`,
2408
+ `${input.style.right}${units.style.right}`,
2409
+ `${input.style.bottom}${units.style.bottom}`,
2410
+ `${input.style.left}${units.style.left}`,
2411
+ ]),
2412
+ };
2413
+ }
2414
+ static getValueWithUnit(input) {
2415
+ if (typeof input === 'number')
2416
+ return { value: input, unit: 'px' };
2417
+ if (input === 'auto')
2418
+ return { value: 0, unit: 'px' };
2419
+ const match = input.match(/^([0-9.]+)([a-z%]*)$/i);
2420
+ if (!match)
2421
+ throw new Error(`Invalid unit format: ${input}`);
2422
+ return { value: parseFloat(match[1]), unit: match[2] || '' };
2423
+ }
2424
+ static getValueFromUnit(value, unit) {
2425
+ return unit ? `${value}${unit}` : `${value}`;
2426
+ }
2427
+ static parseGap(gap) {
2428
+ const parts = gap.split(/\s+/);
2429
+ const match = parts[0].match(/^(\d+\.?\d*)([a-z%]+)$/);
2430
+ if (!match) {
2431
+ throw new Error('Invalid gap format');
1526
2432
  }
1527
- const key = extractValue(item, this.valueField());
1528
- const ds = this.dataSource();
1529
- if (ds.config?.byKey) {
1530
- const found = await ds.config?.byKey(key);
1531
- if (found) {
1532
- return found;
2433
+ const [, xValue, unit] = match;
2434
+ let yValue = parseFloat(xValue);
2435
+ if (parts.length === 2) {
2436
+ const secondMatch = parts[1].match(/^(\d+\.?\d*)[a-z%]+$/);
2437
+ if (!secondMatch) {
2438
+ throw new Error('Invalid gap format');
1533
2439
  }
2440
+ yValue = parseFloat(secondMatch[1]);
1534
2441
  }
1535
- return isObjectLike(item) ? item : {
1536
- [this.valueField()]: item,
1537
- [this.textField()]: item,
2442
+ return {
2443
+ values: {
2444
+ x: parseFloat(xValue),
2445
+ y: yValue,
2446
+ },
2447
+ unit,
1538
2448
  };
1539
2449
  }
1540
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPDataListWidgetComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1541
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPDataListWidgetComponent }); }
2450
+ static parseGridTemplate(gridTemplate) {
2451
+ const match = gridTemplate.match(/^repeat\((\d+),\s*(?:1fr|auto|minmax\([^)]*\))\)$/);
2452
+ if (!match) {
2453
+ throw new Error("Invalid grid template format. Expected 'repeat(N, 1fr|auto|minmax(...))'.");
2454
+ }
2455
+ return parseInt(match[1], 10);
2456
+ }
2457
+ static createGridTemplate(repetitionCount) {
2458
+ if (repetitionCount <= 0) {
2459
+ throw new Error('Repetition count must be a positive integer.');
2460
+ }
2461
+ return `repeat(${repetitionCount}, 1fr)`;
2462
+ }
1542
2463
  }
1543
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPDataListWidgetComponent, decorators: [{
1544
- type: Injectable
1545
- }] });
1546
- class AXPColumnWidgetComponent {
1547
- constructor() {
1548
- this.token = inject(AXP_WIDGET_COLUMN_TOKEN);
1549
- this.path = this.token.path;
1550
- this.options = this.token.options ?? {};
1551
- this.rawValue = null;
2464
+ function findNonEmptyBreakpoints(values) {
2465
+ const breakpoints = ['default', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'];
2466
+ const nonEmptyBreakpoints = [];
2467
+ for (const breakpoint of breakpoints) {
2468
+ if (values[breakpoint] !== undefined) {
2469
+ nonEmptyBreakpoints.push(breakpoint);
2470
+ }
1552
2471
  }
1553
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPColumnWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1554
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPColumnWidgetComponent }); }
2472
+ return nonEmptyBreakpoints;
1555
2473
  }
1556
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPColumnWidgetComponent, decorators: [{
1557
- type: Injectable
1558
- }] });
2474
+
2475
+ const AXP_WIDGETS_LAYOUT_CATEGORY = {
2476
+ name: 'layout',
2477
+ order: 1,
2478
+ title: 'Layout',
2479
+ };
2480
+ const AXP_WIDGETS_EDITOR_CATEGORY = {
2481
+ name: 'editor',
2482
+ order: 2,
2483
+ title: 'Editors',
2484
+ };
2485
+ const AXP_WIDGETS_ACTION_CATEGORY = {
2486
+ name: 'action',
2487
+ order: 3,
2488
+ title: 'Action',
2489
+ };
2490
+ const AXP_WIDGETS_ADVANCE_CATEGORY = {
2491
+ name: 'advance',
2492
+ order: 4,
2493
+ title: 'Advance',
2494
+ };
2495
+ const AXP_WIDGETS_CATEGORIES = [
2496
+ AXP_WIDGETS_LAYOUT_CATEGORY,
2497
+ AXP_WIDGETS_EDITOR_CATEGORY,
2498
+ AXP_WIDGETS_ACTION_CATEGORY,
2499
+ AXP_WIDGETS_ADVANCE_CATEGORY,
2500
+ ];
2501
+
2502
+ var AXPWidgetGroupEnum;
2503
+ (function (AXPWidgetGroupEnum) {
2504
+ AXPWidgetGroupEnum["FormElement"] = "form-element";
2505
+ AXPWidgetGroupEnum["DashboardWidget"] = "dashboard-widget";
2506
+ AXPWidgetGroupEnum["FormTemplate"] = "form-template";
2507
+ AXPWidgetGroupEnum["PropertyEditor"] = "property-editor";
2508
+ AXPWidgetGroupEnum["MetaData"] = "meta-data";
2509
+ AXPWidgetGroupEnum["SettingWidget"] = "setting-widget";
2510
+ AXPWidgetGroupEnum["EntityWidget"] = "entity-widget";
2511
+ })(AXPWidgetGroupEnum || (AXPWidgetGroupEnum = {}));
1559
2512
 
1560
2513
  /**
1561
2514
  * Generated bundle index. Do not edit.
1562
2515
  */
1563
2516
 
1564
- export { AXPBaseWidgetComponent, AXPColumnWidgetComponent, AXPDataListWidgetComponent, AXPLayoutBuilderContextStore, AXPLayoutBuilderModule, AXPLayoutBuilderService, AXPLayoutContextChangeEvent, AXPLayoutElement, AXPLayoutWidgetComponent, AXPPageStatus, AXPValueWidgetComponent, AXPWidgetColumnRendererComponent, AXPWidgetContainerComponent, 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 };
2517
+ export { AXPBaseWidgetComponent, AXPBlockBaseLayoutWidgetComponent, AXPBoxModelLayoutWidgetComponent, AXPColumnWidgetComponent, AXPDataListWidgetComponent, AXPFlexBaseLayoutWidgetComponent, AXPFlexItemBaseLayoutWidgetComponent, AXPGridBaseLayoutWidgetComponent, AXPGridItemBaseLayoutWidgetComponent, AXPInlineBaseLayoutWidgetComponent, AXPLayoutBaseWidgetComponent, AXPLayoutBuilderContextStore, AXPLayoutBuilderModule, AXPLayoutBuilderService, AXPLayoutContextChangeEvent, AXPLayoutElement, AXPPageStatus, AXPPropertyEditorHelper, AXPTableBaseLayoutWidgetComponent, AXPTableItemBaseLayoutWidgetComponent, AXPTableItemOpsBaseLayoutWidgetComponent, AXPValueWidgetComponent, AXPWidgetColumnRendererComponent, AXPWidgetContainerComponent, 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 };
1565
2518
  //# sourceMappingURL=acorex-platform-layout-builder.mjs.map