@momo-kits/foundation 1.0.0 → 1.0.1

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 (62) hide show
  1. package/ActivityIndicator.tsx +244 -0
  2. package/Button/index.tsx +94 -164
  3. package/Button/types.ts +12 -3
  4. package/CheckBox/index.tsx +57 -0
  5. package/CheckBox/styles.ts +14 -0
  6. package/CheckBox/types.ts +7 -0
  7. package/Consts/colors+spacing+radius.ts +6 -4
  8. package/Consts/index.ts +4 -73
  9. package/Consts/styles.ts +1 -1
  10. package/Consts/theme.ts +65 -0
  11. package/ContentLoader/index.tsx +8 -11
  12. package/Icon/index.tsx +11 -11
  13. package/Icon/types.ts +1 -4
  14. package/IconButton/index.tsx +52 -72
  15. package/IconButton/styles.ts +19 -0
  16. package/IconButton/types.ts +1 -2
  17. package/Image/index.tsx +19 -18
  18. package/Image/types.ts +0 -1
  19. package/Input/TextArea.tsx +202 -0
  20. package/Input/index.tsx +200 -0
  21. package/Input/styles.ts +92 -0
  22. package/Input/types.ts +23 -0
  23. package/Layout/GridSystem.tsx +109 -0
  24. package/Layout/ScreenContainer.tsx +78 -0
  25. package/Layout/ScreenSection.tsx +104 -0
  26. package/Layout/SectionItem.tsx +60 -0
  27. package/Layout/index.ts +11 -5
  28. package/Layout/types.ts +6 -33
  29. package/Layout/utils.ts +55 -23
  30. package/Navigation/Components.tsx +16 -8
  31. package/Navigation/ModalScreen.tsx +35 -25
  32. package/Navigation/Navigation.ts +2 -2
  33. package/Navigation/NavigationButton.tsx +5 -3
  34. package/Navigation/NavigationContainer.tsx +59 -17
  35. package/Navigation/StackScreen.tsx +8 -2
  36. package/Navigation/index.ts +5 -3
  37. package/Navigation/types.ts +53 -36
  38. package/Navigation/utils.tsx +20 -18
  39. package/Radio/index.tsx +34 -0
  40. package/Radio/styles.ts +11 -0
  41. package/Radio/types.ts +7 -0
  42. package/Switch/index.tsx +37 -0
  43. package/Switch/styles.ts +23 -0
  44. package/Switch/types.ts +5 -0
  45. package/Text/index.tsx +36 -120
  46. package/Text/styles.ts +24 -23
  47. package/Text/types.ts +2 -0
  48. package/index.ts +18 -1
  49. package/package.json +1 -1
  50. package/publish.sh +8 -6
  51. package/CheckBox/index.js +0 -74
  52. package/CheckBox/styles.js +0 -3
  53. package/Layout/Row.tsx +0 -42
  54. package/Layout/Screen.tsx +0 -68
  55. package/Layout/Section.tsx +0 -30
  56. package/Layout/View.tsx +0 -84
  57. package/Layout/styles.ts +0 -24
  58. package/Navigation/ScreenContainer.tsx +0 -38
  59. package/SizedBox/index.js +0 -23
  60. package/SizedBox/styles.js +0 -7
  61. package/TextInput/index.js +0 -225
  62. package/TextInput/styles.js +0 -55
@@ -0,0 +1,202 @@
1
+ import React, {FC, useContext, useRef, useState} from 'react';
2
+ import {
3
+ NativeSyntheticEvent,
4
+ TextInput,
5
+ TextInputFocusEventData,
6
+ TouchableOpacity,
7
+ View,
8
+ } from 'react-native';
9
+ import styles from './styles';
10
+ import {Image} from '../Image';
11
+ import {Text} from '../Text';
12
+ import {TextAreaProps} from './types';
13
+ import {ApplicationContext} from '../Navigation';
14
+ import {Colors} from '../Consts';
15
+
16
+ const errorMessageIcon =
17
+ 'https://img.mservice.com.vn/app/img/kits/error_mess_icon.png';
18
+ const ic_clear =
19
+ 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_close_circle_full.png';
20
+ const DEFAULT_HEIGHT = 112;
21
+ const MAX_LENGTH = 300;
22
+ const TextArea: FC<TextAreaProps> = props => {
23
+ const {theme} = useContext(ApplicationContext);
24
+ const {
25
+ errorMessage,
26
+ onChangeText,
27
+ floatingIconColor,
28
+ floatingIcon,
29
+ floatingValue,
30
+ onFocus,
31
+ onBlur,
32
+ disabled,
33
+ value,
34
+ defaultValue,
35
+ height,
36
+ placeholder,
37
+ maxLength,
38
+ } = props;
39
+
40
+ const [focused, setFocused] = useState(false);
41
+ const [inputValue, setInputValue] = useState(defaultValue ?? '');
42
+ const inputRef = useRef<any>(null);
43
+
44
+ const onClearText = () => {
45
+ inputRef?.current?.clear();
46
+ };
47
+
48
+ const _onChangeText = (text: string) => {
49
+ onChangeText?.(text);
50
+ setInputValue(text);
51
+ };
52
+
53
+ const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
54
+ setFocused(true);
55
+ onFocus?.(e);
56
+ };
57
+
58
+ const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
59
+ setFocused(false);
60
+ onBlur?.(e);
61
+ };
62
+ const getBorderColor = () => {
63
+ let borderColor = theme.colors.border.default;
64
+
65
+ if (focused) {
66
+ borderColor = theme.colors.primary;
67
+ }
68
+
69
+ if (!!errorMessage) {
70
+ borderColor = theme.colors.error.primary;
71
+ }
72
+
73
+ if (disabled) {
74
+ borderColor = theme.colors.border.disable;
75
+ }
76
+
77
+ return {borderColor};
78
+ };
79
+
80
+ const renderFloatingView = () => {
81
+ if (floatingValue) {
82
+ let floatingTextColor = theme.colors.text.hint;
83
+ let floatingIconTintColor = floatingIconColor;
84
+ if (disabled) {
85
+ floatingTextColor = theme.colors.text.disable;
86
+ floatingIconTintColor = theme.colors.text.disable;
87
+ }
88
+
89
+ return (
90
+ <View
91
+ style={[
92
+ styles.floatingView,
93
+ {
94
+ backgroundColor: Colors.black_01,
95
+ zIndex: 10,
96
+ },
97
+ ]}>
98
+ <Text color={floatingTextColor} typography={'label_s'}>
99
+ {floatingValue}
100
+ </Text>
101
+ {floatingIcon && (
102
+ <Image
103
+ tintColor={floatingIconTintColor}
104
+ source={{uri: floatingIcon}}
105
+ style={styles.floatingIcon}
106
+ />
107
+ )}
108
+ </View>
109
+ );
110
+ }
111
+ };
112
+
113
+ const renderCountingView = () => {
114
+ return (
115
+ <View style={styles.countingView}>
116
+ <Text color={theme.colors.text.hint} typography={'description_xs'}>
117
+ {`${inputValue.length}/${maxLength}`}
118
+ </Text>
119
+ </View>
120
+ );
121
+ };
122
+ const renderInputView = () => {
123
+ const disabledColor = theme.colors.text.disable;
124
+ let textColor = theme.colors.text.default;
125
+ let placeholderColor = theme.colors.text.hint;
126
+
127
+ if (disabled) {
128
+ textColor = disabledColor;
129
+ placeholderColor = disabledColor;
130
+ }
131
+
132
+ return (
133
+ <View
134
+ style={[
135
+ getBorderColor(),
136
+ styles.textAreaWrapper,
137
+ {height: height || DEFAULT_HEIGHT},
138
+ ]}>
139
+ {renderFloatingView()}
140
+ <View style={styles.rowArea}>
141
+ <View style={styles.textAreaView}>
142
+ <TextInput
143
+ ref={inputRef}
144
+ editable={!disabled}
145
+ textAlignVertical="top"
146
+ style={[
147
+ styles.textArea,
148
+ {
149
+ color: textColor,
150
+ },
151
+ ]}
152
+ maxLength={maxLength}
153
+ multiline={true}
154
+ value={value}
155
+ onChangeText={_onChangeText}
156
+ onFocus={_onFocus}
157
+ onBlur={_onBlur}
158
+ placeholder={placeholder}
159
+ selectionColor={theme.colors.primary}
160
+ placeholderTextColor={placeholderColor}
161
+ />
162
+ </View>
163
+ {focused && (
164
+ <TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
165
+ <Image
166
+ tintColor={theme.colors.text.hint}
167
+ source={{uri: ic_clear}}
168
+ style={styles.iconClose}
169
+ />
170
+ </TouchableOpacity>
171
+ )}
172
+ </View>
173
+ {renderCountingView()}
174
+ </View>
175
+ );
176
+ };
177
+
178
+ const renderErrorView = () => {
179
+ if (errorMessage) {
180
+ return (
181
+ <View style={styles.errorView}>
182
+ <Image style={styles.errorIcon} source={{uri: errorMessageIcon}} />
183
+ <Text color={theme.colors.error.primary} typography={'description_s'}>
184
+ {errorMessage}
185
+ </Text>
186
+ </View>
187
+ );
188
+ }
189
+ };
190
+ return (
191
+ <View style={styles.wrapper}>
192
+ {renderInputView()}
193
+ {renderErrorView()}
194
+ </View>
195
+ );
196
+ };
197
+
198
+ TextArea.defaultProps = {
199
+ maxLength: MAX_LENGTH,
200
+ };
201
+
202
+ export default TextArea;
@@ -0,0 +1,200 @@
1
+ import React, {FC, useContext, useRef, useState} from 'react';
2
+ import {
3
+ NativeSyntheticEvent,
4
+ TextInput,
5
+ TextInputFocusEventData,
6
+ TouchableOpacity,
7
+ View,
8
+ } from 'react-native';
9
+ import {ApplicationContext} from '../Navigation';
10
+ import styles from './styles';
11
+ import {InputProps} from './types';
12
+ import TextArea from './TextArea';
13
+ import {Text} from '../Text';
14
+ import {Image} from '../Image';
15
+ import {Colors} from '../Consts';
16
+
17
+ const errorMessageIcon =
18
+ 'https://img.mservice.com.vn/app/img/kits/error_mess_icon.png';
19
+ const ic_clear =
20
+ 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_close_circle_full.png';
21
+ const MAX_LENGTH = 100;
22
+ const Input: FC<InputProps> = props => {
23
+ const {theme} = useContext(ApplicationContext);
24
+ const {
25
+ value,
26
+ onChangeText,
27
+ floatingValue,
28
+ floatingIcon,
29
+ size,
30
+ placeholder,
31
+ onBlur,
32
+ onFocus,
33
+ errorMessage,
34
+ icon,
35
+ disabled,
36
+ floatingIconColor,
37
+ iconColor,
38
+ } = props;
39
+
40
+ const [focused, setFocused] = useState(false);
41
+ const inputRef = useRef(null);
42
+
43
+ const onClearText = () => {
44
+ inputRef?.current?.clear();
45
+ };
46
+
47
+ const _onChangeText = (text: string) => {
48
+ onChangeText?.(text);
49
+ };
50
+ const getSizeStyle = () => {
51
+ if (size === 'small') {
52
+ return styles.smallContainer;
53
+ }
54
+ return styles.container;
55
+ };
56
+
57
+ const getBorderColor = () => {
58
+ let borderColor = theme.colors.border.default;
59
+
60
+ if (focused) {
61
+ borderColor = theme.colors.primary;
62
+ }
63
+
64
+ if (!!errorMessage) {
65
+ borderColor = theme.colors.error.primary;
66
+ }
67
+
68
+ if (disabled) {
69
+ borderColor = theme.colors.border.disable;
70
+ }
71
+
72
+ return {borderColor};
73
+ };
74
+
75
+ const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
76
+ setFocused(true);
77
+ onFocus?.(e);
78
+ };
79
+
80
+ const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
81
+ setFocused(false);
82
+ onBlur?.(e);
83
+ };
84
+
85
+ const renderFloatingView = () => {
86
+ if (floatingValue) {
87
+ let floatingTextColor = theme.colors.text.hint;
88
+ let floatingIconTintColor = floatingIconColor;
89
+ if (disabled) {
90
+ floatingTextColor = theme.colors.text.disable;
91
+ floatingIconTintColor = theme.colors.text.disable;
92
+ }
93
+
94
+ return (
95
+ <View
96
+ style={[
97
+ styles.floatingView,
98
+ {
99
+ backgroundColor: Colors.black_01,
100
+ zIndex: 10,
101
+ },
102
+ ]}>
103
+ <Text color={floatingTextColor} typography={'label_s'}>
104
+ {floatingValue}
105
+ </Text>
106
+ {floatingIcon && (
107
+ <Image
108
+ tintColor={floatingIconTintColor}
109
+ source={{uri: floatingIcon}}
110
+ style={styles.floatingIcon}
111
+ />
112
+ )}
113
+ </View>
114
+ );
115
+ }
116
+ };
117
+
118
+ const renderInputView = () => {
119
+ const disabledColor = theme.colors.text.disable;
120
+ let textColor = theme.colors.text.default;
121
+ let placeholderColor = theme.colors.text.hint;
122
+ let iconTintColor = iconColor;
123
+
124
+ if (disabled) {
125
+ textColor = disabledColor;
126
+ placeholderColor = disabledColor;
127
+ iconTintColor = disabledColor;
128
+ }
129
+
130
+ return (
131
+ <View style={[getSizeStyle(), getBorderColor(), styles.inputWrapper]}>
132
+ {renderFloatingView()}
133
+ <View style={styles.inputView}>
134
+ <TextInput
135
+ editable={!disabled}
136
+ textAlignVertical="top"
137
+ ref={inputRef}
138
+ style={[
139
+ styles.input,
140
+ {
141
+ color: textColor,
142
+ },
143
+ ]}
144
+ value={value}
145
+ onChangeText={_onChangeText}
146
+ onFocus={_onFocus}
147
+ onBlur={_onBlur}
148
+ placeholder={placeholder}
149
+ selectionColor={theme.colors.primary}
150
+ placeholderTextColor={placeholderColor}
151
+ />
152
+ </View>
153
+ <View style={styles.iconView}>
154
+ {focused && (
155
+ <TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
156
+ <Image
157
+ tintColor={theme.colors.text.hint}
158
+ source={{uri: ic_clear}}
159
+ style={styles.iconClose}
160
+ />
161
+ </TouchableOpacity>
162
+ )}
163
+ {icon && (
164
+ <Image
165
+ tintColor={iconTintColor}
166
+ source={{uri: icon}}
167
+ style={styles.icon}
168
+ />
169
+ )}
170
+ </View>
171
+ </View>
172
+ );
173
+ };
174
+
175
+ const renderErrorView = () => {
176
+ if (errorMessage) {
177
+ return (
178
+ <View style={styles.errorView}>
179
+ <Image style={styles.errorIcon} source={{uri: errorMessageIcon}} />
180
+ <Text color={theme.colors.error.primary} typography={'description_s'}>
181
+ {errorMessage}
182
+ </Text>
183
+ </View>
184
+ );
185
+ }
186
+ };
187
+
188
+ return (
189
+ <View style={styles.wrapper}>
190
+ {renderInputView()}
191
+ {renderErrorView()}
192
+ </View>
193
+ );
194
+ };
195
+
196
+ Input.defaultProps = {
197
+ size: 'large',
198
+ maxLength: MAX_LENGTH,
199
+ };
200
+ export {Input, TextArea};
@@ -0,0 +1,92 @@
1
+ import {StyleSheet} from 'react-native';
2
+ import {Radius, Spacing} from '../Consts';
3
+
4
+ export default StyleSheet.create({
5
+ //input style
6
+ input: {width: '100%', paddingLeft: Spacing.M, height: '100%'},
7
+ wrapper: {
8
+ marginVertical: Spacing.M,
9
+ width: '100%',
10
+ },
11
+ container: {
12
+ borderWidth: 1,
13
+ borderRadius: Radius.S,
14
+ marginBottom: Spacing.XS,
15
+ height: 56,
16
+ paddingVertical: 8,
17
+ },
18
+ smallContainer: {
19
+ borderRadius: Radius.S,
20
+ borderWidth: 1,
21
+ marginBottom: Spacing.XS,
22
+ height: 48,
23
+ },
24
+ floatingView: {
25
+ position: 'absolute',
26
+ top: -10,
27
+ left: Spacing.S,
28
+ paddingHorizontal: Spacing.S,
29
+ flexDirection: 'row',
30
+ },
31
+ floatingIcon: {width: 16, height: 16, marginLeft: Spacing.XS},
32
+ errorIcon: {width: 16, height: 16, marginRight: Spacing.XS},
33
+ errorView: {
34
+ flexDirection: 'row',
35
+ alignItems: 'center',
36
+ },
37
+ inputView: {
38
+ justifyContent: 'space-between',
39
+ flex: 1,
40
+ },
41
+ iconClose: {
42
+ width: 16,
43
+ height: 16,
44
+ },
45
+ iconView: {
46
+ flexDirection: 'row',
47
+ alignItems: 'center',
48
+ marginLeft: Spacing.XS,
49
+ marginRight: Spacing.M,
50
+ },
51
+ icon: {
52
+ width: 24,
53
+ height: 24,
54
+ },
55
+ iconWrapper: {
56
+ width: 24,
57
+ height: 24,
58
+ justifyContent: 'center',
59
+ alignItems: 'center',
60
+ },
61
+ inputWrapper: {
62
+ flexDirection: 'row',
63
+ },
64
+
65
+ //text area style
66
+ textAreaView: {
67
+ flex: 1,
68
+ },
69
+ textArea: {
70
+ width: '100%',
71
+ flex: 1,
72
+ paddingRight: Spacing.XS,
73
+ },
74
+ textAreaWrapper: {
75
+ borderWidth: 1,
76
+ borderRadius: Radius.S,
77
+ paddingVertical: Spacing.S,
78
+ paddingLeft: Spacing.M,
79
+ paddingRight: Spacing.S,
80
+ },
81
+ countingView: {
82
+ width: '100%',
83
+ alignItems: 'flex-end',
84
+ paddingRight: Spacing.XS,
85
+ },
86
+ rowArea: {
87
+ flexDirection: 'row',
88
+ width: '100%',
89
+ flex: 1,
90
+ marginBottom: Spacing.XS,
91
+ },
92
+ });
package/Input/types.ts ADDED
@@ -0,0 +1,23 @@
1
+ import {TextInputProps} from 'react-native';
2
+
3
+ export type InputSize = 'small' | 'large';
4
+ export interface InputProps extends TextInputProps {
5
+ size: InputSize;
6
+ floatingValue: string;
7
+ floatingIcon: string;
8
+ errorMessage: string;
9
+ icon: string;
10
+ disabled: boolean;
11
+ floatingIconColor: string;
12
+ iconColor: string;
13
+ }
14
+
15
+ export interface TextAreaProps extends TextInputProps {
16
+ errorMessage: string;
17
+ floatingValue: string;
18
+ floatingIcon: string;
19
+ disabled: boolean;
20
+ floatingIconColor: string;
21
+ placeholder: string;
22
+ height: number;
23
+ }
@@ -0,0 +1,109 @@
1
+ import React, {useContext} from 'react';
2
+ import {useSafeAreaInsets} from 'react-native-safe-area-context';
3
+ import {StyleSheet, View} from 'react-native';
4
+ import {ApplicationContext} from '../Navigation';
5
+ import {useGridSystem} from './index';
6
+ import {Colors, Spacing} from '../Consts';
7
+
8
+ const GridSystem: React.FC<any> = () => {
9
+ const {theme} = useContext(ApplicationContext);
10
+ const grid = useGridSystem();
11
+ const insets = useSafeAreaInsets();
12
+
13
+ const list = [];
14
+ for (let i = 1; i <= grid.numberOfColumns; i++) {
15
+ list.push(i);
16
+ }
17
+
18
+ return (
19
+ <>
20
+ <View
21
+ pointerEvents="none"
22
+ style={[
23
+ styles.gridContainer,
24
+ insets,
25
+ {
26
+ borderColor: theme.colors.error.primary,
27
+ marginHorizontal: grid.screenPadding,
28
+ },
29
+ ]}>
30
+ {list.map((i, index) => {
31
+ return (
32
+ <View style={{flexDirection: 'row'}} key={index.toString()}>
33
+ {index != -0 && <View style={{width: grid.gutterSize}} />}
34
+ <View
35
+ key={index.toString()}
36
+ pointerEvents="none"
37
+ style={[
38
+ styles.gridColumn,
39
+ {
40
+ width: grid.sizePerSpan,
41
+ },
42
+ ]}
43
+ />
44
+ </View>
45
+ );
46
+ })}
47
+ </View>
48
+ <View pointerEvents="none" style={styles.dangerLeftContainer} />
49
+ <View pointerEvents="none" style={styles.dangerRightContainer} />
50
+ <View
51
+ pointerEvents="none"
52
+ style={[styles.dangerTopContainer, {height: insets.top}]}
53
+ />
54
+ <View
55
+ pointerEvents="none"
56
+ style={[styles.dangerBottomContainer, {height: insets.bottom}]}
57
+ />
58
+ </>
59
+ );
60
+ };
61
+
62
+ const styles = StyleSheet.create({
63
+ gridContainer: {
64
+ position: 'absolute',
65
+ top: 0,
66
+ bottom: 0,
67
+ left: 0,
68
+ right: 0,
69
+ flexDirection: 'row',
70
+ borderWidth: 1,
71
+ },
72
+ gridColumn: {
73
+ height: '100%',
74
+ opacity: 0.2,
75
+ backgroundColor: Colors.blue_07,
76
+ },
77
+ dangerTopContainer: {
78
+ opacity: 0.2,
79
+ backgroundColor: Colors.red_03,
80
+ width: '100%',
81
+ top: 0,
82
+ position: 'absolute',
83
+ },
84
+ dangerBottomContainer: {
85
+ opacity: 0.2,
86
+ backgroundColor: Colors.red_03,
87
+ width: '100%',
88
+ bottom: 0,
89
+ position: 'absolute',
90
+ },
91
+ dangerLeftContainer: {
92
+ opacity: 0.2,
93
+ backgroundColor: Colors.red_03,
94
+ width: Spacing.M,
95
+ height: '100%',
96
+ left: 0,
97
+ position: 'absolute',
98
+ },
99
+ dangerRightContainer: {
100
+ opacity: 0.2,
101
+ backgroundColor: Colors.red_03,
102
+ width: Spacing.M,
103
+ height: '100%',
104
+ right: 0,
105
+ position: 'absolute',
106
+ },
107
+ });
108
+
109
+ export default GridSystem;
@@ -0,0 +1,78 @@
1
+ import {KeyboardAvoidingView, Platform, ScrollView, View} from 'react-native';
2
+ import {useHeaderHeight} from '@react-navigation/stack';
3
+ import {SafeAreaView} from 'react-native-safe-area-context';
4
+ import React, {useContext, useLayoutEffect} from 'react';
5
+ import {ScreenContainerProps} from '../Navigation/types';
6
+ import {ApplicationContext} from '../Navigation';
7
+ import {Spacing, Styles} from '../Consts';
8
+ import {ScreenSection, validateChildren} from './index';
9
+
10
+ const ScreenContainer: React.FC<ScreenContainerProps> = ({
11
+ children,
12
+ navigation,
13
+ options,
14
+ edges,
15
+ enableKeyboardAvoidingView,
16
+ scrollable,
17
+ }) => {
18
+ let Component: any = View;
19
+ const {theme} = useContext(ApplicationContext);
20
+ const headerHeight = useHeaderHeight();
21
+ if (scrollable) {
22
+ Component = ScrollView;
23
+ }
24
+
25
+ useLayoutEffect(() => {
26
+ if (options) {
27
+ navigation.setOptions(options);
28
+ }
29
+ }, [navigation, options]);
30
+
31
+ const renderContent = () => {
32
+ const results = validateChildren(children, ScreenSection);
33
+ if (Array.isArray(results)) {
34
+ return results.map((item, index) => {
35
+ return (
36
+ <View
37
+ key={`ScreenSection${index}`}
38
+ style={{
39
+ paddingTop: index != 0 ? 12 : Spacing.S,
40
+ flex: item.props?.expanded ? 1 : undefined,
41
+ }}>
42
+ {item}
43
+ </View>
44
+ );
45
+ });
46
+ }
47
+ return results;
48
+ };
49
+
50
+ return (
51
+ <SafeAreaView
52
+ style={[
53
+ Styles.flex,
54
+ {
55
+ backgroundColor: theme.colors.background.default,
56
+ },
57
+ ]}
58
+ edges={edges}>
59
+ <KeyboardAvoidingView
60
+ style={Styles.flex}
61
+ keyboardVerticalOffset={headerHeight}
62
+ enabled={enableKeyboardAvoidingView}
63
+ behavior={Platform.select({
64
+ ios: 'padding',
65
+ android: undefined,
66
+ })}>
67
+ <Component style={Styles.flex}>{renderContent()}</Component>
68
+ </KeyboardAvoidingView>
69
+ </SafeAreaView>
70
+ );
71
+ };
72
+
73
+ ScreenContainer.defaultProps = {
74
+ edges: ['bottom', 'left', 'right'],
75
+ enableKeyboardAvoidingView: false,
76
+ scrollable: false,
77
+ };
78
+ export default ScreenContainer;