@umituz/react-native-design-system 2.6.88 → 2.6.89

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.
@@ -0,0 +1,522 @@
1
+ # StepProgress
2
+
3
+ StepProgress, çok adımlı iş akışlarında ilerleme durumunu gösteren basit ve etkili bir bileşendir. Yatay ilerleme çubuğu ile hangi adımda olduğunuzu görselleştirir.
4
+
5
+ ## Özellikler
6
+
7
+ - 📊 **Görsel İlerleme**: Adım ilerlemesini görselleştirir
8
+ - 🎨 **Tema Bilinci**: Design token uyumlu
9
+ - 🎯 **Basit Kullanım**: Sadece 2 prop gerekli
10
+ - ♿ **Erişilebilir**: Screen reader desteği
11
+ - 📐 **Responsive**: Otomatik genişlik ayarı
12
+
13
+ ## Kurulum
14
+
15
+ ```tsx
16
+ import { StepProgress } from 'react-native-design-system';
17
+ ```
18
+
19
+ ## Temel Kullanım
20
+
21
+ ```tsx
22
+ import React, { useState } from 'react';
23
+ import { View } from 'react-native';
24
+ import { StepProgress } from 'react-native-design-system';
25
+
26
+ export const BasicExample = () => {
27
+ const [currentStep, setCurrentStep] = useState(2);
28
+ const totalSteps = 4;
29
+
30
+ return (
31
+ <View>
32
+ <StepProgress
33
+ currentStep={currentStep}
34
+ totalSteps={totalSteps}
35
+ />
36
+ </View>
37
+ );
38
+ };
39
+ ```
40
+
41
+ ## Temel İlerleme
42
+
43
+ ```tsx
44
+ {/* 3 adımdan 2. adım */}
45
+ <StepProgress
46
+ currentStep={2}
47
+ totalSteps={3}
48
+ />
49
+
50
+ {/* 5 adımdan 1. adım */}
51
+ <StepProgress
52
+ currentStep={1}
53
+ totalSteps={5}
54
+ />
55
+ ```
56
+
57
+ ## Dinamik İlerleme
58
+
59
+ ```tsx
60
+ export const DynamicProgress = () => {
61
+ const [step, setStep] = useState(1);
62
+ const totalSteps = 4;
63
+
64
+ return (
65
+ <View>
66
+ <StepProgress
67
+ currentStep={step}
68
+ totalSteps={totalSteps}
69
+ />
70
+
71
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 16 }}>
72
+ <Button
73
+ title="Geri"
74
+ disabled={step === 1}
75
+ onPress={() => setStep(step - 1)}
76
+ />
77
+ <Button
78
+ title="İleri"
79
+ disabled={step === totalSteps}
80
+ onPress={() => setStep(step + 1)}
81
+ />
82
+ </View>
83
+ </View>
84
+ );
85
+ };
86
+ ```
87
+
88
+ ## Örnek Kullanımlar
89
+
90
+ ### Onboarding Flow
91
+
92
+ ```tsx
93
+ export const OnboardingProgress = () => {
94
+ const [currentStep, setCurrentStep] = useState(1);
95
+ const steps = [
96
+ { id: 1, title: 'Hoş Geldiniz' },
97
+ { id: 2, title: 'Profil' },
98
+ { id: 3, title: 'İlgi Alanları' },
99
+ { id: 4, title: 'Bitir' },
100
+ ];
101
+
102
+ return (
103
+ <ScreenLayout>
104
+ <StepProgress
105
+ currentStep={currentStep}
106
+ totalSteps={steps.length}
107
+ />
108
+
109
+ <View style={{ flex: 1, justifyContent: 'center' }}>
110
+ <AtomicText type="headlineLarge" style={{ textAlign: 'center' }}>
111
+ {steps[currentStep - 1].title}
112
+ </AtomicText>
113
+ </View>
114
+
115
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
116
+ <Button
117
+ title="Geri"
118
+ disabled={currentStep === 1}
119
+ onPress={() => setCurrentStep(currentStep - 1)}
120
+ />
121
+ <Button
122
+ title={currentStep === steps.length ? 'Bitir' : 'İleri'}
123
+ onPress={() => {
124
+ if (currentStep < steps.length) {
125
+ setCurrentStep(currentStep + 1);
126
+ } else {
127
+ // Finish
128
+ }
129
+ }}
130
+ />
131
+ </View>
132
+ </ScreenLayout>
133
+ );
134
+ };
135
+ ```
136
+
137
+ ### Checkout Süreci
138
+
139
+ ```tsx
140
+ export const CheckoutProgress = () => {
141
+ const [checkoutStep, setCheckoutStep] = useState(1);
142
+ const checkoutSteps = ['Sepet', 'Teslimat', 'Ödeme', 'Onay'];
143
+
144
+ return (
145
+ <View>
146
+ <StepProgress
147
+ currentStep={checkoutStep}
148
+ totalSteps={checkoutSteps.length}
149
+ />
150
+
151
+ <View style={{ marginTop: 16 }}>
152
+ <AtomicText type="titleMedium" style={{ textAlign: 'center', marginBottom: 8 }}>
153
+ {checkoutSteps[checkoutStep - 1]}
154
+ </AtomicText>
155
+ </View>
156
+
157
+ {/* Step content */}
158
+ </View>
159
+ );
160
+ };
161
+ ```
162
+
163
+ ### Quiz İlerlemesi
164
+
165
+ ```tsx
166
+ export const QuizProgress = () => {
167
+ const [questionIndex, setQuestionIndex] = useState(0);
168
+ const questions = [
169
+ 'Soru 1',
170
+ 'Soru 2',
171
+ 'Soru 3',
172
+ 'Soru 4',
173
+ 'Soru 5',
174
+ ];
175
+
176
+ const progress = questionIndex + 1;
177
+
178
+ return (
179
+ <View>
180
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 }}>
181
+ <AtomicText type="labelLarge">Soru {progress}/{questions.length}</AtomicText>
182
+ <AtomicText type="labelLarge" color="primary">
183
+ %{Math.round((progress / questions.length) * 100)}
184
+ </AtomicText>
185
+ </View>
186
+
187
+ <StepProgress
188
+ currentStep={progress}
189
+ totalSteps={questions.length}
190
+ />
191
+
192
+ <View style={{ marginTop: 24 }}>
193
+ <AtomicText type="headlineMedium">{questions[questionIndex]}</AtomicText>
194
+ </View>
195
+
196
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 32 }}>
197
+ <Button
198
+ title="Önceki"
199
+ disabled={questionIndex === 0}
200
+ onPress={() => setQuestionIndex(questionIndex - 1)}
201
+ />
202
+ <Button
203
+ title={questionIndex === questions.length - 1 ? 'Bitir' : 'Sonraki'}
204
+ onPress={() => {
205
+ if (questionIndex < questions.length - 1) {
206
+ setQuestionIndex(questionIndex + 1);
207
+ } else {
208
+ // Submit quiz
209
+ }
210
+ }}
211
+ />
212
+ </View>
213
+ </View>
214
+ );
215
+ };
216
+ ```
217
+
218
+ ### Form Adımları
219
+
220
+ ```tsx
221
+ export const FormWizard = () => {
222
+ const [formStep, setFormStep] = useState(1);
223
+ const formSteps = ['Kişisel', 'İletişim', 'Adres', 'Onay'];
224
+
225
+ return (
226
+ <AtomicCard variant="outlined">
227
+ <View style={{ padding: 16 }}>
228
+ <StepProgress
229
+ currentStep={formStep}
230
+ totalSteps={formSteps.length}
231
+ />
232
+
233
+ <View style={{ marginTop: 24 }}>
234
+ {formStep === 1 && (
235
+ <View>
236
+ <AtomicText type="titleLarge">Kişisel Bilgiler</AtomicText>
237
+ <FormField label="Ad" />
238
+ <FormField label="Soyad" />
239
+ </View>
240
+ )}
241
+
242
+ {formStep === 2 && (
243
+ <View>
244
+ <AtomicText type="titleLarge">İletişim Bilgileri</AtomicText>
245
+ <FormField label="E-posta" />
246
+ <FormField label="Telefon" />
247
+ </View>
248
+ )}
249
+
250
+ {formStep === 3 && (
251
+ <View>
252
+ <AtomicText type="titleLarge">Adres</AtomicText>
253
+ <FormField label="Şehir" />
254
+ <FormField label="Ülke" />
255
+ </View>
256
+ )}
257
+
258
+ {formStep === 4 && (
259
+ <View>
260
+ <AtomicText type="titleLarge">Onayla</AtomicText>
261
+ <AtomicText>Bilgilerinizi kontrol edin</AtomicText>
262
+ </View>
263
+ )}
264
+ </View>
265
+
266
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 24 }}>
267
+ <Button
268
+ title="Geri"
269
+ variant="ghost"
270
+ disabled={formStep === 1}
271
+ onPress={() => setFormStep(formStep - 1)}
272
+ />
273
+ <Button
274
+ title={formStep === formSteps.length ? 'Gönder' : 'İleri'}
275
+ onPress={() => {
276
+ if (formStep < formSteps.length) {
277
+ setFormStep(formStep + 1);
278
+ } else {
279
+ // Submit form
280
+ }
281
+ }}
282
+ />
283
+ </View>
284
+ </View>
285
+ </AtomicCard>
286
+ );
287
+ };
288
+ ```
289
+
290
+ ### Görev İzleme
291
+
292
+ ```tsx
293
+ export const TaskTracker = () => {
294
+ const [completedTasks, setCompletedTasks] = useState(0);
295
+ const totalTasks = 10;
296
+
297
+ const toggleTask = () => {
298
+ if (completedTasks < totalTasks) {
299
+ setCompletedTasks(completedTasks + 1);
300
+ }
301
+ };
302
+
303
+ const progressPercentage = Math.round((completedTasks / totalTasks) * 100);
304
+
305
+ return (
306
+ <AtomicCard variant="elevated">
307
+ <View style={{ padding: 16 }}>
308
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 }}>
309
+ <AtomicText type="titleMedium">Günlük Görevler</AtomicText>
310
+ <AtomicText type="labelLarge" color="primary">
311
+ %{progressPercentage}
312
+ </AtomicText>
313
+ </View>
314
+
315
+ <StepProgress
316
+ currentStep={completedTasks}
317
+ totalTasks={totalTasks}
318
+ />
319
+
320
+ <View style={{ marginTop: 16 }}>
321
+ <AtomicText type="bodyMedium" color="secondary">
322
+ {completedTasks}/{totalTasks} görev tamamlandı
323
+ </AtomicText>
324
+ </View>
325
+
326
+ {completedTasks < totalTasks && (
327
+ <Button
328
+ title="Görevi Tamamla"
329
+ onPress={toggleTask}
330
+ style={{ marginTop: 16 }}
331
+ />
332
+ )}
333
+
334
+ {completedTasks === totalTasks && (
335
+ <View style={{ marginTop: 16, alignItems: 'center' }}>
336
+ <AtomicIcon name="checkmark-circle" size="xl" color="success" />
337
+ <AtomicText type="titleMedium" color="success" style={{ marginTop: 8 }}>
338
+ Tüm görevler tamamlandı!
339
+ </AtomicText>
340
+ </View>
341
+ )}
342
+ </View>
343
+ </AtomicCard>
344
+ );
345
+ };
346
+ ```
347
+
348
+ ### Dosya Yükleme İlerlemesi
349
+
350
+ ```tsx
351
+ export const FileUploadProgress = () => {
352
+ const [uploadedFiles, setUploadedFiles] = useState(0);
353
+ const totalFiles = 5;
354
+
355
+ const uploadFile = () => {
356
+ if (uploadedFiles < totalFiles) {
357
+ setUploadedFiles(uploadedFiles + 1);
358
+ }
359
+ };
360
+
361
+ return (
362
+ <View>
363
+ <View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 }}>
364
+ <AtomicText type="titleMedium">Dosya Yükleme</AtomicText>
365
+ <AtomicText type="labelLarge">
366
+ {uploadedFiles}/{totalFiles}
367
+ </AtomicText>
368
+ </View>
369
+
370
+ <StepProgress
371
+ currentStep={uploadedFiles}
372
+ totalSteps={totalFiles}
373
+ />
374
+
375
+ {uploadedFiles < totalFiles && (
376
+ <Button
377
+ title="Dosya Yükle"
378
+ onPress={uploadFile}
379
+ style={{ marginTop: 16 }}
380
+ />
381
+ )}
382
+
383
+ {uploadedFiles === totalFiles && (
384
+ <AtomicText type="bodyMedium" color="success" style={{ marginTop: 16 }}>
385
+ Tüm dosyalar yüklendi ✓
386
+ </AtomicText>
387
+ )}
388
+ </View>
389
+ );
390
+ };
391
+ ```
392
+
393
+ ### Profil Tamamlama
394
+
395
+ ```tsx
396
+ export const ProfileCompletion = () => {
397
+ const [completedSections, setCompletedSections] = useState(2);
398
+ const totalSections = 5;
399
+
400
+ const sections = [
401
+ { id: 1, name: 'Profil Fotoğrafı', completed: true },
402
+ { id: 2, name: 'Kişisel Bilgiler', completed: true },
403
+ { id: 3, name: 'İletişim Bilgileri', completed: false },
404
+ { id: 4, name: 'Eğitim', completed: false },
405
+ { id: 5, name: 'Deneyim', completed: false },
406
+ ];
407
+
408
+ return (
409
+ <View style={{ padding: 16 }}>
410
+ <AtomicText type="headlineMedium" style={{ marginBottom: 8 }}>
411
+ Profilinizi Tamamlayın
412
+ </AtomicText>
413
+
414
+ <StepProgress
415
+ currentStep={completedSections}
416
+ totalSteps={totalSections}
417
+ />
418
+
419
+ <View style={{ marginTop: 16 }}>
420
+ <AtomicText type="bodyMedium" color="secondary">
421
+ {completedSections}/{totalSections} bölüm tamamlandı
422
+ </AtomicText>
423
+ </View>
424
+
425
+ <View style={{ marginTop: 16 }}>
426
+ {sections.map((section) => (
427
+ <View
428
+ key={section.id}
429
+ style={{
430
+ flexDirection: 'row',
431
+ alignItems: 'center',
432
+ paddingVertical: 8,
433
+ borderBottomWidth: 1,
434
+ borderBottomColor: '#e0e0e0',
435
+ }}
436
+ >
437
+ <AtomicIcon
438
+ name={section.completed ? 'checkmark-circle' : 'ellipse-outline'}
439
+ size="md"
440
+ color={section.completed ? 'success' : 'secondary'}
441
+ />
442
+ <AtomicText style={{ marginLeft: 12 }}>
443
+ {section.name}
444
+ </AtomicText>
445
+ </View>
446
+ ))}
447
+ </View>
448
+ </View>
449
+ );
450
+ };
451
+ ```
452
+
453
+ ## Props
454
+
455
+ ### StepProgressProps
456
+
457
+ | Prop | Tip | Varsayılan | Açıklama |
458
+ |------|-----|------------|----------|
459
+ | `currentStep` | `number` | - **(Zorunlu)** | Mevcut adım |
460
+ | `totalSteps` | `number` | - **(Zorunlu)** | Toplam adım sayısı |
461
+ | `style` | `ViewStyle` | - | Özel stil |
462
+
463
+ ## Best Practices
464
+
465
+ ### 1. Adım Sayısı
466
+
467
+ ```tsx
468
+ // İdeal: 3-7 adım
469
+ <StepProgress currentStep={2} totalSteps={5} /> // ✅
470
+
471
+ // Çok az
472
+ <StepProgress currentStep={1} totalSteps={2} /> // ⚠️
473
+
474
+ // Çok fazla
475
+ <StepProgress currentStep={5} totalSteps={20} /> // ❌
476
+ ```
477
+
478
+ ### 2. State Yönetimi
479
+
480
+ ```tsx
481
+ // Doğru
482
+ const [step, setStep] = useState(1);
483
+ <StepProgress currentStep={step} totalSteps={5} />
484
+
485
+ // Yanlış (hardcoded)
486
+ <StepProgress currentStep={2} totalSteps={5} /> // ❌
487
+ ```
488
+
489
+ ### 3. Kullanıcı Geri Bildirimi
490
+
491
+ ```tsx
492
+ // Adım numarasını göster
493
+ <AtomicText>Adım {currentStep}/{totalSteps}</AtomicText>
494
+
495
+ // Yüzde göster
496
+ <AtomicText>%{Math.round((currentStep / totalSteps) * 100)}</AtomicText>
497
+ ```
498
+
499
+ ## Erişilebilirlik
500
+
501
+ StepProgress, tam erişilebilirlik desteği sunar:
502
+
503
+ - ✅ Screen reader desteği
504
+ - ✅ Semantic role
505
+ - ✅ Progress anonsu
506
+ - ✅ Görsel kontrast
507
+
508
+ ## Performans İpuçları
509
+
510
+ 1. **Memoization**: Component'i memo edin
511
+ 2. **Minimal Props**: Sadece gerekli props'ları kullanın
512
+ 3. **Stable References**: Callback'leri useCallback ile sarın
513
+
514
+ ## İlgili Bileşenler
515
+
516
+ - [`StepHeader`](../StepHeader/README.md) - Adım başlığı
517
+ - [`Divider`](../Divider/README.md) - Ayırıcı
518
+ - [`AtomicText`](../../atoms/AtomicText/README.md) - Metin bileşeni
519
+
520
+ ## Lisans
521
+
522
+ MIT