@zauru-sdk/components 2.0.46 → 2.0.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [2.0.48](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.47...v2.0.48) (2024-10-23)
7
+
8
+ **Note:** Version bump only for package @zauru-sdk/components
9
+
10
+
11
+
12
+
13
+
14
+ ## [2.0.47](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.46...v2.0.47) (2024-10-17)
15
+
16
+ **Note:** Version bump only for package @zauru-sdk/components
17
+
18
+
19
+
20
+
21
+
6
22
  ## [2.0.46](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.45...v2.0.46) (2024-10-17)
7
23
 
8
24
  **Note:** Version bump only for package @zauru-sdk/components
@@ -0,0 +1,4 @@
1
+ export declare const ComponentError: ({ error, componentName, }: {
2
+ error: Error;
3
+ componentName?: string;
4
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -1,2 +1,3 @@
1
1
  export * from "./ErrorBoundaryAlert/ErrorBoundaryAlert.js";
2
2
  export * from "./StaticAlert.js";
3
+ export * from "./ComponentError/index.js";
@@ -3,6 +3,7 @@ import { GenericDynamicTableColumn, RowDataType, SelectFieldOption } from "@zaur
3
3
  export type FooterColumnConfig = {
4
4
  content: React.ReactNode;
5
5
  className?: string;
6
+ name?: string;
6
7
  };
7
8
  type Props = {
8
9
  name?: string;
@@ -33,6 +34,7 @@ type Props = {
33
34
  name="invoice_details"
34
35
  withoutBg
35
36
  editable={!show}
37
+ searcheables={[{ value: "id_number", label: "No. Contraseña" }]}
36
38
  defaultValue={
37
39
  invoiceDetailsDefaultValue ?? [{ id: crypto.randomUUID() }]
38
40
  }
@@ -1,3 +1,4 @@
1
- export declare const ErrorLayout: ({ from }: {
1
+ export declare const ErrorLayout: ({ from, error: parentError, }: {
2
2
  from?: string;
3
+ error?: Error;
3
4
  }) => import("react/jsx-runtime").JSX.Element;
@@ -17,5 +17,5 @@ interface SidePanelProps {
17
17
  widthPercentage?: number;
18
18
  buttonIcon?: "chevron" | "filter" | ReactNode;
19
19
  }
20
- declare const SidePanel: React.FC<SidePanelProps>;
21
- export default SidePanel;
20
+ export declare const SidePanel: React.FC<SidePanelProps>;
21
+ export {};
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ export const ComponentError = ({ error, componentName = "", }) => {
4
+ const [isDetailsOpen, setIsDetailsOpen] = useState(true);
5
+ return (_jsxs("div", { className: "bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative", role: "alert", children: [_jsx("strong", { className: "font-bold", children: "\u00A1Error!" }), _jsxs("span", { className: "block sm:inline", children: ["Ocurri\u00F3 un problema al cargar el componente", componentName ? `: "${componentName}"` : "", "."] }), _jsx("button", { onClick: () => setIsDetailsOpen(!isDetailsOpen), className: "mt-2 text-sm underline cursor-pointer", children: isDetailsOpen ? "Ocultar detalles" : "Ver detalles del error" }), isDetailsOpen && (_jsxs("div", { className: "mt-2 text-sm", children: [_jsx("strong", { children: "Detalles del error:" }), _jsx("pre", { className: "mt-1 whitespace-pre-wrap", children: error instanceof Error ? error.message : String(error) })] })), _jsx("span", { className: "absolute top-0 bottom-0 right-0 px-4 py-3", children: _jsxs("svg", { className: "fill-current h-6 w-6 text-red-500", role: "button", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", children: [_jsx("title", { children: "Cerrar" }), _jsx("path", { d: "M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z" })] }) })] }));
6
+ };
@@ -1,2 +1,3 @@
1
1
  export * from "./ErrorBoundaryAlert/ErrorBoundaryAlert.js";
2
2
  export * from "./StaticAlert.js";
3
+ export * from "./ComponentError/index.js";
@@ -10,6 +10,7 @@ import { LoadingInputSkeleton } from "../Skeletons/index.js";
10
10
  import { WithTooltip } from "../WithTooltip/index.js";
11
11
  import { TrashSvg } from "@zauru-sdk/icons";
12
12
  import { useFormContext } from "react-hook-form";
13
+ import { ComponentError } from "../Alerts/index.js";
13
14
  const GenericDynamicTableErrorComponent = ({ name }) => {
14
15
  const { formState: { errors }, } = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
15
16
  const error = errors ? errors[name ?? "-1"] : undefined;
@@ -25,6 +26,7 @@ const GenericDynamicTableErrorComponent = ({ name }) => {
25
26
  name="invoice_details"
26
27
  withoutBg
27
28
  editable={!show}
29
+ searcheables={[{ value: "id_number", label: "No. Contraseña" }]}
28
30
  defaultValue={
29
31
  invoiceDetailsDefaultValue ?? [{ id: crypto.randomUUID() }]
30
32
  }
@@ -67,181 +69,189 @@ const GenericDynamicTableErrorComponent = ({ name }) => {
67
69
  */
68
70
  export const GenericDynamicTable = (props) => {
69
71
  const { columns, onChange, className, footerRow, defaultValue = [], thCSSProperties, thElementsClassName = "", editable = true, searcheables = [], loading = false, paginated = true, defaultItemsPerPage = 10, itemsPerPageOptions = [10, 50, 100], name, withoutBg = false, orientation = "horizontal", maxRows, } = props;
70
- const [tableData, setTableData] = useState(defaultValue);
71
- const [deletedData, setDeletedData] = useState([]);
72
- const [search, setSearch] = useState("");
73
- const [filteredTableData, setFilteredTableData] = useState(tableData);
74
- const [currentPage, setCurrentPage] = useState(1);
75
- const [itemsPerPage, setItemsPerPage] = useState(defaultItemsPerPage);
76
- useEffect(() => {
77
- if (defaultValue.length) {
78
- setTableData(defaultValue);
79
- }
80
- }, []);
81
- useEffect(() => {
82
- setFilteredTableData(tableData);
83
- }, [tableData]);
84
- useEffect(() => {
85
- changeFilteredData();
86
- }, [tableData, search]);
87
- const totalPages = () => {
88
- return Math.ceil(filteredTableData.length / itemsPerPage);
89
- };
90
- const addRow = () => {
91
- if (maxRows && tableData.length >= maxRows) {
92
- return;
93
- }
94
- const defs = {};
95
- columns.forEach((x) => {
96
- defs[`${x.name}`] =
97
- x.type == "label" || x.type == "textField"
98
- ? ""
99
- : x.type == "selectField"
100
- ? 0
101
- : x.type == "checkbox"
102
- ? false
103
- : 0;
104
- });
105
- setTableData((prevData) => [
106
- ...prevData,
107
- { id: generateClientUUID(), ...defs },
108
- ]);
109
- };
110
- const removeRow = (rowId) => {
111
- const newDeletedData = [...deletedData];
112
- const deletedItem = tableData?.find((x) => x.id === rowId);
113
- if (deletedItem && !isNaN(deletedItem.id)) {
114
- newDeletedData.push(deletedItem);
115
- }
116
- setDeletedData(newDeletedData);
117
- setTableData((prevData) => prevData?.filter((x) => x.id !== rowId));
118
- };
119
- const handleChange = (name, value, rowId) => {
120
- setTableData((prevData) => {
121
- const updatedData = prevData.map((row) => {
122
- if (row.id === rowId) {
123
- return { ...row, [name]: value };
124
- }
125
- return row;
72
+ try {
73
+ const [tableData, setTableData] = useState(defaultValue);
74
+ const [deletedData, setDeletedData] = useState([]);
75
+ const [search, setSearch] = useState("");
76
+ const [filteredTableData, setFilteredTableData] = useState(tableData);
77
+ const [currentPage, setCurrentPage] = useState(1);
78
+ const [itemsPerPage, setItemsPerPage] = useState(defaultItemsPerPage);
79
+ useEffect(() => {
80
+ if (defaultValue.length) {
81
+ setTableData(defaultValue);
82
+ }
83
+ }, []);
84
+ useEffect(() => {
85
+ setFilteredTableData(tableData);
86
+ }, [tableData]);
87
+ useEffect(() => {
88
+ changeFilteredData();
89
+ }, [tableData, search]);
90
+ const totalPages = () => {
91
+ return Math.ceil(filteredTableData.length / itemsPerPage);
92
+ };
93
+ const addRow = () => {
94
+ if (maxRows && tableData.length >= maxRows) {
95
+ return;
96
+ }
97
+ const defs = {};
98
+ columns.forEach((x) => {
99
+ defs[`${x.name}`] =
100
+ x.type == "label" || x.type == "textField"
101
+ ? ""
102
+ : x.type == "selectField"
103
+ ? 0
104
+ : x.type == "checkbox"
105
+ ? false
106
+ : 0;
126
107
  });
127
- onChange && onChange(updatedData);
128
- return updatedData;
129
- });
130
- };
131
- const renderHeader = () => {
132
- if (orientation === "horizontal") {
133
- return (_jsxs("tr", { style: { ...thCSSProperties }, children: [columns.map((column, index) => {
134
- const ancho = column.width ?? (editable ? 94 : 100) / (columns.length ?? 1);
135
- return (_jsx("th", { className: `text-left align-middle p-2 ${thElementsClassName} ${column.headerClassName || ""}`, style: { width: `${ancho}%` }, children: column.label }, index));
136
- }), editable && _jsx("th", { style: { width: "4%" } })] }));
137
- }
138
- else {
139
- return null;
140
- }
141
- };
142
- const renderRow = (rowData, index) => {
143
- if (orientation === "horizontal") {
144
- return (_jsxs("tr", { className: index % 2 === 0 ? `${withoutBg ? "" : "bg-gray-200"}` : "", children: [columns.map((column) => renderCell(rowData, column)), editable && renderDeleteButton(rowData)] }, rowData.id));
145
- }
146
- else {
147
- return columns.map((column) => (_jsxs("tr", { className: index % 2 === 0 ? `${withoutBg ? "" : "bg-gray-200"}` : "", children: [_jsx("th", { className: `text-left align-middle p-2 ${thElementsClassName} ${column.headerClassName || ""}`, children: column.label }), renderCell(rowData, column), editable &&
148
- column === columns[columns.length - 1] &&
149
- renderDeleteButton(rowData)] }, `${rowData.id}-${column.name}`)));
150
- }
151
- };
152
- const renderCell = (rowData, column) => {
153
- if (loading) {
154
- return (_jsx("td", { className: `align-middle p-1 ${column.cellClassName || ""}`, children: _jsx(LoadingInputSkeleton, {}) }, `${rowData.id}-${column.name}`));
155
- }
156
- const tempVal = rowData[column.name];
157
- const defaultVal = column.type === "selectField"
158
- ? column.options?.find((x) => x.value === tempVal)
159
- : tempVal;
160
- if (column.type === "label") {
161
- return (_jsx("td", { className: `align-middle p-1 ${column.cellClassName || ""}`, children: _jsx("div", { children: defaultVal }) }, `${rowData.id}-${column.name}`));
162
- }
163
- const FieldComponent = column.type === "textField"
164
- ? TextField
165
- : column.type === "checkbox"
166
- ? CheckBox
167
- : SelectField;
168
- const setTableValue = (columnName, newValue) => {
169
- handleChange(columnName, newValue, rowData.id);
108
+ setTableData((prevData) => [
109
+ ...prevData,
110
+ { id: generateClientUUID(), ...defs },
111
+ ]);
170
112
  };
171
- return (_jsx("td", { className: `align-middle p-1 ${column.cellClassName || ""}`, children: column.loadingOptions ? (_jsx(LoadingInputSkeleton, {})) : (_jsx(FieldComponent, { name: `${rowData.id}-${column.name}`, type: column.textFieldType, integer: !!column.integer, disabled: column.disabled, isClearable: true, onChange: (value) => {
172
- const sendValue = value?.value ?? value;
173
- handleChange(column.name, sendValue, rowData.id);
174
- column.onChange &&
175
- column.onChange(rowData, sendValue, setTableValue);
176
- }, defaultValue: defaultVal, options: column.options ?? [] }, `${rowData.id}-${column.name}`)) }, `${rowData.id}-${column.name}`));
177
- };
178
- const renderDeleteButton = (rowData) => (_jsx("td", { className: "align-middle w-16", children: _jsx(WithTooltip, { text: "Eliminar", children: _jsx("button", { className: "bg-red-500 hover:bg-red-600 font-bold py-1 px-2 rounded ml-2", onClick: (event) => {
179
- event.preventDefault();
180
- event.stopPropagation();
181
- createModal({
182
- title: "¿Está seguro que quiere eliminar este registro?",
183
- description: "Una vez eliminada la información no podrá ser recuperada.",
184
- }).then((response) => {
185
- if (response === "OK") {
186
- removeRow(rowData.id);
187
- }
188
- });
189
- }, type: "button", children: _jsx(TrashSvg, {}) }) }) }));
190
- const renderRows = () => {
191
- let mapeable = filteredTableData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
192
- if (loading) {
193
- mapeable = [
194
- { id: 1 },
195
- { id: 2 },
196
- { id: 3 },
197
- { id: 4 },
198
- { id: 5 },
199
- { id: 6 },
200
- { id: 7 },
201
- { id: 8 },
202
- { id: 9 },
203
- { id: 10 },
204
- ];
205
- }
206
- return mapeable.map((rowData, index) => renderRow(rowData, index));
207
- };
208
- const handleChangeSearch = (newSearch) => {
209
- setSearch(newSearch);
210
- };
211
- const changeFilteredData = () => {
212
- if (search) {
213
- const filteredData = tableData.filter((rowData) => {
214
- for (const searchable of searcheables) {
215
- const column = columns.find((col) => col.name === searchable.value);
216
- if (column) {
217
- const tempVal = rowData[column.name];
218
- const defaultVal = column.type === "selectField"
219
- ? column.options?.find((x) => x.value === tempVal)?.label
220
- : tempVal;
221
- if (defaultVal
222
- ?.toString()
223
- .toLowerCase()
224
- .includes(search.toLowerCase())) {
225
- return true;
226
- }
113
+ const removeRow = (rowId) => {
114
+ const newDeletedData = [...deletedData];
115
+ const deletedItem = tableData?.find((x) => x.id === rowId);
116
+ if (deletedItem && !isNaN(deletedItem.id)) {
117
+ newDeletedData.push(deletedItem);
118
+ }
119
+ setDeletedData(newDeletedData);
120
+ setTableData((prevData) => prevData?.filter((x) => x.id !== rowId));
121
+ };
122
+ const handleChange = (name, value, rowId) => {
123
+ setTableData((prevData) => {
124
+ const updatedData = prevData.map((row) => {
125
+ if (row.id === rowId) {
126
+ return { ...row, [name]: value };
227
127
  }
228
- }
229
- return false;
128
+ return row;
129
+ });
130
+ onChange && onChange(updatedData);
131
+ return updatedData;
230
132
  });
231
- setFilteredTableData(filteredData);
232
- }
233
- else {
234
- setFilteredTableData(tableData);
235
- }
236
- };
237
- return (_jsxs(_Fragment, { children: [name && (_jsxs(_Fragment, { children: [_jsx(GenericDynamicTableErrorComponent, { name: name }), _jsx("input", { name: name, type: "hidden", value: JSON.stringify(tableData), hidden: true }), _jsx("input", { name: `deleted_${name}`, type: "hidden", value: JSON.stringify(deletedData), hidden: true })] })), _jsxs("div", { className: `${className}`, children: [searcheables.length > 0 && (_jsx("div", { children: _jsx(TextField, { className: "mb-2", name: "search", title: `Buscar por: ${searcheables
238
- .map((x) => x.label)
239
- .join(", ")}`, onChange: handleChangeSearch, disabled: loading }) })), _jsxs("table", { className: "w-full", children: [orientation === "horizontal" && _jsx("thead", { children: renderHeader() }), _jsx("tbody", { children: renderRows() }), editable && (_jsx("tfoot", { children: _jsx("tr", { children: _jsx("td", { colSpan: orientation === "horizontal" ? columns.length + 1 : 2, className: "align-middle", children: (!maxRows || tableData.length < maxRows) && (_jsx("button", { className: "bg-blue-500 hover:bg-blue-600 font-bold py-2 px-4 rounded", onClick: (event) => {
240
- event.preventDefault();
241
- event.stopPropagation();
242
- addRow();
243
- }, type: "button", children: "+" })) }) }) })), footerRow && (_jsx("tfoot", { className: "border-t-2 border-black", children: _jsx("tr", { children: footerRow.map((column, index) => (_jsx("td", { colSpan: orientation === "vertical" ? 2 : 1, className: `align-middle ${column.className || ""}`, children: column.content }, index))) }) }))] }), paginated && totalPages() > 1 && (_jsxs("div", { className: "flex justify-between items-center mt-4", children: [_jsxs("div", { className: "flex items-center", children: [_jsx(Button, { type: "button", disabled: currentPage === 1, onClickSave: () => setCurrentPage((old) => Math.max(old - 1, 1)), children: "Anterior" }), _jsx("span", { className: "mx-2", children: `Página ${currentPage} de ${totalPages()}` }), _jsx(Button, { type: "button", disabled: currentPage === totalPages(), onClickSave: () => setCurrentPage((old) => Math.min(old + 1, totalPages())), children: "Siguiente" })] }), _jsx("div", { children: _jsx("select", { value: itemsPerPage, onChange: (e) => {
244
- setItemsPerPage(Number(e.target.value));
245
- setCurrentPage(1); // resetear la página al cambiar los elementos por página
246
- }, children: itemsPerPageOptions.map((option) => (_jsxs("option", { value: option, children: [option, " elementos por p\u00E1gina"] }, option))) }) })] }))] })] }));
133
+ };
134
+ const renderHeader = () => {
135
+ if (orientation === "horizontal") {
136
+ return (_jsxs("tr", { style: { ...thCSSProperties }, children: [columns.map((column, index) => {
137
+ const ancho = column.width ?? (editable ? 94 : 100) / (columns.length ?? 1);
138
+ return (_jsx("th", { className: `text-left align-middle p-2 ${thElementsClassName} ${column.headerClassName || ""}`, style: { width: `${ancho}%` }, children: column.label }, index));
139
+ }), editable && _jsx("th", { style: { width: "4%" } })] }));
140
+ }
141
+ else {
142
+ return null;
143
+ }
144
+ };
145
+ const renderRow = (rowData, index) => {
146
+ if (orientation === "horizontal") {
147
+ return (_jsxs("tr", { className: index % 2 === 0 ? `${withoutBg ? "" : "bg-gray-200"}` : "", children: [columns.map((column) => renderCell(rowData, column)), editable && renderDeleteButton(rowData)] }, rowData.id));
148
+ }
149
+ else {
150
+ return columns.map((column) => (_jsxs("tr", { className: index % 2 === 0 ? `${withoutBg ? "" : "bg-gray-200"}` : "", children: [_jsx("th", { className: `text-left align-middle p-2 ${thElementsClassName} ${column.headerClassName || ""}`, children: column.label }), renderCell(rowData, column), editable &&
151
+ column === columns[columns.length - 1] &&
152
+ renderDeleteButton(rowData)] }, `${rowData.id}-${column.name}`)));
153
+ }
154
+ };
155
+ const renderCell = (rowData, column) => {
156
+ if (loading) {
157
+ return (_jsx("td", { className: `align-middle p-1 ${column.cellClassName || ""}`, children: _jsx(LoadingInputSkeleton, {}) }, `${rowData.id}-${column.name}`));
158
+ }
159
+ const tempVal = rowData[column.name];
160
+ const defaultVal = column.type === "selectField"
161
+ ? column.options?.find((x) => x.value === tempVal)
162
+ : tempVal;
163
+ if (column.type === "label") {
164
+ return (_jsx("td", { className: `align-middle p-1 ${column.cellClassName || ""}`, children: _jsx("div", { children: defaultVal }) }, `${rowData.id}-${column.name}`));
165
+ }
166
+ const FieldComponent = column.type === "textField"
167
+ ? TextField
168
+ : column.type === "checkbox"
169
+ ? CheckBox
170
+ : SelectField;
171
+ const setTableValue = (columnName, newValue) => {
172
+ handleChange(columnName, newValue, rowData.id);
173
+ };
174
+ return (_jsx("td", { className: `align-middle p-1 ${column.cellClassName || ""}`, children: column.loadingOptions ? (_jsx(LoadingInputSkeleton, {})) : (_jsx(FieldComponent, { name: `${rowData.id}-${column.name}`, type: column.textFieldType, integer: !!column.integer, disabled: column.disabled, isClearable: true, onChange: (value) => {
175
+ const sendValue = value?.value ?? value;
176
+ handleChange(column.name, sendValue, rowData.id);
177
+ column.onChange &&
178
+ column.onChange(rowData, sendValue, setTableValue);
179
+ }, defaultValue: defaultVal, options: column.options ?? [] }, `${rowData.id}-${column.name}`)) }, `${rowData.id}-${column.name}`));
180
+ };
181
+ const renderDeleteButton = (rowData) => (_jsx("td", { className: "align-middle w-16", children: _jsx(WithTooltip, { text: "Eliminar", children: _jsx("button", { className: "bg-red-500 hover:bg-red-600 font-bold py-1 px-2 rounded ml-2", onClick: (event) => {
182
+ event.preventDefault();
183
+ event.stopPropagation();
184
+ createModal({
185
+ title: "¿Está seguro que quiere eliminar este registro?",
186
+ description: "Una vez eliminada la información no podrá ser recuperada.",
187
+ }).then((response) => {
188
+ if (response === "OK") {
189
+ removeRow(rowData.id);
190
+ }
191
+ });
192
+ }, type: "button", children: _jsx(TrashSvg, {}) }) }) }));
193
+ const renderRows = () => {
194
+ let mapeable = filteredTableData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
195
+ if (loading) {
196
+ mapeable = [
197
+ { id: 1 },
198
+ { id: 2 },
199
+ { id: 3 },
200
+ { id: 4 },
201
+ { id: 5 },
202
+ { id: 6 },
203
+ { id: 7 },
204
+ { id: 8 },
205
+ { id: 9 },
206
+ { id: 10 },
207
+ ];
208
+ }
209
+ return mapeable.map((rowData, index) => renderRow(rowData, index));
210
+ };
211
+ const handleChangeSearch = (newSearch) => {
212
+ setSearch(newSearch);
213
+ };
214
+ const changeFilteredData = () => {
215
+ if (search) {
216
+ const filteredData = tableData.filter((rowData) => {
217
+ for (const searchable of searcheables) {
218
+ const column = columns.find((col) => col.name === searchable.value);
219
+ if (column) {
220
+ const tempVal = rowData[column.name];
221
+ const defaultVal = column.type === "selectField"
222
+ ? column.options?.find((x) => x.value === tempVal)?.label
223
+ : tempVal;
224
+ if (defaultVal
225
+ ?.toString()
226
+ .toLowerCase()
227
+ .includes(search.toLowerCase())) {
228
+ return true;
229
+ }
230
+ }
231
+ }
232
+ return false;
233
+ });
234
+ setFilteredTableData(filteredData);
235
+ }
236
+ else {
237
+ setFilteredTableData(tableData);
238
+ }
239
+ };
240
+ return (_jsxs(_Fragment, { children: [name && (_jsxs(_Fragment, { children: [_jsx(GenericDynamicTableErrorComponent, { name: name }), _jsx("input", { name: name, type: "hidden", value: JSON.stringify(tableData), hidden: true }), _jsx("input", { name: `deleted_${name}`, type: "hidden", value: JSON.stringify(deletedData), hidden: true })] })), _jsxs("div", { className: `${className}`, children: [searcheables.length > 0 && (_jsx("div", { children: _jsx(TextField, { className: "mb-2", name: "search", title: `Buscar por: ${searcheables
241
+ .map((x) => x.label)
242
+ .join(", ")}`, onChange: handleChangeSearch, disabled: loading }) })), _jsxs("table", { className: "w-full", children: [orientation === "horizontal" && _jsx("thead", { children: renderHeader() }), _jsx("tbody", { children: renderRows() }), editable && (_jsx("tfoot", { children: _jsx("tr", { children: _jsx("td", { colSpan: orientation === "horizontal" ? columns.length + 1 : 2, className: "align-middle", children: (!maxRows || tableData.length < maxRows) && (_jsx("button", { className: "bg-blue-500 hover:bg-blue-600 font-bold py-2 px-4 rounded", onClick: (event) => {
243
+ event.preventDefault();
244
+ event.stopPropagation();
245
+ addRow();
246
+ }, type: "button", children: "+" })) }) }) })), footerRow && (_jsx("tfoot", { className: "border-t-2 border-black", children: _jsxs("tr", { children: [columns.map((column, index) => {
247
+ const footerCell = footerRow.find((fc) => fc.name === column.name);
248
+ return (_jsx("td", { colSpan: orientation === "vertical" ? 2 : 1, className: `align-middle ${footerCell?.className || ""}`, children: footerCell ? footerCell.content : _jsx(_Fragment, {}) }, index));
249
+ }), editable && _jsx("td", {})] }) }))] }), paginated && totalPages() > 1 && (_jsxs("div", { className: "flex justify-between items-center mt-4", children: [_jsxs("div", { className: "flex items-center", children: [_jsx(Button, { type: "button", disabled: currentPage === 1, onClickSave: () => setCurrentPage((old) => Math.max(old - 1, 1)), children: "Anterior" }), _jsx("span", { className: "mx-2", children: `Página ${currentPage} de ${totalPages()}` }), _jsx(Button, { type: "button", disabled: currentPage === totalPages(), onClickSave: () => setCurrentPage((old) => Math.min(old + 1, totalPages())), children: "Siguiente" })] }), _jsx("div", { children: _jsx("select", { value: itemsPerPage, onChange: (e) => {
250
+ setItemsPerPage(Number(e.target.value));
251
+ setCurrentPage(1); // resetear la página al cambiar los elementos por página
252
+ }, children: itemsPerPageOptions.map((option) => (_jsxs("option", { value: option, children: [option, " elementos por p\u00E1gina"] }, option))) }) })] }))] })] }));
253
+ }
254
+ catch (error) {
255
+ return _jsx(ComponentError, { error: error, componentName: "GenericDynamicTable" });
256
+ }
247
257
  };
@@ -15,7 +15,6 @@ export const SelectField = (props) => {
15
15
  const selectRef = useRef(null);
16
16
  const optionsRef = useRef(null);
17
17
  const [isTabPressed, setIsTabPressed] = useState(false);
18
- const [isEnterPressed, setIsEnterPressed] = useState(false);
19
18
  const [isSearching, setIsSearching] = useState(false);
20
19
  const { register: tempRegister, formState: { errors }, setValue: setFormValue, } = useFormContext() || { formState: {} };
21
20
  const error = errors ? errors[props.name ?? "-1"] : undefined;
@@ -80,6 +79,9 @@ export const SelectField = (props) => {
80
79
  setFormValue(name || "", option.value);
81
80
  }
82
81
  }
82
+ setHighlightedIndex(-1);
83
+ setIsSearching(false);
84
+ setFilteredOptions([]);
83
85
  setIsOpen(false);
84
86
  };
85
87
  const handleClear = () => {
@@ -101,24 +103,13 @@ export const SelectField = (props) => {
101
103
  };
102
104
  const handleBlur = () => {
103
105
  setTimeout(() => {
104
- if (isTabPressed &&
105
- filteredOptions.length > 0 &&
106
- !isEnterPressed &&
107
- isSearching) {
108
- if (highlightedIndex >= 0) {
109
- handleOptionClick(filteredOptions[highlightedIndex]);
110
- }
111
- else {
112
- handleOptionClick(filteredOptions[0]);
113
- }
106
+ if (isTabPressed && highlightedIndex >= 0) {
107
+ handleOptionClick(filteredOptions[highlightedIndex]);
114
108
  }
115
- else if (isTabPressed) {
116
- if (highlightedIndex >= 0) {
117
- handleOptionClick(filteredOptions[highlightedIndex]);
118
- }
109
+ else if (isTabPressed && filteredOptions.length > 0 && isSearching) {
110
+ handleOptionClick(filteredOptions[0]);
119
111
  }
120
112
  setIsTabPressed(false);
121
- setIsEnterPressed(false);
122
113
  setIsSearching(false);
123
114
  setIsOpen(false);
124
115
  }, 200);
@@ -139,7 +130,6 @@ export const SelectField = (props) => {
139
130
  }
140
131
  else if (e.key === "Enter" && highlightedIndex !== -1) {
141
132
  e.preventDefault();
142
- setIsEnterPressed(true);
143
133
  handleOptionClick(filteredOptions[highlightedIndex]);
144
134
  }
145
135
  else if (e.key === "Backspace" && (value || valueMulti.length > 0)) {
@@ -1,10 +1,14 @@
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
- export const ErrorLayout = ({ from }) => {
3
+ import { useState } from "react";
4
+ export const ErrorLayout = ({ from, error: parentError, }) => {
4
5
  const error = useRouteError();
5
- return (_jsxs("html", { lang: "es", className: "bg-gray-900 text-white", children: [_jsxs("head", { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "\u00A1Ups! Algo sali\u00F3 mal" }), _jsx(Meta, {}), _jsx(Links, {})] }), _jsxs("body", { 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", children: [_jsx("p", { className: "text-2xl text-gray-300 mb-8 text-center", children: isRouteErrorResponse(error)
6
+ const [showDetails, setShowDetails] = useState(!!parentError);
7
+ return (_jsxs("html", { lang: "es", className: "bg-gray-900 text-white", children: [_jsxs("head", { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "\u00A1Ups! Algo sali\u00F3 mal" }), _jsx(Meta, {}), _jsx(Links, {})] }), _jsxs("body", { 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)
6
8
  ? `Error ${error.status}: ${error.statusText}`
7
9
  : error instanceof Error
8
10
  ? error.message
9
- : "Ha ocurrido un error inesperado" }), from && (_jsxs("p", { className: "text-lg text-gray-400 mb-4 text-center", children: ["Error lanzado desde: ", from] }))] }), _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", children: _jsx("p", { children: "Si el problema persiste, por favor contacta a soporte." }) }), _jsx(Scripts, {})] })] }));
11
+ : "Ha ocurrido un error inesperado" }), from && (_jsxs("p", { className: "text-lg text-gray-400 mb-4 text-center", children: ["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
12
+ ? parentError.message
13
+ : 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." }) }), _jsx(Scripts, {})] })] }));
10
14
  };
@@ -7,7 +7,7 @@ const ChevronLeftIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg"
7
7
  const ChevronRightIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "h-6 w-6", children: _jsx("path", { fillRule: "evenodd", d: "M16.28 11.47a.75.75 0 010 1.06l-7.5 7.5a.75.75 0 01-1.06-1.06L14.69 12 7.72 5.03a.75.75 0 011.06-1.06l7.5 7.5z", clipRule: "evenodd" }) }));
8
8
  // SVG icon for the filter (bars filter icon)
9
9
  const FilterIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "h-6 w-6", children: _jsx("path", { fillRule: "evenodd", d: "M3 6a1 1 0 011-1h16a1 1 0 110 2H4a1 1 0 01-1-1zm0 6a1 1 0 011-1h10a1 1 0 110 2H4a1 1 0 01-1-1zm0 6a1 1 0 011-1h4a1 1 0 110 2H4a1 1 0 01-1-1z", clipRule: "evenodd" }) }));
10
- const SidePanel = ({ children, closeOnClickOutside = true, widthPercentage = 25, buttonIcon = "chevron", }) => {
10
+ export const SidePanel = ({ children, closeOnClickOutside = true, widthPercentage = 25, buttonIcon = "chevron", }) => {
11
11
  const [isOpen, setIsOpen] = useState(false);
12
12
  const panelRef = useRef(null);
13
13
  const togglePanel = () => {
@@ -43,4 +43,3 @@ const SidePanel = ({ children, closeOnClickOutside = true, widthPercentage = 25,
43
43
  };
44
44
  return (_jsxs(_Fragment, { children: [_jsxs(motion.div, { ref: panelRef, initial: { x: "100%" }, animate: { x: isOpen ? 0 : "100%" }, transition: { type: "spring", stiffness: 300, damping: 30 }, className: `fixed top-0 right-0 h-full bg-white shadow-lg z-[9999] overflow-y-auto`, style: { width: `${widthPercentage}%` }, children: [_jsx("button", { onClick: togglePanel, className: "absolute top-4 left-4 p-2 rounded-full bg-gray-200 hover:bg-gray-300 transition-colors", children: _jsx(ChevronRightIcon, {}) }), _jsx("div", { className: "p-6 mt-16", children: children })] }), _jsx(AnimatePresence, { children: !isOpen && (_jsx(motion.button, { initial: { opacity: 0, x: 20 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: 20 }, transition: { duration: 0.2 }, onClick: togglePanel, className: `fixed top-1/2 right-0 transform -translate-y-1/2 bg-indigo-600 text-white p-3 rounded-l-lg shadow-md hover:bg-indigo-700 transition-colors z-[10000]`, children: renderIcon() })) })] }));
45
45
  };
46
- export default SidePanel;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zauru-sdk/components",
3
- "version": "2.0.46",
3
+ "version": "2.0.48",
4
4
  "description": "Componentes reutilizables en las WebApps de Zauru.",
5
5
  "main": "./dist/esm/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -37,7 +37,7 @@
37
37
  "@zauru-sdk/hooks": "^2.0.44",
38
38
  "@zauru-sdk/icons": "^2.0.0",
39
39
  "@zauru-sdk/types": "^2.0.44",
40
- "@zauru-sdk/utils": "^2.0.46",
40
+ "@zauru-sdk/utils": "^2.0.48",
41
41
  "framer-motion": "^11.7.0",
42
42
  "jsonwebtoken": "^9.0.2",
43
43
  "react": "^18.2.0",
@@ -49,5 +49,5 @@
49
49
  "styled-components": "^5.3.5",
50
50
  "zod": "^3.23.8"
51
51
  },
52
- "gitHead": "aefd2b55a21a873eb419e284f872a40b2e6dec4d"
52
+ "gitHead": "23cf4319aea8a8e017a453c31a4aa327898bf3a1"
53
53
  }