next-recomponents 2.0.56 → 2.0.58

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.
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, useState } from "react";
1
+ import { useEffect, useMemo, useRef, useState } from "react";
2
2
  import { createPortal } from "react-dom";
3
3
  import DropIcon, {
4
4
  ArrowDownIcon,
@@ -17,18 +17,22 @@ export function Header({
17
17
  context,
18
18
  drag,
19
19
  padding,
20
+ index,
21
+ length,
20
22
  }: {
21
23
  header: string;
22
24
  context: ContextType & Omit<TableProps, "data">;
25
+ index: number;
23
26
  drag: {
24
27
  widths: Record<string, number>;
25
28
  gridTemplateColumns: string;
26
29
  startDrag: (e: React.MouseEvent, headerKey: string) => void;
27
30
  };
31
+ length: number;
28
32
  padding: string;
29
33
  }) {
30
34
  const [visible, setVisible] = useState(false);
31
-
35
+ const [hovered, setHovered] = useState(false);
32
36
  const sortIndex = context.sort.findIndex((b) => b.field == header);
33
37
  const [text, setText] = useState("");
34
38
  const cellRef = useRef<HTMLDivElement>(null);
@@ -36,17 +40,21 @@ export function Header({
36
40
  null,
37
41
  );
38
42
 
39
- const filteredValues = [
40
- ...new Set(context.data.map((d) => d[header])),
41
- ].filter((d) => {
42
- if (text == "") return true;
43
- return `${d}`.toLowerCase().includes(text.toLowerCase());
44
- });
43
+ const filteredValues = useMemo(() => {
44
+ return [...new Set(context.data.map((d) => d[header]))].filter((d) => {
45
+ if (text == "") return true;
46
+ return `${d}`.toLowerCase().includes(text.toLowerCase());
47
+ });
48
+ }, [context.data, header, text]);
45
49
 
46
- const [selected, setSelected] = useState([...filteredValues]);
50
+ const [selected, setSelected] = useState<any[]>([]);
47
51
 
48
52
  const hasFilter = context.filters.find((b) => b.field == header);
49
53
 
54
+ useEffect(() => {
55
+ setSelected(filteredValues);
56
+ }, [filteredValues]);
57
+
50
58
  useEffect(() => {
51
59
  if (visible) {
52
60
  context.setCurrentHeader(header);
@@ -95,7 +103,7 @@ export function Header({
95
103
  <div className="">
96
104
  <div
97
105
  className={
98
- "border flex items-center justify-center text-center relative "
106
+ " flex items-center justify-center text-center relative "
99
107
  }
100
108
  style={{ zIndex: 10, height: `${padding}px`, maxHeight: "100px" }}
101
109
  >
@@ -118,45 +126,52 @@ export function Header({
118
126
  );
119
127
  } else
120
128
  return (
121
- <div className="">
129
+ <div className=" ">
122
130
  <div
123
131
  ref={cellRef}
124
- className={"shadow "}
132
+ className={index < length - 1 ? "border-r" : ""}
133
+ onMouseEnter={(e) => setHovered(true)}
134
+ onMouseLeave={(e) => setHovered(false)}
125
135
  style={{ zIndex: 10, height: `${padding}px`, maxHeight: "100px" }}
126
136
  >
127
137
  <div className="flex justify-between items-center ">
128
- <div className="flex gap-2">
129
- {hasFilter ? (
138
+ {!context.disabled ? (
139
+ <div className="flex gap-2">
140
+ {hasFilter ? (
141
+ <div
142
+ className="cursor-pointer"
143
+ onClick={(e) => {
144
+ context.setFilters(null);
145
+ setSelected(filteredValues);
146
+ }}
147
+ >
148
+ <FilterIcon />
149
+ </div>
150
+ ) : (
151
+ <div></div>
152
+ )}
153
+
130
154
  <div
131
- className="cursor-pointer"
132
155
  onClick={(e) => {
133
- context.setFilters(null);
134
- setSelected(filteredValues);
156
+ context.setSort({
157
+ [header]: "TOGGLE",
158
+ });
135
159
  }}
136
160
  >
137
- <FilterIcon />
138
- </div>
139
- ) : (
140
- <div></div>
141
- )}
142
- <div
143
- onClick={(e) => {
144
- context.setSort({
145
- [header]: "TOGGLE",
146
- });
147
- }}
148
- >
149
- {sortIndex >= 0 ? (
150
- context.sort[sortIndex].type === "ASC" ? (
151
- <ArrowUPIcon />
161
+ {sortIndex >= 0 ? (
162
+ context.sort[sortIndex].type === "ASC" ? (
163
+ <ArrowUPIcon />
164
+ ) : (
165
+ <ArrowDownIcon />
166
+ )
152
167
  ) : (
153
- <ArrowDownIcon />
154
- )
155
- ) : (
156
- <div></div>
157
- )}
168
+ <div></div>
169
+ )}
170
+ </div>
158
171
  </div>
159
- </div>
172
+ ) : (
173
+ <div></div>
174
+ )}
160
175
  <div
161
176
  className="font-bold flex truncate text-xs items-center "
162
177
  style={{ height: `${padding}px` }}
@@ -168,19 +183,23 @@ export function Header({
168
183
  >
169
184
  {header}
170
185
  </div>
171
- <div
172
- style={{ zIndex: 10 }}
173
- className="icon font-bold p-1 cursor-pointer pr-3 "
174
- onClick={(e) => setVisible(true)}
175
- >
176
- <DropIcon />
177
- </div>
186
+ {!context.disabled ? (
187
+ <div
188
+ style={{ zIndex: 10 }}
189
+ className="icon font-bold p-1 cursor-pointer pr-3 "
190
+ onClick={(e) => setVisible(true)}
191
+ >
192
+ {hovered ? <DropIcon /> : ""}
193
+ </div>
194
+ ) : (
195
+ <div></div>
196
+ )}
178
197
  </div>
179
198
 
180
- {context.currentHeader != header && (
199
+ {!context.disabled && context.currentHeader != header && (
181
200
  <div
182
201
  onMouseDown={(e) => drag.startDrag(e, header)}
183
- className="absolute top-0 h-full cursor-col-resize hover:bg-blue-300 p-2"
202
+ className="absolute top-0 h-full cursor-col-resize hover:bg-blue-300 "
184
203
  style={{ right: -2, width: 6, zIndex: 20 }}
185
204
  />
186
205
  )}
@@ -302,7 +321,13 @@ export function Header({
302
321
  }}
303
322
  checked={text != "" || selected.includes(d)}
304
323
  />
305
- <div className="truncate">{d}</div>
324
+ <div className="truncate">
325
+ {d == ""
326
+ ? "Vacias"
327
+ : !Boolean(d)
328
+ ? "null"
329
+ : d}
330
+ </div>
306
331
  </div>
307
332
  );
308
333
  })}
@@ -16,6 +16,43 @@ export default function DropIcon() {
16
16
  </svg>
17
17
  );
18
18
  }
19
+
20
+ export function PrevIcon() {
21
+ return (
22
+ <svg
23
+ stroke="currentColor"
24
+ fill="currentColor"
25
+ strokeWidth="0"
26
+ viewBox="0 0 24 24"
27
+ height="1em"
28
+ width="1em"
29
+ xmlns="http://www.w3.org/2000/svg"
30
+ >
31
+ <polyline
32
+ fill="none"
33
+ strokeWidth="2"
34
+ points="7 2 17 12 7 22"
35
+ transform="matrix(-1 0 0 1 24 0)"
36
+ ></polyline>
37
+ </svg>
38
+ );
39
+ }
40
+
41
+ export function NextIcon() {
42
+ return (
43
+ <svg
44
+ stroke="currentColor"
45
+ fill="currentColor"
46
+ strokeWidth="0"
47
+ viewBox="0 0 24 24"
48
+ height="1em"
49
+ width="1em"
50
+ xmlns="http://www.w3.org/2000/svg"
51
+ >
52
+ <polyline fill="none" stroke-width="2" points="7 2 17 12 7 22"></polyline>
53
+ </svg>
54
+ );
55
+ }
19
56
  export function EditIcon() {
20
57
  return (
21
58
  <svg
@@ -8,7 +8,7 @@ export default function Searchable({
8
8
  context: ContextType & Omit<TableProps, "data">;
9
9
  }) {
10
10
  return (
11
- <div className="flex justify-start p-2 relative w-96">
11
+ <div className="flex justify-start p-2 relative w-96 text-xs">
12
12
  <input
13
13
  type="search"
14
14
  placeholder="Buscar por ...."
@@ -52,6 +52,7 @@ export interface TableProps {
52
52
  flex?: number;
53
53
  sortBy?: Record<string, "DESC" | "ASC">;
54
54
  onCloseModal?: (data: GridValidRowModel) => Promise<boolean>;
55
+ disabled?: boolean;
55
56
  [key: string]: any;
56
57
  }
57
58
 
@@ -0,0 +1,65 @@
1
+ import { useState, useMemo, useCallback, useEffect } from "react";
2
+
3
+ function usePaginacion({
4
+ total,
5
+ tamanioPagina = 100,
6
+ paginaInicial = 1,
7
+ }: {
8
+ total: number;
9
+ tamanioPagina?: number;
10
+ paginaInicial?: number;
11
+ }) {
12
+ const [totalPaginas, setTotalPaginas] = useState(
13
+ Math.max(1, Math.ceil(total / tamanioPagina)),
14
+ );
15
+
16
+ const [pagina, setPagina] = useState(
17
+ Math.min(Math.max(paginaInicial, 1), totalPaginas),
18
+ );
19
+
20
+ const inicio = total === 0 ? 0 : (pagina - 1) * tamanioPagina + 1;
21
+ const fin = Math.min(pagina * tamanioPagina, total);
22
+
23
+ const rango = useMemo(() => {
24
+ if (total === 0) return "0 a 0";
25
+ return `${inicio} a ${fin}`;
26
+ }, [inicio, fin, total]);
27
+
28
+ const hasNext = pagina < totalPaginas;
29
+ const hasPrev = pagina > 1;
30
+
31
+ const next = useCallback(() => {
32
+ setPagina((p) => Math.min(p + 1, totalPaginas));
33
+ }, [totalPaginas]);
34
+
35
+ const prev = useCallback(() => {
36
+ setPagina((p) => Math.max(p - 1, 1));
37
+ }, []);
38
+
39
+ const irAPagina = useCallback<(n: number) => void>(
40
+ (n) => {
41
+ setPagina(Math.min(Math.max(n, 1), totalPaginas));
42
+ },
43
+ [totalPaginas],
44
+ );
45
+
46
+ useEffect(() => {
47
+ setTotalPaginas(Math.max(1, Math.ceil(total / tamanioPagina)));
48
+ setPagina(1);
49
+ }, [total]);
50
+ return {
51
+ rango,
52
+ inicio,
53
+ fin,
54
+ total,
55
+ pagina,
56
+ totalPaginas,
57
+ hasNext,
58
+ hasPrev,
59
+ next,
60
+ prev,
61
+ irAPagina,
62
+ };
63
+ }
64
+
65
+ export default usePaginacion;