@zauru-sdk/components 6.14.2 → 6.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
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
|
+
# [6.15.0](https://github.com/intuitiva/zauru-typescript-sdk/compare/@zauru-sdk/components@6.14.2...@zauru-sdk/components@6.15.0) (2026-10-28)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* permitir editar GenericDynamicTable sin agregar o borrar filas ([7fc9b41](https://github.com/intuitiva/zauru-typescript-sdk/commit/7fc9b41a7aebf2627a674bc8d9d70b772c378056))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## [6.14.2](https://github.com/intuitiva/zauru-typescript-sdk/compare/@zauru-sdk/components@6.14.1...@zauru-sdk/components@6.14.2) (2026-10-26)
|
|
7
18
|
|
|
8
19
|
|
|
@@ -15,8 +15,13 @@ type Props = {
|
|
|
15
15
|
footerRow?: FooterColumnConfig[];
|
|
16
16
|
thCSSProperties?: React.CSSProperties;
|
|
17
17
|
thElementsClassName?: string;
|
|
18
|
-
/** Controla si se pueden
|
|
18
|
+
/** Controla si se pueden editar los campos. */
|
|
19
19
|
editable?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Si es false, no muestra agregar/eliminar filas aunque `editable` esté activo.
|
|
22
|
+
* Útil para catálogos fijos cuyos valores sí se editan.
|
|
23
|
+
*/
|
|
24
|
+
rowActions?: boolean;
|
|
20
25
|
/** Opciones de búsqueda. */
|
|
21
26
|
searcheables?: SelectFieldOption[];
|
|
22
27
|
/** Activa o desactiva el “skeleton” de carga. */
|
|
@@ -97,12 +97,13 @@ const GenericDynamicTableErrorComponent = ({ name }) => {
|
|
|
97
97
|
*/
|
|
98
98
|
export const GenericDynamicTable = (props) => {
|
|
99
99
|
const { columns, onChange, className, footerRow, defaultValue = [], thCSSProperties, thElementsClassName = "", editable = true, readOnly = false, // Nuevo prop
|
|
100
|
-
searcheables = [], loading = false, paginated = true, defaultItemsPerPage = 10, itemsPerPageOptions = [10, 50, 100], name, withoutBg = false, orientation = "horizontal", maxRows, confirmDelete = true, addRowButtonHandler, rowSummary, } = props;
|
|
100
|
+
rowActions = true, searcheables = [], loading = false, paginated = true, defaultItemsPerPage = 10, itemsPerPageOptions = [10, 50, 100], name, withoutBg = false, orientation = "horizontal", maxRows, confirmDelete = true, addRowButtonHandler, rowSummary, } = props;
|
|
101
101
|
/**
|
|
102
102
|
* Definimos una variable interna para saber si los campos son
|
|
103
103
|
* efectivamente editables: solo si `editable` es true y `readOnly` es false.
|
|
104
104
|
*/
|
|
105
105
|
const isEditable = editable && !readOnly;
|
|
106
|
+
const showRowActions = isEditable && rowActions;
|
|
106
107
|
try {
|
|
107
108
|
const [tableData, setTableData] = useState(defaultValue);
|
|
108
109
|
const [deletedData, setDeletedData] = useState([]);
|
|
@@ -174,9 +175,9 @@ export const GenericDynamicTable = (props) => {
|
|
|
174
175
|
if (orientation === "horizontal") {
|
|
175
176
|
return (_jsxs("tr", { style: { ...thCSSProperties }, children: [rendereableColumns.map((column, index) => {
|
|
176
177
|
const ancho = column.width ??
|
|
177
|
-
(
|
|
178
|
+
(showRowActions ? 94 : 100) / (rendereableColumns.length ?? 1);
|
|
178
179
|
return (_jsx("th", { className: `text-left align-middle p-2 ${thElementsClassName} ${column.headerClassName || ""}`, style: { width: `${ancho}%` }, children: column.label }, index));
|
|
179
|
-
}),
|
|
180
|
+
}), showRowActions && _jsx("th", { style: { width: "4%" } })] }));
|
|
180
181
|
}
|
|
181
182
|
else {
|
|
182
183
|
return null;
|
|
@@ -186,13 +187,13 @@ export const GenericDynamicTable = (props) => {
|
|
|
186
187
|
const rendereableColumns = columns.filter((column) => column.type !== "hidden");
|
|
187
188
|
if (orientation === "horizontal") {
|
|
188
189
|
const rowClassName = index % 2 === 0 ? `${withoutBg ? "" : "bg-gray-200"}` : "";
|
|
189
|
-
const summaryColSpan = rendereableColumns.length + (
|
|
190
|
+
const summaryColSpan = rendereableColumns.length + (showRowActions ? 1 : 0);
|
|
190
191
|
const summaryContent = rowSummary?.(rowData);
|
|
191
|
-
return (_jsxs(React.Fragment, { children: [_jsxs("tr", { className: rowClassName, children: [rendereableColumns.map((column) => renderCell(rowData, column)),
|
|
192
|
+
return (_jsxs(React.Fragment, { children: [_jsxs("tr", { className: rowClassName, children: [rendereableColumns.map((column) => renderCell(rowData, column)), showRowActions && renderDeleteButton(rowData)] }), summaryContent ? (_jsx("tr", { className: rowClassName, children: _jsxs("td", { colSpan: summaryColSpan, className: "px-2 pb-3 pt-0 text-sm text-gray-700 border-b border-gray-300", children: [_jsx("span", { className: "font-medium text-gray-500", children: "Resumen: " }), summaryContent] }) })) : null] }, rowData.id));
|
|
192
193
|
}
|
|
193
194
|
else {
|
|
194
195
|
// Orientación vertical
|
|
195
|
-
return rendereableColumns.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),
|
|
196
|
+
return rendereableColumns.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), showRowActions &&
|
|
196
197
|
column === rendereableColumns[rendereableColumns.length - 1] &&
|
|
197
198
|
renderDeleteButton(rowData)] }, `${rowData.id}-${column.name}`)));
|
|
198
199
|
}
|
|
@@ -303,7 +304,7 @@ export const GenericDynamicTable = (props) => {
|
|
|
303
304
|
};
|
|
304
305
|
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
|
|
305
306
|
.map((x) => x.label)
|
|
306
|
-
.join(", ")}`, onChange: handleChangeSearch, disabled: loading || readOnly }) })), _jsxs("table", { className: "w-full", children: [orientation === "horizontal" && _jsx("thead", { children: renderHeader() }), _jsx("tbody", { children: renderRows() }),
|
|
307
|
+
.join(", ")}`, onChange: handleChangeSearch, disabled: loading || readOnly }) })), _jsxs("table", { className: "w-full", children: [orientation === "horizontal" && _jsx("thead", { children: renderHeader() }), _jsx("tbody", { children: renderRows() }), showRowActions && (_jsx("tfoot", { children: _jsx("tr", { children: _jsx("td", { colSpan: orientation === "horizontal" ? columns.length + 1 : 2, className: "align-middle text-right", children: (!maxRows || tableData.length < maxRows) && (_jsx("button", { className: "bg-blue-500 hover:bg-blue-600 font-bold py-2 px-4 rounded", onClick: (event) => {
|
|
307
308
|
event.preventDefault();
|
|
308
309
|
event.stopPropagation();
|
|
309
310
|
if (addRowButtonHandler) {
|
|
@@ -317,7 +318,7 @@ export const GenericDynamicTable = (props) => {
|
|
|
317
318
|
.map((column, index) => {
|
|
318
319
|
const footerCell = footerRow.find((fc) => fc.name === column.name);
|
|
319
320
|
return (_jsx("td", { colSpan: orientation === "vertical" ? 2 : 1, className: `align-middle ${footerCell?.className || ""}`, children: footerCell ? (footerCell.cell ? (footerCell.cell(tableData)) : (footerCell.content)) : (_jsx(_Fragment, {})) }, index));
|
|
320
|
-
}),
|
|
321
|
+
}), showRowActions && _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 || readOnly, 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() || readOnly, onClickSave: () => setCurrentPage((old) => Math.min(old + 1, totalPages())), children: "Siguiente" })] }), _jsx("div", { children: _jsx("select", { value: itemsPerPage, onChange: (e) => {
|
|
321
322
|
setItemsPerPage(Number(e.target.value));
|
|
322
323
|
setCurrentPage(1); // resetear la página al cambiar los elementos por página
|
|
323
324
|
}, children: itemsPerPageOptions.map((option) => (_jsxs("option", { value: option, children: [option, " elementos por p\u00E1gina"] }, option))) }) })] }))] })] }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zauru-sdk/components",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.15.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",
|
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
"access": "public",
|
|
11
11
|
"registry": "https://registry.npmjs.org/"
|
|
12
12
|
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "npm run build:esm",
|
|
15
|
+
"build:esm": "tsc -p tsconfig.esm.json",
|
|
16
|
+
"play": "ladle serve --port 61000",
|
|
17
|
+
"play:build": "ladle build",
|
|
18
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
19
|
+
},
|
|
13
20
|
"author": {
|
|
14
21
|
"name": "Oscar Cuellar",
|
|
15
22
|
"email": "usackoka@gmail.com"
|
|
@@ -37,6 +44,12 @@
|
|
|
37
44
|
"@reduxjs/toolkit": "^2.2.1",
|
|
38
45
|
"@remix-run/node": "^2.8.1",
|
|
39
46
|
"@remix-run/react": "^2.8.1",
|
|
47
|
+
"@zauru-sdk/common": "^6.12.0",
|
|
48
|
+
"@zauru-sdk/hooks": "^6.4.0",
|
|
49
|
+
"@zauru-sdk/icons": "^6.2.0",
|
|
50
|
+
"@zauru-sdk/redux": "^6.8.1",
|
|
51
|
+
"@zauru-sdk/types": "^6.28.0",
|
|
52
|
+
"@zauru-sdk/utils": "^6.27.0",
|
|
40
53
|
"browser-image-compression": "^2.0.2",
|
|
41
54
|
"framer-motion": "^12.0.0",
|
|
42
55
|
"jsonwebtoken": "^9.0.2",
|
|
@@ -47,20 +60,7 @@
|
|
|
47
60
|
"react-is": "^18.2.0",
|
|
48
61
|
"react-select": "^5.8.0",
|
|
49
62
|
"styled-components": "^5.3.5",
|
|
50
|
-
"zod": "^3.23.8"
|
|
51
|
-
"@zauru-sdk/common": "^6.12.0",
|
|
52
|
-
"@zauru-sdk/icons": "^6.1.0",
|
|
53
|
-
"@zauru-sdk/hooks": "^6.3.23",
|
|
54
|
-
"@zauru-sdk/redux": "^6.7.2",
|
|
55
|
-
"@zauru-sdk/types": "^6.28.0",
|
|
56
|
-
"@zauru-sdk/utils": "^6.26.1"
|
|
63
|
+
"zod": "^3.23.8"
|
|
57
64
|
},
|
|
58
|
-
"gitHead": "
|
|
59
|
-
|
|
60
|
-
"build": "npm run build:esm",
|
|
61
|
-
"build:esm": "tsc -p tsconfig.esm.json",
|
|
62
|
-
"play": "ladle serve --port 61000",
|
|
63
|
-
"play:build": "ladle build",
|
|
64
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
65
|
-
}
|
|
66
|
-
}
|
|
65
|
+
"gitHead": "322f29f8eff1085aba8924ca290f3a04aa54d477"
|
|
66
|
+
}
|
|
@@ -31,8 +31,13 @@ type Props = {
|
|
|
31
31
|
footerRow?: FooterColumnConfig[];
|
|
32
32
|
thCSSProperties?: React.CSSProperties;
|
|
33
33
|
thElementsClassName?: string;
|
|
34
|
-
/** Controla si se pueden
|
|
34
|
+
/** Controla si se pueden editar los campos. */
|
|
35
35
|
editable?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Si es false, no muestra agregar/eliminar filas aunque `editable` esté activo.
|
|
38
|
+
* Útil para catálogos fijos cuyos valores sí se editan.
|
|
39
|
+
*/
|
|
40
|
+
rowActions?: boolean;
|
|
36
41
|
/** Opciones de búsqueda. */
|
|
37
42
|
searcheables?: SelectFieldOption[];
|
|
38
43
|
/** Activa o desactiva el “skeleton” de carga. */
|
|
@@ -169,6 +174,7 @@ export const GenericDynamicTable = (props: Props) => {
|
|
|
169
174
|
thElementsClassName = "",
|
|
170
175
|
editable = true,
|
|
171
176
|
readOnly = false, // Nuevo prop
|
|
177
|
+
rowActions = true,
|
|
172
178
|
searcheables = [],
|
|
173
179
|
loading = false,
|
|
174
180
|
paginated = true,
|
|
@@ -188,6 +194,7 @@ export const GenericDynamicTable = (props: Props) => {
|
|
|
188
194
|
* efectivamente editables: solo si `editable` es true y `readOnly` es false.
|
|
189
195
|
*/
|
|
190
196
|
const isEditable = editable && !readOnly;
|
|
197
|
+
const showRowActions = isEditable && rowActions;
|
|
191
198
|
|
|
192
199
|
try {
|
|
193
200
|
const [tableData, setTableData] = useState<RowDataType[]>(defaultValue);
|
|
@@ -276,7 +283,7 @@ export const GenericDynamicTable = (props: Props) => {
|
|
|
276
283
|
{rendereableColumns.map((column, index) => {
|
|
277
284
|
const ancho =
|
|
278
285
|
column.width ??
|
|
279
|
-
(
|
|
286
|
+
(showRowActions ? 94 : 100) / (rendereableColumns.length ?? 1);
|
|
280
287
|
return (
|
|
281
288
|
<th
|
|
282
289
|
key={index}
|
|
@@ -289,7 +296,7 @@ export const GenericDynamicTable = (props: Props) => {
|
|
|
289
296
|
</th>
|
|
290
297
|
);
|
|
291
298
|
})}
|
|
292
|
-
{
|
|
299
|
+
{showRowActions && <th style={{ width: "4%" }}></th>}
|
|
293
300
|
</tr>
|
|
294
301
|
);
|
|
295
302
|
} else {
|
|
@@ -306,14 +313,14 @@ export const GenericDynamicTable = (props: Props) => {
|
|
|
306
313
|
const rowClassName =
|
|
307
314
|
index % 2 === 0 ? `${withoutBg ? "" : "bg-gray-200"}` : "";
|
|
308
315
|
const summaryColSpan =
|
|
309
|
-
rendereableColumns.length + (
|
|
316
|
+
rendereableColumns.length + (showRowActions ? 1 : 0);
|
|
310
317
|
const summaryContent = rowSummary?.(rowData);
|
|
311
318
|
|
|
312
319
|
return (
|
|
313
320
|
<React.Fragment key={rowData.id}>
|
|
314
321
|
<tr className={rowClassName}>
|
|
315
322
|
{rendereableColumns.map((column) => renderCell(rowData, column))}
|
|
316
|
-
{
|
|
323
|
+
{showRowActions && renderDeleteButton(rowData)}
|
|
317
324
|
</tr>
|
|
318
325
|
{summaryContent ? (
|
|
319
326
|
<tr className={rowClassName}>
|
|
@@ -345,7 +352,7 @@ export const GenericDynamicTable = (props: Props) => {
|
|
|
345
352
|
{column.label}
|
|
346
353
|
</th>
|
|
347
354
|
{renderCell(rowData, column)}
|
|
348
|
-
{
|
|
355
|
+
{showRowActions &&
|
|
349
356
|
column === rendereableColumns[rendereableColumns.length - 1] &&
|
|
350
357
|
renderDeleteButton(rowData)}
|
|
351
358
|
</tr>
|
|
@@ -572,7 +579,7 @@ export const GenericDynamicTable = (props: Props) => {
|
|
|
572
579
|
<table className="w-full">
|
|
573
580
|
{orientation === "horizontal" && <thead>{renderHeader()}</thead>}
|
|
574
581
|
<tbody>{renderRows()}</tbody>
|
|
575
|
-
{
|
|
582
|
+
{showRowActions && (
|
|
576
583
|
<tfoot>
|
|
577
584
|
<tr>
|
|
578
585
|
<td
|
|
@@ -633,7 +640,7 @@ export const GenericDynamicTable = (props: Props) => {
|
|
|
633
640
|
</td>
|
|
634
641
|
);
|
|
635
642
|
})}
|
|
636
|
-
{
|
|
643
|
+
{showRowActions && <td></td>}
|
|
637
644
|
</tr>
|
|
638
645
|
</tfoot>
|
|
639
646
|
)}
|