@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/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__ */ jsx(
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 jsx2 } from "react/jsx-runtime";
20
- var variantClasses = {
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 sizeClasses = {
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({ variant = "primary", size = "md", className = "", ...props }) {
32
- return /* @__PURE__ */ jsx2(
33
- "button",
34
- {
35
- ...props,
36
- className: [
37
- "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",
38
- variantClasses[variant],
39
- sizeClasses[size],
40
- className
41
- ].join(" ")
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 jsx3 } from "react/jsx-runtime";
147
+ import { jsx as jsx6 } from "react/jsx-runtime";
48
148
  function Card({ as: Component = "div", className = "", ...props }) {
49
- return /* @__PURE__ */ jsx3(
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 jsx4 } from "react/jsx-runtime";
382
+ import { jsx as jsx11 } from "react/jsx-runtime";
63
383
  function Input({ className = "", ...props }) {
64
- return /* @__PURE__ */ jsx4(
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
  };