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