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