@umituz/react-native-design-system 2.6.94 → 2.6.96
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.
- package/package.json +1 -1
- package/src/atoms/AtomicAvatar.README.md +284 -397
- package/src/atoms/AtomicBadge.README.md +123 -358
- package/src/atoms/AtomicCard.README.md +358 -247
- package/src/atoms/AtomicDatePicker.README.md +127 -332
- package/src/atoms/AtomicFab.README.md +194 -352
- package/src/atoms/AtomicIcon.README.md +241 -274
- package/src/atoms/AtomicProgress.README.md +100 -338
- package/src/atoms/AtomicSpinner.README.md +304 -337
- package/src/atoms/AtomicText.README.md +153 -389
- package/src/atoms/AtomicTextArea.README.md +267 -268
- package/src/atoms/EmptyState.README.md +247 -292
- package/src/atoms/GlassView/README.md +313 -444
- package/src/atoms/button/README.md +186 -297
- package/src/atoms/button/STRATEGY.md +252 -0
- package/src/atoms/chip/README.md +242 -290
- package/src/atoms/input/README.md +296 -290
- package/src/atoms/picker/README.md +278 -309
- package/src/atoms/skeleton/AtomicSkeleton.README.md +394 -252
- package/src/molecules/BaseModal/README.md +356 -0
- package/src/molecules/BaseModal.README.md +324 -200
- package/src/molecules/ConfirmationModal.README.md +349 -302
- package/src/molecules/Divider/README.md +293 -376
- package/src/molecules/FormField.README.md +321 -534
- package/src/molecules/GlowingCard/GlowingCard.tsx +1 -1
- package/src/molecules/GlowingCard/README.md +230 -372
- package/src/molecules/List/README.md +281 -488
- package/src/molecules/ListItem.README.md +320 -315
- package/src/molecules/SearchBar/README.md +332 -430
- package/src/molecules/StepHeader/README.md +311 -411
- package/src/molecules/StepProgress/README.md +281 -448
- package/src/molecules/alerts/README.md +272 -355
- package/src/molecules/avatar/README.md +295 -356
- package/src/molecules/bottom-sheet/README.md +303 -340
- package/src/molecules/calendar/README.md +301 -265
- package/src/molecules/countdown/README.md +347 -456
- package/src/molecules/emoji/README.md +281 -514
- package/src/molecules/listitem/README.md +307 -399
- package/src/molecules/media-card/MediaCard.tsx +31 -34
- package/src/molecules/media-card/README.md +217 -319
- package/src/molecules/navigation/README.md +263 -284
- package/src/molecules/navigation/components/NavigationHeader.tsx +77 -0
- package/src/molecules/navigation/index.ts +1 -0
- package/src/molecules/splash/README.md +76 -80
- package/src/molecules/swipe-actions/README.md +376 -588
|
@@ -1,384 +1,282 @@
|
|
|
1
1
|
# MediaCard
|
|
2
2
|
|
|
3
|
-
MediaCard
|
|
3
|
+
MediaCard is an optimized card component for displaying images, videos, and media content with overlay text, badges, and selection state support.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Import & Usage
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- 🏷️ **Badge**: Rozet/badge desteği
|
|
10
|
-
- ✅ **Selected State**: Seçim durumu
|
|
11
|
-
- 📏 **3 Size**: Small, Medium, Large
|
|
12
|
-
- 👆 **Pressable**: Tıklanabilir kart
|
|
13
|
-
- ♿ **Erişilebilir**: Tam erişilebilirlik desteği
|
|
14
|
-
|
|
15
|
-
## Kurulum
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
import { MediaCard } from 'react-native-design-system';
|
|
7
|
+
```typescript
|
|
8
|
+
import { MediaCard } from 'react-native-design-system/src/molecules/media-card';
|
|
19
9
|
```
|
|
20
10
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```tsx
|
|
24
|
-
import React from 'react';
|
|
25
|
-
import { View } from 'react-native';
|
|
26
|
-
import { MediaCard } from 'react-native-design-system';
|
|
27
|
-
|
|
28
|
-
export const BasicExample = () => {
|
|
29
|
-
return (
|
|
30
|
-
<View style={{ padding: 16 }}>
|
|
31
|
-
<MediaCard
|
|
32
|
-
uri="https://example.com/image.jpg"
|
|
33
|
-
title="Görsel Başlığı"
|
|
34
|
-
subtitle="Alt başlık"
|
|
35
|
-
/>
|
|
36
|
-
</View>
|
|
37
|
-
);
|
|
38
|
-
};
|
|
39
|
-
```
|
|
11
|
+
**Location:** `src/molecules/media-card/MediaCard.tsx`
|
|
40
12
|
|
|
41
|
-
## Basic
|
|
13
|
+
## Basic Usage
|
|
42
14
|
|
|
43
15
|
```tsx
|
|
44
16
|
<MediaCard
|
|
45
17
|
uri="https://example.com/image.jpg"
|
|
18
|
+
title="Media Title"
|
|
19
|
+
subtitle="Description"
|
|
46
20
|
/>
|
|
47
21
|
```
|
|
48
22
|
|
|
49
|
-
##
|
|
23
|
+
## Strategy
|
|
50
24
|
|
|
51
|
-
|
|
52
|
-
<MediaCard
|
|
53
|
-
uri="https://example.com/image.jpg"
|
|
54
|
-
title="Manzara"
|
|
55
|
-
subtitle="Doğa harikası"
|
|
56
|
-
/>
|
|
57
|
-
```
|
|
25
|
+
**Purpose**: Provide a visually appealing and interactive card component optimized for media content display.
|
|
58
26
|
|
|
59
|
-
|
|
27
|
+
**When to Use**:
|
|
28
|
+
- Photo galleries and image grids
|
|
29
|
+
- Template/media selection interfaces
|
|
30
|
+
- Product cards with images
|
|
31
|
+
- Avatar/story selectors
|
|
32
|
+
- Background pickers
|
|
33
|
+
- Meme collections
|
|
60
34
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
badge="YENİ"
|
|
66
|
-
/>
|
|
67
|
-
```
|
|
35
|
+
**When NOT to Use**:
|
|
36
|
+
- For text-only content - use AtomicCard instead
|
|
37
|
+
- For complex layouts - use custom components
|
|
38
|
+
- For non-interactive displays - use Image component
|
|
68
39
|
|
|
69
|
-
##
|
|
40
|
+
## Rules
|
|
70
41
|
|
|
71
|
-
|
|
72
|
-
<MediaCard
|
|
73
|
-
uri="https://example.com/image.jpg"
|
|
74
|
-
title="Seçili"
|
|
75
|
-
selected
|
|
76
|
-
/>
|
|
77
|
-
```
|
|
42
|
+
### Required
|
|
78
43
|
|
|
79
|
-
|
|
44
|
+
1. **ALWAYS** provide a `uri` prop with valid image URL
|
|
45
|
+
2. **MUST** have unique keys when rendering in lists
|
|
46
|
+
3. **NEVER** use invalid or broken image URLs
|
|
47
|
+
4. **ALWAYS** provide accessibility labels for screen readers
|
|
48
|
+
5. **MUST** handle loading and error states appropriately
|
|
80
49
|
|
|
81
|
-
|
|
82
|
-
<View style={{ flexDirection: 'row', gap: 8 }}>
|
|
83
|
-
{/* Small */}
|
|
84
|
-
<MediaCard
|
|
85
|
-
uri="https://example.com/image.jpg"
|
|
86
|
-
size="sm"
|
|
87
|
-
/>
|
|
88
|
-
|
|
89
|
-
{/* Medium */}
|
|
90
|
-
<MediaCard
|
|
91
|
-
uri="https://example.com/image.jpg"
|
|
92
|
-
size="md"
|
|
93
|
-
/>
|
|
94
|
-
|
|
95
|
-
{/* Large */}
|
|
96
|
-
<MediaCard
|
|
97
|
-
uri="https://example.com/image.jpg"
|
|
98
|
-
size="lg"
|
|
99
|
-
/>
|
|
100
|
-
</View>
|
|
101
|
-
```
|
|
50
|
+
### Content Guidelines
|
|
102
51
|
|
|
103
|
-
|
|
52
|
+
1. **ALWAYS** use appropriate size for context (sm/md/lg)
|
|
53
|
+
2. **MUST** maintain aspect ratio for images
|
|
54
|
+
3. **SHOULD** provide meaningful titles and subtitles
|
|
55
|
+
4. **NEVER** use text that overflows the card
|
|
104
56
|
|
|
105
|
-
|
|
106
|
-
<MediaCard
|
|
107
|
-
uri="https://example.com/image.jpg"
|
|
108
|
-
title="Tıkla"
|
|
109
|
-
onPress={() => console.log('Tıklandı')}
|
|
110
|
-
/>
|
|
111
|
-
```
|
|
57
|
+
### Selection State
|
|
112
58
|
|
|
113
|
-
|
|
59
|
+
1. **MUST** clearly indicate selected state
|
|
60
|
+
2. **ALWAYS** provide visual feedback for selection
|
|
61
|
+
3. **SHOULD** allow toggle behavior (select/deselect)
|
|
114
62
|
|
|
115
|
-
|
|
116
|
-
<MediaCard
|
|
117
|
-
uri="https://example.com/image.jpg"
|
|
118
|
-
width={200}
|
|
119
|
-
size="lg"
|
|
120
|
-
/>
|
|
121
|
-
```
|
|
63
|
+
## Forbidden
|
|
122
64
|
|
|
123
|
-
|
|
65
|
+
❌ **NEVER** do these:
|
|
124
66
|
|
|
125
67
|
```tsx
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<MediaCard
|
|
129
|
-
uri="https://example.com/image.jpg"
|
|
130
|
-
overlayPosition="bottom"
|
|
131
|
-
title="Altta"
|
|
132
|
-
/>
|
|
133
|
-
|
|
134
|
-
{/* Ortada */}
|
|
135
|
-
<MediaCard
|
|
136
|
-
uri="https://example.com/image.jpg"
|
|
137
|
-
overlayPosition="center"
|
|
138
|
-
title="Ortada"
|
|
139
|
-
/>
|
|
140
|
-
</View>
|
|
141
|
-
```
|
|
68
|
+
// ❌ Missing URI
|
|
69
|
+
<MediaCard />
|
|
142
70
|
|
|
143
|
-
|
|
71
|
+
// ❌ Invalid URI
|
|
72
|
+
<MediaCard uri="not-a-url" />
|
|
144
73
|
|
|
145
|
-
|
|
74
|
+
// ❌ Text overflow
|
|
146
75
|
<MediaCard
|
|
147
|
-
uri="
|
|
148
|
-
|
|
76
|
+
uri="image.jpg"
|
|
77
|
+
title="This is an extremely long title that will overflow"
|
|
149
78
|
/>
|
|
150
|
-
```
|
|
151
79
|
|
|
152
|
-
|
|
80
|
+
// ❌ Wrong aspect ratio
|
|
81
|
+
<MediaCard
|
|
82
|
+
uri="portrait.jpg"
|
|
83
|
+
aspectRatio={2} // Too wide for portrait image
|
|
84
|
+
/>
|
|
153
85
|
|
|
154
|
-
|
|
86
|
+
// ❌ Inconsistent sizes in grid
|
|
87
|
+
<View>
|
|
88
|
+
<MediaCard size="sm" />
|
|
89
|
+
<MediaCard size="lg" /> {/* ❌ Inconsistent */}
|
|
90
|
+
</View>
|
|
155
91
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return (
|
|
159
|
-
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 8, padding: 16 }}>
|
|
160
|
-
{photos.map((photo) => (
|
|
161
|
-
<MediaCard
|
|
162
|
-
key={photo.id}
|
|
163
|
-
uri={photo.uri}
|
|
164
|
-
size="sm"
|
|
165
|
-
onPress={() => navigation.navigate('PhotoDetail', { photoId: photo.id })}
|
|
166
|
-
/>
|
|
167
|
-
))}
|
|
168
|
-
</View>
|
|
169
|
-
);
|
|
170
|
-
};
|
|
92
|
+
// ❌ No accessibility
|
|
93
|
+
<MediaCard uri="image.jpg" /> {/* Missing accessibilityLabel */}
|
|
171
94
|
```
|
|
172
95
|
|
|
173
|
-
|
|
96
|
+
## Best Practices
|
|
174
97
|
|
|
175
|
-
|
|
176
|
-
export const TemplateGallery = ({ templates }) => {
|
|
177
|
-
const [selectedTemplate, setSelectedTemplate] = useState(null);
|
|
178
|
-
|
|
179
|
-
return (
|
|
180
|
-
<View style={{ padding: 16 }}>
|
|
181
|
-
<FlatList
|
|
182
|
-
data={templates}
|
|
183
|
-
numColumns={2}
|
|
184
|
-
keyExtractor={(item) => item.id}
|
|
185
|
-
renderItem={({ item }) => (
|
|
186
|
-
<MediaCard
|
|
187
|
-
uri={item.thumbnail}
|
|
188
|
-
title={item.name}
|
|
189
|
-
selected={selectedTemplate?.id === item.id}
|
|
190
|
-
onPress={() => setSelectedTemplate(item)}
|
|
191
|
-
style={{ margin: 8 }}
|
|
192
|
-
/>
|
|
193
|
-
)}
|
|
194
|
-
/>
|
|
195
|
-
|
|
196
|
-
<Button
|
|
197
|
-
title="Şablonu Kullan"
|
|
198
|
-
onPress={() => applyTemplate(selectedTemplate)}
|
|
199
|
-
/>
|
|
200
|
-
</View>
|
|
201
|
-
);
|
|
202
|
-
};
|
|
203
|
-
```
|
|
98
|
+
### Size Selection
|
|
204
99
|
|
|
205
|
-
|
|
100
|
+
✅ **DO**:
|
|
101
|
+
- Use `sm` for dense grids and galleries
|
|
102
|
+
- Use `md` for standard product cards
|
|
103
|
+
- Use `lg` for featured/hero items
|
|
104
|
+
- Keep sizes consistent within grids
|
|
206
105
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
{products.map((product) => (
|
|
212
|
-
<MediaCard
|
|
213
|
-
key={product.id}
|
|
214
|
-
uri={product.image}
|
|
215
|
-
title={product.name}
|
|
216
|
-
subtitle={`${product.price} TL`}
|
|
217
|
-
badge={product.isNew ? 'YENİ' : ''}
|
|
218
|
-
onPress={() => navigation.navigate('ProductDetail', { productId: product.id })}
|
|
219
|
-
/>
|
|
220
|
-
))}
|
|
221
|
-
</View>
|
|
222
|
-
);
|
|
223
|
-
};
|
|
224
|
-
```
|
|
106
|
+
❌ **DON'T**:
|
|
107
|
+
- Mix sizes arbitrarily in the same grid
|
|
108
|
+
- Use `lg` for small thumbnails
|
|
109
|
+
- Use `sm` for hero/featured content
|
|
225
110
|
|
|
226
|
-
###
|
|
111
|
+
### Aspect Ratio
|
|
227
112
|
|
|
113
|
+
✅ **DO**:
|
|
228
114
|
```tsx
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
<ScrollView horizontal style={{ padding: 16 }}>
|
|
232
|
-
{stories.map((story) => (
|
|
233
|
-
<MediaCard
|
|
234
|
-
key={story.id}
|
|
235
|
-
uri={story.avatar}
|
|
236
|
-
size="sm"
|
|
237
|
-
aspectRatio={1}
|
|
238
|
-
onPress={() => openStory(story)}
|
|
239
|
-
style={{ marginRight: 8 }}
|
|
240
|
-
/>
|
|
241
|
-
))}
|
|
242
|
-
</ScrollView>
|
|
243
|
-
);
|
|
244
|
-
};
|
|
245
|
-
```
|
|
115
|
+
// Square images
|
|
116
|
+
<MediaCard aspectRatio={1} />
|
|
246
117
|
|
|
247
|
-
|
|
118
|
+
// Portrait images
|
|
119
|
+
<MediaCard aspectRatio={0.8} />
|
|
248
120
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const [selectedMemes, setSelectedMemes] = useState(new Set());
|
|
252
|
-
|
|
253
|
-
const toggleSelection = (id) => {
|
|
254
|
-
const newSet = new Set(selectedMemes);
|
|
255
|
-
if (newSet.has(id)) {
|
|
256
|
-
newSet.delete(id);
|
|
257
|
-
} else {
|
|
258
|
-
newSet.add(id);
|
|
259
|
-
}
|
|
260
|
-
setSelectedMemes(newSet);
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
return (
|
|
264
|
-
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 8 }}>
|
|
265
|
-
{memes.map((meme) => (
|
|
266
|
-
<MediaCard
|
|
267
|
-
key={meme.id}
|
|
268
|
-
uri={meme.image}
|
|
269
|
-
selected={selectedMemes.has(meme.id)}
|
|
270
|
-
onPress={() => toggleSelection(meme.id)}
|
|
271
|
-
/>
|
|
272
|
-
))}
|
|
273
|
-
</View>
|
|
274
|
-
);
|
|
275
|
-
};
|
|
121
|
+
// Landscape images
|
|
122
|
+
<MediaCard aspectRatio={1.2} />
|
|
276
123
|
```
|
|
277
124
|
|
|
278
|
-
|
|
279
|
-
|
|
125
|
+
❌ **DON'T**:
|
|
280
126
|
```tsx
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return (
|
|
285
|
-
<View style={{ padding: 16 }}>
|
|
286
|
-
<FlatList
|
|
287
|
-
data={backgrounds}
|
|
288
|
-
numColumns={3}
|
|
289
|
-
keyExtractor={(item) => item.id}
|
|
290
|
-
renderItem={({ item }) => (
|
|
291
|
-
<MediaCard
|
|
292
|
-
uri={item.thumbnail}
|
|
293
|
-
selected={selectedBg?.id === item.id}
|
|
294
|
-
onPress={() => setSelectedBg(item)}
|
|
295
|
-
style={{ margin: 4 }}
|
|
296
|
-
/>
|
|
297
|
-
)}
|
|
298
|
-
/>
|
|
299
|
-
</View>
|
|
300
|
-
);
|
|
301
|
-
};
|
|
127
|
+
// Don't distort images
|
|
128
|
+
<MediaCard aspectRatio={2} /> // For portrait image
|
|
302
129
|
```
|
|
303
130
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
### MediaCardProps
|
|
307
|
-
|
|
308
|
-
| Prop | Tip | Varsayılan | Açıklama |
|
|
309
|
-
|------|-----|------------|----------|
|
|
310
|
-
| `uri` | `string` | - **(Zorunlu)** | Resim URI'si |
|
|
311
|
-
| `title` | `string` | - | Başlık metni |
|
|
312
|
-
| `subtitle` | `string` | - | Alt başlık |
|
|
313
|
-
| `badge` | `string \| number` | - | Badge içeriği |
|
|
314
|
-
| `selected` | `boolean` | `false` | Seçili durumu |
|
|
315
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Kart boyutu |
|
|
316
|
-
| `aspectRatio` | `number` | `0.8` | En-boy oranı |
|
|
317
|
-
| `overlayPosition` | `'top' \| 'bottom' \| 'center'` | `'bottom'` | Overlay pozisyonu |
|
|
318
|
-
| `showOverlay` | `boolean` | `true` | Overlay göster |
|
|
319
|
-
| `width` | `number` | - | Custom genişlik |
|
|
320
|
-
| `onPress` | `() => void` | - | Tıklama olayı |
|
|
321
|
-
| `testID` | `string` | - | Test ID'si |
|
|
322
|
-
|
|
323
|
-
## Best Practices
|
|
324
|
-
|
|
325
|
-
### 1. Boyut Seçimi
|
|
131
|
+
### Overlay Usage
|
|
326
132
|
|
|
133
|
+
✅ **DO**:
|
|
327
134
|
```tsx
|
|
328
|
-
//
|
|
329
|
-
<MediaCard
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
135
|
+
// Provide context
|
|
136
|
+
<MediaCard
|
|
137
|
+
title="Product Name"
|
|
138
|
+
subtitle="$29.99"
|
|
139
|
+
/>
|
|
333
140
|
|
|
334
|
-
//
|
|
335
|
-
<MediaCard
|
|
141
|
+
// Clean display
|
|
142
|
+
<MediaCard showOverlay={false} />
|
|
336
143
|
```
|
|
337
144
|
|
|
338
|
-
|
|
339
|
-
|
|
145
|
+
❌ **DON'T**:
|
|
340
146
|
```tsx
|
|
341
|
-
//
|
|
342
|
-
<MediaCard
|
|
343
|
-
|
|
344
|
-
// Dikdörtgen
|
|
345
|
-
<MediaCard aspectRatio={0.8} />
|
|
346
|
-
|
|
347
|
-
// Yatay
|
|
348
|
-
<MediaCard aspectRatio={1.2} />
|
|
147
|
+
// Don't show overlay for no reason
|
|
148
|
+
<MediaCard title="" subtitle="" />
|
|
349
149
|
```
|
|
350
150
|
|
|
351
|
-
|
|
352
|
-
|
|
151
|
+
## AI Coding Guidelines
|
|
152
|
+
|
|
153
|
+
### For AI Agents
|
|
154
|
+
|
|
155
|
+
When generating MediaCard components, follow these rules:
|
|
156
|
+
|
|
157
|
+
1. **Always import from correct path**:
|
|
158
|
+
```typescript
|
|
159
|
+
import { MediaCard } from 'react-native-design-system/src/molecules/media-card';
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
2. **Always provide required props**:
|
|
163
|
+
```tsx
|
|
164
|
+
<MediaCard
|
|
165
|
+
uri="有效的图片URL"
|
|
166
|
+
title="简洁的标题"
|
|
167
|
+
size="根据上下文选择合适尺寸"
|
|
168
|
+
/>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
3. **Always handle press events**:
|
|
172
|
+
```tsx
|
|
173
|
+
<MediaCard
|
|
174
|
+
uri="image.jpg"
|
|
175
|
+
onPress={() => navigation.navigate('Detail', { id })}
|
|
176
|
+
/>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
4. **Always use appropriate sizes**:
|
|
180
|
+
```tsx
|
|
181
|
+
// Dense grid
|
|
182
|
+
<MediaCard size="sm" />
|
|
183
|
+
|
|
184
|
+
// Standard card
|
|
185
|
+
<MediaCard size="md" />
|
|
186
|
+
|
|
187
|
+
// Featured item
|
|
188
|
+
<MediaCard size="lg" />
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
5. **Never forget accessibility**:
|
|
192
|
+
```tsx
|
|
193
|
+
// ❌ Bad
|
|
194
|
+
<MediaCard uri="image.jpg" />
|
|
195
|
+
|
|
196
|
+
// ✅ Good
|
|
197
|
+
<MediaCard
|
|
198
|
+
uri="image.jpg"
|
|
199
|
+
accessibilityLabel="Product image"
|
|
200
|
+
title="Product Name"
|
|
201
|
+
/>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Common Patterns
|
|
205
|
+
|
|
206
|
+
#### Photo Gallery
|
|
353
207
|
```tsx
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
<MediaCard
|
|
208
|
+
<FlatList
|
|
209
|
+
numColumns={3}
|
|
210
|
+
data={photos}
|
|
211
|
+
renderItem={({ item }) => (
|
|
212
|
+
<MediaCard
|
|
213
|
+
uri={item.uri}
|
|
214
|
+
size="sm"
|
|
215
|
+
onPress={() => navigateToPhoto(item.id)}
|
|
216
|
+
/>
|
|
217
|
+
)}
|
|
218
|
+
/>
|
|
359
219
|
```
|
|
360
220
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
MediaCard
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
## Performans İpuçları
|
|
371
|
-
|
|
372
|
-
1. **Optimization**: Resimleri optimize edin
|
|
373
|
-
2. **Caching**: Resimleri cache'leyin
|
|
374
|
-
3. **Lazy Loading**: Uzun listelerde lazy load kullanın
|
|
375
|
-
|
|
376
|
-
## İlgili Bileşenler
|
|
221
|
+
#### Template Selector
|
|
222
|
+
```tsx
|
|
223
|
+
<MediaCard
|
|
224
|
+
uri={template.thumbnail}
|
|
225
|
+
title={template.name}
|
|
226
|
+
selected={selectedId === template.id}
|
|
227
|
+
onPress={() => setSelectedTemplate(template)}
|
|
228
|
+
/>
|
|
229
|
+
```
|
|
377
230
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
231
|
+
#### Product Card
|
|
232
|
+
```tsx
|
|
233
|
+
<MediaCard
|
|
234
|
+
uri={product.image}
|
|
235
|
+
title={product.name}
|
|
236
|
+
subtitle={`$${product.price}`}
|
|
237
|
+
badge={product.isNew ? 'NEW' : ''}
|
|
238
|
+
onPress={() => navigateToProduct(product.id)}
|
|
239
|
+
/>
|
|
240
|
+
```
|
|
381
241
|
|
|
382
|
-
##
|
|
242
|
+
## Props Reference
|
|
243
|
+
|
|
244
|
+
| Prop | Type | Required | Default | Description |
|
|
245
|
+
|------|------|----------|---------|-------------|
|
|
246
|
+
| `uri` | `string` | Yes | - | Image URI |
|
|
247
|
+
| `title` | `string` | No | - | Overlay title |
|
|
248
|
+
| `subtitle` | `string` | No | - | Overlay subtitle |
|
|
249
|
+
| `badge` | `string \| number` | No | - | Badge content |
|
|
250
|
+
| `selected` | `boolean` | No | `false` | Selected state |
|
|
251
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | No | `'md'` | Card size |
|
|
252
|
+
| `aspectRatio` | `number` | No | `0.8` | Aspect ratio |
|
|
253
|
+
| `overlayPosition` | `'top' \| 'bottom' \| 'center'` | No | `'bottom'` | Overlay position |
|
|
254
|
+
| `showOverlay` | `boolean` | No | `true` | Show overlay |
|
|
255
|
+
| `width` | `number` | No | - | Custom width |
|
|
256
|
+
| `onPress` | `() => void` | No | - | Press handler |
|
|
257
|
+
|
|
258
|
+
## Accessibility
|
|
259
|
+
|
|
260
|
+
- ✅ Screen reader announces title and subtitle
|
|
261
|
+
- ✅ Touch target size: minimum 44x44pt
|
|
262
|
+
- ✅ Selected state announced to screen readers
|
|
263
|
+
- ✅ Test ID support for testing
|
|
264
|
+
- ✅ Accessibility label support
|
|
265
|
+
|
|
266
|
+
## Performance
|
|
267
|
+
|
|
268
|
+
1. **Image optimization**: Use optimized image sizes
|
|
269
|
+
2. **Caching**: Enable image caching
|
|
270
|
+
3. **Lazy loading**: Use in long lists
|
|
271
|
+
4. **Memoization**: Memo press handlers
|
|
272
|
+
|
|
273
|
+
## Related Components
|
|
274
|
+
|
|
275
|
+
- [`AtomicCard`](../../atoms/AtomicCard/README.md) - Basic card component
|
|
276
|
+
- [`GlowingCard`](../GlowingCard/README.md) - Glowing effect card
|
|
277
|
+
- [`AtomicImage`](../../atoms/AtomicImage/README.md) - Image component
|
|
278
|
+
- [`Avatar`](../avatar/README.md) - User avatar component
|
|
279
|
+
|
|
280
|
+
## License
|
|
383
281
|
|
|
384
282
|
MIT
|