@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
@@ -1,281 +0,0 @@
1
- import { render, screen, fireEvent } from '@testing-library/react'
2
- import '@testing-library/jest-dom'
3
- import { AdvancedChart } from './index'
4
-
5
- // Mock recharts to avoid canvas issues in tests
6
- jest.mock('recharts', () => ({
7
- ResponsiveContainer: ({ children }: any) => <div data-testid="responsive-container">{children}</div>,
8
- LineChart: ({ children }: any) => <div data-testid="line-chart">{children}</div>,
9
- BarChart: ({ children }: any) => <div data-testid="bar-chart">{children}</div>,
10
- AreaChart: ({ children }: any) => <div data-testid="area-chart">{children}</div>,
11
- PieChart: ({ children }: any) => <div data-testid="pie-chart">{children}</div>,
12
- ScatterChart: ({ children }: any) => <div data-testid="scatter-chart">{children}</div>,
13
- Line: () => <div data-testid="line" />,
14
- Bar: () => <div data-testid="bar" />,
15
- Area: () => <div data-testid="area" />,
16
- Pie: () => <div data-testid="pie" />,
17
- Scatter: () => <div data-testid="scatter" />,
18
- Cell: () => <div data-testid="cell" />,
19
- XAxis: () => <div data-testid="x-axis" />,
20
- YAxis: () => <div data-testid="y-axis" />,
21
- CartesianGrid: () => <div data-testid="grid" />,
22
- Tooltip: () => <div data-testid="tooltip" />,
23
- Legend: () => <div data-testid="legend" />,
24
- ReferenceLine: () => <div data-testid="reference-line" />,
25
- ReferenceArea: () => <div data-testid="reference-area" />,
26
- Brush: () => <div data-testid="brush" />,
27
- }))
28
-
29
- // Mock data for testing
30
- const mockData = [
31
- { name: 'Jan', value: 400, revenue: 2400 },
32
- { name: 'Feb', value: 300, revenue: 1398 },
33
- { name: 'Mar', value: 200, revenue: 9800 },
34
- { name: 'Apr', value: 278, revenue: 3908 },
35
- { name: 'May', value: 189, revenue: 4800 },
36
- { name: 'Jun', value: 239, revenue: 3800 },
37
- ]
38
-
39
- const mockSeries = [
40
- {
41
- dataKey: 'value',
42
- name: 'Users',
43
- color: '#8884d8',
44
- },
45
- {
46
- dataKey: 'revenue',
47
- name: 'Revenue',
48
- color: '#82ca9d',
49
- },
50
- ]
51
-
52
- describe('AdvancedChart', () => {
53
- it('renders without crashing', () => {
54
- render(
55
- <AdvancedChart
56
- data={mockData}
57
- series={mockSeries}
58
- type="line"
59
- />
60
- )
61
-
62
- expect(screen.getByText('Advanced Chart')).toBeInTheDocument()
63
- })
64
-
65
- it('renders with custom title', () => {
66
- render(
67
- <AdvancedChart
68
- data={mockData}
69
- series={mockSeries}
70
- type="line"
71
- title="Custom Chart Title"
72
- />
73
- )
74
-
75
- expect(screen.getByText('Custom Chart Title')).toBeInTheDocument()
76
- })
77
-
78
- it('renders with subtitle', () => {
79
- render(
80
- <AdvancedChart
81
- data={mockData}
82
- series={mockSeries}
83
- type="line"
84
- title="Chart Title"
85
- subtitle="Chart Subtitle"
86
- />
87
- )
88
-
89
- expect(screen.getByText('Chart Subtitle')).toBeInTheDocument()
90
- })
91
-
92
- it('renders line chart type', () => {
93
- render(
94
- <AdvancedChart
95
- data={mockData}
96
- series={mockSeries}
97
- type="line"
98
- />
99
- )
100
-
101
- expect(screen.getByTestId('line-chart')).toBeInTheDocument()
102
- })
103
-
104
- it('renders bar chart type', () => {
105
- render(
106
- <AdvancedChart
107
- data={mockData}
108
- series={mockSeries}
109
- type="bar"
110
- />
111
- )
112
-
113
- expect(screen.getByTestId('bar-chart')).toBeInTheDocument()
114
- })
115
-
116
- it('renders area chart type', () => {
117
- render(
118
- <AdvancedChart
119
- data={mockData}
120
- series={mockSeries}
121
- type="area"
122
- />
123
- )
124
-
125
- expect(screen.getByTestId('area-chart')).toBeInTheDocument()
126
- })
127
-
128
- it('renders pie chart type', () => {
129
- render(
130
- <AdvancedChart
131
- data={mockData}
132
- series={mockSeries}
133
- type="pie"
134
- />
135
- )
136
-
137
- expect(screen.getByTestId('pie-chart')).toBeInTheDocument()
138
- })
139
-
140
- it('renders scatter chart type', () => {
141
- render(
142
- <AdvancedChart
143
- data={mockData}
144
- series={mockSeries}
145
- type="scatter"
146
- />
147
- )
148
-
149
- expect(screen.getByTestId('scatter-chart')).toBeInTheDocument()
150
- })
151
-
152
- it('shows loading state', () => {
153
- render(
154
- <AdvancedChart
155
- data={mockData}
156
- series={mockSeries}
157
- type="line"
158
- loading={true}
159
- />
160
- )
161
-
162
- expect(screen.getByText('Loading chart...')).toBeInTheDocument()
163
- })
164
-
165
- it('shows error state', () => {
166
- render(
167
- <AdvancedChart
168
- data={mockData}
169
- series={mockSeries}
170
- type="line"
171
- error="Something went wrong"
172
- />
173
- )
174
-
175
- expect(screen.getByText('Something went wrong')).toBeInTheDocument()
176
- expect(screen.getByText('Retry')).toBeInTheDocument()
177
- })
178
-
179
- it('calls onRefresh when refresh button is clicked', () => {
180
- const mockOnRefresh = jest.fn()
181
-
182
- render(
183
- <AdvancedChart
184
- data={mockData}
185
- series={mockSeries}
186
- type="line"
187
- onRefresh={mockOnRefresh}
188
- />
189
- )
190
-
191
- const refreshButton = screen.getByRole('button', { name: /refresh/i })
192
- fireEvent.click(refreshButton)
193
-
194
- expect(mockOnRefresh).toHaveBeenCalled()
195
- })
196
-
197
- it('calls onExport when export button is clicked', () => {
198
- const mockOnExport = jest.fn()
199
-
200
- render(
201
- <AdvancedChart
202
- data={mockData}
203
- series={mockSeries}
204
- type="line"
205
- onExport={mockOnExport}
206
- />
207
- )
208
-
209
- const exportButton = screen.getByRole('button', { name: /download/i })
210
- fireEvent.click(exportButton)
211
-
212
- expect(mockOnExport).toHaveBeenCalledWith('png')
213
- })
214
-
215
- it('displays trend indicator', () => {
216
- render(
217
- <AdvancedChart
218
- data={mockData}
219
- series={mockSeries}
220
- type="line"
221
- title="Revenue Chart"
222
- />
223
- )
224
-
225
- // Should display trend percentage
226
- expect(screen.getByText(/%/)).toBeInTheDocument()
227
- })
228
-
229
- it('renders with custom height', () => {
230
- render(
231
- <AdvancedChart
232
- data={mockData}
233
- series={mockSeries}
234
- type="line"
235
- height={600}
236
- />
237
- )
238
-
239
- expect(screen.getByTestId('responsive-container')).toBeInTheDocument()
240
- })
241
-
242
- it('handles responsive mode', () => {
243
- render(
244
- <AdvancedChart
245
- data={mockData}
246
- series={mockSeries}
247
- type="line"
248
- responsive={true}
249
- />
250
- )
251
-
252
- expect(screen.getByTestId('responsive-container')).toBeInTheDocument()
253
- })
254
-
255
- it('handles non-responsive mode', () => {
256
- render(
257
- <AdvancedChart
258
- data={mockData}
259
- series={mockSeries}
260
- type="line"
261
- responsive={false}
262
- />
263
- )
264
-
265
- expect(screen.queryByTestId('responsive-container')).not.toBeInTheDocument()
266
- })
267
-
268
- it('applies custom className', () => {
269
- render(
270
- <AdvancedChart
271
- data={mockData}
272
- series={mockSeries}
273
- type="line"
274
- className="custom-chart"
275
- />
276
- )
277
-
278
- const chartContainer = screen.getByText('Advanced Chart').closest('div')
279
- expect(chartContainer).toHaveClass('custom-chart')
280
- })
281
- })
@@ -1,187 +0,0 @@
1
- import { render, screen, fireEvent } from '@testing-library/react'
2
- import '@testing-library/jest-dom'
3
- import { DataTable } from './index'
4
-
5
- // Mock data for testing
6
- const mockData = [
7
- { id: 1, name: 'John Doe', email: 'john@example.com', status: 'active' },
8
- { id: 2, name: 'Jane Smith', email: 'jane@example.com', status: 'inactive' },
9
- { id: 3, name: 'Bob Johnson', email: 'bob@example.com', status: 'active' }
10
- ]
11
-
12
- const mockColumns = [
13
- {
14
- accessorKey: 'name',
15
- header: 'Name',
16
- },
17
- {
18
- accessorKey: 'email',
19
- header: 'Email',
20
- },
21
- {
22
- accessorKey: 'status',
23
- header: 'Status',
24
- }
25
- ]
26
-
27
- describe('DataTable', () => {
28
- it('renders without crashing', () => {
29
- render(
30
- <DataTable
31
- columns={mockColumns}
32
- data={mockData}
33
- />
34
- )
35
-
36
- expect(screen.getByText('Name')).toBeInTheDocument()
37
- expect(screen.getByText('Email')).toBeInTheDocument()
38
- expect(screen.getByText('Status')).toBeInTheDocument()
39
- })
40
-
41
- it('displays data correctly', () => {
42
- render(
43
- <DataTable
44
- columns={mockColumns}
45
- data={mockData}
46
- />
47
- )
48
-
49
- expect(screen.getByText('John Doe')).toBeInTheDocument()
50
- expect(screen.getByText('jane@example.com')).toBeInTheDocument()
51
- expect(screen.getByText('active')).toBeInTheDocument()
52
- })
53
-
54
- it('shows search input when searchable is true', () => {
55
- render(
56
- <DataTable
57
- columns={mockColumns}
58
- data={mockData}
59
- searchable
60
- />
61
- )
62
-
63
- expect(screen.getByPlaceholderText('Search all columns...')).toBeInTheDocument()
64
- })
65
-
66
- it('shows filter button when filterable is true', () => {
67
- render(
68
- <DataTable
69
- columns={mockColumns}
70
- data={mockData}
71
- filterable
72
- />
73
- )
74
-
75
- expect(screen.getByText('Filters')).toBeInTheDocument()
76
- })
77
-
78
- it('shows export button when exportable is true', () => {
79
- render(
80
- <DataTable
81
- columns={mockColumns}
82
- data={mockData}
83
- exportable
84
- />
85
- )
86
-
87
- expect(screen.getByText('Export')).toBeInTheDocument()
88
- })
89
-
90
- it('handles search functionality', () => {
91
- render(
92
- <DataTable
93
- columns={mockColumns}
94
- data={mockData}
95
- searchable
96
- />
97
- )
98
-
99
- const searchInput = screen.getByPlaceholderText('Search all columns...')
100
- fireEvent.change(searchInput, { target: { value: 'john' } })
101
-
102
- expect(screen.getByText('John Doe')).toBeInTheDocument()
103
- // Jane Smith should be filtered out
104
- expect(screen.queryByText('Jane Smith')).not.toBeInTheDocument()
105
- })
106
-
107
- it('handles pagination', () => {
108
- // Create more data for pagination testing
109
- const moreData = Array.from({ length: 20 }, (_, i) => ({
110
- id: i + 1,
111
- name: `User ${i + 1}`,
112
- email: `user${i + 1}@example.com`,
113
- status: i % 2 === 0 ? 'active' : 'inactive'
114
- }))
115
-
116
- render(
117
- <DataTable
118
- columns={mockColumns}
119
- data={moreData}
120
- pagination
121
- pageSize={10}
122
- />
123
- )
124
-
125
- expect(screen.getByText('Page 1 of 2')).toBeInTheDocument()
126
- expect(screen.getByText('Rows per page')).toBeInTheDocument()
127
- })
128
-
129
- it('calls onRowSelect when row is selected', () => {
130
- const mockOnRowSelect = jest.fn()
131
-
132
- render(
133
- <DataTable
134
- columns={mockColumns}
135
- data={mockData}
136
- selectable
137
- onRowSelect={mockOnRowSelect}
138
- />
139
- )
140
-
141
- // This would require implementing selection in the component
142
- // For now, just verify the component renders with selection enabled
143
- expect(screen.getByRole('table')).toBeInTheDocument()
144
- })
145
-
146
- it('calls onExport when export button is clicked', () => {
147
- const mockOnExport = jest.fn()
148
-
149
- render(
150
- <DataTable
151
- columns={mockColumns}
152
- data={mockData}
153
- exportable
154
- onExport={mockOnExport}
155
- />
156
- )
157
-
158
- const exportButton = screen.getByText('Export')
159
- fireEvent.click(exportButton)
160
-
161
- expect(mockOnExport).toHaveBeenCalledWith(mockData)
162
- })
163
-
164
- it('handles empty data state', () => {
165
- render(
166
- <DataTable
167
- columns={mockColumns}
168
- data={[]}
169
- />
170
- )
171
-
172
- expect(screen.getByText('No results found.')).toBeInTheDocument()
173
- })
174
-
175
- it('applies custom className', () => {
176
- render(
177
- <DataTable
178
- columns={mockColumns}
179
- data={mockData}
180
- className="custom-table"
181
- />
182
- )
183
-
184
- const tableContainer = screen.getByRole('table').closest('div')
185
- expect(tableContainer).toHaveClass('custom-table')
186
- })
187
- })
@@ -1,191 +0,0 @@
1
- import React from 'react'
2
- import { motion, AnimatePresence } from 'framer-motion'
3
- import { cva, type VariantProps } from 'class-variance-authority'
4
- import { cn } from '../../lib/utils'
5
-
6
- const badgeVariants = cva(
7
- ["inline-flex items-center gap-1.5",
8
- "font-medium transition-all duration-200",
9
- "border focus:outline-none",
10
- "focus-visible:ring-2 focus-visible:ring-offset-1"],
11
- {
12
- variants: {
13
- variant: {
14
- default: [
15
- "border-transparent bg-primary text-primary-foreground",
16
- "hover:bg-primary/90",
17
- "focus-visible:ring-primary/30",
18
- ],
19
- secondary: [
20
- "border-transparent bg-secondary text-secondary-foreground",
21
- "hover:bg-secondary/80",
22
- "focus-visible:ring-gray-400/30",
23
- ],
24
- destructive: [
25
- "border-transparent bg-destructive text-destructive-foreground",
26
- "hover:bg-destructive/90",
27
- "focus-visible:ring-destructive/30",
28
- ],
29
- outline: [
30
- "border-input bg-transparent",
31
- "hover:border-input/80",
32
- "focus-visible:ring-gray-400/30",
33
- ],
34
- success: [
35
- "border-transparent bg-green-500 text-white",
36
- "hover:bg-green-600",
37
- "focus-visible:ring-green-500/30",
38
- ],
39
- warning: [
40
- "border-transparent bg-yellow-500 text-white",
41
- "hover:bg-yellow-600",
42
- "focus-visible:ring-yellow-500/30",
43
- ],
44
- pro: [
45
- "border-transparent bg-gradient-to-r from-purple-600 to-pink-600 text-white",
46
- "hover:from-purple-700 hover:to-pink-700",
47
- "focus-visible:ring-purple-400/30",
48
- ],
49
- },
50
- size: {
51
- sm: "h-5 px-2 text-xs",
52
- default: "h-6 px-3 text-sm",
53
- lg: "h-8 px-4 text-base",
54
- },
55
- },
56
- defaultVariants: {
57
- variant: "default",
58
- size: "default",
59
- },
60
- }
61
- )
62
-
63
- export interface BadgeProProps
64
- extends React.HTMLAttributes<HTMLDivElement>,
65
- VariantProps<typeof badgeVariants> {
66
- enablePulse?: boolean
67
- enableGlow?: boolean
68
- enableShimmer?: boolean
69
- removable?: boolean
70
- onRemove?: () => void
71
- leftIcon?: React.ReactNode
72
- rightIcon?: React.ReactNode
73
- }
74
-
75
- export const BadgePro = React.forwardRef<
76
- HTMLDivElement,
77
- BadgeProProps
78
- >(({
79
- className,
80
- variant,
81
- size,
82
- enablePulse = false,
83
- enableGlow = false,
84
- enableShimmer = false,
85
- removable = false,
86
- onRemove,
87
- leftIcon,
88
- rightIcon,
89
- children,
90
- ...props
91
- }, ref) => {
92
- const [isRemoving, setIsRemoving] = React.useState(false)
93
-
94
- const handleRemove = () => {
95
- setIsRemoving(true)
96
- setTimeout(() => {
97
- onRemove?.()
98
- }, 300)
99
- }
100
-
101
- // Auto-assign icons for special variants
102
- let autoLeftIcon = leftIcon
103
- let autoChildren = children
104
-
105
- if (variant === 'pro' && !leftIcon) {
106
- autoLeftIcon = (
107
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="w-3 h-3">
108
- <path d="M12 0L13.09 8.26L22 9L13.09 9.74L12 18L10.91 9.74L2 9L10.91 8.26L12 0Z" fill="currentColor"/>
109
- <path d="M19 5L19.5 7L21 7.5L19.5 8L19 10L18.5 8L17 7.5L18.5 7L19 5Z" fill="currentColor"/>
110
- <path d="M19 15L19.5 17L21 17.5L19.5 18L19 20L18.5 18L17 17.5L18.5 17L19 15Z" fill="currentColor"/>
111
- </svg>
112
- )
113
- autoChildren = children || 'Pro'
114
- }
115
-
116
- return (
117
- <AnimatePresence>
118
- {!isRemoving && (
119
- <motion.div
120
- ref={ref}
121
- className={cn(
122
- badgeVariants({ variant, size }),
123
- enablePulse && "animate-pulse",
124
- enableGlow && "shadow-lg shadow-current/50",
125
- enableShimmer && "relative overflow-hidden",
126
- className
127
- )}
128
- initial={{ opacity: 0, scale: 0.8 }}
129
- animate={{ opacity: 1, scale: 1 }}
130
- exit={{ opacity: 0, scale: 0.8 }}
131
- transition={{ duration: 0.2 }}
132
- whileHover={{ scale: 1.05 }}
133
- whileTap={{ scale: 0.95 }}
134
- >
135
- {enableShimmer && (
136
- <motion.div
137
- className="absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-white/20 to-transparent"
138
- animate={{ translateX: "200%" }}
139
- transition={{ duration: 2, repeat: Infinity, ease: "linear" }}
140
- />
141
- )}
142
-
143
- {autoLeftIcon && (
144
- <motion.span
145
- className="inline-flex shrink-0"
146
- animate={enablePulse ? { scale: [1, 1.2, 1] } : {}}
147
- transition={{ duration: 2, repeat: Infinity }}
148
- >
149
- {autoLeftIcon}
150
- </motion.span>
151
- )}
152
-
153
- <span className="truncate">{autoChildren}</span>
154
-
155
- {rightIcon && (
156
- <span className="inline-flex shrink-0">
157
- {rightIcon}
158
- </span>
159
- )}
160
-
161
- {removable && onRemove && (
162
- <motion.button
163
- type="button"
164
- className="ml-1 -mr-1 h-3.5 w-3.5 rounded-full inline-flex items-center justify-center hover:bg-black/10 dark:hover:bg-white/10"
165
- onClick={handleRemove}
166
- whileHover={{ rotate: 90 }}
167
- transition={{ type: "spring", stiffness: 300 }}
168
- aria-label="Remove badge"
169
- >
170
- <svg
171
- width="8"
172
- height="8"
173
- viewBox="0 0 8 8"
174
- fill="none"
175
- xmlns="http://www.w3.org/2000/svg"
176
- className="opacity-70"
177
- aria-hidden="true"
178
- >
179
- <path d="M0.799988 7.19999L7.19999 0.799988M0.799988 0.799988L7.19999 7.19999" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
180
- </svg>
181
- </motion.button>
182
- )}
183
- </motion.div>
184
- )}
185
- </AnimatePresence>
186
- )
187
- })
188
-
189
- BadgePro.displayName = 'BadgePro'
190
-
191
- export { badgeVariants }