@momo-kits/foundation 1.0.1 → 1.0.3
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/Button/index.tsx +39 -22
- package/CheckBox/index.tsx +10 -4
- package/CheckBox/types.ts +6 -3
- package/Consts/theme.ts +57 -1
- package/ContentLoader/index.tsx +1 -2
- package/Icon/index.tsx +3 -0
- package/IconButton/index.tsx +24 -4
- package/Image/index.tsx +4 -4
- package/Input/Input.tsx +161 -0
- package/Input/TextArea.tsx +15 -55
- package/Input/common.tsx +70 -0
- package/Input/index.tsx +23 -197
- package/Layout/GridSystem.tsx +1 -1
- package/Layout/ScreenContainer.tsx +6 -0
- package/Layout/ScreenSection.tsx +13 -0
- package/Layout/SectionItem.tsx +3 -0
- package/Layout/utils.ts +14 -0
- package/Navigation/Components.tsx +35 -10
- package/Navigation/ModalScreen.tsx +53 -38
- package/Navigation/Navigation.ts +3 -0
- package/Navigation/NavigationButton.tsx +5 -2
- package/Navigation/NavigationContainer.tsx +8 -46
- package/Navigation/StackScreen.tsx +2 -2
- package/Navigation/types.ts +20 -3
- package/Navigation/utils.tsx +30 -9
- package/Playground/index.tsx +132 -0
- package/Playground/styles.ts +16 -0
- package/Playground/types.ts +15 -0
- package/Popup/PopupNotify.tsx +210 -0
- package/Popup/PopupPromotion.tsx +66 -0
- package/Popup/index.tsx +4 -0
- package/Popup/types.ts +23 -0
- package/Radio/index.tsx +13 -5
- package/Radio/styles.ts +1 -0
- package/Radio/types.ts +3 -3
- package/Switch/index.tsx +2 -4
- package/Switch/types.ts +2 -2
- package/Text/index.tsx +9 -7
- package/Text/styles.ts +3 -3
- package/Text/types.ts +5 -14
- package/index.ts +6 -6
- package/package.json +3 -4
- package/publish.sh +6 -8
- package/ActivityIndicator.tsx +0 -244
- package/Button/types.ts +0 -27
- package/IconButton/types.ts +0 -16
- package/Input/types.ts +0 -23
package/Input/common.tsx
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {View} from 'react-native';
|
|
2
|
+
import styles from './styles';
|
|
3
|
+
import {Text} from '../Text';
|
|
4
|
+
import {Image} from '../Image';
|
|
5
|
+
import React, {useContext} from 'react';
|
|
6
|
+
import {ApplicationContext} from '../Navigation';
|
|
7
|
+
|
|
8
|
+
export const getBorderColor = (
|
|
9
|
+
focused: boolean,
|
|
10
|
+
errorMessage?: string,
|
|
11
|
+
disabled?: boolean,
|
|
12
|
+
) => {
|
|
13
|
+
const {theme} = useContext(ApplicationContext);
|
|
14
|
+
|
|
15
|
+
let borderColor = theme.colors.border.default;
|
|
16
|
+
|
|
17
|
+
if (focused) {
|
|
18
|
+
borderColor = theme.colors.primary;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!!errorMessage) {
|
|
22
|
+
borderColor = theme.colors.error.primary;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (disabled) {
|
|
26
|
+
borderColor = theme.colors.border.disable;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {borderColor};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const renderFloatingView = (
|
|
33
|
+
floatingValue?: string,
|
|
34
|
+
floatingIconColor?: string,
|
|
35
|
+
disabled?: boolean,
|
|
36
|
+
floatingIcon?: string,
|
|
37
|
+
) => {
|
|
38
|
+
const {theme} = useContext(ApplicationContext);
|
|
39
|
+
|
|
40
|
+
if (floatingValue) {
|
|
41
|
+
let floatingTextColor = theme.colors.text.hint;
|
|
42
|
+
let floatingIconTintColor = floatingIconColor;
|
|
43
|
+
if (disabled) {
|
|
44
|
+
floatingTextColor = theme.colors.text.disable;
|
|
45
|
+
floatingIconTintColor = theme.colors.text.disable;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<View
|
|
50
|
+
style={[
|
|
51
|
+
styles.floatingView,
|
|
52
|
+
{
|
|
53
|
+
backgroundColor: theme.colors.background.surface,
|
|
54
|
+
zIndex: 10,
|
|
55
|
+
},
|
|
56
|
+
]}>
|
|
57
|
+
<Text color={floatingTextColor} typography={'label_s'}>
|
|
58
|
+
{floatingValue}
|
|
59
|
+
</Text>
|
|
60
|
+
{floatingIcon && (
|
|
61
|
+
<Image
|
|
62
|
+
tintColor={floatingIconTintColor}
|
|
63
|
+
source={{uri: floatingIcon}}
|
|
64
|
+
style={styles.floatingIcon}
|
|
65
|
+
/>
|
|
66
|
+
)}
|
|
67
|
+
</View>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
};
|
package/Input/index.tsx
CHANGED
|
@@ -1,200 +1,26 @@
|
|
|
1
|
-
import
|
|
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';
|
|
1
|
+
import Input from './Input';
|
|
12
2
|
import TextArea from './TextArea';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
import {TextInputProps} from 'react-native';
|
|
4
|
+
|
|
5
|
+
export interface InputProps extends TextInputProps {
|
|
6
|
+
size?: 'small' | 'large';
|
|
7
|
+
floatingValue?: string;
|
|
8
|
+
floatingIcon?: string;
|
|
9
|
+
errorMessage?: string;
|
|
10
|
+
icon?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
floatingIconColor?: string;
|
|
13
|
+
iconColor?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TextAreaProps extends TextInputProps {
|
|
17
|
+
errorMessage: string;
|
|
18
|
+
floatingValue: string;
|
|
19
|
+
floatingIcon: string;
|
|
20
|
+
disabled: boolean;
|
|
21
|
+
floatingIconColor: string;
|
|
22
|
+
placeholder: string;
|
|
23
|
+
height: number;
|
|
24
|
+
}
|
|
16
25
|
|
|
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
26
|
export {Input, TextArea};
|
package/Layout/GridSystem.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import {ApplicationContext} from '../Navigation';
|
|
|
5
5
|
import {useGridSystem} from './index';
|
|
6
6
|
import {Colors, Spacing} from '../Consts';
|
|
7
7
|
|
|
8
|
-
const GridSystem: React.FC
|
|
8
|
+
const GridSystem: React.FC = () => {
|
|
9
9
|
const {theme} = useContext(ApplicationContext);
|
|
10
10
|
const grid = useGridSystem();
|
|
11
11
|
const insets = useSafeAreaInsets();
|
|
@@ -22,12 +22,18 @@ const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
|
22
22
|
Component = ScrollView;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* handle set options for navigation if have props options
|
|
27
|
+
*/
|
|
25
28
|
useLayoutEffect(() => {
|
|
26
29
|
if (options) {
|
|
27
30
|
navigation.setOptions(options);
|
|
28
31
|
}
|
|
29
32
|
}, [navigation, options]);
|
|
30
33
|
|
|
34
|
+
/**
|
|
35
|
+
* build content for screen
|
|
36
|
+
*/
|
|
31
37
|
const renderContent = () => {
|
|
32
38
|
const results = validateChildren(children, ScreenSection);
|
|
33
39
|
if (Array.isArray(results)) {
|
package/Layout/ScreenSection.tsx
CHANGED
|
@@ -7,6 +7,9 @@ import {ScreenSectionProps} from './types';
|
|
|
7
7
|
const ScreenSection: React.FC<ScreenSectionProps> = ({children}) => {
|
|
8
8
|
const grid = useGridSystem();
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* render overlay only dev mode
|
|
12
|
+
*/
|
|
10
13
|
const renderOverlay = () => {
|
|
11
14
|
return (
|
|
12
15
|
<View
|
|
@@ -24,6 +27,12 @@ const ScreenSection: React.FC<ScreenSectionProps> = ({children}) => {
|
|
|
24
27
|
);
|
|
25
28
|
};
|
|
26
29
|
|
|
30
|
+
/**
|
|
31
|
+
* build a row view in side session
|
|
32
|
+
* @param rows
|
|
33
|
+
* @param cursor
|
|
34
|
+
* @param endRow
|
|
35
|
+
*/
|
|
27
36
|
const addRowView = (
|
|
28
37
|
rows: any[],
|
|
29
38
|
cursor: number = 0,
|
|
@@ -50,6 +59,10 @@ const ScreenSection: React.FC<ScreenSectionProps> = ({children}) => {
|
|
|
50
59
|
);
|
|
51
60
|
};
|
|
52
61
|
|
|
62
|
+
/**
|
|
63
|
+
* render children content for session
|
|
64
|
+
* @param children
|
|
65
|
+
*/
|
|
53
66
|
const renderView = (
|
|
54
67
|
children: any,
|
|
55
68
|
): React.ReactElement | React.ReactElement[] => {
|
package/Layout/SectionItem.tsx
CHANGED
package/Layout/utils.ts
CHANGED
|
@@ -2,6 +2,10 @@ import {Alert, Dimensions} from 'react-native';
|
|
|
2
2
|
import React, {ReactElement} from 'react';
|
|
3
3
|
import {GutterSize, NumberOfColumns, ScreenPadding} from '../Consts';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* hook component for use grid system
|
|
7
|
+
* @param useMargin
|
|
8
|
+
*/
|
|
5
9
|
const useGridSystem = (useMargin: boolean = true) => {
|
|
6
10
|
const isDevMode = false;
|
|
7
11
|
const gutterSize = GutterSize;
|
|
@@ -12,6 +16,10 @@ const useGridSystem = (useMargin: boolean = true) => {
|
|
|
12
16
|
const totalGutterSize = gutterSize * (numberOfColumns - 1);
|
|
13
17
|
const sizePerSpan = (parentWidth - totalGutterSize) / numberOfColumns;
|
|
14
18
|
|
|
19
|
+
/**
|
|
20
|
+
* get size of element with number span
|
|
21
|
+
* @param span
|
|
22
|
+
*/
|
|
15
23
|
const getSizeSpan = (span: number = numberOfColumns): number => {
|
|
16
24
|
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
17
25
|
};
|
|
@@ -25,6 +33,12 @@ const useGridSystem = (useMargin: boolean = true) => {
|
|
|
25
33
|
getSizeSpan,
|
|
26
34
|
};
|
|
27
35
|
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* validate children type
|
|
39
|
+
* @param children
|
|
40
|
+
* @param childrenType
|
|
41
|
+
*/
|
|
28
42
|
const validateChildren = (
|
|
29
43
|
children:
|
|
30
44
|
| React.ReactElement<any, string | React.JSXElementConstructor<any>>
|
|
@@ -3,6 +3,8 @@ import {StatusBar, StyleSheet, View} from 'react-native';
|
|
|
3
3
|
import {ApplicationContext, NavigationButton} from './index';
|
|
4
4
|
import {Styles} from '../Consts';
|
|
5
5
|
import {Image} from '../Image';
|
|
6
|
+
import {HeaderBackgroundProps, TitleCustomProps} from './types';
|
|
7
|
+
import {useGridSystem} from '../Layout';
|
|
6
8
|
|
|
7
9
|
const styles = StyleSheet.create({
|
|
8
10
|
headerBackground: {
|
|
@@ -11,29 +13,52 @@ const styles = StyleSheet.create({
|
|
|
11
13
|
position: 'absolute',
|
|
12
14
|
aspectRatio: 375 / 154,
|
|
13
15
|
},
|
|
16
|
+
headerTitleContainer: {
|
|
17
|
+
alignItems: 'center',
|
|
18
|
+
justifyContent: 'center',
|
|
19
|
+
},
|
|
14
20
|
});
|
|
15
21
|
|
|
16
|
-
const HeaderBackground = (
|
|
22
|
+
const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
23
|
+
surface = false,
|
|
24
|
+
image,
|
|
25
|
+
}) => {
|
|
17
26
|
const {theme} = useContext(ApplicationContext);
|
|
27
|
+
const allowImage = !surface && theme.assets?.headerBackground;
|
|
18
28
|
return (
|
|
19
29
|
<View
|
|
20
30
|
style={[
|
|
21
31
|
Styles.flex,
|
|
22
32
|
{backgroundColor: theme.colors.background.surface, overflow: 'hidden'},
|
|
23
33
|
]}>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
<StatusBar
|
|
35
|
+
barStyle={allowImage || theme.dark ? 'light-content' : 'dark-content'}
|
|
36
|
+
/>
|
|
37
|
+
{allowImage && (
|
|
38
|
+
<Image
|
|
39
|
+
style={styles.headerBackground}
|
|
40
|
+
source={{uri: image ?? theme.assets?.headerBackground}}
|
|
41
|
+
/>
|
|
32
42
|
)}
|
|
33
43
|
</View>
|
|
34
44
|
);
|
|
35
45
|
};
|
|
36
46
|
|
|
47
|
+
const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
48
|
+
title,
|
|
49
|
+
subTitle,
|
|
50
|
+
image,
|
|
51
|
+
content,
|
|
52
|
+
}) => {
|
|
53
|
+
const {getSizeSpan} = useGridSystem();
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<View style={[styles.headerTitleContainer, {width: getSizeSpan(10)}]}>
|
|
57
|
+
{content ?? <View />}
|
|
58
|
+
</View>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
37
62
|
const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
|
|
38
63
|
const validType = (item: any) => {
|
|
39
64
|
if (item.type !== NavigationButton) {
|
|
@@ -60,4 +85,4 @@ const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
|
|
|
60
85
|
return <View style={Styles.headerRightButton}>{renderAction()}</View>;
|
|
61
86
|
};
|
|
62
87
|
|
|
63
|
-
export {HeaderBackground, HeaderRightAction};
|
|
88
|
+
export {HeaderBackground, HeaderRightAction, HeaderCustom};
|
|
@@ -12,12 +12,21 @@ import {BottomSheetModalMethods} from '@gorhom/bottom-sheet/lib/typescript/types
|
|
|
12
12
|
import Navigation from './Navigation';
|
|
13
13
|
import {ModalParams} from './types';
|
|
14
14
|
import {Radius, Spacing, Styles} from '../Consts';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
ApplicationContext,
|
|
17
|
+
HeaderRightAction,
|
|
18
|
+
NavigationButton,
|
|
19
|
+
NavigationContainer,
|
|
20
|
+
} from './index';
|
|
16
21
|
|
|
17
|
-
const ModalScreen: React.FC<
|
|
18
|
-
const {navigation, route} = props;
|
|
22
|
+
const ModalScreen: React.FC<ModalParams> = ({navigation, route, ...rest}) => {
|
|
19
23
|
const {theme} = useContext(ApplicationContext);
|
|
20
|
-
const {
|
|
24
|
+
const {
|
|
25
|
+
isBottomSheet,
|
|
26
|
+
backgroundColor,
|
|
27
|
+
screen,
|
|
28
|
+
barrierDismissible,
|
|
29
|
+
}: ModalParams = route.params;
|
|
21
30
|
const Component = useRef(screen).current;
|
|
22
31
|
const params = {
|
|
23
32
|
...route.params,
|
|
@@ -33,11 +42,7 @@ const ModalScreen: React.FC<any> = props => {
|
|
|
33
42
|
if (!pop) {
|
|
34
43
|
action = () => {};
|
|
35
44
|
}
|
|
36
|
-
if (
|
|
37
|
-
onRequestClose(() => {
|
|
38
|
-
params?.onDismiss?.();
|
|
39
|
-
action();
|
|
40
|
-
});
|
|
45
|
+
if (barrierDismissible && !isBottomSheet) {
|
|
41
46
|
return;
|
|
42
47
|
}
|
|
43
48
|
params?.onDismiss?.();
|
|
@@ -48,16 +53,39 @@ const ModalScreen: React.FC<any> = props => {
|
|
|
48
53
|
* build bottom sheet
|
|
49
54
|
*/
|
|
50
55
|
if (isBottomSheet) {
|
|
56
|
+
const bgColor = backgroundColor ?? theme.colors.background.surface;
|
|
51
57
|
return (
|
|
52
|
-
<BottomSheet {...
|
|
53
|
-
<View style={{
|
|
58
|
+
<BottomSheet {...rest} onDismiss={onDismiss}>
|
|
59
|
+
<View style={[styles.sheetContainer, {backgroundColor: bgColor}]}>
|
|
60
|
+
<View style={styles.indicatorContainer}>
|
|
61
|
+
<View
|
|
62
|
+
style={[
|
|
63
|
+
styles.indicator,
|
|
64
|
+
{backgroundColor: theme.colors.text.disable},
|
|
65
|
+
]}
|
|
66
|
+
/>
|
|
67
|
+
</View>
|
|
54
68
|
<NavigationContainer
|
|
55
69
|
theme={{...theme, assets: undefined}}
|
|
56
70
|
screen={props => <Component {...params} {...props} />}
|
|
57
71
|
onDismiss={() => {
|
|
58
72
|
navigation.pop();
|
|
59
73
|
}}
|
|
60
|
-
|
|
74
|
+
screenOptions={{
|
|
75
|
+
headerRight: (props: any) => (
|
|
76
|
+
<HeaderRightAction>
|
|
77
|
+
<NavigationButton
|
|
78
|
+
icon="24_navigation_close"
|
|
79
|
+
{...props}
|
|
80
|
+
onPress={onDismiss}
|
|
81
|
+
/>
|
|
82
|
+
</HeaderRightAction>
|
|
83
|
+
),
|
|
84
|
+
headerBackground: () => (
|
|
85
|
+
<View style={[Styles.flex, {backgroundColor: bgColor}]} />
|
|
86
|
+
),
|
|
87
|
+
}}
|
|
88
|
+
hideBackFirst={true}
|
|
61
89
|
/>
|
|
62
90
|
</View>
|
|
63
91
|
</BottomSheet>
|
|
@@ -96,7 +124,6 @@ const ModalScreen: React.FC<any> = props => {
|
|
|
96
124
|
};
|
|
97
125
|
|
|
98
126
|
const BottomSheet: React.FC<ModalParams> = ({children, onDismiss}) => {
|
|
99
|
-
const {theme} = useContext(ApplicationContext);
|
|
100
127
|
const snapPoints = useMemo(() => ['50%', '90%'], []);
|
|
101
128
|
const {bottom} = useSafeAreaInsets();
|
|
102
129
|
const bottomSheetRef = useRef<BottomSheetModalMethods>(null);
|
|
@@ -109,17 +136,6 @@ const BottomSheet: React.FC<ModalParams> = ({children, onDismiss}) => {
|
|
|
109
136
|
};
|
|
110
137
|
}, []);
|
|
111
138
|
|
|
112
|
-
const handleComponent = () => (
|
|
113
|
-
<View
|
|
114
|
-
style={[
|
|
115
|
-
styles.indicatorContainer,
|
|
116
|
-
{backgroundColor: theme.colors.background.surface},
|
|
117
|
-
]}>
|
|
118
|
-
<View
|
|
119
|
-
style={[styles.indicator, {backgroundColor: theme.colors.text.disable}]}
|
|
120
|
-
/>
|
|
121
|
-
</View>
|
|
122
|
-
);
|
|
123
139
|
const backdropComponent = (backdropProps: any) => (
|
|
124
140
|
<BottomSheetBackdrop
|
|
125
141
|
disappearsOnIndex={-1}
|
|
@@ -133,27 +149,22 @@ const BottomSheet: React.FC<ModalParams> = ({children, onDismiss}) => {
|
|
|
133
149
|
<BottomSheetModal
|
|
134
150
|
ref={bottomSheetRef}
|
|
135
151
|
snapPoints={snapPoints}
|
|
136
|
-
handleHeight={24}
|
|
137
152
|
onDismiss={() => onDismiss?.(mountedRef.current)}
|
|
138
|
-
handleComponent={
|
|
153
|
+
handleComponent={null}
|
|
139
154
|
backdropComponent={backdropComponent}>
|
|
140
|
-
<View
|
|
141
|
-
style={{
|
|
142
|
-
paddingBottom: bottom,
|
|
143
|
-
backgroundColor: theme.colors.background.default,
|
|
144
|
-
}}>
|
|
145
|
-
{children}
|
|
146
|
-
</View>
|
|
155
|
+
<View style={{paddingBottom: bottom}}>{children}</View>
|
|
147
156
|
</BottomSheetModal>
|
|
148
157
|
</SafeAreaView>
|
|
149
158
|
);
|
|
150
159
|
};
|
|
151
160
|
|
|
161
|
+
ModalScreen.defaultProps = {
|
|
162
|
+
barrierDismissible: false,
|
|
163
|
+
};
|
|
164
|
+
|
|
152
165
|
const styles = StyleSheet.create({
|
|
153
166
|
container: {flex: 1, flexDirection: 'row'},
|
|
154
167
|
modalContent: {
|
|
155
|
-
borderRadius: Radius.M,
|
|
156
|
-
overflow: 'hidden',
|
|
157
168
|
maxWidth: '100%',
|
|
158
169
|
maxHeight: '80%',
|
|
159
170
|
},
|
|
@@ -168,14 +179,18 @@ const styles = StyleSheet.create({
|
|
|
168
179
|
flex: 1,
|
|
169
180
|
minHeight: '10%',
|
|
170
181
|
},
|
|
171
|
-
|
|
182
|
+
sheetContainer: {
|
|
183
|
+
height: '100%',
|
|
172
184
|
width: '100%',
|
|
173
|
-
paddingTop: Spacing.S,
|
|
174
185
|
borderTopLeftRadius: Radius.M,
|
|
175
186
|
borderTopRightRadius: Radius.M,
|
|
176
187
|
overflow: 'hidden',
|
|
177
|
-
|
|
188
|
+
},
|
|
189
|
+
indicatorContainer: {
|
|
190
|
+
width: '100%',
|
|
191
|
+
paddingTop: Spacing.S,
|
|
178
192
|
alignItems: 'center',
|
|
193
|
+
justifyContent: 'center',
|
|
179
194
|
},
|
|
180
195
|
indicator: {
|
|
181
196
|
width: 64,
|
package/Navigation/Navigation.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {NavigationProp} from '@react-navigation/native';
|
|
2
2
|
import {NavigationOptions} from './types';
|
|
3
3
|
import {HeaderRightAction} from './index';
|
|
4
|
+
import {getOptions} from './utils';
|
|
4
5
|
|
|
5
6
|
class Navigation {
|
|
6
7
|
instance: NavigationProp<any>;
|
|
@@ -16,6 +17,7 @@ class Navigation {
|
|
|
16
17
|
console.warn(
|
|
17
18
|
'headerRight not return element type of HeaderRightAction, Please migrate to use HeaderRightAction of kits.',
|
|
18
19
|
);
|
|
20
|
+
return;
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
};
|
|
@@ -27,6 +29,7 @@ class Navigation {
|
|
|
27
29
|
setOptions = (params: NavigationOptions) => {
|
|
28
30
|
this.verifyParams(params);
|
|
29
31
|
params = this.filterParams(params);
|
|
32
|
+
params = getOptions(params);
|
|
30
33
|
this.instance.setOptions(params);
|
|
31
34
|
};
|
|
32
35
|
}
|
|
@@ -4,8 +4,11 @@ import {NavigationButtonProps} from './types';
|
|
|
4
4
|
import {ApplicationContext} from './index';
|
|
5
5
|
import {Icon} from '../Icon';
|
|
6
6
|
|
|
7
|
-
const NavigationButton: React.FC<NavigationButtonProps> =
|
|
8
|
-
|
|
7
|
+
const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
8
|
+
icon,
|
|
9
|
+
tintColor,
|
|
10
|
+
onPress,
|
|
11
|
+
}) => {
|
|
9
12
|
const {theme} = useContext(ApplicationContext);
|
|
10
13
|
return (
|
|
11
14
|
<TouchableOpacity style={styles.container} onPress={onPress}>
|