flysoft-react-ui 0.5.2 → 1.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/dist/App.d.ts.map +1 -1
- package/dist/App.js +5 -6
- package/dist/components/form-controls/AutocompleteInput.d.ts.map +1 -1
- package/dist/components/form-controls/AutocompleteInput.js +177 -131
- package/dist/components/form-controls/Button.d.ts +3 -0
- package/dist/components/form-controls/Button.d.ts.map +1 -1
- package/dist/components/form-controls/Button.js +160 -19
- package/dist/components/form-controls/Checkbox.d.ts.map +1 -1
- package/dist/components/form-controls/Checkbox.js +3 -1
- package/dist/components/form-controls/DateInput.d.ts +5 -1
- package/dist/components/form-controls/DateInput.d.ts.map +1 -1
- package/dist/components/form-controls/DateInput.js +94 -27
- package/dist/components/form-controls/Input.d.ts.map +1 -1
- package/dist/components/form-controls/Input.js +2 -1
- package/dist/components/form-controls/LinkButton.d.ts +15 -0
- package/dist/components/form-controls/LinkButton.d.ts.map +1 -0
- package/dist/components/form-controls/LinkButton.js +248 -0
- package/dist/components/form-controls/SearchSelectInput-OLD.d.ts.map +1 -1
- package/dist/components/form-controls/SearchSelectInput-OLD.js +5 -4
- package/dist/components/form-controls/SearchSelectInput.d.ts.map +1 -1
- package/dist/components/form-controls/SearchSelectInput.js +3 -2
- package/dist/components/form-controls/index.d.ts +2 -0
- package/dist/components/form-controls/index.d.ts.map +1 -1
- package/dist/components/form-controls/index.js +1 -0
- package/dist/components/layout/Accordion.d.ts +13 -0
- package/dist/components/layout/Accordion.d.ts.map +1 -0
- package/dist/components/layout/Accordion.js +67 -0
- package/dist/components/layout/AppLayout.d.ts.map +1 -1
- package/dist/components/layout/AppLayout.js +7 -7
- package/dist/components/layout/Card.d.ts +8 -3
- package/dist/components/layout/Card.d.ts.map +1 -1
- package/dist/components/layout/Card.js +21 -22
- package/dist/components/layout/DataTable.js +1 -1
- package/dist/components/layout/DropdownMenu.d.ts.map +1 -0
- package/dist/components/{utils → layout}/DropdownMenu.js +12 -6
- package/dist/components/layout/DropdownPanel.d.ts +7 -0
- package/dist/components/layout/DropdownPanel.d.ts.map +1 -0
- package/dist/components/layout/DropdownPanel.js +137 -0
- package/dist/components/{utils → layout}/Filter.d.ts +5 -0
- package/dist/components/layout/Filter.d.ts.map +1 -0
- package/dist/components/{utils → layout}/Filter.js +18 -9
- package/dist/components/layout/Menu.d.ts +31 -0
- package/dist/components/layout/Menu.d.ts.map +1 -0
- package/dist/components/layout/Menu.js +21 -0
- package/dist/components/layout/index.d.ts +10 -0
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/layout/index.js +5 -0
- package/dist/components/utils/Badge.d.ts.map +1 -1
- package/dist/components/utils/Badge.js +3 -2
- package/dist/components/utils/Dialog.d.ts +2 -2
- package/dist/components/utils/Dialog.d.ts.map +1 -1
- package/dist/components/utils/Dialog.js +4 -3
- package/dist/components/utils/FiltersDialog.d.ts +1 -1
- package/dist/components/utils/FiltersDialog.d.ts.map +1 -1
- package/dist/components/utils/FiltersDialog.js +2 -2
- package/dist/components/utils/Loader.js +1 -1
- package/dist/components/utils/RoadMap.d.ts.map +1 -1
- package/dist/components/utils/RoadMap.js +2 -1
- package/dist/components/utils/Snackbar.d.ts.map +1 -1
- package/dist/components/utils/Snackbar.js +2 -1
- package/dist/components/utils/iconUtils.d.ts +16 -0
- package/dist/components/utils/iconUtils.d.ts.map +1 -0
- package/dist/components/utils/iconUtils.js +40 -0
- package/dist/components/utils/index.d.ts +0 -2
- package/dist/components/utils/index.d.ts.map +1 -1
- package/dist/components/utils/index.js +0 -1
- package/dist/contexts/CrudContext.d.ts +62 -0
- package/dist/contexts/CrudContext.d.ts.map +1 -0
- package/dist/contexts/CrudContext.js +333 -0
- package/dist/contexts/index.d.ts +2 -2
- package/dist/contexts/index.d.ts.map +1 -1
- package/dist/contexts/index.js +2 -2
- package/dist/docs/AccordionDocs.d.ts +4 -0
- package/dist/docs/AccordionDocs.d.ts.map +1 -0
- package/dist/docs/AccordionDocs.js +21 -0
- package/dist/docs/AuthDocs.tsx/AuthDocsContent.js +3 -5
- package/dist/docs/AutocompleteInputDocs.js +1 -1
- package/dist/docs/ButtonDocs.d.ts.map +1 -1
- package/dist/docs/ButtonDocs.js +1 -1
- package/dist/docs/CardDocs.d.ts.map +1 -1
- package/dist/docs/CardDocs.js +17 -8
- package/dist/docs/DataTableDocs.js +3 -3
- package/dist/docs/DialogDocs.d.ts.map +1 -1
- package/dist/docs/DialogDocs.js +1 -1
- package/dist/docs/DocAdmin.js +1 -1
- package/dist/docs/DocsMenu.d.ts.map +1 -1
- package/dist/docs/DocsMenu.js +3 -3
- package/dist/docs/DocsRouter.d.ts.map +1 -1
- package/dist/docs/DocsRouter.js +5 -1
- package/dist/docs/DropdownMenuDocs.js +1 -1
- package/dist/docs/DropdownPanelDocs.d.ts +4 -0
- package/dist/docs/DropdownPanelDocs.d.ts.map +1 -0
- package/dist/docs/DropdownPanelDocs.js +7 -0
- package/dist/docs/FilterDocs.d.ts.map +1 -1
- package/dist/docs/FilterDocs.js +19 -1
- package/dist/docs/LinkButtonDocs.d.ts +4 -0
- package/dist/docs/LinkButtonDocs.d.ts.map +1 -0
- package/dist/docs/LinkButtonDocs.js +7 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts +0 -9
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts.map +1 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.js +32 -16
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.js +34 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.js +66 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.js +7 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts +10 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.js +39 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts.map +1 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.js +33 -27
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts +9 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.js +30 -0
- package/dist/docs/MenuDocs.d.ts +4 -0
- package/dist/docs/MenuDocs.d.ts.map +1 -0
- package/dist/docs/MenuDocs.js +26 -0
- package/dist/docs/SearchSelectInputDocs.js +1 -1
- package/dist/docs/docMockServices/empresaService.d.ts +5 -5
- package/dist/docs/docMockServices/empresaService.d.ts.map +1 -1
- package/dist/docs/docMockServices/empresaService.js +20 -11
- package/dist/docs/docMockServices/interfaces.d.ts +12 -0
- package/dist/docs/docMockServices/interfaces.d.ts.map +1 -1
- package/dist/docs/docMockServices/personaEmpresaService.d.ts +6 -6
- package/dist/docs/docMockServices/personaEmpresaService.d.ts.map +1 -1
- package/dist/docs/docMockServices/personaEmpresaService.js +52 -14
- package/dist/docs/docMockServices/personaService.d.ts +2 -2
- package/dist/docs/docMockServices/personaService.d.ts.map +1 -1
- package/dist/docs/docMockServices/personaService.js +17 -7
- package/dist/index.css +1 -1
- package/dist/index.d.ts +12 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/templates/forms/ContactForm.js +2 -2
- package/dist/templates/forms/LoginForm.js +1 -1
- package/dist/templates/forms/RegistrationForm.js +1 -1
- package/dist/templates/layouts/SidebarLayout.d.ts.map +1 -1
- package/dist/templates/layouts/SidebarLayout.js +3 -2
- package/dist/templates/patterns/FormPattern.d.ts.map +1 -1
- package/dist/templates/patterns/FormPattern.js +4 -3
- package/package.json +4 -3
- package/dist/components/utils/DropdownMenu.d.ts.map +0 -1
- package/dist/components/utils/Filter.d.ts.map +0 -1
- package/dist/contexts/ListCrudContext.d.ts +0 -29
- package/dist/contexts/ListCrudContext.d.ts.map +0 -1
- package/dist/contexts/ListCrudContext.js +0 -209
- /package/dist/components/{utils → layout}/DropdownMenu.d.ts +0 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Link } from "react-router-dom";
|
|
4
|
+
import { normalizeIconClass } from "../utils/iconUtils";
|
|
5
|
+
// Función helper para convertir nombres de colores comunes a valores CSS válidos
|
|
6
|
+
const getColorValue = (color) => {
|
|
7
|
+
if (!color)
|
|
8
|
+
return undefined;
|
|
9
|
+
// Si ya es un valor CSS válido (hex, rgb, rgba, hsl, etc.), retornarlo
|
|
10
|
+
if (color.startsWith("#") ||
|
|
11
|
+
color.startsWith("rgb") ||
|
|
12
|
+
color.startsWith("hsl")) {
|
|
13
|
+
return color;
|
|
14
|
+
}
|
|
15
|
+
// Mapeo de nombres de colores comunes
|
|
16
|
+
const colorMap = {
|
|
17
|
+
white: "#ffffff",
|
|
18
|
+
black: "#000000",
|
|
19
|
+
"gray-800": "#1f2937",
|
|
20
|
+
"gray-700": "#374151",
|
|
21
|
+
"gray-600": "#4b5563",
|
|
22
|
+
"gray-500": "#6b7280",
|
|
23
|
+
"gray-400": "#9ca3af",
|
|
24
|
+
"gray-300": "#d1d5db",
|
|
25
|
+
"gray-200": "#e5e7eb",
|
|
26
|
+
"gray-100": "#f3f4f6",
|
|
27
|
+
"gray-50": "#f9fafb",
|
|
28
|
+
};
|
|
29
|
+
return colorMap[color.toLowerCase()] || color;
|
|
30
|
+
};
|
|
31
|
+
export const LinkButton = ({ to, target, variant = "primary", size = "md", color = "primary", bg, textColor, icon, iconPosition = "left", children, className = "", onClick, ...props }) => {
|
|
32
|
+
const [ripples, setRipples] = React.useState([]);
|
|
33
|
+
const baseClasses = `
|
|
34
|
+
inline-flex items-center justify-center font-medium rounded-sm transition-colors
|
|
35
|
+
cursor-pointer relative overflow-hidden no-underline outline-none focus:outline-none
|
|
36
|
+
focus-visible:outline-none active:outline-none focus:ring-0 focus:ring-offset-0
|
|
37
|
+
font-[var(--font-default)]
|
|
38
|
+
`;
|
|
39
|
+
// Mapeo de clases para variant primary con color primary (usa Tailwind)
|
|
40
|
+
const getVariantClasses = (variantType, colorType) => {
|
|
41
|
+
// Solo usar clases Tailwind para primary con color primary
|
|
42
|
+
if (colorType === "primary") {
|
|
43
|
+
if (variantType === "primary") {
|
|
44
|
+
return `
|
|
45
|
+
bg-[var(--color-primary)] text-[var(--color-primary-contrast)]
|
|
46
|
+
hover:bg-[var(--color-primary-dark)]
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
else if (variantType === "outline") {
|
|
50
|
+
return `
|
|
51
|
+
border border-[var(--color-primary)] text-[var(--color-primary)]
|
|
52
|
+
hover:bg-[var(--color-bg-secondary)]
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return `
|
|
57
|
+
text-[var(--color-primary)] hover:bg-[var(--color-bg-secondary)]
|
|
58
|
+
`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Para otros colores, retornar clases base sin color (se aplicarán con estilos inline)
|
|
62
|
+
if (variantType === "primary") {
|
|
63
|
+
return ``;
|
|
64
|
+
}
|
|
65
|
+
else if (variantType === "outline") {
|
|
66
|
+
return `border hover:bg-[var(--color-bg-secondary)]`;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return `hover:bg-[var(--color-bg-secondary)]`;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
// Si se proporciona bg personalizado, no usar las clases de variante
|
|
73
|
+
const variantClasses = bg ? "" : getVariantClasses(variant, color);
|
|
74
|
+
// Determinar si necesitamos usar estilos inline para colores del sistema
|
|
75
|
+
const needsInlineStyles = !bg && color !== "primary";
|
|
76
|
+
const sizeClasses = {
|
|
77
|
+
sm: `${children ? "px-3 py-1.5" : "p-1.5"} text-sm`,
|
|
78
|
+
md: `${children ? "px-4 py-2" : "p-2"} text-base`,
|
|
79
|
+
lg: `${children ? "px-6 py-3" : "p-3"} text-lg`,
|
|
80
|
+
};
|
|
81
|
+
// Clases adicionales para variant outline cuando hay bg personalizado
|
|
82
|
+
const outlineClasses = bg && variant === "outline" ? "border" : "";
|
|
83
|
+
const classes = `${baseClasses} ${variantClasses} ${sizeClasses[size]} ${outlineClasses} ${className}`;
|
|
84
|
+
// Función para obtener el valor de una variable CSS
|
|
85
|
+
const getCSSVariable = (varName) => {
|
|
86
|
+
if (typeof window !== "undefined") {
|
|
87
|
+
const value = getComputedStyle(document.documentElement)
|
|
88
|
+
.getPropertyValue(varName)
|
|
89
|
+
.trim();
|
|
90
|
+
// Si no se encuentra la variable, intentar con el prefijo flysoft
|
|
91
|
+
if (!value && varName.startsWith("--color-")) {
|
|
92
|
+
const flysoftVarName = varName.replace("--color-", "--flysoft-");
|
|
93
|
+
return (getComputedStyle(document.documentElement)
|
|
94
|
+
.getPropertyValue(flysoftVarName)
|
|
95
|
+
.trim() || value);
|
|
96
|
+
}
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
return "";
|
|
100
|
+
};
|
|
101
|
+
// Estilos inline para colores personalizados o colores del sistema (no primary)
|
|
102
|
+
const inlineStyles = bg
|
|
103
|
+
? {
|
|
104
|
+
backgroundColor: variant === "primary" ? getColorValue(bg) || bg : undefined,
|
|
105
|
+
color: getColorValue(textColor) ||
|
|
106
|
+
textColor ||
|
|
107
|
+
(variant === "primary" ? "#ffffff" : getColorValue(bg) || bg),
|
|
108
|
+
borderColor: variant === "outline" ? getColorValue(bg) || bg : undefined,
|
|
109
|
+
...(variant === "ghost" && {
|
|
110
|
+
color: getColorValue(textColor) || textColor || getColorValue(bg) || bg,
|
|
111
|
+
}),
|
|
112
|
+
}
|
|
113
|
+
: needsInlineStyles
|
|
114
|
+
? {
|
|
115
|
+
...(variant === "primary" && {
|
|
116
|
+
backgroundColor: getCSSVariable(`--color-${color}`),
|
|
117
|
+
color: getCSSVariable(`--color-${color}-contrast`) || "#ffffff",
|
|
118
|
+
}),
|
|
119
|
+
...(variant === "outline" && {
|
|
120
|
+
borderColor: getCSSVariable(`--color-${color}`),
|
|
121
|
+
color: getCSSVariable(`--color-${color}`),
|
|
122
|
+
}),
|
|
123
|
+
...(variant === "ghost" && {
|
|
124
|
+
color: getCSSVariable(`--color-${color}`),
|
|
125
|
+
}),
|
|
126
|
+
}
|
|
127
|
+
: {};
|
|
128
|
+
// Función para oscurecer un color (para hover en variant primary con bg personalizado)
|
|
129
|
+
const darkenColor = (color, percent) => {
|
|
130
|
+
const hex = color.replace("#", "");
|
|
131
|
+
const num = parseInt(hex, 16);
|
|
132
|
+
const r = Math.max(0, Math.floor((num >> 16) * (1 - percent / 100)));
|
|
133
|
+
const g = Math.max(0, Math.floor(((num >> 8) & 0x00ff) * (1 - percent / 100)));
|
|
134
|
+
const b = Math.max(0, Math.floor((num & 0x0000ff) * (1 - percent / 100)));
|
|
135
|
+
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, "0")}`;
|
|
136
|
+
};
|
|
137
|
+
const renderIcon = () => {
|
|
138
|
+
if (!icon)
|
|
139
|
+
return null;
|
|
140
|
+
const iconClasses = size === "sm" ? "w-4 h-4" : size === "md" ? "w-5 h-5" : "w-6 h-6";
|
|
141
|
+
return (_jsx("i", { className: `${normalizeIconClass(icon)} ${iconClasses} ${children ? (iconPosition === "right" ? "ml-2" : "mr-2") : ""} mt-0.5` }));
|
|
142
|
+
};
|
|
143
|
+
// Determinar el color del ripple basado en el variant y si hay bg personalizado
|
|
144
|
+
const rippleColor = bg
|
|
145
|
+
? variant === "primary"
|
|
146
|
+
? "rgba(255, 255, 255, 0.45)"
|
|
147
|
+
: "rgba(0, 0, 0, 0.15)"
|
|
148
|
+
: variant === "primary"
|
|
149
|
+
? "rgba(255, 255, 255, 0.45)"
|
|
150
|
+
: "rgba(0, 0, 0, 0.15)";
|
|
151
|
+
const handleClick = (event) => {
|
|
152
|
+
const targetElement = event.currentTarget;
|
|
153
|
+
if (targetElement) {
|
|
154
|
+
const rect = targetElement.getBoundingClientRect();
|
|
155
|
+
const size = Math.max(rect.width, rect.height) * 1.2;
|
|
156
|
+
const x = event.clientX - rect.left;
|
|
157
|
+
const y = event.clientY - rect.top;
|
|
158
|
+
const id = window.performance.now();
|
|
159
|
+
const newRipple = { id, x, y, size };
|
|
160
|
+
setRipples((prev) => [...prev, newRipple]);
|
|
161
|
+
window.setTimeout(() => {
|
|
162
|
+
setRipples((prev) => prev.filter((ripple) => ripple.id !== id));
|
|
163
|
+
}, 600);
|
|
164
|
+
}
|
|
165
|
+
onClick?.(event);
|
|
166
|
+
};
|
|
167
|
+
// Determinar si es una ruta externa (http/https) o interna
|
|
168
|
+
const isExternal = to.startsWith("http://") || to.startsWith("https://") || to.startsWith("mailto:") || to.startsWith("tel:");
|
|
169
|
+
// Combinar estilos inline - agregar outline: none para asegurar que no aparezca
|
|
170
|
+
const combinedStyles = {
|
|
171
|
+
...inlineStyles,
|
|
172
|
+
outline: "none",
|
|
173
|
+
outlineWidth: "0",
|
|
174
|
+
outlineStyle: "none",
|
|
175
|
+
outlineOffset: "0",
|
|
176
|
+
WebkitTapHighlightColor: "transparent",
|
|
177
|
+
boxShadow: "none",
|
|
178
|
+
};
|
|
179
|
+
const linkProps = {
|
|
180
|
+
className: classes,
|
|
181
|
+
style: combinedStyles,
|
|
182
|
+
onClick: handleClick,
|
|
183
|
+
onFocus: (e) => {
|
|
184
|
+
e.currentTarget.style.outline = "none";
|
|
185
|
+
e.currentTarget.style.outlineWidth = "0";
|
|
186
|
+
e.currentTarget.style.outlineStyle = "none";
|
|
187
|
+
e.currentTarget.style.outlineOffset = "0";
|
|
188
|
+
e.currentTarget.style.boxShadow = "none";
|
|
189
|
+
},
|
|
190
|
+
onBlur: (e) => {
|
|
191
|
+
e.currentTarget.style.outline = "none";
|
|
192
|
+
e.currentTarget.style.outlineWidth = "0";
|
|
193
|
+
e.currentTarget.style.outlineStyle = "none";
|
|
194
|
+
e.currentTarget.style.outlineOffset = "0";
|
|
195
|
+
e.currentTarget.style.boxShadow = "none";
|
|
196
|
+
},
|
|
197
|
+
onKeyDown: (e) => {
|
|
198
|
+
// Eliminar outline cuando se presiona cualquier tecla
|
|
199
|
+
if (e.key === "Tab" || e.key === "Enter" || e.key === " ") {
|
|
200
|
+
e.currentTarget.style.outline = "none";
|
|
201
|
+
e.currentTarget.style.outlineWidth = "0";
|
|
202
|
+
e.currentTarget.style.outlineStyle = "none";
|
|
203
|
+
e.currentTarget.style.outlineOffset = "0";
|
|
204
|
+
e.currentTarget.style.boxShadow = "none";
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
onMouseEnter: (e) => {
|
|
208
|
+
if (variant === "primary") {
|
|
209
|
+
if (bg) {
|
|
210
|
+
const hoverBg = darkenColor(getColorValue(bg) || bg, 15);
|
|
211
|
+
e.currentTarget.style.backgroundColor = hoverBg;
|
|
212
|
+
}
|
|
213
|
+
else if (needsInlineStyles) {
|
|
214
|
+
const hoverBg = getCSSVariable(`--color-${color}-dark`);
|
|
215
|
+
e.currentTarget.style.backgroundColor = hoverBg;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
onMouseLeave: (e) => {
|
|
220
|
+
if (variant === "primary") {
|
|
221
|
+
if (bg) {
|
|
222
|
+
e.currentTarget.style.backgroundColor = getColorValue(bg) || bg;
|
|
223
|
+
}
|
|
224
|
+
else if (needsInlineStyles) {
|
|
225
|
+
e.currentTarget.style.backgroundColor = getCSSVariable(`--color-${color}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
...props,
|
|
230
|
+
};
|
|
231
|
+
if (isExternal) {
|
|
232
|
+
const externalTarget = target || "_blank";
|
|
233
|
+
return (_jsxs("a", { href: to, target: externalTarget, rel: externalTarget === "_blank" ? "noopener noreferrer" : undefined, ...linkProps, children: [_jsx("span", { className: "absolute inset-0 pointer-events-none", children: ripples.map((ripple) => (_jsx("span", { className: "absolute rounded-full opacity-40 flysoft-button-ripple", style: {
|
|
234
|
+
top: ripple.y,
|
|
235
|
+
left: ripple.x,
|
|
236
|
+
width: ripple.size,
|
|
237
|
+
height: ripple.size,
|
|
238
|
+
backgroundColor: rippleColor,
|
|
239
|
+
} }, ripple.id))) }), _jsxs("span", { className: "relative inline-flex items-center justify-center", children: [icon && iconPosition === "left" && renderIcon(), children, icon && iconPosition === "right" && renderIcon()] })] }));
|
|
240
|
+
}
|
|
241
|
+
return (_jsxs(Link, { to: to, ...linkProps, children: [_jsx("span", { className: "absolute inset-0 pointer-events-none", children: ripples.map((ripple) => (_jsx("span", { className: "absolute rounded-full opacity-40 flysoft-button-ripple", style: {
|
|
242
|
+
top: ripple.y,
|
|
243
|
+
left: ripple.x,
|
|
244
|
+
width: ripple.size,
|
|
245
|
+
height: ripple.size,
|
|
246
|
+
backgroundColor: rippleColor,
|
|
247
|
+
} }, ripple.id))) }), _jsxs("span", { className: "relative inline-flex items-center justify-center", children: [icon && iconPosition === "left" && renderIcon(), children, icon && iconPosition === "right" && renderIcon()] })] }));
|
|
248
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchSelectInput-OLD.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/SearchSelectInput-OLD.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchSelectInput-OLD.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/SearchSelectInput-OLD.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC,GAAG,kBAAkB,EAAE,CAAC,GAAG,MAAM,CACxE,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;IACtD;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EACP,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,GACxB,KAAK,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAC7C;;OAEG;IACH,iBAAiB,EAAE,CACjB,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD;;;;OAIG;IACH,uBAAuB,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC9D;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;IAChC;;OAEG;IACH,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAChE;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;CAC7C;AA6sCD,eAAO,MAAM,iBAAiB,EAAiC,CAC7D,CAAC,GAAG,kBAAkB,EACtB,CAAC,GAAG,MAAM,EAEV,KAAK,EAAE,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IACpC,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;CAC5C,KACE,KAAK,CAAC,YAAY,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { useFormContext } from "react-hook-form";
|
|
|
4
4
|
import { Input } from "./Input";
|
|
5
5
|
import { Button } from "./Button";
|
|
6
6
|
import { Dialog } from "../utils/Dialog";
|
|
7
|
+
import { normalizeIconClass } from "../utils/iconUtils";
|
|
7
8
|
function SearchSelectInputInner({ value, onChange, onSearchPromiseFn, onSingleSearchPromiseFn, onSelectOption, dialogTitle = "Seleccione una opción", searchButtonPosition = "right", noResultsText = "Sin resultados", getOptionLabel, getOptionValue, getOptionDescription, renderOption, className = "", size = "md", ...inputProps }, ref) {
|
|
8
9
|
// Extraer onBlur de inputProps para manejarlo por separado
|
|
9
10
|
const { onBlur: registerOnBlur, ...restInputProps } = inputProps;
|
|
@@ -944,18 +945,18 @@ function SearchSelectInputInner({ value, onChange, onSearchPromiseFn, onSingleSe
|
|
|
944
945
|
restInputProps.onFocus(e);
|
|
945
946
|
}
|
|
946
947
|
handleInputFocus(e);
|
|
947
|
-
}, onBlur: registerOnBlur, onKeyDown: handleKeyDown, size: size, icon: displayIcon, iconPosition: displayIconPosition, onIconClick: displayOnIconClick, readOnly: true }) }), _jsx(Dialog, { isOpen: isDialogOpen, title: dialogTitle,
|
|
948
|
+
}, onBlur: registerOnBlur, onKeyDown: handleKeyDown, size: size, icon: displayIcon, iconPosition: displayIconPosition, onIconClick: displayOnIconClick, readOnly: true }) }), _jsx(Dialog, { isOpen: isDialogOpen, title: dialogTitle, children: _jsxs("div", { className: "space-y-2", children: [_jsx(Input, { value: dialogSearchText, onChange: (e) => setDialogSearchText(e.target.value), onKeyDown: (e) => {
|
|
948
949
|
if (e.key === "Enter") {
|
|
949
950
|
e.preventDefault();
|
|
950
951
|
handleDialogSearch();
|
|
951
952
|
}
|
|
952
|
-
}, icon: "fa-search", iconPosition: "right", onIconClick: dialogSearchText.trim() ? handleDialogSearch : undefined, size: size, placeholder: "Buscar...", autoFocus: true }), isLoading ? (_jsx("div", { className: "flex items-center justify-center py-8", children: _jsx("i", { className: "
|
|
953
|
+
}, icon: "fa-search", iconPosition: "right", onIconClick: dialogSearchText.trim() ? handleDialogSearch : undefined, size: size, placeholder: "Buscar...", autoFocus: true }), isLoading ? (_jsx("div", { className: "flex items-center justify-center py-8", children: _jsx("i", { className: "fal fa-spinner fa-spin text-2xl text-[var(--color-primary)]" }) })) : options.length > 0 ? (_jsx("ul", { className: "space-y-1 max-h-96 overflow-y-auto", children: options.map((option, index) => {
|
|
953
954
|
const label = labelGetter(option);
|
|
954
955
|
const description = descriptionGetter(option);
|
|
955
956
|
const anyOption = option;
|
|
956
|
-
return (_jsx("li", { className: "px-3 py-2 cursor-pointer rounded-md flex items-start gap-2 text-sm\r\n text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors", onClick: () => handleSelect(option), children: renderOption ? (renderOption(option)) : (_jsxs(_Fragment, { children: [anyOption.icon && (_jsx("i", { className:
|
|
957
|
+
return (_jsx("li", { className: "px-3 py-2 cursor-pointer rounded-md flex items-start gap-2 text-sm\r\n text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors", onClick: () => handleSelect(option), children: renderOption ? (renderOption(option)) : (_jsxs(_Fragment, { children: [anyOption.icon && (_jsx("i", { className: `${normalizeIconClass(anyOption.icon)} mt-0.5 text-[var(--color-text-muted)]` })), _jsxs("div", { className: "flex flex-col flex-1", children: [_jsx("span", { className: "font-[var(--font-default)]", children: label }), description !== undefined &&
|
|
957
958
|
description !== null && (_jsx("span", { className: "text-xs text-[var(--color-text-secondary)]", children: description }))] })] })) }, String(valueGetter(option) ?? label ?? index)));
|
|
958
|
-
}) })) : hasSearched ? (_jsx("div", { className: "px-3 py-8 text-center text-sm text-[var(--color-text-secondary)]", children: noResultsText })) : null] }),
|
|
959
|
+
}) })) : hasSearched ? (_jsx("div", { className: "px-3 py-8 text-center text-sm text-[var(--color-text-secondary)]", children: noResultsText })) : null] }), footer: _jsx(Button, { variant: "outline", onClick: () => setIsDialogOpen(false), children: "Cerrar" }), onClose: () => setIsDialogOpen(false), closeOnOverlayClick: true })] }));
|
|
959
960
|
}
|
|
960
961
|
const SearchSelectInputForwarded = React.forwardRef(SearchSelectInputInner);
|
|
961
962
|
SearchSelectInputForwarded.displayName = "SearchSelectInput";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchSelectInput.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/SearchSelectInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAEf,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchSelectInput.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/SearchSelectInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAEf,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAKxD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,sBAAsB,CAAC,CAAC,GAAG,kBAAkB,EAAE,CAAC,GAAG,MAAM,CACxE,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;IACtD,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EACP,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,GACxB,KAAK,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAC7C;;OAEG;IACH,iBAAiB,EAAE,CACjB,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD;;;;OAIG;IACH,uBAAuB,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC9D;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;IAChC;;OAEG;IACH,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAChE;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAyfD,eAAO,MAAM,iBAAiB,EAA6B,CACzD,CAAC,GAAG,kBAAkB,EACtB,CAAC,GAAG,MAAM,EAEV,KAAK,EAAE,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IACpC,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;CAC5C,KACE,KAAK,CAAC,YAAY,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { useFormContext } from "react-hook-form";
|
|
|
4
4
|
import { Input } from "./Input";
|
|
5
5
|
import { Button } from "./Button";
|
|
6
6
|
import { Dialog, Loader } from "../utils";
|
|
7
|
+
import { normalizeIconClass } from "../utils/iconUtils";
|
|
7
8
|
const SearchSelectInputInner = React.forwardRef(function SearchSelectInput({ value, onChange, onSearchPromiseFn, onSingleSearchPromiseFn, onSelectOption, dialogTitle = "Seleccione una opción", icon = "fa-search", iconPosition = "right", noResultsText = "Sin resultados", getOptionLabel, getOptionValue, getOptionDescription, renderOption, label, readOnly = false, ...inputProps }, ref) {
|
|
8
9
|
const [inputText, setInputText] = useState("");
|
|
9
10
|
const [dialogInputText, setDialogInputText] = useState("");
|
|
@@ -249,7 +250,7 @@ const SearchSelectInputInner = React.forwardRef(function SearchSelectInput({ val
|
|
|
249
250
|
const label = labelGetter(option);
|
|
250
251
|
const description = descriptionGetter(option);
|
|
251
252
|
const anyOption = option;
|
|
252
|
-
return (_jsx("li", { className: "px-3 py-2 cursor-pointer rounded-md flex items-start gap-2 text-sm\r\n text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors", onClick: () => handleSelect(option), children: renderOption ? (renderOption(option)) : (_jsxs(_Fragment, { children: [anyOption.icon && (_jsx("i", { className:
|
|
253
|
+
return (_jsx("li", { className: "px-3 py-2 cursor-pointer rounded-md flex items-start gap-2 text-sm\r\n text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors", onClick: () => handleSelect(option), children: renderOption ? (renderOption(option)) : (_jsxs(_Fragment, { children: [anyOption.icon && (_jsx("i", { className: `${normalizeIconClass(anyOption.icon)} mt-0.5 text-[var(--color-text-muted)]` })), _jsxs("div", { className: "flex flex-col flex-1", children: [_jsx("span", { className: "font-[var(--font-default)]", children: label }), description !== undefined &&
|
|
253
254
|
description !== null && (_jsx("span", { className: "text-xs text-[var(--color-text-secondary)]", children: description }))] })] })) }, String(valueGetter(option) ?? label ?? index)));
|
|
254
255
|
}) }) })) : (_jsx("div", { className: "px-3 py-8 text-center text-sm text-[var(--color-text-secondary)]", children: noResultsText })) }) })] }));
|
|
255
256
|
};
|
|
@@ -328,7 +329,7 @@ const SearchSelectInputInner = React.forwardRef(function SearchSelectInput({ val
|
|
|
328
329
|
if (!readOnly && !justClearedRef.current) {
|
|
329
330
|
setIsDialogOpen(true);
|
|
330
331
|
}
|
|
331
|
-
}, icon: displayIcon, iconPosition: displayIconPosition, onIconClick: displayOnIconClick, readOnly: readOnly }), !readOnly && (_jsx(Dialog, { isOpen: isDialogOpen, title: dialogTitle,
|
|
332
|
+
}, icon: displayIcon, iconPosition: displayIconPosition, onIconClick: displayOnIconClick, readOnly: readOnly }), !readOnly && (_jsx(Dialog, { isOpen: isDialogOpen, title: dialogTitle, footer: _jsx(Button, { variant: "outline", onClick: () => setIsDialogOpen(false), children: "Cerrar" }), onClose: () => setIsDialogOpen(false), children: getDialogBody() }))] }));
|
|
332
333
|
});
|
|
333
334
|
SearchSelectInputInner.displayName = "SearchSelectInput";
|
|
334
335
|
// Exportar con el cast genérico para permitir uso como <SearchSelectInput<T, K>>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Button } from "./Button";
|
|
2
|
+
export { LinkButton } from "./LinkButton";
|
|
2
3
|
export { Input } from "./Input";
|
|
3
4
|
export { AutocompleteInput } from "./AutocompleteInput";
|
|
4
5
|
export { SearchSelectInput } from "./SearchSelectInput-OLD";
|
|
@@ -8,6 +9,7 @@ export { Pagination } from "./Pagination";
|
|
|
8
9
|
export { Checkbox } from "./Checkbox";
|
|
9
10
|
export { RadioButtonGroup } from "./RadioButtonGroup";
|
|
10
11
|
export type { ButtonProps } from "./Button";
|
|
12
|
+
export type { LinkButtonProps } from "./LinkButton";
|
|
11
13
|
export type { InputProps } from "./Input";
|
|
12
14
|
export type { AutocompleteInputProps, AutocompleteOption, } from "./AutocompleteInput";
|
|
13
15
|
export type { SearchSelectInputProps, SearchSelectOption, } from "./SearchSelectInput-OLD";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EACV,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACzE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/form-controls/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EACV,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACzE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface AccordionProps {
|
|
3
|
+
title: string | React.ReactNode;
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
icon?: string;
|
|
6
|
+
rightNode?: React.ReactNode;
|
|
7
|
+
defaultOpen?: boolean;
|
|
8
|
+
className?: string;
|
|
9
|
+
variant?: "default" | "elevated" | "outlined";
|
|
10
|
+
onToggle?: (isOpen: boolean) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare const Accordion: React.FC<AccordionProps>;
|
|
13
|
+
//# sourceMappingURL=Accordion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Accordion.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC9C,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CACtC;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAgI9C,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { useState, useRef, useEffect } from "react";
|
|
3
|
+
import { normalizeIconClass } from "../utils/iconUtils";
|
|
4
|
+
export const Accordion = ({ title, children, icon, rightNode, defaultOpen = false, className = "", variant = "default", onToggle, }) => {
|
|
5
|
+
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
6
|
+
const [contentHeight, setContentHeight] = useState(0);
|
|
7
|
+
const contentRef = useRef(null);
|
|
8
|
+
// Separar clases de background del className
|
|
9
|
+
const classArray = className.trim().split(/\s+/).filter(Boolean);
|
|
10
|
+
const bgClasses = [];
|
|
11
|
+
const otherClasses = [];
|
|
12
|
+
classArray.forEach((cls) => {
|
|
13
|
+
// Detectar clases de background (bg-*, bg-gradient-*, bg-[...])
|
|
14
|
+
if (cls.startsWith("bg-") || cls.startsWith("bg-gradient-")) {
|
|
15
|
+
bgClasses.push(cls);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
otherClasses.push(cls);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const backgroundClass = bgClasses.length > 0 ? bgClasses.join(" ") : "bg-[var(--color-bg-default)]";
|
|
22
|
+
const baseClasses = `
|
|
23
|
+
${backgroundClass} rounded-lg border
|
|
24
|
+
font-[var(--font-default)]
|
|
25
|
+
`;
|
|
26
|
+
const variantClasses = {
|
|
27
|
+
default: `border-[var(--color-border-default)]`,
|
|
28
|
+
elevated: `border-[var(--color-border-default)] shadow-[var(--shadow-lg)]`,
|
|
29
|
+
outlined: `border-[var(--color-gray-300)]`,
|
|
30
|
+
};
|
|
31
|
+
const classes = `${baseClasses} ${variantClasses[variant]} ${otherClasses.join(" ")}`;
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (contentRef.current) {
|
|
34
|
+
if (isOpen) {
|
|
35
|
+
// Usar requestAnimationFrame para asegurar que el DOM esté actualizado
|
|
36
|
+
requestAnimationFrame(() => {
|
|
37
|
+
if (contentRef.current) {
|
|
38
|
+
setContentHeight(contentRef.current.scrollHeight);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
setContentHeight(0);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}, [isOpen, children]);
|
|
47
|
+
// Inicializar altura si está abierto por defecto
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (defaultOpen && contentRef.current) {
|
|
50
|
+
requestAnimationFrame(() => {
|
|
51
|
+
if (contentRef.current) {
|
|
52
|
+
setContentHeight(contentRef.current.scrollHeight);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}, [defaultOpen]);
|
|
57
|
+
const handleToggle = () => {
|
|
58
|
+
const newIsOpen = !isOpen;
|
|
59
|
+
setIsOpen(newIsOpen);
|
|
60
|
+
if (onToggle) {
|
|
61
|
+
onToggle(newIsOpen);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
return (_jsxs("div", { className: `${classes} overflow-hidden`, children: [_jsxs("button", { onClick: handleToggle, className: "w-full flex items-center justify-between px-4 py-3 hover:bg-black/5 dark:hover:bg-white/5 transition-colors cursor-pointer", "aria-expanded": isOpen, children: [_jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [icon && (_jsx("i", { className: `${normalizeIconClass(icon)} text-[var(--color-text-secondary)] flex-shrink-0` })), _jsx("span", { className: "text-left font-medium text-[var(--color-text-primary)] truncate", children: title })] }), _jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [rightNode && (_jsx("div", { className: "flex items-center", onClick: (e) => e.stopPropagation(), children: rightNode })), _jsx("i", { className: `${normalizeIconClass(`fa-chevron-${isOpen ? "up" : "down"}`)} text-[var(--color-text-secondary)] transition-all duration-200 flex-shrink-0` })] })] }), _jsx("div", { ref: contentRef, className: "overflow-hidden transition-all duration-300 ease-in-out", style: {
|
|
65
|
+
maxHeight: `${contentHeight}px`,
|
|
66
|
+
}, children: _jsx("div", { className: "px-4 py-3 text-[var(--color-text-primary)]", children: children }) })] }));
|
|
67
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppLayout.d.ts","sourceRoot":"","sources":["../../../src/components/layout/AppLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2B,MAAM,OAAO,CAAC;AAIhD,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACpB,MAAM,iCAAiC,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,
|
|
1
|
+
{"version":3,"file":"AppLayout.d.ts","sourceRoot":"","sources":["../../../src/components/layout/AppLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2B,MAAM,OAAO,CAAC;AAIhD,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACpB,MAAM,iCAAiC,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAgd9C,CAAC"}
|
|
@@ -116,7 +116,7 @@ export const AppLayout = ({ navbar, leftDrawer, children, className = "", }) =>
|
|
|
116
116
|
const navbarStyle = fullWidthNavbar
|
|
117
117
|
? {
|
|
118
118
|
transform: isNavbarVisible ? "translateY(0)" : "translateY(-100%)",
|
|
119
|
-
transition: "transform
|
|
119
|
+
transition: "transform 100ms ease-in",
|
|
120
120
|
willChange: "transform",
|
|
121
121
|
height: navbarHeight, // Override any height classes in className
|
|
122
122
|
}
|
|
@@ -124,7 +124,7 @@ export const AppLayout = ({ navbar, leftDrawer, children, className = "", }) =>
|
|
|
124
124
|
height: isNavbarVisible ? navbarHeight : "0",
|
|
125
125
|
minHeight: isNavbarVisible ? navbarHeight : "0",
|
|
126
126
|
maxHeight: isNavbarVisible ? navbarHeight : "0",
|
|
127
|
-
transition: "height
|
|
127
|
+
transition: "height 100ms ease-in, min-height 100ms ease-in, max-height 100ms ease-in",
|
|
128
128
|
overflow: "hidden",
|
|
129
129
|
};
|
|
130
130
|
const navbarContentClasses = `flex items-center justify-between gap-2`;
|
|
@@ -135,13 +135,13 @@ export const AppLayout = ({ navbar, leftDrawer, children, className = "", }) =>
|
|
|
135
135
|
height: fullWidthNavbar || isNavbarVisible ? navbarHeight : "0",
|
|
136
136
|
maxHeight: fullWidthNavbar || isNavbarVisible ? navbarHeight : "0",
|
|
137
137
|
overflow: "hidden",
|
|
138
|
-
transition: "height
|
|
138
|
+
transition: "height 100ms ease-in, max-height 100ms ease-in",
|
|
139
139
|
opacity: isNavbarVisible || fullWidthNavbar ? 1 : 0,
|
|
140
140
|
};
|
|
141
141
|
const navbarLeftClasses = `flex items-center gap-2`;
|
|
142
142
|
const navbarRightClasses = `flex items-center gap-2`;
|
|
143
143
|
// Clases del contenido principal
|
|
144
|
-
const mainClasses = `flex flex-1 overflow-hidden transition-all duration-
|
|
144
|
+
const mainClasses = `flex flex-1 overflow-hidden transition-all duration-100 ease-in`;
|
|
145
145
|
// Style for main content with dynamic navbar height padding
|
|
146
146
|
const mainStyle = fullWidthNavbar && shouldShowNavbar && isNavbarVisible
|
|
147
147
|
? { paddingTop: navbarHeight }
|
|
@@ -151,7 +151,7 @@ export const AppLayout = ({ navbar, leftDrawer, children, className = "", }) =>
|
|
|
151
151
|
const leftDrawerClasses = `
|
|
152
152
|
${leftDrawerWidth ? "" : "w-64"} bg-[var(--color-bg-default)]
|
|
153
153
|
flex-shrink-0 flex flex-col
|
|
154
|
-
transition-all duration-
|
|
154
|
+
transition-all duration-100 ease-in
|
|
155
155
|
${fullWidthNavbar && shouldShowNavbar && isNavbarVisible ? "pt-4" : "h-full"}
|
|
156
156
|
${leftDrawerClassName}
|
|
157
157
|
`
|
|
@@ -194,7 +194,7 @@ export const AppLayout = ({ navbar, leftDrawer, children, className = "", }) =>
|
|
|
194
194
|
const mobileDrawerBaseClasses = `
|
|
195
195
|
fixed top-0 left-0 h-screen w-64 max-w-[80vw]
|
|
196
196
|
bg-[var(--color-bg-default)] shadow-[var(--shadow-xl)]
|
|
197
|
-
transform -translate-x-full transition-transform duration-
|
|
197
|
+
transform -translate-x-full transition-transform duration-100 ease-in
|
|
198
198
|
z-[1999] flex flex-col
|
|
199
199
|
${leftDrawerClassName}
|
|
200
200
|
`
|
|
@@ -206,5 +206,5 @@ export const AppLayout = ({ navbar, leftDrawer, children, className = "", }) =>
|
|
|
206
206
|
const mobileDrawerContentClasses = `
|
|
207
207
|
flex-1 overflow-y-auto scrollbar-hide
|
|
208
208
|
`;
|
|
209
|
-
return (_jsxs("div", { className: layoutClasses, children: [fullWidthNavbar ? (_jsxs(_Fragment, { children: [shouldShowNavbar && (_jsx("nav", { className: navbarClasses, style: navbarStyle, children: _jsxs("div", { className: navbarContentClasses, style: navbarContentStyle, children: [_jsxs("div", { className: navbarLeftClasses, children: [shouldShowMobileDrawer && hasLeftDrawerContent && (_jsx("div", { className: "pr-4 lg:px-4 md:px-3", children: _jsx(Button, { variant: "ghost", icon: "fa-bars", onClick: handleMobileDrawerToggle, "aria-label": "Abrir men\u00FA" }) })), navBarLeftNode && (_jsx("div", { children: typeof navBarLeftNode === "string" ? (_jsx("span", { children: navBarLeftNode })) : (navBarLeftNode) }))] }), navBarRightNode && (_jsx("div", { className: navbarRightClasses, children: typeof navBarRightNode === "string" ? (_jsx("span", { children: navBarRightNode })) : (navBarRightNode) }))] }) })), _jsxs("div", { className: mainClasses, style: mainStyle, children: [shouldShowDesktopDrawer && (_jsxs("aside", { className: leftDrawerClasses, style: leftDrawerStyle, children: [leftDrawerHeader && (_jsx("div", { className: leftDrawerHeaderClasses, children: leftDrawerHeader })), leftDrawerContent && (_jsx("div", { className: leftDrawerContentClasses, children: leftDrawerContent })), leftDrawerFooter && (_jsx("div", { className: leftDrawerFooterClasses, children: leftDrawerFooter }))] })), _jsx("main", { ref: contentRef, className: contentClasses, children: children })] })] })) : (_jsx(_Fragment, { children: _jsxs("div", { className: contentWrapperClasses, children: [shouldShowDesktopDrawer && (_jsxs("aside", { className: leftDrawerClasses, style: leftDrawerStyle, children: [leftDrawerHeader && (_jsx("div", { className: leftDrawerHeaderClasses, children: leftDrawerHeader })), leftDrawerContent && (_jsx("div", { className: leftDrawerContentClasses, children: leftDrawerContent })), leftDrawerFooter && (_jsx("div", { className: leftDrawerFooterClasses, children: leftDrawerFooter }))] })), _jsxs("div", { className: drawerAndContentClasses, style: drawerAndContentStyle, children: [shouldShowNavbar && (_jsx("nav", { className: navbarClasses, style: navbarStyle, children: _jsxs("div", { className: navbarContentClasses, style: navbarContentStyle, children: [_jsxs("div", { className: navbarLeftClasses, children: [shouldShowMobileDrawer && hasLeftDrawerContent && (_jsx("div", { className: "pr-4
|
|
209
|
+
return (_jsxs("div", { className: layoutClasses, children: [fullWidthNavbar ? (_jsxs(_Fragment, { children: [shouldShowNavbar && (_jsx("nav", { className: navbarClasses, style: navbarStyle, children: _jsxs("div", { className: navbarContentClasses, style: navbarContentStyle, children: [_jsxs("div", { className: navbarLeftClasses, children: [shouldShowMobileDrawer && hasLeftDrawerContent && (_jsx("div", { className: "pr-4 lg:px-4 md:px-3", children: _jsx(Button, { variant: "ghost", icon: "fa-bars", onClick: handleMobileDrawerToggle, "aria-label": "Abrir men\u00FA" }) })), navBarLeftNode && (_jsx("div", { children: typeof navBarLeftNode === "string" ? (_jsx("span", { children: navBarLeftNode })) : (navBarLeftNode) }))] }), navBarRightNode && (_jsx("div", { className: navbarRightClasses, children: typeof navBarRightNode === "string" ? (_jsx("span", { children: navBarRightNode })) : (navBarRightNode) }))] }) })), _jsxs("div", { className: mainClasses, style: mainStyle, children: [shouldShowDesktopDrawer && (_jsxs("aside", { className: leftDrawerClasses, style: leftDrawerStyle, children: [leftDrawerHeader && (_jsx("div", { className: leftDrawerHeaderClasses, children: leftDrawerHeader })), leftDrawerContent && (_jsx("div", { className: leftDrawerContentClasses, children: leftDrawerContent })), leftDrawerFooter && (_jsx("div", { className: leftDrawerFooterClasses, children: leftDrawerFooter }))] })), _jsx("main", { ref: contentRef, className: contentClasses, children: children })] })] })) : (_jsx(_Fragment, { children: _jsxs("div", { className: contentWrapperClasses, children: [shouldShowDesktopDrawer && (_jsxs("aside", { className: leftDrawerClasses, style: leftDrawerStyle, children: [leftDrawerHeader && (_jsx("div", { className: leftDrawerHeaderClasses, children: leftDrawerHeader })), leftDrawerContent && (_jsx("div", { className: leftDrawerContentClasses, children: leftDrawerContent })), leftDrawerFooter && (_jsx("div", { className: leftDrawerFooterClasses, children: leftDrawerFooter }))] })), _jsxs("div", { className: drawerAndContentClasses, style: drawerAndContentStyle, children: [shouldShowNavbar && (_jsx("nav", { className: navbarClasses, style: navbarStyle, children: _jsxs("div", { className: navbarContentClasses, style: navbarContentStyle, children: [_jsxs("div", { className: navbarLeftClasses, children: [shouldShowMobileDrawer && hasLeftDrawerContent && (_jsx("div", { className: "pr-4 px-2", children: _jsx(Button, { variant: "ghost", icon: "fa-bars", onClick: handleMobileDrawerToggle, "aria-label": "Abrir men\u00FA" }) })), navBarLeftNode && (_jsx("div", { children: typeof navBarLeftNode === "string" ? (_jsx("span", { children: navBarLeftNode })) : (navBarLeftNode) }))] }), navBarRightNode && (_jsx("div", { className: navbarRightClasses, children: typeof navBarRightNode === "string" ? (_jsx("span", { children: navBarRightNode })) : (navBarRightNode) }))] }) })), _jsx("main", { ref: contentRef, className: contentClasses, children: children })] })] }) })), shouldShowMobileDrawer && hasLeftDrawerContent && isMobileDrawerOpen && (_jsx("div", { className: overlayClasses, onClick: handleOverlayClick })), shouldShowMobileDrawer && hasLeftDrawerContent && (_jsxs("aside", { className: `${mobileDrawerBaseClasses} ${isMobileDrawerOpen ? mobileDrawerOpenClasses : ""}`, style: mobileDrawerStyle, children: [_jsxs("div", { className: "flex-shrink-0 flex items-center justify-between", children: [leftDrawerHeader ? (_jsx("div", { className: "flex-1", children: leftDrawerHeader })) : (_jsx("div", { className: "flex-1" })), _jsx("div", { className: "absolute top-3 right-2", children: _jsx(Button, { variant: "ghost", icon: "fa-times", onClick: handleMobileDrawerToggle, "aria-label": "Cerrar men\u00FA" }) })] }), leftDrawerContent && (_jsx("div", { className: mobileDrawerContentClasses, children: leftDrawerContent })), leftDrawerFooter && (_jsx("div", { className: "flex-shrink-0", children: leftDrawerFooter }))] }))] }));
|
|
210
210
|
};
|
|
@@ -2,14 +2,19 @@ import React from "react";
|
|
|
2
2
|
export interface CardProps {
|
|
3
3
|
title?: string | React.ReactNode;
|
|
4
4
|
subtitle?: string | React.ReactNode;
|
|
5
|
-
children
|
|
5
|
+
children?: React.ReactNode;
|
|
6
6
|
className?: string;
|
|
7
7
|
/**
|
|
8
|
-
* Acciones para el header de la tarjeta.
|
|
8
|
+
* Acciones para el header de la tarjeta. Se muestra directamente el ReactNode proporcionado.
|
|
9
9
|
*/
|
|
10
|
-
headerActions?:
|
|
10
|
+
headerActions?: React.ReactNode;
|
|
11
11
|
footer?: React.ReactNode;
|
|
12
12
|
variant?: "default" | "elevated" | "outlined";
|
|
13
|
+
/**
|
|
14
|
+
* Si es true, las headerActions siempre se muestran. Si es false, solo se muestran al hacer hover (en pantallas grandes).
|
|
15
|
+
* En resoluciones md e inferiores, siempre se muestran sin importar este valor.
|
|
16
|
+
*/
|
|
17
|
+
alwaysDisplayHeaderActions?: boolean;
|
|
13
18
|
}
|
|
14
19
|
export declare const Card: React.FC<CardProps>;
|
|
15
20
|
//# sourceMappingURL=Card.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IACpC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC9C;;;OAGG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CA4GpC,CAAC"}
|