@moontra/moonui 2.0.8 → 2.0.9

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 (94) hide show
  1. package/package.json +9 -2
  2. package/src/__tests__/use-intersection-observer.test.tsx +216 -0
  3. package/src/__tests__/use-local-storage.test.tsx +174 -0
  4. package/src/__tests__/use-pro-access.test.tsx +183 -0
  5. package/src/components/ui/__tests__/accordion.test.tsx +571 -0
  6. package/src/components/ui/__tests__/alert.test.tsx +484 -0
  7. package/src/components/ui/__tests__/aspect-ratio.test.tsx +492 -0
  8. package/src/components/ui/__tests__/avatar.test.tsx +382 -0
  9. package/src/components/ui/__tests__/badge.test.tsx +364 -0
  10. package/src/components/ui/__tests__/breadcrumb.test.tsx +687 -0
  11. package/src/components/ui/__tests__/button.test.tsx +91 -0
  12. package/src/components/ui/__tests__/card.test.tsx +104 -0
  13. package/src/components/ui/__tests__/checkbox.test.tsx +591 -0
  14. package/src/components/ui/__tests__/collapsible.test.tsx +592 -0
  15. package/src/components/ui/__tests__/color-picker.test.tsx +365 -0
  16. package/src/components/ui/__tests__/command.test.tsx +677 -0
  17. package/src/components/ui/__tests__/data-table.test.tsx +256 -0
  18. package/src/components/ui/__tests__/date-picker.test.tsx +320 -0
  19. package/src/components/ui/__tests__/dialog.test.tsx +764 -0
  20. package/src/components/ui/__tests__/input.test.tsx +318 -0
  21. package/src/components/ui/__tests__/label.test.tsx +103 -0
  22. package/src/components/ui/__tests__/popover.test.tsx +637 -0
  23. package/src/components/ui/__tests__/progress.test.tsx +382 -0
  24. package/src/components/ui/__tests__/radio-group.test.tsx +555 -0
  25. package/src/components/ui/__tests__/select.test.tsx +705 -0
  26. package/src/components/ui/__tests__/skeleton.test.tsx +253 -0
  27. package/src/components/ui/__tests__/slider.test.tsx +493 -0
  28. package/src/components/ui/__tests__/switch.test.tsx +372 -0
  29. package/src/components/ui/__tests__/table.test.tsx +824 -0
  30. package/src/components/ui/__tests__/tabs.test.tsx +887 -0
  31. package/src/components/ui/__tests__/toast.test.tsx +458 -0
  32. package/src/components/ui/__tests__/tooltip.test.tsx +583 -0
  33. package/src/components/ui/accordion.tsx +63 -0
  34. package/src/components/ui/alert.tsx +130 -0
  35. package/src/components/ui/aspect-ratio.tsx +72 -0
  36. package/src/components/ui/avatar.tsx +135 -0
  37. package/src/components/ui/badge.tsx +225 -0
  38. package/src/components/ui/breadcrumb.tsx +207 -0
  39. package/src/components/ui/button.stories.tsx +162 -0
  40. package/src/components/ui/button.tsx +221 -0
  41. package/src/components/ui/calendar.tsx +262 -0
  42. package/src/components/ui/card.stories.tsx +208 -0
  43. package/src/components/ui/card.tsx +141 -0
  44. package/src/components/ui/checkbox.tsx +256 -0
  45. package/src/components/ui/collapsible.tsx +129 -0
  46. package/src/components/ui/color-picker.tsx +664 -0
  47. package/src/components/ui/command.tsx +218 -0
  48. package/src/components/ui/data-table.stories.tsx +509 -0
  49. package/src/components/ui/data-table.tsx +623 -0
  50. package/src/components/ui/date-picker.stories.tsx +321 -0
  51. package/src/components/ui/date-picker.tsx +603 -0
  52. package/src/components/ui/dialog.tsx +332 -0
  53. package/src/components/ui/dropdown-menu.tsx +200 -0
  54. package/src/components/ui/file-upload.tsx +400 -0
  55. package/src/components/ui/github-stars.tsx +201 -0
  56. package/src/components/ui/index.ts +12 -0
  57. package/src/components/ui/input.stories.tsx +255 -0
  58. package/src/components/ui/input.tsx +219 -0
  59. package/src/components/ui/label.tsx +26 -0
  60. package/src/components/ui/locked-component.tsx +215 -0
  61. package/src/components/ui/moon-logo.tsx +97 -0
  62. package/src/components/ui/pagination.tsx +116 -0
  63. package/src/components/ui/popover.tsx +183 -0
  64. package/src/components/ui/progress.tsx +182 -0
  65. package/src/components/ui/radio-group.tsx +243 -0
  66. package/src/components/ui/select.tsx +273 -0
  67. package/src/components/ui/separator.tsx +140 -0
  68. package/src/components/ui/simple-editor.tsx +652 -0
  69. package/src/components/ui/skeleton.tsx +351 -0
  70. package/src/components/ui/slider.tsx +351 -0
  71. package/src/components/ui/switch.tsx +83 -0
  72. package/src/components/ui/table.tsx +322 -0
  73. package/src/components/ui/tabs.tsx +195 -0
  74. package/src/components/ui/textarea.tsx +46 -0
  75. package/src/components/ui/toast.tsx +313 -0
  76. package/src/components/ui/toggle.tsx +47 -0
  77. package/src/components/ui/tooltip.tsx +152 -0
  78. package/src/docs/theme-system.md +1194 -0
  79. package/src/index.tsx +39 -0
  80. package/src/lib/micro-interactions.ts +255 -0
  81. package/src/lib/theme.tsx +398 -0
  82. package/src/lib/utils.ts +69 -0
  83. package/src/styles/design-system.css +365 -0
  84. package/src/styles/index.css +4 -0
  85. package/src/styles/tailwind.css +6 -0
  86. package/src/styles/tokens.css +453 -0
  87. package/src/use-intersection-observer.tsx +154 -0
  88. package/src/use-local-storage.tsx +71 -0
  89. package/src/use-paddle.ts +138 -0
  90. package/src/use-performance-optimizer.ts +379 -0
  91. package/src/use-pro-access.ts +141 -0
  92. package/src/use-scroll-animation.ts +221 -0
  93. package/src/use-subscription.ts +37 -0
  94. package/src/use-toast.ts +32 -0
@@ -0,0 +1,458 @@
1
+ import React from 'react'
2
+ import { render, screen, fireEvent } from '@testing-library/react'
3
+ import userEvent from '@testing-library/user-event'
4
+ import {
5
+ Toast,
6
+ ToastProvider,
7
+ ToastTitle,
8
+ ToastDescription,
9
+ ToastAction,
10
+ ToastClose,
11
+ useToast,
12
+ Toaster
13
+ } from '../toast'
14
+
15
+ // Mock icons for testing
16
+ jest.mock('lucide-react', () => ({
17
+ X: (props: React.ComponentProps<'div'>) => <div data-testid="x-icon" {...props} />,
18
+ }))
19
+
20
+ // Test wrapper component for useToast hook
21
+ const TestToastWrapper = ({ children }: { children: React.ReactNode }) => (
22
+ <ToastProvider>{children}</ToastProvider>
23
+ )
24
+
25
+ describe('Toast Components', () => {
26
+ describe('Toast Component', () => {
27
+ describe('Basic Rendering', () => {
28
+ it('renders correctly with default props', () => {
29
+ render(
30
+ <TestToastWrapper>
31
+ <Toast />
32
+ </TestToastWrapper>
33
+ )
34
+
35
+ const toast = screen.getByRole('button', { name: /kapat/i })
36
+ expect(toast).toBeInTheDocument()
37
+ })
38
+
39
+ it('renders with title', () => {
40
+ render(
41
+ <TestToastWrapper>
42
+ <Toast title="Test Title" />
43
+ </TestToastWrapper>
44
+ )
45
+
46
+ expect(screen.getByText('Test Title')).toBeInTheDocument()
47
+ })
48
+
49
+ it('renders with description', () => {
50
+ render(
51
+ <TestToastWrapper>
52
+ <Toast description="Test Description" />
53
+ </TestToastWrapper>
54
+ )
55
+
56
+ expect(screen.getByText('Test Description')).toBeInTheDocument()
57
+ })
58
+
59
+ it('applies custom className', () => {
60
+ const { container } = render(
61
+ <ToastProvider>
62
+ <Toast className="custom-toast" />
63
+ </ToastProvider>
64
+ )
65
+
66
+ expect(container.querySelector('.custom-toast')).toBeInTheDocument()
67
+ })
68
+
69
+ it('has correct displayName', () => {
70
+ expect((Toast as any).displayName || 'Toast').toBe('Toast')
71
+ })
72
+ })
73
+
74
+ describe('Variants', () => {
75
+ it('renders primary variant correctly', () => {
76
+ const { container } = render(
77
+ <ToastProvider>
78
+ <Toast variant="primary" />
79
+ </ToastProvider>
80
+ )
81
+
82
+ expect(container.querySelector('[class*="bg-primary"]')).toBeInTheDocument()
83
+ })
84
+
85
+ it('renders secondary variant correctly', () => {
86
+ const { container } = render(
87
+ <ToastProvider>
88
+ <Toast variant="secondary" />
89
+ </ToastProvider>
90
+ )
91
+
92
+ expect(container.querySelector('[class*="bg-secondary"]')).toBeInTheDocument()
93
+ })
94
+
95
+ it('renders success variant correctly', () => {
96
+ const { container } = render(
97
+ <ToastProvider>
98
+ <Toast variant="success" />
99
+ </ToastProvider>
100
+ )
101
+
102
+ expect(container.querySelector('[class*="bg-success"]')).toBeInTheDocument()
103
+ })
104
+
105
+ it('renders caution variant correctly', () => {
106
+ const { container } = render(
107
+ <ToastProvider>
108
+ <Toast variant="caution" />
109
+ </ToastProvider>
110
+ )
111
+
112
+ expect(container.querySelector('[class*="bg-warning"]')).toBeInTheDocument()
113
+ })
114
+
115
+ it('renders destructive variant correctly', () => {
116
+ const { container } = render(
117
+ <ToastProvider>
118
+ <Toast variant="destructive" />
119
+ </ToastProvider>
120
+ )
121
+
122
+ expect(container.querySelector('[class*="bg-destructive"]')).toBeInTheDocument()
123
+ })
124
+
125
+ it('renders info variant correctly', () => {
126
+ const { container } = render(
127
+ <ToastProvider>
128
+ <Toast variant="info" />
129
+ </ToastProvider>
130
+ )
131
+
132
+ expect(container.querySelector('[class*="bg-info"]')).toBeInTheDocument()
133
+ })
134
+ })
135
+
136
+ describe('Actions', () => {
137
+ it('renders action element', () => {
138
+ const action = <button data-testid="toast-action">Action</button>
139
+ render(
140
+ <TestToastWrapper>
141
+ <Toast action={action} />
142
+ </TestToastWrapper>
143
+ )
144
+
145
+ expect(screen.getByTestId('toast-action')).toBeInTheDocument()
146
+ })
147
+
148
+ it('handles close button click', async () => {
149
+ const onClose = jest.fn()
150
+ const user = userEvent.setup()
151
+
152
+ render(
153
+ <TestToastWrapper>
154
+ <Toast id="test-toast" onClose={onClose} />
155
+ </TestToastWrapper>
156
+ )
157
+
158
+ const closeButton = screen.getByRole('button', { name: /kapat/i })
159
+ await user.click(closeButton)
160
+
161
+ expect(onClose).toHaveBeenCalled()
162
+ })
163
+ })
164
+
165
+ describe('HTML Attributes', () => {
166
+ it('passes through HTML attributes', () => {
167
+ const { container } = render(
168
+ <TestToastWrapper>
169
+ <Toast data-testid="toast" aria-label="Custom toast" />
170
+ </TestToastWrapper>
171
+ )
172
+
173
+ const toast = container.querySelector('[data-testid="toast"]')
174
+ expect(toast).toHaveAttribute('aria-label', 'Custom toast')
175
+ })
176
+ })
177
+ })
178
+
179
+ describe('ToastProvider Component', () => {
180
+ describe('Basic Rendering', () => {
181
+ it('renders children correctly', () => {
182
+ render(
183
+ <ToastProvider>
184
+ <div data-testid="child">Child Content</div>
185
+ </ToastProvider>
186
+ )
187
+
188
+ expect(screen.getByTestId('child')).toBeInTheDocument()
189
+ })
190
+
191
+ it('renders toast container', () => {
192
+ const { container } = render(
193
+ <ToastProvider>
194
+ <div>Content</div>
195
+ </ToastProvider>
196
+ )
197
+
198
+ const toastContainer = container.querySelector('[aria-label="Bildirimler"]')
199
+ expect(toastContainer).toBeInTheDocument()
200
+ })
201
+ })
202
+
203
+ describe('Toast Management', () => {
204
+ it('renders toasts in provider', () => {
205
+ render(
206
+ <ToastProvider>
207
+ <Toast title="Test Toast" />
208
+ </ToastProvider>
209
+ )
210
+
211
+ expect(screen.getByText('Test Toast')).toBeInTheDocument()
212
+ })
213
+
214
+ it('renders multiple toasts', () => {
215
+ render(
216
+ <ToastProvider>
217
+ <Toast title="Toast 1" />
218
+ <Toast title="Toast 2" />
219
+ </ToastProvider>
220
+ )
221
+
222
+ expect(screen.getByText('Toast 1')).toBeInTheDocument()
223
+ expect(screen.getByText('Toast 2')).toBeInTheDocument()
224
+ })
225
+ })
226
+ })
227
+
228
+ describe('ToastTitle Component', () => {
229
+ describe('Basic Rendering', () => {
230
+ it('renders correctly with default props', () => {
231
+ render(<ToastTitle>Title Content</ToastTitle>)
232
+
233
+ expect(screen.getByText('Title Content')).toBeInTheDocument()
234
+ })
235
+
236
+ it('applies custom className', () => {
237
+ render(<ToastTitle className="custom-title">Title</ToastTitle>)
238
+
239
+ expect(screen.getByText('Title')).toHaveClass('custom-title')
240
+ })
241
+
242
+ it('passes through HTML attributes', () => {
243
+ render(<ToastTitle data-testid="toast-title">Title</ToastTitle>)
244
+
245
+ expect(screen.getByTestId('toast-title')).toBeInTheDocument()
246
+ })
247
+ })
248
+ })
249
+
250
+ describe('ToastDescription Component', () => {
251
+ describe('Basic Rendering', () => {
252
+ it('renders correctly with default props', () => {
253
+ render(<ToastDescription>Description Content</ToastDescription>)
254
+
255
+ expect(screen.getByText('Description Content')).toBeInTheDocument()
256
+ })
257
+
258
+ it('applies custom className', () => {
259
+ render(<ToastDescription className="custom-desc">Description</ToastDescription>)
260
+
261
+ expect(screen.getByText('Description')).toHaveClass('custom-desc')
262
+ })
263
+
264
+ it('passes through HTML attributes', () => {
265
+ render(<ToastDescription data-testid="toast-desc">Description</ToastDescription>)
266
+
267
+ expect(screen.getByTestId('toast-desc')).toBeInTheDocument()
268
+ })
269
+ })
270
+ })
271
+
272
+ describe('ToastAction Component', () => {
273
+ describe('Basic Rendering', () => {
274
+ it('renders correctly with default props', () => {
275
+ render(<ToastAction>Action</ToastAction>)
276
+
277
+ expect(screen.getByRole('button', { name: 'Action' })).toBeInTheDocument()
278
+ })
279
+
280
+ it('applies custom className', () => {
281
+ render(<ToastAction className="custom-action">Action</ToastAction>)
282
+
283
+ expect(screen.getByRole('button')).toHaveClass('custom-action')
284
+ })
285
+
286
+ it('handles click events', async () => {
287
+ const onClick = jest.fn()
288
+
289
+ render(<ToastAction onClick={onClick}>Action</ToastAction>)
290
+
291
+ fireEvent.click(screen.getByRole('button'))
292
+ expect(onClick).toHaveBeenCalled()
293
+ })
294
+
295
+ it('passes through HTML attributes', () => {
296
+ render(<ToastAction data-testid="toast-action">Action</ToastAction>)
297
+
298
+ expect(screen.getByTestId('toast-action')).toBeInTheDocument()
299
+ })
300
+ })
301
+ })
302
+
303
+ describe('ToastClose Component', () => {
304
+ describe('Basic Rendering', () => {
305
+ it('renders correctly with default props', () => {
306
+ render(<ToastClose />)
307
+
308
+ expect(screen.getByRole('button', { name: /kapat/i })).toBeInTheDocument()
309
+ expect(screen.getByTestId('x-icon')).toBeInTheDocument()
310
+ })
311
+
312
+ it('applies custom className', () => {
313
+ render(<ToastClose className="custom-close" />)
314
+
315
+ expect(screen.getByRole('button')).toHaveClass('custom-close')
316
+ })
317
+
318
+ it('handles click events', async () => {
319
+ const onClick = jest.fn()
320
+
321
+ render(<ToastClose onClick={onClick} />)
322
+
323
+ fireEvent.click(screen.getByRole('button'))
324
+ expect(onClick).toHaveBeenCalled()
325
+ })
326
+
327
+ it('passes through HTML attributes', () => {
328
+ render(<ToastClose data-testid="toast-close" />)
329
+
330
+ expect(screen.getByTestId('toast-close')).toBeInTheDocument()
331
+ })
332
+ })
333
+ })
334
+
335
+ describe('useToast Hook', () => {
336
+ describe('Context Usage', () => {
337
+ it('works correctly within ToastProvider', () => {
338
+ const TestComponent = () => {
339
+ const { toasts } = useToast()
340
+ return <div data-testid="toast-count">{toasts.length}</div>
341
+ }
342
+
343
+ render(
344
+ <ToastProvider>
345
+ <TestComponent />
346
+ </ToastProvider>
347
+ )
348
+
349
+ expect(screen.getByTestId('toast-count')).toHaveTextContent('0')
350
+ })
351
+ })
352
+ })
353
+
354
+ describe('Toaster Component', () => {
355
+ it('renders Toaster component', () => {
356
+ render(<Toaster><div>Test content</div></Toaster>)
357
+ // Toaster should render without errors
358
+ expect(document.body).toBeInTheDocument()
359
+ })
360
+ })
361
+
362
+ describe('Complex Combinations', () => {
363
+ it('renders complete toast with all components', () => {
364
+ render(
365
+ <TestToastWrapper>
366
+ <Toast
367
+ title="Complete Toast"
368
+ description="This is a complete toast"
369
+ variant="success"
370
+ action={<ToastAction>Retry</ToastAction>}
371
+ />
372
+ </TestToastWrapper>
373
+ )
374
+
375
+ expect(screen.getByText('Complete Toast')).toBeInTheDocument()
376
+ expect(screen.getByText('This is a complete toast')).toBeInTheDocument()
377
+ expect(screen.getByRole('button', { name: 'Retry' })).toBeInTheDocument()
378
+ expect(screen.getByRole('button', { name: /kapat/i })).toBeInTheDocument()
379
+ })
380
+
381
+ it('handles multiple toasts', () => {
382
+ render(
383
+ <TestToastWrapper>
384
+ <Toast title="Toast 1" />
385
+ <Toast title="Toast 2" />
386
+ <Toast title="Toast 3" />
387
+ </TestToastWrapper>
388
+ )
389
+
390
+ expect(screen.getByText('Toast 1')).toBeInTheDocument()
391
+ expect(screen.getByText('Toast 2')).toBeInTheDocument()
392
+ expect(screen.getByText('Toast 3')).toBeInTheDocument()
393
+ })
394
+ })
395
+
396
+ describe('Edge Cases', () => {
397
+ it('handles toast without id', () => {
398
+ render(
399
+ <TestToastWrapper>
400
+ <Toast title="No ID Toast" />
401
+ </TestToastWrapper>
402
+ )
403
+
404
+ expect(screen.getByText('No ID Toast')).toBeInTheDocument()
405
+ })
406
+
407
+ it('handles empty toast content', () => {
408
+ render(
409
+ <TestToastWrapper>
410
+ <Toast />
411
+ </TestToastWrapper>
412
+ )
413
+
414
+ expect(screen.getByRole('button', { name: /kapat/i })).toBeInTheDocument()
415
+ })
416
+
417
+ it('handles null/undefined props', () => {
418
+ render(
419
+ <TestToastWrapper>
420
+ <Toast title={null} description={undefined} />
421
+ </TestToastWrapper>
422
+ )
423
+
424
+ expect(screen.getByRole('button', { name: /kapat/i })).toBeInTheDocument()
425
+ })
426
+
427
+ it('handles complex nested content', () => {
428
+ render(
429
+ <TestToastWrapper>
430
+ <Toast
431
+ title={<span>Complex <strong>Title</strong></span>}
432
+ description={<div>Complex <em>Description</em></div>}
433
+ />
434
+ </TestToastWrapper>
435
+ )
436
+
437
+ expect(screen.getAllByText('Complex')).toHaveLength(2)
438
+ expect(screen.getByText('Title')).toBeInTheDocument()
439
+ expect(screen.getByText('Description')).toBeInTheDocument()
440
+ })
441
+
442
+ it('passes through HTML attributes for all components', () => {
443
+ render(
444
+ <div>
445
+ <ToastTitle data-testid="title" aria-label="Title">Title</ToastTitle>
446
+ <ToastDescription data-testid="desc" aria-label="Description">Description</ToastDescription>
447
+ <ToastAction data-testid="action" aria-label="Action">Action</ToastAction>
448
+ <ToastClose data-testid="close" aria-label="Close" />
449
+ </div>
450
+ )
451
+
452
+ expect(screen.getByTestId('title')).toHaveAttribute('aria-label', 'Title')
453
+ expect(screen.getByTestId('desc')).toHaveAttribute('aria-label', 'Description')
454
+ expect(screen.getByTestId('action')).toHaveAttribute('aria-label', 'Action')
455
+ expect(screen.getByTestId('close')).toHaveAttribute('aria-label', 'Close')
456
+ })
457
+ })
458
+ })