@moontra/moonui 2.2.0 → 2.2.1

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 (44) hide show
  1. package/dist/index.d.mts +91 -14
  2. package/dist/index.d.ts +91 -14
  3. package/dist/index.js +1714 -369
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1546 -371
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +2 -2
  8. package/src/components/ui/alert.tsx +123 -93
  9. package/src/components/ui/avatar.tsx +2 -0
  10. package/src/components/ui/badge.tsx +19 -17
  11. package/src/components/ui/breadcrumb.tsx +2 -0
  12. package/src/components/ui/button.stories.tsx +4 -2
  13. package/src/components/ui/button.tsx +39 -33
  14. package/src/components/ui/calendar.tsx +1 -1
  15. package/src/components/ui/card-input.tsx +231 -0
  16. package/src/components/ui/card.stories.tsx +2 -0
  17. package/src/components/ui/card.tsx +2 -0
  18. package/src/components/ui/data-table.stories.tsx +4 -2
  19. package/src/components/ui/data-table.tsx +7 -7
  20. package/src/components/ui/date-picker.stories.tsx +2 -0
  21. package/src/components/ui/date-picker.tsx +18 -9
  22. package/src/components/ui/draggable-list.tsx +2 -0
  23. package/src/components/ui/index.ts +357 -44
  24. package/src/components/ui/input.stories.tsx +2 -0
  25. package/src/components/ui/input.tsx +2 -0
  26. package/src/components/ui/locked-component.tsx +222 -0
  27. package/src/components/ui/pagination.tsx +2 -0
  28. package/src/components/ui/phone-input.tsx +172 -0
  29. package/src/components/ui/popover-pro.tsx +424 -0
  30. package/src/components/ui/rich-text-editor/index.tsx +2 -1
  31. package/src/components/ui/scroll-area.tsx +48 -0
  32. package/src/components/ui/select.tsx +5 -1
  33. package/src/components/ui/separator.tsx +2 -2
  34. package/src/components/ui/swipeable-card.tsx +2 -0
  35. package/src/components/ui/table.tsx +2 -0
  36. package/src/components/ui/tabs.tsx +2 -0
  37. package/src/components/ui/tags-input.tsx +130 -0
  38. package/src/components/ui/textarea.tsx +2 -0
  39. package/src/components/ui/toast.tsx +2 -0
  40. package/src/index.tsx +4 -46
  41. package/src/lib/performance-profiler.ts +79 -0
  42. package/src/styles/index.css +315 -2
  43. package/src/use-performance-optimizer.ts +26 -26
  44. package/src/use-scroll-animation.ts +5 -7
@@ -0,0 +1,172 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "../../lib/utils"
5
+ import { Input } from "./input"
6
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select"
7
+ import { Phone } from "lucide-react"
8
+
9
+ // Country codes data
10
+ const countryCodes = [
11
+ { code: "+1", country: "US", flag: "🇺🇸", name: "United States" },
12
+ { code: "+44", country: "GB", flag: "🇬🇧", name: "United Kingdom" },
13
+ { code: "+49", country: "DE", flag: "🇩🇪", name: "Germany" },
14
+ { code: "+33", country: "FR", flag: "🇫🇷", name: "France" },
15
+ { code: "+39", country: "IT", flag: "🇮🇹", name: "Italy" },
16
+ { code: "+34", country: "ES", flag: "🇪🇸", name: "Spain" },
17
+ { code: "+31", country: "NL", flag: "🇳🇱", name: "Netherlands" },
18
+ { code: "+46", country: "SE", flag: "🇸🇪", name: "Sweden" },
19
+ { code: "+47", country: "NO", flag: "🇳🇴", name: "Norway" },
20
+ { code: "+45", country: "DK", flag: "🇩🇰", name: "Denmark" },
21
+ { code: "+358", country: "FI", flag: "🇫🇮", name: "Finland" },
22
+ { code: "+48", country: "PL", flag: "🇵🇱", name: "Poland" },
23
+ { code: "+90", country: "TR", flag: "🇹🇷", name: "Turkey" },
24
+ { code: "+86", country: "CN", flag: "🇨🇳", name: "China" },
25
+ { code: "+81", country: "JP", flag: "🇯🇵", name: "Japan" },
26
+ { code: "+82", country: "KR", flag: "🇰🇷", name: "South Korea" },
27
+ { code: "+91", country: "IN", flag: "🇮🇳", name: "India" },
28
+ { code: "+61", country: "AU", flag: "🇦🇺", name: "Australia" },
29
+ { code: "+64", country: "NZ", flag: "🇳🇿", name: "New Zealand" },
30
+ { code: "+27", country: "ZA", flag: "🇿🇦", name: "South Africa" },
31
+ { code: "+55", country: "BR", flag: "🇧🇷", name: "Brazil" },
32
+ { code: "+52", country: "MX", flag: "🇲🇽", name: "Mexico" },
33
+ { code: "+54", country: "AR", flag: "🇦🇷", name: "Argentina" },
34
+ { code: "+20", country: "EG", flag: "🇪🇬", name: "Egypt" },
35
+ { code: "+966", country: "SA", flag: "🇸🇦", name: "Saudi Arabia" },
36
+ { code: "+971", country: "AE", flag: "🇦🇪", name: "UAE" },
37
+ ]
38
+
39
+ // Format phone number based on country
40
+ const formatPhoneNumber = (value: string, countryCode: string): string => {
41
+ const cleaned = value.replace(/\D/g, "")
42
+
43
+ switch (countryCode) {
44
+ case "+1": // US/Canada
45
+ if (cleaned.length <= 3) return cleaned
46
+ if (cleaned.length <= 6) return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3)}`
47
+ return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3, 6)}-${cleaned.slice(6, 10)}`
48
+
49
+ case "+44": // UK
50
+ if (cleaned.length <= 4) return cleaned
51
+ if (cleaned.length <= 7) return `${cleaned.slice(0, 4)} ${cleaned.slice(4)}`
52
+ return `${cleaned.slice(0, 4)} ${cleaned.slice(4, 7)} ${cleaned.slice(7, 11)}`
53
+
54
+ case "+90": // Turkey
55
+ if (cleaned.length <= 3) return cleaned
56
+ if (cleaned.length <= 6) return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3)}`
57
+ if (cleaned.length <= 9) return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3, 6)} ${cleaned.slice(6)}`
58
+ return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3, 6)} ${cleaned.slice(6, 8)} ${cleaned.slice(8, 10)}`
59
+
60
+ default: // Generic formatting
61
+ let formatted = ""
62
+ for (let i = 0; i < cleaned.length; i++) {
63
+ if (i > 0 && i % 3 === 0) formatted += " "
64
+ formatted += cleaned[i]
65
+ }
66
+ return formatted
67
+ }
68
+ }
69
+
70
+ // Get max length based on country
71
+ const getMaxLength = (countryCode: string): number => {
72
+ switch (countryCode) {
73
+ case "+1": return 10 // US/Canada
74
+ case "+44": return 11 // UK
75
+ case "+90": return 10 // Turkey
76
+ default: return 15 // Generic max
77
+ }
78
+ }
79
+
80
+ export interface PhoneInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value"> {
81
+ value?: string
82
+ onChange?: (value: string, countryCode: string) => void
83
+ defaultCountry?: string
84
+ showIcon?: boolean
85
+ showCountrySelect?: boolean
86
+ countries?: typeof countryCodes
87
+ }
88
+
89
+ export const PhoneInput = React.forwardRef<HTMLInputElement, PhoneInputProps>(
90
+ ({
91
+ className,
92
+ value = "",
93
+ onChange,
94
+ defaultCountry = "+1",
95
+ showIcon = true,
96
+ showCountrySelect = true,
97
+ countries = countryCodes,
98
+ size,
99
+ ...props
100
+ }, ref) => {
101
+ const [countryCode, setCountryCode] = React.useState(defaultCountry)
102
+ const [phoneNumber, setPhoneNumber] = React.useState(value)
103
+
104
+ const selectedCountry = countries.find(c => c.code === countryCode) || countries[0]
105
+
106
+ const handlePhoneChange = (e: React.ChangeEvent<HTMLInputElement>) => {
107
+ const rawValue = e.target.value.replace(/\D/g, "")
108
+ const maxLength = getMaxLength(countryCode)
109
+ const truncated = rawValue.slice(0, maxLength)
110
+ const formatted = formatPhoneNumber(truncated, countryCode)
111
+
112
+ setPhoneNumber(truncated)
113
+ onChange?.(truncated, countryCode)
114
+
115
+ // Update the input value with formatted version
116
+ e.target.value = formatted
117
+ }
118
+
119
+ const handleCountryChange = (newCountryCode: string) => {
120
+ setCountryCode(newCountryCode)
121
+ onChange?.(phoneNumber, newCountryCode)
122
+ }
123
+
124
+ const formattedValue = formatPhoneNumber(phoneNumber, countryCode)
125
+
126
+ return (
127
+ <div className={cn("relative flex gap-2", className)}>
128
+ {showCountrySelect && (
129
+ <Select value={countryCode} onValueChange={handleCountryChange}>
130
+ <SelectTrigger className="w-[120px]">
131
+ <SelectValue>
132
+ <div className="flex items-center gap-2">
133
+ <span>{selectedCountry.flag}</span>
134
+ <span>{selectedCountry.code}</span>
135
+ </div>
136
+ </SelectValue>
137
+ </SelectTrigger>
138
+ <SelectContent>
139
+ {countries.map((country) => (
140
+ <SelectItem key={country.code} value={country.code}>
141
+ <div className="flex items-center gap-2">
142
+ <span>{country.flag}</span>
143
+ <span>{country.code}</span>
144
+ <span className="text-muted-foreground">{country.name}</span>
145
+ </div>
146
+ </SelectItem>
147
+ ))}
148
+ </SelectContent>
149
+ </Select>
150
+ )}
151
+
152
+ <div className="relative flex-1">
153
+ <Input
154
+ ref={ref}
155
+ type="tel"
156
+ inputMode="numeric"
157
+ autoComplete="tel"
158
+ placeholder={countryCode === "+1" ? "(555) 123-4567" : "123 456 789"}
159
+ value={formattedValue}
160
+ onChange={handlePhoneChange}
161
+ className={cn(showIcon && "pl-10", className)}
162
+ {...props}
163
+ />
164
+ {showIcon && (
165
+ <Phone className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
166
+ )}
167
+ </div>
168
+ </div>
169
+ )
170
+ }
171
+ )
172
+ PhoneInput.displayName = "PhoneInput"
@@ -0,0 +1,424 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as PopoverPrimitive from "@radix-ui/react-popover"
5
+ import { motion, AnimatePresence, useSpring, useTransform } from "framer-motion"
6
+ import { cn } from "../../lib/utils"
7
+ import { cva, type VariantProps } from "class-variance-authority"
8
+
9
+ const PopoverPro = PopoverPrimitive.Root
10
+ const PopoverTriggerPro = PopoverPrimitive.Trigger
11
+ const PopoverAnchorPro = PopoverPrimitive.Anchor
12
+ const PopoverPortalPro = PopoverPrimitive.Portal
13
+
14
+ // Animation variants
15
+ const popoverAnimations = {
16
+ // Basic animations
17
+ fade: {
18
+ initial: { opacity: 0 },
19
+ animate: { opacity: 1 },
20
+ exit: { opacity: 0 }
21
+ },
22
+ scale: {
23
+ initial: { opacity: 0, scale: 0.95 },
24
+ animate: { opacity: 1, scale: 1 },
25
+ exit: { opacity: 0, scale: 0.95 }
26
+ },
27
+ slide: {
28
+ initial: { opacity: 0, y: -10 },
29
+ animate: { opacity: 1, y: 0 },
30
+ exit: { opacity: 0, y: -10 }
31
+ },
32
+ // Advanced animations
33
+ spring: {
34
+ initial: { opacity: 0, scale: 0.8, y: -20 },
35
+ animate: {
36
+ opacity: 1,
37
+ scale: 1,
38
+ y: 0,
39
+ transition: {
40
+ type: "spring",
41
+ stiffness: 300,
42
+ damping: 20
43
+ }
44
+ },
45
+ exit: { opacity: 0, scale: 0.8, y: -20 }
46
+ },
47
+ elastic: {
48
+ initial: { opacity: 0, scale: 0.5, rotate: -10 },
49
+ animate: {
50
+ opacity: 1,
51
+ scale: 1,
52
+ rotate: 0,
53
+ transition: {
54
+ type: "spring",
55
+ stiffness: 400,
56
+ damping: 15
57
+ }
58
+ },
59
+ exit: { opacity: 0, scale: 0.5, rotate: 10 }
60
+ },
61
+ bounce: {
62
+ initial: { opacity: 0, y: -30 },
63
+ animate: {
64
+ opacity: 1,
65
+ y: 0,
66
+ transition: {
67
+ type: "spring",
68
+ stiffness: 500,
69
+ damping: 15,
70
+ mass: 1
71
+ }
72
+ },
73
+ exit: { opacity: 0, y: -30 }
74
+ },
75
+ flip: {
76
+ initial: { opacity: 0, rotateX: -90 },
77
+ animate: {
78
+ opacity: 1,
79
+ rotateX: 0,
80
+ transition: {
81
+ type: "spring",
82
+ stiffness: 300,
83
+ damping: 20
84
+ }
85
+ },
86
+ exit: { opacity: 0, rotateX: 90 }
87
+ },
88
+ slideFromBottom: {
89
+ initial: { opacity: 0, y: 20 },
90
+ animate: {
91
+ opacity: 1,
92
+ y: 0,
93
+ transition: {
94
+ type: "spring",
95
+ stiffness: 300,
96
+ damping: 25
97
+ }
98
+ },
99
+ exit: { opacity: 0, y: 20 }
100
+ },
101
+ zoom: {
102
+ initial: { opacity: 0, scale: 0 },
103
+ animate: {
104
+ opacity: 1,
105
+ scale: 1,
106
+ transition: {
107
+ type: "spring",
108
+ stiffness: 300,
109
+ damping: 20
110
+ }
111
+ },
112
+ exit: { opacity: 0, scale: 0 }
113
+ },
114
+ morph: {
115
+ initial: {
116
+ opacity: 0,
117
+ scale: 0.8,
118
+ borderRadius: "50%"
119
+ },
120
+ animate: {
121
+ opacity: 1,
122
+ scale: 1,
123
+ borderRadius: "12px",
124
+ transition: {
125
+ type: "spring",
126
+ stiffness: 300,
127
+ damping: 25
128
+ }
129
+ },
130
+ exit: {
131
+ opacity: 0,
132
+ scale: 0.8,
133
+ borderRadius: "50%"
134
+ }
135
+ }
136
+ }
137
+
138
+ const popoverContentVariants = cva(
139
+ "z-50 w-72 rounded-md p-4 shadow-md outline-none",
140
+ {
141
+ variants: {
142
+ variant: {
143
+ default: "border bg-popover text-popover-foreground",
144
+ glass: [
145
+ "border border-white/20 bg-white/80 backdrop-blur-xl",
146
+ "dark:border-gray-800/50 dark:bg-gray-900/80",
147
+ "shadow-xl"
148
+ ],
149
+ gradient: [
150
+ "bg-gradient-to-br from-white to-gray-50",
151
+ "dark:from-gray-900 dark:to-gray-950",
152
+ "border border-gray-200 dark:border-gray-800",
153
+ "shadow-xl"
154
+ ],
155
+ solid: [
156
+ "bg-white dark:bg-gray-900",
157
+ "border-2 border-gray-200 dark:border-gray-700",
158
+ "shadow-2xl"
159
+ ],
160
+ floating: [
161
+ "bg-white dark:bg-gray-900",
162
+ "shadow-2xl shadow-black/20 dark:shadow-black/40",
163
+ "border border-gray-100 dark:border-gray-800"
164
+ ],
165
+ neumorphic: [
166
+ "bg-gray-100 dark:bg-gray-900",
167
+ "shadow-[20px_20px_60px_#bebebe,-20px_-20px_60px_#ffffff]",
168
+ "dark:shadow-[20px_20px_60px_#1a1a1a,-20px_-20px_60px_#2a2a2a]",
169
+ "border-0"
170
+ ]
171
+ },
172
+ size: {
173
+ sm: "w-56 p-3",
174
+ default: "w-72 p-4",
175
+ lg: "w-96 p-6",
176
+ xl: "w-[32rem] p-8",
177
+ auto: "w-auto p-4"
178
+ },
179
+ overlayBlur: {
180
+ none: "",
181
+ sm: "backdrop-blur-sm",
182
+ md: "backdrop-blur-md",
183
+ lg: "backdrop-blur-lg",
184
+ xl: "backdrop-blur-xl"
185
+ }
186
+ },
187
+ defaultVariants: {
188
+ variant: "default",
189
+ size: "default",
190
+ overlayBlur: "none"
191
+ }
192
+ }
193
+ )
194
+
195
+ export interface PopoverContentProProps
196
+ extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>,
197
+ VariantProps<typeof popoverContentVariants> {
198
+ animation?: keyof typeof popoverAnimations
199
+ enableSpringPhysics?: boolean
200
+ showArrow?: boolean
201
+ arrowSize?: number
202
+ customBackdrop?: boolean
203
+ dragToDismiss?: boolean
204
+ pinnable?: boolean
205
+ resizable?: boolean
206
+ focusTrap?: boolean
207
+ closeOnEscape?: boolean
208
+ closeOnClickOutside?: boolean
209
+ staggerChildren?: boolean
210
+ glowEffect?: boolean
211
+ magneticEdges?: boolean
212
+ }
213
+
214
+ const PopoverContentPro = React.forwardRef<
215
+ React.ElementRef<typeof PopoverPrimitive.Content>,
216
+ PopoverContentProProps
217
+ >(
218
+ (
219
+ {
220
+ className,
221
+ align = "center",
222
+ sideOffset = 4,
223
+ variant,
224
+ size,
225
+ overlayBlur,
226
+ animation = "spring",
227
+ enableSpringPhysics = false,
228
+ showArrow = false,
229
+ arrowSize = 8,
230
+ customBackdrop = false,
231
+ dragToDismiss = false,
232
+ pinnable = false,
233
+ resizable = false,
234
+ focusTrap = false,
235
+ closeOnEscape = true,
236
+ closeOnClickOutside = true,
237
+ staggerChildren = false,
238
+ glowEffect = false,
239
+ magneticEdges = false,
240
+ children,
241
+ ...props
242
+ },
243
+ ref
244
+ ) => {
245
+ const [isPinned, setIsPinned] = React.useState(false)
246
+ const [isDragging, setIsDragging] = React.useState(false)
247
+ const animationVariant = popoverAnimations[animation] || popoverAnimations.spring
248
+
249
+ // Spring physics for magnetic edges
250
+ const x = useSpring(0, { stiffness: 300, damping: 30 })
251
+ const y = useSpring(0, { stiffness: 300, damping: 30 })
252
+
253
+ const contentElement = (
254
+ <PopoverPrimitive.Content
255
+ ref={ref}
256
+ align={align}
257
+ sideOffset={sideOffset}
258
+ onEscapeKeyDown={(e) => {
259
+ if (!closeOnEscape || isPinned) {
260
+ e.preventDefault()
261
+ }
262
+ }}
263
+ onPointerDownOutside={(e) => {
264
+ if (!closeOnClickOutside || isPinned) {
265
+ e.preventDefault()
266
+ }
267
+ }}
268
+ className={cn(
269
+ popoverContentVariants({ variant, size, overlayBlur }),
270
+ glowEffect && "shadow-[0_0_30px_rgba(59,130,246,0.3)]",
271
+ resizable && "resize overflow-auto",
272
+ isDragging && "cursor-grabbing",
273
+ className
274
+ )}
275
+ {...props}
276
+ >
277
+ {pinnable && (
278
+ <button
279
+ onClick={() => setIsPinned(!isPinned)}
280
+ className="absolute top-2 right-2 p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-800"
281
+ aria-label={isPinned ? "Unpin popover" : "Pin popover"}
282
+ >
283
+ <svg
284
+ width="16"
285
+ height="16"
286
+ viewBox="0 0 24 24"
287
+ fill="none"
288
+ stroke="currentColor"
289
+ strokeWidth="2"
290
+ className={cn(
291
+ "transition-transform",
292
+ isPinned && "rotate-45"
293
+ )}
294
+ >
295
+ <path d="M12 17v5M9 10V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v6M9 10l-2 2v3h10v-3l-2-2" />
296
+ </svg>
297
+ </button>
298
+ )}
299
+
300
+ {showArrow && (
301
+ <PopoverPrimitive.Arrow
302
+ width={arrowSize * 2}
303
+ height={arrowSize}
304
+ className={cn(
305
+ "fill-current",
306
+ variant === "glass" && "text-white/80 dark:text-gray-900/80",
307
+ variant === "gradient" && "text-white dark:text-gray-900",
308
+ variant === "default" && "text-popover"
309
+ )}
310
+ />
311
+ )}
312
+
313
+ <div
314
+ className={cn(
315
+ staggerChildren && "space-y-2",
316
+ dragToDismiss && "select-none"
317
+ )}
318
+ >
319
+ {children}
320
+ </div>
321
+ </PopoverPrimitive.Content>
322
+ )
323
+
324
+ if (enableSpringPhysics || magneticEdges) {
325
+ return (
326
+ <AnimatePresence mode="wait">
327
+ <motion.div
328
+ {...(animationVariant as any)}
329
+ style={magneticEdges ? { x, y } : undefined}
330
+ drag={dragToDismiss}
331
+ dragElastic={0.2}
332
+ dragConstraints={{ left: -50, right: 50, top: -50, bottom: 50 }}
333
+ onDragStart={() => setIsDragging(true)}
334
+ onDragEnd={() => setIsDragging(false)}
335
+ >
336
+ {contentElement}
337
+ </motion.div>
338
+ </AnimatePresence>
339
+ )
340
+ }
341
+
342
+ return contentElement
343
+ }
344
+ )
345
+
346
+ PopoverContentPro.displayName = PopoverPrimitive.Content.displayName
347
+
348
+ // Additional Pro components
349
+ const PopoverHeaderPro = React.forwardRef<
350
+ HTMLDivElement,
351
+ React.HTMLAttributes<HTMLDivElement>
352
+ >(({ className, ...props }, ref) => (
353
+ <div
354
+ ref={ref}
355
+ className={cn("mb-4 space-y-1", className)}
356
+ {...props}
357
+ />
358
+ ))
359
+ PopoverHeaderPro.displayName = "PopoverHeaderPro"
360
+
361
+ const PopoverTitlePro = React.forwardRef<
362
+ HTMLHeadingElement,
363
+ React.HTMLAttributes<HTMLHeadingElement>
364
+ >(({ className, ...props }, ref) => (
365
+ <h3
366
+ ref={ref}
367
+ className={cn("font-semibold text-lg leading-none tracking-tight", className)}
368
+ {...props}
369
+ />
370
+ ))
371
+ PopoverTitlePro.displayName = "PopoverTitlePro"
372
+
373
+ const PopoverDescriptionPro = React.forwardRef<
374
+ HTMLParagraphElement,
375
+ React.HTMLAttributes<HTMLParagraphElement>
376
+ >(({ className, ...props }, ref) => (
377
+ <p
378
+ ref={ref}
379
+ className={cn("text-sm text-muted-foreground", className)}
380
+ {...props}
381
+ />
382
+ ))
383
+ PopoverDescriptionPro.displayName = "PopoverDescriptionPro"
384
+
385
+ const PopoverFooterPro = React.forwardRef<
386
+ HTMLDivElement,
387
+ React.HTMLAttributes<HTMLDivElement>
388
+ >(({ className, ...props }, ref) => (
389
+ <div
390
+ ref={ref}
391
+ className={cn(
392
+ "mt-4 flex items-center justify-end space-x-2 pt-4 border-t",
393
+ className
394
+ )}
395
+ {...props}
396
+ />
397
+ ))
398
+ PopoverFooterPro.displayName = "PopoverFooterPro"
399
+
400
+ const PopoverSeparatorPro = React.forwardRef<
401
+ HTMLHRElement,
402
+ React.HTMLAttributes<HTMLHRElement>
403
+ >(({ className, ...props }, ref) => (
404
+ <hr
405
+ ref={ref}
406
+ className={cn("my-4 border-t", className)}
407
+ {...props}
408
+ />
409
+ ))
410
+ PopoverSeparatorPro.displayName = "PopoverSeparatorPro"
411
+
412
+ export {
413
+ PopoverPro,
414
+ PopoverTriggerPro,
415
+ PopoverContentPro,
416
+ PopoverAnchorPro,
417
+ PopoverPortalPro,
418
+ PopoverHeaderPro,
419
+ PopoverTitlePro,
420
+ PopoverDescriptionPro,
421
+ PopoverFooterPro,
422
+ PopoverSeparatorPro,
423
+ popoverContentVariants
424
+ }
@@ -1,6 +1,7 @@
1
- // Basic Rich Text Editor - Free Version
2
1
  "use client"
3
2
 
3
+ // Basic Rich Text Editor - Free Version
4
+
4
5
  import * as React from "react"
5
6
  import { cn } from "../../../lib/utils"
6
7
 
@@ -0,0 +1,48 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
5
+
6
+ import { cn } from "../../lib/utils"
7
+
8
+ const ScrollArea = React.forwardRef<
9
+ React.ElementRef<typeof ScrollAreaPrimitive.Root>,
10
+ React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
11
+ >(({ className, children, ...props }, ref) => (
12
+ <ScrollAreaPrimitive.Root
13
+ ref={ref}
14
+ className={cn("relative overflow-hidden", className)}
15
+ {...props}
16
+ >
17
+ <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
18
+ {children}
19
+ </ScrollAreaPrimitive.Viewport>
20
+ <ScrollBar />
21
+ <ScrollAreaPrimitive.Corner />
22
+ </ScrollAreaPrimitive.Root>
23
+ ))
24
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
25
+
26
+ const ScrollBar = React.forwardRef<
27
+ React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
28
+ React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
29
+ >(({ className, orientation = "vertical", ...props }, ref) => (
30
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
31
+ ref={ref}
32
+ orientation={orientation}
33
+ className={cn(
34
+ "flex touch-none select-none transition-colors",
35
+ orientation === "vertical" &&
36
+ "h-full w-2.5 border-l border-l-transparent p-[1px]",
37
+ orientation === "horizontal" &&
38
+ "h-2.5 flex-col border-t border-t-transparent p-[1px]",
39
+ className
40
+ )}
41
+ {...props}
42
+ >
43
+ <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
44
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
45
+ ))
46
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
47
+
48
+ export { ScrollArea, ScrollBar }
@@ -143,10 +143,14 @@ SelectScrollDownButton.displayName =
143
143
  const SelectContent = React.forwardRef<
144
144
  React.ElementRef<typeof SelectPrimitive.Content>,
145
145
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
146
- >(({ className, children, position = "item-aligned", ...props }, ref) => (
146
+ >(({ className, children, position = "popper", side = "bottom", sideOffset = 4, align = "start", ...props }, ref) => (
147
147
  <SelectPrimitive.Portal>
148
148
  <SelectPrimitive.Content
149
149
  ref={ref}
150
+ side={side}
151
+ sideOffset={sideOffset}
152
+ align={align}
153
+ avoidCollisions={false}
150
154
  className={cn(
151
155
  ["relative z-50 max-h-96 min-w-[8rem] overflow-hidden",
152
156
  "rounded-md border border-gray-200 dark:border-gray-700",
@@ -105,7 +105,7 @@ const separatorVariants = cva(
105
105
  )
106
106
 
107
107
  export interface SeparatorProps
108
- extends React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>,
108
+ extends Omit<React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>, keyof VariantProps<typeof separatorVariants>>,
109
109
  VariantProps<typeof separatorVariants> {}
110
110
 
111
111
  const Separator = React.forwardRef<
@@ -126,7 +126,7 @@ const Separator = React.forwardRef<
126
126
  <SeparatorPrimitive.Root
127
127
  ref={ref}
128
128
  decorative={decorative}
129
- orientation={orientation}
129
+ orientation={orientation || undefined}
130
130
  className={cn(
131
131
  separatorVariants({ orientation, variant, size }),
132
132
  className
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  // Basic Swipeable Card - Free Version
2
4
  "use client"
3
5
 
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import * as React from "react";
2
4
  import { cva, type VariantProps } from "class-variance-authority";
3
5