ui-core-abv 0.10.3 → 0.10.5

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.
@@ -4175,6 +4175,24 @@ class UicFormStateService {
4175
4175
  this.formChangesSub = null;
4176
4176
  });
4177
4177
  }
4178
+ /**
4179
+ * Opciones de subcampos de repeater resueltas por ítem (optionsSource con dependsOn).
4180
+ * Cada FormGroup de ítem guarda las suyas; el registro se reemplaza (inmutable) en cada cambio
4181
+ * para que los consumidores puedan memoizar por referencia.
4182
+ */
4183
+ rowFieldOptions = new WeakMap();
4184
+ rowFieldOptionsVersion = signal(0);
4185
+ setRowFieldOptions(row, fieldName, state) {
4186
+ const current = this.rowFieldOptions.get(row) ?? {};
4187
+ this.rowFieldOptions.set(row, {
4188
+ ...current,
4189
+ [fieldName]: { ...current[fieldName], ...state }
4190
+ });
4191
+ this.rowFieldOptionsVersion.update(version => version + 1);
4192
+ }
4193
+ getRowFieldOptions(row) {
4194
+ return this.rowFieldOptions.get(row);
4195
+ }
4178
4196
  getFieldValue(fieldName) {
4179
4197
  if (!this.currentForm)
4180
4198
  return undefined;
@@ -4189,6 +4207,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
4189
4207
 
4190
4208
  class UicRepeaterComponent {
4191
4209
  fb = inject(FormBuilder);
4210
+ formState = inject(UicFormStateService, { optional: true });
4211
+ itemFieldsCache = new WeakMap();
4192
4212
  formArray;
4193
4213
  field;
4194
4214
  cols = 2;
@@ -4210,6 +4230,31 @@ class UicRepeaterComponent {
4210
4230
  }
4211
4231
  }
4212
4232
  }
4233
+ /**
4234
+ * Subcampos del ítem con las opciones resueltas para ese ítem (optionsSource con dependsOn).
4235
+ * Se memoiza por referencia para no recrear los FormField en cada ciclo de detección.
4236
+ */
4237
+ getItemFields(control) {
4238
+ const base = this.field.repeaterFields ?? [];
4239
+ this.formState?.rowFieldOptionsVersion();
4240
+ const row = control;
4241
+ const state = this.formState?.getRowFieldOptions(row);
4242
+ const cached = this.itemFieldsCache.get(row);
4243
+ if (cached && cached.base === base && cached.state === state)
4244
+ return cached.fields;
4245
+ const fields = !state ? base : base.map(subField => {
4246
+ const rowState = state[subField.name];
4247
+ if (!rowState)
4248
+ return subField;
4249
+ return {
4250
+ ...subField,
4251
+ ...(rowState.options !== undefined ? { options: rowState.options } : {}),
4252
+ ...(rowState.loading !== undefined ? { loading: rowState.loading } : {})
4253
+ };
4254
+ });
4255
+ this.itemFieldsCache.set(row, { base, state, fields });
4256
+ return fields;
4257
+ }
4213
4258
  getGroup(index) {
4214
4259
  return this.formArray.at(index);
4215
4260
  }
@@ -4279,7 +4324,7 @@ class UicRepeaterComponent {
4279
4324
  }
4280
4325
  }
4281
4326
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicRepeaterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4282
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UicRepeaterComponent, isStandalone: true, selector: "ui-repeater", inputs: { formArray: "formArray", field: "field", cols: "cols", error: "error", fileUidResolverFn: "fileUidResolverFn", selectOptionsResolver: "selectOptionsResolver", parentForm: "parentForm" }, ngImport: i0, template: "<div class=\"repeater-label\"> {{field.label}} </div>\r\n<div class=\"uic-repeater\" [class.disabled]=\"formArray.disabled\">\r\n @for (group of formArray.controls; track $index) {\r\n <div class=\"uic-repeater-item\">\r\n <div class=\"uic-repeater-item-header\">\r\n <div class=\"uic-repeater-item-title\">\r\n {{ field.repeaterItemTitle || field.label || 'Item' }} {{ $index + 1 }}\r\n </div>\r\n @if (canRemove && !formArray.disabled) {\r\n <ui-button \r\n [icon]=\"'ri-delete-bin-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'red'\" \r\n size=\"s\" \r\n (click)=\"removeGroup($index)\"\r\n [text]=\"field.repeaterRemoveLabel || 'Eliminar'\">\r\n </ui-button>\r\n }\r\n </div>\r\n <div class=\"uic-repeater-item-body\">\r\n <ui-dynamic-form \r\n [form]=\"getGroup($index)\" \r\n [fields]=\"field.repeaterFields || []\" \r\n [disabled]=\"formArray.disabled\"\r\n [cols]=\"cols\"\r\n [fileUidResolverFn]=\"fileUidResolverFn\"\r\n [selectOptionsResolver]=\"selectOptionsResolver\"\r\n [parentFormValues]=\"getParentFormValues()\"\r\n [isSubForm]=\"true\">\r\n </ui-dynamic-form>\r\n </div>\r\n </div>\r\n }\r\n \r\n @if (canAdd && !formArray.disabled) {\r\n <div class=\"uic-repeater-add-action\">\r\n <ui-button \r\n [icon]=\"'ri-add-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'primary'\" \r\n (click)=\"addGroup()\"\r\n [text]=\"field.repeaterAddLabel || 'A\u00F1adir'\">\r\n </ui-button>\r\n </div>\r\n }\r\n @if (error) {\r\n <p class=\"uic-repeater-error\">{{ error }}</p>\r\n }\r\n</div>\r\n", styles: [".uic-repeater{display:flex;flex-direction:column;gap:16px;width:100%}.uic-repeater.disabled{opacity:.7}.uic-repeater .uic-repeater-item{border:1px solid var(--primary-400, #e0e0e0);border-radius:8px;background-color:var(--uic-bg-color, #fff)}.uic-repeater .uic-repeater-item .uic-repeater-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px;border-bottom:1px solid var(--primary-400);padding:5px 10px;min-height:34px}.uic-repeater .uic-repeater-item .uic-repeater-item-header .uic-repeater-item-title{margin:0;font-size:14px;font-weight:600;color:var(--primary-700)}.uic-repeater .uic-repeater-item .uic-repeater-item-body{width:100%;padding:0 12px}.uic-repeater .uic-repeater-add-action{margin-top:1px}.uic-repeater .uic-repeater-error{margin:4px 0 0;font-size:12px;color:var(--uic-red, #e53935)}.repeater-label{font-size:max(var(--form-ref) + 4px,14px);line-height:1.125rem;min-height:1.125rem;font-weight:400;color:var(--grey-950);margin-bottom:var(--input-label-space)}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "ngmodule", type: i0.forwardRef(() => ReactiveFormsModule) }, { kind: "component", type: i0.forwardRef(() => UicButtonComponent), selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "component", type: i0.forwardRef(() => UicDynamicFormComponent), selector: "ui-dynamic-form", inputs: ["fields", "isSubForm", "form", "disabled", "externalValidationStates", "voiceToTextSilenceMs", "cols", "iconMode", "fileUidResolverFn", "selectOptionsResolver", "parentFormValues"], outputs: ["fieldBlur"] }] });
4327
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UicRepeaterComponent, isStandalone: true, selector: "ui-repeater", inputs: { formArray: "formArray", field: "field", cols: "cols", error: "error", fileUidResolverFn: "fileUidResolverFn", selectOptionsResolver: "selectOptionsResolver", parentForm: "parentForm" }, ngImport: i0, template: "<div class=\"repeater-label\"> {{field.label}} </div>\r\n<div class=\"uic-repeater\" [class.disabled]=\"formArray.disabled\">\r\n @for (group of formArray.controls; track $index) {\r\n <div class=\"uic-repeater-item\">\r\n <div class=\"uic-repeater-item-header\">\r\n <div class=\"uic-repeater-item-title\">\r\n {{ field.repeaterItemTitle || field.label || 'Item' }} {{ $index + 1 }}\r\n </div>\r\n @if (canRemove && !formArray.disabled) {\r\n <ui-button \r\n [icon]=\"'ri-delete-bin-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'red'\" \r\n size=\"s\" \r\n (click)=\"removeGroup($index)\"\r\n [text]=\"field.repeaterRemoveLabel || 'Eliminar'\">\r\n </ui-button>\r\n }\r\n </div>\r\n <div class=\"uic-repeater-item-body\">\r\n <ui-dynamic-form \r\n [form]=\"getGroup($index)\" \r\n [fields]=\"getItemFields(group)\" \r\n [disabled]=\"formArray.disabled\"\r\n [cols]=\"cols\"\r\n [fileUidResolverFn]=\"fileUidResolverFn\"\r\n [selectOptionsResolver]=\"selectOptionsResolver\"\r\n [parentFormValues]=\"getParentFormValues()\"\r\n [isSubForm]=\"true\">\r\n </ui-dynamic-form>\r\n </div>\r\n </div>\r\n }\r\n \r\n @if (canAdd && !formArray.disabled) {\r\n <div class=\"uic-repeater-add-action\">\r\n <ui-button \r\n [icon]=\"'ri-add-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'primary'\" \r\n (click)=\"addGroup()\"\r\n [text]=\"field.repeaterAddLabel || 'A\u00F1adir'\">\r\n </ui-button>\r\n </div>\r\n }\r\n @if (error) {\r\n <p class=\"uic-repeater-error\">{{ error }}</p>\r\n }\r\n</div>\r\n", styles: [".uic-repeater{display:flex;flex-direction:column;gap:16px;width:100%}.uic-repeater.disabled{opacity:.7}.uic-repeater .uic-repeater-item{border:1px solid var(--primary-400, #e0e0e0);border-radius:8px;background-color:var(--uic-bg-color, #fff)}.uic-repeater .uic-repeater-item .uic-repeater-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px;border-bottom:1px solid var(--primary-400);padding:5px 10px;min-height:34px}.uic-repeater .uic-repeater-item .uic-repeater-item-header .uic-repeater-item-title{margin:0;font-size:14px;font-weight:600;color:var(--primary-700)}.uic-repeater .uic-repeater-item .uic-repeater-item-body{width:100%;padding:0 12px}.uic-repeater .uic-repeater-add-action{margin-top:1px}.uic-repeater .uic-repeater-error{margin:4px 0 0;font-size:12px;color:var(--uic-red, #e53935)}.repeater-label{font-size:max(var(--form-ref) + 4px,14px);line-height:1.125rem;min-height:1.125rem;font-weight:400;color:var(--grey-950);margin-bottom:var(--input-label-space)}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "ngmodule", type: i0.forwardRef(() => ReactiveFormsModule) }, { kind: "component", type: i0.forwardRef(() => UicButtonComponent), selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "component", type: i0.forwardRef(() => UicDynamicFormComponent), selector: "ui-dynamic-form", inputs: ["fields", "isSubForm", "form", "disabled", "externalValidationStates", "voiceToTextSilenceMs", "cols", "iconMode", "fileUidResolverFn", "selectOptionsResolver", "parentFormValues"], outputs: ["fieldBlur"] }] });
4283
4328
  }
4284
4329
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicRepeaterComponent, decorators: [{
4285
4330
  type: Component,
@@ -4288,7 +4333,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
4288
4333
  ReactiveFormsModule,
4289
4334
  UicButtonComponent,
4290
4335
  forwardRef(() => UicDynamicFormComponent)
4291
- ], template: "<div class=\"repeater-label\"> {{field.label}} </div>\r\n<div class=\"uic-repeater\" [class.disabled]=\"formArray.disabled\">\r\n @for (group of formArray.controls; track $index) {\r\n <div class=\"uic-repeater-item\">\r\n <div class=\"uic-repeater-item-header\">\r\n <div class=\"uic-repeater-item-title\">\r\n {{ field.repeaterItemTitle || field.label || 'Item' }} {{ $index + 1 }}\r\n </div>\r\n @if (canRemove && !formArray.disabled) {\r\n <ui-button \r\n [icon]=\"'ri-delete-bin-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'red'\" \r\n size=\"s\" \r\n (click)=\"removeGroup($index)\"\r\n [text]=\"field.repeaterRemoveLabel || 'Eliminar'\">\r\n </ui-button>\r\n }\r\n </div>\r\n <div class=\"uic-repeater-item-body\">\r\n <ui-dynamic-form \r\n [form]=\"getGroup($index)\" \r\n [fields]=\"field.repeaterFields || []\" \r\n [disabled]=\"formArray.disabled\"\r\n [cols]=\"cols\"\r\n [fileUidResolverFn]=\"fileUidResolverFn\"\r\n [selectOptionsResolver]=\"selectOptionsResolver\"\r\n [parentFormValues]=\"getParentFormValues()\"\r\n [isSubForm]=\"true\">\r\n </ui-dynamic-form>\r\n </div>\r\n </div>\r\n }\r\n \r\n @if (canAdd && !formArray.disabled) {\r\n <div class=\"uic-repeater-add-action\">\r\n <ui-button \r\n [icon]=\"'ri-add-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'primary'\" \r\n (click)=\"addGroup()\"\r\n [text]=\"field.repeaterAddLabel || 'A\u00F1adir'\">\r\n </ui-button>\r\n </div>\r\n }\r\n @if (error) {\r\n <p class=\"uic-repeater-error\">{{ error }}</p>\r\n }\r\n</div>\r\n", styles: [".uic-repeater{display:flex;flex-direction:column;gap:16px;width:100%}.uic-repeater.disabled{opacity:.7}.uic-repeater .uic-repeater-item{border:1px solid var(--primary-400, #e0e0e0);border-radius:8px;background-color:var(--uic-bg-color, #fff)}.uic-repeater .uic-repeater-item .uic-repeater-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px;border-bottom:1px solid var(--primary-400);padding:5px 10px;min-height:34px}.uic-repeater .uic-repeater-item .uic-repeater-item-header .uic-repeater-item-title{margin:0;font-size:14px;font-weight:600;color:var(--primary-700)}.uic-repeater .uic-repeater-item .uic-repeater-item-body{width:100%;padding:0 12px}.uic-repeater .uic-repeater-add-action{margin-top:1px}.uic-repeater .uic-repeater-error{margin:4px 0 0;font-size:12px;color:var(--uic-red, #e53935)}.repeater-label{font-size:max(var(--form-ref) + 4px,14px);line-height:1.125rem;min-height:1.125rem;font-weight:400;color:var(--grey-950);margin-bottom:var(--input-label-space)}\n"] }]
4336
+ ], template: "<div class=\"repeater-label\"> {{field.label}} </div>\r\n<div class=\"uic-repeater\" [class.disabled]=\"formArray.disabled\">\r\n @for (group of formArray.controls; track $index) {\r\n <div class=\"uic-repeater-item\">\r\n <div class=\"uic-repeater-item-header\">\r\n <div class=\"uic-repeater-item-title\">\r\n {{ field.repeaterItemTitle || field.label || 'Item' }} {{ $index + 1 }}\r\n </div>\r\n @if (canRemove && !formArray.disabled) {\r\n <ui-button \r\n [icon]=\"'ri-delete-bin-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'red'\" \r\n size=\"s\" \r\n (click)=\"removeGroup($index)\"\r\n [text]=\"field.repeaterRemoveLabel || 'Eliminar'\">\r\n </ui-button>\r\n }\r\n </div>\r\n <div class=\"uic-repeater-item-body\">\r\n <ui-dynamic-form \r\n [form]=\"getGroup($index)\" \r\n [fields]=\"getItemFields(group)\" \r\n [disabled]=\"formArray.disabled\"\r\n [cols]=\"cols\"\r\n [fileUidResolverFn]=\"fileUidResolverFn\"\r\n [selectOptionsResolver]=\"selectOptionsResolver\"\r\n [parentFormValues]=\"getParentFormValues()\"\r\n [isSubForm]=\"true\">\r\n </ui-dynamic-form>\r\n </div>\r\n </div>\r\n }\r\n \r\n @if (canAdd && !formArray.disabled) {\r\n <div class=\"uic-repeater-add-action\">\r\n <ui-button \r\n [icon]=\"'ri-add-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'primary'\" \r\n (click)=\"addGroup()\"\r\n [text]=\"field.repeaterAddLabel || 'A\u00F1adir'\">\r\n </ui-button>\r\n </div>\r\n }\r\n @if (error) {\r\n <p class=\"uic-repeater-error\">{{ error }}</p>\r\n }\r\n</div>\r\n", styles: [".uic-repeater{display:flex;flex-direction:column;gap:16px;width:100%}.uic-repeater.disabled{opacity:.7}.uic-repeater .uic-repeater-item{border:1px solid var(--primary-400, #e0e0e0);border-radius:8px;background-color:var(--uic-bg-color, #fff)}.uic-repeater .uic-repeater-item .uic-repeater-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px;border-bottom:1px solid var(--primary-400);padding:5px 10px;min-height:34px}.uic-repeater .uic-repeater-item .uic-repeater-item-header .uic-repeater-item-title{margin:0;font-size:14px;font-weight:600;color:var(--primary-700)}.uic-repeater .uic-repeater-item .uic-repeater-item-body{width:100%;padding:0 12px}.uic-repeater .uic-repeater-add-action{margin-top:1px}.uic-repeater .uic-repeater-error{margin:4px 0 0;font-size:12px;color:var(--uic-red, #e53935)}.repeater-label{font-size:max(var(--form-ref) + 4px,14px);line-height:1.125rem;min-height:1.125rem;font-weight:400;color:var(--grey-950);margin-bottom:var(--input-label-space)}\n"] }]
4292
4337
  }], propDecorators: { formArray: [{
4293
4338
  type: Input,
4294
4339
  args: [{ required: true }]
@@ -4427,6 +4472,14 @@ class UicDynamicFormComponent {
4427
4472
  }
4428
4473
  getValueByFieldName(fieldName) {
4429
4474
  const formValues = this.formState.values();
4475
+ // Sub-formulario (ítem de repeater): gana el hermano. Primero se busca en el
4476
+ // propio ítem y, si no existe, se cae al formulario raíz. Las referencias solo
4477
+ // van de menor a mayor o igual ámbito (ítem -> ítem/raíz), nunca raíz -> ítem.
4478
+ if (this.isSubForm) {
4479
+ const localControl = this.formSignal()?.controls[fieldName];
4480
+ if (localControl)
4481
+ return localControl.getRawValue();
4482
+ }
4430
4483
  if (Object.prototype.hasOwnProperty.call(formValues, fieldName)) {
4431
4484
  return formValues[fieldName];
4432
4485
  }
@@ -5047,6 +5100,9 @@ class UicFormWrapperComponent {
5047
5100
  formValueSub = null;
5048
5101
  optionSourceSubs = new Map();
5049
5102
  optionSourceDependencyValueByField = new Map();
5103
+ rowOptionSourceSubs = new Map();
5104
+ rowOptionSourceDependencyKeys = new WeakMap();
5105
+ formState = inject(UicFormStateService);
5050
5106
  computedFieldSubs = new Map();
5051
5107
  computedFieldDependencySignatureByField = new Map();
5052
5108
  computedExternalValidationLastValue = new Map();
@@ -5358,12 +5414,106 @@ class UicFormWrapperComponent {
5358
5414
  if (field.type !== 'repeater' || !field.repeaterFields?.length)
5359
5415
  continue;
5360
5416
  field.repeaterFields.forEach(subField => {
5361
- if (this.hasUsableOptionsSource(subField)) {
5417
+ // Con dependsOn se resuelve por ítem (ver updateRowScopedSubFieldOptionsSources).
5418
+ if (this.hasUsableOptionsSource(subField) && !subField.optionsSource?.dependsOn) {
5362
5419
  this.resolveRepeaterSubFieldOptionsSource(field, subField, force);
5363
5420
  }
5364
5421
  });
5365
5422
  }
5366
5423
  }
5424
+ this.updateRowScopedSubFieldOptionsSources(force);
5425
+ }
5426
+ /**
5427
+ * Subcampos con optionsSource.dependsOn: cada ítem resuelve sus propias opciones.
5428
+ * La dependencia sigue la regla de ámbito "gana el hermano": primero el ítem, luego el raíz
5429
+ * (las relaciones van de menor a mayor o igual ámbito, nunca raíz -> ítem).
5430
+ */
5431
+ updateRowScopedSubFieldOptionsSources(force = false) {
5432
+ const activeRows = new Set();
5433
+ for (const block of this.effectiveSchema?.blocks ?? []) {
5434
+ for (const field of block.fields) {
5435
+ if (field.type !== 'repeater' || !field.repeaterFields?.length)
5436
+ continue;
5437
+ const dependentSubFields = field.repeaterFields.filter(subField => this.hasUsableOptionsSource(subField) && !!subField.optionsSource?.dependsOn);
5438
+ if (!dependentSubFields.length)
5439
+ continue;
5440
+ const formArray = this.form?.get(field.name);
5441
+ if (!formArray)
5442
+ continue;
5443
+ const rootValues = this.toNestedValues(this.form.getRawValue());
5444
+ formArray.controls.forEach(control => {
5445
+ const row = control;
5446
+ activeRows.add(row);
5447
+ dependentSubFields.forEach(subField => this.resolveRowSubFieldOptionsSource(row, subField, rootValues, force));
5448
+ });
5449
+ }
5450
+ }
5451
+ for (const [row, subs] of this.rowOptionSourceSubs) {
5452
+ if (activeRows.has(row))
5453
+ continue;
5454
+ subs.forEach(sub => sub.unsubscribe());
5455
+ this.rowOptionSourceSubs.delete(row);
5456
+ }
5457
+ }
5458
+ resolveRowSubFieldOptionsSource(row, subField, rootValues, force) {
5459
+ const source = subField.optionsSource;
5460
+ const dependsOn = source.dependsOn;
5461
+ if (!this.selectOptionsResolver) {
5462
+ this.formState.setRowFieldOptions(row, subField.name, { options: subField.options ?? [], loading: false });
5463
+ return;
5464
+ }
5465
+ const rowValues = this.toNestedValues(row.getRawValue());
5466
+ const dependencyValue = row.contains(dependsOn)
5467
+ ? row.get([dependsOn])?.value
5468
+ : this.getValueByPath(rootValues, dependsOn);
5469
+ const dependencyKey = `${dependsOn}:${this.safeStringify(dependencyValue ?? null)}`;
5470
+ let dependencyKeys = this.rowOptionSourceDependencyKeys.get(row);
5471
+ if (!dependencyKeys) {
5472
+ dependencyKeys = new Map();
5473
+ this.rowOptionSourceDependencyKeys.set(row, dependencyKeys);
5474
+ }
5475
+ if (!force && dependencyKeys.get(subField.name) === dependencyKey)
5476
+ return;
5477
+ dependencyKeys.set(subField.name, dependencyKey);
5478
+ let subs = this.rowOptionSourceSubs.get(row);
5479
+ if (!subs) {
5480
+ subs = new Map();
5481
+ this.rowOptionSourceSubs.set(row, subs);
5482
+ }
5483
+ subs.get(subField.name)?.unsubscribe();
5484
+ subs.delete(subField.name);
5485
+ const control = row.get([subField.name]);
5486
+ if (dependencyValue === null || dependencyValue === undefined || dependencyValue === '') {
5487
+ if (control)
5488
+ this.clearControlValue(control, subField);
5489
+ this.formState.setRowFieldOptions(row, subField.name, { options: [], loading: false });
5490
+ return;
5491
+ }
5492
+ this.formState.setRowFieldOptions(row, subField.name, { loading: true });
5493
+ const values = { ...rootValues, ...rowValues };
5494
+ let optionsResult;
5495
+ try {
5496
+ optionsResult = this.selectOptionsResolver(source, { field: subField, values, dependencyValue });
5497
+ }
5498
+ catch (error) {
5499
+ this.handleRowOptionsSourceError(row, subField, source, error);
5500
+ return;
5501
+ }
5502
+ const sub = this.toObservable(optionsResult).subscribe({
5503
+ next: items => {
5504
+ const options = this.mapOptionsSourceItems(items, source);
5505
+ this.formState.setRowFieldOptions(row, subField.name, { options, loading: false });
5506
+ if (control)
5507
+ this.clearInvalidControlValue(control, options);
5508
+ },
5509
+ error: (error) => this.handleRowOptionsSourceError(row, subField, source, error),
5510
+ complete: () => this.formState.setRowFieldOptions(row, subField.name, { loading: false })
5511
+ });
5512
+ subs.set(subField.name, sub);
5513
+ }
5514
+ handleRowOptionsSourceError(row, subField, source, error) {
5515
+ this.formState.setRowFieldOptions(row, subField.name, { options: [], loading: false });
5516
+ this.optionsSourceError.emit({ field: subField, source, error });
5367
5517
  }
5368
5518
  resolveRepeaterSubFieldOptionsSource(parentField, subField, force = false) {
5369
5519
  const source = subField.optionsSource;
@@ -5435,17 +5585,8 @@ class UicFormWrapperComponent {
5435
5585
  this.updateDependentRepeaterSubFieldOptionsSources();
5436
5586
  }
5437
5587
  updateDependentRepeaterSubFieldOptionsSources() {
5438
- for (const block of this.effectiveSchema?.blocks ?? []) {
5439
- for (const field of block.fields) {
5440
- if (field.type !== 'repeater' || !field.repeaterFields?.length)
5441
- continue;
5442
- field.repeaterFields.forEach(subField => {
5443
- if (this.hasUsableOptionsSource(subField) && subField.optionsSource?.dependsOn) {
5444
- this.resolveRepeaterSubFieldOptionsSource(field, subField, true);
5445
- }
5446
- });
5447
- }
5448
- }
5588
+ // Sin force: cada ítem solo vuelve a resolver si cambió el valor de su dependencia.
5589
+ this.updateRowScopedSubFieldOptionsSources();
5449
5590
  }
5450
5591
  resolveOptionsSourceField(field, force = false) {
5451
5592
  const source = field.optionsSource;
@@ -5570,6 +5711,9 @@ class UicFormWrapperComponent {
5570
5711
  const control = this.getFieldControl(fieldName);
5571
5712
  if (!control)
5572
5713
  return;
5714
+ this.clearInvalidControlValue(control, options);
5715
+ }
5716
+ clearInvalidControlValue(control, options) {
5573
5717
  const currentValue = control.value;
5574
5718
  if (currentValue === null || currentValue === undefined || currentValue === '')
5575
5719
  return;
@@ -5591,6 +5735,9 @@ class UicFormWrapperComponent {
5591
5735
  const control = this.getFieldControl(field.name);
5592
5736
  if (!control)
5593
5737
  return;
5738
+ this.clearControlValue(control, field);
5739
+ }
5740
+ clearControlValue(control, field) {
5594
5741
  const blankValue = this.blankValue(field);
5595
5742
  if (control.value !== blankValue) {
5596
5743
  control.setValue(blankValue, { emitEvent: false });
@@ -5623,6 +5770,8 @@ class UicFormWrapperComponent {
5623
5770
  this.optionSourceSubs.forEach(sub => sub.unsubscribe());
5624
5771
  this.optionSourceSubs.clear();
5625
5772
  this.optionSourceDependencyValueByField.clear();
5773
+ this.rowOptionSourceSubs.forEach(subs => subs.forEach(sub => sub.unsubscribe()));
5774
+ this.rowOptionSourceSubs.clear();
5626
5775
  }
5627
5776
  clearComputedFieldSubs() {
5628
5777
  this.computedFieldSubs.forEach(sub => sub.unsubscribe());
@@ -7561,6 +7710,9 @@ function mapEditableBlocksToBlocks(blocks, editable) {
7561
7710
  }
7562
7711
  : field.fieldData.optionsSource;
7563
7712
  const isComputedField = field.fieldData.type === 'computed';
7713
+ // Los códigos sf_N se repiten entre repeaters: las reglas de un subcampo
7714
+ // se resuelven primero contra los hermanos de su propio repeater.
7715
+ const siblingCodeToName = new Map((field.repeaterSubFields ?? []).map(sf => [sf.code, sf.fieldData.name]));
7564
7716
  return {
7565
7717
  ...field.fieldData,
7566
7718
  type: isComputedField ? 'text' : field.fieldData.type,
@@ -7579,7 +7731,7 @@ function mapEditableBlocksToBlocks(blocks, editable) {
7579
7731
  const sfIsComputed = sf.fieldData.type === 'computed';
7580
7732
  const sfVisibilityRules = sf.fieldData.visibilityRules?.map(rule => ({
7581
7733
  ...rule,
7582
- fieldName: fieldCodeToName.get(rule.fieldName) ?? rule.fieldName
7734
+ fieldName: siblingCodeToName.get(rule.fieldName) ?? fieldCodeToName.get(rule.fieldName) ?? rule.fieldName
7583
7735
  }));
7584
7736
  const sfOptionsSource = sf.fieldData.optionsSource?.dependsOn
7585
7737
  ? {
@@ -10977,7 +11129,7 @@ class FieldEditorComponent {
10977
11129
  });
10978
11130
  }
10979
11131
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FieldEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10980
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: FieldEditorComponent, isStandalone: true, selector: "lib-field-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, focusRequiredField: { classPropertyName: "focusRequiredField", publicName: "focusRequiredField", isSignal: true, isRequired: false, transformFunction: null }, isSubField: { classPropertyName: "isSubField", publicName: "isSubField", isSignal: true, isRequired: false, transformFunction: null }, enableNameModify: { classPropertyName: "enableNameModify", publicName: "enableNameModify", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fieldChange: "fieldChange" }, ngImport: i0, template: "<div class=\"props-title\">{{'form_builder.field_editor.basic' | uicTranslate}} <i (click)=\"toggleSection('basic')\" class=\"{{hiddenSections().includes('basic') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('basic')\">\r\n <ui-form-wrapper\r\n #basicFormWrapper\r\n [fields]=\"requiredFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [focusFieldName]=\"focusRequiredField() ? 'label' : null\"\r\n [focusFieldTrigger]=\"focusRequiredField() ? config().code : null\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n @if (hasOptionsSourceConfig()) {\r\n <ui-form-wrapper\r\n [fields]=\"optionsSourceFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n @if (hasOptions() && !hasExternalOptionsSource()) {\r\n <ui-field-options-editor [options]=\"localField().options ?? []\" (optionsChange)=\"updateOptions($event)\"></ui-field-options-editor>\r\n }\r\n }\r\n @if (isComputed()) {\r\n <ui-form-wrapper\r\n [fields]=\"computedSourceFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n }\r\n</div>\r\n\r\n<div class=\"props-title\">{{'form_builder.field_editor.advanced' | uicTranslate}} <i (click)=\"toggleSection('advanced')\" class=\"{{hiddenSections().includes('advanced') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('advanced')\">\r\n <ui-form-wrapper\r\n [fields]=\"advancedFields()\" \r\n [initialValues]=\"initialValues()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n</div>\r\n\r\n<div class=\"props-title\">{{'form_builder.field_editor.style' | uicTranslate}} <i (click)=\"toggleSection('style')\" class=\"{{hiddenSections().includes('style') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('style')\">\r\n <ui-form-wrapper\r\n [fields]=\"styleFields()\" \r\n [initialValues]=\"initialValues()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\"> \r\n </ui-form-wrapper>\r\n</div>\r\n\r\n@if (!isSubField() && hasExternalValidation()) {\r\n <div class=\"props-title\">{{'form_builder.field_editor.external_validation_title' | uicTranslate}} <i (click)=\"toggleSection('external_validation')\" class=\"{{hiddenSections().includes('external_validation') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i></div>\r\n <div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('external_validation')\">\r\n <ui-form-wrapper\r\n [fields]=\"externalValidationFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n </div>\r\n}\r\n\r\n@if (!isSubField()) {\r\n <div class=\"props-title\">{{'form_builder.field_editor.dependency_title' | uicTranslate}} <i (click)=\"toggleSection('dependency')\" class=\"{{hiddenSections().includes('dependency') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n <div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('dependency')\">\r\n @if (localField().visibilityRules) {\r\n <p>{{'form_builder.field_editor.dependency_description' | uicTranslate}}</p>\r\n \r\n <!-- List of existing rules -->\r\n <div class=\"rules-container\">\r\n @for (rule of localField().visibilityRules; track $index) {\r\n <div class=\"rule-card\" [class.editing]=\"editingRuleIndex() === $index && !isAddingNewRule()\">\r\n <div class=\"rule-content\">\r\n <div class=\"rule-text\">\r\n <strong>{{ rule.fieldLabel || rule.fieldName }}</strong>\r\n @if (rule.operator) {\r\n <span class=\"rule-operator\">{{ 'form_builder.visibility_operators.' + rule.operator | uicTranslate }}</span>\r\n }\r\n @if (rule.value !== null && rule.value !== undefined) {\r\n <span class=\"rule-value\">{{ rule.value }}</span>\r\n }\r\n </div>\r\n </div>\r\n @if (editingRuleIndex() === -1) {\r\n <div class=\"rule-actions\">\r\n <button class=\"rule-btn edit\" (click)=\"startEditingRule($index)\" title=\"Editar\">\r\n <i class=\"ri-edit-line\"></i>\r\n </button>\r\n <button class=\"rule-btn delete\" (click)=\"removeRule($index)\" title=\"Eliminar\">\r\n <i class=\"ri-delete-bin-line\"></i>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n <!-- Inline edit form for existing rule -->\r\n @if (editingRuleIndex() === $index && !isAddingNewRule()) {\r\n <div class=\"rule-editor\">\r\n <ui-form-wrapper\r\n [fields]=\"branchFields()\" \r\n [initialValues]=\"branchInitialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateRuleValue($event)\">\r\n </ui-form-wrapper>\r\n <div class=\"editor-actions\">\r\n <ui-button color=\"black\" size=\"s\" (click)=\"cancelEditingRule()\">{{'form_builder.field_editor.cancel' | uicTranslate}}</ui-button>\r\n <ui-button color=\"primary\" size=\"s\" (click)=\"confirmEditingRule()\">{{'form_builder.field_editor.save' | uicTranslate}}</ui-button>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- New rule form (only while adding) -->\r\n @if (isAddingNewRule()) {\r\n <div class=\"rule-editor new-rule\">\r\n <ui-form-wrapper\r\n [fields]=\"branchFields()\" \r\n [initialValues]=\"branchInitialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateRuleValue($event)\">\r\n </ui-form-wrapper>\r\n <div class=\"editor-actions\">\r\n <ui-button color=\"black\" size=\"s\" (click)=\"cancelEditingRule()\">{{'form_builder.field_editor.cancel' | uicTranslate}}</ui-button>\r\n <ui-button color=\"primary\" size=\"s\" (click)=\"confirmEditingRule()\">{{'form_builder.field_editor.save' | uicTranslate}}</ui-button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Add button (hidden while editing) -->\r\n @if (editingRuleIndex() === -1) {\r\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\r\n }\r\n } @else {\r\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\r\n }\r\n </div>\r\n}\r\n", styles: [".hidden{display:none}.props-title{font-size:14px;font-weight:600;margin-bottom:8px;background:var(--grey-200);padding:5px;border-radius:5px;display:flex;justify-content:space-between}.props-title i{cursor:pointer}.props-inputs{padding-left:20px;margin-bottom:10px}p{font-size:14px;margin:10px 0;color:var(--yellow-800)}.rules-container{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}.rule-card{display:flex;align-items:center;justify-content:space-between;padding:6px 8px;border:1px solid var(--grey-300);border-radius:3px;background:var(--white);font-size:12px}.rule-card.editing{border-color:var(--primary-400, #6366f1);border-bottom:none;border-radius:3px 3px 0 0}.rule-card .rule-content{flex:1;min-width:0}.rule-card .rule-text{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.rule-card .rule-text strong{font-weight:600;color:var(--grey-800)}.rule-card .rule-text .rule-operator{font-style:italic;color:var(--grey-600)}.rule-card .rule-text .rule-value{background:var(--grey-100);padding:0 3px;border-radius:2px;color:var(--grey-800)}.rule-actions{display:flex;gap:4px;flex-shrink:0;margin-left:4px}.rule-btn{background:none;border:none;cursor:pointer;padding:2px 4px;display:flex;align-items:center;justify-content:center;font-size:14px;color:var(--grey-600);transition:color .2s}.rule-btn:hover{color:var(--grey-800)}.rule-btn.delete{color:var(--red-600)}.rule-btn.delete:hover{color:var(--red-800)}.rule-editor{padding:8px;border:1px solid var(--primary-400, #6366f1);border-radius:0 0 3px 3px;background:var(--grey-50);margin-bottom:6px}.rule-editor.new-rule{border-radius:3px;margin-top:4px}.editor-actions{display:flex;gap:4px;margin-top:6px}\n"], dependencies: [{ kind: "component", type: UicFormWrapperComponent, selector: "ui-form-wrapper", inputs: ["schema", "fields", "cols", "externalData", "selectOptionsResolver", "computedFieldResolver", "externalValidatorResolver", "loading", "disabled", "showButtons", "iconMode", "fillSelects", "initialValues", "focusFieldName", "focusFieldTrigger", "fileUidResolverFn"], outputs: ["formSubmit", "formChange", "optionsSourceError"] }, { kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "component", type: UicFieldOptionsEditorComponent, selector: "ui-field-options-editor", inputs: ["options"], outputs: ["optionsChange"] }] });
11132
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: FieldEditorComponent, isStandalone: true, selector: "lib-field-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, focusRequiredField: { classPropertyName: "focusRequiredField", publicName: "focusRequiredField", isSignal: true, isRequired: false, transformFunction: null }, isSubField: { classPropertyName: "isSubField", publicName: "isSubField", isSignal: true, isRequired: false, transformFunction: null }, enableNameModify: { classPropertyName: "enableNameModify", publicName: "enableNameModify", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fieldChange: "fieldChange" }, ngImport: i0, template: "<div class=\"props-title\">{{'form_builder.field_editor.basic' | uicTranslate}} <i (click)=\"toggleSection('basic')\" class=\"{{hiddenSections().includes('basic') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('basic')\">\n <ui-form-wrapper\n #basicFormWrapper\n [fields]=\"requiredFields()\"\n [initialValues]=\"initialValues()\"\n [focusFieldName]=\"focusRequiredField() ? 'label' : null\"\n [focusFieldTrigger]=\"focusRequiredField() ? config().code : null\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n @if (hasOptionsSourceConfig()) {\n <ui-form-wrapper\n [fields]=\"optionsSourceFields()\"\n [initialValues]=\"initialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n @if (hasOptions() && !hasExternalOptionsSource()) {\n <ui-field-options-editor [options]=\"localField().options ?? []\" (optionsChange)=\"updateOptions($event)\"></ui-field-options-editor>\n }\n }\n @if (isComputed()) {\n <ui-form-wrapper\n [fields]=\"computedSourceFields()\"\n [initialValues]=\"initialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n }\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.advanced' | uicTranslate}} <i (click)=\"toggleSection('advanced')\" class=\"{{hiddenSections().includes('advanced') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('advanced')\">\n <ui-form-wrapper\n [fields]=\"advancedFields()\" \n [initialValues]=\"initialValues()\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.style' | uicTranslate}} <i (click)=\"toggleSection('style')\" class=\"{{hiddenSections().includes('style') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('style')\">\n <ui-form-wrapper\n [fields]=\"styleFields()\" \n [initialValues]=\"initialValues()\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\"> \n </ui-form-wrapper>\n</div>\n\n@if (!isSubField() && hasExternalValidation()) {\n <div class=\"props-title\">{{'form_builder.field_editor.external_validation_title' | uicTranslate}} <i (click)=\"toggleSection('external_validation')\" class=\"{{hiddenSections().includes('external_validation') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i></div>\n <div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('external_validation')\">\n <ui-form-wrapper\n [fields]=\"externalValidationFields()\"\n [initialValues]=\"initialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n </div>\n}\n\n<div class=\"props-title\">{{'form_builder.field_editor.dependency_title' | uicTranslate}} <i (click)=\"toggleSection('dependency')\" class=\"{{hiddenSections().includes('dependency') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('dependency')\">\n @if (localField().visibilityRules) {\n <p>{{'form_builder.field_editor.dependency_description' | uicTranslate}}</p>\n \n <!-- List of existing rules -->\n <div class=\"rules-container\">\n @for (rule of localField().visibilityRules; track $index) {\n <div class=\"rule-card\" [class.editing]=\"editingRuleIndex() === $index && !isAddingNewRule()\">\n <div class=\"rule-content\">\n <div class=\"rule-text\">\n <strong>{{ rule.fieldLabel || rule.fieldName }}</strong>\n @if (rule.operator) {\n <span class=\"rule-operator\">{{ 'form_builder.visibility_operators.' + rule.operator | uicTranslate }}</span>\n }\n @if (rule.value !== null && rule.value !== undefined) {\n <span class=\"rule-value\">{{ rule.value }}</span>\n }\n </div>\n </div>\n @if (editingRuleIndex() === -1) {\n <div class=\"rule-actions\">\n <button class=\"rule-btn edit\" (click)=\"startEditingRule($index)\" title=\"Editar\">\n <i class=\"ri-edit-line\"></i>\n </button>\n <button class=\"rule-btn delete\" (click)=\"removeRule($index)\" title=\"Eliminar\">\n <i class=\"ri-delete-bin-line\"></i>\n </button>\n </div>\n }\n </div>\n <!-- Inline edit form for existing rule -->\n @if (editingRuleIndex() === $index && !isAddingNewRule()) {\n <div class=\"rule-editor\">\n <ui-form-wrapper\n [fields]=\"branchFields()\" \n [initialValues]=\"branchInitialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\" \n (formChange)=\"updateRuleValue($event)\">\n </ui-form-wrapper>\n <div class=\"editor-actions\">\n <ui-button color=\"black\" size=\"s\" (click)=\"cancelEditingRule()\">{{'form_builder.field_editor.cancel' | uicTranslate}}</ui-button>\n <ui-button color=\"primary\" size=\"s\" (click)=\"confirmEditingRule()\">{{'form_builder.field_editor.save' | uicTranslate}}</ui-button>\n </div>\n </div>\n }\n }\n </div>\n\n <!-- New rule form (only while adding) -->\n @if (isAddingNewRule()) {\n <div class=\"rule-editor new-rule\">\n <ui-form-wrapper\n [fields]=\"branchFields()\" \n [initialValues]=\"branchInitialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\" \n (formChange)=\"updateRuleValue($event)\">\n </ui-form-wrapper>\n <div class=\"editor-actions\">\n <ui-button color=\"black\" size=\"s\" (click)=\"cancelEditingRule()\">{{'form_builder.field_editor.cancel' | uicTranslate}}</ui-button>\n <ui-button color=\"primary\" size=\"s\" (click)=\"confirmEditingRule()\">{{'form_builder.field_editor.save' | uicTranslate}}</ui-button>\n </div>\n </div>\n }\n\n <!-- Add button (hidden while editing) -->\n @if (editingRuleIndex() === -1) {\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\n }\n } @else {\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\n }\n</div>\n", styles: [".hidden{display:none}.props-title{font-size:14px;font-weight:600;margin-bottom:8px;background:var(--grey-200);padding:5px;border-radius:5px;display:flex;justify-content:space-between}.props-title i{cursor:pointer}.props-inputs{padding-left:20px;margin-bottom:10px}p{font-size:14px;margin:10px 0;color:var(--yellow-800)}.rules-container{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}.rule-card{display:flex;align-items:center;justify-content:space-between;padding:6px 8px;border:1px solid var(--grey-300);border-radius:3px;background:var(--white);font-size:12px}.rule-card.editing{border-color:var(--primary-400, #6366f1);border-bottom:none;border-radius:3px 3px 0 0}.rule-card .rule-content{flex:1;min-width:0}.rule-card .rule-text{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.rule-card .rule-text strong{font-weight:600;color:var(--grey-800)}.rule-card .rule-text .rule-operator{font-style:italic;color:var(--grey-600)}.rule-card .rule-text .rule-value{background:var(--grey-100);padding:0 3px;border-radius:2px;color:var(--grey-800)}.rule-actions{display:flex;gap:4px;flex-shrink:0;margin-left:4px}.rule-btn{background:none;border:none;cursor:pointer;padding:2px 4px;display:flex;align-items:center;justify-content:center;font-size:14px;color:var(--grey-600);transition:color .2s}.rule-btn:hover{color:var(--grey-800)}.rule-btn.delete{color:var(--red-600)}.rule-btn.delete:hover{color:var(--red-800)}.rule-editor{padding:8px;border:1px solid var(--primary-400, #6366f1);border-radius:0 0 3px 3px;background:var(--grey-50);margin-bottom:6px}.rule-editor.new-rule{border-radius:3px;margin-top:4px}.editor-actions{display:flex;gap:4px;margin-top:6px}\n"], dependencies: [{ kind: "component", type: UicFormWrapperComponent, selector: "ui-form-wrapper", inputs: ["schema", "fields", "cols", "externalData", "selectOptionsResolver", "computedFieldResolver", "externalValidatorResolver", "loading", "disabled", "showButtons", "iconMode", "fillSelects", "initialValues", "focusFieldName", "focusFieldTrigger", "fileUidResolverFn"], outputs: ["formSubmit", "formChange", "optionsSourceError"] }, { kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "component", type: UicFieldOptionsEditorComponent, selector: "ui-field-options-editor", inputs: ["options"], outputs: ["optionsChange"] }] });
10981
11133
  }
10982
11134
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FieldEditorComponent, decorators: [{
10983
11135
  type: Component,
@@ -10986,7 +11138,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
10986
11138
  UicButtonComponent,
10987
11139
  UicTranslatePipe,
10988
11140
  UicFieldOptionsEditorComponent
10989
- ], template: "<div class=\"props-title\">{{'form_builder.field_editor.basic' | uicTranslate}} <i (click)=\"toggleSection('basic')\" class=\"{{hiddenSections().includes('basic') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('basic')\">\r\n <ui-form-wrapper\r\n #basicFormWrapper\r\n [fields]=\"requiredFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [focusFieldName]=\"focusRequiredField() ? 'label' : null\"\r\n [focusFieldTrigger]=\"focusRequiredField() ? config().code : null\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n @if (hasOptionsSourceConfig()) {\r\n <ui-form-wrapper\r\n [fields]=\"optionsSourceFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n @if (hasOptions() && !hasExternalOptionsSource()) {\r\n <ui-field-options-editor [options]=\"localField().options ?? []\" (optionsChange)=\"updateOptions($event)\"></ui-field-options-editor>\r\n }\r\n }\r\n @if (isComputed()) {\r\n <ui-form-wrapper\r\n [fields]=\"computedSourceFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n }\r\n</div>\r\n\r\n<div class=\"props-title\">{{'form_builder.field_editor.advanced' | uicTranslate}} <i (click)=\"toggleSection('advanced')\" class=\"{{hiddenSections().includes('advanced') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('advanced')\">\r\n <ui-form-wrapper\r\n [fields]=\"advancedFields()\" \r\n [initialValues]=\"initialValues()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n</div>\r\n\r\n<div class=\"props-title\">{{'form_builder.field_editor.style' | uicTranslate}} <i (click)=\"toggleSection('style')\" class=\"{{hiddenSections().includes('style') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('style')\">\r\n <ui-form-wrapper\r\n [fields]=\"styleFields()\" \r\n [initialValues]=\"initialValues()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\"> \r\n </ui-form-wrapper>\r\n</div>\r\n\r\n@if (!isSubField() && hasExternalValidation()) {\r\n <div class=\"props-title\">{{'form_builder.field_editor.external_validation_title' | uicTranslate}} <i (click)=\"toggleSection('external_validation')\" class=\"{{hiddenSections().includes('external_validation') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i></div>\r\n <div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('external_validation')\">\r\n <ui-form-wrapper\r\n [fields]=\"externalValidationFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n </div>\r\n}\r\n\r\n@if (!isSubField()) {\r\n <div class=\"props-title\">{{'form_builder.field_editor.dependency_title' | uicTranslate}} <i (click)=\"toggleSection('dependency')\" class=\"{{hiddenSections().includes('dependency') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n <div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('dependency')\">\r\n @if (localField().visibilityRules) {\r\n <p>{{'form_builder.field_editor.dependency_description' | uicTranslate}}</p>\r\n \r\n <!-- List of existing rules -->\r\n <div class=\"rules-container\">\r\n @for (rule of localField().visibilityRules; track $index) {\r\n <div class=\"rule-card\" [class.editing]=\"editingRuleIndex() === $index && !isAddingNewRule()\">\r\n <div class=\"rule-content\">\r\n <div class=\"rule-text\">\r\n <strong>{{ rule.fieldLabel || rule.fieldName }}</strong>\r\n @if (rule.operator) {\r\n <span class=\"rule-operator\">{{ 'form_builder.visibility_operators.' + rule.operator | uicTranslate }}</span>\r\n }\r\n @if (rule.value !== null && rule.value !== undefined) {\r\n <span class=\"rule-value\">{{ rule.value }}</span>\r\n }\r\n </div>\r\n </div>\r\n @if (editingRuleIndex() === -1) {\r\n <div class=\"rule-actions\">\r\n <button class=\"rule-btn edit\" (click)=\"startEditingRule($index)\" title=\"Editar\">\r\n <i class=\"ri-edit-line\"></i>\r\n </button>\r\n <button class=\"rule-btn delete\" (click)=\"removeRule($index)\" title=\"Eliminar\">\r\n <i class=\"ri-delete-bin-line\"></i>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n <!-- Inline edit form for existing rule -->\r\n @if (editingRuleIndex() === $index && !isAddingNewRule()) {\r\n <div class=\"rule-editor\">\r\n <ui-form-wrapper\r\n [fields]=\"branchFields()\" \r\n [initialValues]=\"branchInitialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateRuleValue($event)\">\r\n </ui-form-wrapper>\r\n <div class=\"editor-actions\">\r\n <ui-button color=\"black\" size=\"s\" (click)=\"cancelEditingRule()\">{{'form_builder.field_editor.cancel' | uicTranslate}}</ui-button>\r\n <ui-button color=\"primary\" size=\"s\" (click)=\"confirmEditingRule()\">{{'form_builder.field_editor.save' | uicTranslate}}</ui-button>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- New rule form (only while adding) -->\r\n @if (isAddingNewRule()) {\r\n <div class=\"rule-editor new-rule\">\r\n <ui-form-wrapper\r\n [fields]=\"branchFields()\" \r\n [initialValues]=\"branchInitialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateRuleValue($event)\">\r\n </ui-form-wrapper>\r\n <div class=\"editor-actions\">\r\n <ui-button color=\"black\" size=\"s\" (click)=\"cancelEditingRule()\">{{'form_builder.field_editor.cancel' | uicTranslate}}</ui-button>\r\n <ui-button color=\"primary\" size=\"s\" (click)=\"confirmEditingRule()\">{{'form_builder.field_editor.save' | uicTranslate}}</ui-button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Add button (hidden while editing) -->\r\n @if (editingRuleIndex() === -1) {\r\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\r\n }\r\n } @else {\r\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\r\n }\r\n </div>\r\n}\r\n", styles: [".hidden{display:none}.props-title{font-size:14px;font-weight:600;margin-bottom:8px;background:var(--grey-200);padding:5px;border-radius:5px;display:flex;justify-content:space-between}.props-title i{cursor:pointer}.props-inputs{padding-left:20px;margin-bottom:10px}p{font-size:14px;margin:10px 0;color:var(--yellow-800)}.rules-container{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}.rule-card{display:flex;align-items:center;justify-content:space-between;padding:6px 8px;border:1px solid var(--grey-300);border-radius:3px;background:var(--white);font-size:12px}.rule-card.editing{border-color:var(--primary-400, #6366f1);border-bottom:none;border-radius:3px 3px 0 0}.rule-card .rule-content{flex:1;min-width:0}.rule-card .rule-text{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.rule-card .rule-text strong{font-weight:600;color:var(--grey-800)}.rule-card .rule-text .rule-operator{font-style:italic;color:var(--grey-600)}.rule-card .rule-text .rule-value{background:var(--grey-100);padding:0 3px;border-radius:2px;color:var(--grey-800)}.rule-actions{display:flex;gap:4px;flex-shrink:0;margin-left:4px}.rule-btn{background:none;border:none;cursor:pointer;padding:2px 4px;display:flex;align-items:center;justify-content:center;font-size:14px;color:var(--grey-600);transition:color .2s}.rule-btn:hover{color:var(--grey-800)}.rule-btn.delete{color:var(--red-600)}.rule-btn.delete:hover{color:var(--red-800)}.rule-editor{padding:8px;border:1px solid var(--primary-400, #6366f1);border-radius:0 0 3px 3px;background:var(--grey-50);margin-bottom:6px}.rule-editor.new-rule{border-radius:3px;margin-top:4px}.editor-actions{display:flex;gap:4px;margin-top:6px}\n"] }]
11141
+ ], template: "<div class=\"props-title\">{{'form_builder.field_editor.basic' | uicTranslate}} <i (click)=\"toggleSection('basic')\" class=\"{{hiddenSections().includes('basic') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('basic')\">\n <ui-form-wrapper\n #basicFormWrapper\n [fields]=\"requiredFields()\"\n [initialValues]=\"initialValues()\"\n [focusFieldName]=\"focusRequiredField() ? 'label' : null\"\n [focusFieldTrigger]=\"focusRequiredField() ? config().code : null\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n @if (hasOptionsSourceConfig()) {\n <ui-form-wrapper\n [fields]=\"optionsSourceFields()\"\n [initialValues]=\"initialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n @if (hasOptions() && !hasExternalOptionsSource()) {\n <ui-field-options-editor [options]=\"localField().options ?? []\" (optionsChange)=\"updateOptions($event)\"></ui-field-options-editor>\n }\n }\n @if (isComputed()) {\n <ui-form-wrapper\n [fields]=\"computedSourceFields()\"\n [initialValues]=\"initialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n }\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.advanced' | uicTranslate}} <i (click)=\"toggleSection('advanced')\" class=\"{{hiddenSections().includes('advanced') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('advanced')\">\n <ui-form-wrapper\n [fields]=\"advancedFields()\" \n [initialValues]=\"initialValues()\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.style' | uicTranslate}} <i (click)=\"toggleSection('style')\" class=\"{{hiddenSections().includes('style') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('style')\">\n <ui-form-wrapper\n [fields]=\"styleFields()\" \n [initialValues]=\"initialValues()\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\"> \n </ui-form-wrapper>\n</div>\n\n@if (!isSubField() && hasExternalValidation()) {\n <div class=\"props-title\">{{'form_builder.field_editor.external_validation_title' | uicTranslate}} <i (click)=\"toggleSection('external_validation')\" class=\"{{hiddenSections().includes('external_validation') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i></div>\n <div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('external_validation')\">\n <ui-form-wrapper\n [fields]=\"externalValidationFields()\"\n [initialValues]=\"initialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n </div>\n}\n\n<div class=\"props-title\">{{'form_builder.field_editor.dependency_title' | uicTranslate}} <i (click)=\"toggleSection('dependency')\" class=\"{{hiddenSections().includes('dependency') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('dependency')\">\n @if (localField().visibilityRules) {\n <p>{{'form_builder.field_editor.dependency_description' | uicTranslate}}</p>\n \n <!-- List of existing rules -->\n <div class=\"rules-container\">\n @for (rule of localField().visibilityRules; track $index) {\n <div class=\"rule-card\" [class.editing]=\"editingRuleIndex() === $index && !isAddingNewRule()\">\n <div class=\"rule-content\">\n <div class=\"rule-text\">\n <strong>{{ rule.fieldLabel || rule.fieldName }}</strong>\n @if (rule.operator) {\n <span class=\"rule-operator\">{{ 'form_builder.visibility_operators.' + rule.operator | uicTranslate }}</span>\n }\n @if (rule.value !== null && rule.value !== undefined) {\n <span class=\"rule-value\">{{ rule.value }}</span>\n }\n </div>\n </div>\n @if (editingRuleIndex() === -1) {\n <div class=\"rule-actions\">\n <button class=\"rule-btn edit\" (click)=\"startEditingRule($index)\" title=\"Editar\">\n <i class=\"ri-edit-line\"></i>\n </button>\n <button class=\"rule-btn delete\" (click)=\"removeRule($index)\" title=\"Eliminar\">\n <i class=\"ri-delete-bin-line\"></i>\n </button>\n </div>\n }\n </div>\n <!-- Inline edit form for existing rule -->\n @if (editingRuleIndex() === $index && !isAddingNewRule()) {\n <div class=\"rule-editor\">\n <ui-form-wrapper\n [fields]=\"branchFields()\" \n [initialValues]=\"branchInitialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\" \n (formChange)=\"updateRuleValue($event)\">\n </ui-form-wrapper>\n <div class=\"editor-actions\">\n <ui-button color=\"black\" size=\"s\" (click)=\"cancelEditingRule()\">{{'form_builder.field_editor.cancel' | uicTranslate}}</ui-button>\n <ui-button color=\"primary\" size=\"s\" (click)=\"confirmEditingRule()\">{{'form_builder.field_editor.save' | uicTranslate}}</ui-button>\n </div>\n </div>\n }\n }\n </div>\n\n <!-- New rule form (only while adding) -->\n @if (isAddingNewRule()) {\n <div class=\"rule-editor new-rule\">\n <ui-form-wrapper\n [fields]=\"branchFields()\" \n [initialValues]=\"branchInitialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\" \n (formChange)=\"updateRuleValue($event)\">\n </ui-form-wrapper>\n <div class=\"editor-actions\">\n <ui-button color=\"black\" size=\"s\" (click)=\"cancelEditingRule()\">{{'form_builder.field_editor.cancel' | uicTranslate}}</ui-button>\n <ui-button color=\"primary\" size=\"s\" (click)=\"confirmEditingRule()\">{{'form_builder.field_editor.save' | uicTranslate}}</ui-button>\n </div>\n </div>\n }\n\n <!-- Add button (hidden while editing) -->\n @if (editingRuleIndex() === -1) {\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\n }\n } @else {\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\n }\n</div>\n", styles: [".hidden{display:none}.props-title{font-size:14px;font-weight:600;margin-bottom:8px;background:var(--grey-200);padding:5px;border-radius:5px;display:flex;justify-content:space-between}.props-title i{cursor:pointer}.props-inputs{padding-left:20px;margin-bottom:10px}p{font-size:14px;margin:10px 0;color:var(--yellow-800)}.rules-container{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}.rule-card{display:flex;align-items:center;justify-content:space-between;padding:6px 8px;border:1px solid var(--grey-300);border-radius:3px;background:var(--white);font-size:12px}.rule-card.editing{border-color:var(--primary-400, #6366f1);border-bottom:none;border-radius:3px 3px 0 0}.rule-card .rule-content{flex:1;min-width:0}.rule-card .rule-text{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.rule-card .rule-text strong{font-weight:600;color:var(--grey-800)}.rule-card .rule-text .rule-operator{font-style:italic;color:var(--grey-600)}.rule-card .rule-text .rule-value{background:var(--grey-100);padding:0 3px;border-radius:2px;color:var(--grey-800)}.rule-actions{display:flex;gap:4px;flex-shrink:0;margin-left:4px}.rule-btn{background:none;border:none;cursor:pointer;padding:2px 4px;display:flex;align-items:center;justify-content:center;font-size:14px;color:var(--grey-600);transition:color .2s}.rule-btn:hover{color:var(--grey-800)}.rule-btn.delete{color:var(--red-600)}.rule-btn.delete:hover{color:var(--red-800)}.rule-editor{padding:8px;border:1px solid var(--primary-400, #6366f1);border-radius:0 0 3px 3px;background:var(--grey-50);margin-bottom:6px}.rule-editor.new-rule{border-radius:3px;margin-top:4px}.editor-actions{display:flex;gap:4px;margin-top:6px}\n"] }]
10990
11142
  }], ctorParameters: () => [] });
10991
11143
 
10992
11144
  class FieldTypeSelectorComponent {
@@ -11080,6 +11232,8 @@ class BlockEditorComponent {
11080
11232
  deleteSubField(parentCode, sfCode, event) {
11081
11233
  event.stopPropagation();
11082
11234
  const parentField = this.block().fields.find(f => f.code === parentCode);
11235
+ if (parentField && this.isSubFieldVisibilityParent(parentField, sfCode))
11236
+ return;
11083
11237
  const updated = (parentField?.repeaterSubFields ?? []).filter(sf => sf.code !== sfCode);
11084
11238
  this.updateSubFields(parentCode, updated);
11085
11239
  if (this.selectedSubFieldCode() === sfCode) {
@@ -11139,6 +11293,10 @@ class BlockEditorComponent {
11139
11293
  isVisibilityParent(fieldCode) {
11140
11294
  return this.visibilityParentFieldCodes.has(fieldCode);
11141
11295
  }
11296
+ // Las reglas de un subcampo solo referencian hermanos del mismo repeater (códigos sf_N no son únicos entre repeaters).
11297
+ isSubFieldVisibilityParent(parentField, sfCode) {
11298
+ return (parentField.repeaterSubFields ?? []).some(sf => sf.fieldData.visibilityRules?.some(rule => rule.fieldName === sfCode));
11299
+ }
11142
11300
  isBlockVisibilityParent() {
11143
11301
  return this.block().fields.some(field => this.isVisibilityParent(field.code));
11144
11302
  }
@@ -11150,7 +11308,7 @@ class BlockEditorComponent {
11150
11308
  this.blockChange.emit({ ...this.block(), fields: nextFields });
11151
11309
  }
11152
11310
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BlockEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11153
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: BlockEditorComponent, isStandalone: true, selector: "lib-block-editor", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, selectedFieldId: { classPropertyName: "selectedFieldId", publicName: "selectedFieldId", isSignal: true, isRequired: false, transformFunction: null }, selectedSubFieldCode: { classPropertyName: "selectedSubFieldCode", publicName: "selectedSubFieldCode", isSignal: true, isRequired: false, transformFunction: null }, selectedSubFieldParentCode: { classPropertyName: "selectedSubFieldParentCode", publicName: "selectedSubFieldParentCode", isSignal: true, isRequired: false, transformFunction: null }, visibilityParentFieldCodes: { classPropertyName: "visibilityParentFieldCodes", publicName: "visibilityParentFieldCodes", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { blockChange: "blockChange", addFieldRequest: "addFieldRequest", deleteBlock: "deleteBlock", notifySelectedField: "notifySelectedField", notifySelectedSubField: "notifySelectedSubField", notifyNewSubField: "notifyNewSubField" }, ngImport: i0, template: "<div class=\"form-block-card\">\r\n <div class=\"form-block-card-header\">\r\n <div>\r\n <input [placeholder]=\"'form_builder.block_title' | uicTranslate\" [ngModel]=\"block().title\" (ngModelChange)=\"changeTitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_subtitle' | uicTranslate\" [ngModel]=\"block().subtitle\" (ngModelChange)=\"changeSubtitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_message' | uicTranslate\" [ngModel]=\"block().message\" (ngModelChange)=\"changeMessage($event)\">\r\n </div>\r\n <ui-button\r\n [uiTooltip]=\"(isBlockVisibilityParent() ? 'form_builder.delete_block_dependency_blocked' : 'form_builder.delete_block') | uicTranslate\"\r\n [disabled]=\"isBlockVisibilityParent()\"\r\n (click)=\"requestDeleteBlock($event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n <div\r\n class=\"form-block-card-body\"\r\n cdkDropList\r\n [cdkDropListData]=\"block().fields\"\r\n (cdkDropListDropped)=\"reorderFields($event)\">\r\n \r\n <!-- FIELDS -->\r\n @for(edtField of block().fields; track edtField.code; let i = $index) {\r\n <div class=\"field-with-subfields\">\r\n <div\r\n class=\"xfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"isRepeaterParentSelected(edtField)\"\r\n (click)=\"selectField(edtField)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"edtField.field?.icon ?? ''\"></i> \r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b> {{edtField.fieldData.label}}\r\n @if (edtField.fieldData.hidden) {\r\n <i class=\"hidden-field ri-eye-off-line\" [uiTooltip]=\"'form_builder.base.hidden' | uicTranslate\"></i>\r\n }\r\n @if(edtField.fieldData.visibilityRules) {\r\n <i class=\"branched-field ri-git-merge-line\"></i>\r\n <span class=\"vs-rule\"> {{edtField.fieldData.visibilityRules[0]?.fieldLabel ?? '-'}} </span>\r\n }\r\n </b>\r\n <p> {{edtField.field?.label ?? edtField.type ?? edtField.fieldData.type}} </p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n @if (edtField.fieldData.type === 'repeater') {\r\n <ui-button\r\n [icon]=\"isRepeaterExpanded(edtField.code) ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'\"\r\n size=\"s\" color=\"black\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"toggleRepeater(edtField.code, $event)\">\r\n </ui-button>\r\n }\r\n <ui-button\r\n [uiTooltip]=\"(isVisibilityParent(edtField.code) ? 'form_builder.delete_field_dependency_blocked' : 'form_builder.field_editor.delete') | uicTranslate\"\r\n [disabled]=\"isVisibilityParent(edtField.code)\"\r\n (click)=\"deleteField(edtField.code, $event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n\r\n @if (edtField.fieldData.type === 'repeater' && isRepeaterExpanded(edtField.code)) {\r\n <div class=\"repeater-inline-panel\">\r\n <div\r\n class=\"repeater-subfields-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"edtField.repeaterSubFields ?? []\"\r\n (cdkDropListDropped)=\"reorderSubFields(edtField.code, $event)\">\r\n @for (sf of edtField.repeaterSubFields ?? []; track sf.code) {\r\n <div\r\n class=\"xfield-card subfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"selectedSubFieldCode() === sf.code && edtField.code === selectedSubFieldParentCode()\"\r\n (click)=\"onSelectSubField(edtField.code, sf, $event)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"sf.field?.icon ?? 'ri-question-line'\"></i>\r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b>{{ sf.fieldData.label || sf.fieldData.name }}\r\n @if (sf.fieldData.hidden) {\r\n <i class=\"hidden-field ri-eye-off-line\" [uiTooltip]=\"'form_builder.base.hidden' | uicTranslate\"></i>\r\n }\r\n </b>\r\n <p>{{ sf.field?.label ?? sf.type ?? sf.fieldData.type }}</p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n <ui-button\r\n size=\"s\" icon=\"ri-delete-bin-line\" color=\"red\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"deleteSubField(edtField.code, sf.code, $event)\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"empty-hint\">{{'form_builder.repeater.no_subfields' | uicTranslate}}</p>\r\n }\r\n </div>\r\n <div class=\"new-subfield\">\r\n {{'form_builder.repeater.add_subfield' | uicTranslate}}\r\n <lib-field-type-selector [excludeTypes]=\"excludeSubFieldTypes\" (selectType)=\"addSubField(edtField.code, $event)\"></lib-field-type-selector>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n\r\n </div>\r\n <div class=\"new-field\">\r\n {{'form_builder.add_new_field' | uicTranslate}}\r\n <lib-field-type-selector (selectType)=\"addField($event)\"></lib-field-type-selector>\r\n </div>\r\n</div>\r\n", styles: [".form-block-card{border:solid 1px var(--blue-500);border-radius:5px;overflow:hidden}.form-block-card-header{display:flex;gap:5px;align-items:center;background-color:#fff;padding:10px;border-bottom:solid 1px var(--grey-300)}.form-block-card-header>div{flex:1 1;gap:4px;display:flex;flex-direction:column}.form-block-card-header>div input{border:solid 1px var(--grey-100);padding:3px 6px;border-radius:5px}.form-block-card-header>div input:focus{border:solid 1px var(--primary-500);outline:none}.form-block-card-body{padding:15px;display:flex;flex-direction:column;background-color:var(--grey-50);gap:10px}.xfield-card{background-color:#fff;border-radius:5px;padding:10px;gap:10px;display:flex;align-items:center;border:solid 2px var(--grey-200);cursor:pointer;transition:border-color .3s ease}.xfield-card:hover{border-color:var(--grey-300)}.xfield-card-icon{display:flex;justify-content:center;align-items:center;border-radius:5px;width:30px;height:30px;font-size:20px;background-color:var(--grey-300);color:var(--grey-600)}.xfield-card-body{flex:1 1}.xfield-card-body b{display:flex;align-items:center;gap:5px}.xfield-card-body p{color:var(--grey-400);font-size:12px}.field-drag-handle{cursor:grab;color:var(--grey-400);transition:color .2s ease}.field-drag-handle:active{cursor:grabbing}.xfield-card:hover .field-drag-handle{color:var(--grey-600)}.cdk-drag-preview{box-sizing:border-box;border-radius:5px;box-shadow:0 6px 12px #0000002e}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.field-with-subfields{display:flex;flex-direction:column;gap:0}.repeater-inline-panel{background-color:var(--grey-100);border:solid 1px var(--blue-300);border-top:none;border-radius:0 0 5px 5px;padding:10px 10px 8px 28px;display:flex;flex-direction:column;gap:8px}.repeater-subfields-list{display:flex;flex-direction:column;gap:6px;min-height:6px}.subfield-card{font-size:13px;border-radius:4px;padding:7px 8px!important}.subfield-card .xfield-card-icon{width:26px!important;height:26px!important;font-size:16px!important}.subfield-card b{font-size:13px}.subfield-card p{font-size:11px}.new-subfield{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--grey-500);flex-wrap:wrap;padding-top:2px}.empty-hint{font-size:12px;color:var(--grey-400);text-align:center;padding:4px 0;margin:0}.form-block-card-body.cdk-drop-list-dragging .xfield-card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.branched-field{color:var(--yellow-600)}.hidden-field{color:var(--grey-500)}.selected-field,.selected-field:hover{border-color:var(--primary-500)}.new-field{border-top:solid 1px var(--grey-300);padding:10px;background-color:#fff;display:flex;flex-direction:column;gap:5px;font-size:14px}.vs-rule{font-size:12px;color:var(--grey-600)}\n"], dependencies: [{ kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "directive", type: UicToolTipDirective, selector: "[uiTooltip]", inputs: ["uiTooltip"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1$3.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1$3.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1$3.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: FieldTypeSelectorComponent, selector: "lib-field-type-selector", inputs: ["excludeTypes"], outputs: ["selectType"] }] });
11311
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: BlockEditorComponent, isStandalone: true, selector: "lib-block-editor", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, selectedFieldId: { classPropertyName: "selectedFieldId", publicName: "selectedFieldId", isSignal: true, isRequired: false, transformFunction: null }, selectedSubFieldCode: { classPropertyName: "selectedSubFieldCode", publicName: "selectedSubFieldCode", isSignal: true, isRequired: false, transformFunction: null }, selectedSubFieldParentCode: { classPropertyName: "selectedSubFieldParentCode", publicName: "selectedSubFieldParentCode", isSignal: true, isRequired: false, transformFunction: null }, visibilityParentFieldCodes: { classPropertyName: "visibilityParentFieldCodes", publicName: "visibilityParentFieldCodes", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { blockChange: "blockChange", addFieldRequest: "addFieldRequest", deleteBlock: "deleteBlock", notifySelectedField: "notifySelectedField", notifySelectedSubField: "notifySelectedSubField", notifyNewSubField: "notifyNewSubField" }, ngImport: i0, template: "<div class=\"form-block-card\">\r\n <div class=\"form-block-card-header\">\r\n <div>\r\n <input [placeholder]=\"'form_builder.block_title' | uicTranslate\" [ngModel]=\"block().title\" (ngModelChange)=\"changeTitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_subtitle' | uicTranslate\" [ngModel]=\"block().subtitle\" (ngModelChange)=\"changeSubtitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_message' | uicTranslate\" [ngModel]=\"block().message\" (ngModelChange)=\"changeMessage($event)\">\r\n </div>\r\n <ui-button\r\n [uiTooltip]=\"(isBlockVisibilityParent() ? 'form_builder.delete_block_dependency_blocked' : 'form_builder.delete_block') | uicTranslate\"\r\n [disabled]=\"isBlockVisibilityParent()\"\r\n (click)=\"requestDeleteBlock($event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n <div\r\n class=\"form-block-card-body\"\r\n cdkDropList\r\n [cdkDropListData]=\"block().fields\"\r\n (cdkDropListDropped)=\"reorderFields($event)\">\r\n \r\n <!-- FIELDS -->\r\n @for(edtField of block().fields; track edtField.code; let i = $index) {\r\n <div class=\"field-with-subfields\">\r\n <div\r\n class=\"xfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"isRepeaterParentSelected(edtField)\"\r\n (click)=\"selectField(edtField)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"edtField.field?.icon ?? ''\"></i> \r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b> {{edtField.fieldData.label}}\r\n @if (edtField.fieldData.hidden) {\r\n <i class=\"hidden-field ri-eye-off-line\" [uiTooltip]=\"'form_builder.base.hidden' | uicTranslate\"></i>\r\n }\r\n @if(edtField.fieldData.visibilityRules) {\r\n <i class=\"branched-field ri-git-merge-line\"></i>\r\n <span class=\"vs-rule\"> {{edtField.fieldData.visibilityRules[0]?.fieldLabel ?? '-'}} </span>\r\n }\r\n </b>\r\n <p> {{edtField.field?.label ?? edtField.type ?? edtField.fieldData.type}} </p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n @if (edtField.fieldData.type === 'repeater') {\r\n <ui-button\r\n [icon]=\"isRepeaterExpanded(edtField.code) ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'\"\r\n size=\"s\" color=\"black\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"toggleRepeater(edtField.code, $event)\">\r\n </ui-button>\r\n }\r\n <ui-button\r\n [uiTooltip]=\"(isVisibilityParent(edtField.code) ? 'form_builder.delete_field_dependency_blocked' : 'form_builder.field_editor.delete') | uicTranslate\"\r\n [disabled]=\"isVisibilityParent(edtField.code)\"\r\n (click)=\"deleteField(edtField.code, $event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n\r\n @if (edtField.fieldData.type === 'repeater' && isRepeaterExpanded(edtField.code)) {\r\n <div class=\"repeater-inline-panel\">\r\n <div\r\n class=\"repeater-subfields-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"edtField.repeaterSubFields ?? []\"\r\n (cdkDropListDropped)=\"reorderSubFields(edtField.code, $event)\">\r\n @for (sf of edtField.repeaterSubFields ?? []; track sf.code) {\r\n <div\r\n class=\"xfield-card subfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"selectedSubFieldCode() === sf.code && edtField.code === selectedSubFieldParentCode()\"\r\n (click)=\"onSelectSubField(edtField.code, sf, $event)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"sf.field?.icon ?? 'ri-question-line'\"></i>\r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b>{{ sf.fieldData.label || sf.fieldData.name }}\r\n @if (sf.fieldData.hidden) {\r\n <i class=\"hidden-field ri-eye-off-line\" [uiTooltip]=\"'form_builder.base.hidden' | uicTranslate\"></i>\r\n }\r\n @if (sf.fieldData.visibilityRules) {\r\n <i class=\"branched-field ri-git-merge-line\"></i>\r\n <span class=\"vs-rule\"> {{sf.fieldData.visibilityRules[0]?.fieldLabel ?? '-'}} </span>\r\n }\r\n </b>\r\n <p>{{ sf.field?.label ?? sf.type ?? sf.fieldData.type }}</p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n <ui-button\r\n [uiTooltip]=\"(isSubFieldVisibilityParent(edtField, sf.code) ? 'form_builder.delete_field_dependency_blocked' : 'form_builder.field_editor.delete') | uicTranslate\"\r\n [disabled]=\"isSubFieldVisibilityParent(edtField, sf.code)\"\r\n size=\"s\" icon=\"ri-delete-bin-line\" color=\"red\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"deleteSubField(edtField.code, sf.code, $event)\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"empty-hint\">{{'form_builder.repeater.no_subfields' | uicTranslate}}</p>\r\n }\r\n </div>\r\n <div class=\"new-subfield\">\r\n {{'form_builder.repeater.add_subfield' | uicTranslate}}\r\n <lib-field-type-selector [excludeTypes]=\"excludeSubFieldTypes\" (selectType)=\"addSubField(edtField.code, $event)\"></lib-field-type-selector>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n\r\n </div>\r\n <div class=\"new-field\">\r\n {{'form_builder.add_new_field' | uicTranslate}}\r\n <lib-field-type-selector (selectType)=\"addField($event)\"></lib-field-type-selector>\r\n </div>\r\n</div>\r\n", styles: [".form-block-card{border:solid 1px var(--blue-500);border-radius:5px;overflow:hidden}.form-block-card-header{display:flex;gap:5px;align-items:center;background-color:#fff;padding:10px;border-bottom:solid 1px var(--grey-300)}.form-block-card-header>div{flex:1 1;gap:4px;display:flex;flex-direction:column}.form-block-card-header>div input{border:solid 1px var(--grey-100);padding:3px 6px;border-radius:5px}.form-block-card-header>div input:focus{border:solid 1px var(--primary-500);outline:none}.form-block-card-body{padding:15px;display:flex;flex-direction:column;background-color:var(--grey-50);gap:10px}.xfield-card{background-color:#fff;border-radius:5px;padding:10px;gap:10px;display:flex;align-items:center;border:solid 2px var(--grey-200);cursor:pointer;transition:border-color .3s ease}.xfield-card:hover{border-color:var(--grey-300)}.xfield-card-icon{display:flex;justify-content:center;align-items:center;border-radius:5px;width:30px;height:30px;font-size:20px;background-color:var(--grey-300);color:var(--grey-600)}.xfield-card-body{flex:1 1}.xfield-card-body b{display:flex;align-items:center;gap:5px}.xfield-card-body p{color:var(--grey-400);font-size:12px}.field-drag-handle{cursor:grab;color:var(--grey-400);transition:color .2s ease}.field-drag-handle:active{cursor:grabbing}.xfield-card:hover .field-drag-handle{color:var(--grey-600)}.cdk-drag-preview{box-sizing:border-box;border-radius:5px;box-shadow:0 6px 12px #0000002e}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.field-with-subfields{display:flex;flex-direction:column;gap:0}.repeater-inline-panel{background-color:var(--grey-100);border:solid 1px var(--blue-300);border-top:none;border-radius:0 0 5px 5px;padding:10px 10px 8px 28px;display:flex;flex-direction:column;gap:8px}.repeater-subfields-list{display:flex;flex-direction:column;gap:6px;min-height:6px}.subfield-card{font-size:13px;border-radius:4px;padding:7px 8px!important}.subfield-card .xfield-card-icon{width:26px!important;height:26px!important;font-size:16px!important}.subfield-card b{font-size:13px}.subfield-card p{font-size:11px}.new-subfield{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--grey-500);flex-wrap:wrap;padding-top:2px}.empty-hint{font-size:12px;color:var(--grey-400);text-align:center;padding:4px 0;margin:0}.form-block-card-body.cdk-drop-list-dragging .xfield-card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.branched-field{color:var(--yellow-600)}.hidden-field{color:var(--grey-500)}.selected-field,.selected-field:hover{border-color:var(--primary-500)}.new-field{border-top:solid 1px var(--grey-300);padding:10px;background-color:#fff;display:flex;flex-direction:column;gap:5px;font-size:14px}.vs-rule{font-size:12px;color:var(--grey-600)}\n"], dependencies: [{ kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "directive", type: UicToolTipDirective, selector: "[uiTooltip]", inputs: ["uiTooltip"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1$3.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1$3.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1$3.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: FieldTypeSelectorComponent, selector: "lib-field-type-selector", inputs: ["excludeTypes"], outputs: ["selectType"] }] });
11154
11312
  }
11155
11313
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BlockEditorComponent, decorators: [{
11156
11314
  type: Component,
@@ -11161,7 +11319,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
11161
11319
  DragDropModule,
11162
11320
  FormsModule,
11163
11321
  FieldTypeSelectorComponent
11164
- ], template: "<div class=\"form-block-card\">\r\n <div class=\"form-block-card-header\">\r\n <div>\r\n <input [placeholder]=\"'form_builder.block_title' | uicTranslate\" [ngModel]=\"block().title\" (ngModelChange)=\"changeTitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_subtitle' | uicTranslate\" [ngModel]=\"block().subtitle\" (ngModelChange)=\"changeSubtitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_message' | uicTranslate\" [ngModel]=\"block().message\" (ngModelChange)=\"changeMessage($event)\">\r\n </div>\r\n <ui-button\r\n [uiTooltip]=\"(isBlockVisibilityParent() ? 'form_builder.delete_block_dependency_blocked' : 'form_builder.delete_block') | uicTranslate\"\r\n [disabled]=\"isBlockVisibilityParent()\"\r\n (click)=\"requestDeleteBlock($event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n <div\r\n class=\"form-block-card-body\"\r\n cdkDropList\r\n [cdkDropListData]=\"block().fields\"\r\n (cdkDropListDropped)=\"reorderFields($event)\">\r\n \r\n <!-- FIELDS -->\r\n @for(edtField of block().fields; track edtField.code; let i = $index) {\r\n <div class=\"field-with-subfields\">\r\n <div\r\n class=\"xfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"isRepeaterParentSelected(edtField)\"\r\n (click)=\"selectField(edtField)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"edtField.field?.icon ?? ''\"></i> \r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b> {{edtField.fieldData.label}}\r\n @if (edtField.fieldData.hidden) {\r\n <i class=\"hidden-field ri-eye-off-line\" [uiTooltip]=\"'form_builder.base.hidden' | uicTranslate\"></i>\r\n }\r\n @if(edtField.fieldData.visibilityRules) {\r\n <i class=\"branched-field ri-git-merge-line\"></i>\r\n <span class=\"vs-rule\"> {{edtField.fieldData.visibilityRules[0]?.fieldLabel ?? '-'}} </span>\r\n }\r\n </b>\r\n <p> {{edtField.field?.label ?? edtField.type ?? edtField.fieldData.type}} </p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n @if (edtField.fieldData.type === 'repeater') {\r\n <ui-button\r\n [icon]=\"isRepeaterExpanded(edtField.code) ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'\"\r\n size=\"s\" color=\"black\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"toggleRepeater(edtField.code, $event)\">\r\n </ui-button>\r\n }\r\n <ui-button\r\n [uiTooltip]=\"(isVisibilityParent(edtField.code) ? 'form_builder.delete_field_dependency_blocked' : 'form_builder.field_editor.delete') | uicTranslate\"\r\n [disabled]=\"isVisibilityParent(edtField.code)\"\r\n (click)=\"deleteField(edtField.code, $event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n\r\n @if (edtField.fieldData.type === 'repeater' && isRepeaterExpanded(edtField.code)) {\r\n <div class=\"repeater-inline-panel\">\r\n <div\r\n class=\"repeater-subfields-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"edtField.repeaterSubFields ?? []\"\r\n (cdkDropListDropped)=\"reorderSubFields(edtField.code, $event)\">\r\n @for (sf of edtField.repeaterSubFields ?? []; track sf.code) {\r\n <div\r\n class=\"xfield-card subfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"selectedSubFieldCode() === sf.code && edtField.code === selectedSubFieldParentCode()\"\r\n (click)=\"onSelectSubField(edtField.code, sf, $event)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"sf.field?.icon ?? 'ri-question-line'\"></i>\r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b>{{ sf.fieldData.label || sf.fieldData.name }}\r\n @if (sf.fieldData.hidden) {\r\n <i class=\"hidden-field ri-eye-off-line\" [uiTooltip]=\"'form_builder.base.hidden' | uicTranslate\"></i>\r\n }\r\n </b>\r\n <p>{{ sf.field?.label ?? sf.type ?? sf.fieldData.type }}</p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n <ui-button\r\n size=\"s\" icon=\"ri-delete-bin-line\" color=\"red\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"deleteSubField(edtField.code, sf.code, $event)\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"empty-hint\">{{'form_builder.repeater.no_subfields' | uicTranslate}}</p>\r\n }\r\n </div>\r\n <div class=\"new-subfield\">\r\n {{'form_builder.repeater.add_subfield' | uicTranslate}}\r\n <lib-field-type-selector [excludeTypes]=\"excludeSubFieldTypes\" (selectType)=\"addSubField(edtField.code, $event)\"></lib-field-type-selector>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n\r\n </div>\r\n <div class=\"new-field\">\r\n {{'form_builder.add_new_field' | uicTranslate}}\r\n <lib-field-type-selector (selectType)=\"addField($event)\"></lib-field-type-selector>\r\n </div>\r\n</div>\r\n", styles: [".form-block-card{border:solid 1px var(--blue-500);border-radius:5px;overflow:hidden}.form-block-card-header{display:flex;gap:5px;align-items:center;background-color:#fff;padding:10px;border-bottom:solid 1px var(--grey-300)}.form-block-card-header>div{flex:1 1;gap:4px;display:flex;flex-direction:column}.form-block-card-header>div input{border:solid 1px var(--grey-100);padding:3px 6px;border-radius:5px}.form-block-card-header>div input:focus{border:solid 1px var(--primary-500);outline:none}.form-block-card-body{padding:15px;display:flex;flex-direction:column;background-color:var(--grey-50);gap:10px}.xfield-card{background-color:#fff;border-radius:5px;padding:10px;gap:10px;display:flex;align-items:center;border:solid 2px var(--grey-200);cursor:pointer;transition:border-color .3s ease}.xfield-card:hover{border-color:var(--grey-300)}.xfield-card-icon{display:flex;justify-content:center;align-items:center;border-radius:5px;width:30px;height:30px;font-size:20px;background-color:var(--grey-300);color:var(--grey-600)}.xfield-card-body{flex:1 1}.xfield-card-body b{display:flex;align-items:center;gap:5px}.xfield-card-body p{color:var(--grey-400);font-size:12px}.field-drag-handle{cursor:grab;color:var(--grey-400);transition:color .2s ease}.field-drag-handle:active{cursor:grabbing}.xfield-card:hover .field-drag-handle{color:var(--grey-600)}.cdk-drag-preview{box-sizing:border-box;border-radius:5px;box-shadow:0 6px 12px #0000002e}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.field-with-subfields{display:flex;flex-direction:column;gap:0}.repeater-inline-panel{background-color:var(--grey-100);border:solid 1px var(--blue-300);border-top:none;border-radius:0 0 5px 5px;padding:10px 10px 8px 28px;display:flex;flex-direction:column;gap:8px}.repeater-subfields-list{display:flex;flex-direction:column;gap:6px;min-height:6px}.subfield-card{font-size:13px;border-radius:4px;padding:7px 8px!important}.subfield-card .xfield-card-icon{width:26px!important;height:26px!important;font-size:16px!important}.subfield-card b{font-size:13px}.subfield-card p{font-size:11px}.new-subfield{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--grey-500);flex-wrap:wrap;padding-top:2px}.empty-hint{font-size:12px;color:var(--grey-400);text-align:center;padding:4px 0;margin:0}.form-block-card-body.cdk-drop-list-dragging .xfield-card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.branched-field{color:var(--yellow-600)}.hidden-field{color:var(--grey-500)}.selected-field,.selected-field:hover{border-color:var(--primary-500)}.new-field{border-top:solid 1px var(--grey-300);padding:10px;background-color:#fff;display:flex;flex-direction:column;gap:5px;font-size:14px}.vs-rule{font-size:12px;color:var(--grey-600)}\n"] }]
11322
+ ], template: "<div class=\"form-block-card\">\r\n <div class=\"form-block-card-header\">\r\n <div>\r\n <input [placeholder]=\"'form_builder.block_title' | uicTranslate\" [ngModel]=\"block().title\" (ngModelChange)=\"changeTitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_subtitle' | uicTranslate\" [ngModel]=\"block().subtitle\" (ngModelChange)=\"changeSubtitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_message' | uicTranslate\" [ngModel]=\"block().message\" (ngModelChange)=\"changeMessage($event)\">\r\n </div>\r\n <ui-button\r\n [uiTooltip]=\"(isBlockVisibilityParent() ? 'form_builder.delete_block_dependency_blocked' : 'form_builder.delete_block') | uicTranslate\"\r\n [disabled]=\"isBlockVisibilityParent()\"\r\n (click)=\"requestDeleteBlock($event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n <div\r\n class=\"form-block-card-body\"\r\n cdkDropList\r\n [cdkDropListData]=\"block().fields\"\r\n (cdkDropListDropped)=\"reorderFields($event)\">\r\n \r\n <!-- FIELDS -->\r\n @for(edtField of block().fields; track edtField.code; let i = $index) {\r\n <div class=\"field-with-subfields\">\r\n <div\r\n class=\"xfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"isRepeaterParentSelected(edtField)\"\r\n (click)=\"selectField(edtField)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"edtField.field?.icon ?? ''\"></i> \r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b> {{edtField.fieldData.label}}\r\n @if (edtField.fieldData.hidden) {\r\n <i class=\"hidden-field ri-eye-off-line\" [uiTooltip]=\"'form_builder.base.hidden' | uicTranslate\"></i>\r\n }\r\n @if(edtField.fieldData.visibilityRules) {\r\n <i class=\"branched-field ri-git-merge-line\"></i>\r\n <span class=\"vs-rule\"> {{edtField.fieldData.visibilityRules[0]?.fieldLabel ?? '-'}} </span>\r\n }\r\n </b>\r\n <p> {{edtField.field?.label ?? edtField.type ?? edtField.fieldData.type}} </p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n @if (edtField.fieldData.type === 'repeater') {\r\n <ui-button\r\n [icon]=\"isRepeaterExpanded(edtField.code) ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'\"\r\n size=\"s\" color=\"black\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"toggleRepeater(edtField.code, $event)\">\r\n </ui-button>\r\n }\r\n <ui-button\r\n [uiTooltip]=\"(isVisibilityParent(edtField.code) ? 'form_builder.delete_field_dependency_blocked' : 'form_builder.field_editor.delete') | uicTranslate\"\r\n [disabled]=\"isVisibilityParent(edtField.code)\"\r\n (click)=\"deleteField(edtField.code, $event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n\r\n @if (edtField.fieldData.type === 'repeater' && isRepeaterExpanded(edtField.code)) {\r\n <div class=\"repeater-inline-panel\">\r\n <div\r\n class=\"repeater-subfields-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"edtField.repeaterSubFields ?? []\"\r\n (cdkDropListDropped)=\"reorderSubFields(edtField.code, $event)\">\r\n @for (sf of edtField.repeaterSubFields ?? []; track sf.code) {\r\n <div\r\n class=\"xfield-card subfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"selectedSubFieldCode() === sf.code && edtField.code === selectedSubFieldParentCode()\"\r\n (click)=\"onSelectSubField(edtField.code, sf, $event)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"sf.field?.icon ?? 'ri-question-line'\"></i>\r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b>{{ sf.fieldData.label || sf.fieldData.name }}\r\n @if (sf.fieldData.hidden) {\r\n <i class=\"hidden-field ri-eye-off-line\" [uiTooltip]=\"'form_builder.base.hidden' | uicTranslate\"></i>\r\n }\r\n @if (sf.fieldData.visibilityRules) {\r\n <i class=\"branched-field ri-git-merge-line\"></i>\r\n <span class=\"vs-rule\"> {{sf.fieldData.visibilityRules[0]?.fieldLabel ?? '-'}} </span>\r\n }\r\n </b>\r\n <p>{{ sf.field?.label ?? sf.type ?? sf.fieldData.type }}</p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n <ui-button\r\n [uiTooltip]=\"(isSubFieldVisibilityParent(edtField, sf.code) ? 'form_builder.delete_field_dependency_blocked' : 'form_builder.field_editor.delete') | uicTranslate\"\r\n [disabled]=\"isSubFieldVisibilityParent(edtField, sf.code)\"\r\n size=\"s\" icon=\"ri-delete-bin-line\" color=\"red\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"deleteSubField(edtField.code, sf.code, $event)\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"empty-hint\">{{'form_builder.repeater.no_subfields' | uicTranslate}}</p>\r\n }\r\n </div>\r\n <div class=\"new-subfield\">\r\n {{'form_builder.repeater.add_subfield' | uicTranslate}}\r\n <lib-field-type-selector [excludeTypes]=\"excludeSubFieldTypes\" (selectType)=\"addSubField(edtField.code, $event)\"></lib-field-type-selector>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n\r\n </div>\r\n <div class=\"new-field\">\r\n {{'form_builder.add_new_field' | uicTranslate}}\r\n <lib-field-type-selector (selectType)=\"addField($event)\"></lib-field-type-selector>\r\n </div>\r\n</div>\r\n", styles: [".form-block-card{border:solid 1px var(--blue-500);border-radius:5px;overflow:hidden}.form-block-card-header{display:flex;gap:5px;align-items:center;background-color:#fff;padding:10px;border-bottom:solid 1px var(--grey-300)}.form-block-card-header>div{flex:1 1;gap:4px;display:flex;flex-direction:column}.form-block-card-header>div input{border:solid 1px var(--grey-100);padding:3px 6px;border-radius:5px}.form-block-card-header>div input:focus{border:solid 1px var(--primary-500);outline:none}.form-block-card-body{padding:15px;display:flex;flex-direction:column;background-color:var(--grey-50);gap:10px}.xfield-card{background-color:#fff;border-radius:5px;padding:10px;gap:10px;display:flex;align-items:center;border:solid 2px var(--grey-200);cursor:pointer;transition:border-color .3s ease}.xfield-card:hover{border-color:var(--grey-300)}.xfield-card-icon{display:flex;justify-content:center;align-items:center;border-radius:5px;width:30px;height:30px;font-size:20px;background-color:var(--grey-300);color:var(--grey-600)}.xfield-card-body{flex:1 1}.xfield-card-body b{display:flex;align-items:center;gap:5px}.xfield-card-body p{color:var(--grey-400);font-size:12px}.field-drag-handle{cursor:grab;color:var(--grey-400);transition:color .2s ease}.field-drag-handle:active{cursor:grabbing}.xfield-card:hover .field-drag-handle{color:var(--grey-600)}.cdk-drag-preview{box-sizing:border-box;border-radius:5px;box-shadow:0 6px 12px #0000002e}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.field-with-subfields{display:flex;flex-direction:column;gap:0}.repeater-inline-panel{background-color:var(--grey-100);border:solid 1px var(--blue-300);border-top:none;border-radius:0 0 5px 5px;padding:10px 10px 8px 28px;display:flex;flex-direction:column;gap:8px}.repeater-subfields-list{display:flex;flex-direction:column;gap:6px;min-height:6px}.subfield-card{font-size:13px;border-radius:4px;padding:7px 8px!important}.subfield-card .xfield-card-icon{width:26px!important;height:26px!important;font-size:16px!important}.subfield-card b{font-size:13px}.subfield-card p{font-size:11px}.new-subfield{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--grey-500);flex-wrap:wrap;padding-top:2px}.empty-hint{font-size:12px;color:var(--grey-400);text-align:center;padding:4px 0;margin:0}.form-block-card-body.cdk-drop-list-dragging .xfield-card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.branched-field{color:var(--yellow-600)}.hidden-field{color:var(--grey-500)}.selected-field,.selected-field:hover{border-color:var(--primary-500)}.new-field{border-top:solid 1px var(--grey-300);padding:10px;background-color:#fff;display:flex;flex-direction:column;gap:5px;font-size:14px}.vs-rule{font-size:12px;color:var(--grey-600)}\n"] }]
11165
11323
  }], ctorParameters: () => [], propDecorators: { visibilityParentFieldCodes: [{
11166
11324
  type: Input
11167
11325
  }] } });
@@ -11259,7 +11417,9 @@ class UicUserFormbuilderComponent {
11259
11417
  }));
11260
11418
  const fieldOptions = [...siblingOptions, ...parentNonRepeaterOptions];
11261
11419
  return {
11262
- fieldName: fieldOptions,
11420
+ // Visibilidad: en el builder solo se permiten hermanos del mismo ítem.
11421
+ // El motor también resuelve campos del raíz (gana el hermano), pero solo vía esquema manual.
11422
+ fieldName: siblingOptions,
11263
11423
  'optionsSource.key': this.optionSources,
11264
11424
  'optionsSource.dependsOn': fieldOptions,
11265
11425
  'computedSource.key': this.computedSources,
@@ -11697,15 +11857,33 @@ class UicUserFormbuilderComponent {
11697
11857
  }
11698
11858
  // Hydrate sub-fields for repeater
11699
11859
  if (hydratedField.repeaterSubFields?.length) {
11860
+ const siblingLabelByCode = new Map(hydratedField.repeaterSubFields.map(sf => [sf.code, sf.fieldData.label || sf.fieldData.name]));
11700
11861
  const hydratedSubFields = hydratedField.repeaterSubFields.map(sf => {
11701
- if (sf.field)
11702
- return sf;
11703
- const sfConfig = FIELDS_CONFIG.find(c => c.value === sf.type);
11704
- if (!sfConfig)
11705
- return sf;
11706
- changed = true;
11707
- blockChanged = true;
11708
- return { ...sf, field: sfConfig };
11862
+ let hydratedSf = sf;
11863
+ if (!sf.field) {
11864
+ const sfConfig = FIELDS_CONFIG.find(c => c.value === sf.type);
11865
+ if (sfConfig) {
11866
+ changed = true;
11867
+ blockChanged = true;
11868
+ hydratedSf = { ...hydratedSf, field: sfConfig };
11869
+ }
11870
+ }
11871
+ // Reglas de subcampo: solo hermanos del mismo repeater.
11872
+ const sfRules = hydratedSf.fieldData.visibilityRules;
11873
+ if (sfRules?.some(rule => siblingLabelByCode.has(rule.fieldName) && rule.fieldLabel !== siblingLabelByCode.get(rule.fieldName))) {
11874
+ changed = true;
11875
+ blockChanged = true;
11876
+ hydratedSf = {
11877
+ ...hydratedSf,
11878
+ fieldData: {
11879
+ ...hydratedSf.fieldData,
11880
+ visibilityRules: sfRules.map(rule => siblingLabelByCode.has(rule.fieldName)
11881
+ ? { ...rule, fieldLabel: siblingLabelByCode.get(rule.fieldName) }
11882
+ : rule)
11883
+ }
11884
+ };
11885
+ }
11886
+ return hydratedSf;
11709
11887
  });
11710
11888
  if (hydratedSubFields !== hydratedField.repeaterSubFields) {
11711
11889
  hydratedField = { ...hydratedField, repeaterSubFields: hydratedSubFields };