@moontra/moonui-pro 2.20.1 → 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 +7418 -4934
  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 +12 -12
  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
@@ -1,246 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as DialogPrimitive from "@radix-ui/react-dialog"
5
- import { motion, AnimatePresence } from "framer-motion"
6
- import { X } from "lucide-react"
7
- import { cn } from "../../lib/utils"
8
-
9
- const Dialog = DialogPrimitive.Root
10
- const DialogTrigger = DialogPrimitive.Trigger
11
- const DialogPortal = DialogPrimitive.Portal
12
- const DialogClose = DialogPrimitive.Close
13
-
14
- interface DialogProOverlayProps
15
- extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> {
16
- blur?: "none" | "sm" | "md" | "lg" | "xl"
17
- variant?: "default" | "dark" | "light" | "gradient"
18
- }
19
-
20
- const DialogProOverlay = React.forwardRef<
21
- React.ElementRef<typeof DialogPrimitive.Overlay>,
22
- DialogProOverlayProps
23
- >(({ className, blur = "md", variant = "default", ...props }, ref) => {
24
- const blurClasses = {
25
- none: "",
26
- sm: "backdrop-blur-sm",
27
- md: "backdrop-blur-md",
28
- lg: "backdrop-blur-lg",
29
- xl: "backdrop-blur-xl",
30
- }
31
-
32
- const variantClasses = {
33
- default: "bg-black/80",
34
- dark: "bg-black/90",
35
- light: "bg-white/80",
36
- gradient: "bg-gradient-to-br from-black/80 via-gray-900/80 to-black/80",
37
- }
38
-
39
- return (
40
- <DialogPrimitive.Overlay
41
- ref={ref}
42
- className={cn(
43
- "fixed inset-0 z-50",
44
- blurClasses[blur],
45
- variantClasses[variant],
46
- className
47
- )}
48
- {...props}
49
- />
50
- )
51
- })
52
- DialogProOverlay.displayName = DialogPrimitive.Overlay.displayName
53
-
54
- interface DialogProContentProps
55
- extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
56
- animation?: "fade" | "scale" | "slide" | "rotate" | "bounce"
57
- animationDuration?: number
58
- overlay?: boolean
59
- overlayProps?: DialogProOverlayProps
60
- }
61
-
62
- const DialogProContent = React.forwardRef<
63
- React.ElementRef<typeof DialogPrimitive.Content>,
64
- DialogProContentProps
65
- >(({
66
- className,
67
- children,
68
- animation = "scale",
69
- animationDuration = 0.3,
70
- overlay = true,
71
- overlayProps = {},
72
- ...props
73
- }, ref) => {
74
- const animationVariants = {
75
- fade: {
76
- initial: { opacity: 0 },
77
- animate: { opacity: 1 },
78
- exit: { opacity: 0 }
79
- },
80
- scale: {
81
- initial: { opacity: 0, scale: 0.9, y: 20 },
82
- animate: { opacity: 1, scale: 1, y: 0 },
83
- exit: { opacity: 0, scale: 0.9, y: 20 }
84
- },
85
- slide: {
86
- initial: { opacity: 0, y: 100 },
87
- animate: { opacity: 1, y: 0 },
88
- exit: { opacity: 0, y: 100 }
89
- },
90
- rotate: {
91
- initial: { opacity: 0, scale: 0.9, rotate: -10 },
92
- animate: { opacity: 1, scale: 1, rotate: 0 },
93
- exit: { opacity: 0, scale: 0.9, rotate: 10 }
94
- },
95
- bounce: {
96
- initial: { opacity: 0, scale: 0.3, y: -100 },
97
- animate: {
98
- opacity: 1,
99
- scale: 1,
100
- y: 0,
101
- transition: {
102
- type: "spring",
103
- duration: animationDuration,
104
- bounce: 0.5
105
- }
106
- },
107
- exit: { opacity: 0, scale: 0.5, y: -50 }
108
- }
109
- }
110
-
111
- return (
112
- <AnimatePresence>
113
- <DialogPortal>
114
- {overlay && (
115
- <motion.div
116
- initial={{ opacity: 0 }}
117
- animate={{ opacity: 1 }}
118
- exit={{ opacity: 0 }}
119
- transition={{ duration: animationDuration * 0.8 }}
120
- >
121
- <DialogProOverlay {...overlayProps} />
122
- </motion.div>
123
- )}
124
- <motion.div
125
- className="fixed inset-0 z-50 flex items-center justify-center p-4"
126
- initial={{ opacity: 0 }}
127
- animate={{ opacity: 1 }}
128
- exit={{ opacity: 0 }}
129
- >
130
- <DialogPrimitive.Content
131
- ref={ref}
132
- asChild
133
- className={cn(
134
- "relative w-full max-w-lg",
135
- className
136
- )}
137
- {...props}
138
- >
139
- <motion.div
140
- variants={animationVariants[animation]}
141
- initial="initial"
142
- animate="animate"
143
- exit="exit"
144
- transition={{
145
- duration: animationDuration,
146
- ease: "easeInOut"
147
- }}
148
- className={cn(
149
- "relative bg-background rounded-lg shadow-2xl",
150
- "border border-border",
151
- "w-full max-w-lg",
152
- "max-h-[90vh] overflow-auto",
153
- className
154
- )}
155
- >
156
- {/* Glass effect overlay */}
157
- <div className="absolute inset-0 rounded-lg bg-gradient-to-br from-white/5 to-white/0 pointer-events-none" />
158
-
159
- {/* Content wrapper with padding */}
160
- <div className="relative p-6">
161
- {children}
162
- </div>
163
-
164
- {/* Close button with enhanced styling */}
165
- <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-all hover:opacity-100 hover:rotate-90 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">
166
- <X className="h-4 w-4" />
167
- <span className="sr-only">Close</span>
168
- </DialogPrimitive.Close>
169
- </motion.div>
170
- </DialogPrimitive.Content>
171
- </motion.div>
172
- </DialogPortal>
173
- </AnimatePresence>
174
- )
175
- })
176
- DialogProContent.displayName = DialogPrimitive.Content.displayName
177
-
178
- const DialogProHeader = ({
179
- className,
180
- ...props
181
- }: React.HTMLAttributes<HTMLDivElement>) => (
182
- <motion.div
183
- className={cn(
184
- "flex flex-col space-y-1.5 text-center sm:text-left",
185
- className
186
- )}
187
- initial={{ opacity: 0, y: -10 }}
188
- animate={{ opacity: 1, y: 0 }}
189
- transition={{ delay: 0.1, duration: 0.3 }}
190
- />
191
- )
192
- DialogProHeader.displayName = "DialogProHeader"
193
-
194
- const DialogProFooter = ({
195
- className,
196
- ...props
197
- }: React.HTMLAttributes<HTMLDivElement>) => (
198
- <motion.div
199
- className={cn(
200
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
201
- className
202
- )}
203
- initial={{ opacity: 0, y: 10 }}
204
- animate={{ opacity: 1, y: 0 }}
205
- transition={{ delay: 0.2, duration: 0.3 }}
206
- />
207
- )
208
- DialogProFooter.displayName = "DialogProFooter"
209
-
210
- const DialogProTitle = React.forwardRef<
211
- React.ElementRef<typeof DialogPrimitive.Title>,
212
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
213
- >(({ className, ...props }, ref) => (
214
- <DialogPrimitive.Title
215
- ref={ref}
216
- className={cn(
217
- "text-lg font-semibold leading-none tracking-tight",
218
- className
219
- )}
220
- {...props}
221
- />
222
- ))
223
- DialogProTitle.displayName = DialogPrimitive.Title.displayName
224
-
225
- const DialogProDescription = React.forwardRef<
226
- React.ElementRef<typeof DialogPrimitive.Description>,
227
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
228
- >(({ className, ...props }, ref) => (
229
- <DialogPrimitive.Description
230
- ref={ref}
231
- className={cn("text-sm text-muted-foreground", className)}
232
- {...props}
233
- />
234
- ))
235
- DialogProDescription.displayName = DialogPrimitive.Description.displayName
236
-
237
- export {
238
- Dialog as DialogPro,
239
- DialogTrigger as DialogProTrigger,
240
- DialogProContent,
241
- DialogProHeader,
242
- DialogProFooter,
243
- DialogProTitle,
244
- DialogProDescription,
245
- DialogClose as DialogProClose,
246
- }
@@ -1,4 +0,0 @@
1
- export * from './button'
2
- export * from './card'
3
- export * from './dialog'
4
- export * from './badge'
@@ -1,243 +0,0 @@
1
- import { render, screen, fireEvent, waitFor } from '@testing-library/react'
2
- import '@testing-library/jest-dom'
3
- import React from 'react'
4
- import MoonUIFileUploadPro from './index'
5
-
6
- // Mock FileReader
7
- const mockFileReader = {
8
- readAsDataURL: jest.fn(),
9
- result: 'data:image/png;base64,mock-base64-data',
10
- onload: null as any,
11
- onerror: null as any,
12
- }
13
-
14
- global.FileReader = jest.fn(() => mockFileReader) as any
15
-
16
- // Mock file objects
17
- const createMockFile = (name: string, size: number, type: string) => {
18
- const file = new File(['mock content'], name, { type })
19
- Object.defineProperty(file, 'size', { value: size })
20
- return file
21
- }
22
-
23
- describe('MoonUIFileUploadPro', () => {
24
- beforeEach(() => {
25
- jest.clearAllMocks()
26
- })
27
-
28
- it('renders without crashing', () => {
29
- render(<MoonUIFileUploadPro />)
30
-
31
- expect(screen.getByText('File Upload')).toBeInTheDocument()
32
- expect(screen.getByText('Drag and drop files here, or click to select')).toBeInTheDocument()
33
- })
34
-
35
- it('renders with custom title and description', () => {
36
- render(
37
- <MoonUIFileUploadPro
38
- accept="image/*"
39
- maxSize={5}
40
- multiple
41
- />
42
- )
43
-
44
- expect(screen.getByText('Upload up to 5 files (max 5MB each)')).toBeInTheDocument()
45
- expect(screen.getByText('Accepted types: image/*')).toBeInTheDocument()
46
- })
47
-
48
- it('handles file selection', async () => {
49
- const mockOnUpload = jest.fn()
50
- render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
51
-
52
- const file = createMockFile('test.jpg', 1024, 'image/jpeg')
53
- const input = screen.getByRole('button', { hidden: true }) // Hidden file input
54
-
55
- fireEvent.change(input, { target: { files: [file] } })
56
-
57
- await waitFor(() => {
58
- expect(mockOnUpload).toHaveBeenCalledWith([file])
59
- })
60
- })
61
-
62
- it('validates file size', () => {
63
- const mockOnUpload = jest.fn()
64
- render(<MoonUIFileUploadPro onUpload={mockOnUpload} maxSize={1} />)
65
-
66
- const file = createMockFile('large-file.jpg', 2 * 1024 * 1024, 'image/jpeg') // 2MB
67
- const input = screen.getByRole('button', { hidden: true })
68
-
69
- // Mock alert
70
- global.alert = jest.fn()
71
-
72
- fireEvent.change(input, { target: { files: [file] } })
73
-
74
- expect(global.alert).toHaveBeenCalledWith('large-file.jpg: File size must be less than 1MB')
75
- expect(mockOnUpload).not.toHaveBeenCalled()
76
- })
77
-
78
- it('validates file type', () => {
79
- const mockOnUpload = jest.fn()
80
- render(
81
- <MoonUIFileUploadPro
82
- onUpload={mockOnUpload}
83
- allowedMimeTypes={['image/jpeg', 'image/png']}
84
- />
85
- )
86
-
87
- const file = createMockFile('document.pdf', 1024, 'application/pdf')
88
- const input = screen.getByRole('button', { hidden: true })
89
-
90
- global.alert = jest.fn()
91
-
92
- fireEvent.change(input, { target: { files: [file] } })
93
-
94
- expect(global.alert).toHaveBeenCalledWith('document.pdf: File type application/pdf is not allowed')
95
- expect(mockOnUpload).not.toHaveBeenCalled()
96
- })
97
-
98
- it('handles multiple files', async () => {
99
- const mockOnUpload = jest.fn()
100
- render(<MoonUIFileUploadPro onUpload={mockOnUpload} multiple />)
101
-
102
- const files = [
103
- createMockFile('file1.jpg', 1024, 'image/jpeg'),
104
- createMockFile('file2.png', 2048, 'image/png'),
105
- ]
106
- const input = screen.getByRole('button', { hidden: true })
107
-
108
- fireEvent.change(input, { target: { files } })
109
-
110
- await waitFor(() => {
111
- expect(mockOnUpload).toHaveBeenCalledWith(files)
112
- })
113
- })
114
-
115
- it('respects maxFiles limit', () => {
116
- const mockOnUpload = jest.fn()
117
- render(<MoonUIFileUploadPro onUpload={mockOnUpload} maxFiles={2} />)
118
-
119
- const files = [
120
- createMockFile('file1.jpg', 1024, 'image/jpeg'),
121
- createMockFile('file2.png', 1024, 'image/png'),
122
- createMockFile('file3.gif', 1024, 'image/gif'),
123
- ]
124
- const input = screen.getByRole('button', { hidden: true })
125
-
126
- global.alert = jest.fn()
127
-
128
- fireEvent.change(input, { target: { files } })
129
-
130
- expect(global.alert).toHaveBeenCalledWith('Maximum 2 files allowed')
131
- expect(mockOnUpload).not.toHaveBeenCalled()
132
- })
133
-
134
- it('handles drag and drop', () => {
135
- const mockOnUpload = jest.fn()
136
- render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
137
-
138
- const dropZone = screen.getByText('Drag and drop files here, or click to select').closest('div')
139
- const file = createMockFile('test.jpg', 1024, 'image/jpeg')
140
-
141
- fireEvent.dragOver(dropZone!, {
142
- dataTransfer: { files: [file] },
143
- })
144
-
145
- expect(dropZone).toHaveClass('border-primary')
146
-
147
- fireEvent.drop(dropZone!, {
148
- dataTransfer: { files: [file] },
149
- })
150
-
151
- expect(dropZone).not.toHaveClass('border-primary')
152
- })
153
-
154
- it('handles file removal', async () => {
155
- const mockOnRemove = jest.fn()
156
- render(<MoonUIFileUploadPro onRemove={mockOnRemove} />)
157
-
158
- const file = createMockFile('test.jpg', 1024, 'image/jpeg')
159
- const input = screen.getByRole('button', { hidden: true })
160
-
161
- fireEvent.change(input, { target: { files: [file] } })
162
-
163
- await waitFor(() => {
164
- expect(screen.getByText('test.jpg')).toBeInTheDocument()
165
- })
166
-
167
- const removeButton = screen.getByRole('button', { name: /remove/i })
168
- fireEvent.click(removeButton)
169
-
170
- expect(mockOnRemove).toHaveBeenCalledWith(file)
171
- })
172
-
173
- it('shows progress during upload', async () => {
174
- const mockOnUpload = jest.fn().mockResolvedValue(undefined)
175
- render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
176
-
177
- const file = createMockFile('test.jpg', 1024, 'image/jpeg')
178
- const input = screen.getByRole('button', { hidden: true })
179
-
180
- fireEvent.change(input, { target: { files: [file] } })
181
-
182
- await waitFor(() => {
183
- expect(screen.getByText('Uploading files...')).toBeInTheDocument()
184
- })
185
- })
186
-
187
- it('handles upload success', async () => {
188
- const mockOnUpload = jest.fn().mockResolvedValue(undefined)
189
- render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
190
-
191
- const file = createMockFile('test.jpg', 1024, 'image/jpeg')
192
- const input = screen.getByRole('button', { hidden: true })
193
-
194
- fireEvent.change(input, { target: { files: [file] } })
195
-
196
- await waitFor(() => {
197
- expect(screen.getByText('success')).toBeInTheDocument()
198
- })
199
- })
200
-
201
- it('handles upload error', async () => {
202
- const mockOnUpload = jest.fn().mockRejectedValue(new Error('Upload failed'))
203
- render(<MoonUIFileUploadPro onUpload={mockOnUpload} />)
204
-
205
- const file = createMockFile('test.jpg', 1024, 'image/jpeg')
206
- const input = screen.getByRole('button', { hidden: true })
207
-
208
- fireEvent.change(input, { target: { files: [file] } })
209
-
210
- await waitFor(() => {
211
- expect(screen.getByText('error')).toBeInTheDocument()
212
- expect(screen.getByText('Upload failed')).toBeInTheDocument()
213
- })
214
- })
215
-
216
- it('is disabled when disabled prop is true', () => {
217
- render(<MoonUIFileUploadPro disabled />)
218
-
219
- const dropZone = screen.getByText('Drag and drop files here, or click to select').closest('div')
220
- expect(dropZone).toHaveClass('cursor-not-allowed')
221
- })
222
-
223
- it('applies custom className', () => {
224
- render(<MoonUIFileUploadPro className="custom-upload" />)
225
-
226
- const container = screen.getByText('File Upload').closest('div')
227
- expect(container).toHaveClass('custom-upload')
228
- })
229
-
230
- it('formats file sizes correctly', () => {
231
- render(<MoonUIFileUploadPro />)
232
-
233
- // This would be tested through the file display after upload
234
- // The formatFileSize function should be tested separately
235
- })
236
-
237
- it('displays correct file icons', () => {
238
- render(<MoonUIFileUploadPro />)
239
-
240
- // This would be tested through the file display after upload
241
- // The getFileIcon function should be tested separately
242
- })
243
- })