@sdods/ui 0.1.0 → 0.2.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.d.ts CHANGED
@@ -1,66 +1,104 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import { ClassValue } from 'clsx';
2
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
3
  import * as React from 'react';
4
+ import { VariantProps } from 'class-variance-authority';
5
+ import * as LabelPrimitive from '@radix-ui/react-label';
6
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
7
+ import * as SwitchPrimitives from '@radix-ui/react-switch';
8
+ import * as react_jsx_runtime from 'react/jsx-runtime';
9
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
3
10
 
4
- interface Theme {
5
- name: string;
6
- colors: {
7
- primary: string;
8
- secondary: string;
9
- accent: string;
10
- background: string;
11
- foreground: string;
12
- muted: string;
13
- border: string;
14
- error: string;
15
- success: string;
16
- warning: string;
17
- };
18
- fonts: {
19
- sans: string;
20
- mono: string;
21
- };
22
- radii: {
23
- sm: string;
24
- md: string;
25
- lg: string;
26
- full: string;
27
- };
28
- }
29
- declare const themes: Record<string, Theme>;
30
- interface ThemeProviderProps {
31
- theme?: Theme | keyof typeof themes;
32
- children: React.ReactNode;
33
- }
34
- declare function ThemeProvider({ theme, children }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
35
- declare function useTheme(): Theme;
36
- interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
37
- variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive';
38
- size?: 'sm' | 'md' | 'lg';
39
- loading?: boolean;
11
+ /**
12
+ * cn() - Class Name utility
13
+ * Combines clsx for conditional classes + tailwind-merge for conflict resolution
14
+ */
15
+
16
+ declare function cn(...inputs: ClassValue[]): string;
17
+
18
+ declare const buttonVariants: (props?: ({
19
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
20
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
21
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
22
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
23
+ asChild?: boolean;
40
24
  }
41
25
  declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
42
- interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
43
- variant?: 'default' | 'elevated' | 'outlined';
44
- }
45
- declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
26
+
27
+ /**
28
+ * Input Component
29
+ * Accessible text input with consistent styling
30
+ */
31
+
46
32
  interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
47
- error?: string;
48
- label?: string;
49
33
  }
50
34
  declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
51
- interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
52
- variant?: 'default' | 'primary' | 'success' | 'warning' | 'error';
53
- }
54
- declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
55
- interface SpinnerProps {
56
- size?: 'sm' | 'md' | 'lg';
35
+
36
+ declare const Label: React.ForwardRefExoticComponent<Omit<LabelPrimitive.LabelProps & React.RefAttributes<HTMLLabelElement>, "ref"> & VariantProps<(props?: class_variance_authority_types.ClassProp | undefined) => string> & React.RefAttributes<HTMLLabelElement>>;
37
+
38
+ /**
39
+ * Separator Component
40
+ * Visual divider via Radix
41
+ */
42
+
43
+ declare const Separator: React.ForwardRefExoticComponent<Omit<SeparatorPrimitive.SeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
44
+
45
+ /**
46
+ * Switch Component
47
+ * Accessible toggle switch via Radix
48
+ */
49
+
50
+ declare const Switch: React.ForwardRefExoticComponent<Omit<SwitchPrimitives.SwitchProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
51
+
52
+ /**
53
+ * Card Component
54
+ * Container for content with consistent styling
55
+ */
56
+
57
+ declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
58
+ declare const CardHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
59
+ declare const CardTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLParagraphElement>>;
60
+ declare const CardDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
61
+ declare const CardContent: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
62
+ declare const CardFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
63
+
64
+ declare const Dialog: React.FC<DialogPrimitive.DialogProps>;
65
+ declare const DialogTrigger: React.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
66
+ declare const DialogPortal: React.FC<DialogPrimitive.DialogPortalProps>;
67
+ declare const DialogClose: React.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
68
+ declare const DialogOverlay: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
69
+ declare const DialogContent: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
70
+ declare const DialogHeader: {
71
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
72
+ displayName: string;
73
+ };
74
+ declare const DialogFooter: {
75
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
76
+ displayName: string;
77
+ };
78
+ declare const DialogTitle: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
79
+ declare const DialogDescription: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
80
+
81
+ interface GoogleOneTapProps {
82
+ clientId: string;
83
+ onSuccess?: (response: {
84
+ credential: string;
85
+ }) => void;
86
+ onError?: (error: Error) => void;
87
+ onDismiss?: () => void;
88
+ autoPrompt?: boolean;
89
+ position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
57
90
  className?: string;
58
91
  }
59
- declare function Spinner({ size, className }: SpinnerProps): react_jsx_runtime.JSX.Element;
60
- interface AvatarProps extends React.ImgHTMLAttributes<HTMLImageElement> {
61
- size?: 'sm' | 'md' | 'lg';
62
- fallback?: string;
63
- }
64
- declare function Avatar({ size, fallback, src, alt, className, ...props }: AvatarProps): react_jsx_runtime.JSX.Element;
92
+ /**
93
+ * Manual One Tap UI (for when you want custom styling)
94
+ */
95
+ declare function GoogleOneTapPrompt({ email, avatarUrl, onContinue, onDismiss, position, className, }: {
96
+ email: string;
97
+ avatarUrl?: string;
98
+ onContinue: () => void;
99
+ onDismiss: () => void;
100
+ position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
101
+ className?: string;
102
+ }): react_jsx_runtime.JSX.Element;
65
103
 
66
- export { Avatar, type AvatarProps, Badge, type BadgeProps, Button, type ButtonProps, Card, type CardProps, Input, type InputProps, Spinner, type SpinnerProps, type Theme, ThemeProvider, type ThemeProviderProps, themes, useTheme };
104
+ export { Button, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, GoogleOneTapPrompt as GoogleOneTap, GoogleOneTapPrompt, type GoogleOneTapProps, Input, type InputProps, Label, Separator, Switch, buttonVariants, cn };
package/dist/index.js CHANGED
@@ -1,313 +1,314 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
1
+ import { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+ import * as React6 from 'react';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import { cva } from 'class-variance-authority';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+ import * as LabelPrimitive from '@radix-ui/react-label';
8
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
9
+ import * as SwitchPrimitives from '@radix-ui/react-switch';
10
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
11
+ import { X } from 'lucide-react';
29
12
 
30
- // src/index.tsx
31
- var index_exports = {};
32
- __export(index_exports, {
33
- Avatar: () => Avatar,
34
- Badge: () => Badge,
35
- Button: () => Button,
36
- Card: () => Card,
37
- Input: () => Input,
38
- Spinner: () => Spinner,
39
- ThemeProvider: () => ThemeProvider,
40
- themes: () => themes,
41
- useTheme: () => useTheme
42
- });
43
- module.exports = __toCommonJS(index_exports);
44
- var React = __toESM(require("react"));
45
- var import_clsx = require("clsx");
46
- var import_jsx_runtime = require("react/jsx-runtime");
47
- var themes = {
48
- yarlis: {
49
- name: "yarlis",
50
- colors: {
51
- primary: "#316FA7",
52
- secondary: "#7C3AED",
53
- accent: "#06B6D4",
54
- background: "#0F172A",
55
- foreground: "#F8FAFC",
56
- muted: "#64748B",
57
- border: "#334155",
58
- error: "#EF4444",
59
- success: "#22C55E",
60
- warning: "#F59E0B"
61
- },
62
- fonts: {
63
- sans: "Inter, system-ui, sans-serif",
64
- mono: "JetBrains Mono, monospace"
65
- },
66
- radii: {
67
- sm: "0.25rem",
68
- md: "0.5rem",
69
- lg: "1rem",
70
- full: "9999px"
71
- }
72
- },
73
- light: {
74
- name: "light",
75
- colors: {
76
- primary: "#2563EB",
77
- secondary: "#7C3AED",
78
- accent: "#06B6D4",
79
- background: "#FFFFFF",
80
- foreground: "#0F172A",
81
- muted: "#64748B",
82
- border: "#E2E8F0",
83
- error: "#EF4444",
84
- success: "#22C55E",
85
- warning: "#F59E0B"
86
- },
87
- fonts: {
88
- sans: "Inter, system-ui, sans-serif",
89
- mono: "JetBrains Mono, monospace"
13
+ // src/lib/cn.ts
14
+ function cn(...inputs) {
15
+ return twMerge(clsx(inputs));
16
+ }
17
+ var buttonVariants = cva(
18
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
19
+ {
20
+ variants: {
21
+ variant: {
22
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
23
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
24
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
25
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
26
+ ghost: "hover:bg-accent hover:text-accent-foreground",
27
+ link: "text-primary underline-offset-4 hover:underline"
28
+ },
29
+ size: {
30
+ default: "h-10 px-4 py-2",
31
+ sm: "h-9 rounded-md px-3",
32
+ lg: "h-11 rounded-md px-8",
33
+ icon: "h-10 w-10"
34
+ }
90
35
  },
91
- radii: {
92
- sm: "0.25rem",
93
- md: "0.5rem",
94
- lg: "1rem",
95
- full: "9999px"
36
+ defaultVariants: {
37
+ variant: "default",
38
+ size: "default"
96
39
  }
97
40
  }
98
- };
99
- var ThemeContext = React.createContext(themes.yarlis);
100
- function ThemeProvider({ theme = "yarlis", children }) {
101
- const resolvedTheme = typeof theme === "string" ? themes[theme] : theme;
102
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: resolvedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
103
- "div",
104
- {
105
- style: {
106
- "--color-primary": resolvedTheme.colors.primary,
107
- "--color-secondary": resolvedTheme.colors.secondary,
108
- "--color-accent": resolvedTheme.colors.accent,
109
- "--color-background": resolvedTheme.colors.background,
110
- "--color-foreground": resolvedTheme.colors.foreground,
111
- "--color-muted": resolvedTheme.colors.muted,
112
- "--color-border": resolvedTheme.colors.border,
113
- "--color-error": resolvedTheme.colors.error,
114
- "--color-success": resolvedTheme.colors.success,
115
- "--color-warning": resolvedTheme.colors.warning,
116
- "--font-sans": resolvedTheme.fonts.sans,
117
- "--font-mono": resolvedTheme.fonts.mono,
118
- "--radius-sm": resolvedTheme.radii.sm,
119
- "--radius-md": resolvedTheme.radii.md,
120
- "--radius-lg": resolvedTheme.radii.lg,
121
- "--radius-full": resolvedTheme.radii.full
122
- },
123
- children
124
- }
125
- ) });
126
- }
127
- function useTheme() {
128
- return React.useContext(ThemeContext);
129
- }
130
- var Button = React.forwardRef(
131
- ({ variant = "primary", size = "md", loading, className, children, disabled, ...props }, ref) => {
132
- const baseStyles = "inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none";
133
- const variants = {
134
- primary: "bg-[var(--color-primary)] text-white hover:opacity-90 focus:ring-[var(--color-primary)]",
135
- secondary: "bg-[var(--color-secondary)] text-white hover:opacity-90 focus:ring-[var(--color-secondary)]",
136
- outline: "border border-[var(--color-border)] bg-transparent hover:bg-[var(--color-muted)]/10",
137
- ghost: "bg-transparent hover:bg-[var(--color-muted)]/10",
138
- destructive: "bg-[var(--color-error)] text-white hover:opacity-90 focus:ring-[var(--color-error)]"
139
- };
140
- const sizes = {
141
- sm: "h-8 px-3 text-sm rounded-[var(--radius-sm)]",
142
- md: "h-10 px-4 text-base rounded-[var(--radius-md)]",
143
- lg: "h-12 px-6 text-lg rounded-[var(--radius-md)]"
144
- };
145
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
146
- "button",
41
+ );
42
+ var Button = React6.forwardRef(
43
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
44
+ const Comp = asChild ? Slot : "button";
45
+ return /* @__PURE__ */ jsx(
46
+ Comp,
147
47
  {
48
+ className: cn(buttonVariants({ variant, size, className })),
148
49
  ref,
149
- className: (0, import_clsx.clsx)(baseStyles, variants[variant], sizes[size], className),
150
- disabled: disabled || loading,
151
- ...props,
152
- children: [
153
- loading && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className: "animate-spin -ml-1 mr-2 h-4 w-4", fill: "none", viewBox: "0 0 24 24", children: [
154
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
155
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
156
- ] }),
157
- children
158
- ]
50
+ ...props
159
51
  }
160
52
  );
161
53
  }
162
54
  );
163
55
  Button.displayName = "Button";
164
- var Card = React.forwardRef(
165
- ({ variant = "default", className, children, ...props }, ref) => {
166
- const variants = {
167
- default: "bg-[var(--color-background)] border border-[var(--color-border)]",
168
- elevated: "bg-[var(--color-background)] shadow-lg",
169
- outlined: "bg-transparent border-2 border-[var(--color-border)]"
170
- };
171
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
172
- "div",
56
+ var Input = React6.forwardRef(
57
+ ({ className, type, ...props }, ref) => {
58
+ return /* @__PURE__ */ jsx(
59
+ "input",
173
60
  {
174
- ref,
175
- className: (0, import_clsx.clsx)(
176
- "rounded-[var(--radius-lg)] p-6",
177
- variants[variant],
61
+ type,
62
+ className: cn(
63
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
178
64
  className
179
65
  ),
180
- ...props,
181
- children
66
+ ref,
67
+ ...props
182
68
  }
183
69
  );
184
70
  }
185
71
  );
186
- Card.displayName = "Card";
187
- var Input = React.forwardRef(
188
- ({ error, label, className, id, ...props }, ref) => {
189
- const inputId = id || React.useId();
190
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-1", children: [
191
- label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: inputId, className: "text-sm font-medium text-[var(--color-foreground)]", children: label }),
192
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
193
- "input",
194
- {
195
- ref,
196
- id: inputId,
197
- className: (0, import_clsx.clsx)(
198
- "h-10 px-3 rounded-[var(--radius-md)] border bg-[var(--color-background)] text-[var(--color-foreground)]",
199
- "focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)]",
200
- error ? "border-[var(--color-error)]" : "border-[var(--color-border)]",
201
- className
202
- ),
203
- ...props
204
- }
205
- ),
206
- error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm text-[var(--color-error)]", children: error })
207
- ] });
72
+ Input.displayName = "Input";
73
+ var labelVariants = cva(
74
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
75
+ );
76
+ var Label = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
77
+ LabelPrimitive.Root,
78
+ {
79
+ ref,
80
+ className: cn(labelVariants(), className),
81
+ ...props
208
82
  }
83
+ ));
84
+ Label.displayName = LabelPrimitive.Root.displayName;
85
+ var Separator = React6.forwardRef(
86
+ ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
87
+ SeparatorPrimitive.Root,
88
+ {
89
+ ref,
90
+ decorative,
91
+ orientation,
92
+ className: cn(
93
+ "shrink-0 bg-border",
94
+ orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
95
+ className
96
+ ),
97
+ ...props
98
+ }
99
+ )
209
100
  );
210
- Input.displayName = "Input";
211
- var Badge = React.forwardRef(
212
- ({ variant = "default", className, ...props }, ref) => {
213
- const variants = {
214
- default: "bg-[var(--color-muted)]/20 text-[var(--color-foreground)]",
215
- primary: "bg-[var(--color-primary)]/20 text-[var(--color-primary)]",
216
- success: "bg-[var(--color-success)]/20 text-[var(--color-success)]",
217
- warning: "bg-[var(--color-warning)]/20 text-[var(--color-warning)]",
218
- error: "bg-[var(--color-error)]/20 text-[var(--color-error)]"
219
- };
220
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
221
- "span",
101
+ Separator.displayName = SeparatorPrimitive.Root.displayName;
102
+ var Switch = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
103
+ SwitchPrimitives.Root,
104
+ {
105
+ className: cn(
106
+ "peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
107
+ className
108
+ ),
109
+ ...props,
110
+ ref,
111
+ children: /* @__PURE__ */ jsx(
112
+ SwitchPrimitives.Thumb,
222
113
  {
223
- ref,
224
- className: (0, import_clsx.clsx)(
225
- "inline-flex items-center px-2 py-1 text-xs font-medium rounded-[var(--radius-full)]",
226
- variants[variant],
227
- className
228
- ),
229
- ...props
114
+ className: cn(
115
+ "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
116
+ )
230
117
  }
231
- );
118
+ )
119
+ }
120
+ ));
121
+ Switch.displayName = SwitchPrimitives.Root.displayName;
122
+ var Card = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
123
+ "div",
124
+ {
125
+ ref,
126
+ className: cn(
127
+ "rounded-lg border bg-card text-card-foreground shadow-sm",
128
+ className
129
+ ),
130
+ ...props
131
+ }
132
+ ));
133
+ Card.displayName = "Card";
134
+ var CardHeader = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
135
+ "div",
136
+ {
137
+ ref,
138
+ className: cn("flex flex-col space-y-1.5 p-6", className),
139
+ ...props
140
+ }
141
+ ));
142
+ CardHeader.displayName = "CardHeader";
143
+ var CardTitle = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
144
+ "h3",
145
+ {
146
+ ref,
147
+ className: cn("text-2xl font-semibold leading-none tracking-tight", className),
148
+ ...props
149
+ }
150
+ ));
151
+ CardTitle.displayName = "CardTitle";
152
+ var CardDescription = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
153
+ "p",
154
+ {
155
+ ref,
156
+ className: cn("text-sm text-muted-foreground", className),
157
+ ...props
158
+ }
159
+ ));
160
+ CardDescription.displayName = "CardDescription";
161
+ var CardContent = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
162
+ CardContent.displayName = "CardContent";
163
+ var CardFooter = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
164
+ "div",
165
+ {
166
+ ref,
167
+ className: cn("flex items-center p-6 pt-0", className),
168
+ ...props
169
+ }
170
+ ));
171
+ CardFooter.displayName = "CardFooter";
172
+ var Dialog = DialogPrimitive.Root;
173
+ var DialogTrigger = DialogPrimitive.Trigger;
174
+ var DialogPortal = DialogPrimitive.Portal;
175
+ var DialogClose = DialogPrimitive.Close;
176
+ var DialogOverlay = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
177
+ DialogPrimitive.Overlay,
178
+ {
179
+ ref,
180
+ className: cn(
181
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
182
+ className
183
+ ),
184
+ ...props
185
+ }
186
+ ));
187
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
188
+ var DialogContent = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
189
+ /* @__PURE__ */ jsx(DialogOverlay, {}),
190
+ /* @__PURE__ */ jsxs(
191
+ DialogPrimitive.Content,
192
+ {
193
+ ref,
194
+ className: cn(
195
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
196
+ className
197
+ ),
198
+ ...props,
199
+ children: [
200
+ children,
201
+ /* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
202
+ /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
203
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
204
+ ] })
205
+ ]
206
+ }
207
+ )
208
+ ] }));
209
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
210
+ var DialogHeader = ({
211
+ className,
212
+ ...props
213
+ }) => /* @__PURE__ */ jsx(
214
+ "div",
215
+ {
216
+ className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className),
217
+ ...props
218
+ }
219
+ );
220
+ DialogHeader.displayName = "DialogHeader";
221
+ var DialogFooter = ({
222
+ className,
223
+ ...props
224
+ }) => /* @__PURE__ */ jsx(
225
+ "div",
226
+ {
227
+ className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
228
+ ...props
232
229
  }
233
230
  );
234
- Badge.displayName = "Badge";
235
- function Spinner({ size = "md", className }) {
236
- const sizes = {
237
- sm: "h-4 w-4",
238
- md: "h-8 w-8",
239
- lg: "h-12 w-12"
231
+ DialogFooter.displayName = "DialogFooter";
232
+ var DialogTitle = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
233
+ DialogPrimitive.Title,
234
+ {
235
+ ref,
236
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
237
+ ...props
238
+ }
239
+ ));
240
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
241
+ var DialogDescription = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
242
+ DialogPrimitive.Description,
243
+ {
244
+ ref,
245
+ className: cn("text-sm text-muted-foreground", className),
246
+ ...props
247
+ }
248
+ ));
249
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
250
+ function GoogleOneTapPrompt({
251
+ email,
252
+ avatarUrl,
253
+ onContinue,
254
+ onDismiss,
255
+ position = "top-right",
256
+ className
257
+ }) {
258
+ const positionClasses = {
259
+ "top-right": "top-4 right-4",
260
+ "top-left": "top-4 left-4",
261
+ "bottom-right": "bottom-4 right-4",
262
+ "bottom-left": "bottom-4 left-4"
240
263
  };
241
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
242
- "svg",
264
+ return /* @__PURE__ */ jsxs(
265
+ "div",
243
266
  {
244
- className: (0, import_clsx.clsx)("animate-spin text-[var(--color-primary)]", sizes[size], className),
245
- fill: "none",
246
- viewBox: "0 0 24 24",
267
+ className: cn(
268
+ "fixed z-50 w-80 bg-background border rounded-lg shadow-2xl p-4 animate-in slide-in-from-right-5 fade-in-0",
269
+ positionClasses[position],
270
+ className
271
+ ),
247
272
  children: [
248
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
249
- "circle",
273
+ /* @__PURE__ */ jsx(
274
+ "button",
250
275
  {
251
- className: "opacity-25",
252
- cx: "12",
253
- cy: "12",
254
- r: "10",
255
- stroke: "currentColor",
256
- strokeWidth: "4"
276
+ onClick: onDismiss,
277
+ className: "absolute top-2 right-2 p-1 text-muted-foreground hover:text-foreground rounded-full hover:bg-accent transition-colors",
278
+ "aria-label": "Dismiss",
279
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
257
280
  }
258
281
  ),
259
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
260
- "path",
282
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
283
+ /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", className: "h-5 w-5", children: [
284
+ /* @__PURE__ */ jsx("path", { fill: "#4285F4", d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" }),
285
+ /* @__PURE__ */ jsx("path", { fill: "#34A853", d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" }),
286
+ /* @__PURE__ */ jsx("path", { fill: "#FBBC05", d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" }),
287
+ /* @__PURE__ */ jsx("path", { fill: "#EA4335", d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" })
288
+ ] }),
289
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Sign in with Google" })
290
+ ] }),
291
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 p-3 bg-accent/50 rounded-lg mb-3", children: [
292
+ avatarUrl ? /* @__PURE__ */ jsx("img", { src: avatarUrl, alt: "", className: "w-10 h-10 rounded-full" }) : /* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded-full bg-primary flex items-center justify-center text-primary-foreground font-medium", children: email.charAt(0).toUpperCase() }),
293
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx("div", { className: "text-sm font-medium truncate", children: email }) })
294
+ ] }),
295
+ /* @__PURE__ */ jsxs(
296
+ "button",
261
297
  {
262
- className: "opacity-75",
263
- fill: "currentColor",
264
- d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
298
+ onClick: onContinue,
299
+ className: "w-full py-2.5 px-4 bg-primary text-primary-foreground rounded-md font-medium hover:bg-primary/90 transition-colors",
300
+ children: [
301
+ "Continue as ",
302
+ email.split("@")[0]
303
+ ]
265
304
  }
266
- )
267
- ]
268
- }
269
- );
270
- }
271
- function Avatar({ size = "md", fallback, src, alt, className, ...props }) {
272
- const [error, setError] = React.useState(false);
273
- const sizes = {
274
- sm: "h-8 w-8 text-xs",
275
- md: "h-10 w-10 text-sm",
276
- lg: "h-16 w-16 text-lg"
277
- };
278
- if (error || !src) {
279
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
280
- "div",
281
- {
282
- className: (0, import_clsx.clsx)(
283
- "flex items-center justify-center rounded-[var(--radius-full)] bg-[var(--color-primary)] text-white font-medium",
284
- sizes[size],
285
- className
286
305
  ),
287
- children: fallback || alt?.charAt(0).toUpperCase() || "?"
288
- }
289
- );
290
- }
291
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
292
- "img",
293
- {
294
- src,
295
- alt,
296
- onError: () => setError(true),
297
- className: (0, import_clsx.clsx)("rounded-[var(--radius-full)] object-cover", sizes[size], className),
298
- ...props
306
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-3 leading-relaxed", children: "To create your account, Google will share your name, email address, and profile picture." })
307
+ ]
299
308
  }
300
309
  );
301
310
  }
302
- // Annotate the CommonJS export names for ESM import in node:
303
- 0 && (module.exports = {
304
- Avatar,
305
- Badge,
306
- Button,
307
- Card,
308
- Input,
309
- Spinner,
310
- ThemeProvider,
311
- themes,
312
- useTheme
313
- });
311
+
312
+ export { Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, GoogleOneTapPrompt as GoogleOneTap, GoogleOneTapPrompt, Input, Label, Separator, Switch, buttonVariants, cn };
313
+ //# sourceMappingURL=index.js.map
314
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/cn.ts","../src/components/primitives/button.tsx","../src/components/primitives/input.tsx","../src/components/primitives/label.tsx","../src/components/primitives/separator.tsx","../src/components/primitives/switch.tsx","../src/components/primitives/card.tsx","../src/components/primitives/dialog.tsx","../src/components/patterns/google-one-tap.tsx"],"names":["React","React2","jsx","cva","React3","React4","React5","React7","jsxs","X"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * cn() - Class Name utility\n * Combines clsx for conditional classes + tailwind-merge for conflict resolution\n */\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","/**\n * Button Component\n * Accessible button with variants via CVA\n */\nimport * as React from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../lib/cn';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n );\n }\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n","/**\n * Input Component\n * Accessible text input with consistent styling\n */\nimport * as React from 'react';\nimport { cn } from '../../lib/cn';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n ref={ref}\n {...props}\n />\n );\n }\n);\nInput.displayName = 'Input';\n\nexport { Input };\n","/**\n * Label Component\n * Accessible form label via Radix\n */\nimport * as React from 'react';\nimport * as LabelPrimitive from '@radix-ui/react-label';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../lib/cn';\n\nconst labelVariants = cva(\n 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(labelVariants(), className)}\n {...props}\n />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","/**\n * Separator Component\n * Visual divider via Radix\n */\nimport * as React from 'react';\nimport * as SeparatorPrimitive from '@radix-ui/react-separator';\nimport { cn } from '../../lib/cn';\n\nconst Separator = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(\n (\n { className, orientation = 'horizontal', decorative = true, ...props },\n ref\n ) => (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'shrink-0 bg-border',\n orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',\n className\n )}\n {...props}\n />\n )\n);\nSeparator.displayName = SeparatorPrimitive.Root.displayName;\n\nexport { Separator };\n","/**\n * Switch Component\n * Accessible toggle switch via Radix\n */\nimport * as React from 'react';\nimport * as SwitchPrimitives from '@radix-ui/react-switch';\nimport { cn } from '../../lib/cn';\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>\n>(({ className, ...props }, ref) => (\n <SwitchPrimitives.Root\n className={cn(\n 'peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',\n className\n )}\n {...props}\n ref={ref}\n >\n <SwitchPrimitives.Thumb\n className={cn(\n 'pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0'\n )}\n />\n </SwitchPrimitives.Root>\n));\nSwitch.displayName = SwitchPrimitives.Root.displayName;\n\nexport { Switch };\n","/**\n * Card Component\n * Container for content with consistent styling\n */\nimport * as React from 'react';\nimport { cn } from '../../lib/cn';\n\nconst Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'rounded-lg border bg-card text-card-foreground shadow-sm',\n className\n )}\n {...props}\n />\n));\nCard.displayName = 'Card';\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex flex-col space-y-1.5 p-6', className)}\n {...props}\n />\n));\nCardHeader.displayName = 'CardHeader';\n\nconst CardTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h3\n ref={ref}\n className={cn('text-2xl font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n));\nCardTitle.displayName = 'CardTitle';\n\nconst CardDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n));\nCardDescription.displayName = 'CardDescription';\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />\n));\nCardContent.displayName = 'CardContent';\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center p-6 pt-0', className)}\n {...props}\n />\n));\nCardFooter.displayName = 'CardFooter';\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };\n","/**\n * Dialog Component\n * Accessible modal dialog via Radix\n */\nimport * as React from 'react';\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\nimport { X } from 'lucide-react';\nimport { cn } from '../../lib/cn';\n\nconst Dialog = DialogPrimitive.Root;\nconst DialogTrigger = DialogPrimitive.Trigger;\nconst DialogPortal = DialogPrimitive.Portal;\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n className\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',\n className\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)}\n {...props}\n />\n);\nDialogHeader.displayName = 'DialogHeader';\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}\n {...props}\n />\n);\nDialogFooter.displayName = 'DialogFooter';\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn('text-lg font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogClose,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n};\n","/**\n * Google One Tap Pattern\n * Floating login prompt in corner (like Mailchimp)\n */\nimport { cn } from '../../lib/cn';\nimport { X } from 'lucide-react';\n\nexport interface GoogleOneTapProps {\n clientId: string;\n onSuccess?: (response: { credential: string }) => void;\n onError?: (error: Error) => void;\n onDismiss?: () => void;\n autoPrompt?: boolean;\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';\n className?: string;\n}\n\n/**\n * Manual One Tap UI (for when you want custom styling)\n */\nexport function GoogleOneTapPrompt({\n email,\n avatarUrl,\n onContinue,\n onDismiss,\n position = 'top-right',\n className,\n}: {\n email: string;\n avatarUrl?: string;\n onContinue: () => void;\n onDismiss: () => void;\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';\n className?: string;\n}) {\n const positionClasses = {\n 'top-right': 'top-4 right-4',\n 'top-left': 'top-4 left-4',\n 'bottom-right': 'bottom-4 right-4',\n 'bottom-left': 'bottom-4 left-4',\n };\n\n return (\n <div\n className={cn(\n 'fixed z-50 w-80 bg-background border rounded-lg shadow-2xl p-4 animate-in slide-in-from-right-5 fade-in-0',\n positionClasses[position],\n className\n )}\n >\n <button\n onClick={onDismiss}\n className=\"absolute top-2 right-2 p-1 text-muted-foreground hover:text-foreground rounded-full hover:bg-accent transition-colors\"\n aria-label=\"Dismiss\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n\n <div className=\"flex items-center gap-2 mb-3\">\n <svg viewBox=\"0 0 24 24\" className=\"h-5 w-5\">\n <path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\"/>\n <path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"/>\n <path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"/>\n <path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"/>\n </svg>\n <span className=\"text-sm text-muted-foreground\">Sign in with Google</span>\n </div>\n\n <div className=\"flex items-center gap-3 p-3 bg-accent/50 rounded-lg mb-3\">\n {avatarUrl ? (\n <img src={avatarUrl} alt=\"\" className=\"w-10 h-10 rounded-full\" />\n ) : (\n <div className=\"w-10 h-10 rounded-full bg-primary flex items-center justify-center text-primary-foreground font-medium\">\n {email.charAt(0).toUpperCase()}\n </div>\n )}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium truncate\">{email}</div>\n </div>\n </div>\n\n <button\n onClick={onContinue}\n className=\"w-full py-2.5 px-4 bg-primary text-primary-foreground rounded-md font-medium hover:bg-primary/90 transition-colors\"\n >\n Continue as {email.split('@')[0]}\n </button>\n\n <p className=\"text-xs text-muted-foreground mt-3 leading-relaxed\">\n To create your account, Google will share your name, email address, and profile picture.\n </p>\n </div>\n );\n}\n\nexport { GoogleOneTapPrompt as GoogleOneTap };\n"]}
package/package.json CHANGED
@@ -1,49 +1,59 @@
1
1
  {
2
2
  "name": "@sdods/ui",
3
- "version": "0.1.0",
4
- "description": "React component library with theming",
3
+ "version": "0.2.0",
4
+ "description": "Portable, accessible UI components built on Radix + Tailwind",
5
+ "type": "module",
5
6
  "main": "./dist/index.js",
6
- "module": "./dist/index.mjs",
7
+ "module": "./dist/index.js",
7
8
  "types": "./dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
10
- "import": "./dist/index.mjs",
11
- "require": "./dist/index.js",
11
+ "import": "./dist/index.js",
12
12
  "types": "./dist/index.d.ts"
13
13
  },
14
- "./styles.css": "./dist/styles.css"
14
+ "./styles": "./src/styles/ui.css"
15
15
  },
16
- "files": [
17
- "dist"
18
- ],
19
16
  "sideEffects": [
20
- "**/*.css"
17
+ "*.css"
18
+ ],
19
+ "files": [
20
+ "dist",
21
+ "src/styles"
21
22
  ],
22
23
  "scripts": {
23
- "build": "tsup src/index.tsx --format cjs,esm --dts --external react",
24
- "dev": "tsup src/index.tsx --format cjs,esm --dts --watch --external react",
25
- "test": "vitest",
26
- "typecheck": "tsc --noEmit",
27
- "clean": "rm -rf dist"
28
- },
29
- "dependencies": {
30
- "@sdods/core": "workspace:*",
31
- "clsx": "^2.1.0"
24
+ "build": "tsup",
25
+ "dev": "tsup --watch",
26
+ "lint": "eslint src/",
27
+ "typecheck": "tsc --noEmit"
32
28
  },
33
29
  "peerDependencies": {
34
30
  "react": ">=18.0.0",
35
31
  "react-dom": ">=18.0.0"
36
32
  },
33
+ "dependencies": {
34
+ "@radix-ui/react-dialog": "^1.1.4",
35
+ "@radix-ui/react-dropdown-menu": "^2.1.4",
36
+ "@radix-ui/react-label": "^2.1.0",
37
+ "@radix-ui/react-popover": "^1.1.4",
38
+ "@radix-ui/react-select": "^2.1.4",
39
+ "@radix-ui/react-separator": "^1.1.0",
40
+ "@radix-ui/react-slot": "^1.1.0",
41
+ "@radix-ui/react-switch": "^1.1.1",
42
+ "@radix-ui/react-tabs": "^1.1.1",
43
+ "@radix-ui/react-toast": "^1.2.4",
44
+ "@radix-ui/react-tooltip": "^1.1.5",
45
+ "class-variance-authority": "^0.7.1",
46
+ "clsx": "^2.1.1",
47
+ "lucide-react": "^0.468.0",
48
+ "tailwind-merge": "^2.6.0"
49
+ },
37
50
  "devDependencies": {
38
- "@types/react": "^18.2.0",
39
- "@types/react-dom": "^18.2.0",
40
- "react": "^18.2.0",
41
- "react-dom": "^18.2.0",
42
- "tsup": "^8.0.0",
43
- "typescript": "^5.4.0",
44
- "vitest": "^2.0.0"
51
+ "@types/react": "^18.3.0",
52
+ "@types/react-dom": "^18.3.0",
53
+ "tsup": "^8.3.0",
54
+ "typescript": "^5.7.0"
45
55
  },
46
- "keywords": ["sdods", "ui", "react", "components", "design-system"],
56
+ "keywords": ["ui", "components", "react", "radix", "tailwind", "accessible"],
47
57
  "license": "MIT",
48
58
  "repository": {
49
59
  "type": "git",
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @sdods/ui Base Styles
3
+ * Minimal CSS that complements Tailwind
4
+ * Token references from @sdods/themes
5
+ */
6
+
7
+ @layer base {
8
+ * {
9
+ border-color: hsl(var(--border));
10
+ }
11
+
12
+ body {
13
+ background-color: hsl(var(--background));
14
+ color: hsl(var(--foreground));
15
+ }
16
+ }
17
+
18
+ @layer utilities {
19
+ /* Touch manipulation for mobile */
20
+ .touch-manipulation {
21
+ touch-action: manipulation;
22
+ }
23
+ }
24
+
25
+ /* Animations for dialogs/modals */
26
+ @keyframes fadeIn {
27
+ from { opacity: 0; }
28
+ to { opacity: 1; }
29
+ }
30
+
31
+ @keyframes fadeOut {
32
+ from { opacity: 1; }
33
+ to { opacity: 0; }
34
+ }
35
+
36
+ @keyframes slideIn {
37
+ from { transform: translate(-50%, -48%) scale(0.95); }
38
+ to { transform: translate(-50%, -50%) scale(1); }
39
+ }
40
+
41
+ @keyframes slideOut {
42
+ from { transform: translate(-50%, -50%) scale(1); }
43
+ to { transform: translate(-50%, -48%) scale(0.95); }
44
+ }
package/dist/index.d.mts DELETED
@@ -1,66 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as React from 'react';
3
-
4
- interface Theme {
5
- name: string;
6
- colors: {
7
- primary: string;
8
- secondary: string;
9
- accent: string;
10
- background: string;
11
- foreground: string;
12
- muted: string;
13
- border: string;
14
- error: string;
15
- success: string;
16
- warning: string;
17
- };
18
- fonts: {
19
- sans: string;
20
- mono: string;
21
- };
22
- radii: {
23
- sm: string;
24
- md: string;
25
- lg: string;
26
- full: string;
27
- };
28
- }
29
- declare const themes: Record<string, Theme>;
30
- interface ThemeProviderProps {
31
- theme?: Theme | keyof typeof themes;
32
- children: React.ReactNode;
33
- }
34
- declare function ThemeProvider({ theme, children }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
35
- declare function useTheme(): Theme;
36
- interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
37
- variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive';
38
- size?: 'sm' | 'md' | 'lg';
39
- loading?: boolean;
40
- }
41
- declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
42
- interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
43
- variant?: 'default' | 'elevated' | 'outlined';
44
- }
45
- declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
46
- interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
47
- error?: string;
48
- label?: string;
49
- }
50
- declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
51
- interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
52
- variant?: 'default' | 'primary' | 'success' | 'warning' | 'error';
53
- }
54
- declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
55
- interface SpinnerProps {
56
- size?: 'sm' | 'md' | 'lg';
57
- className?: string;
58
- }
59
- declare function Spinner({ size, className }: SpinnerProps): react_jsx_runtime.JSX.Element;
60
- interface AvatarProps extends React.ImgHTMLAttributes<HTMLImageElement> {
61
- size?: 'sm' | 'md' | 'lg';
62
- fallback?: string;
63
- }
64
- declare function Avatar({ size, fallback, src, alt, className, ...props }: AvatarProps): react_jsx_runtime.JSX.Element;
65
-
66
- export { Avatar, type AvatarProps, Badge, type BadgeProps, Button, type ButtonProps, Card, type CardProps, Input, type InputProps, Spinner, type SpinnerProps, type Theme, ThemeProvider, type ThemeProviderProps, themes, useTheme };
package/dist/index.mjs DELETED
@@ -1,270 +0,0 @@
1
- // src/index.tsx
2
- import * as React from "react";
3
- import { clsx } from "clsx";
4
- import { jsx, jsxs } from "react/jsx-runtime";
5
- var themes = {
6
- yarlis: {
7
- name: "yarlis",
8
- colors: {
9
- primary: "#316FA7",
10
- secondary: "#7C3AED",
11
- accent: "#06B6D4",
12
- background: "#0F172A",
13
- foreground: "#F8FAFC",
14
- muted: "#64748B",
15
- border: "#334155",
16
- error: "#EF4444",
17
- success: "#22C55E",
18
- warning: "#F59E0B"
19
- },
20
- fonts: {
21
- sans: "Inter, system-ui, sans-serif",
22
- mono: "JetBrains Mono, monospace"
23
- },
24
- radii: {
25
- sm: "0.25rem",
26
- md: "0.5rem",
27
- lg: "1rem",
28
- full: "9999px"
29
- }
30
- },
31
- light: {
32
- name: "light",
33
- colors: {
34
- primary: "#2563EB",
35
- secondary: "#7C3AED",
36
- accent: "#06B6D4",
37
- background: "#FFFFFF",
38
- foreground: "#0F172A",
39
- muted: "#64748B",
40
- border: "#E2E8F0",
41
- error: "#EF4444",
42
- success: "#22C55E",
43
- warning: "#F59E0B"
44
- },
45
- fonts: {
46
- sans: "Inter, system-ui, sans-serif",
47
- mono: "JetBrains Mono, monospace"
48
- },
49
- radii: {
50
- sm: "0.25rem",
51
- md: "0.5rem",
52
- lg: "1rem",
53
- full: "9999px"
54
- }
55
- }
56
- };
57
- var ThemeContext = React.createContext(themes.yarlis);
58
- function ThemeProvider({ theme = "yarlis", children }) {
59
- const resolvedTheme = typeof theme === "string" ? themes[theme] : theme;
60
- return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: resolvedTheme, children: /* @__PURE__ */ jsx(
61
- "div",
62
- {
63
- style: {
64
- "--color-primary": resolvedTheme.colors.primary,
65
- "--color-secondary": resolvedTheme.colors.secondary,
66
- "--color-accent": resolvedTheme.colors.accent,
67
- "--color-background": resolvedTheme.colors.background,
68
- "--color-foreground": resolvedTheme.colors.foreground,
69
- "--color-muted": resolvedTheme.colors.muted,
70
- "--color-border": resolvedTheme.colors.border,
71
- "--color-error": resolvedTheme.colors.error,
72
- "--color-success": resolvedTheme.colors.success,
73
- "--color-warning": resolvedTheme.colors.warning,
74
- "--font-sans": resolvedTheme.fonts.sans,
75
- "--font-mono": resolvedTheme.fonts.mono,
76
- "--radius-sm": resolvedTheme.radii.sm,
77
- "--radius-md": resolvedTheme.radii.md,
78
- "--radius-lg": resolvedTheme.radii.lg,
79
- "--radius-full": resolvedTheme.radii.full
80
- },
81
- children
82
- }
83
- ) });
84
- }
85
- function useTheme() {
86
- return React.useContext(ThemeContext);
87
- }
88
- var Button = React.forwardRef(
89
- ({ variant = "primary", size = "md", loading, className, children, disabled, ...props }, ref) => {
90
- const baseStyles = "inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none";
91
- const variants = {
92
- primary: "bg-[var(--color-primary)] text-white hover:opacity-90 focus:ring-[var(--color-primary)]",
93
- secondary: "bg-[var(--color-secondary)] text-white hover:opacity-90 focus:ring-[var(--color-secondary)]",
94
- outline: "border border-[var(--color-border)] bg-transparent hover:bg-[var(--color-muted)]/10",
95
- ghost: "bg-transparent hover:bg-[var(--color-muted)]/10",
96
- destructive: "bg-[var(--color-error)] text-white hover:opacity-90 focus:ring-[var(--color-error)]"
97
- };
98
- const sizes = {
99
- sm: "h-8 px-3 text-sm rounded-[var(--radius-sm)]",
100
- md: "h-10 px-4 text-base rounded-[var(--radius-md)]",
101
- lg: "h-12 px-6 text-lg rounded-[var(--radius-md)]"
102
- };
103
- return /* @__PURE__ */ jsxs(
104
- "button",
105
- {
106
- ref,
107
- className: clsx(baseStyles, variants[variant], sizes[size], className),
108
- disabled: disabled || loading,
109
- ...props,
110
- children: [
111
- loading && /* @__PURE__ */ jsxs("svg", { className: "animate-spin -ml-1 mr-2 h-4 w-4", fill: "none", viewBox: "0 0 24 24", children: [
112
- /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
113
- /* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
114
- ] }),
115
- children
116
- ]
117
- }
118
- );
119
- }
120
- );
121
- Button.displayName = "Button";
122
- var Card = React.forwardRef(
123
- ({ variant = "default", className, children, ...props }, ref) => {
124
- const variants = {
125
- default: "bg-[var(--color-background)] border border-[var(--color-border)]",
126
- elevated: "bg-[var(--color-background)] shadow-lg",
127
- outlined: "bg-transparent border-2 border-[var(--color-border)]"
128
- };
129
- return /* @__PURE__ */ jsx(
130
- "div",
131
- {
132
- ref,
133
- className: clsx(
134
- "rounded-[var(--radius-lg)] p-6",
135
- variants[variant],
136
- className
137
- ),
138
- ...props,
139
- children
140
- }
141
- );
142
- }
143
- );
144
- Card.displayName = "Card";
145
- var Input = React.forwardRef(
146
- ({ error, label, className, id, ...props }, ref) => {
147
- const inputId = id || React.useId();
148
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
149
- label && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "text-sm font-medium text-[var(--color-foreground)]", children: label }),
150
- /* @__PURE__ */ jsx(
151
- "input",
152
- {
153
- ref,
154
- id: inputId,
155
- className: clsx(
156
- "h-10 px-3 rounded-[var(--radius-md)] border bg-[var(--color-background)] text-[var(--color-foreground)]",
157
- "focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)]",
158
- error ? "border-[var(--color-error)]" : "border-[var(--color-border)]",
159
- className
160
- ),
161
- ...props
162
- }
163
- ),
164
- error && /* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--color-error)]", children: error })
165
- ] });
166
- }
167
- );
168
- Input.displayName = "Input";
169
- var Badge = React.forwardRef(
170
- ({ variant = "default", className, ...props }, ref) => {
171
- const variants = {
172
- default: "bg-[var(--color-muted)]/20 text-[var(--color-foreground)]",
173
- primary: "bg-[var(--color-primary)]/20 text-[var(--color-primary)]",
174
- success: "bg-[var(--color-success)]/20 text-[var(--color-success)]",
175
- warning: "bg-[var(--color-warning)]/20 text-[var(--color-warning)]",
176
- error: "bg-[var(--color-error)]/20 text-[var(--color-error)]"
177
- };
178
- return /* @__PURE__ */ jsx(
179
- "span",
180
- {
181
- ref,
182
- className: clsx(
183
- "inline-flex items-center px-2 py-1 text-xs font-medium rounded-[var(--radius-full)]",
184
- variants[variant],
185
- className
186
- ),
187
- ...props
188
- }
189
- );
190
- }
191
- );
192
- Badge.displayName = "Badge";
193
- function Spinner({ size = "md", className }) {
194
- const sizes = {
195
- sm: "h-4 w-4",
196
- md: "h-8 w-8",
197
- lg: "h-12 w-12"
198
- };
199
- return /* @__PURE__ */ jsxs(
200
- "svg",
201
- {
202
- className: clsx("animate-spin text-[var(--color-primary)]", sizes[size], className),
203
- fill: "none",
204
- viewBox: "0 0 24 24",
205
- children: [
206
- /* @__PURE__ */ jsx(
207
- "circle",
208
- {
209
- className: "opacity-25",
210
- cx: "12",
211
- cy: "12",
212
- r: "10",
213
- stroke: "currentColor",
214
- strokeWidth: "4"
215
- }
216
- ),
217
- /* @__PURE__ */ jsx(
218
- "path",
219
- {
220
- className: "opacity-75",
221
- fill: "currentColor",
222
- d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
223
- }
224
- )
225
- ]
226
- }
227
- );
228
- }
229
- function Avatar({ size = "md", fallback, src, alt, className, ...props }) {
230
- const [error, setError] = React.useState(false);
231
- const sizes = {
232
- sm: "h-8 w-8 text-xs",
233
- md: "h-10 w-10 text-sm",
234
- lg: "h-16 w-16 text-lg"
235
- };
236
- if (error || !src) {
237
- return /* @__PURE__ */ jsx(
238
- "div",
239
- {
240
- className: clsx(
241
- "flex items-center justify-center rounded-[var(--radius-full)] bg-[var(--color-primary)] text-white font-medium",
242
- sizes[size],
243
- className
244
- ),
245
- children: fallback || alt?.charAt(0).toUpperCase() || "?"
246
- }
247
- );
248
- }
249
- return /* @__PURE__ */ jsx(
250
- "img",
251
- {
252
- src,
253
- alt,
254
- onError: () => setError(true),
255
- className: clsx("rounded-[var(--radius-full)] object-cover", sizes[size], className),
256
- ...props
257
- }
258
- );
259
- }
260
- export {
261
- Avatar,
262
- Badge,
263
- Button,
264
- Card,
265
- Input,
266
- Spinner,
267
- ThemeProvider,
268
- themes,
269
- useTheme
270
- };