next-recomponents 2.0.40 → 2.0.42

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": "2.0.40",
3
+ "version": "2.0.42",
4
4
  "description": "description nueva",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/index.tsx CHANGED
@@ -19,3 +19,4 @@ export { useFormValues } from "./form";
19
19
  export { default as DocumentViewer } from "./doc-viewer";
20
20
  export { default as Table3 } from "./table3";
21
21
  export { default as usePopup } from "./pop";
22
+ export { default as TableAdvanced } from "./table-advanced";
@@ -21,13 +21,13 @@ export default function Input({
21
21
  const [showPassword, setShowPassword] = useState(false);
22
22
  const svg = icon;
23
23
  return (
24
- <div className="w-full relative">
25
- <div className="relative flex items-center border rounded bg-white pr-1 mb-5">
24
+ <div className="w-full relative my-3">
25
+ <div className="relative flex items-center border rounded bg-white pr-1 mb-5 w-full">
26
26
  <input
27
27
  {...props}
28
28
  type={isPassword && showPassword ? "text" : props.type}
29
29
  className={[
30
- "flex p-2 w-full bg-transparent pt-4",
30
+ "block p-2 w-full bg-transparent min-w-0",
31
31
  isPassword && "pr-10",
32
32
  value !== "" && !isValid && "bg-red-200 text-black",
33
33
  value !== "" && isValid && "bg-green-200 text-black",
@@ -36,7 +36,7 @@ export default function Input({
36
36
  .filter(Boolean)
37
37
  .join(" ")}
38
38
  />
39
- <label className="absolute -top-2.5 left-2 text-xs font-bold bg-white px-1">
39
+ <label className="absolute -top-2.5 left-2 text-xs font-bold px-1">
40
40
  {label}
41
41
  {props?.required && <span className="text-red-500 ml-1">*</span>}
42
42
  </label>
@@ -15,6 +15,7 @@ export default function Modal({
15
15
  children,
16
16
  color = "primary",
17
17
  title,
18
+ onClose,
18
19
  }: {
19
20
  button: ReactElement<React.ComponentPropsWithRef<"button">>;
20
21
  children: ReactElement<
@@ -22,9 +23,12 @@ export default function Modal({
22
23
  >;
23
24
  color?: PopupColor;
24
25
  title?: string;
26
+ onClose?: () => Promise<boolean>;
25
27
  }) {
26
28
  const pop = usePopup();
27
- const hide = () => pop.close(false);
29
+ const hide = () => {
30
+ pop.close(false);
31
+ };
28
32
 
29
33
  const childrenWithHide = useMemo(
30
34
  () => cloneElement(children, { hide }),
@@ -39,14 +43,14 @@ export default function Modal({
39
43
  const onClick = props?.onClick;
40
44
 
41
45
  return (
42
- <>
46
+ <div className="">
43
47
  {cloneElement(button, {
44
48
  onClick: (e) => {
45
49
  onClick?.(e as any);
46
- pop.modal(childrenWithHide, color, false, true);
50
+ pop.modal(childrenWithHide, color, false, true, onClose);
47
51
  },
48
52
  })}
49
53
  {pop.PopupComponent}
50
- </>
54
+ </div>
51
55
  );
52
56
  }
package/src/pop/color.tsx CHANGED
@@ -58,7 +58,7 @@ export const COLOR_CONFIG: Record<PopupColor, ColorTokens> = {
58
58
  label: "◎",
59
59
  },
60
60
  white: {
61
- bg: "from-gray-50 to-white",
61
+ bg: "from-white to-white",
62
62
  iconBg: "bg-gray-100",
63
63
  iconText: "text-gray-500",
64
64
  border: "border-gray-200",
package/src/pop/index.tsx CHANGED
@@ -30,13 +30,21 @@ export default function usePopup() {
30
30
  [],
31
31
  );
32
32
 
33
- const close = useCallback((confirmed: boolean, value?: string) => {
34
- setPopup((prev) => {
35
- if (confirmed) prev.onConfirm?.(value);
36
- else prev.onCancel?.();
37
- return { ...prev, visible: false, inputValue: "" };
38
- });
39
- }, []);
33
+ const close = useCallback(
34
+ async (confirmed: boolean, value?: string) => {
35
+ const prev = { ...popup };
36
+ let visible = false;
37
+ if (confirmed) {
38
+ prev.onConfirm?.(value);
39
+ } else if (prev?.onCancel) {
40
+ visible = !Boolean(await prev.onCancel?.());
41
+ }
42
+
43
+ const data = { ...prev, visible, inputValue: "" };
44
+ setPopup(data);
45
+ },
46
+ [popup],
47
+ );
40
48
 
41
49
  const alert = useCallback(
42
50
  (message: string, color: PopupColor = "primary"): Promise<void> =>
@@ -58,14 +66,19 @@ export default function usePopup() {
58
66
  color: PopupColor = "primary",
59
67
  icons: boolean = false,
60
68
  full: boolean = false,
69
+ onClose?: () => Promise<boolean>,
61
70
  ): Promise<void> =>
62
71
  new Promise((resolve) =>
63
72
  open({
64
73
  type: "modal",
65
74
  message,
66
75
  color,
67
- onConfirm: () => resolve(),
68
- onCancel: () => resolve(),
76
+ // onConfirm: () => {
77
+ // resolve();
78
+ // },
79
+ onCancel: async () => {
80
+ return await onClose?.();
81
+ },
69
82
  icons,
70
83
  full,
71
84
  }),
@@ -16,7 +16,7 @@ export function PopupOverlay({
16
16
 
17
17
  return (
18
18
  <div
19
- className={"fixed inset-0 flex items-center justify-center z-[1000] "}
19
+ className="fixed inset-0 flex items-center justify-center z-[1000] overflow-auto p-1"
20
20
  style={{ background: "rgba(15,23,42,0.45)", backdropFilter: "blur(2px)" }}
21
21
  // onClick={(e) => {
22
22
  // if (e.target === e.currentTarget) {
@@ -33,7 +33,7 @@ export function PopupOverlay({
33
33
  `}</style>
34
34
 
35
35
  <div
36
- className={`bg-gradient-to-br ${c.bg} border ${c.border} ${popup.full == true ? " w-full h-screen m-20 " : " max-w-sm "} rounded-2xl shadow-2xl mx-4`}
36
+ className={`bg-gradient-to-br ${c.bg} border ${c.border} ${popup.full == true ? " w-screen h-screen mt-10 " : " max-w-sm "} rounded shadow m-2`}
37
37
  style={{ animation: "fadeInScale 0.18s ease-out", overflow: "auto" }}
38
38
  >
39
39
  {/* Header */}
@@ -77,7 +77,9 @@ export function PopupOverlay({
77
77
  )}
78
78
 
79
79
  {/* Divider */}
80
- <div className={`border-t ${c.border} mt-4`} />
80
+ {popup.type !== "modal" && (
81
+ <div className={`border-t ${c.border} mt-4`} />
82
+ )}
81
83
 
82
84
  {/* Actions */}
83
85
  {popup.type !== "modal" && (
package/src/pop/types.ts CHANGED
@@ -40,7 +40,7 @@ export interface PopupState {
40
40
  inputValue: string;
41
41
  color: PopupColor;
42
42
  onConfirm?: (value?: string) => void;
43
- onCancel?: () => void;
43
+ onCancel?: () => void | Promise<boolean | void>;
44
44
  icons?: boolean;
45
45
  full?: boolean;
46
46
  }
@@ -119,7 +119,7 @@ export default function Select({
119
119
  }
120
120
  }, [isOpen]);
121
121
  return (
122
- <div ref={containerRef} className="w-full relative mb-5">
122
+ <div ref={containerRef} className="w-full relative my-3">
123
123
  <div className="relative flex items-center border rounded bg-white">
124
124
  <input
125
125
  autoComplete="off"
@@ -163,7 +163,7 @@ export default function Select({
163
163
  onKeyDown={handleKeyDown}
164
164
  />
165
165
  {label && (
166
- <label className="absolute -top-2.5 left-2 text-xs font-bold bg-white px-1">
166
+ <label className="absolute -top-2.5 left-2 text-xs font-bold px-1">
167
167
  {label} {props?.required && <span className="text-red-500">*</span>}
168
168
  </label>
169
169
  )}
@@ -9,13 +9,6 @@ import regularExpresions from "../regular-expresions";
9
9
 
10
10
  // ─── Types ────────────────────────────────────────────────────────────────────
11
11
 
12
- export interface TableButtonProps extends React.MouseEvent<
13
- HTMLButtonElement,
14
- MouseEvent
15
- > {
16
- row: Record<string, any>;
17
- }
18
-
19
12
  type FooterAggregation = "sum" | "avg" | "count";
20
13
 
21
14
  interface FooterType {
@@ -23,7 +16,12 @@ interface FooterType {
23
16
  }
24
17
 
25
18
  type GridDensity = "compact" | "standard" | "comfortable";
26
-
19
+ export interface TableButtonProps extends React.MouseEvent<
20
+ HTMLButtonElement,
21
+ MouseEvent
22
+ > {
23
+ row: Record<string, any>;
24
+ }
27
25
  interface TableProps {
28
26
  data: any;
29
27
  searchable?: boolean;
@@ -0,0 +1,88 @@
1
+ import { useEffect, useMemo, useReducer, useState } from "react";
2
+ import { filterReducer } from "./filter.reducer";
3
+ import { FiltersType, SortType } from "./types";
4
+ import { sortReducer } from "./sort.reducer";
5
+ import useExcel from "../use-excel";
6
+
7
+ export default function useContext({ onSelect }: { onSelect?: boolean }) {
8
+ const excel = useExcel();
9
+ const [editions, setEditions] = useState<any[]>([]);
10
+ const [selected, setSelected] = useState<any[]>([]);
11
+ const [data, setData] = useState<any[]>([]);
12
+ const headers = [...new Set(data.map((b) => Object.keys(b)).flat())];
13
+
14
+ const [currentHeader, setCurrentHeader] = useState<string | null>(null);
15
+ const cols = headers.length;
16
+ const [filters, setFilters] = useReducer(
17
+ filterReducer,
18
+ new Array<FiltersType>(),
19
+ );
20
+ const [searchBy, setSearchBy] = useState<string>("");
21
+ const [sort, setSort] = useReducer(sortReducer, new Array<SortType>());
22
+
23
+ const sortedData: any[] = useMemo(() => {
24
+ return [...data].sort((a, b) => {
25
+ for (const { field, type } of sort.reverse()) {
26
+ const av = a[field];
27
+ const bv = b[field];
28
+
29
+ // nulls/undefined van siempre al final, independiente de ASC/DESC
30
+ if (av == null && bv == null) continue;
31
+ if (av == null) return 1;
32
+ if (bv == null) return -1;
33
+
34
+ let cmp: number;
35
+ if (typeof av === "number" && typeof bv === "number") {
36
+ cmp = av - bv;
37
+ } else {
38
+ cmp = `${av}`.localeCompare(`${bv}`, undefined, { numeric: true });
39
+ }
40
+
41
+ if (cmp !== 0) {
42
+ return type === "DESC" ? -cmp : cmp;
43
+ }
44
+ // empate: sigue al siguiente campo en context.sort
45
+ }
46
+ return 0;
47
+ });
48
+ }, [data, sort]);
49
+ const filteredData = [...sortedData].filter((d) => {
50
+ if (editions.includes(d?.id)) return true;
51
+
52
+ for (const { field, values } of filters) {
53
+ if (!values.includes(d[field])) {
54
+ return false;
55
+ }
56
+ }
57
+ return true;
58
+ });
59
+
60
+ useEffect(() => {
61
+ if (filters.length == 0) {
62
+ setEditions([]);
63
+ }
64
+ }, [filters]);
65
+ return {
66
+ currentHeader,
67
+ setCurrentHeader,
68
+ sort,
69
+ setSort,
70
+ cols,
71
+ headers,
72
+ data,
73
+ sortedData,
74
+ filters,
75
+ setFilters,
76
+ filteredData,
77
+ setData,
78
+ searchBy,
79
+ setSearchBy,
80
+ selected,
81
+ setSelected,
82
+ editions,
83
+ excel,
84
+ setEditions,
85
+ };
86
+ }
87
+
88
+ export type ContextType = ReturnType<typeof useContext>;
@@ -0,0 +1,19 @@
1
+ import { FiltersType } from "./types";
2
+
3
+ export const filterReducer = (acc: FiltersType[], b: FiltersType | null) => {
4
+ if (b == null) return [];
5
+ const newAcc: FiltersType[] = [];
6
+ newAcc.push(b);
7
+ return newAcc;
8
+
9
+ // const newAcc = [...acc];
10
+
11
+ // const index = newAcc.findIndex((aa) => aa.field == b.field);
12
+ // if (index >= 0) {
13
+ // newAcc[index].values = b.values;
14
+ // } else {
15
+ // newAcc.push(b);
16
+ // }
17
+
18
+ // return newAcc;
19
+ };