next-recomponents 1.7.63 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +30 -37
- package/dist/index.d.ts +30 -37
- package/dist/index.js +671 -742
- package/dist/index.mjs +677 -748
- package/package.json +1 -1
- package/src/container/index.tsx +3 -6
- package/src/index.tsx +1 -2
- package/src/table/filters.tsx +16 -15
- package/src/table/h.tsx +49 -63
- package/src/table/td.tsx +5 -24
- package/src/table/vtd.tsx +1 -0
- package/src/table3/body.tsx +75 -0
- package/src/table3/dialog.tsx +49 -0
- package/src/table3/filter.tsx +213 -0
- package/src/table3/footer.tsx +56 -0
- package/src/table3/head.tsx +72 -0
- package/src/table3/index.tsx +190 -0
- package/src/table3/panel.tsx +85 -0
- package/src/table3/tr.tsx +148 -0
- package/tsconfig.json +2 -2
- package/src/table2/context.tsx +0 -141
- package/src/table2/h.table.tsx +0 -5
- package/src/table2/icons.tsx +0 -116
- package/src/table2/index.tsx +0 -70
- package/src/table2/v.table.body.tsx +0 -155
- package/src/table2/v.table.head.filter.tsx +0 -196
- package/src/table2/v.table.head.tsx +0 -43
- package/src/table2/v.table.pagination.tsx +0 -73
- package/src/table2/v.table.tsx +0 -58
- package/src/use-modal/index.tsx +0 -79
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export default function TableFooter({
|
|
2
|
+
objectData,
|
|
3
|
+
headers,
|
|
4
|
+
footer,
|
|
5
|
+
selectItems,
|
|
6
|
+
modal,
|
|
7
|
+
}: {
|
|
8
|
+
objectData: any;
|
|
9
|
+
headers: string[];
|
|
10
|
+
footer?: Record<string, "count" | "sum" | "avg">;
|
|
11
|
+
selectItems?: any;
|
|
12
|
+
modal?: any;
|
|
13
|
+
}) {
|
|
14
|
+
function operacion(tipo: "count" | "sum" | "avg", header: string): any {
|
|
15
|
+
switch (tipo) {
|
|
16
|
+
case "count":
|
|
17
|
+
return Object.values(objectData).filter(
|
|
18
|
+
(data: any) => data._visible === true
|
|
19
|
+
).length;
|
|
20
|
+
case "sum":
|
|
21
|
+
return Object.values(objectData)
|
|
22
|
+
.filter((data: any) => data._visible === true)
|
|
23
|
+
.reduce((acc, data: any) => acc + data?.[header], 0);
|
|
24
|
+
case "avg":
|
|
25
|
+
return (
|
|
26
|
+
Object.values(objectData)
|
|
27
|
+
.filter((data: any) => data._visible === true)
|
|
28
|
+
.reduce((acc: number, data: any) => acc + data?.[header], 0) /
|
|
29
|
+
Object.values(objectData).filter(
|
|
30
|
+
(data: any) => data._visible === true
|
|
31
|
+
).length
|
|
32
|
+
);
|
|
33
|
+
default:
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return (
|
|
38
|
+
footer && (
|
|
39
|
+
<tfoot>
|
|
40
|
+
<tr className="bg-blue-500 text-white">
|
|
41
|
+
{selectItems && <th></th>}
|
|
42
|
+
{modal && <th></th>}
|
|
43
|
+
{headers.map((header) => {
|
|
44
|
+
if (header.startsWith("_")) {
|
|
45
|
+
return null;
|
|
46
|
+
} else if (footer?.[header]) {
|
|
47
|
+
return <th key={header}>{operacion(footer[header], header)}</th>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return <th key={header}></th>;
|
|
51
|
+
})}
|
|
52
|
+
</tr>
|
|
53
|
+
</tfoot>
|
|
54
|
+
)
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Filter from "./filter";
|
|
3
|
+
|
|
4
|
+
export default function TableHead({
|
|
5
|
+
headers,
|
|
6
|
+
selectItems,
|
|
7
|
+
setObjectData,
|
|
8
|
+
objectData,
|
|
9
|
+
page,
|
|
10
|
+
setPage,
|
|
11
|
+
maxItems,
|
|
12
|
+
colSizes,
|
|
13
|
+
modal,
|
|
14
|
+
}: {
|
|
15
|
+
headers: string[];
|
|
16
|
+
selectItems?: boolean;
|
|
17
|
+
setObjectData: any;
|
|
18
|
+
objectData: any;
|
|
19
|
+
page: number;
|
|
20
|
+
setPage: any;
|
|
21
|
+
maxItems?: number;
|
|
22
|
+
colSizes?: Record<string, any>;
|
|
23
|
+
modal?: React.ReactNode;
|
|
24
|
+
}) {
|
|
25
|
+
return (
|
|
26
|
+
<thead>
|
|
27
|
+
<tr className="bg-blue-500 text-white font-bold">
|
|
28
|
+
{modal && <th>-</th>}
|
|
29
|
+
{selectItems && (
|
|
30
|
+
<th>
|
|
31
|
+
<input
|
|
32
|
+
className="m-2"
|
|
33
|
+
type="checkbox"
|
|
34
|
+
checked={Object.values(objectData).every(
|
|
35
|
+
(d: any) => d._selected === true
|
|
36
|
+
)}
|
|
37
|
+
onChange={(e) => {
|
|
38
|
+
const newVal = Object.values(objectData).map((d: any) => {
|
|
39
|
+
if (d?._id) {
|
|
40
|
+
return {
|
|
41
|
+
_id: d._id,
|
|
42
|
+
_selected: e.target.checked,
|
|
43
|
+
};
|
|
44
|
+
} else {
|
|
45
|
+
return {
|
|
46
|
+
id: d.id,
|
|
47
|
+
_selected: e.target.checked,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
setObjectData(newVal);
|
|
52
|
+
}}
|
|
53
|
+
/>
|
|
54
|
+
</th>
|
|
55
|
+
)}
|
|
56
|
+
{Object.values(headers).map((h) => {
|
|
57
|
+
if (h.startsWith("_")) return null;
|
|
58
|
+
return (
|
|
59
|
+
<Filter
|
|
60
|
+
key={h}
|
|
61
|
+
objectData={objectData}
|
|
62
|
+
h={h}
|
|
63
|
+
setObjectData={setObjectData}
|
|
64
|
+
setPage={setPage}
|
|
65
|
+
colSizes={colSizes}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
})}
|
|
69
|
+
</tr>
|
|
70
|
+
</thead>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, {
|
|
3
|
+
DetailedHTMLProps,
|
|
4
|
+
TableHTMLAttributes,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useReducer,
|
|
8
|
+
useRef,
|
|
9
|
+
useState,
|
|
10
|
+
} from "react";
|
|
11
|
+
|
|
12
|
+
import TableHead from "./head";
|
|
13
|
+
import TableBody from "./body";
|
|
14
|
+
import Panel from "./panel";
|
|
15
|
+
import TableFooter from "./footer";
|
|
16
|
+
import Dialog from "./dialog";
|
|
17
|
+
|
|
18
|
+
interface Table3Props
|
|
19
|
+
extends DetailedHTMLProps<
|
|
20
|
+
TableHTMLAttributes<HTMLTableElement>,
|
|
21
|
+
HTMLTableElement
|
|
22
|
+
> {
|
|
23
|
+
data: Record<string, any>[];
|
|
24
|
+
selectItems?: boolean;
|
|
25
|
+
maxItems?: number;
|
|
26
|
+
onSave?: (e: any) => void;
|
|
27
|
+
exportName?: string;
|
|
28
|
+
colSizes?: Record<string, number>;
|
|
29
|
+
modal?: React.ReactNode;
|
|
30
|
+
footer?: Record<string, "sum" | "count" | "avg">;
|
|
31
|
+
header?: React.ReactNode;
|
|
32
|
+
onChange?: (e: any) => any;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default function Table3({
|
|
36
|
+
data,
|
|
37
|
+
selectItems,
|
|
38
|
+
maxItems,
|
|
39
|
+
onSave,
|
|
40
|
+
exportName,
|
|
41
|
+
colSizes,
|
|
42
|
+
modal,
|
|
43
|
+
header,
|
|
44
|
+
footer,
|
|
45
|
+
onChange,
|
|
46
|
+
...props
|
|
47
|
+
}: Table3Props) {
|
|
48
|
+
const [handlers, setHandlers] = useState<Record<string, any>>({});
|
|
49
|
+
const [page, setPage] = useState(1);
|
|
50
|
+
|
|
51
|
+
function dataReducer(a: any, b: any) {
|
|
52
|
+
if (b == null) return {};
|
|
53
|
+
if (Array.isArray(b)) {
|
|
54
|
+
const obj = b.reduce((acc: any, bb: any) => {
|
|
55
|
+
const id = bb?.id || bb?._id;
|
|
56
|
+
if (!id) throw new Error("Se necesita el id o _id");
|
|
57
|
+
|
|
58
|
+
const cc = a?.[id]?._updated
|
|
59
|
+
? {
|
|
60
|
+
...bb,
|
|
61
|
+
...a?.[id],
|
|
62
|
+
_selected: bb?._selected,
|
|
63
|
+
_visible: bb?._visible == false ? false : true,
|
|
64
|
+
}
|
|
65
|
+
: {
|
|
66
|
+
...bb,
|
|
67
|
+
_selected: bb?._selected,
|
|
68
|
+
_visible: bb?._visible == false ? false : true,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const newHandlers = { ...handlers };
|
|
72
|
+
|
|
73
|
+
for (let item in cc) {
|
|
74
|
+
const isReactComponent = React.isValidElement(cc[item]);
|
|
75
|
+
|
|
76
|
+
if (isReactComponent) {
|
|
77
|
+
// guarda el componente original
|
|
78
|
+
newHandlers[item] = cc[item];
|
|
79
|
+
|
|
80
|
+
// guarda el valor "actual" en la data
|
|
81
|
+
const value =
|
|
82
|
+
(cc[item] as any)?.props?.value ||
|
|
83
|
+
(typeof (cc[item] as any)?.props?.children !== "object"
|
|
84
|
+
? (cc[item] as any)?.props?.children
|
|
85
|
+
: "");
|
|
86
|
+
cc[item] = value || "";
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
setHandlers(newHandlers);
|
|
91
|
+
|
|
92
|
+
acc[id] = { ...bb, ...cc };
|
|
93
|
+
|
|
94
|
+
return acc;
|
|
95
|
+
}, {});
|
|
96
|
+
|
|
97
|
+
return obj;
|
|
98
|
+
} else {
|
|
99
|
+
const newA = { ...a };
|
|
100
|
+
const id = b?.id || b?._id;
|
|
101
|
+
if (!id) throw new Error("Se necesita el id o _id para actualizar");
|
|
102
|
+
|
|
103
|
+
newA[id] = { ...newA[id], ...b };
|
|
104
|
+
|
|
105
|
+
return newA;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const [objectData, setObjectData] = useReducer(dataReducer, null);
|
|
109
|
+
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
setObjectData(data);
|
|
112
|
+
setPage(1);
|
|
113
|
+
}, [data]);
|
|
114
|
+
|
|
115
|
+
const headers = useMemo<string[]>(() => {
|
|
116
|
+
if (!objectData) return [];
|
|
117
|
+
return [
|
|
118
|
+
...new Set<any>(
|
|
119
|
+
Object.values(objectData)
|
|
120
|
+
.map((o: any) => Object.keys(o))
|
|
121
|
+
.flat()
|
|
122
|
+
),
|
|
123
|
+
];
|
|
124
|
+
}, [objectData]);
|
|
125
|
+
const totalPages = useMemo(() => {
|
|
126
|
+
if (!objectData) return 0;
|
|
127
|
+
return maxItems ? Math.ceil(Object.keys(objectData).length / maxItems) : 1;
|
|
128
|
+
}, [objectData, maxItems]);
|
|
129
|
+
|
|
130
|
+
const modalRef = useRef<HTMLDialogElement>(null);
|
|
131
|
+
const [dialogRow, setDialogRow] = useState<any>({});
|
|
132
|
+
const context = {
|
|
133
|
+
objectData,
|
|
134
|
+
headers,
|
|
135
|
+
handlers,
|
|
136
|
+
setObjectData,
|
|
137
|
+
page,
|
|
138
|
+
setPage,
|
|
139
|
+
totalPages,
|
|
140
|
+
exportName,
|
|
141
|
+
onSave,
|
|
142
|
+
modalRef,
|
|
143
|
+
modal,
|
|
144
|
+
dialogRow,
|
|
145
|
+
setDialogRow,
|
|
146
|
+
selectItems,
|
|
147
|
+
maxItems,
|
|
148
|
+
colSizes,
|
|
149
|
+
header,
|
|
150
|
+
footer,
|
|
151
|
+
onChange,
|
|
152
|
+
...props,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
if (dialogRow?.id || dialogRow?._id) {
|
|
157
|
+
const newDialogRow =
|
|
158
|
+
objectData[dialogRow?.id] || objectData[dialogRow?._id];
|
|
159
|
+
setDialogRow(newDialogRow);
|
|
160
|
+
}
|
|
161
|
+
}, [objectData]);
|
|
162
|
+
|
|
163
|
+
const style: any = props?.style
|
|
164
|
+
? { ...props.style, tableLayout: "fixed" }
|
|
165
|
+
: { tableLayout: "fixed" };
|
|
166
|
+
|
|
167
|
+
if (!objectData) return null;
|
|
168
|
+
console.log({ objectData });
|
|
169
|
+
return (
|
|
170
|
+
<div className="border shadow rounded m-1 p-1 bg-white">
|
|
171
|
+
{modal && (
|
|
172
|
+
<Dialog
|
|
173
|
+
modalRef={modalRef}
|
|
174
|
+
dialogRow={dialogRow}
|
|
175
|
+
setDialogRow={setDialogRow}
|
|
176
|
+
setObjectData={setObjectData}
|
|
177
|
+
>
|
|
178
|
+
{modal}
|
|
179
|
+
</Dialog>
|
|
180
|
+
)}
|
|
181
|
+
<div className="font-bold text-2xl py-5 px-2 bg-blue-50">{header}</div>
|
|
182
|
+
<Panel {...context} />
|
|
183
|
+
<table {...props} style={style}>
|
|
184
|
+
<TableHead {...context} />
|
|
185
|
+
<TableBody {...context} />
|
|
186
|
+
<TableFooter {...context} />
|
|
187
|
+
</table>
|
|
188
|
+
</div>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ExcelIcon, SaveIcon } from "../../src/table/filters";
|
|
2
|
+
import useExcel from "../../src/use-excel";
|
|
3
|
+
|
|
4
|
+
export default function Panel({
|
|
5
|
+
page,
|
|
6
|
+
setPage,
|
|
7
|
+
onSave,
|
|
8
|
+
objectData,
|
|
9
|
+
exportName,
|
|
10
|
+
totalPages,
|
|
11
|
+
}: {
|
|
12
|
+
page: number;
|
|
13
|
+
setPage: any;
|
|
14
|
+
onSave?: any;
|
|
15
|
+
objectData: any;
|
|
16
|
+
exportName?: string;
|
|
17
|
+
totalPages: number;
|
|
18
|
+
}) {
|
|
19
|
+
const excel = useExcel();
|
|
20
|
+
return (
|
|
21
|
+
<div className="flex gap-2 bg-gray-100 items-center">
|
|
22
|
+
<div className="flex gap-1 ">
|
|
23
|
+
{onSave && (
|
|
24
|
+
<button
|
|
25
|
+
className="p-2 border shadow rounded bg-blue-500 text-white flex items-center gap-1 text-md"
|
|
26
|
+
onClick={(e) => {
|
|
27
|
+
onSave?.(Object.values(objectData).reverse());
|
|
28
|
+
}}
|
|
29
|
+
>
|
|
30
|
+
{" "}
|
|
31
|
+
<SaveIcon />
|
|
32
|
+
Guardar
|
|
33
|
+
</button>
|
|
34
|
+
)}
|
|
35
|
+
{exportName && (
|
|
36
|
+
<button
|
|
37
|
+
className="p-2 border shadow rounded bg-green-800 text-white flex items-center gap-1 text-md"
|
|
38
|
+
onClick={(e) => {
|
|
39
|
+
excel.export(
|
|
40
|
+
Object.values(objectData)
|
|
41
|
+
.reverse()
|
|
42
|
+
.map((d: any) => {
|
|
43
|
+
const { _visible, _id, _selected, ...data } = d;
|
|
44
|
+
return data;
|
|
45
|
+
}) as any[],
|
|
46
|
+
exportName + ".xlsx"
|
|
47
|
+
);
|
|
48
|
+
}}
|
|
49
|
+
>
|
|
50
|
+
<ExcelIcon />
|
|
51
|
+
Exportar
|
|
52
|
+
</button>
|
|
53
|
+
)}
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div className="flex gap-2 items-center text-2xl">
|
|
57
|
+
<button onClick={() => setPage(1)} disabled={page === 1}>
|
|
58
|
+
⏮
|
|
59
|
+
</button>
|
|
60
|
+
|
|
61
|
+
<button onClick={() => setPage(page - 1)} disabled={page === 1}>
|
|
62
|
+
◀
|
|
63
|
+
</button>
|
|
64
|
+
|
|
65
|
+
<span className="text-sm">
|
|
66
|
+
Página {page} / {totalPages}
|
|
67
|
+
</span>
|
|
68
|
+
|
|
69
|
+
<button
|
|
70
|
+
onClick={() => setPage(page + 1)}
|
|
71
|
+
disabled={page === totalPages}
|
|
72
|
+
>
|
|
73
|
+
▶
|
|
74
|
+
</button>
|
|
75
|
+
|
|
76
|
+
<button
|
|
77
|
+
onClick={() => setPage(totalPages)}
|
|
78
|
+
disabled={page === totalPages}
|
|
79
|
+
>
|
|
80
|
+
⏭
|
|
81
|
+
</button>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { EditIcon } from "../../src/table/filters";
|
|
3
|
+
|
|
4
|
+
export default function TR({
|
|
5
|
+
handlers,
|
|
6
|
+
setObjectData,
|
|
7
|
+
id,
|
|
8
|
+
row,
|
|
9
|
+
headers,
|
|
10
|
+
selectItems,
|
|
11
|
+
colSizes,
|
|
12
|
+
modal,
|
|
13
|
+
modalRef,
|
|
14
|
+
dialogRow,
|
|
15
|
+
setDialogRow,
|
|
16
|
+
index,
|
|
17
|
+
selected,
|
|
18
|
+
setSelected,
|
|
19
|
+
onChange,
|
|
20
|
+
}: {
|
|
21
|
+
handlers: any;
|
|
22
|
+
setObjectData: any;
|
|
23
|
+
headers: string[];
|
|
24
|
+
id: any;
|
|
25
|
+
row: any;
|
|
26
|
+
selectItems?: boolean;
|
|
27
|
+
colSizes?: Record<string, any>;
|
|
28
|
+
modal?: React.ReactNode;
|
|
29
|
+
modalRef: React.RefObject<HTMLDialogElement>;
|
|
30
|
+
dialogRow: any;
|
|
31
|
+
setDialogRow: any;
|
|
32
|
+
index: number;
|
|
33
|
+
selected: number;
|
|
34
|
+
setSelected: any;
|
|
35
|
+
onChange: any;
|
|
36
|
+
}) {
|
|
37
|
+
const color =
|
|
38
|
+
selected == index
|
|
39
|
+
? "bg-blue-600 text-white hover:bg-blue-800"
|
|
40
|
+
: index % 2 == 0
|
|
41
|
+
? "bg-white"
|
|
42
|
+
: "bg-blue-50";
|
|
43
|
+
return (
|
|
44
|
+
<tr
|
|
45
|
+
key={id}
|
|
46
|
+
className={` hover:bg-blue-100 ${color} cursor-pointer`}
|
|
47
|
+
onClick={(e) => {
|
|
48
|
+
setSelected(selected == index ? -1 : index);
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
{modal && (
|
|
52
|
+
<th className="border">
|
|
53
|
+
<button
|
|
54
|
+
className="p-1 border shadow-rounded bg-blue-500 rounded text-white"
|
|
55
|
+
onClick={(e) => {
|
|
56
|
+
modalRef.current?.showModal();
|
|
57
|
+
setDialogRow(row);
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<EditIcon />
|
|
61
|
+
</button>
|
|
62
|
+
</th>
|
|
63
|
+
)}
|
|
64
|
+
{selectItems && (
|
|
65
|
+
<th className="border">
|
|
66
|
+
<input
|
|
67
|
+
type="checkbox"
|
|
68
|
+
checked={Boolean(row?._selected)}
|
|
69
|
+
onChange={(e) => {
|
|
70
|
+
if (row?._id) {
|
|
71
|
+
setObjectData({ _id: +id, _selected: e.target.checked });
|
|
72
|
+
} else {
|
|
73
|
+
setObjectData({ id: +id, _selected: e.target.checked });
|
|
74
|
+
}
|
|
75
|
+
}}
|
|
76
|
+
/>
|
|
77
|
+
</th>
|
|
78
|
+
)}
|
|
79
|
+
{headers.map((h) => {
|
|
80
|
+
const colSize = colSizes?.[h];
|
|
81
|
+
if (h.startsWith("_")) {
|
|
82
|
+
return null;
|
|
83
|
+
} else if (handlers?.[h]) {
|
|
84
|
+
const original = handlers[h];
|
|
85
|
+
|
|
86
|
+
const cloned = React.cloneElement(original, {
|
|
87
|
+
// si es controlado por value → actualiza con row[h]
|
|
88
|
+
value: original.props?.value !== undefined ? row[h] : undefined,
|
|
89
|
+
|
|
90
|
+
// si usa children → actualiza con row[h] también
|
|
91
|
+
children: original.props?.children
|
|
92
|
+
? typeof original.props.children == "object"
|
|
93
|
+
? original.props?.children
|
|
94
|
+
: row?.[h]
|
|
95
|
+
: null,
|
|
96
|
+
|
|
97
|
+
...Object.keys({
|
|
98
|
+
...original.props,
|
|
99
|
+
onChange: original.props?.onChange,
|
|
100
|
+
})
|
|
101
|
+
.filter((action) => action.startsWith("on"))
|
|
102
|
+
.reduce((acc, action) => {
|
|
103
|
+
acc[action] = (e: any) => {
|
|
104
|
+
e.row = row;
|
|
105
|
+
|
|
106
|
+
const userResponse = original.props?.[action]?.(e) || {};
|
|
107
|
+
const newObject = row?._id
|
|
108
|
+
? {
|
|
109
|
+
_id: row?._id,
|
|
110
|
+
[h]: e.target.value,
|
|
111
|
+
_updated: true,
|
|
112
|
+
_visible: true,
|
|
113
|
+
...userResponse,
|
|
114
|
+
}
|
|
115
|
+
: {
|
|
116
|
+
id: row?.id || null,
|
|
117
|
+
[h]: e.target.value,
|
|
118
|
+
_updated: true,
|
|
119
|
+
_visible: true,
|
|
120
|
+
...userResponse,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const finalResponse =
|
|
124
|
+
action == "onChange" && onChange
|
|
125
|
+
? onChange({ ...e, row: { ...e.row, ...newObject } })
|
|
126
|
+
: {};
|
|
127
|
+
|
|
128
|
+
setObjectData({ ...newObject, ...finalResponse });
|
|
129
|
+
};
|
|
130
|
+
return acc;
|
|
131
|
+
}, {} as any),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<td key={h} className={`text-black `}>
|
|
136
|
+
{cloned}
|
|
137
|
+
</td>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
return (
|
|
141
|
+
<td key={h} className={`text-center border max-w-[${colSize}px]`}>
|
|
142
|
+
{row[h]}
|
|
143
|
+
</td>
|
|
144
|
+
);
|
|
145
|
+
})}
|
|
146
|
+
</tr>
|
|
147
|
+
);
|
|
148
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES6",
|
|
4
|
-
"module": "
|
|
5
|
-
"moduleResolution": "node16",
|
|
4
|
+
"module": "ESNext",
|
|
6
5
|
"jsx": "react-jsx",
|
|
7
6
|
"declaration": true,
|
|
8
7
|
"outDir": "dist",
|
|
9
8
|
"esModuleInterop": true,
|
|
9
|
+
"moduleResolution": "node",
|
|
10
10
|
"skipLibCheck": true,
|
|
11
11
|
"strict": true,
|
|
12
12
|
"baseUrl": "."
|
package/src/table2/context.tsx
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { useEffect, useMemo, useState } from "react";
|
|
2
|
-
import useExcel from "src/use-excel";
|
|
3
|
-
|
|
4
|
-
export default function useTableContext({
|
|
5
|
-
data,
|
|
6
|
-
maxItems,
|
|
7
|
-
symbols,
|
|
8
|
-
handlers,
|
|
9
|
-
onSave,
|
|
10
|
-
exportName,
|
|
11
|
-
selectItems,
|
|
12
|
-
colSizes,
|
|
13
|
-
}: {
|
|
14
|
-
data: Record<string, any>[];
|
|
15
|
-
maxItems: number;
|
|
16
|
-
symbols: Record<string, React.ReactNode>;
|
|
17
|
-
handlers: Record<string, React.ReactNode>;
|
|
18
|
-
onSave?: (data: Record<string, any>[]) => void;
|
|
19
|
-
exportName?: string;
|
|
20
|
-
selectItems?: boolean;
|
|
21
|
-
colSizes?: Record<string, number>;
|
|
22
|
-
}) {
|
|
23
|
-
function dataReduce(datums: Record<string, any>[]) {
|
|
24
|
-
return datums
|
|
25
|
-
.map((row: any) => {
|
|
26
|
-
for (let key in row) {
|
|
27
|
-
if (typeof row[key] === "object") {
|
|
28
|
-
row[key] = JSON.stringify(row[key]);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return row;
|
|
32
|
-
})
|
|
33
|
-
.reduce((acc, d) => {
|
|
34
|
-
const id = d?._id || d?.id;
|
|
35
|
-
if (!id) throw new Error("Data must have an '_id' or 'id' field");
|
|
36
|
-
acc[id] = d;
|
|
37
|
-
acc[id]._checkedItem = false;
|
|
38
|
-
return acc;
|
|
39
|
-
}, {});
|
|
40
|
-
}
|
|
41
|
-
const excel = useExcel();
|
|
42
|
-
|
|
43
|
-
const [defaultData, setDefaultData] = useState(dataReduce(data));
|
|
44
|
-
|
|
45
|
-
const [page, setPage] = useState(1);
|
|
46
|
-
|
|
47
|
-
const headers = useMemo(() => {
|
|
48
|
-
return [...new Set(data.flatMap((d) => Object.keys(d)))];
|
|
49
|
-
}, [data]);
|
|
50
|
-
|
|
51
|
-
const list = useMemo(() => {
|
|
52
|
-
return headers.reduce((acc, h) => {
|
|
53
|
-
acc[h] = [
|
|
54
|
-
...new Set(
|
|
55
|
-
Object.values(defaultData).map((row: any) => {
|
|
56
|
-
const value =
|
|
57
|
-
typeof row[h] === "object" ? JSON.stringify(row[h]) : row[h];
|
|
58
|
-
return value;
|
|
59
|
-
})
|
|
60
|
-
),
|
|
61
|
-
];
|
|
62
|
-
return acc;
|
|
63
|
-
}, {} as any);
|
|
64
|
-
}, [headers, defaultData]);
|
|
65
|
-
|
|
66
|
-
const [filters, setFilters] = useState<any>(
|
|
67
|
-
headers.reduce((acc, h) => {
|
|
68
|
-
acc[h] = list[h].reduce((ac: any, l: any) => {
|
|
69
|
-
ac[l] = true;
|
|
70
|
-
return ac;
|
|
71
|
-
}, {});
|
|
72
|
-
return acc;
|
|
73
|
-
}, {} as any)
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
const bodyKeys = useMemo(() => Object.keys(defaultData), [defaultData]);
|
|
77
|
-
const body = useMemo(() => defaultData, [defaultData]);
|
|
78
|
-
|
|
79
|
-
const filteredBody = useMemo(() => {
|
|
80
|
-
return bodyKeys.filter((key) => {
|
|
81
|
-
return headers.every((header) => {
|
|
82
|
-
return (
|
|
83
|
-
filters?.[`${header}`]?.[body?.[`${key}`]?.[`${header}`]] !== false
|
|
84
|
-
);
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
}, [filters, headers, defaultData]);
|
|
88
|
-
|
|
89
|
-
const paginatedBody = useMemo(() => {
|
|
90
|
-
return filteredBody.filter((k, index) => {
|
|
91
|
-
if (maxItems === Infinity) return true;
|
|
92
|
-
|
|
93
|
-
const desde = (page - 1) * maxItems;
|
|
94
|
-
const hasta = desde + maxItems;
|
|
95
|
-
return index >= desde && index < hasta;
|
|
96
|
-
});
|
|
97
|
-
}, [filteredBody, page]);
|
|
98
|
-
|
|
99
|
-
const totalPages = useMemo(
|
|
100
|
-
() =>
|
|
101
|
-
maxItems === Infinity ? 1 : Math.ceil(filteredBody.length / maxItems),
|
|
102
|
-
[filteredBody, maxItems]
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
useEffect(() => {
|
|
106
|
-
const original = dataReduce(data);
|
|
107
|
-
const originalKeys = Object.keys(original);
|
|
108
|
-
setDefaultData((prevDefaultData: any) => {
|
|
109
|
-
const newDefault: any = {};
|
|
110
|
-
for (let key of originalKeys) {
|
|
111
|
-
// si ya existía en el estado anterior, lo conservamos
|
|
112
|
-
newDefault[key] = prevDefaultData?.[key] ?? original[key];
|
|
113
|
-
}
|
|
114
|
-
return newDefault;
|
|
115
|
-
});
|
|
116
|
-
}, [data]);
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
page,
|
|
120
|
-
setPage,
|
|
121
|
-
defaultData,
|
|
122
|
-
setDefaultData,
|
|
123
|
-
totalPages,
|
|
124
|
-
headers,
|
|
125
|
-
filters,
|
|
126
|
-
setFilters,
|
|
127
|
-
list,
|
|
128
|
-
filteredBody,
|
|
129
|
-
maxItems,
|
|
130
|
-
paginatedBody,
|
|
131
|
-
handlers,
|
|
132
|
-
symbols,
|
|
133
|
-
onSave,
|
|
134
|
-
exportName,
|
|
135
|
-
excel,
|
|
136
|
-
selectItems,
|
|
137
|
-
colSizes,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export type TableContextType = ReturnType<typeof useTableContext>;
|