@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,215 @@
1
+ // Locked Component UI
2
+ // Pro componentlerin locked state'ini gösteren wrapper component
3
+
4
+ import React, { useState } from 'react'
5
+ import { cn } from '../../lib/utils'
6
+ import { Button } from './button'
7
+ import { Badge } from './badge'
8
+ import { Lock, Crown, Zap } from 'lucide-react'
9
+ import Link from 'next/link'
10
+ import { useComponentAccess } from '../../use-pro-access'
11
+
12
+ interface LockedComponentProps {
13
+ children: React.ReactNode
14
+ componentName: string
15
+ className?: string
16
+ showPreview?: boolean
17
+ previewDuration?: number // ms
18
+ }
19
+
20
+ export function LockedComponent({
21
+ children,
22
+ componentName,
23
+ className,
24
+ showPreview = true,
25
+ previewDuration = 2000
26
+ }: LockedComponentProps) {
27
+ const [isPreviewActive, setIsPreviewActive] = useState(false)
28
+ const [previewTimeout, setPreviewTimeout] = useState<NodeJS.Timeout | null>(null)
29
+
30
+ const handleMouseEnter = () => {
31
+ if (!showPreview) return
32
+
33
+ setIsPreviewActive(true)
34
+
35
+ // Clear existing timeout
36
+ if (previewTimeout) {
37
+ clearTimeout(previewTimeout)
38
+ }
39
+
40
+ // Set new timeout
41
+ const timeout = setTimeout(() => {
42
+ setIsPreviewActive(false)
43
+ }, previewDuration)
44
+
45
+ setPreviewTimeout(timeout)
46
+ }
47
+
48
+ const handleMouseLeave = () => {
49
+ if (previewTimeout) {
50
+ clearTimeout(previewTimeout)
51
+ setPreviewTimeout(null)
52
+ }
53
+ setIsPreviewActive(false)
54
+ }
55
+
56
+ return (
57
+ <div
58
+ className={cn(
59
+ "relative group cursor-pointer transition-all duration-300",
60
+ className
61
+ )}
62
+ onMouseEnter={handleMouseEnter}
63
+ onMouseLeave={handleMouseLeave}
64
+ >
65
+ {/* Component Content */}
66
+ <div
67
+ className={cn(
68
+ "transition-all duration-300",
69
+ !isPreviewActive && "blur-sm grayscale-[0.3] opacity-60"
70
+ )}
71
+ >
72
+ {children}
73
+ </div>
74
+
75
+ {/* Overlay */}
76
+ <div
77
+ className={cn(
78
+ "absolute inset-0 bg-gradient-to-br from-amber-500/10 via-transparent to-purple-500/10",
79
+ "border-2 border-dashed border-amber-400/30 rounded-lg",
80
+ "flex items-center justify-center",
81
+ "transition-all duration-300",
82
+ isPreviewActive ? "opacity-0" : "opacity-100"
83
+ )}
84
+ >
85
+ <div className="text-center space-y-3 p-6">
86
+ {/* Pro Badge */}
87
+ <div className="flex justify-center">
88
+ <Badge
89
+ variant="secondary"
90
+ className="bg-gradient-to-r from-amber-500 to-orange-500 text-white border-0 px-3 py-1"
91
+ >
92
+ <Crown className="w-3 h-3 mr-1" />
93
+ PRO ONLY
94
+ </Badge>
95
+ </div>
96
+
97
+ {/* Lock Icon */}
98
+ <div className="flex justify-center">
99
+ <div className="p-3 rounded-full bg-amber-100 dark:bg-amber-900/30">
100
+ <Lock className="w-6 h-6 text-amber-600 dark:text-amber-400" />
101
+ </div>
102
+ </div>
103
+
104
+ {/* Component Name */}
105
+ <h3 className="font-semibold text-gray-900 dark:text-gray-100">
106
+ {componentName}
107
+ </h3>
108
+
109
+ {/* Description */}
110
+ <p className="text-sm text-gray-600 dark:text-gray-400 max-w-xs">
111
+ This premium component is available with Pro subscription
112
+ </p>
113
+
114
+ {/* Upgrade Button */}
115
+ <Link href="/pricing">
116
+ <Button
117
+ size="sm"
118
+ className="bg-gradient-to-r from-amber-500 to-orange-500 hover:from-amber-600 hover:to-orange-600 border-0"
119
+ >
120
+ <Zap className="w-4 h-4 mr-2" />
121
+ Upgrade to Pro
122
+ </Button>
123
+ </Link>
124
+ </div>
125
+ </div>
126
+
127
+ {/* Preview Hint */}
128
+ {showPreview && !isPreviewActive && (
129
+ <div className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
130
+ <div className="bg-black/80 text-white text-xs px-2 py-1 rounded">
131
+ Hover to preview
132
+ </div>
133
+ </div>
134
+ )}
135
+ </div>
136
+ )
137
+ }
138
+
139
+ // Pro Component Wrapper - Otomatik erişim kontrolü ile
140
+ interface ProComponentWrapperProps {
141
+ children: React.ReactNode
142
+ componentId: string
143
+ componentName?: string
144
+ className?: string
145
+ fallback?: React.ReactNode
146
+ }
147
+
148
+ export function ProComponentWrapper({
149
+ children,
150
+ componentId,
151
+ componentName,
152
+ className,
153
+ fallback
154
+ }: ProComponentWrapperProps) {
155
+ const { canUse, isLocked, isLoading } = useComponentAccess(componentId)
156
+
157
+ // Loading state
158
+ if (isLoading) {
159
+ return (
160
+ <div className={cn("animate-pulse bg-gray-200 dark:bg-gray-800 rounded-lg h-32", className)}>
161
+ <div className="flex items-center justify-center h-full">
162
+ <div className="text-sm text-gray-500">Loading...</div>
163
+ </div>
164
+ </div>
165
+ )
166
+ }
167
+
168
+ // Unlocked - show actual component
169
+ if (canUse) {
170
+ return <div className={className}>{children}</div>
171
+ }
172
+
173
+ // Locked - show locked state
174
+ if (isLocked) {
175
+ return (
176
+ <LockedComponent
177
+ componentName={componentName || componentId}
178
+ className={className}
179
+ >
180
+ {fallback || children}
181
+ </LockedComponent>
182
+ )
183
+ }
184
+
185
+ // Default fallback
186
+ return <div className={className}>{children}</div>
187
+ }
188
+
189
+ // Pro Badge Component
190
+ export function ProBadge({ className }: { className?: string }) {
191
+ return (
192
+ <Badge
193
+ variant="secondary"
194
+ className={cn(
195
+ "bg-gradient-to-r from-amber-500 to-orange-500 text-white border-0 text-xs",
196
+ className
197
+ )}
198
+ >
199
+ <Crown className="w-3 h-3 mr-1" />
200
+ PRO
201
+ </Badge>
202
+ )
203
+ }
204
+
205
+ // Free Badge Component
206
+ export function FreeBadge({ className }: { className?: string }) {
207
+ return (
208
+ <Badge
209
+ variant="outline"
210
+ className={cn("border-green-500 text-green-600 dark:text-green-400 text-xs", className)}
211
+ >
212
+ FREE
213
+ </Badge>
214
+ )
215
+ }
@@ -0,0 +1,97 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "../../lib/utils"
5
+
6
+ interface MoonLogoProps extends React.SVGProps<SVGSVGElement> {
7
+ variant?: "default" | "monochrome" | "gradient"
8
+ showText?: boolean
9
+ }
10
+
11
+ export function MoonLogo({
12
+ className,
13
+ variant = "default",
14
+ showText = true,
15
+ ...props
16
+ }: MoonLogoProps) {
17
+ const logoId = React.useId()
18
+ const gradientId = `moon-gradient-${logoId}`
19
+
20
+ return (
21
+ <div className={cn("flex items-center gap-2", className)}>
22
+ {/* Moon Icon */}
23
+ <svg
24
+ width="32"
25
+ height="32"
26
+ viewBox="0 0 32 32"
27
+ fill="none"
28
+ xmlns="http://www.w3.org/2000/svg"
29
+ className="flex-shrink-0"
30
+ {...props}
31
+ >
32
+ {variant === "gradient" && (
33
+ <defs>
34
+ <linearGradient id={gradientId} x1="0%" y1="0%" x2="100%" y2="100%">
35
+ <stop offset="0%" stopColor="#3B82F6" />
36
+ <stop offset="50%" stopColor="#8B5CF6" />
37
+ <stop offset="100%" stopColor="#EC4899" />
38
+ </linearGradient>
39
+ </defs>
40
+ )}
41
+
42
+ {/* Moon Circle */}
43
+ <circle
44
+ cx="16"
45
+ cy="16"
46
+ r="14"
47
+ fill={variant === "gradient" ? `url(#${gradientId})` : "currentColor"}
48
+ className={variant === "default" ? "fill-primary" : ""}
49
+ />
50
+
51
+ {/* Crescent cutout */}
52
+ <circle
53
+ cx="22"
54
+ cy="10"
55
+ r="10"
56
+ fill="white"
57
+ className="dark:fill-background"
58
+ />
59
+ </svg>
60
+
61
+ {/* Text */}
62
+ {showText && (
63
+ <span className="text-xl font-bold">
64
+ <span className="text-foreground">Moon</span>
65
+ <span className="text-primary">UI</span>
66
+ </span>
67
+ )}
68
+ </div>
69
+ )
70
+ }
71
+
72
+ export function MoonLogoIcon({
73
+ className,
74
+ variant = "default",
75
+ ...props
76
+ }: Omit<MoonLogoProps, "showText">) {
77
+ return <MoonLogo showText={false} className={className} variant={variant} {...props} />
78
+ }
79
+
80
+ export function MoonLogoAnimated({
81
+ className,
82
+ variant = "default",
83
+ showText = true,
84
+ ...props
85
+ }: MoonLogoProps) {
86
+ return (
87
+ <MoonLogo
88
+ className={cn(
89
+ "transition-all duration-300 hover:scale-105",
90
+ className
91
+ )}
92
+ variant={variant}
93
+ showText={showText}
94
+ {...props}
95
+ />
96
+ )
97
+ }
@@ -0,0 +1,116 @@
1
+ import * as React from "react"
2
+ import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
3
+ import { cn } from "../../lib/utils"
4
+ import { ButtonProps, buttonVariants } from "./button"
5
+
6
+ const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
7
+ <nav
8
+ role="navigation"
9
+ aria-label="pagination"
10
+ className={cn("mx-auto flex w-full justify-center", className)}
11
+ {...props}
12
+ />
13
+ )
14
+ Pagination.displayName = "Pagination"
15
+
16
+ const PaginationContent = React.forwardRef<
17
+ HTMLUListElement,
18
+ React.ComponentProps<"ul">
19
+ >(({ className, ...props }, ref) => (
20
+ <ul
21
+ ref={ref}
22
+ className={cn("flex flex-row items-center gap-1", className)}
23
+ {...props}
24
+ />
25
+ ))
26
+ PaginationContent.displayName = "PaginationContent"
27
+
28
+ const PaginationItem = React.forwardRef<
29
+ HTMLLIElement,
30
+ React.ComponentProps<"li">
31
+ >(({ className, ...props }, ref) => (
32
+ <li ref={ref} className={cn("", className)} {...props} />
33
+ ))
34
+ PaginationItem.displayName = "PaginationItem"
35
+
36
+ type PaginationLinkProps = {
37
+ isActive?: boolean
38
+ } & Pick<ButtonProps, "size"> &
39
+ React.ComponentProps<"a">
40
+
41
+ const PaginationLink = ({
42
+ className,
43
+ isActive,
44
+ size = "icon",
45
+ ...props
46
+ }: PaginationLinkProps) => (
47
+ <a
48
+ aria-current={isActive ? "page" : undefined}
49
+ className={cn(
50
+ buttonVariants({
51
+ variant: isActive ? "outline" : "ghost",
52
+ size,
53
+ }),
54
+ className
55
+ )}
56
+ {...props}
57
+ />
58
+ )
59
+ PaginationLink.displayName = "PaginationLink"
60
+
61
+ const PaginationPrevious = ({
62
+ className,
63
+ ...props
64
+ }: React.ComponentProps<typeof PaginationLink>) => (
65
+ <PaginationLink
66
+ aria-label="Go to previous page"
67
+ size="default"
68
+ className={cn("gap-1 pl-2.5", className)}
69
+ {...props}
70
+ >
71
+ <ChevronLeft className="h-4 w-4" />
72
+ <span>Previous</span>
73
+ </PaginationLink>
74
+ )
75
+ PaginationPrevious.displayName = "PaginationPrevious"
76
+
77
+ const PaginationNext = ({
78
+ className,
79
+ ...props
80
+ }: React.ComponentProps<typeof PaginationLink>) => (
81
+ <PaginationLink
82
+ aria-label="Go to next page"
83
+ size="default"
84
+ className={cn("gap-1 pr-2.5", className)}
85
+ {...props}
86
+ >
87
+ <span>Next</span>
88
+ <ChevronRight className="h-4 w-4" />
89
+ </PaginationLink>
90
+ )
91
+ PaginationNext.displayName = "PaginationNext"
92
+
93
+ const PaginationEllipsis = ({
94
+ className,
95
+ ...props
96
+ }: React.ComponentProps<"span">) => (
97
+ <span
98
+ aria-hidden
99
+ className={cn("flex h-9 w-9 items-center justify-center", className)}
100
+ {...props}
101
+ >
102
+ <MoreHorizontal className="h-4 w-4" />
103
+ <span className="sr-only">More pages</span>
104
+ </span>
105
+ )
106
+ PaginationEllipsis.displayName = "PaginationEllipsis"
107
+
108
+ export {
109
+ Pagination,
110
+ PaginationContent,
111
+ PaginationEllipsis,
112
+ PaginationItem,
113
+ PaginationLink,
114
+ PaginationNext,
115
+ PaginationPrevious,
116
+ }
@@ -0,0 +1,183 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+
7
+ import { cn } from "../../lib/utils";
8
+
9
+ /**
10
+ * Popover Bileşeni
11
+ *
12
+ * Tıklanabilir bir öğeden açılan, tema sistemiyle tam entegre bir içerik bileşeni.
13
+ * Filtreler, ayarlar ve diğer içerikler için kullanışlı ve erişilebilir bir arayüz sağlar.
14
+ */
15
+
16
+ const popoverContentVariants = cva(
17
+ "z-50 w-72 rounded-md border border-border bg-background p-4 shadow-md outline-none 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",
18
+ {
19
+ variants: {
20
+ variant: {
21
+ default: "",
22
+ destructive: "border-destructive bg-destructive/5",
23
+ outline: "border-border bg-transparent",
24
+ subtle: "border-transparent bg-muted/50",
25
+ },
26
+ size: {
27
+ sm: "w-48 p-3",
28
+ default: "w-72 p-4",
29
+ lg: "w-96 p-5",
30
+ },
31
+ side: {
32
+ top: "data-[side=top]:slide-in-from-bottom-2",
33
+ right: "data-[side=right]:slide-in-from-left-2",
34
+ bottom: "data-[side=bottom]:slide-in-from-top-2",
35
+ left: "data-[side=left]:slide-in-from-right-2",
36
+ },
37
+ position: {
38
+ pointerEventsNone: "pointer-events-none",
39
+ default: "",
40
+ },
41
+ radius: {
42
+ none: "rounded-none",
43
+ sm: "rounded-sm",
44
+ default: "rounded-md",
45
+ lg: "rounded-lg",
46
+ full: "rounded-full",
47
+ },
48
+ shadow: {
49
+ none: "shadow-none",
50
+ sm: "shadow-sm",
51
+ default: "shadow-md",
52
+ md: "shadow-md",
53
+ lg: "shadow-lg",
54
+ xl: "shadow-xl",
55
+ },
56
+ },
57
+ defaultVariants: {
58
+ variant: "default",
59
+ size: "default",
60
+ radius: "default",
61
+ shadow: "default",
62
+ },
63
+ }
64
+ );
65
+
66
+ const Popover = PopoverPrimitive.Root;
67
+ const PopoverTrigger = PopoverPrimitive.Trigger;
68
+ const PopoverAnchor = PopoverPrimitive.Anchor;
69
+
70
+ export interface PopoverContentProps
71
+ extends Omit<React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>, 'side'>,
72
+ VariantProps<typeof popoverContentVariants> {
73
+ /**
74
+ * Popover'ın arka plan bulanıklığı etkin mi
75
+ */
76
+ backdrop?: boolean;
77
+ /**
78
+ * Popover'a tıklandığında kapanıp kapanmayacağı
79
+ */
80
+ closeOnInteractOutside?: boolean;
81
+ /**
82
+ * Popover açıkken arka planın karartılması
83
+ */
84
+ overlayBackdrop?: boolean;
85
+ }
86
+
87
+ const PopoverContent = React.forwardRef<
88
+ React.ElementRef<typeof PopoverPrimitive.Content>,
89
+ PopoverContentProps
90
+ >(({
91
+ className,
92
+ variant,
93
+ size,
94
+ side,
95
+ position,
96
+ radius,
97
+ shadow,
98
+ backdrop = false,
99
+ closeOnInteractOutside = true,
100
+ overlayBackdrop = false,
101
+ sideOffset = 4,
102
+ ...props
103
+ }, ref) => (
104
+ <>
105
+ {overlayBackdrop && (
106
+ <div className="fixed inset-0 z-40 bg-overlay opacity-30" />
107
+ )}
108
+ <PopoverPrimitive.Content
109
+ ref={ref}
110
+ sideOffset={sideOffset}
111
+ collisionPadding={8}
112
+ onInteractOutside={(e) => {
113
+ if (!closeOnInteractOutside) {
114
+ e.preventDefault();
115
+ }
116
+ }}
117
+ className={cn(
118
+ popoverContentVariants({
119
+ variant,
120
+ size,
121
+ side,
122
+ position,
123
+ radius,
124
+ shadow
125
+ }),
126
+ backdrop && "backdrop-blur-md bg-opacity-80",
127
+ className
128
+ )}
129
+ {...props}
130
+ />
131
+ </>
132
+ ));
133
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
134
+
135
+ /**
136
+ * PopoverClose bileşeni
137
+ */
138
+ const PopoverClose = PopoverPrimitive.Close;
139
+
140
+ /**
141
+ * Popover için bölüm ayırıcı
142
+ */
143
+ const PopoverSeparator = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
144
+ <div
145
+ className={cn("my-2 h-px bg-border", className)}
146
+ {...props}
147
+ />
148
+ );
149
+ PopoverSeparator.displayName = "PopoverSeparator";
150
+
151
+ /**
152
+ * Popover başlık bileşeni
153
+ */
154
+ const PopoverHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
155
+ <div
156
+ className={cn("-mx-4 -mt-4 mb-3 px-4 pt-4 pb-3 border-b border-border", className)}
157
+ {...props}
158
+ />
159
+ );
160
+ PopoverHeader.displayName = "PopoverHeader";
161
+
162
+ /**
163
+ * Popover footer bileşeni
164
+ */
165
+ const PopoverFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
166
+ <div
167
+ className={cn("-mx-4 -mb-4 mt-3 px-4 pt-3 pb-4 border-t border-border", className)}
168
+ {...props}
169
+ />
170
+ );
171
+ PopoverFooter.displayName = "PopoverFooter";
172
+
173
+ export {
174
+ Popover,
175
+ PopoverTrigger,
176
+ PopoverContent,
177
+ PopoverAnchor,
178
+ PopoverClose,
179
+ PopoverSeparator,
180
+ PopoverHeader,
181
+ PopoverFooter,
182
+ popoverContentVariants,
183
+ };