@momo-kits/foundation 1.0.13 → 1.0.14
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 +1 -1
- package/CheckBox/index.tsx +2 -1
- package/Icon/index.tsx +1 -0
- package/IconButton/index.tsx +1 -0
- package/Image/index.tsx +11 -2
- package/Input/Input.tsx +2 -5
- package/Input/InputMoney.tsx +1 -1
- package/Input/InputSearch.tsx +3 -1
- package/Input/InputTextArea.tsx +1 -1
- package/Layout/Card.tsx +87 -0
- package/Layout/GridSystem.tsx +19 -4
- package/Layout/ScreenContainer.tsx +55 -16
- package/Layout/{ScreenSection.tsx → Section.tsx} +51 -25
- package/Layout/index.ts +14 -10
- package/Layout/types.ts +11 -2
- package/Layout/utils.ts +2 -35
- package/Navigation/Components.tsx +15 -12
- package/Navigation/ModalScreen.tsx +4 -2
- package/Navigation/NavigationButton.tsx +2 -0
- package/Navigation/NavigationContainer.tsx +2 -3
- package/Navigation/StackScreen.tsx +0 -1
- package/Navigation/types.ts +5 -2
- package/Popup/PopupNotify.tsx +1 -0
- package/Popup/PopupPromotion.tsx +2 -2
- package/Radio/index.tsx +1 -0
- package/Skeleton/index.tsx +1 -1
- package/Switch/index.tsx +1 -0
- package/Text/index.tsx +12 -2
- package/package.json +1 -1
- package/Layout/SectionItem.tsx +0 -63
package/Button/index.tsx
CHANGED
|
@@ -10,7 +10,6 @@ import {Text} from '../Text';
|
|
|
10
10
|
import {Typography} from '../Text/types';
|
|
11
11
|
import {Colors} from '../Consts';
|
|
12
12
|
import styles from './styles';
|
|
13
|
-
import {Image} from '../Image';
|
|
14
13
|
import {Icon} from '../Icon';
|
|
15
14
|
|
|
16
15
|
export interface ButtonProps extends TouchableOpacityProps {
|
|
@@ -224,6 +223,7 @@ const Button: FC<ButtonProps> = ({
|
|
|
224
223
|
return (
|
|
225
224
|
<TouchableOpacity
|
|
226
225
|
{...rest}
|
|
226
|
+
accessibilityLabel={`Button/${title}`}
|
|
227
227
|
activeOpacity={activeOpacity}
|
|
228
228
|
onPress={onPressButton}
|
|
229
229
|
style={buttonStyle}>
|
package/CheckBox/index.tsx
CHANGED
|
@@ -35,6 +35,7 @@ const CheckBox: FC<CheckBoxProps> = props => {
|
|
|
35
35
|
};
|
|
36
36
|
return (
|
|
37
37
|
<TouchableOpacity
|
|
38
|
+
accessibilityLabel={`CheckBox/${label}`}
|
|
38
39
|
activeOpacity={0.8}
|
|
39
40
|
onPress={onChangeValue}
|
|
40
41
|
disabled={disabled}
|
|
@@ -48,7 +49,7 @@ const CheckBox: FC<CheckBoxProps> = props => {
|
|
|
48
49
|
/>
|
|
49
50
|
)}
|
|
50
51
|
</View>
|
|
51
|
-
<Text typography={'description_default'}>{label}</Text>
|
|
52
|
+
{!!label && <Text typography={'description_default'}>{label}</Text>}
|
|
52
53
|
</TouchableOpacity>
|
|
53
54
|
);
|
|
54
55
|
};
|
package/Icon/index.tsx
CHANGED
package/IconButton/index.tsx
CHANGED
package/Image/index.tsx
CHANGED
|
@@ -11,9 +11,15 @@ import {FastImagePropsWithoutStyle} from './types';
|
|
|
11
11
|
export interface ImageProps extends FastImagePropsWithoutStyle {
|
|
12
12
|
style?: StyleProp<ViewStyle>;
|
|
13
13
|
loading?: boolean;
|
|
14
|
+
accessibilityLabel?: string;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
const Image: React.FC<ImageProps> = ({
|
|
17
|
+
const Image: React.FC<ImageProps> = ({
|
|
18
|
+
style,
|
|
19
|
+
source,
|
|
20
|
+
accessibilityLabel,
|
|
21
|
+
...rest
|
|
22
|
+
}) => {
|
|
17
23
|
const {theme} = useContext(ApplicationContext);
|
|
18
24
|
const [loading, setLoading] = useState(rest.loading);
|
|
19
25
|
const [fail, setFail] = useState(false);
|
|
@@ -48,7 +54,9 @@ const Image: React.FC<ImageProps> = ({style, source, ...rest}) => {
|
|
|
48
54
|
};
|
|
49
55
|
|
|
50
56
|
return (
|
|
51
|
-
<View
|
|
57
|
+
<View
|
|
58
|
+
style={[styles.container, style]}
|
|
59
|
+
accessibilityLabel={`Image/${accessibilityLabel ?? source}`}>
|
|
52
60
|
<FastImage
|
|
53
61
|
{...rest}
|
|
54
62
|
source={source}
|
|
@@ -68,4 +76,5 @@ const Image: React.FC<ImageProps> = ({style, source, ...rest}) => {
|
|
|
68
76
|
Image.defaultProps = {
|
|
69
77
|
loading: true,
|
|
70
78
|
};
|
|
79
|
+
|
|
71
80
|
export {Image};
|
package/Input/Input.tsx
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
} from 'react-native';
|
|
9
9
|
import {ApplicationContext} from '../Navigation';
|
|
10
10
|
import styles from './styles';
|
|
11
|
-
import {Image} from '../Image';
|
|
12
11
|
import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
|
|
13
12
|
import {InputProps} from './index';
|
|
14
13
|
import {Icon} from '../Icon';
|
|
@@ -112,16 +111,14 @@ const Input: FC<InputProps> = ({
|
|
|
112
111
|
/>
|
|
113
112
|
</TouchableOpacity>
|
|
114
113
|
)}
|
|
115
|
-
{icon &&
|
|
116
|
-
<Icon icon={iconTintColor} source={icon} style={styles.icon} />
|
|
117
|
-
)}
|
|
114
|
+
{icon && <Icon color={iconTintColor} source={icon} size={24} />}
|
|
118
115
|
</View>
|
|
119
116
|
</View>
|
|
120
117
|
);
|
|
121
118
|
};
|
|
122
119
|
|
|
123
120
|
return (
|
|
124
|
-
<View style={styles.wrapper}>
|
|
121
|
+
<View style={styles.wrapper} accessibilityLabel={`Input`}>
|
|
125
122
|
{renderInputView()}
|
|
126
123
|
<ErrorView errorMessage={errorMessage} />
|
|
127
124
|
</View>
|
package/Input/InputMoney.tsx
CHANGED
package/Input/InputSearch.tsx
CHANGED
|
@@ -125,7 +125,9 @@ const InputSearch: FC<InputSearchProps> = ({
|
|
|
125
125
|
);
|
|
126
126
|
};
|
|
127
127
|
return (
|
|
128
|
-
<View
|
|
128
|
+
<View
|
|
129
|
+
style={[style, styles.searchInputContainer]}
|
|
130
|
+
accessibilityLabel={`InputSearch`}>
|
|
129
131
|
<View
|
|
130
132
|
style={[
|
|
131
133
|
getBorderColor(),
|
package/Input/InputTextArea.tsx
CHANGED
|
@@ -138,7 +138,7 @@ const InputTextArea: FC<InputTextAreaProps> = props => {
|
|
|
138
138
|
};
|
|
139
139
|
|
|
140
140
|
return (
|
|
141
|
-
<View style={styles.wrapper}>
|
|
141
|
+
<View style={styles.wrapper} accessibilityLabel={`InputTextArea`}>
|
|
142
142
|
{renderInputView()}
|
|
143
143
|
<ErrorView errorMessage={errorMessage} />
|
|
144
144
|
</View>
|
package/Layout/Card.tsx
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React, {useContext} from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
|
|
4
|
+
import {CardProps, GridContextProps} from './types';
|
|
5
|
+
import {GridContext} from './index';
|
|
6
|
+
|
|
7
|
+
const Card: React.FC<CardProps> = ({
|
|
8
|
+
widthSpan = 12,
|
|
9
|
+
heightSpan,
|
|
10
|
+
usePadding,
|
|
11
|
+
children,
|
|
12
|
+
style,
|
|
13
|
+
}) => {
|
|
14
|
+
const grid = useContext(GridContext);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* render overlay view only dev mode
|
|
18
|
+
*/
|
|
19
|
+
const renderOverlay = () => {
|
|
20
|
+
return (
|
|
21
|
+
<View
|
|
22
|
+
pointerEvents={'none'}
|
|
23
|
+
style={{
|
|
24
|
+
position: 'absolute',
|
|
25
|
+
top: 0,
|
|
26
|
+
bottom: 0,
|
|
27
|
+
left: 0,
|
|
28
|
+
right: 0,
|
|
29
|
+
borderColor: 'red',
|
|
30
|
+
borderWidth: 1,
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const styles: any = style ?? {};
|
|
37
|
+
|
|
38
|
+
const numberOfColumns = 12;
|
|
39
|
+
const gutterSize = 8;
|
|
40
|
+
let margin = 0;
|
|
41
|
+
if (usePadding) {
|
|
42
|
+
margin = 12;
|
|
43
|
+
}
|
|
44
|
+
const widthSection = grid.getSizeSpan(widthSpan) - margin * 2;
|
|
45
|
+
const totalGutterSize = gutterSize * (numberOfColumns - 1);
|
|
46
|
+
const sizePerSpan = (widthSection - totalGutterSize) / numberOfColumns;
|
|
47
|
+
const gridContext: GridContextProps = {
|
|
48
|
+
numberOfColumns,
|
|
49
|
+
gutterSize,
|
|
50
|
+
margin,
|
|
51
|
+
sizePerSpan,
|
|
52
|
+
getSizeSpan: span => {
|
|
53
|
+
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<View
|
|
59
|
+
accessibilityLabel={`Card`}
|
|
60
|
+
style={{
|
|
61
|
+
...styles,
|
|
62
|
+
width: grid.getSizeSpan(widthSpan),
|
|
63
|
+
height: heightSpan ? grid.getSizeSpan(heightSpan) : undefined,
|
|
64
|
+
paddingHorizontal: margin,
|
|
65
|
+
overflow: 'hidden',
|
|
66
|
+
margin: undefined,
|
|
67
|
+
marginTop: undefined,
|
|
68
|
+
marginBottom: undefined,
|
|
69
|
+
marginLeft: undefined,
|
|
70
|
+
marginRight: undefined,
|
|
71
|
+
}}>
|
|
72
|
+
<GridContext.Provider value={gridContext}>
|
|
73
|
+
{children}
|
|
74
|
+
</GridContext.Provider>
|
|
75
|
+
{__DEV__ && renderOverlay()}
|
|
76
|
+
</View>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
Card.defaultProps = {
|
|
81
|
+
widthSpan: 12,
|
|
82
|
+
usePadding: false,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
Card.displayName = 'Card';
|
|
86
|
+
|
|
87
|
+
export default Card;
|
package/Layout/GridSystem.tsx
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
import React, {useContext} from 'react';
|
|
2
2
|
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
3
|
-
import {StyleSheet, View} from 'react-native';
|
|
3
|
+
import {Dimensions, StyleSheet, View} from 'react-native';
|
|
4
4
|
import {ApplicationContext} from '../Navigation';
|
|
5
|
-
import {useGridSystem} from './index';
|
|
6
5
|
import {Colors, Spacing} from '../Consts';
|
|
6
|
+
import {GridContextProps} from './types';
|
|
7
7
|
|
|
8
8
|
const GridSystem: React.FC = () => {
|
|
9
9
|
const {theme} = useContext(ApplicationContext);
|
|
10
|
-
const
|
|
10
|
+
const numberOfColumns = 12;
|
|
11
|
+
const gutterSize = 12;
|
|
12
|
+
const margin = 12;
|
|
13
|
+
const widthSection = Dimensions.get('window').width - margin * 2;
|
|
14
|
+
const totalGutterSize = gutterSize * (numberOfColumns - 1);
|
|
15
|
+
const sizePerSpan = (widthSection - totalGutterSize) / numberOfColumns;
|
|
16
|
+
|
|
17
|
+
const grid: GridContextProps = {
|
|
18
|
+
numberOfColumns,
|
|
19
|
+
gutterSize,
|
|
20
|
+
margin,
|
|
21
|
+
sizePerSpan,
|
|
22
|
+
getSizeSpan: span => {
|
|
23
|
+
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
24
|
+
},
|
|
25
|
+
};
|
|
11
26
|
const insets = useSafeAreaInsets();
|
|
12
27
|
|
|
13
28
|
const list = [];
|
|
@@ -24,7 +39,7 @@ const GridSystem: React.FC = () => {
|
|
|
24
39
|
insets,
|
|
25
40
|
{
|
|
26
41
|
borderColor: theme.colors.error.primary,
|
|
27
|
-
marginHorizontal: grid.
|
|
42
|
+
marginHorizontal: grid.margin,
|
|
28
43
|
},
|
|
29
44
|
]}>
|
|
30
45
|
{list.map((i, index) => {
|
|
@@ -4,35 +4,57 @@ import {SafeAreaView} from 'react-native-safe-area-context';
|
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import {ScreenContainerProps} from '../Navigation/types';
|
|
6
6
|
import {Spacing, Styles} from '../Consts';
|
|
7
|
-
import {
|
|
8
|
-
import {Image} from '../Image';
|
|
7
|
+
import {Section, validateChildren} from './index';
|
|
9
8
|
|
|
10
9
|
const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
11
10
|
children,
|
|
12
11
|
edges,
|
|
13
12
|
enableKeyboardAvoidingView,
|
|
14
13
|
scrollable,
|
|
14
|
+
scrollY,
|
|
15
|
+
headerBackground,
|
|
15
16
|
scrollViewProps,
|
|
16
|
-
|
|
17
|
+
footerComponent: Footer,
|
|
17
18
|
}) => {
|
|
19
|
+
let marginHeader = 0;
|
|
20
|
+
let handleScroll;
|
|
21
|
+
let imageAnimatedStyle = {};
|
|
18
22
|
let Component: any = View;
|
|
19
23
|
const headerHeight = useHeaderHeight();
|
|
20
24
|
if (scrollable) {
|
|
21
25
|
Component = Animated.ScrollView;
|
|
22
26
|
}
|
|
27
|
+
if (scrollY) {
|
|
28
|
+
marginHeader = useHeaderHeight();
|
|
29
|
+
imageAnimatedStyle = {
|
|
30
|
+
transform: [
|
|
31
|
+
{
|
|
32
|
+
scale: scrollY.interpolate?.({
|
|
33
|
+
inputRange: [-300, -110, 100],
|
|
34
|
+
outputRange: [1.75, 1, 1],
|
|
35
|
+
extrapolate: 'clamp',
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
handleScroll = Animated.event(
|
|
41
|
+
[{nativeEvent: {contentOffset: {y: scrollY}}}],
|
|
42
|
+
{useNativeDriver: true},
|
|
43
|
+
);
|
|
44
|
+
}
|
|
23
45
|
|
|
24
46
|
/**
|
|
25
47
|
* build content for screen
|
|
26
48
|
*/
|
|
27
49
|
const renderContent = () => {
|
|
28
|
-
const results = validateChildren(children,
|
|
50
|
+
const results = validateChildren(children, Section);
|
|
29
51
|
if (Array.isArray(results)) {
|
|
30
52
|
return results.map((item, index) => {
|
|
31
53
|
return (
|
|
32
54
|
<View
|
|
33
|
-
key={`
|
|
55
|
+
key={`Section${index}`}
|
|
34
56
|
style={{
|
|
35
|
-
|
|
57
|
+
marginTop: item.props?.useMargin ? Spacing.M : 0,
|
|
36
58
|
flex: item.props?.expanded ? 1 : undefined,
|
|
37
59
|
}}>
|
|
38
60
|
{item}
|
|
@@ -44,7 +66,28 @@ const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
|
44
66
|
};
|
|
45
67
|
|
|
46
68
|
return (
|
|
47
|
-
<SafeAreaView
|
|
69
|
+
<SafeAreaView
|
|
70
|
+
style={Styles.flex}
|
|
71
|
+
edges={edges}
|
|
72
|
+
accessibilityLabel={`ScreenContainer`}>
|
|
73
|
+
<View
|
|
74
|
+
style={{
|
|
75
|
+
position: 'absolute',
|
|
76
|
+
height: 300,
|
|
77
|
+
width: '100%',
|
|
78
|
+
}}>
|
|
79
|
+
{headerBackground && (
|
|
80
|
+
<Animated.Image
|
|
81
|
+
source={{
|
|
82
|
+
uri: headerBackground,
|
|
83
|
+
}}
|
|
84
|
+
style={{
|
|
85
|
+
aspectRatio: 1.3,
|
|
86
|
+
...imageAnimatedStyle,
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
90
|
+
</View>
|
|
48
91
|
<KeyboardAvoidingView
|
|
49
92
|
style={Styles.flex}
|
|
50
93
|
keyboardVerticalOffset={headerHeight}
|
|
@@ -53,17 +96,13 @@ const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
|
53
96
|
ios: 'padding',
|
|
54
97
|
android: undefined,
|
|
55
98
|
})}>
|
|
56
|
-
<Component
|
|
57
|
-
{
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
uri: headerImage,
|
|
61
|
-
}}
|
|
62
|
-
style={{width: '100%', height: 300}}
|
|
63
|
-
/>
|
|
64
|
-
)}
|
|
99
|
+
<Component
|
|
100
|
+
{...scrollViewProps}
|
|
101
|
+
onScroll={handleScroll}
|
|
102
|
+
style={[Styles.flex, {marginTop: marginHeader}]}>
|
|
65
103
|
{renderContent()}
|
|
66
104
|
</Component>
|
|
105
|
+
{Footer && <Section>{Footer}</Section>}
|
|
67
106
|
</KeyboardAvoidingView>
|
|
68
107
|
</SafeAreaView>
|
|
69
108
|
);
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {View} from 'react-native';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
2
|
+
import {Dimensions, View} from 'react-native';
|
|
3
|
+
import {validateChildren} from './utils';
|
|
4
|
+
import Card from './Card';
|
|
5
|
+
import {GridContextProps, SectionProps} from './types';
|
|
6
|
+
import {GridContext} from './index';
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
-
const
|
|
8
|
+
const Section: React.FC<SectionProps> = ({children, useMargin = true}) => {
|
|
9
|
+
const numberOfColumns = 12;
|
|
10
|
+
const gutterSize = 12;
|
|
11
|
+
let margin = 0;
|
|
12
|
+
if (useMargin) {
|
|
13
|
+
margin = 12;
|
|
14
|
+
}
|
|
15
|
+
let widthSection = Dimensions.get('window').width;
|
|
16
|
+
if (useMargin) widthSection = widthSection - margin * 2;
|
|
17
|
+
const totalGutterSize = gutterSize * (numberOfColumns - 1);
|
|
18
|
+
const sizePerSpan = (widthSection - totalGutterSize) / numberOfColumns;
|
|
19
|
+
|
|
20
|
+
const gridContext: GridContextProps = {
|
|
21
|
+
numberOfColumns,
|
|
22
|
+
gutterSize,
|
|
23
|
+
margin,
|
|
24
|
+
sizePerSpan,
|
|
25
|
+
getSizeSpan: span => {
|
|
26
|
+
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
9
29
|
|
|
10
30
|
/**
|
|
11
31
|
* render overlay only dev mode
|
|
@@ -40,17 +60,17 @@ const ScreenSection: React.FC<ScreenSectionProps> = ({children}) => {
|
|
|
40
60
|
) => {
|
|
41
61
|
return (
|
|
42
62
|
<View
|
|
43
|
-
key={`
|
|
63
|
+
key={`Card${cursor}`}
|
|
44
64
|
style={{
|
|
45
65
|
flexDirection: 'row',
|
|
46
|
-
marginBottom: endRow ? 0 :
|
|
66
|
+
marginBottom: endRow ? 0 : gridContext.gutterSize,
|
|
47
67
|
}}>
|
|
48
68
|
{rows.map((i: React.ReactElement, index: number) => {
|
|
49
69
|
return (
|
|
50
|
-
<View
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
<View key={`Card${cursor}${index}`} style={{flexDirection: 'row'}}>
|
|
71
|
+
{index != 0 && (
|
|
72
|
+
<View style={{width: gridContext.gutterSize}}></View>
|
|
73
|
+
)}
|
|
54
74
|
{i}
|
|
55
75
|
</View>
|
|
56
76
|
);
|
|
@@ -79,7 +99,7 @@ const ScreenSection: React.FC<ScreenSectionProps> = ({children}) => {
|
|
|
79
99
|
return previousValue + currentValue;
|
|
80
100
|
});
|
|
81
101
|
|
|
82
|
-
if (totalSpan <=
|
|
102
|
+
if (totalSpan <= gridContext.numberOfColumns) {
|
|
83
103
|
rows.push(item);
|
|
84
104
|
} else {
|
|
85
105
|
cursor += 1;
|
|
@@ -99,19 +119,25 @@ const ScreenSection: React.FC<ScreenSectionProps> = ({children}) => {
|
|
|
99
119
|
};
|
|
100
120
|
|
|
101
121
|
return (
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
122
|
+
<GridContext.Provider value={gridContext}>
|
|
123
|
+
<View
|
|
124
|
+
accessibilityLabel={`Section`}
|
|
125
|
+
style={{
|
|
126
|
+
width: gridContext.getSizeSpan(12),
|
|
127
|
+
marginHorizontal: gridContext.margin,
|
|
128
|
+
flexDirection: 'row',
|
|
129
|
+
flexWrap: 'wrap',
|
|
130
|
+
}}>
|
|
131
|
+
{renderView(validateChildren(children, Card))}
|
|
132
|
+
{__DEV__ && renderOverlay()}
|
|
133
|
+
</View>
|
|
134
|
+
</GridContext.Provider>
|
|
112
135
|
);
|
|
113
136
|
};
|
|
114
137
|
|
|
115
|
-
|
|
138
|
+
Section.displayName = 'Section';
|
|
116
139
|
|
|
117
|
-
|
|
140
|
+
Section.defaultProps = {
|
|
141
|
+
useMargin: true,
|
|
142
|
+
};
|
|
143
|
+
export default Section;
|
package/Layout/index.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import Card from './Card';
|
|
2
|
+
import Section from './Section';
|
|
3
3
|
import GridSystem from './GridSystem';
|
|
4
|
-
import {
|
|
4
|
+
import {validateChildren} from './utils';
|
|
5
|
+
import {createContext} from 'react';
|
|
6
|
+
import {GridContextProps} from './types';
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
};
|
|
8
|
+
const GridContext = createContext<GridContextProps>({
|
|
9
|
+
numberOfColumns: 12,
|
|
10
|
+
gutterSize: 12,
|
|
11
|
+
margin: 12,
|
|
12
|
+
sizePerSpan: 0,
|
|
13
|
+
getSizeSpan: span => 0,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export {GridContext, Card, Section, GridSystem, validateChildren};
|
package/Layout/types.ts
CHANGED
|
@@ -2,11 +2,20 @@ import {ViewProps} from 'react-native';
|
|
|
2
2
|
|
|
3
3
|
type SpanNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
4
4
|
|
|
5
|
-
export
|
|
5
|
+
export type GridContextProps = {
|
|
6
|
+
numberOfColumns: number;
|
|
7
|
+
gutterSize: number;
|
|
8
|
+
margin?: number;
|
|
9
|
+
sizePerSpan: number;
|
|
10
|
+
getSizeSpan: (span: number) => number;
|
|
11
|
+
};
|
|
12
|
+
export interface SectionProps extends ViewProps {
|
|
6
13
|
expanded?: boolean;
|
|
14
|
+
useMargin?: boolean;
|
|
7
15
|
}
|
|
8
16
|
|
|
9
|
-
export interface
|
|
17
|
+
export interface CardProps extends ViewProps {
|
|
10
18
|
widthSpan: SpanNumber;
|
|
11
19
|
heightSpan?: SpanNumber;
|
|
20
|
+
usePadding?: boolean;
|
|
12
21
|
}
|
package/Layout/utils.ts
CHANGED
|
@@ -1,38 +1,5 @@
|
|
|
1
|
-
import {Alert
|
|
1
|
+
import {Alert} from 'react-native';
|
|
2
2
|
import React, {ReactElement} from 'react';
|
|
3
|
-
import {GutterSize, NumberOfColumns, ScreenPadding} from '../Consts';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* hook component for use grid system
|
|
7
|
-
* @param useMargin
|
|
8
|
-
*/
|
|
9
|
-
const useGridSystem = (useMargin: boolean = true) => {
|
|
10
|
-
const isDevMode = false;
|
|
11
|
-
const gutterSize = GutterSize;
|
|
12
|
-
const screenPadding = useMargin ? ScreenPadding : 0;
|
|
13
|
-
const numberOfColumns = NumberOfColumns;
|
|
14
|
-
const widthDevice = Dimensions.get('window').width;
|
|
15
|
-
const parentWidth = widthDevice - screenPadding * 2;
|
|
16
|
-
const totalGutterSize = gutterSize * (numberOfColumns - 1);
|
|
17
|
-
const sizePerSpan = (parentWidth - totalGutterSize) / numberOfColumns;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* get size of element with number span
|
|
21
|
-
* @param span
|
|
22
|
-
*/
|
|
23
|
-
const getSizeSpan = (span: number = numberOfColumns): number => {
|
|
24
|
-
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
isDevMode,
|
|
29
|
-
gutterSize,
|
|
30
|
-
screenPadding,
|
|
31
|
-
numberOfColumns,
|
|
32
|
-
sizePerSpan,
|
|
33
|
-
getSizeSpan,
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
3
|
|
|
37
4
|
/**
|
|
38
5
|
* validate children type
|
|
@@ -80,4 +47,4 @@ const validateChildren = (
|
|
|
80
47
|
return results;
|
|
81
48
|
};
|
|
82
49
|
|
|
83
|
-
export {
|
|
50
|
+
export {validateChildren};
|
|
@@ -11,7 +11,6 @@ import {ApplicationContext, NavigationButton} from './index';
|
|
|
11
11
|
import {Colors, Spacing, Styles} from '../Consts';
|
|
12
12
|
import {Image} from '../Image';
|
|
13
13
|
import {HeaderBackgroundProps, TitleCustomProps} from './types';
|
|
14
|
-
import {useGridSystem} from '../Layout';
|
|
15
14
|
import {Text} from '../Text';
|
|
16
15
|
import {Icon} from '../Icon';
|
|
17
16
|
|
|
@@ -25,6 +24,7 @@ const styles = StyleSheet.create({
|
|
|
25
24
|
headerTitleContainer: {
|
|
26
25
|
alignItems: 'center',
|
|
27
26
|
justifyContent: 'center',
|
|
27
|
+
width: '100%',
|
|
28
28
|
},
|
|
29
29
|
avatar: {width: 36, height: 36, borderRadius: 18},
|
|
30
30
|
dotAvatar: {
|
|
@@ -74,6 +74,7 @@ const HeaderTitle: React.FC<any> = props => {
|
|
|
74
74
|
return (
|
|
75
75
|
<Animated.Text
|
|
76
76
|
{...props}
|
|
77
|
+
accessibilityLabel={`HeaderTitle/${props.children}`}
|
|
77
78
|
style={[styles.title, {opacity, color: props.tintColor}]}
|
|
78
79
|
/>
|
|
79
80
|
);
|
|
@@ -94,7 +95,12 @@ const HeaderLeft: React.FC<any> = ({tintColor}) => {
|
|
|
94
95
|
|
|
95
96
|
return (
|
|
96
97
|
<View style={styles.headerLeft}>
|
|
97
|
-
<NavigationButton
|
|
98
|
+
<NavigationButton
|
|
99
|
+
icon="ic_back"
|
|
100
|
+
tintColor={tintColor}
|
|
101
|
+
onPress={goBack}
|
|
102
|
+
accessibilityLabel={'Back'}
|
|
103
|
+
/>
|
|
98
104
|
</View>
|
|
99
105
|
);
|
|
100
106
|
};
|
|
@@ -106,7 +112,9 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
106
112
|
}) => {
|
|
107
113
|
const {theme} = useContext(ApplicationContext);
|
|
108
114
|
let headerImage = theme.assets?.headerBackground;
|
|
115
|
+
let borderBottomWidth = 0;
|
|
109
116
|
if (image === null) {
|
|
117
|
+
borderBottomWidth = 1;
|
|
110
118
|
headerImage = undefined;
|
|
111
119
|
}
|
|
112
120
|
const opacity = animatedValue?.interpolate({
|
|
@@ -114,6 +122,7 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
114
122
|
outputRange: [0, 1],
|
|
115
123
|
extrapolate: 'clamp',
|
|
116
124
|
});
|
|
125
|
+
|
|
117
126
|
return (
|
|
118
127
|
<Animated.View
|
|
119
128
|
style={[
|
|
@@ -121,7 +130,7 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
121
130
|
{
|
|
122
131
|
backgroundColor: backgroundColor ?? theme.colors.background.default,
|
|
123
132
|
overflow: 'hidden',
|
|
124
|
-
borderBottomWidth:
|
|
133
|
+
borderBottomWidth: borderBottomWidth,
|
|
125
134
|
borderColor: theme.colors.border.default,
|
|
126
135
|
opacity,
|
|
127
136
|
},
|
|
@@ -144,8 +153,6 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
|
144
153
|
tintColor,
|
|
145
154
|
dotColor,
|
|
146
155
|
}) => {
|
|
147
|
-
const {getSizeSpan} = useGridSystem();
|
|
148
|
-
|
|
149
156
|
const header = (
|
|
150
157
|
<View style={Styles.row}>
|
|
151
158
|
<View>
|
|
@@ -164,11 +171,7 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
|
164
171
|
</View>
|
|
165
172
|
</View>
|
|
166
173
|
);
|
|
167
|
-
return
|
|
168
|
-
<View style={[styles.headerTitleContainer, {width: getSizeSpan(10)}]}>
|
|
169
|
-
{content ?? header}
|
|
170
|
-
</View>
|
|
171
|
-
);
|
|
174
|
+
return <View style={styles.headerTitleContainer}>{content ?? header}</View>;
|
|
172
175
|
};
|
|
173
176
|
|
|
174
177
|
const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
|
|
@@ -214,11 +217,11 @@ const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
|
|
|
214
217
|
borderWidth: backgroundColor ? 0.5 : 0,
|
|
215
218
|
},
|
|
216
219
|
]}>
|
|
217
|
-
<TouchableOpacity>
|
|
220
|
+
<TouchableOpacity accessibilityLabel={'Toolkit/More'}>
|
|
218
221
|
<Icon color={tintColor} source="navigation_more_horiz" size={20} />
|
|
219
222
|
</TouchableOpacity>
|
|
220
223
|
<View style={[styles.divider, {backgroundColor: tintColor}]} />
|
|
221
|
-
<TouchableOpacity>
|
|
224
|
+
<TouchableOpacity accessibilityLabel={'Toolkit/Close'}>
|
|
222
225
|
<Icon
|
|
223
226
|
color={tintColor}
|
|
224
227
|
source="16_navigation_close_circle"
|
|
@@ -63,7 +63,7 @@ const Modal: React.FC<ModalParams> = ({navigation, route}) => {
|
|
|
63
63
|
style={styles.modalSpaceVertical}
|
|
64
64
|
onPress={() => onDismiss()}
|
|
65
65
|
/>
|
|
66
|
-
<View style={styles.modalContent}>
|
|
66
|
+
<View style={styles.modalContent} accessibilityLabel={'Modal'}>
|
|
67
67
|
<Component {...params} />
|
|
68
68
|
</View>
|
|
69
69
|
<Pressable
|
|
@@ -128,7 +128,9 @@ const BottomSheet: React.FC<BottomSheetParams> = ({navigation, route}) => {
|
|
|
128
128
|
}}
|
|
129
129
|
handleComponent={null}
|
|
130
130
|
backdropComponent={backdropComponent}>
|
|
131
|
-
<View
|
|
131
|
+
<View
|
|
132
|
+
style={{paddingBottom: bottom}}
|
|
133
|
+
accessibilityLabel={'BottomSheet'}>
|
|
132
134
|
<View style={[styles.sheetContainer, {backgroundColor}]}>
|
|
133
135
|
<View style={styles.indicatorContainer}>
|
|
134
136
|
<View
|
|
@@ -11,6 +11,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
11
11
|
onPress,
|
|
12
12
|
backgroundColor,
|
|
13
13
|
useBorder = true,
|
|
14
|
+
accessibilityLabel,
|
|
14
15
|
}) => {
|
|
15
16
|
const {theme} = useContext(ApplicationContext);
|
|
16
17
|
if (!backgroundColor && tintColor != Colors.black_01) {
|
|
@@ -19,6 +20,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
19
20
|
|
|
20
21
|
return (
|
|
21
22
|
<TouchableOpacity
|
|
23
|
+
accessibilityLabel={`NavigationButton/${accessibilityLabel}`}
|
|
22
24
|
style={[
|
|
23
25
|
styles.container,
|
|
24
26
|
{
|
|
@@ -10,7 +10,7 @@ import StackScreen from './StackScreen';
|
|
|
10
10
|
import ModalScreen from './ModalScreen';
|
|
11
11
|
import Navigator from './Navigator';
|
|
12
12
|
import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
|
|
13
|
-
import {GridSystem
|
|
13
|
+
import {GridSystem} from '../Layout';
|
|
14
14
|
import {defaultContext} from '../Consts';
|
|
15
15
|
import {NavigationContainerProps} from './types';
|
|
16
16
|
|
|
@@ -22,7 +22,6 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
22
22
|
theme,
|
|
23
23
|
options,
|
|
24
24
|
}) => {
|
|
25
|
-
const grid = useGridSystem();
|
|
26
25
|
const navigationRef = React.useRef<NavigationContainerRef>(null);
|
|
27
26
|
const navigator = useRef(new Navigator(navigationRef));
|
|
28
27
|
|
|
@@ -75,7 +74,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
75
74
|
</ReactNavigationContainer>
|
|
76
75
|
</ApplicationContext.Provider>
|
|
77
76
|
</BottomSheetModalProvider>
|
|
78
|
-
{
|
|
77
|
+
{__DEV__ && <GridSystem />}
|
|
79
78
|
</SafeAreaProvider>
|
|
80
79
|
);
|
|
81
80
|
};
|
package/Navigation/types.ts
CHANGED
|
@@ -71,9 +71,11 @@ export type NavigationContainerProps = {
|
|
|
71
71
|
export interface ScreenContainerProps extends ViewProps {
|
|
72
72
|
edges?: any[];
|
|
73
73
|
enableKeyboardAvoidingView?: boolean;
|
|
74
|
-
|
|
74
|
+
headerBackground?: string;
|
|
75
|
+
scrollable?: boolean;
|
|
76
|
+
scrollY?: Animated.Value;
|
|
75
77
|
scrollViewProps?: ScrollViewProps;
|
|
76
|
-
|
|
78
|
+
footerComponent?: React.ElementType;
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
export type ScreenParams = {
|
|
@@ -100,6 +102,7 @@ export type NavigationButtonProps = {
|
|
|
100
102
|
backgroundColor?: string;
|
|
101
103
|
useBorder?: boolean;
|
|
102
104
|
onPress: () => void;
|
|
105
|
+
accessibilityLabel?: string;
|
|
103
106
|
};
|
|
104
107
|
|
|
105
108
|
export type NavigationOptions = {
|
package/Popup/PopupNotify.tsx
CHANGED
package/Popup/PopupPromotion.tsx
CHANGED
|
@@ -38,7 +38,7 @@ const PopupPromotion: React.FC<PopupPromotionProps> = ({image, onClose}) => {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
return (
|
|
41
|
-
|
|
41
|
+
<View accessibilityLabel={'PopupPromotion'}>
|
|
42
42
|
<Image
|
|
43
43
|
style={styles.container}
|
|
44
44
|
source={{
|
|
@@ -46,7 +46,7 @@ const PopupPromotion: React.FC<PopupPromotionProps> = ({image, onClose}) => {
|
|
|
46
46
|
}}
|
|
47
47
|
/>
|
|
48
48
|
{buildCloseIcon()}
|
|
49
|
-
|
|
49
|
+
</View>
|
|
50
50
|
);
|
|
51
51
|
};
|
|
52
52
|
|
package/Radio/index.tsx
CHANGED
package/Skeleton/index.tsx
CHANGED
|
@@ -42,7 +42,7 @@ const Skeleton: React.FC<SkeletonTypes> = ({style}) => {
|
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
return (
|
|
45
|
-
<View style={[styles.container, style]}>
|
|
45
|
+
<View style={[styles.container, style]} accessibilityLabel={'Skeleton'}>
|
|
46
46
|
<View
|
|
47
47
|
onLayout={e => onLayout(e.nativeEvent.layout.width)}
|
|
48
48
|
style={[Styles.flex, {backgroundColor: PRIMARY_COLOR}]}>
|
package/Switch/index.tsx
CHANGED
package/Text/index.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import {Text as RNText, TextProps as RNTextProps} from 'react-native';
|
|
|
3
3
|
import styles from './styles';
|
|
4
4
|
import {Typography, TypographyWeight} from './types';
|
|
5
5
|
import {ApplicationContext} from '../Navigation';
|
|
6
|
+
import {GridContext} from '../Layout';
|
|
6
7
|
|
|
7
8
|
const SFProText: TypographyWeight = {
|
|
8
9
|
100: 'Thin',
|
|
@@ -40,6 +41,7 @@ const FontStyle: {[key: string]: string} = {
|
|
|
40
41
|
export interface TextProps extends RNTextProps {
|
|
41
42
|
typography: Typography;
|
|
42
43
|
color?: string;
|
|
44
|
+
widthSpan?: number;
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
const Text: React.FC<TextProps> = ({
|
|
@@ -47,8 +49,10 @@ const Text: React.FC<TextProps> = ({
|
|
|
47
49
|
color,
|
|
48
50
|
children,
|
|
49
51
|
style,
|
|
52
|
+
widthSpan,
|
|
50
53
|
...rest
|
|
51
54
|
}) => {
|
|
55
|
+
const grid = useContext(GridContext);
|
|
52
56
|
const {theme} = useContext(ApplicationContext);
|
|
53
57
|
|
|
54
58
|
const getTypoStyle = (typo: Typography) => {
|
|
@@ -83,11 +87,17 @@ const Text: React.FC<TextProps> = ({
|
|
|
83
87
|
};
|
|
84
88
|
|
|
85
89
|
const textStyle = getTypoStyle(typography);
|
|
86
|
-
|
|
90
|
+
const spanStyle = widthSpan ? {width: grid.getSizeSpan(widthSpan)} : {};
|
|
87
91
|
return (
|
|
88
92
|
<RNText
|
|
89
93
|
{...rest}
|
|
90
|
-
|
|
94
|
+
accessibilityLabel={`Text/${children}`}
|
|
95
|
+
style={[
|
|
96
|
+
style,
|
|
97
|
+
textStyle,
|
|
98
|
+
spanStyle,
|
|
99
|
+
{color: color ?? theme.colors.text.default},
|
|
100
|
+
]}>
|
|
91
101
|
{children ?? ''}
|
|
92
102
|
</RNText>
|
|
93
103
|
);
|
package/package.json
CHANGED
package/Layout/SectionItem.tsx
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import React, {useContext} from 'react';
|
|
2
|
-
import {View} from 'react-native';
|
|
3
|
-
import {useGridSystem} from './index';
|
|
4
|
-
import {SectionItemProps} from './types';
|
|
5
|
-
import {ApplicationContext} from '../Navigation';
|
|
6
|
-
|
|
7
|
-
const SectionItem: React.FC<SectionItemProps> = ({
|
|
8
|
-
widthSpan = 12,
|
|
9
|
-
heightSpan,
|
|
10
|
-
children,
|
|
11
|
-
style,
|
|
12
|
-
}) => {
|
|
13
|
-
const {theme} = useContext(ApplicationContext);
|
|
14
|
-
const grid = useGridSystem();
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* render overlay view only dev mode
|
|
18
|
-
*/
|
|
19
|
-
const renderOverlay = () => {
|
|
20
|
-
return (
|
|
21
|
-
<View
|
|
22
|
-
pointerEvents={'none'}
|
|
23
|
-
style={{
|
|
24
|
-
position: 'absolute',
|
|
25
|
-
top: 0,
|
|
26
|
-
bottom: 0,
|
|
27
|
-
left: 0,
|
|
28
|
-
right: 0,
|
|
29
|
-
borderColor: 'red',
|
|
30
|
-
borderWidth: 1,
|
|
31
|
-
}}
|
|
32
|
-
/>
|
|
33
|
-
);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const styles: any = style ?? {};
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<View
|
|
40
|
-
style={{
|
|
41
|
-
...styles,
|
|
42
|
-
width: grid.getSizeSpan(widthSpan),
|
|
43
|
-
height: heightSpan ? grid.getSizeSpan(heightSpan) : undefined,
|
|
44
|
-
overflow: 'hidden',
|
|
45
|
-
margin: undefined,
|
|
46
|
-
marginTop: undefined,
|
|
47
|
-
marginBottom: undefined,
|
|
48
|
-
marginLeft: undefined,
|
|
49
|
-
marginRight: undefined,
|
|
50
|
-
}}>
|
|
51
|
-
{children}
|
|
52
|
-
{grid.isDevMode && renderOverlay()}
|
|
53
|
-
</View>
|
|
54
|
-
);
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
SectionItem.defaultProps = {
|
|
58
|
-
widthSpan: 12,
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
SectionItem.displayName = 'SectionItem';
|
|
62
|
-
|
|
63
|
-
export default SectionItem;
|