@moontra/moonui 6.7.0 → 6.8.0

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.
@@ -5,13 +5,16 @@ import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
5
5
  import { cn } from "../../lib/utils"
6
6
  import { ButtonProps, buttonVariants } from "./button"
7
7
 
8
- const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
9
- <nav
10
- role="navigation"
11
- aria-label="pagination"
12
- className={cn("moonui-theme", "mx-auto flex w-full justify-center", className)}
13
- {...props}
14
- />
8
+ const Pagination = React.forwardRef<HTMLElement, React.ComponentProps<"nav">>(
9
+ ({ className, ...props }, ref) => (
10
+ <nav
11
+ ref={ref}
12
+ role="navigation"
13
+ aria-label="pagination"
14
+ className={cn("moonui-theme", "mx-auto flex w-full justify-center", className)}
15
+ {...props}
16
+ />
17
+ )
15
18
  )
16
19
  Pagination.displayName = "Pagination"
17
20
 
@@ -40,71 +43,85 @@ type PaginationLinkProps = {
40
43
  } & Partial<Pick<ButtonProps, "size">> &
41
44
  React.ComponentProps<"a">
42
45
 
43
- const PaginationLink = ({
44
- className,
45
- isActive,
46
- size = "icon",
47
- ...props
48
- }: PaginationLinkProps) => (
49
- <a
50
- aria-current={isActive ? "page" : undefined}
51
- className={cn(
52
- buttonVariants({
53
- variant: isActive ? "outline" : "ghost",
54
- size,
55
- }),
56
- className
57
- )}
58
- {...props}
59
- />
46
+ const PaginationLink = React.forwardRef<HTMLAnchorElement, PaginationLinkProps>(
47
+ ({ className, isActive, size = "icon", ...props }, ref) => (
48
+ <a
49
+ ref={ref}
50
+ aria-current={isActive ? "page" : undefined}
51
+ className={cn(
52
+ buttonVariants({
53
+ variant: isActive ? "outline" : "ghost",
54
+ size,
55
+ }),
56
+ className
57
+ )}
58
+ {...props}
59
+ />
60
+ )
60
61
  )
61
62
  PaginationLink.displayName = "PaginationLink"
62
63
 
63
- const PaginationPrevious = ({
64
- className,
65
- ...props
66
- }: React.ComponentProps<typeof PaginationLink>) => (
64
+ /**
65
+ * #315: "Previous"/"Next" etiketleri KOŞULSUZ render ediliyordu ve component'te hiçbir
66
+ * responsive affordance yoktu. 375px'te ölçüm: nav clientWidth=229 / scrollWidth=317
67
+ * (88px iç taşma) ata zincirindeki `overflow-hidden` etiketi kırpıyor, kullanıcı
68
+ * "Previous" yerine "vious" görüyordu. Etiket artık `sm` altında gizleniyor; erişilebilir
69
+ * ad `aria-label` ile korunduğu için ekran-okuyucu deneyimi DEĞİŞMİYOR.
70
+ */
71
+ const paginationLabelClass = "hidden sm:inline"
72
+
73
+ const PaginationPrevious = React.forwardRef<
74
+ HTMLAnchorElement,
75
+ React.ComponentProps<typeof PaginationLink>
76
+ >(({ className, ...props }, ref) => (
67
77
  <PaginationLink
78
+ ref={ref}
68
79
  aria-label="Go to previous page"
69
80
  size="md"
70
81
  className={cn("moonui-theme", "gap-1 pl-2.5", className)}
71
82
  {...props}
72
83
  >
73
84
  <ChevronLeft className="h-4 w-4" />
74
- <span>Previous</span>
85
+ <span className={paginationLabelClass}>Previous</span>
75
86
  </PaginationLink>
76
- )
87
+ ))
77
88
  PaginationPrevious.displayName = "PaginationPrevious"
78
89
 
79
- const PaginationNext = ({
80
- className,
81
- ...props
82
- }: React.ComponentProps<typeof PaginationLink>) => (
90
+ const PaginationNext = React.forwardRef<
91
+ HTMLAnchorElement,
92
+ React.ComponentProps<typeof PaginationLink>
93
+ >(({ className, ...props }, ref) => (
83
94
  <PaginationLink
95
+ ref={ref}
84
96
  aria-label="Go to next page"
85
97
  size="md"
86
98
  className={cn("moonui-theme", "gap-1 pr-2.5", className)}
87
99
  {...props}
88
100
  >
89
- <span>Next</span>
101
+ <span className={paginationLabelClass}>Next</span>
90
102
  <ChevronRight className="h-4 w-4" />
91
103
  </PaginationLink>
92
- )
104
+ ))
93
105
  PaginationNext.displayName = "PaginationNext"
94
106
 
95
- const PaginationEllipsis = ({
96
- className,
97
- ...props
98
- }: React.ComponentProps<"span">) => (
107
+ const PaginationEllipsis = React.forwardRef<
108
+ HTMLSpanElement,
109
+ React.ComponentProps<"span">
110
+ >(({ className, ...props }, ref) => (
111
+ // #315: `aria-hidden` ESKİDEN BU ELEMANDAYDI → içindeki `sr-only` "More pages" metni
112
+ // erişilebilirlik ağacından düşüyor, hiç duyurulmuyordu. Gizleme artık yalnız dekoratif
113
+ // ikonda. (breadcrumb.tsx'te birebir aynı çakışma vardı — aynı PR'da düzeltildi.)
99
114
  <span
100
- aria-hidden
115
+ ref={ref}
101
116
  className={cn("moonui-theme", "flex h-9 w-9 items-center justify-center", className)}
102
117
  {...props}
103
118
  >
104
- <MoreHorizontal className="h-4 w-4" />
119
+ <span aria-hidden="true" className="flex items-center">
120
+ <MoreHorizontal className="h-4 w-4" />
121
+ </span>
105
122
  <span className="sr-only">More pages</span>
106
123
  </span>
107
- )
124
+ ))
108
125
  PaginationEllipsis.displayName = "PaginationEllipsis"
109
126
 
110
127
  export {
@@ -115,4 +132,7 @@ export {
115
132
  PaginationLink,
116
133
  PaginationNext,
117
134
  PaginationPrevious,
118
- }
135
+ }
136
+
137
+ // #315: Props tiplerinin hiçbiri export edilmiyordu.
138
+ export type { PaginationLinkProps }
@@ -9,22 +9,52 @@ import { cn } from "../../lib/utils";
9
9
  /* -------------------------------------------------------------------------------------------------
10
10
  * Tabs Root
11
11
  * -----------------------------------------------------------------------------------------------*/
12
+ type TabsOrientation = "horizontal" | "vertical";
13
+
14
+ /**
15
+ * #322: Yönelim için TEK KAYNAK.
16
+ *
17
+ * Eskiden üç ayrı yol vardı ve birbirini eziyordu:
18
+ * 1. Root `vertical` prop'undan `orientation` hesaplıyor, ARDINDAN `{...props}` yayıyordu
19
+ * → tüketicinin (ya da Radix'in kalıtsal) `orientation` prop'u `vertical`'ı SESSİZCE
20
+ * eziyordu.
21
+ * 2. `TabsList`/`TabsTrigger` kendi `orientation` prop'unu yalnız CVA sınıfına veriyor,
22
+ * Root'tan hiç beslenmiyordu → klavye yönü dikey, görünüm yatay kalabiliyordu.
23
+ *
24
+ * Artık Root çözülmüş yönelimi context ile dağıtıyor; alt component'ler kendi prop'unu
25
+ * verirse o kazanır (yerel ezme kasıtlı olarak korundu).
26
+ */
27
+ const TabsOrientationContext = React.createContext<TabsOrientation>("horizontal");
28
+
12
29
  interface TabsProps extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root> {
13
- /** Mobil görünümde dikey düzen için */
30
+ /**
31
+ * @deprecated `orientation="vertical"` kullanın — pro `MoonUITabsPro` ile aynı ad ve
32
+ * tip. `vertical` yalnız `orientation` verilmediğinde dikkate alınır.
33
+ */
14
34
  vertical?: boolean;
15
35
  }
16
36
 
17
37
  const Tabs = React.forwardRef<
18
38
  React.ElementRef<typeof TabsPrimitive.Root>,
19
39
  TabsProps
20
- >(({ vertical = false, ...props }, ref) => (
21
- <TabsPrimitive.Root
22
- ref={ref}
23
- className={cn("moonui-theme", props.className)}
24
- orientation={vertical ? "vertical" : "horizontal"}
25
- {...props}
26
- />
27
- ));
40
+ >(({ vertical = false, orientation, className, ...props }, ref) => {
41
+ const resolvedOrientation: TabsOrientation =
42
+ orientation ?? (vertical ? "vertical" : "horizontal");
43
+
44
+ return (
45
+ <TabsOrientationContext.Provider value={resolvedOrientation}>
46
+ <TabsPrimitive.Root
47
+ ref={ref}
48
+ // #322: `className` eskiden destructure EDİLMİYORDU; `cn("moonui-theme", …)`
49
+ // hesaplanıp ardından `{...props}` yayıldığı için tüketici `className` verdiğinde
50
+ // hesaplanan değer tümüyle eziliyor ve `moonui-theme` tema kapsamı düşüyordu.
51
+ className={cn("moonui-theme", className)}
52
+ orientation={resolvedOrientation}
53
+ {...props}
54
+ />
55
+ </TabsOrientationContext.Provider>
56
+ );
57
+ });
28
58
 
29
59
  Tabs.displayName = TabsPrimitive.Root.displayName;
30
60
 
@@ -77,10 +107,14 @@ const TabsList = React.forwardRef<
77
107
  TabsListProps
78
108
  >(({ className, variant, orientation, fullWidth, scrollable, ...props }, ref) => {
79
109
  // scrollable prop'unu DOM'a geçirmemek için destructure ediyoruz
110
+ // #322: yönelim Root'tan context ile geliyor; yerel prop verilirse o kazanır.
111
+ const contextOrientation = React.useContext(TabsOrientationContext);
112
+ const resolvedOrientation = orientation ?? contextOrientation;
113
+
80
114
  return (
81
115
  <TabsPrimitive.List
82
116
  ref={ref}
83
- className={cn("moonui-theme", tabsListVariants({ variant, orientation, fullWidth, scrollable, className }))}
117
+ className={cn("moonui-theme", tabsListVariants({ variant, orientation: resolvedOrientation, fullWidth, scrollable, className }))}
84
118
  {...props}
85
119
  />
86
120
  );
@@ -152,14 +186,19 @@ const TabsTrigger = React.forwardRef<
152
186
  fadeTabs = false,
153
187
  orientation,
154
188
  fullWidth,
155
- children,
156
- ...props
157
- }, ref) => (
189
+ children,
190
+ ...props
191
+ }, ref) => {
192
+ // #322: yönelim Root'tan context ile geliyor; yerel prop verilirse o kazanır.
193
+ const contextOrientation = React.useContext(TabsOrientationContext);
194
+ const resolvedOrientation = orientation ?? contextOrientation;
195
+
196
+ return (
158
197
  <TabsPrimitive.Trigger
159
198
  ref={ref}
160
199
  className={cn(
161
200
  "moonui-theme",
162
- tabsTriggerVariants({ variant, size, orientation, fullWidth }),
201
+ tabsTriggerVariants({ variant, size, orientation: resolvedOrientation, fullWidth }),
163
202
  fadeTabs && "data-[state=inactive]:opacity-60",
164
203
  className
165
204
  )}
@@ -176,7 +215,8 @@ const TabsTrigger = React.forwardRef<
176
215
  <span className="ml-2">{badge}</span>
177
216
  )}
178
217
  </TabsPrimitive.Trigger>
179
- ));
218
+ );
219
+ });
180
220
 
181
221
  TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
182
222
 
@@ -207,4 +247,14 @@ const TabsContent = React.forwardRef<
207
247
 
208
248
  TabsContent.displayName = TabsPrimitive.Content.displayName;
209
249
 
210
- export { Tabs, TabsList, TabsTrigger, TabsContent };
250
+ export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants, tabsTriggerVariants };
251
+
252
+ // #322: Props interface'lerinin hiçbiri export edilmiyordu (pro tarafı `MoonUITabsProProps`
253
+ // ve `TabItem`'ı export ediyor — asimetriydi).
254
+ export type {
255
+ TabsProps,
256
+ TabsListProps,
257
+ TabsTriggerProps,
258
+ TabsContentProps,
259
+ TabsOrientation,
260
+ };