@studiolxd/brand 42.0.0 → 44.0.0
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/CHANGELOG.md +113 -0
- package/dist/_shared/datepicker.js +75 -78
- package/dist/_shared/imagecropdialog.js +124 -123
- package/dist/_shared/validate.js +31 -5
- package/dist/_types/atoms/FileUpload/FileUpload.d.ts +79 -11
- package/dist/_types/atoms/FileUpload/validate.d.ts +36 -3
- package/dist/_types/atoms/TimeSelect/TimeSelect.d.ts +34 -6
- package/dist/_types/messages/BrandMessages.d.ts +13 -1
- package/dist/_types/messages/index.d.ts +1 -1
- package/dist/_types/molecules/AvatarUpload/AvatarUpload.d.ts +123 -25
- package/dist/_types/molecules/Calendar/Calendar.d.ts +44 -13
- package/dist/_types/molecules/CalendarPlanner/CalendarPlanner.d.ts +5 -4
- package/dist/_types/molecules/CalendarRoster/CalendarRoster.d.ts +5 -4
- package/dist/_types/molecules/DatePicker/DatePicker.d.ts +56 -26
- package/dist/_types/molecules/DatePicker/dateMask.d.ts +9 -2
- package/dist/_types/molecules/DateTimeField/DateTimeField.d.ts +12 -12
- package/dist/_types/molecules/ImageCropDialog/ImageCropDialog.d.ts +28 -4
- package/dist/_types/molecules/TimeField/TimeField.d.ts +9 -2
- package/dist/_types/molecules/_shared/calendarGrid.d.ts +6 -2
- package/dist/avatar-upload.js +98 -95
- package/dist/calendar-planner.js +47 -46
- package/dist/calendar-roster.js +62 -61
- package/dist/calendar.js +87 -86
- package/dist/file-upload.js +120 -117
- package/dist/time-select.js +57 -56
- package/package.json +1 -1
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
import { type FormSize } from '../../constants/form-size';
|
|
2
2
|
import './FileUpload.css';
|
|
3
|
+
/**
|
|
4
|
+
* El cromo de la zona de subida: lo que dice la zona, lo que dice de los
|
|
5
|
+
* límites y lo que dice cuando un archivo no vale.
|
|
6
|
+
*
|
|
7
|
+
* Las dos pistas de límite son **plantillas y no frases hechas**, y ahí está
|
|
8
|
+
* la parte interesante. «Máximo 2,5 MB» tiene dos mitades que se deciden en
|
|
9
|
+
* sitios distintos, igual que `dd/mm/aaaa`: la frase es idioma y sale de aquí;
|
|
10
|
+
* la cifra —la coma o el punto decimal, el espacio antes de `MB`— es formato y
|
|
11
|
+
* la escribe `Intl.NumberFormat` con el `locale` del componente. Por eso el
|
|
12
|
+
* catálogo recibe el peso **ya formateado** y solo lo envuelve: una traducción
|
|
13
|
+
* que escribiera «max. 2.5 MB» a mano metería el punto inglés en una interfaz
|
|
14
|
+
* española.
|
|
15
|
+
*/
|
|
16
|
+
export interface FileUploadMessages {
|
|
17
|
+
/** Texto visible de la zona de arrastre en reposo. */
|
|
18
|
+
dropzone: string;
|
|
19
|
+
/** Texto visible mientras se arrastra un archivo por encima. */
|
|
20
|
+
dropzoneActive: string;
|
|
21
|
+
/** Texto visible secundario: que además se puede hacer clic. */
|
|
22
|
+
dropzoneHint: string;
|
|
23
|
+
/** Pista de peso máximo. Recibe el peso **ya escrito en el locale** («2,5 MB»). */
|
|
24
|
+
maxSize: (maxSize: string) => string;
|
|
25
|
+
/** Pista de número máximo de archivos. */
|
|
26
|
+
maxFiles: (maxFiles: number) => string;
|
|
27
|
+
/** aria-label de la lista de archivos elegidos. */
|
|
28
|
+
files: string;
|
|
29
|
+
/** aria-label de la barra de progreso. */
|
|
30
|
+
progress: string;
|
|
31
|
+
/** aria-label del botón de quitar un archivo de la lista. */
|
|
32
|
+
removeFile: (fileName: string) => string;
|
|
33
|
+
/** Error de archivo demasiado pesado. Recibe el peso ya escrito en el locale. */
|
|
34
|
+
tooLarge: (maxSize: string) => string;
|
|
35
|
+
/** Error de tipo de archivo no admitido. */
|
|
36
|
+
invalidType: string;
|
|
37
|
+
}
|
|
3
38
|
export interface FileUploadProps {
|
|
4
39
|
multiple?: boolean;
|
|
5
40
|
accept?: string;
|
|
@@ -35,27 +70,60 @@ export interface FileUploadProps {
|
|
|
35
70
|
/** Se añade DESPUÉS de las clases propias del componente. */
|
|
36
71
|
className?: string;
|
|
37
72
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
73
|
+
* Locale con el que se escriben **los pesos** («2,5 MB» / «2.5 MB»). No
|
|
74
|
+
* decide el idioma de los textos —eso es el catálogo— sino el formato de la
|
|
75
|
+
* cifra. Default `'es-ES'`.
|
|
76
|
+
*/
|
|
77
|
+
locale?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Texto visible de la zona de arrastre. **Sin default**: sin él, sale de
|
|
80
|
+
* `fileUpload.dropzone` del `BrandMessagesProvider`.
|
|
40
81
|
*/
|
|
41
82
|
dropzoneLabel?: string;
|
|
42
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* Texto visible mientras se arrastra encima. **Sin default**: sin él, sale
|
|
85
|
+
* de `fileUpload.dropzoneActive`.
|
|
86
|
+
*/
|
|
43
87
|
dropzoneActiveLabel?: string;
|
|
44
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Texto visible secundario de la zona. **Sin default**: sin él, sale de
|
|
90
|
+
* `fileUpload.dropzoneHint`.
|
|
91
|
+
*/
|
|
45
92
|
dropzoneHintLabel?: string;
|
|
46
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* Pista de peso máximo. Recibe el peso **ya escrito en el locale**.
|
|
95
|
+
* **Sin default**: sin ella, sale de `fileUpload.maxSize`.
|
|
96
|
+
*/
|
|
47
97
|
maxSizeHint?: (maxSize: string) => string;
|
|
48
|
-
/**
|
|
98
|
+
/**
|
|
99
|
+
* Pista de número máximo de archivos. **Sin default**: sin ella, sale de
|
|
100
|
+
* `fileUpload.maxFiles`.
|
|
101
|
+
*/
|
|
49
102
|
maxFilesHint?: (maxFiles: number) => string;
|
|
50
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* aria-label de la lista de archivos. **Sin default**: sin él, sale de
|
|
105
|
+
* `fileUpload.files`.
|
|
106
|
+
*/
|
|
51
107
|
filesLabel?: string;
|
|
52
|
-
/**
|
|
108
|
+
/**
|
|
109
|
+
* aria-label de la barra de progreso. **Sin default**: sin él, sale de
|
|
110
|
+
* `fileUpload.progress`.
|
|
111
|
+
*/
|
|
53
112
|
progressLabel?: string;
|
|
54
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* aria-label del botón de quitar un archivo. **Sin default**: sin él, sale
|
|
115
|
+
* de `fileUpload.removeFile`.
|
|
116
|
+
*/
|
|
55
117
|
removeFileLabel?: (fileName: string) => string;
|
|
56
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* Error de archivo demasiado pesado. **Sin default**: sin él, sale de
|
|
120
|
+
* `fileUpload.tooLarge`.
|
|
121
|
+
*/
|
|
57
122
|
tooLargeError?: (maxSize: string) => string;
|
|
58
|
-
/**
|
|
123
|
+
/**
|
|
124
|
+
* Error de tipo no admitido. **Sin default**: sin él, sale de
|
|
125
|
+
* `fileUpload.invalidType`.
|
|
126
|
+
*/
|
|
59
127
|
invalidTypeError?: string;
|
|
60
128
|
}
|
|
61
129
|
/**
|
|
@@ -4,11 +4,44 @@
|
|
|
4
4
|
* otra cosa (la diana es el avatar, no una zona de arrastre), pero acepta y
|
|
5
5
|
* rechaza exactamente por la misma regla, y una segunda copia de esta función
|
|
6
6
|
* sería una segunda definición de qué archivo vale.
|
|
7
|
+
*
|
|
8
|
+
* Aquí vive además la mitad **de formato** de esta familia: el peso escrito y
|
|
9
|
+
* la lista de formatos. La regla de la campaña del proveedor es la misma que
|
|
10
|
+
* en la máscara de fecha: *si cambia al cambiar de idioma es cromo y va al
|
|
11
|
+
* catálogo; si cambia al cambiar de país es formato y sale del `locale`*.
|
|
7
12
|
*/
|
|
8
|
-
/** El
|
|
9
|
-
export declare
|
|
13
|
+
/** El locale que se usa cuando el componente no recibe ninguno. */
|
|
14
|
+
export declare const DEFAULT_LOCALE = "es-ES";
|
|
15
|
+
/**
|
|
16
|
+
* El peso de un archivo, escrito **en el locale**: `2,5 MB` en `es-ES` y
|
|
17
|
+
* `2.5 MB` en `en-US`.
|
|
18
|
+
*
|
|
19
|
+
* «2,5 MB» tiene dos mitades, igual que `dd/mm/aaaa`:
|
|
20
|
+
*
|
|
21
|
+
* - **El símbolo no se traduce.** `MB` es `MB` en las seis lenguas de la
|
|
22
|
+
* suite; no es una palabra, es una unidad del SI.
|
|
23
|
+
* - **El separador decimal y la colocación del sufijo son formato.** La coma
|
|
24
|
+
* o el punto, el espacio antes de la unidad y hasta si va delante o detrás
|
|
25
|
+
* los decide el `locale`, no el idioma de la interfaz.
|
|
26
|
+
*
|
|
27
|
+
* Por eso esto no es una plantilla del catálogo sino `Intl.NumberFormat` con
|
|
28
|
+
* `style: 'unit'`: la cifra la escribe el navegador. Al catálogo va solo la
|
|
29
|
+
* frase que la envuelve («Máximo {size}»), que sí es cromo.
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatFileSize(bytes: number, locale?: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Una lista de cosas escrita con la conjunción del idioma: `JPEG, PNG o WEBP`
|
|
34
|
+
* en castellano, `JPEG, PNG, or WEBP` en inglés, `JPEG, PNG oder WEBP` en
|
|
35
|
+
* alemán.
|
|
36
|
+
*
|
|
37
|
+
* Es `Intl.ListFormat` y no un `join(', ')` con una «o» pegada: la conjunción,
|
|
38
|
+
* la coma de Oxford y el espaciado cambian de una lengua a otra, y pegarlos a
|
|
39
|
+
* mano deja el texto en castellano dentro de una frase traducida. `disjunction`
|
|
40
|
+
* porque se acepta **uno** de los formatos, no todos.
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatList(items: string[], locale?: string): string;
|
|
10
43
|
/**
|
|
11
44
|
* `null` si el archivo pasa; si no, el mensaje que lo explica. Los mensajes
|
|
12
45
|
* los pone quien llama: son texto de producto, no de esta función.
|
|
13
46
|
*/
|
|
14
|
-
export declare function validateFile(file: File, accept: string | undefined, maxSize: number | undefined, tooLargeError: (maxSize: string) => string, invalidTypeError: string): string | null;
|
|
47
|
+
export declare function validateFile(file: File, accept: string | undefined, maxSize: number | undefined, tooLargeError: (maxSize: string) => string, invalidTypeError: string, locale?: string): string | null;
|
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
import './TimeSelect.css';
|
|
2
|
+
/**
|
|
3
|
+
* El cromo de la hora: cómo se llaman los dos desplegables y qué pone dentro
|
|
4
|
+
* mientras no hay hora elegida.
|
|
5
|
+
*
|
|
6
|
+
* **Las dos máscaras también son idioma, no formato.** `HH` y `MM` parecen
|
|
7
|
+
* notación técnica, pero son la inicial de una palabra —hora y minuto— y
|
|
8
|
+
* cambian con ella: en alemán se escriben `SS`/`MM` (*Stunde*, *Minute*). Lo
|
|
9
|
+
* que NO se traduce es el dibujo: dos cifras, la hora antes que el minuto y
|
|
10
|
+
* los dos puntos en medio; eso no lo decide ni la prop ni el catálogo.
|
|
11
|
+
*
|
|
12
|
+
* Las **cifras de las opciones** (`00`…`23`) tampoco están aquí: son datos.
|
|
13
|
+
*/
|
|
14
|
+
export interface TimeSelectMessages {
|
|
15
|
+
/** Nombre accesible del desplegable de horas. */
|
|
16
|
+
hours: string;
|
|
17
|
+
/** Nombre accesible del desplegable de minutos. */
|
|
18
|
+
minutes: string;
|
|
19
|
+
/** Máscara del desplegable de horas sin valor: `HH`. */
|
|
20
|
+
maskHours: string;
|
|
21
|
+
/** Máscara del desplegable de minutos sin valor: `MM`. */
|
|
22
|
+
maskMinutes: string;
|
|
23
|
+
}
|
|
2
24
|
export interface TimeValue {
|
|
3
25
|
h: number;
|
|
4
26
|
m: number;
|
|
@@ -27,18 +49,24 @@ export interface TimeSelectProps {
|
|
|
27
49
|
/** Se añade DESPUÉS de las clases propias del componente. */
|
|
28
50
|
className?: string;
|
|
29
51
|
/**
|
|
30
|
-
* aria-label del selector de horas.
|
|
31
|
-
*
|
|
52
|
+
* aria-label del selector de horas. **Sin default**: sin él, el texto sale
|
|
53
|
+
* de `timeSelect.hours` del `BrandMessagesProvider`.
|
|
32
54
|
*/
|
|
33
55
|
hoursLabel?: string;
|
|
34
56
|
/**
|
|
35
|
-
* aria-label del selector de minutos.
|
|
36
|
-
*
|
|
57
|
+
* aria-label del selector de minutos. **Sin default**: sin él, sale de
|
|
58
|
+
* `timeSelect.minutes` del `BrandMessagesProvider`.
|
|
37
59
|
*/
|
|
38
60
|
minutesLabel?: string;
|
|
39
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Máscara del selector de horas. **Sin default**: sin ella, sale de
|
|
63
|
+
* `timeSelect.maskHours` del `BrandMessagesProvider`.
|
|
64
|
+
*/
|
|
40
65
|
hoursPlaceholder?: string;
|
|
41
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* Máscara del selector de minutos. **Sin default**: sin ella, sale de
|
|
68
|
+
* `timeSelect.maskMinutes` del `BrandMessagesProvider`.
|
|
69
|
+
*/
|
|
42
70
|
minutesPlaceholder?: string;
|
|
43
71
|
}
|
|
44
72
|
/**
|
|
@@ -13,6 +13,12 @@ import type { AsyncMultiSelectMessages } from '../atoms/AsyncMultiSelect/AsyncMu
|
|
|
13
13
|
import type { DocsSearchMessages } from '../molecules/DocsSearch/DocsSearch';
|
|
14
14
|
import type { SearchFormMessages } from '../molecules/SearchForm/SearchForm';
|
|
15
15
|
import type { FilterBarMessages } from '../molecules/FilterBar/FilterBar';
|
|
16
|
+
import type { CalendarMessages } from '../molecules/Calendar/Calendar';
|
|
17
|
+
import type { DatePickerMessages } from '../molecules/DatePicker/DatePicker';
|
|
18
|
+
import type { TimeSelectMessages } from '../atoms/TimeSelect/TimeSelect';
|
|
19
|
+
import type { FileUploadMessages } from '../atoms/FileUpload/FileUpload';
|
|
20
|
+
import type { ImageCropDialogMessages } from '../molecules/ImageCropDialog/ImageCropDialog';
|
|
21
|
+
import type { AvatarUploadMessages } from '../molecules/AvatarUpload/AvatarUpload';
|
|
16
22
|
/**
|
|
17
23
|
* El contrato de textos de la librería: un espacio por componente, y dentro
|
|
18
24
|
* de cada espacio **todas las claves obligatorias**.
|
|
@@ -50,5 +56,11 @@ export interface BrandMessages {
|
|
|
50
56
|
docsSearch: DocsSearchMessages;
|
|
51
57
|
searchForm: SearchFormMessages;
|
|
52
58
|
filterBar: FilterBarMessages;
|
|
59
|
+
calendar: CalendarMessages;
|
|
60
|
+
datePicker: DatePickerMessages;
|
|
61
|
+
timeSelect: TimeSelectMessages;
|
|
62
|
+
fileUpload: FileUploadMessages;
|
|
63
|
+
imageCropDialog: ImageCropDialogMessages;
|
|
64
|
+
avatarUpload: AvatarUploadMessages;
|
|
53
65
|
}
|
|
54
|
-
export type { PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, FilterBarMessages, };
|
|
66
|
+
export type { PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, };
|
|
@@ -2,4 +2,4 @@ export { BrandMessagesProvider } from './BrandMessagesProvider';
|
|
|
2
2
|
export type { BrandMessagesProviderProps } from './BrandMessagesProvider';
|
|
3
3
|
export { useBrandMessages } from './BrandMessagesContext';
|
|
4
4
|
export type { BrandMessagesReader } from './BrandMessagesContext';
|
|
5
|
-
export type { BrandMessages, PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, FilterBarMessages, } from './BrandMessages';
|
|
5
|
+
export type { BrandMessages, PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, } from './BrandMessages';
|
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { type FormSize } from '../../constants/form-size';
|
|
3
3
|
import './AvatarUpload.css';
|
|
4
|
+
/**
|
|
5
|
+
* El cromo de la subida de avatar. Todo lo de aquí vale igual en la pantalla
|
|
6
|
+
* de la cuenta y en la de la organización; lo que cambia entre las dos —qué se
|
|
7
|
+
* sube— entra por `subject`, que es contenido y sigue siendo prop.
|
|
8
|
+
*
|
|
9
|
+
* **El par visible/accesible del botón está aquí entero, y a propósito.**
|
|
10
|
+
* WCAG 2.5.3 (Label in Name) exige que el nombre accesible **contenga** el
|
|
11
|
+
* texto visible: quien navega por voz dice lo que ve. Si el visible saliera
|
|
12
|
+
* del catálogo común («Subir») y el accesible de la pantalla («Subir logo»),
|
|
13
|
+
* los dos lados del contrato vivirían en ficheros distintos y una traducción
|
|
14
|
+
* podría romperlo sin que nada fallara — el botón quedaría inalcanzable por
|
|
15
|
+
* voz. Por eso el catálogo trae los dos: `button`, el verbo suelto, y
|
|
16
|
+
* `buttonFor`, la **plantilla** que lo envuelve con el sujeto.
|
|
17
|
+
*
|
|
18
|
+
* La plantilla, y no una concatenación en el componente, porque el orden es
|
|
19
|
+
* del idioma: «Subir el logo» y *«Upload the logo»* ponen el verbo delante,
|
|
20
|
+
* pero el alemán lo pone al final («das Logo hochladen»). Un `${verbo}
|
|
21
|
+
* ${sujeto}` cableado aquí sería castellano disfrazado.
|
|
22
|
+
*
|
|
23
|
+
* **La regla del catálogo, en una línea: `buttonFor(x)` tiene que contener
|
|
24
|
+
* `button`.** En desarrollo se avisa por consola si no lo cumple.
|
|
25
|
+
*/
|
|
26
|
+
export interface AvatarUploadMessages {
|
|
27
|
+
/** Texto **visible** del botón: el verbo suelto («Subir»). */
|
|
28
|
+
button: string;
|
|
29
|
+
/**
|
|
30
|
+
* Nombre **accesible** del botón, con el sujeto dentro («Subir el logo»).
|
|
31
|
+
* Tiene que contener `button`, o WCAG 2.5.3 se rompe.
|
|
32
|
+
*/
|
|
33
|
+
buttonFor: (subject: string) => string;
|
|
34
|
+
/** Qué se sube cuando la pantalla no lo dice: el sujeto genérico («el avatar»). */
|
|
35
|
+
subject: string;
|
|
36
|
+
/** Pista **visible** de que además se puede arrastrar. */
|
|
37
|
+
dropHint: (subject: string) => string;
|
|
38
|
+
/** Lo que se anuncia cuando empieza un arrastre sobre la ventana. */
|
|
39
|
+
dropActive: (subject: string) => string;
|
|
40
|
+
/** Pista de peso máximo. Recibe el peso **ya escrito en el locale** («2,5 MB»). */
|
|
41
|
+
maxSize: (maxSize: string) => string;
|
|
42
|
+
/** Error de formato. Recibe los formatos **ya unidos con la conjunción del idioma**. */
|
|
43
|
+
invalidType: (formats: string) => string;
|
|
44
|
+
/** Error de peso. Recibe el peso ya escrito en el locale. */
|
|
45
|
+
tooLarge: (maxSize: string) => string;
|
|
46
|
+
/** Texto del botón que descarta el recorte. */
|
|
47
|
+
cropCancel: string;
|
|
48
|
+
/** Texto del botón que confirma el recorte. */
|
|
49
|
+
cropConfirm: string;
|
|
50
|
+
}
|
|
4
51
|
export interface AvatarUploadProps {
|
|
5
52
|
/** URL de la imagen actual. Sin ella, el avatar enseña las iniciales de `name`. */
|
|
6
53
|
src?: string | null;
|
|
@@ -36,16 +83,31 @@ export interface AvatarUploadProps {
|
|
|
36
83
|
/** Un archivo rechazado por la validación de cliente, con el mensaje que se enseña. */
|
|
37
84
|
onError?: (message: string) => void;
|
|
38
85
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
86
|
+
* **Qué** se sube, como sintagma con artículo: `"el logo"`, `"la foto de
|
|
87
|
+
* perfil"`. Es lo único de esta pieza que cambia de una pantalla a otra, así
|
|
88
|
+
* que es contenido y entra por aquí, del catálogo de la aplicación.
|
|
89
|
+
*
|
|
90
|
+
* Con él se arman el nombre accesible del botón, la pista de arrastre y el
|
|
91
|
+
* aviso de soltar, cada uno con su plantilla del catálogo. Sin él, el sujeto
|
|
92
|
+
* genérico de `avatarUpload.subject` («el avatar»).
|
|
93
|
+
*/
|
|
94
|
+
subject?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Texto **visible** del botón. **Sin default**: sin él, sale de
|
|
97
|
+
* `avatarUpload.button` del `BrandMessagesProvider`.
|
|
98
|
+
*
|
|
99
|
+
* Corto a propósito: el sujeto va en el nombre accesible, que se arma con
|
|
100
|
+
* `subject`.
|
|
41
101
|
*/
|
|
42
102
|
buttonLabel?: string;
|
|
43
103
|
/**
|
|
44
|
-
* Nombre **accesible** del botón,
|
|
45
|
-
*
|
|
104
|
+
* Nombre **accesible** del botón, entero. Es la salida de emergencia: lo
|
|
105
|
+
* normal es pasar `subject` y dejar que el catálogo lo arme, porque así el
|
|
106
|
+
* verbo visible y el accesible salen del mismo sitio y no se pueden
|
|
107
|
+
* desparejar al traducir.
|
|
46
108
|
*
|
|
47
109
|
* WCAG 2.5.3 (Label in Name) exige que **contenga** el texto visible: quien
|
|
48
|
-
* navega por voz dice lo que ve. "Subir" dentro de "Subir logo" cumple;
|
|
110
|
+
* navega por voz dice lo que ve. "Subir" dentro de "Subir el logo" cumple;
|
|
49
111
|
* "Cargar imagen de la organización" no, y deja el control inalcanzable.
|
|
50
112
|
* En desarrollo se avisa por consola si no lo contiene.
|
|
51
113
|
*/
|
|
@@ -58,51 +120,87 @@ export interface AvatarUploadProps {
|
|
|
58
120
|
hintLabel?: string;
|
|
59
121
|
/**
|
|
60
122
|
* Los formatos, escritos para leer. Default: los subtipos de `accept` en
|
|
61
|
-
* mayúsculas
|
|
123
|
+
* mayúsculas, unidos con la conjunción del `locale` (`JPEG, PNG o WEBP`).
|
|
124
|
+
* Con comodines (`image/*`) pásalo escrito.
|
|
62
125
|
*/
|
|
63
126
|
formatsLabel?: string;
|
|
64
|
-
/**
|
|
127
|
+
/**
|
|
128
|
+
* Locale con el que se escriben **el peso** («2,5 MB» / «2.5 MB») y **la
|
|
129
|
+
* conjunción de la lista de formatos** («o» / «or» / «oder»). No decide el
|
|
130
|
+
* idioma de los textos —eso es el catálogo— sino el formato. Default
|
|
131
|
+
* `'es-ES'`.
|
|
132
|
+
*/
|
|
133
|
+
locale?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Pista de peso máximo. Recibe el peso **ya escrito en el locale**.
|
|
136
|
+
* **Sin default**: sin ella, sale de `avatarUpload.maxSize`.
|
|
137
|
+
*/
|
|
65
138
|
maxSizeHint?: (maxSize: string) => string;
|
|
66
139
|
/**
|
|
67
|
-
* Error de formato.
|
|
68
|
-
* Dice lo que SÍ se acepta: por el botón el
|
|
69
|
-
* diálogo del sistema), pero soltando un
|
|
140
|
+
* Error de formato. **Sin default**: sin él, sale de
|
|
141
|
+
* `avatarUpload.invalidType`. Dice lo que SÍ se acepta: por el botón el
|
|
142
|
+
* error es imposible (lo filtra el diálogo del sistema), pero soltando un
|
|
143
|
+
* archivo no hay filtro que valga.
|
|
70
144
|
*/
|
|
71
145
|
invalidTypeError?: (formats: string) => string;
|
|
72
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* Error de peso. **Sin default**: sin él, sale de `avatarUpload.tooLarge`.
|
|
148
|
+
*/
|
|
73
149
|
tooLargeError?: (maxSize: string) => string;
|
|
74
150
|
/**
|
|
75
|
-
* Lo que se anuncia cuando empieza un arrastre sobre la ventana.
|
|
76
|
-
*
|
|
151
|
+
* Lo que se anuncia cuando empieza un arrastre sobre la ventana. **Sin
|
|
152
|
+
* default**: sin él, `avatarUpload.dropActive` con el `subject`.
|
|
77
153
|
*/
|
|
78
154
|
dropActiveMessage?: string;
|
|
79
155
|
/**
|
|
80
156
|
* Pista **visible** bajo el botón: dice que además se puede arrastrar, que
|
|
81
|
-
* es lo único de esta pieza que no se adivina mirándola.
|
|
82
|
-
*
|
|
157
|
+
* es lo único de esta pieza que no se adivina mirándola. **Sin default**:
|
|
158
|
+
* sin ella, `avatarUpload.dropHint` con el `subject`. Con cadena vacía no se
|
|
159
|
+
* pinta.
|
|
83
160
|
*/
|
|
84
161
|
dropHintLabel?: string;
|
|
85
162
|
/**
|
|
86
|
-
* Título del diálogo de recorte.
|
|
87
|
-
*
|
|
88
|
-
*
|
|
163
|
+
* Título del diálogo de recorte. **Obligatorio y sin default**, como el
|
|
164
|
+
* `title` del propio `ImageCropDialog`: el diálogo no sabe qué se recorta
|
|
165
|
+
* («Recorta tu foto», «Recorta tu logo») y eso es contenido de la pantalla.
|
|
89
166
|
*/
|
|
90
|
-
cropTitle
|
|
167
|
+
cropTitle: string;
|
|
91
168
|
/**
|
|
92
169
|
* Descripción del diálogo de recorte. **Sin default**: el diálogo enseña la
|
|
93
170
|
* imagen y su marco de selección, que se explican solos. Pásala solo si en
|
|
94
171
|
* tu caso hay algo que decir que no esté ya a la vista.
|
|
95
172
|
*/
|
|
96
173
|
cropDescription?: ReactNode;
|
|
97
|
-
/**
|
|
174
|
+
/**
|
|
175
|
+
* Texto del botón que descarta el recorte. **Sin default**: sin él, sale de
|
|
176
|
+
* `avatarUpload.cropCancel`.
|
|
177
|
+
*
|
|
178
|
+
* Aquí sí sale del catálogo, al revés que en `ImageCropDialog`: el diálogo
|
|
179
|
+
* genérico no sabe qué confirma («Aplicar», «Usar esta imagen») y por eso lo
|
|
180
|
+
* exige; esta subida sí lo sabe —se descarta o se guarda un recorte— y el
|
|
181
|
+
* par vale igual en todas las pantallas.
|
|
182
|
+
*/
|
|
98
183
|
cropCancelLabel?: ReactNode;
|
|
99
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Texto del botón que confirma el recorte. **Sin default**: sin él, sale de
|
|
186
|
+
* `avatarUpload.cropConfirm`.
|
|
187
|
+
*/
|
|
100
188
|
cropConfirmLabel?: ReactNode;
|
|
101
|
-
/**
|
|
189
|
+
/**
|
|
190
|
+
* Etiqueta del aspa de cerrar. Se reenvía **tal cual** al `ImageCropDialog`
|
|
191
|
+
* y de ahí al `Modal`, que todavía no lee del proveedor: mientras no se
|
|
192
|
+
* migre, sin esta prop el aspa dice lo que diga `Modal`.
|
|
193
|
+
*/
|
|
102
194
|
cropCloseLabel?: string;
|
|
103
|
-
/**
|
|
195
|
+
/**
|
|
196
|
+
* Lo que se dice mientras la imagen se carga en el diálogo. Reenvío puro:
|
|
197
|
+
* sin él, el `ImageCropDialog` lo lee de `imageCropDialog.loading`.
|
|
198
|
+
*/
|
|
104
199
|
cropLoadingLabel?: string;
|
|
105
|
-
/**
|
|
200
|
+
/**
|
|
201
|
+
* Lo que se dice cuando la imagen no se puede cargar. Reenvío puro: sin él,
|
|
202
|
+
* el `ImageCropDialog` lo lee de `imageCropDialog.error`.
|
|
203
|
+
*/
|
|
106
204
|
cropErrorMessage?: string;
|
|
107
205
|
/** Se añade DESPUÉS de las clases propias del componente. */
|
|
108
206
|
className?: string;
|
|
@@ -122,4 +220,4 @@ export interface AvatarUploadProps {
|
|
|
122
220
|
* arrastrar no existe para el teclado, así que es la vía principal, no un
|
|
123
221
|
* respaldo.
|
|
124
222
|
*/
|
|
125
|
-
export declare function AvatarUpload({ src, name, alt, shape, size: sizeProp, accept, maxSize, outputMimeType, outputSize, disabled, busy, errorMessage, onChange, onSelect, onError, buttonLabel, buttonAccessibleLabel, hintLabel, formatsLabel, maxSizeHint, invalidTypeError, tooLargeError, dropActiveMessage, dropHintLabel, cropTitle, cropDescription, cropCancelLabel, cropConfirmLabel, cropCloseLabel, cropLoadingLabel, cropErrorMessage, className, }: AvatarUploadProps): import("react/jsx-runtime").JSX.Element;
|
|
223
|
+
export declare function AvatarUpload({ src, name, alt, shape, size: sizeProp, accept, maxSize, outputMimeType, outputSize, disabled, busy, errorMessage, onChange, onSelect, onError, subject: subjectProp, buttonLabel, buttonAccessibleLabel, hintLabel, formatsLabel, locale, maxSizeHint, invalidTypeError, tooLargeError, dropActiveMessage, dropHintLabel, cropTitle, cropDescription, cropCancelLabel, cropConfirmLabel, cropCloseLabel, cropLoadingLabel, cropErrorMessage, className, }: AvatarUploadProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,4 +1,32 @@
|
|
|
1
1
|
import './Calendar.css';
|
|
2
|
+
/**
|
|
3
|
+
* El cromo del calendario: las dos flechas —que cambian de nombre según la
|
|
4
|
+
* vista— y el rótulo de la rejilla de años. Dicen lo mismo en toda la suite,
|
|
5
|
+
* así que salen del catálogo y no de una prop por uso.
|
|
6
|
+
*
|
|
7
|
+
* **Lo que NO está aquí, y no es olvido:** los nombres de los meses, los de
|
|
8
|
+
* los días de la semana, las cifras del año y el nombre accesible de cada
|
|
9
|
+
* celda («lunes, 15 de enero de 2025»). Eso no es texto de interfaz sino
|
|
10
|
+
* **formato de fecha**: sale de `locale` con `Intl`, que además es quien sabe
|
|
11
|
+
* en qué día empieza la semana y con qué cifras se escribe el año. Traducirlo
|
|
12
|
+
* por catálogo sería reescribir a mano lo que el navegador ya trae bien.
|
|
13
|
+
*
|
|
14
|
+
* Tampoco está `gridLabel`: nombra a ESTE calendario («Fecha de alta»), que
|
|
15
|
+
* es contenido de la pantalla. Sin él la rejilla toma como nombre el título
|
|
16
|
+
* del mes visible, que ya viene del locale.
|
|
17
|
+
*/
|
|
18
|
+
export interface CalendarMessages {
|
|
19
|
+
/** Nombre accesible de la flecha de retroceso sobre la rejilla de días. */
|
|
20
|
+
previousMonth: string;
|
|
21
|
+
/** Nombre accesible de la flecha de avance sobre la rejilla de días. */
|
|
22
|
+
nextMonth: string;
|
|
23
|
+
/** Nombre accesible de la flecha de retroceso sobre la rejilla de años. */
|
|
24
|
+
previousYears: string;
|
|
25
|
+
/** Nombre accesible de la flecha de avance sobre la rejilla de años. */
|
|
26
|
+
nextYears: string;
|
|
27
|
+
/** Nombre accesible de la rejilla de años. */
|
|
28
|
+
yearGrid: string;
|
|
29
|
+
}
|
|
2
30
|
export interface CalendarProps {
|
|
3
31
|
/** Fecha seleccionada (modo controlado) */
|
|
4
32
|
value?: Date | null;
|
|
@@ -21,34 +49,37 @@ export interface CalendarProps {
|
|
|
21
49
|
/** Locale para nombres de mes y día. Default: 'es-ES' */
|
|
22
50
|
locale?: string;
|
|
23
51
|
/**
|
|
24
|
-
* aria-label del botón de mes anterior.
|
|
25
|
-
*
|
|
52
|
+
* aria-label del botón de mes anterior. **Sin default**: sin él, el texto
|
|
53
|
+
* sale de `calendar.previousMonth` del `BrandMessagesProvider`.
|
|
26
54
|
*/
|
|
27
55
|
previousMonthLabel?: string;
|
|
28
56
|
/**
|
|
29
|
-
* aria-label del botón de mes siguiente.
|
|
30
|
-
*
|
|
57
|
+
* aria-label del botón de mes siguiente. **Sin default**: sin él, el texto
|
|
58
|
+
* sale de `calendar.nextMonth` del `BrandMessagesProvider`.
|
|
31
59
|
*/
|
|
32
60
|
nextMonthLabel?: string;
|
|
33
61
|
/**
|
|
34
|
-
* aria-label del botón de retroceso **en la vista de años**.
|
|
35
|
-
*
|
|
62
|
+
* aria-label del botón de retroceso **en la vista de años**. **Sin
|
|
63
|
+
* default**: sin él, sale de `calendar.previousYears` del
|
|
64
|
+
* `BrandMessagesProvider`.
|
|
36
65
|
*/
|
|
37
66
|
previousYearsLabel?: string;
|
|
38
67
|
/**
|
|
39
|
-
* aria-label del botón de avance en la vista de años.
|
|
40
|
-
*
|
|
68
|
+
* aria-label del botón de avance en la vista de años. **Sin default**: sin
|
|
69
|
+
* él, sale de `calendar.nextYears` del `BrandMessagesProvider`.
|
|
41
70
|
*/
|
|
42
71
|
nextYearsLabel?: string;
|
|
43
72
|
/**
|
|
44
|
-
* aria-label de la rejilla de años.
|
|
73
|
+
* aria-label de la rejilla de años. **Sin default**: sin él, sale de
|
|
74
|
+
* `calendar.yearGrid` del `BrandMessagesProvider`.
|
|
45
75
|
*/
|
|
46
76
|
yearGridLabel?: string;
|
|
47
77
|
/**
|
|
48
|
-
* aria-label de la rejilla de días.
|
|
49
|
-
*
|
|
50
|
-
* nombre
|
|
51
|
-
*
|
|
78
|
+
* aria-label de la rejilla de días. **No sale del catálogo**: nombra a ESTE
|
|
79
|
+
* calendario («Fecha de alta»), que es contenido de la pantalla. Sin ella,
|
|
80
|
+
* la rejilla toma como nombre el título del mes visible. Cuando el
|
|
81
|
+
* calendario vive dentro de un panel con nombre propio (el `Popover` de
|
|
82
|
+
* `DatePicker`), conviene pasarlo aquí.
|
|
52
83
|
*/
|
|
53
84
|
gridLabel?: string;
|
|
54
85
|
/** Tamaño del componente. Default: 'md' */
|
|
@@ -43,13 +43,14 @@ export interface CalendarPlannerProps {
|
|
|
43
43
|
/** Locale para nombres de mes y día. Default: 'es-ES' */
|
|
44
44
|
locale?: string;
|
|
45
45
|
/**
|
|
46
|
-
* aria-label del botón de mes anterior.
|
|
47
|
-
*
|
|
46
|
+
* aria-label del botón de mes anterior. **Sin default**: sin él, sale de
|
|
47
|
+
* `calendar.previousMonth` del `BrandMessagesProvider` — es el mismo texto
|
|
48
|
+
* que el del `Calendar`, así que es el mismo espacio.
|
|
48
49
|
*/
|
|
49
50
|
previousMonthLabel?: string;
|
|
50
51
|
/**
|
|
51
|
-
* aria-label del botón de mes siguiente.
|
|
52
|
-
*
|
|
52
|
+
* aria-label del botón de mes siguiente. **Sin default**: sin él, sale de
|
|
53
|
+
* `calendar.nextMonth` del `BrandMessagesProvider`.
|
|
53
54
|
*/
|
|
54
55
|
nextMonthLabel?: string;
|
|
55
56
|
/**
|
|
@@ -62,13 +62,14 @@ export interface CalendarRosterProps {
|
|
|
62
62
|
*/
|
|
63
63
|
legendLabel?: string;
|
|
64
64
|
/**
|
|
65
|
-
* aria-label del botón de mes anterior.
|
|
66
|
-
*
|
|
65
|
+
* aria-label del botón de mes anterior. **Sin default**: sin él, sale de
|
|
66
|
+
* `calendar.previousMonth` del `BrandMessagesProvider` — es el mismo texto
|
|
67
|
+
* que el del `Calendar`, así que es el mismo espacio.
|
|
67
68
|
*/
|
|
68
69
|
previousMonthLabel?: string;
|
|
69
70
|
/**
|
|
70
|
-
* aria-label del botón de mes siguiente.
|
|
71
|
-
*
|
|
71
|
+
* aria-label del botón de mes siguiente. **Sin default**: sin él, sale de
|
|
72
|
+
* `calendar.nextMonth` del `BrandMessagesProvider`.
|
|
72
73
|
*/
|
|
73
74
|
nextMonthLabel?: string;
|
|
74
75
|
/** Locale para nombres de mes y día. Default: 'es-ES' */
|