@momo-kits/foundation 0.81.1-beta.6 → 0.81.1-optimize.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/Application/BottomTab.tsx +76 -23
- package/Application/Components.tsx +243 -198
- package/Application/ModalScreen.tsx +20 -65
- package/Application/Navigation.ts +15 -4
- package/Application/NavigationContainer.tsx +20 -20
- package/Application/Navigator.ts +61 -28
- package/Application/StackScreen.tsx +41 -23
- package/Application/index.ts +16 -6
- package/Application/types.ts +34 -19
- package/Application/utils.tsx +26 -0
- package/Assets/icon.json +83 -5
- package/Assets/icon_bank.json +506 -0
- package/Assets/language.json +3 -1
- package/Badge/Badge.tsx +56 -0
- package/Badge/BadgeDot.tsx +11 -0
- package/Badge/BadgeRibbon.tsx +125 -0
- package/Badge/Shape.tsx +29 -0
- package/Badge/index.tsx +7 -0
- package/Badge/styles.ts +58 -0
- package/Badge/types.ts +63 -0
- package/Button/index.tsx +26 -9
- package/Button/styles.ts +19 -0
- package/CheckBox/index.tsx +1 -2
- package/Consts/colors+spacing+radius.ts +3 -3
- package/Icon/index.tsx +7 -3
- package/Icon/types.ts +3 -3
- package/IconButton/index.tsx +0 -1
- package/Image/index.tsx +39 -49
- package/Image/styles.ts +1 -9
- package/Image/types.ts +3 -1
- package/Input/Input.tsx +37 -16
- package/Input/InputDropDown.tsx +5 -14
- package/Input/InputMoney.tsx +28 -11
- package/Input/InputOTP.tsx +169 -145
- package/Input/InputSearch.tsx +9 -13
- package/Input/InputTextArea.tsx +6 -12
- package/Input/common.tsx +5 -3
- package/Input/index.tsx +15 -9
- package/Input/styles.ts +1 -4
- package/Layout/Card.tsx +20 -11
- package/Layout/GridSystem.tsx +1 -2
- package/Layout/Item.tsx +0 -1
- package/Layout/ItemList.tsx +39 -40
- package/Layout/ItemSectionList.tsx +39 -0
- package/Layout/Screen.tsx +96 -45
- package/Layout/Section.tsx +17 -19
- package/Layout/index.ts +2 -1
- package/Layout/styles.ts +16 -15
- package/Layout/types.ts +2 -5
- package/Pagination/PaginationNumber.tsx +1 -1
- package/Pagination/PaginationScroll.tsx +0 -1
- package/Popup/PopupNotify.tsx +71 -14
- package/Popup/PopupPromotion.tsx +43 -6
- package/Popup/types.ts +12 -3
- package/Radio/index.tsx +1 -2
- package/Skeleton/index.tsx +1 -1
- package/Switch/index.tsx +0 -1
- package/Tag/index.tsx +2 -4
- package/Text/index.tsx +3 -2
- package/Text/styles.ts +38 -0
- package/Text/types.ts +25 -13
- package/Title/index.tsx +82 -38
- package/Title/styles.ts +16 -10
- package/Title/types.ts +2 -1
- package/index.ts +2 -0
- package/package.json +6 -6
- package/verify.js +15 -0
package/Input/InputTextArea.tsx
CHANGED
|
@@ -29,12 +29,12 @@ const InputTextArea = forwardRef(
|
|
|
29
29
|
floatingValue,
|
|
30
30
|
onFocus,
|
|
31
31
|
onBlur,
|
|
32
|
-
disabled,
|
|
32
|
+
disabled = false,
|
|
33
33
|
value,
|
|
34
34
|
defaultValue,
|
|
35
35
|
height,
|
|
36
36
|
placeholder,
|
|
37
|
-
maxLength,
|
|
37
|
+
maxLength = MAX_LENGTH,
|
|
38
38
|
required,
|
|
39
39
|
errorSpacing,
|
|
40
40
|
style,
|
|
@@ -46,7 +46,6 @@ const InputTextArea = forwardRef(
|
|
|
46
46
|
const [focused, setFocused] = useState(false);
|
|
47
47
|
const [inputValue, setInputValue] = useState(defaultValue ?? '');
|
|
48
48
|
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
49
|
-
const accessibilityLabel = `InputTextArea/${floatingValue ?? placeholder}`;
|
|
50
49
|
|
|
51
50
|
const onClearText = () => {
|
|
52
51
|
inputRef?.current?.clear();
|
|
@@ -71,7 +70,9 @@ const InputTextArea = forwardRef(
|
|
|
71
70
|
const renderCountingView = () => {
|
|
72
71
|
return (
|
|
73
72
|
<View style={styles.countingView}>
|
|
74
|
-
<Text
|
|
73
|
+
<Text
|
|
74
|
+
color={theme.colors.text.hint}
|
|
75
|
+
typography={'description_xs_regular'}>
|
|
75
76
|
{`${inputValue.length}/${maxLength}`}
|
|
76
77
|
</Text>
|
|
77
78
|
</View>
|
|
@@ -108,7 +109,6 @@ const InputTextArea = forwardRef(
|
|
|
108
109
|
<View style={styles.textAreaView}>
|
|
109
110
|
<TextInput
|
|
110
111
|
{...props}
|
|
111
|
-
accessibilityLabel={accessibilityLabel}
|
|
112
112
|
ref={inputRef}
|
|
113
113
|
editable={!disabled}
|
|
114
114
|
textAlignVertical="top"
|
|
@@ -148,9 +148,7 @@ const InputTextArea = forwardRef(
|
|
|
148
148
|
};
|
|
149
149
|
|
|
150
150
|
return (
|
|
151
|
-
<View
|
|
152
|
-
style={[style, styles.wrapper]}
|
|
153
|
-
accessibilityLabel={accessibilityLabel}>
|
|
151
|
+
<View style={[style, styles.wrapper]}>
|
|
154
152
|
{renderInputView()}
|
|
155
153
|
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
156
154
|
</View>
|
|
@@ -158,8 +156,4 @@ const InputTextArea = forwardRef(
|
|
|
158
156
|
},
|
|
159
157
|
);
|
|
160
158
|
|
|
161
|
-
InputTextArea.defaultProps = {
|
|
162
|
-
maxLength: MAX_LENGTH,
|
|
163
|
-
};
|
|
164
|
-
|
|
165
159
|
export default InputTextArea;
|
package/Input/common.tsx
CHANGED
|
@@ -64,7 +64,7 @@ export const ErrorView: FC<{errorMessage?: string; errorSpacing?: boolean}> = ({
|
|
|
64
64
|
style={Styles.flex}
|
|
65
65
|
color={errorColor}
|
|
66
66
|
numberOfLines={2}
|
|
67
|
-
typography={'
|
|
67
|
+
typography={'description_default_regular'}>
|
|
68
68
|
{errorMessage}
|
|
69
69
|
</Text>
|
|
70
70
|
</View>
|
|
@@ -104,10 +104,12 @@ export const FloatingView: FC<FloatingViewProps> = ({
|
|
|
104
104
|
},
|
|
105
105
|
style,
|
|
106
106
|
]}>
|
|
107
|
-
<Text color={floatingTextColor} typography={'
|
|
107
|
+
<Text color={floatingTextColor} typography={'label_s_medium'}>
|
|
108
108
|
{floatingValue}
|
|
109
109
|
{required && (
|
|
110
|
-
<Text
|
|
110
|
+
<Text
|
|
111
|
+
typography={'label_s_medium'}
|
|
112
|
+
color={theme.colors.error.primary}>
|
|
111
113
|
*
|
|
112
114
|
</Text>
|
|
113
115
|
)}
|
package/Input/index.tsx
CHANGED
|
@@ -76,6 +76,10 @@ export interface InputProps extends TextInputProps {
|
|
|
76
76
|
* Optional. Represents the color of the leading icon in the Input component.
|
|
77
77
|
*/
|
|
78
78
|
leadingIconColor?: string;
|
|
79
|
+
|
|
80
|
+
fontWeight?: 'Regular' | 'Bold';
|
|
81
|
+
|
|
82
|
+
onPressIcon?: () => void;
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
type InputPropsWithoutSizeAndIcon = Omit<
|
|
@@ -83,10 +87,6 @@ type InputPropsWithoutSizeAndIcon = Omit<
|
|
|
83
87
|
'size' | 'icon' | 'iconColor'
|
|
84
88
|
>;
|
|
85
89
|
|
|
86
|
-
type InputPropsOmitForSearch = Omit<
|
|
87
|
-
InputProps,
|
|
88
|
-
'required' | 'size' | 'errorMessage' | 'disabled'
|
|
89
|
-
>;
|
|
90
90
|
type InputPropsWithoutPlaceholder = Omit<InputProps, 'placeholder'>;
|
|
91
91
|
|
|
92
92
|
export interface InputTextAreaProps extends InputPropsWithoutSizeAndIcon {
|
|
@@ -97,7 +97,7 @@ export interface InputTextAreaProps extends InputPropsWithoutSizeAndIcon {
|
|
|
97
97
|
height?: number;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
export interface InputSearchProps extends
|
|
100
|
+
export interface InputSearchProps extends TextInputProps {
|
|
101
101
|
/**
|
|
102
102
|
* Optional. Represents the text to be displayed on the search button within the InputSearch component.
|
|
103
103
|
*/
|
|
@@ -109,13 +109,19 @@ export interface InputSearchProps extends InputPropsOmitForSearch {
|
|
|
109
109
|
*/
|
|
110
110
|
showButtonText?: boolean;
|
|
111
111
|
|
|
112
|
+
onPressButtonText?: () => void;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Optional. Represents the color of the icon in the Input component.
|
|
116
|
+
*/
|
|
117
|
+
iconColor?: string;
|
|
118
|
+
|
|
112
119
|
/**
|
|
113
|
-
* Optional.
|
|
114
|
-
* Defaults to `true` if not provided.
|
|
120
|
+
* Optional. Represents the name or key of the icon to be displayed in the Input component.
|
|
115
121
|
*/
|
|
116
|
-
|
|
122
|
+
icon?: string;
|
|
117
123
|
|
|
118
|
-
|
|
124
|
+
hasColorBG?: boolean
|
|
119
125
|
}
|
|
120
126
|
|
|
121
127
|
export interface InputMoneyProps extends InputPropsWithoutPlaceholder {}
|
package/Input/styles.ts
CHANGED
|
@@ -7,7 +7,6 @@ export default StyleSheet.create({
|
|
|
7
7
|
input: {
|
|
8
8
|
flex: 1,
|
|
9
9
|
paddingLeft: Spacing.M,
|
|
10
|
-
height: '100%',
|
|
11
10
|
fontSize: scaleSize(15),
|
|
12
11
|
},
|
|
13
12
|
wrapper: {
|
|
@@ -54,8 +53,7 @@ export default StyleSheet.create({
|
|
|
54
53
|
marginRight: Spacing.M,
|
|
55
54
|
},
|
|
56
55
|
icon: {
|
|
57
|
-
|
|
58
|
-
height: 24,
|
|
56
|
+
marginLeft: Spacing.S
|
|
59
57
|
},
|
|
60
58
|
iconWrapper: {
|
|
61
59
|
width: 24,
|
|
@@ -102,7 +100,6 @@ export default StyleSheet.create({
|
|
|
102
100
|
searchInputWrapper: {
|
|
103
101
|
flexDirection: 'row',
|
|
104
102
|
borderRadius: Radius.XL,
|
|
105
|
-
borderWidth: 1,
|
|
106
103
|
paddingHorizontal: Spacing.S,
|
|
107
104
|
alignItems: 'center',
|
|
108
105
|
flex: 1,
|
package/Layout/Card.tsx
CHANGED
|
@@ -7,7 +7,7 @@ import Item from './Item';
|
|
|
7
7
|
import {Image} from '../Image';
|
|
8
8
|
import {ApplicationContext} from '../Application';
|
|
9
9
|
import styles from './styles';
|
|
10
|
-
import {Colors, Shadow, Spacing} from '../Consts';
|
|
10
|
+
import {Colors, Radius, Shadow, Spacing} from '../Consts';
|
|
11
11
|
import ItemList from './ItemList';
|
|
12
12
|
|
|
13
13
|
export interface CardProps extends ViewProps {
|
|
@@ -27,8 +27,9 @@ const Card: React.FC<CardProps> = ({
|
|
|
27
27
|
style,
|
|
28
28
|
backgroundImage,
|
|
29
29
|
useShadow = false,
|
|
30
|
+
...props
|
|
30
31
|
}) => {
|
|
31
|
-
const {showGrid} = useContext(ApplicationContext);
|
|
32
|
+
const {showGrid, theme} = useContext(ApplicationContext);
|
|
32
33
|
const {numberOfColumns} = useGridSystem();
|
|
33
34
|
|
|
34
35
|
const gutterSize = 8;
|
|
@@ -41,12 +42,12 @@ const Card: React.FC<CardProps> = ({
|
|
|
41
42
|
const gridContext: GridContextProps = {
|
|
42
43
|
numberOfColumns,
|
|
43
44
|
gutterSize,
|
|
44
|
-
margin,
|
|
45
45
|
sizePerSpan,
|
|
46
46
|
getSizeSpan: span => {
|
|
47
47
|
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
48
48
|
},
|
|
49
49
|
};
|
|
50
|
+
|
|
50
51
|
/**
|
|
51
52
|
* render overlay only dev mode
|
|
52
53
|
*/
|
|
@@ -107,8 +108,9 @@ const Card: React.FC<CardProps> = ({
|
|
|
107
108
|
if (Array.isArray(children)) {
|
|
108
109
|
let cursor = 0;
|
|
109
110
|
let rows: any[] = [];
|
|
110
|
-
|
|
111
|
-
|
|
111
|
+
const arrayChild = children.filter(item => !!item);
|
|
112
|
+
for (let i = 0; i < arrayChild.length; ++i) {
|
|
113
|
+
const item = arrayChild[i];
|
|
112
114
|
const totalSpan = rows
|
|
113
115
|
.concat([item])
|
|
114
116
|
.map(i => i.props?.widthSpan)
|
|
@@ -124,7 +126,7 @@ const Card: React.FC<CardProps> = ({
|
|
|
124
126
|
rows = [item];
|
|
125
127
|
}
|
|
126
128
|
|
|
127
|
-
if (i ==
|
|
129
|
+
if (i == arrayChild.length - 1) {
|
|
128
130
|
cursor += 1;
|
|
129
131
|
element.push(addRowView(rows, cursor, true));
|
|
130
132
|
}
|
|
@@ -138,25 +140,32 @@ const Card: React.FC<CardProps> = ({
|
|
|
138
140
|
return element;
|
|
139
141
|
};
|
|
140
142
|
|
|
141
|
-
const {theme} = useContext(ApplicationContext);
|
|
142
143
|
return (
|
|
143
144
|
<GridContext.Provider value={gridContext}>
|
|
144
145
|
<View
|
|
145
|
-
|
|
146
|
+
{...props}
|
|
146
147
|
style={[
|
|
148
|
+
{backgroundColor: theme.colors.background.surface},
|
|
147
149
|
style,
|
|
150
|
+
styles.protectedStyle,
|
|
148
151
|
styles.card,
|
|
149
152
|
{
|
|
150
153
|
width: widthSection,
|
|
151
|
-
marginHorizontal:
|
|
152
|
-
backgroundColor: theme.colors.background.surface,
|
|
154
|
+
marginHorizontal: margin,
|
|
153
155
|
},
|
|
156
|
+
!!backgroundImage && {backgroundColor: undefined},
|
|
154
157
|
useShadow && Shadow.Light,
|
|
155
158
|
]}>
|
|
156
159
|
{!!backgroundImage && (
|
|
157
160
|
<Image
|
|
158
161
|
source={{uri: backgroundImage}}
|
|
159
|
-
style={
|
|
162
|
+
style={[
|
|
163
|
+
styles.imageBackground,
|
|
164
|
+
{
|
|
165
|
+
width: widthSection,
|
|
166
|
+
borderRadius: Radius.M,
|
|
167
|
+
},
|
|
168
|
+
]}
|
|
160
169
|
/>
|
|
161
170
|
)}
|
|
162
171
|
{renderView(validateChildren(children, [Item, ItemList]))}
|
package/Layout/GridSystem.tsx
CHANGED
|
@@ -24,7 +24,6 @@ const GridSystem: React.FC<any> = ({
|
|
|
24
24
|
const grid: GridContextProps = {
|
|
25
25
|
numberOfColumns,
|
|
26
26
|
gutterSize,
|
|
27
|
-
margin,
|
|
28
27
|
sizePerSpan,
|
|
29
28
|
getSizeSpan: span => {
|
|
30
29
|
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
@@ -46,7 +45,7 @@ const GridSystem: React.FC<any> = ({
|
|
|
46
45
|
screenGrid && insets,
|
|
47
46
|
{
|
|
48
47
|
borderColor: theme.colors.error.primary,
|
|
49
|
-
marginHorizontal:
|
|
48
|
+
marginHorizontal: margin,
|
|
50
49
|
top: Spacing.M,
|
|
51
50
|
bottom: Spacing.M,
|
|
52
51
|
},
|
package/Layout/Item.tsx
CHANGED
package/Layout/ItemList.tsx
CHANGED
|
@@ -1,56 +1,55 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {forwardRef, useContext} from 'react';
|
|
2
2
|
import {FlatList, FlatListProps, View} from 'react-native';
|
|
3
3
|
import Item, {SpanNumber} from './Item';
|
|
4
4
|
import {GridContext} from './index';
|
|
5
5
|
import styles from './styles';
|
|
6
6
|
|
|
7
7
|
export interface ItemListProps extends FlatListProps<any> {
|
|
8
|
-
/**
|
|
9
|
-
* Require key support number columns change grid system
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
key: string;
|
|
13
8
|
/**
|
|
14
9
|
* Represents the width of the Card component in terms of span numbers (1-12).
|
|
15
10
|
*/
|
|
16
11
|
widthSpan?: SpanNumber;
|
|
17
12
|
}
|
|
18
13
|
|
|
19
|
-
const ItemList
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
14
|
+
const ItemList = forwardRef(
|
|
15
|
+
(
|
|
16
|
+
{
|
|
17
|
+
renderItem,
|
|
18
|
+
widthSpan,
|
|
19
|
+
style,
|
|
20
|
+
contentContainerStyle,
|
|
21
|
+
...props
|
|
22
|
+
}: ItemListProps,
|
|
23
|
+
ref,
|
|
24
|
+
) => {
|
|
25
|
+
const {gutterSize, numberOfColumns} = useContext(GridContext);
|
|
26
|
+
const widthItem = (widthSpan ?? numberOfColumns) as SpanNumber;
|
|
27
|
+
const numColumns = Math.floor(numberOfColumns / widthItem);
|
|
28
|
+
const indexBegin = props?.data?.map((_i, index) => index * numColumns);
|
|
29
|
+
const _renderItem = (item: any) => {
|
|
30
|
+
if (indexBegin?.includes(item?.index)) {
|
|
31
|
+
return <Item widthSpan={widthItem}>{renderItem?.(item)}</Item>;
|
|
32
|
+
}
|
|
33
|
+
return (
|
|
34
|
+
<View style={{paddingLeft: gutterSize}}>
|
|
35
|
+
<Item widthSpan={widthItem}>{renderItem?.(item)}</Item>
|
|
36
|
+
</View>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
35
40
|
return (
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
<FlatList
|
|
42
|
+
ref={ref as React.RefObject<FlatList>}
|
|
43
|
+
{...props}
|
|
44
|
+
numColumns={numColumns}
|
|
45
|
+
renderItem={_renderItem}
|
|
46
|
+
horizontal={false}
|
|
47
|
+
ItemSeparatorComponent={() => <View style={{height: gutterSize}} />}
|
|
48
|
+
style={[style, styles.protectedStyle]}
|
|
49
|
+
contentContainerStyle={[contentContainerStyle, styles.protectedStyle]}
|
|
50
|
+
/>
|
|
39
51
|
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<FlatList
|
|
44
|
-
{...props}
|
|
45
|
-
key={`${key ?? 'ItemList'}${numColumns}}`}
|
|
46
|
-
numColumns={numColumns}
|
|
47
|
-
renderItem={_renderItem}
|
|
48
|
-
horizontal={false}
|
|
49
|
-
ItemSeparatorComponent={() => <View style={{height: gutterSize}} />}
|
|
50
|
-
style={[style, styles.protectedStyle]}
|
|
51
|
-
contentContainerStyle={[contentContainerStyle, styles.protectedStyle]}
|
|
52
|
-
/>
|
|
53
|
-
);
|
|
54
|
-
};
|
|
52
|
+
},
|
|
53
|
+
);
|
|
55
54
|
|
|
56
55
|
export default ItemList;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, {FC, useContext} from 'react';
|
|
2
|
+
import {SectionList, SectionListProps, View} from 'react-native';
|
|
3
|
+
import Item, {SpanNumber} from './Item';
|
|
4
|
+
import {GridContext} from './index';
|
|
5
|
+
import styles from './styles';
|
|
6
|
+
|
|
7
|
+
export interface ItemSectionListProps extends SectionListProps<any> {
|
|
8
|
+
/**
|
|
9
|
+
* Represents the width of the Card component in terms of span numbers (1-12).
|
|
10
|
+
*/
|
|
11
|
+
widthSpan?: SpanNumber;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const ItemSectionList: FC<ItemSectionListProps> = ({
|
|
15
|
+
renderItem,
|
|
16
|
+
widthSpan,
|
|
17
|
+
style,
|
|
18
|
+
contentContainerStyle,
|
|
19
|
+
...props
|
|
20
|
+
}) => {
|
|
21
|
+
const {gutterSize, numberOfColumns} = useContext(GridContext);
|
|
22
|
+
const widthItem = (widthSpan ?? numberOfColumns) as SpanNumber;
|
|
23
|
+
const _renderItem = (item: any) => {
|
|
24
|
+
return <Item widthSpan={widthItem}>{renderItem?.(item)}</Item>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<SectionList
|
|
29
|
+
{...props}
|
|
30
|
+
renderItem={_renderItem}
|
|
31
|
+
horizontal={false}
|
|
32
|
+
ItemSeparatorComponent={() => <View style={{height: gutterSize}} />}
|
|
33
|
+
style={[style, styles.protectedStyle]}
|
|
34
|
+
contentContainerStyle={[contentContainerStyle, styles.protectedStyle]}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default ItemSectionList;
|
package/Layout/Screen.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import {useHeaderHeight} from '@react-navigation/stack';
|
|
|
12
12
|
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
13
13
|
import React, {
|
|
14
14
|
forwardRef,
|
|
15
|
+
Fragment,
|
|
15
16
|
ReactNode,
|
|
16
17
|
useContext,
|
|
17
18
|
useEffect,
|
|
@@ -28,6 +29,7 @@ import Navigation from '../Application/Navigation';
|
|
|
28
29
|
import styles from './styles';
|
|
29
30
|
import {AnimatedHeader, NavigationOptions} from '../Application/types';
|
|
30
31
|
import {Image} from '../Image';
|
|
32
|
+
import {HeaderType} from './types';
|
|
31
33
|
|
|
32
34
|
export interface ScreenProps extends ViewProps {
|
|
33
35
|
children: React.ReactNode;
|
|
@@ -47,9 +49,9 @@ export interface ScreenProps extends ViewProps {
|
|
|
47
49
|
scrollable?: boolean;
|
|
48
50
|
|
|
49
51
|
/**
|
|
50
|
-
* Optional.
|
|
52
|
+
* Optional. Set type of header.
|
|
51
53
|
*/
|
|
52
|
-
|
|
54
|
+
headerType?: HeaderType;
|
|
53
55
|
|
|
54
56
|
/**
|
|
55
57
|
* Optional. Props for the animated component or bool used top navigation animated.
|
|
@@ -89,13 +91,13 @@ const Screen = forwardRef(
|
|
|
89
91
|
enableKeyboardAvoidingView = false,
|
|
90
92
|
scrollable = false,
|
|
91
93
|
navigation,
|
|
92
|
-
useExtendedHeader,
|
|
93
94
|
animatedHeader,
|
|
94
95
|
scrollViewProps,
|
|
95
96
|
headerComponent: Header,
|
|
96
97
|
footerComponent: Footer,
|
|
97
98
|
layoutOffset = -56,
|
|
98
99
|
backgroundColor,
|
|
100
|
+
headerType = 'default',
|
|
99
101
|
}: ScreenProps,
|
|
100
102
|
ref,
|
|
101
103
|
) => {
|
|
@@ -108,20 +110,16 @@ const Screen = forwardRef(
|
|
|
108
110
|
let handleScroll;
|
|
109
111
|
let headerBackground: string | undefined = undefined;
|
|
110
112
|
let Component: any = View;
|
|
113
|
+
let keyboardVerticalOffset = heightHeader - 20;
|
|
111
114
|
animatedValue.current = undefined;
|
|
112
115
|
|
|
113
|
-
if (
|
|
114
|
-
|
|
116
|
+
if (headerType == 'extended' || animatedHeader) {
|
|
117
|
+
keyboardVerticalOffset = -20;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
headerTransparent: true,
|
|
121
|
-
headerBackground: () => null,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
}, [useExtendedHeader]);
|
|
120
|
+
if (headerType == 'extended') {
|
|
121
|
+
headerBackground = theme.assets?.headerBackground;
|
|
122
|
+
}
|
|
125
123
|
|
|
126
124
|
useEffect(() => {
|
|
127
125
|
if (animatedHeader) {
|
|
@@ -152,17 +150,63 @@ const Screen = forwardRef(
|
|
|
152
150
|
};
|
|
153
151
|
}
|
|
154
152
|
navigation?.setOptions(styleAnimatedHeader);
|
|
155
|
-
const current: any = navigation;
|
|
156
|
-
const parent = current?.getParent?.();
|
|
157
|
-
if (parent) {
|
|
158
|
-
return current?.addListener?.('focus', () => {
|
|
159
|
-
const stackNavigation = new Navigation(parent, theme);
|
|
160
|
-
stackNavigation?.setOptions(styleAnimatedHeader);
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
153
|
}
|
|
164
154
|
}, [animatedHeader]);
|
|
165
155
|
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
if (!animatedHeader) {
|
|
158
|
+
let headerOptions: NavigationOptions = {};
|
|
159
|
+
switch (headerType) {
|
|
160
|
+
case 'none':
|
|
161
|
+
headerOptions = {
|
|
162
|
+
headerTransparent: true,
|
|
163
|
+
headerBackground: () => null,
|
|
164
|
+
headerShown: false,
|
|
165
|
+
};
|
|
166
|
+
break;
|
|
167
|
+
|
|
168
|
+
case 'surface':
|
|
169
|
+
headerOptions = {
|
|
170
|
+
headerTransparent: false,
|
|
171
|
+
headerShown: true,
|
|
172
|
+
headerTintColor: theme.colors.text.default,
|
|
173
|
+
headerBackground: (props: any) => (
|
|
174
|
+
<HeaderBackground
|
|
175
|
+
{...props}
|
|
176
|
+
image={null}
|
|
177
|
+
backgroundColor={theme.colors.background.surface}
|
|
178
|
+
useBorder={true}
|
|
179
|
+
animatedValue={animatedValue.current}
|
|
180
|
+
/>
|
|
181
|
+
),
|
|
182
|
+
headerTitle: (props: any) => (
|
|
183
|
+
<HeaderTitle {...props} animatedValue={animatedValue.current} />
|
|
184
|
+
),
|
|
185
|
+
};
|
|
186
|
+
break;
|
|
187
|
+
|
|
188
|
+
case 'extended':
|
|
189
|
+
headerOptions = {
|
|
190
|
+
headerShown: true,
|
|
191
|
+
headerTransparent: true,
|
|
192
|
+
headerTintColor: Colors.black_01,
|
|
193
|
+
headerBackground: () => null,
|
|
194
|
+
headerTitle: (props: any) => <HeaderTitle {...props} />,
|
|
195
|
+
};
|
|
196
|
+
break;
|
|
197
|
+
|
|
198
|
+
default:
|
|
199
|
+
headerOptions = {
|
|
200
|
+
headerTransparent: false,
|
|
201
|
+
headerShown: true,
|
|
202
|
+
headerTintColor: Colors.black_01,
|
|
203
|
+
headerBackground: (props: any) => <HeaderBackground {...props} />,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
navigation?.setOptions(headerOptions);
|
|
207
|
+
}
|
|
208
|
+
}, [headerType]);
|
|
209
|
+
|
|
166
210
|
/**
|
|
167
211
|
* animated when use scroll && animated value
|
|
168
212
|
*/
|
|
@@ -216,25 +260,33 @@ const Screen = forwardRef(
|
|
|
216
260
|
/**
|
|
217
261
|
* build content for screen
|
|
218
262
|
*/
|
|
219
|
-
const renderContent = () => {
|
|
220
|
-
const results = validateChildren(children, [Section, Card]);
|
|
263
|
+
const renderContent = (children: any): any => {
|
|
264
|
+
const results = validateChildren(children, [Section, Card, undefined]);
|
|
221
265
|
if (Array.isArray(results)) {
|
|
222
266
|
return results.map((item, index) => {
|
|
223
|
-
const space = item
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
267
|
+
const space = item?.props?.useMargin === false ? 0 : Spacing.M;
|
|
268
|
+
if (item?.type == Fragment) {
|
|
269
|
+
return renderContent(item?.props?.children);
|
|
270
|
+
}
|
|
271
|
+
if (item) {
|
|
272
|
+
return (
|
|
273
|
+
<View
|
|
274
|
+
key={`ScreenItem${index}`}
|
|
275
|
+
style={{
|
|
276
|
+
marginTop: space,
|
|
277
|
+
flex: item.props?.expanded ? 1 : undefined,
|
|
278
|
+
}}>
|
|
279
|
+
{item}
|
|
280
|
+
</View>
|
|
281
|
+
);
|
|
282
|
+
}
|
|
234
283
|
});
|
|
235
284
|
} else {
|
|
236
285
|
const item: any = children;
|
|
237
286
|
const space = item?.props?.useMargin === false ? 0 : Spacing.M;
|
|
287
|
+
if (item?.type == Fragment) {
|
|
288
|
+
return renderContent(item?.props?.children);
|
|
289
|
+
}
|
|
238
290
|
return (
|
|
239
291
|
<View
|
|
240
292
|
key={`ScreenItem`}
|
|
@@ -249,9 +301,7 @@ const Screen = forwardRef(
|
|
|
249
301
|
};
|
|
250
302
|
|
|
251
303
|
return (
|
|
252
|
-
<View
|
|
253
|
-
style={[Styles.flex, {backgroundColor}]}
|
|
254
|
-
accessibilityLabel={`ScreenContainer`}>
|
|
304
|
+
<View style={[Styles.flex, {backgroundColor}]}>
|
|
255
305
|
{!!headerBackground && (
|
|
256
306
|
<>
|
|
257
307
|
<Image
|
|
@@ -259,7 +309,6 @@ const Screen = forwardRef(
|
|
|
259
309
|
uri: headerBackground,
|
|
260
310
|
}}
|
|
261
311
|
style={styles.extendedHeader}
|
|
262
|
-
loading={false}
|
|
263
312
|
/>
|
|
264
313
|
<View style={{height: heightHeader}} />
|
|
265
314
|
</>
|
|
@@ -267,6 +316,7 @@ const Screen = forwardRef(
|
|
|
267
316
|
<KeyboardAvoidingView
|
|
268
317
|
style={Styles.flex}
|
|
269
318
|
enabled={enableKeyboardAvoidingView}
|
|
319
|
+
keyboardVerticalOffset={keyboardVerticalOffset}
|
|
270
320
|
behavior={Platform.select({
|
|
271
321
|
ios: 'padding',
|
|
272
322
|
android: undefined,
|
|
@@ -275,7 +325,6 @@ const Screen = forwardRef(
|
|
|
275
325
|
<Component
|
|
276
326
|
{...scrollViewProps}
|
|
277
327
|
ref={ref}
|
|
278
|
-
heightHeader={heightHeader}
|
|
279
328
|
showsVerticalScrollIndicator={false}
|
|
280
329
|
onScroll={handleScroll}
|
|
281
330
|
style={Styles.flex}>
|
|
@@ -283,15 +332,17 @@ const Screen = forwardRef(
|
|
|
283
332
|
style={[styles.screenBanner, {maxHeight: 210 + layoutOffset}]}>
|
|
284
333
|
{renderHeader()}
|
|
285
334
|
</View>
|
|
286
|
-
{renderContent()}
|
|
335
|
+
{renderContent(children)}
|
|
287
336
|
</Component>
|
|
288
337
|
{Footer && (
|
|
289
338
|
<View
|
|
290
|
-
style={
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
339
|
+
style={[
|
|
340
|
+
styles.footerContainer,
|
|
341
|
+
{
|
|
342
|
+
paddingBottom: Math.min(insets.bottom, 21) + Spacing.S,
|
|
343
|
+
backgroundColor: theme.colors.background.surface,
|
|
344
|
+
},
|
|
345
|
+
]}>
|
|
295
346
|
<Section>{Footer}</Section>
|
|
296
347
|
</View>
|
|
297
348
|
)}
|