@momo-kits/foundation 0.76.1-beta.2 → 0.77.1-optimize.10
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/BottomTabBar.tsx +439 -0
- package/Application/BottomTab/index.tsx +138 -0
- package/Application/Components.tsx +348 -167
- package/Application/ModalScreen.tsx +135 -98
- package/Application/Navigation.ts +22 -16
- package/Application/NavigationContainer.tsx +99 -48
- package/Application/Navigator.ts +110 -41
- package/Application/StackScreen.tsx +129 -8
- package/Application/index.ts +23 -4
- package/Application/types.ts +86 -34
- package/Application/utils.tsx +67 -49
- package/Assets/DotAnimation.json +256 -0
- package/Assets/SpinnerAnimation.json +1027 -0
- package/Assets/icon.json +83 -5
- package/Assets/icon_bank.json +506 -0
- package/Assets/language.json +202 -0
- 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 +91 -40
- package/Button/styles.ts +19 -0
- package/CheckBox/index.tsx +58 -43
- package/CheckBox/styles.ts +1 -1
- package/CheckBox/types.ts +6 -4
- package/Consts/colors+spacing+radius.ts +18 -0
- package/Consts/styles.ts +0 -26
- package/Consts/theme.ts +4 -0
- package/Divider/index.tsx +2 -0
- package/Icon/index.tsx +14 -9
- package/Icon/types.ts +4 -3
- package/IconButton/index.tsx +24 -15
- package/Image/index.tsx +63 -47
- package/Image/styles.ts +1 -9
- package/Image/types.ts +5 -1
- package/Input/Input.tsx +227 -116
- package/Input/InputDropDown.tsx +132 -0
- package/Input/InputMoney.tsx +173 -111
- package/Input/InputOTP.tsx +257 -0
- package/Input/InputSearch.tsx +160 -132
- package/Input/InputTextArea.tsx +150 -123
- package/Input/common.tsx +35 -17
- package/Input/index.tsx +211 -18
- package/Input/styles.ts +44 -7
- package/Input/utils.ts +2 -2
- package/Layout/Card.tsx +67 -29
- package/Layout/FloatingButton.tsx +168 -0
- package/Layout/GridSystem.tsx +31 -21
- package/Layout/Item.tsx +21 -25
- package/Layout/ItemList.tsx +55 -0
- package/Layout/ItemSectionList.tsx +39 -0
- package/Layout/Screen.tsx +355 -153
- package/Layout/Section.tsx +66 -34
- package/Layout/index.ts +13 -3
- package/Layout/styles.ts +101 -0
- package/Layout/types.ts +1 -39
- package/Layout/utils.ts +27 -52
- package/Loader/DotLoader.tsx +37 -0
- package/Loader/Loader.tsx +13 -0
- package/Loader/ProgressBar.tsx +44 -0
- package/Loader/Spinner.tsx +29 -0
- package/Loader/index.tsx +4 -0
- package/Loader/styles.ts +10 -0
- package/Loader/types.ts +35 -0
- package/Loader/utils.ts +25 -0
- package/Pagination/PaginationDot.tsx +7 -2
- package/Pagination/PaginationNumber.tsx +8 -6
- package/Pagination/PaginationScroll.tsx +0 -1
- package/Pagination/PaginationWhiteDot.tsx +8 -5
- package/Pagination/styles.ts +3 -0
- package/Pagination/types.ts +2 -0
- package/Popup/PopupNotify.tsx +108 -46
- package/Popup/PopupPromotion.tsx +63 -22
- package/Popup/types.ts +15 -4
- package/Radio/index.tsx +35 -21
- package/Radio/types.ts +7 -5
- package/Skeleton/index.tsx +1 -1
- package/Skeleton/types.ts +3 -0
- package/Switch/index.tsx +35 -24
- package/Switch/types.ts +5 -3
- package/Tag/index.tsx +2 -4
- package/Text/index.tsx +27 -22
- package/Text/styles.ts +38 -0
- package/Text/types.ts +25 -13
- package/Text/utils.ts +1 -1
- package/Title/index.tsx +186 -0
- package/Title/styles.ts +79 -0
- package/Title/types.ts +20 -0
- package/code-scanner.js +143 -0
- package/index.ts +6 -0
- package/migrate_typo.js +56 -0
- package/package.json +14 -9
- package/tsconfig.json +24 -0
- package/verify.js +47 -0
- package/Application/BottomTab.tsx +0 -52
- package/Application/NavigationButton.tsx +0 -54
- package/Assets/header-background.png +0 -0
package/Layout/Screen.tsx
CHANGED
|
@@ -1,188 +1,390 @@
|
|
|
1
|
+
import {useHeaderHeight} from '@react-navigation/stack';
|
|
2
|
+
import React, {
|
|
3
|
+
forwardRef,
|
|
4
|
+
Fragment,
|
|
5
|
+
ReactNode,
|
|
6
|
+
useContext,
|
|
7
|
+
useEffect,
|
|
8
|
+
useRef,
|
|
9
|
+
} from 'react';
|
|
1
10
|
import {
|
|
2
11
|
Animated,
|
|
3
12
|
KeyboardAvoidingView,
|
|
13
|
+
NativeScrollEvent,
|
|
14
|
+
NativeSyntheticEvent,
|
|
4
15
|
Platform,
|
|
5
|
-
|
|
16
|
+
ScrollViewProps,
|
|
6
17
|
View,
|
|
18
|
+
ViewProps,
|
|
7
19
|
} from 'react-native';
|
|
8
|
-
import {useHeaderHeight} from '@react-navigation/stack';
|
|
9
20
|
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
21
|
+
import {
|
|
22
|
+
ApplicationContext,
|
|
23
|
+
HeaderBackground,
|
|
24
|
+
HeaderTitle,
|
|
25
|
+
} from '../Application';
|
|
15
26
|
import Navigation from '../Application/Navigation';
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
marginHeader,
|
|
24
|
-
useAnimatedHeader = false,
|
|
25
|
-
useExtendedHeader = false,
|
|
26
|
-
headerBackground,
|
|
27
|
-
scrollViewProps,
|
|
28
|
-
footerComponent: Footer,
|
|
29
|
-
}) => {
|
|
30
|
-
const animatedValue = useRef<Animated.Value | undefined>(undefined);
|
|
31
|
-
const {theme} = useContext(ApplicationContext);
|
|
32
|
-
const insets = useSafeAreaInsets();
|
|
33
|
-
const headerTransparent = useAnimatedHeader || useExtendedHeader;
|
|
34
|
-
|
|
35
|
-
let handleScroll;
|
|
36
|
-
let imageAnimatedStyle = {};
|
|
37
|
-
let opacity;
|
|
38
|
-
let Component: any = View;
|
|
39
|
-
animatedValue.current = undefined;
|
|
27
|
+
import {AnimatedHeader, NavigationOptions} from '../Application/types';
|
|
28
|
+
import {Colors, Spacing, Styles} from '../Consts';
|
|
29
|
+
import {FloatingButton, FloatingButtonProps} from './FloatingButton';
|
|
30
|
+
import {Image} from '../Image';
|
|
31
|
+
import {Card, Section, validateChildren} from './index';
|
|
32
|
+
import styles from './styles';
|
|
33
|
+
import {HeaderType} from './types';
|
|
40
34
|
|
|
35
|
+
export interface ScreenProps extends ViewProps {
|
|
36
|
+
children: React.ReactNode;
|
|
41
37
|
/**
|
|
42
|
-
*
|
|
38
|
+
* Optional. Navigation object for handling navigation actions.
|
|
43
39
|
*/
|
|
44
|
-
|
|
45
|
-
animatedValue.current = new Animated.Value(0);
|
|
46
|
-
marginHeader = marginHeader ?? useHeaderHeight();
|
|
47
|
-
if (useExtendedHeader) {
|
|
48
|
-
headerBackground = theme.assets?.headerBackground;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
40
|
+
navigation?: Navigation;
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
navigation?.setOptions({
|
|
58
|
-
animatedValue: animatedValue.current,
|
|
59
|
-
headerTransparent,
|
|
60
|
-
...title,
|
|
61
|
-
});
|
|
62
|
-
}, [useExtendedHeader, useAnimatedHeader]);
|
|
42
|
+
/**
|
|
43
|
+
* Optional. If `true`, enable keyboard avoiding view for the screen.
|
|
44
|
+
*/
|
|
45
|
+
enableKeyboardAvoidingView?: boolean;
|
|
63
46
|
|
|
64
47
|
/**
|
|
65
|
-
*
|
|
48
|
+
* Optional. If `true`, the screen content is scrollable.
|
|
66
49
|
*/
|
|
67
|
-
|
|
68
|
-
const current: any = navigation;
|
|
69
|
-
if (headerTransparent) {
|
|
70
|
-
return current?.addListener?.('focus', () => {
|
|
71
|
-
const stackNavigation = new Navigation(current?.getParent(), theme);
|
|
72
|
-
stackNavigation?.setOptions({
|
|
73
|
-
animatedValue: animatedValue.current,
|
|
74
|
-
headerTransparent: true,
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}, [useAnimatedHeader, useExtendedHeader, navigation]);
|
|
50
|
+
scrollable?: boolean;
|
|
79
51
|
|
|
80
52
|
/**
|
|
81
|
-
*
|
|
53
|
+
* Optional. Set type of header.
|
|
82
54
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
55
|
+
headerType?: HeaderType;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Optional. Props for the animated component or bool used top navigation animated.
|
|
59
|
+
*/
|
|
60
|
+
animatedHeader?: AnimatedHeader;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Optional. Props for the underlying ScrollView component when `scrollable` is `true`.
|
|
64
|
+
*/
|
|
65
|
+
scrollViewProps?: ScrollViewProps;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Optional. ReactNode representing the header component of the screen.
|
|
69
|
+
*/
|
|
70
|
+
headerComponent?: ReactNode;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Optional. ReactNode representing the footer component of the screen.
|
|
74
|
+
*/
|
|
75
|
+
footerComponent?: ReactNode;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Optional. Background color of the screen.
|
|
79
|
+
*/
|
|
80
|
+
backgroundColor?: string;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Optional. layout card offset overlap header banner.
|
|
84
|
+
*/
|
|
85
|
+
layoutOffset?: -8 | -24 | -56;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Optional. Props for the floating action button.
|
|
89
|
+
*/
|
|
90
|
+
floatingButtonProps?: Omit<FloatingButtonProps, 'animatedValue' | 'bottom'>;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* optional animated value
|
|
94
|
+
*/
|
|
95
|
+
animatedValue?: Animated.Value;
|
|
96
|
+
/**
|
|
97
|
+
* Optional. If `true`, the screen content is using grid layout by span.
|
|
98
|
+
*/
|
|
99
|
+
useGridLayout?: boolean;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const Screen = forwardRef(
|
|
103
|
+
(
|
|
104
|
+
{
|
|
105
|
+
children,
|
|
106
|
+
enableKeyboardAvoidingView = false,
|
|
107
|
+
scrollable = false,
|
|
108
|
+
navigation,
|
|
109
|
+
animatedHeader,
|
|
110
|
+
scrollViewProps,
|
|
111
|
+
headerComponent: Header,
|
|
112
|
+
footerComponent: Footer,
|
|
113
|
+
layoutOffset = -56,
|
|
114
|
+
backgroundColor,
|
|
115
|
+
headerType = 'default',
|
|
116
|
+
floatingButtonProps,
|
|
117
|
+
useGridLayout = true,
|
|
118
|
+
animatedValue: animated,
|
|
119
|
+
}: ScreenProps,
|
|
120
|
+
ref,
|
|
121
|
+
) => {
|
|
122
|
+
const animatedValue = useRef<Animated.Value>(
|
|
123
|
+
animated ?? new Animated.Value(0),
|
|
124
|
+
);
|
|
125
|
+
const {theme} = useContext(ApplicationContext);
|
|
126
|
+
const insets = useSafeAreaInsets();
|
|
127
|
+
const heightHeader = useHeaderHeight();
|
|
128
|
+
const currentTint = useRef(Colors.black_01);
|
|
129
|
+
const isTab = navigation?.instance?.getState?.()?.type == 'tab';
|
|
130
|
+
|
|
131
|
+
let styleAnimatedHeader: NavigationOptions;
|
|
132
|
+
let handleScroll;
|
|
133
|
+
let headerBackground: string | undefined = undefined;
|
|
134
|
+
let Component: any = View;
|
|
135
|
+
let keyboardVerticalOffset = heightHeader - 20;
|
|
136
|
+
|
|
137
|
+
if (headerType == 'extended' || animatedHeader) {
|
|
138
|
+
keyboardVerticalOffset = -20;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (headerType == 'extended') {
|
|
142
|
+
headerBackground = theme.assets?.headerBackground;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (animatedHeader) {
|
|
147
|
+
styleAnimatedHeader = {
|
|
148
|
+
headerTransparent: true,
|
|
149
|
+
headerBackground: (props: any) => (
|
|
150
|
+
<HeaderBackground
|
|
151
|
+
{...props}
|
|
152
|
+
animatedValue={animatedValue.current}
|
|
153
|
+
/>
|
|
154
|
+
),
|
|
155
|
+
headerTitle: (props: any) => (
|
|
156
|
+
<HeaderTitle {...props} animatedValue={animatedValue.current} />
|
|
157
|
+
),
|
|
158
|
+
};
|
|
159
|
+
if (animatedHeader.type == 'surface') {
|
|
160
|
+
styleAnimatedHeader = {
|
|
161
|
+
...styleAnimatedHeader,
|
|
162
|
+
headerBackground: (props: any) => (
|
|
163
|
+
<HeaderBackground
|
|
164
|
+
{...props}
|
|
165
|
+
image={null}
|
|
166
|
+
useSurface={true}
|
|
167
|
+
animatedValue={animatedValue.current}
|
|
168
|
+
/>
|
|
169
|
+
),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (animatedHeader.headerTitle) {
|
|
173
|
+
styleAnimatedHeader = {
|
|
174
|
+
...styleAnimatedHeader,
|
|
175
|
+
headerTitle: (props: any) =>
|
|
176
|
+
animatedHeader.headerTitle?.({
|
|
177
|
+
...props,
|
|
178
|
+
animatedValue: animatedValue.current,
|
|
179
|
+
}),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
navigation?.setOptions(styleAnimatedHeader);
|
|
183
|
+
}
|
|
184
|
+
}, [animatedHeader]);
|
|
185
|
+
|
|
186
|
+
useEffect(() => {
|
|
187
|
+
if (!animatedHeader) {
|
|
188
|
+
let headerOptions: NavigationOptions;
|
|
189
|
+
switch (headerType) {
|
|
190
|
+
case 'none':
|
|
191
|
+
headerOptions = {
|
|
192
|
+
headerTransparent: true,
|
|
193
|
+
headerBackground: () => null,
|
|
194
|
+
headerShown: false,
|
|
195
|
+
};
|
|
196
|
+
break;
|
|
197
|
+
|
|
198
|
+
case 'surface':
|
|
199
|
+
headerOptions = {
|
|
200
|
+
headerTransparent: false,
|
|
201
|
+
headerShown: true,
|
|
202
|
+
headerTintColor: theme.colors.text.default,
|
|
203
|
+
headerBackground: (props: any) => (
|
|
204
|
+
<HeaderBackground {...props} image={null} useSurface={true} />
|
|
205
|
+
),
|
|
206
|
+
headerTitle: (props: any) => <HeaderTitle {...props} />,
|
|
207
|
+
};
|
|
208
|
+
break;
|
|
209
|
+
|
|
210
|
+
case 'extended':
|
|
211
|
+
headerOptions = {
|
|
212
|
+
headerShown: true,
|
|
213
|
+
headerTransparent: true,
|
|
214
|
+
headerTintColor: Colors.black_01,
|
|
215
|
+
headerBackground: () => null,
|
|
216
|
+
headerTitle: (props: any) => <HeaderTitle {...props} />,
|
|
217
|
+
};
|
|
218
|
+
break;
|
|
219
|
+
|
|
220
|
+
default:
|
|
221
|
+
headerOptions = {
|
|
222
|
+
headerTransparent: false,
|
|
223
|
+
headerShown: true,
|
|
224
|
+
headerTintColor: Colors.black_01,
|
|
225
|
+
headerBackground: (props: any) => <HeaderBackground {...props} />,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
navigation?.setOptions(headerOptions);
|
|
229
|
+
}
|
|
230
|
+
}, [headerType]);
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* animated when use scroll && animated value
|
|
234
|
+
*/
|
|
235
|
+
if (scrollable) {
|
|
236
|
+
Component = Animated.ScrollView;
|
|
237
|
+
handleScroll = scrollViewProps?.onScroll;
|
|
238
|
+
if (animatedHeader || floatingButtonProps) {
|
|
239
|
+
handleScroll = Animated.event(
|
|
240
|
+
[
|
|
241
|
+
{
|
|
242
|
+
nativeEvent: {
|
|
243
|
+
contentOffset: {y: animatedValue.current as Animated.Value},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
],
|
|
104
247
|
{
|
|
105
|
-
|
|
106
|
-
|
|
248
|
+
useNativeDriver: true,
|
|
249
|
+
listener: (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
250
|
+
scrollViewProps?.onScroll?.(e);
|
|
251
|
+
if (animatedHeader?.type == 'surface') {
|
|
252
|
+
const offsetY = e.nativeEvent.contentOffset.y;
|
|
253
|
+
let color = Colors.black_01;
|
|
254
|
+
if (offsetY > 50) {
|
|
255
|
+
color = theme.colors.text.default;
|
|
256
|
+
}
|
|
257
|
+
if (color != currentTint.current) {
|
|
258
|
+
currentTint.current = color;
|
|
259
|
+
navigation?.setOptions({
|
|
260
|
+
headerTintColor: color,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
107
264
|
},
|
|
108
265
|
},
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
);
|
|
266
|
+
);
|
|
267
|
+
}
|
|
112
268
|
}
|
|
113
|
-
}
|
|
114
269
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
270
|
+
/**
|
|
271
|
+
* render top navigation banner
|
|
272
|
+
*/
|
|
273
|
+
const renderHeader = () => {
|
|
274
|
+
if (typeof animatedHeader?.component === 'function') {
|
|
275
|
+
return animatedHeader?.component({
|
|
276
|
+
animatedValue: animatedValue.current,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* build content for screen
|
|
283
|
+
*/
|
|
284
|
+
const renderContent = (children: any): any => {
|
|
285
|
+
const results = validateChildren(children, [Section, Card, undefined]);
|
|
286
|
+
if (Array.isArray(results)) {
|
|
287
|
+
return results.map((item, index) => {
|
|
288
|
+
const space = item?.props?.useMargin === false ? 0 : Spacing.M;
|
|
289
|
+
if (item?.type == Fragment) {
|
|
290
|
+
return renderContent(item?.props?.children);
|
|
291
|
+
}
|
|
292
|
+
if (item) {
|
|
293
|
+
return (
|
|
294
|
+
<View
|
|
295
|
+
key={`ScreenItem${index}`}
|
|
296
|
+
style={{
|
|
297
|
+
marginTop: space,
|
|
298
|
+
flex: item.props?.expanded ? 1 : undefined,
|
|
299
|
+
}}>
|
|
300
|
+
{item}
|
|
301
|
+
</View>
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
} else {
|
|
306
|
+
const item: any = children;
|
|
307
|
+
const space = item?.props?.useMargin === false ? 0 : Spacing.M;
|
|
308
|
+
if (item?.type == Fragment) {
|
|
309
|
+
return renderContent(item?.props?.children);
|
|
310
|
+
}
|
|
123
311
|
return (
|
|
124
312
|
<View
|
|
125
|
-
key={`ScreenItem
|
|
313
|
+
key={`ScreenItem`}
|
|
126
314
|
style={{
|
|
127
315
|
marginTop: space,
|
|
128
|
-
flex: item
|
|
316
|
+
flex: item?.props?.expanded ? 1 : undefined,
|
|
129
317
|
}}>
|
|
130
|
-
{
|
|
318
|
+
{children}
|
|
131
319
|
</View>
|
|
132
320
|
);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return (
|
|
139
|
-
<View style={Styles.flex} accessibilityLabel={`ScreenContainer`}>
|
|
140
|
-
<View
|
|
141
|
-
style={{
|
|
142
|
-
position: 'absolute',
|
|
143
|
-
maxHeight: 215,
|
|
144
|
-
width: '100%',
|
|
145
|
-
overflow: 'hidden',
|
|
146
|
-
}}>
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<View style={[Styles.flex, {backgroundColor}]}>
|
|
147
326
|
{!!headerBackground && (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
/>
|
|
327
|
+
<>
|
|
328
|
+
<Image
|
|
329
|
+
source={{
|
|
330
|
+
uri: headerBackground,
|
|
331
|
+
}}
|
|
332
|
+
style={styles.extendedHeader}
|
|
333
|
+
/>
|
|
334
|
+
<View style={{height: heightHeader}} />
|
|
335
|
+
</>
|
|
158
336
|
)}
|
|
337
|
+
<KeyboardAvoidingView
|
|
338
|
+
style={Styles.flex}
|
|
339
|
+
enabled={enableKeyboardAvoidingView}
|
|
340
|
+
keyboardVerticalOffset={keyboardVerticalOffset}
|
|
341
|
+
behavior={Platform.select({
|
|
342
|
+
ios: 'padding',
|
|
343
|
+
android: undefined,
|
|
344
|
+
})}>
|
|
345
|
+
{Header}
|
|
346
|
+
|
|
347
|
+
<Component
|
|
348
|
+
{...scrollViewProps}
|
|
349
|
+
ref={ref}
|
|
350
|
+
showsVerticalScrollIndicator={false}
|
|
351
|
+
onScroll={handleScroll}
|
|
352
|
+
style={Styles.flex}>
|
|
353
|
+
<View
|
|
354
|
+
style={[styles.screenBanner, {maxHeight: 210 + layoutOffset}]}>
|
|
355
|
+
{renderHeader()}
|
|
356
|
+
</View>
|
|
357
|
+
{useGridLayout ? renderContent(children) : children}
|
|
358
|
+
</Component>
|
|
359
|
+
|
|
360
|
+
{floatingButtonProps && (
|
|
361
|
+
<View>
|
|
362
|
+
<FloatingButton
|
|
363
|
+
{...floatingButtonProps}
|
|
364
|
+
animatedValue={animatedValue.current}
|
|
365
|
+
bottom={
|
|
366
|
+
Footer || isTab ? 12 : Math.min(insets.bottom, 21) + Spacing.S
|
|
367
|
+
}
|
|
368
|
+
/>
|
|
369
|
+
</View>
|
|
370
|
+
)}
|
|
371
|
+
|
|
372
|
+
{Footer && (
|
|
373
|
+
<View
|
|
374
|
+
style={[
|
|
375
|
+
styles.shadow,
|
|
376
|
+
{
|
|
377
|
+
paddingBottom: Math.min(insets.bottom, 21) + Spacing.S,
|
|
378
|
+
backgroundColor: theme.colors.background.surface,
|
|
379
|
+
},
|
|
380
|
+
]}>
|
|
381
|
+
<Section>{Footer}</Section>
|
|
382
|
+
</View>
|
|
383
|
+
)}
|
|
384
|
+
</KeyboardAvoidingView>
|
|
159
385
|
</View>
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
behavior={Platform.select({
|
|
164
|
-
ios: 'padding',
|
|
165
|
-
android: undefined,
|
|
166
|
-
})}>
|
|
167
|
-
<Component
|
|
168
|
-
{...scrollViewProps}
|
|
169
|
-
onScroll={handleScroll}
|
|
170
|
-
style={[Styles.flex, {marginTop: marginHeader}]}>
|
|
171
|
-
{renderContent()}
|
|
172
|
-
</Component>
|
|
173
|
-
{Footer && (
|
|
174
|
-
<View
|
|
175
|
-
style={{
|
|
176
|
-
paddingTop: Spacing.S,
|
|
177
|
-
paddingBottom: insets.bottom + Spacing.S,
|
|
178
|
-
backgroundColor: theme.colors.background.surface,
|
|
179
|
-
}}>
|
|
180
|
-
<Section>{Footer}</Section>
|
|
181
|
-
</View>
|
|
182
|
-
)}
|
|
183
|
-
</KeyboardAvoidingView>
|
|
184
|
-
</View>
|
|
185
|
-
);
|
|
186
|
-
};
|
|
386
|
+
);
|
|
387
|
+
},
|
|
388
|
+
);
|
|
187
389
|
|
|
188
390
|
export default Screen;
|
package/Layout/Section.tsx
CHANGED
|
@@ -1,16 +1,41 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {Dimensions, View} from 'react-native';
|
|
1
|
+
import React, {Fragment, useContext} from 'react';
|
|
2
|
+
import {Dimensions, View, ViewProps} from 'react-native';
|
|
3
3
|
import {useGridSystem, validateChildren} from './utils';
|
|
4
|
-
import {GridContextProps
|
|
4
|
+
import {GridContextProps} from './types';
|
|
5
5
|
import {GridContext} from './index';
|
|
6
|
-
import {GRIDVIEW} from '../Consts';
|
|
7
6
|
import Item from './Item';
|
|
7
|
+
import {ApplicationContext} from '../Application';
|
|
8
|
+
import styles from './styles';
|
|
9
|
+
import {Image} from '../Image';
|
|
10
|
+
import ItemList from './ItemList';
|
|
11
|
+
|
|
12
|
+
export interface SectionProps extends ViewProps {
|
|
13
|
+
/**
|
|
14
|
+
* Optional. If `true`, the Section component will be displayed in an expanded state.
|
|
15
|
+
* Defaults to `false` if not provided.
|
|
16
|
+
*/
|
|
17
|
+
expanded?: boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Optional. If `true`, margin will be applied to the Section component.
|
|
21
|
+
* Defaults to `false` if not provided.
|
|
22
|
+
*/
|
|
23
|
+
useMargin?: boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Optional. Background image for the Section component.
|
|
27
|
+
*/
|
|
28
|
+
backgroundImage?: string;
|
|
29
|
+
}
|
|
8
30
|
|
|
9
31
|
const Section: React.FC<SectionProps> = ({
|
|
10
32
|
children,
|
|
11
33
|
useMargin = true,
|
|
12
|
-
|
|
34
|
+
backgroundImage,
|
|
35
|
+
style,
|
|
36
|
+
...props
|
|
13
37
|
}) => {
|
|
38
|
+
const {showGrid} = useContext(ApplicationContext);
|
|
14
39
|
const {numberOfColumns} = useGridSystem();
|
|
15
40
|
|
|
16
41
|
const gutterSize = 12;
|
|
@@ -26,7 +51,6 @@ const Section: React.FC<SectionProps> = ({
|
|
|
26
51
|
const gridContext: GridContextProps = {
|
|
27
52
|
numberOfColumns,
|
|
28
53
|
gutterSize,
|
|
29
|
-
margin,
|
|
30
54
|
sizePerSpan,
|
|
31
55
|
getSizeSpan: span => {
|
|
32
56
|
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
@@ -37,20 +61,7 @@ const Section: React.FC<SectionProps> = ({
|
|
|
37
61
|
* render overlay only dev mode
|
|
38
62
|
*/
|
|
39
63
|
const renderOverlay = () => {
|
|
40
|
-
return
|
|
41
|
-
<View
|
|
42
|
-
pointerEvents={'none'}
|
|
43
|
-
style={{
|
|
44
|
-
position: 'absolute',
|
|
45
|
-
top: 0,
|
|
46
|
-
bottom: 0,
|
|
47
|
-
left: 0,
|
|
48
|
-
right: 0,
|
|
49
|
-
borderColor: 'red',
|
|
50
|
-
borderWidth: 1,
|
|
51
|
-
}}
|
|
52
|
-
/>
|
|
53
|
-
);
|
|
64
|
+
return <View pointerEvents={'none'} style={styles.boxGridSection} />;
|
|
54
65
|
};
|
|
55
66
|
|
|
56
67
|
/**
|
|
@@ -96,8 +107,9 @@ const Section: React.FC<SectionProps> = ({
|
|
|
96
107
|
if (Array.isArray(children)) {
|
|
97
108
|
let cursor = 0;
|
|
98
109
|
let rows: any[] = [];
|
|
99
|
-
|
|
100
|
-
|
|
110
|
+
const arrayChild = children.filter(item => !!item);
|
|
111
|
+
for (let i = 0; i < arrayChild.length; ++i) {
|
|
112
|
+
const item = arrayChild[i];
|
|
101
113
|
const totalSpan = rows
|
|
102
114
|
.concat([item])
|
|
103
115
|
.map(i => i.props?.widthSpan)
|
|
@@ -113,30 +125,50 @@ const Section: React.FC<SectionProps> = ({
|
|
|
113
125
|
rows = [item];
|
|
114
126
|
}
|
|
115
127
|
|
|
116
|
-
if (i ==
|
|
128
|
+
if (i == arrayChild.length - 1) {
|
|
117
129
|
cursor += 1;
|
|
118
130
|
element.push(addRowView(rows, cursor, true));
|
|
119
131
|
}
|
|
120
132
|
}
|
|
121
133
|
} else {
|
|
122
134
|
element.push(children);
|
|
135
|
+
if (children?.type == Fragment) {
|
|
136
|
+
return renderView(children?.props.children);
|
|
137
|
+
}
|
|
123
138
|
}
|
|
124
139
|
return element;
|
|
125
140
|
};
|
|
126
141
|
|
|
127
142
|
return (
|
|
128
|
-
<GridContext.Provider
|
|
143
|
+
<GridContext.Provider
|
|
144
|
+
value={{
|
|
145
|
+
numberOfColumns,
|
|
146
|
+
gutterSize,
|
|
147
|
+
sizePerSpan,
|
|
148
|
+
getSizeSpan: span => {
|
|
149
|
+
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
150
|
+
},
|
|
151
|
+
}}>
|
|
129
152
|
<View
|
|
130
|
-
|
|
131
|
-
style={
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
153
|
+
{...props}
|
|
154
|
+
style={[
|
|
155
|
+
style,
|
|
156
|
+
styles.protectedStyle,
|
|
157
|
+
{
|
|
158
|
+
width: widthSection,
|
|
159
|
+
marginHorizontal: margin,
|
|
160
|
+
flexDirection: 'row',
|
|
161
|
+
flexWrap: 'wrap',
|
|
162
|
+
},
|
|
163
|
+
]}>
|
|
164
|
+
{!!backgroundImage && (
|
|
165
|
+
<Image
|
|
166
|
+
source={{uri: backgroundImage}}
|
|
167
|
+
style={styles.imageBackground}
|
|
168
|
+
/>
|
|
169
|
+
)}
|
|
170
|
+
{renderView(validateChildren(children, [Item, ItemList]))}
|
|
171
|
+
{showGrid && renderOverlay()}
|
|
140
172
|
</View>
|
|
141
173
|
</GridContext.Provider>
|
|
142
174
|
);
|