next-recomponents 1.3.4 → 1.3.6
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 +11 -5
- package/dist/index.d.ts +11 -5
- package/dist/index.js +292 -274
- package/dist/index.mjs +284 -266
- package/package.json +1 -1
- package/src/table/filter.menu.tsx +5 -8
- package/src/table/filters.tsx +16 -0
- package/src/table/h.tsx +74 -31
- package/src/table/index.tsx +9 -40
- package/src/table/td.tsx +48 -57
package/package.json
CHANGED
|
@@ -22,13 +22,7 @@ export default function FilterMenu({
|
|
|
22
22
|
|
|
23
23
|
useEffect(() => {
|
|
24
24
|
setNewMapedData(
|
|
25
|
-
[
|
|
26
|
-
...new Set<string>(
|
|
27
|
-
mapedData
|
|
28
|
-
.filter((md) => md.__visible__ === true)
|
|
29
|
-
.map((md: any) => md[h])
|
|
30
|
-
),
|
|
31
|
-
].filter((item) => {
|
|
25
|
+
[...new Set<string>(mapedData.map((md: any) => md[h]))].filter((item) => {
|
|
32
26
|
return item && `${item}`.toLowerCase().includes(text.toLowerCase());
|
|
33
27
|
})
|
|
34
28
|
);
|
|
@@ -90,10 +84,13 @@ export default function FilterMenu({
|
|
|
90
84
|
.every((d) => d === false)}
|
|
91
85
|
onChange={(e) => {
|
|
92
86
|
const nmd = [...mapedData];
|
|
87
|
+
const all = nmd
|
|
88
|
+
.map((d) => d[h].exclude)
|
|
89
|
+
.every((d) => d === false);
|
|
93
90
|
setMapedData(
|
|
94
91
|
nmd.map((d) => {
|
|
95
92
|
const newd = { ...d };
|
|
96
|
-
newd[h].exclude =
|
|
93
|
+
newd[h].exclude = all;
|
|
97
94
|
return newd;
|
|
98
95
|
})
|
|
99
96
|
);
|
package/src/table/filters.tsx
CHANGED
|
@@ -14,6 +14,22 @@ export function FilterOffIcon() {
|
|
|
14
14
|
);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export function SaveIcon() {
|
|
18
|
+
return (
|
|
19
|
+
<svg
|
|
20
|
+
stroke="currentColor"
|
|
21
|
+
fill="currentColor"
|
|
22
|
+
strokeWidth="0"
|
|
23
|
+
viewBox="0 0 512 512"
|
|
24
|
+
height="20px"
|
|
25
|
+
width="20px"
|
|
26
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
27
|
+
>
|
|
28
|
+
<path d="M272 64h-16c-4.4 0-8 3.6-8 8v72c0 4.4 7.6 8 12 8h12c4.4 0 8-3.6 8-8V72c0-4.4-3.6-8-8-8z"></path>
|
|
29
|
+
<path d="M433.9 130.1L382 78.2c-9-9-21.3-14.2-34.1-14.2h-28c-8.8 0-16 7.3-16 16.2v80c0 8.8-7.2 16-16 16H160c-8.8 0-16-7.2-16-16v-80c0-8.8-7.2-16.2-16-16.2H96c-17.6 0-32 14.4-32 32v320c0 17.6 14.4 32 32 32h320c17.6 0 32-14.4 32-32V164c0-12.7-5.1-24.9-14.1-33.9zM322 400.1c0 8.8-8 16-17.8 16H143.8c-9.8 0-17.8-7.2-17.8-16v-96c0-8.8 8-16 17.8-16h160.4c9.8 0 17.8 7.2 17.8 16v96z"></path>
|
|
30
|
+
</svg>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
17
33
|
export function ExcelIcon() {
|
|
18
34
|
return (
|
|
19
35
|
<svg
|
package/src/table/h.tsx
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { TableProps } from ".";
|
|
3
3
|
import TD from "./td";
|
|
4
|
-
import { FilterOffIcon } from "./filters";
|
|
4
|
+
import { ExcelIcon, FilterOffIcon, SaveIcon } from "./filters";
|
|
5
5
|
import FilterMenu from "./filter.menu";
|
|
6
|
+
import useExportdata from "./export";
|
|
6
7
|
|
|
7
8
|
export default function HTable({
|
|
8
9
|
data,
|
|
9
|
-
mapedData,
|
|
10
|
-
setMapedData,
|
|
11
10
|
symbols,
|
|
12
11
|
totals,
|
|
13
12
|
exportName,
|
|
13
|
+
onSave,
|
|
14
14
|
...props
|
|
15
15
|
}: TableProps) {
|
|
16
|
+
if (!Array.isArray(data)) return null;
|
|
17
|
+
const [mapedData, setMapedData] = useState([...data]);
|
|
18
|
+
const exported = useExportdata();
|
|
16
19
|
const [selected, setSelected] = useState<number | null>(null);
|
|
17
20
|
const [selectedFilter, setSelectedFilter] = useState<number | null>(null);
|
|
18
21
|
const modalRef = useRef<HTMLDialogElement>(null);
|
|
@@ -34,22 +37,31 @@ export default function HTable({
|
|
|
34
37
|
}, {});
|
|
35
38
|
}, [mapedData]);
|
|
36
39
|
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
setMapedData(data);
|
|
42
|
+
}, [data]);
|
|
43
|
+
|
|
37
44
|
useEffect(() => {
|
|
38
45
|
const newData = data.map((d: any, trkey: number) => {
|
|
39
|
-
const obj: any = {
|
|
46
|
+
const obj: any = {};
|
|
40
47
|
for (let key in d) {
|
|
48
|
+
const item: any = {};
|
|
49
|
+
for (let key in d) {
|
|
50
|
+
item[key] = d[key]?.content || d[key];
|
|
51
|
+
}
|
|
41
52
|
const typeOf = typeof d[key];
|
|
42
53
|
const isObject = typeOf == "object";
|
|
43
|
-
const isDate = typeOf == "string" && d[key].includes("T");
|
|
54
|
+
const isDate = typeOf == "string" && d[key].toString().includes("T");
|
|
44
55
|
const cellTypeOf = isDate ? "date" : isObject ? "object" : typeOf;
|
|
45
56
|
const content =
|
|
46
57
|
cellTypeOf == "date"
|
|
47
58
|
? d[key].split("T").join(" ").split(".")[0]
|
|
48
59
|
: cellTypeOf == "object"
|
|
49
60
|
? React.isValidElement(d[key])
|
|
50
|
-
? d[key]
|
|
61
|
+
? (d[key]?.props as any).defaultValue
|
|
51
62
|
: JSON.stringify(d[key])
|
|
52
63
|
: d[key];
|
|
64
|
+
const handler = React.isValidElement(d[key]) ? d[key] : null;
|
|
53
65
|
obj[key] = {
|
|
54
66
|
index: trkey,
|
|
55
67
|
originalData: content,
|
|
@@ -58,14 +70,44 @@ export default function HTable({
|
|
|
58
70
|
content,
|
|
59
71
|
name: key,
|
|
60
72
|
exclude: false,
|
|
73
|
+
handler,
|
|
61
74
|
};
|
|
62
75
|
}
|
|
63
76
|
return obj;
|
|
64
77
|
});
|
|
65
78
|
setMapedData(newData);
|
|
66
79
|
}, [data]);
|
|
80
|
+
|
|
81
|
+
const values = useMemo(() => {
|
|
82
|
+
return mapedData
|
|
83
|
+
.map((d: any) => Object.keys(d).map((k) => ({ [k]: d[k].content })))
|
|
84
|
+
.map((d) => Object.assign({}, ...d));
|
|
85
|
+
}, [mapedData]);
|
|
86
|
+
|
|
67
87
|
return (
|
|
68
88
|
<>
|
|
89
|
+
<div className="flex gap-2">
|
|
90
|
+
{onSave && (
|
|
91
|
+
<button
|
|
92
|
+
className="p-2 border rounded shadow bg-blue-800 text-white flex gap-1"
|
|
93
|
+
onClick={(e) => {
|
|
94
|
+
onSave({ data: values });
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
97
|
+
<SaveIcon /> Guardar
|
|
98
|
+
</button>
|
|
99
|
+
)}
|
|
100
|
+
{exportName && mapedData.length > 0 && (
|
|
101
|
+
<>
|
|
102
|
+
<button
|
|
103
|
+
className="p-2 border rounded shadow bg-green-800 text-white flex gap-1"
|
|
104
|
+
onClick={(e) => exported.export(values, exportName)}
|
|
105
|
+
>
|
|
106
|
+
<ExcelIcon /> Exportar
|
|
107
|
+
</button>
|
|
108
|
+
</>
|
|
109
|
+
)}
|
|
110
|
+
</div>
|
|
69
111
|
<table {...props} className="w-full border-collapse table-auto">
|
|
70
112
|
<thead className="bg-gray-800 text-white">
|
|
71
113
|
<tr>
|
|
@@ -73,7 +115,7 @@ export default function HTable({
|
|
|
73
115
|
return (
|
|
74
116
|
<th
|
|
75
117
|
key={h}
|
|
76
|
-
className="whitespace-nowrap overflow-hidden text-ellipsis max-w-[200px] border-b p-
|
|
118
|
+
className="whitespace-nowrap overflow-hidden text-ellipsis max-w-[200px] border-b p-2"
|
|
77
119
|
>
|
|
78
120
|
<div
|
|
79
121
|
className="cursor-pointer flex "
|
|
@@ -81,11 +123,11 @@ export default function HTable({
|
|
|
81
123
|
setSelectedFilter(key == selectedFilter ? null : key);
|
|
82
124
|
}}
|
|
83
125
|
>
|
|
84
|
-
<div className="text-white w-full bg-black rounded
|
|
126
|
+
<div className="text-white w-full bg-black rounded flex justify-center">
|
|
85
127
|
{h}{" "}
|
|
86
128
|
{!mapedData
|
|
87
|
-
|
|
88
|
-
|
|
129
|
+
?.map((d: any) => d[h]?.exclude)
|
|
130
|
+
?.every((d: any) => d === false) && (
|
|
89
131
|
<div className="text-red-300">
|
|
90
132
|
<FilterOffIcon />
|
|
91
133
|
</div>
|
|
@@ -136,7 +178,6 @@ export default function HTable({
|
|
|
136
178
|
key={id}
|
|
137
179
|
index={trKey}
|
|
138
180
|
symbols={symbols}
|
|
139
|
-
handlers={props.handlers}
|
|
140
181
|
item={item}
|
|
141
182
|
color={color}
|
|
142
183
|
mapedData={mapedData}
|
|
@@ -148,27 +189,29 @@ export default function HTable({
|
|
|
148
189
|
);
|
|
149
190
|
})}
|
|
150
191
|
</tbody>
|
|
151
|
-
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
<div className="
|
|
162
|
-
|
|
192
|
+
{totals && (
|
|
193
|
+
<tfoot className="bg-gray-800 text-white">
|
|
194
|
+
<tr>
|
|
195
|
+
{head.map((h, fkey) => {
|
|
196
|
+
return (
|
|
197
|
+
<th
|
|
198
|
+
key={fkey}
|
|
199
|
+
className="text-right border-b max-w-[200px] p-2 "
|
|
200
|
+
>
|
|
201
|
+
{totals.includes(h) && (
|
|
202
|
+
<div className="flex justify-between text-white w-full bg-black rounded ">
|
|
203
|
+
<div className="p-1">
|
|
204
|
+
{symbols && symbols[h] && symbols[h]}
|
|
205
|
+
</div>
|
|
206
|
+
<div className="p-1">{mapedTotals[h]}</div>
|
|
163
207
|
</div>
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
</tfoot>
|
|
208
|
+
)}
|
|
209
|
+
</th>
|
|
210
|
+
);
|
|
211
|
+
})}
|
|
212
|
+
</tr>
|
|
213
|
+
</tfoot>
|
|
214
|
+
)}
|
|
172
215
|
</table>
|
|
173
216
|
</>
|
|
174
217
|
);
|
package/src/table/index.tsx
CHANGED
|
@@ -1,58 +1,27 @@
|
|
|
1
|
-
import { ReactNode
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
2
|
import HTable from "./h";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
type DataType = string | number | Date | object | undefined | null;
|
|
4
|
+
type Item = { content: DataType; handler: ReactNode };
|
|
5
|
+
export type DataTypeOrItem = DataType | Item;
|
|
5
6
|
|
|
6
7
|
export interface TableProps
|
|
7
8
|
extends React.DetailedHTMLProps<
|
|
8
9
|
React.TableHTMLAttributes<HTMLTableElement>,
|
|
9
10
|
HTMLTableElement
|
|
10
11
|
> {
|
|
11
|
-
data: Record<string,
|
|
12
|
+
data: Record<string, DataTypeOrItem> | Array<Record<string, DataTypeOrItem>>;
|
|
12
13
|
dataTypes?: Record<string, any>;
|
|
13
|
-
mapedData?: any;
|
|
14
|
-
setMapedData?: any;
|
|
15
14
|
totals?: Array<string>;
|
|
16
15
|
symbols?: Record<string, ReactNode>;
|
|
17
16
|
exportName?: string;
|
|
18
|
-
|
|
17
|
+
onSave?: (e: { data: Record<string, any> }) => void;
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
export default function Table(props: TableProps) {
|
|
22
|
-
const [mapedData, setMapedData] = useState([]);
|
|
23
|
-
const isArray = Array.isArray(props.data);
|
|
24
|
-
const exported = useExport();
|
|
20
|
+
export default function Table({ ...props }: TableProps) {
|
|
25
21
|
return (
|
|
26
22
|
<div className="bg-gray-200 border rounded shadow p-1">
|
|
27
|
-
{props
|
|
28
|
-
|
|
29
|
-
<button
|
|
30
|
-
className="p-2 border rounded shadow bg-green-800 text-white flex gap-1"
|
|
31
|
-
onClick={(e) =>
|
|
32
|
-
exported.export(
|
|
33
|
-
mapedData.map((md: any) => {
|
|
34
|
-
const { __visible__, ...newMd } = md;
|
|
35
|
-
for (let i of Object.keys(newMd)) {
|
|
36
|
-
newMd[i] = newMd[i].content;
|
|
37
|
-
}
|
|
38
|
-
return newMd;
|
|
39
|
-
}),
|
|
40
|
-
props.exportName
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
>
|
|
44
|
-
<ExcelIcon /> Exportar
|
|
45
|
-
</button>
|
|
46
|
-
</>
|
|
47
|
-
)}
|
|
48
|
-
{isArray ? (
|
|
49
|
-
<HTable
|
|
50
|
-
{...{
|
|
51
|
-
...props,
|
|
52
|
-
mapedData,
|
|
53
|
-
setMapedData,
|
|
54
|
-
}}
|
|
55
|
-
/>
|
|
23
|
+
{Array.isArray(props.data) ? (
|
|
24
|
+
<HTable {...props} />
|
|
56
25
|
) : (
|
|
57
26
|
<div className=" p-5 border rounded shadow bg-yellw-500">
|
|
58
27
|
No es un array
|
package/src/table/td.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo, useState } from "react";
|
|
1
|
+
import React, { Dispatch, useMemo, useState } from "react";
|
|
2
2
|
|
|
3
3
|
interface TDProps
|
|
4
4
|
extends React.DetailedHTMLProps<
|
|
@@ -7,17 +7,14 @@ interface TDProps
|
|
|
7
7
|
> {
|
|
8
8
|
index: number;
|
|
9
9
|
item: {
|
|
10
|
-
cellTypeOf: string;
|
|
11
10
|
content: string;
|
|
12
|
-
title: string;
|
|
13
11
|
name: string;
|
|
14
|
-
|
|
12
|
+
handler: React.ReactNode;
|
|
15
13
|
};
|
|
16
14
|
color: string;
|
|
17
15
|
symbols: Record<string, any> | undefined;
|
|
18
|
-
handlers: Record<string, any> | undefined;
|
|
19
16
|
mapedData?: any;
|
|
20
|
-
setMapedData?:
|
|
17
|
+
setMapedData?: Dispatch<any>;
|
|
21
18
|
}
|
|
22
19
|
export default function TD({
|
|
23
20
|
className,
|
|
@@ -25,7 +22,6 @@ export default function TD({
|
|
|
25
22
|
index,
|
|
26
23
|
color,
|
|
27
24
|
symbols,
|
|
28
|
-
handlers,
|
|
29
25
|
mapedData,
|
|
30
26
|
setMapedData,
|
|
31
27
|
...props
|
|
@@ -52,69 +48,64 @@ export default function TD({
|
|
|
52
48
|
{ defaultValue: item?.content }
|
|
53
49
|
);
|
|
54
50
|
|
|
55
|
-
const newProps2 =
|
|
56
|
-
handlers &&
|
|
57
|
-
React.isValidElement(handlers[item?.name]) &&
|
|
58
|
-
Object.keys(handlers[item?.name]?.props)?.reduce(
|
|
59
|
-
(acc: any, i) => {
|
|
60
|
-
try {
|
|
61
|
-
const newAcc = { ...acc };
|
|
62
|
-
const hasEvent = `${i}`.startsWith("on");
|
|
63
|
-
if (hasEvent) {
|
|
64
|
-
newAcc[i] = (e: any) => {
|
|
65
|
-
e.item = item;
|
|
66
|
-
handlers[item?.name].props[i]?.(e);
|
|
67
|
-
if (i == "onChange") {
|
|
68
|
-
const newData = [...mapedData];
|
|
69
|
-
newData[index][item?.name].content = e.target.value;
|
|
70
|
-
setMapedData?.(newData);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
return newAcc;
|
|
75
|
-
} catch (error) {}
|
|
76
|
-
},
|
|
77
|
-
{ value: item?.content }
|
|
78
|
-
);
|
|
79
51
|
return (
|
|
80
52
|
<td
|
|
81
53
|
onDoubleClick={(e) => setIsHidded(!isHidded)}
|
|
82
|
-
title={item?.title}
|
|
54
|
+
// title={item?.title}
|
|
83
55
|
className={[
|
|
84
56
|
isHidded && color,
|
|
85
57
|
!isHidded && "whitespace-nowrap overflow-hidden text-ellipsis ",
|
|
86
58
|
"border-b max-w-[200px] p-5 ",
|
|
87
|
-
["number", "money"].includes(item?.cellTypeOf) && "text-right",
|
|
59
|
+
// ["number", "money"].includes(item?.cellTypeOf) && "text-right",
|
|
88
60
|
].join(" ")}
|
|
89
61
|
>
|
|
90
|
-
{
|
|
91
|
-
|
|
92
|
-
{React.Children.map(handlers[item?.name], (child) => {
|
|
93
|
-
if (React.isValidElement(child)) {
|
|
94
|
-
return React.cloneElement(child as any, {
|
|
95
|
-
...newProps2,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
})}
|
|
99
|
-
</div>
|
|
100
|
-
) : (
|
|
101
|
-
<div
|
|
102
|
-
className={symbols && symbols[item?.name] && "flex justify-between"}
|
|
103
|
-
>
|
|
62
|
+
<div className={symbols && symbols[item?.name] && "flex justify-between"}>
|
|
63
|
+
{symbols && (
|
|
104
64
|
<div>
|
|
105
|
-
{symbols
|
|
106
|
-
React.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
65
|
+
{React.Children.map(symbols[item?.name], (child) => {
|
|
66
|
+
if (React.isValidElement(child)) {
|
|
67
|
+
return React.cloneElement(child, {
|
|
68
|
+
...newProps,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return child;
|
|
72
|
+
})}
|
|
73
|
+
</div>
|
|
74
|
+
)}
|
|
75
|
+
|
|
76
|
+
<div>
|
|
77
|
+
{item?.handler
|
|
78
|
+
? React.Children.map(item.handler, (handler) => {
|
|
79
|
+
if (React.isValidElement(handler)) {
|
|
80
|
+
return React.cloneElement(handler as any, {
|
|
81
|
+
value: mapedData[index][item.name].content,
|
|
82
|
+
onChange: (e: any) => {
|
|
83
|
+
const nmd = [...mapedData];
|
|
84
|
+
nmd[index][item.name].content = e.target.value;
|
|
85
|
+
e.item = Object.assign(
|
|
86
|
+
{},
|
|
87
|
+
...nmd.map((d: any) =>
|
|
88
|
+
Object.keys(d).map((k) => ({ [k]: d[k].content }))
|
|
89
|
+
)[index]
|
|
90
|
+
);
|
|
91
|
+
e.setData = (data: any) => {
|
|
92
|
+
const nmd = [...mapedData];
|
|
93
|
+
for (let datum in data) {
|
|
94
|
+
nmd[index][datum].content = data[datum];
|
|
95
|
+
}
|
|
96
|
+
setMapedData?.(nmd);
|
|
97
|
+
};
|
|
98
|
+
setMapedData?.(nmd);
|
|
99
|
+
handler?.props?.onChange?.(e);
|
|
100
|
+
// console.log("hola mundo", e.item);
|
|
101
|
+
},
|
|
110
102
|
});
|
|
111
103
|
}
|
|
112
|
-
return
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
<div>{item?.content}</div>
|
|
104
|
+
return handler;
|
|
105
|
+
})
|
|
106
|
+
: item.content}
|
|
116
107
|
</div>
|
|
117
|
-
|
|
108
|
+
</div>
|
|
118
109
|
</td>
|
|
119
110
|
);
|
|
120
111
|
}
|