@umituz/react-native-design-system 2.6.93 → 2.6.95
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/exports/theme.ts +0 -1
- 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/IconContainer.tsx +1 -1
- 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/splash/README.md +76 -92
- package/src/molecules/swipe-actions/README.md +376 -588
|
@@ -1,342 +1,348 @@
|
|
|
1
1
|
# AtomicInput
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Customizable text input component with Material Design 3 principles for React Native applications.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Import & Usage
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- 🔢 **Character Counter**: Karakter sayacı
|
|
13
|
-
- 🎭 **İkon Desteği**: Leading ve trailing ikonlar
|
|
14
|
-
- ♿ **Erişilebilirlik**: Tam erişilebilirlik desteği
|
|
15
|
-
- ⌨️ **Klavye Türleri**: Farklı klavye türleri desteği
|
|
16
|
-
- 📝 **Multi-line**: Çok satırlı metin girişi
|
|
7
|
+
```typescript
|
|
8
|
+
import { AtomicInput } from 'react-native-design-system/src/atoms/input';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Location:** `src/atoms/input/AtomicInput.tsx`
|
|
17
12
|
|
|
18
|
-
##
|
|
13
|
+
## Basic Usage
|
|
19
14
|
|
|
20
15
|
```tsx
|
|
21
|
-
|
|
16
|
+
<AtomicInput
|
|
17
|
+
label="Email"
|
|
18
|
+
value={email}
|
|
19
|
+
onChangeText={setEmail}
|
|
20
|
+
placeholder="Enter your email"
|
|
21
|
+
keyboardType="email-address"
|
|
22
|
+
/>
|
|
22
23
|
```
|
|
23
24
|
|
|
24
|
-
##
|
|
25
|
+
## Strategy
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
import React, { useState } from 'react';
|
|
28
|
-
import { View } from 'react-native';
|
|
29
|
-
import { AtomicInput } from 'react-native-design-system';
|
|
30
|
-
|
|
31
|
-
export const BasicExample = () => {
|
|
32
|
-
const [value, setValue] = useState('');
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<View style={{ padding: 16 }}>
|
|
36
|
-
<AtomicInput
|
|
37
|
-
label="E-posta"
|
|
38
|
-
value={value}
|
|
39
|
-
onChangeText={setValue}
|
|
40
|
-
placeholder="ornek@email.com"
|
|
41
|
-
keyboardType="email-address"
|
|
42
|
-
/>
|
|
43
|
-
</View>
|
|
44
|
-
);
|
|
45
|
-
};
|
|
46
|
-
```
|
|
27
|
+
**Purpose**: Provide consistent, accessible, and performant text input with built-in validation states and Material Design aesthetics.
|
|
47
28
|
|
|
48
|
-
|
|
29
|
+
**When to Use**:
|
|
30
|
+
- Form inputs (name, email, password, etc.)
|
|
31
|
+
- Search fields
|
|
32
|
+
- Text entry for user data
|
|
33
|
+
- Multi-line text areas (textarea)
|
|
49
34
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
variant="outlined"
|
|
55
|
-
label="Outlined Input"
|
|
56
|
-
placeholder="Outlined variant"
|
|
57
|
-
/>
|
|
58
|
-
|
|
59
|
-
{/* Filled */}
|
|
60
|
-
<AtomicInput
|
|
61
|
-
variant="filled"
|
|
62
|
-
label="Filled Input"
|
|
63
|
-
placeholder="Filled variant"
|
|
64
|
-
/>
|
|
65
|
-
|
|
66
|
-
{/* Flat */}
|
|
67
|
-
<AtomicInput
|
|
68
|
-
variant="flat"
|
|
69
|
-
label="Flat Input"
|
|
70
|
-
placeholder="Flat variant"
|
|
71
|
-
/>
|
|
72
|
-
</View>
|
|
73
|
-
```
|
|
35
|
+
**When NOT to Use**:
|
|
36
|
+
- For numeric-only input - use NumericInput instead
|
|
37
|
+
- For selecting from options - use Picker component
|
|
38
|
+
- For rich text editing - use a specialized rich text editor
|
|
74
39
|
|
|
75
|
-
##
|
|
40
|
+
## Rules
|
|
76
41
|
|
|
77
|
-
|
|
78
|
-
<View style={{ gap: 16 }}>
|
|
79
|
-
{/* Small */}
|
|
80
|
-
<AtomicInput
|
|
81
|
-
size="sm"
|
|
82
|
-
label="Small Input"
|
|
83
|
-
placeholder="Small size"
|
|
84
|
-
/>
|
|
85
|
-
|
|
86
|
-
{/* Medium (Varsayılan) */}
|
|
87
|
-
<AtomicInput
|
|
88
|
-
size="md"
|
|
89
|
-
label="Medium Input"
|
|
90
|
-
placeholder="Medium size"
|
|
91
|
-
/>
|
|
92
|
-
|
|
93
|
-
{/* Large */}
|
|
94
|
-
<AtomicInput
|
|
95
|
-
size="lg"
|
|
96
|
-
label="Large Input"
|
|
97
|
-
placeholder="Large size"
|
|
98
|
-
/>
|
|
99
|
-
</View>
|
|
100
|
-
```
|
|
42
|
+
### Required
|
|
101
43
|
|
|
102
|
-
|
|
44
|
+
1. **ALWAYS** provide a `label` prop for accessibility
|
|
45
|
+
2. **MUST** have `value` and `onChangeText` for controlled input
|
|
46
|
+
3. **NEVER** use without proper state management
|
|
47
|
+
4. **ALWAYS** provide appropriate `keyboardType` for the input type
|
|
48
|
+
5. **MUST** provide accessible labels and error messages
|
|
49
|
+
|
|
50
|
+
### Validation
|
|
51
|
+
|
|
52
|
+
1. **MUST** show error state with `state="error"` when validation fails
|
|
53
|
+
2. **ALWAYS** provide `helperText` to explain error or constraints
|
|
54
|
+
3. **SHOULD** show success state after valid input
|
|
55
|
+
4. **MUST** indicate required fields clearly
|
|
56
|
+
|
|
57
|
+
### Password Fields
|
|
58
|
+
|
|
59
|
+
1. **MUST** use `secureTextEntry` for passwords
|
|
60
|
+
2. **SHOULD** provide `showPasswordToggle` for better UX
|
|
61
|
+
3. **ALWAYS** consider password strength indicators
|
|
62
|
+
|
|
63
|
+
### Multi-line
|
|
64
|
+
|
|
65
|
+
1. **MUST** use `multiline` prop for text areas
|
|
66
|
+
2. **SHOULD** specify `numberOfLines` for better UX
|
|
67
|
+
3. **ALWAYS** consider character limit with `showCharacterCount`
|
|
68
|
+
|
|
69
|
+
## Forbidden
|
|
70
|
+
|
|
71
|
+
❌ **NEVER** do these:
|
|
103
72
|
|
|
104
73
|
```tsx
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
/>
|
|
128
|
-
|
|
129
|
-
{/* Disabled */}
|
|
130
|
-
<AtomicInput
|
|
131
|
-
state="disabled"
|
|
132
|
-
label="Disabled"
|
|
133
|
-
placeholder="Disabled state"
|
|
134
|
-
value="Değer girilemez"
|
|
135
|
-
disabled
|
|
136
|
-
/>
|
|
137
|
-
</View>
|
|
74
|
+
// ❌ Uncontrolled input (no value/onChangeText)
|
|
75
|
+
<AtomicInput label="Name" />
|
|
76
|
+
|
|
77
|
+
// ❌ Input without label
|
|
78
|
+
<AtomicInput value={value} onChangeText={setValue} />
|
|
79
|
+
|
|
80
|
+
// ❌ Hardcoded placeholder text (use i18n)
|
|
81
|
+
<AtomicInput label="Email" placeholder="Enter your email" />
|
|
82
|
+
{/* ❌ Use placeholder={t('input.emailPlaceholder')} */}
|
|
83
|
+
|
|
84
|
+
// ❌ Email input without email keyboard type
|
|
85
|
+
<AtomicInput label="Email" keyboardType="default" />
|
|
86
|
+
{/* ❌ Use keyboardType="email-address" */}
|
|
87
|
+
|
|
88
|
+
// ❌ Password without secureTextEntry
|
|
89
|
+
<AtomicInput label="Password" />
|
|
90
|
+
{/* ❌ Use secureTextEntry */}
|
|
91
|
+
|
|
92
|
+
// ❌ Nested inputs
|
|
93
|
+
<AtomicInput label="Outer">
|
|
94
|
+
<AtomicInput label="Inner" />
|
|
95
|
+
</AtomicInput>
|
|
138
96
|
```
|
|
139
97
|
|
|
140
|
-
##
|
|
98
|
+
## Best Practices
|
|
99
|
+
|
|
100
|
+
### Input Types
|
|
141
101
|
|
|
102
|
+
✅ **DO**:
|
|
142
103
|
```tsx
|
|
104
|
+
// Email input
|
|
143
105
|
<AtomicInput
|
|
144
|
-
label=
|
|
145
|
-
|
|
106
|
+
label={t('form.email')}
|
|
107
|
+
keyboardType="email-address"
|
|
108
|
+
autoCapitalize="none"
|
|
109
|
+
/>
|
|
110
|
+
|
|
111
|
+
// Password input
|
|
112
|
+
<AtomicInput
|
|
113
|
+
label={t('form.password')}
|
|
146
114
|
secureTextEntry
|
|
147
115
|
showPasswordToggle
|
|
148
116
|
/>
|
|
149
|
-
```
|
|
150
117
|
|
|
151
|
-
|
|
118
|
+
// Numeric input
|
|
119
|
+
<AtomicInput
|
|
120
|
+
label={t('form.age')}
|
|
121
|
+
keyboardType="number-pad"
|
|
122
|
+
/>
|
|
123
|
+
```
|
|
152
124
|
|
|
125
|
+
❌ **DON'T**:
|
|
153
126
|
```tsx
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
leadingIcon="person-outline"
|
|
160
|
-
/>
|
|
161
|
-
|
|
162
|
-
{/* Trailing Icon */}
|
|
163
|
-
<AtomicInput
|
|
164
|
-
label="Arama"
|
|
165
|
-
placeholder="Arama yapın"
|
|
166
|
-
trailingIcon="search-outline"
|
|
167
|
-
onTrailingIconPress={() => console.log('Arama')}
|
|
168
|
-
/>
|
|
169
|
-
|
|
170
|
-
{/* Both Icons */}
|
|
171
|
-
<AtomicInput
|
|
172
|
-
label="Email"
|
|
173
|
-
placeholder="Email adresiniz"
|
|
174
|
-
leadingIcon="mail-outline"
|
|
175
|
-
trailingIcon="close-circle-outline"
|
|
176
|
-
onTrailingIconPress={() => console.log('Temizle')}
|
|
177
|
-
/>
|
|
178
|
-
</View>
|
|
127
|
+
// Don't use default keyboard for specific types
|
|
128
|
+
<AtomicInput keyboardType="default" />
|
|
129
|
+
|
|
130
|
+
// Don't forget autoCapitalize for email
|
|
131
|
+
<AtomicInput keyboardType="email-address" autoCapitalize="words" />
|
|
179
132
|
```
|
|
180
133
|
|
|
181
|
-
|
|
134
|
+
### Validation
|
|
182
135
|
|
|
136
|
+
✅ **DO**:
|
|
183
137
|
```tsx
|
|
184
138
|
<AtomicInput
|
|
185
|
-
label=
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
139
|
+
label={t('form.email')}
|
|
140
|
+
value={email}
|
|
141
|
+
onChangeText={setEmail}
|
|
142
|
+
state={emailError ? 'error' : 'default'}
|
|
143
|
+
helperText={emailError || t('form.emailHint')}
|
|
144
|
+
onBlur={() => validateEmail(email)}
|
|
191
145
|
/>
|
|
192
146
|
```
|
|
193
147
|
|
|
194
|
-
|
|
195
|
-
|
|
148
|
+
❌ **DON'T**:
|
|
196
149
|
```tsx
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
email: '',
|
|
205
|
-
password: '',
|
|
206
|
-
bio: ''
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
const handleInputChange = (field: string) => (value: string) => {
|
|
210
|
-
setFormData(prev => ({ ...prev, [field]: value }));
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
return (
|
|
214
|
-
<View style={{ padding: 16, gap: 16 }}>
|
|
215
|
-
<AtomicInput
|
|
216
|
-
label="Ad Soyad"
|
|
217
|
-
value={formData.name}
|
|
218
|
-
onChangeText={handleInputChange('name')}
|
|
219
|
-
placeholder="Adınız ve soyadınız"
|
|
220
|
-
leadingIcon="person-outline"
|
|
221
|
-
state="default"
|
|
222
|
-
/>
|
|
223
|
-
|
|
224
|
-
<AtomicInput
|
|
225
|
-
label="E-posta"
|
|
226
|
-
value={formData.email}
|
|
227
|
-
onChangeText={handleInputChange('email')}
|
|
228
|
-
placeholder="ornek@email.com"
|
|
229
|
-
keyboardType="email-address"
|
|
230
|
-
leadingIcon="mail-outline"
|
|
231
|
-
autoCapitalize="none"
|
|
232
|
-
/>
|
|
233
|
-
|
|
234
|
-
<AtomicInput
|
|
235
|
-
label="Şifre"
|
|
236
|
-
value={formData.password}
|
|
237
|
-
onChangeText={handleInputChange('password')}
|
|
238
|
-
placeholder="En az 8 karakter"
|
|
239
|
-
secureTextEntry
|
|
240
|
-
showPasswordToggle
|
|
241
|
-
leadingIcon="lock-closed-outline"
|
|
242
|
-
maxLength={20}
|
|
243
|
-
showCharacterCount
|
|
244
|
-
/>
|
|
245
|
-
|
|
246
|
-
<AtomicInput
|
|
247
|
-
label="Hakkınızda"
|
|
248
|
-
value={formData.bio}
|
|
249
|
-
onChangeText={handleInputChange('bio')}
|
|
250
|
-
placeholder="Kendinizden bahsedin"
|
|
251
|
-
multiline
|
|
252
|
-
numberOfLines={4}
|
|
253
|
-
maxLength={200}
|
|
254
|
-
showCharacterCount
|
|
255
|
-
/>
|
|
256
|
-
|
|
257
|
-
<Button title="Gönder" onPress={() => console.log(formData)} />
|
|
258
|
-
</View>
|
|
259
|
-
);
|
|
260
|
-
};
|
|
150
|
+
// Don't validate on every keystroke (use onBlur or debounce)
|
|
151
|
+
<AtomicInput
|
|
152
|
+
onChangeText={(text) => {
|
|
153
|
+
setValue(text);
|
|
154
|
+
validate(text); // ❌ Too frequent validation
|
|
155
|
+
}}
|
|
156
|
+
/>
|
|
261
157
|
```
|
|
262
158
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
### AtomicInputProps
|
|
266
|
-
|
|
267
|
-
| Prop | Tip | Varsayılan | Açıklama |
|
|
268
|
-
|------|-----|------------|----------|
|
|
269
|
-
| `variant` | `'outlined' \| 'filled' \| 'flat'` | `'outlined'` | Input görünüm stili |
|
|
270
|
-
| `state` | `'default' \| 'error' \| 'success' \| 'disabled'` | `'default'` | Input durumu |
|
|
271
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Input boyutu |
|
|
272
|
-
| `label` | `string` | - | Input etiketi |
|
|
273
|
-
| `value` | `string` | `''` | Input değeri |
|
|
274
|
-
| `onChangeText` | `(text: string) => void` | - | Değişiklik olayı |
|
|
275
|
-
| `placeholder` | `string` | - | Placeholder metni |
|
|
276
|
-
| `helperText` | `string` | - | Yardımcı metin |
|
|
277
|
-
| `leadingIcon` | `string` | - | Sol ikon ismi (Ionicons) |
|
|
278
|
-
| `trailingIcon` | `string` | - | Sağ ikon ismi (Ionicons) |
|
|
279
|
-
| `onTrailingIconPress` | `() => void` | - | Sağ ikon tıklama olayı |
|
|
280
|
-
| `showPasswordToggle` | `boolean` | `false` | Şifre göster/gizle butonu |
|
|
281
|
-
| `secureTextEntry` | `boolean` | `false` | Şifre girişi |
|
|
282
|
-
| `maxLength` | `number` | - | Maksimum karakter sayısı |
|
|
283
|
-
| `showCharacterCount` | `boolean` | `false` | Karakter sayacı göster |
|
|
284
|
-
| `keyboardType` | `KeyboardType` | `'default'` | Klavye türü |
|
|
285
|
-
| `returnKeyType` | `ReturnKeyType` | - | Return tuşu türü |
|
|
286
|
-
| `onSubmitEditing` | `() => void` | - | Submit olayı |
|
|
287
|
-
| `blurOnSubmit` | `boolean` | - | Submit'te blur |
|
|
288
|
-
| `autoFocus` | `boolean` | - | Otomatik odak |
|
|
289
|
-
| `autoCapitalize` | `AutoCapitalize` | `'sentences'` | Otomatik büyük harf |
|
|
290
|
-
| `autoCorrect` | `boolean` | `true` | Otomatik düzeltme |
|
|
291
|
-
| `disabled` | `boolean` | `false` | Devre dışı |
|
|
292
|
-
| `multiline` | `boolean` | `false` | Çok satırlı |
|
|
293
|
-
| `numberOfLines` | `number` | - | Satır sayısı |
|
|
294
|
-
| `style` | `StyleProp<ViewStyle>` | - | Container stil |
|
|
295
|
-
| `inputStyle` | `StyleProp<TextStyle>` | - | Input stil |
|
|
296
|
-
| `testID` | `string` | - | Test ID'si |
|
|
297
|
-
| `onBlur` | `() => void` | - | Blur olayı |
|
|
298
|
-
| `onFocus` | `() => void` | - | Focus olayı |
|
|
299
|
-
|
|
300
|
-
## Stil Özelleştirme
|
|
159
|
+
### Character Counting
|
|
301
160
|
|
|
161
|
+
✅ **DO**:
|
|
302
162
|
```tsx
|
|
303
163
|
<AtomicInput
|
|
304
|
-
label=
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
}}
|
|
310
|
-
inputStyle={{
|
|
311
|
-
fontSize: 16,
|
|
312
|
-
fontWeight: '600',
|
|
313
|
-
}}
|
|
164
|
+
label={t('form.bio')}
|
|
165
|
+
multiline
|
|
166
|
+
numberOfLines={4}
|
|
167
|
+
maxLength={150}
|
|
168
|
+
showCharacterCount
|
|
314
169
|
/>
|
|
315
170
|
```
|
|
316
171
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
- ✅ Focus management
|
|
323
|
-
- ✅ Error state anonsu
|
|
324
|
-
- ✅ Label ilişkilendirmesi
|
|
325
|
-
- ✅ Test ID desteği
|
|
172
|
+
❌ **DON'T**:
|
|
173
|
+
```tsx
|
|
174
|
+
// Don't show character count without maxLength
|
|
175
|
+
<AtomicInput showCharacterCount />
|
|
176
|
+
```
|
|
326
177
|
|
|
327
|
-
##
|
|
178
|
+
## AI Coding Guidelines
|
|
179
|
+
|
|
180
|
+
### For AI Agents
|
|
181
|
+
|
|
182
|
+
When generating AtomicInput components, follow these rules:
|
|
183
|
+
|
|
184
|
+
1. **Always import from correct path**:
|
|
185
|
+
```typescript
|
|
186
|
+
import { AtomicInput } from 'react-native-design-system/src/atoms/input';
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
2. **Always use controlled input**:
|
|
190
|
+
```tsx
|
|
191
|
+
const [value, setValue] = useState('');
|
|
192
|
+
|
|
193
|
+
<AtomicInput
|
|
194
|
+
label="明确的标签"
|
|
195
|
+
value={value}
|
|
196
|
+
onChangeText={setValue}
|
|
197
|
+
placeholder="适当的占位符"
|
|
198
|
+
/>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
3. **Always use i18n for labels**:
|
|
202
|
+
```tsx
|
|
203
|
+
<AtomicInput
|
|
204
|
+
label={t('form.username')}
|
|
205
|
+
placeholder={t('form.usernamePlaceholder')}
|
|
206
|
+
/>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
4. **Always provide appropriate keyboard type**:
|
|
210
|
+
```tsx
|
|
211
|
+
// Email
|
|
212
|
+
<AtomicInput keyboardType="email-address" autoCapitalize="none" />
|
|
213
|
+
|
|
214
|
+
// Password
|
|
215
|
+
<AtomicInput secureTextEntry showPasswordToggle />
|
|
216
|
+
|
|
217
|
+
// Phone
|
|
218
|
+
<AtomicInput keyboardType="phone-pad" />
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
5. **Always handle validation properly**:
|
|
222
|
+
```tsx
|
|
223
|
+
const [error, setError] = useState('');
|
|
224
|
+
|
|
225
|
+
<AtomicInput
|
|
226
|
+
label={t('form.email')}
|
|
227
|
+
value={email}
|
|
228
|
+
onChangeText={setEmail}
|
|
229
|
+
state={error ? 'error' : 'default'}
|
|
230
|
+
helperText={error || t('form.emailHint')}
|
|
231
|
+
onBlur={() => setError(validateEmail(email))}
|
|
232
|
+
/>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Common Patterns
|
|
236
|
+
|
|
237
|
+
#### Email Input
|
|
238
|
+
```tsx
|
|
239
|
+
<AtomicInput
|
|
240
|
+
label={t('form.email')}
|
|
241
|
+
value={email}
|
|
242
|
+
onChangeText={setEmail}
|
|
243
|
+
keyboardType="email-address"
|
|
244
|
+
autoCapitalize="none"
|
|
245
|
+
autoComplete="email"
|
|
246
|
+
state={emailError ? 'error' : 'default'}
|
|
247
|
+
helperText={emailError || t('form.emailHint')}
|
|
248
|
+
/>
|
|
249
|
+
```
|
|
328
250
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
251
|
+
#### Password Input
|
|
252
|
+
```tsx
|
|
253
|
+
<AtomicInput
|
|
254
|
+
label={t('form.password')}
|
|
255
|
+
value={password}
|
|
256
|
+
onChangeText={setPassword}
|
|
257
|
+
secureTextEntry
|
|
258
|
+
showPasswordToggle
|
|
259
|
+
maxLength={20}
|
|
260
|
+
showCharacterCount
|
|
261
|
+
state={passwordError ? 'error' : 'default'}
|
|
262
|
+
helperText={passwordError || t('form.passwordHint')}
|
|
263
|
+
/>
|
|
264
|
+
```
|
|
333
265
|
|
|
334
|
-
|
|
266
|
+
#### Search Input
|
|
267
|
+
```tsx
|
|
268
|
+
<AtomicInput
|
|
269
|
+
label={t('search.label')}
|
|
270
|
+
value={searchQuery}
|
|
271
|
+
onChangeText={setSearchQuery}
|
|
272
|
+
placeholder={t('search.placeholder')}
|
|
273
|
+
leadingIcon="search-outline"
|
|
274
|
+
keyboardType="web-search"
|
|
275
|
+
returnKeyType="search"
|
|
276
|
+
onSubmitEditing={handleSearch}
|
|
277
|
+
/>
|
|
278
|
+
```
|
|
335
279
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
280
|
+
#### Text Area
|
|
281
|
+
```tsx
|
|
282
|
+
<AtomicInput
|
|
283
|
+
label={t('form.bio')}
|
|
284
|
+
value={bio}
|
|
285
|
+
onChangeText={setBio}
|
|
286
|
+
multiline
|
|
287
|
+
numberOfLines={4}
|
|
288
|
+
maxLength={150}
|
|
289
|
+
showCharacterCount
|
|
290
|
+
placeholder={t('form.bioPlaceholder')}
|
|
291
|
+
/>
|
|
292
|
+
```
|
|
339
293
|
|
|
340
|
-
##
|
|
294
|
+
## Props Reference
|
|
295
|
+
|
|
296
|
+
| Prop | Type | Required | Default | Description |
|
|
297
|
+
|------|------|----------|---------|-------------|
|
|
298
|
+
| `label` | `string` | Yes | - | Input label |
|
|
299
|
+
| `value` | `string` | Yes | - | Input value (controlled) |
|
|
300
|
+
| `onChangeText` | `(text: string) => void` | Yes | - | Change handler |
|
|
301
|
+
| `placeholder` | `string` | No | - | Placeholder text |
|
|
302
|
+
| `variant` | `'outlined' \| 'filled' \| 'flat'` | No | `'outlined'` | Visual style |
|
|
303
|
+
| `state` | `'default' \| 'error' \| 'success' \| 'disabled'` | No | `'default'` | Input state |
|
|
304
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | No | `'md'` | Input size |
|
|
305
|
+
| `helperText` | `string` | No | - | Helper or error text |
|
|
306
|
+
| `leadingIcon` | `string` | No | - | Leading icon name |
|
|
307
|
+
| `trailingIcon` | `string` | No | - | Trailing icon name |
|
|
308
|
+
| `onTrailingIconPress` | `() => void` | No | - | Trailing icon press |
|
|
309
|
+
| `secureTextEntry` | `boolean` | No | `false` | Password input |
|
|
310
|
+
| `showPasswordToggle` | `boolean` | No | `false` | Show password toggle |
|
|
311
|
+
| `keyboardType` | `KeyboardType` | No | `'default'` | Keyboard type |
|
|
312
|
+
| `multiline` | `boolean` | No | `false` | Multi-line input |
|
|
313
|
+
| `numberOfLines` | `number` | No | - | Number of lines |
|
|
314
|
+
| `maxLength` | `number` | No | - | Max length |
|
|
315
|
+
| `showCharacterCount` | `boolean` | No | `false` | Show character count |
|
|
316
|
+
| `disabled` | `boolean` | No | `false` | Disabled state |
|
|
317
|
+
|
|
318
|
+
## Accessibility
|
|
319
|
+
|
|
320
|
+
- ✅ Screen reader announces label and value
|
|
321
|
+
- ✅ Error state announced to screen readers
|
|
322
|
+
- ✅ Helper text provides additional context
|
|
323
|
+
- ✅ Keyboard type matches input type
|
|
324
|
+
- ✅ Focus management for form navigation
|
|
325
|
+
- ✅ Test ID support for testing
|
|
326
|
+
|
|
327
|
+
## Performance Tips
|
|
328
|
+
|
|
329
|
+
1. **Avoid inline functions**: Use `useCallback` for onChangeText
|
|
330
|
+
2. **Debounce validation**: Don't validate on every keystroke
|
|
331
|
+
3. **Memoize handlers**: Prevent unnecessary re-renders
|
|
332
|
+
4. **Lazy validation**: Validate on blur or submit
|
|
333
|
+
|
|
334
|
+
## Related Components
|
|
335
|
+
|
|
336
|
+
- [`AtomicPicker`](./picker/README.md) - Selection component
|
|
337
|
+
- [`FormField`](../../molecules/FormField/README.md) - Form field wrapper
|
|
338
|
+
- [`AtomicButton`](./button/README.md) - Form submit button
|
|
339
|
+
|
|
340
|
+
## Version History
|
|
341
|
+
|
|
342
|
+
- **2.6.0**: Added character count and password toggle
|
|
343
|
+
- **2.5.0**: Added multi-line support
|
|
344
|
+
- **2.0.0**: Initial release with Material Design 3
|
|
345
|
+
|
|
346
|
+
## License
|
|
341
347
|
|
|
342
348
|
MIT
|