@moontra/moonui 2.0.8 → 2.0.10
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/package.json +9 -2
- package/src/__tests__/use-intersection-observer.test.tsx +216 -0
- package/src/__tests__/use-local-storage.test.tsx +174 -0
- package/src/__tests__/use-pro-access.test.tsx +183 -0
- package/src/components/ui/__tests__/accordion.test.tsx +571 -0
- package/src/components/ui/__tests__/alert.test.tsx +484 -0
- package/src/components/ui/__tests__/aspect-ratio.test.tsx +492 -0
- package/src/components/ui/__tests__/avatar.test.tsx +382 -0
- package/src/components/ui/__tests__/badge.test.tsx +364 -0
- package/src/components/ui/__tests__/breadcrumb.test.tsx +687 -0
- package/src/components/ui/__tests__/button.test.tsx +91 -0
- package/src/components/ui/__tests__/card.test.tsx +104 -0
- package/src/components/ui/__tests__/checkbox.test.tsx +591 -0
- package/src/components/ui/__tests__/collapsible.test.tsx +592 -0
- package/src/components/ui/__tests__/color-picker.test.tsx +365 -0
- package/src/components/ui/__tests__/command.test.tsx +677 -0
- package/src/components/ui/__tests__/data-table.test.tsx +256 -0
- package/src/components/ui/__tests__/date-picker.test.tsx +320 -0
- package/src/components/ui/__tests__/dialog.test.tsx +764 -0
- package/src/components/ui/__tests__/input.test.tsx +318 -0
- package/src/components/ui/__tests__/label.test.tsx +103 -0
- package/src/components/ui/__tests__/popover.test.tsx +637 -0
- package/src/components/ui/__tests__/progress.test.tsx +382 -0
- package/src/components/ui/__tests__/radio-group.test.tsx +555 -0
- package/src/components/ui/__tests__/select.test.tsx +705 -0
- package/src/components/ui/__tests__/skeleton.test.tsx +253 -0
- package/src/components/ui/__tests__/slider.test.tsx +493 -0
- package/src/components/ui/__tests__/switch.test.tsx +372 -0
- package/src/components/ui/__tests__/table.test.tsx +824 -0
- package/src/components/ui/__tests__/tabs.test.tsx +887 -0
- package/src/components/ui/__tests__/toast.test.tsx +458 -0
- package/src/components/ui/__tests__/tooltip.test.tsx +583 -0
- package/src/components/ui/accordion.tsx +63 -0
- package/src/components/ui/alert.tsx +130 -0
- package/src/components/ui/aspect-ratio.tsx +72 -0
- package/src/components/ui/avatar.tsx +135 -0
- package/src/components/ui/badge.tsx +225 -0
- package/src/components/ui/breadcrumb.tsx +207 -0
- package/src/components/ui/button.stories.tsx +162 -0
- package/src/components/ui/button.tsx +221 -0
- package/src/components/ui/calendar.tsx +262 -0
- package/src/components/ui/card.stories.tsx +208 -0
- package/src/components/ui/card.tsx +141 -0
- package/src/components/ui/checkbox.tsx +256 -0
- package/src/components/ui/collapsible.tsx +129 -0
- package/src/components/ui/color-picker.tsx +664 -0
- package/src/components/ui/command.tsx +218 -0
- package/src/components/ui/data-table.stories.tsx +509 -0
- package/src/components/ui/data-table.tsx +623 -0
- package/src/components/ui/date-picker.stories.tsx +321 -0
- package/src/components/ui/date-picker.tsx +603 -0
- package/src/components/ui/dialog.tsx +332 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/file-upload.tsx +400 -0
- package/src/components/ui/github-stars.tsx +201 -0
- package/src/components/ui/index.ts +12 -0
- package/src/components/ui/input.stories.tsx +255 -0
- package/src/components/ui/input.tsx +219 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/locked-component.tsx +215 -0
- package/src/components/ui/moon-logo.tsx +97 -0
- package/src/components/ui/pagination.tsx +116 -0
- package/src/components/ui/popover.tsx +183 -0
- package/src/components/ui/progress.tsx +182 -0
- package/src/components/ui/radio-group.tsx +243 -0
- package/src/components/ui/select.tsx +273 -0
- package/src/components/ui/separator.tsx +140 -0
- package/src/components/ui/simple-editor.tsx +652 -0
- package/src/components/ui/skeleton.tsx +351 -0
- package/src/components/ui/slider.tsx +351 -0
- package/src/components/ui/switch.tsx +83 -0
- package/src/components/ui/table.tsx +322 -0
- package/src/components/ui/tabs.tsx +195 -0
- package/src/components/ui/textarea.tsx +46 -0
- package/src/components/ui/toast.tsx +313 -0
- package/src/components/ui/toggle.tsx +47 -0
- package/src/components/ui/tooltip.tsx +152 -0
- package/src/docs/theme-system.md +1194 -0
- package/src/index.tsx +39 -0
- package/src/lib/micro-interactions.ts +255 -0
- package/src/lib/theme.tsx +398 -0
- package/src/lib/utils.ts +69 -0
- package/src/styles/design-system.css +365 -0
- package/src/styles/index.css +4 -0
- package/src/styles/tailwind.css +6 -0
- package/src/styles/tokens.css +453 -0
- package/src/use-intersection-observer.tsx +154 -0
- package/src/use-local-storage.tsx +71 -0
- package/src/use-paddle.ts +138 -0
- package/src/use-performance-optimizer.ts +379 -0
- package/src/use-pro-access.ts +141 -0
- package/src/use-scroll-animation.ts +221 -0
- package/src/use-subscription.ts +37 -0
- package/src/use-toast.ts +32 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as ToastPrimitives from "@radix-ui/react-toast";
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
|
+
import { X } from "lucide-react";
|
|
7
|
+
import { cn } from "../../lib/utils";
|
|
8
|
+
|
|
9
|
+
const ToastProvider = ToastPrimitives.Provider;
|
|
10
|
+
|
|
11
|
+
const ToastViewport = React.forwardRef<
|
|
12
|
+
React.ElementRef<typeof ToastPrimitives.Viewport>,
|
|
13
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
|
|
14
|
+
>(({ className, ...props }, ref) => (
|
|
15
|
+
<ToastPrimitives.Viewport
|
|
16
|
+
ref={ref}
|
|
17
|
+
className={cn(
|
|
18
|
+
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
));
|
|
24
|
+
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
|
|
25
|
+
|
|
26
|
+
const toastVariants = cva(
|
|
27
|
+
"group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-8 shadow-sm transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
|
|
28
|
+
{
|
|
29
|
+
variants: {
|
|
30
|
+
variant: {
|
|
31
|
+
default: "border bg-background text-foreground",
|
|
32
|
+
destructive:
|
|
33
|
+
"destructive group border-destructive bg-destructive text-destructive-foreground",
|
|
34
|
+
success:
|
|
35
|
+
"border-green-200 bg-green-50 text-green-900 dark:border-green-800 dark:bg-green-900/20 dark:text-green-100",
|
|
36
|
+
warning:
|
|
37
|
+
"border-orange-200 bg-orange-50 text-orange-900 dark:border-orange-800 dark:bg-orange-900/20 dark:text-orange-100",
|
|
38
|
+
info:
|
|
39
|
+
"border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-800 dark:bg-blue-900/20 dark:text-blue-100",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
defaultVariants: {
|
|
43
|
+
variant: "default",
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
type ToastProps = React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
|
|
49
|
+
VariantProps<typeof toastVariants>;
|
|
50
|
+
|
|
51
|
+
type ToastActionElement = React.ReactElement<typeof ToastAction>;
|
|
52
|
+
|
|
53
|
+
const Toast = React.forwardRef<
|
|
54
|
+
React.ElementRef<typeof ToastPrimitives.Root>,
|
|
55
|
+
ToastProps
|
|
56
|
+
>(({ className, variant, ...props }, ref) => {
|
|
57
|
+
return (
|
|
58
|
+
<ToastPrimitives.Root
|
|
59
|
+
ref={ref}
|
|
60
|
+
className={cn(toastVariants({ variant }), className)}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
Toast.displayName = ToastPrimitives.Root.displayName;
|
|
66
|
+
|
|
67
|
+
const ToastAction = React.forwardRef<
|
|
68
|
+
React.ElementRef<typeof ToastPrimitives.Action>,
|
|
69
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
|
|
70
|
+
>(({ className, ...props }, ref) => (
|
|
71
|
+
<ToastPrimitives.Action
|
|
72
|
+
ref={ref}
|
|
73
|
+
className={cn(
|
|
74
|
+
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-secondary focus:outline-none focus:ring-1 focus:ring-ring disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
|
|
75
|
+
className
|
|
76
|
+
)}
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
));
|
|
80
|
+
ToastAction.displayName = ToastPrimitives.Action.displayName;
|
|
81
|
+
|
|
82
|
+
const ToastClose = React.forwardRef<
|
|
83
|
+
React.ElementRef<typeof ToastPrimitives.Close>,
|
|
84
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
|
|
85
|
+
>(({ className, ...props }, ref) => (
|
|
86
|
+
<ToastPrimitives.Close
|
|
87
|
+
ref={ref}
|
|
88
|
+
className={cn(
|
|
89
|
+
"absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
|
|
90
|
+
className
|
|
91
|
+
)}
|
|
92
|
+
toast-close=""
|
|
93
|
+
{...props}
|
|
94
|
+
>
|
|
95
|
+
<X className="h-4 w-4" />
|
|
96
|
+
</ToastPrimitives.Close>
|
|
97
|
+
));
|
|
98
|
+
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
|
99
|
+
|
|
100
|
+
const ToastTitle = React.forwardRef<
|
|
101
|
+
React.ElementRef<typeof ToastPrimitives.Title>,
|
|
102
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
|
103
|
+
>(({ className, ...props }, ref) => (
|
|
104
|
+
<ToastPrimitives.Title
|
|
105
|
+
ref={ref}
|
|
106
|
+
className={cn("text-sm font-semibold [&+div]:text-xs", className)}
|
|
107
|
+
{...props}
|
|
108
|
+
/>
|
|
109
|
+
));
|
|
110
|
+
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
|
111
|
+
|
|
112
|
+
const ToastDescription = React.forwardRef<
|
|
113
|
+
React.ElementRef<typeof ToastPrimitives.Description>,
|
|
114
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
|
|
115
|
+
>(({ className, ...props }, ref) => (
|
|
116
|
+
<ToastPrimitives.Description
|
|
117
|
+
ref={ref}
|
|
118
|
+
className={cn("text-sm opacity-90", className)}
|
|
119
|
+
{...props}
|
|
120
|
+
/>
|
|
121
|
+
));
|
|
122
|
+
ToastDescription.displayName = ToastPrimitives.Description.displayName;
|
|
123
|
+
|
|
124
|
+
type ToastData = {
|
|
125
|
+
id: string;
|
|
126
|
+
title?: React.ReactNode;
|
|
127
|
+
description?: React.ReactNode;
|
|
128
|
+
action?: ToastActionElement;
|
|
129
|
+
variant?: ToastProps["variant"];
|
|
130
|
+
duration?: number;
|
|
131
|
+
open?: boolean;
|
|
132
|
+
onOpenChange?: (open: boolean) => void;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const TOAST_LIMIT = 5;
|
|
136
|
+
const TOAST_REMOVE_DELAY = 1000000;
|
|
137
|
+
|
|
138
|
+
type State = {
|
|
139
|
+
toasts: ToastData[];
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
|
143
|
+
|
|
144
|
+
const addToRemoveQueue = (toastId: string) => {
|
|
145
|
+
if (toastTimeouts.has(toastId)) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const timeout = setTimeout(() => {
|
|
150
|
+
toastTimeouts.delete(toastId);
|
|
151
|
+
dispatch({
|
|
152
|
+
type: "REMOVE_TOAST",
|
|
153
|
+
toastId: toastId,
|
|
154
|
+
});
|
|
155
|
+
}, TOAST_REMOVE_DELAY);
|
|
156
|
+
|
|
157
|
+
toastTimeouts.set(toastId, timeout);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const reducer = (state: State, action: any): State => {
|
|
161
|
+
switch (action.type) {
|
|
162
|
+
case "ADD_TOAST":
|
|
163
|
+
return {
|
|
164
|
+
...state,
|
|
165
|
+
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
case "UPDATE_TOAST":
|
|
169
|
+
return {
|
|
170
|
+
...state,
|
|
171
|
+
toasts: state.toasts.map((t) =>
|
|
172
|
+
t.id === action.toast.id ? { ...t, ...action.toast } : t
|
|
173
|
+
),
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
case "DISMISS_TOAST": {
|
|
177
|
+
const { toastId } = action;
|
|
178
|
+
|
|
179
|
+
if (toastId) {
|
|
180
|
+
addToRemoveQueue(toastId);
|
|
181
|
+
} else {
|
|
182
|
+
state.toasts.forEach((toast) => {
|
|
183
|
+
addToRemoveQueue(toast.id);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
...state,
|
|
189
|
+
toasts: state.toasts.map((t) =>
|
|
190
|
+
t.id === toastId || toastId === undefined
|
|
191
|
+
? {
|
|
192
|
+
...t,
|
|
193
|
+
open: false,
|
|
194
|
+
}
|
|
195
|
+
: t
|
|
196
|
+
),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
case "REMOVE_TOAST":
|
|
200
|
+
if (action.toastId === undefined) {
|
|
201
|
+
return {
|
|
202
|
+
...state,
|
|
203
|
+
toasts: [],
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
...state,
|
|
208
|
+
toasts: state.toasts.filter((t) => t.id !== action.toastId),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const listeners: Array<(state: State) => void> = [];
|
|
214
|
+
|
|
215
|
+
let memoryState: State = { toasts: [] };
|
|
216
|
+
let toastCounter = 0;
|
|
217
|
+
|
|
218
|
+
function dispatch(action: any) {
|
|
219
|
+
memoryState = reducer(memoryState, action);
|
|
220
|
+
listeners.forEach((listener) => {
|
|
221
|
+
listener(memoryState);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
type Toast = Omit<ToastData, "id">;
|
|
226
|
+
|
|
227
|
+
function toast({ ...props }: Toast) {
|
|
228
|
+
const id = `toast-${Date.now()}-${++toastCounter}`;
|
|
229
|
+
|
|
230
|
+
const update = (props: ToastData) =>
|
|
231
|
+
dispatch({
|
|
232
|
+
type: "UPDATE_TOAST",
|
|
233
|
+
toast: { ...props, id },
|
|
234
|
+
});
|
|
235
|
+
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
|
|
236
|
+
|
|
237
|
+
dispatch({
|
|
238
|
+
type: "ADD_TOAST",
|
|
239
|
+
toast: {
|
|
240
|
+
...props,
|
|
241
|
+
id,
|
|
242
|
+
open: true,
|
|
243
|
+
onOpenChange: (open: boolean) => {
|
|
244
|
+
if (!open) dismiss();
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
id: id,
|
|
251
|
+
dismiss,
|
|
252
|
+
update,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function useToast() {
|
|
257
|
+
const [state, setState] = React.useState<State>(memoryState);
|
|
258
|
+
|
|
259
|
+
React.useEffect(() => {
|
|
260
|
+
listeners.push(setState);
|
|
261
|
+
return () => {
|
|
262
|
+
const index = listeners.indexOf(setState);
|
|
263
|
+
if (index > -1) {
|
|
264
|
+
listeners.splice(index, 1);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}, [state]);
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
...state,
|
|
271
|
+
toast,
|
|
272
|
+
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function Toaster() {
|
|
277
|
+
const { toasts } = useToast();
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<ToastProvider>
|
|
281
|
+
{toasts.map(function ({ id, title, description, action, variant, open, onOpenChange, ...props }) {
|
|
282
|
+
return (
|
|
283
|
+
<Toast key={id} variant={variant} open={open} onOpenChange={onOpenChange} {...props}>
|
|
284
|
+
<div className="grid gap-1">
|
|
285
|
+
{title && <ToastTitle>{title}</ToastTitle>}
|
|
286
|
+
{description && (
|
|
287
|
+
<ToastDescription>{description}</ToastDescription>
|
|
288
|
+
)}
|
|
289
|
+
</div>
|
|
290
|
+
{action}
|
|
291
|
+
<ToastClose />
|
|
292
|
+
</Toast>
|
|
293
|
+
);
|
|
294
|
+
})}
|
|
295
|
+
<ToastViewport />
|
|
296
|
+
</ToastProvider>
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export {
|
|
301
|
+
type ToastProps,
|
|
302
|
+
type ToastActionElement,
|
|
303
|
+
ToastProvider,
|
|
304
|
+
ToastViewport,
|
|
305
|
+
Toast,
|
|
306
|
+
ToastTitle,
|
|
307
|
+
ToastDescription,
|
|
308
|
+
ToastAction,
|
|
309
|
+
ToastClose,
|
|
310
|
+
Toaster,
|
|
311
|
+
toast,
|
|
312
|
+
useToast,
|
|
313
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as TogglePrimitive from "@radix-ui/react-toggle"
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
6
|
+
|
|
7
|
+
import { cn } from "../../lib/utils"
|
|
8
|
+
|
|
9
|
+
const toggleVariants = cva(
|
|
10
|
+
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
|
|
11
|
+
{
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
default: "bg-transparent",
|
|
15
|
+
outline:
|
|
16
|
+
"border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
|
|
17
|
+
},
|
|
18
|
+
size: {
|
|
19
|
+
default: "h-10 px-3",
|
|
20
|
+
sm: "h-9 px-2.5",
|
|
21
|
+
lg: "h-11 px-5",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
variant: "default",
|
|
26
|
+
size: "default",
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
export interface ToggleProps extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root>, VariantProps<typeof toggleVariants> {}
|
|
32
|
+
|
|
33
|
+
const Toggle = React.forwardRef<
|
|
34
|
+
React.ElementRef<typeof TogglePrimitive.Root>,
|
|
35
|
+
ToggleProps
|
|
36
|
+
>(({ className, variant, size, ...props }, ref) => (
|
|
37
|
+
<TogglePrimitive.Root
|
|
38
|
+
ref={ref}
|
|
39
|
+
className={cn(toggleVariants({ variant, size, className }))}
|
|
40
|
+
{...props}
|
|
41
|
+
/>
|
|
42
|
+
))
|
|
43
|
+
|
|
44
|
+
Toggle.displayName = TogglePrimitive.Root.displayName
|
|
45
|
+
|
|
46
|
+
export { Toggle, toggleVariants }
|
|
47
|
+
export type { ToggleProps }
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
6
|
+
|
|
7
|
+
import { cn } from "../../lib/utils"
|
|
8
|
+
|
|
9
|
+
const TooltipProvider = TooltipPrimitive.Provider
|
|
10
|
+
|
|
11
|
+
const tooltipVariants = cva(
|
|
12
|
+
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
13
|
+
{
|
|
14
|
+
variants: {
|
|
15
|
+
variant: {
|
|
16
|
+
default: "bg-primary text-primary-foreground",
|
|
17
|
+
secondary: "bg-secondary text-secondary-foreground",
|
|
18
|
+
success: "bg-green-500 text-white border-green-600",
|
|
19
|
+
warning: "bg-yellow-500 text-white border-yellow-600",
|
|
20
|
+
destructive: "bg-destructive text-destructive-foreground",
|
|
21
|
+
info: "bg-blue-500 text-white border-blue-600",
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
sm: "px-2 py-1 text-xs",
|
|
25
|
+
md: "px-3 py-1.5 text-sm",
|
|
26
|
+
lg: "px-4 py-2 text-base",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
variant: "default",
|
|
31
|
+
size: "md",
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
const Tooltip = TooltipPrimitive.Root
|
|
37
|
+
|
|
38
|
+
const TooltipTrigger = TooltipPrimitive.Trigger
|
|
39
|
+
|
|
40
|
+
const TooltipArrow = React.forwardRef<
|
|
41
|
+
React.ElementRef<typeof TooltipPrimitive.Arrow>,
|
|
42
|
+
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Arrow>
|
|
43
|
+
>(({ className, ...props }, ref) => (
|
|
44
|
+
<TooltipPrimitive.Arrow
|
|
45
|
+
ref={ref}
|
|
46
|
+
className={cn("fill-current", className)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
))
|
|
50
|
+
TooltipArrow.displayName = TooltipPrimitive.Arrow.displayName
|
|
51
|
+
|
|
52
|
+
export interface TooltipContentProps
|
|
53
|
+
extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>,
|
|
54
|
+
VariantProps<typeof tooltipVariants> {
|
|
55
|
+
showArrow?: boolean
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const TooltipContent = React.forwardRef<
|
|
59
|
+
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
60
|
+
TooltipContentProps
|
|
61
|
+
>(({ className, variant, size, showArrow = false, sideOffset = 4, ...props }, ref) => (
|
|
62
|
+
<TooltipPrimitive.Content
|
|
63
|
+
ref={ref}
|
|
64
|
+
sideOffset={sideOffset}
|
|
65
|
+
className={cn(tooltipVariants({ variant, size }), className)}
|
|
66
|
+
{...props}
|
|
67
|
+
>
|
|
68
|
+
{props.children}
|
|
69
|
+
{showArrow && <TooltipArrow />}
|
|
70
|
+
</TooltipPrimitive.Content>
|
|
71
|
+
))
|
|
72
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName
|
|
73
|
+
|
|
74
|
+
// Simplified Tooltip component for easy usage
|
|
75
|
+
export interface SimpleTooltipProps {
|
|
76
|
+
children: React.ReactElement
|
|
77
|
+
content: React.ReactNode
|
|
78
|
+
variant?: TooltipContentProps["variant"]
|
|
79
|
+
size?: TooltipContentProps["size"]
|
|
80
|
+
side?: "top" | "right" | "bottom" | "left"
|
|
81
|
+
align?: "start" | "center" | "end"
|
|
82
|
+
delayDuration?: number
|
|
83
|
+
skipDelayDuration?: number
|
|
84
|
+
sideOffset?: number
|
|
85
|
+
showArrow?: boolean
|
|
86
|
+
className?: string
|
|
87
|
+
open?: boolean
|
|
88
|
+
defaultOpen?: boolean
|
|
89
|
+
onOpenChange?: (open: boolean) => void
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const SimpleTooltip = React.forwardRef<
|
|
93
|
+
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
94
|
+
SimpleTooltipProps
|
|
95
|
+
>(
|
|
96
|
+
(
|
|
97
|
+
{
|
|
98
|
+
children,
|
|
99
|
+
content,
|
|
100
|
+
variant = "default",
|
|
101
|
+
size = "md",
|
|
102
|
+
side = "top",
|
|
103
|
+
align = "center",
|
|
104
|
+
delayDuration = 400,
|
|
105
|
+
skipDelayDuration = 300,
|
|
106
|
+
sideOffset = 4,
|
|
107
|
+
showArrow = false,
|
|
108
|
+
className,
|
|
109
|
+
open,
|
|
110
|
+
defaultOpen,
|
|
111
|
+
onOpenChange,
|
|
112
|
+
...props
|
|
113
|
+
},
|
|
114
|
+
ref
|
|
115
|
+
) => {
|
|
116
|
+
return (
|
|
117
|
+
<Tooltip
|
|
118
|
+
open={open}
|
|
119
|
+
defaultOpen={defaultOpen}
|
|
120
|
+
onOpenChange={onOpenChange}
|
|
121
|
+
delayDuration={delayDuration}
|
|
122
|
+
skipDelayDuration={skipDelayDuration}
|
|
123
|
+
>
|
|
124
|
+
<TooltipTrigger asChild>{children}</TooltipTrigger>
|
|
125
|
+
<TooltipContent
|
|
126
|
+
ref={ref}
|
|
127
|
+
side={side}
|
|
128
|
+
align={align}
|
|
129
|
+
variant={variant}
|
|
130
|
+
size={size}
|
|
131
|
+
sideOffset={sideOffset}
|
|
132
|
+
showArrow={showArrow}
|
|
133
|
+
className={className}
|
|
134
|
+
{...props}
|
|
135
|
+
>
|
|
136
|
+
{content}
|
|
137
|
+
</TooltipContent>
|
|
138
|
+
</Tooltip>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
SimpleTooltip.displayName = "SimpleTooltip"
|
|
143
|
+
|
|
144
|
+
export {
|
|
145
|
+
Tooltip,
|
|
146
|
+
TooltipProvider,
|
|
147
|
+
TooltipTrigger,
|
|
148
|
+
TooltipContent,
|
|
149
|
+
TooltipArrow,
|
|
150
|
+
SimpleTooltip,
|
|
151
|
+
tooltipVariants,
|
|
152
|
+
}
|