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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-recomponents",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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 = false;
93
+ newd[h].exclude = all;
97
94
  return newd;
98
95
  })
99
96
  );
@@ -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 = { __visible__: true };
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-5"
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 p-1 flex justify-center">
126
+ <div className="text-white w-full bg-black rounded flex justify-center">
85
127
  {h}{" "}
86
128
  {!mapedData
87
- .map((d: any) => d[h].exclude)
88
- .every((d: any) => d === false) && (
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
- <tfoot className="bg-gray-800 text-white">
152
- <tr>
153
- {head.map((h, fkey) => {
154
- return (
155
- <th
156
- key={fkey}
157
- className="text-right border-b max-w-[200px] p-5 "
158
- >
159
- {totals && totals.includes(h) && (
160
- <div className="flex justify-between text-white w-full bg-black rounded p-1">
161
- <div className="p-1">
162
- {symbols && symbols[h] && symbols[h]}
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
- <div className="p-1">{mapedTotals[h]}</div>
165
- </div>
166
- )}
167
- </th>
168
- );
169
- })}
170
- </tr>
171
- </tfoot>
208
+ )}
209
+ </th>
210
+ );
211
+ })}
212
+ </tr>
213
+ </tfoot>
214
+ )}
172
215
  </table>
173
216
  </>
174
217
  );
@@ -1,58 +1,27 @@
1
- import { ReactNode, useState } from "react";
1
+ import { ReactNode } from "react";
2
2
  import HTable from "./h";
3
- import useExport from "./export";
4
- import { ExcelIcon } from "./filters";
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, any> | Array<Record<string, any>>;
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
- handlers?: Record<string, ReactNode>;
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?.exportName && props.data.length > 0 && (
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
- index: number;
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?: (data: any) => void;
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
- {handlers && handlers[item?.name] ? (
91
- <div>
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.Children.map(symbols[item?.name], (child) => {
107
- if (React.isValidElement(child)) {
108
- return React.cloneElement(child, {
109
- ...newProps,
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 child;
113
- })}
114
- </div>
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
  }