@soyfri/shared-library 4.1.0 → 4.1.1-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.
- package/README.md +116 -4
- package/chunks/{StatusMessage-CV1xnzeu.cjs → StatusMessage-Bl_E83nN.cjs} +15 -8
- package/chunks/StatusMessage-Bl_E83nN.cjs.map +1 -0
- package/chunks/{StatusMessage-B0oqiu3w.mjs → StatusMessage-Pa5IutUR.mjs} +17 -10
- package/chunks/StatusMessage-Pa5IutUR.mjs.map +1 -0
- package/components/StatusMessage/StatusMessageContext.d.cts +3 -1
- package/components/StatusMessage/StatusMessageContext.d.mts +3 -1
- package/components/StatusMessage/StatusMessageContext.d.ts +3 -1
- package/components/StatusMessage/StatusMessageRenderer.d.cts +28 -0
- package/components/StatusMessage/StatusMessageRenderer.d.mts +28 -0
- package/components/StatusMessage/StatusMessageRenderer.d.ts +28 -0
- package/components/StatusMessage/index.cjs +67 -4
- package/components/StatusMessage/index.cjs.map +1 -1
- package/components/StatusMessage/index.d.cts +3 -0
- package/components/StatusMessage/index.d.mts +3 -0
- package/components/StatusMessage/index.d.ts +3 -0
- package/components/StatusMessage/index.mjs +70 -7
- package/components/StatusMessage/index.mjs.map +1 -1
- package/components/StatusMessage/useStatusMessage.d.cts +36 -0
- package/components/StatusMessage/useStatusMessage.d.mts +36 -0
- package/components/StatusMessage/useStatusMessage.d.ts +36 -0
- package/index.cjs +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
- package/chunks/StatusMessage-B0oqiu3w.mjs.map +0 -1
- package/chunks/StatusMessage-CV1xnzeu.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -267,14 +267,126 @@ const { copy, CopyMessage } = useClipboard({ message: 'Copiado', severity: 'succ
|
|
|
267
267
|
|
|
268
268
|
```bash
|
|
269
269
|
npm install
|
|
270
|
-
npm run dev # build
|
|
271
|
-
npm run storybook # Storybook en :6006 (documentación interactiva
|
|
272
|
-
npm run build # build de producción (vite
|
|
270
|
+
npm run dev # vite build --mode lib --watch (rebuild incremental)
|
|
271
|
+
npm run storybook # Storybook en :6006 (documentación interactiva)
|
|
272
|
+
npm run build # build de producción (vite; el postbuild arma el dist/package.json)
|
|
273
|
+
npm test # vitest run: levanta chromium y corre el play de cada story
|
|
274
|
+
npm run lint # eslint (flat config v9)
|
|
273
275
|
```
|
|
274
276
|
|
|
277
|
+
Las **stories son los tests**: Vitest corre las stories de Storybook en un browser real
|
|
278
|
+
(Playwright, chromium headless). No hay suite de tests fuera de las stories.
|
|
279
|
+
|
|
280
|
+
## Revisión de PRs con `@claude`
|
|
281
|
+
|
|
282
|
+
Reemplaza el review de Copilot. Claude **no revisa solo**: responde cuando alguien lo menciona en un comentario de un PR, de un issue o de un review. Si nadie lo menciona, no consume nada.
|
|
283
|
+
|
|
284
|
+
### Cómo se pide
|
|
285
|
+
|
|
286
|
+
La mención es el disparador; lo que escribís después es la instrucción. Cuanto
|
|
287
|
+
más concreta, mejor sale el review.
|
|
288
|
+
|
|
289
|
+
```text
|
|
290
|
+
@claude
|
|
291
|
+
```
|
|
292
|
+
Review general del PR. Es lo más parecido a Copilot y **lo que peor rinde en un
|
|
293
|
+
PR grande**: lee una parte y opina en general.
|
|
294
|
+
|
|
295
|
+
```text
|
|
296
|
+
@claude ¿el exports map de build.js cubre todos los subpaths que genera vite.config.js?
|
|
297
|
+
```
|
|
298
|
+
Contesta esa pregunta concreta. Es donde mejor rinde.
|
|
299
|
+
|
|
300
|
+
```text
|
|
301
|
+
@claude revisá si este PR rompe algún contrato público: props que desaparecen,
|
|
302
|
+
componentes nuevos que faltan en src/index.ts, dependencias nuevas que no estén
|
|
303
|
+
en peerDependencies.
|
|
304
|
+
```
|
|
305
|
+
Un review acotado a un eje. Podés pedirle varios, de a uno por comentario.
|
|
306
|
+
|
|
307
|
+
```text
|
|
308
|
+
@claude ¿este componente re-renderiza de más? Mirá los sx y los callbacks inline.
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
```text
|
|
312
|
+
@claude ¿cómo agregarías el forwardRef que falta en Gallery?
|
|
313
|
+
```
|
|
314
|
+
Te propone el cambio, pero **no lo aplica**: el workflow le da `contents: read`,
|
|
315
|
+
así que puede leer todo el repo y no puede pushear nada. Quien edita seguís siendo vos.
|
|
316
|
+
|
|
317
|
+
### Cómo pedirlo en un PR grande
|
|
318
|
+
|
|
319
|
+
En un PR de cien archivos no le pidas "revisá el PR". Tiene un tope de turnos y
|
|
320
|
+
se le va a ir leyendo archivos sin llegar a lo que importa. Dos formas de
|
|
321
|
+
aprovecharlo:
|
|
322
|
+
|
|
323
|
+
1. **Inline, sobre la línea del diff.** Es la mejor: sabe exactamente de qué
|
|
324
|
+
línea le hablás, no tiene que buscarla, y el review sale enfocado y barato.
|
|
325
|
+
2. **Un eje por comentario.** Uno para contratos públicos, otro para
|
|
326
|
+
re-renders, otro para los tests que faltan. Tres comentarios acotados dan
|
|
327
|
+
mucho mejor resultado que uno que pide todo junto.
|
|
328
|
+
|
|
329
|
+
También podés acotarlo vos: *"revisá sólo `src/components/Table/`"*.
|
|
330
|
+
|
|
331
|
+
### Dónde comentar
|
|
332
|
+
|
|
333
|
+
- **En el hilo del PR** → contexto del PR entero.
|
|
334
|
+
- **Inline, sobre una línea del diff** → sabe exactamente de qué línea le
|
|
335
|
+
hablás. Para algo puntual es mejor y mucho más barato.
|
|
336
|
+
|
|
337
|
+
### Qué revisa
|
|
338
|
+
|
|
339
|
+
El checklist vive en [`.github/claude-review.md`](.github/claude-review.md) y se
|
|
340
|
+
edita ahí, sin tocar el workflow. Hoy cubre, en orden de prioridad:
|
|
341
|
+
|
|
342
|
+
1. **Contratos públicos** — props que desaparecen o pasan a requeridas,
|
|
343
|
+
componentes nuevos que faltan en la lista manual de `src/index.ts`, los
|
|
344
|
+
subpaths, el `exports` map, `mui.ts` como pass-through, la versión sin
|
|
345
|
+
bumpear, y **dependencias nuevas que no estén en `peerDependencies`** (se
|
|
346
|
+
bundlearían dentro del paquete y el consumidor terminaría con dos copias).
|
|
347
|
+
2. **Tests** — no los corre; avisa si faltan. Stories ausentes, `play` sin sus
|
|
348
|
+
dos `step`, queries que no van por rol, un `action` usado como si fuera un spy.
|
|
349
|
+
3. **Re-renders** — `sx` y callbacks inline, deps mal puestas, estado demasiado
|
|
350
|
+
arriba, value de Context reconstruido en cada render.
|
|
351
|
+
4. **Legibilidad**, **genéricos** donde el tipo se está perdiendo, y
|
|
352
|
+
**accesibilidad** más allá de lo que ya ve el lint.
|
|
353
|
+
5. **Código sin usar** — verificando antes con `grep`, porque en un paquete
|
|
354
|
+
publicado algo puede estar exportado a propósito.
|
|
355
|
+
|
|
356
|
+
**No corre el build ni los tests.** Sería lento y `component-tests.yml` ya es el
|
|
357
|
+
gate del PR: en vez de correrlos, lee cómo les fue y lo reporta.
|
|
358
|
+
|
|
359
|
+
### Qué esperar
|
|
360
|
+
|
|
361
|
+
Aparece un comentario de `github-actions[bot]` que se va actualizando mientras
|
|
362
|
+
trabaja. Podés seguir el hilo respondiéndole con otro `@claude`.
|
|
363
|
+
|
|
364
|
+
Arranca con un resumen de qué hace el PR y después separa lo bloqueante de lo
|
|
365
|
+
que es sugerencia. Va a encontrar cosas reales y también falsos positivos, los
|
|
366
|
+
dos con el mismo tono de seguridad. Es un primer lector, no una autoridad: quien
|
|
367
|
+
decide sigue siendo quien revisa.
|
|
368
|
+
|
|
369
|
+
### Qué lee
|
|
370
|
+
|
|
371
|
+
El `CLAUDE.md` de este repo y el checklist de [`.github/claude-review.md`](.github/claude-review.md) en cada corrida, así que aplica las convenciones propias (`mui.ts` como pass-through, `forwardRef`, props que extienden las de MUI, stories como tests). El `~/.claude/CLAUDE.md` de cada dev **no** viaja al runner — por eso el idioma y el puntero a esos dos archivos van fijados en `claude_args` dentro del workflow.
|
|
372
|
+
|
|
373
|
+
### Configuración
|
|
374
|
+
|
|
375
|
+
Dos archivos: `.github/workflows/claude.yml` (el workflow) y [`.github/claude-review.md`](.github/claude-review.md) (**qué revisa**). Para cambiar el criterio del review editá el segundo — el YAML no se toca.
|
|
376
|
+
|
|
377
|
+
Lo único que hay que cargar es el secret `CLAUDE_CODE_OAUTH_TOKEN` (generado con `claude setup-token`). Ese token factura contra la suscripción de quien lo generó, no genera cargo por API: no hay ninguna `ANTHROPIC_API_KEY` en el repo. Los minutos de Actions sí salen de la cuota de la organización.
|
|
378
|
+
|
|
379
|
+
Para GitHub se usa el `GITHUB_TOKEN` que Actions provee en cada corrida, no la [Claude GitHub App](https://github.com/apps/claude): `soyfrii` exige aprobación de un owner para instalar apps de terceros. A cambio, los comentarios los firma `github-actions[bot]` y un commit hecho por Claude no dispara los otros workflows. Si la App oficial se aprueba algún día, se borra la línea `github_token` y pasa a firmar como `claude[bot]`.
|
|
380
|
+
|
|
381
|
+
**Solo lectura sobre el código.** `contents: read` hace imposible que Claude pushee un commit — no es una convención, GitHub le rechaza el push. `pull-requests` e `issues` en `write` no permiten tocar código: son los que le dejan escribir el comentario con el review. Además, `--disallowedTools` le bloquea las herramientas de edición de archivos, y el `--allowedTools` sólo le habilita comandos de lectura (`ls`, `cat`, `head`, `tail`, `wc`, `find`, `grep`, `git log/diff/show` y `gh` para leer el PR y sus checks) — sin esa lista no podía recorrer el repo para responder una pregunta concreta. Esos comandos se **suman** a las herramientas base de la action, no las reemplazan.
|
|
382
|
+
|
|
383
|
+
Topes de costo: `timeout-minutes: 15`, `--max-turns 40`, `concurrency` con `cancel-in-progress`, un `if:` que evita levantar un runner por comentarios que no mencionan `@claude`, y el hecho de que no corra el build ni los tests.
|
|
384
|
+
|
|
385
|
+
Como el repo es **privado**, sólo colaboradores pueden comentar y por lo tanto disparar una corrida. Si esto se replica a un repo público hay que agregar un filtro por `author_association`, o cualquiera podría consumir la suscripción.
|
|
386
|
+
|
|
275
387
|
## Tecnologías
|
|
276
388
|
|
|
277
|
-
React 18/19 · Material UI v7 ·
|
|
389
|
+
React 18/19 · Material UI v7 · MUI X v8 (date pickers) · Emotion · react-hook-form 7 · TypeScript 5.8 · Storybook 10 · Vite 7 · Vitest 4 + Playwright.
|
|
278
390
|
|
|
279
391
|
## Licencia
|
|
280
392
|
|
|
@@ -7,6 +7,7 @@ const mergeSx = require("./mergeSx-Dbccoo_H.cjs");
|
|
|
7
7
|
const iconsMaterial = require("@mui/icons-material");
|
|
8
8
|
const StatusMessage = React.forwardRef(
|
|
9
9
|
function StatusMessage2(inProps, ref) {
|
|
10
|
+
var _a;
|
|
10
11
|
const props = styles.useThemeProps({ props: inProps, name: "FriStatusMessage" });
|
|
11
12
|
const {
|
|
12
13
|
title,
|
|
@@ -27,8 +28,13 @@ const StatusMessage = React.forwardRef(
|
|
|
27
28
|
if (!isControlled) setInternalOpen(false);
|
|
28
29
|
close == null ? void 0 : close();
|
|
29
30
|
};
|
|
30
|
-
const
|
|
31
|
-
|
|
31
|
+
const MESSAGE_TYPES = {
|
|
32
|
+
success: { severity: "success", Icon: iconsMaterial.CheckCircleOutline, color: "success.main" },
|
|
33
|
+
danger: { severity: "error", Icon: iconsMaterial.ErrorOutline, color: "error.main" },
|
|
34
|
+
warning: { severity: "warning", Icon: iconsMaterial.WarningAmber, color: "warning.main" }
|
|
35
|
+
};
|
|
36
|
+
const DEFAULT_MESSAGE_TYPE = "success";
|
|
37
|
+
const { severity, Icon, color } = (_a = MESSAGE_TYPES[messageType]) != null ? _a : MESSAGE_TYPES[DEFAULT_MESSAGE_TYPE];
|
|
32
38
|
if (!description) return null;
|
|
33
39
|
if (!isOpen) return null;
|
|
34
40
|
if (displayType === "modal") {
|
|
@@ -61,7 +67,7 @@ const StatusMessage = React.forwardRef(
|
|
|
61
67
|
gap: 2
|
|
62
68
|
},
|
|
63
69
|
children: [
|
|
64
|
-
/* @__PURE__ */ jsxRuntime.jsx(material.Box, { sx: { mb: 2 }, children:
|
|
70
|
+
/* @__PURE__ */ jsxRuntime.jsx(material.Box, { sx: { mb: 2 }, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { sx: { fontSize: 64, color } }) }),
|
|
65
71
|
title && /* @__PURE__ */ jsxRuntime.jsx(
|
|
66
72
|
material.Typography,
|
|
67
73
|
{
|
|
@@ -76,7 +82,7 @@ const StatusMessage = React.forwardRef(
|
|
|
76
82
|
]
|
|
77
83
|
}
|
|
78
84
|
),
|
|
79
|
-
/* @__PURE__ */ jsxRuntime.jsx(material.DialogActions, { sx: { justifyContent: "center", p: 2 }, children: /* @__PURE__ */ jsxRuntime.jsx(material.Button, { onClick: handleClose, variant: "contained", color:
|
|
85
|
+
/* @__PURE__ */ jsxRuntime.jsx(material.DialogActions, { sx: { justifyContent: "center", p: 2 }, children: /* @__PURE__ */ jsxRuntime.jsx(material.Button, { onClick: handleClose, variant: "contained", color: severity, children: "Aceptar" }) })
|
|
80
86
|
]
|
|
81
87
|
}
|
|
82
88
|
);
|
|
@@ -86,16 +92,17 @@ const StatusMessage = React.forwardRef(
|
|
|
86
92
|
{
|
|
87
93
|
ref,
|
|
88
94
|
className,
|
|
89
|
-
severity
|
|
95
|
+
severity,
|
|
90
96
|
sx: mergeSx.mergeSx({ mb: 2, mt: 2 }, sx),
|
|
97
|
+
variant: "outlined",
|
|
91
98
|
onClose: close !== void 0 ? handleClose : void 0,
|
|
92
99
|
children: [
|
|
93
|
-
title && /* @__PURE__ */ jsxRuntime.jsx(material.
|
|
94
|
-
|
|
100
|
+
title && /* @__PURE__ */ jsxRuntime.jsx(material.AlertTitle, { children: title }),
|
|
101
|
+
description
|
|
95
102
|
]
|
|
96
103
|
}
|
|
97
104
|
);
|
|
98
105
|
}
|
|
99
106
|
);
|
|
100
107
|
exports.StatusMessage = StatusMessage;
|
|
101
|
-
//# sourceMappingURL=StatusMessage-
|
|
108
|
+
//# sourceMappingURL=StatusMessage-Bl_E83nN.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusMessage-Bl_E83nN.cjs","sources":["../../src/components/StatusMessage/StatusMessage.tsx"],"sourcesContent":["import { forwardRef, useId, useState } from 'react';\nimport {\n Alert,\n Box,\n Typography,\n Dialog,\n DialogContent,\n DialogActions,\n Button,\n AlertTitle,\n} from '@mui/material';\nimport { useThemeProps, type SxProps, type Theme } from '@mui/material/styles';\n\nimport { mergeSx } from '../_shared/mergeSx';\nimport {\n ErrorOutline as ErrorOutlineIcon,\n CheckCircleOutline as CheckCircleOutlineIcon,\n WarningAmber as WarningAmberIcon,\n} from '@mui/icons-material';\n\nexport interface StatusMessageProps {\n /** Título del mensaje. */\n title?: string;\n /** Descripción/contenido detallado. Requerido para que el componente renderice. */\n description?: string;\n /** Tipo de mensaje (controla color + icono). `danger` mapea a `error` de MUI. */\n messageType?: 'success' | 'danger' | 'warning';\n /** Forma de presentación: alerta inline o modal. Default: `'alert'`. */\n displayType?: 'alert' | 'modal';\n /** Callback al cerrar. Si se omite, no se muestra botón de cerrar. */\n close?: () => void;\n /**\n * Controla visibilidad. Si se omite, el componente maneja su propio\n * state (se oculta solo al llamar `close`). Si se pasa, queda controlled\n * y el consumer es responsable de actualizarlo.\n */\n open?: boolean;\n /**\n * sx del nodo raíz: el `Alert` en modo `alert`, el `Dialog` en modo `modal`.\n * Antes el componente no aceptaba ni `sx` ni `className`, así que ajustar su\n * separación desde el call-site era imposible.\n */\n sx?: SxProps<Theme>;\n className?: string;\n}\n\n/**\n * Mensaje de éxito / error / advertencia en forma de alerta inline o modal.\n *\n * - **Uncontrolled**: sin pasar `open`, el componente maneja su propia\n * visibilidad. Al llamar `close`, se oculta automáticamente.\n * - **Controlled**: pasando `open`, el consumer decide cuándo mostrar/ocultar.\n */\nexport const StatusMessage = forwardRef<HTMLDivElement, StatusMessageProps>(\n function StatusMessage(inProps, ref) {\n const props = useThemeProps({ props: inProps, name: 'FriStatusMessage' });\n const {\n title,\n description,\n messageType = 'success',\n displayType = 'alert',\n close,\n open: controlledOpen,\n sx,\n className,\n } = props;\n const [internalOpen, setInternalOpen] = useState(true);\n const titleId = useId();\n const descId = useId();\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const handleClose = () => {\n if (!isControlled) setInternalOpen(false);\n close?.();\n };\n\n const MESSAGE_TYPES = {\n success: { severity: \"success\", Icon: CheckCircleOutlineIcon, color: \"success.main\" },\n danger: { severity: \"error\", Icon: ErrorOutlineIcon, color: \"error.main\" },\n warning: { severity: \"warning\", Icon: WarningAmberIcon, color: \"warning.main\" },\n } as const;\n const DEFAULT_MESSAGE_TYPE: keyof typeof MESSAGE_TYPES = \"success\";\n\n const { severity, Icon, color } = MESSAGE_TYPES[messageType] ?? MESSAGE_TYPES[DEFAULT_MESSAGE_TYPE];\n\n if (!description) return null;\n if (!isOpen) return null;\n\n if (displayType === 'modal') {\n return (\n <Dialog\n ref={ref}\n className={className}\n sx={sx}\n open={isOpen}\n onClose={handleClose}\n aria-labelledby={title ? titleId : undefined}\n aria-describedby={descId}\n maxWidth=\"md\"\n slotProps={{\n paper: {\n sx: { borderRadius: '16px', p: 2 },\n },\n }}\n >\n <DialogContent\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n p: 4,\n gap: 2,\n }}\n >\n <Box sx={{ mb: 2 }}>\n <Icon sx={{ fontSize: 64, color }} />\n </Box>\n {title && (\n <Typography\n id={titleId}\n variant=\"h4\"\n component=\"h2\"\n sx={{ fontWeight: 'bold' }}\n >\n {title}\n </Typography>\n )}\n <Typography id={descId} variant=\"body1\" color=\"text.secondary\">\n {description}\n </Typography>\n </DialogContent>\n <DialogActions sx={{ justifyContent: 'center', p: 2 }}>\n <Button onClick={handleClose} variant=\"contained\" color={severity}>\n Aceptar\n </Button>\n </DialogActions>\n </Dialog>\n );\n }\n\n return (\n <Alert\n ref={ref}\n className={className}\n severity={severity}\n sx={mergeSx({ mb: 2, mt: 2 }, sx)}\n variant={'outlined'}\n onClose={close !== undefined ? handleClose : undefined}\n >\n {title && (\n <AlertTitle>\n {title}\n </AlertTitle>\n )}\n {description}\n </Alert>\n );\n },\n);\n\nexport default StatusMessage;\n"],"names":["forwardRef","StatusMessage","useThemeProps","useState","useId","CheckCircleOutlineIcon","ErrorOutlineIcon","WarningAmberIcon","jsxs","Dialog","DialogContent","jsx","Box","Typography","DialogActions","Button","Alert","mergeSx","AlertTitle"],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useState, useId } from "react";
|
|
3
|
-
import { Dialog, DialogContent, Box, Typography, DialogActions, Button, Alert } from "@mui/material";
|
|
3
|
+
import { Dialog, DialogContent, Box, Typography, DialogActions, Button, Alert, AlertTitle } from "@mui/material";
|
|
4
4
|
import { useThemeProps } from "@mui/material/styles";
|
|
5
5
|
import { m as mergeSx } from "./mergeSx-BXoNZjB_.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { WarningAmber, ErrorOutline, CheckCircleOutline } from "@mui/icons-material";
|
|
7
7
|
const StatusMessage = forwardRef(
|
|
8
8
|
function StatusMessage2(inProps, ref) {
|
|
9
|
+
var _a;
|
|
9
10
|
const props = useThemeProps({ props: inProps, name: "FriStatusMessage" });
|
|
10
11
|
const {
|
|
11
12
|
title,
|
|
@@ -26,8 +27,13 @@ const StatusMessage = forwardRef(
|
|
|
26
27
|
if (!isControlled) setInternalOpen(false);
|
|
27
28
|
close == null ? void 0 : close();
|
|
28
29
|
};
|
|
29
|
-
const
|
|
30
|
-
|
|
30
|
+
const MESSAGE_TYPES = {
|
|
31
|
+
success: { severity: "success", Icon: CheckCircleOutline, color: "success.main" },
|
|
32
|
+
danger: { severity: "error", Icon: ErrorOutline, color: "error.main" },
|
|
33
|
+
warning: { severity: "warning", Icon: WarningAmber, color: "warning.main" }
|
|
34
|
+
};
|
|
35
|
+
const DEFAULT_MESSAGE_TYPE = "success";
|
|
36
|
+
const { severity, Icon, color } = (_a = MESSAGE_TYPES[messageType]) != null ? _a : MESSAGE_TYPES[DEFAULT_MESSAGE_TYPE];
|
|
31
37
|
if (!description) return null;
|
|
32
38
|
if (!isOpen) return null;
|
|
33
39
|
if (displayType === "modal") {
|
|
@@ -60,7 +66,7 @@ const StatusMessage = forwardRef(
|
|
|
60
66
|
gap: 2
|
|
61
67
|
},
|
|
62
68
|
children: [
|
|
63
|
-
/* @__PURE__ */ jsx(Box, { sx: { mb: 2 }, children:
|
|
69
|
+
/* @__PURE__ */ jsx(Box, { sx: { mb: 2 }, children: /* @__PURE__ */ jsx(Icon, { sx: { fontSize: 64, color } }) }),
|
|
64
70
|
title && /* @__PURE__ */ jsx(
|
|
65
71
|
Typography,
|
|
66
72
|
{
|
|
@@ -75,7 +81,7 @@ const StatusMessage = forwardRef(
|
|
|
75
81
|
]
|
|
76
82
|
}
|
|
77
83
|
),
|
|
78
|
-
/* @__PURE__ */ jsx(DialogActions, { sx: { justifyContent: "center", p: 2 }, children: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "contained", color:
|
|
84
|
+
/* @__PURE__ */ jsx(DialogActions, { sx: { justifyContent: "center", p: 2 }, children: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "contained", color: severity, children: "Aceptar" }) })
|
|
79
85
|
]
|
|
80
86
|
}
|
|
81
87
|
);
|
|
@@ -85,12 +91,13 @@ const StatusMessage = forwardRef(
|
|
|
85
91
|
{
|
|
86
92
|
ref,
|
|
87
93
|
className,
|
|
88
|
-
severity
|
|
94
|
+
severity,
|
|
89
95
|
sx: mergeSx({ mb: 2, mt: 2 }, sx),
|
|
96
|
+
variant: "outlined",
|
|
90
97
|
onClose: close !== void 0 ? handleClose : void 0,
|
|
91
98
|
children: [
|
|
92
|
-
title && /* @__PURE__ */ jsx(
|
|
93
|
-
|
|
99
|
+
title && /* @__PURE__ */ jsx(AlertTitle, { children: title }),
|
|
100
|
+
description
|
|
94
101
|
]
|
|
95
102
|
}
|
|
96
103
|
);
|
|
@@ -99,4 +106,4 @@ const StatusMessage = forwardRef(
|
|
|
99
106
|
export {
|
|
100
107
|
StatusMessage as S
|
|
101
108
|
};
|
|
102
|
-
//# sourceMappingURL=StatusMessage-
|
|
109
|
+
//# sourceMappingURL=StatusMessage-Pa5IutUR.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusMessage-Pa5IutUR.mjs","sources":["../../src/components/StatusMessage/StatusMessage.tsx"],"sourcesContent":["import { forwardRef, useId, useState } from 'react';\nimport {\n Alert,\n Box,\n Typography,\n Dialog,\n DialogContent,\n DialogActions,\n Button,\n AlertTitle,\n} from '@mui/material';\nimport { useThemeProps, type SxProps, type Theme } from '@mui/material/styles';\n\nimport { mergeSx } from '../_shared/mergeSx';\nimport {\n ErrorOutline as ErrorOutlineIcon,\n CheckCircleOutline as CheckCircleOutlineIcon,\n WarningAmber as WarningAmberIcon,\n} from '@mui/icons-material';\n\nexport interface StatusMessageProps {\n /** Título del mensaje. */\n title?: string;\n /** Descripción/contenido detallado. Requerido para que el componente renderice. */\n description?: string;\n /** Tipo de mensaje (controla color + icono). `danger` mapea a `error` de MUI. */\n messageType?: 'success' | 'danger' | 'warning';\n /** Forma de presentación: alerta inline o modal. Default: `'alert'`. */\n displayType?: 'alert' | 'modal';\n /** Callback al cerrar. Si se omite, no se muestra botón de cerrar. */\n close?: () => void;\n /**\n * Controla visibilidad. Si se omite, el componente maneja su propio\n * state (se oculta solo al llamar `close`). Si se pasa, queda controlled\n * y el consumer es responsable de actualizarlo.\n */\n open?: boolean;\n /**\n * sx del nodo raíz: el `Alert` en modo `alert`, el `Dialog` en modo `modal`.\n * Antes el componente no aceptaba ni `sx` ni `className`, así que ajustar su\n * separación desde el call-site era imposible.\n */\n sx?: SxProps<Theme>;\n className?: string;\n}\n\n/**\n * Mensaje de éxito / error / advertencia en forma de alerta inline o modal.\n *\n * - **Uncontrolled**: sin pasar `open`, el componente maneja su propia\n * visibilidad. Al llamar `close`, se oculta automáticamente.\n * - **Controlled**: pasando `open`, el consumer decide cuándo mostrar/ocultar.\n */\nexport const StatusMessage = forwardRef<HTMLDivElement, StatusMessageProps>(\n function StatusMessage(inProps, ref) {\n const props = useThemeProps({ props: inProps, name: 'FriStatusMessage' });\n const {\n title,\n description,\n messageType = 'success',\n displayType = 'alert',\n close,\n open: controlledOpen,\n sx,\n className,\n } = props;\n const [internalOpen, setInternalOpen] = useState(true);\n const titleId = useId();\n const descId = useId();\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const handleClose = () => {\n if (!isControlled) setInternalOpen(false);\n close?.();\n };\n\n const MESSAGE_TYPES = {\n success: { severity: \"success\", Icon: CheckCircleOutlineIcon, color: \"success.main\" },\n danger: { severity: \"error\", Icon: ErrorOutlineIcon, color: \"error.main\" },\n warning: { severity: \"warning\", Icon: WarningAmberIcon, color: \"warning.main\" },\n } as const;\n const DEFAULT_MESSAGE_TYPE: keyof typeof MESSAGE_TYPES = \"success\";\n\n const { severity, Icon, color } = MESSAGE_TYPES[messageType] ?? MESSAGE_TYPES[DEFAULT_MESSAGE_TYPE];\n\n if (!description) return null;\n if (!isOpen) return null;\n\n if (displayType === 'modal') {\n return (\n <Dialog\n ref={ref}\n className={className}\n sx={sx}\n open={isOpen}\n onClose={handleClose}\n aria-labelledby={title ? titleId : undefined}\n aria-describedby={descId}\n maxWidth=\"md\"\n slotProps={{\n paper: {\n sx: { borderRadius: '16px', p: 2 },\n },\n }}\n >\n <DialogContent\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n p: 4,\n gap: 2,\n }}\n >\n <Box sx={{ mb: 2 }}>\n <Icon sx={{ fontSize: 64, color }} />\n </Box>\n {title && (\n <Typography\n id={titleId}\n variant=\"h4\"\n component=\"h2\"\n sx={{ fontWeight: 'bold' }}\n >\n {title}\n </Typography>\n )}\n <Typography id={descId} variant=\"body1\" color=\"text.secondary\">\n {description}\n </Typography>\n </DialogContent>\n <DialogActions sx={{ justifyContent: 'center', p: 2 }}>\n <Button onClick={handleClose} variant=\"contained\" color={severity}>\n Aceptar\n </Button>\n </DialogActions>\n </Dialog>\n );\n }\n\n return (\n <Alert\n ref={ref}\n className={className}\n severity={severity}\n sx={mergeSx({ mb: 2, mt: 2 }, sx)}\n variant={'outlined'}\n onClose={close !== undefined ? handleClose : undefined}\n >\n {title && (\n <AlertTitle>\n {title}\n </AlertTitle>\n )}\n {description}\n </Alert>\n );\n },\n);\n\nexport default StatusMessage;\n"],"names":["StatusMessage","CheckCircleOutlineIcon","ErrorOutlineIcon","WarningAmberIcon"],"mappings":"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"}
|
|
@@ -2,7 +2,9 @@ import { Dispatch, SetStateAction, ReactNode } from 'react';
|
|
|
2
2
|
import { StatusMessageProps } from './StatusMessage';
|
|
3
3
|
export type StatusMessageState = {
|
|
4
4
|
[K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;
|
|
5
|
-
} & Pick<StatusMessageProps, 'displayType'
|
|
5
|
+
} & Pick<StatusMessageProps, 'displayType'> & {
|
|
6
|
+
autoReset?: boolean;
|
|
7
|
+
};
|
|
6
8
|
interface StatusMessageContextValue {
|
|
7
9
|
state: StatusMessageState | undefined;
|
|
8
10
|
setMessage: Dispatch<SetStateAction<StatusMessageState | undefined>>;
|
|
@@ -2,7 +2,9 @@ import { Dispatch, SetStateAction, ReactNode } from 'react';
|
|
|
2
2
|
import { StatusMessageProps } from './StatusMessage.mjs';
|
|
3
3
|
export type StatusMessageState = {
|
|
4
4
|
[K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;
|
|
5
|
-
} & Pick<StatusMessageProps, 'displayType'
|
|
5
|
+
} & Pick<StatusMessageProps, 'displayType'> & {
|
|
6
|
+
autoReset?: boolean;
|
|
7
|
+
};
|
|
6
8
|
interface StatusMessageContextValue {
|
|
7
9
|
state: StatusMessageState | undefined;
|
|
8
10
|
setMessage: Dispatch<SetStateAction<StatusMessageState | undefined>>;
|
|
@@ -2,7 +2,9 @@ import { Dispatch, SetStateAction, ReactNode } from 'react';
|
|
|
2
2
|
import { StatusMessageProps } from './StatusMessage';
|
|
3
3
|
export type StatusMessageState = {
|
|
4
4
|
[K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;
|
|
5
|
-
} & Pick<StatusMessageProps, 'displayType'
|
|
5
|
+
} & Pick<StatusMessageProps, 'displayType'> & {
|
|
6
|
+
autoReset?: boolean;
|
|
7
|
+
};
|
|
6
8
|
interface StatusMessageContextValue {
|
|
7
9
|
state: StatusMessageState | undefined;
|
|
8
10
|
setMessage: Dispatch<SetStateAction<StatusMessageState | undefined>>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pinta el mensaje vigente del `StatusMessageProvider` en el lugar donde se monte.
|
|
3
|
+
*
|
|
4
|
+
* Separa el *disparo* del mensaje (`useStatusMessage().showMessage`, desde un
|
|
5
|
+
* handler cualquiera) del *lugar* donde se muestra: el consumidor monta un único
|
|
6
|
+
* `<StatusMessageRenderer />` donde quiere ver el feedback (arriba del form, en
|
|
7
|
+
* el layout de la página) y no tiene que llevar `state` ni `close` a mano hasta
|
|
8
|
+
* cada `<StatusMessage>`.
|
|
9
|
+
*
|
|
10
|
+
* - Sin mensaje en el contexto renderiza `null`, así que puede quedar montado
|
|
11
|
+
* siempre sin reservar espacio.
|
|
12
|
+
* - `close` se conecta a `clearMessage`: cerrar limpia el contexto y el
|
|
13
|
+
* componente se desmonta. Por eso el `StatusMessage` queda en modo
|
|
14
|
+
* *uncontrolled* (sin `open`): su visibilidad la decide la existencia del
|
|
15
|
+
* `state`, no un booleano aparte.
|
|
16
|
+
* - El auto-cierre (`autoReset`, 6s) lo resuelve el Provider, no este componente.
|
|
17
|
+
*
|
|
18
|
+
* Debe montarse dentro de un `StatusMessageProvider`; fuera de él el contexto
|
|
19
|
+
* devuelve su valor por defecto (`state: undefined`) y nunca muestra nada, sin
|
|
20
|
+
* error que lo avise.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* <StatusMessageProvider>
|
|
24
|
+
* <StatusMessageRenderer />
|
|
25
|
+
* <MiFormulario /> // adentro: useStatusMessage().showMessage({ messageType: 'danger', description })
|
|
26
|
+
* </StatusMessageProvider>
|
|
27
|
+
*/
|
|
28
|
+
export declare const StatusMessageRenderer: () => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pinta el mensaje vigente del `StatusMessageProvider` en el lugar donde se monte.
|
|
3
|
+
*
|
|
4
|
+
* Separa el *disparo* del mensaje (`useStatusMessage().showMessage`, desde un
|
|
5
|
+
* handler cualquiera) del *lugar* donde se muestra: el consumidor monta un único
|
|
6
|
+
* `<StatusMessageRenderer />` donde quiere ver el feedback (arriba del form, en
|
|
7
|
+
* el layout de la página) y no tiene que llevar `state` ni `close` a mano hasta
|
|
8
|
+
* cada `<StatusMessage>`.
|
|
9
|
+
*
|
|
10
|
+
* - Sin mensaje en el contexto renderiza `null`, así que puede quedar montado
|
|
11
|
+
* siempre sin reservar espacio.
|
|
12
|
+
* - `close` se conecta a `clearMessage`: cerrar limpia el contexto y el
|
|
13
|
+
* componente se desmonta. Por eso el `StatusMessage` queda en modo
|
|
14
|
+
* *uncontrolled* (sin `open`): su visibilidad la decide la existencia del
|
|
15
|
+
* `state`, no un booleano aparte.
|
|
16
|
+
* - El auto-cierre (`autoReset`, 6s) lo resuelve el Provider, no este componente.
|
|
17
|
+
*
|
|
18
|
+
* Debe montarse dentro de un `StatusMessageProvider`; fuera de él el contexto
|
|
19
|
+
* devuelve su valor por defecto (`state: undefined`) y nunca muestra nada, sin
|
|
20
|
+
* error que lo avise.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* <StatusMessageProvider>
|
|
24
|
+
* <StatusMessageRenderer />
|
|
25
|
+
* <MiFormulario /> // adentro: useStatusMessage().showMessage({ messageType: 'danger', description })
|
|
26
|
+
* </StatusMessageProvider>
|
|
27
|
+
*/
|
|
28
|
+
export declare const StatusMessageRenderer: () => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pinta el mensaje vigente del `StatusMessageProvider` en el lugar donde se monte.
|
|
3
|
+
*
|
|
4
|
+
* Separa el *disparo* del mensaje (`useStatusMessage().showMessage`, desde un
|
|
5
|
+
* handler cualquiera) del *lugar* donde se muestra: el consumidor monta un único
|
|
6
|
+
* `<StatusMessageRenderer />` donde quiere ver el feedback (arriba del form, en
|
|
7
|
+
* el layout de la página) y no tiene que llevar `state` ni `close` a mano hasta
|
|
8
|
+
* cada `<StatusMessage>`.
|
|
9
|
+
*
|
|
10
|
+
* - Sin mensaje en el contexto renderiza `null`, así que puede quedar montado
|
|
11
|
+
* siempre sin reservar espacio.
|
|
12
|
+
* - `close` se conecta a `clearMessage`: cerrar limpia el contexto y el
|
|
13
|
+
* componente se desmonta. Por eso el `StatusMessage` queda en modo
|
|
14
|
+
* *uncontrolled* (sin `open`): su visibilidad la decide la existencia del
|
|
15
|
+
* `state`, no un booleano aparte.
|
|
16
|
+
* - El auto-cierre (`autoReset`, 6s) lo resuelve el Provider, no este componente.
|
|
17
|
+
*
|
|
18
|
+
* Debe montarse dentro de un `StatusMessageProvider`; fuera de él el contexto
|
|
19
|
+
* devuelve su valor por defecto (`state: undefined`) y nunca muestra nada, sin
|
|
20
|
+
* error que lo avise.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* <StatusMessageProvider>
|
|
24
|
+
* <StatusMessageRenderer />
|
|
25
|
+
* <MiFormulario /> // adentro: useStatusMessage().showMessage({ messageType: 'danger', description })
|
|
26
|
+
* </StatusMessageProvider>
|
|
27
|
+
*/
|
|
28
|
+
export declare const StatusMessageRenderer: () => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
|
+
var __objRest = (source, exclude) => {
|
|
22
|
+
var target = {};
|
|
23
|
+
for (var prop in source)
|
|
24
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
25
|
+
target[prop] = source[prop];
|
|
26
|
+
if (source != null && __getOwnPropSymbols)
|
|
27
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
28
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
}
|
|
31
|
+
return target;
|
|
32
|
+
};
|
|
2
33
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
-
const StatusMessage = require("../../chunks/StatusMessage-
|
|
34
|
+
const StatusMessage = require("../../chunks/StatusMessage-Bl_E83nN.cjs");
|
|
4
35
|
const jsxRuntime = require("react/jsx-runtime");
|
|
5
36
|
const React = require("react");
|
|
6
37
|
const initialValues = {
|
|
@@ -14,13 +45,45 @@ const StatusMessageContext = React.createContext(initialValues);
|
|
|
14
45
|
const useStatusMessageContext = () => React.useContext(StatusMessageContext);
|
|
15
46
|
const StatusMessageProvider = ({ children }) => {
|
|
16
47
|
const [stateMessage, setMessage] = React.useState(void 0);
|
|
17
|
-
const cleanMessage = () => {
|
|
48
|
+
const cleanMessage = React.useCallback(() => {
|
|
18
49
|
setMessage(void 0);
|
|
19
|
-
};
|
|
20
|
-
|
|
50
|
+
}, []);
|
|
51
|
+
const value = React.useMemo(
|
|
52
|
+
() => ({ setMessage, cleanMessage, state: stateMessage }),
|
|
53
|
+
[cleanMessage, stateMessage]
|
|
54
|
+
);
|
|
55
|
+
React.useEffect(() => {
|
|
56
|
+
if (!stateMessage || stateMessage.autoReset === false) return;
|
|
57
|
+
const timeout = setTimeout(() => {
|
|
58
|
+
setMessage(void 0);
|
|
59
|
+
}, 6e3);
|
|
60
|
+
return () => clearTimeout(timeout);
|
|
61
|
+
}, [stateMessage]);
|
|
62
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StatusMessageContext.Provider, { value, children });
|
|
63
|
+
};
|
|
64
|
+
const useStatusMessage = () => {
|
|
65
|
+
const { state, setMessage, cleanMessage } = useStatusMessageContext();
|
|
66
|
+
const showMessage = React.useCallback(
|
|
67
|
+
(_a) => {
|
|
68
|
+
var _b = _a, { displayType = "alert", autoReset = true, title } = _b, rest = __objRest(_b, ["displayType", "autoReset", "title"]);
|
|
69
|
+
setMessage(__spreadProps(__spreadValues({}, rest), { title, displayType, autoReset }));
|
|
70
|
+
},
|
|
71
|
+
[setMessage]
|
|
72
|
+
);
|
|
73
|
+
return React.useMemo(
|
|
74
|
+
() => ({ state, showMessage, clearMessage: cleanMessage }),
|
|
75
|
+
[state, showMessage, cleanMessage]
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
const StatusMessageRenderer = () => {
|
|
79
|
+
const { state, clearMessage } = useStatusMessage();
|
|
80
|
+
if (!state) return null;
|
|
81
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StatusMessage.StatusMessage, __spreadProps(__spreadValues({}, state), { close: clearMessage }));
|
|
21
82
|
};
|
|
22
83
|
exports.StatusMessage = StatusMessage.StatusMessage;
|
|
23
84
|
exports.default = StatusMessage.StatusMessage;
|
|
24
85
|
exports.StatusMessageProvider = StatusMessageProvider;
|
|
86
|
+
exports.StatusMessageRenderer = StatusMessageRenderer;
|
|
87
|
+
exports.useStatusMessage = useStatusMessage;
|
|
25
88
|
exports.useStatusMessageContext = useStatusMessageContext;
|
|
26
89
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../src/components/StatusMessage/StatusMessageContext.tsx"],"sourcesContent":["import {\n createContext,\n useState,\n useContext,\n type Dispatch,\n type SetStateAction,\n type ReactNode,\n} from 'react';\nimport type { StatusMessageProps } from './StatusMessage';\n\nexport type StatusMessageState = {\n [K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;\n} & Pick<StatusMessageProps, 'displayType'
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../src/components/StatusMessage/StatusMessageContext.tsx","../../../src/components/StatusMessage/useStatusMessage.ts","../../../src/components/StatusMessage/StatusMessageRenderer.tsx"],"sourcesContent":["import {\n createContext,\n useState,\n useContext,\n type Dispatch,\n type SetStateAction,\n type ReactNode,\n useEffect,\n useCallback,\n useMemo,\n} from 'react';\nimport type { StatusMessageProps } from './StatusMessage';\n\nexport type StatusMessageState = {\n [K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;\n} & Pick<StatusMessageProps, 'displayType'> & {\n autoReset?: boolean;\n };\n\ninterface StatusMessageContextValue {\n state: StatusMessageState | undefined;\n setMessage: Dispatch<SetStateAction<StatusMessageState | undefined>>;\n cleanMessage: () => void;\n}\n\nconst initialValues: StatusMessageContextValue = {\n state: undefined,\n setMessage: () => {},\n cleanMessage: () => {},\n};\n\nconst StatusMessageContext = createContext<StatusMessageContextValue>(initialValues);\n\nexport const useStatusMessageContext = () => useContext(StatusMessageContext);\n\ninterface StatusMessageProviderProps {\n children: ReactNode;\n}\n\nexport const StatusMessageProvider = ({ children }: StatusMessageProviderProps) => {\n const [stateMessage, setMessage] = useState<StatusMessageState | undefined>(undefined);\n // Estables para que los consumidores puedan usarlas como deps de un efecto\n // sin re-dispararlo en cada render del Provider.\n const cleanMessage = useCallback(() => {\n setMessage(undefined);\n }, []);\n \n const value = useMemo(\n () => ({ setMessage, cleanMessage, state: stateMessage }),\n [cleanMessage, stateMessage],\n );\n\n useEffect(() => {\n if (!stateMessage || stateMessage.autoReset === false) return;\n const timeout = setTimeout(() => {\n setMessage(undefined);\n }, 6000);\n return () => clearTimeout(timeout);\n }, [stateMessage]);\n\n return (\n <StatusMessageContext.Provider value={value}>\n {children}\n </StatusMessageContext.Provider>\n );\n};\n","import { useCallback, useMemo } from \"react\";\nimport { useStatusMessageContext, type StatusMessageState } from \"./StatusMessageContext\";\n\n/**\n * Lo que recibe `showMessage`. Mismos nombres que las props de `StatusMessage`\n * para que lo que entra sea lo que el componente termina recibiendo.\n * `messageType` y `description` son obligatorios: sin tipo no hay color/icono\n * y sin descripción `StatusMessage` no renderiza.\n */\nexport type ShowMessageOptions = {\n messageType: NonNullable<StatusMessageState[\"messageType\"]>;\n description: string;\n title?: string;\n /** Default: `'alert'`. */\n displayType?: StatusMessageState[\"displayType\"];\n /** Si es `true` el Provider limpia el mensaje a los 6s. Default: `true`. */\n autoReset?: boolean;\n};\n\n/**\n * API recomendada para disparar feedback desde un handler. Se monta sobre el\n * contexto para no exponer el `setMessage` crudo (un `Dispatch` que obliga al\n * consumidor a armar el estado completo) y para centralizar los defaults.\n *\n * Recibe un objeto y no parámetros posicionales: con `title`/`autoReset`\n * opcionales, el orden se volvía ilegible (`fn('Ok', undefined, false)`).\n *\n * `showMessage` y `clearMessage` tienen identidad estable, así que se pueden\n * usar como dependencias de un efecto sin re-dispararlo en cada render.\n *\n * @example\n * const { showMessage } = useStatusMessage();\n * showMessage({ messageType: 'success', description: 'Cambios guardados' });\n */\nexport const useStatusMessage = () => {\n const { state, setMessage, cleanMessage } = useStatusMessageContext();\n\n const showMessage = useCallback(\n ({ displayType = \"alert\", autoReset = true, title, ...rest }: ShowMessageOptions) => {\n setMessage({ ...rest, title, displayType, autoReset });\n },\n [setMessage],\n );\n\n return useMemo(\n () => ({ state, showMessage, clearMessage: cleanMessage }),\n [state, showMessage, cleanMessage],\n );\n};\n","import StatusMessage from \"./StatusMessage\";\nimport { useStatusMessage } from \"./useStatusMessage\";\n\n/**\n * Pinta el mensaje vigente del `StatusMessageProvider` en el lugar donde se monte.\n *\n * Separa el *disparo* del mensaje (`useStatusMessage().showMessage`, desde un\n * handler cualquiera) del *lugar* donde se muestra: el consumidor monta un único\n * `<StatusMessageRenderer />` donde quiere ver el feedback (arriba del form, en\n * el layout de la página) y no tiene que llevar `state` ni `close` a mano hasta\n * cada `<StatusMessage>`.\n *\n * - Sin mensaje en el contexto renderiza `null`, así que puede quedar montado\n * siempre sin reservar espacio.\n * - `close` se conecta a `clearMessage`: cerrar limpia el contexto y el\n * componente se desmonta. Por eso el `StatusMessage` queda en modo\n * *uncontrolled* (sin `open`): su visibilidad la decide la existencia del\n * `state`, no un booleano aparte.\n * - El auto-cierre (`autoReset`, 6s) lo resuelve el Provider, no este componente.\n *\n * Debe montarse dentro de un `StatusMessageProvider`; fuera de él el contexto\n * devuelve su valor por defecto (`state: undefined`) y nunca muestra nada, sin\n * error que lo avise.\n *\n * @example\n * <StatusMessageProvider>\n * <StatusMessageRenderer />\n * <MiFormulario /> // adentro: useStatusMessage().showMessage({ messageType: 'danger', description })\n * </StatusMessageProvider>\n */\nexport const StatusMessageRenderer = () => {\n const { state, clearMessage } = useStatusMessage();\n\n if (!state) return null;\n\n return <StatusMessage {...state} close={clearMessage} />;\n};\n"],"names":["createContext","useContext","useState","useCallback","useMemo","useEffect","jsx","StatusMessage"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAM,gBAA2C;AAAA,EAC/C,OAAO;AAAA,EACP,YAAY,MAAM;AAAA,EAAC;AAAA,EACnB,cAAc,MAAM;AAAA,EAAC;AACvB;AAEA,MAAM,uBAAuBA,MAAAA,cAAyC,aAAa;AAE5E,MAAM,0BAA0B,MAAMC,MAAAA,WAAW,oBAAoB;AAMrE,MAAM,wBAAwB,CAAC,EAAE,eAA2C;AACjF,QAAM,CAAC,cAAc,UAAU,IAAIC,MAAAA,SAAyC,MAAS;AAGrF,QAAM,eAAeC,MAAAA,YAAY,MAAM;AACrC,eAAW,MAAS;AAAA,EACtB,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQC,MAAAA;AAAAA,IACZ,OAAO,EAAE,YAAY,cAAc,OAAO,aAAA;AAAA,IAC1C,CAAC,cAAc,YAAY;AAAA,EAAA;AAG5BC,QAAAA,UAAU,MAAM;AACb,QAAI,CAAC,gBAAgB,aAAa,cAAc,MAAO;AACvD,UAAM,UAAU,WAAW,MAAM;AAC9B,iBAAW,MAAS;AAAA,IACvB,GAAG,GAAI;AACP,WAAO,MAAM,aAAa,OAAO;AAAA,EACpC,GAAG,CAAC,YAAY,CAAC;AAElB,SACEC,2BAAAA,IAAC,qBAAqB,UAArB,EAA8B,OAC5B,SAAA,CACH;AAEJ;AC/BO,MAAM,mBAAmB,MAAM;AACnC,QAAM,EAAE,OAAO,YAAY,aAAA,IAAiB,wBAAA;AAE5C,QAAM,cAAcH,MAAAA;AAAAA,IACjB,CAAC,OAAoF;AAApF,mBAAE,gBAAc,SAAS,YAAY,MAAM,UAA3C,IAAqD,iBAArD,IAAqD,CAAnD,eAAuB,aAAkB;AACzC,iBAAW,iCAAK,OAAL,EAAW,OAAO,aAAa,YAAW;AAAA,IACxD;AAAA,IACA,CAAC,UAAU;AAAA,EAAA;AAGd,SAAOC,MAAAA;AAAAA,IACJ,OAAO,EAAE,OAAO,aAAa,cAAc,aAAA;AAAA,IAC3C,CAAC,OAAO,aAAa,YAAY;AAAA,EAAA;AAEvC;AClBO,MAAM,wBAAwB,MAAM;AACxC,QAAM,EAAE,OAAO,aAAA,IAAiB,iBAAA;AAEhC,MAAI,CAAC,MAAO,QAAO;AAEnB,SAAOE,2BAAAA,IAACC,cAAAA,eAAA,iCAAkB,QAAlB,EAAyB,OAAO,eAAc;AACzD;;;;;;;"}
|
|
@@ -2,3 +2,6 @@ export { StatusMessage, default } from './StatusMessage';
|
|
|
2
2
|
export type { StatusMessageProps } from './StatusMessage';
|
|
3
3
|
export { StatusMessageProvider, useStatusMessageContext, } from './StatusMessageContext';
|
|
4
4
|
export type { StatusMessageState } from './StatusMessageContext';
|
|
5
|
+
export { StatusMessageRenderer } from './StatusMessageRenderer';
|
|
6
|
+
export { useStatusMessage } from './useStatusMessage';
|
|
7
|
+
export type { ShowMessageOptions } from './useStatusMessage';
|
|
@@ -2,3 +2,6 @@ export { StatusMessage, default } from './StatusMessage.mjs';
|
|
|
2
2
|
export type { StatusMessageProps } from './StatusMessage.mjs';
|
|
3
3
|
export { StatusMessageProvider, useStatusMessageContext, } from './StatusMessageContext.mjs';
|
|
4
4
|
export type { StatusMessageState } from './StatusMessageContext.mjs';
|
|
5
|
+
export { StatusMessageRenderer } from './StatusMessageRenderer.mjs';
|
|
6
|
+
export { useStatusMessage } from './useStatusMessage.mjs';
|
|
7
|
+
export type { ShowMessageOptions } from './useStatusMessage.mjs';
|
|
@@ -2,3 +2,6 @@ export { StatusMessage, default } from './StatusMessage';
|
|
|
2
2
|
export type { StatusMessageProps } from './StatusMessage';
|
|
3
3
|
export { StatusMessageProvider, useStatusMessageContext, } from './StatusMessageContext';
|
|
4
4
|
export type { StatusMessageState } from './StatusMessageContext';
|
|
5
|
+
export { StatusMessageRenderer } from './StatusMessageRenderer';
|
|
6
|
+
export { useStatusMessage } from './useStatusMessage';
|
|
7
|
+
export type { ShowMessageOptions } from './useStatusMessage';
|
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __objRest = (source, exclude) => {
|
|
21
|
+
var target = {};
|
|
22
|
+
for (var prop in source)
|
|
23
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
24
|
+
target[prop] = source[prop];
|
|
25
|
+
if (source != null && __getOwnPropSymbols)
|
|
26
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
27
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
28
|
+
target[prop] = source[prop];
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
};
|
|
32
|
+
import { S as StatusMessage } from "../../chunks/StatusMessage-Pa5IutUR.mjs";
|
|
2
33
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useContext, useState, createContext } from "react";
|
|
34
|
+
import { useContext, useState, useCallback, useMemo, useEffect, createContext } from "react";
|
|
4
35
|
const initialValues = {
|
|
5
36
|
state: void 0,
|
|
6
37
|
setMessage: () => {
|
|
@@ -12,15 +43,47 @@ const StatusMessageContext = createContext(initialValues);
|
|
|
12
43
|
const useStatusMessageContext = () => useContext(StatusMessageContext);
|
|
13
44
|
const StatusMessageProvider = ({ children }) => {
|
|
14
45
|
const [stateMessage, setMessage] = useState(void 0);
|
|
15
|
-
const cleanMessage = () => {
|
|
46
|
+
const cleanMessage = useCallback(() => {
|
|
16
47
|
setMessage(void 0);
|
|
17
|
-
};
|
|
18
|
-
|
|
48
|
+
}, []);
|
|
49
|
+
const value = useMemo(
|
|
50
|
+
() => ({ setMessage, cleanMessage, state: stateMessage }),
|
|
51
|
+
[cleanMessage, stateMessage]
|
|
52
|
+
);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (!stateMessage || stateMessage.autoReset === false) return;
|
|
55
|
+
const timeout = setTimeout(() => {
|
|
56
|
+
setMessage(void 0);
|
|
57
|
+
}, 6e3);
|
|
58
|
+
return () => clearTimeout(timeout);
|
|
59
|
+
}, [stateMessage]);
|
|
60
|
+
return /* @__PURE__ */ jsx(StatusMessageContext.Provider, { value, children });
|
|
61
|
+
};
|
|
62
|
+
const useStatusMessage = () => {
|
|
63
|
+
const { state, setMessage, cleanMessage } = useStatusMessageContext();
|
|
64
|
+
const showMessage = useCallback(
|
|
65
|
+
(_a) => {
|
|
66
|
+
var _b = _a, { displayType = "alert", autoReset = true, title } = _b, rest = __objRest(_b, ["displayType", "autoReset", "title"]);
|
|
67
|
+
setMessage(__spreadProps(__spreadValues({}, rest), { title, displayType, autoReset }));
|
|
68
|
+
},
|
|
69
|
+
[setMessage]
|
|
70
|
+
);
|
|
71
|
+
return useMemo(
|
|
72
|
+
() => ({ state, showMessage, clearMessage: cleanMessage }),
|
|
73
|
+
[state, showMessage, cleanMessage]
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
const StatusMessageRenderer = () => {
|
|
77
|
+
const { state, clearMessage } = useStatusMessage();
|
|
78
|
+
if (!state) return null;
|
|
79
|
+
return /* @__PURE__ */ jsx(StatusMessage, __spreadProps(__spreadValues({}, state), { close: clearMessage }));
|
|
19
80
|
};
|
|
20
81
|
export {
|
|
21
|
-
|
|
82
|
+
StatusMessage,
|
|
22
83
|
StatusMessageProvider,
|
|
23
|
-
|
|
84
|
+
StatusMessageRenderer,
|
|
85
|
+
StatusMessage as default,
|
|
86
|
+
useStatusMessage,
|
|
24
87
|
useStatusMessageContext
|
|
25
88
|
};
|
|
26
89
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../src/components/StatusMessage/StatusMessageContext.tsx"],"sourcesContent":["import {\n createContext,\n useState,\n useContext,\n type Dispatch,\n type SetStateAction,\n type ReactNode,\n} from 'react';\nimport type { StatusMessageProps } from './StatusMessage';\n\nexport type StatusMessageState = {\n [K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;\n} & Pick<StatusMessageProps, 'displayType'
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../src/components/StatusMessage/StatusMessageContext.tsx","../../../src/components/StatusMessage/useStatusMessage.ts","../../../src/components/StatusMessage/StatusMessageRenderer.tsx"],"sourcesContent":["import {\n createContext,\n useState,\n useContext,\n type Dispatch,\n type SetStateAction,\n type ReactNode,\n useEffect,\n useCallback,\n useMemo,\n} from 'react';\nimport type { StatusMessageProps } from './StatusMessage';\n\nexport type StatusMessageState = {\n [K in 'title' | 'description' | 'messageType']: StatusMessageProps[K] | undefined;\n} & Pick<StatusMessageProps, 'displayType'> & {\n autoReset?: boolean;\n };\n\ninterface StatusMessageContextValue {\n state: StatusMessageState | undefined;\n setMessage: Dispatch<SetStateAction<StatusMessageState | undefined>>;\n cleanMessage: () => void;\n}\n\nconst initialValues: StatusMessageContextValue = {\n state: undefined,\n setMessage: () => {},\n cleanMessage: () => {},\n};\n\nconst StatusMessageContext = createContext<StatusMessageContextValue>(initialValues);\n\nexport const useStatusMessageContext = () => useContext(StatusMessageContext);\n\ninterface StatusMessageProviderProps {\n children: ReactNode;\n}\n\nexport const StatusMessageProvider = ({ children }: StatusMessageProviderProps) => {\n const [stateMessage, setMessage] = useState<StatusMessageState | undefined>(undefined);\n // Estables para que los consumidores puedan usarlas como deps de un efecto\n // sin re-dispararlo en cada render del Provider.\n const cleanMessage = useCallback(() => {\n setMessage(undefined);\n }, []);\n \n const value = useMemo(\n () => ({ setMessage, cleanMessage, state: stateMessage }),\n [cleanMessage, stateMessage],\n );\n\n useEffect(() => {\n if (!stateMessage || stateMessage.autoReset === false) return;\n const timeout = setTimeout(() => {\n setMessage(undefined);\n }, 6000);\n return () => clearTimeout(timeout);\n }, [stateMessage]);\n\n return (\n <StatusMessageContext.Provider value={value}>\n {children}\n </StatusMessageContext.Provider>\n );\n};\n","import { useCallback, useMemo } from \"react\";\nimport { useStatusMessageContext, type StatusMessageState } from \"./StatusMessageContext\";\n\n/**\n * Lo que recibe `showMessage`. Mismos nombres que las props de `StatusMessage`\n * para que lo que entra sea lo que el componente termina recibiendo.\n * `messageType` y `description` son obligatorios: sin tipo no hay color/icono\n * y sin descripción `StatusMessage` no renderiza.\n */\nexport type ShowMessageOptions = {\n messageType: NonNullable<StatusMessageState[\"messageType\"]>;\n description: string;\n title?: string;\n /** Default: `'alert'`. */\n displayType?: StatusMessageState[\"displayType\"];\n /** Si es `true` el Provider limpia el mensaje a los 6s. Default: `true`. */\n autoReset?: boolean;\n};\n\n/**\n * API recomendada para disparar feedback desde un handler. Se monta sobre el\n * contexto para no exponer el `setMessage` crudo (un `Dispatch` que obliga al\n * consumidor a armar el estado completo) y para centralizar los defaults.\n *\n * Recibe un objeto y no parámetros posicionales: con `title`/`autoReset`\n * opcionales, el orden se volvía ilegible (`fn('Ok', undefined, false)`).\n *\n * `showMessage` y `clearMessage` tienen identidad estable, así que se pueden\n * usar como dependencias de un efecto sin re-dispararlo en cada render.\n *\n * @example\n * const { showMessage } = useStatusMessage();\n * showMessage({ messageType: 'success', description: 'Cambios guardados' });\n */\nexport const useStatusMessage = () => {\n const { state, setMessage, cleanMessage } = useStatusMessageContext();\n\n const showMessage = useCallback(\n ({ displayType = \"alert\", autoReset = true, title, ...rest }: ShowMessageOptions) => {\n setMessage({ ...rest, title, displayType, autoReset });\n },\n [setMessage],\n );\n\n return useMemo(\n () => ({ state, showMessage, clearMessage: cleanMessage }),\n [state, showMessage, cleanMessage],\n );\n};\n","import StatusMessage from \"./StatusMessage\";\nimport { useStatusMessage } from \"./useStatusMessage\";\n\n/**\n * Pinta el mensaje vigente del `StatusMessageProvider` en el lugar donde se monte.\n *\n * Separa el *disparo* del mensaje (`useStatusMessage().showMessage`, desde un\n * handler cualquiera) del *lugar* donde se muestra: el consumidor monta un único\n * `<StatusMessageRenderer />` donde quiere ver el feedback (arriba del form, en\n * el layout de la página) y no tiene que llevar `state` ni `close` a mano hasta\n * cada `<StatusMessage>`.\n *\n * - Sin mensaje en el contexto renderiza `null`, así que puede quedar montado\n * siempre sin reservar espacio.\n * - `close` se conecta a `clearMessage`: cerrar limpia el contexto y el\n * componente se desmonta. Por eso el `StatusMessage` queda en modo\n * *uncontrolled* (sin `open`): su visibilidad la decide la existencia del\n * `state`, no un booleano aparte.\n * - El auto-cierre (`autoReset`, 6s) lo resuelve el Provider, no este componente.\n *\n * Debe montarse dentro de un `StatusMessageProvider`; fuera de él el contexto\n * devuelve su valor por defecto (`state: undefined`) y nunca muestra nada, sin\n * error que lo avise.\n *\n * @example\n * <StatusMessageProvider>\n * <StatusMessageRenderer />\n * <MiFormulario /> // adentro: useStatusMessage().showMessage({ messageType: 'danger', description })\n * </StatusMessageProvider>\n */\nexport const StatusMessageRenderer = () => {\n const { state, clearMessage } = useStatusMessage();\n\n if (!state) return null;\n\n return <StatusMessage {...state} close={clearMessage} />;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAM,gBAA2C;AAAA,EAC/C,OAAO;AAAA,EACP,YAAY,MAAM;AAAA,EAAC;AAAA,EACnB,cAAc,MAAM;AAAA,EAAC;AACvB;AAEA,MAAM,uBAAuB,cAAyC,aAAa;AAE5E,MAAM,0BAA0B,MAAM,WAAW,oBAAoB;AAMrE,MAAM,wBAAwB,CAAC,EAAE,eAA2C;AACjF,QAAM,CAAC,cAAc,UAAU,IAAI,SAAyC,MAAS;AAGrF,QAAM,eAAe,YAAY,MAAM;AACrC,eAAW,MAAS;AAAA,EACtB,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQ;AAAA,IACZ,OAAO,EAAE,YAAY,cAAc,OAAO,aAAA;AAAA,IAC1C,CAAC,cAAc,YAAY;AAAA,EAAA;AAG5B,YAAU,MAAM;AACb,QAAI,CAAC,gBAAgB,aAAa,cAAc,MAAO;AACvD,UAAM,UAAU,WAAW,MAAM;AAC9B,iBAAW,MAAS;AAAA,IACvB,GAAG,GAAI;AACP,WAAO,MAAM,aAAa,OAAO;AAAA,EACpC,GAAG,CAAC,YAAY,CAAC;AAElB,SACE,oBAAC,qBAAqB,UAArB,EAA8B,OAC5B,SAAA,CACH;AAEJ;AC/BO,MAAM,mBAAmB,MAAM;AACnC,QAAM,EAAE,OAAO,YAAY,aAAA,IAAiB,wBAAA;AAE5C,QAAM,cAAc;AAAA,IACjB,CAAC,OAAoF;AAApF,mBAAE,gBAAc,SAAS,YAAY,MAAM,UAA3C,IAAqD,iBAArD,IAAqD,CAAnD,eAAuB,aAAkB;AACzC,iBAAW,iCAAK,OAAL,EAAW,OAAO,aAAa,YAAW;AAAA,IACxD;AAAA,IACA,CAAC,UAAU;AAAA,EAAA;AAGd,SAAO;AAAA,IACJ,OAAO,EAAE,OAAO,aAAa,cAAc,aAAA;AAAA,IAC3C,CAAC,OAAO,aAAa,YAAY;AAAA,EAAA;AAEvC;AClBO,MAAM,wBAAwB,MAAM;AACxC,QAAM,EAAE,OAAO,aAAA,IAAiB,iBAAA;AAEhC,MAAI,CAAC,MAAO,QAAO;AAEnB,SAAO,oBAAC,eAAA,iCAAkB,QAAlB,EAAyB,OAAO,eAAc;AACzD;"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { StatusMessageState } from './StatusMessageContext';
|
|
2
|
+
/**
|
|
3
|
+
* Lo que recibe `showMessage`. Mismos nombres que las props de `StatusMessage`
|
|
4
|
+
* para que lo que entra sea lo que el componente termina recibiendo.
|
|
5
|
+
* `messageType` y `description` son obligatorios: sin tipo no hay color/icono
|
|
6
|
+
* y sin descripción `StatusMessage` no renderiza.
|
|
7
|
+
*/
|
|
8
|
+
export type ShowMessageOptions = {
|
|
9
|
+
messageType: NonNullable<StatusMessageState["messageType"]>;
|
|
10
|
+
description: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
/** Default: `'alert'`. */
|
|
13
|
+
displayType?: StatusMessageState["displayType"];
|
|
14
|
+
/** Si es `true` el Provider limpia el mensaje a los 6s. Default: `true`. */
|
|
15
|
+
autoReset?: boolean;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* API recomendada para disparar feedback desde un handler. Se monta sobre el
|
|
19
|
+
* contexto para no exponer el `setMessage` crudo (un `Dispatch` que obliga al
|
|
20
|
+
* consumidor a armar el estado completo) y para centralizar los defaults.
|
|
21
|
+
*
|
|
22
|
+
* Recibe un objeto y no parámetros posicionales: con `title`/`autoReset`
|
|
23
|
+
* opcionales, el orden se volvía ilegible (`fn('Ok', undefined, false)`).
|
|
24
|
+
*
|
|
25
|
+
* `showMessage` y `clearMessage` tienen identidad estable, así que se pueden
|
|
26
|
+
* usar como dependencias de un efecto sin re-dispararlo en cada render.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const { showMessage } = useStatusMessage();
|
|
30
|
+
* showMessage({ messageType: 'success', description: 'Cambios guardados' });
|
|
31
|
+
*/
|
|
32
|
+
export declare const useStatusMessage: () => {
|
|
33
|
+
state: StatusMessageState | undefined;
|
|
34
|
+
showMessage: ({ displayType, autoReset, title, ...rest }: ShowMessageOptions) => void;
|
|
35
|
+
clearMessage: () => void;
|
|
36
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { StatusMessageState } from './StatusMessageContext.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* Lo que recibe `showMessage`. Mismos nombres que las props de `StatusMessage`
|
|
4
|
+
* para que lo que entra sea lo que el componente termina recibiendo.
|
|
5
|
+
* `messageType` y `description` son obligatorios: sin tipo no hay color/icono
|
|
6
|
+
* y sin descripción `StatusMessage` no renderiza.
|
|
7
|
+
*/
|
|
8
|
+
export type ShowMessageOptions = {
|
|
9
|
+
messageType: NonNullable<StatusMessageState["messageType"]>;
|
|
10
|
+
description: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
/** Default: `'alert'`. */
|
|
13
|
+
displayType?: StatusMessageState["displayType"];
|
|
14
|
+
/** Si es `true` el Provider limpia el mensaje a los 6s. Default: `true`. */
|
|
15
|
+
autoReset?: boolean;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* API recomendada para disparar feedback desde un handler. Se monta sobre el
|
|
19
|
+
* contexto para no exponer el `setMessage` crudo (un `Dispatch` que obliga al
|
|
20
|
+
* consumidor a armar el estado completo) y para centralizar los defaults.
|
|
21
|
+
*
|
|
22
|
+
* Recibe un objeto y no parámetros posicionales: con `title`/`autoReset`
|
|
23
|
+
* opcionales, el orden se volvía ilegible (`fn('Ok', undefined, false)`).
|
|
24
|
+
*
|
|
25
|
+
* `showMessage` y `clearMessage` tienen identidad estable, así que se pueden
|
|
26
|
+
* usar como dependencias de un efecto sin re-dispararlo en cada render.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const { showMessage } = useStatusMessage();
|
|
30
|
+
* showMessage({ messageType: 'success', description: 'Cambios guardados' });
|
|
31
|
+
*/
|
|
32
|
+
export declare const useStatusMessage: () => {
|
|
33
|
+
state: StatusMessageState | undefined;
|
|
34
|
+
showMessage: ({ displayType, autoReset, title, ...rest }: ShowMessageOptions) => void;
|
|
35
|
+
clearMessage: () => void;
|
|
36
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { StatusMessageState } from './StatusMessageContext';
|
|
2
|
+
/**
|
|
3
|
+
* Lo que recibe `showMessage`. Mismos nombres que las props de `StatusMessage`
|
|
4
|
+
* para que lo que entra sea lo que el componente termina recibiendo.
|
|
5
|
+
* `messageType` y `description` son obligatorios: sin tipo no hay color/icono
|
|
6
|
+
* y sin descripción `StatusMessage` no renderiza.
|
|
7
|
+
*/
|
|
8
|
+
export type ShowMessageOptions = {
|
|
9
|
+
messageType: NonNullable<StatusMessageState["messageType"]>;
|
|
10
|
+
description: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
/** Default: `'alert'`. */
|
|
13
|
+
displayType?: StatusMessageState["displayType"];
|
|
14
|
+
/** Si es `true` el Provider limpia el mensaje a los 6s. Default: `true`. */
|
|
15
|
+
autoReset?: boolean;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* API recomendada para disparar feedback desde un handler. Se monta sobre el
|
|
19
|
+
* contexto para no exponer el `setMessage` crudo (un `Dispatch` que obliga al
|
|
20
|
+
* consumidor a armar el estado completo) y para centralizar los defaults.
|
|
21
|
+
*
|
|
22
|
+
* Recibe un objeto y no parámetros posicionales: con `title`/`autoReset`
|
|
23
|
+
* opcionales, el orden se volvía ilegible (`fn('Ok', undefined, false)`).
|
|
24
|
+
*
|
|
25
|
+
* `showMessage` y `clearMessage` tienen identidad estable, así que se pueden
|
|
26
|
+
* usar como dependencias de un efecto sin re-dispararlo en cada render.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const { showMessage } = useStatusMessage();
|
|
30
|
+
* showMessage({ messageType: 'success', description: 'Cambios guardados' });
|
|
31
|
+
*/
|
|
32
|
+
export declare const useStatusMessage: () => {
|
|
33
|
+
state: StatusMessageState | undefined;
|
|
34
|
+
showMessage: ({ displayType, autoReset, title, ...rest }: ShowMessageOptions) => void;
|
|
35
|
+
clearMessage: () => void;
|
|
36
|
+
};
|
package/index.cjs
CHANGED
|
@@ -19,7 +19,7 @@ const EmptyState = require("./chunks/EmptyState-C3G5C0DO.cjs");
|
|
|
19
19
|
const Step = require("./chunks/Step-fng1hpkt.cjs");
|
|
20
20
|
const Tab = require("./chunks/Tab-CjCGp0aH.cjs");
|
|
21
21
|
const Table = require("./chunks/Table-BcI9uvYg.cjs");
|
|
22
|
-
const StatusMessage = require("./chunks/StatusMessage-
|
|
22
|
+
const StatusMessage = require("./chunks/StatusMessage-Bl_E83nN.cjs");
|
|
23
23
|
const Modal = require("./chunks/Modal-KRUDCrlp.cjs");
|
|
24
24
|
const Input = require("./chunks/Input-Bcm7XRHs.cjs");
|
|
25
25
|
const Select = require("./chunks/Select-CjiKx_1z.cjs");
|
package/index.mjs
CHANGED
|
@@ -17,7 +17,7 @@ import { E } from "./chunks/EmptyState-CVaRjXkT.mjs";
|
|
|
17
17
|
import { a, S as S3 } from "./chunks/Step-BdgcmiDk.mjs";
|
|
18
18
|
import { a as a2, T } from "./chunks/Tab-BXTh3QSn.mjs";
|
|
19
19
|
import { T as T2 } from "./chunks/Table-DGmx3UyH.mjs";
|
|
20
|
-
import { S as S4 } from "./chunks/StatusMessage-
|
|
20
|
+
import { S as S4 } from "./chunks/StatusMessage-Pa5IutUR.mjs";
|
|
21
21
|
import { M, b, c, a as a3 } from "./chunks/Modal-E1V8hyFI.mjs";
|
|
22
22
|
import { I } from "./chunks/Input-BOt_sv7B.mjs";
|
|
23
23
|
import { O, S as S5 } from "./chunks/Select-CWZJnddP.mjs";
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"StatusMessage-B0oqiu3w.mjs","sources":["../../src/components/StatusMessage/StatusMessage.tsx"],"sourcesContent":["import { forwardRef, useId, useState } from 'react';\nimport {\n Alert,\n Box,\n Typography,\n Dialog,\n DialogContent,\n DialogActions,\n Button,\n} from '@mui/material';\nimport { useThemeProps, type SxProps, type Theme } from '@mui/material/styles';\n\nimport { mergeSx } from '../_shared/mergeSx';\nimport {\n ErrorOutline as ErrorOutlineIcon,\n CheckCircleOutline as CheckCircleOutlineIcon,\n WarningAmber as WarningAmberIcon,\n} from '@mui/icons-material';\n\nexport interface StatusMessageProps {\n /** Título del mensaje. */\n title?: string;\n /** Descripción/contenido detallado. Requerido para que el componente renderice. */\n description?: string;\n /** Tipo de mensaje (controla color + icono). `danger` mapea a `error` de MUI. */\n messageType?: 'success' | 'danger' | 'warning';\n /** Forma de presentación: alerta inline o modal. Default: `'alert'`. */\n displayType?: 'alert' | 'modal';\n /** Callback al cerrar. Si se omite, no se muestra botón de cerrar. */\n close?: () => void;\n /**\n * Controla visibilidad. Si se omite, el componente maneja su propio\n * state (se oculta solo al llamar `close`). Si se pasa, queda controlled\n * y el consumer es responsable de actualizarlo.\n */\n open?: boolean;\n /**\n * sx del nodo raíz: el `Alert` en modo `alert`, el `Dialog` en modo `modal`.\n * Antes el componente no aceptaba ni `sx` ni `className`, así que ajustar su\n * separación desde el call-site era imposible.\n */\n sx?: SxProps<Theme>;\n className?: string;\n}\n\n/**\n * Mensaje de éxito / error / advertencia en forma de alerta inline o modal.\n *\n * - **Uncontrolled**: sin pasar `open`, el componente maneja su propia\n * visibilidad. Al llamar `close`, se oculta automáticamente.\n * - **Controlled**: pasando `open`, el consumer decide cuándo mostrar/ocultar.\n */\nexport const StatusMessage = forwardRef<HTMLDivElement, StatusMessageProps>(\n function StatusMessage(inProps, ref) {\n const props = useThemeProps({ props: inProps, name: 'FriStatusMessage' });\n const {\n title,\n description,\n messageType = 'success',\n displayType = 'alert',\n close,\n open: controlledOpen,\n sx,\n className,\n } = props;\n const [internalOpen, setInternalOpen] = useState(true);\n const titleId = useId();\n const descId = useId();\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const handleClose = () => {\n if (!isControlled) setInternalOpen(false);\n close?.();\n };\n\n const alertVariant = messageType === 'danger' ? 'error' : messageType;\n\n const icon =\n messageType === 'success' ? (\n <CheckCircleOutlineIcon sx={{ fontSize: 64, color: 'success.main' }} />\n ) : messageType === 'danger' ? (\n <ErrorOutlineIcon sx={{ fontSize: 64, color: 'error.main' }} />\n ) : (\n <WarningAmberIcon sx={{ fontSize: 64, color: 'warning.main' }} />\n );\n\n if (!description) return null;\n if (!isOpen) return null;\n\n if (displayType === 'modal') {\n return (\n <Dialog\n ref={ref}\n className={className}\n sx={sx}\n open={isOpen}\n onClose={handleClose}\n aria-labelledby={title ? titleId : undefined}\n aria-describedby={descId}\n maxWidth=\"md\"\n slotProps={{\n paper: {\n sx: { borderRadius: '16px', p: 2 },\n },\n }}\n >\n <DialogContent\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n p: 4,\n gap: 2,\n }}\n >\n <Box sx={{ mb: 2 }}>{icon}</Box>\n {title && (\n <Typography\n id={titleId}\n variant=\"h4\"\n component=\"h2\"\n sx={{ fontWeight: 'bold' }}\n >\n {title}\n </Typography>\n )}\n <Typography id={descId} variant=\"body1\" color=\"text.secondary\">\n {description}\n </Typography>\n </DialogContent>\n <DialogActions sx={{ justifyContent: 'center', p: 2 }}>\n <Button onClick={handleClose} variant=\"contained\" color={alertVariant}>\n Aceptar\n </Button>\n </DialogActions>\n </Dialog>\n );\n }\n\n return (\n <Alert\n ref={ref}\n className={className}\n severity={alertVariant}\n sx={mergeSx({ mb: 2, mt: 2 }, sx)}\n onClose={close !== undefined ? handleClose : undefined}\n >\n {title && (\n <Typography variant=\"h6\" sx={{ fontWeight: 'bold' }}>\n {title}\n </Typography>\n )}\n <Typography variant=\"body2\" sx={{ mt: 1 }}>\n {description}\n </Typography>\n </Alert>\n );\n },\n);\n\nexport default StatusMessage;\n"],"names":["StatusMessage","CheckCircleOutlineIcon","ErrorOutlineIcon","WarningAmberIcon"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"StatusMessage-CV1xnzeu.cjs","sources":["../../src/components/StatusMessage/StatusMessage.tsx"],"sourcesContent":["import { forwardRef, useId, useState } from 'react';\nimport {\n Alert,\n Box,\n Typography,\n Dialog,\n DialogContent,\n DialogActions,\n Button,\n} from '@mui/material';\nimport { useThemeProps, type SxProps, type Theme } from '@mui/material/styles';\n\nimport { mergeSx } from '../_shared/mergeSx';\nimport {\n ErrorOutline as ErrorOutlineIcon,\n CheckCircleOutline as CheckCircleOutlineIcon,\n WarningAmber as WarningAmberIcon,\n} from '@mui/icons-material';\n\nexport interface StatusMessageProps {\n /** Título del mensaje. */\n title?: string;\n /** Descripción/contenido detallado. Requerido para que el componente renderice. */\n description?: string;\n /** Tipo de mensaje (controla color + icono). `danger` mapea a `error` de MUI. */\n messageType?: 'success' | 'danger' | 'warning';\n /** Forma de presentación: alerta inline o modal. Default: `'alert'`. */\n displayType?: 'alert' | 'modal';\n /** Callback al cerrar. Si se omite, no se muestra botón de cerrar. */\n close?: () => void;\n /**\n * Controla visibilidad. Si se omite, el componente maneja su propio\n * state (se oculta solo al llamar `close`). Si se pasa, queda controlled\n * y el consumer es responsable de actualizarlo.\n */\n open?: boolean;\n /**\n * sx del nodo raíz: el `Alert` en modo `alert`, el `Dialog` en modo `modal`.\n * Antes el componente no aceptaba ni `sx` ni `className`, así que ajustar su\n * separación desde el call-site era imposible.\n */\n sx?: SxProps<Theme>;\n className?: string;\n}\n\n/**\n * Mensaje de éxito / error / advertencia en forma de alerta inline o modal.\n *\n * - **Uncontrolled**: sin pasar `open`, el componente maneja su propia\n * visibilidad. Al llamar `close`, se oculta automáticamente.\n * - **Controlled**: pasando `open`, el consumer decide cuándo mostrar/ocultar.\n */\nexport const StatusMessage = forwardRef<HTMLDivElement, StatusMessageProps>(\n function StatusMessage(inProps, ref) {\n const props = useThemeProps({ props: inProps, name: 'FriStatusMessage' });\n const {\n title,\n description,\n messageType = 'success',\n displayType = 'alert',\n close,\n open: controlledOpen,\n sx,\n className,\n } = props;\n const [internalOpen, setInternalOpen] = useState(true);\n const titleId = useId();\n const descId = useId();\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const handleClose = () => {\n if (!isControlled) setInternalOpen(false);\n close?.();\n };\n\n const alertVariant = messageType === 'danger' ? 'error' : messageType;\n\n const icon =\n messageType === 'success' ? (\n <CheckCircleOutlineIcon sx={{ fontSize: 64, color: 'success.main' }} />\n ) : messageType === 'danger' ? (\n <ErrorOutlineIcon sx={{ fontSize: 64, color: 'error.main' }} />\n ) : (\n <WarningAmberIcon sx={{ fontSize: 64, color: 'warning.main' }} />\n );\n\n if (!description) return null;\n if (!isOpen) return null;\n\n if (displayType === 'modal') {\n return (\n <Dialog\n ref={ref}\n className={className}\n sx={sx}\n open={isOpen}\n onClose={handleClose}\n aria-labelledby={title ? titleId : undefined}\n aria-describedby={descId}\n maxWidth=\"md\"\n slotProps={{\n paper: {\n sx: { borderRadius: '16px', p: 2 },\n },\n }}\n >\n <DialogContent\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n p: 4,\n gap: 2,\n }}\n >\n <Box sx={{ mb: 2 }}>{icon}</Box>\n {title && (\n <Typography\n id={titleId}\n variant=\"h4\"\n component=\"h2\"\n sx={{ fontWeight: 'bold' }}\n >\n {title}\n </Typography>\n )}\n <Typography id={descId} variant=\"body1\" color=\"text.secondary\">\n {description}\n </Typography>\n </DialogContent>\n <DialogActions sx={{ justifyContent: 'center', p: 2 }}>\n <Button onClick={handleClose} variant=\"contained\" color={alertVariant}>\n Aceptar\n </Button>\n </DialogActions>\n </Dialog>\n );\n }\n\n return (\n <Alert\n ref={ref}\n className={className}\n severity={alertVariant}\n sx={mergeSx({ mb: 2, mt: 2 }, sx)}\n onClose={close !== undefined ? handleClose : undefined}\n >\n {title && (\n <Typography variant=\"h6\" sx={{ fontWeight: 'bold' }}>\n {title}\n </Typography>\n )}\n <Typography variant=\"body2\" sx={{ mt: 1 }}>\n {description}\n </Typography>\n </Alert>\n );\n },\n);\n\nexport default StatusMessage;\n"],"names":["forwardRef","StatusMessage","useThemeProps","useState","useId","jsx","CheckCircleOutlineIcon","ErrorOutlineIcon","WarningAmberIcon","jsxs","Dialog","DialogContent","Box","Typography","DialogActions","Button","Alert","mergeSx"],"mappings":";;;;;;;AAoDO,MAAM,gBAAgBA,MAAAA;AAAAA,EAC3B,SAASC,eAAc,SAAS,KAAK;AACrC,UAAM,QAAQC,OAAAA,cAAc,EAAE,OAAO,SAAS,MAAM,oBAAoB;AACxE,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,cAAc;AAAA,MACd;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IAAA,IACE;AACJ,UAAM,CAAC,cAAc,eAAe,IAAIC,MAAAA,SAAS,IAAI;AACrD,UAAM,UAAUC,MAAAA,MAAA;AAChB,UAAM,SAASA,MAAAA,MAAA;AAEf,UAAM,eAAe,mBAAmB;AACxC,UAAM,SAAS,eAAe,iBAAiB;AAE/C,UAAM,cAAc,MAAM;AACxB,UAAI,CAAC,aAAc,iBAAgB,KAAK;AACxC;AAAA,IACF;AAEA,UAAM,eAAe,gBAAgB,WAAW,UAAU;AAE1D,UAAM,OACJ,gBAAgB,YACdC,2BAAAA,IAACC,cAAAA,sBAAuB,IAAI,EAAE,UAAU,IAAI,OAAO,eAAA,EAAe,CAAG,IACnE,gBAAgB,WAClBD,+BAACE,cAAAA,cAAA,EAAiB,IAAI,EAAE,UAAU,IAAI,OAAO,eAAa,CAAG,IAE7DF,2BAAAA,IAACG,cAAAA,cAAA,EAAiB,IAAI,EAAE,UAAU,IAAI,OAAO,kBAAkB;AAGnE,QAAI,CAAC,YAAa,QAAO;AACzB,QAAI,CAAC,OAAQ,QAAO;AAEpB,QAAI,gBAAgB,SAAS;AAC3B,aACEC,2BAAAA;AAAAA,QAACC,SAAAA;AAAAA,QAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,SAAS;AAAA,UACT,mBAAiB,QAAQ,UAAU;AAAA,UACnC,oBAAkB;AAAA,UAClB,UAAS;AAAA,UACT,WAAW;AAAA,YACT,OAAO;AAAA,cACL,IAAI,EAAE,cAAc,QAAQ,GAAG,EAAA;AAAA,YAAE;AAAA,UACnC;AAAA,UAGF,UAAA;AAAA,YAAAD,2BAAAA;AAAAA,cAACE,SAAAA;AAAAA,cAAA;AAAA,gBACC,IAAI;AAAA,kBACF,SAAS;AAAA,kBACT,eAAe;AAAA,kBACf,YAAY;AAAA,kBACZ,WAAW;AAAA,kBACX,GAAG;AAAA,kBACH,KAAK;AAAA,gBAAA;AAAA,gBAGP,UAAA;AAAA,kBAAAN,+BAACO,SAAAA,OAAI,IAAI,EAAE,IAAI,EAAA,GAAM,UAAA,MAAK;AAAA,kBACzB,SACCP,2BAAAA;AAAAA,oBAACQ,SAAAA;AAAAA,oBAAA;AAAA,sBACC,IAAI;AAAA,sBACJ,SAAQ;AAAA,sBACR,WAAU;AAAA,sBACV,IAAI,EAAE,YAAY,OAAA;AAAA,sBAEjB,UAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAGLR,2BAAAA,IAACQ,SAAAA,cAAW,IAAI,QAAQ,SAAQ,SAAQ,OAAM,kBAC3C,UAAA,YAAA,CACH;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,2CAEDC,SAAAA,eAAA,EAAc,IAAI,EAAE,gBAAgB,UAAU,GAAG,EAAA,GAChD,UAAAT,2BAAAA,IAACU,SAAAA,QAAA,EAAO,SAAS,aAAa,SAAQ,aAAY,OAAO,cAAc,qBAEvE,EAAA,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAGN;AAEA,WACEN,2BAAAA;AAAAA,MAACO,SAAAA;AAAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,IAAIC,QAAAA,QAAQ,EAAE,IAAI,GAAG,IAAI,EAAA,GAAK,EAAE;AAAA,QAChC,SAAS,UAAU,SAAY,cAAc;AAAA,QAE5C,UAAA;AAAA,UAAA,SACCZ,2BAAAA,IAACQ,uBAAW,SAAQ,MAAK,IAAI,EAAE,YAAY,OAAA,GACxC,UAAA,MAAA,CACH;AAAA,UAEFR,2BAAAA,IAACQ,SAAAA,cAAW,SAAQ,SAAQ,IAAI,EAAE,IAAI,EAAA,GACnC,UAAA,YAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGJ;AACF;;"}
|