@moontra/moonui-pro 2.20.2 → 2.20.4
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 +8 -3
- package/plugin/index.d.ts +86 -0
- package/plugin/index.js +308 -0
- package/scripts/postinstall.js +191 -23
- package/src/components/advanced-chart/index.tsx +0 -1246
- package/src/components/advanced-forms/index.tsx +0 -585
- package/src/components/animated-button/index.tsx +0 -385
- package/src/components/calendar/event-dialog.tsx +0 -377
- package/src/components/calendar/index.tsx +0 -1220
- package/src/components/calendar-pro/index.tsx +0 -1697
- package/src/components/color-picker/index.tsx +0 -432
- package/src/components/credit-card-input/index.tsx +0 -406
- package/src/components/dashboard/dashboard-grid.tsx +0 -480
- package/src/components/dashboard/demo.tsx +0 -425
- package/src/components/dashboard/index.tsx +0 -1046
- package/src/components/dashboard/time-range-picker.tsx +0 -336
- package/src/components/dashboard/types.ts +0 -225
- package/src/components/dashboard/widgets/activity-feed.tsx +0 -349
- package/src/components/dashboard/widgets/chart-widget.tsx +0 -418
- package/src/components/dashboard/widgets/comparison-widget.tsx +0 -177
- package/src/components/dashboard/widgets/index.ts +0 -5
- package/src/components/dashboard/widgets/metric-card.tsx +0 -363
- package/src/components/dashboard/widgets/progress-widget.tsx +0 -113
- package/src/components/data-table/data-table-bulk-actions.tsx +0 -204
- package/src/components/data-table/data-table-column-toggle.tsx +0 -169
- package/src/components/data-table/data-table-export.ts +0 -156
- package/src/components/data-table/data-table-filter-drawer.tsx +0 -448
- package/src/components/data-table/index.tsx +0 -845
- package/src/components/draggable-list/index.tsx +0 -100
- package/src/components/error-boundary/index.tsx +0 -232
- package/src/components/file-upload/index.tsx +0 -1660
- package/src/components/floating-action-button/index.tsx +0 -206
- package/src/components/form-wizard/form-wizard-context.tsx +0 -335
- package/src/components/form-wizard/form-wizard-navigation.tsx +0 -118
- package/src/components/form-wizard/form-wizard-progress.tsx +0 -329
- package/src/components/form-wizard/form-wizard-step.tsx +0 -111
- package/src/components/form-wizard/index.tsx +0 -102
- package/src/components/form-wizard/types.ts +0 -77
- package/src/components/gesture-drawer/index.tsx +0 -551
- package/src/components/github-stars/github-api.ts +0 -426
- package/src/components/github-stars/hooks.ts +0 -517
- package/src/components/github-stars/index.tsx +0 -375
- package/src/components/github-stars/types.ts +0 -148
- package/src/components/github-stars/variants.tsx +0 -515
- package/src/components/health-check/index.tsx +0 -439
- package/src/components/hover-card-3d/index.tsx +0 -529
- package/src/components/index.ts +0 -130
- package/src/components/internal/index.ts +0 -78
- package/src/components/kanban/add-card-modal.tsx +0 -502
- package/src/components/kanban/card-detail-modal.tsx +0 -761
- package/src/components/kanban/index.ts +0 -13
- package/src/components/kanban/kanban.tsx +0 -1689
- package/src/components/kanban/types.ts +0 -168
- package/src/components/lazy-component/index.tsx +0 -823
- package/src/components/license-error/index.tsx +0 -31
- package/src/components/magnetic-button/index.tsx +0 -216
- package/src/components/memory-efficient-data/index.tsx +0 -1018
- package/src/components/moonui-quiz-form/index.tsx +0 -817
- package/src/components/navbar/index.tsx +0 -781
- package/src/components/optimized-image/index.tsx +0 -425
- package/src/components/performance-debugger/index.tsx +0 -613
- package/src/components/performance-monitor/index.tsx +0 -808
- package/src/components/phone-number-input/index.tsx +0 -343
- package/src/components/phone-number-input/phone-number-input-simple.tsx +0 -167
- package/src/components/pinch-zoom/index.tsx +0 -566
- package/src/components/quiz-form/index.tsx +0 -479
- package/src/components/rich-text-editor/index.tsx +0 -2322
- package/src/components/rich-text-editor/slash-commands-extension.ts +0 -230
- package/src/components/rich-text-editor/slash-commands.css +0 -35
- package/src/components/rich-text-editor/table-styles.css +0 -65
- package/src/components/sidebar/index.tsx +0 -884
- package/src/components/spotlight-card/index.tsx +0 -191
- package/src/components/swipeable-card/index.tsx +0 -100
- package/src/components/timeline/index.tsx +0 -1183
- package/src/components/ui/accordion.tsx +0 -581
- package/src/components/ui/alert-dialog.tsx +0 -141
- package/src/components/ui/alert.tsx +0 -141
- package/src/components/ui/aspect-ratio.tsx +0 -245
- package/src/components/ui/avatar.tsx +0 -155
- package/src/components/ui/badge.tsx +0 -230
- package/src/components/ui/breadcrumb.tsx +0 -216
- package/src/components/ui/button.tsx +0 -228
- package/src/components/ui/calendar.tsx +0 -387
- package/src/components/ui/card.tsx +0 -216
- package/src/components/ui/checkbox.tsx +0 -259
- package/src/components/ui/collapsible.tsx +0 -631
- package/src/components/ui/color-picker.tsx +0 -97
- package/src/components/ui/command.tsx +0 -948
- package/src/components/ui/dialog.tsx +0 -752
- package/src/components/ui/dropdown-menu.tsx +0 -706
- package/src/components/ui/gesture-drawer.tsx +0 -11
- package/src/components/ui/hover-card.tsx +0 -29
- package/src/components/ui/index.ts +0 -222
- package/src/components/ui/input.tsx +0 -224
- package/src/components/ui/label.tsx +0 -29
- package/src/components/ui/lightbox.tsx +0 -606
- package/src/components/ui/magnetic-button.tsx +0 -129
- package/src/components/ui/media-gallery.tsx +0 -611
- package/src/components/ui/navigation-menu.tsx +0 -130
- package/src/components/ui/pagination.tsx +0 -125
- package/src/components/ui/popover.tsx +0 -185
- package/src/components/ui/progress.tsx +0 -30
- package/src/components/ui/radio-group.tsx +0 -257
- package/src/components/ui/scroll-area.tsx +0 -47
- package/src/components/ui/select.tsx +0 -378
- package/src/components/ui/separator.tsx +0 -145
- package/src/components/ui/sheet.tsx +0 -139
- package/src/components/ui/skeleton.tsx +0 -20
- package/src/components/ui/slider.tsx +0 -354
- package/src/components/ui/spotlight-card.tsx +0 -119
- package/src/components/ui/switch.tsx +0 -86
- package/src/components/ui/table.tsx +0 -331
- package/src/components/ui/tabs-pro.tsx +0 -542
- package/src/components/ui/tabs.tsx +0 -54
- package/src/components/ui/textarea.tsx +0 -28
- package/src/components/ui/toast.tsx +0 -317
- package/src/components/ui/toggle.tsx +0 -119
- package/src/components/ui/tooltip.tsx +0 -151
- package/src/components/virtual-list/index.tsx +0 -668
- package/src/hooks/use-chart.ts +0 -205
- package/src/hooks/use-data-table.ts +0 -182
- package/src/hooks/use-docs-pro-access.ts +0 -13
- package/src/hooks/use-license-check.ts +0 -65
- package/src/hooks/use-subscription.ts +0 -19
- package/src/hooks/use-toast.ts +0 -15
- package/src/index.ts +0 -22
- package/src/lib/ai-providers.ts +0 -377
- package/src/lib/component-metadata.ts +0 -18
- package/src/lib/micro-interactions.ts +0 -255
- package/src/lib/paddle.ts +0 -17
- package/src/lib/utils.ts +0 -6
- package/src/patterns/login-form/index.tsx +0 -276
- package/src/patterns/login-form/types.ts +0 -67
- package/src/setupTests.ts +0 -41
- package/src/styles/advanced-chart.css +0 -239
- package/src/styles/calendar.css +0 -35
- package/src/styles/design-system.css +0 -363
- package/src/styles/index.css +0 -681
- package/src/styles/tailwind.css +0 -7
- package/src/styles/tokens.css +0 -455
- package/src/types/next-auth.d.ts +0 -21
- package/src/use-intersection-observer.tsx +0 -154
- package/src/use-local-storage.tsx +0 -71
- package/src/use-paddle.ts +0 -138
- package/src/use-performance-optimizer.ts +0 -389
- package/src/use-pro-access.ts +0 -141
- package/src/use-scroll-animation.ts +0 -219
- package/src/use-subscription.ts +0 -37
- package/src/use-toast.ts +0 -32
- package/src/utils/chart-helpers.ts +0 -357
- package/src/utils/cn.ts +0 -6
- package/src/utils/data-processing.ts +0 -151
- package/src/utils/license-validator.tsx +0 -183
|
@@ -1,542 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
5
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
|
-
import { motion, AnimatePresence, type Variants } from "framer-motion";
|
|
7
|
-
import { X, Plus, ChevronLeft, ChevronRight, MoreHorizontal, Loader2 } from "lucide-react";
|
|
8
|
-
import { cn } from "../../lib/utils";
|
|
9
|
-
import { Button } from "./button";
|
|
10
|
-
import {
|
|
11
|
-
DropdownMenu,
|
|
12
|
-
DropdownMenuContent,
|
|
13
|
-
DropdownMenuItem,
|
|
14
|
-
DropdownMenuTrigger,
|
|
15
|
-
} from "./dropdown-menu";
|
|
16
|
-
|
|
17
|
-
// Animation variants
|
|
18
|
-
const contentVariants: Record<string, Variants> = {
|
|
19
|
-
fade: {
|
|
20
|
-
initial: { opacity: 0 },
|
|
21
|
-
animate: { opacity: 1 },
|
|
22
|
-
exit: { opacity: 0 },
|
|
23
|
-
},
|
|
24
|
-
slide: {
|
|
25
|
-
initial: { x: 20, opacity: 0 },
|
|
26
|
-
animate: { x: 0, opacity: 1 },
|
|
27
|
-
exit: { x: -20, opacity: 0 },
|
|
28
|
-
},
|
|
29
|
-
scale: {
|
|
30
|
-
initial: { scale: 0.95, opacity: 0 },
|
|
31
|
-
animate: { scale: 1, opacity: 1 },
|
|
32
|
-
exit: { scale: 1.05, opacity: 0 },
|
|
33
|
-
},
|
|
34
|
-
flip: {
|
|
35
|
-
initial: { rotateY: 90, opacity: 0 },
|
|
36
|
-
animate: { rotateY: 0, opacity: 1 },
|
|
37
|
-
exit: { rotateY: -90, opacity: 0 },
|
|
38
|
-
},
|
|
39
|
-
morph: {
|
|
40
|
-
initial: { scale: 0.8, opacity: 0, filter: "blur(10px)" },
|
|
41
|
-
animate: { scale: 1, opacity: 1, filter: "blur(0px)" },
|
|
42
|
-
exit: { scale: 1.2, opacity: 0, filter: "blur(10px)" },
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// Tab item type
|
|
47
|
-
interface TabItem {
|
|
48
|
-
value: string;
|
|
49
|
-
label: React.ReactNode;
|
|
50
|
-
icon?: React.ReactNode;
|
|
51
|
-
badge?: React.ReactNode;
|
|
52
|
-
closeable?: boolean;
|
|
53
|
-
disabled?: boolean;
|
|
54
|
-
content?: React.ReactNode;
|
|
55
|
-
lazy?: boolean;
|
|
56
|
-
tooltip?: string;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Pro Tabs Root
|
|
60
|
-
interface MoonUITabsProProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>, 'orientation'> {
|
|
61
|
-
/** Visual variant */
|
|
62
|
-
variant?: "default" | "pills" | "underline" | "cards" | "minimal" | "gradient" | "glassmorphism" | "neon";
|
|
63
|
-
/** Animation mode */
|
|
64
|
-
animationMode?: "fade" | "slide" | "scale" | "flip" | "morph" | "none";
|
|
65
|
-
/** Orientation */
|
|
66
|
-
orientation?: "horizontal" | "vertical";
|
|
67
|
-
/** Allow closing tabs */
|
|
68
|
-
closeable?: boolean;
|
|
69
|
-
/** Allow adding tabs */
|
|
70
|
-
addable?: boolean;
|
|
71
|
-
/** Allow reordering tabs */
|
|
72
|
-
draggable?: boolean;
|
|
73
|
-
/** Persist state to localStorage */
|
|
74
|
-
persistKey?: string;
|
|
75
|
-
/** Sync with URL */
|
|
76
|
-
urlSync?: boolean;
|
|
77
|
-
/** Lazy load tab content */
|
|
78
|
-
lazy?: boolean;
|
|
79
|
-
/** Tab items for dynamic tabs */
|
|
80
|
-
items?: TabItem[];
|
|
81
|
-
/** Callback when tabs change */
|
|
82
|
-
onTabsChange?: (items: TabItem[]) => void;
|
|
83
|
-
/** Callback when tab is closed */
|
|
84
|
-
onTabClose?: (value: string) => void;
|
|
85
|
-
/** Callback when tab is added */
|
|
86
|
-
onTabAdd?: () => void;
|
|
87
|
-
/** Loading state */
|
|
88
|
-
loading?: boolean;
|
|
89
|
-
/** Swipeable on mobile */
|
|
90
|
-
swipeable?: boolean;
|
|
91
|
-
/** Show scroll buttons */
|
|
92
|
-
scrollable?: boolean;
|
|
93
|
-
/** Analytics callback */
|
|
94
|
-
onAnalytics?: (event: string, data: any) => void;
|
|
95
|
-
/** Tab validation before switching */
|
|
96
|
-
onBeforeChange?: (from: string, to: string) => boolean | Promise<boolean>;
|
|
97
|
-
/** Keyboard shortcuts */
|
|
98
|
-
shortcuts?: boolean;
|
|
99
|
-
/** Max tabs */
|
|
100
|
-
maxTabs?: number;
|
|
101
|
-
/** Tab groups */
|
|
102
|
-
groups?: Array<{ label: string; tabs: string[] }>;
|
|
103
|
-
className?: string;
|
|
104
|
-
children?: React.ReactNode;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const MoonUITabsPro = React.forwardRef<
|
|
108
|
-
React.ElementRef<typeof TabsPrimitive.Root>,
|
|
109
|
-
MoonUITabsProProps
|
|
110
|
-
>(({
|
|
111
|
-
variant = "default",
|
|
112
|
-
animationMode = "fade",
|
|
113
|
-
orientation = "horizontal",
|
|
114
|
-
closeable = false,
|
|
115
|
-
addable = false,
|
|
116
|
-
draggable = false,
|
|
117
|
-
persistKey,
|
|
118
|
-
urlSync = false,
|
|
119
|
-
lazy = false,
|
|
120
|
-
items: initialItems = [],
|
|
121
|
-
onTabsChange,
|
|
122
|
-
onTabClose,
|
|
123
|
-
onTabAdd,
|
|
124
|
-
loading = false,
|
|
125
|
-
swipeable = false,
|
|
126
|
-
scrollable = false,
|
|
127
|
-
onAnalytics,
|
|
128
|
-
onBeforeChange,
|
|
129
|
-
shortcuts = false,
|
|
130
|
-
maxTabs,
|
|
131
|
-
groups,
|
|
132
|
-
className,
|
|
133
|
-
children,
|
|
134
|
-
value: controlledValue,
|
|
135
|
-
defaultValue,
|
|
136
|
-
onValueChange,
|
|
137
|
-
...props
|
|
138
|
-
}, ref) => {
|
|
139
|
-
const [items, setItems] = React.useState<TabItem[]>(initialItems);
|
|
140
|
-
const [localValue, setLocalValue] = React.useState(() => {
|
|
141
|
-
// Check persistence
|
|
142
|
-
if (persistKey && typeof window !== 'undefined') {
|
|
143
|
-
const stored = localStorage.getItem(`tabs-${persistKey}`);
|
|
144
|
-
if (stored) {
|
|
145
|
-
const parsed = JSON.parse(stored);
|
|
146
|
-
return parsed.activeTab || defaultValue || items[0]?.value;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
// Check URL
|
|
150
|
-
if (urlSync && typeof window !== 'undefined') {
|
|
151
|
-
const params = new URLSearchParams(window.location.search);
|
|
152
|
-
const tabParam = params.get('tab');
|
|
153
|
-
if (tabParam) return tabParam;
|
|
154
|
-
}
|
|
155
|
-
return defaultValue || items[0]?.value;
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
const [loadedTabs, setLoadedTabs] = React.useState<Set<string>>(new Set());
|
|
159
|
-
const [isChanging, setIsChanging] = React.useState(false);
|
|
160
|
-
const scrollRef = React.useRef<HTMLDivElement>(null);
|
|
161
|
-
|
|
162
|
-
const value = controlledValue !== undefined ? controlledValue : localValue;
|
|
163
|
-
|
|
164
|
-
// Handle value change
|
|
165
|
-
const handleValueChange = React.useCallback(async (newValue: string) => {
|
|
166
|
-
if (loading || isChanging) return;
|
|
167
|
-
|
|
168
|
-
// Validation
|
|
169
|
-
if (onBeforeChange) {
|
|
170
|
-
setIsChanging(true);
|
|
171
|
-
const canChange = await onBeforeChange(value || '', newValue);
|
|
172
|
-
setIsChanging(false);
|
|
173
|
-
if (!canChange) return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
setLocalValue(newValue);
|
|
177
|
-
onValueChange?.(newValue);
|
|
178
|
-
|
|
179
|
-
// Track lazy loading
|
|
180
|
-
if (lazy && !loadedTabs.has(newValue)) {
|
|
181
|
-
setLoadedTabs(prev => new Set([...prev, newValue]));
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Analytics
|
|
185
|
-
onAnalytics?.('tab_switch', { from: value, to: newValue });
|
|
186
|
-
|
|
187
|
-
// Persistence
|
|
188
|
-
if (persistKey && typeof window !== 'undefined') {
|
|
189
|
-
localStorage.setItem(`tabs-${persistKey}`, JSON.stringify({
|
|
190
|
-
activeTab: newValue,
|
|
191
|
-
tabs: items
|
|
192
|
-
}));
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// URL sync
|
|
196
|
-
if (urlSync && typeof window !== 'undefined') {
|
|
197
|
-
const params = new URLSearchParams(window.location.search);
|
|
198
|
-
params.set('tab', newValue);
|
|
199
|
-
window.history.replaceState({}, '', `${window.location.pathname}?${params}`);
|
|
200
|
-
}
|
|
201
|
-
}, [value, loading, isChanging, onBeforeChange, onValueChange, lazy, loadedTabs, onAnalytics, persistKey, items, urlSync]);
|
|
202
|
-
|
|
203
|
-
// Handle tab close
|
|
204
|
-
const handleTabClose = React.useCallback((tabValue: string, e: React.MouseEvent) => {
|
|
205
|
-
e.stopPropagation();
|
|
206
|
-
|
|
207
|
-
const newItems = items.filter(item => item.value !== tabValue);
|
|
208
|
-
setItems(newItems);
|
|
209
|
-
onTabsChange?.(newItems);
|
|
210
|
-
onTabClose?.(tabValue);
|
|
211
|
-
onAnalytics?.('tab_close', { value: tabValue });
|
|
212
|
-
|
|
213
|
-
// If closing active tab, switch to first available
|
|
214
|
-
if (value === tabValue && newItems.length > 0) {
|
|
215
|
-
handleValueChange(newItems[0].value);
|
|
216
|
-
}
|
|
217
|
-
}, [items, value, onTabsChange, onTabClose, onAnalytics, handleValueChange]);
|
|
218
|
-
|
|
219
|
-
// Handle tab add
|
|
220
|
-
const handleTabAdd = React.useCallback(() => {
|
|
221
|
-
if (maxTabs && items.length >= maxTabs) {
|
|
222
|
-
onAnalytics?.('tab_add_blocked', { reason: 'max_tabs' });
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
onTabAdd?.();
|
|
227
|
-
onAnalytics?.('tab_add', { count: items.length + 1 });
|
|
228
|
-
}, [items.length, maxTabs, onTabAdd, onAnalytics]);
|
|
229
|
-
|
|
230
|
-
// Keyboard shortcuts
|
|
231
|
-
React.useEffect(() => {
|
|
232
|
-
if (!shortcuts) return;
|
|
233
|
-
|
|
234
|
-
const handleKeyDown = (e: KeyboardEvent) => {
|
|
235
|
-
// Ctrl/Cmd + number to switch tabs
|
|
236
|
-
if ((e.metaKey || e.ctrlKey) && e.key >= '1' && e.key <= '9') {
|
|
237
|
-
e.preventDefault();
|
|
238
|
-
const index = parseInt(e.key) - 1;
|
|
239
|
-
if (items[index]) {
|
|
240
|
-
handleValueChange(items[index].value);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
// Ctrl/Cmd + W to close current tab
|
|
244
|
-
if ((e.metaKey || e.ctrlKey) && e.key === 'w' && closeable) {
|
|
245
|
-
e.preventDefault();
|
|
246
|
-
const currentTab = items.find(item => item.value === value);
|
|
247
|
-
if (currentTab?.closeable !== false) {
|
|
248
|
-
handleTabClose(value || '', new MouseEvent('click') as any);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
// Ctrl/Cmd + T to add new tab
|
|
252
|
-
if ((e.metaKey || e.ctrlKey) && e.key === 't' && addable) {
|
|
253
|
-
e.preventDefault();
|
|
254
|
-
handleTabAdd();
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
document.addEventListener('keydown', handleKeyDown);
|
|
259
|
-
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
260
|
-
}, [shortcuts, items, value, closeable, addable, handleValueChange, handleTabClose, handleTabAdd]);
|
|
261
|
-
|
|
262
|
-
// Scroll buttons
|
|
263
|
-
const scrollLeft = () => {
|
|
264
|
-
if (scrollRef.current) {
|
|
265
|
-
scrollRef.current.scrollBy({ left: -200, behavior: 'smooth' });
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
const scrollRight = () => {
|
|
270
|
-
if (scrollRef.current) {
|
|
271
|
-
scrollRef.current.scrollBy({ left: 200, behavior: 'smooth' });
|
|
272
|
-
}
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
return (
|
|
276
|
-
<div className={cn(
|
|
277
|
-
"relative w-full",
|
|
278
|
-
variant === "gradient" && "bg-gradient-to-r from-primary/10 to-secondary/10 rounded-lg p-1",
|
|
279
|
-
variant === "glassmorphism" && "backdrop-blur-xl bg-white/10 dark:bg-black/10 border border-white/20 dark:border-white/10 rounded-lg p-1",
|
|
280
|
-
variant === "neon" && "bg-black rounded-lg p-1 shadow-[0_0_20px_rgba(139,92,246,0.3)]",
|
|
281
|
-
className
|
|
282
|
-
)}>
|
|
283
|
-
{loading && (
|
|
284
|
-
<div className="absolute inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm rounded-lg">
|
|
285
|
-
<Loader2 className="h-6 w-6 animate-spin text-primary" />
|
|
286
|
-
</div>
|
|
287
|
-
)}
|
|
288
|
-
|
|
289
|
-
<TabsPrimitive.Root
|
|
290
|
-
ref={ref}
|
|
291
|
-
value={value}
|
|
292
|
-
onValueChange={handleValueChange}
|
|
293
|
-
orientation={orientation}
|
|
294
|
-
{...props}
|
|
295
|
-
>
|
|
296
|
-
{/* If items are provided, render items-based tabs */}
|
|
297
|
-
{items.length > 0 ? (
|
|
298
|
-
<>
|
|
299
|
-
<div className={cn(
|
|
300
|
-
"relative flex items-center",
|
|
301
|
-
orientation === "vertical" && "flex-col items-start"
|
|
302
|
-
)}>
|
|
303
|
-
{/* Scroll button left */}
|
|
304
|
-
{scrollable && orientation === "horizontal" && (
|
|
305
|
-
<Button
|
|
306
|
-
variant="ghost"
|
|
307
|
-
size="sm"
|
|
308
|
-
className="h-8 w-8 p-0 absolute left-0 z-10"
|
|
309
|
-
onClick={scrollLeft}
|
|
310
|
-
>
|
|
311
|
-
<ChevronLeft className="h-4 w-4" />
|
|
312
|
-
</Button>
|
|
313
|
-
)}
|
|
314
|
-
|
|
315
|
-
{/* Tabs List */}
|
|
316
|
-
<div
|
|
317
|
-
ref={scrollRef}
|
|
318
|
-
className={cn(
|
|
319
|
-
"flex-1 overflow-x-auto scrollbar-hide",
|
|
320
|
-
scrollable && orientation === "horizontal" && "mx-10"
|
|
321
|
-
)}
|
|
322
|
-
>
|
|
323
|
-
<TabsPrimitive.List
|
|
324
|
-
className={cn(
|
|
325
|
-
"flex items-center gap-1",
|
|
326
|
-
orientation === "vertical" && "flex-col items-start w-full",
|
|
327
|
-
variant === "underline" && "border-b border-border"
|
|
328
|
-
)}
|
|
329
|
-
>
|
|
330
|
-
{items.map((item, index) => (
|
|
331
|
-
<motion.div
|
|
332
|
-
key={item.value}
|
|
333
|
-
layout
|
|
334
|
-
drag={draggable ? orientation === "horizontal" ? "x" : "y" : false}
|
|
335
|
-
dragConstraints={{ left: 0, right: 0, top: 0, bottom: 0 }}
|
|
336
|
-
dragElastic={0.2}
|
|
337
|
-
whileDrag={{ scale: 1.05, zIndex: 50 }}
|
|
338
|
-
className="relative"
|
|
339
|
-
>
|
|
340
|
-
<TabsPrimitive.Trigger
|
|
341
|
-
value={item.value}
|
|
342
|
-
disabled={item.disabled}
|
|
343
|
-
className={cn(
|
|
344
|
-
"relative inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
345
|
-
// Variant styles
|
|
346
|
-
variant === "default" && "data-[state=active]:bg-background data-[state=active]:shadow-sm",
|
|
347
|
-
variant === "pills" && "rounded-full data-[state=active]:bg-primary data-[state=active]:text-primary-foreground",
|
|
348
|
-
variant === "underline" && "rounded-none border-b-2 border-transparent data-[state=active]:border-primary",
|
|
349
|
-
variant === "cards" && "bg-muted/50 data-[state=active]:bg-background data-[state=active]:shadow-md",
|
|
350
|
-
variant === "minimal" && "hover:bg-muted/50 data-[state=active]:bg-transparent data-[state=active]:underline",
|
|
351
|
-
variant === "gradient" && "data-[state=active]:bg-gradient-to-r data-[state=active]:from-primary data-[state=active]:to-secondary data-[state=active]:text-white",
|
|
352
|
-
variant === "glassmorphism" && "backdrop-blur-md data-[state=active]:bg-white/20 dark:data-[state=active]:bg-white/10",
|
|
353
|
-
variant === "neon" && "text-purple-400 data-[state=active]:text-white data-[state=active]:shadow-[0_0_10px_rgba(139,92,246,0.8)]",
|
|
354
|
-
orientation === "vertical" && "w-full justify-start"
|
|
355
|
-
)}
|
|
356
|
-
>
|
|
357
|
-
{item.icon && <span className="mr-2">{item.icon}</span>}
|
|
358
|
-
{item.label}
|
|
359
|
-
{item.badge && <span className="ml-2">{item.badge}</span>}
|
|
360
|
-
{closeable && item.closeable !== false && (
|
|
361
|
-
<button
|
|
362
|
-
onClick={(e) => handleTabClose(item.value, e)}
|
|
363
|
-
className="ml-2 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"
|
|
364
|
-
>
|
|
365
|
-
<X className="h-3 w-3" />
|
|
366
|
-
</button>
|
|
367
|
-
)}
|
|
368
|
-
</TabsPrimitive.Trigger>
|
|
369
|
-
|
|
370
|
-
{/* Active indicator animation */}
|
|
371
|
-
{value === item.value && animationMode !== "none" && (
|
|
372
|
-
<motion.div
|
|
373
|
-
layoutId="active-tab"
|
|
374
|
-
className={cn(
|
|
375
|
-
"absolute inset-0 -z-10",
|
|
376
|
-
variant === "default" && "bg-background shadow-sm rounded-md",
|
|
377
|
-
variant === "pills" && "bg-primary rounded-full",
|
|
378
|
-
variant === "underline" && "bottom-0 h-0.5 bg-primary"
|
|
379
|
-
)}
|
|
380
|
-
transition={{
|
|
381
|
-
type: "spring",
|
|
382
|
-
stiffness: 500,
|
|
383
|
-
damping: 30
|
|
384
|
-
}}
|
|
385
|
-
/>
|
|
386
|
-
)}
|
|
387
|
-
</motion.div>
|
|
388
|
-
))}
|
|
389
|
-
|
|
390
|
-
{/* Add tab button */}
|
|
391
|
-
{addable && (
|
|
392
|
-
<Button
|
|
393
|
-
variant="ghost"
|
|
394
|
-
size="sm"
|
|
395
|
-
onClick={handleTabAdd}
|
|
396
|
-
className="h-8 w-8 p-0 ml-2"
|
|
397
|
-
disabled={maxTabs ? items.length >= maxTabs : false}
|
|
398
|
-
>
|
|
399
|
-
<Plus className="h-4 w-4" />
|
|
400
|
-
</Button>
|
|
401
|
-
)}
|
|
402
|
-
</TabsPrimitive.List>
|
|
403
|
-
</div>
|
|
404
|
-
|
|
405
|
-
{/* Scroll button right */}
|
|
406
|
-
{scrollable && orientation === "horizontal" && (
|
|
407
|
-
<Button
|
|
408
|
-
variant="ghost"
|
|
409
|
-
size="sm"
|
|
410
|
-
className="h-8 w-8 p-0 absolute right-0 z-10"
|
|
411
|
-
onClick={scrollRight}
|
|
412
|
-
>
|
|
413
|
-
<ChevronRight className="h-4 w-4" />
|
|
414
|
-
</Button>
|
|
415
|
-
)}
|
|
416
|
-
|
|
417
|
-
{/* Overflow menu for hidden tabs */}
|
|
418
|
-
{items.length > 5 && (
|
|
419
|
-
<DropdownMenu>
|
|
420
|
-
<DropdownMenuTrigger asChild>
|
|
421
|
-
<Button variant="ghost" size="sm" className="h-8 w-8 p-0 ml-2">
|
|
422
|
-
<MoreHorizontal className="h-4 w-4" />
|
|
423
|
-
</Button>
|
|
424
|
-
</DropdownMenuTrigger>
|
|
425
|
-
<DropdownMenuContent align="end">
|
|
426
|
-
{items.slice(5).map(item => (
|
|
427
|
-
<DropdownMenuItem
|
|
428
|
-
key={item.value}
|
|
429
|
-
onClick={() => handleValueChange(item.value)}
|
|
430
|
-
>
|
|
431
|
-
{item.icon && <span className="mr-2">{item.icon}</span>}
|
|
432
|
-
{item.label}
|
|
433
|
-
</DropdownMenuItem>
|
|
434
|
-
))}
|
|
435
|
-
</DropdownMenuContent>
|
|
436
|
-
</DropdownMenu>
|
|
437
|
-
)}
|
|
438
|
-
</div>
|
|
439
|
-
|
|
440
|
-
{/* Tab contents with animations */}
|
|
441
|
-
{animationMode !== "none" ? (
|
|
442
|
-
<AnimatePresence mode="wait">
|
|
443
|
-
{items.map(item => {
|
|
444
|
-
if (value !== item.value) return null;
|
|
445
|
-
|
|
446
|
-
return (
|
|
447
|
-
<TabsPrimitive.Content
|
|
448
|
-
key={item.value}
|
|
449
|
-
value={item.value}
|
|
450
|
-
forceMount
|
|
451
|
-
className="mt-4 focus-visible:outline-none"
|
|
452
|
-
>
|
|
453
|
-
<motion.div
|
|
454
|
-
initial="initial"
|
|
455
|
-
animate="animate"
|
|
456
|
-
exit="exit"
|
|
457
|
-
variants={contentVariants[animationMode]}
|
|
458
|
-
transition={{ duration: 0.3 }}
|
|
459
|
-
>
|
|
460
|
-
{item.content || children}
|
|
461
|
-
</motion.div>
|
|
462
|
-
</TabsPrimitive.Content>
|
|
463
|
-
);
|
|
464
|
-
})}
|
|
465
|
-
</AnimatePresence>
|
|
466
|
-
) : (
|
|
467
|
-
items.map(item => (
|
|
468
|
-
<TabsPrimitive.Content
|
|
469
|
-
key={item.value}
|
|
470
|
-
value={item.value}
|
|
471
|
-
className="mt-4 focus-visible:outline-none"
|
|
472
|
-
>
|
|
473
|
-
{item.content || children}
|
|
474
|
-
</TabsPrimitive.Content>
|
|
475
|
-
))
|
|
476
|
-
)}
|
|
477
|
-
</>
|
|
478
|
-
) : (
|
|
479
|
-
/* Otherwise, render children-based tabs */
|
|
480
|
-
children
|
|
481
|
-
)}
|
|
482
|
-
</TabsPrimitive.Root>
|
|
483
|
-
</div>
|
|
484
|
-
);
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
MoonUITabsPro.displayName = "MoonUITabsPro";
|
|
488
|
-
|
|
489
|
-
// Additional Pro Tab Components
|
|
490
|
-
const MoonUITabsListPro = React.forwardRef<
|
|
491
|
-
React.ElementRef<typeof TabsPrimitive.List>,
|
|
492
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
|
493
|
-
>(({ className, ...props }, ref) => (
|
|
494
|
-
<TabsPrimitive.List
|
|
495
|
-
ref={ref}
|
|
496
|
-
className={cn(
|
|
497
|
-
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
|
|
498
|
-
className
|
|
499
|
-
)}
|
|
500
|
-
{...props}
|
|
501
|
-
/>
|
|
502
|
-
));
|
|
503
|
-
MoonUITabsListPro.displayName = "MoonUITabsListPro";
|
|
504
|
-
|
|
505
|
-
const MoonUITabsTriggerPro = React.forwardRef<
|
|
506
|
-
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
507
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
508
|
-
>(({ className, ...props }, ref) => (
|
|
509
|
-
<TabsPrimitive.Trigger
|
|
510
|
-
ref={ref}
|
|
511
|
-
className={cn(
|
|
512
|
-
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all 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=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
|
|
513
|
-
className
|
|
514
|
-
)}
|
|
515
|
-
{...props}
|
|
516
|
-
/>
|
|
517
|
-
));
|
|
518
|
-
MoonUITabsTriggerPro.displayName = "MoonUITabsTriggerPro";
|
|
519
|
-
|
|
520
|
-
const MoonUITabsContentPro = React.forwardRef<
|
|
521
|
-
React.ElementRef<typeof TabsPrimitive.Content>,
|
|
522
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
|
523
|
-
>(({ className, ...props }, ref) => (
|
|
524
|
-
<TabsPrimitive.Content
|
|
525
|
-
ref={ref}
|
|
526
|
-
className={cn(
|
|
527
|
-
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
528
|
-
className
|
|
529
|
-
)}
|
|
530
|
-
{...props}
|
|
531
|
-
/>
|
|
532
|
-
));
|
|
533
|
-
MoonUITabsContentPro.displayName = "MoonUITabsContentPro";
|
|
534
|
-
|
|
535
|
-
export {
|
|
536
|
-
MoonUITabsPro,
|
|
537
|
-
MoonUITabsListPro,
|
|
538
|
-
MoonUITabsTriggerPro,
|
|
539
|
-
MoonUITabsContentPro,
|
|
540
|
-
type TabItem,
|
|
541
|
-
type MoonUITabsProProps
|
|
542
|
-
};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
5
|
-
import { cn } from "../../lib/utils";
|
|
6
|
-
|
|
7
|
-
const Tabs = TabsPrimitive.Root;
|
|
8
|
-
|
|
9
|
-
const TabsList = React.forwardRef<
|
|
10
|
-
React.ElementRef<typeof TabsPrimitive.List>,
|
|
11
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
|
12
|
-
>(({ className, ...props }, ref) => (
|
|
13
|
-
<TabsPrimitive.List
|
|
14
|
-
ref={ref}
|
|
15
|
-
className={cn(
|
|
16
|
-
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
|
|
17
|
-
className
|
|
18
|
-
)}
|
|
19
|
-
{...props}
|
|
20
|
-
/>
|
|
21
|
-
));
|
|
22
|
-
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
23
|
-
|
|
24
|
-
const TabsTrigger = React.forwardRef<
|
|
25
|
-
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
26
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
27
|
-
>(({ className, ...props }, ref) => (
|
|
28
|
-
<TabsPrimitive.Trigger
|
|
29
|
-
ref={ref}
|
|
30
|
-
className={cn(
|
|
31
|
-
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all 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=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
|
|
32
|
-
className
|
|
33
|
-
)}
|
|
34
|
-
{...props}
|
|
35
|
-
/>
|
|
36
|
-
));
|
|
37
|
-
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
38
|
-
|
|
39
|
-
const TabsContent = React.forwardRef<
|
|
40
|
-
React.ElementRef<typeof TabsPrimitive.Content>,
|
|
41
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
|
42
|
-
>(({ className, ...props }, ref) => (
|
|
43
|
-
<TabsPrimitive.Content
|
|
44
|
-
ref={ref}
|
|
45
|
-
className={cn(
|
|
46
|
-
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
47
|
-
className
|
|
48
|
-
)}
|
|
49
|
-
{...props}
|
|
50
|
-
/>
|
|
51
|
-
));
|
|
52
|
-
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
53
|
-
|
|
54
|
-
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import React from "react"
|
|
4
|
-
import { cn } from "../../lib/utils"
|
|
5
|
-
|
|
6
|
-
export interface MoonUITextareaProProps
|
|
7
|
-
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
|
8
|
-
|
|
9
|
-
const MoonUITextareaPro = React.forwardRef<HTMLTextAreaElement, MoonUITextareaProProps>(
|
|
10
|
-
({ className, ...props }, ref) => {
|
|
11
|
-
return (
|
|
12
|
-
<textarea
|
|
13
|
-
className={cn(
|
|
14
|
-
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background 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",
|
|
15
|
-
className
|
|
16
|
-
)}
|
|
17
|
-
ref={ref}
|
|
18
|
-
{...props}
|
|
19
|
-
/>
|
|
20
|
-
)
|
|
21
|
-
}
|
|
22
|
-
)
|
|
23
|
-
MoonUITextareaPro.displayName = "MoonUITextareaPro"
|
|
24
|
-
|
|
25
|
-
export { MoonUITextareaPro };
|
|
26
|
-
|
|
27
|
-
// Backward compatibility exports
|
|
28
|
-
export { MoonUITextareaPro as Textarea }
|