@praxisui/dynamic-fields 3.0.0-beta.2 → 3.0.0-beta.3

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.
@@ -869,6 +869,11 @@ class SimpleBaseInputComponent {
869
869
  const componentState = this.componentState();
870
870
  const ngControl = this.getNgControl();
871
871
  const parentInvalid = !!ngControl?.invalid;
872
+ const parentTouched = !!ngControl?.touched;
873
+ const parentDirty = !!ngControl?.dirty;
874
+ const controlState = this.control();
875
+ const controlTouched = !!controlState.touched;
876
+ const controlDirty = !!controlState.dirty;
872
877
  const errors = ngControl?.errors ?? this.control().errors;
873
878
  const meta = this.metadata();
874
879
  const trig = meta?.validators?.validationTrigger;
@@ -883,13 +888,19 @@ class SimpleBaseInputComponent {
883
888
  case 'immediate':
884
889
  return true;
885
890
  case 'blur':
886
- return componentState.touched;
891
+ return componentState.touched || parentTouched || controlTouched;
887
892
  case 'submit':
888
893
  // Praxis onSubmit marca todos como touched; usamos esse sinal
889
- return componentState.touched;
894
+ return componentState.touched || parentTouched || controlTouched;
890
895
  case 'change':
891
896
  default:
892
- return (componentState.dirty || componentState.touched) && this.errorDisplayReady();
897
+ return (componentState.dirty
898
+ || componentState.touched
899
+ || parentDirty
900
+ || parentTouched
901
+ || controlDirty
902
+ || controlTouched)
903
+ && this.errorDisplayReady();
893
904
  }
894
905
  }, ...(ngDevMode ? [{ debugName: "hasValidationError" }] : []));
895
906
  /** CSS classes básicas do componente */
@@ -1492,10 +1503,12 @@ class SimpleBaseInputComponent {
1492
1503
  // =============================================================================
1493
1504
  setupFormControlIntegration() {
1494
1505
  const control = this.control();
1506
+ this.syncComponentStateFromControl(control);
1495
1507
  control.valueChanges
1496
1508
  .pipe(takeUntilDestroyed(this.destroyRef))
1497
1509
  .subscribe((value) => {
1498
1510
  this.fieldState.update((state) => ({ ...state, value }));
1511
+ this.syncComponentStateFromControl(control);
1499
1512
  });
1500
1513
  control.statusChanges
1501
1514
  .pipe(takeUntilDestroyed(this.destroyRef))
@@ -1505,6 +1518,7 @@ class SimpleBaseInputComponent {
1505
1518
  valid: status === 'VALID',
1506
1519
  errors: control.errors,
1507
1520
  }));
1521
+ this.syncComponentStateFromControl(control);
1508
1522
  this.refreshErrorTooltip();
1509
1523
  });
1510
1524
  // Sincronizar erros/estado do controle pai apenas quando usando controle interno
@@ -1520,35 +1534,51 @@ class SimpleBaseInputComponent {
1520
1534
  errors: errs,
1521
1535
  valid: !errs,
1522
1536
  }));
1537
+ this.syncComponentStateFromControl(control);
1523
1538
  this.refreshErrorTooltip();
1524
1539
  this.cdr.markForCheck();
1525
1540
  });
1526
1541
  }
1527
1542
  }
1543
+ syncComponentStateFromControl(control) {
1544
+ this.componentState.update((state) => ({
1545
+ ...state,
1546
+ touched: !!control.touched,
1547
+ dirty: !!control.dirty,
1548
+ disabled: !!control.disabled,
1549
+ }));
1550
+ }
1528
1551
  // Atualiza tooltip/atributos de erro quando erros mudam e quando inline errors estiverem desabilitados
1529
1552
  refreshErrorTooltip() {
1530
1553
  if (!this.nativeElement)
1531
1554
  return;
1532
- // Só aplica tooltip nativo quando errorPosition === 'tooltip' e não houver MatTooltip no template
1533
- // Força avaliação de tooltipPosition para evitar aviso de membro não utilizado
1534
- void this.tooltipPosition();
1535
- if (!this.tooltipEnabled()) {
1536
- this.nativeElement.removeAttribute('title');
1537
- this.nativeElement.removeAttribute('aria-invalid');
1538
- return;
1539
- }
1540
1555
  const hasErrors = !!(this.getNgControl()?.errors ?? this.control().errors);
1541
1556
  if (hasErrors) {
1542
- const msg = this.errorMessage();
1543
- if (msg)
1544
- this.nativeElement.setAttribute('title', msg);
1545
1557
  this.nativeElement.setAttribute('aria-invalid', 'true');
1558
+ if (this.tooltipEnabled()) {
1559
+ // Força avaliação de tooltipPosition para evitar aviso de membro não utilizado
1560
+ void this.tooltipPosition();
1561
+ const msg = this.errorMessage();
1562
+ if (msg) {
1563
+ this.nativeElement.setAttribute('title', msg);
1564
+ }
1565
+ else {
1566
+ this.nativeElement.removeAttribute('title');
1567
+ }
1568
+ }
1569
+ else {
1570
+ this.nativeElement.removeAttribute('title');
1571
+ }
1546
1572
  }
1547
1573
  else {
1548
1574
  this.nativeElement.removeAttribute('title');
1549
1575
  this.nativeElement.removeAttribute('aria-invalid');
1550
1576
  }
1551
1577
  }
1578
+ ariaInvalidAttribute() {
1579
+ const hasErrors = !!(this.getNgControl()?.errors ?? this.control().errors);
1580
+ return hasErrors ? 'true' : null;
1581
+ }
1552
1582
  tDynamicFields(keySuffix, fallback, params) {
1553
1583
  return this.i18n.t(`praxis.dynamicFields.${keySuffix}`, params, fallback, 'dynamicFields');
1554
1584
  }
@@ -7725,6 +7755,7 @@ class TextInputComponent extends SimpleBaseInputComponent {
7725
7755
  [minlength]="metadata()?.minLength || null"
7726
7756
  [attr.aria-label]="!label && placeholder ? placeholder : null"
7727
7757
  [attr.aria-required]="metadata()?.required ? 'true' : 'false'"
7758
+ [attr.aria-invalid]="ariaInvalidAttribute()"
7728
7759
  [matTooltip]="tooltipEnabled() ? errorMessage() : null"
7729
7760
  [matTooltipDisabled]="!(tooltipEnabled() && !!errorMessage())"
7730
7761
  [matTooltipPosition]="tooltipPosition()"
@@ -7816,6 +7847,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
7816
7847
  [minlength]="metadata()?.minLength || null"
7817
7848
  [attr.aria-label]="!label && placeholder ? placeholder : null"
7818
7849
  [attr.aria-required]="metadata()?.required ? 'true' : 'false'"
7850
+ [attr.aria-invalid]="ariaInvalidAttribute()"
7819
7851
  [matTooltip]="tooltipEnabled() ? errorMessage() : null"
7820
7852
  [matTooltipDisabled]="!(tooltipEnabled() && !!errorMessage())"
7821
7853
  [matTooltipPosition]="tooltipPosition()"
@@ -47981,7 +48013,13 @@ const DYNAMIC_FIELD_ERROR_STATE_RECIPE = {
47981
48013
  state: 'error',
47982
48014
  label: 'Error',
47983
48015
  supported: true,
47984
- metadataPatch: { required: true },
48016
+ metadataPatch: {
48017
+ required: true,
48018
+ validators: {
48019
+ requiredMessage: 'Governed sample error state for playground preview.',
48020
+ validationTrigger: 'immediate',
48021
+ },
48022
+ },
47985
48023
  errorMessage: 'Governed sample error state for playground preview.',
47986
48024
  };
47987
48025
  const DYNAMIC_FIELD_BASE_STATE_RECIPES = [