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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-recomponents",
3
- "version": "1.3.5",
3
+ "version": "1.3.7",
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,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-5"
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 p-1 flex justify-center">
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
- <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]}
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
- <div className="p-1">{mapedTotals[h]}</div>
165
- </div>
166
- )}
167
- </th>
168
- );
169
- })}
170
- </tr>
171
- </tfoot>
210
+ )}
211
+ </th>
212
+ );
213
+ })}
214
+ </tr>
215
+ </tfoot>
216
+ )}
172
217
  </table>
173
218
  </>
174
219
  );
@@ -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
  }