next-recomponents 1.3.5 → 1.3.7
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 -278
- package/dist/index.mjs +284 -270
- 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 -29
- 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,46 @@ 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.length > 0
|
|
83
|
+
? mapedData
|
|
84
|
+
.map((d: any) => Object.keys(d).map((k) => ({ [k]: d[k].content })))
|
|
85
|
+
.map((d) => Object.assign({}, ...d))
|
|
86
|
+
: ({} as any);
|
|
87
|
+
}, [mapedData]);
|
|
88
|
+
|
|
67
89
|
return (
|
|
68
90
|
<>
|
|
91
|
+
<div className="flex gap-2">
|
|
92
|
+
{onSave && (
|
|
93
|
+
<button
|
|
94
|
+
className="p-2 border rounded shadow bg-blue-800 text-white flex gap-1"
|
|
95
|
+
onClick={(e) => {
|
|
96
|
+
onSave({ data: values });
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
<SaveIcon /> Guardar
|
|
100
|
+
</button>
|
|
101
|
+
)}
|
|
102
|
+
{exportName && mapedData.length > 0 && (
|
|
103
|
+
<>
|
|
104
|
+
<button
|
|
105
|
+
className="p-2 border rounded shadow bg-green-800 text-white flex gap-1"
|
|
106
|
+
onClick={(e) => exported.export(values, exportName)}
|
|
107
|
+
>
|
|
108
|
+
<ExcelIcon /> Exportar
|
|
109
|
+
</button>
|
|
110
|
+
</>
|
|
111
|
+
)}
|
|
112
|
+
</div>
|
|
69
113
|
<table {...props} className="w-full border-collapse table-auto">
|
|
70
114
|
<thead className="bg-gray-800 text-white">
|
|
71
115
|
<tr>
|
|
@@ -73,7 +117,7 @@ export default function HTable({
|
|
|
73
117
|
return (
|
|
74
118
|
<th
|
|
75
119
|
key={h}
|
|
76
|
-
className="whitespace-nowrap overflow-hidden text-ellipsis max-w-[200px] border-b p-
|
|
120
|
+
className="whitespace-nowrap overflow-hidden text-ellipsis max-w-[200px] border-b p-2"
|
|
77
121
|
>
|
|
78
122
|
<div
|
|
79
123
|
className="cursor-pointer flex "
|
|
@@ -81,7 +125,7 @@ export default function HTable({
|
|
|
81
125
|
setSelectedFilter(key == selectedFilter ? null : key);
|
|
82
126
|
}}
|
|
83
127
|
>
|
|
84
|
-
<div className="text-white w-full bg-black rounded
|
|
128
|
+
<div className="text-white w-full bg-black rounded flex justify-center">
|
|
85
129
|
{h}{" "}
|
|
86
130
|
{!mapedData
|
|
87
131
|
?.map((d: any) => d[h]?.exclude)
|
|
@@ -136,7 +180,6 @@ export default function HTable({
|
|
|
136
180
|
key={id}
|
|
137
181
|
index={trKey}
|
|
138
182
|
symbols={symbols}
|
|
139
|
-
handlers={props.handlers}
|
|
140
183
|
item={item}
|
|
141
184
|
color={color}
|
|
142
185
|
mapedData={mapedData}
|
|
@@ -148,27 +191,29 @@ export default function HTable({
|
|
|
148
191
|
);
|
|
149
192
|
})}
|
|
150
193
|
</tbody>
|
|
151
|
-
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
<div className="
|
|
162
|
-
|
|
194
|
+
{totals && (
|
|
195
|
+
<tfoot className="bg-gray-800 text-white">
|
|
196
|
+
<tr>
|
|
197
|
+
{head.map((h, fkey) => {
|
|
198
|
+
return (
|
|
199
|
+
<th
|
|
200
|
+
key={fkey}
|
|
201
|
+
className="text-right border-b max-w-[200px] p-2 "
|
|
202
|
+
>
|
|
203
|
+
{totals.includes(h) && (
|
|
204
|
+
<div className="flex justify-between text-white w-full bg-black rounded ">
|
|
205
|
+
<div className="p-1">
|
|
206
|
+
{symbols && symbols[h] && symbols[h]}
|
|
207
|
+
</div>
|
|
208
|
+
<div className="p-1">{mapedTotals[h]}</div>
|
|
163
209
|
</div>
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
</tfoot>
|
|
210
|
+
)}
|
|
211
|
+
</th>
|
|
212
|
+
);
|
|
213
|
+
})}
|
|
214
|
+
</tr>
|
|
215
|
+
</tfoot>
|
|
216
|
+
)}
|
|
172
217
|
</table>
|
|
173
218
|
</>
|
|
174
219
|
);
|
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
|
}
|