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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-recomponents",
3
- "version": "1.7.63",
3
+ "version": "1.8.2",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -44,7 +44,7 @@ export default function Container({
44
44
  <h1 className="text-xl font-bold">{appName}</h1>
45
45
  </div>
46
46
  <div
47
- className={` gap-2 bg-blue-400 text-white ${
47
+ className={` gap-2 bg-gray-800 text-white ${
48
48
  isSidebarOpen ? "px-[270px]" : "px-[60px]"
49
49
  } hidden sm:flex`}
50
50
  >
@@ -84,7 +84,7 @@ export default function Container({
84
84
  ? 250
85
85
  : 60,
86
86
  }}
87
- className="bg-blue-400 text-white overflow-y-auto fixed md:static top-0 left-0 h-full z-50 md:z-auto transition-all duration-300 ease-in-out"
87
+ className="bg-gray-800 text-white overflow-y-auto fixed md:static top-0 left-0 h-full z-50 md:z-auto transition-all duration-300 ease-in-out"
88
88
  >
89
89
  <div className="p-4 ">
90
90
  {menuList && (
@@ -123,10 +123,7 @@ export default function Container({
123
123
  </div>
124
124
  )}
125
125
  {!isSidebarOpen && (
126
- <div
127
- title={`${itemMenu.name}`}
128
- className="text-sm hover:bg-gray-200 hover:text-black rounded p-1"
129
- >
126
+ <div className="text-sm hover:bg-gray-200 hover:text-black rounded p-1">
130
127
  {icon}
131
128
  </div>
132
129
  )}
package/src/index.tsx CHANGED
@@ -16,5 +16,4 @@ export { default as MyCalendar } from "./calendar";
16
16
  export type { TableEventProps } from "./table";
17
17
  export { useFormValues } from "./form";
18
18
  export { default as DocumentViewer } from "./doc-viewer";
19
- export { default as TableDos } from "./table2";
20
- export { default as useModal } from "./use-modal";
19
+ export { default as Table3 } from "./table3";
@@ -13,6 +13,21 @@ export function FilterOffIcon() {
13
13
  </svg>
14
14
  );
15
15
  }
16
+ export function EditIcon() {
17
+ return (
18
+ <svg
19
+ stroke="currentColor"
20
+ fill="currentColor"
21
+ strokeWidth="0"
22
+ viewBox="0 0 576 512"
23
+ height="20px"
24
+ width="20px"
25
+ xmlns="http://www.w3.org/2000/svg"
26
+ >
27
+ <path d="M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z"></path>
28
+ </svg>
29
+ );
30
+ }
16
31
 
17
32
  export function MdLastPage() {
18
33
  return (
@@ -110,21 +125,7 @@ export function ExcelIcon() {
110
125
  </svg>
111
126
  );
112
127
  }
113
- export function EditIcon() {
114
- return (
115
- <svg
116
- stroke="currentColor"
117
- fill="currentColor"
118
- strokeWidth="0"
119
- viewBox="0 0 576 512"
120
- height="20px"
121
- width="20px"
122
- xmlns="http://www.w3.org/2000/svg"
123
- >
124
- <path d="M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z"></path>
125
- </svg>
126
- );
127
- }
128
+
128
129
  export function ArrowIcon() {
129
130
  return (
130
131
  <svg
package/src/table/h.tsx CHANGED
@@ -67,14 +67,7 @@ export default function HTable({
67
67
 
68
68
  const isDate = !isObject && regex.test(`${d[key]}`);
69
69
  const cellTypeOf = isDate ? "date" : isObject ? "object" : typeOf;
70
- const mapedIndex = mapedData.find((mpd) =>
71
- `${d.id}`.includes(
72
- (mpd?.id as any)?.content,
73
- (mpd?._id as any)?.content
74
- )
75
- );
76
-
77
- const mapedContent = (mapedIndex?.[key] as any)?.content;
70
+ const mapedContent = (mapedData[trkey][key] as any)?.content;
78
71
 
79
72
  const content =
80
73
  mapedContent ||
@@ -145,43 +138,41 @@ export default function HTable({
145
138
  )}
146
139
  </div>
147
140
  <table {...props} className="w-full border-collapse table-auto">
148
- <thead className="bg-blue-400 text-white">
141
+ <thead className="bg-gray-800 text-white">
149
142
  <tr>
150
143
  {head.map((h, key) => {
151
144
  return (
152
- h != "_id" && (
153
- <th
154
- key={h}
155
- className="whitespace-nowrap overflow-hidden text-ellipsis max-w-[200px] border-b "
145
+ <th
146
+ key={h}
147
+ className="whitespace-nowrap overflow-hidden text-ellipsis max-w-[200px] border-b p-2"
148
+ >
149
+ <div
150
+ className="cursor-pointer flex "
151
+ onClick={(e) => {
152
+ setSelectedFilter(key == selectedFilter ? null : key);
153
+ }}
156
154
  >
157
- <div
158
- className="cursor-pointer flex "
159
- onClick={(e) => {
160
- setSelectedFilter(key == selectedFilter ? null : key);
161
- }}
162
- >
163
- <div className="text-white w-full rounded flex justify-center">
164
- {h}{" "}
165
- {!mapedData
166
- ?.map((d: any) => d[h]?.exclude)
167
- ?.every((d: any) => d === false) && (
168
- <div className="text-red-300">
169
- <FilterOffIcon />
170
- </div>
171
- )}
172
- </div>
155
+ <div className="text-white w-full bg-black rounded flex justify-center">
156
+ {h}{" "}
157
+ {!mapedData
158
+ ?.map((d: any) => d[h]?.exclude)
159
+ ?.every((d: any) => d === false) && (
160
+ <div className="text-red-300">
161
+ <FilterOffIcon />
162
+ </div>
163
+ )}
173
164
  </div>
165
+ </div>
174
166
 
175
- <FilterMenu
176
- h={h}
177
- mapedData={mapedData}
178
- setMapedData={setMapedData}
179
- index={key}
180
- selectedFilter={selectedFilter}
181
- setSelectedFilter={setSelectedFilter}
182
- />
183
- </th>
184
- )
167
+ <FilterMenu
168
+ h={h}
169
+ mapedData={mapedData}
170
+ setMapedData={setMapedData}
171
+ index={key}
172
+ selectedFilter={selectedFilter}
173
+ setSelectedFilter={setSelectedFilter}
174
+ />
175
+ </th>
185
176
  );
186
177
  })}
187
178
  </tr>
@@ -201,7 +192,7 @@ export default function HTable({
201
192
  return null;
202
193
  }
203
194
  }
204
- const dataKey = md?._id?.content || md?.id?.content || trKey;
195
+ const dataKey = md?.id?.content || trKey;
205
196
 
206
197
  return (
207
198
  <tr
@@ -212,32 +203,24 @@ export default function HTable({
212
203
  key={dataKey}
213
204
  onClick={(e) => setSelected(trKey)}
214
205
  className={[
215
- "hover:bg-blue-100 ",
206
+ "hover:bg-green-100 ",
216
207
  color,
217
- selected == trKey && " bg-blue-200 hover:bg-blue-300",
208
+ selected == trKey && "bg-green-200 hover:bg-green-300",
218
209
  ].join(" ")}
219
210
  >
220
211
  {head.map((h, tdKey: number) => {
221
212
  const item = md[h];
222
- const id =
223
- trKey +
224
- "-" +
225
- (md?.["_id"]?.content || md?.id?.content || tdKey) +
226
- "-" +
227
- h;
213
+ const id = trKey + "-" + (md?.id?.content || tdKey) + "-" + h;
228
214
  return (
229
- h != "_id" && (
230
- <TD
231
- data-key={id}
232
- key={id}
233
- index={trKey}
234
- symbols={symbols}
235
- item={item}
236
- color={color}
237
- mapedData={mapedData}
238
- setMapedData={setMapedData}
239
- />
240
- )
215
+ <TD
216
+ key={id}
217
+ index={trKey}
218
+ symbols={symbols}
219
+ item={item}
220
+ color={color}
221
+ mapedData={mapedData}
222
+ setMapedData={setMapedData}
223
+ />
241
224
  );
242
225
  })}
243
226
  </tr>
@@ -245,13 +228,16 @@ export default function HTable({
245
228
  })}
246
229
  </tbody>
247
230
  {totals && (
248
- <tfoot className="bg-blue-400 text-white">
231
+ <tfoot className="bg-gray-800 text-white">
249
232
  <tr>
250
233
  {head.map((h, fkey) => {
251
234
  return (
252
- <th key={fkey} className="text-right border-b max-w-[200px] ">
235
+ <th
236
+ key={fkey}
237
+ className="text-right border-b max-w-[200px] p-2 "
238
+ >
253
239
  {totals.includes(h) && (
254
- <div className="flex justify-between text-white w-full rounded ">
240
+ <div className="flex justify-between text-white w-full bg-black rounded ">
255
241
  <div className="p-1">
256
242
  {symbols && symbols[h] && symbols[h]}
257
243
  </div>
package/src/table/td.tsx CHANGED
@@ -84,38 +84,19 @@ export default function TD({
84
84
  { ...symbols[item?.name]?.props }
85
85
  );
86
86
 
87
- const typeOf = (value: any): string => {
88
- if (value instanceof Date) return "date";
89
- if (typeof value === "number") return "number";
90
- if (typeof value === "string") {
91
- // validar si es fecha en string
92
- const d = new Date(value);
93
- if (!isNaN(d.getTime())) return "date-string";
94
- return "string";
95
- }
96
- return typeof value;
97
- };
98
-
99
- const result = typeOf(item?.content);
100
-
101
87
  return (
102
88
  <td
103
- {...props}
104
89
  onDoubleClick={(e) => setIsHidded(!isHidded)}
105
90
  // title={item?.title}
106
91
  className={[
107
92
  isHidded && color,
108
- !isHidded && "whitespace-nowrap overflow-hidden text-ellipsis ",
109
- " px-2 ",
93
+ !isHidded && "whitespace-nowrap overflow-hidden text-ellipsis ",
94
+ "border-b max-w-[200px] p-2 ",
95
+ // ["number", "money"].includes(item?.cellTypeOf) && "text-right",
110
96
  ].join(" ")}
111
97
  >
112
98
  <div
113
- className={
114
- symbols && symbols?.[item?.name]
115
- ? symbols[item?.name]
116
- : " flex " +
117
- (result == "number" ? "justify-end" : "justify-start")
118
- }
99
+ className={symbols && symbols[item?.name] && "flex justify-between "}
119
100
  >
120
101
  {symbols ? (
121
102
  <div className="flex items-center justify-between gap-1">
@@ -133,7 +114,7 @@ export default function TD({
133
114
  <div>{!newProps?.["row"] && item?.content}</div>
134
115
  </div>
135
116
  ) : (
136
- <div className="">{item?.content}</div>
117
+ <div>{item?.content}</div>
137
118
  )}
138
119
  </div>
139
120
  </td>
package/src/table/vtd.tsx CHANGED
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import React, { Dispatch, useMemo, useState } from "react";
2
3
 
3
4
  interface TDProps
@@ -0,0 +1,75 @@
1
+ import { useState } from "react";
2
+ import TR from "./tr";
3
+
4
+ export default function TableBody({
5
+ objectData,
6
+ setObjectData,
7
+ headers,
8
+ handlers,
9
+ selectItems,
10
+ page,
11
+ maxItems,
12
+ colSizes,
13
+ modal,
14
+ modalRef,
15
+ dialogRow,
16
+ setDialogRow,
17
+ onChange,
18
+ }: {
19
+ objectData: any;
20
+ setObjectData: any;
21
+ headers: string[];
22
+ handlers: Record<string, any>;
23
+ selectItems?: boolean;
24
+ page: number;
25
+ maxItems?: number;
26
+ colSizes?: Record<string, number>;
27
+ modal?: React.ReactNode;
28
+ modalRef: React.RefObject<HTMLDialogElement>;
29
+ dialogRow: any;
30
+ setDialogRow: any;
31
+ onChange?: any;
32
+ }) {
33
+ const [selected, setSelected] = useState(-1);
34
+
35
+ return (
36
+ <tbody>
37
+ {Object.keys(objectData)
38
+ .reverse()
39
+ .filter((id) => {
40
+ return objectData[id]?._visible === true;
41
+ })
42
+ .filter((_id, key) => {
43
+ if (!maxItems) return true;
44
+ const start = (page - 1) * maxItems; // ej: 0 en la página 1
45
+ const end = page * maxItems; // ej: 10 en la página 1
46
+ return key >= start && key < end; // 👈 usamos < en vez de <=
47
+ })
48
+ .map((id, index) => {
49
+ const row = objectData[id];
50
+ return (
51
+ <TR
52
+ key={id}
53
+ {...{
54
+ headers,
55
+ index,
56
+ setObjectData,
57
+ id,
58
+ row,
59
+ handlers,
60
+ selectItems,
61
+ colSizes,
62
+ modal,
63
+ modalRef,
64
+ dialogRow,
65
+ setDialogRow,
66
+ setSelected,
67
+ selected,
68
+ onChange,
69
+ }}
70
+ />
71
+ );
72
+ })}
73
+ </tbody>
74
+ );
75
+ }
@@ -0,0 +1,49 @@
1
+ import React, { useMemo } from "react";
2
+
3
+ function Dialog({
4
+ modalRef,
5
+ children,
6
+ dialogRow,
7
+ setDialogRow,
8
+ setObjectData,
9
+ }: {
10
+ modalRef: React.RefObject<HTMLDialogElement>;
11
+ children: React.ReactNode;
12
+ dialogRow: any;
13
+ setDialogRow: any;
14
+ setObjectData: any;
15
+ }) {
16
+ const show = () => modalRef.current?.showModal();
17
+ const hide = () => modalRef.current?.close();
18
+ const clonedModal = useMemo(() => {
19
+ if (dialogRow && React.isValidElement(children)) {
20
+ return React.cloneElement(children, {
21
+ key: JSON.stringify(dialogRow),
22
+ row: dialogRow,
23
+ show,
24
+ hide,
25
+ update: setObjectData,
26
+ });
27
+ }
28
+ return null;
29
+ }, [dialogRow, children]);
30
+ return (
31
+ <dialog
32
+ ref={modalRef}
33
+ className="p-6 rounded-xl shadow-2xl backdrop:bg-black/50 w-[100%] h-screen"
34
+ >
35
+ <div className="flex justify-between items-center mb-4">
36
+ <div></div>
37
+ <button
38
+ onClick={() => modalRef.current?.close()}
39
+ className="text-white hover:text-gray-100 text-xl border shadow rounded p-1 bg-red-500"
40
+ >
41
+
42
+ </button>
43
+ </div>
44
+ <div className="text-gray-700">{clonedModal}</div>
45
+ </dialog>
46
+ );
47
+ }
48
+
49
+ export default Dialog;
@@ -0,0 +1,213 @@
1
+ "use client";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { FilterOffIcon } from "../../src/table/filters";
4
+
5
+ export default function Filter({
6
+ h,
7
+ objectData,
8
+ setObjectData,
9
+ setPage,
10
+ colSizes,
11
+ }: {
12
+ h: any;
13
+ objectData: any;
14
+ setObjectData: any;
15
+ setPage: any;
16
+ colSizes?: Record<string, number>;
17
+ }) {
18
+ const [visible, setVisible] = useState(false);
19
+ const [text, setText] = useState("");
20
+ const items = useMemo(
21
+ () => [...new Set(Object.values(objectData).map((o: any) => o[h]))],
22
+ [objectData]
23
+ );
24
+ const [selected, setSelected] = useState<string[]>(items);
25
+
26
+ const itemsFiltered = useMemo(
27
+ () =>
28
+ items
29
+ .sort((a, b) => `${a}`.localeCompare(b))
30
+ .filter((item: string) => {
31
+ if (!text) return true;
32
+
33
+ return `${item}`.toLowerCase().includes(text.toLowerCase());
34
+ }),
35
+ [items, text]
36
+ );
37
+ function filtrar(itemsInterno: any[] = []) {
38
+ const array = Object.values(objectData);
39
+ let obj;
40
+ if (itemsInterno.length > 0) {
41
+ setSelected(items);
42
+ obj = array.map((row: any) => {
43
+ return row?._id
44
+ ? {
45
+ _id: row._id,
46
+ _visible: itemsInterno.includes(row[h]),
47
+ }
48
+ : { id: row.id, _visible: itemsInterno.includes(row[h]) };
49
+ });
50
+ } else {
51
+ obj = array.map((row: any) => {
52
+ return row?._id
53
+ ? {
54
+ _id: row._id,
55
+ _visible:
56
+ itemsFiltered.length < items.length
57
+ ? itemsFiltered.includes(row[h])
58
+ : selected.includes(row[h]),
59
+ }
60
+ : {
61
+ id: row.id,
62
+ _visible:
63
+ itemsFiltered.length < items.length
64
+ ? itemsFiltered.includes(row[h])
65
+ : selected.includes(row[h]),
66
+ };
67
+ });
68
+ }
69
+
70
+ setObjectData(obj);
71
+ setPage(1);
72
+ setVisible(false);
73
+ setText("");
74
+ }
75
+ const hidden = Object.values(objectData)
76
+ .filter((d: any) => d._visible === false)
77
+ .map((d: any) => d[h]);
78
+
79
+ return (
80
+ <th className="cursor-pointer">
81
+ <div className="relative">
82
+ {visible && (
83
+ <div
84
+ className=" w-full h-screen top-0 left-0 fixed"
85
+ style={{ zIndex: 9998 }}
86
+ onClick={(e) => setVisible(!visible)}
87
+ ></div>
88
+ )}
89
+ </div>
90
+ <div className="relative w-full justify-center flex">
91
+ <div
92
+ style={{
93
+ minWidth: "100px",
94
+ maxWidth: `${(colSizes?.[h] || 0) + 100}px`,
95
+ width: `${colSizes?.[h]}px`,
96
+ }}
97
+ className={`resize-x overflow-auto text-center flex justify-evenly p-1 items-center`}
98
+ onClick={(e) => setVisible(!visible)}
99
+ >
100
+ <div>{h}</div>
101
+ {selected.length < items.length && (
102
+ <div className="text-red-500 ">
103
+ <FilterOffIcon />
104
+ </div>
105
+ )}
106
+ </div>
107
+ {visible && (
108
+ <div
109
+ className="border shadow rounded bg-white p-1 absolute fixed text-black"
110
+ style={{ zIndex: 9999 }}
111
+ >
112
+ <div className="flex flex-col gap-1 w-[300px] min-w-[300px] resize-x overflow-auto">
113
+ {selected.length < items.length && (
114
+ <div
115
+ className="p-1 flex items-center justify-between px-2 bg-red-200 border shadow rounded"
116
+ onClick={(e) => {
117
+ filtrar(items);
118
+ }}
119
+ >
120
+ Borrar Filtro{" "}
121
+ <div className="text-white ">
122
+ <FilterOffIcon />
123
+ </div>
124
+ </div>
125
+ )}
126
+ <div className="">
127
+ <input
128
+ className="border shadow rounded p-2 w-full"
129
+ type="search"
130
+ onChange={(e) => setText(`${e.target.value}`)}
131
+ value={text}
132
+ onKeyDown={(e) => {
133
+ if (e.key === "Enter") {
134
+ setSelected(
135
+ items.filter((i) =>
136
+ `${i}`.toLowerCase().includes(`${text}`.toLowerCase())
137
+ )
138
+ );
139
+ filtrar();
140
+ }
141
+ }}
142
+ />
143
+ </div>
144
+ <div>
145
+ <label className="flex gap-1 cursor-pointer px-1">
146
+ <input
147
+ type="checkbox"
148
+ checked={!Boolean(selected.length < items.length)}
149
+ onChange={(e) => {
150
+ if (selected.length < items.length) {
151
+ setSelected(items);
152
+ } else {
153
+ setSelected([]);
154
+ }
155
+ }}
156
+ />
157
+ (Seleccionar Todo)
158
+ </label>
159
+ </div>
160
+ <div className="overflow-auto flex gap-1 flex-col p-1 border shadow rounded h-[300px]">
161
+ {itemsFiltered.map((item) => {
162
+ return (
163
+ <div key={item} className="hover:bg-gray-100 ">
164
+ <label className="flex gap-1 cursor-pointer truncate">
165
+ <input
166
+ type="checkbox"
167
+ disabled={
168
+ hidden.includes(item) && items.includes(item)
169
+ }
170
+ checked={selected.includes(item)}
171
+ onChange={(e) => {
172
+ const newSelected = [...selected];
173
+ const index = newSelected.indexOf(item);
174
+ if (index >= 0) {
175
+ newSelected.splice(index, 1);
176
+ } else {
177
+ newSelected.push(item);
178
+ }
179
+ setSelected(newSelected);
180
+ }}
181
+ />
182
+ {item || "(Vacias)"}
183
+ </label>
184
+ </div>
185
+ );
186
+ })}
187
+ </div>
188
+ <div className="flex justify-between px-1">
189
+ <button
190
+ className="p-1 shadow rounded border bg-red-500 text-white"
191
+ onClick={(e) => {
192
+ setText("");
193
+ setVisible(false);
194
+ }}
195
+ >
196
+ Cancelar
197
+ </button>
198
+ <button
199
+ className="p-1 shadow rounded border bg-blue-500 text-white"
200
+ onClick={(e) => {
201
+ filtrar();
202
+ }}
203
+ >
204
+ Aceptar
205
+ </button>
206
+ </div>
207
+ </div>
208
+ </div>
209
+ )}
210
+ </div>
211
+ </th>
212
+ );
213
+ }