@stackvibe-studio/ui 0.2.0 → 0.3.0

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