@umituz/react-native-design-system 2.6.34 → 2.6.36

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "2.6.34",
3
+ "version": "2.6.36",
4
4
  "description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive and safe area utilities",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -43,7 +43,15 @@ export interface AtomicInputProps {
43
43
  /** Show character counter */
44
44
  showCharacterCount?: boolean;
45
45
  /** Keyboard type */
46
- keyboardType?: 'default' | 'email-address' | 'numeric' | 'phone-pad' | 'url' | 'number-pad' | 'decimal-pad';
46
+ keyboardType?: 'default' | 'email-address' | 'numeric' | 'phone-pad' | 'url' | 'number-pad' | 'decimal-pad' | 'web-search' | 'twitter' | 'numeric' | 'visible-password';
47
+ /** Return key type */
48
+ returnKeyType?: 'done' | 'go' | 'next' | 'search' | 'send';
49
+ /** Callback when submit button is pressed */
50
+ onSubmitEditing?: () => void;
51
+ /** Blur on submit */
52
+ blurOnSubmit?: boolean;
53
+ /** Auto focus */
54
+ autoFocus?: boolean;
47
55
  /** Auto-capitalize */
48
56
  autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters';
49
57
  /** Auto-correct */
@@ -78,7 +86,7 @@ export interface AtomicInputProps {
78
86
  * - Responsive sizing
79
87
  * - Full accessibility support
80
88
  */
81
- export const AtomicInput: React.FC<AtomicInputProps> = ({
89
+ export const AtomicInput = React.forwardRef<TextInput, AtomicInputProps>(({
82
90
  variant = 'outlined',
83
91
  state = 'default',
84
92
  size = 'md',
@@ -95,6 +103,10 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
95
103
  maxLength,
96
104
  showCharacterCount = false,
97
105
  keyboardType = 'default',
106
+ returnKeyType,
107
+ onSubmitEditing,
108
+ blurOnSubmit,
109
+ autoFocus,
98
110
  autoCapitalize = 'sentences',
99
111
  autoCorrect = true,
100
112
  disabled = false,
@@ -105,7 +117,7 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
105
117
  onFocus,
106
118
  multiline = false,
107
119
  numberOfLines,
108
- }) => {
120
+ }, ref) => {
109
121
  const tokens = useAppDesignTokens();
110
122
 
111
123
  const {
@@ -198,6 +210,7 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
198
210
  )}
199
211
 
200
212
  <TextInput
213
+ ref={ref}
201
214
  value={localValue}
202
215
  onChangeText={handleTextChange}
203
216
  placeholder={placeholder}
@@ -205,6 +218,10 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
205
218
  secureTextEntry={secureTextEntry && !isPasswordVisible}
206
219
  maxLength={maxLength}
207
220
  keyboardType={keyboardType}
221
+ returnKeyType={returnKeyType}
222
+ onSubmitEditing={onSubmitEditing}
223
+ blurOnSubmit={blurOnSubmit}
224
+ autoFocus={autoFocus}
208
225
  autoCapitalize={autoCapitalize}
209
226
  autoCorrect={autoCorrect}
210
227
  editable={!isDisabled}
@@ -274,7 +291,7 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
274
291
  )}
275
292
  </View>
276
293
  );
277
- };
294
+ });
278
295
 
279
296
  const styles = StyleSheet.create({
280
297
  container: {
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import {
3
+ KeyboardAvoidingView,
4
+ Platform,
5
+ StyleSheet,
6
+ type KeyboardAvoidingViewProps,
7
+ } from 'react-native';
8
+
9
+ export interface AtomicKeyboardAvoidingViewProps extends KeyboardAvoidingViewProps {
10
+ /**
11
+ * Optional offset to adjust the position of the content.
12
+ * On iOS, this is often necessary to account for headers, tabs, etc.
13
+ */
14
+ offset?: number;
15
+ }
16
+
17
+ /**
18
+ * AtomicKeyboardAvoidingView - A consistent wrapper for React Native's KeyboardAvoidingView
19
+ *
20
+ * Provides sensible defaults and OS-specific behaviors:
21
+ * - iOS: behavior="padding"
22
+ * - Android: behavior=undefined (handled by windowSoftInputMode="adjustResize")
23
+ */
24
+ export const AtomicKeyboardAvoidingView: React.FC<AtomicKeyboardAvoidingViewProps> = ({
25
+ children,
26
+ behavior,
27
+ style,
28
+ offset = 0,
29
+ ...props
30
+ }) => {
31
+ const defaultBehavior = Platform.OS === 'ios' ? 'padding' : undefined;
32
+
33
+ return (
34
+ <KeyboardAvoidingView
35
+ behavior={behavior ?? defaultBehavior}
36
+ style={[styles.container, style]}
37
+ keyboardVerticalOffset={offset}
38
+ {...props}
39
+ >
40
+ {children}
41
+ </KeyboardAvoidingView>
42
+ );
43
+ };
44
+
45
+ const styles = StyleSheet.create({
46
+ container: {
47
+ flex: 1,
48
+ },
49
+ });
@@ -1,32 +1,52 @@
1
- /**
2
- * AtomicTextArea - Multiline Text Input Component
3
- *
4
- * Atomic Design Level: ATOM
5
- * Purpose: Multiline text input across all apps
6
- */
7
-
8
- import React from 'react';
9
- import { View, TextInput, StyleSheet, ViewStyle } from 'react-native';
1
+ import React, { forwardRef } from 'react';
2
+ import { View, TextInput, StyleSheet, type ViewStyle, type StyleProp, type TextStyle } from 'react-native';
10
3
  import { useAppDesignTokens } from '../theme';
11
4
  import { AtomicText } from './AtomicText';
12
5
 
13
6
  export interface AtomicTextAreaProps {
7
+ /** Text area label */
14
8
  label?: string;
9
+ /** Current value */
15
10
  value?: string;
11
+ /** Value change callback */
16
12
  onChangeText?: (text: string) => void;
13
+ /** Placeholder text */
17
14
  placeholder?: string;
15
+ /** Helper text below input */
18
16
  helperText?: string;
17
+ /** Error message to display */
19
18
  errorText?: string;
19
+ /** Maximum character length */
20
20
  maxLength?: number;
21
+ /** Number of lines (default: 4) */
21
22
  numberOfLines?: number;
23
+ /** Alternative to numberOfLines */
22
24
  rows?: number;
25
+ /** Minimum height override */
23
26
  minHeight?: number;
27
+ /** Disabled state */
24
28
  disabled?: boolean;
25
- style?: ViewStyle;
29
+ /** Container style */
30
+ style?: StyleProp<ViewStyle>;
31
+ /** Input text style */
32
+ inputStyle?: StyleProp<TextStyle>;
33
+ /** Auto focus */
34
+ autoFocus?: boolean;
35
+ /** Return key type */
36
+ returnKeyType?: 'done' | 'go' | 'next' | 'search' | 'send';
37
+ /** Callback when submit button is pressed */
38
+ onSubmitEditing?: () => void;
39
+ /** Blur on submit */
40
+ blurOnSubmit?: boolean;
41
+ /** Test ID */
26
42
  testID?: string;
27
43
  }
28
44
 
29
- export const AtomicTextArea: React.FC<AtomicTextAreaProps> = ({
45
+ /**
46
+ * AtomicTextArea - Multiline Text Input Component
47
+ * Consistent with AtomicInput but optimized for multiline usage.
48
+ */
49
+ export const AtomicTextArea = forwardRef<TextInput, AtomicTextAreaProps>(({
30
50
  label,
31
51
  value,
32
52
  onChangeText,
@@ -39,8 +59,13 @@ export const AtomicTextArea: React.FC<AtomicTextAreaProps> = ({
39
59
  minHeight,
40
60
  disabled = false,
41
61
  style,
62
+ inputStyle,
63
+ autoFocus,
64
+ returnKeyType,
65
+ onSubmitEditing,
66
+ blurOnSubmit,
42
67
  testID,
43
- }) => {
68
+ }, ref) => {
44
69
  const lineCount = numberOfLines ?? rows;
45
70
  const calculatedMinHeight = minHeight ?? lineCount * 24;
46
71
  const tokens = useAppDesignTokens();
@@ -51,20 +76,26 @@ export const AtomicTextArea: React.FC<AtomicTextAreaProps> = ({
51
76
  {label && (
52
77
  <AtomicText
53
78
  type="labelMedium"
54
- style={[styles.label, { color: tokens.colors.textSecondary }]}
79
+ color={hasError ? 'error' : 'secondary'}
80
+ style={styles.label}
55
81
  >
56
82
  {label}
57
83
  </AtomicText>
58
84
  )}
59
85
  <TextInput
86
+ ref={ref}
60
87
  value={value}
61
88
  onChangeText={onChangeText}
62
89
  placeholder={placeholder}
63
- placeholderTextColor={tokens.colors.textTertiary}
90
+ placeholderTextColor={tokens.colors.textSecondary}
64
91
  maxLength={maxLength}
65
92
  numberOfLines={lineCount}
66
93
  multiline
67
94
  editable={!disabled}
95
+ autoFocus={autoFocus}
96
+ returnKeyType={returnKeyType}
97
+ onSubmitEditing={onSubmitEditing}
98
+ blurOnSubmit={blurOnSubmit}
68
99
  textAlignVertical="top"
69
100
  style={[
70
101
  styles.input,
@@ -73,39 +104,57 @@ export const AtomicTextArea: React.FC<AtomicTextAreaProps> = ({
73
104
  borderColor: hasError ? tokens.colors.error : tokens.colors.border,
74
105
  color: tokens.colors.textPrimary,
75
106
  minHeight: calculatedMinHeight,
107
+ padding: tokens.spacing.md,
108
+ borderRadius: tokens.borderRadius.md,
109
+ fontSize: 16,
76
110
  },
111
+ inputStyle,
77
112
  disabled && { opacity: 0.5 },
78
113
  ]}
79
114
  />
80
115
  {(helperText || errorText) && (
81
- <AtomicText
82
- type="bodySmall"
83
- style={[
84
- styles.helperText,
85
- { color: hasError ? tokens.colors.error : tokens.colors.textSecondary },
86
- ]}
87
- >
88
- {errorText || helperText}
89
- </AtomicText>
116
+ <View style={styles.helperRow}>
117
+ <AtomicText
118
+ type="bodySmall"
119
+ color={hasError ? 'error' : 'secondary'}
120
+ style={styles.helperText}
121
+ >
122
+ {errorText || helperText}
123
+ </AtomicText>
124
+ {maxLength && value !== undefined && (
125
+ <AtomicText
126
+ type="labelSmall"
127
+ color="secondary"
128
+ style={styles.characterCount}
129
+ >
130
+ {value.length}/{maxLength}
131
+ </AtomicText>
132
+ )}
133
+ </View>
90
134
  )}
91
135
  </View>
92
136
  );
93
- };
137
+ });
94
138
 
95
139
  const styles = StyleSheet.create({
96
140
  container: {
97
- marginBottom: 16,
141
+ width: '100%',
98
142
  },
99
143
  label: {
100
144
  marginBottom: 8,
101
145
  },
102
146
  input: {
103
147
  borderWidth: 1,
104
- borderRadius: 12,
105
- padding: 12,
106
- fontSize: 16,
107
148
  },
108
- helperText: {
149
+ helperRow: {
150
+ flexDirection: 'row',
151
+ justifyContent: 'space-between',
109
152
  marginTop: 4,
110
153
  },
154
+ helperText: {
155
+ flex: 1,
156
+ },
157
+ characterCount: {
158
+ marginLeft: 8,
159
+ },
111
160
  });
@@ -111,3 +111,6 @@ export { AtomicTouchable, type AtomicTouchableProps } from './AtomicTouchable';
111
111
 
112
112
  // StatusBar
113
113
  export { AtomicStatusBar, type AtomicStatusBarProps } from './status-bar';
114
+
115
+ // Keyboard Avoiding
116
+ export { AtomicKeyboardAvoidingView, type AtomicKeyboardAvoidingViewProps } from './AtomicKeyboardAvoidingView';
@@ -6,9 +6,10 @@
6
6
  */
7
7
 
8
8
  import React, { useMemo } from 'react';
9
- import { View, ScrollView, KeyboardAvoidingView, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
9
+ import { View, ScrollView, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
10
10
  import { useAppDesignTokens } from '../../theme';
11
11
  import { useResponsive } from '../../responsive';
12
+ import { AtomicKeyboardAvoidingView } from '../../atoms';
12
13
 
13
14
  export interface FormLayoutProps {
14
15
  /** Form fields and content */
@@ -103,9 +104,9 @@ export const FormLayout: React.FC<FormLayoutProps> = ({
103
104
  const mainContent = disableKeyboardAvoid ? (
104
105
  scrollableContent
105
106
  ) : (
106
- <KeyboardAvoidingView style={styles.container} behavior="padding">
107
+ <AtomicKeyboardAvoidingView style={styles.container}>
107
108
  {scrollableContent}
108
- </KeyboardAvoidingView>
109
+ </AtomicKeyboardAvoidingView>
109
110
  );
110
111
 
111
112
  return (
@@ -24,10 +24,11 @@
24
24
  */
25
25
 
26
26
  import React, { useMemo } from 'react';
27
- import { View, ScrollView, StyleSheet, KeyboardAvoidingView, type ViewStyle, type RefreshControlProps } from 'react-native';
27
+ import { View, ScrollView, StyleSheet, type ViewStyle, type RefreshControlProps } from 'react-native';
28
28
  import { SafeAreaView, useSafeAreaInsets, type Edge } from '../../safe-area';
29
29
  import { useAppDesignTokens } from '../../theme';
30
30
  import { getScreenLayoutConfig } from '../../responsive/responsiveLayout';
31
+ import { AtomicKeyboardAvoidingView } from '../../atoms';
31
32
 
32
33
  /**
33
34
  * NOTE: This component now works in conjunction with the SafeAreaProvider
@@ -206,12 +207,11 @@ export const ScreenLayout: React.FC<ScreenLayoutProps> = ({
206
207
  const ContentWrapper: React.FC<{ children: React.ReactNode }> = ({ children: wrapperChildren }) => {
207
208
  if (keyboardAvoiding) {
208
209
  return (
209
- <KeyboardAvoidingView
210
+ <AtomicKeyboardAvoidingView
210
211
  style={styles.keyboardAvoidingView}
211
- behavior="padding"
212
212
  >
213
213
  {wrapperChildren}
214
- </KeyboardAvoidingView>
214
+ </AtomicKeyboardAvoidingView>
215
215
  );
216
216
  }
217
217
  return <>{wrapperChildren}</>;