@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.
- package/ActivityIndicator.tsx +244 -0
- package/Button/index.tsx +94 -164
- package/Button/types.ts +12 -3
- package/CheckBox/index.tsx +57 -0
- package/CheckBox/styles.ts +14 -0
- package/CheckBox/types.ts +7 -0
- package/Consts/colors+spacing+radius.ts +6 -4
- package/Consts/index.ts +4 -73
- package/Consts/styles.ts +1 -1
- package/Consts/theme.ts +65 -0
- package/ContentLoader/index.tsx +8 -11
- package/Icon/index.tsx +11 -11
- package/Icon/types.ts +1 -4
- package/IconButton/index.tsx +52 -72
- package/IconButton/styles.ts +19 -0
- package/IconButton/types.ts +1 -2
- package/Image/index.tsx +19 -18
- package/Image/types.ts +0 -1
- package/Input/TextArea.tsx +202 -0
- package/Input/index.tsx +200 -0
- package/Input/styles.ts +92 -0
- package/Input/types.ts +23 -0
- package/Layout/GridSystem.tsx +109 -0
- package/Layout/ScreenContainer.tsx +78 -0
- package/Layout/ScreenSection.tsx +104 -0
- package/Layout/SectionItem.tsx +60 -0
- package/Layout/index.ts +11 -5
- package/Layout/types.ts +6 -33
- package/Layout/utils.ts +55 -23
- package/Navigation/Components.tsx +16 -8
- package/Navigation/ModalScreen.tsx +35 -25
- package/Navigation/Navigation.ts +2 -2
- package/Navigation/NavigationButton.tsx +5 -3
- package/Navigation/NavigationContainer.tsx +59 -17
- package/Navigation/StackScreen.tsx +8 -2
- package/Navigation/index.ts +5 -3
- package/Navigation/types.ts +53 -36
- package/Navigation/utils.tsx +20 -18
- package/Radio/index.tsx +34 -0
- package/Radio/styles.ts +11 -0
- package/Radio/types.ts +7 -0
- package/Switch/index.tsx +37 -0
- package/Switch/styles.ts +23 -0
- package/Switch/types.ts +5 -0
- package/Text/index.tsx +36 -120
- package/Text/styles.ts +24 -23
- package/Text/types.ts +2 -0
- package/index.ts +18 -1
- package/package.json +1 -1
- package/publish.sh +8 -6
- package/CheckBox/index.js +0 -74
- package/CheckBox/styles.js +0 -3
- package/Layout/Row.tsx +0 -42
- package/Layout/Screen.tsx +0 -68
- package/Layout/Section.tsx +0 -30
- package/Layout/View.tsx +0 -84
- package/Layout/styles.ts +0 -24
- package/Navigation/ScreenContainer.tsx +0 -38
- package/SizedBox/index.js +0 -23
- package/SizedBox/styles.js +0 -7
- package/TextInput/index.js +0 -225
- package/TextInput/styles.js +0 -55
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
import {useGridSystem, validateChildren} from './utils';
|
|
4
|
+
import SectionItem from './SectionItem';
|
|
5
|
+
import {ScreenSectionProps} from './types';
|
|
6
|
+
|
|
7
|
+
const ScreenSection: React.FC<ScreenSectionProps> = ({children}) => {
|
|
8
|
+
const grid = useGridSystem();
|
|
9
|
+
|
|
10
|
+
const renderOverlay = () => {
|
|
11
|
+
return (
|
|
12
|
+
<View
|
|
13
|
+
pointerEvents={'none'}
|
|
14
|
+
style={{
|
|
15
|
+
position: 'absolute',
|
|
16
|
+
top: 0,
|
|
17
|
+
bottom: 0,
|
|
18
|
+
left: 0,
|
|
19
|
+
right: 0,
|
|
20
|
+
borderColor: 'red',
|
|
21
|
+
borderWidth: 1,
|
|
22
|
+
}}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const addRowView = (
|
|
28
|
+
rows: any[],
|
|
29
|
+
cursor: number = 0,
|
|
30
|
+
endRow: boolean = false,
|
|
31
|
+
) => {
|
|
32
|
+
return (
|
|
33
|
+
<View
|
|
34
|
+
key={`SectionItem${cursor}`}
|
|
35
|
+
style={{
|
|
36
|
+
flexDirection: 'row',
|
|
37
|
+
marginBottom: endRow ? 0 : grid.gutterSize,
|
|
38
|
+
}}>
|
|
39
|
+
{rows.map((i: React.ReactElement, index: number) => {
|
|
40
|
+
return (
|
|
41
|
+
<View
|
|
42
|
+
key={`SectionItem${cursor}${index}`}
|
|
43
|
+
style={{flexDirection: 'row'}}>
|
|
44
|
+
{index != 0 && <View style={{width: grid.gutterSize}}></View>}
|
|
45
|
+
{i}
|
|
46
|
+
</View>
|
|
47
|
+
);
|
|
48
|
+
})}
|
|
49
|
+
</View>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const renderView = (
|
|
54
|
+
children: any,
|
|
55
|
+
): React.ReactElement | React.ReactElement[] => {
|
|
56
|
+
const element: React.ReactElement | React.ReactElement[] = [];
|
|
57
|
+
if (Array.isArray(children)) {
|
|
58
|
+
let cursor = 0;
|
|
59
|
+
let rows: any[] = [];
|
|
60
|
+
for (let i = 0; i < children.length; ++i) {
|
|
61
|
+
const item = children[i];
|
|
62
|
+
const totalSpan = rows
|
|
63
|
+
.concat([item])
|
|
64
|
+
.map(i => i.props?.widthSpan)
|
|
65
|
+
.reduce((previousValue, currentValue) => {
|
|
66
|
+
return previousValue + currentValue;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (totalSpan <= grid.numberOfColumns) {
|
|
70
|
+
rows.push(item);
|
|
71
|
+
} else {
|
|
72
|
+
cursor += 1;
|
|
73
|
+
element.push(addRowView(rows, cursor));
|
|
74
|
+
rows = [item];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (i == children.length - 1) {
|
|
78
|
+
cursor += 1;
|
|
79
|
+
element.push(addRowView(rows, cursor, true));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
element.push(children);
|
|
84
|
+
}
|
|
85
|
+
return element;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<View
|
|
90
|
+
style={{
|
|
91
|
+
width: grid.getSizeSpan(),
|
|
92
|
+
marginHorizontal: grid.screenPadding,
|
|
93
|
+
flexDirection: 'row',
|
|
94
|
+
flexWrap: 'wrap',
|
|
95
|
+
}}>
|
|
96
|
+
{renderView(validateChildren(children, SectionItem))}
|
|
97
|
+
{grid.isDevMode && renderOverlay()}
|
|
98
|
+
</View>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
ScreenSection.displayName = 'ScreenSection';
|
|
103
|
+
|
|
104
|
+
export default ScreenSection;
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
const renderOverlay = () => {
|
|
17
|
+
return (
|
|
18
|
+
<View
|
|
19
|
+
pointerEvents={'none'}
|
|
20
|
+
style={{
|
|
21
|
+
position: 'absolute',
|
|
22
|
+
top: 0,
|
|
23
|
+
bottom: 0,
|
|
24
|
+
left: 0,
|
|
25
|
+
right: 0,
|
|
26
|
+
borderColor: 'red',
|
|
27
|
+
borderWidth: 1,
|
|
28
|
+
}}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const styles: any = style ?? {};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<View
|
|
37
|
+
style={{
|
|
38
|
+
...styles,
|
|
39
|
+
width: grid.getSizeSpan(widthSpan),
|
|
40
|
+
height: heightSpan ? grid.getSizeSpan(heightSpan) : undefined,
|
|
41
|
+
overflow: 'hidden',
|
|
42
|
+
margin: undefined,
|
|
43
|
+
marginTop: undefined,
|
|
44
|
+
marginBottom: undefined,
|
|
45
|
+
marginLeft: undefined,
|
|
46
|
+
marginRight: undefined,
|
|
47
|
+
}}>
|
|
48
|
+
{children}
|
|
49
|
+
{grid.isDevMode && renderOverlay()}
|
|
50
|
+
</View>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
SectionItem.defaultProps = {
|
|
55
|
+
widthSpan: 12,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
SectionItem.displayName = 'SectionItem';
|
|
59
|
+
|
|
60
|
+
export default SectionItem;
|
package/Layout/index.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import SectionItem from './SectionItem';
|
|
2
|
+
import ScreenSection from './ScreenSection';
|
|
3
|
+
import GridSystem from './GridSystem';
|
|
4
|
+
import {useGridSystem, validateChildren} from './utils';
|
|
5
5
|
|
|
6
|
-
export {
|
|
6
|
+
export {
|
|
7
|
+
SectionItem,
|
|
8
|
+
ScreenSection,
|
|
9
|
+
GridSystem,
|
|
10
|
+
useGridSystem,
|
|
11
|
+
validateChildren,
|
|
12
|
+
};
|
package/Layout/types.ts
CHANGED
|
@@ -1,39 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {ViewProps} from 'react-native';
|
|
2
2
|
|
|
3
3
|
type SpanNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
4
|
-
type ViewAlignItems = 'flex-start' | 'flex-end' | 'center';
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
| 'flex-end'
|
|
9
|
-
| 'center'
|
|
10
|
-
| 'space-between'
|
|
11
|
-
| 'space-around'
|
|
12
|
-
| 'space-evenly';
|
|
13
|
-
|
|
14
|
-
type ViewDirection = 'row' | 'column';
|
|
15
|
-
|
|
16
|
-
type ViewShadow = 'none' | 'light' | 'dark';
|
|
17
|
-
export interface MMScreenProps {
|
|
18
|
-
children: ReactElement;
|
|
19
|
-
scrollable: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface MMSectionProps {
|
|
23
|
-
haveMargin?: boolean;
|
|
24
|
-
children: ReactElement;
|
|
5
|
+
export interface ScreenSectionProps extends ViewProps {
|
|
6
|
+
expanded?: boolean;
|
|
25
7
|
}
|
|
26
8
|
|
|
27
|
-
export interface
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
isEndLine?: boolean;
|
|
31
|
-
isRowChild?: boolean;
|
|
32
|
-
alignItems?: ViewAlignItems;
|
|
33
|
-
justifyContent: ViewJustifyContent;
|
|
34
|
-
padding: Array<number>;
|
|
35
|
-
backgroundColor: string;
|
|
36
|
-
borderRadius: number;
|
|
37
|
-
direction: ViewDirection;
|
|
38
|
-
shadow: ViewShadow;
|
|
9
|
+
export interface SectionItemProps extends ViewProps {
|
|
10
|
+
widthSpan: SpanNumber;
|
|
11
|
+
heightSpan?: SpanNumber;
|
|
39
12
|
}
|
package/Layout/utils.ts
CHANGED
|
@@ -1,37 +1,69 @@
|
|
|
1
|
-
import {Dimensions} from 'react-native';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
1
|
+
import {Alert, Dimensions} from 'react-native';
|
|
2
|
+
import React, {ReactElement} from 'react';
|
|
3
|
+
import {GutterSize, NumberOfColumns, ScreenPadding} from '../Consts';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const useGridSystem = (useMargin: boolean = true) => {
|
|
6
|
+
const isDevMode = false;
|
|
7
|
+
const gutterSize = GutterSize;
|
|
8
|
+
const screenPadding = useMargin ? ScreenPadding : 0;
|
|
9
|
+
const numberOfColumns = NumberOfColumns;
|
|
10
|
+
const widthDevice = Dimensions.get('window').width;
|
|
11
|
+
const parentWidth = widthDevice - screenPadding * 2;
|
|
12
|
+
const totalGutterSize = gutterSize * (numberOfColumns - 1);
|
|
13
|
+
const sizePerSpan = (parentWidth - totalGutterSize) / numberOfColumns;
|
|
6
14
|
|
|
7
|
-
|
|
15
|
+
const getSizeSpan = (span: number = numberOfColumns): number => {
|
|
16
|
+
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
17
|
+
};
|
|
8
18
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
19
|
+
return {
|
|
20
|
+
isDevMode,
|
|
21
|
+
gutterSize,
|
|
22
|
+
screenPadding,
|
|
23
|
+
numberOfColumns,
|
|
24
|
+
sizePerSpan,
|
|
25
|
+
getSizeSpan,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const validateChildren = (
|
|
29
|
+
children:
|
|
30
|
+
| React.ReactElement<any, string | React.JSXElementConstructor<any>>
|
|
13
31
|
| string
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
32
|
+
| number
|
|
33
|
+
| {}
|
|
34
|
+
| Iterable<React.ReactNode>
|
|
35
|
+
| React.ReactPortal
|
|
36
|
+
| null
|
|
37
|
+
| undefined
|
|
38
|
+
| boolean,
|
|
39
|
+
childrenType: React.FC<any>,
|
|
17
40
|
) => {
|
|
41
|
+
if (!__DEV__) return children;
|
|
42
|
+
let results: React.ReactElement[] = [];
|
|
18
43
|
if (Array.isArray(children)) {
|
|
19
|
-
|
|
44
|
+
results = children?.filter((child: ReactElement) => {
|
|
20
45
|
if (child?.type === childrenType) {
|
|
21
46
|
return child;
|
|
47
|
+
} else {
|
|
48
|
+
Alert.alert(
|
|
49
|
+
'Component Kits',
|
|
50
|
+
`Wrong children type for this component, expected is ${childrenType.displayName}.`,
|
|
51
|
+
);
|
|
22
52
|
}
|
|
23
|
-
console.error(
|
|
24
|
-
'Wrong children type for this container, please check document.',
|
|
25
|
-
);
|
|
26
|
-
return null;
|
|
27
53
|
});
|
|
28
54
|
} else {
|
|
29
|
-
|
|
30
|
-
|
|
55
|
+
const singleChild: any = children;
|
|
56
|
+
if (singleChild?.type === childrenType) {
|
|
57
|
+
results = [singleChild];
|
|
58
|
+
} else {
|
|
59
|
+
Alert.alert(
|
|
60
|
+
'Component Kits',
|
|
61
|
+
`Wrong children type for this component, expected is ${childrenType.displayName}.`,
|
|
62
|
+
);
|
|
31
63
|
}
|
|
32
|
-
console.error(
|
|
33
|
-
'Wrong children type for this container, please check document.',
|
|
34
|
-
);
|
|
35
|
-
return null;
|
|
36
64
|
}
|
|
65
|
+
|
|
66
|
+
return results;
|
|
37
67
|
};
|
|
68
|
+
|
|
69
|
+
export {useGridSystem, validateChildren};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React, {useContext} from 'react';
|
|
2
2
|
import {StatusBar, StyleSheet, View} from 'react-native';
|
|
3
|
-
import {
|
|
3
|
+
import {ApplicationContext, NavigationButton} from './index';
|
|
4
|
+
import {Styles} from '../Consts';
|
|
5
|
+
import {Image} from '../Image';
|
|
4
6
|
|
|
5
7
|
const styles = StyleSheet.create({
|
|
6
8
|
headerBackground: {
|
|
@@ -11,17 +13,23 @@ const styles = StyleSheet.create({
|
|
|
11
13
|
},
|
|
12
14
|
});
|
|
13
15
|
|
|
14
|
-
const HeaderBackground
|
|
15
|
-
const {theme} = useContext(
|
|
16
|
-
const source: any = theme.assets?.headerBackground;
|
|
16
|
+
const HeaderBackground = () => {
|
|
17
|
+
const {theme} = useContext(ApplicationContext);
|
|
17
18
|
return (
|
|
18
19
|
<View
|
|
19
20
|
style={[
|
|
20
21
|
Styles.flex,
|
|
21
|
-
{backgroundColor: theme.colors.background, overflow: 'hidden'},
|
|
22
|
+
{backgroundColor: theme.colors.background.surface, overflow: 'hidden'},
|
|
22
23
|
]}>
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
{theme.assets?.headerBackground && (
|
|
25
|
+
<>
|
|
26
|
+
<StatusBar barStyle="light-content" />
|
|
27
|
+
<Image
|
|
28
|
+
style={styles.headerBackground}
|
|
29
|
+
source={{uri: theme.assets?.headerBackground}}
|
|
30
|
+
/>
|
|
31
|
+
</>
|
|
32
|
+
)}
|
|
25
33
|
</View>
|
|
26
34
|
);
|
|
27
35
|
};
|
|
@@ -29,7 +37,7 @@ const HeaderBackground: React.FC<any> = () => {
|
|
|
29
37
|
const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
|
|
30
38
|
const validType = (item: any) => {
|
|
31
39
|
if (item.type !== NavigationButton) {
|
|
32
|
-
console.
|
|
40
|
+
console.warn(
|
|
33
41
|
'element type of NavigationButton, Please migrate to use NavigationButton of kits.',
|
|
34
42
|
);
|
|
35
43
|
}
|
|
@@ -6,20 +6,17 @@ import {
|
|
|
6
6
|
StyleSheet,
|
|
7
7
|
View,
|
|
8
8
|
} from 'react-native';
|
|
9
|
-
import {
|
|
10
|
-
ModalParams,
|
|
11
|
-
NavigationContext,
|
|
12
|
-
Radius,
|
|
13
|
-
SafeAreaView,
|
|
14
|
-
Styles,
|
|
15
|
-
useSafeAreaInsets,
|
|
16
|
-
} from '../index';
|
|
9
|
+
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
17
10
|
import {BottomSheetBackdrop, BottomSheetModal} from '@gorhom/bottom-sheet';
|
|
18
11
|
import {BottomSheetModalMethods} from '@gorhom/bottom-sheet/lib/typescript/types';
|
|
19
12
|
import Navigation from './Navigation';
|
|
13
|
+
import {ModalParams} from './types';
|
|
14
|
+
import {Radius, Spacing, Styles} from '../Consts';
|
|
15
|
+
import {ApplicationContext, NavigationContainer} from './index';
|
|
20
16
|
|
|
21
17
|
const ModalScreen: React.FC<any> = props => {
|
|
22
18
|
const {navigation, route} = props;
|
|
19
|
+
const {theme} = useContext(ApplicationContext);
|
|
23
20
|
const {isBottomSheet, screen, onRequestClose}: ModalParams = route.params;
|
|
24
21
|
const Component = useRef(screen).current;
|
|
25
22
|
const params = {
|
|
@@ -53,7 +50,16 @@ const ModalScreen: React.FC<any> = props => {
|
|
|
53
50
|
if (isBottomSheet) {
|
|
54
51
|
return (
|
|
55
52
|
<BottomSheet {...props} onDismiss={onDismiss}>
|
|
56
|
-
<
|
|
53
|
+
<View style={{height: '100%'}}>
|
|
54
|
+
<NavigationContainer
|
|
55
|
+
theme={{...theme, assets: undefined}}
|
|
56
|
+
screen={props => <Component {...params} {...props} />}
|
|
57
|
+
onDismiss={() => {
|
|
58
|
+
navigation.pop();
|
|
59
|
+
}}
|
|
60
|
+
isBottomSheet={isBottomSheet}
|
|
61
|
+
/>
|
|
62
|
+
</View>
|
|
57
63
|
</BottomSheet>
|
|
58
64
|
);
|
|
59
65
|
}
|
|
@@ -89,9 +95,8 @@ const ModalScreen: React.FC<any> = props => {
|
|
|
89
95
|
);
|
|
90
96
|
};
|
|
91
97
|
|
|
92
|
-
const BottomSheet: React.FC<
|
|
93
|
-
const {
|
|
94
|
-
const {theme} = useContext(NavigationContext);
|
|
98
|
+
const BottomSheet: React.FC<ModalParams> = ({children, onDismiss}) => {
|
|
99
|
+
const {theme} = useContext(ApplicationContext);
|
|
95
100
|
const snapPoints = useMemo(() => ['50%', '90%'], []);
|
|
96
101
|
const {bottom} = useSafeAreaInsets();
|
|
97
102
|
const bottomSheetRef = useRef<BottomSheetModalMethods>(null);
|
|
@@ -105,8 +110,14 @@ const BottomSheet: React.FC<any> = props => {
|
|
|
105
110
|
}, []);
|
|
106
111
|
|
|
107
112
|
const handleComponent = () => (
|
|
108
|
-
<View
|
|
109
|
-
|
|
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
|
+
/>
|
|
110
121
|
</View>
|
|
111
122
|
);
|
|
112
123
|
const backdropComponent = (backdropProps: any) => (
|
|
@@ -126,7 +137,11 @@ const BottomSheet: React.FC<any> = props => {
|
|
|
126
137
|
onDismiss={() => onDismiss?.(mountedRef.current)}
|
|
127
138
|
handleComponent={handleComponent}
|
|
128
139
|
backdropComponent={backdropComponent}>
|
|
129
|
-
<View
|
|
140
|
+
<View
|
|
141
|
+
style={{
|
|
142
|
+
paddingBottom: bottom,
|
|
143
|
+
backgroundColor: theme.colors.background.default,
|
|
144
|
+
}}>
|
|
130
145
|
{children}
|
|
131
146
|
</View>
|
|
132
147
|
</BottomSheetModal>
|
|
@@ -153,23 +168,18 @@ const styles = StyleSheet.create({
|
|
|
153
168
|
flex: 1,
|
|
154
169
|
minHeight: '10%',
|
|
155
170
|
},
|
|
156
|
-
|
|
171
|
+
indicatorContainer: {
|
|
172
|
+
width: '100%',
|
|
173
|
+
paddingTop: Spacing.S,
|
|
157
174
|
borderTopLeftRadius: Radius.M,
|
|
158
175
|
borderTopRightRadius: Radius.M,
|
|
159
176
|
overflow: 'hidden',
|
|
160
|
-
backgroundColor: 'blue',
|
|
161
|
-
},
|
|
162
|
-
indicatorContainer: {
|
|
163
|
-
width: '100%',
|
|
164
|
-
height: 4,
|
|
165
|
-
position: 'absolute',
|
|
166
|
-
top: -8,
|
|
167
|
-
flexDirection: 'row',
|
|
168
177
|
justifyContent: 'center',
|
|
178
|
+
alignItems: 'center',
|
|
169
179
|
},
|
|
170
180
|
indicator: {
|
|
171
181
|
width: 64,
|
|
172
|
-
height:
|
|
182
|
+
height: 4,
|
|
173
183
|
borderRadius: Radius.S,
|
|
174
184
|
},
|
|
175
185
|
});
|
package/Navigation/Navigation.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {NavigationProp} from '@react-navigation/native';
|
|
2
2
|
import {NavigationOptions} from './types';
|
|
3
|
-
import {HeaderRightAction} from './
|
|
3
|
+
import {HeaderRightAction} from './index';
|
|
4
4
|
|
|
5
5
|
class Navigation {
|
|
6
6
|
instance: NavigationProp<any>;
|
|
@@ -13,7 +13,7 @@ class Navigation {
|
|
|
13
13
|
if (params.headerRight) {
|
|
14
14
|
const headerRight = params.headerRight?.();
|
|
15
15
|
if (headerRight.type !== HeaderRightAction) {
|
|
16
|
-
console.
|
|
16
|
+
console.warn(
|
|
17
17
|
'headerRight not return element type of HeaderRightAction, Please migrate to use HeaderRightAction of kits.',
|
|
18
18
|
);
|
|
19
19
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {StyleSheet, TouchableOpacity} from 'react-native';
|
|
2
2
|
import React, {useContext} from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import {NavigationButtonProps} from './types';
|
|
4
|
+
import {ApplicationContext} from './index';
|
|
5
|
+
import {Icon} from '../Icon';
|
|
4
6
|
|
|
5
7
|
const NavigationButton: React.FC<NavigationButtonProps> = props => {
|
|
6
8
|
const {icon, tintColor, onPress} = props;
|
|
7
|
-
const {theme} = useContext(
|
|
9
|
+
const {theme} = useContext(ApplicationContext);
|
|
8
10
|
return (
|
|
9
11
|
<TouchableOpacity style={styles.container} onPress={onPress}>
|
|
10
|
-
<Icon
|
|
12
|
+
<Icon source={icon} color={tintColor ?? theme.colors.text.default} />
|
|
11
13
|
</TouchableOpacity>
|
|
12
14
|
);
|
|
13
15
|
};
|
|
@@ -1,31 +1,50 @@
|
|
|
1
|
-
import {
|
|
2
|
-
defaultContext,
|
|
3
|
-
NavigationContainerProps,
|
|
4
|
-
SafeAreaProvider,
|
|
5
|
-
} from '../index';
|
|
6
1
|
import React, {createContext, useRef} from 'react';
|
|
7
2
|
import {BottomSheetModalProvider} from '@gorhom/bottom-sheet';
|
|
3
|
+
import {SafeAreaProvider} from 'react-native-safe-area-context';
|
|
8
4
|
import {
|
|
9
5
|
NavigationContainer as ReactNavigationContainer,
|
|
10
6
|
NavigationContainerRef,
|
|
11
7
|
} from '@react-navigation/native';
|
|
12
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
createStackNavigator,
|
|
10
|
+
StackNavigationOptions,
|
|
11
|
+
} from '@react-navigation/stack';
|
|
13
12
|
import StackScreen from './StackScreen';
|
|
14
13
|
import ModalScreen from './ModalScreen';
|
|
15
14
|
import Navigator from './Navigator';
|
|
16
15
|
import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
|
|
16
|
+
import {GridSystem, useGridSystem} from '../Layout';
|
|
17
|
+
import {defaultContext, defaultTheme} from '../Consts';
|
|
18
|
+
import {NavigationContainerProps} from './types';
|
|
19
|
+
import {HeaderRightAction, NavigationButton} from './index';
|
|
17
20
|
|
|
18
21
|
const Stack = createStackNavigator();
|
|
19
22
|
|
|
20
|
-
const
|
|
23
|
+
const ApplicationContext = createContext(defaultContext);
|
|
21
24
|
const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
22
25
|
screen,
|
|
23
26
|
theme,
|
|
24
27
|
onDismiss,
|
|
28
|
+
isBottomSheet,
|
|
25
29
|
}) => {
|
|
30
|
+
const grid = useGridSystem();
|
|
26
31
|
const navigationRef = React.useRef<NavigationContainerRef>(null);
|
|
27
32
|
const navigator = useRef(new Navigator(navigationRef));
|
|
28
|
-
|
|
33
|
+
const themed: any = theme;
|
|
34
|
+
let options: StackNavigationOptions = {};
|
|
35
|
+
if (isBottomSheet) {
|
|
36
|
+
options = {
|
|
37
|
+
headerRight: (props: any) => (
|
|
38
|
+
<HeaderRightAction {...props}>
|
|
39
|
+
<NavigationButton
|
|
40
|
+
icon="24_navigation_close"
|
|
41
|
+
{...props}
|
|
42
|
+
onPress={onDismiss}
|
|
43
|
+
/>
|
|
44
|
+
</HeaderRightAction>
|
|
45
|
+
),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
29
48
|
const goBack = () => {
|
|
30
49
|
const canGoBack = navigationRef?.current?.canGoBack();
|
|
31
50
|
if (canGoBack) {
|
|
@@ -38,24 +57,41 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
38
57
|
return (
|
|
39
58
|
<SafeAreaProvider>
|
|
40
59
|
<BottomSheetModalProvider>
|
|
41
|
-
<
|
|
60
|
+
<ApplicationContext.Provider
|
|
42
61
|
value={{theme, navigator: navigator.current}}>
|
|
43
62
|
<ReactNavigationContainer
|
|
44
|
-
theme={
|
|
63
|
+
theme={themed}
|
|
45
64
|
ref={navigator.current?.ref}
|
|
46
65
|
independent={true}>
|
|
47
|
-
<Stack.Navigator initialRouteName="Stack">
|
|
66
|
+
<Stack.Navigator initialRouteName="Stack" headerMode="screen">
|
|
48
67
|
<Stack.Screen
|
|
49
68
|
name="Stack"
|
|
50
69
|
component={StackScreen}
|
|
51
|
-
initialParams={{screen}}
|
|
52
|
-
options={getStackOptions(theme,
|
|
70
|
+
initialParams={{screen, isBottomSheet}}
|
|
71
|
+
options={getStackOptions(theme, {
|
|
72
|
+
headerLeft: (props: any) => (
|
|
73
|
+
<NavigationButton
|
|
74
|
+
icon="ic_back"
|
|
75
|
+
{...props}
|
|
76
|
+
onPress={goBack}
|
|
77
|
+
/>
|
|
78
|
+
),
|
|
79
|
+
...options,
|
|
80
|
+
})}
|
|
53
81
|
/>
|
|
54
82
|
<Stack.Screen
|
|
55
83
|
name="Dialog"
|
|
56
84
|
component={StackScreen}
|
|
57
|
-
options={getDialogOptions(theme,
|
|
58
|
-
|
|
85
|
+
options={getDialogOptions(theme, {
|
|
86
|
+
headerLeft: props => (
|
|
87
|
+
<NavigationButton
|
|
88
|
+
icon="ic_back"
|
|
89
|
+
{...props}
|
|
90
|
+
onPress={goBack}
|
|
91
|
+
/>
|
|
92
|
+
),
|
|
93
|
+
})}
|
|
94
|
+
initialParams={{screen, isBottomSheet}}
|
|
59
95
|
/>
|
|
60
96
|
<Stack.Screen
|
|
61
97
|
name="Modal"
|
|
@@ -65,10 +101,16 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
65
101
|
/>
|
|
66
102
|
</Stack.Navigator>
|
|
67
103
|
</ReactNavigationContainer>
|
|
68
|
-
</
|
|
104
|
+
</ApplicationContext.Provider>
|
|
69
105
|
</BottomSheetModalProvider>
|
|
106
|
+
{grid.isDevMode && <GridSystem />}
|
|
70
107
|
</SafeAreaProvider>
|
|
71
108
|
);
|
|
72
109
|
};
|
|
73
110
|
|
|
74
|
-
|
|
111
|
+
NavigationContainer.defaultProps = {
|
|
112
|
+
theme: defaultTheme,
|
|
113
|
+
isBottomSheet: false,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export {ApplicationContext, NavigationContainer};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, {useLayoutEffect} from 'react';
|
|
2
2
|
import {ScreenParams} from './types';
|
|
3
3
|
import Navigation from './Navigation';
|
|
4
4
|
|
|
5
5
|
const StackScreen: React.FC<any> = props => {
|
|
6
6
|
const {route, navigation} = props;
|
|
7
|
-
const {screen: Component}: ScreenParams = route.params;
|
|
7
|
+
const {screen: Component, isBottomSheet}: ScreenParams = route.params;
|
|
8
8
|
|
|
9
9
|
const params = {
|
|
10
10
|
...route.params,
|
|
@@ -13,6 +13,12 @@ const StackScreen: React.FC<any> = props => {
|
|
|
13
13
|
|
|
14
14
|
delete params.screen;
|
|
15
15
|
|
|
16
|
+
useLayoutEffect(() => {
|
|
17
|
+
if (isBottomSheet && !navigation?.canGoBack()) {
|
|
18
|
+
navigation?.setOptions({headerLeft: null});
|
|
19
|
+
}
|
|
20
|
+
}, []);
|
|
21
|
+
|
|
16
22
|
return <Component {...params} />;
|
|
17
23
|
};
|
|
18
24
|
|