@kaufmann-lab/ui 0.1.0 → 0.1.2
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/README.md +37 -26
- package/fesm2022/kaufmann-lab-ui.mjs +152 -42
- package/fesm2022/kaufmann-lab-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/src/tokens/base.css +17 -4
- package/src/tokens/themes/andes-maq.css +5 -2
- package/src/tokens/themes/divemotor.css +4 -2
- package/types/kaufmann-lab-ui.d.ts +75 -11
package/package.json
CHANGED
package/src/tokens/base.css
CHANGED
|
@@ -31,8 +31,15 @@
|
|
|
31
31
|
*/
|
|
32
32
|
--kf-color-tertiary-deep: #003252;
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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: #
|
|
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
|
-
|
|
23
|
-
|
|
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
|
-
|
|
23
|
-
|
|
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
|
}
|
|
@@ -2,8 +2,14 @@ import * as _angular_core from '@angular/core';
|
|
|
2
2
|
import { AfterContentInit, TemplateRef, AfterViewInit } from '@angular/core';
|
|
3
3
|
import { ControlValueAccessor } from '@angular/forms';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Nombre de cada ícono del design system. Página 5 del PDF fija un set de
|
|
7
|
+
* 59; `eye-off` es una extensión propia por fuera de ese set, agregada para
|
|
8
|
+
* el toggle de mostrar/ocultar contraseña de `Input` — no hay un ícono de
|
|
9
|
+
* "ojo tachado" en la spec original porque esa interacción no estaba
|
|
10
|
+
* contemplada ahí.
|
|
11
|
+
*/
|
|
12
|
+
type IconName = 'activity' | 'alert-circle' | 'alert-octagon' | 'alert-triangle' | 'award' | 'bar-chart' | 'bell' | 'bus' | 'calculator' | 'calendar' | 'car' | 'cart' | 'check' | 'check-circle' | 'check-square' | 'chevron-down' | 'chevron-left' | 'chevron-left-bar' | 'chevron-right' | 'clipboard' | 'clock' | 'credit-card' | 'download' | 'edit' | 'external-link' | 'eye' | 'eye-off' | 'file' | 'filter' | 'gauge' | 'gift' | 'grid' | 'history' | 'inbox' | 'layers' | 'list' | 'map' | 'map-pin' | 'menu' | 'mic' | 'mic-off' | 'more-vertical' | 'pause' | 'phone' | 'play' | 'plus' | 'search' | 'settings' | 'shield-check' | 'sort' | 'star' | 'ticket' | 'tool' | 'trash' | 'truck' | 'upload-cloud' | 'user' | 'user-search' | 'video' | 'x';
|
|
7
13
|
type IconSize = 'sm' | 'md' | 'lg';
|
|
8
14
|
/**
|
|
9
15
|
* Ícono de trazo del design system — 59 glyphs (página 5), grilla 24×24,
|
|
@@ -323,15 +329,22 @@ declare class Carousel implements AfterContentInit {
|
|
|
323
329
|
* forms) queda en su valor por defecto — igual que `disabled` combina el
|
|
324
330
|
* input signal con `setDisabledState` en el resto de la librería.
|
|
325
331
|
*
|
|
332
|
+
* `invalid` pinta el recuadro en rojo y setea `aria-invalid` en el `<input>`
|
|
333
|
+
* nativo — mismo mecanismo que `Input.invalid`, para el caso típico de un
|
|
334
|
+
* checkbox obligatorio (ej. "Acepto términos y condiciones") sin marcar.
|
|
335
|
+
*
|
|
326
336
|
* <kf-checkbox label="Aceptar términos" [(checked)]="accepted" />
|
|
327
337
|
* <kf-checkbox label="Seleccionar todo" [indeterminate]="isPartial()" />
|
|
328
338
|
* <kf-checkbox label="Notificaciones" formControlName="notifications" />
|
|
339
|
+
* <kf-checkbox label="Acepto los términos y condiciones" [invalid]="submitted() && !accepted()" />
|
|
329
340
|
*/
|
|
330
341
|
declare class Checkbox implements ControlValueAccessor {
|
|
331
342
|
readonly label: _angular_core.InputSignal<string | undefined>;
|
|
332
343
|
readonly checked: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
333
344
|
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
334
345
|
readonly indeterminate: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
346
|
+
/** Recuadro en rojo + aria-invalid — ej. checkbox obligatorio sin marcar. */
|
|
347
|
+
readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
335
348
|
readonly checkedChange: _angular_core.OutputEmitterRef<boolean>;
|
|
336
349
|
private readonly inputRef;
|
|
337
350
|
/** Callbacks registrados por Forms; no-op hasta que registerOnChange/Touched las reemplacen. */
|
|
@@ -345,7 +358,7 @@ declare class Checkbox implements ControlValueAccessor {
|
|
|
345
358
|
registerOnTouched(fn: () => void): void;
|
|
346
359
|
setDisabledState?(isDisabled: boolean): void;
|
|
347
360
|
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>;
|
|
361
|
+
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
362
|
}
|
|
350
363
|
|
|
351
364
|
/**
|
|
@@ -666,13 +679,21 @@ declare class Field {
|
|
|
666
679
|
* No reemplaza al `<label>` nativo — lo envuelve, para no perder la
|
|
667
680
|
* asociación de accesibilidad `for`/`id` con el control real.
|
|
668
681
|
*
|
|
682
|
+
* `required` agrega un asterisco visual en el tono de error, separado del
|
|
683
|
+
* texto por un espacio y marcado `aria-hidden` — el estado obligatorio real
|
|
684
|
+
* para lectores de pantalla lo comunica el propio control (`aria-required`
|
|
685
|
+
* / `required` en el `<input>`/`<select>` asociado), no este label.
|
|
686
|
+
*
|
|
669
687
|
* <kf-field-label [for]="inputId">Patente o VIN</kf-field-label>
|
|
688
|
+
* <kf-field-label [for]="inputId" required>Correo electrónico</kf-field-label>
|
|
670
689
|
*/
|
|
671
690
|
declare class FieldLabel {
|
|
672
691
|
/** `id` del control asociado — se refleja como `for` en el `<label>` interno. */
|
|
673
692
|
readonly for: _angular_core.InputSignal<string | undefined>;
|
|
693
|
+
/** Muestra un asterisco visual indicando que el campo es obligatorio. */
|
|
694
|
+
readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
674
695
|
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>;
|
|
696
|
+
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
697
|
}
|
|
677
698
|
|
|
678
699
|
/** Forma normalizada interna de cada opción, ya resuelta a value/label. */
|
|
@@ -754,30 +775,67 @@ declare class FolderTabs {
|
|
|
754
775
|
* <kf-input label="Placa" icon="car" placeholder="ABC-123" hint="Formato: 3 letras + 3 números" />
|
|
755
776
|
* <input kf-input formControlName="email" type="email" />
|
|
756
777
|
*
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
*
|
|
760
|
-
*
|
|
778
|
+
* `invalid` + `errorMessage` cubren el estado de error: con `invalid` el
|
|
779
|
+
* borde pasa a rojo (`--kf-color-error`) y se setea `aria-invalid="true"` en
|
|
780
|
+
* el `<input>` nativo; `errorMessage` reemplaza el `hint` neutro por un
|
|
781
|
+
* mensaje en rojo con `role="alert"`, para que un lector de pantalla lo
|
|
782
|
+
* anuncie apenas aparece (a diferencia de `hint`, que es solo informativo y
|
|
783
|
+
* nunca interrumpe). Si se pasan ambos, `errorMessage` tiene prioridad
|
|
784
|
+
* visual sobre `hint` — no tiene sentido mostrar los dos a la vez.
|
|
785
|
+
*
|
|
786
|
+
* <kf-input label="Correo" formControlName="email"
|
|
787
|
+
* [invalid]="email.invalid && email.touched"
|
|
788
|
+
* [errorMessage]="email.touched && email.hasError('required') ? 'Ingresa tu correo.' : undefined" />
|
|
789
|
+
*
|
|
790
|
+
* `toggleable` solo tiene efecto cuando `type="password"`: agrega un botón
|
|
791
|
+
* de ojo al final del campo que alterna la visibilidad del valor tipeado
|
|
792
|
+
* (cambia el `type` real del `<input>` nativo entre `password` y `text`,
|
|
793
|
+
* nunca expone el valor en el DOM de otra forma). El botón es `type="button"`
|
|
794
|
+
* — nunca dispara submit del form contenedor — y anuncia su acción con
|
|
795
|
+
* `aria-label` dinámico y `aria-pressed`, ya que es un toggle, no un botón
|
|
796
|
+
* de una sola acción.
|
|
797
|
+
*
|
|
798
|
+
* <kf-input type="password" label="Contraseña" toggleable formControlName="password" />
|
|
761
799
|
*/
|
|
762
800
|
declare class Input implements ControlValueAccessor, AfterViewInit {
|
|
763
801
|
private static nextId;
|
|
764
802
|
private readonly nativeInput;
|
|
765
803
|
readonly label: _angular_core.InputSignal<string | undefined>;
|
|
766
|
-
/**
|
|
767
|
-
readonly
|
|
804
|
+
/** Marca el label con un asterisco visual — no aplica `required` al `<input>` nativo por sí solo. */
|
|
805
|
+
readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
806
|
+
/** Ícono líder, renderizado vía `kf-icon`. */
|
|
807
|
+
readonly icon: _angular_core.InputSignal<IconName | undefined>;
|
|
768
808
|
readonly suffix: _angular_core.InputSignal<string | undefined>;
|
|
769
809
|
readonly hint: _angular_core.InputSignal<string | undefined>;
|
|
810
|
+
/** Borde y aria-invalid en rojo. Ver `errorMessage` para el mensaje asociado. */
|
|
811
|
+
readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
812
|
+
/** Mensaje de error con `role="alert"` — reemplaza a `hint` mientras esté presente. */
|
|
813
|
+
readonly errorMessage: _angular_core.InputSignal<string | undefined>;
|
|
770
814
|
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
771
815
|
readonly type: _angular_core.InputSignal<string>;
|
|
772
816
|
readonly placeholder: _angular_core.InputSignal<string>;
|
|
817
|
+
/** Agrega el botón de mostrar/ocultar — sin efecto si `type` no es `"password"`. */
|
|
818
|
+
readonly toggleable: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
773
819
|
protected readonly inputId: string;
|
|
774
820
|
protected readonly hintId: string;
|
|
821
|
+
protected readonly errorId: string;
|
|
775
822
|
protected readonly value: _angular_core.WritableSignal<string>;
|
|
776
823
|
protected readonly focused: _angular_core.WritableSignal<boolean>;
|
|
777
824
|
/** Deshabilitado por Reactive Forms (formControl.disable()). */
|
|
778
825
|
private readonly disabledByForm;
|
|
779
826
|
/** Disabled real: por input() directo o por el FormControl asociado. */
|
|
780
827
|
protected readonly isDisabled: _angular_core.Signal<boolean>;
|
|
828
|
+
/** Estado interno del toggle — irrelevante si `showPasswordToggle()` es false. */
|
|
829
|
+
protected readonly passwordVisible: _angular_core.WritableSignal<boolean>;
|
|
830
|
+
/** El botón solo tiene sentido si el campo realmente es de contraseña. */
|
|
831
|
+
protected readonly showPasswordToggle: _angular_core.Signal<boolean>;
|
|
832
|
+
/**
|
|
833
|
+
* `type` real que recibe el `<input>` nativo: igual a `type()` salvo
|
|
834
|
+
* cuando el toggle está activo y visible, donde pasa a `text` para
|
|
835
|
+
* mostrar el valor en claro sin cambiar `type()` en sí (evita que un
|
|
836
|
+
* consumidor que lee `type()` desde afuera vea un valor inconsistente).
|
|
837
|
+
*/
|
|
838
|
+
protected readonly effectiveType: _angular_core.Signal<string>;
|
|
781
839
|
private onChange;
|
|
782
840
|
private onTouched;
|
|
783
841
|
ngAfterViewInit(): void;
|
|
@@ -787,8 +845,14 @@ declare class Input implements ControlValueAccessor, AfterViewInit {
|
|
|
787
845
|
setDisabledState(isDisabled: boolean): void;
|
|
788
846
|
protected onInput(rawValue: string): void;
|
|
789
847
|
protected onBlur(): void;
|
|
848
|
+
/**
|
|
849
|
+
* Alterna la visibilidad del valor. No dispara `onBlur`/pierde el foco:
|
|
850
|
+
* el botón vive dentro del mismo `.kf-input__field`, así que un click acá
|
|
851
|
+
* no debe tratarse como si el usuario hubiese abandonado el campo.
|
|
852
|
+
*/
|
|
853
|
+
protected onTogglePasswordVisibility(): void;
|
|
790
854
|
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>;
|
|
855
|
+
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; }; "toggleable": { "alias": "toggleable"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
792
856
|
}
|
|
793
857
|
|
|
794
858
|
/**
|