@acorex/platform 21.0.0-next.70 → 21.0.0-next.71

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 (32) hide show
  1. package/fesm2022/acorex-platform-common.mjs +11 -0
  2. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  3. package/fesm2022/acorex-platform-core.mjs +332 -76
  4. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  5. package/fesm2022/acorex-platform-layout-builder.mjs +563 -44
  6. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-layout-components.mjs +83 -67
  8. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-layout-entity.mjs +543 -237
  10. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-layout-views.mjs +319 -66
  12. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  13. package/fesm2022/acorex-platform-layout-widget-core.mjs +54 -6
  14. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  15. package/fesm2022/acorex-platform-layout-widgets.mjs +198 -91
  16. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  17. package/fesm2022/acorex-platform-themes-default.mjs +13 -14
  18. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  19. package/fesm2022/acorex-platform-themes-shared.mjs +50 -30
  20. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  21. package/package.json +1 -1
  22. package/types/acorex-platform-common.d.ts +11 -0
  23. package/types/acorex-platform-core.d.ts +137 -47
  24. package/types/acorex-platform-layout-builder.d.ts +90 -13
  25. package/types/acorex-platform-layout-components.d.ts +21 -17
  26. package/types/acorex-platform-layout-entity.d.ts +63 -10
  27. package/types/acorex-platform-layout-views.d.ts +68 -6
  28. package/types/acorex-platform-layout-widget-core.d.ts +43 -8
  29. package/types/acorex-platform-layout-widgets.d.ts +21 -6
  30. package/types/acorex-platform-themes-default.d.ts +24 -4
  31. package/types/acorex-platform-themes-shared.d.ts +6 -0
  32. package/types/acorex-platform-workflow.d.ts +1 -1
@@ -528,12 +528,12 @@ class AXPProviderSelectWidgetEditBase extends AXPDataListWidgetComponent {
528
528
  setSmart(itemToExpose, mapping.target, this.singleOrMultiple(values));
529
529
  }
530
530
  });
531
- this.contextService.patch(itemToExpose, true);
531
+ this.contextService.applyObjectPaths(itemToExpose, { origin: 'user' });
532
532
  }
533
533
  if (this.filterMode()) {
534
534
  const newValue = e.value;
535
535
  const text = this.selectedItems().map((item) => get(item, this.textField()));
536
- this.setValue({
536
+ this.setUserValue({
537
537
  value: newValue,
538
538
  displayText: text,
539
539
  operation: {
@@ -541,14 +541,12 @@ class AXPProviderSelectWidgetEditBase extends AXPDataListWidgetComponent {
541
541
  },
542
542
  });
543
543
  }
544
+ else if (this.multiple()) {
545
+ const keys = this.selectedItems().map((item) => get(item, this.valueField()));
546
+ this.setUserValue(keys);
547
+ }
544
548
  else {
545
- if (this.multiple()) {
546
- const keys = this.selectedItems().map((item) => get(item, this.valueField()));
547
- this.setValue(keys);
548
- }
549
- else {
550
- this.setValue(e.value);
551
- }
549
+ this.setUserValue(e.value);
552
550
  }
553
551
  }
554
552
  }
@@ -5176,18 +5174,21 @@ class AXPLargeTextWidgetEditComponent extends AXPValueWidgetComponent {
5176
5174
  super.ngOnInit();
5177
5175
  const v = this.getValue();
5178
5176
  if (this.multiLanguage() && typeof v === 'string') {
5179
- this.setValue({ [this.currentLanguage()]: v });
5177
+ this.setValue({ [this.currentLanguage()]: v }, { origin: 'system' });
5180
5178
  }
5181
5179
  }
5182
5180
  handleValueChange(e) {
5181
+ if (!e.isUserInteraction) {
5182
+ return;
5183
+ }
5183
5184
  if (this.multiLanguage()) {
5184
5185
  const v = this.getValue();
5185
5186
  const obj = v && typeof v === 'object' && !Array.isArray(v) ? { ...v } : {};
5186
5187
  obj[this.currentLanguage()] = e.value ?? '';
5187
- this.setValue(obj);
5188
+ this.setUserValue(obj);
5188
5189
  }
5189
5190
  else {
5190
- this.setValue(e.value ?? '');
5191
+ this.setUserValue(e.value ?? '');
5191
5192
  }
5192
5193
  }
5193
5194
  openMultiLanguagePopup() {
@@ -7149,50 +7150,91 @@ const AXPRichTextWidget = {
7149
7150
  },
7150
7151
  };
7151
7152
 
7153
+ //#region ---- Badge styling ----
7154
+ const BADGE_BASE_CLASSES = 'ax-inline-flex ax-items-center ax-px-2 ax-py-1 ax-text-xs ax-font-medium ax-rounded-lg ax-border';
7155
+ const DEFAULT_BADGE_CSS_CLASS = 'ax-primary-lighter';
7156
+ function readSelectItemCssClass(item, cssClassField) {
7157
+ if (!cssClassField) {
7158
+ return undefined;
7159
+ }
7160
+ const raw = item[cssClassField];
7161
+ return typeof raw === 'string' && raw.trim() ? raw.trim() : undefined;
7162
+ }
7163
+ /**
7164
+ * Resolves badge classes: layout base + scope {@link cssClass} (whole badge) or default fallback.
7165
+ */
7166
+ function resolveSelectBadgeClasses(item, options) {
7167
+ const scopeClass = readSelectItemCssClass(item, options.cssClassField);
7168
+ if (scopeClass) {
7169
+ return `${BADGE_BASE_CLASSES} ${scopeClass}`;
7170
+ }
7171
+ const fallback = options.badgeClass?.trim() || DEFAULT_BADGE_CSS_CLASS;
7172
+ return `${BADGE_BASE_CLASSES} ${fallback}`;
7173
+ }
7174
+ //#endregion
7175
+
7152
7176
  class AXPSelectBoxWidgetColumnComponent extends AXPColumnWidgetComponent {
7153
7177
  constructor() {
7154
7178
  super(...arguments);
7155
- this.valueField = this.options['valueField'] ?? 'id';
7156
- this.textField = this.options['textField'] ?? 'title';
7157
- this.badgeClass = this.options['badgeClass'] ?? 'ax-primary-lightest dark:ax-primary-darker';
7158
- this.dataSource = this.options['dataSource'] ?? [];
7179
+ this.textField = computed(() => this.options['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
7180
+ this.valueField = computed(() => this.options['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
7181
+ this.cssClassField = computed(() => this.options['cssClassField'], ...(ngDevMode ? [{ debugName: "cssClassField" }] : /* istanbul ignore next */ []));
7182
+ this.badgeClass = computed(() => this.options['badgeClass'], ...(ngDevMode ? [{ debugName: "badgeClass" }] : /* istanbul ignore next */ []));
7183
+ this.dataSource = computed(() => this.options['dataSource'] ?? [], ...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
7159
7184
  this.internalValue = computed(() => castArray(this.rawValue)
7160
7185
  .map((item) => this.extractItem(item))
7161
7186
  .filter((c) => c != null), ...(ngDevMode ? [{ debugName: "internalValue" }] : /* istanbul ignore next */ []));
7162
7187
  }
7188
+ resolveBadgeClasses(item) {
7189
+ const row = item;
7190
+ return resolveSelectBadgeClasses(row, {
7191
+ cssClassField: this.cssClassField(),
7192
+ badgeClass: this.badgeClass(),
7193
+ });
7194
+ }
7195
+ getItemLabel(item) {
7196
+ const row = item;
7197
+ const label = row[this.textField()];
7198
+ if (label != null && typeof label === 'object') {
7199
+ return label;
7200
+ }
7201
+ return String(label ?? '');
7202
+ }
7163
7203
  extractItem(item) {
7164
7204
  if (isNil(item)) {
7165
7205
  return null;
7166
7206
  }
7167
- // Check if dataSource contains objects
7168
- const isDataSourceObjects = Array.isArray(this.dataSource) && this.dataSource.length > 0 && typeof this.dataSource[0] === 'object';
7169
- // If item is primitive and dataSource contains objects, lookup the item in dataSource
7170
- if (typeof item !== 'object' && isDataSourceObjects) {
7171
- const foundItem = this.dataSource.find((ds) => ds[this.valueField] === item);
7172
- if (foundItem) {
7173
- return {
7174
- [this.valueField]: foundItem[this.valueField],
7175
- [this.textField]: foundItem[this.textField],
7176
- };
7207
+ const valueField = this.valueField();
7208
+ const textField = this.textField();
7209
+ const cssClassField = this.cssClassField();
7210
+ const dataSource = this.dataSource();
7211
+ const isDataSourceObjects = Array.isArray(dataSource) && dataSource.length > 0 && typeof dataSource[0] === 'object';
7212
+ if (typeof item !== 'object') {
7213
+ if (isDataSourceObjects) {
7214
+ const foundItem = dataSource.find((ds) => ds[valueField] === item);
7215
+ if (foundItem) {
7216
+ return { ...foundItem };
7217
+ }
7177
7218
  }
7178
- }
7179
- // If item is already an object
7180
- if (typeof item === 'object') {
7181
7219
  return {
7182
- [this.valueField]: item?.[this.valueField],
7183
- [this.textField]: item?.[this.textField],
7220
+ [valueField]: item,
7221
+ [textField]: item,
7184
7222
  };
7185
7223
  }
7186
- // Fallback for primitive values when dataSource is not objects
7187
- return {
7188
- [this.valueField]: item,
7189
- [this.textField]: item,
7190
- };
7224
+ const row = item;
7225
+ if (!readSelectItemCssClass(row, cssClassField) && isDataSourceObjects && row[valueField] != null) {
7226
+ const foundItem = dataSource.find((ds) => ds[valueField] === row[valueField]);
7227
+ const cssKey = cssClassField ?? 'cssClass';
7228
+ if (foundItem?.[cssKey]) {
7229
+ return { ...row, [cssKey]: foundItem[cssKey] };
7230
+ }
7231
+ }
7232
+ return { ...row };
7191
7233
  }
7192
7234
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSelectBoxWidgetColumnComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
7193
7235
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPSelectBoxWidgetColumnComponent, isStandalone: true, selector: "axp-select-box-widget-column", inputs: { rawValue: "rawValue", rowData: "rowData" }, usesInheritance: true, ngImport: i0, template: ` <div class="ax-flex ax-gap-2">
7194
7236
  @for (item of internalValue(); track $index) {
7195
- <span class="ax-px-2 ax-py-1 ax-text-xs ax-font-medium ax-rounded-lg {{ badgeClass }}">{{ item[this.textField] | translate | async }}</span>
7237
+ <span class="{{ resolveBadgeClasses(item) }}">{{ getItemLabel(item) | translate | async }}</span>
7196
7238
  } @empty {
7197
7239
  <span class="ax-text-muted">---</span>
7198
7240
  }
@@ -7204,7 +7246,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
7204
7246
  selector: 'axp-select-box-widget-column',
7205
7247
  template: ` <div class="ax-flex ax-gap-2">
7206
7248
  @for (item of internalValue(); track $index) {
7207
- <span class="ax-px-2 ax-py-1 ax-text-xs ax-font-medium ax-rounded-lg {{ badgeClass }}">{{ item[this.textField] | translate | async }}</span>
7249
+ <span class="{{ resolveBadgeClasses(item) }}">{{ getItemLabel(item) | translate | async }}</span>
7208
7250
  } @empty {
7209
7251
  <span class="ax-text-muted">---</span>
7210
7252
  }
@@ -7348,16 +7390,14 @@ class AXPSelectBoxWidgetEditComponent extends AXPDataListWidgetComponent {
7348
7390
  setSmart(itemToExpose, expr.target, this.singleOrMultiple(values));
7349
7391
  }
7350
7392
  });
7351
- this.contextService.patch(itemToExpose, true);
7393
+ this.contextService.applyObjectPaths(itemToExpose, { origin: 'user' });
7352
7394
  }
7353
7395
  //#endregion
7354
7396
  //#region ---- Set Value Based on Mode ----
7355
- // Apply strategy even when the value comes from outside (isUserInteraction=false).
7356
7397
  if (this.filterMode()) {
7357
- // Filter mode: set value with operation structure
7358
7398
  const newValue = e.value;
7359
7399
  const text = this.selectedItems().map((item) => get(item, this.textField()));
7360
- this.setValue({
7400
+ this.setUserValue({
7361
7401
  value: newValue,
7362
7402
  displayText: text,
7363
7403
  operation: {
@@ -7365,19 +7405,27 @@ class AXPSelectBoxWidgetEditComponent extends AXPDataListWidgetComponent {
7365
7405
  },
7366
7406
  });
7367
7407
  }
7408
+ else if (this.widgetsConfigs.selectValueStrategy === 'valueField') {
7409
+ this.setUserValue(e.value);
7410
+ }
7411
+ else if (this.multiple()) {
7412
+ this.setUserValue(this.selectedItems());
7413
+ }
7414
+ else {
7415
+ this.setUserValue(this.selectedItems()[0]);
7416
+ }
7368
7417
  }
7369
- if (!this.filterMode()) {
7370
- // Normal mode: set value directly
7418
+ else if (!this.filterMode()) {
7419
+ // Programmatic sync from the select box (hydration, datasource refresh).
7420
+ const systemOrigin = { origin: 'system' };
7371
7421
  if (this.widgetsConfigs.selectValueStrategy === 'valueField') {
7372
- this.setValue(e.value);
7422
+ this.setValue(e.value, systemOrigin);
7423
+ }
7424
+ else if (this.multiple()) {
7425
+ this.setValue(this.selectedItems(), systemOrigin);
7373
7426
  }
7374
7427
  else {
7375
- if (this.multiple()) {
7376
- this.setValue(this.selectedItems());
7377
- }
7378
- else {
7379
- this.setValue(this.selectedItems()[0]);
7380
- }
7428
+ this.setValue(this.selectedItems()[0], systemOrigin);
7381
7429
  }
7382
7430
  }
7383
7431
  //#endregion
@@ -7553,23 +7601,35 @@ var selectBoxWidgetEdit_component = /*#__PURE__*/Object.freeze({
7553
7601
  });
7554
7602
 
7555
7603
  class AXPSelectBoxWidgetViewComponent extends AXPDataListWidgetComponent {
7556
- //TODO: why do we need this?
7557
- //protected badgeClass = computed<string>(() => (this.options()['badgeClass'] as string) ?? 'ax-accent1');
7558
- get __class() {
7559
- const cls = {};
7560
- cls[`ax-flex`] = true;
7561
- cls[`ax-gap-1`] = true;
7562
- return cls;
7604
+ constructor() {
7605
+ super(...arguments);
7606
+ this.cssClassField = computed(() => this.options()['cssClassField'], ...(ngDevMode ? [{ debugName: "cssClassField" }] : /* istanbul ignore next */ []));
7607
+ this.badgeClass = computed(() => this.options()['badgeClass'], ...(ngDevMode ? [{ debugName: "badgeClass" }] : /* istanbul ignore next */ []));
7608
+ }
7609
+ resolveBadgeClasses(item) {
7610
+ return resolveSelectBadgeClasses(item, {
7611
+ cssClassField: this.cssClassField(),
7612
+ badgeClass: this.badgeClass(),
7613
+ });
7614
+ }
7615
+ getItemLabel(item) {
7616
+ const row = item;
7617
+ const label = row[this.textField()];
7618
+ if (label != null && typeof label === 'object') {
7619
+ return label;
7620
+ }
7621
+ return String(label ?? '');
7563
7622
  }
7564
7623
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSelectBoxWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
7565
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPSelectBoxWidgetViewComponent, isStandalone: true, selector: "axp-select-box-widget-view", host: { properties: { "class": "this.__class" } }, usesInheritance: true, ngImport: i0, template: `
7624
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPSelectBoxWidgetViewComponent, isStandalone: true, selector: "axp-select-box-widget-view", host: { classAttribute: "ax-flex ax-gap-1 ax-flex-wrap" }, usesInheritance: true, ngImport: i0, template: `
7566
7625
  @for (item of selectedItems(); track $index) {
7567
- <span >{{item[this.textField()] | translate | async}}</span>
7568
- }
7569
- @empty {
7626
+ <span class="{{ resolveBadgeClasses(item) }}">
7627
+ {{ getItemLabel(item) | translate | async }}
7628
+ </span>
7629
+ } @empty {
7570
7630
  <span class="ax-text-muted">---</span>
7571
7631
  }
7572
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1$4.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7632
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1$4.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7573
7633
  }
7574
7634
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSelectBoxWidgetViewComponent, decorators: [{
7575
7635
  type: Component,
@@ -7577,19 +7637,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
7577
7637
  selector: 'axp-select-box-widget-view',
7578
7638
  template: `
7579
7639
  @for (item of selectedItems(); track $index) {
7580
- <span >{{item[this.textField()] | translate | async}}</span>
7581
- }
7582
- @empty {
7640
+ <span class="{{ resolveBadgeClasses(item) }}">
7641
+ {{ getItemLabel(item) | translate | async }}
7642
+ </span>
7643
+ } @empty {
7583
7644
  <span class="ax-text-muted">---</span>
7584
7645
  }
7585
7646
  `,
7586
7647
  changeDetection: ChangeDetectionStrategy.OnPush,
7587
- imports: [AXBadgeModule, CommonModule, AXTranslationModule],
7648
+ host: {
7649
+ class: 'ax-flex ax-gap-1 ax-flex-wrap',
7650
+ },
7651
+ imports: [CommonModule, AXTranslationModule],
7588
7652
  }]
7589
- }], propDecorators: { __class: [{
7590
- type: HostBinding,
7591
- args: ['class']
7592
- }] } });
7653
+ }] });
7593
7654
 
7594
7655
  var selectBoxWidgetView_component = /*#__PURE__*/Object.freeze({
7595
7656
  __proto__: null,
@@ -8908,7 +8969,7 @@ class AXPTextBoxWidgetEditComponent extends AXPValueWidgetComponent {
8908
8969
  super.ngOnInit();
8909
8970
  const v = this.getValue();
8910
8971
  if (this.multiLanguage() && typeof v === 'string') {
8911
- this.setValue({ [this.currentLanguage()]: v });
8972
+ this.setValue({ [this.currentLanguage()]: v }, { origin: 'system' });
8912
8973
  }
8913
8974
  this.translationService.langChanges$.subscribe((i) => {
8914
8975
  this.currentLanguage.set(i);
@@ -8922,10 +8983,10 @@ class AXPTextBoxWidgetEditComponent extends AXPValueWidgetComponent {
8922
8983
  const v = this.getValue();
8923
8984
  const obj = v && typeof v === 'object' && !Array.isArray(v) ? { ...v } : {};
8924
8985
  obj[this.currentLanguage()] = e.value ?? '';
8925
- this.setValue(obj);
8986
+ this.setUserValue(obj);
8926
8987
  }
8927
8988
  else {
8928
- this.setValue(e.value ?? '');
8989
+ this.setUserValue(e.value ?? '');
8929
8990
  }
8930
8991
  }
8931
8992
  getCurrentText() {
@@ -14974,6 +15035,10 @@ class AXPItemConfiguratorWidgetEditComponent extends AXPValueWidgetComponent {
14974
15035
  //#endregion
14975
15036
  //#region ---- State Signals ----
14976
15037
  this.isInitialized = signal(false, ...(ngDevMode ? [{ debugName: "isInitialized" }] : /* istanbul ignore next */ []));
15038
+ /** True while syncing models from shared context (discard/load); writes use system origin. */
15039
+ this.hydratingFromContext = signal(false, ...(ngDevMode ? [{ debugName: "hydratingFromContext" }] : /* istanbul ignore next */ []));
15040
+ this.baseline = signal(null, ...(ngDevMode ? [{ debugName: "baseline" }] : /* istanbul ignore next */ []));
15041
+ this.isDirtySignal = signal(false, ...(ngDevMode ? [{ debugName: "isDirtySignal" }] : /* istanbul ignore next */ []));
14977
15042
  //#endregion
14978
15043
  //#region ---- Models ----
14979
15044
  this.selectedItemIdModel = model('', ...(ngDevMode ? [{ debugName: "selectedItemIdModel" }] : /* istanbul ignore next */ []));
@@ -15027,6 +15092,7 @@ class AXPItemConfiguratorWidgetEditComponent extends AXPValueWidgetComponent {
15027
15092
  }, ...(ngDevMode ? [{ debugName: "loadNamedDataSourceEffect" }] : /* istanbul ignore next */ []));
15028
15093
  this.syncValueToConfigurator = effect(() => {
15029
15094
  const value = this.getValue();
15095
+ this.hydratingFromContext.set(true);
15030
15096
  if (value && value.type) {
15031
15097
  const sid = untracked(() => this.selectedItemIdModel());
15032
15098
  const vals = untracked(() => this.valuesModel());
@@ -15048,6 +15114,8 @@ class AXPItemConfiguratorWidgetEditComponent extends AXPValueWidgetComponent {
15048
15114
  }
15049
15115
  });
15050
15116
  }
15117
+ untracked(() => this.syncBaselineFromModels());
15118
+ queueMicrotask(() => this.hydratingFromContext.set(false));
15051
15119
  }, ...(ngDevMode ? [{ debugName: "syncValueToConfigurator" }] : /* istanbul ignore next */ []));
15052
15120
  this.syncConfiguratorToValue = effect(() => {
15053
15121
  const sid = this.selectedItemIdModel();
@@ -15056,26 +15124,65 @@ class AXPItemConfiguratorWidgetEditComponent extends AXPValueWidgetComponent {
15056
15124
  return;
15057
15125
  }
15058
15126
  const currentValue = untracked(() => this.getValue());
15059
- const empty = { type: '', options: {} };
15060
- if (!sid) {
15061
- if (!isEqual(currentValue ?? empty, empty)) {
15062
- untracked(() => {
15063
- this.setValue(empty);
15064
- });
15065
- }
15127
+ const next = this.buildWidgetNode(sid, vals);
15128
+ if (isEqual(next, currentValue)) {
15066
15129
  return;
15067
15130
  }
15068
- const next = {
15069
- ...(currentValue && typeof currentValue === 'object' ? currentValue : {}),
15070
- type: sid,
15071
- options: vals,
15072
- };
15073
- if (!isEqual(next, currentValue)) {
15074
- untracked(() => {
15075
- this.setValue(next);
15076
- });
15077
- }
15131
+ const origin = this.hydratingFromContext() ? 'system' : 'user';
15132
+ untracked(() => {
15133
+ this.setValue(next, { origin });
15134
+ });
15078
15135
  }, ...(ngDevMode ? [{ debugName: "syncConfiguratorToValue" }] : /* istanbul ignore next */ []));
15136
+ this.evaluateDirty = effect(() => {
15137
+ if (!this.isInitialized()) {
15138
+ return;
15139
+ }
15140
+ const base = this.baseline();
15141
+ if (base == null) {
15142
+ return;
15143
+ }
15144
+ const sid = this.selectedItemIdModel();
15145
+ const vals = this.valuesModel();
15146
+ const current = this.buildWidgetNode(sid, vals);
15147
+ const dirty = !isEqual(current, base);
15148
+ this.setDirtyState(dirty);
15149
+ }, ...(ngDevMode ? [{ debugName: "evaluateDirty" }] : /* istanbul ignore next */ []));
15150
+ }
15151
+ //#endregion
15152
+ //#region ---- Widget API ----
15153
+ api() {
15154
+ return {
15155
+ isDirty: () => this.isDirtySignal(),
15156
+ };
15157
+ }
15158
+ //#endregion
15159
+ //#region ---- Utility Methods ----
15160
+ buildWidgetNode(sid, vals) {
15161
+ if (!sid) {
15162
+ return { type: '', options: {} };
15163
+ }
15164
+ const currentValue = untracked(() => this.getValue());
15165
+ return {
15166
+ ...(currentValue && typeof currentValue === 'object' ? currentValue : {}),
15167
+ type: sid,
15168
+ options: vals,
15169
+ };
15170
+ }
15171
+ syncBaselineFromModels() {
15172
+ if (!this.isInitialized()) {
15173
+ return;
15174
+ }
15175
+ const sid = this.selectedItemIdModel();
15176
+ const vals = this.valuesModel();
15177
+ this.baseline.set(cloneDeep(this.buildWidgetNode(sid, vals)));
15178
+ this.setDirtyState(false);
15179
+ }
15180
+ setDirtyState(dirty) {
15181
+ if (this.isDirtySignal() === dirty) {
15182
+ return;
15183
+ }
15184
+ this.isDirtySignal.set(dirty);
15185
+ this.layoutService.notifyWidgetDirtyChanged();
15079
15186
  }
15080
15187
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPItemConfiguratorWidgetEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
15081
15188
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPItemConfiguratorWidgetEditComponent, isStandalone: true, selector: "axp-item-configurator-widget-edit", inputs: { selectedItemIdModel: { classPropertyName: "selectedItemIdModel", publicName: "selectedItemIdModel", isSignal: true, isRequired: false, transformFunction: null }, valuesModel: { classPropertyName: "valuesModel", publicName: "valuesModel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedItemIdModel: "selectedItemIdModelChange", valuesModel: "valuesModelChange" }, usesInheritance: true, ngImport: i0, template: `