next-recomponents 2.0.1 → 2.0.3
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 +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +711 -635
- package/dist/index.mjs +661 -585
- package/package.json +1 -1
- package/src/alert/index.tsx +145 -23
- package/src/index.tsx +1 -1
- package/src/table/index.tsx +46 -29
- package/tsconfig.json +1 -1
package/package.json
CHANGED
package/src/alert/index.tsx
CHANGED
|
@@ -1,27 +1,149 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
| "
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
|
|
4
|
+
function usePopup() {
|
|
5
|
+
const [popup, setPopup] = useState<{
|
|
6
|
+
type: "alert" | "confirm" | "prompt";
|
|
7
|
+
message: string;
|
|
8
|
+
visible: boolean;
|
|
9
|
+
inputValue: string;
|
|
10
|
+
onConfirm?: (value?: string) => void;
|
|
11
|
+
onCancel?: () => void;
|
|
12
|
+
}>({ type: "alert", message: "", visible: false, inputValue: "" });
|
|
13
|
+
|
|
14
|
+
function alert(message: string): Promise<void> {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
setPopup({
|
|
17
|
+
type: "alert",
|
|
18
|
+
message,
|
|
19
|
+
visible: true,
|
|
20
|
+
inputValue: "",
|
|
21
|
+
onConfirm: () => resolve(),
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function confirm(message: string): Promise<boolean> {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
setPopup({
|
|
29
|
+
type: "confirm",
|
|
30
|
+
message,
|
|
31
|
+
visible: true,
|
|
32
|
+
inputValue: "",
|
|
33
|
+
onConfirm: () => resolve(true),
|
|
34
|
+
onCancel: () => resolve(false),
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function prompt(message: string): Promise<string | null> {
|
|
40
|
+
return new Promise((resolve) => {
|
|
41
|
+
setPopup({
|
|
42
|
+
type: "prompt",
|
|
43
|
+
message,
|
|
44
|
+
visible: true,
|
|
45
|
+
inputValue: "",
|
|
46
|
+
onConfirm: (value) => resolve(value ?? ""),
|
|
47
|
+
onCancel: () => resolve(null),
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function close(confirmed: boolean, value?: string) {
|
|
53
|
+
setPopup((prev) => {
|
|
54
|
+
if (confirmed) prev.onConfirm?.(value);
|
|
55
|
+
else prev.onCancel?.();
|
|
56
|
+
return { ...prev, visible: false, inputValue: "" };
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const PopupComponent = popup.visible ? (
|
|
20
61
|
<div
|
|
21
|
-
|
|
22
|
-
|
|
62
|
+
style={{
|
|
63
|
+
position: "fixed",
|
|
64
|
+
top: 0,
|
|
65
|
+
left: 0,
|
|
66
|
+
width: "100%",
|
|
67
|
+
height: "100%",
|
|
68
|
+
background: "rgba(0,0,0,0.5)",
|
|
69
|
+
display: "flex",
|
|
70
|
+
alignItems: "center",
|
|
71
|
+
justifyContent: "center",
|
|
72
|
+
zIndex: 1000,
|
|
73
|
+
}}
|
|
23
74
|
>
|
|
24
|
-
|
|
75
|
+
<div
|
|
76
|
+
style={{
|
|
77
|
+
background: "#fff",
|
|
78
|
+
padding: "24px 32px",
|
|
79
|
+
borderRadius: "8px",
|
|
80
|
+
minWidth: "300px",
|
|
81
|
+
textAlign: "center",
|
|
82
|
+
boxShadow: "0 4px 20px rgba(0,0,0,0.2)",
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
<p style={{ margin: "0 0 16px", fontSize: "16px" }}>{popup.message}</p>
|
|
86
|
+
|
|
87
|
+
{popup.type === "prompt" && (
|
|
88
|
+
<input
|
|
89
|
+
autoFocus
|
|
90
|
+
type="text"
|
|
91
|
+
value={popup.inputValue}
|
|
92
|
+
onChange={(e) =>
|
|
93
|
+
setPopup((prev) => ({ ...prev, inputValue: e.target.value }))
|
|
94
|
+
}
|
|
95
|
+
onKeyDown={(e) =>
|
|
96
|
+
e.key === "Enter" && close(true, popup.inputValue)
|
|
97
|
+
}
|
|
98
|
+
style={{
|
|
99
|
+
width: "100%",
|
|
100
|
+
padding: "8px 12px",
|
|
101
|
+
marginBottom: "16px",
|
|
102
|
+
border: "1px solid #d1d5db",
|
|
103
|
+
borderRadius: "6px",
|
|
104
|
+
fontSize: "14px",
|
|
105
|
+
boxSizing: "border-box",
|
|
106
|
+
}}
|
|
107
|
+
/>
|
|
108
|
+
)}
|
|
109
|
+
|
|
110
|
+
<div style={{ display: "flex", gap: "8px", justifyContent: "center" }}>
|
|
111
|
+
{(popup.type === "confirm" || popup.type === "prompt") && (
|
|
112
|
+
<button
|
|
113
|
+
onClick={() => close(false)}
|
|
114
|
+
style={{
|
|
115
|
+
padding: "8px 24px",
|
|
116
|
+
background: "#e5e7eb",
|
|
117
|
+
color: "#374151",
|
|
118
|
+
border: "none",
|
|
119
|
+
borderRadius: "6px",
|
|
120
|
+
cursor: "pointer",
|
|
121
|
+
fontSize: "14px",
|
|
122
|
+
}}
|
|
123
|
+
>
|
|
124
|
+
Cancelar
|
|
125
|
+
</button>
|
|
126
|
+
)}
|
|
127
|
+
<button
|
|
128
|
+
onClick={() => close(true, popup.inputValue)}
|
|
129
|
+
style={{
|
|
130
|
+
padding: "8px 24px",
|
|
131
|
+
background: "#3b82f6",
|
|
132
|
+
color: "#fff",
|
|
133
|
+
border: "none",
|
|
134
|
+
borderRadius: "6px",
|
|
135
|
+
cursor: "pointer",
|
|
136
|
+
fontSize: "14px",
|
|
137
|
+
}}
|
|
138
|
+
>
|
|
139
|
+
OK
|
|
140
|
+
</button>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
25
143
|
</div>
|
|
26
|
-
);
|
|
144
|
+
) : null;
|
|
145
|
+
|
|
146
|
+
return { alert, confirm, prompt, PopupComponent };
|
|
27
147
|
}
|
|
148
|
+
|
|
149
|
+
export default usePopup;
|
package/src/index.tsx
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { default as Alert } from "./alert";
|
|
2
1
|
export { default as Button } from "./button";
|
|
3
2
|
export { default as Container } from "./container";
|
|
4
3
|
export { default as Form } from "./form";
|
|
@@ -18,3 +17,4 @@ export { default as MyCalendar } from "./calendar";
|
|
|
18
17
|
export { useFormValues } from "./form";
|
|
19
18
|
export { default as DocumentViewer } from "./doc-viewer";
|
|
20
19
|
export { default as Table3 } from "./table3";
|
|
20
|
+
export { default as usePopup } from "./alert";
|
package/src/table/index.tsx
CHANGED
|
@@ -34,6 +34,7 @@ interface TableProps {
|
|
|
34
34
|
hideColumns?: string[];
|
|
35
35
|
footer?: FooterType;
|
|
36
36
|
symbols?: any;
|
|
37
|
+
|
|
37
38
|
[key: string]: any;
|
|
38
39
|
}
|
|
39
40
|
export default function Table(props: TableProps) {
|
|
@@ -88,7 +89,7 @@ function IHTable({
|
|
|
88
89
|
buttons,
|
|
89
90
|
exportName,
|
|
90
91
|
modal,
|
|
91
|
-
height =
|
|
92
|
+
height = 600,
|
|
92
93
|
width = "100%",
|
|
93
94
|
header,
|
|
94
95
|
hideColumns = [],
|
|
@@ -118,7 +119,7 @@ function IHTable({
|
|
|
118
119
|
if (!rows.length) return [];
|
|
119
120
|
|
|
120
121
|
const arr = Object.keys(rows[0])
|
|
121
|
-
.filter((key) => !key.startsWith("_") && !hideColumns.includes(key))
|
|
122
|
+
.filter((key) => !key.startsWith("_") && !hideColumns.includes(key))
|
|
122
123
|
.map((key, i) => ({
|
|
123
124
|
field: key,
|
|
124
125
|
headerName: key,
|
|
@@ -128,6 +129,7 @@ function IHTable({
|
|
|
128
129
|
renderCell: buttons?.[key]
|
|
129
130
|
? (params: any) =>
|
|
130
131
|
React.cloneElement(buttons[key], {
|
|
132
|
+
className: (params?.className ?? "") + " m-auto text-xs ",
|
|
131
133
|
children: params?.row?.[key],
|
|
132
134
|
onClick: (e: any) => {
|
|
133
135
|
e.row = params?.row;
|
|
@@ -164,6 +166,7 @@ function IHTable({
|
|
|
164
166
|
|
|
165
167
|
return arr;
|
|
166
168
|
}, [rows]);
|
|
169
|
+
|
|
167
170
|
const handleRowUpdate = (newRow: GridRowModel) => {
|
|
168
171
|
if (!newRow.id) throw new Error("Fila sin id");
|
|
169
172
|
newRow._edited = true;
|
|
@@ -171,15 +174,6 @@ function IHTable({
|
|
|
171
174
|
return newRow;
|
|
172
175
|
};
|
|
173
176
|
|
|
174
|
-
// useEffect(() => {
|
|
175
|
-
// if (modal) {
|
|
176
|
-
// const ids = Array.from(selectedRows?.ids || []);
|
|
177
|
-
// if (ids.length == 1) {
|
|
178
|
-
// // ref.current?.showModal();
|
|
179
|
-
// handleOpen();
|
|
180
|
-
// }
|
|
181
|
-
// }
|
|
182
|
-
// }, [selectedRows]);
|
|
183
177
|
const ref = useRef<HTMLDialogElement>(null);
|
|
184
178
|
const cat1: any = {
|
|
185
179
|
1: 110,
|
|
@@ -203,6 +197,7 @@ function IHTable({
|
|
|
203
197
|
}
|
|
204
198
|
return filtered;
|
|
205
199
|
}, [selectedRows]);
|
|
200
|
+
|
|
206
201
|
return (
|
|
207
202
|
rows.length > 0 && (
|
|
208
203
|
<Box
|
|
@@ -215,13 +210,7 @@ function IHTable({
|
|
|
215
210
|
}}
|
|
216
211
|
>
|
|
217
212
|
{modal && (
|
|
218
|
-
<Dialog
|
|
219
|
-
open={open}
|
|
220
|
-
onClose={handleClose}
|
|
221
|
-
maxWidth="xl"
|
|
222
|
-
fullWidth
|
|
223
|
-
// className="w-lg h-screen rounded-lg p-6 shadow-lg border border-gray-300 bg-white"
|
|
224
|
-
>
|
|
213
|
+
<Dialog open={open} onClose={handleClose} maxWidth="xl" fullWidth>
|
|
225
214
|
<div className="flex justify-end">
|
|
226
215
|
<button
|
|
227
216
|
onClick={() => {
|
|
@@ -293,7 +282,6 @@ function IHTable({
|
|
|
293
282
|
checkboxSelection={Boolean(onSelect)}
|
|
294
283
|
rowSelectionModel={selectedRows}
|
|
295
284
|
onRowSelectionModelChange={(newSelection) => {
|
|
296
|
-
console.log(newSelection);
|
|
297
285
|
setSelectedRows(newSelection);
|
|
298
286
|
}}
|
|
299
287
|
sx={{
|
|
@@ -305,8 +293,6 @@ function IHTable({
|
|
|
305
293
|
editMode="row"
|
|
306
294
|
processRowUpdate={handleRowUpdate}
|
|
307
295
|
pageSizeOptions={[5, 10]}
|
|
308
|
-
// pagination={true}
|
|
309
|
-
// hideFooter={hideFooter}
|
|
310
296
|
/>
|
|
311
297
|
<CustomFooter footer={footer || {}} rows={rows} />
|
|
312
298
|
</Box>
|
|
@@ -314,17 +300,48 @@ function IHTable({
|
|
|
314
300
|
);
|
|
315
301
|
}
|
|
316
302
|
|
|
317
|
-
function CustomFooter(
|
|
318
|
-
|
|
303
|
+
function CustomFooter({
|
|
304
|
+
rows,
|
|
305
|
+
footer,
|
|
306
|
+
}: {
|
|
307
|
+
rows: GridValidRowModel[];
|
|
308
|
+
footer: FooterType;
|
|
309
|
+
}) {
|
|
310
|
+
const entries = Object.entries(footer);
|
|
311
|
+
if (!entries.length) return null;
|
|
312
|
+
|
|
313
|
+
const compute = (key: string, type: "sum" | "avg" | "count") => {
|
|
314
|
+
const values = rows
|
|
315
|
+
.map((r) => Number(r[key] ?? 0))
|
|
316
|
+
.filter((v) => !isNaN(v));
|
|
317
|
+
if (type === "sum") return values.reduce((acc, v) => acc + v, 0);
|
|
318
|
+
if (type === "avg")
|
|
319
|
+
return values.length
|
|
320
|
+
? values.reduce((acc, v) => acc + v, 0) / values.length
|
|
321
|
+
: 0;
|
|
322
|
+
if (type === "count") return values.length;
|
|
323
|
+
return 0;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const label: Record<string, string> = {
|
|
327
|
+
sum: "Suma",
|
|
328
|
+
avg: "Promedio",
|
|
329
|
+
count: "Conteo",
|
|
330
|
+
};
|
|
319
331
|
|
|
320
332
|
return (
|
|
321
|
-
<div>
|
|
322
|
-
{
|
|
323
|
-
const
|
|
333
|
+
<div className="flex justify-end gap-6 px-4 py-2 bg-gray-100 border-t border-gray-300 text-sm font-semibold text-gray-700">
|
|
334
|
+
{entries.map(([key, type]) => {
|
|
335
|
+
const value = compute(key, type);
|
|
336
|
+
const formatted =
|
|
337
|
+
type === "avg"
|
|
338
|
+
? value.toLocaleString(undefined, { maximumFractionDigits: 2 })
|
|
339
|
+
: value.toLocaleString();
|
|
324
340
|
return (
|
|
325
|
-
<
|
|
326
|
-
|
|
327
|
-
|
|
341
|
+
<span key={key}>
|
|
342
|
+
{label[type]} de <span className="text-gray-900">{key}</span>:{" "}
|
|
343
|
+
<span className="text-blue-700">{formatted}</span>
|
|
344
|
+
</span>
|
|
328
345
|
);
|
|
329
346
|
})}
|
|
330
347
|
</div>
|