@moontra/moonui 6.11.0 → 6.12.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.
@@ -3,6 +3,7 @@
3
3
  import * as React from "react";
4
4
  import { cva, type VariantProps } from "class-variance-authority";
5
5
  import { motion, type HTMLMotionProps } from "framer-motion";
6
+ import { Slot } from "@radix-ui/react-slot";
6
7
  import { cn } from "../../lib/utils";
7
8
  import { microInteractionVariants, hoverAnimations, tapAnimations } from "@/lib/micro-interactions";
8
9
 
@@ -11,16 +12,14 @@ import { microInteractionVariants, hoverAnimations, tapAnimations } from "@/lib/
11
12
  // hiç uygulanmıyordu; kart kökün `dark:bg-gray-900` değerinde kalıyordu.
12
13
  // Semantik `bg-card` token'ına bağlandı.
13
14
  //
14
- // NOT `size` ve `asChild` (aynı issue'da raporlandı) BİLİNÇLİ olarak
15
- // değiştirilmedi, ayrı gerekçelerle:
16
- // `size`: CVA'da dört değerin dördü de boş string ve `compoundVariants` YOK
17
- // (separator'ın aksine gizli bir çalışma yolu yok). Doğal hedefi de yok —
18
- // padding kökte değil CardHeader/Content/Footer'ın kendi `p-6`'sında. Anlamlı
19
- // kılmak alt-component'lerin padding'ini yeniden tasarlamak demek: görsel
20
- // değişim + API kararı, bu PR'ın kapsamı dışı.
21
- // `asChild`: yalnız tipte var, gövdede hiç okunmuyor. Gerçekten uygulamak
22
- // Radix `Slot` bağımlılığı + child-tek-eleman sözleşmesi demek.
23
- // İkisi de #310'da açık kalıyor; bu PR ölü SINIF kısmını kapatıyor.
15
+ // #310 (ikinci tur): `size` ve `asChild` ARTIK GERÇEK.
16
+ // `size`: CVA'daki dört değer de boş stringdi ve `compoundVariants` yoktu — prop
17
+ // kabul ediliyor, hiçbir görsel fark üretmiyordu. Kökte uygulanacak doğal bir hedefi
18
+ // de yok, çünkü padding `CardHeader/Content/Footer`'ın kendi `p-6`'sında. Bu yüzden
19
+ // kök `size`'ı CONTEXT ile alt bölümlere dağıtıyor (aşağıda).
20
+ // KRİTİK: `md` bugünkü `p-6`' KORUR varsayılan kullanımda görsel değişim YOK.
21
+ // `asChild`: yalnız tipteydi, gövdede hiç okunmuyordu → `...props` ile native div'e
22
+ // sızıyor (`<div aschild="true">`, React uyarısı). Radix `Slot`a bağlandı.
24
23
 
25
24
  const cardVariants = cva(
26
25
  "rounded-lg border bg-card text-card-foreground shadow-sm dark:shadow-gray-900/20 dark:border-gray-800 dark:bg-gray-900 dark:text-gray-100 transition-all duration-200",
@@ -62,6 +61,29 @@ const cardVariants = cva(
62
61
  }
63
62
  );
64
63
 
64
+ /**
65
+ * #310: Kart bölümlerinin padding ölçeği. `md` = bugünkü `p-6` — bu, mevcut tüketicide
66
+ * görsel değişim OLMAMASI için zorunlu (varsayılan `size` zaten `md`).
67
+ */
68
+ type CardSize = "sm" | "md" | "lg" | "xl";
69
+
70
+ const CARD_SECTION_PADDING: Record<CardSize, string> = {
71
+ sm: "p-4",
72
+ md: "p-6",
73
+ lg: "p-8",
74
+ xl: "p-10",
75
+ };
76
+
77
+ /**
78
+ * Kök `Card`ın çözülmüş `size`ını alt bölümlere taşıyan tek kaynak. Alt component'ler
79
+ * `Card` dışında da tek başına kullanılabildiği için context varsayılanı `md`dir.
80
+ */
81
+ const CardSizeContext = React.createContext<CardSize>("md");
82
+
83
+ /** `default` deprecated alias'tır (#319); kanonik `md`ye eşlenir. */
84
+ const resolveCardSize = (size: CardProps["size"]): CardSize =>
85
+ size && size !== "default" ? size : "md";
86
+
65
87
  export interface CardProps
66
88
  extends React.HTMLAttributes<HTMLDivElement>,
67
89
  VariantProps<typeof cardVariants> {
@@ -70,7 +92,25 @@ export interface CardProps
70
92
  }
71
93
 
72
94
  const Card = React.forwardRef<HTMLDivElement, CardProps>(
73
- ({ className, variant, size, radius, interactive, microInteraction = "lift", ...props }, ref) => {
95
+ ({ className, variant, size, radius, interactive, asChild = false, microInteraction = "lift", ...props }, ref) => {
96
+ const resolvedSize = resolveCardSize(size);
97
+ const rootClassName = cn(
98
+ "moonui-theme",
99
+ cardVariants({ variant, size, radius, interactive, className })
100
+ );
101
+
102
+ // #310: `asChild` Radix `Slot`a bağlandı. Slot ile motion sarmalayıcı BİRLİKTE
103
+ // kullanılamaz (Slot tek çocuğa prop birleştirir, motion kendi elemanını ister) —
104
+ // bu yüzden asChild verildiğinde micro-interaction atlanır ve bu davranış
105
+ // belgelenir. Görsel etkileşimi tüketici kendi elemanında kurar.
106
+ if (asChild) {
107
+ return (
108
+ <CardSizeContext.Provider value={resolvedSize}>
109
+ <Slot ref={ref} className={rootClassName} {...props} />
110
+ </CardSizeContext.Provider>
111
+ );
112
+ }
113
+
74
114
  // Interactive özelliği varsa motion.div, yoksa normal div kullan
75
115
  if (interactive && microInteraction !== "none") {
76
116
  const interactionProps = {
@@ -81,22 +121,22 @@ const Card = React.forwardRef<HTMLDivElement, CardProps>(
81
121
  };
82
122
 
83
123
  return (
84
- <motion.div
85
- ref={ref}
86
- className={cn("moonui-theme", cardVariants({ variant, size, radius, interactive, className }))}
87
- {...interactionProps}
88
- {...(props as any)}
89
- />
124
+ <CardSizeContext.Provider value={resolvedSize}>
125
+ <motion.div
126
+ ref={ref}
127
+ className={rootClassName}
128
+ {...interactionProps}
129
+ {...(props as any)}
130
+ />
131
+ </CardSizeContext.Provider>
90
132
  );
91
133
  }
92
-
134
+
93
135
  // Non-interactive version
94
136
  return (
95
- <div
96
- ref={ref}
97
- className={cn("moonui-theme", cardVariants({ variant, size, radius, interactive, className }))}
98
- {...props}
99
- />
137
+ <CardSizeContext.Provider value={resolvedSize}>
138
+ <div ref={ref} className={rootClassName} {...props} />
139
+ </CardSizeContext.Provider>
100
140
  );
101
141
  }
102
142
  );
@@ -105,13 +145,17 @@ Card.displayName = "Card";
105
145
  const CardHeader = React.forwardRef<
106
146
  HTMLDivElement,
107
147
  React.HTMLAttributes<HTMLDivElement>
108
- >(({ className, ...props }, ref) => (
109
- <div
110
- ref={ref}
111
- className={cn("moonui-theme", "flex flex-col space-y-1.5 p-6", className)}
112
- {...props}
113
- />
114
- ));
148
+ >(({ className, ...props }, ref) => {
149
+ // #310: padding artık kök `Card`ın `size`ından geliyor (eskiden sabit `p-6`).
150
+ const padding = CARD_SECTION_PADDING[React.useContext(CardSizeContext)];
151
+ return (
152
+ <div
153
+ ref={ref}
154
+ className={cn("moonui-theme", "flex flex-col space-y-1.5", padding, className)}
155
+ {...props}
156
+ />
157
+ );
158
+ });
115
159
  CardHeader.displayName = "CardHeader";
116
160
 
117
161
  const CardTitle = React.forwardRef<
@@ -141,21 +185,32 @@ CardDescription.displayName = "CardDescription";
141
185
  const CardContent = React.forwardRef<
142
186
  HTMLDivElement,
143
187
  React.HTMLAttributes<HTMLDivElement>
144
- >(({ className, ...props }, ref) => (
145
- <div ref={ref} className={cn("moonui-theme", "p-6 pt-0", className)} {...props} />
146
- ));
188
+ >(({ className, ...props }, ref) => {
189
+ const padding = CARD_SECTION_PADDING[React.useContext(CardSizeContext)];
190
+ return (
191
+ <div
192
+ ref={ref}
193
+ className={cn("moonui-theme", padding, "pt-0", className)}
194
+ {...props}
195
+ />
196
+ );
197
+ });
147
198
  CardContent.displayName = "CardContent";
148
199
 
149
200
  const CardFooter = React.forwardRef<
150
201
  HTMLDivElement,
151
202
  React.HTMLAttributes<HTMLDivElement>
152
- >(({ className, ...props }, ref) => (
153
- <div
154
- ref={ref}
155
- className={cn("moonui-theme", "flex items-center p-6 pt-0", className)}
156
- {...props}
157
- />
158
- ));
203
+ >(({ className, ...props }, ref) => {
204
+ const padding = CARD_SECTION_PADDING[React.useContext(CardSizeContext)];
205
+ return (
206
+ <div
207
+ ref={ref}
208
+ className={cn("moonui-theme", "flex items-center", padding, "pt-0", className)}
209
+ {...props}
210
+ />
211
+ );
212
+ });
159
213
  CardFooter.displayName = "CardFooter";
160
214
 
161
- export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
215
+ export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent, cardVariants };
216
+ export type { CardSize };