@kaufmann-lab/ui 0.1.0 → 0.1.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaufmann-lab/ui",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Shared Angular component library for the Kaufmann frontends",
5
5
  "license": "MIT",
6
6
  "author": "Kaufmann Lab",
@@ -31,8 +31,15 @@
31
31
  */
32
32
  --kf-color-tertiary-deep: #003252;
33
33
 
34
- --kf-color-secondary: #e6750c;
35
- --kf-color-secondary-hover: #c4650a;
34
+ /*
35
+ * Oscurecido desde el naranja de marca original (#e6750c) — con texto
36
+ * blanco (kf-button variant="secondary") el tono original daba 3.04:1,
37
+ * por debajo del mínimo WCAG AA de 4.5:1 para texto normal. Este valor
38
+ * da 4.56:1; `-hover` sube a 5.42:1. `-strong` (pensado para texto sobre
39
+ * fondo claro, no fondo de botón) no se tocó: ya cumplía de sobra.
40
+ */
41
+ --kf-color-secondary: #b85d09;
42
+ --kf-color-secondary-hover: #a55408;
36
43
  --kf-color-secondary-soft: #fff0e3;
37
44
  --kf-color-secondary-strong: #954e08;
38
45
 
@@ -45,10 +52,16 @@
45
52
  --kf-color-warning-soft: #fff8db;
46
53
  --kf-color-warning-strong: #8a6a00;
47
54
 
48
- --kf-color-error: #eb5757;
55
+ /*
56
+ * Oscurecido desde el rojo original (#eb5757) — con texto blanco
57
+ * (kf-button variant="danger") el tono original daba 3.48:1, por debajo
58
+ * del mínimo WCAG AA de 4.5:1. Este valor da 5.15:1; `-hover` sube a
59
+ * 6.09:1. `-strong` no se tocó: ya cumplía de sobra (7.02:1).
60
+ */
61
+ --kf-color-error: #bc4545;
49
62
  /* Usado también como estado hover/active del botón `danger` — mismo rojo
50
63
  que "error", ver Button.ts (el PDF define un único rojo semántico). */
51
- --kf-color-error-hover: #d64545;
64
+ --kf-color-error-hover: #a93e3e;
52
65
  --kf-color-error-soft: #fdecec;
53
66
  --kf-color-error-strong: #a42d2d;
54
67
 
@@ -19,7 +19,10 @@
19
19
  --kf-color-primary-active: #000000;
20
20
  --kf-color-primary-soft: #f1f4f9;
21
21
 
22
- --kf-color-secondary: #c47f00;
23
- --kf-color-secondary-hover: #a66900;
22
+ /* Oscurecido desde #c47f00 (3.29:1 con texto blanco) para cumplir WCAG AA
23
+ (4.5:1) en kf-button variant="secondary". Mismo criterio que divemotor,
24
+ ver base.css. */
25
+ --kf-color-secondary: #9c6500;
26
+ --kf-color-secondary-hover: #8d5900;
24
27
  --kf-color-secondary-soft: #fdf3e0;
25
28
  }
@@ -19,7 +19,9 @@
19
19
  --kf-color-primary-active: #004f9e;
20
20
  --kf-color-primary-soft: #e8f2ff;
21
21
 
22
- --kf-color-secondary: #e6750c;
23
- --kf-color-secondary-hover: #c4650a;
22
+ /* Ver el comentario del mismo cambio en base.css: oscurecido para cumplir
23
+ WCAG AA (4.5:1) con texto blanco en kf-button variant="secondary". */
24
+ --kf-color-secondary: #b85d09;
25
+ --kf-color-secondary-hover: #a55408;
24
26
  --kf-color-secondary-soft: #fff0e3;
25
27
  }
@@ -323,15 +323,22 @@ declare class Carousel implements AfterContentInit {
323
323
  * forms) queda en su valor por defecto — igual que `disabled` combina el
324
324
  * input signal con `setDisabledState` en el resto de la librería.
325
325
  *
326
+ * `invalid` pinta el recuadro en rojo y setea `aria-invalid` en el `<input>`
327
+ * nativo — mismo mecanismo que `Input.invalid`, para el caso típico de un
328
+ * checkbox obligatorio (ej. "Acepto términos y condiciones") sin marcar.
329
+ *
326
330
  * <kf-checkbox label="Aceptar términos" [(checked)]="accepted" />
327
331
  * <kf-checkbox label="Seleccionar todo" [indeterminate]="isPartial()" />
328
332
  * <kf-checkbox label="Notificaciones" formControlName="notifications" />
333
+ * <kf-checkbox label="Acepto los términos y condiciones" [invalid]="submitted() && !accepted()" />
329
334
  */
330
335
  declare class Checkbox implements ControlValueAccessor {
331
336
  readonly label: _angular_core.InputSignal<string | undefined>;
332
337
  readonly checked: _angular_core.InputSignalWithTransform<boolean, unknown>;
333
338
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
334
339
  readonly indeterminate: _angular_core.InputSignalWithTransform<boolean, unknown>;
340
+ /** Recuadro en rojo + aria-invalid — ej. checkbox obligatorio sin marcar. */
341
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
335
342
  readonly checkedChange: _angular_core.OutputEmitterRef<boolean>;
336
343
  private readonly inputRef;
337
344
  /** Callbacks registrados por Forms; no-op hasta que registerOnChange/Touched las reemplacen. */
@@ -345,7 +352,7 @@ declare class Checkbox implements ControlValueAccessor {
345
352
  registerOnTouched(fn: () => void): void;
346
353
  setDisabledState?(isDisabled: boolean): void;
347
354
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Checkbox, never>;
348
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<Checkbox, "kf-checkbox", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "required": false; "isSignal": true; }; }, { "checkedChange": "checkedChange"; }, never, never, true, never>;
355
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Checkbox, "kf-checkbox", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; }, { "checkedChange": "checkedChange"; }, never, never, true, never>;
349
356
  }
350
357
 
351
358
  /**
@@ -666,13 +673,21 @@ declare class Field {
666
673
  * No reemplaza al `<label>` nativo — lo envuelve, para no perder la
667
674
  * asociación de accesibilidad `for`/`id` con el control real.
668
675
  *
676
+ * `required` agrega un asterisco visual en el tono de error, separado del
677
+ * texto por un espacio y marcado `aria-hidden` — el estado obligatorio real
678
+ * para lectores de pantalla lo comunica el propio control (`aria-required`
679
+ * / `required` en el `<input>`/`<select>` asociado), no este label.
680
+ *
669
681
  * <kf-field-label [for]="inputId">Patente o VIN</kf-field-label>
682
+ * <kf-field-label [for]="inputId" required>Correo electrónico</kf-field-label>
670
683
  */
671
684
  declare class FieldLabel {
672
685
  /** `id` del control asociado — se refleja como `for` en el `<label>` interno. */
673
686
  readonly for: _angular_core.InputSignal<string | undefined>;
687
+ /** Muestra un asterisco visual indicando que el campo es obligatorio. */
688
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
674
689
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FieldLabel, never>;
675
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FieldLabel, "kf-field-label", never, { "for": { "alias": "for"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
690
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FieldLabel, "kf-field-label", never, { "for": { "alias": "for"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
676
691
  }
677
692
 
678
693
  /** Forma normalizada interna de cada opción, ya resuelta a value/label. */
@@ -754,24 +769,38 @@ declare class FolderTabs {
754
769
  * <kf-input label="Placa" icon="car" placeholder="ABC-123" hint="Formato: 3 letras + 3 números" />
755
770
  * <input kf-input formControlName="email" type="email" />
756
771
  *
757
- * Nota sobre "icon": todavía no existe un componente Icon / sprite SVG en esta
758
- * librería. El prop se acepta igual para no romper el contrato de la spec,
759
- * pero por ahora solo reserva el espacio visual (placeholder vacío) — no
760
- * renderiza ningún glyph real.
772
+ * `invalid` + `errorMessage` cubren el estado de error: con `invalid` el
773
+ * borde pasa a rojo (`--kf-color-error`) y se setea `aria-invalid="true"` en
774
+ * el `<input>` nativo; `errorMessage` reemplaza el `hint` neutro por un
775
+ * mensaje en rojo con `role="alert"`, para que un lector de pantalla lo
776
+ * anuncie apenas aparece (a diferencia de `hint`, que es solo informativo y
777
+ * nunca interrumpe). Si se pasan ambos, `errorMessage` tiene prioridad
778
+ * visual sobre `hint` — no tiene sentido mostrar los dos a la vez.
779
+ *
780
+ * <kf-input label="Correo" formControlName="email"
781
+ * [invalid]="email.invalid && email.touched"
782
+ * [errorMessage]="email.touched && email.hasError('required') ? 'Ingresa tu correo.' : undefined" />
761
783
  */
762
784
  declare class Input implements ControlValueAccessor, AfterViewInit {
763
785
  private static nextId;
764
786
  private readonly nativeInput;
765
787
  readonly label: _angular_core.InputSignal<string | undefined>;
766
- /** Nombre de ícono líder. Ver nota de clase: sin componente Icon todavía. */
767
- readonly icon: _angular_core.InputSignal<string | undefined>;
788
+ /** Marca el label con un asterisco visual — no aplica `required` al `<input>` nativo por sí solo. */
789
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
790
+ /** Ícono líder, renderizado vía `kf-icon`. */
791
+ readonly icon: _angular_core.InputSignal<IconName | undefined>;
768
792
  readonly suffix: _angular_core.InputSignal<string | undefined>;
769
793
  readonly hint: _angular_core.InputSignal<string | undefined>;
794
+ /** Borde y aria-invalid en rojo. Ver `errorMessage` para el mensaje asociado. */
795
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
796
+ /** Mensaje de error con `role="alert"` — reemplaza a `hint` mientras esté presente. */
797
+ readonly errorMessage: _angular_core.InputSignal<string | undefined>;
770
798
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
771
799
  readonly type: _angular_core.InputSignal<string>;
772
800
  readonly placeholder: _angular_core.InputSignal<string>;
773
801
  protected readonly inputId: string;
774
802
  protected readonly hintId: string;
803
+ protected readonly errorId: string;
775
804
  protected readonly value: _angular_core.WritableSignal<string>;
776
805
  protected readonly focused: _angular_core.WritableSignal<boolean>;
777
806
  /** Deshabilitado por Reactive Forms (formControl.disable()). */
@@ -788,7 +817,7 @@ declare class Input implements ControlValueAccessor, AfterViewInit {
788
817
  protected onInput(rawValue: string): void;
789
818
  protected onBlur(): void;
790
819
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Input, never>;
791
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<Input, "kf-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "suffix": { "alias": "suffix"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
820
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Input, "kf-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "suffix": { "alias": "suffix"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
792
821
  }
793
822
 
794
823
  /**