next-recomponents 2.0.4 → 2.0.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": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "description nueva",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/pop/index.tsx CHANGED
@@ -1,17 +1,110 @@
1
1
  "use client";
2
2
  import { useState } from "react";
3
3
 
4
+ type Color =
5
+ | "white"
6
+ | "primary"
7
+ | "secondary"
8
+ | "info"
9
+ | "danger"
10
+ | "warning"
11
+ | "success";
12
+
13
+ // ─── Color tokens ─────────────────────────────────────────────────────────────
14
+
15
+ const COLOR_CONFIG: Record<
16
+ Color,
17
+ {
18
+ bg: string;
19
+ iconBg: string;
20
+ iconText: string;
21
+ border: string;
22
+ confirm: string;
23
+ label: string;
24
+ }
25
+ > = {
26
+ primary: {
27
+ bg: "from-blue-50 to-indigo-50",
28
+ iconBg: "bg-blue-100",
29
+ iconText: "text-blue-600",
30
+ border: "border-blue-200",
31
+ confirm: "bg-blue-600 hover:bg-blue-700 focus:ring-blue-300",
32
+ label: "ℹ",
33
+ },
34
+ info: {
35
+ bg: "from-sky-50 to-cyan-50",
36
+ iconBg: "bg-sky-100",
37
+ iconText: "text-sky-600",
38
+ border: "border-sky-200",
39
+ confirm: "bg-sky-600 hover:bg-sky-700 focus:ring-sky-300",
40
+ label: "ℹ",
41
+ },
42
+ success: {
43
+ bg: "from-emerald-50 to-green-50",
44
+ iconBg: "bg-emerald-100",
45
+ iconText: "text-emerald-600",
46
+ border: "border-emerald-200",
47
+ confirm: "bg-emerald-600 hover:bg-emerald-700 focus:ring-emerald-300",
48
+ label: "✓",
49
+ },
50
+ warning: {
51
+ bg: "from-amber-50 to-yellow-50",
52
+ iconBg: "bg-amber-100",
53
+ iconText: "text-amber-600",
54
+ border: "border-amber-200",
55
+ confirm: "bg-amber-500 hover:bg-amber-600 focus:ring-amber-300",
56
+ label: "⚠",
57
+ },
58
+ danger: {
59
+ bg: "from-red-50 to-rose-50",
60
+ iconBg: "bg-red-100",
61
+ iconText: "text-red-600",
62
+ border: "border-red-200",
63
+ confirm: "bg-red-600 hover:bg-red-700 focus:ring-red-300",
64
+ label: "✕",
65
+ },
66
+ secondary: {
67
+ bg: "from-slate-50 to-gray-50",
68
+ iconBg: "bg-slate-100",
69
+ iconText: "text-slate-600",
70
+ border: "border-slate-200",
71
+ confirm: "bg-slate-700 hover:bg-slate-800 focus:ring-slate-300",
72
+ label: "◎",
73
+ },
74
+ white: {
75
+ bg: "from-gray-50 to-white",
76
+ iconBg: "bg-gray-100",
77
+ iconText: "text-gray-500",
78
+ border: "border-gray-200",
79
+ confirm: "bg-gray-700 hover:bg-gray-800 focus:ring-gray-300",
80
+ label: "◎",
81
+ },
82
+ };
83
+
84
+ // ─── Types ────────────────────────────────────────────────────────────────────
85
+
86
+ interface PopupState {
87
+ type: "alert" | "confirm" | "prompt";
88
+ message: string;
89
+ visible: boolean;
90
+ inputValue: string;
91
+ onConfirm?: (value?: string) => void;
92
+ onCancel?: () => void;
93
+ color: Color;
94
+ }
95
+
96
+ // ─── Hook ─────────────────────────────────────────────────────────────────────
97
+
4
98
  export default function usePopup() {
5
- const [popup, setPopup] = useState<{
6
- type: "alert" | "confirm" | "prompt";
7
- message: string;
8
- visible: boolean;
9
- inputValue: string;
10
- onConfirm?: (value?: string) => void;
11
- onCancel?: () => void;
12
- }>({ type: "alert", message: "", visible: false, inputValue: "" });
13
-
14
- function alert(message: string): Promise<void> {
99
+ const [popup, setPopup] = useState<PopupState>({
100
+ type: "alert",
101
+ message: "",
102
+ visible: false,
103
+ inputValue: "",
104
+ color: "primary",
105
+ });
106
+
107
+ function alert(message: string, color: Color = "primary"): Promise<void> {
15
108
  return new Promise((resolve) => {
16
109
  setPopup({
17
110
  type: "alert",
@@ -19,11 +112,15 @@ export default function usePopup() {
19
112
  visible: true,
20
113
  inputValue: "",
21
114
  onConfirm: () => resolve(),
115
+ color,
22
116
  });
23
117
  });
24
118
  }
25
119
 
26
- function confirm(message: string): Promise<boolean> {
120
+ function confirm(
121
+ message: string,
122
+ color: Color = "primary",
123
+ ): Promise<boolean> {
27
124
  return new Promise((resolve) => {
28
125
  setPopup({
29
126
  type: "confirm",
@@ -32,11 +129,15 @@ export default function usePopup() {
32
129
  inputValue: "",
33
130
  onConfirm: () => resolve(true),
34
131
  onCancel: () => resolve(false),
132
+ color,
35
133
  });
36
134
  });
37
135
  }
38
136
 
39
- function prompt(message: string): Promise<string | null> {
137
+ function prompt(
138
+ message: string,
139
+ color: Color = "primary",
140
+ ): Promise<string | null> {
40
141
  return new Promise((resolve) => {
41
142
  setPopup({
42
143
  type: "prompt",
@@ -45,6 +146,7 @@ export default function usePopup() {
45
146
  inputValue: "",
46
147
  onConfirm: (value) => resolve(value ?? ""),
47
148
  onCancel: () => resolve(null),
149
+ color,
48
150
  });
49
151
  });
50
152
  }
@@ -57,86 +159,90 @@ export default function usePopup() {
57
159
  });
58
160
  }
59
161
 
162
+ const c = COLOR_CONFIG[popup.color];
163
+
60
164
  const PopupComponent = popup.visible ? (
61
165
  <div
62
- style={{
63
- position: "fixed",
64
- top: 0,
65
- left: 0,
66
- width: "100%",
67
- height: "100%",
68
- background: "rgba(0,0,0,0.5)",
69
- display: "flex",
70
- alignItems: "center",
71
- justifyContent: "center",
72
- zIndex: 1000,
73
- }}
166
+ className="fixed inset-0 flex items-center justify-center z-[1000]"
167
+ style={{ background: "rgba(15,23,42,0.45)", backdropFilter: "blur(2px)" }}
168
+ onClick={(e) => e.target === e.currentTarget && close(false)}
74
169
  >
75
170
  <div
76
- style={{
77
- background: "#fff",
78
- padding: "24px 32px",
79
- borderRadius: "8px",
80
- minWidth: "300px",
81
- textAlign: "center",
82
- boxShadow: "0 4px 20px rgba(0,0,0,0.2)",
83
- }}
171
+ className={`
172
+ bg-gradient-to-br ${c.bg} border ${c.border}
173
+ rounded-2xl shadow-2xl w-full max-w-sm mx-4
174
+ animate-[fadeInScale_0.18s_ease-out]
175
+ `}
176
+ style={{ animation: "fadeInScale 0.18s ease-out" }}
84
177
  >
85
- <p style={{ margin: "0 0 16px", fontSize: "16px" }}>{popup.message}</p>
178
+ <style>{`
179
+ @keyframes fadeInScale {
180
+ from { opacity: 0; transform: scale(0.93) translateY(8px); }
181
+ to { opacity: 1; transform: scale(1) translateY(0); }
182
+ }
183
+ `}</style>
86
184
 
185
+ {/* Icon + Message */}
186
+ <div className="flex flex-col items-center gap-3 px-8 pt-8 pb-5 text-center">
187
+ <div
188
+ className={`w-12 h-12 rounded-full ${c.iconBg} flex items-center justify-center`}
189
+ >
190
+ <span className={`text-xl font-bold ${c.iconText}`}>{c.label}</span>
191
+ </div>
192
+ <p className="text-gray-800 text-[15px] font-medium leading-snug">
193
+ {popup.message}
194
+ </p>
195
+ </div>
196
+
197
+ {/* Prompt input */}
87
198
  {popup.type === "prompt" && (
88
- <input
89
- autoFocus
90
- type="text"
91
- value={popup.inputValue}
92
- onChange={(e) =>
93
- setPopup((prev) => ({ ...prev, inputValue: e.target.value }))
94
- }
95
- onKeyDown={(e) =>
96
- e.key === "Enter" && close(true, popup.inputValue)
97
- }
98
- style={{
99
- width: "100%",
100
- padding: "8px 12px",
101
- marginBottom: "16px",
102
- border: "1px solid #d1d5db",
103
- borderRadius: "6px",
104
- fontSize: "14px",
105
- boxSizing: "border-box",
106
- }}
107
- />
199
+ <div className="px-8 pb-2">
200
+ <input
201
+ autoFocus
202
+ type="text"
203
+ value={popup.inputValue}
204
+ onChange={(e) =>
205
+ setPopup((prev) => ({ ...prev, inputValue: e.target.value }))
206
+ }
207
+ onKeyDown={(e) =>
208
+ e.key === "Enter" && close(true, popup.inputValue)
209
+ }
210
+ className={`
211
+ w-full px-3 py-2 rounded-lg border ${c.border} bg-white
212
+ text-sm text-gray-800 outline-none
213
+ focus:ring-2 ${c.confirm.includes("blue") ? "focus:ring-blue-200" : "focus:ring-gray-200"}
214
+ transition
215
+ `}
216
+ placeholder="Escribe aquí..."
217
+ />
218
+ </div>
108
219
  )}
109
220
 
110
- <div style={{ display: "flex", gap: "8px", justifyContent: "center" }}>
221
+ {/* Divider */}
222
+ <div className={`border-t ${c.border} mx-0 mt-4`} />
223
+
224
+ {/* Actions */}
225
+ <div className="flex gap-2 px-6 py-4 justify-end">
111
226
  {(popup.type === "confirm" || popup.type === "prompt") && (
112
227
  <button
113
228
  onClick={() => close(false)}
114
- style={{
115
- padding: "8px 24px",
116
- background: "#e5e7eb",
117
- color: "#374151",
118
- border: "none",
119
- borderRadius: "6px",
120
- cursor: "pointer",
121
- fontSize: "14px",
122
- }}
229
+ className="
230
+ px-4 py-2 rounded-lg text-sm font-medium
231
+ bg-white border border-gray-200 text-gray-600
232
+ hover:bg-gray-50 transition
233
+ "
123
234
  >
124
235
  Cancelar
125
236
  </button>
126
237
  )}
127
238
  <button
128
239
  onClick={() => close(true, popup.inputValue)}
129
- style={{
130
- padding: "8px 24px",
131
- background: "#3b82f6",
132
- color: "#fff",
133
- border: "none",
134
- borderRadius: "6px",
135
- cursor: "pointer",
136
- fontSize: "14px",
137
- }}
240
+ className={`
241
+ px-5 py-2 rounded-lg text-sm font-semibold text-white
242
+ ${c.confirm} transition focus:outline-none focus:ring-2
243
+ `}
138
244
  >
139
- OK
245
+ Aceptar
140
246
  </button>
141
247
  </div>
142
248
  </div>