@praxisui/visual-builder 9.0.0-beta.0 → 9.0.0-beta.10

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.
@@ -1003,7 +1003,7 @@ class RuleBuilderService {
1003
1003
  ...this.getInitialState(),
1004
1004
  isDirty: false,
1005
1005
  });
1006
- // Salva estado inicial para habilitar undo/redo desde a primeira ação
1006
+ // Salva estado inicial para habilitar undo/redo desde a primeira ação
1007
1007
  this.saveSnapshot('Estado inicial');
1008
1008
  }
1009
1009
  /**
@@ -1279,7 +1279,7 @@ class RuleBuilderService {
1279
1279
  parsed = typeof content === 'string' ? JSON.parse(content) : content;
1280
1280
  }
1281
1281
  catch (e) {
1282
- throw new Error(`Importação falhou: JSON inválido (${e?.message || e})`);
1282
+ throw new Error(`Importação falhou: JSON inválido (${e?.message || e})`);
1283
1283
  }
1284
1284
  if (!parsed || (typeof parsed === 'object' && !Object.keys(parsed).length)) {
1285
1285
  return;
@@ -1309,7 +1309,7 @@ class RuleBuilderService {
1309
1309
  }
1310
1310
  }
1311
1311
  }
1312
- throw new Error(`Formato de importação não suportado ou inválido: ${format}`);
1312
+ throw new Error(`Formato de importação não suportado ou inválido: ${format}`);
1313
1313
  }
1314
1314
  /**
1315
1315
  * Export rules to JSON payload
@@ -1328,11 +1328,11 @@ class RuleBuilderService {
1328
1328
  };
1329
1329
  if (this.containsPropertyRule()) {
1330
1330
  payload.warning =
1331
- 'Exportação de propertyRule é experimental e pode exigir revisão manual.';
1331
+ 'Exportação de propertyRule é experimental e pode exigir revisão manual.';
1332
1332
  }
1333
1333
  return JSON.stringify(payload, null, options?.prettyPrint ? 2 : undefined);
1334
1334
  }
1335
- throw new Error(`Formato de exportação não suportado: ${format}`);
1335
+ throw new Error(`Formato de exportação não suportado: ${format}`);
1336
1336
  }
1337
1337
  toSpecification() {
1338
1338
  return null;
@@ -1417,31 +1417,31 @@ class RuleBuilderService {
1417
1417
  }
1418
1418
  generateNodeLabel(type) {
1419
1419
  const labels = {
1420
- [RuleNodeType.FIELD_CONDITION]: 'Condição de campo',
1420
+ [RuleNodeType.FIELD_CONDITION]: 'Condição de campo',
1421
1421
  [RuleNodeType.PROPERTY_RULE]: 'Propriedade',
1422
1422
  [RuleNodeType.AND_GROUP]: 'Grupo E',
1423
1423
  [RuleNodeType.OR_GROUP]: 'Grupo OU',
1424
- [RuleNodeType.NOT_GROUP]: 'Grupo NÃO',
1424
+ [RuleNodeType.NOT_GROUP]: 'Grupo NÃO',
1425
1425
  [RuleNodeType.XOR_GROUP]: 'Grupo XOR',
1426
1426
  [RuleNodeType.IMPLIES_GROUP]: 'Implica',
1427
- [RuleNodeType.REQUIRED_IF]: 'Obrigatório se',
1428
- [RuleNodeType.VISIBLE_IF]: 'Visível se',
1427
+ [RuleNodeType.REQUIRED_IF]: 'Obrigatório se',
1428
+ [RuleNodeType.VISIBLE_IF]: 'Visível se',
1429
1429
  [RuleNodeType.DISABLED_IF]: 'Desabilitado se',
1430
1430
  [RuleNodeType.READONLY_IF]: 'Somente leitura se',
1431
1431
  [RuleNodeType.FOR_EACH]: 'Para cada item',
1432
- [RuleNodeType.UNIQUE_BY]: 'Único por campo',
1433
- [RuleNodeType.MIN_LENGTH]: 'Mínimo de itens',
1434
- [RuleNodeType.MAX_LENGTH]: 'Máximo de itens',
1432
+ [RuleNodeType.UNIQUE_BY]: 'Único por campo',
1433
+ [RuleNodeType.MIN_LENGTH]: 'Mínimo de itens',
1434
+ [RuleNodeType.MAX_LENGTH]: 'Máximo de itens',
1435
1435
  [RuleNodeType.IF_DEFINED]: 'Se definido',
1436
- [RuleNodeType.IF_NOT_NULL]: 'Se não for nulo',
1436
+ [RuleNodeType.IF_NOT_NULL]: 'Se não for nulo',
1437
1437
  [RuleNodeType.IF_EXISTS]: 'Se existir',
1438
- [RuleNodeType.WITH_DEFAULT]: 'Com valor padrão',
1439
- [RuleNodeType.FUNCTION_CALL]: 'Chamada de função',
1438
+ [RuleNodeType.WITH_DEFAULT]: 'Com valor padrão',
1439
+ [RuleNodeType.FUNCTION_CALL]: 'Chamada de função',
1440
1440
  [RuleNodeType.FIELD_TO_FIELD]: 'Campo para campo',
1441
1441
  [RuleNodeType.CONTEXTUAL]: 'Contextual',
1442
1442
  [RuleNodeType.AT_LEAST]: 'Pelo menos',
1443
1443
  [RuleNodeType.EXACTLY]: 'Exatamente',
1444
- [RuleNodeType.EXPRESSION]: 'Expressão',
1444
+ [RuleNodeType.EXPRESSION]: 'Expressão',
1445
1445
  [RuleNodeType.CONTEXTUAL_TEMPLATE]: 'Template contextual',
1446
1446
  [RuleNodeType.CUSTOM]: 'Personalizado',
1447
1447
  };
@@ -1471,8 +1471,8 @@ class RuleBuilderService {
1471
1471
  });
1472
1472
  }
1473
1473
  /**
1474
- * Constrói um array de FormLayoutRule a partir do estado atual do builder,
1475
- * focando em nós propertyRule ou nós com propriedades/targets definidos.
1474
+ * Constrói um array de FormLayoutRule a partir do estado atual do builder,
1475
+ * focando em nós propertyRule ou nós com propriedades/targets definidos.
1476
1476
  */
1477
1477
  exportFormRulesFromState(state) {
1478
1478
  const rules = [];
@@ -1486,7 +1486,7 @@ class RuleBuilderService {
1486
1486
  }
1487
1487
  }
1488
1488
  if (warnings.length) {
1489
- console.warn('[RuleBuilderService] Algumas propriedades foram removidas ou ajustadas durante a exportação de formRules:', warnings);
1489
+ console.warn('[RuleBuilderService] Algumas propriedades foram removidas ou ajustadas durante a exportação de formRules:', warnings);
1490
1490
  }
1491
1491
  return rules;
1492
1492
  }
@@ -1545,7 +1545,7 @@ class RuleBuilderService {
1545
1545
  return null;
1546
1546
  }
1547
1547
  return {
1548
- [operator]: [{ var: cfg.fieldName }, this.normalizeConditionValue(cfg.value)],
1548
+ [operator]: [{ var: cfg.fieldName }, this.buildConditionRightOperand(cfg)],
1549
1549
  };
1550
1550
  }
1551
1551
  if (node.type === RuleNodeType.AND_GROUP || node.type === RuleNodeType.OR_GROUP) {
@@ -1624,7 +1624,7 @@ class RuleBuilderService {
1624
1624
  const id = (rawRule && (rawRule.id || rawRule.name)) || `#${index + 1}`;
1625
1625
  const ruleErrorsStart = errors.length;
1626
1626
  if (!rawRule || typeof rawRule !== 'object') {
1627
- errors.push(`Regra ${id}: valor inválido (esperado objeto)`);
1627
+ errors.push(`Regra ${id}: valor inválido (esperado objeto)`);
1628
1628
  return;
1629
1629
  }
1630
1630
  const rawTargets = Array.isArray(rawRule.targets) && rawRule.targets.length
@@ -1634,16 +1634,16 @@ class RuleBuilderService {
1634
1634
  : [];
1635
1635
  const { targets, targetType } = this.normalizeTargets(rawTargets, rawRule.targetType);
1636
1636
  if (!targets.length) {
1637
- errors.push(`Regra ${id}: targets obrigatórios ausentes`);
1637
+ errors.push(`Regra ${id}: targets obrigatórios ausentes`);
1638
1638
  return;
1639
1639
  }
1640
1640
  if (!allowedTargets.has(targetType)) {
1641
- errors.push(`Regra ${id}: targetType inválido "${rawRule.targetType || targetType}"`);
1641
+ errors.push(`Regra ${id}: targetType inválido "${rawRule.targetType || targetType}"`);
1642
1642
  return;
1643
1643
  }
1644
1644
  const effect = rawRule.effect;
1645
1645
  if (!effect || typeof effect !== 'object') {
1646
- errors.push(`Regra ${id}: effect ausente ou inválido`);
1646
+ errors.push(`Regra ${id}: effect ausente ou inválido`);
1647
1647
  return;
1648
1648
  }
1649
1649
  const condition = this.normalizeJsonLogicCondition(effect.condition);
@@ -1654,7 +1654,7 @@ class RuleBuilderService {
1654
1654
  const propertiesWhenFalse = this.sanitizeRuleProperties(targetType, effect.propertiesWhenFalse, errors, `regra ${id} (propertiesWhenFalse)`, true);
1655
1655
  if (Object.keys(properties).length === 0 &&
1656
1656
  Object.keys(propertiesWhenFalse).length === 0) {
1657
- errors.push(`Regra ${id}: nenhuma propriedade válida encontrada`);
1657
+ errors.push(`Regra ${id}: nenhuma propriedade válida encontrada`);
1658
1658
  }
1659
1659
  if (errors.length === ruleErrorsStart) {
1660
1660
  normalized.push({
@@ -1672,7 +1672,7 @@ class RuleBuilderService {
1672
1672
  }
1673
1673
  });
1674
1674
  if (errors.length) {
1675
- throw new Error(`FormRules inválidos: ${errors.join('; ')}`);
1675
+ throw new Error(`FormRules inválidos: ${errors.join('; ')}`);
1676
1676
  }
1677
1677
  return normalized;
1678
1678
  }
@@ -1687,7 +1687,7 @@ class RuleBuilderService {
1687
1687
  const def = defMap.get(name);
1688
1688
  if (!def) {
1689
1689
  if (strict || collector) {
1690
- collector?.push(`${context}: propriedade "${name}" não é permitida para ${targetType}`);
1690
+ collector?.push(`${context}: propriedade "${name}" não é permitida para ${targetType}`);
1691
1691
  }
1692
1692
  return acc;
1693
1693
  }
@@ -1696,14 +1696,14 @@ class RuleBuilderService {
1696
1696
  acc[name] = coerced.value;
1697
1697
  }
1698
1698
  else if (strict || collector) {
1699
- collector?.push(`${context}: valor inválido para "${name}" (esperado ${def.type}, recebido ${typeof value})`);
1699
+ collector?.push(`${context}: valor inválido para "${name}" (esperado ${def.type}, recebido ${typeof value})`);
1700
1700
  }
1701
1701
  return acc;
1702
1702
  }, {});
1703
1703
  }
1704
1704
  coerceRulePropertyValue(def, value) {
1705
1705
  if (value === null) {
1706
- // null mantém semântica de remover override
1706
+ // null mantém semântica de remover override
1707
1707
  return { ok: true, value: null };
1708
1708
  }
1709
1709
  switch (def.type) {
@@ -1951,15 +1951,20 @@ class RuleBuilderService {
1951
1951
  if (!this.isVarExpression(left)) {
1952
1952
  return undefined;
1953
1953
  }
1954
+ const config = {
1955
+ type: 'fieldCondition',
1956
+ fieldName: this.extractVarPath(left.var),
1957
+ operator: builderOperator,
1958
+ value: right,
1959
+ };
1960
+ if (this.isVarExpression(right)) {
1961
+ config['valueType'] = 'field';
1962
+ config['compareToField'] = this.extractVarPath(right.var);
1963
+ }
1954
1964
  return {
1955
1965
  id: v4(),
1956
1966
  type: RuleNodeType.FIELD_CONDITION,
1957
- config: {
1958
- type: 'fieldCondition',
1959
- fieldName: this.extractVarPath(left.var),
1960
- operator: builderOperator,
1961
- value: right,
1962
- },
1967
+ config: config,
1963
1968
  };
1964
1969
  }
1965
1970
  parseJsonLogicChild(child) {
@@ -2073,6 +2078,14 @@ class RuleBuilderService {
2073
2078
  }
2074
2079
  return value;
2075
2080
  }
2081
+ buildConditionRightOperand(cfg) {
2082
+ if (cfg['valueType'] === 'field' &&
2083
+ typeof cfg['compareToField'] === 'string' &&
2084
+ cfg['compareToField'].trim()) {
2085
+ return { var: cfg['compareToField'].trim() };
2086
+ }
2087
+ return this.normalizeConditionValue(cfg['value']);
2088
+ }
2076
2089
  isJsonLogicExpressionCandidate(value) {
2077
2090
  return !!value && typeof value === 'object' && !Array.isArray(value);
2078
2091
  }
@@ -2228,13 +2241,17 @@ class RuleBuilderService {
2228
2241
  this.addValidationError(errors, `field-condition:compare-field:${node.id}`, 'Escolha o campo usado na comparacao.', 'error', node.id);
2229
2242
  return;
2230
2243
  }
2231
- if (cfg.valueType === 'context' &&
2232
- (!cfg.contextVariable || typeof cfg.contextVariable !== 'string')) {
2233
- this.addValidationError(errors, `field-condition:context:${node.id}`, 'Escolha a variavel de contexto usada na comparacao.', 'error', node.id);
2244
+ if (cfg.valueType === 'context') {
2245
+ this.addValidationError(errors, `field-condition:context:${node.id}`, 'Comparação com variável de contexto ainda não possui serialização JSON Logic canônica.', 'error', node.id);
2246
+ return;
2247
+ }
2248
+ if (cfg.valueType === 'function') {
2249
+ this.addValidationError(errors, `field-condition:function:${node.id}`, 'Comparação com chamada de função ainda não possui serialização JSON Logic canônica.', 'error', node.id);
2234
2250
  return;
2235
2251
  }
2236
2252
  if (cfg.valueType !== 'field' &&
2237
2253
  cfg.valueType !== 'context' &&
2254
+ cfg.valueType !== 'function' &&
2238
2255
  !Object.prototype.hasOwnProperty.call(cfg, 'value')) {
2239
2256
  this.addValidationError(errors, `field-condition:value:${node.id}`, 'Informe o valor da condicao.', 'error', node.id);
2240
2257
  }
@@ -2310,7 +2327,7 @@ class RuleBuilderService {
2310
2327
  return null;
2311
2328
  if (input.type)
2312
2329
  return input;
2313
- // Inferência básica de tipos de especificação comuns
2330
+ // Inferência básica de tipos de especificação comuns
2314
2331
  // Campo simples: { field, operator, value }
2315
2332
  if (input.field && input.operator !== undefined) {
2316
2333
  return { type: 'field', ...input };
@@ -5279,6 +5296,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
5279
5296
  args: ['searchInput']
5280
5297
  }] } });
5281
5298
 
5299
+ const VISUAL_SAFE_OPERATORS = new Set([
5300
+ 'equals',
5301
+ 'notEquals',
5302
+ 'greaterThan',
5303
+ 'greaterThanOrEqual',
5304
+ 'lessThan',
5305
+ 'lessThanOrEqual',
5306
+ 'contains',
5307
+ 'startsWith',
5308
+ 'endsWith',
5309
+ 'in',
5310
+ ]);
5282
5311
  class FieldConditionEditorComponent {
5283
5312
  fb;
5284
5313
  config = null;
@@ -5384,34 +5413,40 @@ class FieldConditionEditorComponent {
5384
5413
  const normalizedFieldName = this.normalizeFieldName(this.config.fieldName);
5385
5414
  const resolvedField = this.resolveFieldSchema(normalizedFieldName) || null;
5386
5415
  const formFieldName = resolvedField?.name || normalizedFieldName;
5416
+ const valueType = this.normalizeValueTypeForVisualEditor(this.config.valueType);
5387
5417
  this.conditionForm.patchValue({
5388
5418
  fieldName: formFieldName || '',
5389
5419
  operator: normalizedOperator || '',
5390
- value: this.config.value !== undefined ? this.config.value : '',
5391
- valueType: this.config.valueType || 'literal',
5392
- compareToField: this.config.compareToField || '',
5393
- contextVariable: this.config.contextVariable || '',
5420
+ value: valueType === 'literal' && this.config.value !== undefined
5421
+ ? this.config.value
5422
+ : '',
5423
+ valueType,
5424
+ compareToField: valueType === 'field' ? this.config.compareToField || '' : '',
5425
+ contextVariable: '',
5426
+ functionName: '',
5394
5427
  });
5428
+ this.valueType = valueType;
5395
5429
  if (formFieldName) {
5396
5430
  this.onFieldChanged(formFieldName);
5397
5431
  }
5398
5432
  const opCtrl = this.conditionForm.get('operator');
5399
5433
  if (opCtrl) {
5400
- this.selectedOperator = opCtrl.value;
5434
+ this.selectedOperator = opCtrl.value || null;
5401
5435
  }
5402
5436
  }
5403
5437
  emitConfigChange() {
5404
5438
  if (!this.conditionForm.valid)
5405
5439
  return;
5406
5440
  const formValue = this.conditionForm.value;
5441
+ const valueType = this.normalizeValueTypeForVisualEditor(formValue.valueType);
5407
5442
  const config = {
5408
5443
  type: 'fieldCondition',
5409
5444
  fieldName: formValue.fieldName,
5410
5445
  operator: formValue.operator,
5411
- value: this.processValue(formValue.value),
5412
- valueType: formValue.valueType,
5413
- compareToField: formValue.compareToField,
5414
- contextVariable: formValue.contextVariable,
5446
+ value: valueType === 'literal' ? this.processValue(formValue.value) : null,
5447
+ valueType,
5448
+ compareToField: valueType === 'field' ? formValue.compareToField : '',
5449
+ contextVariable: '',
5415
5450
  };
5416
5451
  this.configChanged.emit(config);
5417
5452
  }
@@ -5487,6 +5522,9 @@ class FieldConditionEditorComponent {
5487
5522
  return operator;
5488
5523
  }
5489
5524
  }
5525
+ normalizeValueTypeForVisualEditor(valueType) {
5526
+ return valueType === 'field' ? 'field' : 'literal';
5527
+ }
5490
5528
  // Template methods
5491
5529
  getFieldIcon(type) {
5492
5530
  const icons = {
@@ -5644,8 +5682,7 @@ class FieldConditionEditorComponent {
5644
5682
  }
5645
5683
  this.selectedField = resolvedField;
5646
5684
  if (this.selectedField) {
5647
- this.availableOperators =
5648
- FIELD_TYPE_OPERATORS[this.selectedField.type] || [];
5685
+ this.availableOperators = (FIELD_TYPE_OPERATORS[this.selectedField.type] || []).filter((operator) => VISUAL_SAFE_OPERATORS.has(operator));
5649
5686
  // Reset operator if not compatible
5650
5687
  const currentOperator = this.conditionForm.get('operator')?.value;
5651
5688
  if (currentOperator &&
@@ -5664,9 +5701,10 @@ class FieldConditionEditorComponent {
5664
5701
  this.conditionForm.patchValue({ value: '' });
5665
5702
  }
5666
5703
  onValueTypeChanged(event) {
5667
- this.valueType = event.value;
5704
+ this.valueType = this.normalizeValueTypeForVisualEditor(event.value);
5668
5705
  // Reset related fields
5669
5706
  this.conditionForm.patchValue({
5707
+ valueType: this.valueType,
5670
5708
  value: '',
5671
5709
  compareToField: '',
5672
5710
  contextVariable: '',
@@ -5689,6 +5727,11 @@ class FieldConditionEditorComponent {
5689
5727
  const valueType = this.conditionForm.get('valueType')?.value;
5690
5728
  const valueControl = this.conditionForm.get('value');
5691
5729
  const valueProvided = valueControl && valueControl.value !== undefined && valueControl.value !== '';
5730
+ const normalizedValueType = this.normalizeValueTypeForVisualEditor(valueType);
5731
+ if (valueType !== normalizedValueType) {
5732
+ errors.push('Tipo de valor disponivel apenas por JSON avancado');
5733
+ return errors;
5734
+ }
5692
5735
  switch (valueType) {
5693
5736
  case 'literal':
5694
5737
  if (!valueProvided) {
@@ -5825,8 +5868,8 @@ class FieldConditionEditorComponent {
5825
5868
  >
5826
5869
  <mat-option value="literal">Valor digitado</mat-option>
5827
5870
  <mat-option value="field">Outro campo</mat-option>
5828
- <mat-option value="context">Variável de contexto</mat-option>
5829
- <mat-option value="function">Chamada de função</mat-option>
5871
+ <mat-option value="context" disabled>Contexto (JSON-only)</mat-option>
5872
+ <mat-option value="function" disabled>Função (JSON-only)</mat-option>
5830
5873
  </mat-select>
5831
5874
  </mat-form-field>
5832
5875
  @switch (valueType) {
@@ -5978,15 +6021,6 @@ class FieldConditionEditorComponent {
5978
6021
  </div>
5979
6022
  }
5980
6023
 
5981
- <!-- Ações -->
5982
- <div class="actions-col">
5983
- <button mat-icon-button type="button" aria-label="Duplicar" matTooltip="Duplicar (placeholder)">
5984
- <mat-icon>content_copy</mat-icon>
5985
- </button>
5986
- <button mat-icon-button type="button" aria-label="Excluir" matTooltip="Excluir (placeholder)">
5987
- <mat-icon>delete</mat-icon>
5988
- </button>
5989
- </div>
5990
6024
  </div>
5991
6025
 
5992
6026
  @if (!hasFieldOptions()) {
@@ -6012,7 +6046,7 @@ class FieldConditionEditorComponent {
6012
6046
  </div>
6013
6047
  }
6014
6048
  </form>
6015
- `, isInline: true, styles: [".field-condition-form{display:flex;flex-direction:column;gap:8px;min-width:300px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:8px 10px;overflow:visible}.condition-row-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:4px}.condition-title{display:inline-flex;align-items:center;gap:8px;font-weight:600;color:var(--md-sys-color-on-surface)}.compact-grid{gap:12px}.condition-row{display:grid;grid-template-columns:minmax(180px,2fr) minmax(140px,1.5fr) minmax(220px,3fr) auto;gap:12px 4px;align-items:center}.compact-field{width:100%}.value-inline{display:grid;grid-template-columns:1.2fr 2fr;gap:8px;align-items:center}.value-field{width:100%}.actions-col{display:flex;flex-direction:column;gap:4px;align-items:center;justify-content:center}.field-option,.context-option,.function-option{display:flex;align-items:center;gap:8px;width:100%}.field-icon{font-size:16px;width:16px;height:16px;color:var(--md-sys-color-primary)}.field-label{flex:1;font-weight:500}.field-type{font-size:11px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);padding:2px 6px;border-radius:4px}.select-search-container{position:sticky;top:0;z-index:1;background:var(--md-sys-color-surface-container-lowest, #fff);padding:8px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant, rgba(0,0,0,.12))}.search-input-field{width:100%}.search-input-field ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.no-results{font-style:italic;font-size:13px;text-align:center}.field-info{flex:1;display:flex;flex-direction:column;line-height:1.2;overflow:hidden}.field-name{font-size:10px;opacity:.6}.variable-name{font-family:monospace;font-weight:500;color:var(--md-sys-color-secondary)}.variable-type{font-size:11px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);padding:2px 6px;border-radius:4px}.function-name{font-weight:500;color:var(--md-sys-color-tertiary)}.function-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.boolean-inline{display:flex;align-items:center;padding:4px 0}.condition-preview{background:var(--md-sys-color-surface-container);border-radius:8px;padding:8px 12px;border-left:4px solid var(--md-sys-color-primary);margin-top:2px}.preview-label{font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface-variant);margin-bottom:2px}.preview-text{font-family:monospace;font-size:14px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface);padding:6px 8px;border-radius:4px;border:1px solid var(--md-sys-color-outline-variant)}.error-row{display:inline-flex;align-items:center;gap:6px;background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border:1px solid var(--md-sys-color-error);border-radius:8px;padding:4px 10px;font-size:12px;min-height:32px}@media(max-width:1024px){.condition-row{grid-template-columns:repeat(2,minmax(180px,1fr))}.value-inline{grid-template-columns:1fr}}@media(max-width:768px){.condition-row{grid-template-columns:1fr}}.no-fields-hint{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--md-sys-color-on-surface-variant);padding:8px 0}:host ::ng-deep .mat-mdc-select-panel{scrollbar-width:thin;scrollbar-color:var(--md-sys-color-on-surface-variant) transparent}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar{width:8px}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar-thumb{background-color:var(--md-sys-color-on-surface-variant);border-radius:8px}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar-track{background-color:transparent}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i3.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i3.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i7$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i8$2.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i8$2.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i8$2.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6049
+ `, isInline: true, styles: [".field-condition-form{display:flex;flex-direction:column;gap:8px;min-width:300px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:8px 10px;overflow:visible}.condition-row-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:4px}.condition-title{display:inline-flex;align-items:center;gap:8px;font-weight:600;color:var(--md-sys-color-on-surface)}.compact-grid{gap:12px}.condition-row{display:grid;grid-template-columns:minmax(180px,2fr) minmax(140px,1.5fr) minmax(220px,3fr) auto;gap:12px 4px;align-items:center}.compact-field{width:100%}.value-inline{display:grid;grid-template-columns:1.2fr 2fr;gap:8px;align-items:center}.value-field{width:100%}.field-option,.context-option,.function-option{display:flex;align-items:center;gap:8px;width:100%}.field-icon{font-size:16px;width:16px;height:16px;color:var(--md-sys-color-primary)}.field-label{flex:1;font-weight:500}.field-type{font-size:11px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);padding:2px 6px;border-radius:4px}.select-search-container{position:sticky;top:0;z-index:1;background:var(--md-sys-color-surface-container-lowest, #fff);padding:8px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant, rgba(0,0,0,.12))}.search-input-field{width:100%}.search-input-field ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.no-results{font-style:italic;font-size:13px;text-align:center}.field-info{flex:1;display:flex;flex-direction:column;line-height:1.2;overflow:hidden}.field-name{font-size:10px;opacity:.6}.variable-name{font-family:monospace;font-weight:500;color:var(--md-sys-color-secondary)}.variable-type{font-size:11px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);padding:2px 6px;border-radius:4px}.function-name{font-weight:500;color:var(--md-sys-color-tertiary)}.function-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.boolean-inline{display:flex;align-items:center;padding:4px 0}.condition-preview{background:var(--md-sys-color-surface-container);border-radius:8px;padding:8px 12px;border-left:4px solid var(--md-sys-color-primary);margin-top:2px}.preview-label{font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface-variant);margin-bottom:2px}.preview-text{font-family:monospace;font-size:14px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface);padding:6px 8px;border-radius:4px;border:1px solid var(--md-sys-color-outline-variant)}.error-row{display:inline-flex;align-items:center;gap:6px;background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border:1px solid var(--md-sys-color-error);border-radius:8px;padding:4px 10px;font-size:12px;min-height:32px}@media(max-width:1024px){.condition-row{grid-template-columns:repeat(2,minmax(180px,1fr))}.value-inline{grid-template-columns:1fr}}@media(max-width:768px){.condition-row{grid-template-columns:1fr}}.no-fields-hint{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--md-sys-color-on-surface-variant);padding:8px 0}:host ::ng-deep .mat-mdc-select-panel{scrollbar-width:thin;scrollbar-color:var(--md-sys-color-on-surface-variant) transparent}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar{width:8px}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar-thumb{background-color:var(--md-sys-color-on-surface-variant);border-radius:8px}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar-track{background-color:transparent}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i3.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i3.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i7$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i8$2.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i8$2.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i8$2.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6016
6050
  }
6017
6051
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FieldConditionEditorComponent, decorators: [{
6018
6052
  type: Component,
@@ -6133,8 +6167,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
6133
6167
  >
6134
6168
  <mat-option value="literal">Valor digitado</mat-option>
6135
6169
  <mat-option value="field">Outro campo</mat-option>
6136
- <mat-option value="context">Variável de contexto</mat-option>
6137
- <mat-option value="function">Chamada de função</mat-option>
6170
+ <mat-option value="context" disabled>Contexto (JSON-only)</mat-option>
6171
+ <mat-option value="function" disabled>Função (JSON-only)</mat-option>
6138
6172
  </mat-select>
6139
6173
  </mat-form-field>
6140
6174
  @switch (valueType) {
@@ -6286,15 +6320,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
6286
6320
  </div>
6287
6321
  }
6288
6322
 
6289
- <!-- Ações -->
6290
- <div class="actions-col">
6291
- <button mat-icon-button type="button" aria-label="Duplicar" matTooltip="Duplicar (placeholder)">
6292
- <mat-icon>content_copy</mat-icon>
6293
- </button>
6294
- <button mat-icon-button type="button" aria-label="Excluir" matTooltip="Excluir (placeholder)">
6295
- <mat-icon>delete</mat-icon>
6296
- </button>
6297
- </div>
6298
6323
  </div>
6299
6324
 
6300
6325
  @if (!hasFieldOptions()) {
@@ -6320,7 +6345,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
6320
6345
  </div>
6321
6346
  }
6322
6347
  </form>
6323
- `, styles: [".field-condition-form{display:flex;flex-direction:column;gap:8px;min-width:300px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:8px 10px;overflow:visible}.condition-row-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:4px}.condition-title{display:inline-flex;align-items:center;gap:8px;font-weight:600;color:var(--md-sys-color-on-surface)}.compact-grid{gap:12px}.condition-row{display:grid;grid-template-columns:minmax(180px,2fr) minmax(140px,1.5fr) minmax(220px,3fr) auto;gap:12px 4px;align-items:center}.compact-field{width:100%}.value-inline{display:grid;grid-template-columns:1.2fr 2fr;gap:8px;align-items:center}.value-field{width:100%}.actions-col{display:flex;flex-direction:column;gap:4px;align-items:center;justify-content:center}.field-option,.context-option,.function-option{display:flex;align-items:center;gap:8px;width:100%}.field-icon{font-size:16px;width:16px;height:16px;color:var(--md-sys-color-primary)}.field-label{flex:1;font-weight:500}.field-type{font-size:11px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);padding:2px 6px;border-radius:4px}.select-search-container{position:sticky;top:0;z-index:1;background:var(--md-sys-color-surface-container-lowest, #fff);padding:8px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant, rgba(0,0,0,.12))}.search-input-field{width:100%}.search-input-field ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.no-results{font-style:italic;font-size:13px;text-align:center}.field-info{flex:1;display:flex;flex-direction:column;line-height:1.2;overflow:hidden}.field-name{font-size:10px;opacity:.6}.variable-name{font-family:monospace;font-weight:500;color:var(--md-sys-color-secondary)}.variable-type{font-size:11px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);padding:2px 6px;border-radius:4px}.function-name{font-weight:500;color:var(--md-sys-color-tertiary)}.function-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.boolean-inline{display:flex;align-items:center;padding:4px 0}.condition-preview{background:var(--md-sys-color-surface-container);border-radius:8px;padding:8px 12px;border-left:4px solid var(--md-sys-color-primary);margin-top:2px}.preview-label{font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface-variant);margin-bottom:2px}.preview-text{font-family:monospace;font-size:14px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface);padding:6px 8px;border-radius:4px;border:1px solid var(--md-sys-color-outline-variant)}.error-row{display:inline-flex;align-items:center;gap:6px;background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border:1px solid var(--md-sys-color-error);border-radius:8px;padding:4px 10px;font-size:12px;min-height:32px}@media(max-width:1024px){.condition-row{grid-template-columns:repeat(2,minmax(180px,1fr))}.value-inline{grid-template-columns:1fr}}@media(max-width:768px){.condition-row{grid-template-columns:1fr}}.no-fields-hint{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--md-sys-color-on-surface-variant);padding:8px 0}:host ::ng-deep .mat-mdc-select-panel{scrollbar-width:thin;scrollbar-color:var(--md-sys-color-on-surface-variant) transparent}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar{width:8px}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar-thumb{background-color:var(--md-sys-color-on-surface-variant);border-radius:8px}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar-track{background-color:transparent}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}\n"] }]
6348
+ `, styles: [".field-condition-form{display:flex;flex-direction:column;gap:8px;min-width:300px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:8px 10px;overflow:visible}.condition-row-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:4px}.condition-title{display:inline-flex;align-items:center;gap:8px;font-weight:600;color:var(--md-sys-color-on-surface)}.compact-grid{gap:12px}.condition-row{display:grid;grid-template-columns:minmax(180px,2fr) minmax(140px,1.5fr) minmax(220px,3fr) auto;gap:12px 4px;align-items:center}.compact-field{width:100%}.value-inline{display:grid;grid-template-columns:1.2fr 2fr;gap:8px;align-items:center}.value-field{width:100%}.field-option,.context-option,.function-option{display:flex;align-items:center;gap:8px;width:100%}.field-icon{font-size:16px;width:16px;height:16px;color:var(--md-sys-color-primary)}.field-label{flex:1;font-weight:500}.field-type{font-size:11px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);padding:2px 6px;border-radius:4px}.select-search-container{position:sticky;top:0;z-index:1;background:var(--md-sys-color-surface-container-lowest, #fff);padding:8px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant, rgba(0,0,0,.12))}.search-input-field{width:100%}.search-input-field ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.no-results{font-style:italic;font-size:13px;text-align:center}.field-info{flex:1;display:flex;flex-direction:column;line-height:1.2;overflow:hidden}.field-name{font-size:10px;opacity:.6}.variable-name{font-family:monospace;font-weight:500;color:var(--md-sys-color-secondary)}.variable-type{font-size:11px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);padding:2px 6px;border-radius:4px}.function-name{font-weight:500;color:var(--md-sys-color-tertiary)}.function-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.boolean-inline{display:flex;align-items:center;padding:4px 0}.condition-preview{background:var(--md-sys-color-surface-container);border-radius:8px;padding:8px 12px;border-left:4px solid var(--md-sys-color-primary);margin-top:2px}.preview-label{font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface-variant);margin-bottom:2px}.preview-text{font-family:monospace;font-size:14px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface);padding:6px 8px;border-radius:4px;border:1px solid var(--md-sys-color-outline-variant)}.error-row{display:inline-flex;align-items:center;gap:6px;background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border:1px solid var(--md-sys-color-error);border-radius:8px;padding:4px 10px;font-size:12px;min-height:32px}@media(max-width:1024px){.condition-row{grid-template-columns:repeat(2,minmax(180px,1fr))}.value-inline{grid-template-columns:1fr}}@media(max-width:768px){.condition-row{grid-template-columns:1fr}}.no-fields-hint{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--md-sys-color-on-surface-variant);padding:8px 0}:host ::ng-deep .mat-mdc-select-panel{scrollbar-width:thin;scrollbar-color:var(--md-sys-color-on-surface-variant) transparent}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar{width:8px}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar-thumb{background-color:var(--md-sys-color-on-surface-variant);border-radius:8px}:host ::ng-deep .mat-mdc-select-panel::-webkit-scrollbar-track{background-color:transparent}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}\n"] }]
6324
6349
  }], ctorParameters: () => [{ type: i1$1.FormBuilder }], propDecorators: { config: [{
6325
6350
  type: Input
6326
6351
  }], fieldSchemas: [{
@@ -6699,132 +6724,132 @@ const PRAXIS_VISUAL_BUILDER_EN_US = {
6699
6724
 
6700
6725
  const PRAXIS_VISUAL_BUILDER_PT_BR = {
6701
6726
  'praxis.visualBuilder.expression.title': 'Editor de expressoes legadas',
6702
- 'praxis.visualBuilder.expression.tooltip.format': 'Formatar expressão',
6703
- 'praxis.visualBuilder.expression.tooltip.validate': 'Validar expressão',
6727
+ 'praxis.visualBuilder.expression.tooltip.format': 'Formatar expressão',
6728
+ 'praxis.visualBuilder.expression.tooltip.validate': 'Validar expressão',
6704
6729
  'praxis.visualBuilder.expression.tooltip.help': 'Ajuda e exemplos',
6705
6730
  'praxis.visualBuilder.expression.label.rules': 'Texto legado da regra',
6706
- 'praxis.visualBuilder.expression.validationTitle': 'Resultados da validação',
6731
+ 'praxis.visualBuilder.expression.validationTitle': 'Resultados da validação',
6707
6732
  'praxis.visualBuilder.expression.validationIssues': 'Pontos a corrigir:',
6708
6733
  'praxis.visualBuilder.expression.lineColumn': 'Linha {{line}}, Coluna {{column}}',
6709
- 'praxis.visualBuilder.expression.suggestion': 'Sugestão:',
6734
+ 'praxis.visualBuilder.expression.suggestion': 'Sugestão:',
6710
6735
  'praxis.visualBuilder.expression.performance': 'Desempenho:',
6711
- 'praxis.visualBuilder.expression.parseTime': 'Tempo de análise:',
6736
+ 'praxis.visualBuilder.expression.parseTime': 'Tempo de análise:',
6712
6737
  'praxis.visualBuilder.expression.complexity': 'Complexidade:',
6713
- 'praxis.visualBuilder.expression.generatedSpec': 'Especificação gerada:',
6714
- 'praxis.visualBuilder.expression.quickReference': 'Referência rápida',
6738
+ 'praxis.visualBuilder.expression.generatedSpec': 'Especificação gerada:',
6739
+ 'praxis.visualBuilder.expression.quickReference': 'Referência rápida',
6715
6740
  'praxis.visualBuilder.expression.tab.operators': 'Operadores',
6716
- 'praxis.visualBuilder.expression.tab.functions': 'Funções',
6717
- 'praxis.visualBuilder.expression.tab.variables': 'Variáveis',
6718
- 'praxis.visualBuilder.expression.variablesScope': 'Variáveis ({{scope}})',
6719
- 'praxis.visualBuilder.expression.menu.toggleReference': 'Mostrar/ocultar referência rápida',
6741
+ 'praxis.visualBuilder.expression.tab.functions': 'Funções',
6742
+ 'praxis.visualBuilder.expression.tab.variables': 'Variáveis',
6743
+ 'praxis.visualBuilder.expression.variablesScope': 'Variáveis ({{scope}})',
6744
+ 'praxis.visualBuilder.expression.menu.toggleReference': 'Mostrar/ocultar referência rápida',
6720
6745
  'praxis.visualBuilder.expression.menu.examples': 'Ver exemplos',
6721
- 'praxis.visualBuilder.expression.menu.docs': 'Documentação',
6746
+ 'praxis.visualBuilder.expression.menu.docs': 'Documentação',
6722
6747
  'praxis.visualBuilder.expression.placeholder': 'Digite o texto das regras (ex.: ${idade} > 18 && status == "ativo")',
6723
- 'praxis.visualBuilder.expression.group.logical': 'Operadores lógicos',
6724
- 'praxis.visualBuilder.expression.group.comparison': 'Operadores de comparação',
6725
- 'praxis.visualBuilder.expression.op.and': 'E (AND) lógico',
6726
- 'praxis.visualBuilder.expression.op.or': 'OU (OR) lógico',
6727
- 'praxis.visualBuilder.expression.op.not': 'NÃO (NOT) lógico',
6748
+ 'praxis.visualBuilder.expression.group.logical': 'Operadores lógicos',
6749
+ 'praxis.visualBuilder.expression.group.comparison': 'Operadores de comparação',
6750
+ 'praxis.visualBuilder.expression.op.and': 'E (AND) lógico',
6751
+ 'praxis.visualBuilder.expression.op.or': 'OU (OR) lógico',
6752
+ 'praxis.visualBuilder.expression.op.not': 'NÃO (NOT) lógico',
6728
6753
  'praxis.visualBuilder.expression.op.xor': 'OU exclusivo (XOR)',
6729
- 'praxis.visualBuilder.expression.op.implies': 'Implica (se... então...)',
6754
+ 'praxis.visualBuilder.expression.op.implies': 'Implica (se... então...)',
6730
6755
  'praxis.visualBuilder.expression.op.eq': 'Igual a',
6731
6756
  'praxis.visualBuilder.expression.op.neq': 'Diferente de',
6732
6757
  'praxis.visualBuilder.expression.op.lt': 'Menor que',
6733
6758
  'praxis.visualBuilder.expression.op.lte': 'Menor ou igual',
6734
6759
  'praxis.visualBuilder.expression.op.gt': 'Maior que',
6735
6760
  'praxis.visualBuilder.expression.op.gte': 'Maior ou igual',
6736
- 'praxis.visualBuilder.expression.op.in': 'Contém o valor',
6737
- 'praxis.visualBuilder.expression.group.textFunctions': 'Funções de texto',
6738
- 'praxis.visualBuilder.expression.group.listFunctions': 'Funções para listas',
6739
- 'praxis.visualBuilder.expression.group.conditionalFunctions': 'Funções condicionais',
6740
- 'praxis.visualBuilder.expression.fn.contains': 'Verifica se o campo contém o valor',
6741
- 'praxis.visualBuilder.expression.fn.startsWith': 'Verifica se o campo começa com o prefixo',
6761
+ 'praxis.visualBuilder.expression.op.in': 'Contém o valor',
6762
+ 'praxis.visualBuilder.expression.group.textFunctions': 'Funções de texto',
6763
+ 'praxis.visualBuilder.expression.group.listFunctions': 'Funções para listas',
6764
+ 'praxis.visualBuilder.expression.group.conditionalFunctions': 'Funções condicionais',
6765
+ 'praxis.visualBuilder.expression.fn.contains': 'Verifica se o campo contém o valor',
6766
+ 'praxis.visualBuilder.expression.fn.startsWith': 'Verifica se o campo começa com o prefixo',
6742
6767
  'praxis.visualBuilder.expression.fn.endsWith': 'Verifica se o campo termina com o sufixo',
6743
6768
  'praxis.visualBuilder.expression.fn.forEach': 'Todos os itens devem seguir a regra',
6744
- 'praxis.visualBuilder.expression.fn.uniqueBy': 'Os itens devem ser únicos pelo campo',
6745
- 'praxis.visualBuilder.expression.fn.minLength': 'Tamanho mínimo da lista',
6746
- 'praxis.visualBuilder.expression.fn.maxLength': 'Tamanho máximo da lista',
6747
- 'praxis.visualBuilder.expression.fn.requiredIf': 'Campo obrigatório quando a condição é verdadeira',
6748
- 'praxis.visualBuilder.expression.fn.visibleIf': 'Campo visível quando a condição é verdadeira',
6749
- 'praxis.visualBuilder.expression.fn.disabledIf': 'Campo desabilitado quando a condição é verdadeira',
6750
- 'praxis.visualBuilder.expression.fn.readonlyIf': 'Campo somente leitura quando a condição é verdadeira',
6751
- 'praxis.visualBuilder.expression.error.parse': 'Erro ao interpretar a expressão',
6752
- 'praxis.visualBuilder.expression.error.validation': 'Erro de validação',
6753
- 'praxis.visualBuilder.expression.hint.startTyping': 'Comece a digitar para ver sugestões...',
6754
- 'praxis.visualBuilder.expression.hint.valid': 'Expressão válida (complexidade {{complexity}})',
6769
+ 'praxis.visualBuilder.expression.fn.uniqueBy': 'Os itens devem ser únicos pelo campo',
6770
+ 'praxis.visualBuilder.expression.fn.minLength': 'Tamanho mínimo da lista',
6771
+ 'praxis.visualBuilder.expression.fn.maxLength': 'Tamanho máximo da lista',
6772
+ 'praxis.visualBuilder.expression.fn.requiredIf': 'Campo obrigatório quando a condição é verdadeira',
6773
+ 'praxis.visualBuilder.expression.fn.visibleIf': 'Campo visível quando a condição é verdadeira',
6774
+ 'praxis.visualBuilder.expression.fn.disabledIf': 'Campo desabilitado quando a condição é verdadeira',
6775
+ 'praxis.visualBuilder.expression.fn.readonlyIf': 'Campo somente leitura quando a condição é verdadeira',
6776
+ 'praxis.visualBuilder.expression.error.parse': 'Erro ao interpretar a expressão',
6777
+ 'praxis.visualBuilder.expression.error.validation': 'Erro de validação',
6778
+ 'praxis.visualBuilder.expression.hint.startTyping': 'Comece a digitar para ver sugestões...',
6779
+ 'praxis.visualBuilder.expression.hint.valid': 'Expressão válida (complexidade {{complexity}})',
6755
6780
  'praxis.visualBuilder.expression.hint.fixItems': '{{count}} ponto(s) para corrigir',
6756
6781
  'praxis.visualBuilder.expression.hint.validating': 'Validando...',
6757
- 'praxis.visualBuilder.expression.summary.valid': 'Expressão válida e pronta para uso',
6782
+ 'praxis.visualBuilder.expression.summary.valid': 'Expressão válida e pronta para uso',
6758
6783
  'praxis.visualBuilder.expression.summary.issues': '{{errors}} erro(s), {{warnings}} aviso(s)',
6759
6784
  'praxis.visualBuilder.expression.operatorSuggestion': 'Operador {{value}}',
6760
6785
  'praxis.visualBuilder.expression.keywordSuggestion': 'Palavra-chave {{value}}',
6761
6786
  'praxis.visualBuilder.conditionalValidator.label.validatorType': 'Tipo de validador',
6762
6787
  'praxis.visualBuilder.conditionalValidator.label.targetField': 'Campo alvo',
6763
- 'praxis.visualBuilder.conditionalValidator.label.logicOperator': 'Operador lógico',
6788
+ 'praxis.visualBuilder.conditionalValidator.label.logicOperator': 'Operador lógico',
6764
6789
  'praxis.visualBuilder.conditionalValidator.label.errorMessage': 'Mensagem de erro personalizada',
6765
- 'praxis.visualBuilder.conditionalValidator.label.animation': 'Animação ao ocultar/exibir',
6766
- 'praxis.visualBuilder.conditionalValidator.label.disabledStyle': 'Aparência quando desabilitado',
6790
+ 'praxis.visualBuilder.conditionalValidator.label.animation': 'Animação ao ocultar/exibir',
6791
+ 'praxis.visualBuilder.conditionalValidator.label.disabledStyle': 'Aparência quando desabilitado',
6767
6792
  'praxis.visualBuilder.conditionalValidator.label.disabledMessage': 'Mensagem ao desabilitar',
6768
- 'praxis.visualBuilder.conditionalValidator.label.readonlyStyle': 'Aparência em modo somente leitura',
6769
- 'praxis.visualBuilder.conditionalValidator.label.logic': 'Lógica:',
6770
- 'praxis.visualBuilder.conditionalValidator.type.requiredIf.label': 'Obrigatório se',
6771
- 'praxis.visualBuilder.conditionalValidator.type.requiredIf.description': 'Campo obrigatório quando a condição for atendida',
6772
- 'praxis.visualBuilder.conditionalValidator.type.visibleIf.label': 'Visível se',
6773
- 'praxis.visualBuilder.conditionalValidator.type.visibleIf.description': 'Campo aparece quando a condição for atendida',
6793
+ 'praxis.visualBuilder.conditionalValidator.label.readonlyStyle': 'Aparência em modo somente leitura',
6794
+ 'praxis.visualBuilder.conditionalValidator.label.logic': 'Lógica:',
6795
+ 'praxis.visualBuilder.conditionalValidator.type.requiredIf.label': 'Obrigatório se',
6796
+ 'praxis.visualBuilder.conditionalValidator.type.requiredIf.description': 'Campo obrigatório quando a condição for atendida',
6797
+ 'praxis.visualBuilder.conditionalValidator.type.visibleIf.label': 'Visível se',
6798
+ 'praxis.visualBuilder.conditionalValidator.type.visibleIf.description': 'Campo aparece quando a condição for atendida',
6774
6799
  'praxis.visualBuilder.conditionalValidator.type.disabledIf.label': 'Desabilitado se',
6775
- 'praxis.visualBuilder.conditionalValidator.type.disabledIf.description': 'Campo fica desabilitado quando a condição for atendida',
6800
+ 'praxis.visualBuilder.conditionalValidator.type.disabledIf.description': 'Campo fica desabilitado quando a condição for atendida',
6776
6801
  'praxis.visualBuilder.conditionalValidator.type.readonlyIf.label': 'Somente leitura se',
6777
- 'praxis.visualBuilder.conditionalValidator.type.readonlyIf.description': 'Campo fica somente leitura quando a condição for atendida',
6778
- 'praxis.visualBuilder.conditionalValidator.help.targetField': 'Escolha o campo que será afetado por esta regra',
6779
- 'praxis.visualBuilder.conditionalValidator.help.errorMessage': 'Substitui a mensagem padrão exibida ao usuário',
6780
- 'praxis.visualBuilder.conditionalValidator.section.condition': 'Configuração da condição',
6781
- 'praxis.visualBuilder.conditionalValidator.section.validation': 'Configurações de validação',
6782
- 'praxis.visualBuilder.conditionalValidator.section.uiBehavior': 'Configurações de comportamento da interface',
6783
- 'praxis.visualBuilder.conditionalValidator.section.preview': 'Pré-visualização',
6784
- 'praxis.visualBuilder.conditionalValidator.mode.simple': 'Condição simples',
6785
- 'praxis.visualBuilder.conditionalValidator.mode.advanced': 'Lógica avançada',
6786
- 'praxis.visualBuilder.conditionalValidator.logic.and': 'E (AND) - todas as condições precisam ser verdadeiras',
6787
- 'praxis.visualBuilder.conditionalValidator.logic.or': 'OU (OR) - qualquer condição pode ser verdadeira',
6788
- 'praxis.visualBuilder.conditionalValidator.logic.not': 'NÃO (NOT) - a condição precisa ser falsa',
6789
- 'praxis.visualBuilder.conditionalValidator.logic.xor': 'XOR - apenas uma condição pode ser verdadeira',
6790
- 'praxis.visualBuilder.conditionalValidator.action.addCondition': 'Adicionar condição',
6791
- 'praxis.visualBuilder.conditionalValidator.placeholder.errorMessage': 'Este campo é obrigatório',
6792
- 'praxis.visualBuilder.conditionalValidator.placeholder.disabledMessage': 'Este campo está desabilitado no momento',
6802
+ 'praxis.visualBuilder.conditionalValidator.type.readonlyIf.description': 'Campo fica somente leitura quando a condição for atendida',
6803
+ 'praxis.visualBuilder.conditionalValidator.help.targetField': 'Escolha o campo que será afetado por esta regra',
6804
+ 'praxis.visualBuilder.conditionalValidator.help.errorMessage': 'Substitui a mensagem padrão exibida ao usuário',
6805
+ 'praxis.visualBuilder.conditionalValidator.section.condition': 'Configuração da condição',
6806
+ 'praxis.visualBuilder.conditionalValidator.section.validation': 'Configurações de validação',
6807
+ 'praxis.visualBuilder.conditionalValidator.section.uiBehavior': 'Configurações de comportamento da interface',
6808
+ 'praxis.visualBuilder.conditionalValidator.section.preview': 'Pré-visualização',
6809
+ 'praxis.visualBuilder.conditionalValidator.mode.simple': 'Condição simples',
6810
+ 'praxis.visualBuilder.conditionalValidator.mode.advanced': 'Lógica avançada',
6811
+ 'praxis.visualBuilder.conditionalValidator.logic.and': 'E (AND) - todas as condições precisam ser verdadeiras',
6812
+ 'praxis.visualBuilder.conditionalValidator.logic.or': 'OU (OR) - qualquer condição pode ser verdadeira',
6813
+ 'praxis.visualBuilder.conditionalValidator.logic.not': 'NÃO (NOT) - a condição precisa ser falsa',
6814
+ 'praxis.visualBuilder.conditionalValidator.logic.xor': 'XOR - apenas uma condição pode ser verdadeira',
6815
+ 'praxis.visualBuilder.conditionalValidator.action.addCondition': 'Adicionar condição',
6816
+ 'praxis.visualBuilder.conditionalValidator.placeholder.errorMessage': 'Este campo é obrigatório',
6817
+ 'praxis.visualBuilder.conditionalValidator.placeholder.disabledMessage': 'Este campo está desabilitado no momento',
6793
6818
  'praxis.visualBuilder.conditionalValidator.option.validateOnChange': 'Validar ao alterar o campo',
6794
6819
  'praxis.visualBuilder.conditionalValidator.option.validateOnBlur': 'Validar ao sair do campo',
6795
- 'praxis.visualBuilder.conditionalValidator.option.showErrorImmediately': 'Exibir erro assim que a condição for atendida',
6796
- 'praxis.visualBuilder.conditionalValidator.option.hideLabel': 'Ocultar rótulo do campo quando escondido',
6797
- 'praxis.visualBuilder.conditionalValidator.option.preserveSpace': 'Preservar espaço ao esconder',
6820
+ 'praxis.visualBuilder.conditionalValidator.option.showErrorImmediately': 'Exibir erro assim que a condição for atendida',
6821
+ 'praxis.visualBuilder.conditionalValidator.option.hideLabel': 'Ocultar rótulo do campo quando escondido',
6822
+ 'praxis.visualBuilder.conditionalValidator.option.preserveSpace': 'Preservar espaço ao esconder',
6798
6823
  'praxis.visualBuilder.conditionalValidator.option.clearOnDisable': 'Limpar valor ao desabilitar',
6799
6824
  'praxis.visualBuilder.conditionalValidator.option.showDisabledMessage': 'Mostrar mensagem quando desabilitado',
6800
- 'praxis.visualBuilder.conditionalValidator.option.showReadonlyIndicator': 'Mostrar ícone indicando somente leitura',
6801
- 'praxis.visualBuilder.conditionalValidator.animation.none': 'Sem animação',
6802
- 'praxis.visualBuilder.conditionalValidator.animation.fade': 'Transição suave (fade)',
6825
+ 'praxis.visualBuilder.conditionalValidator.option.showReadonlyIndicator': 'Mostrar ícone indicando somente leitura',
6826
+ 'praxis.visualBuilder.conditionalValidator.animation.none': 'Sem animação',
6827
+ 'praxis.visualBuilder.conditionalValidator.animation.fade': 'Transição suave (fade)',
6803
6828
  'praxis.visualBuilder.conditionalValidator.animation.slide': 'Deslizante (vertical)',
6804
6829
  'praxis.visualBuilder.conditionalValidator.animation.scale': 'Crescer/encolher',
6805
- 'praxis.visualBuilder.conditionalValidator.disabledStyle.default': 'Padrão (cinza)',
6830
+ 'praxis.visualBuilder.conditionalValidator.disabledStyle.default': 'Padrão (cinza)',
6806
6831
  'praxis.visualBuilder.conditionalValidator.disabledStyle.faded': 'Esmaecido',
6807
6832
  'praxis.visualBuilder.conditionalValidator.disabledStyle.hidden': 'Ocultar totalmente',
6808
- 'praxis.visualBuilder.conditionalValidator.readonlyStyle.default': 'Padrão (não editável)',
6833
+ 'praxis.visualBuilder.conditionalValidator.readonlyStyle.default': 'Padrão (não editável)',
6809
6834
  'praxis.visualBuilder.conditionalValidator.readonlyStyle.display': 'Mostrar apenas o valor',
6810
6835
  'praxis.visualBuilder.conditionalValidator.readonlyStyle.bordered': 'Valor com borda',
6811
6836
  'praxis.visualBuilder.conditionalValidator.category.other': 'Outros',
6812
6837
  'praxis.visualBuilder.conditionalValidator.selectField': 'Selecione um campo',
6813
- 'praxis.visualBuilder.conditionalValidator.summary.incomplete': 'Complete as informações da regra para ver o resumo',
6814
- 'praxis.visualBuilder.conditionalValidator.summary.action.required': 'ficará obrigatório',
6815
- 'praxis.visualBuilder.conditionalValidator.summary.action.visible': 'ficará visível',
6816
- 'praxis.visualBuilder.conditionalValidator.summary.action.disabled': 'ficará desabilitado',
6817
- 'praxis.visualBuilder.conditionalValidator.summary.action.readonly': 'ficará somente leitura',
6818
- 'praxis.visualBuilder.conditionalValidator.summary.simpleCondition': 'quando a condição for atendida',
6819
- 'praxis.visualBuilder.conditionalValidator.summary.advancedCondition': 'quando as condições ({{operator}}) forem atendidas',
6820
- 'praxis.visualBuilder.conditionalValidator.summary.logicPreview.one': '{{operator}} com 1 condição',
6821
- 'praxis.visualBuilder.conditionalValidator.summary.logicPreview.other': '{{operator}} com {{count}} condições',
6838
+ 'praxis.visualBuilder.conditionalValidator.summary.incomplete': 'Complete as informações da regra para ver o resumo',
6839
+ 'praxis.visualBuilder.conditionalValidator.summary.action.required': 'ficará obrigatório',
6840
+ 'praxis.visualBuilder.conditionalValidator.summary.action.visible': 'ficará visível',
6841
+ 'praxis.visualBuilder.conditionalValidator.summary.action.disabled': 'ficará desabilitado',
6842
+ 'praxis.visualBuilder.conditionalValidator.summary.action.readonly': 'ficará somente leitura',
6843
+ 'praxis.visualBuilder.conditionalValidator.summary.simpleCondition': 'quando a condição for atendida',
6844
+ 'praxis.visualBuilder.conditionalValidator.summary.advancedCondition': 'quando as condições ({{operator}}) forem atendidas',
6845
+ 'praxis.visualBuilder.conditionalValidator.summary.logicPreview.one': '{{operator}} com 1 condição',
6846
+ 'praxis.visualBuilder.conditionalValidator.summary.logicPreview.other': '{{operator}} com {{count}} condições',
6822
6847
  'praxis.visualBuilder.conditionalValidator.error.validatorTypeRequired': 'Escolha o tipo de validador',
6823
- 'praxis.visualBuilder.conditionalValidator.error.targetFieldRequired': 'Informe o campo que será avaliado',
6824
- 'praxis.visualBuilder.conditionalValidator.error.conditionRequired': 'Adicione pelo menos uma condição',
6848
+ 'praxis.visualBuilder.conditionalValidator.error.targetFieldRequired': 'Informe o campo que será avaliado',
6849
+ 'praxis.visualBuilder.conditionalValidator.error.conditionRequired': 'Adicione pelo menos uma condição',
6825
6850
  'praxis.visualBuilder.ruleList.eyebrow': 'Regras',
6826
6851
  'praxis.visualBuilder.ruleList.title': 'Regras',
6827
- 'praxis.visualBuilder.ruleList.subtitle': 'Visibilidade, estilo e comportamento em um fluxo único.',
6852
+ 'praxis.visualBuilder.ruleList.subtitle': 'Visibilidade, estilo e comportamento em um fluxo único.',
6828
6853
  'praxis.visualBuilder.ruleList.headerCaption': 'ativas',
6829
6854
  'praxis.visualBuilder.ruleList.searchPlaceholder': 'Buscar regras...',
6830
6855
  'praxis.visualBuilder.ruleList.clearSearch': 'Limpar busca',
@@ -6833,11 +6858,11 @@ const PRAXIS_VISUAL_BUILDER_PT_BR = {
6833
6858
  'praxis.visualBuilder.ruleList.aiButton': 'IA',
6834
6859
  'praxis.visualBuilder.ruleList.listAria': 'Lista de regras',
6835
6860
  'praxis.visualBuilder.ruleList.status.ready': 'Pronta',
6836
- 'praxis.visualBuilder.ruleList.status.valid': 'Válida',
6861
+ 'praxis.visualBuilder.ruleList.status.valid': 'Válida',
6837
6862
  'praxis.visualBuilder.ruleList.status.incomplete': 'Incompleta',
6838
6863
  'praxis.visualBuilder.ruleList.status.draft': 'Rascunho',
6839
6864
  'praxis.visualBuilder.ruleList.status.error': 'Com erro',
6840
- 'praxis.visualBuilder.ruleList.summary.validLabel': 'Válidas',
6865
+ 'praxis.visualBuilder.ruleList.summary.validLabel': 'Válidas',
6841
6866
  'praxis.visualBuilder.ruleList.summary.incompleteLabel': 'Pendentes',
6842
6867
  'praxis.visualBuilder.ruleList.summary.errorLabel': 'Com erro',
6843
6868
  'praxis.visualBuilder.ruleList.filter.all': 'Todas',
@@ -6848,12 +6873,12 @@ const PRAXIS_VISUAL_BUILDER_PT_BR = {
6848
6873
  'praxis.visualBuilder.ruleList.noResults': 'Nenhuma regra encontrada.',
6849
6874
  'praxis.visualBuilder.ruleList.condition.with': 'Condicional',
6850
6875
  'praxis.visualBuilder.ruleList.condition.without': 'Sempre',
6851
- 'praxis.visualBuilder.ruleList.condition.configured': 'Expressão configurada',
6876
+ 'praxis.visualBuilder.ruleList.condition.configured': 'Expressão configurada',
6852
6877
  'praxis.visualBuilder.ruleList.targetType.fieldPlural': 'campos',
6853
- 'praxis.visualBuilder.ruleList.targetType.sectionPlural': 'seções',
6878
+ 'praxis.visualBuilder.ruleList.targetType.sectionPlural': 'seções',
6854
6879
  'praxis.visualBuilder.ruleList.targetType.rowPlural': 'linhas',
6855
6880
  'praxis.visualBuilder.ruleList.targetType.columnPlural': 'colunas',
6856
- 'praxis.visualBuilder.ruleList.targetType.actionPlural': 'ações',
6881
+ 'praxis.visualBuilder.ruleList.targetType.actionPlural': 'ações',
6857
6882
  'praxis.visualBuilder.ruleList.targetType.visualBlockPlural': 'blocos visuais',
6858
6883
  'praxis.visualBuilder.ruleList.target.none': 'Nenhum alvo',
6859
6884
  'praxis.visualBuilder.ruleList.summary.when': 'Quando',
@@ -6873,98 +6898,98 @@ const PRAXIS_VISUAL_BUILDER_PT_BR = {
6873
6898
  'praxis.visualBuilder.ruleList.summary.draft': 'Comece escolhendo um alvo e definindo o efeito principal.',
6874
6899
  'praxis.visualBuilder.ruleList.summary.error': 'A regra precisa de ajuste antes de ser publicada.',
6875
6900
  'praxis.visualBuilder.ruleList.insight.target': 'Alvo principal',
6876
- 'praxis.visualBuilder.ruleList.insight.condition': 'Condição',
6901
+ 'praxis.visualBuilder.ruleList.insight.condition': 'Condição',
6877
6902
  'praxis.visualBuilder.ruleList.insight.effect': 'Efeito',
6878
6903
  'praxis.visualBuilder.ruleList.effect.pending': 'Sem efeito',
6879
6904
  'praxis.visualBuilder.ruleList.effect.whenFalse': 'quando falso',
6880
6905
  'praxis.visualBuilder.ruleList.effect.visibleOn': 'mostrar',
6881
6906
  'praxis.visualBuilder.ruleList.effect.visibleOff': 'ocultar',
6882
- 'praxis.visualBuilder.ruleList.effect.requiredOn': 'tornar obrigatório',
6907
+ 'praxis.visualBuilder.ruleList.effect.requiredOn': 'tornar obrigatório',
6883
6908
  'praxis.visualBuilder.ruleList.effect.requiredOff': 'tornar opcional',
6884
6909
  'praxis.visualBuilder.ruleList.effect.disabledOn': 'desabilitar',
6885
6910
  'praxis.visualBuilder.ruleList.effect.disabledOff': 'habilitar',
6886
6911
  'praxis.visualBuilder.ruleList.effect.set': 'definir',
6887
6912
  'praxis.visualBuilder.ruleList.time.now': 'Agora',
6888
- 'praxis.visualBuilder.ruleList.time.minute': 'min atrás',
6889
- 'praxis.visualBuilder.ruleList.time.minutes': 'min atrás',
6890
- 'praxis.visualBuilder.ruleList.time.hour': 'h atrás',
6891
- 'praxis.visualBuilder.ruleList.time.hours': 'h atrás',
6892
- 'praxis.visualBuilder.ruleList.time.day': 'dia atrás',
6893
- 'praxis.visualBuilder.ruleList.time.days': 'dias atrás',
6913
+ 'praxis.visualBuilder.ruleList.time.minute': 'min atrás',
6914
+ 'praxis.visualBuilder.ruleList.time.minutes': 'min atrás',
6915
+ 'praxis.visualBuilder.ruleList.time.hour': 'h atrás',
6916
+ 'praxis.visualBuilder.ruleList.time.hours': 'h atrás',
6917
+ 'praxis.visualBuilder.ruleList.time.day': 'dia atrás',
6918
+ 'praxis.visualBuilder.ruleList.time.days': 'dias atrás',
6894
6919
  'praxis.visualBuilder.target.title': 'Alvos',
6895
6920
  'praxis.visualBuilder.target.subtitle': 'Onde aplicar a regra',
6896
6921
  'praxis.visualBuilder.target.description': 'Escolha um tipo de alvo e selecione os itens que a regra vai afetar.',
6897
6922
  'praxis.visualBuilder.target.heroTitle': 'Selecione os alvos da regra',
6898
- 'praxis.visualBuilder.target.heroDescription': 'Defina onde esta regra será aplicada: campos, seções, linhas, colunas ou ações do formulário.',
6899
- 'praxis.visualBuilder.target.heroHint': 'Escolha um tipo de alvo e selecione os elementos específicos do formulário.',
6923
+ 'praxis.visualBuilder.target.heroDescription': 'Defina onde esta regra será aplicada: campos, seções, linhas, colunas ou ações do formulário.',
6924
+ 'praxis.visualBuilder.target.heroHint': 'Escolha um tipo de alvo e selecione os elementos específicos do formulário.',
6900
6925
  'praxis.visualBuilder.target.selectTitle': 'Selecionar alvos',
6901
- 'praxis.visualBuilder.target.searchPlaceholder': 'Filtrar por rótulo ou ID interno...',
6926
+ 'praxis.visualBuilder.target.searchPlaceholder': 'Filtrar por rótulo ou ID interno...',
6902
6927
  'praxis.visualBuilder.target.searchClear': 'Limpar busca',
6903
6928
  'praxis.visualBuilder.target.noResults': 'Nenhum alvo encontrado.',
6904
6929
  'praxis.visualBuilder.target.selectedLabel': 'Alvos selecionados',
6905
6930
  'praxis.visualBuilder.target.selectedSummary': 'selecionados',
6906
- 'praxis.visualBuilder.target.stats.available': 'disponíveis',
6931
+ 'praxis.visualBuilder.target.stats.available': 'disponíveis',
6907
6932
  'praxis.visualBuilder.target.stats.selected': 'selecionados',
6908
- 'praxis.visualBuilder.target.group.availableSingular': 'disponível',
6909
- 'praxis.visualBuilder.target.group.availablePlural': 'disponíveis',
6933
+ 'praxis.visualBuilder.target.group.availableSingular': 'disponível',
6934
+ 'praxis.visualBuilder.target.group.availablePlural': 'disponíveis',
6910
6935
  'praxis.visualBuilder.target.group.fields': 'Campos',
6911
6936
  'praxis.visualBuilder.target.meta.internalId': 'ID interno',
6912
- 'praxis.visualBuilder.target.meta.scope': 'do formulário',
6937
+ 'praxis.visualBuilder.target.meta.scope': 'do formulário',
6913
6938
  'praxis.visualBuilder.target.type.field.label': 'Campo',
6914
6939
  'praxis.visualBuilder.target.type.field.labelPlural': 'Campos',
6915
- 'praxis.visualBuilder.target.type.field.description': 'Campos específicos.',
6916
- 'praxis.visualBuilder.target.type.section.label': 'Seção',
6917
- 'praxis.visualBuilder.target.type.section.labelPlural': 'Seções',
6918
- 'praxis.visualBuilder.target.type.section.description': 'Seção inteira.',
6940
+ 'praxis.visualBuilder.target.type.field.description': 'Campos específicos.',
6941
+ 'praxis.visualBuilder.target.type.section.label': 'Seção',
6942
+ 'praxis.visualBuilder.target.type.section.labelPlural': 'Seções',
6943
+ 'praxis.visualBuilder.target.type.section.description': 'Seção inteira.',
6919
6944
  'praxis.visualBuilder.target.type.row.label': 'Linha',
6920
6945
  'praxis.visualBuilder.target.type.row.labelPlural': 'Linhas',
6921
6946
  'praxis.visualBuilder.target.type.row.description': 'Linha do layout.',
6922
6947
  'praxis.visualBuilder.target.type.column.label': 'Coluna',
6923
6948
  'praxis.visualBuilder.target.type.column.labelPlural': 'Colunas',
6924
6949
  'praxis.visualBuilder.target.type.column.description': 'Coluna do layout.',
6925
- 'praxis.visualBuilder.target.type.action.label': 'Ação',
6926
- 'praxis.visualBuilder.target.type.action.labelPlural': 'Ações',
6927
- 'praxis.visualBuilder.target.type.action.description': 'Botões de ação.',
6950
+ 'praxis.visualBuilder.target.type.action.label': 'Ação',
6951
+ 'praxis.visualBuilder.target.type.action.labelPlural': 'Ações',
6952
+ 'praxis.visualBuilder.target.type.action.description': 'Botões de ação.',
6928
6953
  'praxis.visualBuilder.target.type.visualBlock.label': 'Bloco visual',
6929
6954
  'praxis.visualBuilder.target.type.visualBlock.labelPlural': 'Blocos visuais',
6930
6955
  'praxis.visualBuilder.target.type.visualBlock.description': 'Bloco editorial no layout.',
6931
6956
  'praxis.visualBuilder.target.type.allPlural': 'Alvos',
6932
6957
  'praxis.visualBuilder.ruleDefinition.step1.title': 'Alvos',
6933
6958
  'praxis.visualBuilder.ruleDefinition.step1.subtitle': 'Onde aplicar',
6934
- 'praxis.visualBuilder.ruleDefinition.step1.question': 'Escolha onde essa regra entra em ação.',
6935
- 'praxis.visualBuilder.ruleDefinition.step2.title': 'Condição',
6959
+ 'praxis.visualBuilder.ruleDefinition.step1.question': 'Escolha onde essa regra entra em ação.',
6960
+ 'praxis.visualBuilder.ruleDefinition.step2.title': 'Condição',
6936
6961
  'praxis.visualBuilder.ruleDefinition.step2.subtitle': 'Quando executar',
6937
6962
  'praxis.visualBuilder.ruleDefinition.step2.question': 'Quando a regra deve ser aplicada?',
6938
6963
  'praxis.visualBuilder.ruleDefinition.step3.title': 'Efeitos',
6939
6964
  'praxis.visualBuilder.ruleDefinition.step3.subtitle': 'O que fazer',
6940
- 'praxis.visualBuilder.ruleDefinition.step3.question': 'O que deve acontecer quando a condição for satisfeita?',
6941
- 'praxis.visualBuilder.ruleDefinition.step4.title': 'Revisão',
6965
+ 'praxis.visualBuilder.ruleDefinition.step3.question': 'O que deve acontecer quando a condição for satisfeita?',
6966
+ 'praxis.visualBuilder.ruleDefinition.step4.title': 'Revisão',
6942
6967
  'praxis.visualBuilder.ruleDefinition.step4.subtitle': 'Confirmar regra',
6943
6968
  'praxis.visualBuilder.ruleDefinition.step4.question': 'Revise e confirme a regra',
6944
- 'praxis.visualBuilder.ruleDefinition.action.next': 'Próximo',
6969
+ 'praxis.visualBuilder.ruleDefinition.action.next': 'Próximo',
6945
6970
  'praxis.visualBuilder.ruleDefinition.action.previous': 'Anterior',
6946
6971
  'praxis.visualBuilder.ruleDefinition.action.cancel': 'Cancelar',
6947
6972
  'praxis.visualBuilder.ruleDefinition.action.reset': 'Resetar',
6948
6973
  'praxis.visualBuilder.ruleDefinition.action.save': 'Salvar regra',
6949
6974
  'praxis.visualBuilder.ruleDefinition.conditionMode.always': 'Sempre',
6950
6975
  'praxis.visualBuilder.ruleDefinition.conditionMode.visual': 'Visual',
6951
- 'praxis.visualBuilder.ruleDefinition.conditionWarning.tooltip': 'Altere o alvo ou ajuste os campos da condição para este contexto.',
6976
+ 'praxis.visualBuilder.ruleDefinition.conditionWarning.tooltip': 'Altere o alvo ou ajuste os campos da condição para este contexto.',
6952
6977
  'praxis.visualBuilder.ruleDefinition.conditionWarning.prefix': 'Campos fora do contexto atual',
6953
- 'praxis.visualBuilder.ruleDefinition.conditionWarning.suffix': 'Eles serão ignorados até você escolher campos compatíveis.',
6954
- 'praxis.visualBuilder.ruleDefinition.condition.alwaysHint': 'A regra será aplicada sempre.',
6978
+ 'praxis.visualBuilder.ruleDefinition.conditionWarning.suffix': 'Eles serão ignorados até você escolher campos compatíveis.',
6979
+ 'praxis.visualBuilder.ruleDefinition.condition.alwaysHint': 'A regra será aplicada sempre.',
6955
6980
  'praxis.visualBuilder.ruleDefinition.review.targets': 'Alvos selecionados',
6956
6981
  'praxis.visualBuilder.ruleDefinition.review.heroTitle': 'Resumo da regra',
6957
6982
  'praxis.visualBuilder.ruleDefinition.review.noTargets': 'Nenhum alvo selecionado.',
6958
- 'praxis.visualBuilder.ruleDefinition.review.condition': 'Condição',
6983
+ 'praxis.visualBuilder.ruleDefinition.review.condition': 'Condição',
6959
6984
  'praxis.visualBuilder.ruleDefinition.review.mode': 'Modo',
6960
- 'praxis.visualBuilder.ruleDefinition.review.alwaysMode': 'Sempre (sem condição)',
6985
+ 'praxis.visualBuilder.ruleDefinition.review.alwaysMode': 'Sempre (sem condição)',
6961
6986
  'praxis.visualBuilder.ruleDefinition.review.effects': 'Efeitos',
6962
6987
  'praxis.visualBuilder.ruleDefinition.review.whenFalse': 'Quando falso',
6963
- 'praxis.visualBuilder.ruleDefinition.review.whenFalseNone': 'Sem ação adicional',
6964
- 'praxis.visualBuilder.ruleDefinition.review.technical': 'Detalhes técnicos',
6965
- 'praxis.visualBuilder.ruleDefinition.review.conditionJson': 'JSON da condição',
6966
- 'praxis.visualBuilder.ruleDefinition.review.summary.always': 'sempre que o formulário estiver neste contexto',
6967
- 'praxis.visualBuilder.ruleDefinition.review.summary.conditional': 'quando a condição configurada for satisfeita',
6988
+ 'praxis.visualBuilder.ruleDefinition.review.whenFalseNone': 'Sem ação adicional',
6989
+ 'praxis.visualBuilder.ruleDefinition.review.technical': 'Detalhes técnicos',
6990
+ 'praxis.visualBuilder.ruleDefinition.review.conditionJson': 'JSON da condição',
6991
+ 'praxis.visualBuilder.ruleDefinition.review.summary.always': 'sempre que o formulário estiver neste contexto',
6992
+ 'praxis.visualBuilder.ruleDefinition.review.summary.conditional': 'quando a condição configurada for satisfeita',
6968
6993
  'praxis.visualBuilder.ruleDefinition.review.json': 'JSON da regra',
6969
6994
  'praxis.visualBuilder.ruleDefinition.review.effects.noneEditorial': 'Nenhum efeito principal definido',
6970
6995
  'praxis.visualBuilder.ruleDefinition.conditionDescription.always': 'Sempre',
@@ -6974,14 +6999,14 @@ const PRAXIS_VISUAL_BUILDER_PT_BR = {
6974
6999
  'praxis.visualBuilder.ruleDefinition.effects.trueCount': 'efeito(s) verdadeiro(s)',
6975
7000
  'praxis.visualBuilder.ruleDefinition.effects.falseCount': 'efeito(s) falso(s)',
6976
7001
  'praxis.visualBuilder.ruleDefinition.targetType.fieldPlural': 'Campos',
6977
- 'praxis.visualBuilder.ruleDefinition.targetType.sectionPlural': 'Seções',
7002
+ 'praxis.visualBuilder.ruleDefinition.targetType.sectionPlural': 'Seções',
6978
7003
  'praxis.visualBuilder.ruleDefinition.targetType.rowPlural': 'Linhas',
6979
7004
  'praxis.visualBuilder.ruleDefinition.targetType.columnPlural': 'Colunas',
6980
- 'praxis.visualBuilder.ruleDefinition.targetType.actionPlural': 'Ações',
7005
+ 'praxis.visualBuilder.ruleDefinition.targetType.actionPlural': 'Ações',
6981
7006
  'praxis.visualBuilder.ruleDefinition.targetType.visualBlockPlural': 'Blocos visuais',
6982
7007
  'praxis.visualBuilder.ruleDefinition.effect.visibleOn': 'Mostrar os elementos selecionados',
6983
7008
  'praxis.visualBuilder.ruleDefinition.effect.visibleOff': 'Ocultar os elementos selecionados',
6984
- 'praxis.visualBuilder.ruleDefinition.effect.requiredOn': 'Tornar os campos obrigatórios',
7009
+ 'praxis.visualBuilder.ruleDefinition.effect.requiredOn': 'Tornar os campos obrigatórios',
6985
7010
  'praxis.visualBuilder.ruleDefinition.effect.requiredOff': 'Tornar os campos opcionais',
6986
7011
  'praxis.visualBuilder.ruleDefinition.effect.disabledOn': 'Desabilitar os elementos selecionados',
6987
7012
  'praxis.visualBuilder.ruleDefinition.effect.disabledOff': 'Habilitar os elementos selecionados',
@@ -6991,11 +7016,11 @@ const PRAXIS_VISUAL_BUILDER_PT_BR = {
6991
7016
  'praxis.visualBuilder.ruleEditor.shell.breadcrumb': 'Editor de regras',
6992
7017
  'praxis.visualBuilder.ruleEditor.shell.nav.layout': 'Layout',
6993
7018
  'praxis.visualBuilder.ruleEditor.shell.nav.rules': 'Regras',
6994
- 'praxis.visualBuilder.ruleEditor.shell.nav.docs': 'Documentação',
6995
- 'praxis.visualBuilder.ruleEditor.shell.unsaved': 'Alterações não salvas',
7019
+ 'praxis.visualBuilder.ruleEditor.shell.nav.docs': 'Documentação',
7020
+ 'praxis.visualBuilder.ruleEditor.shell.unsaved': 'Alterações não salvas',
6996
7021
  'praxis.visualBuilder.ruleEditor.toolbar.collapseList': 'Recolher painel lateral',
6997
7022
  'praxis.visualBuilder.ruleEditor.toolbar.expandList': 'Expandir painel lateral',
6998
- 'praxis.visualBuilder.ruleEditor.toolbar.aiTooltip': 'Descreva sua regra e a IA monta o rascunho para você',
7023
+ 'praxis.visualBuilder.ruleEditor.toolbar.aiTooltip': 'Descreva sua regra e a IA monta o rascunho para você',
6999
7024
  'praxis.visualBuilder.ruleEditor.toolbar.newRule': 'Nova regra',
7000
7025
  'praxis.visualBuilder.ruleEditor.toolbar.aiButton': 'Criar com IA',
7001
7026
  'praxis.visualBuilder.ruleEditor.toolbar.undo': 'Desfazer',
@@ -7004,11 +7029,11 @@ const PRAXIS_VISUAL_BUILDER_PT_BR = {
7004
7029
  'praxis.visualBuilder.ruleEditor.toolbar.export': 'Exportar',
7005
7030
  'praxis.visualBuilder.ruleEditor.toolbar.importTooltip': 'Importar regras',
7006
7031
  'praxis.visualBuilder.ruleEditor.toolbar.import': 'Importar',
7007
- 'praxis.visualBuilder.ruleEditor.toolbar.advanced': 'Mais opções',
7008
- 'praxis.visualBuilder.ruleEditor.toolbar.devOptions': 'Opções de desenvolvedor',
7032
+ 'praxis.visualBuilder.ruleEditor.toolbar.advanced': 'Mais opções',
7033
+ 'praxis.visualBuilder.ruleEditor.toolbar.devOptions': 'Opções de desenvolvedor',
7009
7034
  'praxis.visualBuilder.ruleEditor.hero.eyebrow': 'Builder visual',
7010
7035
  'praxis.visualBuilder.ruleEditor.hero.title': 'Construa regras com clareza visual',
7011
- 'praxis.visualBuilder.ruleEditor.hero.subtitle': 'Combine alvos, condições e efeitos em uma experiência guiada para usuários de negócio e usuários técnicos.',
7036
+ 'praxis.visualBuilder.ruleEditor.hero.subtitle': 'Combine alvos, condições e efeitos em uma experiência guiada para usuários de negócio e usuários técnicos.',
7012
7037
  'praxis.visualBuilder.ruleEditor.hero.progress': 'Progresso',
7013
7038
  'praxis.visualBuilder.ruleEditor.hero.progressOf': 'de',
7014
7039
  'praxis.visualBuilder.ruleEditor.hero.progressEmpty': '0 de 0',
@@ -7017,30 +7042,30 @@ const PRAXIS_VISUAL_BUILDER_PT_BR = {
7017
7042
  'praxis.visualBuilder.ruleEditor.hero.healthError': 'Revisar',
7018
7043
  'praxis.visualBuilder.ruleEditor.hero.healthProgress': 'Em progresso',
7019
7044
  'praxis.visualBuilder.ruleEditor.hero.healthIdle': 'Em branco',
7020
- 'praxis.visualBuilder.ruleEditor.hero.selectedFallback': 'Regra em edição',
7045
+ 'praxis.visualBuilder.ruleEditor.hero.selectedFallback': 'Regra em edição',
7021
7046
  'praxis.visualBuilder.ruleEditor.hero.targetCount': 'alvo(s)',
7022
7047
  'praxis.visualBuilder.ruleEditor.hero.conditional': 'condicional',
7023
7048
  'praxis.visualBuilder.ruleEditor.hero.always': 'sempre ativa',
7024
7049
  'praxis.visualBuilder.ruleEditor.hero.effectCount': 'efeito(s)',
7025
- 'praxis.visualBuilder.ruleEditor.debug.show': 'Mostrar painel de depuração (debug)',
7026
- 'praxis.visualBuilder.ruleEditor.debug.hide': 'Ocultar painel de depuração (debug)',
7050
+ 'praxis.visualBuilder.ruleEditor.debug.show': 'Mostrar painel de depuração (debug)',
7051
+ 'praxis.visualBuilder.ruleEditor.debug.hide': 'Ocultar painel de depuração (debug)',
7027
7052
  'praxis.visualBuilder.ruleEditor.debug.clearAll': 'Limpar tudo',
7028
- 'praxis.visualBuilder.ruleEditor.debug.title': 'Estado de depuração (debug)',
7029
- 'praxis.visualBuilder.ruleEditor.unsupported.title': 'Tipo de regra não suportado',
7030
- 'praxis.visualBuilder.ruleEditor.unsupported.body': 'Este nó usa um formato legado. Remova e recrie como regra de propriedade.',
7053
+ 'praxis.visualBuilder.ruleEditor.debug.title': 'Estado de depuração (debug)',
7054
+ 'praxis.visualBuilder.ruleEditor.unsupported.title': 'Tipo de regra não suportado',
7055
+ 'praxis.visualBuilder.ruleEditor.unsupported.body': 'Este usa um formato legado. Remova e recrie como regra de propriedade.',
7031
7056
  'praxis.visualBuilder.ruleEditor.empty.title': 'Selecione uma regra ou crie uma nova',
7032
- 'praxis.visualBuilder.ruleEditor.empty.body': 'Monte regras visuais com alvo, condição e efeito em uma trilha guiada.',
7057
+ 'praxis.visualBuilder.ruleEditor.empty.body': 'Monte regras visuais com alvo, condição e efeito em uma trilha guiada.',
7033
7058
  'praxis.visualBuilder.ruleEditor.empty.cta': 'Criar regra',
7034
7059
  'praxis.visualBuilder.ruleEditor.status.rules': 'Regras',
7035
- 'praxis.visualBuilder.ruleEditor.status.unsaved': 'Não salvo',
7060
+ 'praxis.visualBuilder.ruleEditor.status.unsaved': 'Não salvo',
7036
7061
  'praxis.visualBuilder.ruleEditor.status.errors': 'erro(s)',
7037
- 'praxis.visualBuilder.ruleEditor.status.valid': 'Válido',
7062
+ 'praxis.visualBuilder.ruleEditor.status.valid': 'Válido',
7038
7063
  'praxis.visualBuilder.ruleEditor.confirm.clearAll': 'Tem certeza que deseja apagar todas as regras?',
7039
7064
  'praxis.visualBuilder.ruleEditor.confirm.removeRule': 'Remover esta regra?',
7040
7065
  'praxis.visualBuilder.ruleEditor.action.close': 'Fechar',
7041
7066
  'praxis.visualBuilder.ruleEditor.actionLabel.show': 'Mostrar',
7042
7067
  'praxis.visualBuilder.ruleEditor.actionLabel.hide': 'Ocultar',
7043
- 'praxis.visualBuilder.ruleEditor.actionLabel.require': 'Tornar obrigatório',
7068
+ 'praxis.visualBuilder.ruleEditor.actionLabel.require': 'Tornar obrigatório',
7044
7069
  'praxis.visualBuilder.ruleEditor.actionLabel.optional': 'Tornar opcional',
7045
7070
  'praxis.visualBuilder.ruleEditor.actionLabel.disable': 'Desabilitar',
7046
7071
  'praxis.visualBuilder.ruleEditor.actionLabel.enable': 'Habilitar',
@@ -7048,12 +7073,12 @@ const PRAXIS_VISUAL_BUILDER_PT_BR = {
7048
7073
  'praxis.visualBuilder.ruleEditor.label.ruleFor': 'Regra para',
7049
7074
  'praxis.visualBuilder.ruleEditor.label.targets': 'alvo(s)',
7050
7075
  'praxis.visualBuilder.ruleEditor.label.newWithoutTargets': 'Nova regra sem alvos',
7051
- 'praxis.visualBuilder.ruleEditor.label.withCondition': 'com condição',
7052
- 'praxis.visualBuilder.ruleEditor.validation.found': 'erro(s) de validação encontrado(s)',
7076
+ 'praxis.visualBuilder.ruleEditor.label.withCondition': 'com condição',
7077
+ 'praxis.visualBuilder.ruleEditor.validation.found': 'erro(s) de validação encontrado(s)',
7053
7078
  'praxis.visualBuilder.ruleEditor.validation.view': 'Ver',
7054
7079
  'praxis.visualBuilder.ruleEditor.newRule': 'Nova regra',
7055
- 'praxis.visualBuilder.ruleEditor.duplicateCopy': 'cópia',
7056
- 'praxis.visualBuilder.ruleEditor.import.success': 'Importação concluída',
7080
+ 'praxis.visualBuilder.ruleEditor.duplicateCopy': 'cópia',
7081
+ 'praxis.visualBuilder.ruleEditor.import.success': 'Importação concluída',
7057
7082
  'praxis.visualBuilder.ruleEditor.import.failure': 'Falha ao importar regras',
7058
7083
  'praxis.visualBuilder.ruleEditor.ai.applyError': 'Erro ao aplicar regra',
7059
7084
  'praxis.visualBuilder.ruleEditor.ai.draftPrefix': 'IA',
@@ -12126,6 +12151,7 @@ class RuleDefinitionComponent {
12126
12151
  <button
12127
12152
  mat-stroked-button
12128
12153
  type="button"
12154
+ data-testid="rule-definition-previous"
12129
12155
  (click)="goPrevious()"
12130
12156
  [disabled]="selectedStepIndex === 0"
12131
12157
  >
@@ -12135,6 +12161,7 @@ class RuleDefinitionComponent {
12135
12161
  mat-flat-button
12136
12162
  color="primary"
12137
12163
  type="button"
12164
+ [attr.data-testid]="selectedStepIndex === 3 ? 'rule-definition-save' : 'rule-definition-next'"
12138
12165
  (click)="goNext()"
12139
12166
  [disabled]="!canAdvance()"
12140
12167
  >
@@ -12428,6 +12455,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
12428
12455
  <button
12429
12456
  mat-stroked-button
12430
12457
  type="button"
12458
+ data-testid="rule-definition-previous"
12431
12459
  (click)="goPrevious()"
12432
12460
  [disabled]="selectedStepIndex === 0"
12433
12461
  >
@@ -12437,6 +12465,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
12437
12465
  mat-flat-button
12438
12466
  color="primary"
12439
12467
  type="button"
12468
+ [attr.data-testid]="selectedStepIndex === 3 ? 'rule-definition-save' : 'rule-definition-next'"
12440
12469
  (click)="goNext()"
12441
12470
  [disabled]="!canAdvance()"
12442
12471
  >
@@ -13744,7 +13773,7 @@ class RuleEditorComponent {
13744
13773
  (change)="onFileSelected($event)"
13745
13774
  />
13746
13775
  </div>
13747
- `, isInline: true, styles: [".rule-editor-container{--_pvb-editor-accent: var(--md-sys-color-primary, var(--sicoob-primary-default));--_pvb-editor-accent-soft: color-mix(in srgb, var(--_pvb-editor-accent) 16%, transparent);--_pvb-editor-surface: var(--md-sys-color-surface, var(--sicoob-background-primary));--_pvb-editor-surface-low: var(--md-sys-color-surface-container-low, var(--sicoob-background-secondary));--_pvb-editor-surface-strong: var(--md-sys-color-surface-container, var(--sicoob-background-tertiary));--_pvb-editor-border: var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium));--_pvb-editor-text: var(--md-sys-color-on-surface, var(--sicoob-text-default));--_pvb-editor-text-soft: var(--md-sys-color-on-surface-variant, var(--sicoob-text-subtle));display:flex;flex-direction:column;height:100%;background:radial-gradient(circle at top center,color-mix(in srgb,var(--_pvb-editor-accent) 12%,transparent) 0%,transparent 32%),linear-gradient(180deg,color-mix(in srgb,var(--_pvb-editor-surface-low) 96%,black 4%),color-mix(in srgb,var(--_pvb-editor-surface) 98%,black 2%));overflow:hidden;position:relative;color:var(--_pvb-editor-text)}.rule-editor-container.embedded{height:100%}.condition-only-editor{display:flex;flex-direction:column;height:100%;min-height:360px;overflow:hidden}.condition-only-header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 16px;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 68%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 94%,black 6%)}.condition-only-header h3{margin:0;font-size:16px;font-weight:600}.condition-only-header p{margin:4px 0 0;font-size:12px;color:var(--_pvb-editor-text-soft)}.condition-only-canvas{flex:1;min-height:0}.builder-shell-header{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:54px;padding:0 18px;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 68%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 94%,black 6%);flex-shrink:0}.shell-brand{display:flex;align-items:center;gap:10px;min-width:0}.shell-menu{margin-right:2px}.brand-mark{width:32px;height:32px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--_pvb-editor-accent) 16%,transparent);border:1px solid color-mix(in srgb,var(--_pvb-editor-accent) 24%,transparent)}.brand-mark mat-icon{display:flex;align-items:center;justify-content:center;font-size:18px;width:18px;height:18px;color:var(--_pvb-editor-accent)}.brand-copy{display:flex;flex-direction:column;gap:2px;min-width:0}.brand-title{font-size:14px;font-weight:700}.brand-breadcrumb{font-size:12px;color:var(--_pvb-editor-text-soft)}.shell-nav{display:inline-flex;align-items:center;gap:10px;padding:4px;border-radius:14px;background:color-mix(in srgb,var(--_pvb-editor-surface-low) 94%,black 6%);border:1px solid color-mix(in srgb,var(--_pvb-editor-border) 56%,transparent)}.nav-pill{min-width:96px;height:34px;border:0;border-radius:10px;background:transparent;color:var(--_pvb-editor-text-soft);font:inherit;font-size:13px;cursor:default}.nav-pill.active{color:var(--_pvb-editor-text);background:color-mix(in srgb,var(--_pvb-editor-accent) 16%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--_pvb-editor-accent) 34%,transparent)}.shell-status{display:flex;align-items:center;gap:6px}.unsaved-indicator{display:inline-flex;align-items:center;gap:8px;font-size:13px;color:var(--_pvb-editor-text);margin-right:6px}.unsaved-dot{width:8px;height:8px;border-radius:999px;background:#f0b429;box-shadow:0 0 12px #f0b42973}.builder-shell-header button[mat-icon-button]{width:36px;height:36px;line-height:36px;padding:8px}.builder-shell-header button[mat-icon-button] mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.editor-content-grid{display:grid;grid-template-columns:360px 1fr;flex:1;overflow:hidden;min-height:0;transition:grid-template-columns .2s ease}.editor-content-grid.list-closed{grid-template-columns:0 1fr}.rule-list-panel{border-right:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-low) 94%,black 6%);display:flex;flex-direction:column;overflow:hidden}.rule-definition-panel{background:radial-gradient(circle at 50% 0%,color-mix(in srgb,var(--_pvb-editor-accent) 8%,transparent) 0%,transparent 26%),transparent;overflow:hidden;display:flex;flex-direction:column;position:relative;min-height:0;flex:1}.empty-state,.unsupported-node{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--_pvb-editor-text-soft);gap:16px;text-align:center;padding:32px}.empty-state mat-icon,.unsupported-node mat-icon{font-size:64px;width:64px;height:64px;opacity:.9;color:var(--_pvb-editor-accent)}.status-bar{height:32px;background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 92%,black 8%);border-top:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent);display:flex;align-items:center;justify-content:space-between;padding:0 16px;font-size:12px;color:var(--_pvb-editor-text-soft);flex-shrink:0}.status-left,.status-center{display:flex;align-items:center;gap:8px}.validation-status{display:flex;align-items:center;gap:4px}.validation-status.error{color:var(--md-sys-color-error)}.validation-status.success{color:var(--md-sys-color-tertiary)}.validation-status mat-icon{font-size:16px;width:16px;height:16px}.debug-panel{position:absolute;top:0;right:0;bottom:0;width:400px;background:var(--_pvb-editor-surface);border-left:1px solid var(--_pvb-editor-border);box-shadow:-2px 0 8px #0000001a;z-index:var(--praxis-layer-authoring-toolbar, 340);display:flex;flex-direction:column}.debug-header{padding:8px 16px;border-bottom:1px solid var(--_pvb-editor-border);display:flex;align-items:center;justify-content:space-between;background:var(--_pvb-editor-surface-strong)}.debug-content{flex:1;overflow:auto;padding:16px;font-family:monospace;font-size:12px}@media(max-width:1180px){.builder-shell-header{flex-wrap:wrap;justify-content:flex-start;padding:10px 14px}.shell-nav{order:3;width:100%;justify-content:center}.shell-status{margin-left:auto}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "ngmodule", type: MatSidenavModule }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i10$1.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i7$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: RuleListComponent, selector: "praxis-rule-list", inputs: ["rules", "selectedRuleId", "nodeMap", "validationErrors"], outputs: ["ruleSelected", "ruleDeleted", "ruleDuplicated", "ruleAdded", "aiRequested"] }, { kind: "component", type: RuleDefinitionComponent, selector: "praxis-rule-definition", inputs: ["ruleNode", "fieldSchemas", "targetSchemas", "propertySchema"], outputs: ["ruleChanged"] }, { kind: "component", type: RuleCanvasComponent, selector: "praxis-rule-canvas", inputs: ["conditionOnly", "state", "fieldSchemas", "validationErrors"], outputs: ["nodeSelected", "nodeAdded", "nodeUpdated", "nodeRemoved"] }, { kind: "pipe", type: i12$1.JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13776
+ `, isInline: true, styles: [".rule-editor-container{--_pvb-editor-accent: var(--md-sys-color-primary, var(--sicoob-primary-default));--_pvb-editor-accent-soft: color-mix(in srgb, var(--_pvb-editor-accent) 16%, transparent);--_pvb-editor-surface: var(--md-sys-color-surface, var(--sicoob-background-primary));--_pvb-editor-surface-low: var(--md-sys-color-surface-container-low, var(--sicoob-background-secondary));--_pvb-editor-surface-strong: var(--md-sys-color-surface-container, var(--sicoob-background-tertiary));--_pvb-editor-border: var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium));--_pvb-editor-text: var(--md-sys-color-on-surface, var(--sicoob-text-default));--_pvb-editor-text-soft: var(--md-sys-color-on-surface-variant, var(--sicoob-text-subtle));display:flex;flex-direction:column;height:100%;background:radial-gradient(circle at top center,color-mix(in srgb,var(--_pvb-editor-accent) 12%,transparent) 0%,transparent 32%),linear-gradient(180deg,color-mix(in srgb,var(--_pvb-editor-surface-low) 96%,black 4%),color-mix(in srgb,var(--_pvb-editor-surface) 98%,black 2%));overflow:hidden;position:relative;color:var(--_pvb-editor-text)}.rule-editor-container.embedded{height:100%}.condition-only-editor{display:flex;flex-direction:column;height:100%;min-height:360px;overflow:hidden}.condition-only-header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 16px;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 68%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 94%,black 6%)}.condition-only-header h3{margin:0;font-size:16px;font-weight:600}.condition-only-header p{margin:4px 0 0;font-size:12px;color:var(--_pvb-editor-text-soft)}.condition-only-canvas{flex:1;min-height:0}.builder-shell-header{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:54px;padding:0 18px;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 68%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 94%,black 6%);flex-shrink:0}.shell-brand{display:flex;align-items:center;gap:10px;min-width:0}.shell-menu{margin-right:2px}.brand-mark{width:32px;height:32px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--_pvb-editor-accent) 16%,transparent);border:1px solid color-mix(in srgb,var(--_pvb-editor-accent) 24%,transparent)}.brand-mark mat-icon{display:flex;align-items:center;justify-content:center;font-size:18px;width:18px;height:18px;color:var(--_pvb-editor-accent)}.brand-copy{display:flex;flex-direction:column;gap:2px;min-width:0}.brand-title{font-size:14px;font-weight:700}.brand-breadcrumb{font-size:12px;color:var(--_pvb-editor-text-soft)}.shell-nav{display:inline-flex;align-items:center;gap:10px;padding:4px;border-radius:14px;background:color-mix(in srgb,var(--_pvb-editor-surface-low) 94%,black 6%);border:1px solid color-mix(in srgb,var(--_pvb-editor-border) 56%,transparent)}.nav-pill{min-width:96px;height:34px;border:0;border-radius:10px;background:transparent;color:var(--_pvb-editor-text-soft);font:inherit;font-size:13px;cursor:default}.nav-pill.active{color:var(--_pvb-editor-text);background:color-mix(in srgb,var(--_pvb-editor-accent) 16%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--_pvb-editor-accent) 34%,transparent)}.shell-status{display:flex;align-items:center;gap:6px}.unsaved-indicator{display:inline-flex;align-items:center;gap:8px;font-size:13px;color:var(--_pvb-editor-text);margin-right:6px}.unsaved-dot{width:8px;height:8px;border-radius:999px;background:#f0b429;box-shadow:0 0 12px #f0b42973}.builder-shell-header button[mat-icon-button]{width:36px;height:36px;line-height:36px;padding:8px}.builder-shell-header button[mat-icon-button] mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.editor-content-grid{display:grid;grid-template-columns:360px 1fr;flex:1;overflow:hidden;min-height:0;min-width:0;transition:grid-template-columns .2s ease}.editor-content-grid.list-closed{grid-template-columns:0 1fr}.rule-list-panel{border-right:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-low) 94%,black 6%);display:flex;flex-direction:column;overflow:hidden;min-width:0}.rule-definition-panel{background:radial-gradient(circle at 50% 0%,color-mix(in srgb,var(--_pvb-editor-accent) 8%,transparent) 0%,transparent 26%),transparent;overflow:hidden;display:flex;flex-direction:column;position:relative;min-height:0;min-width:0;flex:1}.empty-state,.unsupported-node{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--_pvb-editor-text-soft);gap:16px;text-align:center;padding:32px}.empty-state mat-icon,.unsupported-node mat-icon{font-size:64px;width:64px;height:64px;opacity:.9;color:var(--_pvb-editor-accent)}.status-bar{height:32px;background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 92%,black 8%);border-top:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent);display:flex;align-items:center;justify-content:space-between;padding:0 16px;font-size:12px;color:var(--_pvb-editor-text-soft);flex-shrink:0}.status-left,.status-center{display:flex;align-items:center;gap:8px}.validation-status{display:flex;align-items:center;gap:4px}.validation-status.error{color:var(--md-sys-color-error)}.validation-status.success{color:var(--md-sys-color-tertiary)}.validation-status mat-icon{font-size:16px;width:16px;height:16px}.debug-panel{position:absolute;top:0;right:0;bottom:0;width:400px;background:var(--_pvb-editor-surface);border-left:1px solid var(--_pvb-editor-border);box-shadow:-2px 0 8px #0000001a;z-index:var(--praxis-layer-authoring-toolbar, 340);display:flex;flex-direction:column}.debug-header{padding:8px 16px;border-bottom:1px solid var(--_pvb-editor-border);display:flex;align-items:center;justify-content:space-between;background:var(--_pvb-editor-surface-strong)}.debug-content{flex:1;overflow:auto;padding:16px;font-family:monospace;font-size:12px}@media(max-width:1180px){.builder-shell-header{flex-wrap:wrap;justify-content:flex-start;padding:10px 14px}.shell-nav{order:3;width:100%;justify-content:center}.shell-status{margin-left:auto}}@media(max-width:720px){.editor-content-grid,.editor-content-grid.list-closed{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(360px,1fr);overflow-y:auto}.rule-list-panel{max-height:min(360px,48vh);border-right:0;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent)}.rule-definition-panel{min-height:360px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "ngmodule", type: MatSidenavModule }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i10$1.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i7$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: RuleListComponent, selector: "praxis-rule-list", inputs: ["rules", "selectedRuleId", "nodeMap", "validationErrors"], outputs: ["ruleSelected", "ruleDeleted", "ruleDuplicated", "ruleAdded", "aiRequested"] }, { kind: "component", type: RuleDefinitionComponent, selector: "praxis-rule-definition", inputs: ["ruleNode", "fieldSchemas", "targetSchemas", "propertySchema"], outputs: ["ruleChanged"] }, { kind: "component", type: RuleCanvasComponent, selector: "praxis-rule-canvas", inputs: ["conditionOnly", "state", "fieldSchemas", "validationErrors"], outputs: ["nodeSelected", "nodeAdded", "nodeUpdated", "nodeRemoved"] }, { kind: "pipe", type: i12$1.JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13748
13777
  }
13749
13778
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: RuleEditorComponent, decorators: [{
13750
13779
  type: Component,
@@ -13972,7 +14001,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
13972
14001
  (change)="onFileSelected($event)"
13973
14002
  />
13974
14003
  </div>
13975
- `, styles: [".rule-editor-container{--_pvb-editor-accent: var(--md-sys-color-primary, var(--sicoob-primary-default));--_pvb-editor-accent-soft: color-mix(in srgb, var(--_pvb-editor-accent) 16%, transparent);--_pvb-editor-surface: var(--md-sys-color-surface, var(--sicoob-background-primary));--_pvb-editor-surface-low: var(--md-sys-color-surface-container-low, var(--sicoob-background-secondary));--_pvb-editor-surface-strong: var(--md-sys-color-surface-container, var(--sicoob-background-tertiary));--_pvb-editor-border: var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium));--_pvb-editor-text: var(--md-sys-color-on-surface, var(--sicoob-text-default));--_pvb-editor-text-soft: var(--md-sys-color-on-surface-variant, var(--sicoob-text-subtle));display:flex;flex-direction:column;height:100%;background:radial-gradient(circle at top center,color-mix(in srgb,var(--_pvb-editor-accent) 12%,transparent) 0%,transparent 32%),linear-gradient(180deg,color-mix(in srgb,var(--_pvb-editor-surface-low) 96%,black 4%),color-mix(in srgb,var(--_pvb-editor-surface) 98%,black 2%));overflow:hidden;position:relative;color:var(--_pvb-editor-text)}.rule-editor-container.embedded{height:100%}.condition-only-editor{display:flex;flex-direction:column;height:100%;min-height:360px;overflow:hidden}.condition-only-header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 16px;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 68%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 94%,black 6%)}.condition-only-header h3{margin:0;font-size:16px;font-weight:600}.condition-only-header p{margin:4px 0 0;font-size:12px;color:var(--_pvb-editor-text-soft)}.condition-only-canvas{flex:1;min-height:0}.builder-shell-header{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:54px;padding:0 18px;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 68%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 94%,black 6%);flex-shrink:0}.shell-brand{display:flex;align-items:center;gap:10px;min-width:0}.shell-menu{margin-right:2px}.brand-mark{width:32px;height:32px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--_pvb-editor-accent) 16%,transparent);border:1px solid color-mix(in srgb,var(--_pvb-editor-accent) 24%,transparent)}.brand-mark mat-icon{display:flex;align-items:center;justify-content:center;font-size:18px;width:18px;height:18px;color:var(--_pvb-editor-accent)}.brand-copy{display:flex;flex-direction:column;gap:2px;min-width:0}.brand-title{font-size:14px;font-weight:700}.brand-breadcrumb{font-size:12px;color:var(--_pvb-editor-text-soft)}.shell-nav{display:inline-flex;align-items:center;gap:10px;padding:4px;border-radius:14px;background:color-mix(in srgb,var(--_pvb-editor-surface-low) 94%,black 6%);border:1px solid color-mix(in srgb,var(--_pvb-editor-border) 56%,transparent)}.nav-pill{min-width:96px;height:34px;border:0;border-radius:10px;background:transparent;color:var(--_pvb-editor-text-soft);font:inherit;font-size:13px;cursor:default}.nav-pill.active{color:var(--_pvb-editor-text);background:color-mix(in srgb,var(--_pvb-editor-accent) 16%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--_pvb-editor-accent) 34%,transparent)}.shell-status{display:flex;align-items:center;gap:6px}.unsaved-indicator{display:inline-flex;align-items:center;gap:8px;font-size:13px;color:var(--_pvb-editor-text);margin-right:6px}.unsaved-dot{width:8px;height:8px;border-radius:999px;background:#f0b429;box-shadow:0 0 12px #f0b42973}.builder-shell-header button[mat-icon-button]{width:36px;height:36px;line-height:36px;padding:8px}.builder-shell-header button[mat-icon-button] mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.editor-content-grid{display:grid;grid-template-columns:360px 1fr;flex:1;overflow:hidden;min-height:0;transition:grid-template-columns .2s ease}.editor-content-grid.list-closed{grid-template-columns:0 1fr}.rule-list-panel{border-right:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-low) 94%,black 6%);display:flex;flex-direction:column;overflow:hidden}.rule-definition-panel{background:radial-gradient(circle at 50% 0%,color-mix(in srgb,var(--_pvb-editor-accent) 8%,transparent) 0%,transparent 26%),transparent;overflow:hidden;display:flex;flex-direction:column;position:relative;min-height:0;flex:1}.empty-state,.unsupported-node{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--_pvb-editor-text-soft);gap:16px;text-align:center;padding:32px}.empty-state mat-icon,.unsupported-node mat-icon{font-size:64px;width:64px;height:64px;opacity:.9;color:var(--_pvb-editor-accent)}.status-bar{height:32px;background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 92%,black 8%);border-top:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent);display:flex;align-items:center;justify-content:space-between;padding:0 16px;font-size:12px;color:var(--_pvb-editor-text-soft);flex-shrink:0}.status-left,.status-center{display:flex;align-items:center;gap:8px}.validation-status{display:flex;align-items:center;gap:4px}.validation-status.error{color:var(--md-sys-color-error)}.validation-status.success{color:var(--md-sys-color-tertiary)}.validation-status mat-icon{font-size:16px;width:16px;height:16px}.debug-panel{position:absolute;top:0;right:0;bottom:0;width:400px;background:var(--_pvb-editor-surface);border-left:1px solid var(--_pvb-editor-border);box-shadow:-2px 0 8px #0000001a;z-index:var(--praxis-layer-authoring-toolbar, 340);display:flex;flex-direction:column}.debug-header{padding:8px 16px;border-bottom:1px solid var(--_pvb-editor-border);display:flex;align-items:center;justify-content:space-between;background:var(--_pvb-editor-surface-strong)}.debug-content{flex:1;overflow:auto;padding:16px;font-family:monospace;font-size:12px}@media(max-width:1180px){.builder-shell-header{flex-wrap:wrap;justify-content:flex-start;padding:10px 14px}.shell-nav{order:3;width:100%;justify-content:center}.shell-status{margin-left:auto}}\n"] }]
14004
+ `, styles: [".rule-editor-container{--_pvb-editor-accent: var(--md-sys-color-primary, var(--sicoob-primary-default));--_pvb-editor-accent-soft: color-mix(in srgb, var(--_pvb-editor-accent) 16%, transparent);--_pvb-editor-surface: var(--md-sys-color-surface, var(--sicoob-background-primary));--_pvb-editor-surface-low: var(--md-sys-color-surface-container-low, var(--sicoob-background-secondary));--_pvb-editor-surface-strong: var(--md-sys-color-surface-container, var(--sicoob-background-tertiary));--_pvb-editor-border: var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium));--_pvb-editor-text: var(--md-sys-color-on-surface, var(--sicoob-text-default));--_pvb-editor-text-soft: var(--md-sys-color-on-surface-variant, var(--sicoob-text-subtle));display:flex;flex-direction:column;height:100%;background:radial-gradient(circle at top center,color-mix(in srgb,var(--_pvb-editor-accent) 12%,transparent) 0%,transparent 32%),linear-gradient(180deg,color-mix(in srgb,var(--_pvb-editor-surface-low) 96%,black 4%),color-mix(in srgb,var(--_pvb-editor-surface) 98%,black 2%));overflow:hidden;position:relative;color:var(--_pvb-editor-text)}.rule-editor-container.embedded{height:100%}.condition-only-editor{display:flex;flex-direction:column;height:100%;min-height:360px;overflow:hidden}.condition-only-header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 16px;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 68%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 94%,black 6%)}.condition-only-header h3{margin:0;font-size:16px;font-weight:600}.condition-only-header p{margin:4px 0 0;font-size:12px;color:var(--_pvb-editor-text-soft)}.condition-only-canvas{flex:1;min-height:0}.builder-shell-header{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:54px;padding:0 18px;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 68%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 94%,black 6%);flex-shrink:0}.shell-brand{display:flex;align-items:center;gap:10px;min-width:0}.shell-menu{margin-right:2px}.brand-mark{width:32px;height:32px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--_pvb-editor-accent) 16%,transparent);border:1px solid color-mix(in srgb,var(--_pvb-editor-accent) 24%,transparent)}.brand-mark mat-icon{display:flex;align-items:center;justify-content:center;font-size:18px;width:18px;height:18px;color:var(--_pvb-editor-accent)}.brand-copy{display:flex;flex-direction:column;gap:2px;min-width:0}.brand-title{font-size:14px;font-weight:700}.brand-breadcrumb{font-size:12px;color:var(--_pvb-editor-text-soft)}.shell-nav{display:inline-flex;align-items:center;gap:10px;padding:4px;border-radius:14px;background:color-mix(in srgb,var(--_pvb-editor-surface-low) 94%,black 6%);border:1px solid color-mix(in srgb,var(--_pvb-editor-border) 56%,transparent)}.nav-pill{min-width:96px;height:34px;border:0;border-radius:10px;background:transparent;color:var(--_pvb-editor-text-soft);font:inherit;font-size:13px;cursor:default}.nav-pill.active{color:var(--_pvb-editor-text);background:color-mix(in srgb,var(--_pvb-editor-accent) 16%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--_pvb-editor-accent) 34%,transparent)}.shell-status{display:flex;align-items:center;gap:6px}.unsaved-indicator{display:inline-flex;align-items:center;gap:8px;font-size:13px;color:var(--_pvb-editor-text);margin-right:6px}.unsaved-dot{width:8px;height:8px;border-radius:999px;background:#f0b429;box-shadow:0 0 12px #f0b42973}.builder-shell-header button[mat-icon-button]{width:36px;height:36px;line-height:36px;padding:8px}.builder-shell-header button[mat-icon-button] mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.editor-content-grid{display:grid;grid-template-columns:360px 1fr;flex:1;overflow:hidden;min-height:0;min-width:0;transition:grid-template-columns .2s ease}.editor-content-grid.list-closed{grid-template-columns:0 1fr}.rule-list-panel{border-right:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent);background:color-mix(in srgb,var(--_pvb-editor-surface-low) 94%,black 6%);display:flex;flex-direction:column;overflow:hidden;min-width:0}.rule-definition-panel{background:radial-gradient(circle at 50% 0%,color-mix(in srgb,var(--_pvb-editor-accent) 8%,transparent) 0%,transparent 26%),transparent;overflow:hidden;display:flex;flex-direction:column;position:relative;min-height:0;min-width:0;flex:1}.empty-state,.unsupported-node{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--_pvb-editor-text-soft);gap:16px;text-align:center;padding:32px}.empty-state mat-icon,.unsupported-node mat-icon{font-size:64px;width:64px;height:64px;opacity:.9;color:var(--_pvb-editor-accent)}.status-bar{height:32px;background:color-mix(in srgb,var(--_pvb-editor-surface-strong) 92%,black 8%);border-top:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent);display:flex;align-items:center;justify-content:space-between;padding:0 16px;font-size:12px;color:var(--_pvb-editor-text-soft);flex-shrink:0}.status-left,.status-center{display:flex;align-items:center;gap:8px}.validation-status{display:flex;align-items:center;gap:4px}.validation-status.error{color:var(--md-sys-color-error)}.validation-status.success{color:var(--md-sys-color-tertiary)}.validation-status mat-icon{font-size:16px;width:16px;height:16px}.debug-panel{position:absolute;top:0;right:0;bottom:0;width:400px;background:var(--_pvb-editor-surface);border-left:1px solid var(--_pvb-editor-border);box-shadow:-2px 0 8px #0000001a;z-index:var(--praxis-layer-authoring-toolbar, 340);display:flex;flex-direction:column}.debug-header{padding:8px 16px;border-bottom:1px solid var(--_pvb-editor-border);display:flex;align-items:center;justify-content:space-between;background:var(--_pvb-editor-surface-strong)}.debug-content{flex:1;overflow:auto;padding:16px;font-family:monospace;font-size:12px}@media(max-width:1180px){.builder-shell-header{flex-wrap:wrap;justify-content:flex-start;padding:10px 14px}.shell-nav{order:3;width:100%;justify-content:center}.shell-status{margin-left:auto}}@media(max-width:720px){.editor-content-grid,.editor-content-grid.list-closed{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(360px,1fr);overflow-y:auto}.rule-list-panel{max-height:min(360px,48vh);border-right:0;border-bottom:1px solid color-mix(in srgb,var(--_pvb-editor-border) 74%,transparent)}.rule-definition-panel{min-height:360px}}\n"] }]
13976
14005
  }], ctorParameters: () => [{ type: RuleBuilderService }, { type: FieldSchemaService }, { type: i3$1.AiResponseValidatorService }, { type: i4.MatSnackBar }, { type: i1.MatDialog }, { type: i0.ChangeDetectorRef }, { type: i1$2.PraxisI18nService, decorators: [{
13977
14006
  type: Optional
13978
14007
  }] }], propDecorators: { embedded: [{
@@ -14164,7 +14193,6 @@ const variableAddSchema = {
14164
14193
  name: { type: 'string' },
14165
14194
  scope: { type: 'string' },
14166
14195
  type: { enum: ['string', 'number', 'boolean', 'object', 'array'] },
14167
- valueType: { enum: ['literal', 'field', 'context', 'function'] },
14168
14196
  defaultValue: {},
14169
14197
  description: { type: 'string' },
14170
14198
  },
@@ -14221,7 +14249,7 @@ const PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST = {
14221
14249
  editableTargets: [
14222
14250
  { kind: 'node', resolver: 'rule-node-by-id', description: 'Visual rule graph node keyed by stable RuleNode.id.' },
14223
14251
  { kind: 'edge', resolver: 'rule-node-edge-by-source-target', description: 'Parent-child or semantic graph edge between existing rule nodes.' },
14224
- { kind: 'variable', resolver: 'context-variable-by-name-scope', description: 'Context variable available to rule conditions and contextual nodes.' },
14252
+ { kind: 'variable', resolver: 'context-variable-by-name-scope', description: 'Context variable governed by ContextManagementService for contextual/template flows; visual field-condition references are not authorable until a canonical JSON Logic shape exists.' },
14225
14253
  { kind: 'condition', resolver: 'json-logic-condition-by-node', description: 'JSON Logic condition attached to a node or represented by condition nodes.' },
14226
14254
  { kind: 'effect', resolver: 'property-effect-by-node', description: 'Targeted property effect persisted as propertyRule/FormLayoutRule semantics.' },
14227
14255
  { kind: 'dslDocument', resolver: 'rule-builder-json-logic-document', description: 'Serialized JSON Logic/form-config document produced from the visual model.' },
@@ -14350,7 +14378,7 @@ const PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST = {
14350
14378
  identityKeys: ['scope', 'name'],
14351
14379
  inputSchema: variableAddSchema,
14352
14380
  failureModes: ['duplicate-variable', 'scope-not-found', 'variable-type-invalid', 'context-token-conflict'],
14353
- description: 'Adds a governed context variable that can be referenced by contextual and field condition nodes.',
14381
+ description: 'Adds a governed context variable to ContextManagementService for contextual/template flows. Field-condition references stay unsupported until a canonical JSON Logic shape exists.',
14354
14382
  } }],
14355
14383
  validators: ['variable-id-unique', 'variable-scope-exists', 'context-variable-reference-valid', 'dsl-round-trip-stable'],
14356
14384
  affectedPaths: ['RuleBuilderConfig.contextVariables', 'ContextManagementService'],
@@ -14372,7 +14400,7 @@ const PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST = {
14372
14400
  identityKeys: ['nodeId'],
14373
14401
  inputSchema: conditionSetSchema,
14374
14402
  failureModes: ['node-not-found', 'json-logic-invalid', 'unsupported-operator', 'visual-parse-failed', 'dsl-round-trip-failed'],
14375
- description: 'Sets a canonical JSON Logic condition and proves it can parse back into the visual graph.',
14403
+ description: 'Sets a canonical JSON Logic condition within the runtime-supported visual subset and proves it can parse back into the visual graph.',
14376
14404
  } }],
14377
14405
  validators: ['json-logic-valid', 'condition-operators-supported', 'condition-fields-known', 'dsl-round-trip-stable'],
14378
14406
  affectedPaths: ['RuleBuilderState.nodes[].config.condition', 'RuleBuilderState.currentJSON'],
@@ -14439,10 +14467,10 @@ const PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST = {
14439
14467
  { validatorId: 'destructive-removal-confirmed', level: 'error', code: 'VISUAL_BUILDER_DESTRUCTIVE_REMOVAL_CONFIRMED', description: 'Destructive node or edge removal requires explicit confirmation.' },
14440
14468
  { validatorId: 'variable-id-unique', level: 'error', code: 'VISUAL_BUILDER_VARIABLE_ID_UNIQUE', description: 'Context variable name and scope must be unique.' },
14441
14469
  { validatorId: 'variable-scope-exists', level: 'error', code: 'VISUAL_BUILDER_VARIABLE_SCOPE_EXISTS', description: 'Context variable scope must exist in ContextManagementService before variables are added.' },
14442
- { validatorId: 'context-variable-reference-valid', level: 'error', code: 'VISUAL_BUILDER_CONTEXT_VARIABLE_VALID', description: 'Context variable references must resolve to declared variables.' },
14470
+ { validatorId: 'context-variable-reference-valid', level: 'error', code: 'VISUAL_BUILDER_CONTEXT_VARIABLE_VALID', description: 'Contextual/template variable references must resolve to declared variables.' },
14443
14471
  { validatorId: 'json-logic-valid', level: 'error', code: 'VISUAL_BUILDER_JSON_LOGIC_VALID', description: 'Conditions must be valid JSON Logic objects, not JavaScript or legacy textual DSL.' },
14444
14472
  { validatorId: 'condition-operators-supported', level: 'error', code: 'VISUAL_BUILDER_CONDITION_OPERATORS_SUPPORTED', description: 'Condition operators must be supported by visual parsing and export.' },
14445
- { validatorId: 'condition-fields-known', level: 'error', code: 'VISUAL_BUILDER_CONDITION_FIELDS_KNOWN', description: 'Condition field references must resolve to configured field schemas or context variables.' },
14473
+ { validatorId: 'condition-fields-known', level: 'error', code: 'VISUAL_BUILDER_CONDITION_FIELDS_KNOWN', description: 'Condition field references must resolve to configured field schemas; field-to-field comparisons use JSON Logic var operands.' },
14446
14474
  { validatorId: 'effect-targets-exist', level: 'error', code: 'VISUAL_BUILDER_EFFECT_TARGETS_EXIST', description: 'Effect targets must exist in configured target schemas.' },
14447
14475
  { validatorId: 'effect-properties-governed', level: 'error', code: 'VISUAL_BUILDER_EFFECT_PROPERTIES_GOVERNED', description: 'Effect properties must be allowed for the target type.' },
14448
14476
  { validatorId: 'effect-values-valid', level: 'error', code: 'VISUAL_BUILDER_EFFECT_VALUES_VALID', description: 'Effect property values must satisfy target property schema types.' },
@@ -14451,11 +14479,11 @@ const PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST = {
14451
14479
  ],
14452
14480
  roundTripRequirements: [
14453
14481
  'RuleBuilderState is the visual source of truth; JSON export must import back without semantic drift.',
14454
- 'RuleNode.id and context variable scope/name are canonical identities; array indexes are not canonical identities.',
14482
+ 'RuleNode.id and context variable scope/name are canonical identities for their own surfaces; array indexes are not canonical identities.',
14455
14483
  'Edges must reference existing nodes and must not create cycles in hierarchical rule graphs.',
14456
14484
  'Conditions are canonical JSON Logic objects. JavaScript expressions and legacy textual DSL must not be introduced as persisted authoring payloads.',
14457
14485
  'Effects must be constrained by target property schemas and RULE_PROPERTY_SCHEMA so exported FormLayoutRule payloads stay deterministic.',
14458
- 'Component-specific configuration belongs to child component manifests; visual-builder owns graph, JSON Logic, variables and property-effect orchestration.',
14486
+ 'Component-specific configuration belongs to child component manifests; visual-builder owns graph, supported JSON Logic, context-variable registry and property-effect orchestration.',
14459
14487
  ],
14460
14488
  examples: [
14461
14489
  { id: 'add-field-condition', request: 'Add a condition that age is greater than 18.', operationId: 'node.add', params: { nodeId: 'age-gt-18', nodeType: 'fieldCondition', label: 'Age over 18', config: { type: 'fieldCondition', fieldName: 'age', operator: 'gt', value: 18 } }, isPositive: true },
@@ -14463,7 +14491,7 @@ const PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST = {
14463
14491
  { id: 'configure-node', request: 'Rename the eligibility rule and mark it expanded.', operationId: 'node.configure', params: { nodeId: 'eligibility', label: 'Eligibility rule', expanded: true }, isPositive: true },
14464
14492
  { id: 'connect-edge', request: 'Make the age condition a child of the AND group.', operationId: 'edge.connect', params: { sourceNodeId: 'eligibility-and', targetNodeId: 'age-gt-18', edgeKind: 'child' }, isPositive: true },
14465
14493
  { id: 'remove-edge', request: 'Disconnect the age condition from the AND group.', operationId: 'edge.remove', params: { sourceNodeId: 'eligibility-and', targetNodeId: 'age-gt-18', edgeKind: 'child' }, isPositive: true },
14466
- { id: 'add-variable', request: 'Add a global variable for current tenant.', operationId: 'variable.add', params: { name: 'tenantId', scope: 'global', type: 'string', valueType: 'context', description: 'Current tenant id' }, isPositive: true },
14494
+ { id: 'add-variable', request: 'Add a global variable for current tenant.', operationId: 'variable.add', params: { name: 'tenantId', scope: 'global', type: 'string', description: 'Current tenant id' }, isPositive: true },
14467
14495
  { id: 'set-condition', request: 'Set this condition to require country equal Brazil.', operationId: 'condition.set', params: { nodeId: 'country-br', condition: { '===': [{ var: 'country' }, 'BR'] }, source: 'jsonLogic' }, isPositive: true },
14468
14496
  { id: 'set-effect', request: 'Make the salary field readonly when the condition is true.', operationId: 'effect.set', params: { nodeId: 'salary-readonly', targetType: 'field', targets: ['salary'], properties: { readonly: true } }, isPositive: true },
14469
14497
  { id: 'validate-round-trip', request: 'Validate that this graph exports and imports without drift.', operationId: 'dsl.roundTrip.validate', params: { format: 'json', requireStableIds: true, compareMode: 'semantic' }, isPositive: true },