@umituz/react-native-design-system 2.6.87 → 2.6.88
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 -6
- package/src/atoms/AtomicProgress.README.md +402 -0
- package/src/atoms/EmptyState.README.md +372 -0
- package/src/atoms/skeleton/AtomicSkeleton.README.md +339 -0
- package/src/molecules/ConfirmationModal.README.md +370 -0
- package/src/molecules/Divider/README.md +470 -0
- package/src/molecules/StepHeader/README.md +487 -0
- package/src/molecules/alerts/README.md +471 -0
- package/src/molecules/avatar/README.md +431 -0
- package/src/molecules/bottom-sheet/README.md +413 -0
- package/src/molecules/calendar/README.md +339 -0
- package/src/molecules/countdown/README.md +558 -0
- package/src/molecules/media-card/README.md +384 -0
- package/src/molecules/navigation/README.md +377 -0
- package/src/molecules/splash/README.md +474 -0
- package/src/molecules/splash/components/SplashScreen.tsx +0 -14
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
# Countdown
|
|
2
|
+
|
|
3
|
+
Countdown, geri sayım sayacı bileşenidir. Belirli bir tarihe/hedefe kalan süreyi gösterir. Birden fazla hedef arasında geçiş yapabilir, gün, saat, dakika ve saniye olarak gösterebilir.
|
|
4
|
+
|
|
5
|
+
## Özellikler
|
|
6
|
+
|
|
7
|
+
- ⏰ **Geri Sayım**: Belirli bir tarihe kadar geri sayım
|
|
8
|
+
- 🎯 **Çoklu Hedef**: Birden fazla hedef arasında geçiş
|
|
9
|
+
- 📊 **Time Unit**: Gün, saat, dakika, saniye gösterimi
|
|
10
|
+
- 🎨 **Özelleştirilebilir**: Boyut, etiket, görünüm
|
|
11
|
+
- 🔄 **Hook**: useCountdown hook ile kontrol
|
|
12
|
+
- 🎭 **Tema Bilinci**: Design token uyumlu
|
|
13
|
+
- ♿ **Erişilebilir**: Screen reader desteği
|
|
14
|
+
|
|
15
|
+
## Kurulum
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { Countdown, useCountdown } from 'react-native-design-system';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Temel Kullanım
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import React from 'react';
|
|
25
|
+
import { View } from 'react-native';
|
|
26
|
+
import { Countdown } from 'react-native-design-system';
|
|
27
|
+
|
|
28
|
+
export const BasicExample = () => {
|
|
29
|
+
const targetDate = new Date('2025-12-31T23:59:59');
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<View style={{ padding: 16 }}>
|
|
33
|
+
<Countdown
|
|
34
|
+
target={{
|
|
35
|
+
date: targetDate,
|
|
36
|
+
label: 'Yılbaşı',
|
|
37
|
+
}}
|
|
38
|
+
/>
|
|
39
|
+
</View>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Basit Countdown
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
<Countdown
|
|
48
|
+
target={{
|
|
49
|
+
date: new Date('2025-12-31'),
|
|
50
|
+
label: 'Yılbaşı',
|
|
51
|
+
}}
|
|
52
|
+
/>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Custom Görünüm
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<Countdown
|
|
59
|
+
target={{
|
|
60
|
+
date: new Date('2025-06-30'),
|
|
61
|
+
label: 'Yaz Başlangıcı',
|
|
62
|
+
icon: 'sunny-outline',
|
|
63
|
+
}}
|
|
64
|
+
displayConfig={{
|
|
65
|
+
size: 'large',
|
|
66
|
+
showLabel: true,
|
|
67
|
+
showToggle: false,
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Sadece Saat/Dakika/Saniye
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<Countdown
|
|
76
|
+
target={{
|
|
77
|
+
date: new Date(Date.now() + 3600000), // 1 saat
|
|
78
|
+
label: 'Teklif Bitişi',
|
|
79
|
+
}}
|
|
80
|
+
displayConfig={{
|
|
81
|
+
showDays: false,
|
|
82
|
+
showHours: true,
|
|
83
|
+
showMinutes: true,
|
|
84
|
+
showSeconds: true,
|
|
85
|
+
}}
|
|
86
|
+
/>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Çoklu Hedef
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
<Countdown
|
|
93
|
+
target={{
|
|
94
|
+
date: new Date('2025-12-31'),
|
|
95
|
+
label: 'Yılbaşı',
|
|
96
|
+
icon: 'calendar-outline',
|
|
97
|
+
}}
|
|
98
|
+
alternateTargets={[
|
|
99
|
+
{
|
|
100
|
+
date: new Date('2025-06-30'),
|
|
101
|
+
label: 'Yaz Başlangıcı',
|
|
102
|
+
icon: 'sunny-outline',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
date: new Date('2025-03-20'),
|
|
106
|
+
label: 'İlk Bahar',
|
|
107
|
+
icon: 'flower-outline',
|
|
108
|
+
},
|
|
109
|
+
]}
|
|
110
|
+
/>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Custom Label Format
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
<Countdown
|
|
117
|
+
target={{
|
|
118
|
+
date: new Date('2025-12-31'),
|
|
119
|
+
label: 'Yılbaşı',
|
|
120
|
+
}}
|
|
121
|
+
formatLabel={(unit, value) => {
|
|
122
|
+
const labels = {
|
|
123
|
+
days: 'gün',
|
|
124
|
+
hours: 'saat',
|
|
125
|
+
minutes: 'dakika',
|
|
126
|
+
seconds: 'saniye',
|
|
127
|
+
};
|
|
128
|
+
return labels[unit];
|
|
129
|
+
}}
|
|
130
|
+
/>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## onExpire Callback
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
<Countdown
|
|
137
|
+
target={{
|
|
138
|
+
date: new Date('2025-12-31'),
|
|
139
|
+
label: 'Yılbaşı',
|
|
140
|
+
}}
|
|
141
|
+
onExpire={() => {
|
|
142
|
+
console.log('Süre doldu!');
|
|
143
|
+
Alert.alert('Süre doldu!');
|
|
144
|
+
}}
|
|
145
|
+
/>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## useCountdown Hook
|
|
149
|
+
|
|
150
|
+
### Temel Kullanım
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
import { useCountdown } from 'react-native-design-system';
|
|
154
|
+
|
|
155
|
+
export const MyComponent = () => {
|
|
156
|
+
const { timeRemaining, isActive, isExpired, start, stop, reset } = useCountdown(
|
|
157
|
+
{
|
|
158
|
+
date: new Date('2025-12-31'),
|
|
159
|
+
label: 'Yılbaşı',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
interval: 1000,
|
|
163
|
+
autoStart: true,
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<View>
|
|
169
|
+
<Text>{timeRemaining.days} gün {timeRemaining.hours} saat</Text>
|
|
170
|
+
<Button title={isActive ? 'Durdur' : 'Başlat'} onPress={isActive ? stop : start} />
|
|
171
|
+
</View>
|
|
172
|
+
);
|
|
173
|
+
};
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Manual Kontrol
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
const { timeRemaining, isActive, start, stop, reset } = useCountdown(
|
|
180
|
+
target,
|
|
181
|
+
{ autoStart: false }
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<View>
|
|
186
|
+
<Text>{timeRemaining.totalSeconds} saniye</Text>
|
|
187
|
+
<Button title="Başlat" onPress={start} />
|
|
188
|
+
<Button title="Durdur" onPress={stop} />
|
|
189
|
+
<Button title="Sıfırla" onPress={reset} />
|
|
190
|
+
</View>
|
|
191
|
+
);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### onTick Callback
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
const { timeRemaining } = useCountdown(target, {
|
|
198
|
+
onTick: (time) => {
|
|
199
|
+
console.log('Kalan süre:', time.totalSeconds);
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Örnek Kullanımlar
|
|
205
|
+
|
|
206
|
+
### Flash Sale
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
export const FlashSaleCountdown = () => {
|
|
210
|
+
const endDate = new Date(Date.now() + 3600000); // 1 saat
|
|
211
|
+
|
|
212
|
+
return (
|
|
213
|
+
<AtomicCard variant="elevated">
|
|
214
|
+
<Countdown
|
|
215
|
+
target={{
|
|
216
|
+
date: endDate,
|
|
217
|
+
label: 'Flash Sale Bitiş',
|
|
218
|
+
icon: 'flash-outline',
|
|
219
|
+
}}
|
|
220
|
+
displayConfig={{
|
|
221
|
+
showDays: false,
|
|
222
|
+
size: 'large',
|
|
223
|
+
}}
|
|
224
|
+
onExpire={() => {
|
|
225
|
+
Alert.alert('Satış bitti!');
|
|
226
|
+
}}
|
|
227
|
+
/>
|
|
228
|
+
</AtomicCard>
|
|
229
|
+
);
|
|
230
|
+
};
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Etkinlik Sayacı
|
|
234
|
+
|
|
235
|
+
```tsx
|
|
236
|
+
export const EventCountdown = () => {
|
|
237
|
+
const [events] = useState([
|
|
238
|
+
{
|
|
239
|
+
date: new Date('2025-06-30'),
|
|
240
|
+
label: 'Yaz Konseri',
|
|
241
|
+
icon: 'musical-notes-outline',
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
date: new Date('2025-09-15'),
|
|
245
|
+
label: 'Teknoloji Zirvesi',
|
|
246
|
+
icon: 'laptop-outline',
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
date: new Date('2025-12-25'),
|
|
250
|
+
label: 'Yılbaşı Partisi',
|
|
251
|
+
icon: 'gift-outline',
|
|
252
|
+
},
|
|
253
|
+
]);
|
|
254
|
+
|
|
255
|
+
return (
|
|
256
|
+
<View style={{ padding: 16 }}>
|
|
257
|
+
<Countdown
|
|
258
|
+
target={events[0]}
|
|
259
|
+
alternateTargets={events.slice(1)}
|
|
260
|
+
displayConfig={{
|
|
261
|
+
size: 'medium',
|
|
262
|
+
showToggle: true,
|
|
263
|
+
}}
|
|
264
|
+
onTargetChange={(target) => {
|
|
265
|
+
console.log('Hedef değişti:', target.label);
|
|
266
|
+
}}
|
|
267
|
+
/>
|
|
268
|
+
</View>
|
|
269
|
+
);
|
|
270
|
+
};
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Yarışma Sayacı
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
export const CompetitionCountdown = () => {
|
|
277
|
+
const deadline = new Date('2025-03-31T23:59:59');
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<View style={{ padding: 16 }}>
|
|
281
|
+
<AtomicText type="headlineMedium" style={{ textAlign: 'center', marginBottom: 16 }}>
|
|
282
|
+
Yarışma Katılım Süresi
|
|
283
|
+
</AtomicText>
|
|
284
|
+
|
|
285
|
+
<Countdown
|
|
286
|
+
target={{
|
|
287
|
+
date: deadline,
|
|
288
|
+
label: 'Son Katılım Tarihi',
|
|
289
|
+
icon: 'trophy-outline',
|
|
290
|
+
}}
|
|
291
|
+
displayConfig={{
|
|
292
|
+
size: 'large',
|
|
293
|
+
showLabel: true,
|
|
294
|
+
}}
|
|
295
|
+
formatLabel={(unit) => {
|
|
296
|
+
const labels = {
|
|
297
|
+
days: 'GÜN',
|
|
298
|
+
hours: 'SAAT',
|
|
299
|
+
minutes: 'DAKİKA',
|
|
300
|
+
seconds: 'SANİYE',
|
|
301
|
+
};
|
|
302
|
+
return labels[unit];
|
|
303
|
+
}}
|
|
304
|
+
onExpire={() => {
|
|
305
|
+
Alert.alert('Yarışma sona erdi!');
|
|
306
|
+
}}
|
|
307
|
+
/>
|
|
308
|
+
</View>
|
|
309
|
+
);
|
|
310
|
+
};
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### İndirim Sayacı
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
export const DiscountTimer = ({ discountPercentage, validUntil }) => {
|
|
317
|
+
return (
|
|
318
|
+
<View style={{ backgroundColor: '#ff6b6b', padding: 16, borderRadius: 8 }}>
|
|
319
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 8 }}>
|
|
320
|
+
<AtomicIcon name="pricetag-outline" size="sm" color="#fff" />
|
|
321
|
+
<AtomicText type="titleMedium" style={{ color: '#fff', marginLeft: 8 }}>
|
|
322
|
+
%{discountPercentage} İndirim
|
|
323
|
+
</AtomicText>
|
|
324
|
+
</View>
|
|
325
|
+
|
|
326
|
+
<Countdown
|
|
327
|
+
target={{
|
|
328
|
+
date: validUntil,
|
|
329
|
+
label: 'Teklif Bitişi',
|
|
330
|
+
}}
|
|
331
|
+
displayConfig={{
|
|
332
|
+
showDays: false,
|
|
333
|
+
size: 'medium',
|
|
334
|
+
showLabel: false,
|
|
335
|
+
}}
|
|
336
|
+
/>
|
|
337
|
+
</View>
|
|
338
|
+
);
|
|
339
|
+
};
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Oyun Sayacı
|
|
343
|
+
|
|
344
|
+
```tsx
|
|
345
|
+
export const GameTimer = ({ duration, onTimeUp }) => {
|
|
346
|
+
const targetDate = useMemo(() => new Date(Date.now() + duration), [duration]);
|
|
347
|
+
const [timeLeft, setTimeLeft] = useState(duration);
|
|
348
|
+
|
|
349
|
+
const { timeRemaining, isExpired } = useCountdown(
|
|
350
|
+
{ date: targetDate },
|
|
351
|
+
{
|
|
352
|
+
onTick: (time) => {
|
|
353
|
+
setTimeLeft(time.totalSeconds * 1000);
|
|
354
|
+
},
|
|
355
|
+
onExpire: () => {
|
|
356
|
+
onTimeUp?.();
|
|
357
|
+
},
|
|
358
|
+
}
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
return (
|
|
362
|
+
<View style={{ alignItems: 'center' }}>
|
|
363
|
+
<Countdown
|
|
364
|
+
target={{ date: targetDate }}
|
|
365
|
+
displayConfig={{
|
|
366
|
+
showDays: false,
|
|
367
|
+
showHours: false,
|
|
368
|
+
showMinutes: true,
|
|
369
|
+
showSeconds: true,
|
|
370
|
+
showLabel: false,
|
|
371
|
+
size: 'large',
|
|
372
|
+
}}
|
|
373
|
+
/>
|
|
374
|
+
|
|
375
|
+
{isExpired && (
|
|
376
|
+
<AtomicText type="headlineLarge" style={{ color: 'red' }}>
|
|
377
|
+
Süre Doldu!
|
|
378
|
+
</AtomicText>
|
|
379
|
+
)}
|
|
380
|
+
</View>
|
|
381
|
+
);
|
|
382
|
+
};
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Günlük Hedef Sayacı
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
export const DailyResetCountdown = () => {
|
|
389
|
+
const getNextMidnight = () => {
|
|
390
|
+
const now = new Date();
|
|
391
|
+
const tomorrow = new Date(now);
|
|
392
|
+
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
393
|
+
tomorrow.setHours(0, 0, 0, 0);
|
|
394
|
+
return tomorrow;
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
const [target] = useState(getNextMidnight);
|
|
398
|
+
|
|
399
|
+
return (
|
|
400
|
+
<View style={{ padding: 16 }}>
|
|
401
|
+
<AtomicText type="titleMedium" style={{ marginBottom: 8 }}>
|
|
402
|
+
Günlük Hedefler Sıfırlanmasına:
|
|
403
|
+
</AtomicText>
|
|
404
|
+
|
|
405
|
+
<Countdown
|
|
406
|
+
target={{
|
|
407
|
+
date: target,
|
|
408
|
+
label: 'Yarın',
|
|
409
|
+
}}
|
|
410
|
+
displayConfig={{
|
|
411
|
+
showDays: false,
|
|
412
|
+
size: 'medium',
|
|
413
|
+
showLabel: false,
|
|
414
|
+
}}
|
|
415
|
+
onExpire={() => {
|
|
416
|
+
// Refresh targets
|
|
417
|
+
window.location.reload();
|
|
418
|
+
}}
|
|
419
|
+
/>
|
|
420
|
+
</View>
|
|
421
|
+
);
|
|
422
|
+
};
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Props
|
|
426
|
+
|
|
427
|
+
### CountdownProps
|
|
428
|
+
|
|
429
|
+
| Prop | Tip | Varsayılan | Açıklama |
|
|
430
|
+
|------|-----|------------|----------|
|
|
431
|
+
| `target` | `CountdownTarget` | - **(Zorunlu)** | Hedef tarih |
|
|
432
|
+
| `alternateTargets` | `CountdownTarget[]` | `[]` | Alternatif hedefler |
|
|
433
|
+
| `displayConfig` | `CountdownDisplayConfig` | `{}` | Görünüm konfigürasyonu |
|
|
434
|
+
| `interval` | `number` | `1000` | Güncelleme aralığı (ms) |
|
|
435
|
+
| `onExpire` | `() => void` | - | Süre dolunca |
|
|
436
|
+
| `onTargetChange` | `(target) => void` | - | Hedef değişince |
|
|
437
|
+
| `formatLabel` | `(unit, value) => string` | - | Label formatlama |
|
|
438
|
+
|
|
439
|
+
### CountdownTarget
|
|
440
|
+
|
|
441
|
+
| Prop | Tip | Açıklama |
|
|
442
|
+
|------|-----|----------|
|
|
443
|
+
| `date` | `Date` | Hedef tarih |
|
|
444
|
+
| `label` | `string` | Hedef etiketi |
|
|
445
|
+
| `icon` | `string` | İkon ismi |
|
|
446
|
+
|
|
447
|
+
### CountdownDisplayConfig
|
|
448
|
+
|
|
449
|
+
| Prop | Tip | Varsayılan | Açıklama |
|
|
450
|
+
|------|-----|------------|----------|
|
|
451
|
+
| `showLabel` | `boolean` | `true` | Label göster |
|
|
452
|
+
| `showToggle` | `boolean` | `alternateTargets.length > 0` | Toggle göster |
|
|
453
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Boyut |
|
|
454
|
+
| `showDays` | `boolean` | `auto` | Gün göster |
|
|
455
|
+
| `showHours` | `boolean` | `true` | Saat göster |
|
|
456
|
+
| `showMinutes` | `boolean` | `true` | Dakika göster |
|
|
457
|
+
| `showSeconds` | `boolean` | `true` | Saniye göster |
|
|
458
|
+
|
|
459
|
+
### useCountdown Options
|
|
460
|
+
|
|
461
|
+
| Prop | Tip | Varsayılan | Açıklama |
|
|
462
|
+
|------|-----|------------|----------|
|
|
463
|
+
| `interval` | `number` | `1000` | Güncelleme aralığı (ms) |
|
|
464
|
+
| `autoStart` | `boolean` | `true` | Otomatik başlat |
|
|
465
|
+
| `onExpire` | `() => void` | - | Süre dolunca |
|
|
466
|
+
| `onTick` | `(time) => void` | - | Her tick'te |
|
|
467
|
+
|
|
468
|
+
### useCountdown Return
|
|
469
|
+
|
|
470
|
+
| Prop | Tip | Açıklama |
|
|
471
|
+
|------|-----|----------|
|
|
472
|
+
| `timeRemaining` | `TimeRemaining` | Kalan süre |
|
|
473
|
+
| `isActive` | `boolean` | Aktif mi |
|
|
474
|
+
| `isExpired` | `boolean` | Doldu mu |
|
|
475
|
+
| `start` | `() => void` | Başlat |
|
|
476
|
+
| `stop` | `() => void` | Durdur |
|
|
477
|
+
| `reset` | `() => void` | Sıfırla |
|
|
478
|
+
| `setTarget` | `(target) => void` | Hedef belirle |
|
|
479
|
+
|
|
480
|
+
## Best Practices
|
|
481
|
+
|
|
482
|
+
### 1. Hedef Seçimi
|
|
483
|
+
|
|
484
|
+
```tsx
|
|
485
|
+
// Gelecek tarih
|
|
486
|
+
target={{ date: new Date('2025-12-31') }} // ✅
|
|
487
|
+
|
|
488
|
+
// Geçmiş tarih
|
|
489
|
+
target={{ date: new Date('2020-01-01') }} // ❌
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### 2. Performans
|
|
493
|
+
|
|
494
|
+
```tsx
|
|
495
|
+
// Uygun interval
|
|
496
|
+
interval={1000} // ✅ 1 saniye (önerilen)
|
|
497
|
+
interval={100} // ❌ 100ms (çok sık)
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### 3. Memory Leak Önleme
|
|
501
|
+
|
|
502
|
+
```tsx
|
|
503
|
+
useEffect(() => {
|
|
504
|
+
return () => {
|
|
505
|
+
// Cleanup
|
|
506
|
+
};
|
|
507
|
+
}, []);
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### 4. Timezone
|
|
511
|
+
|
|
512
|
+
```tsx
|
|
513
|
+
// UTC kullan
|
|
514
|
+
const date = new Date('2025-12-31T23:59:59Z');
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## Erişilebilirlik
|
|
518
|
+
|
|
519
|
+
Countdown, tam erişilebilirlik desteği sunar:
|
|
520
|
+
|
|
521
|
+
- ✅ Screen reader desteği
|
|
522
|
+
- ✅ Semantic anlamlar
|
|
523
|
+
- ✅ Timer role
|
|
524
|
+
- ✅ Live region
|
|
525
|
+
|
|
526
|
+
## Performans İpuçları
|
|
527
|
+
|
|
528
|
+
1. **Interval**: Uygun interval kullanın (1000ms önerilen)
|
|
529
|
+
2. **Memoization**: Component'leri memo edin
|
|
530
|
+
3. **Cleanup**: useEffect'te cleanup yapın
|
|
531
|
+
4. **Throttle**: onTick callback'ini throttle edin
|
|
532
|
+
|
|
533
|
+
## İlgili Bileşenler
|
|
534
|
+
|
|
535
|
+
- [`TimeUnit`](#timeunit) - Zaman birimi bileşeni
|
|
536
|
+
- [`CountdownHeader`](#countdownheader) - Countdown başlığı
|
|
537
|
+
- [`AtomicText`](../../atoms/AtomicText/README.md) - Metin bileşeni
|
|
538
|
+
- [`AtomicIcon`](../../atoms/AtomicIcon/README.md) - İkon bileşeni
|
|
539
|
+
|
|
540
|
+
## Yardımcı Fonksiyonlar
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
// Kalan süreyi hesapla
|
|
544
|
+
calculateTimeRemaining(targetDate: Date): TimeRemaining
|
|
545
|
+
|
|
546
|
+
// Sayıyı padding yap
|
|
547
|
+
padNumber(num: number): string
|
|
548
|
+
|
|
549
|
+
// Sonraki gün başlangıcı
|
|
550
|
+
getNextDayStart(): Date
|
|
551
|
+
|
|
552
|
+
// Sonraki yıl başlangıcı
|
|
553
|
+
getNextYearStart(): Date
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
## Lisans
|
|
557
|
+
|
|
558
|
+
MIT
|