@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.
Files changed (100) hide show
  1. package/Application/BottomTab/BottomTabBar.tsx +439 -0
  2. package/Application/BottomTab/index.tsx +138 -0
  3. package/Application/Components.tsx +348 -167
  4. package/Application/ModalScreen.tsx +135 -98
  5. package/Application/Navigation.ts +22 -16
  6. package/Application/NavigationContainer.tsx +99 -48
  7. package/Application/Navigator.ts +110 -41
  8. package/Application/StackScreen.tsx +129 -8
  9. package/Application/index.ts +23 -4
  10. package/Application/types.ts +86 -34
  11. package/Application/utils.tsx +67 -49
  12. package/Assets/DotAnimation.json +256 -0
  13. package/Assets/SpinnerAnimation.json +1027 -0
  14. package/Assets/icon.json +83 -5
  15. package/Assets/icon_bank.json +506 -0
  16. package/Assets/language.json +202 -0
  17. package/Badge/Badge.tsx +56 -0
  18. package/Badge/BadgeDot.tsx +11 -0
  19. package/Badge/BadgeRibbon.tsx +125 -0
  20. package/Badge/Shape.tsx +29 -0
  21. package/Badge/index.tsx +7 -0
  22. package/Badge/styles.ts +58 -0
  23. package/Badge/types.ts +63 -0
  24. package/Button/index.tsx +91 -40
  25. package/Button/styles.ts +19 -0
  26. package/CheckBox/index.tsx +58 -43
  27. package/CheckBox/styles.ts +1 -1
  28. package/CheckBox/types.ts +6 -4
  29. package/Consts/colors+spacing+radius.ts +18 -0
  30. package/Consts/styles.ts +0 -26
  31. package/Consts/theme.ts +4 -0
  32. package/Divider/index.tsx +2 -0
  33. package/Icon/index.tsx +14 -9
  34. package/Icon/types.ts +4 -3
  35. package/IconButton/index.tsx +24 -15
  36. package/Image/index.tsx +63 -47
  37. package/Image/styles.ts +1 -9
  38. package/Image/types.ts +5 -1
  39. package/Input/Input.tsx +227 -116
  40. package/Input/InputDropDown.tsx +132 -0
  41. package/Input/InputMoney.tsx +173 -111
  42. package/Input/InputOTP.tsx +257 -0
  43. package/Input/InputSearch.tsx +160 -132
  44. package/Input/InputTextArea.tsx +150 -123
  45. package/Input/common.tsx +35 -17
  46. package/Input/index.tsx +211 -18
  47. package/Input/styles.ts +44 -7
  48. package/Input/utils.ts +2 -2
  49. package/Layout/Card.tsx +67 -29
  50. package/Layout/FloatingButton.tsx +168 -0
  51. package/Layout/GridSystem.tsx +31 -21
  52. package/Layout/Item.tsx +21 -25
  53. package/Layout/ItemList.tsx +55 -0
  54. package/Layout/ItemSectionList.tsx +39 -0
  55. package/Layout/Screen.tsx +355 -153
  56. package/Layout/Section.tsx +66 -34
  57. package/Layout/index.ts +13 -3
  58. package/Layout/styles.ts +101 -0
  59. package/Layout/types.ts +1 -39
  60. package/Layout/utils.ts +27 -52
  61. package/Loader/DotLoader.tsx +37 -0
  62. package/Loader/Loader.tsx +13 -0
  63. package/Loader/ProgressBar.tsx +44 -0
  64. package/Loader/Spinner.tsx +29 -0
  65. package/Loader/index.tsx +4 -0
  66. package/Loader/styles.ts +10 -0
  67. package/Loader/types.ts +35 -0
  68. package/Loader/utils.ts +25 -0
  69. package/Pagination/PaginationDot.tsx +7 -2
  70. package/Pagination/PaginationNumber.tsx +8 -6
  71. package/Pagination/PaginationScroll.tsx +0 -1
  72. package/Pagination/PaginationWhiteDot.tsx +8 -5
  73. package/Pagination/styles.ts +3 -0
  74. package/Pagination/types.ts +2 -0
  75. package/Popup/PopupNotify.tsx +108 -46
  76. package/Popup/PopupPromotion.tsx +63 -22
  77. package/Popup/types.ts +15 -4
  78. package/Radio/index.tsx +35 -21
  79. package/Radio/types.ts +7 -5
  80. package/Skeleton/index.tsx +1 -1
  81. package/Skeleton/types.ts +3 -0
  82. package/Switch/index.tsx +35 -24
  83. package/Switch/types.ts +5 -3
  84. package/Tag/index.tsx +2 -4
  85. package/Text/index.tsx +27 -22
  86. package/Text/styles.ts +38 -0
  87. package/Text/types.ts +25 -13
  88. package/Text/utils.ts +1 -1
  89. package/Title/index.tsx +186 -0
  90. package/Title/styles.ts +79 -0
  91. package/Title/types.ts +20 -0
  92. package/code-scanner.js +143 -0
  93. package/index.ts +6 -0
  94. package/migrate_typo.js +56 -0
  95. package/package.json +14 -9
  96. package/tsconfig.json +24 -0
  97. package/verify.js +47 -0
  98. package/Application/BottomTab.tsx +0 -52
  99. package/Application/NavigationButton.tsx +0 -54
  100. 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
- Text,
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 React, {useContext, useEffect, useRef} from 'react';
11
- import {ScreenProps} from '../Application/types';
12
- import {Spacing, Styles} from '../Consts';
13
- import {Card, Section, validateChildren} from './index';
14
- import {ApplicationContext} from '../Application';
21
+ import {
22
+ ApplicationContext,
23
+ HeaderBackground,
24
+ HeaderTitle,
25
+ } from '../Application';
15
26
  import Navigation from '../Application/Navigation';
16
- import {HeaderTitle} from '../Application/Components';
17
-
18
- const Screen: React.FC<ScreenProps> = ({
19
- children,
20
- enableKeyboardAvoidingView = false,
21
- scrollable = false,
22
- navigation,
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
- * automatic margin content if use header transparent
38
+ * Optional. Navigation object for handling navigation actions.
43
39
  */
44
- if (headerTransparent) {
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
- useEffect(() => {
53
- let title = {};
54
- if (useExtendedHeader) {
55
- title = {headerTitle: HeaderTitle};
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
- * animated for header stack when used bottom tab
48
+ * Optional. If `true`, the screen content is scrollable.
66
49
  */
67
- useEffect(() => {
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
- * animated when use scroll && animated value
53
+ * Optional. Set type of header.
82
54
  */
83
- if (scrollable) {
84
- Component = Animated.ScrollView;
85
- if (useAnimatedHeader) {
86
- opacity = animatedValue.current?.interpolate({
87
- inputRange: [0, 100],
88
- outputRange: [1, 0],
89
- extrapolate: 'clamp',
90
- });
91
- imageAnimatedStyle = {
92
- transform: [
93
- {
94
- scale: animatedValue.current?.interpolate?.({
95
- inputRange: [-300, 0, 1],
96
- outputRange: [1.75, 1, 1],
97
- extrapolate: 'clamp',
98
- }),
99
- },
100
- ],
101
- };
102
- handleScroll = Animated.event(
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
- nativeEvent: {
106
- contentOffset: {y: animatedValue.current as Animated.Value},
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
- {useNativeDriver: true},
111
- );
266
+ );
267
+ }
112
268
  }
113
- }
114
269
 
115
- /**
116
- * build content for screen
117
- */
118
- const renderContent = () => {
119
- const results = validateChildren(children, [Section, Card]);
120
- if (Array.isArray(results)) {
121
- return results.map((item, index) => {
122
- const space = item.props?.useMargin === false ? 0 : Spacing.M;
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${index}`}
313
+ key={`ScreenItem`}
126
314
  style={{
127
315
  marginTop: space,
128
- flex: item.props?.expanded ? 1 : undefined,
316
+ flex: item?.props?.expanded ? 1 : undefined,
129
317
  }}>
130
- {item}
318
+ {children}
131
319
  </View>
132
320
  );
133
- });
134
- }
135
- return results;
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
- <Animated.Image
149
- source={{
150
- uri: headerBackground,
151
- }}
152
- style={{
153
- opacity: opacity ?? 1,
154
- aspectRatio: 1.75,
155
- ...imageAnimatedStyle,
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
- <KeyboardAvoidingView
161
- style={Styles.flex}
162
- enabled={enableKeyboardAvoidingView}
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;
@@ -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, SectionProps} from './types';
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
- backgroundColor,
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
- for (let i = 0; i < children.length; ++i) {
100
- const item = children[i];
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 == children.length - 1) {
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 value={gridContext}>
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
- accessibilityLabel={`Section`}
131
- style={{
132
- width: widthSection,
133
- marginHorizontal: gridContext.margin,
134
- flexDirection: 'row',
135
- flexWrap: 'wrap',
136
- backgroundColor: backgroundColor,
137
- }}>
138
- {renderView(validateChildren(children, [Item]))}
139
- {GRIDVIEW && renderOverlay()}
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
  );