@zauru-sdk/components 6.2.28 → 6.3.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/.ladle/components.tsx +30 -0
- package/.ladle/config.mjs +9 -0
- package/.ladle/vite.config.ts +23 -0
- package/CHANGELOG.md +14 -0
- package/PLAYGROUND.md +59 -0
- package/dist/Alerts/StaticAlert.d.ts +1 -1
- package/dist/Buttons/ActionList.d.ts +17 -0
- package/dist/Buttons/Button.d.ts +1 -1
- package/dist/Buttons/index.d.ts +1 -0
- package/dist/Containers/ButtonSectionContainer.d.ts +2 -0
- package/dist/Containers/Container.d.ts +3 -1
- package/dist/DynamicTable/GenericDynamicTable.d.ts +2 -0
- package/dist/Form/FileUpload/index.d.ts +1 -0
- package/dist/Form/FormLayout/index.d.ts +11 -0
- package/dist/Form/RadioButtonGroup/index.d.ts +1 -0
- package/dist/Form/SelectField/index.d.ts +4 -1
- package/dist/Form/index.d.ts +2 -0
- package/dist/Labels/SearchFiltersSummary.d.ts +12 -0
- package/dist/Labels/index.d.ts +1 -0
- package/dist/Layouts/errorLayout/index.d.ts +4 -1
- package/dist/NavBar/NavBar.d.ts +1 -1
- package/dist/NavBar/NavBar.types.d.ts +1 -0
- package/dist/Table/ZauruTable.d.ts +5 -0
- package/dist/Tooltip/Tooltip.d.ts +7 -0
- package/dist/Tooltip/index.d.ts +1 -0
- package/dist/WithTooltip/WithTooltip.d.ts +7 -0
- package/dist/WithTooltip/index.d.ts +1 -0
- package/dist/esm/Alerts/StaticAlert.js +6 -0
- package/dist/esm/BlockUI/BlockUI.js +1 -1
- package/dist/esm/Buttons/ActionList.js +8 -0
- package/dist/esm/Buttons/Button.js +5 -5
- package/dist/esm/Buttons/index.js +1 -0
- package/dist/esm/Containers/ButtonSectionContainer.js +2 -2
- package/dist/esm/Containers/Container.js +7 -2
- package/dist/esm/Containers/OutletContainer.js +1 -1
- package/dist/esm/DynamicTable/GenericDynamicTable.js +6 -3
- package/dist/esm/Footer/Footer.js +1 -1
- package/dist/esm/Form/FileUpload/index.js +2 -2
- package/dist/esm/Form/FormLayout/index.js +7 -0
- package/dist/esm/Form/RadioButtonGroup/index.js +1 -0
- package/dist/esm/Form/SelectField/index.js +16 -6
- package/dist/esm/Form/TextField/index.js +13 -3
- package/dist/esm/Form/index.js +2 -0
- package/dist/esm/Labels/SearchFiltersSummary.js +7 -0
- package/dist/esm/Labels/index.js +1 -0
- package/dist/esm/Layouts/errorLayout/index.js +9 -3
- package/dist/esm/Modal/ItemModal.js +7 -4
- package/dist/esm/NavBar/NavBar.js +8 -3
- package/dist/esm/Table/ZauruTable.js +67 -8
- package/dist/esm/Tooltip/Tooltip.js +14 -0
- package/dist/esm/Tooltip/index.js +1 -0
- package/dist/esm/WithTooltip/WithTooltip.js +5 -0
- package/dist/esm/WithTooltip/index.js +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/index.d.ts +2 -0
- package/package.json +10 -3
- package/postcss.config.cjs +6 -0
- package/src/Alerts/StaticAlert.tsx +11 -1
- package/src/BlockUI/BlockUI.tsx +1 -1
- package/src/Buttons/ActionList.tsx +56 -0
- package/src/Buttons/Button.tsx +15 -9
- package/src/Buttons/index.ts +1 -0
- package/src/Containers/ButtonSectionContainer.tsx +4 -2
- package/src/Containers/Container.tsx +43 -13
- package/src/Containers/OutletContainer.tsx +1 -1
- package/src/DynamicTable/GenericDynamicTable.tsx +26 -9
- package/src/Footer/Footer.tsx +2 -1
- package/src/Form/FileUpload/index.tsx +3 -0
- package/src/Form/FormLayout/index.tsx +35 -0
- package/src/Form/RadioButtonGroup/index.tsx +4 -0
- package/src/Form/SelectField/index.tsx +44 -23
- package/src/Form/TextField/index.tsx +14 -1
- package/src/Form/index.ts +2 -0
- package/src/Labels/SearchFiltersSummary.tsx +34 -0
- package/src/Labels/index.tsx +1 -0
- package/src/Layouts/errorLayout/index.tsx +11 -2
- package/src/Modal/ItemModal.tsx +18 -5
- package/src/NavBar/NavBar.tsx +20 -2
- package/src/NavBar/NavBar.types.ts +1 -0
- package/src/Table/ZauruTable.tsx +83 -7
- package/src/Tooltip/Tooltip.tsx +42 -0
- package/src/Tooltip/index.ts +1 -0
- package/src/WithTooltip/WithTooltip.tsx +22 -0
- package/src/WithTooltip/index.tsx +1 -0
- package/src/index.ts +2 -0
- package/stories/Alerts.stories.tsx +17 -0
- package/stories/Button.stories.tsx +52 -0
- package/stories/Card.stories.tsx +7 -0
- package/stories/Container.stories.tsx +24 -0
- package/stories/Form.stories.tsx +58 -0
- package/stories/Labels.stories.tsx +17 -0
- package/stories/Modal.stories.tsx +21 -0
- package/stories/Tab.stories.tsx +10 -0
- package/stories/Table.stories.tsx +37 -0
- package/stories/Titles.stories.tsx +11 -0
- package/stories/Tooltip.stories.tsx +15 -0
- package/tailwind.config.cjs +12 -0
- package/tsconfig.json +1 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IdeaIconSVG } from "@zauru-sdk/icons";
|
|
3
|
-
import { useEffect, useState } from "react";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
4
|
import { useFormContext } from "react-hook-form";
|
|
5
5
|
export const TextField = (props) => {
|
|
6
6
|
const { id, name, defaultValue = "", hidden, type = "text", onChange, onKeyDown, disabled = false, readOnly = false, min, integer = false, stopChangeEvents, style, title, helpText, className = "", hint, required, autoComplete = "off", } = props;
|
|
7
7
|
const [showTooltip, setShowTooltip] = useState(false);
|
|
8
8
|
const [value, setValue] = useState(defaultValue);
|
|
9
|
+
const inputRef = useRef(null);
|
|
9
10
|
const { register: tempRegister, formState: { errors }, setValue: setOnFormValue, } = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
|
|
10
11
|
const error = errors ? errors[props.name ?? "-1"] : undefined;
|
|
11
12
|
const register = tempRegister
|
|
@@ -14,12 +15,21 @@ export const TextField = (props) => {
|
|
|
14
15
|
required,
|
|
15
16
|
})
|
|
16
17
|
: undefined; // Solo usar register si está disponible
|
|
18
|
+
const assignRef = (element) => {
|
|
19
|
+
inputRef.current = element;
|
|
20
|
+
if (typeof register?.ref === "function") {
|
|
21
|
+
register.ref(element);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
17
24
|
const color = error ? "red" : "gray";
|
|
18
25
|
const isReadOnly = disabled || readOnly;
|
|
19
26
|
const bgColor = isReadOnly ? "bg-gray-200" : `bg-${color}-50`;
|
|
20
27
|
const textColor = isReadOnly ? "text-gray-500" : `text-${color}-900`;
|
|
21
28
|
const borderColor = isReadOnly ? "border-gray-300" : `border-${color}-200`;
|
|
22
29
|
useEffect(() => {
|
|
30
|
+
if (inputRef.current && document.activeElement === inputRef.current) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
23
33
|
if (setOnFormValue) {
|
|
24
34
|
setOnFormValue(name ?? "-1", defaultValue);
|
|
25
35
|
}
|
|
@@ -54,14 +64,14 @@ export const TextField = (props) => {
|
|
|
54
64
|
}
|
|
55
65
|
};
|
|
56
66
|
if (hidden) {
|
|
57
|
-
return (_jsx("input", { type: type, id: id ?? name, value: value, hidden: true, ...(register ?? {}), name: name, onChange: handleInputChange }));
|
|
67
|
+
return (_jsx("input", { type: type, id: id ?? name, value: value, hidden: true, ...(register ?? {}), ref: assignRef, name: name, onChange: handleInputChange }));
|
|
58
68
|
}
|
|
59
69
|
const inputComponent = (_jsx("input", { type: type, readOnly: isReadOnly, disabled: disabled, id: id ?? name, value: value, onWheel: (e) => {
|
|
60
70
|
e.currentTarget.blur();
|
|
61
71
|
}, step: type === "number" ? 0.01 : undefined, onKeyDown: (event) => {
|
|
62
72
|
handleKeyDown(event);
|
|
63
73
|
onKeyDown && onKeyDown(event);
|
|
64
|
-
}, min: min, style: style, className: `block w-full rounded-md ${bgColor} ${borderColor} ${textColor} shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm`, ...(register ?? {}), name: name, autoComplete: autoComplete, onChange: handleInputChange }));
|
|
74
|
+
}, min: min, style: style, className: `block w-full rounded-md ${bgColor} ${borderColor} ${textColor} shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm`, ...(register ?? {}), ref: assignRef, name: name, autoComplete: autoComplete, onChange: handleInputChange }));
|
|
65
75
|
if (!error && !title && !helpText) {
|
|
66
76
|
return _jsx("div", { className: `${className}`, children: inputComponent });
|
|
67
77
|
}
|
package/dist/esm/Form/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./DynamicBaculoForm/index.js";
|
|
|
5
5
|
export * from "./FieldContainer/index.js";
|
|
6
6
|
export * from "./FileUpload/index.js";
|
|
7
7
|
export * from "./FormButtons/index.js";
|
|
8
|
+
export * from "./FormLayout/index.js";
|
|
8
9
|
export * from "./SelectField/index.js";
|
|
9
10
|
export * from "./TextArea/index.js";
|
|
10
11
|
export * from "./TextField/index.js";
|
|
@@ -12,3 +13,4 @@ export * from "./TimePicker/index.js";
|
|
|
12
13
|
export * from "./YesNo/index.js";
|
|
13
14
|
export * from "./ReactZodForm/index.js";
|
|
14
15
|
export * from "./RadioButton/index.js";
|
|
16
|
+
export * from "./RadioButtonGroup/index.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export const SearchFiltersSummary = ({ items, emptyText = "Sin filtros registrados", className = "", }) => {
|
|
3
|
+
if (!items?.length) {
|
|
4
|
+
return (_jsx("p", { className: `text-xs text-gray-400 ${className}`, children: emptyText }));
|
|
5
|
+
}
|
|
6
|
+
return (_jsx("dl", { className: `flex flex-col gap-1 text-xs text-gray-700 ${className}`, children: items.map((item) => (_jsxs("div", { className: "flex flex-wrap items-baseline gap-x-1", children: [_jsxs("dt", { className: "font-semibold text-gray-500", children: [item.label, ":"] }), _jsx("dd", { className: "text-gray-800", children: item.value })] }, item.key))) }));
|
|
7
|
+
};
|
package/dist/esm/Labels/index.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { isRouteErrorResponse, Links, Meta, Scripts, useRouteError, Link, } from "@remix-run/react";
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
export const ErrorLayout = ({ from, isRootLevel = true, error: parentError, }) => {
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
export const ErrorLayout = ({ from, isRootLevel = true, error: parentError, onError, }) => {
|
|
5
5
|
try {
|
|
6
6
|
const error = useRouteError();
|
|
7
7
|
const [showDetails, setShowDetails] = useState(!!parentError);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const reportable = error instanceof Error ? error : parentError;
|
|
10
|
+
if (reportable instanceof Error) {
|
|
11
|
+
onError?.(reportable, { from });
|
|
12
|
+
}
|
|
13
|
+
}, [error, parentError, from, onError]);
|
|
8
14
|
const baseError = (_jsxs("div", { className: "min-h-screen flex flex-col items-center justify-center p-4", children: [_jsx("img", { src: "/logo.png", alt: "Zauru Logo", className: "mb-8 h-20" }), _jsx("h1", { className: "text-5xl font-extrabold text-red-500 mb-6", children: "\u00A1Ups!" }), _jsxs("div", { className: "w-full max-w-2xl flex flex-col items-center", children: [_jsx("p", { className: "text-2xl text-gray-300 mb-8 text-center", children: isRouteErrorResponse(error)
|
|
9
15
|
? `Error en request: ${error.status}: ${error.statusText} - PATH: ${error.data.path} - MESSAGE: ${error.data.message}`
|
|
10
16
|
: error instanceof Error
|
|
11
17
|
? `Error: ${error.message} - NAME: ${error.name} - STACK: ${error.stack?.slice(0, 100)} - CAUSE: ${error.cause}`
|
|
12
18
|
: `Ha ocurrido un error inesperado: ${error}` }), from && (_jsxs("p", { className: "text-lg text-gray-400 mb-4 text-center", children: [isRootLevel
|
|
13
19
|
? "(*) Error lanzado desde: "
|
|
14
|
-
: "Error lanzado desde: ", from] })), parentError && (_jsxs("div", { className: "mb-4 text-center", children: [_jsx("button", { onClick: () => setShowDetails(!showDetails), className: "text-blue-400 hover:text-blue-300 transition duration-300", children: showDetails ? "Ocultar detalles" : "Ver más detalles" }), showDetails && (_jsx("p", { className: "mt-2 text-gray-400 text-sm", children: parentError instanceof Error
|
|
20
|
+
: "Error lanzado desde: ", from] })), parentError && (_jsxs("div", { className: "mb-4 text-center", children: [_jsx("button", { onClick: () => setShowDetails(!showDetails), className: "text-blue-400 hover:text-blue-300 transition duration-300 cursor-pointer", children: showDetails ? "Ocultar detalles" : "Ver más detalles" }), showDetails && (_jsx("p", { className: "mt-2 text-gray-400 text-sm", children: parentError instanceof Error
|
|
15
21
|
? parentError.message
|
|
16
22
|
: String(parentError) }))] }))] }), _jsx(Link, { to: "/", className: "bg-blue-600 text-white py-3 px-8 rounded-full text-lg font-semibold hover:bg-blue-700 transition duration-300 transform hover:scale-105", children: "Regresar al inicio" }), _jsx("div", { className: "mt-12 text-gray-500 text-center", children: _jsx("p", { children: "Si el problema persiste, por favor contacta a soporte." }) })] }));
|
|
17
23
|
if (!isRootLevel) {
|
|
@@ -29,7 +29,8 @@ const ItemSelectionModal = ({ itemList, onClose, config, categoryViewMode = "tex
|
|
|
29
29
|
const filteredList = itemList
|
|
30
30
|
.map((category) => ({
|
|
31
31
|
...category,
|
|
32
|
-
items: category.items.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase())
|
|
32
|
+
items: category.items.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
33
|
+
item.code.toLowerCase().includes(searchTerm.toLowerCase())),
|
|
33
34
|
}))
|
|
34
35
|
.filter((category) => category.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
35
36
|
category.items.length > 0);
|
|
@@ -74,11 +75,13 @@ const ItemSelectionModal = ({ itemList, onClose, config, categoryViewMode = "tex
|
|
|
74
75
|
};
|
|
75
76
|
return (_jsx("div", { className: "fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50", onClick: handleCloseModal, children: _jsxs("div", {
|
|
76
77
|
//Le ponemos ref para poder scrollear al tope
|
|
77
|
-
ref: modalContentRef, className: "bg-white p-4 rounded-lg shadow-lg w-11/12 max-w-4xl h-5/6 overflow-y-auto", onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { className: "flex justify-between items-center mb-4", children: [_jsx("h2", { className: "text-2xl font-bold", children: selectedItem
|
|
78
|
+
ref: modalContentRef, className: "bg-white p-4 rounded-lg shadow-lg w-11/12 max-w-4xl h-5/6 overflow-y-auto", onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { className: "flex justify-between items-center mb-4", children: [_jsx("h2", { className: "text-2xl font-bold", children: selectedItem
|
|
79
|
+
? "Confirmar selección"
|
|
80
|
+
: `Seleccionar un Ítem - (${itemList.reduce((acc, category) => acc + category.items.length, 0)} ítems disponibles)` }), _jsx("button", { className: "text-gray-500 hover:text-gray-800 text-3xl cursor-pointer", onClick: handleCloseModal, children: "\u00D7" })] }), !selectedItem ? (
|
|
78
81
|
/* ==============================
|
|
79
82
|
PASO 1: SELECCIONAR ÍTEM
|
|
80
83
|
============================== */
|
|
81
|
-
_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative mb-4", children: [_jsx("input", { type: "text", placeholder: "Buscar por nombre o categor\u00EDa...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), className: "p-2 border rounded-lg w-full" }), searchTerm && (_jsx("button", { className: "absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 hover:text-gray-800", onClick: () => setSearchTerm(""), children: "\u00D7" }))] }), filteredList.length === 0 ? (_jsx("p", { className: "text-gray-500 text-center", children: "No se encontraron resultados." })) : (filteredList.map((category, index) => {
|
|
84
|
+
_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative mb-4", children: [_jsx("input", { type: "text", placeholder: "Buscar por nombre, c\u00F3digo o categor\u00EDa...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), className: "p-2 border rounded-lg w-full" }), searchTerm && (_jsx("button", { className: "absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 hover:text-gray-800", onClick: () => setSearchTerm(""), children: "\u00D7" }))] }), filteredList.length === 0 ? (_jsx("p", { className: "text-gray-500 text-center", children: "No se encontraron resultados." })) : (filteredList.map((category, index) => {
|
|
82
85
|
const isExpanded = expandedCategories[category.name];
|
|
83
86
|
// Estilos condicionales para "text" vs. "card"
|
|
84
87
|
const categoryContainerClasses = categoryViewMode === "card"
|
|
@@ -107,7 +110,7 @@ const ItemSelectionModal = ({ itemList, onClose, config, categoryViewMode = "tex
|
|
|
107
110
|
/* ==============================
|
|
108
111
|
PASO 2: CONFIRMAR SELECCIÓN
|
|
109
112
|
============================== */
|
|
110
|
-
_jsxs("div", { className: "flex flex-col items-center justify-center", children: [_jsx("img", { src: selectedItem.imageUrl, alt: selectedItem.name, className: "w-40 h-40 object-cover rounded mb-4 shadow-md" }), _jsx("p", { className: "mb-2 text-xl font-bold", children: selectedItem.name }), _jsxs("p", { className: "mb-2 text-base font-semibold text-gray-700", children: ["Stock disponible:", _jsx("span", { className: "ml-1 font-normal text-gray-800", children: selectedItem.stock })] }), !selectedItem.flexiblePrice && (_jsxs("p", { className: "mb-4 text-base font-semibold text-gray-700", children: ["Precio unitario:", _jsxs("span", { className: "ml-1 font-normal text-gray-800", children: [selectedItem.currencyPrefix, selectedItem.priceText] })] })), _jsxs("div", { className: "mb-4 w-full max-w-sm flex flex-col items-center", children: [_jsx("p", { className: "text-base font-semibold text-gray-700 mb-2", children: "Seleccionar cantidad" }), _jsxs("div", { className: "flex items-center space-x-4", children: [_jsx("button", { className: "bg-gray-300 rounded-full w-12 h-12 flex justify-center items-center text-2xl font-bold hover:bg-gray-400", onClick: () => setQuantity((prev) => (prev > 1 ? prev - 1 : 1)), children: "-" }), _jsx("input", { className: "w-20 text-center border rounded text-lg", type: "number", min: 1, value: quantity, onChange: (e) => {
|
|
113
|
+
_jsxs("div", { className: "flex flex-col items-center justify-center", children: [_jsx("img", { src: selectedItem.imageUrl, alt: selectedItem.name, className: "w-40 h-40 object-cover rounded mb-4 shadow-md" }), _jsx("p", { className: "mb-2 text-xl font-bold", children: selectedItem.name }), _jsxs("p", { className: "mb-2 text-base font-semibold text-gray-700", children: ["C\u00F3digo:", _jsx("span", { className: "ml-1 font-normal text-gray-800", children: selectedItem.code })] }), _jsxs("p", { className: "mb-2 text-base font-semibold text-gray-700", children: ["Stock disponible:", _jsx("span", { className: "ml-1 font-normal text-gray-800", children: selectedItem.stock })] }), !selectedItem.flexiblePrice && (_jsxs("p", { className: "mb-4 text-base font-semibold text-gray-700", children: ["Precio unitario:", _jsxs("span", { className: "ml-1 font-normal text-gray-800", children: [selectedItem.currencyPrefix, selectedItem.priceText] })] })), _jsxs("div", { className: "mb-4 w-full max-w-sm flex flex-col items-center", children: [_jsx("p", { className: "text-base font-semibold text-gray-700 mb-2", children: "Seleccionar cantidad" }), _jsxs("div", { className: "flex items-center space-x-4", children: [_jsx("button", { className: "bg-gray-300 rounded-full w-12 h-12 flex justify-center items-center text-2xl font-bold hover:bg-gray-400", onClick: () => setQuantity((prev) => (prev > 1 ? prev - 1 : 1)), children: "-" }), _jsx("input", { className: "w-20 text-center border rounded text-lg", type: "number", min: 1, value: quantity, onChange: (e) => {
|
|
111
114
|
const val = parseInt(e.target.value, 10);
|
|
112
115
|
setQuantity(isNaN(val) || val < 1 ? 1 : val);
|
|
113
116
|
} }), _jsx("button", { className: "bg-gray-300 rounded-full w-12 h-12 flex justify-center items-center text-2xl font-bold hover:bg-gray-400", onClick: () => setQuantity((prev) => prev + 1), children: "+" })] })] }), selectedItem.flexiblePrice && (_jsxs("div", { className: "mb-4 w-full max-w-sm flex flex-col items-center", children: [_jsx("p", { className: "text-base font-semibold text-gray-700 mb-2", children: "Seleccionar precio" }), _jsxs("div", { className: "flex items-center space-x-4", children: [_jsx("button", { className: "bg-gray-300 rounded-full w-12 h-12 flex justify-center items-center text-2xl font-bold hover:bg-gray-400", onClick: () => setCustomPrice((prev) => {
|
|
@@ -6,7 +6,7 @@ import { Link, useNavigate, useLocation } from "@remix-run/react";
|
|
|
6
6
|
import { useAppSelector } from "@zauru-sdk/redux";
|
|
7
7
|
const OptionsDropDownButton = ({ color, options, name }) => {
|
|
8
8
|
const [showOptionsMenu, setShowOptionsMenu] = useState(true);
|
|
9
|
-
return (_jsx("div", { className: "nav-item ml-auto", children: _jsx("div", { className: "flex justify-center", children: _jsxs("div", { className: "relative inline-block", children: [_jsxs("button", { onClick: () => setShowOptionsMenu(!showOptionsMenu), className: `relative flex items-center p-2 text-xs text-white ${color.bg700} active:${color.bg900} border border-transparent rounded-full uppercase focus:ring-opacity-40 focus:outline-none`, children: [name ?? _jsx(OpcionButtonSvgIcon, {}), _jsx(DropDownArrowSvgIcon, {})] }), _jsx("div", { className: "absolute right-0 z-20 w-56 py-2 mt-2 overflow-hidden bg-white rounded-md shadow-xl dark:bg-gray-800", hidden: showOptionsMenu, onMouseLeave: () => setShowOptionsMenu(true), children: options.map((option, index) => (_jsx(React.Fragment, { children: option }, index))) })] }) }) }));
|
|
9
|
+
return (_jsx("div", { className: "nav-item ml-auto", children: _jsx("div", { className: "flex justify-center", children: _jsxs("div", { className: "relative inline-block", children: [_jsxs("button", { onClick: () => setShowOptionsMenu(!showOptionsMenu), className: `relative flex cursor-pointer items-center p-2 text-xs text-white ${color.bg700} active:${color.bg900} border border-transparent rounded-full uppercase focus:ring-opacity-40 focus:outline-none`, children: [name ?? _jsx(OpcionButtonSvgIcon, {}), _jsx(DropDownArrowSvgIcon, {})] }), _jsx("div", { className: "absolute right-0 z-20 w-56 py-2 mt-2 overflow-hidden bg-white rounded-md shadow-xl dark:bg-gray-800", hidden: showOptionsMenu, onMouseLeave: () => setShowOptionsMenu(true), children: options.map((option, index) => (_jsx(React.Fragment, { children: option }, index))) })] }) }) }));
|
|
10
10
|
};
|
|
11
11
|
const NavItem = ({ name, link, icon, selectedColor, childrens = [], reduxNotificationBadge, }) => {
|
|
12
12
|
const location = useLocation();
|
|
@@ -30,11 +30,15 @@ const NavItem = ({ name, link, icon, selectedColor, childrens = [], reduxNotific
|
|
|
30
30
|
// De lo contrario, usamos el color normal (bg700)
|
|
31
31
|
className: `${isActive ? specialColor.bg900 : specialColor.bg700} container text-white w-full sm:w-auto h-10 text-sm py-1 uppercase shadow hover:shadow-lg outline-none rounded-full focus:outline-none my-auto sm:my-0 sm:mr-1 mb-1 ease-linear transition-all duration-150`, children: _jsxs(Link, { className: "px-3 flex items-center text-xs leading-snug text-white uppercase hover:opacity-75 relative", to: link, children: [_jsxs("div", { className: "mx-auto pt-2", children: [icon, _jsx("span", { children: name })] }), notificationBadge !== undefined && (_jsx("span", { className: "absolute -top-2 -right-2 bg-red-500 text-white text-xs font-bold rounded-full flex items-center justify-center w-5 h-5", children: notificationBadge }))] }) }) }));
|
|
32
32
|
};
|
|
33
|
-
export const NavBar = ({ title, loggedIn, items, selectedColor, version, reloadCatalogsOption, }) => {
|
|
33
|
+
export const NavBar = ({ title, loggedIn, items, selectedColor, version, reloadCatalogsOption, showDarkModeToggle = false, }) => {
|
|
34
34
|
const color = COLORS[selectedColor];
|
|
35
35
|
const [NavBarOpen, setNavBarOpen] = useState(false);
|
|
36
36
|
const [currentVersion, setCurrentVersion] = useState(version);
|
|
37
|
+
const [isDarkMode, setIsDarkMode] = useState(false);
|
|
37
38
|
const navigate = useNavigate();
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
document.documentElement.classList.toggle("dark", isDarkMode);
|
|
41
|
+
}, [isDarkMode]);
|
|
38
42
|
useEffect(() => {
|
|
39
43
|
if (version !== currentVersion) {
|
|
40
44
|
setCurrentVersion(version);
|
|
@@ -54,8 +58,9 @@ export const NavBar = ({ title, loggedIn, items, selectedColor, version, reloadC
|
|
|
54
58
|
.filter((item) => item.loggedIn === loggedIn)
|
|
55
59
|
.filter((item) => item.hide !== true)) }), _jsx("ul", { className: "sm:flex sm:flex-col lg:flex-row ml-auto", children: loggedIn && (_jsx(OptionsDropDownButton, { color: color, options: [
|
|
56
60
|
reloadCatalogsOption && (_jsx(Link, { className: `block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`, to: "/reload-catalogs", children: _jsxs("div", { className: "mx-auto pt-2", children: [_jsxs("svg", { className: `h-5 w-5 mr-1`, width: "24", height: "24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", viewBox: "0 0 24 24", strokeLinecap: "round", strokeLinejoin: "round", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M20.5 8c-1.392-3.179-4.823-5-8.522-5C7.299 3 3.453 6.552 3 11.1" }), _jsx("path", { d: "M16.489 8.4h3.97A.54.54 0 0 0 21 7.86V3.9M3.5 16c1.392 3.179 4.823 5 8.522 5 4.679 0 8.525-3.552 8.978-8.1" }), _jsx("path", { d: "M7.511 15.6h-3.97a.54.54 0 0 0-.541.54v3.96" })] }), _jsx("span", { children: "Recargar cat\u00E1logos" })] }) }, "recargar-catalogos")),
|
|
61
|
+
showDarkModeToggle && (_jsx("button", { type: "button", className: "block w-full cursor-pointer text-left px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 dark:hover:text-white", onClick: () => setIsDarkMode((value) => !value), children: _jsx("div", { className: "mx-auto pt-2", children: _jsx("span", { children: isDarkMode ? "Modo claro" : "Modo oscuro" }) }) }, "dark-mode-toggle")),
|
|
57
62
|
_jsx(Link, { className: `block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`, to: "/logout", children: _jsxs("div", { className: "mx-auto pt-2", children: [_jsx(LogoutDropDownSvgIcon, {}), _jsx("span", { children: "Cerrar sesi\u00F3n" })] }) }, "cerrar-sesion"),
|
|
58
63
|
] })) })] }));
|
|
59
|
-
}, [items, loggedIn, hiddenItemsChange]);
|
|
64
|
+
}, [items, loggedIn, hiddenItemsChange, showDarkModeToggle, isDarkMode]);
|
|
60
65
|
return (_jsx("nav", { className: `py-3 ${color.bg600}`, children: _jsxs("div", { className: "flex items-center justify-between ml-5 mr-5", children: [_jsxs("div", { className: "flex justify-between items-center w-full lg:w-auto", children: [_jsxs(Link, { className: "text-sm font-bold leading-relaxed inline-block mr-4 py-2 whitespace-nowrap uppercase text-white", to: "/home", children: [_jsx("div", { className: "inline-block mr-2 mb-2 align-middle", children: _jsx("img", { className: "w-auto h-7", src: "/logo.png", alt: "logo-zauru" }) }), title] }), version !== currentVersion && (_jsx("button", { className: `ml-2 px-2 py-1 text-xs text-white ${color.bg700} rounded-full hover:${color.bg900} transition-colors duration-200`, onClick: refreshPage, children: "\uD83D\uDD04 Actualizar versi\u00F3n" })), _jsx("button", { className: `rounded lg:hidden focus:outline-none focus:ring focus:${color.ring600} focus:ring-opacity-50`, "aria-label": "Toggle mobile menu", type: "button", onClick: () => setNavBarOpen(!NavBarOpen), children: _jsx(MenuAlt4Svg, { open: NavBarOpen }) })] }), _jsx("div", { className: `lg:hidden fixed top-0 left-0 z-50 w-64 h-full ${color.bg700} dark:bg-gray-900 shadow-lg transform ${NavBarOpen ? "translate-x-0" : "-translate-x-full"} transition-transform duration-300 ease-in-out overflow-y-auto`, children: _jsx("div", { className: "p-4", children: options }) }), _jsx("div", { className: "hidden lg:flex lg:items-center w-full lg:w-auto", children: options })] }) }));
|
|
61
66
|
};
|
|
@@ -5,16 +5,65 @@ import { createTheme } from "react-data-table-component";
|
|
|
5
5
|
import { SearchSVG } from "@zauru-sdk/icons";
|
|
6
6
|
import * as ReactDataTableComponent from "react-data-table-component";
|
|
7
7
|
const DataTable = ReactDataTableComponent.default;
|
|
8
|
+
const headerTextWrapStyle = {
|
|
9
|
+
whiteSpace: "normal",
|
|
10
|
+
overflow: "visible",
|
|
11
|
+
textOverflow: "clip",
|
|
12
|
+
overflowWrap: "break-word",
|
|
13
|
+
wordBreak: "break-word",
|
|
14
|
+
lineHeight: "1.25",
|
|
15
|
+
};
|
|
8
16
|
const customStyles = {
|
|
17
|
+
table: {
|
|
18
|
+
style: {
|
|
19
|
+
minWidth: 0,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
tableWrapper: {
|
|
23
|
+
style: {
|
|
24
|
+
display: "block",
|
|
25
|
+
width: "100%",
|
|
26
|
+
maxWidth: "100%",
|
|
27
|
+
minWidth: 0,
|
|
28
|
+
overflowX: "auto",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
responsiveWrapper: {
|
|
32
|
+
style: {
|
|
33
|
+
width: "100%",
|
|
34
|
+
maxWidth: "100%",
|
|
35
|
+
minWidth: 0,
|
|
36
|
+
overflowX: "auto",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
headRow: {
|
|
40
|
+
style: {
|
|
41
|
+
minHeight: "40px",
|
|
42
|
+
height: "auto",
|
|
43
|
+
alignItems: "stretch",
|
|
44
|
+
},
|
|
45
|
+
denseStyle: {
|
|
46
|
+
minHeight: "36px",
|
|
47
|
+
height: "auto",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
9
50
|
headCells: {
|
|
10
51
|
style: {
|
|
11
52
|
color: "#202124",
|
|
12
53
|
fontSize: "14px",
|
|
13
54
|
justifyContent: "left",
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
55
|
+
alignItems: "flex-start",
|
|
56
|
+
paddingTop: "8px",
|
|
57
|
+
paddingBottom: "8px",
|
|
58
|
+
...headerTextWrapStyle,
|
|
59
|
+
".rdt_TableCol_Sortable": {
|
|
60
|
+
height: "auto",
|
|
61
|
+
minHeight: "100%",
|
|
62
|
+
overflow: "visible",
|
|
63
|
+
whiteSpace: "normal",
|
|
64
|
+
alignItems: "flex-start",
|
|
65
|
+
},
|
|
66
|
+
".rdt_TableCol_Sortable > div": headerTextWrapStyle,
|
|
18
67
|
},
|
|
19
68
|
},
|
|
20
69
|
cells: {
|
|
@@ -23,6 +72,16 @@ const customStyles = {
|
|
|
23
72
|
wordBreak: "break-word",
|
|
24
73
|
},
|
|
25
74
|
},
|
|
75
|
+
expanderRow: {
|
|
76
|
+
style: {
|
|
77
|
+
minWidth: 0,
|
|
78
|
+
width: "100%",
|
|
79
|
+
maxWidth: "100%",
|
|
80
|
+
overflowX: "auto",
|
|
81
|
+
display: "grid",
|
|
82
|
+
gridTemplateColumns: "minmax(0, 1fr)",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
26
85
|
rows: {
|
|
27
86
|
highlightOnHoverStyle: {
|
|
28
87
|
backgroundColor: "rgb(230, 244, 244)",
|
|
@@ -86,7 +145,7 @@ createTheme("subTable", {
|
|
|
86
145
|
});
|
|
87
146
|
//Documentación de la tabla https://react-data-table-component.netlify.app/?path=/docs/getting-started-intro--docs
|
|
88
147
|
export const ZauruTable = (props) => {
|
|
89
|
-
const { columns, conditionalRowStyles, data, loading = false, pagination, search, theme, className, offlineSearch = [], whitOutPagination = false, ...others } = props;
|
|
148
|
+
const { columns, conditionalRowStyles, data, loading = false, pagination, search, expandable, theme, className, offlineSearch = [], whitOutPagination = false, ...others } = props;
|
|
90
149
|
const [, setSearchParams] = useSearchParams({
|
|
91
150
|
page: "1",
|
|
92
151
|
perPage: "10",
|
|
@@ -152,7 +211,7 @@ export const ZauruTable = (props) => {
|
|
|
152
211
|
};
|
|
153
212
|
const loadSubHeader = !!(search || offlineSearch.length > 0);
|
|
154
213
|
const subHeaderComponent = loadSubHeader ? subHeaderComponentMemo : undefined;
|
|
155
|
-
return (_jsx(DataTable, { className: className, subHeaderWrap: true, theme: theme ?? "solarized", columns: columns, conditionalRowStyles: conditionalRowStyles, data: filteredData, customStyles: customStyles, progressPending: loading, highlightOnHover: true, pointerOnHover: true, dense: true, striped: true, pagination: !whitOutPagination, persistTableHead: true, responsive: true, noHeader: true, subHeader: loadSubHeader, subHeaderComponent: subHeaderComponent, paginationServer: !!pagination, paginationTotalRows: pagination?.totalRows ?? undefined, onChangeRowsPerPage: pagination ? handlePerRowsChange : undefined, onChangePage: pagination ? handlePageChange : undefined, paginationComponentOptions: paginationComponentOptions, paginationRowsPerPageOptions: pagination?.rowsPerPageOptions
|
|
156
|
-
|
|
157
|
-
|
|
214
|
+
return (_jsx("div", { className: "w-full min-w-0 max-w-full overflow-x-auto", children: _jsx(DataTable, { className: className, subHeaderWrap: true, theme: theme ?? "solarized", columns: columns, conditionalRowStyles: conditionalRowStyles, data: filteredData, customStyles: customStyles, progressPending: loading, highlightOnHover: true, pointerOnHover: true, dense: true, striped: true, pagination: !whitOutPagination, persistTableHead: true, responsive: true, noHeader: true, expandableRows: !!expandable, expandOnRowClicked: !!expandable, expandableRowExpanded: expandable ? expandable.expandableRowExpanded : undefined, expandableRowsComponent: expandable ? expandable.expandableRowsComponent : undefined, subHeader: loadSubHeader, subHeaderComponent: subHeaderComponent, paginationServer: !!pagination, paginationTotalRows: pagination?.totalRows ?? undefined, onChangeRowsPerPage: pagination ? handlePerRowsChange : undefined, onChangePage: pagination ? handlePageChange : undefined, paginationComponentOptions: paginationComponentOptions, paginationRowsPerPageOptions: pagination?.rowsPerPageOptions
|
|
215
|
+
? pagination.rowsPerPageOptions
|
|
216
|
+
: [10, 50, 100], ...others }) }));
|
|
158
217
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
export const Tooltip = ({ children, text }) => {
|
|
5
|
+
const [show, setShow] = useState(false);
|
|
6
|
+
return (_jsxs("div", { className: "relative inline-block", children: [_jsx("div", { onMouseEnter: () => setShow(true), onMouseLeave: () => setShow(false), children: children }), show && (_jsxs("div", { className: "absolute z-10 bg-gray-700 text-white px-2 py-1 rounded-md bottom-full left-1/2 transform -translate-x-1/2", style: { whiteSpace: "nowrap", height: "2rem" }, children: [text, _jsx("div", { className: "absolute top-full left-1/2 transform -translate-x-1/2", style: {
|
|
7
|
+
width: "0",
|
|
8
|
+
height: "0",
|
|
9
|
+
borderTop: "6px solid transparent",
|
|
10
|
+
borderLeft: "6px solid transparent",
|
|
11
|
+
borderRight: "6px solid transparent",
|
|
12
|
+
borderBottom: "6px solid gray",
|
|
13
|
+
} })] }))] }));
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Tooltip.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export const WithTooltip = (props) => {
|
|
3
|
+
const { children, text } = props;
|
|
4
|
+
return (_jsxs("div", { className: "group relative inline-block", children: [children, _jsx("div", { className: "pointer-events-none absolute left-1/2 -translate-x-1/2 bottom-full mb-2 opacity-0 transition-opacity duration-300 group-hover:opacity-100", children: _jsxs("div", { className: "relative bg-black text-white text-sm rounded py-1 px-2 text-wrap w-40", children: [text, _jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-black" })] }) })] }));
|
|
5
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./WithTooltip.js";
|
package/dist/esm/index.js
CHANGED
|
@@ -19,6 +19,8 @@ export * from "./Tab/index.js";
|
|
|
19
19
|
export * from "./Table/index.js";
|
|
20
20
|
export * from "./TaskList/index.js";
|
|
21
21
|
export * from "./Titles/index.js";
|
|
22
|
+
export * from "./Tooltip/index.js";
|
|
23
|
+
export * from "./WithTooltip/index.js";
|
|
22
24
|
export * from "./Wizards/index.js";
|
|
23
25
|
export * from "./Zendesk/index.js";
|
|
24
26
|
export * from "./HOC/ValidateEmployeeAccess/index.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export * from "./Tab/index.js";
|
|
|
19
19
|
export * from "./Table/index.js";
|
|
20
20
|
export * from "./TaskList/index.js";
|
|
21
21
|
export * from "./Titles/index.js";
|
|
22
|
+
export * from "./Tooltip/index.js";
|
|
23
|
+
export * from "./WithTooltip/index.js";
|
|
22
24
|
export * from "./Wizards/index.js";
|
|
23
25
|
export * from "./Zendesk/index.js";
|
|
24
26
|
export * from "./HOC/ValidateEmployeeAccess/index.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zauru-sdk/components",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "Componentes reutilizables en las WebApps de Zauru.",
|
|
5
5
|
"main": "./dist/esm/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "npm run build:esm",
|
|
15
15
|
"build:esm": "tsc -p tsconfig.esm.json",
|
|
16
|
+
"play": "ladle serve --port 61000",
|
|
17
|
+
"play:build": "ladle build",
|
|
16
18
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
17
19
|
},
|
|
18
20
|
"author": {
|
|
@@ -21,15 +23,20 @@
|
|
|
21
23
|
},
|
|
22
24
|
"license": "MIT",
|
|
23
25
|
"devDependencies": {
|
|
26
|
+
"@ladle/react": "^5.1.1",
|
|
24
27
|
"@tailwindcss/forms": "^0.5.7",
|
|
25
28
|
"@types/jsonwebtoken": "^9.0.2",
|
|
26
29
|
"@types/rails__activestorage": "^7.1.1",
|
|
27
30
|
"@types/react": "^19.0.0",
|
|
28
31
|
"@types/react-dom": "^19.0.0",
|
|
29
32
|
"@types/styled-components": "^5.1.34",
|
|
33
|
+
"autoprefixer": "^10.6.0",
|
|
30
34
|
"postcss": "^8.4.35",
|
|
35
|
+
"react-redux": "^9.1.2",
|
|
36
|
+
"react-router-dom": "6.26.2",
|
|
31
37
|
"tailwindcss": "^3.4.1",
|
|
32
|
-
"typescript": "^5.1.6"
|
|
38
|
+
"typescript": "^5.1.6",
|
|
39
|
+
"vite": "^8.3.0"
|
|
33
40
|
},
|
|
34
41
|
"dependencies": {
|
|
35
42
|
"@hookform/resolvers": "^3.9.0",
|
|
@@ -55,5 +62,5 @@
|
|
|
55
62
|
"styled-components": "^5.3.5",
|
|
56
63
|
"zod": "^3.23.8"
|
|
57
64
|
},
|
|
58
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "27363fa3e10c6b9f3ca319b0529fae01da836f87"
|
|
59
66
|
}
|
|
@@ -7,7 +7,7 @@ type Props = {
|
|
|
7
7
|
description: any;
|
|
8
8
|
showCloseButton?: boolean;
|
|
9
9
|
onClose?: () => void;
|
|
10
|
-
type?: "success" | "info";
|
|
10
|
+
type?: "success" | "info" | "warning";
|
|
11
11
|
loading?: boolean;
|
|
12
12
|
};
|
|
13
13
|
|
|
@@ -33,6 +33,16 @@ const getConfig = (type: string) => {
|
|
|
33
33
|
<path d="M8.445 12.6675A.9.9 0 0 0 7.1424 13.91l2.5726 2.7448c.3679.3856.9884.3689 1.335-.036l5.591-7.0366a.9.9 0 0 0-1.3674-1.1705l-4.6548 5.9132a.4.4 0 0 1-.607.0252l-1.567-1.6826zM1.9995 12c0-5.5 4.5-10 10-10s10 4.5 10 10-4.5 10-10 10-10-4.5-10-10z"></path>
|
|
34
34
|
),
|
|
35
35
|
};
|
|
36
|
+
case "warning":
|
|
37
|
+
return {
|
|
38
|
+
containerClassName:
|
|
39
|
+
"text-yellow-900 bg-yellow-100 border border-yellow-200 rounded-md",
|
|
40
|
+
buttonClassName:
|
|
41
|
+
"rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-500",
|
|
42
|
+
path: (
|
|
43
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm.93 14.93h-1.86c-.41 0-.75-.34-.75-.75s.34-.75.75-.75h1.86c.41 0 .75.34.75.75s-.34.75-.75.75zm.57-4.42l-.57 2.36h-1.86l-.57-2.36c-.13-.54.21-1.08.76-1.08h1.48c.55 0 .88.54.76 1.08zm0-2.36h-2.58c-.55 0-.88-.54-.76-1.08l.57-2.36h1.86l.57 2.36c.12.54-.21 1.08-.76 1.08z"></path>
|
|
44
|
+
),
|
|
45
|
+
};
|
|
36
46
|
default:
|
|
37
47
|
return {
|
|
38
48
|
containerClassName:
|
package/src/BlockUI/BlockUI.tsx
CHANGED
|
@@ -20,7 +20,7 @@ export const BlockUI = (props: Props) => {
|
|
|
20
20
|
<div className="flex items-center">
|
|
21
21
|
<span className="text-3xl mr-4">{loadingText}</span>
|
|
22
22
|
<svg
|
|
23
|
-
className="animate-spin h-
|
|
23
|
+
className="animate-spin h-5 w-5 text-gray-600"
|
|
24
24
|
xmlns="http://www.w3.org/2000/svg"
|
|
25
25
|
fill="none"
|
|
26
26
|
viewBox="0 0 24 24"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export type ActionListItem = {
|
|
4
|
+
key: string;
|
|
5
|
+
label: string;
|
|
6
|
+
loadingLabel?: string;
|
|
7
|
+
loading?: boolean;
|
|
8
|
+
badge?: string;
|
|
9
|
+
badgeClassName?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
onClick: () => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type ActionListProps = {
|
|
15
|
+
items: ActionListItem[];
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
className?: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const ActionList = ({
|
|
21
|
+
items,
|
|
22
|
+
disabled = false,
|
|
23
|
+
className = "",
|
|
24
|
+
}: ActionListProps) => {
|
|
25
|
+
return (
|
|
26
|
+
<div className={`flex flex-col gap-1 ${className}`}>
|
|
27
|
+
{items.map((item) => {
|
|
28
|
+
const itemBusy = Boolean(item.loading);
|
|
29
|
+
const itemDisabled = disabled || item.disabled || itemBusy;
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<button
|
|
33
|
+
key={item.key}
|
|
34
|
+
type="button"
|
|
35
|
+
disabled={itemDisabled}
|
|
36
|
+
onClick={item.onClick}
|
|
37
|
+
className="flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-1 disabled:cursor-progress disabled:opacity-60"
|
|
38
|
+
>
|
|
39
|
+
{item.badge ? (
|
|
40
|
+
<span
|
|
41
|
+
className={`inline-flex min-w-[2.25rem] justify-center rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${
|
|
42
|
+
item.badgeClassName ?? "bg-gray-100 text-gray-700"
|
|
43
|
+
}`}
|
|
44
|
+
>
|
|
45
|
+
{item.badge}
|
|
46
|
+
</span>
|
|
47
|
+
) : null}
|
|
48
|
+
<span>
|
|
49
|
+
{itemBusy ? (item.loadingLabel ?? item.label) : item.label}
|
|
50
|
+
</span>
|
|
51
|
+
</button>
|
|
52
|
+
);
|
|
53
|
+
})}
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
};
|
package/src/Buttons/Button.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import type { ColorInterface } from "../NavBar/NavBar.types.js";
|
|
|
2
2
|
import { useFormContext } from "react-hook-form";
|
|
3
3
|
import { useState, useRef, useEffect } from "react";
|
|
4
4
|
|
|
5
|
-
type DropdownOption = {
|
|
5
|
+
export type DropdownOption = {
|
|
6
6
|
label: string;
|
|
7
7
|
value: string;
|
|
8
8
|
onClick: () => void;
|
|
@@ -141,7 +141,7 @@ export const Button = (props: Props) => {
|
|
|
141
141
|
className={`${isButtonDisabled ? " bg-opacity-25 " : ""} ${
|
|
142
142
|
loading
|
|
143
143
|
? " cursor-progress"
|
|
144
|
-
: `${isButtonDisabled ? "" : `hover:${color.bg700}`}`
|
|
144
|
+
: `${isButtonDisabled ? " cursor-not-allowed" : `cursor-pointer hover:${color.bg700}`}`
|
|
145
145
|
} inline-flex justify-center rounded-md border border-transparent ${
|
|
146
146
|
color.bg600
|
|
147
147
|
} py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${
|
|
@@ -174,11 +174,13 @@ export const Button = (props: Props) => {
|
|
|
174
174
|
<button
|
|
175
175
|
type="button"
|
|
176
176
|
disabled={isButtonDisabled}
|
|
177
|
+
aria-haspopup="menu"
|
|
178
|
+
aria-expanded={isDropdownOpen}
|
|
177
179
|
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
|
|
178
180
|
className={`${isButtonDisabled ? " bg-opacity-25 " : ""} ${
|
|
179
181
|
loading
|
|
180
182
|
? " cursor-progress"
|
|
181
|
-
: `${isButtonDisabled ? "" : `hover:${color.bg700}`}`
|
|
183
|
+
: `${isButtonDisabled ? " cursor-not-allowed" : `cursor-pointer hover:${color.bg700}`}`
|
|
182
184
|
} inline-flex justify-center items-center rounded-md border border-transparent ${
|
|
183
185
|
color.bg600
|
|
184
186
|
} py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${
|
|
@@ -205,25 +207,29 @@ export const Button = (props: Props) => {
|
|
|
205
207
|
</button>
|
|
206
208
|
</div>
|
|
207
209
|
|
|
208
|
-
{isDropdownOpen && (
|
|
209
|
-
<div
|
|
210
|
+
{isDropdownOpen && !isButtonDisabled ? (
|
|
211
|
+
<div
|
|
212
|
+
role="menu"
|
|
213
|
+
className="absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
|
|
214
|
+
>
|
|
210
215
|
<div className="py-1">
|
|
211
|
-
{dropdownOptions.map((option
|
|
216
|
+
{dropdownOptions.map((option) => (
|
|
212
217
|
<button
|
|
213
|
-
key={
|
|
218
|
+
key={option.value}
|
|
214
219
|
type="button"
|
|
220
|
+
role="menuitem"
|
|
215
221
|
onClick={() => {
|
|
216
222
|
option.onClick();
|
|
217
223
|
setIsDropdownOpen(false);
|
|
218
224
|
}}
|
|
219
|
-
className="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 text-left"
|
|
225
|
+
className="block w-full cursor-pointer px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 text-left"
|
|
220
226
|
>
|
|
221
227
|
{option.label}
|
|
222
228
|
</button>
|
|
223
229
|
))}
|
|
224
230
|
</div>
|
|
225
231
|
</div>
|
|
226
|
-
)}
|
|
232
|
+
) : null}
|
|
227
233
|
</div>
|
|
228
234
|
);
|
|
229
235
|
|
package/src/Buttons/index.ts
CHANGED
|
@@ -3,14 +3,16 @@ import React from "react";
|
|
|
3
3
|
type Props = {
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
className?: string;
|
|
6
|
+
/** Fondo gris de pie de formulario. El nombre `whitBg` se conserva por compatibilidad con las webapps. */
|
|
7
|
+
whitBg?: boolean;
|
|
6
8
|
};
|
|
7
9
|
|
|
8
10
|
export const ButtonSectionContainer = (props: Props) => {
|
|
9
|
-
const { children, className } = props;
|
|
11
|
+
const { children, className, whitBg = false } = props;
|
|
10
12
|
|
|
11
13
|
return (
|
|
12
14
|
<div
|
|
13
|
-
className={
|
|
15
|
+
className={`${whitBg ? "bg-gray-50 px-4 py-3 sm:px-6" : ""} mt-5 flex flex-col md:flex-row md:justify-end md:items-center space-x-0 space-y-4 md:space-y-0 md:space-x-4 ${className}`}
|
|
14
16
|
>
|
|
15
17
|
{children}
|
|
16
18
|
</div>
|