veloria-ui 0.1.2

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.
Files changed (41) hide show
  1. package/CHANGELOG.md +206 -0
  2. package/LICENSE +21 -0
  3. package/README.md +253 -0
  4. package/dist/cli/index.js +511 -0
  5. package/dist/index.d.mts +1317 -0
  6. package/dist/index.d.ts +1317 -0
  7. package/dist/index.js +5373 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/index.mjs +5130 -0
  10. package/dist/index.mjs.map +1 -0
  11. package/dist/provider.d.mts +15 -0
  12. package/dist/provider.d.ts +15 -0
  13. package/dist/provider.js +1197 -0
  14. package/dist/provider.js.map +1 -0
  15. package/dist/provider.mjs +1161 -0
  16. package/dist/provider.mjs.map +1 -0
  17. package/dist/tailwind.d.ts +25 -0
  18. package/dist/tailwind.js +129 -0
  19. package/package.json +138 -0
  20. package/src/cli/index.ts +303 -0
  21. package/src/cli/registry.ts +139 -0
  22. package/src/components/advanced-forms/index.tsx +975 -0
  23. package/src/components/basic/Button.tsx +135 -0
  24. package/src/components/basic/IconButton.tsx +69 -0
  25. package/src/components/basic/index.tsx +446 -0
  26. package/src/components/data-display/index.tsx +1158 -0
  27. package/src/components/feedback/index.tsx +1051 -0
  28. package/src/components/forms/index.tsx +476 -0
  29. package/src/components/layout/index.tsx +296 -0
  30. package/src/components/media/index.tsx +437 -0
  31. package/src/components/navigation/index.tsx +484 -0
  32. package/src/components/overlay/index.tsx +473 -0
  33. package/src/components/utility/index.tsx +566 -0
  34. package/src/hooks/index.ts +602 -0
  35. package/src/hooks/use-toast.tsx +74 -0
  36. package/src/index.ts +396 -0
  37. package/src/provider.tsx +54 -0
  38. package/src/styles/atlas.css +252 -0
  39. package/src/tailwind.ts +124 -0
  40. package/src/types/index.ts +95 -0
  41. package/src/utils/cn.ts +66 -0
@@ -0,0 +1,1161 @@
1
+ "use client";
2
+
3
+ // src/components/feedback/index.tsx
4
+ import * as React2 from "react";
5
+ import * as ToastPrimitive from "@radix-ui/react-toast";
6
+ import * as ProgressPrimitive from "@radix-ui/react-progress";
7
+ import { cva } from "class-variance-authority";
8
+
9
+ // src/utils/cn.ts
10
+ import { clsx } from "clsx";
11
+ import { twMerge } from "tailwind-merge";
12
+ import React from "react";
13
+ function cn(...inputs) {
14
+ return twMerge(clsx(inputs));
15
+ }
16
+
17
+ // src/components/feedback/index.tsx
18
+ import { jsx, jsxs } from "react/jsx-runtime";
19
+ var alertVariants = cva(
20
+ "atlas-alert relative w-full rounded-lg border p-4 [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:pl-7",
21
+ {
22
+ variants: {
23
+ variant: {
24
+ default: "bg-background text-foreground",
25
+ info: "border-info/30 bg-info/10 text-info-foreground [&>svg]:text-info",
26
+ success: "border-success/30 bg-success/10 text-success-foreground [&>svg]:text-success",
27
+ warning: "border-warning/30 bg-warning/10 text-warning-foreground [&>svg]:text-warning",
28
+ danger: "border-destructive/30 bg-destructive/10 text-destructive [&>svg]:text-destructive"
29
+ }
30
+ },
31
+ defaultVariants: { variant: "default" }
32
+ }
33
+ );
34
+ var Alert = React2.forwardRef(
35
+ ({ className, variant, icon, closable, onClose, children, ...props }, ref) => /* @__PURE__ */ jsxs("div", { ref, role: "alert", className: cn(alertVariants({ variant }), className), ...props, children: [
36
+ icon,
37
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
38
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children }),
39
+ closable && /* @__PURE__ */ jsx(
40
+ "button",
41
+ {
42
+ type: "button",
43
+ onClick: onClose,
44
+ className: "shrink-0 rounded-md p-0.5 text-current/50 hover:text-current transition-colors",
45
+ "aria-label": "Dismiss alert",
46
+ children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
47
+ }
48
+ )
49
+ ] })
50
+ ] })
51
+ );
52
+ Alert.displayName = "Alert";
53
+ var AlertTitle = React2.forwardRef(
54
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("h5", { ref, className: cn("mb-1 font-semibold leading-tight tracking-tight", className), ...props })
55
+ );
56
+ AlertTitle.displayName = "AlertTitle";
57
+ var AlertDescription = React2.forwardRef(
58
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", { ref, className: cn("text-sm leading-relaxed", className), ...props })
59
+ );
60
+ AlertDescription.displayName = "AlertDescription";
61
+ var ToastProvider = ToastPrimitive.Provider;
62
+ var ToastViewport = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
63
+ ToastPrimitive.Viewport,
64
+ {
65
+ ref,
66
+ className: cn(
67
+ "atlas-toast-viewport fixed bottom-4 right-4 z-[100] flex flex-col gap-2 w-full max-w-sm p-4",
68
+ className
69
+ ),
70
+ ...props
71
+ }
72
+ ));
73
+ ToastViewport.displayName = ToastPrimitive.Viewport.displayName;
74
+ var toastVariants = cva(
75
+ [
76
+ "group pointer-events-auto relative flex w-full items-start gap-3 overflow-hidden",
77
+ "rounded-lg border p-4 shadow-lg transition-all",
78
+ "data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)]",
79
+ "data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none",
80
+ "data-[state=open]:animate-in data-[state=open]:slide-in-from-bottom-full data-[state=open]:fade-in",
81
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=closed]:slide-out-to-right-full"
82
+ ],
83
+ {
84
+ variants: {
85
+ variant: {
86
+ default: "bg-background border-border",
87
+ success: "bg-success/10 border-success/20 text-success",
88
+ warning: "bg-warning/10 border-warning/20 text-warning",
89
+ danger: "bg-destructive/10 border-destructive/20 text-destructive",
90
+ info: "bg-info/10 border-info/20 text-info"
91
+ }
92
+ },
93
+ defaultVariants: { variant: "default" }
94
+ }
95
+ );
96
+ var Toast = React2.forwardRef(({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx(ToastPrimitive.Root, { ref, className: cn(toastVariants({ variant }), className), ...props }));
97
+ Toast.displayName = ToastPrimitive.Root.displayName;
98
+ var ToastTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(ToastPrimitive.Title, { ref, className: cn("text-sm font-semibold", className), ...props }));
99
+ ToastTitle.displayName = ToastPrimitive.Title.displayName;
100
+ var ToastDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(ToastPrimitive.Description, { ref, className: cn("text-sm opacity-80", className), ...props }));
101
+ ToastDescription.displayName = ToastPrimitive.Description.displayName;
102
+ var ToastClose = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
103
+ ToastPrimitive.Close,
104
+ {
105
+ ref,
106
+ "toast-close": "",
107
+ className: cn(
108
+ "ml-auto shrink-0 rounded-md p-0.5 opacity-50 hover:opacity-100 transition-opacity",
109
+ className
110
+ ),
111
+ "aria-label": "Close",
112
+ ...props,
113
+ children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
114
+ }
115
+ ));
116
+ ToastClose.displayName = ToastPrimitive.Close.displayName;
117
+ var ToastAction = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
118
+ ToastPrimitive.Action,
119
+ {
120
+ ref,
121
+ className: cn(
122
+ "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium",
123
+ "transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring",
124
+ "disabled:pointer-events-none disabled:opacity-50",
125
+ className
126
+ ),
127
+ ...props
128
+ }
129
+ ));
130
+ ToastAction.displayName = ToastPrimitive.Action.displayName;
131
+ var Snackbar = React2.forwardRef(
132
+ ({ className, open, message, action, variant = "default", position = "bottom-center", ...props }, ref) => {
133
+ if (!open) return null;
134
+ return /* @__PURE__ */ jsxs(
135
+ "div",
136
+ {
137
+ ref,
138
+ role: "status",
139
+ "aria-live": "polite",
140
+ className: cn(
141
+ "atlas-snackbar fixed z-50 flex items-center gap-4 rounded-lg px-4 py-3 shadow-lg",
142
+ "min-w-[280px] max-w-[480px]",
143
+ position === "bottom-center" && "bottom-4 left-1/2 -translate-x-1/2",
144
+ position === "bottom-left" && "bottom-4 left-4",
145
+ position === "bottom-right" && "bottom-4 right-4",
146
+ position === "top-center" && "top-4 left-1/2 -translate-x-1/2",
147
+ variant === "default" && "bg-foreground text-background",
148
+ variant === "success" && "bg-success text-success-foreground",
149
+ variant === "warning" && "bg-warning text-warning-foreground",
150
+ variant === "danger" && "bg-destructive text-destructive-foreground",
151
+ className
152
+ ),
153
+ ...props,
154
+ children: [
155
+ /* @__PURE__ */ jsx("p", { className: "flex-1 text-sm font-medium", children: message }),
156
+ action && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action })
157
+ ]
158
+ }
159
+ );
160
+ }
161
+ );
162
+ Snackbar.displayName = "Snackbar";
163
+ var Progress = React2.forwardRef(
164
+ ({ className, value, label, showValue, size = "md", color = "default", ...props }, ref) => /* @__PURE__ */ jsxs("div", { className: "atlas-progress w-full", children: [
165
+ (label || showValue) && /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-1.5", children: [
166
+ label && /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: label }),
167
+ showValue && /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
168
+ value ?? 0,
169
+ "%"
170
+ ] })
171
+ ] }),
172
+ /* @__PURE__ */ jsx(
173
+ ProgressPrimitive.Root,
174
+ {
175
+ ref,
176
+ className: cn(
177
+ "relative overflow-hidden rounded-full bg-secondary",
178
+ size === "sm" && "h-1.5",
179
+ size === "md" && "h-2.5",
180
+ size === "lg" && "h-4",
181
+ className
182
+ ),
183
+ ...props,
184
+ children: /* @__PURE__ */ jsx(
185
+ ProgressPrimitive.Indicator,
186
+ {
187
+ className: cn(
188
+ "h-full w-full flex-1 transition-all duration-500 ease-in-out",
189
+ color === "default" && "bg-primary",
190
+ color === "success" && "bg-success",
191
+ color === "warning" && "bg-warning",
192
+ color === "danger" && "bg-destructive"
193
+ ),
194
+ style: { transform: `translateX(-${100 - (value ?? 0)}%)` }
195
+ }
196
+ )
197
+ }
198
+ )
199
+ ] })
200
+ );
201
+ Progress.displayName = "Progress";
202
+ var CircularProgress = ({
203
+ value = 0,
204
+ size = 48,
205
+ thickness = 4,
206
+ showValue,
207
+ label,
208
+ color = "default",
209
+ indeterminate,
210
+ className,
211
+ ...props
212
+ }) => {
213
+ const radius = (size - thickness) / 2;
214
+ const circumference = 2 * Math.PI * radius;
215
+ const offset = circumference - value / 100 * circumference;
216
+ const colorMap = {
217
+ default: "stroke-primary",
218
+ success: "stroke-success",
219
+ warning: "stroke-warning",
220
+ danger: "stroke-destructive"
221
+ };
222
+ return /* @__PURE__ */ jsxs("div", { className: cn("atlas-circular-progress relative inline-flex items-center justify-center", className), children: [
223
+ /* @__PURE__ */ jsxs(
224
+ "svg",
225
+ {
226
+ width: size,
227
+ height: size,
228
+ viewBox: `0 0 ${size} ${size}`,
229
+ fill: "none",
230
+ className: indeterminate ? "animate-spin" : "",
231
+ role: "progressbar",
232
+ "aria-valuenow": indeterminate ? void 0 : value,
233
+ "aria-valuemin": 0,
234
+ "aria-valuemax": 100,
235
+ "aria-label": label,
236
+ ...props,
237
+ children: [
238
+ /* @__PURE__ */ jsx(
239
+ "circle",
240
+ {
241
+ cx: size / 2,
242
+ cy: size / 2,
243
+ r: radius,
244
+ strokeWidth: thickness,
245
+ className: "stroke-secondary"
246
+ }
247
+ ),
248
+ /* @__PURE__ */ jsx(
249
+ "circle",
250
+ {
251
+ cx: size / 2,
252
+ cy: size / 2,
253
+ r: radius,
254
+ strokeWidth: thickness,
255
+ strokeDasharray: circumference,
256
+ strokeDashoffset: indeterminate ? circumference * 0.75 : offset,
257
+ strokeLinecap: "round",
258
+ className: cn("transition-all duration-500", colorMap[color]),
259
+ transform: `rotate(-90 ${size / 2} ${size / 2})`
260
+ }
261
+ )
262
+ ]
263
+ }
264
+ ),
265
+ showValue && !indeterminate && /* @__PURE__ */ jsxs("span", { className: "absolute text-xs font-semibold", children: [
266
+ value,
267
+ "%"
268
+ ] })
269
+ ] });
270
+ };
271
+ CircularProgress.displayName = "CircularProgress";
272
+ var Skeleton = React2.forwardRef(
273
+ ({ className, variant = "rect", width, height, lines = 1, style, ...props }, ref) => {
274
+ if (variant === "text" && lines > 1) {
275
+ return /* @__PURE__ */ jsx("div", { className: cn("atlas-skeleton space-y-2", className), ref, ...props, children: Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ jsx(
276
+ "div",
277
+ {
278
+ className: "h-4 animate-pulse rounded bg-muted",
279
+ style: { width: i === lines - 1 ? "75%" : "100%" }
280
+ },
281
+ i
282
+ )) });
283
+ }
284
+ return /* @__PURE__ */ jsx(
285
+ "div",
286
+ {
287
+ ref,
288
+ className: cn(
289
+ "atlas-skeleton animate-pulse bg-muted",
290
+ variant === "circle" ? "rounded-full" : "rounded-md",
291
+ variant === "text" && "h-4",
292
+ className
293
+ ),
294
+ style: { width, height, ...style },
295
+ "aria-hidden": "true",
296
+ ...props
297
+ }
298
+ );
299
+ }
300
+ );
301
+ Skeleton.displayName = "Skeleton";
302
+ var spinnerSizes = { xs: 12, sm: 16, md: 24, lg: 32, xl: 48 };
303
+ var LoadingSpinner = ({ size = "md", label = "Loading", className, ...props }) => /* @__PURE__ */ jsxs(
304
+ "svg",
305
+ {
306
+ width: spinnerSizes[size],
307
+ height: spinnerSizes[size],
308
+ viewBox: "0 0 24 24",
309
+ fill: "none",
310
+ className: cn("atlas-loading-spinner animate-spin text-primary", className),
311
+ role: "status",
312
+ "aria-label": label,
313
+ ...props,
314
+ children: [
315
+ /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
316
+ /* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
317
+ ]
318
+ }
319
+ );
320
+ LoadingSpinner.displayName = "LoadingSpinner";
321
+ var EmptyState = React2.forwardRef(
322
+ ({ className, icon, title, description, action, ...props }, ref) => /* @__PURE__ */ jsxs(
323
+ "div",
324
+ {
325
+ ref,
326
+ className: cn(
327
+ "atlas-empty-state flex flex-col items-center justify-center gap-3 text-center py-16 px-6",
328
+ className
329
+ ),
330
+ ...props,
331
+ children: [
332
+ icon && /* @__PURE__ */ jsx("div", { className: "rounded-full bg-muted p-4 text-muted-foreground [&>svg]:h-8 [&>svg]:w-8", children: icon }),
333
+ /* @__PURE__ */ jsxs("div", { className: "max-w-xs", children: [
334
+ /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold", children: title }),
335
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: description })
336
+ ] }),
337
+ action && /* @__PURE__ */ jsx("div", { className: "mt-2", children: action })
338
+ ]
339
+ }
340
+ )
341
+ );
342
+ EmptyState.displayName = "EmptyState";
343
+ var statusColors = {
344
+ online: "bg-success",
345
+ offline: "bg-muted-foreground",
346
+ busy: "bg-destructive",
347
+ away: "bg-warning",
348
+ idle: "bg-warning/60"
349
+ };
350
+ var StatusIndicator = React2.forwardRef(
351
+ ({ className, status, label, pulse, size = "md", ...props }, ref) => /* @__PURE__ */ jsxs(
352
+ "span",
353
+ {
354
+ ref,
355
+ className: cn("atlas-status-indicator inline-flex items-center gap-1.5", className),
356
+ ...props,
357
+ children: [
358
+ /* @__PURE__ */ jsxs("span", { className: "relative inline-flex", children: [
359
+ /* @__PURE__ */ jsx("span", { className: cn(
360
+ "rounded-full",
361
+ statusColors[status],
362
+ size === "sm" && "h-1.5 w-1.5",
363
+ size === "md" && "h-2.5 w-2.5",
364
+ size === "lg" && "h-3.5 w-3.5"
365
+ ) }),
366
+ pulse && status === "online" && /* @__PURE__ */ jsx("span", { className: cn(
367
+ "absolute inline-flex rounded-full animate-ping opacity-75",
368
+ statusColors[status],
369
+ size === "sm" && "h-1.5 w-1.5",
370
+ size === "md" && "h-2.5 w-2.5",
371
+ size === "lg" && "h-3.5 w-3.5"
372
+ ) })
373
+ ] }),
374
+ label && /* @__PURE__ */ jsx("span", { className: "text-sm capitalize", children: label ?? status })
375
+ ]
376
+ }
377
+ )
378
+ );
379
+ StatusIndicator.displayName = "StatusIndicator";
380
+ var Notification = React2.forwardRef(
381
+ ({ className, title, description, avatar, icon, time, unread, onClose, ...props }, ref) => /* @__PURE__ */ jsxs(
382
+ "div",
383
+ {
384
+ ref,
385
+ role: "listitem",
386
+ className: cn(
387
+ "atlas-notification flex gap-3 p-4 transition-colors",
388
+ unread && "bg-primary/5",
389
+ className
390
+ ),
391
+ ...props,
392
+ children: [
393
+ /* @__PURE__ */ jsx("div", { className: "shrink-0", children: avatar ?? /* @__PURE__ */ jsx("div", { className: "flex h-9 w-9 items-center justify-center rounded-full bg-muted text-muted-foreground [&>svg]:h-4 [&>svg]:w-4", children: icon }) }),
394
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
395
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
396
+ /* @__PURE__ */ jsx("p", { className: cn("text-sm font-medium leading-snug", unread && "font-semibold"), children: title }),
397
+ unread && /* @__PURE__ */ jsx("span", { className: "mt-1 h-2 w-2 shrink-0 rounded-full bg-primary", "aria-label": "Unread" })
398
+ ] }),
399
+ description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-sm text-muted-foreground line-clamp-2", children: description }),
400
+ time && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: time })
401
+ ] }),
402
+ onClose && /* @__PURE__ */ jsx(
403
+ "button",
404
+ {
405
+ type: "button",
406
+ onClick: onClose,
407
+ className: "shrink-0 self-start rounded p-0.5 text-muted-foreground hover:text-foreground transition-colors",
408
+ "aria-label": "Dismiss notification",
409
+ children: /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
410
+ }
411
+ )
412
+ ]
413
+ }
414
+ )
415
+ );
416
+ Notification.displayName = "Notification";
417
+ var bannerVariants = {
418
+ info: "bg-info/10 border-info/30 text-info-foreground [&_.atlas-banner-icon]:text-info",
419
+ success: "bg-success/10 border-success/30 text-success-foreground [&_.atlas-banner-icon]:text-success",
420
+ warning: "bg-warning/10 border-warning/30 text-warning-foreground [&_.atlas-banner-icon]:text-warning",
421
+ danger: "bg-destructive/10 border-destructive/30 text-destructive [&_.atlas-banner-icon]:text-destructive"
422
+ };
423
+ var defaultBannerIcons = {
424
+ info: /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
425
+ success: /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
426
+ warning: /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }),
427
+ danger: /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" }) })
428
+ };
429
+ var BannerAlert = React2.forwardRef(
430
+ ({ className, title, description, variant = "info", dismissible, onDismiss, action, icon, ...props }, ref) => /* @__PURE__ */ jsx(
431
+ "div",
432
+ {
433
+ ref,
434
+ role: "alert",
435
+ className: cn(
436
+ "atlas-banner-alert w-full border-y px-4 py-3",
437
+ bannerVariants[variant],
438
+ className
439
+ ),
440
+ ...props,
441
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 max-w-screen-xl mx-auto", children: [
442
+ /* @__PURE__ */ jsx("span", { className: "atlas-banner-icon shrink-0 mt-0.5", children: icon ?? defaultBannerIcons[variant] }),
443
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
444
+ title && /* @__PURE__ */ jsx("p", { className: "font-semibold text-sm", children: title }),
445
+ description && /* @__PURE__ */ jsx("p", { className: "text-sm mt-0.5 opacity-90", children: description })
446
+ ] }),
447
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
448
+ action,
449
+ dismissible && /* @__PURE__ */ jsx(
450
+ "button",
451
+ {
452
+ type: "button",
453
+ onClick: onDismiss,
454
+ "aria-label": "Dismiss",
455
+ className: "rounded-md p-1 opacity-60 hover:opacity-100 transition-opacity focus:outline-none focus:ring-2 focus:ring-current",
456
+ children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
457
+ }
458
+ )
459
+ ] })
460
+ ] })
461
+ }
462
+ )
463
+ );
464
+ BannerAlert.displayName = "BannerAlert";
465
+ var ConfirmDialog = ({
466
+ open,
467
+ onOpenChange,
468
+ title = "Are you sure?",
469
+ description = "This action cannot be undone.",
470
+ confirmLabel = "Confirm",
471
+ cancelLabel = "Cancel",
472
+ variant = "default",
473
+ onConfirm,
474
+ onCancel,
475
+ loading
476
+ }) => {
477
+ const [pending, setPending] = React2.useState(false);
478
+ if (!open) return null;
479
+ const handleConfirm = async () => {
480
+ setPending(true);
481
+ try {
482
+ await onConfirm?.();
483
+ onOpenChange?.(false);
484
+ } finally {
485
+ setPending(false);
486
+ }
487
+ };
488
+ const handleCancel = () => {
489
+ onCancel?.();
490
+ onOpenChange?.(false);
491
+ };
492
+ const isBusy = pending || loading;
493
+ return /* @__PURE__ */ jsxs("div", { className: "atlas-confirm-dialog fixed inset-0 z-50 flex items-center justify-center p-4", children: [
494
+ /* @__PURE__ */ jsx(
495
+ "div",
496
+ {
497
+ className: "fixed inset-0 bg-black/50 animate-in fade-in-0",
498
+ onClick: handleCancel,
499
+ "aria-hidden": "true"
500
+ }
501
+ ),
502
+ /* @__PURE__ */ jsxs(
503
+ "div",
504
+ {
505
+ role: "alertdialog",
506
+ "aria-modal": "true",
507
+ "aria-labelledby": "confirm-title",
508
+ "aria-describedby": "confirm-description",
509
+ className: cn(
510
+ "relative z-10 w-full max-w-sm rounded-xl border border-border bg-background p-6 shadow-xl",
511
+ "animate-in fade-in-0 zoom-in-95"
512
+ ),
513
+ children: [
514
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
515
+ /* @__PURE__ */ jsx("div", { className: cn(
516
+ "flex h-10 w-10 shrink-0 items-center justify-center rounded-full",
517
+ variant === "danger" ? "bg-destructive/10" : "bg-primary/10"
518
+ ), children: variant === "danger" ? /* @__PURE__ */ jsx("svg", { className: "h-5 w-5 text-destructive", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }) : /* @__PURE__ */ jsx("svg", { className: "h-5 w-5 text-primary", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }) }),
519
+ /* @__PURE__ */ jsxs("div", { children: [
520
+ /* @__PURE__ */ jsx("h2", { id: "confirm-title", className: "text-base font-semibold", children: title }),
521
+ /* @__PURE__ */ jsx("p", { id: "confirm-description", className: "mt-1 text-sm text-muted-foreground", children: description })
522
+ ] })
523
+ ] }),
524
+ /* @__PURE__ */ jsxs("div", { className: "mt-6 flex justify-end gap-2", children: [
525
+ /* @__PURE__ */ jsx(
526
+ "button",
527
+ {
528
+ type: "button",
529
+ onClick: handleCancel,
530
+ disabled: isBusy,
531
+ className: "inline-flex h-9 items-center justify-center rounded-md border border-border bg-background px-4 text-sm font-medium hover:bg-accent transition-colors disabled:opacity-50",
532
+ children: cancelLabel
533
+ }
534
+ ),
535
+ /* @__PURE__ */ jsxs(
536
+ "button",
537
+ {
538
+ type: "button",
539
+ onClick: handleConfirm,
540
+ disabled: isBusy,
541
+ className: cn(
542
+ "inline-flex h-9 items-center justify-center gap-2 rounded-md px-4 text-sm font-medium transition-colors disabled:opacity-50",
543
+ variant === "danger" ? "bg-destructive text-destructive-foreground hover:bg-destructive/90" : "bg-primary text-primary-foreground hover:bg-primary/90"
544
+ ),
545
+ children: [
546
+ isBusy && /* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5 animate-spin", fill: "none", viewBox: "0 0 24 24", children: [
547
+ /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
548
+ /* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
549
+ ] }),
550
+ confirmLabel
551
+ ]
552
+ }
553
+ )
554
+ ] })
555
+ ]
556
+ }
557
+ )
558
+ ] });
559
+ };
560
+ ConfirmDialog.displayName = "ConfirmDialog";
561
+ var positionMap = {
562
+ "bottom-right": "fixed bottom-6 right-6 z-40",
563
+ "bottom-left": "fixed bottom-6 left-6 z-40",
564
+ "bottom-center": "fixed bottom-6 left-1/2 -translate-x-1/2 z-40"
565
+ };
566
+ var fabSizes = {
567
+ sm: "h-12 w-12 [&>svg]:h-5 [&>svg]:w-5",
568
+ md: "h-14 w-14 [&>svg]:h-6 [&>svg]:w-6",
569
+ lg: "h-16 w-16 [&>svg]:h-7 [&>svg]:w-7"
570
+ };
571
+ var FloatingActionButton = React2.forwardRef(
572
+ ({ className, icon, label = "Open actions", actions = [], position = "bottom-right", size = "md", onClick, ...props }, ref) => {
573
+ const [open, setOpen] = React2.useState(false);
574
+ const hasActions = actions.length > 0;
575
+ return /* @__PURE__ */ jsxs(
576
+ "div",
577
+ {
578
+ ref,
579
+ className: cn(positionMap[position], "flex flex-col-reverse items-center gap-3", className),
580
+ ...props,
581
+ children: [
582
+ hasActions && open && /* @__PURE__ */ jsx("div", { className: "flex flex-col-reverse gap-2", children: actions.map((action, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
583
+ /* @__PURE__ */ jsx("span", { className: "rounded-md bg-foreground/90 px-2 py-1 text-xs text-background font-medium shadow whitespace-nowrap", children: action.label }),
584
+ /* @__PURE__ */ jsx(
585
+ "button",
586
+ {
587
+ type: "button",
588
+ disabled: action.disabled,
589
+ onClick: () => {
590
+ action.onClick();
591
+ setOpen(false);
592
+ },
593
+ "aria-label": action.label,
594
+ className: cn(
595
+ "flex h-10 w-10 items-center justify-center rounded-full bg-background border border-border",
596
+ "shadow-md text-foreground hover:bg-accent transition-all",
597
+ "[&>svg]:h-4 [&>svg]:w-4",
598
+ "disabled:opacity-50 disabled:pointer-events-none"
599
+ ),
600
+ children: action.icon
601
+ }
602
+ )
603
+ ] }, i)) }),
604
+ /* @__PURE__ */ jsx(
605
+ "button",
606
+ {
607
+ type: "button",
608
+ "aria-label": label,
609
+ "aria-expanded": hasActions ? open : void 0,
610
+ onClick: hasActions ? () => setOpen(!open) : onClick,
611
+ className: cn(
612
+ "flex items-center justify-center rounded-full",
613
+ "bg-primary text-primary-foreground shadow-lg",
614
+ "hover:bg-primary/90 active:scale-95 transition-all",
615
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
616
+ fabSizes[size]
617
+ ),
618
+ children: icon ?? /* @__PURE__ */ jsx(
619
+ "svg",
620
+ {
621
+ className: cn("transition-transform duration-200", hasActions && open && "rotate-45"),
622
+ fill: "none",
623
+ stroke: "currentColor",
624
+ viewBox: "0 0 24 24",
625
+ style: { width: "1.5rem", height: "1.5rem" },
626
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" })
627
+ }
628
+ )
629
+ }
630
+ )
631
+ ]
632
+ }
633
+ );
634
+ }
635
+ );
636
+ FloatingActionButton.displayName = "FloatingActionButton";
637
+ var RichTooltip = ({
638
+ children,
639
+ title,
640
+ description,
641
+ action,
642
+ side = "top",
643
+ open: controlledOpen,
644
+ defaultOpen = false,
645
+ delayDuration = 400
646
+ }) => {
647
+ const [internalOpen, setInternalOpen] = React2.useState(defaultOpen);
648
+ const isOpen = controlledOpen ?? internalOpen;
649
+ const timeoutRef = React2.useRef(null);
650
+ const show = () => {
651
+ timeoutRef.current = setTimeout(() => setInternalOpen(true), delayDuration);
652
+ };
653
+ const hide = () => {
654
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
655
+ setInternalOpen(false);
656
+ };
657
+ const positionClasses = {
658
+ top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
659
+ bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
660
+ left: "right-full top-1/2 -translate-y-1/2 mr-2",
661
+ right: "left-full top-1/2 -translate-y-1/2 ml-2"
662
+ };
663
+ return /* @__PURE__ */ jsxs(
664
+ "div",
665
+ {
666
+ className: "atlas-rich-tooltip relative inline-flex",
667
+ onMouseEnter: show,
668
+ onMouseLeave: hide,
669
+ onFocus: show,
670
+ onBlur: hide,
671
+ children: [
672
+ children,
673
+ isOpen && /* @__PURE__ */ jsxs(
674
+ "div",
675
+ {
676
+ role: "tooltip",
677
+ className: cn(
678
+ "absolute z-50 w-64 rounded-lg border border-border bg-popover p-3 shadow-lg",
679
+ "animate-in fade-in-0 zoom-in-95",
680
+ positionClasses[side]
681
+ ),
682
+ children: [
683
+ title && /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold mb-1", children: title }),
684
+ description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: description }),
685
+ action && /* @__PURE__ */ jsx("div", { className: "mt-2 pt-2 border-t border-border", children: action })
686
+ ]
687
+ }
688
+ )
689
+ ]
690
+ }
691
+ );
692
+ };
693
+ RichTooltip.displayName = "RichTooltip";
694
+ var Tour = ({
695
+ steps,
696
+ open,
697
+ onOpenChange,
698
+ onComplete,
699
+ currentStep: controlledStep,
700
+ onStepChange
701
+ }) => {
702
+ const [internalStep, setInternalStep] = React2.useState(0);
703
+ const step = controlledStep ?? internalStep;
704
+ const current = steps[step];
705
+ if (!open || !current) return null;
706
+ const goNext = () => {
707
+ if (step < steps.length - 1) {
708
+ const next = step + 1;
709
+ onStepChange?.(next);
710
+ setInternalStep(next);
711
+ } else {
712
+ onComplete?.();
713
+ onOpenChange?.(false);
714
+ }
715
+ };
716
+ const goPrev = () => {
717
+ if (step > 0) {
718
+ const prev = step - 1;
719
+ onStepChange?.(prev);
720
+ setInternalStep(prev);
721
+ }
722
+ };
723
+ return /* @__PURE__ */ jsxs("div", { className: "atlas-tour fixed inset-0 z-50 flex items-center justify-center p-4", children: [
724
+ /* @__PURE__ */ jsx(
725
+ "div",
726
+ {
727
+ className: "fixed inset-0 bg-black/40 animate-in fade-in-0",
728
+ onClick: () => onOpenChange?.(false),
729
+ "aria-hidden": "true"
730
+ }
731
+ ),
732
+ /* @__PURE__ */ jsxs(
733
+ "div",
734
+ {
735
+ role: "dialog",
736
+ "aria-modal": "true",
737
+ "aria-label": `Tour step ${step + 1} of ${steps.length}: ${current.title}`,
738
+ className: "relative z-10 w-full max-w-sm rounded-xl border border-border bg-background p-5 shadow-xl animate-in fade-in-0 zoom-in-95",
739
+ children: [
740
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
741
+ /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-muted-foreground", children: [
742
+ "Step ",
743
+ step + 1,
744
+ " of ",
745
+ steps.length
746
+ ] }),
747
+ /* @__PURE__ */ jsx(
748
+ "button",
749
+ {
750
+ type: "button",
751
+ onClick: () => onOpenChange?.(false),
752
+ "aria-label": "Close tour",
753
+ className: "rounded p-0.5 text-muted-foreground hover:text-foreground transition-colors",
754
+ children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
755
+ }
756
+ )
757
+ ] }),
758
+ /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold mb-1", children: current.title }),
759
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: current.description }),
760
+ /* @__PURE__ */ jsxs("div", { className: "mt-5 flex items-center justify-between gap-3", children: [
761
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: steps.map((_, i) => /* @__PURE__ */ jsx(
762
+ "span",
763
+ {
764
+ className: cn(
765
+ "h-1.5 rounded-full transition-all",
766
+ i === step ? "w-4 bg-primary" : "w-1.5 bg-muted"
767
+ )
768
+ },
769
+ i
770
+ )) }),
771
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
772
+ step > 0 && /* @__PURE__ */ jsx(
773
+ "button",
774
+ {
775
+ type: "button",
776
+ onClick: goPrev,
777
+ className: "h-8 px-3 rounded-md border border-border text-sm hover:bg-accent transition-colors",
778
+ children: "Back"
779
+ }
780
+ ),
781
+ /* @__PURE__ */ jsx(
782
+ "button",
783
+ {
784
+ type: "button",
785
+ onClick: goNext,
786
+ className: "h-8 px-4 rounded-md bg-primary text-primary-foreground text-sm font-medium hover:bg-primary/90 transition-colors",
787
+ children: step === steps.length - 1 ? "Done" : "Next"
788
+ }
789
+ )
790
+ ] })
791
+ ] })
792
+ ]
793
+ }
794
+ )
795
+ ] });
796
+ };
797
+ Tour.displayName = "Tour";
798
+
799
+ // src/components/basic/index.tsx
800
+ import * as React3 from "react";
801
+ import { Slot } from "@radix-ui/react-slot";
802
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
803
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
804
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
805
+ import { cva as cva2 } from "class-variance-authority";
806
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
807
+ var Link = React3.forwardRef(
808
+ ({ className, asChild, external, underline = "hover", children, ...props }, ref) => {
809
+ const Comp = asChild ? Slot : "a";
810
+ const externalProps = external ? { target: "_blank", rel: "noopener noreferrer" } : {};
811
+ return /* @__PURE__ */ jsxs2(
812
+ Comp,
813
+ {
814
+ ref,
815
+ className: cn(
816
+ "atlas-link text-primary transition-colors",
817
+ underline === "always" && "underline underline-offset-4",
818
+ underline === "hover" && "hover:underline underline-offset-4",
819
+ underline === "none" && "no-underline",
820
+ className
821
+ ),
822
+ ...externalProps,
823
+ ...props,
824
+ children: [
825
+ children,
826
+ external && /* @__PURE__ */ jsx2(
827
+ "svg",
828
+ {
829
+ className: "inline-block ml-0.5 h-3 w-3 align-super",
830
+ fill: "none",
831
+ stroke: "currentColor",
832
+ viewBox: "0 0 24 24",
833
+ "aria-hidden": "true",
834
+ children: /* @__PURE__ */ jsx2(
835
+ "path",
836
+ {
837
+ strokeLinecap: "round",
838
+ strokeLinejoin: "round",
839
+ strokeWidth: 2,
840
+ d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
841
+ }
842
+ )
843
+ }
844
+ )
845
+ ]
846
+ }
847
+ );
848
+ }
849
+ );
850
+ Link.displayName = "Link";
851
+ var badgeVariants = cva2(
852
+ "atlas-badge inline-flex items-center gap-1 rounded-full font-medium transition-colors",
853
+ {
854
+ variants: {
855
+ variant: {
856
+ solid: "bg-primary text-primary-foreground",
857
+ outline: "border border-current bg-transparent",
858
+ soft: "bg-primary/10 text-primary",
859
+ neutral: "bg-muted text-muted-foreground"
860
+ },
861
+ size: {
862
+ sm: "px-1.5 py-0.5 text-[10px]",
863
+ md: "px-2 py-0.5 text-xs",
864
+ lg: "px-2.5 py-1 text-sm"
865
+ },
866
+ color: {
867
+ primary: "",
868
+ success: "",
869
+ warning: "",
870
+ danger: "",
871
+ info: "",
872
+ neutral: ""
873
+ }
874
+ },
875
+ compoundVariants: [
876
+ { variant: "solid", color: "success", className: "bg-success text-success-foreground" },
877
+ { variant: "solid", color: "warning", className: "bg-warning text-warning-foreground" },
878
+ { variant: "solid", color: "danger", className: "bg-destructive text-destructive-foreground" },
879
+ { variant: "solid", color: "info", className: "bg-info text-info-foreground" },
880
+ { variant: "soft", color: "success", className: "bg-success/10 text-success" },
881
+ { variant: "soft", color: "warning", className: "bg-warning/10 text-warning" },
882
+ { variant: "soft", color: "danger", className: "bg-destructive/10 text-destructive" },
883
+ { variant: "soft", color: "info", className: "bg-info/10 text-info" }
884
+ ],
885
+ defaultVariants: {
886
+ variant: "soft",
887
+ size: "md",
888
+ color: "primary"
889
+ }
890
+ }
891
+ );
892
+ var Badge = React3.forwardRef(
893
+ ({ className, variant, size, color, dot, children, ...props }, ref) => /* @__PURE__ */ jsxs2("span", { ref, className: cn(badgeVariants({ variant, size, color, className })), ...props, children: [
894
+ dot && /* @__PURE__ */ jsx2("span", { className: "h-1.5 w-1.5 rounded-full bg-current", "aria-hidden": "true" }),
895
+ children
896
+ ] })
897
+ );
898
+ Badge.displayName = "Badge";
899
+ var avatarSizes = {
900
+ xs: "h-6 w-6 text-[10px]",
901
+ sm: "h-8 w-8 text-xs",
902
+ md: "h-10 w-10 text-sm",
903
+ lg: "h-12 w-12 text-base",
904
+ xl: "h-16 w-16 text-lg",
905
+ "2xl": "h-20 w-20 text-xl"
906
+ };
907
+ var Avatar = React3.forwardRef(({ className, src, alt, fallback, size = "md", shape = "circle", status, ...props }, ref) => /* @__PURE__ */ jsxs2("div", { className: "atlas-avatar relative inline-flex shrink-0", children: [
908
+ /* @__PURE__ */ jsxs2(
909
+ AvatarPrimitive.Root,
910
+ {
911
+ ref,
912
+ className: cn(
913
+ "relative flex shrink-0 overflow-hidden",
914
+ avatarSizes[size],
915
+ shape === "circle" ? "rounded-full" : "rounded-md",
916
+ className
917
+ ),
918
+ ...props,
919
+ children: [
920
+ /* @__PURE__ */ jsx2(
921
+ AvatarPrimitive.Image,
922
+ {
923
+ src,
924
+ alt,
925
+ className: "aspect-square h-full w-full object-cover"
926
+ }
927
+ ),
928
+ /* @__PURE__ */ jsx2(
929
+ AvatarPrimitive.Fallback,
930
+ {
931
+ className: cn(
932
+ "flex h-full w-full items-center justify-center",
933
+ "bg-muted font-medium text-muted-foreground uppercase"
934
+ ),
935
+ children: fallback ?? (alt ? alt.slice(0, 2) : "?")
936
+ }
937
+ )
938
+ ]
939
+ }
940
+ ),
941
+ status && /* @__PURE__ */ jsx2(
942
+ "span",
943
+ {
944
+ "aria-label": `Status: ${status}`,
945
+ className: cn(
946
+ "absolute bottom-0 right-0 block rounded-full ring-2 ring-background",
947
+ size === "xs" || size === "sm" ? "h-2 w-2" : "h-2.5 w-2.5",
948
+ status === "online" && "bg-success",
949
+ status === "offline" && "bg-muted-foreground",
950
+ status === "busy" && "bg-destructive",
951
+ status === "away" && "bg-warning"
952
+ )
953
+ }
954
+ )
955
+ ] }));
956
+ Avatar.displayName = "Avatar";
957
+ var AvatarGroup = React3.forwardRef(
958
+ ({ className, children, max, size = "md", spacing = "tight", ...props }, ref) => {
959
+ const validChildren = React3.Children.toArray(children).filter(React3.isValidElement);
960
+ const visible = max ? validChildren.slice(0, max) : validChildren;
961
+ const overflow = max ? validChildren.length - max : 0;
962
+ const spacingMap = { tight: "-space-x-2", normal: "-space-x-1", loose: "space-x-1" };
963
+ return /* @__PURE__ */ jsxs2(
964
+ "div",
965
+ {
966
+ ref,
967
+ className: cn("atlas-avatar-group flex items-center", spacingMap[spacing], className),
968
+ ...props,
969
+ children: [
970
+ visible.map(
971
+ (child, i) => React3.cloneElement(child, {
972
+ key: i,
973
+ size,
974
+ className: cn(
975
+ "ring-2 ring-background",
976
+ child.props.className
977
+ )
978
+ })
979
+ ),
980
+ overflow > 0 && /* @__PURE__ */ jsxs2(
981
+ "span",
982
+ {
983
+ className: cn(
984
+ "atlas-avatar relative flex shrink-0 items-center justify-center rounded-full",
985
+ "bg-muted text-muted-foreground font-medium ring-2 ring-background",
986
+ avatarSizes[size]
987
+ ),
988
+ "aria-label": `${overflow} more`,
989
+ children: [
990
+ "+",
991
+ overflow
992
+ ]
993
+ }
994
+ )
995
+ ]
996
+ }
997
+ );
998
+ }
999
+ );
1000
+ AvatarGroup.displayName = "AvatarGroup";
1001
+ var Divider = React3.forwardRef(
1002
+ ({ className, orientation = "horizontal", label, labelPosition = "center", ...props }, ref) => {
1003
+ if (!label) {
1004
+ return /* @__PURE__ */ jsx2(
1005
+ SeparatorPrimitive.Root,
1006
+ {
1007
+ ref,
1008
+ orientation,
1009
+ className: cn(
1010
+ "atlas-divider shrink-0 bg-border",
1011
+ orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
1012
+ className
1013
+ ),
1014
+ ...props
1015
+ }
1016
+ );
1017
+ }
1018
+ return /* @__PURE__ */ jsxs2(
1019
+ "div",
1020
+ {
1021
+ className: cn(
1022
+ "atlas-divider relative flex items-center gap-3 w-full",
1023
+ className
1024
+ ),
1025
+ role: "separator",
1026
+ children: [
1027
+ labelPosition !== "left" && /* @__PURE__ */ jsx2("span", { className: "flex-1 bg-border h-px" }),
1028
+ /* @__PURE__ */ jsx2("span", { className: "text-xs text-muted-foreground whitespace-nowrap", children: label }),
1029
+ labelPosition !== "right" && /* @__PURE__ */ jsx2("span", { className: "flex-1 bg-border h-px" })
1030
+ ]
1031
+ }
1032
+ );
1033
+ }
1034
+ );
1035
+ Divider.displayName = "Divider";
1036
+ var Tag = React3.forwardRef(
1037
+ ({ className, closable, onClose, icon, size = "md", variant = "soft", color = "neutral", children, ...props }, ref) => /* @__PURE__ */ jsxs2(
1038
+ "span",
1039
+ {
1040
+ ref,
1041
+ className: cn(
1042
+ "atlas-tag inline-flex items-center gap-1 rounded font-medium",
1043
+ size === "sm" && "px-1.5 py-0.5 text-[10px]",
1044
+ size === "md" && "px-2 py-1 text-xs",
1045
+ size === "lg" && "px-3 py-1.5 text-sm",
1046
+ variant === "soft" && color === "neutral" && "bg-muted text-muted-foreground",
1047
+ variant === "soft" && color === "primary" && "bg-primary/10 text-primary",
1048
+ variant === "soft" && color === "success" && "bg-success/10 text-success",
1049
+ variant === "soft" && color === "warning" && "bg-warning/10 text-warning",
1050
+ variant === "soft" && color === "danger" && "bg-destructive/10 text-destructive",
1051
+ variant === "outline" && "border border-current bg-transparent",
1052
+ variant === "solid" && color === "neutral" && "bg-muted-foreground text-background",
1053
+ className
1054
+ ),
1055
+ ...props,
1056
+ children: [
1057
+ icon && /* @__PURE__ */ jsx2("span", { className: "shrink-0", "aria-hidden": "true", children: icon }),
1058
+ children,
1059
+ closable && /* @__PURE__ */ jsx2(
1060
+ "button",
1061
+ {
1062
+ type: "button",
1063
+ onClick: onClose,
1064
+ className: "ml-0.5 rounded-full hover:bg-black/10 dark:hover:bg-white/10 p-0.5 transition-colors",
1065
+ "aria-label": "Remove tag",
1066
+ children: /* @__PURE__ */ jsx2("svg", { className: "h-2.5 w-2.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M6 18L18 6M6 6l12 12" }) })
1067
+ }
1068
+ )
1069
+ ]
1070
+ }
1071
+ )
1072
+ );
1073
+ Tag.displayName = "Tag";
1074
+ var Chip = React3.forwardRef(
1075
+ ({ className, selected, avatar, icon, closable, onClose, size = "md", children, ...props }, ref) => /* @__PURE__ */ jsxs2(
1076
+ "button",
1077
+ {
1078
+ ref,
1079
+ type: "button",
1080
+ className: cn(
1081
+ "atlas-chip inline-flex items-center gap-1.5 rounded-full font-medium",
1082
+ "border transition-all duration-150 cursor-pointer",
1083
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1084
+ "disabled:pointer-events-none disabled:opacity-50",
1085
+ size === "sm" && "h-6 px-2 text-xs",
1086
+ size === "md" && "h-8 px-3 text-sm",
1087
+ size === "lg" && "h-9 px-4 text-sm",
1088
+ selected ? "bg-primary text-primary-foreground border-primary" : "bg-background text-foreground border-border hover:bg-accent",
1089
+ className
1090
+ ),
1091
+ "aria-pressed": selected,
1092
+ ...props,
1093
+ children: [
1094
+ avatar && /* @__PURE__ */ jsx2("span", { className: "shrink-0 -ml-0.5", children: avatar }),
1095
+ icon && !avatar && /* @__PURE__ */ jsx2("span", { className: "shrink-0 [&>svg]:h-3.5 [&>svg]:w-3.5", "aria-hidden": "true", children: icon }),
1096
+ children,
1097
+ closable && /* @__PURE__ */ jsx2(
1098
+ "span",
1099
+ {
1100
+ role: "button",
1101
+ tabIndex: 0,
1102
+ onClick: (e) => {
1103
+ e.stopPropagation();
1104
+ onClose?.(e);
1105
+ },
1106
+ className: "shrink-0 -mr-0.5 rounded-full hover:bg-black/10 dark:hover:bg-white/10 p-0.5",
1107
+ "aria-label": "Remove",
1108
+ children: /* @__PURE__ */ jsx2("svg", { className: "h-3 w-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M6 18L18 6M6 6l12 12" }) })
1109
+ }
1110
+ )
1111
+ ]
1112
+ }
1113
+ )
1114
+ );
1115
+ Chip.displayName = "Chip";
1116
+ var TooltipProvider = TooltipPrimitive.Provider;
1117
+ var TooltipRoot = TooltipPrimitive.Root;
1118
+ var TooltipTrigger = TooltipPrimitive.Trigger;
1119
+ var TooltipContent = React3.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx2(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx2(
1120
+ TooltipPrimitive.Content,
1121
+ {
1122
+ ref,
1123
+ sideOffset,
1124
+ className: cn(
1125
+ "atlas-tooltip z-50 overflow-hidden rounded-md",
1126
+ "bg-foreground px-3 py-1.5 text-xs text-background shadow-md",
1127
+ "animate-in fade-in-0 zoom-in-95",
1128
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
1129
+ "data-[side=bottom]:slide-in-from-top-2",
1130
+ "data-[side=left]:slide-in-from-right-2",
1131
+ "data-[side=right]:slide-in-from-left-2",
1132
+ "data-[side=top]:slide-in-from-bottom-2",
1133
+ className
1134
+ ),
1135
+ ...props
1136
+ }
1137
+ ) }));
1138
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
1139
+ var Tooltip = ({ content, children, side = "top", delayDuration = 300, className }) => /* @__PURE__ */ jsx2(TooltipProvider, { children: /* @__PURE__ */ jsxs2(TooltipRoot, { delayDuration, children: [
1140
+ /* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children }),
1141
+ /* @__PURE__ */ jsx2(TooltipContent, { side, className, children: content })
1142
+ ] }) });
1143
+ Tooltip.displayName = "Tooltip";
1144
+
1145
+ // src/provider.tsx
1146
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1147
+ function AtlasProvider({
1148
+ children,
1149
+ toastDuration = 5e3,
1150
+ toastSwipeDirection = "right",
1151
+ tooltipDelay = 300
1152
+ }) {
1153
+ return /* @__PURE__ */ jsx3(ToastProvider, { duration: toastDuration, swipeDirection: toastSwipeDirection, children: /* @__PURE__ */ jsxs3(TooltipProvider, { delayDuration: tooltipDelay, children: [
1154
+ children,
1155
+ /* @__PURE__ */ jsx3(ToastViewport, {})
1156
+ ] }) });
1157
+ }
1158
+ export {
1159
+ AtlasProvider
1160
+ };
1161
+ //# sourceMappingURL=provider.mjs.map