@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,6 +1,38 @@
|
|
|
1
1
|
import type { CalendarProps } from '../Calendar/Calendar';
|
|
2
2
|
import { type DateMaskLetters } from './dateMask';
|
|
3
3
|
import './DatePicker.css';
|
|
4
|
+
/**
|
|
5
|
+
* El cromo del selector de fecha: el botón que abre el calendario, el aviso de
|
|
6
|
+
* fecha incompleta, el nombre del panel y **las letras de la máscara**.
|
|
7
|
+
*
|
|
8
|
+
* Las letras están aquí a propósito, y son el caso interesante de esta
|
|
9
|
+
* familia. `dd/mm/aaaa` tiene dos mitades que no se deciden igual:
|
|
10
|
+
*
|
|
11
|
+
* - **El orden y el separador son formato**: que `es` escriba 25/09/2026,
|
|
12
|
+
* `en-US` 09/25/2026 y `de` 25.09.2026 sale del `locale` con `Intl`
|
|
13
|
+
* (`dateMask.ts`), no de una prop ni del catálogo. Una app en inglés
|
|
14
|
+
* mostrando fechas españolas las quiere en orden español.
|
|
15
|
+
* - **Las letras son idioma**: `aaaa` es «año», `yyyy` es *year* y `jjjj` es
|
|
16
|
+
* *Jahr*. Son la abreviatura de una palabra, así que se traducen — y por eso
|
|
17
|
+
* son cromo y salen del catálogo, como cualquier otro rótulo.
|
|
18
|
+
*
|
|
19
|
+
* Por eso el catálogo trae solo las tres letras y no la máscara montada: la
|
|
20
|
+
* máscara la arma el componente poniendo las letras en el orden del locale.
|
|
21
|
+
*/
|
|
22
|
+
export interface DatePickerMessages {
|
|
23
|
+
/** Nombre accesible del botón que abre el calendario. */
|
|
24
|
+
openCalendar: string;
|
|
25
|
+
/** Aviso de fecha incompleta o inexistente, anunciado con `role="alert"`. */
|
|
26
|
+
invalid: string;
|
|
27
|
+
/** Nombre accesible del panel del calendario (`role="dialog"`). */
|
|
28
|
+
calendar: string;
|
|
29
|
+
/**
|
|
30
|
+
* Las letras de la máscara, una por parte: `{ day: 'dd', month: 'mm',
|
|
31
|
+
* year: 'aaaa' }`. El orden y el separador NO están aquí: salen del
|
|
32
|
+
* `locale`.
|
|
33
|
+
*/
|
|
34
|
+
maskLetters: DateMaskLetters;
|
|
35
|
+
}
|
|
4
36
|
export interface DatePickerProps {
|
|
5
37
|
value?: Date | null;
|
|
6
38
|
/**
|
|
@@ -9,23 +41,28 @@ export interface DatePickerProps {
|
|
|
9
41
|
*/
|
|
10
42
|
onChange?: (date: Date | null) => void;
|
|
11
43
|
/**
|
|
12
|
-
* Pista dentro del campo.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
44
|
+
* Pista dentro del campo. Sin ella, la máscara del locale con las letras
|
|
45
|
+
* del catálogo (`dd/mm/aaaa`, `mm/dd/aaaa` en `en-US`). Es la anulación
|
|
46
|
+
* puntual: un campo que quiere decir otra cosa («Desde») la pasa.
|
|
15
47
|
*/
|
|
16
48
|
placeholder?: string;
|
|
17
49
|
/**
|
|
18
|
-
* Letras de la máscara del marcador de posición.
|
|
19
|
-
*
|
|
20
|
-
* son props: salen del `locale` con
|
|
50
|
+
* Letras de la máscara del marcador de posición. **Sin default**: sin
|
|
51
|
+
* ellas, salen de `datePicker.maskLetters` del `BrandMessagesProvider`. El
|
|
52
|
+
* orden y el separador no son props ni catálogo: salen del `locale` con
|
|
53
|
+
* `Intl`.
|
|
21
54
|
*/
|
|
22
55
|
maskLetters?: DateMaskLetters;
|
|
23
56
|
/**
|
|
24
|
-
* Mensaje cuando lo escrito no es una fecha completa y válida.
|
|
25
|
-
*
|
|
57
|
+
* Mensaje cuando lo escrito no es una fecha completa y válida. **Sin
|
|
58
|
+
* default**: sin él, sale de `datePicker.invalid` del
|
|
59
|
+
* `BrandMessagesProvider`; se anuncia con `role="alert"`.
|
|
26
60
|
*/
|
|
27
61
|
invalidMessage?: string;
|
|
28
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Nombre accesible del botón que abre el calendario. **Sin default**: sin
|
|
64
|
+
* él, sale de `datePicker.openCalendar` del `BrandMessagesProvider`.
|
|
65
|
+
*/
|
|
29
66
|
openCalendarLabel?: string;
|
|
30
67
|
minDate?: CalendarProps['minDate'];
|
|
31
68
|
maxDate?: CalendarProps['maxDate'];
|
|
@@ -43,29 +80,22 @@ export interface DatePickerProps {
|
|
|
43
80
|
'aria-describedby'?: string;
|
|
44
81
|
/** Nombre accesible cuando el control va suelto. En un campo lo nombra la etiqueta. */
|
|
45
82
|
'aria-label'?: string;
|
|
46
|
-
/** Nombre accesible del panel del calendario (`role="dialog"`). */
|
|
47
|
-
calendarLabel?: string;
|
|
48
83
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
84
|
+
* Nombre accesible del panel del calendario (`role="dialog"`). **Sin
|
|
85
|
+
* default**: sin él, sale de `datePicker.calendar` del
|
|
86
|
+
* `BrandMessagesProvider`. En un campo lo pone la etiqueta del campo, que es
|
|
87
|
+
* contenido de la pantalla y gana como cualquier prop.
|
|
51
88
|
*/
|
|
89
|
+
calendarLabel?: string;
|
|
90
|
+
/** aria-label del botón de mes anterior. Sin él, `calendar.previousMonth`. */
|
|
52
91
|
previousMonthLabel?: CalendarProps['previousMonthLabel'];
|
|
53
|
-
/**
|
|
54
|
-
* aria-label del botón de mes siguiente. Default: «Mes siguiente»
|
|
55
|
-
* (castellano).
|
|
56
|
-
*/
|
|
92
|
+
/** aria-label del botón de mes siguiente. Sin él, `calendar.nextMonth`. */
|
|
57
93
|
nextMonthLabel?: CalendarProps['nextMonthLabel'];
|
|
58
|
-
/**
|
|
59
|
-
* aria-label del botón de retroceso **en la vista de años**. Default: «Años
|
|
60
|
-
* anteriores» (castellano).
|
|
61
|
-
*/
|
|
94
|
+
/** aria-label del retroceso en la vista de años. Sin él, `calendar.previousYears`. */
|
|
62
95
|
previousYearsLabel?: CalendarProps['previousYearsLabel'];
|
|
63
|
-
/**
|
|
64
|
-
* aria-label del botón de avance en la vista de años. Default: «Años
|
|
65
|
-
* siguientes» (castellano).
|
|
66
|
-
*/
|
|
96
|
+
/** aria-label del avance en la vista de años. Sin él, `calendar.nextYears`. */
|
|
67
97
|
nextYearsLabel?: CalendarProps['nextYearsLabel'];
|
|
68
|
-
/** aria-label de la rejilla de años.
|
|
98
|
+
/** aria-label de la rejilla de años. Sin él, `calendar.yearGrid`. */
|
|
69
99
|
yearGridLabel?: CalendarProps['yearGridLabel'];
|
|
70
100
|
/**
|
|
71
101
|
* aria-label de la rejilla de días. Por defecto toma `calendarLabel`, que ya
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
export type DatePartName = 'day' | 'month' | 'year';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Letras de la máscara del marcador de posición, una por parte.
|
|
4
|
+
*
|
|
5
|
+
* **No hay juego por defecto, y es deliberado**: las letras se traducen
|
|
6
|
+
* (`aaaa` es «año», `yyyy` es *year*, `jjjj` es *Jahr*), así que salen del
|
|
7
|
+
* catálogo de la aplicación —`datePicker.maskLetters`— igual que cualquier
|
|
8
|
+
* otro rótulo. Lo que este módulo decide es el **orden** y el **separador**,
|
|
9
|
+
* que son formato y salen del `locale`.
|
|
10
|
+
*/
|
|
3
11
|
export interface DateMaskLetters {
|
|
4
12
|
day: string;
|
|
5
13
|
month: string;
|
|
6
14
|
year: string;
|
|
7
15
|
}
|
|
8
|
-
export declare const SPANISH_MASK_LETTERS: DateMaskLetters;
|
|
9
16
|
export interface DateMask {
|
|
10
17
|
/** Orden de las partes en ese locale, p. ej. `['day', 'month', 'year']`. */
|
|
11
18
|
order: DatePartName[];
|
|
@@ -33,29 +33,29 @@ export interface DateTimeFieldProps {
|
|
|
33
33
|
locale?: string;
|
|
34
34
|
/** Se añade DESPUÉS de las clases propias (el consumidor añade, no sustituye). */
|
|
35
35
|
className?: string;
|
|
36
|
-
/** Nombre accesible del panel del calendario.
|
|
36
|
+
/** Nombre accesible del panel del calendario. Sin él, la etiqueta del campo. */
|
|
37
37
|
calendarLabel?: DatePickerProps['calendarLabel'];
|
|
38
|
-
/** Nombre accesible del botón que abre el calendario.
|
|
38
|
+
/** Nombre accesible del botón que abre el calendario. Sin él, `datePicker.openCalendar`. */
|
|
39
39
|
openCalendarLabel?: DatePickerProps['openCalendarLabel'];
|
|
40
|
-
/** Mensaje de fecha incompleta del campo de texto.
|
|
40
|
+
/** Mensaje de fecha incompleta del campo de texto. Sin él, `datePicker.invalid`. */
|
|
41
41
|
invalidMessage?: DatePickerProps['invalidMessage'];
|
|
42
|
-
/** Letras de la máscara del marcador de posición.
|
|
42
|
+
/** Letras de la máscara del marcador de posición. Sin ellas, `datePicker.maskLetters`. */
|
|
43
43
|
maskLetters?: DatePickerProps['maskLetters'];
|
|
44
|
-
/** aria-label del botón de mes anterior
|
|
44
|
+
/** aria-label del botón de mes anterior. Sin él, `calendar.previousMonth`. */
|
|
45
45
|
previousMonthLabel?: DatePickerProps['previousMonthLabel'];
|
|
46
|
-
/** aria-label del botón de mes siguiente.
|
|
46
|
+
/** aria-label del botón de mes siguiente. Sin él, `calendar.nextMonth`. */
|
|
47
47
|
nextMonthLabel?: DatePickerProps['nextMonthLabel'];
|
|
48
|
-
/** aria-label del
|
|
48
|
+
/** aria-label del retroceso en la vista de años. Sin él, `calendar.previousYears`. */
|
|
49
49
|
previousYearsLabel?: DatePickerProps['previousYearsLabel'];
|
|
50
|
-
/** aria-label del
|
|
50
|
+
/** aria-label del avance en la vista de años. Sin él, `calendar.nextYears`. */
|
|
51
51
|
nextYearsLabel?: DatePickerProps['nextYearsLabel'];
|
|
52
|
-
/** aria-label de la rejilla de años.
|
|
52
|
+
/** aria-label de la rejilla de años. Sin él, `calendar.yearGrid`. */
|
|
53
53
|
yearGridLabel?: DatePickerProps['yearGridLabel'];
|
|
54
|
-
/** aria-label de la rejilla de días.
|
|
54
|
+
/** aria-label de la rejilla de días. Sin él, el nombre del panel. */
|
|
55
55
|
gridLabel?: DatePickerProps['gridLabel'];
|
|
56
|
-
/** aria-label del desplegable de horas.
|
|
56
|
+
/** aria-label del desplegable de horas. Sin él, `timeSelect.hours`. */
|
|
57
57
|
hoursLabel?: string;
|
|
58
|
-
/** aria-label del desplegable de minutos.
|
|
58
|
+
/** aria-label del desplegable de minutos. Sin él, `timeSelect.minutes`. */
|
|
59
59
|
minutesLabel?: string;
|
|
60
60
|
onChange?: (date: Date | null) => void;
|
|
61
61
|
/** Se llama al salir de cualquiera de los dos controles: el campo de fecha (un `<input>`) o los desplegables de hora (dos `<button>`). */
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import 'react-image-crop/dist/ReactCrop.css';
|
|
3
3
|
import './ImageCropDialog.css';
|
|
4
|
+
/**
|
|
5
|
+
* El cromo del recortador, y **solo el cromo**: lo que el diálogo dice por su
|
|
6
|
+
* cuenta mientras la imagen va y viene.
|
|
7
|
+
*
|
|
8
|
+
* Aquí se ve la distinción que gobierna la campaña entera. El título, el
|
|
9
|
+
* «Cancelar» y el «Guardar» **no** están en este espacio y siguen siendo props
|
|
10
|
+
* obligatorias sin valor por defecto: el diálogo no sabe qué se está
|
|
11
|
+
* recortando —una foto de perfil, un logo, la portada de un curso— ni qué pasa
|
|
12
|
+
* al confirmar, y eso es contenido de la pantalla que lo abre, no un rótulo
|
|
13
|
+
* del sistema. Lo que sí sabe es que la imagen puede tardar y puede fallar: el
|
|
14
|
+
* aviso de carga y el de error son suyos, valen igual en todas las pantallas y
|
|
15
|
+
* por eso salen del catálogo.
|
|
16
|
+
*/
|
|
17
|
+
export interface ImageCropDialogMessages {
|
|
18
|
+
/** Lo que se dice mientras la imagen se descarga y descodifica. Se anuncia y se ve. */
|
|
19
|
+
loading: string;
|
|
20
|
+
/** Lo que se dice cuando la imagen no se puede cargar. */
|
|
21
|
+
error: string;
|
|
22
|
+
}
|
|
4
23
|
export interface ImageCropDialogProps {
|
|
5
24
|
/** Object URL del fichero elegido; el diálogo está abierto mientras no sea null. */
|
|
6
25
|
sourceUrl: string | null;
|
|
@@ -16,16 +35,21 @@ export interface ImageCropDialogProps {
|
|
|
16
35
|
busy?: boolean;
|
|
17
36
|
cancelLabel: ReactNode;
|
|
18
37
|
confirmLabel: ReactNode;
|
|
19
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Etiqueta del botón de cierre del diálogo. Se reenvía **tal cual** al
|
|
40
|
+
* `Modal`, que todavía no lee del proveedor: mientras no se migre, sin esta
|
|
41
|
+
* prop el aspa sigue diciendo lo que diga `Modal`.
|
|
42
|
+
*/
|
|
20
43
|
closeLabel?: string;
|
|
21
44
|
/**
|
|
22
45
|
* Lo que se dice mientras la imagen se descarga y descodifica. Se anuncia y
|
|
23
|
-
* se ve.
|
|
46
|
+
* se ve. **Sin default**: sin él, sale de `imageCropDialog.loading` del
|
|
47
|
+
* `BrandMessagesProvider`.
|
|
24
48
|
*/
|
|
25
49
|
loadingLabel?: string;
|
|
26
50
|
/**
|
|
27
|
-
* Lo que se dice cuando la imagen no se puede cargar.
|
|
28
|
-
*
|
|
51
|
+
* Lo que se dice cuando la imagen no se puede cargar. **Sin default**: sin
|
|
52
|
+
* él, sale de `imageCropDialog.error` del `BrandMessagesProvider`.
|
|
29
53
|
*/
|
|
30
54
|
errorMessage?: string;
|
|
31
55
|
onConfirm: (blob: Blob) => void | Promise<void>;
|
|
@@ -29,9 +29,16 @@ export interface TimeFieldProps {
|
|
|
29
29
|
helperText?: string;
|
|
30
30
|
/** Se añade DESPUÉS de las clases propias (el consumidor añade, no sustituye). */
|
|
31
31
|
className?: string;
|
|
32
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* aria-label del desplegable de horas. **Sin default**: sin él, el texto
|
|
34
|
+
* sale de `timeSelect.hours` del `BrandMessagesProvider`, que el
|
|
35
|
+
* `TimeSelect` de dentro lee por contexto.
|
|
36
|
+
*/
|
|
33
37
|
hoursLabel?: string;
|
|
34
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* aria-label del desplegable de minutos. **Sin default**: sin él, sale de
|
|
40
|
+
* `timeSelect.minutes` del `BrandMessagesProvider`.
|
|
41
|
+
*/
|
|
35
42
|
minutesLabel?: string;
|
|
36
43
|
onChange?: (value: TimeValue) => void;
|
|
37
44
|
onBlur?: React.FocusEventHandler<HTMLButtonElement>;
|
|
@@ -51,10 +51,14 @@ export interface CalendarMonthNavOptions {
|
|
|
51
51
|
/**
|
|
52
52
|
* Nombre accesible del botón de retroceso. Depende de la vista: «Mes
|
|
53
53
|
* anterior» sobre la rejilla de días, «Años anteriores» sobre la de años.
|
|
54
|
+
*
|
|
55
|
+
* Opcional porque sin `navigable` no se pinta ningún botón: quien la monta
|
|
56
|
+
* lee el texto de su catálogo **solo cuando hay flechas**, y un calendario
|
|
57
|
+
* estático no exige un texto que nadie va a ver.
|
|
54
58
|
*/
|
|
55
|
-
previousLabel
|
|
59
|
+
previousLabel?: string;
|
|
56
60
|
/** Nombre accesible del botón de avance, también según la vista. */
|
|
57
|
-
nextLabel
|
|
61
|
+
nextLabel?: string;
|
|
58
62
|
prevDisabled?: boolean;
|
|
59
63
|
nextDisabled?: boolean;
|
|
60
64
|
onPrev: () => void;
|
package/dist/avatar-upload.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import './avatar-upload.css';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { n } from "./
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { n as e } from "./_shared/brandmessagescontext.js";
|
|
4
|
+
import { Icon as t } from "./icon.js";
|
|
5
|
+
import { VisuallyHidden as n } from "./visually-hidden.js";
|
|
6
|
+
import { n as r } from "./_shared/form-size.js";
|
|
7
|
+
import { Button as i } from "./button.js";
|
|
8
|
+
import { Avatar as a } from "./avatar.js";
|
|
8
9
|
import { ErrorText as ee } from "./error-text.js";
|
|
9
|
-
import {
|
|
10
|
-
import { t as
|
|
11
|
-
import { t as
|
|
12
|
-
import { useCallback as
|
|
10
|
+
import { i as te, n as ne, r as o, t as re } from "./_shared/validate.js";
|
|
11
|
+
import { t as ie } from "./_shared/env.js";
|
|
12
|
+
import { t as ae } from "./_shared/imagecropdialog.js";
|
|
13
|
+
import { useCallback as oe, useEffect as s, useId as se, useRef as c, useState as l } from "react";
|
|
13
14
|
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
14
15
|
//#region src/stories/molecules/AvatarUpload/AvatarUpload.tsx
|
|
15
|
-
var
|
|
16
|
+
var ce = {
|
|
16
17
|
sm: "2xl",
|
|
17
18
|
md: "3xl",
|
|
18
19
|
lg: "4xl"
|
|
@@ -21,92 +22,94 @@ var ae = {
|
|
|
21
22
|
md: "lg",
|
|
22
23
|
lg: "xl"
|
|
23
24
|
};
|
|
24
|
-
function
|
|
25
|
-
return e.split(",").map((e) => e.trim()).filter(Boolean).map((e) => e.startsWith(".") ? e.slice(1) : e.split("/")[1] ?? e).map((e) => e.toUpperCase())
|
|
25
|
+
function le(e, t) {
|
|
26
|
+
return o(e.split(",").map((e) => e.trim()).filter(Boolean).map((e) => e.startsWith(".") ? e.slice(1) : e.split("/")[1] ?? e).map((e) => e.toUpperCase()), t);
|
|
26
27
|
}
|
|
27
|
-
function
|
|
28
|
-
let
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}, [
|
|
32
|
-
|
|
33
|
-
}, []),
|
|
34
|
-
if (
|
|
28
|
+
function p({ src: o, name: p, alt: m, shape: h = "circle", size: ue, accept: g = "image/jpeg,image/png,image/webp", maxSize: _, outputMimeType: de = "image/jpeg", outputSize: v, disabled: fe = !1, busy: y = !1, errorMessage: b, onChange: pe, onSelect: x, onError: S, subject: me, buttonLabel: he, buttonAccessibleLabel: ge, hintLabel: _e, formatsLabel: ve, locale: C = re, maxSizeHint: ye, invalidTypeError: w, tooLargeError: T, dropActiveMessage: be, dropHintLabel: xe, cropTitle: Se, cropDescription: Ce, cropCancelLabel: E, cropConfirmLabel: D, cropCloseLabel: O, cropLoadingLabel: k, cropErrorMessage: A, className: we }) {
|
|
29
|
+
let j = e("avatarUpload"), M = r(ue), N = c(null), P = c(null), [F, I] = l(null), [L, R] = l(!1), [z, B] = l(!1), [Te, V] = l(null), H = se(), U = `${H}-hint`, W = `${H}-error`, G = j("subject", me), K = ve ?? le(g, C), q = _e ?? [K, _ === void 0 ? null : j("maxSize", ye)(ne(_, C))].filter(Boolean).join(" · "), J = Te ?? b, Y = fe || y, X = j("button", he), Z = ge ?? j("buttonFor")(G);
|
|
30
|
+
ie() && !Z.toLowerCase().includes(X.toLowerCase()) && console.warn(`[AvatarUpload] El nombre accesible del botón ("${Z}") no contiene su texto visible ("${X}"). WCAG 2.5.3 (Label in Name) lo exige: quien navega por voz dice lo que ve, y con estos textos no encontraría el control.`), s(() => {
|
|
31
|
+
P.current = F;
|
|
32
|
+
}, [F]), s(() => () => {
|
|
33
|
+
P.current && URL.revokeObjectURL(P.current.url);
|
|
34
|
+
}, []), s(() => {
|
|
35
|
+
if (Y) return;
|
|
35
36
|
let e = 0, t = (e) => Array.from(e.dataTransfer?.types ?? []).includes("Files"), n = (n) => {
|
|
36
|
-
t(n) && (e += 1,
|
|
37
|
+
t(n) && (e += 1, R(!0));
|
|
37
38
|
}, r = () => {
|
|
38
|
-
e = Math.max(0, e - 1), e === 0 &&
|
|
39
|
+
e = Math.max(0, e - 1), e === 0 && R(!1);
|
|
39
40
|
}, i = () => {
|
|
40
|
-
e = 0,
|
|
41
|
+
e = 0, R(!1);
|
|
41
42
|
};
|
|
42
43
|
return window.addEventListener("dragenter", n), window.addEventListener("dragleave", r), window.addEventListener("drop", i), window.addEventListener("dragend", i), () => {
|
|
43
|
-
window.removeEventListener("dragenter", n), window.removeEventListener("dragleave", r), window.removeEventListener("drop", i), window.removeEventListener("dragend", i),
|
|
44
|
+
window.removeEventListener("dragenter", n), window.removeEventListener("dragleave", r), window.removeEventListener("drop", i), window.removeEventListener("dragend", i), R(!1);
|
|
44
45
|
};
|
|
45
|
-
}, [
|
|
46
|
-
let
|
|
47
|
-
let t = te(e, _,
|
|
46
|
+
}, [Y]);
|
|
47
|
+
let Q = oe((e) => {
|
|
48
|
+
let t = te(e, g, _, j("tooLarge", T), j("invalidType", w)(K), C);
|
|
48
49
|
if (t) {
|
|
49
|
-
|
|
50
|
+
V(t), S?.(t);
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
52
|
-
|
|
53
|
+
V(null), x?.(e), I({
|
|
53
54
|
url: URL.createObjectURL(e),
|
|
54
55
|
file: e
|
|
55
56
|
});
|
|
56
57
|
}, [
|
|
58
|
+
g,
|
|
57
59
|
_,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
E,
|
|
61
|
-
J,
|
|
60
|
+
j,
|
|
61
|
+
T,
|
|
62
62
|
w,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
K,
|
|
64
|
+
C,
|
|
65
|
+
S,
|
|
66
|
+
x
|
|
67
|
+
]), Ee = () => {
|
|
68
|
+
F && URL.revokeObjectURL(F.url), I(null);
|
|
69
|
+
}, De = async (e) => {
|
|
70
|
+
F && await pe(e, F.file);
|
|
71
|
+
}, $ = xe ?? j("dropHint")(G);
|
|
69
72
|
return /* @__PURE__ */ d("div", {
|
|
70
73
|
className: [
|
|
71
74
|
"avatar-upload",
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
h === "square" ? "avatar-upload--square" : "",
|
|
76
|
+
L ? "avatar-upload--armed" : "",
|
|
77
|
+
z ? "avatar-upload--over" : "",
|
|
78
|
+
Y ? "avatar-upload--inert" : "",
|
|
79
|
+
we ?? ""
|
|
77
80
|
].filter(Boolean).join(" "),
|
|
78
81
|
children: [
|
|
79
82
|
/* @__PURE__ */ d("div", {
|
|
80
83
|
className: "avatar-upload__target",
|
|
81
84
|
onClick: () => {
|
|
82
|
-
|
|
85
|
+
Y || N.current?.click();
|
|
83
86
|
},
|
|
84
87
|
onDragEnter: (e) => {
|
|
85
|
-
e.preventDefault(),
|
|
88
|
+
e.preventDefault(), Y || B(!0);
|
|
86
89
|
},
|
|
87
90
|
onDragOver: (e) => {
|
|
88
|
-
e.preventDefault(), !
|
|
91
|
+
e.preventDefault(), !Y && (e.dataTransfer.dropEffect = "copy", B(!0));
|
|
89
92
|
},
|
|
90
93
|
onDragLeave: (e) => {
|
|
91
|
-
e.currentTarget.contains(e.relatedTarget) ||
|
|
94
|
+
e.currentTarget.contains(e.relatedTarget) || B(!1);
|
|
92
95
|
},
|
|
93
96
|
onDrop: (e) => {
|
|
94
|
-
if (e.preventDefault(),
|
|
97
|
+
if (e.preventDefault(), B(!1), R(!1), Y) return;
|
|
95
98
|
let t = e.dataTransfer.files?.[0];
|
|
96
|
-
t &&
|
|
99
|
+
t && Q(t);
|
|
97
100
|
},
|
|
98
|
-
children: [/* @__PURE__ */ u(
|
|
99
|
-
src:
|
|
100
|
-
name:
|
|
101
|
-
...
|
|
102
|
-
shape:
|
|
103
|
-
size:
|
|
101
|
+
children: [/* @__PURE__ */ u(a, {
|
|
102
|
+
src: o ?? void 0,
|
|
103
|
+
name: p,
|
|
104
|
+
...m === void 0 ? {} : { alt: m },
|
|
105
|
+
shape: h,
|
|
106
|
+
size: ce[M]
|
|
104
107
|
}), /* @__PURE__ */ u("span", {
|
|
105
108
|
className: "avatar-upload__overlay",
|
|
106
109
|
"aria-hidden": "true",
|
|
107
|
-
children: /* @__PURE__ */ u(
|
|
110
|
+
children: /* @__PURE__ */ u(t, {
|
|
108
111
|
name: "upload",
|
|
109
|
-
size: f[
|
|
112
|
+
size: f[M]
|
|
110
113
|
})
|
|
111
114
|
})]
|
|
112
115
|
}),
|
|
@@ -114,63 +117,63 @@ function m({ src: m, name: oe, alt: h, shape: g = "circle", size: se, accept: _
|
|
|
114
117
|
className: "avatar-upload__body",
|
|
115
118
|
children: [
|
|
116
119
|
/* @__PURE__ */ u("input", {
|
|
117
|
-
ref:
|
|
120
|
+
ref: N,
|
|
118
121
|
type: "file",
|
|
119
122
|
className: "avatar-upload__input",
|
|
120
|
-
accept:
|
|
123
|
+
accept: g,
|
|
121
124
|
tabIndex: -1,
|
|
122
125
|
"aria-hidden": "true",
|
|
123
|
-
disabled:
|
|
126
|
+
disabled: Y,
|
|
124
127
|
onChange: (e) => {
|
|
125
128
|
let t = e.target.files?.[0];
|
|
126
|
-
t &&
|
|
129
|
+
t && Q(t), e.target.value = "";
|
|
127
130
|
}
|
|
128
131
|
}),
|
|
129
|
-
/* @__PURE__ */ u(
|
|
132
|
+
/* @__PURE__ */ u(i, {
|
|
130
133
|
variant: "outline",
|
|
131
|
-
size:
|
|
132
|
-
disabled:
|
|
133
|
-
onClick: () =>
|
|
134
|
-
...
|
|
135
|
-
"aria-describedby": [
|
|
136
|
-
children:
|
|
134
|
+
size: M,
|
|
135
|
+
disabled: Y,
|
|
136
|
+
onClick: () => N.current?.click(),
|
|
137
|
+
...Z === X ? {} : { "aria-label": Z },
|
|
138
|
+
"aria-describedby": [q ? U : null, J ? W : null].filter(Boolean).join(" ") || void 0,
|
|
139
|
+
children: X
|
|
137
140
|
}),
|
|
138
|
-
|
|
139
|
-
id:
|
|
140
|
-
children:
|
|
141
|
+
q && /* @__PURE__ */ u(n, {
|
|
142
|
+
id: U,
|
|
143
|
+
children: q
|
|
141
144
|
}),
|
|
142
|
-
|
|
145
|
+
$ && /* @__PURE__ */ u("span", {
|
|
143
146
|
className: "avatar-upload__hint",
|
|
144
|
-
children:
|
|
147
|
+
children: $
|
|
145
148
|
}),
|
|
146
|
-
|
|
147
|
-
id:
|
|
148
|
-
children:
|
|
149
|
+
J && /* @__PURE__ */ u(ee, {
|
|
150
|
+
id: W,
|
|
151
|
+
children: J
|
|
149
152
|
})
|
|
150
153
|
]
|
|
151
154
|
}),
|
|
152
|
-
/* @__PURE__ */ u(
|
|
155
|
+
/* @__PURE__ */ u(n, {
|
|
153
156
|
role: "status",
|
|
154
|
-
children:
|
|
157
|
+
children: L ? be ?? j("dropActive")(G) : ""
|
|
155
158
|
}),
|
|
156
|
-
/* @__PURE__ */ u(
|
|
157
|
-
sourceUrl:
|
|
158
|
-
title:
|
|
159
|
-
description:
|
|
160
|
-
circularCrop:
|
|
161
|
-
outputMimeType:
|
|
162
|
-
...
|
|
163
|
-
busy:
|
|
164
|
-
cancelLabel:
|
|
165
|
-
confirmLabel: j,
|
|
166
|
-
closeLabel:
|
|
167
|
-
...
|
|
168
|
-
...
|
|
169
|
-
onConfirm:
|
|
170
|
-
onClose:
|
|
159
|
+
/* @__PURE__ */ u(ae, {
|
|
160
|
+
sourceUrl: F?.url ?? null,
|
|
161
|
+
title: Se,
|
|
162
|
+
description: Ce,
|
|
163
|
+
circularCrop: h === "circle",
|
|
164
|
+
outputMimeType: de,
|
|
165
|
+
...v === void 0 ? {} : { outputSize: v },
|
|
166
|
+
busy: y,
|
|
167
|
+
cancelLabel: E ?? j("cropCancel"),
|
|
168
|
+
confirmLabel: D ?? j("cropConfirm"),
|
|
169
|
+
...O === void 0 ? {} : { closeLabel: O },
|
|
170
|
+
...k === void 0 ? {} : { loadingLabel: k },
|
|
171
|
+
...A === void 0 ? {} : { errorMessage: A },
|
|
172
|
+
onConfirm: De,
|
|
173
|
+
onClose: Ee
|
|
171
174
|
})
|
|
172
175
|
]
|
|
173
176
|
});
|
|
174
177
|
}
|
|
175
178
|
//#endregion
|
|
176
|
-
export {
|
|
179
|
+
export { p as AvatarUpload };
|