@stackvibe-studio/ui 0.1.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 +66 -0
- package/dist/components/accordion.d.ts +13 -0
- package/dist/components/alert.d.ts +7 -0
- package/dist/components/avatar.d.ts +6 -0
- package/dist/components/button.d.ts +14 -3
- package/dist/components/checkbox.d.ts +4 -0
- 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/index.d.ts +7 -0
- package/dist/components/progress.d.ts +8 -0
- package/dist/components/select.d.ts +4 -0
- package/dist/components/skeleton.d.ts +5 -0
- package/dist/components/switch.d.ts +10 -0
- package/dist/components/tabs.d.ts +12 -0
- package/dist/components/textarea.d.ts +4 -0
- package/dist/components/toast.d.ts +15 -0
- package/dist/components/tooltip.d.ts +8 -0
- package/dist/index.cjs +673 -24
- package/dist/index.d.ts +15 -0
- package/dist/index.js +651 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/components/accordion.tsx
|
|
4
|
+
import { useState } from "react";
|
|
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";
|
|
54
|
+
var variantClasses = {
|
|
55
|
+
info: "border-cyan-500/40 bg-cyan-500/10 text-cyan-50",
|
|
56
|
+
success: "border-emerald-500/40 bg-emerald-500/10 text-emerald-50",
|
|
57
|
+
warning: "border-amber-500/40 bg-amber-500/10 text-amber-50",
|
|
58
|
+
danger: "border-rose-500/40 bg-rose-500/10 text-rose-50"
|
|
59
|
+
};
|
|
60
|
+
function Alert({ title, variant = "info", className = "", children, ...props }) {
|
|
61
|
+
return /* @__PURE__ */ jsxs2(
|
|
62
|
+
"div",
|
|
63
|
+
{
|
|
64
|
+
...props,
|
|
65
|
+
className: ["rounded-2xl border p-4 text-sm", variantClasses[variant], className].join(" "),
|
|
66
|
+
role: "alert",
|
|
67
|
+
children: [
|
|
68
|
+
title ? /* @__PURE__ */ jsx2("p", { className: "mb-1 font-medium", children: title }) : null,
|
|
69
|
+
/* @__PURE__ */ jsx2("div", { children })
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/components/avatar.tsx
|
|
76
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
77
|
+
var sizeClasses = {
|
|
78
|
+
sm: "h-9 w-9 text-xs",
|
|
79
|
+
md: "h-12 w-12 text-sm",
|
|
80
|
+
lg: "h-16 w-16 text-base"
|
|
81
|
+
};
|
|
82
|
+
function Avatar({ src, alt = "avatar", fallback = "SV", size = "md", className = "", ...props }) {
|
|
83
|
+
return src ? /* @__PURE__ */ jsx3(
|
|
84
|
+
"img",
|
|
85
|
+
{
|
|
86
|
+
...props,
|
|
87
|
+
src,
|
|
88
|
+
alt,
|
|
89
|
+
className: ["rounded-full object-cover ring-1 ring-white/10", sizeClasses[size], className].join(" ")
|
|
90
|
+
}
|
|
91
|
+
) : /* @__PURE__ */ jsx3(
|
|
92
|
+
"div",
|
|
93
|
+
{
|
|
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(" "),
|
|
95
|
+
children: fallback
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
1
100
|
// src/components/badge.tsx
|
|
2
|
-
import { jsx } from "react/jsx-runtime";
|
|
101
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
3
102
|
var variants = {
|
|
4
103
|
primary: "bg-violet-500/20 text-violet-200 ring-1 ring-violet-400/20",
|
|
5
104
|
secondary: "bg-cyan-500/15 text-cyan-200 ring-1 ring-cyan-400/20",
|
|
6
105
|
outline: "bg-transparent text-slate-200 ring-1 ring-white/10"
|
|
7
106
|
};
|
|
8
107
|
function Badge({ variant = "primary", className = "", ...props }) {
|
|
9
|
-
return /* @__PURE__ */
|
|
108
|
+
return /* @__PURE__ */ jsx4(
|
|
10
109
|
"span",
|
|
11
110
|
{
|
|
12
111
|
...props,
|
|
@@ -16,37 +115,38 @@ function Badge({ variant = "primary", className = "", ...props }) {
|
|
|
16
115
|
}
|
|
17
116
|
|
|
18
117
|
// src/components/button.tsx
|
|
19
|
-
import { jsx as
|
|
20
|
-
var
|
|
118
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
119
|
+
var variantClasses2 = {
|
|
21
120
|
primary: "bg-violet-500 text-white hover:bg-violet-400",
|
|
22
121
|
secondary: "bg-cyan-500 text-slate-950 hover:bg-cyan-400",
|
|
23
122
|
ghost: "bg-white/5 text-white hover:bg-white/10",
|
|
24
123
|
outline: "border border-white/15 bg-transparent text-white hover:bg-white/5"
|
|
25
124
|
};
|
|
26
|
-
var
|
|
125
|
+
var sizeClasses2 = {
|
|
27
126
|
sm: "px-3 py-1.5 text-sm",
|
|
28
127
|
md: "px-4 py-2 text-sm",
|
|
29
128
|
lg: "px-5 py-3 text-base"
|
|
30
129
|
};
|
|
31
|
-
function Button(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
130
|
+
function Button(props) {
|
|
131
|
+
const { as = "button", variant = "primary", size = "md", className = "", ...rest } = props;
|
|
132
|
+
const commonClassName = [
|
|
133
|
+
"inline-flex items-center justify-center rounded-xl font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400",
|
|
134
|
+
variantClasses2[variant],
|
|
135
|
+
sizeClasses2[size],
|
|
136
|
+
className
|
|
137
|
+
].join(" ");
|
|
138
|
+
if (as === "a") {
|
|
139
|
+
const { href, ...anchorProps } = rest;
|
|
140
|
+
return /* @__PURE__ */ jsx5("a", { ...anchorProps, href, className: commonClassName });
|
|
141
|
+
}
|
|
142
|
+
const { type = "button", ...buttonProps } = rest;
|
|
143
|
+
return /* @__PURE__ */ jsx5("button", { ...buttonProps, type, className: commonClassName });
|
|
44
144
|
}
|
|
45
145
|
|
|
46
146
|
// src/components/card.tsx
|
|
47
|
-
import { jsx as
|
|
147
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
48
148
|
function Card({ as: Component = "div", className = "", ...props }) {
|
|
49
|
-
return /* @__PURE__ */
|
|
149
|
+
return /* @__PURE__ */ jsx6(
|
|
50
150
|
Component,
|
|
51
151
|
{
|
|
52
152
|
...props,
|
|
@@ -58,10 +158,230 @@ function Card({ as: Component = "div", className = "", ...props }) {
|
|
|
58
158
|
);
|
|
59
159
|
}
|
|
60
160
|
|
|
161
|
+
// src/components/checkbox.tsx
|
|
162
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
163
|
+
function Checkbox({ className = "", ...props }) {
|
|
164
|
+
return /* @__PURE__ */ jsx7(
|
|
165
|
+
"input",
|
|
166
|
+
{
|
|
167
|
+
...props,
|
|
168
|
+
type: "checkbox",
|
|
169
|
+
className: ["h-4 w-4 rounded border border-white/20 bg-slate-900 text-violet-500 focus:ring-violet-400/40", className].join(" ")
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}
|
|
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
|
+
|
|
61
381
|
// src/components/input.tsx
|
|
62
|
-
import { jsx as
|
|
382
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
63
383
|
function Input({ className = "", ...props }) {
|
|
64
|
-
return /* @__PURE__ */
|
|
384
|
+
return /* @__PURE__ */ jsx11(
|
|
65
385
|
"input",
|
|
66
386
|
{
|
|
67
387
|
...props,
|
|
@@ -73,6 +393,292 @@ function Input({ className = "", ...props }) {
|
|
|
73
393
|
);
|
|
74
394
|
}
|
|
75
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
|
+
|
|
444
|
+
// src/components/select.tsx
|
|
445
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
446
|
+
function Select({ className = "", children, ...props }) {
|
|
447
|
+
return /* @__PURE__ */ jsx13(
|
|
448
|
+
"select",
|
|
449
|
+
{
|
|
450
|
+
...props,
|
|
451
|
+
className: [
|
|
452
|
+
"w-full rounded-xl border border-white/10 bg-slate-900 px-3 py-2 text-sm text-white focus:border-violet-400 focus:outline-none focus:ring-2 focus:ring-violet-400/30",
|
|
453
|
+
className
|
|
454
|
+
].join(" "),
|
|
455
|
+
children
|
|
456
|
+
}
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// src/components/skeleton.tsx
|
|
461
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
462
|
+
var roundedClasses = {
|
|
463
|
+
sm: "rounded-md",
|
|
464
|
+
md: "rounded-xl",
|
|
465
|
+
lg: "rounded-2xl",
|
|
466
|
+
full: "rounded-full"
|
|
467
|
+
};
|
|
468
|
+
function Skeleton({ className = "", rounded = "md", ...props }) {
|
|
469
|
+
return /* @__PURE__ */ jsx14(
|
|
470
|
+
"div",
|
|
471
|
+
{
|
|
472
|
+
...props,
|
|
473
|
+
className: ["animate-pulse bg-slate-700/70", roundedClasses[rounded], className].join(" "),
|
|
474
|
+
"aria-hidden": "true"
|
|
475
|
+
}
|
|
476
|
+
);
|
|
477
|
+
}
|
|
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
|
+
|
|
518
|
+
// src/components/tabs.tsx
|
|
519
|
+
import { useState as useState3 } from "react";
|
|
520
|
+
import { jsx as jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
521
|
+
function Tabs({ items, defaultTab, className = "" }) {
|
|
522
|
+
const initialTab = defaultTab ?? items[0]?.id ?? "";
|
|
523
|
+
const [activeTab, setActiveTab] = useState3(initialTab);
|
|
524
|
+
const activeItem = items.find((item) => item.id === activeTab) ?? items[0];
|
|
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(
|
|
527
|
+
"button",
|
|
528
|
+
{
|
|
529
|
+
type: "button",
|
|
530
|
+
onClick: () => setActiveTab(item.id),
|
|
531
|
+
className: [
|
|
532
|
+
"rounded-full px-3 py-1.5 text-sm transition",
|
|
533
|
+
item.id === activeItem?.id ? "bg-violet-500 text-white shadow-lg shadow-violet-500/20" : "bg-slate-800 text-slate-300 hover:bg-slate-700 hover:text-white"
|
|
534
|
+
].join(" "),
|
|
535
|
+
children: item.label
|
|
536
|
+
},
|
|
537
|
+
item.id
|
|
538
|
+
)) }),
|
|
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 })
|
|
540
|
+
] });
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// src/components/textarea.tsx
|
|
544
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
545
|
+
function Textarea({ className = "", ...props }) {
|
|
546
|
+
return /* @__PURE__ */ jsx17(
|
|
547
|
+
"textarea",
|
|
548
|
+
{
|
|
549
|
+
...props,
|
|
550
|
+
className: [
|
|
551
|
+
"w-full rounded-xl border border-white/10 bg-slate-900 px-3 py-2 text-sm text-white placeholder:text-slate-400 focus:border-violet-400 focus:outline-none focus:ring-2 focus:ring-violet-400/30",
|
|
552
|
+
className
|
|
553
|
+
].join(" ")
|
|
554
|
+
}
|
|
555
|
+
);
|
|
556
|
+
}
|
|
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
|
+
|
|
76
682
|
// src/tokens/index.ts
|
|
77
683
|
var themeTokens = {
|
|
78
684
|
colors: {
|
|
@@ -90,10 +696,32 @@ var themeTokens = {
|
|
|
90
696
|
};
|
|
91
697
|
var cx = (...classes) => classes.filter(Boolean).join(" ");
|
|
92
698
|
export {
|
|
699
|
+
Accordion,
|
|
700
|
+
Alert,
|
|
701
|
+
Avatar,
|
|
93
702
|
Badge,
|
|
94
703
|
Button,
|
|
95
704
|
Card,
|
|
705
|
+
Checkbox,
|
|
706
|
+
Dialog,
|
|
707
|
+
DialogDescription,
|
|
708
|
+
DialogFooter,
|
|
709
|
+
DialogHeader,
|
|
710
|
+
DialogTitle,
|
|
711
|
+
Drawer,
|
|
712
|
+
DrawerHeader,
|
|
713
|
+
DrawerTitle,
|
|
714
|
+
DropdownMenu,
|
|
96
715
|
Input,
|
|
716
|
+
Progress,
|
|
717
|
+
Select,
|
|
718
|
+
Skeleton,
|
|
719
|
+
Switch,
|
|
720
|
+
Tabs,
|
|
721
|
+
Textarea,
|
|
722
|
+
Toaster,
|
|
723
|
+
Tooltip,
|
|
97
724
|
cx,
|
|
98
|
-
themeTokens
|
|
725
|
+
themeTokens,
|
|
726
|
+
toast
|
|
99
727
|
};
|