@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.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/src/atoms/AtomicAvatar.README.md +284 -397
  3. package/src/atoms/AtomicBadge.README.md +123 -358
  4. package/src/atoms/AtomicCard.README.md +358 -247
  5. package/src/atoms/AtomicDatePicker.README.md +127 -332
  6. package/src/atoms/AtomicFab.README.md +194 -352
  7. package/src/atoms/AtomicIcon.README.md +241 -274
  8. package/src/atoms/AtomicProgress.README.md +100 -338
  9. package/src/atoms/AtomicSpinner.README.md +304 -337
  10. package/src/atoms/AtomicText.README.md +153 -389
  11. package/src/atoms/AtomicTextArea.README.md +267 -268
  12. package/src/atoms/EmptyState.README.md +247 -292
  13. package/src/atoms/GlassView/README.md +313 -444
  14. package/src/atoms/button/README.md +186 -297
  15. package/src/atoms/button/STRATEGY.md +252 -0
  16. package/src/atoms/chip/README.md +242 -290
  17. package/src/atoms/input/README.md +296 -290
  18. package/src/atoms/picker/README.md +278 -309
  19. package/src/atoms/skeleton/AtomicSkeleton.README.md +394 -252
  20. package/src/molecules/BaseModal/README.md +356 -0
  21. package/src/molecules/BaseModal.README.md +324 -200
  22. package/src/molecules/ConfirmationModal.README.md +349 -302
  23. package/src/molecules/Divider/README.md +293 -376
  24. package/src/molecules/FormField.README.md +321 -534
  25. package/src/molecules/GlowingCard/GlowingCard.tsx +1 -1
  26. package/src/molecules/GlowingCard/README.md +230 -372
  27. package/src/molecules/List/README.md +281 -488
  28. package/src/molecules/ListItem.README.md +320 -315
  29. package/src/molecules/SearchBar/README.md +332 -430
  30. package/src/molecules/StepHeader/README.md +311 -411
  31. package/src/molecules/StepProgress/README.md +281 -448
  32. package/src/molecules/alerts/README.md +272 -355
  33. package/src/molecules/avatar/README.md +295 -356
  34. package/src/molecules/bottom-sheet/README.md +303 -340
  35. package/src/molecules/calendar/README.md +301 -265
  36. package/src/molecules/countdown/README.md +347 -456
  37. package/src/molecules/emoji/README.md +281 -514
  38. package/src/molecules/listitem/README.md +307 -399
  39. package/src/molecules/media-card/MediaCard.tsx +31 -34
  40. package/src/molecules/media-card/README.md +217 -319
  41. package/src/molecules/navigation/README.md +263 -284
  42. package/src/molecules/navigation/components/NavigationHeader.tsx +77 -0
  43. package/src/molecules/navigation/index.ts +1 -0
  44. package/src/molecules/splash/README.md +76 -80
  45. package/src/molecules/swipe-actions/README.md +376 -588
@@ -1,533 +1,435 @@
1
1
  # SearchBar
2
2
 
3
- SearchBar, React Native için modern ve özelleştirilebilir bir arama çubuğu bileşenidir. Material Design prensiplerine uygun olarak tasarlanmıştır.
3
+ A modern and customizable search input component for React Native with built-in loading state, clear button, and theme support.
4
4
 
5
- ## Özellikler
5
+ ## Import & Usage
6
6
 
7
- - 🔍 **Arama İkonu**: Sol tarafta arama ikonu
8
- - **Clear Button**: Sağ tarafta temizleme butonu
9
- - ⏳ **Loading State**: Yükleme göstergesi
10
- - 🎨 **Tema Bilinci**: Tam tema entegrasyonu
11
- - ⌨️ **Klavye Desteği**: Return key olarak "search"
12
- - ♿ **Erişilebilir**: Tam erişilebilirlik desteği
7
+ ```typescript
8
+ import { SearchBar } from 'react-native-design-system/src/molecules/SearchBar';
9
+ ```
10
+
11
+ **Location:** `src/molecules/SearchBar/SearchBar.tsx`
13
12
 
14
- ## Kurulum
13
+ ## Basic Usage
15
14
 
16
15
  ```tsx
17
- import { SearchBar } from 'react-native-design-system';
16
+ const [searchQuery, setSearchQuery] = useState('');
17
+
18
+ <SearchBar
19
+ value={searchQuery}
20
+ onChangeText={setSearchQuery}
21
+ placeholder="Search..."
22
+ />
18
23
  ```
19
24
 
20
- ## Temel Kullanım
25
+ ## Strategy
21
26
 
22
- ```tsx
23
- import React, { useState } from 'react';
24
- import { View } from 'react-native';
25
- import { SearchBar } from 'react-native-design-system';
26
-
27
- export const BasicExample = () => {
28
- const [searchQuery, setSearchQuery] = useState('');
29
-
30
- return (
31
- <View style={{ padding: 16 }}>
32
- <SearchBar
33
- value={searchQuery}
34
- onChangeText={setSearchQuery}
35
- placeholder="Ara..."
36
- />
37
- </View>
38
- );
39
- };
40
- ```
27
+ **Purpose**: Provide a consistent, accessible, and performant search interface for filtering and finding content.
41
28
 
42
- ## Basic Search
29
+ **When to Use**:
30
+ - Searching through lists or datasets
31
+ - Filtering content by keywords
32
+ - Finding specific items (users, products, posts)
33
+ - Global search across multiple content types
34
+ - Autocomplete and suggestion inputs
43
35
 
44
- ```tsx
45
- const [query, setQuery] = useState('');
36
+ **When NOT to Use**:
37
+ - For simple filtering (use Filter controls instead)
38
+ - For form inputs (use FormField instead)
39
+ - For single-choice selection (use Dropdown/Select instead)
40
+ - For URL navigation (use navigation components instead)
41
+
42
+ ## Rules
43
+
44
+ ### Required
45
+
46
+ 1. **MUST** have `value` and `onChangeText` props
47
+ 2. **ALWAYS** provide meaningful placeholder text
48
+ 3. **MUST** debounce search input (500ms recommended)
49
+ 4. **SHOULD** require minimum query length (2-3 chars)
50
+ 5. **ALWAYS** show loading state during search
51
+ 6. **MUST** handle empty results gracefully
52
+ 7. **SHOULD** provide clear button when input has value
53
+
54
+ ### Debouncing
55
+
56
+ 1. **MUST** debounce search input to avoid excessive API calls
57
+ 2. **Recommended delay**: 500ms
58
+ 3. **MUST** cancel pending requests on new input
59
+ 4. **ALWAYS** cleanup debounced timers
60
+
61
+ ### Minimum Query Length
62
+
63
+ 1. **Recommended**: 2-3 characters minimum
64
+ 2. **MUST** show feedback if query too short
65
+ 3. **SHOULD** not search with 1 character (too many results)
66
+ 4. **MUST** handle empty query (clear results)
46
67
 
68
+ ### Loading State
69
+
70
+ 1. **MUST** show loading indicator during search
71
+ 2. **SHOULD** disable input during search if needed
72
+ 3. **MUST** handle search errors gracefully
73
+ 4. **ALWAYS** reset loading state after search completes
74
+
75
+ ## Forbidden
76
+
77
+ ❌ **NEVER** do these:
78
+
79
+ ```tsx
80
+ // ❌ No debouncing
47
81
  <SearchBar
48
82
  value={query}
49
- onChangeText={setQuery}
50
- placeholder="Ürün ara..."
83
+ onChangeText={(text) => {
84
+ setQuery(text);
85
+ searchAPI(text); // ❌ API call on every keystroke
86
+ }}
51
87
  />
52
- ```
53
-
54
- ## With Submit Handler
55
88
 
56
- ```tsx
57
- const handleSearch = () => {
58
- console.log('Searching for:', query);
59
- // Arama yap
60
- };
89
+ // ❌ No minimum length check
90
+ <SearchBar
91
+ value={query}
92
+ onChangeText={(text) => {
93
+ if (text.length > 0) { // ❌ Searches with 1 character
94
+ performSearch(text);
95
+ }
96
+ }}
97
+ />
61
98
 
99
+ // ❌ No loading state
62
100
  <SearchBar
63
101
  value={query}
64
- onChangeText={setQuery}
65
- onSubmit={handleSearch}
66
- placeholder="Ara..."
67
- returnKeyType="search"
102
+ onChangeText={handleSearch}
103
+ // ❌ No loading indicator
68
104
  />
69
- ```
70
105
 
71
- ## Loading State
106
+ // Not handling empty results
107
+ const results = await searchAPI(query);
108
+ setResults(results); // ❌ Could be empty array
72
109
 
73
- ```tsx
74
- const [isSearching, setIsSearching] = useState(false);
110
+ // ❌ Not clearing results
111
+ const handleClear = () => {
112
+ setQuery('');
113
+ // ❌ Results still showing
114
+ };
75
115
 
76
- const handleSearch = async () => {
77
- setIsSearching(true);
78
- await performSearch(query);
79
- setIsSearching(false);
116
+ // No error handling
117
+ const handleSearch = async (query) => {
118
+ setLoading(true);
119
+ const results = await searchAPI(query); // ❌ No try/catch
120
+ setResults(results);
121
+ setLoading(false);
80
122
  };
81
123
 
124
+ // ❌ Auto-focus without context
82
125
  <SearchBar
83
126
  value={query}
84
127
  onChangeText={setQuery}
85
- onSubmit={handleSearch}
86
- loading={isSearching}
87
- placeholder="Ara..."
128
+ autoFocus // ❌ Auto-focuses on every render
88
129
  />
89
130
  ```
90
131
 
91
- ## With Clear Handler
132
+ ## Best Practices
92
133
 
134
+ ### Debounced Search
135
+
136
+ ✅ **DO**:
93
137
  ```tsx
94
- const handleClear = () => {
95
- setSearchQuery('');
96
- // Ek işlemler (örn: sonuçları sıfırla)
97
- };
138
+ const [query, setQuery] = useState('');
98
139
 
99
- <SearchBar
100
- value={searchQuery}
101
- onChangeText={setSearchQuery}
102
- onClear={handleClear}
103
- placeholder="Ara..."
104
- />
105
- ```
140
+ // Debounce search input
141
+ useEffect(() => {
142
+ const timer = setTimeout(() => {
143
+ if (query.length >= 2) {
144
+ performSearch(query);
145
+ }
146
+ }, 500);
106
147
 
107
- ## Disabled State
148
+ return () => clearTimeout(timer);
149
+ }, [query]);
108
150
 
109
- ```tsx
110
151
  <SearchBar
111
152
  value={query}
112
153
  onChangeText={setQuery}
113
- disabled
114
- placeholder="Arama devre dışı..."
154
+ placeholder="Search..."
115
155
  />
116
156
  ```
117
157
 
118
- ## Auto Focus
119
-
158
+ **DON'T**:
120
159
  ```tsx
160
+ // ❌ No debouncing
121
161
  <SearchBar
122
162
  value={query}
123
- onChangeText={setQuery}
124
- autoFocus
125
- placeholder="Ara..."
163
+ onChangeText={(text) => {
164
+ setQuery(text);
165
+ performSearch(text); // API call on every keystroke
166
+ }}
126
167
  />
127
168
  ```
128
169
 
129
- ## Örnek Kullanımlar
130
-
131
- ### Ürün Arama
170
+ ### Minimum Query Length
132
171
 
172
+ ✅ **DO**:
133
173
  ```tsx
134
- import React, { useState, useEffect } from 'react';
135
- import { View, FlatList, Pressable, Text } from 'react-native';
136
- import { SearchBar } from 'react-native-design-system';
137
-
138
- export const ProductSearch = () => {
139
- const [query, setQuery] = useState('');
140
- const [loading, setLoading] = useState(false);
141
- const [results, setResults] = useState([]);
142
-
143
- const handleSearch = async () => {
144
- if (!query.trim()) return;
145
-
146
- setLoading(true);
147
- try {
148
- const response = await fetchProducts(query);
149
- setResults(response);
150
- } catch (error) {
151
- console.error('Search error:', error);
152
- } finally {
153
- setLoading(false);
154
- }
155
- };
156
-
157
- const handleClear = () => {
158
- setQuery('');
174
+ const handleSearch = (text) => {
175
+ if (text.length < 2) {
159
176
  setResults([]);
160
- };
161
-
162
- return (
163
- <View style={{ flex: 1, padding: 16 }}>
164
- <SearchBar
165
- value={query}
166
- onChangeText={setQuery}
167
- onSubmit={handleSearch}
168
- onClear={handleClear}
169
- loading={loading}
170
- placeholder="Ürün ara..."
171
- />
172
-
173
- <FlatList
174
- data={results}
175
- keyExtractor={(item) => item.id}
176
- renderItem={({ item }) => (
177
- <Pressable style={{ padding: 16, borderBottomWidth: 1 }}>
178
- <Text>{item.name}</Text>
179
- </Pressable>
180
- )}
181
- />
182
- </View>
183
- );
184
- };
185
- ```
186
-
187
- ### Kullanıcı Arama
188
-
189
- ```tsx
190
- export const UserSearch = () => {
191
- const [searchQuery, setSearchQuery] = useState('');
192
- const [users, setUsers] = useState([]);
193
- const [loading, setLoading] = useState(false);
194
-
195
- useEffect(() => {
196
- if (searchQuery.length > 2) {
197
- searchUsers(searchQuery);
198
- } else {
199
- setUsers([]);
200
- }
201
- }, [searchQuery]);
202
-
203
- const searchUsers = async (query) => {
204
- setLoading(true);
205
- const results = await fetchUsers(query);
206
- setUsers(results);
207
- setLoading(false);
208
- };
209
-
210
- return (
211
- <View style={{ padding: 16 }}>
212
- <SearchBar
213
- value={searchQuery}
214
- onChangeText={setSearchQuery}
215
- loading={loading}
216
- placeholder="Kullanıcı ara..."
217
- />
218
-
219
- {users.map((user) => (
220
- <View key={user.id} style={{ padding: 16 }}>
221
- <Text>{user.name}</Text>
222
- </View>
223
- ))}
224
- </View>
225
- );
177
+ return;
178
+ }
179
+ performSearch(text);
226
180
  };
227
181
  ```
228
182
 
229
- ### Filtreleme ile Arama
230
-
183
+ **DON'T**:
231
184
  ```tsx
232
- export const FilterableSearch = () => {
233
- const [query, setQuery] = useState('');
234
- const [selectedFilter, setSelectedFilter] = useState('all');
235
-
236
- const handleSearch = () => {
237
- // Seçili filtreye göre arama
238
- console.log(`Searching for "${query}" in ${selectedFilter}`);
239
- };
240
-
241
- return (
242
- <View style={{ padding: 16 }}>
243
- <SearchBar
244
- value={query}
245
- onChangeText={setQuery}
246
- onSubmit={handleSearch}
247
- placeholder={`${selectedFilter === 'all' ? 'Tümü' : selectedFilter} ara...`}
248
- />
249
-
250
- {/* Filtre seçimi */}
251
- <View style={{ flexDirection: 'row', marginTop: 16, gap: 8 }}>
252
- <Pressable onPress={() => setSelectedFilter('all')}>
253
- <Text>Tümü</Text>
254
- </Pressable>
255
- <Pressable onPress={() => setSelectedFilter('users')}>
256
- <Text>Kullanıcılar</Text>
257
- </Pressable>
258
- <Pressable onPress={() => setSelectedFilter('products')}>
259
- <Text>Ürünler</Text>
260
- </Pressable>
261
- </View>
262
- </View>
263
- );
185
+ // Searches with 1 character
186
+ const handleSearch = (text) => {
187
+ if (text.length > 0) {
188
+ performSearch(text); // Too many results
189
+ }
264
190
  };
265
191
  ```
266
192
 
267
- ### Debounce ile Arama
193
+ ### Clear Handler
268
194
 
195
+ ✅ **DO**:
269
196
  ```tsx
270
- import { useCallback, useEffect } from 'react';
271
-
272
- export const DebouncedSearch = () => {
273
- const [query, setQuery] = useState('');
274
- const [debouncedQuery, setDebouncedQuery] = useState('');
275
- const [loading, setLoading] = useState(false);
276
-
277
- // Debounce
278
- useEffect(() => {
279
- const timer = setTimeout(() => {
280
- setDebouncedQuery(query);
281
- }, 500);
282
-
283
- return () => clearTimeout(timer);
284
- }, [query]);
285
-
286
- // Arama
287
- useEffect(() => {
288
- if (debouncedQuery) {
289
- performSearch(debouncedQuery);
290
- }
291
- }, [debouncedQuery]);
292
-
293
- const performSearch = async (searchQuery) => {
294
- setLoading(true);
295
- await fetch(`/api/search?q=${searchQuery}`);
296
- setLoading(false);
297
- };
298
-
299
- return (
300
- <View style={{ padding: 16 }}>
301
- <SearchBar
302
- value={query}
303
- onChangeText={setQuery}
304
- loading={loading}
305
- placeholder="Ara..."
306
- />
307
- </View>
308
- );
197
+ const handleClear = () => {
198
+ setQuery('');
199
+ setResults([]);
200
+ onClear?.();
309
201
  };
310
- ```
311
-
312
- ## Props
313
-
314
- ### SearchBarProps
315
202
 
316
- | Prop | Tip | Varsayılan | Açıklama |
317
- |------|-----|------------|----------|
318
- | `value` | `string` | - **(Zorunlu)** | Arama sorgusu |
319
- | `onChangeText` | `(text: string) => void` | - **(Zorunlu)** | Değişiklik olayı |
320
- | `onSubmit` | `() => void` | - | Submit olayı |
321
- | `onClear` | `() => void` | - | Temizleme olayı |
322
- | `onFocus` | `() => void` | - | Focus olayı |
323
- | `onBlur` | `() => void` | - | Blur olayı |
324
- | `placeholder` | `string` | `'Search...'` | Placeholder metni |
325
- | `autoFocus` | `boolean` | `false` | Otomatik odak |
326
- | `loading` | `boolean` | `false` | Yükleme durumu |
327
- | `disabled` | `boolean` | `false` | Devre dışı |
328
- | `containerStyle` | `ViewStyle` | - | Container stil |
329
- | `inputStyle` | `TextStyle` | - | Input stil |
330
- | `testID` | `string` | - | Test ID'si |
331
-
332
- ## Stil Özelleştirme
333
-
334
- ```tsx
335
203
  <SearchBar
336
204
  value={query}
337
205
  onChangeText={setQuery}
338
- containerStyle={{
339
- backgroundColor: '#f5f5f5',
340
- borderWidth: 2,
341
- borderColor: '#e0e0e0',
342
- }}
343
- inputStyle={{
344
- fontSize: 16,
345
- fontWeight: '500',
346
- }}
206
+ onClear={handleClear}
347
207
  />
348
208
  ```
349
209
 
350
- ## Best Practices
351
-
352
- ### 1. Debounce Kullanımı
210
+ **DON'T**:
211
+ ```tsx
212
+ // Doesn't clear results
213
+ const handleClear = () => {
214
+ setQuery('');
215
+ // Results still showing
216
+ };
217
+ ```
353
218
 
219
+ ## AI Coding Guidelines
220
+
221
+ ### For AI Agents
222
+
223
+ When generating SearchBar components, follow these rules:
224
+
225
+ 1. **Always import from correct path**:
226
+ ```typescript
227
+ import { SearchBar } from 'react-native-design-system/src/molecules/SearchBar';
228
+ ```
229
+
230
+ 2. **Always debounce search input**:
231
+ ```tsx
232
+ // ✅ Good - debounced search
233
+ useEffect(() => {
234
+ const timer = setTimeout(() => {
235
+ if (query.length >= 2) {
236
+ performSearch(query);
237
+ }
238
+ }, 500);
239
+
240
+ return () => clearTimeout(timer);
241
+ }, [query]);
242
+
243
+ // ❌ Bad - no debouncing
244
+ const handleChange = (text) => {
245
+ setQuery(text);
246
+ performSearch(text); // API call on every keystroke
247
+ };
248
+ ```
249
+
250
+ 3. **Always require minimum query length**:
251
+ ```tsx
252
+ // ✅ Good - minimum length check
253
+ if (query.length < 2) {
254
+ setResults([]);
255
+ return;
256
+ }
257
+
258
+ // ❌ Bad - searches immediately
259
+ if (query.length > 0) {
260
+ performSearch(query);
261
+ }
262
+ ```
263
+
264
+ 4. **Always show loading state**:
265
+ ```tsx
266
+ // ✅ Good - loading state
267
+ const [loading, setLoading] = useState(false);
268
+
269
+ const handleSearch = async (query) => {
270
+ if (query.length < 2) return;
271
+
272
+ setLoading(true);
273
+ try {
274
+ const results = await searchAPI(query);
275
+ setResults(results);
276
+ } catch (error) {
277
+ console.error('Search failed:', error);
278
+ } finally {
279
+ setLoading(false);
280
+ }
281
+ };
282
+
283
+ <SearchBar
284
+ value={query}
285
+ onChangeText={setQuery}
286
+ loading={loading}
287
+ />;
288
+
289
+ // ❌ Bad - no loading state
290
+ const handleSearch = async (query) => {
291
+ const results = await searchAPI(query);
292
+ setResults(results);
293
+ };
294
+ ```
295
+
296
+ 5. **Always handle clear properly**:
297
+ ```tsx
298
+ // ✅ Good - clears everything
299
+ const handleClear = () => {
300
+ setQuery('');
301
+ setResults([]);
302
+ setError(null);
303
+ };
304
+
305
+ // ❌ Bad - only clears input
306
+ const handleClear = () => {
307
+ setQuery('');
308
+ // Results still showing
309
+ };
310
+ ```
311
+
312
+ ### Common Patterns
313
+
314
+ #### Basic Search
354
315
  ```tsx
355
- // API çağrılarını azaltmak için debounce kullanın
316
+ const [query, setQuery] = useState('');
317
+
356
318
  useEffect(() => {
357
319
  const timer = setTimeout(() => {
358
- if (query.length > 2) {
320
+ if (query.length >= 2) {
359
321
  performSearch(query);
360
322
  }
361
323
  }, 500);
362
324
 
363
325
  return () => clearTimeout(timer);
364
326
  }, [query]);
365
- ```
366
327
 
367
- ### 2. Minimum Karakter
328
+ <SearchBar
329
+ value={query}
330
+ onChangeText={setQuery}
331
+ placeholder="Search..."
332
+ />
333
+ ```
368
334
 
335
+ #### Search with Loading
369
336
  ```tsx
370
- // En az 3 karakter sonra ara
371
- useEffect(() => {
372
- if (query.length > 2) {
373
- performSearch(query);
374
- } else {
337
+ const [query, setQuery] = useState('');
338
+ const [loading, setLoading] = useState(false);
339
+
340
+ const handleSearch = async (text) => {
341
+ setQuery(text);
342
+
343
+ if (text.length < 2) {
375
344
  setResults([]);
345
+ return;
376
346
  }
377
- }, [query]);
378
- ```
379
347
 
380
- ### 3. Loading State
348
+ setLoading(true);
349
+ try {
350
+ const results = await searchAPI(text);
351
+ setResults(results);
352
+ } finally {
353
+ setLoading(false);
354
+ }
355
+ };
381
356
 
382
- ```tsx
383
- // Kullanıcıya geri bildirim verin
384
357
  <SearchBar
385
358
  value={query}
386
- onChangeText={setQuery}
387
- loading={isSearching}
388
- onSubmit={handleSearch}
359
+ onChangeText={handleSearch}
360
+ loading={loading}
361
+ placeholder="Search..."
389
362
  />
390
363
  ```
391
364
 
392
- ### 4. Clear Handler
393
-
365
+ #### Search with Clear Handler
394
366
  ```tsx
395
- // Temizleme ile sonuçları sıfırlayın
367
+ const [query, setQuery] = useState('');
368
+ const [results, setResults] = useState([]);
369
+
396
370
  const handleClear = () => {
397
371
  setQuery('');
398
372
  setResults([]);
399
- setFilters({});
400
373
  };
401
- ```
402
-
403
- ## Erişilebilirlik
404
-
405
- SearchBar, tam erişilebilirlik desteği sunar:
406
-
407
- - ✅ Screen reader desteği
408
- - ✅ Accessibility label
409
- - ✅ Touch uygun boyut
410
- - ✅ Keyboard navigation
411
- - ✅ Test ID desteği
412
-
413
- ## Performans İpuçları
414
374
 
415
- 1. **Debouncing**: API çağrılarını azaltın
416
- 2. **Minimum Length**: Gereksiz aramaları önleyin
417
- 3. **Cancellation**: Async işlemleri iptal edin
418
- 4. **Memoization**: Sonuçları memoize edin
419
-
420
- ## İlgili Bileşenler
421
-
422
- - [`AtomicInput`](../../atoms/input/README.md) - Input bileşeni
423
- - [`BaseModal`](../BaseModal/README.md) - Modal arama sonuçları
424
- - [`AtomicIcon`](../../atoms/AtomicIcon/README.md) - İkon bileşeni
425
-
426
- ## Örnek Proje
375
+ <SearchBar
376
+ value={query}
377
+ onChangeText={setQuery}
378
+ onClear={handleClear}
379
+ placeholder="Search..."
380
+ />
381
+ ```
427
382
 
383
+ #### Auto-Focus Search
428
384
  ```tsx
429
- import React, { useState, useEffect } from 'react';
430
- import { View, FlatList, Pressable, Text, Image } from 'react-native';
431
- import { SearchBar } from 'react-native-design-system';
432
-
433
- export const AdvancedSearch = () => {
434
- const [query, setQuery] = useState('');
435
- const [loading, setLoading] = useState(false);
436
- const [results, setResults] = useState([]);
437
- const [history, setHistory] = useState([]);
438
-
439
- useEffect(() => {
440
- const timer = setTimeout(() => {
441
- if (query.length > 2) {
442
- performSearch(query);
443
- }
444
- }, 500);
445
-
446
- return () => clearTimeout(timer);
447
- }, [query]);
448
-
449
- const performSearch = async (searchQuery) => {
450
- setLoading(true);
451
- try {
452
- const response = await fetch(`/api/search?q=${searchQuery}`);
453
- const data = await response.json();
454
- setResults(data);
455
-
456
- // Geçmişe ekle
457
- setHistory(prev => [searchQuery, ...prev.slice(0, 9)]);
458
- } catch (error) {
459
- console.error('Search error:', error);
460
- } finally {
461
- setLoading(false);
462
- }
463
- };
464
-
465
- const handleClear = () => {
466
- setQuery('');
467
- setResults([]);
468
- };
469
-
470
- return (
471
- <View style={{ flex: 1, padding: 16 }}>
472
- <SearchBar
473
- value={query}
474
- onChangeText={setQuery}
475
- onClear={handleClear}
476
- loading={loading}
477
- placeholder="Ara..."
478
- />
479
-
480
- {/* Arama Geçmişi */}
481
- {query.length === 0 && history.length > 0 && (
482
- <View style={{ marginTop: 16 }}>
483
- <Text style={{ marginBottom: 8, fontWeight: '600' }}>
484
- Son Aramalar
485
- </Text>
486
- {history.map((item, index) => (
487
- <Pressable
488
- key={index}
489
- onPress={() => setQuery(item)}
490
- style={{ padding: 12 }}
491
- >
492
- <Text>{item}</Text>
493
- </Pressable>
494
- ))}
495
- </View>
496
- )}
497
-
498
- {/* Arama Sonuçları */}
499
- <FlatList
500
- data={results}
501
- keyExtractor={(item) => item.id}
502
- renderItem={({ item }) => (
503
- <Pressable
504
- style={{
505
- flexDirection: 'row',
506
- padding: 16,
507
- borderBottomWidth: 1,
508
- borderBottomColor: '#e0e0e0',
509
- }}
510
- >
511
- <Image
512
- source={{ uri: item.image }}
513
- style={{ width: 50, height: 50, borderRadius: 8 }}
514
- />
515
- <View style={{ marginLeft: 12, flex: 1 }}>
516
- <Text style={{ fontSize: 16, fontWeight: '600' }}>
517
- {item.title}
518
- </Text>
519
- <Text style={{ color: 'gray', marginTop: 4 }}>
520
- {item.description}
521
- </Text>
522
- </View>
523
- </Pressable>
524
- )}
525
- />
526
- </View>
527
- );
528
- };
385
+ <SearchBar
386
+ value={query}
387
+ onChangeText={setQuery}
388
+ autoFocus
389
+ placeholder="Search..."
390
+ />
529
391
  ```
530
392
 
531
- ## Lisans
393
+ ## Props Reference
394
+
395
+ | Prop | Type | Required | Default | Description |
396
+ |------|------|----------|---------|-------------|
397
+ | `value` | `string` | Yes | - | Search query value |
398
+ | `onChangeText` | `(text: string) => void` | Yes | - | Change callback |
399
+ | `placeholder` | `string` | No | `'Search...'` | Placeholder text |
400
+ | `onSubmit` | `() => void` | No | - | Submit callback |
401
+ | `onClear` | `() => void` | No | - | Clear callback |
402
+ | `onFocus` | `() => void` | No | - | Focus callback |
403
+ | `onBlur` | `() => void` | No | - | Blur callback |
404
+ | `autoFocus` | `boolean` | No | `false` | Auto focus input |
405
+ | `loading` | `boolean` | No | `false` | Show loading indicator |
406
+ | `disabled` | `boolean` | No | `false` | Disable input |
407
+ | `containerStyle` | `ViewStyle` | No | - | Custom container style |
408
+ | `inputStyle` | `TextStyle` | No | - | Custom input style |
409
+
410
+ ## Accessibility
411
+
412
+ - ✅ Screen reader announces search input and placeholder
413
+ - ✅ Touch target size maintained (min 44x44pt)
414
+ - ✅ Keyboard navigation (web)
415
+ - ✅ Focus management
416
+ - ✅ Semantic search role
417
+ - ✅ Loading state announced to screen readers
418
+
419
+ ## Performance Tips
420
+
421
+ 1. **Debounce**: Always debounce with 500ms delay
422
+ 2. **Minimum length**: Require 2-3 characters minimum
423
+ 3. **Cancel requests**: Cancel pending requests on new input
424
+ 4. **Memo results**: Memo search results to prevent re-renders
425
+ 5. **Virtualization**: Use FlatList for large result sets
426
+
427
+ ## Related Components
428
+
429
+ - [`FormField`](../FormField/README.md) - Form field component
430
+ - [`ListItem`](../ListItem/README.md) - List item for search results
431
+ - [`Button`](../../atoms/button/README.md) - Button component
432
+
433
+ ## License
532
434
 
533
435
  MIT