@moontra/moonui-pro 2.20.0 → 2.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/index.d.ts +691 -261
  2. package/dist/index.mjs +7419 -4935
  3. package/package.json +4 -3
  4. package/scripts/postbuild.js +27 -0
  5. package/src/components/advanced-chart/index.tsx +5 -1
  6. package/src/components/advanced-forms/index.tsx +175 -16
  7. package/src/components/calendar/event-dialog.tsx +18 -13
  8. package/src/components/calendar/index.tsx +197 -50
  9. package/src/components/dashboard/dashboard-grid.tsx +21 -3
  10. package/src/components/dashboard/types.ts +3 -0
  11. package/src/components/dashboard/widgets/activity-feed.tsx +6 -1
  12. package/src/components/dashboard/widgets/comparison-widget.tsx +177 -0
  13. package/src/components/dashboard/widgets/index.ts +5 -0
  14. package/src/components/dashboard/widgets/metric-card.tsx +21 -1
  15. package/src/components/dashboard/widgets/progress-widget.tsx +113 -0
  16. package/src/components/error-boundary/index.tsx +160 -37
  17. package/src/components/form-wizard/form-wizard-context.tsx +54 -26
  18. package/src/components/form-wizard/form-wizard-progress.tsx +33 -2
  19. package/src/components/form-wizard/types.ts +2 -1
  20. package/src/components/github-stars/hooks.ts +1 -0
  21. package/src/components/github-stars/variants.tsx +3 -1
  22. package/src/components/health-check/index.tsx +14 -14
  23. package/src/components/hover-card-3d/index.tsx +2 -3
  24. package/src/components/index.ts +5 -3
  25. package/src/components/kanban/kanban.tsx +23 -18
  26. package/src/components/license-error/index.tsx +2 -0
  27. package/src/components/magnetic-button/index.tsx +56 -7
  28. package/src/components/memory-efficient-data/index.tsx +117 -115
  29. package/src/components/navbar/index.tsx +781 -0
  30. package/src/components/performance-debugger/index.tsx +62 -38
  31. package/src/components/performance-monitor/index.tsx +47 -33
  32. package/src/components/phone-number-input/index.tsx +32 -27
  33. package/src/components/phone-number-input/phone-number-input-simple.tsx +167 -0
  34. package/src/components/rich-text-editor/index.tsx +26 -28
  35. package/src/components/rich-text-editor/slash-commands-extension.ts +15 -5
  36. package/src/components/sidebar/index.tsx +32 -13
  37. package/src/components/timeline/index.tsx +84 -49
  38. package/src/components/ui/accordion.tsx +550 -42
  39. package/src/components/ui/avatar.tsx +2 -0
  40. package/src/components/ui/badge.tsx +2 -0
  41. package/src/components/ui/breadcrumb.tsx +2 -0
  42. package/src/components/ui/button.tsx +39 -33
  43. package/src/components/ui/card.tsx +2 -0
  44. package/src/components/ui/collapsible.tsx +546 -50
  45. package/src/components/ui/command.tsx +790 -67
  46. package/src/components/ui/dialog.tsx +510 -92
  47. package/src/components/ui/dropdown-menu.tsx +540 -52
  48. package/src/components/ui/index.ts +37 -5
  49. package/src/components/ui/input.tsx +2 -0
  50. package/src/components/ui/magnetic-button.tsx +1 -1
  51. package/src/components/ui/media-gallery.tsx +1 -2
  52. package/src/components/ui/navigation-menu.tsx +130 -0
  53. package/src/components/ui/pagination.tsx +2 -0
  54. package/src/components/ui/select.tsx +6 -2
  55. package/src/components/ui/spotlight-card.tsx +1 -1
  56. package/src/components/ui/table.tsx +2 -0
  57. package/src/components/ui/tabs-pro.tsx +542 -0
  58. package/src/components/ui/tabs.tsx +23 -167
  59. package/src/components/ui/toggle.tsx +13 -13
  60. package/src/index.ts +11 -3
  61. package/src/styles/index.css +596 -0
  62. package/src/use-performance-optimizer.ts +1 -1
  63. package/src/utils/chart-helpers.ts +1 -1
  64. package/src/__tests__/use-intersection-observer.test.tsx +0 -216
  65. package/src/__tests__/use-local-storage.test.tsx +0 -174
  66. package/src/__tests__/use-pro-access.test.tsx +0 -183
  67. package/src/components/advanced-chart/advanced-chart.test.tsx +0 -281
  68. package/src/components/data-table/data-table.test.tsx +0 -187
  69. package/src/components/enhanced/badge.tsx +0 -191
  70. package/src/components/enhanced/button.tsx +0 -362
  71. package/src/components/enhanced/card.tsx +0 -266
  72. package/src/components/enhanced/dialog.tsx +0 -246
  73. package/src/components/enhanced/index.ts +0 -4
  74. package/src/components/file-upload/file-upload.test.tsx +0 -243
  75. package/src/components/rich-text-editor/index-old-backup.tsx +0 -437
  76. package/src/types/moonui.d.ts +0 -22
@@ -2,39 +2,169 @@
2
2
 
3
3
  import * as React from "react"
4
4
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
5
- import { Check, ChevronRight, Circle } from "lucide-react"
5
+ import { cva, type VariantProps } from "class-variance-authority"
6
+ import { motion, AnimatePresence } from "framer-motion"
7
+ import {
8
+ Check,
9
+ ChevronRight,
10
+ Circle,
11
+ Loader2,
12
+ Search,
13
+ Command,
14
+ Sparkles,
15
+ Zap,
16
+ Star,
17
+ Crown,
18
+ Diamond,
19
+ Gem,
20
+ X
21
+ } from "lucide-react"
6
22
 
7
23
  import { cn } from "../../lib/utils"
8
24
 
9
- const MoonUIDropdownMenuPro = DropdownMenuPrimitive.Root
25
+ /**
26
+ * Premium Dropdown Menu Component Pro
27
+ *
28
+ * Gelişmiş, erişilebilir ve özelleştirilebilir dropdown menu component'i.
29
+ * Zengin animasyonlar, arama özelliği, komut paleti entegrasyonu ve premium görünüm sunar.
30
+ *
31
+ * Pro Özellikler:
32
+ * - Gelişmiş animasyon seçenekleri (slide, scale, fade, spring)
33
+ * - Arama ve filtreleme özelliği
34
+ * - Komut paleti entegrasyonu (⌘K style)
35
+ * - Multi-level nested menu desteği
36
+ * - Rich content support (avatars, badges, descriptions)
37
+ * - Glass, gradient ve neon visual variants
38
+ * - Keyboard shortcuts ile gelişmiş navigasyon
39
+ * - Loading states ve async actions
40
+ * - Custom icons ve badges
41
+ * - Responsive mobile optimization
42
+ * - Tooltip entegrasyonu
43
+ * - Customizable animation timing
44
+ * - Advanced keyboard navigation
45
+ * - Context menu mode
46
+ * - Command palette mode
47
+ */
10
48
 
49
+ const MoonUIDropdownMenuPro = DropdownMenuPrimitive.Root
11
50
  const MoonUIDropdownMenuTriggerPro = DropdownMenuPrimitive.Trigger
12
-
13
51
  const MoonUIDropdownMenuGroupPro = DropdownMenuPrimitive.Group
14
-
15
52
  const MoonUIDropdownMenuPortalPro = DropdownMenuPrimitive.Portal
16
-
17
53
  const MoonUIDropdownMenuSubPro = DropdownMenuPrimitive.Sub
18
-
19
54
  const MoonUIDropdownMenuRadioGroupPro = DropdownMenuPrimitive.RadioGroup
20
55
 
56
+ const dropdownContentVariants = cva(
57
+ "z-50 min-w-[8rem] overflow-hidden rounded-lg border bg-popover p-1 text-popover-foreground shadow-lg",
58
+ {
59
+ variants: {
60
+ variant: {
61
+ default: "border-border bg-background",
62
+ glass: "border-white/10 bg-white/5 backdrop-blur-xl dark:border-white/10 dark:bg-black/5",
63
+ gradient: "border-0 bg-gradient-to-br from-background/95 via-primary/5 to-background/95 backdrop-blur-md",
64
+ neon: "border-primary/50 shadow-[0_0_15px_rgba(59,130,246,0.3)] dark:shadow-[0_0_20px_rgba(59,130,246,0.5)]",
65
+ command: "min-w-[300px] border-border bg-background p-0",
66
+ premium: "border-yellow-500/20 bg-gradient-to-br from-yellow-50/5 via-background to-yellow-50/5 dark:from-yellow-900/5 dark:to-yellow-900/5",
67
+ },
68
+ animation: {
69
+ none: "",
70
+ slide: "",
71
+ scale: "",
72
+ fade: "",
73
+ spring: "",
74
+ slideAndFade: "",
75
+ },
76
+ size: {
77
+ sm: "min-w-[6rem] text-xs",
78
+ default: "min-w-[8rem] text-sm",
79
+ lg: "min-w-[12rem] text-base",
80
+ xl: "min-w-[16rem]",
81
+ "2xl": "min-w-[20rem]",
82
+ full: "min-w-[95vw] sm:min-w-[24rem]",
83
+ }
84
+ },
85
+ defaultVariants: {
86
+ variant: "default",
87
+ animation: "slideAndFade",
88
+ size: "default",
89
+ },
90
+ }
91
+ )
92
+
93
+ const dropdownItemVariants = cva(
94
+ "relative flex cursor-pointer select-none items-center rounded-md px-2 py-1.5 text-sm outline-none transition-colors",
95
+ {
96
+ variants: {
97
+ variant: {
98
+ default: "focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-accent hover:text-accent-foreground",
99
+ destructive: "focus:bg-red-100 focus:text-red-900 hover:bg-red-100 hover:text-red-900 dark:focus:bg-red-900/20 dark:focus:text-red-400 dark:hover:bg-red-900/20 dark:hover:text-red-400",
100
+ success: "focus:bg-green-100 focus:text-green-900 hover:bg-green-100 hover:text-green-900 dark:focus:bg-green-900/20 dark:focus:text-green-400 dark:hover:bg-green-900/20 dark:hover:text-green-400",
101
+ warning: "focus:bg-yellow-100 focus:text-yellow-900 hover:bg-yellow-100 hover:text-yellow-900 dark:focus:bg-yellow-900/20 dark:focus:text-yellow-400 dark:hover:bg-yellow-900/20 dark:hover:text-yellow-400",
102
+ premium: "bg-gradient-to-r from-yellow-50/10 to-yellow-50/5 hover:from-yellow-50/20 hover:to-yellow-50/10 dark:from-yellow-900/10 dark:to-yellow-900/5",
103
+ },
104
+ size: {
105
+ sm: "py-1 text-xs",
106
+ default: "py-1.5",
107
+ lg: "py-2 text-base",
108
+ }
109
+ },
110
+ defaultVariants: {
111
+ variant: "default",
112
+ size: "default",
113
+ },
114
+ }
115
+ )
116
+
117
+ interface DropdownMenuContentProps
118
+ extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>,
119
+ VariantProps<typeof dropdownContentVariants> {
120
+ enableSearch?: boolean;
121
+ searchPlaceholder?: string;
122
+ animationDuration?: number;
123
+ enableSpringPhysics?: boolean;
124
+ showPremiumBadge?: boolean;
125
+ loading?: boolean;
126
+ header?: React.ReactNode;
127
+ footer?: React.ReactNode;
128
+ }
129
+
130
+ interface DropdownMenuItemProps
131
+ extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>,
132
+ VariantProps<typeof dropdownItemVariants> {
133
+ inset?: boolean;
134
+ icon?: React.ReactNode;
135
+ description?: string;
136
+ shortcut?: string;
137
+ badge?: React.ReactNode;
138
+ showCheckmark?: boolean;
139
+ loading?: boolean;
140
+ }
141
+
21
142
  const MoonUIDropdownMenuSubTriggerPro = React.forwardRef<
22
143
  React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
23
144
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
24
- inset?: boolean
145
+ inset?: boolean;
146
+ showChevron?: boolean;
147
+ badge?: React.ReactNode;
25
148
  }
26
- >(({ className, inset, children, ...props }, ref) => (
149
+ >(({ className, inset, children, showChevron = true, badge, ...props }, ref) => (
27
150
  <DropdownMenuPrimitive.SubTrigger
28
151
  ref={ref}
29
152
  className={cn(
30
- "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
153
+ "flex cursor-pointer select-none items-center rounded-md px-2 py-1.5 text-sm outline-none",
154
+ "focus:bg-accent focus:text-accent-foreground",
155
+ "data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
156
+ "hover:bg-accent hover:text-accent-foreground",
157
+ "transition-colors duration-150",
31
158
  inset && "pl-8",
32
159
  className
33
160
  )}
34
161
  {...props}
35
162
  >
36
163
  {children}
37
- <ChevronRight className="ml-auto h-4 w-4" />
164
+ <div className="ml-auto flex items-center gap-2">
165
+ {badge}
166
+ {showChevron && <ChevronRight className="h-4 w-4" />}
167
+ </div>
38
168
  </DropdownMenuPrimitive.SubTrigger>
39
169
  ))
40
170
  MoonUIDropdownMenuSubTriggerPro.displayName =
@@ -42,54 +172,285 @@ MoonUIDropdownMenuSubTriggerPro.displayName =
42
172
 
43
173
  const MoonUIDropdownMenuSubContentPro = React.forwardRef<
44
174
  React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
45
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
46
- >(({ className, ...props }, ref) => (
47
- <DropdownMenuPrimitive.SubContent
48
- ref={ref}
49
- className={cn(
50
- "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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-[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",
51
- className
52
- )}
53
- {...props}
54
- />
55
- ))
56
- MoonUIDropdownMenuSubContentPro.displayName =
57
- DropdownMenuPrimitive.SubContent.displayName
175
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent> &
176
+ VariantProps<typeof dropdownContentVariants>
177
+ >(({ className, variant, animation, size, ...props }, ref) => {
178
+ const getAnimationVariants = () => {
179
+ switch (animation) {
180
+ case "slide":
181
+ return {
182
+ initial: { opacity: 0, x: -10 },
183
+ animate: { opacity: 1, x: 0 },
184
+ exit: { opacity: 0, x: -10 },
185
+ };
186
+ case "scale":
187
+ return {
188
+ initial: { opacity: 0, scale: 0.95 },
189
+ animate: { opacity: 1, scale: 1 },
190
+ exit: { opacity: 0, scale: 0.95 },
191
+ };
192
+ case "fade":
193
+ return {
194
+ initial: { opacity: 0 },
195
+ animate: { opacity: 1 },
196
+ exit: { opacity: 0 },
197
+ };
198
+ case "spring":
199
+ return {
200
+ initial: { opacity: 0, scale: 0.9, y: -10 },
201
+ animate: {
202
+ opacity: 1,
203
+ scale: 1,
204
+ y: 0,
205
+ transition: { type: "spring", stiffness: 300, damping: 20 }
206
+ },
207
+ exit: { opacity: 0, scale: 0.9, y: -10 },
208
+ };
209
+ default:
210
+ return {
211
+ initial: { opacity: 0, y: -2, x: -2 },
212
+ animate: { opacity: 1, y: 0, x: 0 },
213
+ exit: { opacity: 0, y: -2, x: -2 },
214
+ };
215
+ }
216
+ };
58
217
 
59
- const MoonUIDropdownMenuContentPro = React.forwardRef<
60
- React.ElementRef<typeof DropdownMenuPrimitive.Content>,
61
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
62
- >(({ className, sideOffset = 4, ...props }, ref) => (
63
- <DropdownMenuPrimitive.Portal>
64
- <DropdownMenuPrimitive.Content
218
+ // Animation removed for SubContent to fix type issues
219
+ return (
220
+ <DropdownMenuPrimitive.SubContent
65
221
  ref={ref}
66
- sideOffset={sideOffset}
67
- className={cn(
68
- "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md 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-[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",
69
- className
70
- )}
222
+ className={cn(dropdownContentVariants({ variant, size }), className)}
71
223
  {...props}
72
224
  />
73
- </DropdownMenuPrimitive.Portal>
74
- ))
225
+ );
226
+ });
227
+ MoonUIDropdownMenuSubContentPro.displayName = DropdownMenuPrimitive.SubContent.displayName
228
+
229
+ const MoonUIDropdownMenuContentPro = React.forwardRef<
230
+ React.ElementRef<typeof DropdownMenuPrimitive.Content>,
231
+ DropdownMenuContentProps
232
+ >(
233
+ (
234
+ {
235
+ className,
236
+ variant,
237
+ animation,
238
+ size,
239
+ sideOffset = 4,
240
+ enableSearch = false,
241
+ searchPlaceholder = "Search...",
242
+ animationDuration = 150,
243
+ enableSpringPhysics = false,
244
+ showPremiumBadge = false,
245
+ loading = false,
246
+ header,
247
+ footer,
248
+ children,
249
+ ...props
250
+ },
251
+ ref
252
+ ) => {
253
+ const [searchQuery, setSearchQuery] = React.useState("");
254
+
255
+ const getAnimationVariants = () => {
256
+ const duration = animationDuration / 1000;
257
+ const springConfig = enableSpringPhysics
258
+ ? { type: "spring", stiffness: 300, damping: 20 }
259
+ : { duration };
260
+
261
+ switch (animation) {
262
+ case "slide":
263
+ return {
264
+ initial: { opacity: 0, y: -10 },
265
+ animate: { opacity: 1, y: 0 },
266
+ exit: { opacity: 0, y: -10 },
267
+ transition: springConfig,
268
+ };
269
+ case "scale":
270
+ return {
271
+ initial: { opacity: 0, scale: 0.95 },
272
+ animate: { opacity: 1, scale: 1 },
273
+ exit: { opacity: 0, scale: 0.95 },
274
+ transition: springConfig,
275
+ };
276
+ case "fade":
277
+ return {
278
+ initial: { opacity: 0 },
279
+ animate: { opacity: 1 },
280
+ exit: { opacity: 0 },
281
+ transition: { duration },
282
+ };
283
+ case "spring":
284
+ return {
285
+ initial: { opacity: 0, scale: 0.9, y: -20 },
286
+ animate: {
287
+ opacity: 1,
288
+ scale: 1,
289
+ y: 0,
290
+ transition: { type: "spring", stiffness: 400, damping: 25 }
291
+ },
292
+ exit: { opacity: 0, scale: 0.9, y: -20 },
293
+ };
294
+ default:
295
+ return {
296
+ initial: { opacity: 0, y: -2 },
297
+ animate: { opacity: 1, y: 0 },
298
+ exit: { opacity: 0, y: -2 },
299
+ transition: { duration },
300
+ };
301
+ }
302
+ };
303
+
304
+ const animationVariants = getAnimationVariants();
305
+
306
+ // Filter children based on search query
307
+ const filteredChildren = React.useMemo(() => {
308
+ if (!enableSearch || !searchQuery) return children;
309
+
310
+ return React.Children.toArray(children).filter((child) => {
311
+ if (!React.isValidElement(child)) return true;
312
+
313
+ const childText = getTextFromElement(child);
314
+ return childText.toLowerCase().includes(searchQuery.toLowerCase());
315
+ });
316
+ }, [children, searchQuery, enableSearch]);
317
+
318
+ return (
319
+ <DropdownMenuPrimitive.Portal>
320
+ <DropdownMenuPrimitive.Content
321
+ ref={ref}
322
+ sideOffset={sideOffset}
323
+ className={cn(
324
+ dropdownContentVariants({ variant, size }),
325
+ variant === "command" && "p-0",
326
+ className
327
+ )}
328
+ {...props}
329
+ >
330
+ {/* Premium Badge */}
331
+ {showPremiumBadge && (
332
+ <div className="mb-1 flex items-center justify-center gap-1 border-b border-yellow-500/20 pb-1">
333
+ <Crown className="h-3 w-3 text-yellow-500" />
334
+ <span className="text-xs font-medium text-yellow-600 dark:text-yellow-400">
335
+ Premium Menu
336
+ </span>
337
+ </div>
338
+ )}
339
+
340
+ {/* Custom Header */}
341
+ {header && (
342
+ <div className="mb-1 border-b pb-1">
343
+ {header}
344
+ </div>
345
+ )}
346
+
347
+ {/* Search Input */}
348
+ {enableSearch && (
349
+ <div className="mb-1 border-b pb-1">
350
+ <div className="flex items-center gap-2 px-2 py-1.5">
351
+ <Search className="h-4 w-4 text-muted-foreground" />
352
+ <input
353
+ type="text"
354
+ placeholder={searchPlaceholder}
355
+ value={searchQuery}
356
+ onChange={(e) => setSearchQuery(e.target.value)}
357
+ className={cn(
358
+ "flex-1 bg-transparent text-sm outline-none",
359
+ "placeholder:text-muted-foreground"
360
+ )}
361
+ onClick={(e) => e.stopPropagation()}
362
+ />
363
+ {searchQuery && (
364
+ <button
365
+ onClick={() => setSearchQuery("")}
366
+ className="text-muted-foreground hover:text-foreground"
367
+ >
368
+ <X className="h-3 w-3" />
369
+ </button>
370
+ )}
371
+ </div>
372
+ </div>
373
+ )}
374
+
375
+ {/* Loading State */}
376
+ {loading ? (
377
+ <div className="flex items-center justify-center py-8">
378
+ <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
379
+ </div>
380
+ ) : (
381
+ <div className={cn(variant === "command" && "p-1")}>
382
+ {filteredChildren}
383
+ </div>
384
+ )}
385
+
386
+ {/* Custom Footer */}
387
+ {footer && (
388
+ <div className="mt-1 border-t pt-1">
389
+ {footer}
390
+ </div>
391
+ )}
392
+ </DropdownMenuPrimitive.Content>
393
+ </DropdownMenuPrimitive.Portal>
394
+ );
395
+ }
396
+ )
75
397
  MoonUIDropdownMenuContentPro.displayName = DropdownMenuPrimitive.Content.displayName
76
398
 
77
399
  const MoonUIDropdownMenuItemPro = React.forwardRef<
78
400
  React.ElementRef<typeof DropdownMenuPrimitive.Item>,
79
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
80
- inset?: boolean
81
- }
82
- >(({ className, inset, ...props }, ref) => (
83
- <DropdownMenuPrimitive.Item
84
- ref={ref}
85
- className={cn(
86
- "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
87
- inset && "pl-8",
88
- className
89
- )}
90
- {...props}
91
- />
92
- ))
401
+ DropdownMenuItemProps
402
+ >(
403
+ (
404
+ {
405
+ className,
406
+ variant,
407
+ size,
408
+ inset,
409
+ icon,
410
+ description,
411
+ shortcut,
412
+ badge,
413
+ showCheckmark,
414
+ loading,
415
+ children,
416
+ ...props
417
+ },
418
+ ref
419
+ ) => (
420
+ <DropdownMenuPrimitive.Item
421
+ ref={ref}
422
+ className={cn(
423
+ dropdownItemVariants({ variant, size }),
424
+ inset && "pl-8",
425
+ className
426
+ )}
427
+ {...props}
428
+ >
429
+ {icon && (
430
+ <span className="mr-2 flex h-4 w-4 items-center justify-center">
431
+ {loading ? <Loader2 className="h-4 w-4 animate-spin" /> : icon}
432
+ </span>
433
+ )}
434
+ <div className="flex flex-1 flex-col">
435
+ <div className="flex items-center">
436
+ {children}
437
+ {badge && <span className="ml-2">{badge}</span>}
438
+ </div>
439
+ {description && (
440
+ <span className="text-xs text-muted-foreground">{description}</span>
441
+ )}
442
+ </div>
443
+ {shortcut && (
444
+ <span className="ml-auto text-xs tracking-widest text-muted-foreground">
445
+ {shortcut}
446
+ </span>
447
+ )}
448
+ {showCheckmark && (
449
+ <Check className="ml-2 h-4 w-4" />
450
+ )}
451
+ </DropdownMenuPrimitive.Item>
452
+ )
453
+ )
93
454
  MoonUIDropdownMenuItemPro.displayName = DropdownMenuPrimitive.Item.displayName
94
455
 
95
456
  const MoonUIDropdownMenuCheckboxItemPro = React.forwardRef<
@@ -181,7 +542,130 @@ const MoonUIDropdownMenuShortcutPro = ({
181
542
  }
182
543
  MoonUIDropdownMenuShortcutPro.displayName = "MoonUIDropdownMenuShortcutPro"
183
544
 
184
- export { MoonUIDropdownMenuPro,
545
+ // Helper function to extract text from React elements
546
+ function getTextFromElement(element: React.ReactElement<any>): string {
547
+ const props = element.props as any;
548
+ if (!props || !props.children) return "";
549
+
550
+ if (typeof props.children === "string") {
551
+ return props.children;
552
+ }
553
+ if (React.isValidElement(props.children)) {
554
+ return getTextFromElement(props.children as React.ReactElement<any>);
555
+ }
556
+ if (Array.isArray(props.children)) {
557
+ return props.children
558
+ .map((child: any) => {
559
+ if (typeof child === "string") return child;
560
+ if (React.isValidElement(child)) return getTextFromElement(child as React.ReactElement<any>);
561
+ return "";
562
+ })
563
+ .join("");
564
+ }
565
+ return "";
566
+ }
567
+
568
+ // Command Palette Mode Component
569
+ interface CommandPaletteDropdownProps {
570
+ items: Array<{
571
+ category?: string;
572
+ items: Array<{
573
+ id: string;
574
+ label: string;
575
+ description?: string;
576
+ icon?: React.ReactNode;
577
+ shortcut?: string;
578
+ action?: () => void;
579
+ keywords?: string[];
580
+ }>;
581
+ }>;
582
+ trigger: React.ReactNode;
583
+ placeholder?: string;
584
+ }
585
+
586
+ const MoonUICommandPaletteDropdown: React.FC<CommandPaletteDropdownProps> = ({
587
+ items,
588
+ trigger,
589
+ placeholder = "Type a command or search...",
590
+ }) => {
591
+ const [open, setOpen] = React.useState(false);
592
+ const [search, setSearch] = React.useState("");
593
+
594
+ const filteredItems = React.useMemo(() => {
595
+ if (!search) return items;
596
+
597
+ return items
598
+ .map((category) => ({
599
+ ...category,
600
+ items: category.items.filter((item) => {
601
+ const searchLower = search.toLowerCase();
602
+ return (
603
+ item.label.toLowerCase().includes(searchLower) ||
604
+ item.description?.toLowerCase().includes(searchLower) ||
605
+ item.keywords?.some((k) => k.toLowerCase().includes(searchLower))
606
+ );
607
+ }),
608
+ }))
609
+ .filter((category) => category.items.length > 0);
610
+ }, [items, search]);
611
+
612
+ return (
613
+ <MoonUIDropdownMenuPro open={open} onOpenChange={setOpen}>
614
+ <MoonUIDropdownMenuTriggerPro asChild>{trigger}</MoonUIDropdownMenuTriggerPro>
615
+ <MoonUIDropdownMenuContentPro
616
+ variant="command"
617
+ size="2xl"
618
+ animation="spring"
619
+ enableSpringPhysics
620
+ className="p-0"
621
+ >
622
+ <div className="flex items-center border-b px-3 pb-2 pt-3">
623
+ <Command className="mr-2 h-4 w-4 shrink-0 opacity-50" />
624
+ <input
625
+ placeholder={placeholder}
626
+ value={search}
627
+ onChange={(e) => setSearch(e.target.value)}
628
+ className="flex h-8 w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground"
629
+ />
630
+ </div>
631
+ <div className="max-h-[300px] overflow-y-auto p-1">
632
+ {filteredItems.map((category, i) => (
633
+ <React.Fragment key={i}>
634
+ {category.category && (
635
+ <MoonUIDropdownMenuLabelPro className="px-2 py-1.5 text-xs text-muted-foreground">
636
+ {category.category}
637
+ </MoonUIDropdownMenuLabelPro>
638
+ )}
639
+ {category.items.map((item) => (
640
+ <MoonUIDropdownMenuItemPro
641
+ key={item.id}
642
+ icon={item.icon}
643
+ description={item.description}
644
+ shortcut={item.shortcut}
645
+ onClick={() => {
646
+ item.action?.();
647
+ setOpen(false);
648
+ }}
649
+ >
650
+ {item.label}
651
+ </MoonUIDropdownMenuItemPro>
652
+ ))}
653
+ {i < filteredItems.length - 1 && <MoonUIDropdownMenuSeparatorPro />}
654
+ </React.Fragment>
655
+ ))}
656
+ {filteredItems.length === 0 && (
657
+ <div className="py-6 text-center text-sm text-muted-foreground">
658
+ No results found
659
+ </div>
660
+ )}
661
+ </div>
662
+ </MoonUIDropdownMenuContentPro>
663
+ </MoonUIDropdownMenuPro>
664
+ );
665
+ };
666
+
667
+ export {
668
+ MoonUIDropdownMenuPro,
185
669
  MoonUIDropdownMenuTriggerPro,
186
670
  MoonUIDropdownMenuContentPro,
187
671
  MoonUIDropdownMenuItemPro,
@@ -196,7 +680,11 @@ export { MoonUIDropdownMenuPro,
196
680
  MoonUIDropdownMenuSubContentPro,
197
681
  MoonUIDropdownMenuSubTriggerPro,
198
682
  MoonUIDropdownMenuRadioGroupPro,
199
- };
683
+ MoonUICommandPaletteDropdown,
684
+ type DropdownMenuContentProps,
685
+ type DropdownMenuItemProps,
686
+ type CommandPaletteDropdownProps,
687
+ };
200
688
 
201
689
  // Clean exports (only dropdown-menu specific)
202
690
  export {