@stackvibe-studio/ui 0.2.0 → 0.3.0
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/README.md +44 -33
- package/dist/components/accordion.d.ts +13 -0
- package/dist/components/button.d.ts +1 -1
- package/dist/components/dialog.d.ts +24 -0
- package/dist/components/drawer.d.ts +17 -0
- package/dist/components/dropdown-menu.d.ts +16 -0
- package/dist/components/progress.d.ts +8 -0
- package/dist/components/switch.d.ts +10 -0
- package/dist/components/toast.d.ts +15 -0
- package/dist/components/tooltip.d.ts +8 -0
- package/dist/index.cjs +529 -32
- package/dist/index.d.ts +8 -0
- package/dist/index.js +513 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,56 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
// src/components/
|
|
3
|
+
// src/components/accordion.tsx
|
|
4
|
+
import { useState } from "react";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
function Accordion({
|
|
7
|
+
items,
|
|
8
|
+
type = "single",
|
|
9
|
+
defaultOpen = [],
|
|
10
|
+
className = ""
|
|
11
|
+
}) {
|
|
12
|
+
const [openIds, setOpenIds] = useState(defaultOpen);
|
|
13
|
+
const toggle = (id) => {
|
|
14
|
+
if (type === "single") {
|
|
15
|
+
setOpenIds(openIds.includes(id) ? [] : [id]);
|
|
16
|
+
} else {
|
|
17
|
+
setOpenIds(
|
|
18
|
+
openIds.includes(id) ? openIds.filter((item) => item !== id) : [...openIds, id]
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
return /* @__PURE__ */ jsx("div", { className: ["divide-y divide-white/10 rounded-2xl border border-white/10 bg-slate-900/60 overflow-hidden", className].join(" "), children: items.map((item) => {
|
|
23
|
+
const isOpen = openIds.includes(item.id);
|
|
24
|
+
return /* @__PURE__ */ jsxs("div", { className: "transition duration-150", children: [
|
|
25
|
+
/* @__PURE__ */ jsxs(
|
|
26
|
+
"button",
|
|
27
|
+
{
|
|
28
|
+
type: "button",
|
|
29
|
+
onClick: () => toggle(item.id),
|
|
30
|
+
className: "flex w-full items-center justify-between px-5 py-4 text-left font-medium text-white hover:bg-white/5 transition cursor-pointer",
|
|
31
|
+
"aria-expanded": isOpen,
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ jsx("span", { children: item.title }),
|
|
34
|
+
/* @__PURE__ */ jsx(
|
|
35
|
+
"svg",
|
|
36
|
+
{
|
|
37
|
+
className: `h-4 w-4 transform text-slate-400 transition-transform duration-200 ${isOpen ? "rotate-180 text-violet-400" : ""}`,
|
|
38
|
+
fill: "none",
|
|
39
|
+
viewBox: "0 0 24 24",
|
|
40
|
+
stroke: "currentColor",
|
|
41
|
+
children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
isOpen && /* @__PURE__ */ jsx("div", { className: "px-5 pb-4 pt-1 text-sm text-slate-300 leading-relaxed border-t border-white/5 animate-in fade-in duration-200", children: item.content })
|
|
48
|
+
] }, item.id);
|
|
49
|
+
}) });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/components/alert.tsx
|
|
53
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
5
54
|
var variantClasses = {
|
|
6
55
|
info: "border-cyan-500/40 bg-cyan-500/10 text-cyan-50",
|
|
7
56
|
success: "border-emerald-500/40 bg-emerald-500/10 text-emerald-50",
|
|
@@ -9,29 +58,29 @@ var variantClasses = {
|
|
|
9
58
|
danger: "border-rose-500/40 bg-rose-500/10 text-rose-50"
|
|
10
59
|
};
|
|
11
60
|
function Alert({ title, variant = "info", className = "", children, ...props }) {
|
|
12
|
-
return /* @__PURE__ */
|
|
61
|
+
return /* @__PURE__ */ jsxs2(
|
|
13
62
|
"div",
|
|
14
63
|
{
|
|
15
64
|
...props,
|
|
16
65
|
className: ["rounded-2xl border p-4 text-sm", variantClasses[variant], className].join(" "),
|
|
17
66
|
role: "alert",
|
|
18
67
|
children: [
|
|
19
|
-
title ? /* @__PURE__ */
|
|
20
|
-
/* @__PURE__ */
|
|
68
|
+
title ? /* @__PURE__ */ jsx2("p", { className: "mb-1 font-medium", children: title }) : null,
|
|
69
|
+
/* @__PURE__ */ jsx2("div", { children })
|
|
21
70
|
]
|
|
22
71
|
}
|
|
23
72
|
);
|
|
24
73
|
}
|
|
25
74
|
|
|
26
75
|
// src/components/avatar.tsx
|
|
27
|
-
import { jsx as
|
|
76
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
28
77
|
var sizeClasses = {
|
|
29
78
|
sm: "h-9 w-9 text-xs",
|
|
30
79
|
md: "h-12 w-12 text-sm",
|
|
31
80
|
lg: "h-16 w-16 text-base"
|
|
32
81
|
};
|
|
33
82
|
function Avatar({ src, alt = "avatar", fallback = "SV", size = "md", className = "", ...props }) {
|
|
34
|
-
return src ? /* @__PURE__ */
|
|
83
|
+
return src ? /* @__PURE__ */ jsx3(
|
|
35
84
|
"img",
|
|
36
85
|
{
|
|
37
86
|
...props,
|
|
@@ -39,7 +88,7 @@ function Avatar({ src, alt = "avatar", fallback = "SV", size = "md", className =
|
|
|
39
88
|
alt,
|
|
40
89
|
className: ["rounded-full object-cover ring-1 ring-white/10", sizeClasses[size], className].join(" ")
|
|
41
90
|
}
|
|
42
|
-
) : /* @__PURE__ */
|
|
91
|
+
) : /* @__PURE__ */ jsx3(
|
|
43
92
|
"div",
|
|
44
93
|
{
|
|
45
94
|
className: ["flex items-center justify-center rounded-full bg-violet-500/20 font-semibold text-violet-100 ring-1 ring-violet-400/20", sizeClasses[size], className].join(" "),
|
|
@@ -49,14 +98,14 @@ function Avatar({ src, alt = "avatar", fallback = "SV", size = "md", className =
|
|
|
49
98
|
}
|
|
50
99
|
|
|
51
100
|
// src/components/badge.tsx
|
|
52
|
-
import { jsx as
|
|
101
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
53
102
|
var variants = {
|
|
54
103
|
primary: "bg-violet-500/20 text-violet-200 ring-1 ring-violet-400/20",
|
|
55
104
|
secondary: "bg-cyan-500/15 text-cyan-200 ring-1 ring-cyan-400/20",
|
|
56
105
|
outline: "bg-transparent text-slate-200 ring-1 ring-white/10"
|
|
57
106
|
};
|
|
58
107
|
function Badge({ variant = "primary", className = "", ...props }) {
|
|
59
|
-
return /* @__PURE__ */
|
|
108
|
+
return /* @__PURE__ */ jsx4(
|
|
60
109
|
"span",
|
|
61
110
|
{
|
|
62
111
|
...props,
|
|
@@ -66,7 +115,7 @@ function Badge({ variant = "primary", className = "", ...props }) {
|
|
|
66
115
|
}
|
|
67
116
|
|
|
68
117
|
// src/components/button.tsx
|
|
69
|
-
import { jsx as
|
|
118
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
70
119
|
var variantClasses2 = {
|
|
71
120
|
primary: "bg-violet-500 text-white hover:bg-violet-400",
|
|
72
121
|
secondary: "bg-cyan-500 text-slate-950 hover:bg-cyan-400",
|
|
@@ -88,16 +137,16 @@ function Button(props) {
|
|
|
88
137
|
].join(" ");
|
|
89
138
|
if (as === "a") {
|
|
90
139
|
const { href, ...anchorProps } = rest;
|
|
91
|
-
return /* @__PURE__ */
|
|
140
|
+
return /* @__PURE__ */ jsx5("a", { ...anchorProps, href, className: commonClassName });
|
|
92
141
|
}
|
|
93
142
|
const { type = "button", ...buttonProps } = rest;
|
|
94
|
-
return /* @__PURE__ */
|
|
143
|
+
return /* @__PURE__ */ jsx5("button", { ...buttonProps, type, className: commonClassName });
|
|
95
144
|
}
|
|
96
145
|
|
|
97
146
|
// src/components/card.tsx
|
|
98
|
-
import { jsx as
|
|
147
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
99
148
|
function Card({ as: Component = "div", className = "", ...props }) {
|
|
100
|
-
return /* @__PURE__ */
|
|
149
|
+
return /* @__PURE__ */ jsx6(
|
|
101
150
|
Component,
|
|
102
151
|
{
|
|
103
152
|
...props,
|
|
@@ -110,9 +159,9 @@ function Card({ as: Component = "div", className = "", ...props }) {
|
|
|
110
159
|
}
|
|
111
160
|
|
|
112
161
|
// src/components/checkbox.tsx
|
|
113
|
-
import { jsx as
|
|
162
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
114
163
|
function Checkbox({ className = "", ...props }) {
|
|
115
|
-
return /* @__PURE__ */
|
|
164
|
+
return /* @__PURE__ */ jsx7(
|
|
116
165
|
"input",
|
|
117
166
|
{
|
|
118
167
|
...props,
|
|
@@ -122,10 +171,217 @@ function Checkbox({ className = "", ...props }) {
|
|
|
122
171
|
);
|
|
123
172
|
}
|
|
124
173
|
|
|
174
|
+
// src/components/dialog.tsx
|
|
175
|
+
import { useEffect, useRef } from "react";
|
|
176
|
+
import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
177
|
+
function Dialog({ open, onOpenChange, children, className = "" }) {
|
|
178
|
+
const dialogRef = useRef(null);
|
|
179
|
+
useEffect(() => {
|
|
180
|
+
const handleKeyDown = (e) => {
|
|
181
|
+
if (e.key === "Escape" && open) {
|
|
182
|
+
onOpenChange(false);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
if (open) {
|
|
186
|
+
document.body.style.overflow = "hidden";
|
|
187
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
188
|
+
} else {
|
|
189
|
+
document.body.style.overflow = "";
|
|
190
|
+
}
|
|
191
|
+
return () => {
|
|
192
|
+
document.body.style.overflow = "";
|
|
193
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
194
|
+
};
|
|
195
|
+
}, [open, onOpenChange]);
|
|
196
|
+
if (!open) return null;
|
|
197
|
+
return /* @__PURE__ */ jsx8(
|
|
198
|
+
"div",
|
|
199
|
+
{
|
|
200
|
+
role: "dialog",
|
|
201
|
+
"aria-modal": "true",
|
|
202
|
+
className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-slate-950/80 backdrop-blur-md animate-in fade-in duration-200",
|
|
203
|
+
onClick: (e) => {
|
|
204
|
+
if (e.target === e.currentTarget) onOpenChange(false);
|
|
205
|
+
},
|
|
206
|
+
children: /* @__PURE__ */ jsxs3(
|
|
207
|
+
"div",
|
|
208
|
+
{
|
|
209
|
+
ref: dialogRef,
|
|
210
|
+
className: [
|
|
211
|
+
"relative w-full max-w-lg rounded-3xl border border-white/10 bg-slate-900/95 p-6 shadow-2xl shadow-violet-500/10 text-white animate-in zoom-in-95 duration-200",
|
|
212
|
+
className
|
|
213
|
+
].join(" "),
|
|
214
|
+
children: [
|
|
215
|
+
/* @__PURE__ */ jsx8(
|
|
216
|
+
"button",
|
|
217
|
+
{
|
|
218
|
+
type: "button",
|
|
219
|
+
onClick: () => onOpenChange(false),
|
|
220
|
+
"aria-label": "Close dialog",
|
|
221
|
+
className: "absolute right-5 top-5 rounded-xl border border-white/10 bg-white/5 p-1.5 text-slate-400 hover:bg-white/10 hover:text-white transition cursor-pointer",
|
|
222
|
+
children: /* @__PURE__ */ jsx8("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx8("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
223
|
+
}
|
|
224
|
+
),
|
|
225
|
+
children
|
|
226
|
+
]
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
function DialogHeader({ children, className = "" }) {
|
|
233
|
+
return /* @__PURE__ */ jsx8("div", { className: ["mb-4 space-y-1.5", className].join(" "), children });
|
|
234
|
+
}
|
|
235
|
+
function DialogTitle({ children, className = "" }) {
|
|
236
|
+
return /* @__PURE__ */ jsx8("h2", { className: ["text-xl font-bold tracking-tight text-white", className].join(" "), children });
|
|
237
|
+
}
|
|
238
|
+
function DialogDescription({ children, className = "" }) {
|
|
239
|
+
return /* @__PURE__ */ jsx8("p", { className: ["text-sm text-slate-300 leading-relaxed", className].join(" "), children });
|
|
240
|
+
}
|
|
241
|
+
function DialogFooter({ children, className = "" }) {
|
|
242
|
+
return /* @__PURE__ */ jsx8("div", { className: ["mt-6 flex flex-wrap items-center justify-end gap-3", className].join(" "), children });
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/components/drawer.tsx
|
|
246
|
+
import { useEffect as useEffect2 } from "react";
|
|
247
|
+
import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
248
|
+
function Drawer({
|
|
249
|
+
open,
|
|
250
|
+
onOpenChange,
|
|
251
|
+
position = "right",
|
|
252
|
+
children,
|
|
253
|
+
className = ""
|
|
254
|
+
}) {
|
|
255
|
+
useEffect2(() => {
|
|
256
|
+
const handleKeyDown = (e) => {
|
|
257
|
+
if (e.key === "Escape" && open) onOpenChange(false);
|
|
258
|
+
};
|
|
259
|
+
if (open) {
|
|
260
|
+
document.body.style.overflow = "hidden";
|
|
261
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
262
|
+
} else {
|
|
263
|
+
document.body.style.overflow = "";
|
|
264
|
+
}
|
|
265
|
+
return () => {
|
|
266
|
+
document.body.style.overflow = "";
|
|
267
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
268
|
+
};
|
|
269
|
+
}, [open, onOpenChange]);
|
|
270
|
+
if (!open) return null;
|
|
271
|
+
const positionClasses = {
|
|
272
|
+
right: "inset-y-0 right-0 w-full max-w-md border-l border-white/10 animate-in slide-in-from-right duration-300",
|
|
273
|
+
left: "inset-y-0 left-0 w-full max-w-md border-r border-white/10 animate-in slide-in-from-left duration-300",
|
|
274
|
+
bottom: "inset-x-0 bottom-0 max-h-[85vh] w-full border-t border-white/10 rounded-t-3xl animate-in slide-in-from-bottom duration-300"
|
|
275
|
+
};
|
|
276
|
+
return /* @__PURE__ */ jsx9(
|
|
277
|
+
"div",
|
|
278
|
+
{
|
|
279
|
+
role: "dialog",
|
|
280
|
+
"aria-modal": "true",
|
|
281
|
+
className: "fixed inset-0 z-50 bg-slate-950/80 backdrop-blur-sm animate-in fade-in duration-200",
|
|
282
|
+
onClick: (e) => {
|
|
283
|
+
if (e.target === e.currentTarget) onOpenChange(false);
|
|
284
|
+
},
|
|
285
|
+
children: /* @__PURE__ */ jsxs4(
|
|
286
|
+
"div",
|
|
287
|
+
{
|
|
288
|
+
className: [
|
|
289
|
+
"fixed bg-slate-900/95 p-6 shadow-2xl text-white overflow-y-auto",
|
|
290
|
+
positionClasses[position],
|
|
291
|
+
className
|
|
292
|
+
].join(" "),
|
|
293
|
+
children: [
|
|
294
|
+
/* @__PURE__ */ jsx9(
|
|
295
|
+
"button",
|
|
296
|
+
{
|
|
297
|
+
type: "button",
|
|
298
|
+
onClick: () => onOpenChange(false),
|
|
299
|
+
"aria-label": "Close drawer",
|
|
300
|
+
className: "absolute right-5 top-5 rounded-xl border border-white/10 bg-white/5 p-1.5 text-slate-400 hover:bg-white/10 hover:text-white transition cursor-pointer",
|
|
301
|
+
children: /* @__PURE__ */ jsx9("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
302
|
+
}
|
|
303
|
+
),
|
|
304
|
+
children
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
function DrawerHeader({ children, className = "" }) {
|
|
312
|
+
return /* @__PURE__ */ jsx9("div", { className: ["mb-6 space-y-1.5", className].join(" "), children });
|
|
313
|
+
}
|
|
314
|
+
function DrawerTitle({ children, className = "" }) {
|
|
315
|
+
return /* @__PURE__ */ jsx9("h2", { className: ["text-xl font-bold tracking-tight text-white", className].join(" "), children });
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// src/components/dropdown-menu.tsx
|
|
319
|
+
import { useState as useState2, useRef as useRef2, useEffect as useEffect3 } from "react";
|
|
320
|
+
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
321
|
+
function DropdownMenu({
|
|
322
|
+
trigger,
|
|
323
|
+
items,
|
|
324
|
+
align = "right",
|
|
325
|
+
className = ""
|
|
326
|
+
}) {
|
|
327
|
+
const [open, setOpen] = useState2(false);
|
|
328
|
+
const menuRef = useRef2(null);
|
|
329
|
+
useEffect3(() => {
|
|
330
|
+
const handleClickOutside = (e) => {
|
|
331
|
+
if (menuRef.current && !menuRef.current.contains(e.target)) {
|
|
332
|
+
setOpen(false);
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
if (open) {
|
|
336
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
337
|
+
}
|
|
338
|
+
return () => {
|
|
339
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
340
|
+
};
|
|
341
|
+
}, [open]);
|
|
342
|
+
return /* @__PURE__ */ jsxs5("div", { ref: menuRef, className: "relative inline-block text-left", children: [
|
|
343
|
+
/* @__PURE__ */ jsx10("div", { onClick: () => setOpen(!open), className: "cursor-pointer", children: trigger }),
|
|
344
|
+
open && /* @__PURE__ */ jsx10(
|
|
345
|
+
"div",
|
|
346
|
+
{
|
|
347
|
+
role: "menu",
|
|
348
|
+
className: [
|
|
349
|
+
"absolute z-50 mt-2 min-w-[12rem] rounded-2xl border border-white/10 bg-slate-900/95 p-1.5 shadow-2xl backdrop-blur-xl animate-in fade-in zoom-in-95 duration-150",
|
|
350
|
+
align === "right" ? "right-0" : "left-0",
|
|
351
|
+
className
|
|
352
|
+
].join(" "),
|
|
353
|
+
children: items.map((item) => /* @__PURE__ */ jsxs5(
|
|
354
|
+
"button",
|
|
355
|
+
{
|
|
356
|
+
type: "button",
|
|
357
|
+
role: "menuitem",
|
|
358
|
+
disabled: item.disabled,
|
|
359
|
+
onClick: () => {
|
|
360
|
+
if (!item.disabled) {
|
|
361
|
+
item.onClick?.();
|
|
362
|
+
setOpen(false);
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
className: [
|
|
366
|
+
"flex w-full items-center gap-2.5 rounded-xl px-3 py-2 text-xs font-medium transition cursor-pointer text-left",
|
|
367
|
+
item.disabled ? "opacity-40 cursor-not-allowed text-slate-400" : item.destructive ? "text-rose-400 hover:bg-rose-500/10 hover:text-rose-300" : "text-slate-200 hover:bg-white/10 hover:text-white"
|
|
368
|
+
].join(" "),
|
|
369
|
+
children: [
|
|
370
|
+
item.icon && /* @__PURE__ */ jsx10("span", { className: "h-4 w-4 shrink-0", children: item.icon }),
|
|
371
|
+
/* @__PURE__ */ jsx10("span", { className: "flex-1", children: item.label })
|
|
372
|
+
]
|
|
373
|
+
},
|
|
374
|
+
item.id
|
|
375
|
+
))
|
|
376
|
+
}
|
|
377
|
+
)
|
|
378
|
+
] });
|
|
379
|
+
}
|
|
380
|
+
|
|
125
381
|
// src/components/input.tsx
|
|
126
|
-
import { jsx as
|
|
382
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
127
383
|
function Input({ className = "", ...props }) {
|
|
128
|
-
return /* @__PURE__ */
|
|
384
|
+
return /* @__PURE__ */ jsx11(
|
|
129
385
|
"input",
|
|
130
386
|
{
|
|
131
387
|
...props,
|
|
@@ -137,10 +393,58 @@ function Input({ className = "", ...props }) {
|
|
|
137
393
|
);
|
|
138
394
|
}
|
|
139
395
|
|
|
396
|
+
// src/components/progress.tsx
|
|
397
|
+
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
398
|
+
var variantGradients = {
|
|
399
|
+
primary: "from-violet-600 to-indigo-500",
|
|
400
|
+
secondary: "from-cyan-500 to-blue-500",
|
|
401
|
+
success: "from-emerald-500 to-teal-400",
|
|
402
|
+
warning: "from-amber-500 to-orange-400"
|
|
403
|
+
};
|
|
404
|
+
function Progress({
|
|
405
|
+
value = 0,
|
|
406
|
+
max = 100,
|
|
407
|
+
variant = "primary",
|
|
408
|
+
showLabel = false,
|
|
409
|
+
className = "",
|
|
410
|
+
...props
|
|
411
|
+
}) {
|
|
412
|
+
const percentage = Math.min(Math.max(value / max * 100, 0), 100);
|
|
413
|
+
return /* @__PURE__ */ jsxs6("div", { className: ["w-full space-y-1.5", className].join(" "), ...props, children: [
|
|
414
|
+
showLabel && /* @__PURE__ */ jsxs6("div", { className: "flex justify-between text-xs font-semibold text-slate-300", children: [
|
|
415
|
+
/* @__PURE__ */ jsx12("span", { children: "Progress" }),
|
|
416
|
+
/* @__PURE__ */ jsxs6("span", { className: "font-mono", children: [
|
|
417
|
+
Math.round(percentage),
|
|
418
|
+
"%"
|
|
419
|
+
] })
|
|
420
|
+
] }),
|
|
421
|
+
/* @__PURE__ */ jsx12(
|
|
422
|
+
"div",
|
|
423
|
+
{
|
|
424
|
+
role: "progressbar",
|
|
425
|
+
"aria-valuenow": value,
|
|
426
|
+
"aria-valuemin": 0,
|
|
427
|
+
"aria-valuemax": max,
|
|
428
|
+
className: "relative h-2.5 w-full overflow-hidden rounded-full bg-slate-800 ring-1 ring-white/10",
|
|
429
|
+
children: /* @__PURE__ */ jsx12(
|
|
430
|
+
"div",
|
|
431
|
+
{
|
|
432
|
+
className: [
|
|
433
|
+
"h-full rounded-full bg-gradient-to-r transition-all duration-300 ease-out shadow-sm",
|
|
434
|
+
variantGradients[variant]
|
|
435
|
+
].join(" "),
|
|
436
|
+
style: { width: `${percentage}%` }
|
|
437
|
+
}
|
|
438
|
+
)
|
|
439
|
+
}
|
|
440
|
+
)
|
|
441
|
+
] });
|
|
442
|
+
}
|
|
443
|
+
|
|
140
444
|
// src/components/select.tsx
|
|
141
|
-
import { jsx as
|
|
445
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
142
446
|
function Select({ className = "", children, ...props }) {
|
|
143
|
-
return /* @__PURE__ */
|
|
447
|
+
return /* @__PURE__ */ jsx13(
|
|
144
448
|
"select",
|
|
145
449
|
{
|
|
146
450
|
...props,
|
|
@@ -154,7 +458,7 @@ function Select({ className = "", children, ...props }) {
|
|
|
154
458
|
}
|
|
155
459
|
|
|
156
460
|
// src/components/skeleton.tsx
|
|
157
|
-
import { jsx as
|
|
461
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
158
462
|
var roundedClasses = {
|
|
159
463
|
sm: "rounded-md",
|
|
160
464
|
md: "rounded-xl",
|
|
@@ -162,7 +466,7 @@ var roundedClasses = {
|
|
|
162
466
|
full: "rounded-full"
|
|
163
467
|
};
|
|
164
468
|
function Skeleton({ className = "", rounded = "md", ...props }) {
|
|
165
|
-
return /* @__PURE__ */
|
|
469
|
+
return /* @__PURE__ */ jsx14(
|
|
166
470
|
"div",
|
|
167
471
|
{
|
|
168
472
|
...props,
|
|
@@ -172,15 +476,54 @@ function Skeleton({ className = "", rounded = "md", ...props }) {
|
|
|
172
476
|
);
|
|
173
477
|
}
|
|
174
478
|
|
|
479
|
+
// src/components/switch.tsx
|
|
480
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
481
|
+
function Switch({
|
|
482
|
+
checked,
|
|
483
|
+
defaultChecked = false,
|
|
484
|
+
onCheckedChange,
|
|
485
|
+
disabled = false,
|
|
486
|
+
className = "",
|
|
487
|
+
id,
|
|
488
|
+
"aria-label": ariaLabel
|
|
489
|
+
}) {
|
|
490
|
+
return /* @__PURE__ */ jsx15(
|
|
491
|
+
"button",
|
|
492
|
+
{
|
|
493
|
+
type: "button",
|
|
494
|
+
role: "switch",
|
|
495
|
+
id,
|
|
496
|
+
"aria-label": ariaLabel,
|
|
497
|
+
"aria-checked": checked ?? defaultChecked,
|
|
498
|
+
disabled,
|
|
499
|
+
onClick: () => onCheckedChange?.(!checked),
|
|
500
|
+
className: [
|
|
501
|
+
"relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-2 focus-visible:ring-offset-slate-950 disabled:cursor-not-allowed disabled:opacity-50",
|
|
502
|
+
checked ?? defaultChecked ? "bg-violet-600" : "bg-slate-800",
|
|
503
|
+
className
|
|
504
|
+
].join(" "),
|
|
505
|
+
children: /* @__PURE__ */ jsx15(
|
|
506
|
+
"span",
|
|
507
|
+
{
|
|
508
|
+
className: [
|
|
509
|
+
"pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out",
|
|
510
|
+
checked ?? defaultChecked ? "translate-x-5" : "translate-x-0"
|
|
511
|
+
].join(" ")
|
|
512
|
+
}
|
|
513
|
+
)
|
|
514
|
+
}
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
|
|
175
518
|
// src/components/tabs.tsx
|
|
176
|
-
import { useState } from "react";
|
|
177
|
-
import { jsx as
|
|
519
|
+
import { useState as useState3 } from "react";
|
|
520
|
+
import { jsx as jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
178
521
|
function Tabs({ items, defaultTab, className = "" }) {
|
|
179
522
|
const initialTab = defaultTab ?? items[0]?.id ?? "";
|
|
180
|
-
const [activeTab, setActiveTab] =
|
|
523
|
+
const [activeTab, setActiveTab] = useState3(initialTab);
|
|
181
524
|
const activeItem = items.find((item) => item.id === activeTab) ?? items[0];
|
|
182
|
-
return /* @__PURE__ */
|
|
183
|
-
/* @__PURE__ */
|
|
525
|
+
return /* @__PURE__ */ jsxs7("div", { className, children: [
|
|
526
|
+
/* @__PURE__ */ jsx16("div", { className: "mb-4 flex flex-wrap gap-2", children: items.map((item) => /* @__PURE__ */ jsx16(
|
|
184
527
|
"button",
|
|
185
528
|
{
|
|
186
529
|
type: "button",
|
|
@@ -193,14 +536,14 @@ function Tabs({ items, defaultTab, className = "" }) {
|
|
|
193
536
|
},
|
|
194
537
|
item.id
|
|
195
538
|
)) }),
|
|
196
|
-
/* @__PURE__ */
|
|
539
|
+
/* @__PURE__ */ jsx16("div", { className: "rounded-2xl border border-white/10 bg-slate-950/60 p-4 text-sm text-slate-200", children: activeItem?.content })
|
|
197
540
|
] });
|
|
198
541
|
}
|
|
199
542
|
|
|
200
543
|
// src/components/textarea.tsx
|
|
201
|
-
import { jsx as
|
|
544
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
202
545
|
function Textarea({ className = "", ...props }) {
|
|
203
|
-
return /* @__PURE__ */
|
|
546
|
+
return /* @__PURE__ */ jsx17(
|
|
204
547
|
"textarea",
|
|
205
548
|
{
|
|
206
549
|
...props,
|
|
@@ -212,6 +555,130 @@ function Textarea({ className = "", ...props }) {
|
|
|
212
555
|
);
|
|
213
556
|
}
|
|
214
557
|
|
|
558
|
+
// src/components/toast.tsx
|
|
559
|
+
import { useState as useState4, useEffect as useEffect4 } from "react";
|
|
560
|
+
import { jsx as jsx18, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
561
|
+
var toasts = [];
|
|
562
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
563
|
+
function notify() {
|
|
564
|
+
listeners.forEach((l) => l([...toasts]));
|
|
565
|
+
}
|
|
566
|
+
var toast = {
|
|
567
|
+
show(message, options) {
|
|
568
|
+
const id = Math.random().toString(36).substring(2, 9);
|
|
569
|
+
const newToast = {
|
|
570
|
+
id,
|
|
571
|
+
message,
|
|
572
|
+
type: options?.type || "info",
|
|
573
|
+
title: options?.title,
|
|
574
|
+
duration: options?.duration || 4e3
|
|
575
|
+
};
|
|
576
|
+
toasts = [...toasts, newToast];
|
|
577
|
+
notify();
|
|
578
|
+
setTimeout(() => {
|
|
579
|
+
toast.dismiss(id);
|
|
580
|
+
}, newToast.duration);
|
|
581
|
+
return id;
|
|
582
|
+
},
|
|
583
|
+
success(message, title) {
|
|
584
|
+
return toast.show(message, { type: "success", title });
|
|
585
|
+
},
|
|
586
|
+
error(message, title) {
|
|
587
|
+
return toast.show(message, { type: "error", title });
|
|
588
|
+
},
|
|
589
|
+
info(message, title) {
|
|
590
|
+
return toast.show(message, { type: "info", title });
|
|
591
|
+
},
|
|
592
|
+
dismiss(id) {
|
|
593
|
+
toasts = toasts.filter((t) => t.id !== id);
|
|
594
|
+
notify();
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
function Toaster() {
|
|
598
|
+
const [activeToasts, setActiveToasts] = useState4([]);
|
|
599
|
+
useEffect4(() => {
|
|
600
|
+
listeners.add(setActiveToasts);
|
|
601
|
+
return () => {
|
|
602
|
+
listeners.delete(setActiveToasts);
|
|
603
|
+
};
|
|
604
|
+
}, []);
|
|
605
|
+
if (activeToasts.length === 0) return null;
|
|
606
|
+
const typeStyles = {
|
|
607
|
+
success: "border-emerald-500/40 bg-slate-900/95 text-emerald-100 shadow-emerald-500/10",
|
|
608
|
+
error: "border-rose-500/40 bg-slate-900/95 text-rose-100 shadow-rose-500/10",
|
|
609
|
+
info: "border-cyan-500/40 bg-slate-900/95 text-cyan-100 shadow-cyan-500/10",
|
|
610
|
+
warning: "border-amber-500/40 bg-slate-900/95 text-amber-100 shadow-amber-500/10"
|
|
611
|
+
};
|
|
612
|
+
return /* @__PURE__ */ jsx18("div", { className: "fixed bottom-5 right-5 z-50 flex flex-col gap-2.5 max-w-sm w-full pointer-events-none", children: activeToasts.map((t) => /* @__PURE__ */ jsxs8(
|
|
613
|
+
"div",
|
|
614
|
+
{
|
|
615
|
+
className: [
|
|
616
|
+
"pointer-events-auto flex items-start justify-between rounded-2xl border p-4 shadow-xl backdrop-blur-md animate-in slide-in-from-bottom-5 duration-200",
|
|
617
|
+
typeStyles[t.type || "info"]
|
|
618
|
+
].join(" "),
|
|
619
|
+
children: [
|
|
620
|
+
/* @__PURE__ */ jsxs8("div", { className: "space-y-1", children: [
|
|
621
|
+
t.title && /* @__PURE__ */ jsx18("p", { className: "font-semibold text-xs tracking-wide uppercase text-white", children: t.title }),
|
|
622
|
+
/* @__PURE__ */ jsx18("p", { className: "text-sm font-medium", children: t.message })
|
|
623
|
+
] }),
|
|
624
|
+
/* @__PURE__ */ jsx18(
|
|
625
|
+
"button",
|
|
626
|
+
{
|
|
627
|
+
type: "button",
|
|
628
|
+
onClick: () => toast.dismiss(t.id),
|
|
629
|
+
className: "ml-3 text-slate-400 hover:text-white transition cursor-pointer",
|
|
630
|
+
children: "\xD7"
|
|
631
|
+
}
|
|
632
|
+
)
|
|
633
|
+
]
|
|
634
|
+
},
|
|
635
|
+
t.id
|
|
636
|
+
)) });
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// src/components/tooltip.tsx
|
|
640
|
+
import { useState as useState5 } from "react";
|
|
641
|
+
import { jsx as jsx19, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
642
|
+
function Tooltip({
|
|
643
|
+
content,
|
|
644
|
+
children,
|
|
645
|
+
side = "top",
|
|
646
|
+
className = ""
|
|
647
|
+
}) {
|
|
648
|
+
const [isVisible, setIsVisible] = useState5(false);
|
|
649
|
+
const sideClasses = {
|
|
650
|
+
top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
|
|
651
|
+
bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
|
|
652
|
+
left: "right-full top-1/2 -translate-y-1/2 mr-2",
|
|
653
|
+
right: "left-full top-1/2 -translate-y-1/2 ml-2"
|
|
654
|
+
};
|
|
655
|
+
return /* @__PURE__ */ jsxs9(
|
|
656
|
+
"div",
|
|
657
|
+
{
|
|
658
|
+
className: "relative inline-flex",
|
|
659
|
+
onMouseEnter: () => setIsVisible(true),
|
|
660
|
+
onMouseLeave: () => setIsVisible(false),
|
|
661
|
+
onFocus: () => setIsVisible(true),
|
|
662
|
+
onBlur: () => setIsVisible(false),
|
|
663
|
+
children: [
|
|
664
|
+
children,
|
|
665
|
+
isVisible && /* @__PURE__ */ jsx19(
|
|
666
|
+
"div",
|
|
667
|
+
{
|
|
668
|
+
role: "tooltip",
|
|
669
|
+
className: [
|
|
670
|
+
"absolute z-50 whitespace-nowrap rounded-lg border border-white/10 bg-slate-900/95 px-2.5 py-1 text-xs font-medium text-slate-200 shadow-xl backdrop-blur-md animate-in fade-in zoom-in-95 duration-150 pointer-events-none",
|
|
671
|
+
sideClasses[side],
|
|
672
|
+
className
|
|
673
|
+
].join(" "),
|
|
674
|
+
children: content
|
|
675
|
+
}
|
|
676
|
+
)
|
|
677
|
+
]
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
|
|
215
682
|
// src/tokens/index.ts
|
|
216
683
|
var themeTokens = {
|
|
217
684
|
colors: {
|
|
@@ -229,17 +696,32 @@ var themeTokens = {
|
|
|
229
696
|
};
|
|
230
697
|
var cx = (...classes) => classes.filter(Boolean).join(" ");
|
|
231
698
|
export {
|
|
699
|
+
Accordion,
|
|
232
700
|
Alert,
|
|
233
701
|
Avatar,
|
|
234
702
|
Badge,
|
|
235
703
|
Button,
|
|
236
704
|
Card,
|
|
237
705
|
Checkbox,
|
|
706
|
+
Dialog,
|
|
707
|
+
DialogDescription,
|
|
708
|
+
DialogFooter,
|
|
709
|
+
DialogHeader,
|
|
710
|
+
DialogTitle,
|
|
711
|
+
Drawer,
|
|
712
|
+
DrawerHeader,
|
|
713
|
+
DrawerTitle,
|
|
714
|
+
DropdownMenu,
|
|
238
715
|
Input,
|
|
716
|
+
Progress,
|
|
239
717
|
Select,
|
|
240
718
|
Skeleton,
|
|
719
|
+
Switch,
|
|
241
720
|
Tabs,
|
|
242
721
|
Textarea,
|
|
722
|
+
Toaster,
|
|
723
|
+
Tooltip,
|
|
243
724
|
cx,
|
|
244
|
-
themeTokens
|
|
725
|
+
themeTokens,
|
|
726
|
+
toast
|
|
245
727
|
};
|