@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
|
@@ -5,10 +5,7 @@ import {
|
|
|
5
5
|
NavigationContainer as ReactNavigationContainer,
|
|
6
6
|
NavigationContainerRef,
|
|
7
7
|
} from '@react-navigation/native';
|
|
8
|
-
import {
|
|
9
|
-
createStackNavigator,
|
|
10
|
-
StackNavigationOptions,
|
|
11
|
-
} from '@react-navigation/stack';
|
|
8
|
+
import {createStackNavigator} from '@react-navigation/stack';
|
|
12
9
|
import StackScreen from './StackScreen';
|
|
13
10
|
import ModalScreen from './ModalScreen';
|
|
14
11
|
import Navigator from './Navigator';
|
|
@@ -16,7 +13,6 @@ import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
|
|
|
16
13
|
import {GridSystem, useGridSystem} from '../Layout';
|
|
17
14
|
import {defaultContext, defaultTheme} from '../Consts';
|
|
18
15
|
import {NavigationContainerProps} from './types';
|
|
19
|
-
import {HeaderRightAction, NavigationButton} from './index';
|
|
20
16
|
|
|
21
17
|
const Stack = createStackNavigator();
|
|
22
18
|
|
|
@@ -25,26 +21,14 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
25
21
|
screen,
|
|
26
22
|
theme,
|
|
27
23
|
onDismiss,
|
|
28
|
-
|
|
24
|
+
screenOptions,
|
|
25
|
+
hideBackFirst,
|
|
29
26
|
}) => {
|
|
30
27
|
const grid = useGridSystem();
|
|
31
28
|
const navigationRef = React.useRef<NavigationContainerRef>(null);
|
|
32
29
|
const navigator = useRef(new Navigator(navigationRef));
|
|
33
30
|
const themed: any = theme;
|
|
34
|
-
|
|
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
|
-
}
|
|
31
|
+
|
|
48
32
|
const goBack = () => {
|
|
49
33
|
const canGoBack = navigationRef?.current?.canGoBack();
|
|
50
34
|
if (canGoBack) {
|
|
@@ -67,31 +51,14 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
67
51
|
<Stack.Screen
|
|
68
52
|
name="Stack"
|
|
69
53
|
component={StackScreen}
|
|
70
|
-
initialParams={{screen,
|
|
71
|
-
options={getStackOptions(theme,
|
|
72
|
-
headerLeft: (props: any) => (
|
|
73
|
-
<NavigationButton
|
|
74
|
-
icon="ic_back"
|
|
75
|
-
{...props}
|
|
76
|
-
onPress={goBack}
|
|
77
|
-
/>
|
|
78
|
-
),
|
|
79
|
-
...options,
|
|
80
|
-
})}
|
|
54
|
+
initialParams={{screen, hideBackFirst}}
|
|
55
|
+
options={{...getStackOptions(theme, goBack), ...screenOptions}}
|
|
81
56
|
/>
|
|
82
57
|
<Stack.Screen
|
|
83
58
|
name="Dialog"
|
|
84
59
|
component={StackScreen}
|
|
85
|
-
options={getDialogOptions(theme,
|
|
86
|
-
|
|
87
|
-
<NavigationButton
|
|
88
|
-
icon="ic_back"
|
|
89
|
-
{...props}
|
|
90
|
-
onPress={goBack}
|
|
91
|
-
/>
|
|
92
|
-
),
|
|
93
|
-
})}
|
|
94
|
-
initialParams={{screen, isBottomSheet}}
|
|
60
|
+
options={getDialogOptions(theme, goBack)}
|
|
61
|
+
initialParams={{screen}}
|
|
95
62
|
/>
|
|
96
63
|
<Stack.Screen
|
|
97
64
|
name="Modal"
|
|
@@ -108,9 +75,4 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
108
75
|
);
|
|
109
76
|
};
|
|
110
77
|
|
|
111
|
-
NavigationContainer.defaultProps = {
|
|
112
|
-
theme: defaultTheme,
|
|
113
|
-
isBottomSheet: false,
|
|
114
|
-
};
|
|
115
|
-
|
|
116
78
|
export {ApplicationContext, NavigationContainer};
|
|
@@ -4,7 +4,7 @@ import Navigation from './Navigation';
|
|
|
4
4
|
|
|
5
5
|
const StackScreen: React.FC<any> = props => {
|
|
6
6
|
const {route, navigation} = props;
|
|
7
|
-
const {screen: Component,
|
|
7
|
+
const {screen: Component, hideBackFirst}: ScreenParams = route.params;
|
|
8
8
|
|
|
9
9
|
const params = {
|
|
10
10
|
...route.params,
|
|
@@ -14,7 +14,7 @@ const StackScreen: React.FC<any> = props => {
|
|
|
14
14
|
delete params.screen;
|
|
15
15
|
|
|
16
16
|
useLayoutEffect(() => {
|
|
17
|
-
if (
|
|
17
|
+
if (hideBackFirst && !navigation?.canGoBack()) {
|
|
18
18
|
navigation?.setOptions({headerLeft: null});
|
|
19
19
|
}
|
|
20
20
|
}, []);
|
package/Navigation/types.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {ViewProps} from 'react-native';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import Navigator from './Navigator';
|
|
4
4
|
import Navigation from './Navigation';
|
|
5
|
+
import {StackNavigationOptions} from '@react-navigation/stack';
|
|
5
6
|
|
|
6
7
|
export type Theme = {
|
|
7
8
|
dark: boolean;
|
|
@@ -65,7 +66,8 @@ export type Context = {
|
|
|
65
66
|
|
|
66
67
|
export type NavigationContainerProps = {
|
|
67
68
|
screen: React.ElementType;
|
|
68
|
-
|
|
69
|
+
screenOptions?: StackNavigationOptions;
|
|
70
|
+
hideBackFirst?: boolean;
|
|
69
71
|
theme: Theme;
|
|
70
72
|
onDismiss?: () => void;
|
|
71
73
|
};
|
|
@@ -88,7 +90,8 @@ export interface ModalParams extends ScreenParams {
|
|
|
88
90
|
[key: string]: any;
|
|
89
91
|
screen: React.ElementType;
|
|
90
92
|
onDismiss?: (mounted?: boolean) => void;
|
|
91
|
-
|
|
93
|
+
barrierDismissible?: boolean;
|
|
94
|
+
backgroundColor?: string;
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
export type NavigationButtonProps = {
|
|
@@ -98,7 +101,21 @@ export type NavigationButtonProps = {
|
|
|
98
101
|
};
|
|
99
102
|
|
|
100
103
|
export type NavigationOptions = {
|
|
104
|
+
surface?: boolean;
|
|
101
105
|
title?: string;
|
|
102
|
-
|
|
106
|
+
headerTitleAlign?: 'left' | 'center';
|
|
107
|
+
customTitle?: TitleCustomProps;
|
|
103
108
|
headerRight?: (props?: any) => React.ReactElement;
|
|
104
109
|
};
|
|
110
|
+
|
|
111
|
+
export type HeaderBackgroundProps = {
|
|
112
|
+
surface?: boolean;
|
|
113
|
+
image?: string;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type TitleCustomProps = {
|
|
117
|
+
title?: string;
|
|
118
|
+
subTitle?: string;
|
|
119
|
+
image?: string;
|
|
120
|
+
content?: React.ReactNode;
|
|
121
|
+
};
|
package/Navigation/utils.tsx
CHANGED
|
@@ -3,17 +3,17 @@ import {
|
|
|
3
3
|
StackNavigationOptions,
|
|
4
4
|
TransitionPresets,
|
|
5
5
|
} from '@react-navigation/stack';
|
|
6
|
-
import {HeaderBackground} from './Components';
|
|
7
|
-
import {Theme} from './types';
|
|
6
|
+
import {HeaderBackground, HeaderCustom} from './Components';
|
|
7
|
+
import {NavigationOptions, Theme} from './types';
|
|
8
8
|
import {Colors} from '../Consts';
|
|
9
|
-
import {NavigationButton} from './index';
|
|
10
9
|
import {Text} from '../Text';
|
|
10
|
+
import {NavigationButton} from './index';
|
|
11
11
|
|
|
12
12
|
const renderTitle = (props: any) => {
|
|
13
13
|
return (
|
|
14
14
|
<Text
|
|
15
15
|
{...props}
|
|
16
|
-
typography="
|
|
16
|
+
typography="header_default"
|
|
17
17
|
weight="bold"
|
|
18
18
|
color={props.tintColor}
|
|
19
19
|
/>
|
|
@@ -33,28 +33,32 @@ const getTintColor = (theme: Theme): any => {
|
|
|
33
33
|
|
|
34
34
|
const getStackOptions = (
|
|
35
35
|
theme: Theme,
|
|
36
|
-
|
|
36
|
+
goBack: () => void,
|
|
37
37
|
): StackNavigationOptions => {
|
|
38
38
|
return {
|
|
39
39
|
headerTitleAlign: 'center',
|
|
40
40
|
headerTitle: renderTitle,
|
|
41
41
|
headerBackground: HeaderBackground,
|
|
42
|
+
headerLeft: (props: any) => (
|
|
43
|
+
<NavigationButton icon="ic_back" {...props} onPress={goBack} />
|
|
44
|
+
),
|
|
42
45
|
...getTintColor(theme),
|
|
43
|
-
...options,
|
|
44
46
|
};
|
|
45
47
|
};
|
|
46
48
|
|
|
47
49
|
const getDialogOptions = (
|
|
48
50
|
theme: Theme,
|
|
49
|
-
|
|
51
|
+
goBack: () => void,
|
|
50
52
|
): StackNavigationOptions => {
|
|
51
53
|
return {
|
|
52
54
|
headerTitleAlign: 'center',
|
|
53
55
|
headerTitle: renderTitle,
|
|
56
|
+
headerLeft: (props: any) => (
|
|
57
|
+
<NavigationButton icon="ic_back" {...props} onPress={goBack} />
|
|
58
|
+
),
|
|
54
59
|
headerBackground: HeaderBackground,
|
|
55
60
|
...getTintColor(theme),
|
|
56
61
|
...TransitionPresets.ModalTransition,
|
|
57
|
-
...options,
|
|
58
62
|
};
|
|
59
63
|
};
|
|
60
64
|
|
|
@@ -83,4 +87,21 @@ const getModalOptions = (): StackNavigationOptions => {
|
|
|
83
87
|
};
|
|
84
88
|
};
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
const getOptions = (params: NavigationOptions) => {
|
|
91
|
+
let surfaceTheme = {};
|
|
92
|
+
let titleTheme = {};
|
|
93
|
+
if (params.surface) {
|
|
94
|
+
surfaceTheme = {
|
|
95
|
+
headerBackground: () => <HeaderBackground surface={true} />,
|
|
96
|
+
headerTintColor: undefined,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (params.customTitle) {
|
|
100
|
+
titleTheme = {
|
|
101
|
+
headerTitle: () => <HeaderCustom {...params.customTitle} />,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return {...params, ...surfaceTheme, ...titleTheme};
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export {getStackOptions, getDialogOptions, getModalOptions, getOptions};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import React, {FC, useContext, useEffect, useState} from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
import {CheckBox, Input, Radio, Text} from '@momo-kits/foundation';
|
|
4
|
+
import {PlaygroundProps, PropValue} from './types';
|
|
5
|
+
import styles from './styles';
|
|
6
|
+
import {Spacing} from '../Consts';
|
|
7
|
+
import {ApplicationContext} from '../Navigation';
|
|
8
|
+
|
|
9
|
+
const Playground: FC<PlaygroundProps> = ({params}) => {
|
|
10
|
+
const {theme} = useContext(ApplicationContext);
|
|
11
|
+
const {props} = params;
|
|
12
|
+
const [compProps, setCompProps] = useState<{[key: string]: any}>({});
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
initProps();
|
|
15
|
+
return () => {};
|
|
16
|
+
}, [props]);
|
|
17
|
+
|
|
18
|
+
const initProps = () => {
|
|
19
|
+
let newProps = {};
|
|
20
|
+
Object.keys(props).forEach(i => {
|
|
21
|
+
newProps = {...newProps, [i]: props[i].value};
|
|
22
|
+
});
|
|
23
|
+
setCompProps(newProps);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const onChangeOptions = (
|
|
27
|
+
value: string | boolean | undefined,
|
|
28
|
+
key: string,
|
|
29
|
+
) => {
|
|
30
|
+
const newProps = {...compProps, [key]: value};
|
|
31
|
+
setCompProps(newProps);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const onCheckUndefined = (value: boolean, key: string) => {
|
|
35
|
+
let newValue = !value ? undefined : props?.[key]?.value;
|
|
36
|
+
const newProps = {...compProps, [key]: newValue};
|
|
37
|
+
setCompProps(newProps);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const generateView = (key: string, prop: PropValue) => {
|
|
41
|
+
let PlayGroundView = <View />;
|
|
42
|
+
switch (prop.type) {
|
|
43
|
+
case 'enum': {
|
|
44
|
+
PlayGroundView = (
|
|
45
|
+
<View style={styles.radioView}>
|
|
46
|
+
{prop?.options?.map(option => {
|
|
47
|
+
return (
|
|
48
|
+
<Radio
|
|
49
|
+
label={option}
|
|
50
|
+
value={option}
|
|
51
|
+
onChange={() => onChangeOptions(option, key)}
|
|
52
|
+
groupValue={compProps?.[key]}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
})}
|
|
56
|
+
</View>
|
|
57
|
+
);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
case 'string': {
|
|
61
|
+
PlayGroundView = (
|
|
62
|
+
<Input
|
|
63
|
+
size={'small'}
|
|
64
|
+
floatingValue={key}
|
|
65
|
+
onChangeText={text => onChangeOptions(text, key)}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case 'bool': {
|
|
71
|
+
let label = compProps?.[key] === true ? 'True' : 'False';
|
|
72
|
+
if (compProps?.[key] === undefined) {
|
|
73
|
+
label = 'undefined';
|
|
74
|
+
}
|
|
75
|
+
PlayGroundView = (
|
|
76
|
+
<CheckBox
|
|
77
|
+
label={label}
|
|
78
|
+
value={compProps?.[key]}
|
|
79
|
+
onChange={value => onChangeOptions(value, key)}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<View
|
|
87
|
+
style={[
|
|
88
|
+
styles.propView,
|
|
89
|
+
{backgroundColor: theme.colors.background.surface},
|
|
90
|
+
]}>
|
|
91
|
+
<Text style={styles.propTitle} typography={'header_default'}>
|
|
92
|
+
{key}
|
|
93
|
+
</Text>
|
|
94
|
+
{PlayGroundView}
|
|
95
|
+
{typeof compProps?.[key] !== 'boolean' && (
|
|
96
|
+
<CheckBox
|
|
97
|
+
style={{marginTop: Spacing.M}}
|
|
98
|
+
label={'Is undefined'}
|
|
99
|
+
value={!compProps?.[key]}
|
|
100
|
+
onChange={value => onCheckUndefined(!value, key)}
|
|
101
|
+
/>
|
|
102
|
+
)}
|
|
103
|
+
</View>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const Component = params.component ?? <View />;
|
|
108
|
+
const propsKeys = Object.keys(props);
|
|
109
|
+
return (
|
|
110
|
+
<View>
|
|
111
|
+
<Text style={{marginBottom: Spacing.M}} typography={'title_s'}>
|
|
112
|
+
Component
|
|
113
|
+
</Text>
|
|
114
|
+
<View
|
|
115
|
+
style={[
|
|
116
|
+
styles.propView,
|
|
117
|
+
{backgroundColor: theme.colors.background.surface},
|
|
118
|
+
]}>
|
|
119
|
+
<Text typography={'header_default'}>{params.displayName}</Text>
|
|
120
|
+
<Component {...compProps} />
|
|
121
|
+
</View>
|
|
122
|
+
<Text style={{marginBottom: Spacing.M}} typography={'title_s'}>
|
|
123
|
+
Props
|
|
124
|
+
</Text>
|
|
125
|
+
{propsKeys.map(prop => {
|
|
126
|
+
return generateView(prop, props[prop]);
|
|
127
|
+
})}
|
|
128
|
+
</View>
|
|
129
|
+
);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export default Playground;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {StyleSheet} from 'react-native';
|
|
2
|
+
import {Colors, Radius, Spacing} from '../Consts';
|
|
3
|
+
|
|
4
|
+
export default StyleSheet.create({
|
|
5
|
+
radioView: {
|
|
6
|
+
flexDirection: 'row',
|
|
7
|
+
flexWrap: 'wrap',
|
|
8
|
+
alignItems: 'center',
|
|
9
|
+
},
|
|
10
|
+
propView: {
|
|
11
|
+
borderRadius: Radius.M,
|
|
12
|
+
padding: Spacing.M,
|
|
13
|
+
marginBottom: Spacing.M,
|
|
14
|
+
},
|
|
15
|
+
propTitle: {marginBottom: Spacing.S, textTransform: 'capitalize'},
|
|
16
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {ReactElement} from 'react';
|
|
2
|
+
|
|
3
|
+
export type PropValue = {
|
|
4
|
+
value: any;
|
|
5
|
+
options?: string[];
|
|
6
|
+
type: 'string' | 'enum' | 'bool';
|
|
7
|
+
description?: string;
|
|
8
|
+
};
|
|
9
|
+
export type PlaygroundProps = {
|
|
10
|
+
params: {
|
|
11
|
+
component: ReactElement;
|
|
12
|
+
displayName: string;
|
|
13
|
+
props: {[key: string]: PropValue};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import React, {useContext} from 'react';
|
|
2
|
+
import {StyleSheet, TouchableOpacity, View} from 'react-native';
|
|
3
|
+
import {PopupNotifyProps} from './types';
|
|
4
|
+
import {Radius, Spacing, Styles} from '../Consts';
|
|
5
|
+
import {Image} from '../Image';
|
|
6
|
+
import {Text} from '../Text';
|
|
7
|
+
import {ApplicationContext} from '../Navigation';
|
|
8
|
+
import {Button} from '../Button';
|
|
9
|
+
import {Icon} from '../Icon';
|
|
10
|
+
|
|
11
|
+
const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
12
|
+
image,
|
|
13
|
+
title,
|
|
14
|
+
description,
|
|
15
|
+
information,
|
|
16
|
+
secondary,
|
|
17
|
+
primary,
|
|
18
|
+
buttonDirection,
|
|
19
|
+
onIconClose,
|
|
20
|
+
}) => {
|
|
21
|
+
const {theme, navigator} = useContext(ApplicationContext);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* on action popup
|
|
25
|
+
* @param callback
|
|
26
|
+
*/
|
|
27
|
+
const onAction = (callback?: () => void) => {
|
|
28
|
+
navigator?.pop();
|
|
29
|
+
callback?.();
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* build main action of popup
|
|
34
|
+
*/
|
|
35
|
+
const buildAction = () => {
|
|
36
|
+
const renderRow = () => {
|
|
37
|
+
return (
|
|
38
|
+
<View style={Styles.row}>
|
|
39
|
+
{secondary?.title && (
|
|
40
|
+
<>
|
|
41
|
+
<View style={Styles.flex}>
|
|
42
|
+
<Button
|
|
43
|
+
title={secondary.title}
|
|
44
|
+
type="text"
|
|
45
|
+
size="medium"
|
|
46
|
+
onPress={() => {
|
|
47
|
+
onAction(secondary?.onPress);
|
|
48
|
+
}}
|
|
49
|
+
/>
|
|
50
|
+
</View>
|
|
51
|
+
<View style={styles.buttonSpace} />
|
|
52
|
+
</>
|
|
53
|
+
)}
|
|
54
|
+
<View style={Styles.flex}>
|
|
55
|
+
<Button
|
|
56
|
+
title={primary.title}
|
|
57
|
+
size="medium"
|
|
58
|
+
onPress={() => {
|
|
59
|
+
onAction(primary.onPress);
|
|
60
|
+
}}
|
|
61
|
+
/>
|
|
62
|
+
</View>
|
|
63
|
+
</View>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
const renderColumn = () => {
|
|
67
|
+
return (
|
|
68
|
+
<View style={Styles.columnCenter}>
|
|
69
|
+
<Button
|
|
70
|
+
title={primary.title}
|
|
71
|
+
size="medium"
|
|
72
|
+
onPress={() => {
|
|
73
|
+
onAction(primary.onPress);
|
|
74
|
+
}}
|
|
75
|
+
/>
|
|
76
|
+
{secondary?.title && (
|
|
77
|
+
<>
|
|
78
|
+
<View style={styles.buttonSpace} />
|
|
79
|
+
<Button
|
|
80
|
+
title={secondary.title}
|
|
81
|
+
type="text"
|
|
82
|
+
size="medium"
|
|
83
|
+
onPress={() => {
|
|
84
|
+
onAction(secondary?.onPress);
|
|
85
|
+
}}
|
|
86
|
+
/>
|
|
87
|
+
</>
|
|
88
|
+
)}
|
|
89
|
+
</View>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
if (buttonDirection == 'auto') {
|
|
94
|
+
if (
|
|
95
|
+
secondary?.title &&
|
|
96
|
+
(secondary.title.length > 12 || primary.title.length > 12)
|
|
97
|
+
) {
|
|
98
|
+
return renderColumn();
|
|
99
|
+
}
|
|
100
|
+
return renderRow();
|
|
101
|
+
}
|
|
102
|
+
if (buttonDirection == 'row') {
|
|
103
|
+
return renderRow();
|
|
104
|
+
}
|
|
105
|
+
return renderColumn();
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* build close action
|
|
110
|
+
*/
|
|
111
|
+
const buildCloseIcon = () => {
|
|
112
|
+
return (
|
|
113
|
+
<View style={styles.iconCloseContainer}>
|
|
114
|
+
<TouchableOpacity
|
|
115
|
+
onPress={() => onAction(onIconClose)}
|
|
116
|
+
style={[
|
|
117
|
+
styles.iconClose,
|
|
118
|
+
{
|
|
119
|
+
backgroundColor: theme.colors.text.default,
|
|
120
|
+
borderColor: theme.colors.background.surface,
|
|
121
|
+
},
|
|
122
|
+
]}>
|
|
123
|
+
<Icon
|
|
124
|
+
source="navigation_close"
|
|
125
|
+
color={theme.colors.background.surface}
|
|
126
|
+
size={14}
|
|
127
|
+
/>
|
|
128
|
+
</TouchableOpacity>
|
|
129
|
+
</View>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<View
|
|
135
|
+
style={[
|
|
136
|
+
styles.container,
|
|
137
|
+
{backgroundColor: theme.colors.background.surface},
|
|
138
|
+
]}>
|
|
139
|
+
{image && <Image source={{uri: image}} style={styles.image} />}
|
|
140
|
+
<View style={styles.content}>
|
|
141
|
+
<Text typography={'title_xs'} numberOfLines={1}>
|
|
142
|
+
{title}
|
|
143
|
+
</Text>
|
|
144
|
+
<View style={styles.description}>
|
|
145
|
+
<Text typography={'paragraph_default'} numberOfLines={3}>
|
|
146
|
+
{description}
|
|
147
|
+
</Text>
|
|
148
|
+
</View>
|
|
149
|
+
{information && (
|
|
150
|
+
<View style={styles.information}>
|
|
151
|
+
<Text typography={'description_xs'} numberOfLines={1}>
|
|
152
|
+
{information}
|
|
153
|
+
</Text>
|
|
154
|
+
</View>
|
|
155
|
+
)}
|
|
156
|
+
</View>
|
|
157
|
+
<View style={styles.contentAction}>{buildAction()}</View>
|
|
158
|
+
{buildCloseIcon()}
|
|
159
|
+
</View>
|
|
160
|
+
);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const styles = StyleSheet.create({
|
|
164
|
+
container: {
|
|
165
|
+
borderRadius: Radius.L,
|
|
166
|
+
},
|
|
167
|
+
image: {
|
|
168
|
+
borderTopLeftRadius: Radius.L,
|
|
169
|
+
borderTopRightRadius: Radius.L,
|
|
170
|
+
aspectRatio: 1.7777,
|
|
171
|
+
},
|
|
172
|
+
content: {padding: Spacing.XL},
|
|
173
|
+
description: {
|
|
174
|
+
marginTop: Spacing.S,
|
|
175
|
+
},
|
|
176
|
+
information: {
|
|
177
|
+
marginTop: Spacing.S,
|
|
178
|
+
},
|
|
179
|
+
contentAction: {
|
|
180
|
+
paddingHorizontal: Spacing.XL,
|
|
181
|
+
paddingBottom: Spacing.L,
|
|
182
|
+
},
|
|
183
|
+
buttonSpace: {
|
|
184
|
+
width: Spacing.S,
|
|
185
|
+
height: Spacing.S,
|
|
186
|
+
},
|
|
187
|
+
iconCloseContainer: {
|
|
188
|
+
position: 'absolute',
|
|
189
|
+
top: -Spacing.S,
|
|
190
|
+
right: -Spacing.S,
|
|
191
|
+
},
|
|
192
|
+
iconClose: {
|
|
193
|
+
width: 20,
|
|
194
|
+
height: 20,
|
|
195
|
+
alignItems: 'center',
|
|
196
|
+
justifyContent: 'center',
|
|
197
|
+
borderRadius: Radius.M,
|
|
198
|
+
borderWidth: 2,
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
PopupNotify.defaultProps = {
|
|
203
|
+
title: 'Title',
|
|
204
|
+
primary: {
|
|
205
|
+
title: 'Primary',
|
|
206
|
+
onPress: () => {},
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export default PopupNotify;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React, {useContext} from 'react';
|
|
2
|
+
import {StyleSheet, View} from 'react-native';
|
|
3
|
+
import {PopupPromotionProps} from './types';
|
|
4
|
+
import {ApplicationContext} from '../Navigation';
|
|
5
|
+
import {Image} from '../Image';
|
|
6
|
+
import {Button} from '../Button';
|
|
7
|
+
import {Spacing} from '../Consts';
|
|
8
|
+
|
|
9
|
+
const PopupPromotion: React.FC<PopupPromotionProps> = ({
|
|
10
|
+
image,
|
|
11
|
+
primary,
|
|
12
|
+
onIconClose,
|
|
13
|
+
}) => {
|
|
14
|
+
const {theme, navigator} = useContext(ApplicationContext);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* on action popup
|
|
18
|
+
* @param callback
|
|
19
|
+
*/
|
|
20
|
+
const onAction = (callback?: () => void) => {
|
|
21
|
+
navigator?.pop();
|
|
22
|
+
callback?.();
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
<Image
|
|
28
|
+
style={styles.container}
|
|
29
|
+
source={{
|
|
30
|
+
uri: image,
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
<View style={styles.actionContainer}>
|
|
34
|
+
<Button
|
|
35
|
+
title={primary?.title}
|
|
36
|
+
onPress={() => {
|
|
37
|
+
onAction(primary?.onPress);
|
|
38
|
+
}}
|
|
39
|
+
/>
|
|
40
|
+
</View>
|
|
41
|
+
</>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const styles = StyleSheet.create({
|
|
46
|
+
container: {
|
|
47
|
+
aspectRatio: 0.66,
|
|
48
|
+
},
|
|
49
|
+
actionContainer: {
|
|
50
|
+
position: 'absolute',
|
|
51
|
+
bottom: 0,
|
|
52
|
+
width: '100%',
|
|
53
|
+
paddingVertical: Spacing.XL,
|
|
54
|
+
paddingHorizontal: Spacing.L,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
PopupPromotion.defaultProps = {
|
|
59
|
+
image: 'https://google.com',
|
|
60
|
+
primary: {
|
|
61
|
+
title: 'Primary',
|
|
62
|
+
onPress: () => {},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default PopupPromotion;
|
package/Popup/index.tsx
ADDED