@momo-kits/foundation 0.75.1-beta.8 → 0.75.1-beta.9
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/Layout/Card.tsx +107 -54
- package/Layout/Item.tsx +60 -0
- package/Layout/ScreenContainer.tsx +4 -5
- package/Layout/Section.tsx +3 -6
- package/Layout/index.ts +2 -1
- package/Layout/types.ts +4 -6
- package/Layout/utils.ts +23 -13
- package/package.json +1 -1
package/Layout/Card.tsx
CHANGED
|
@@ -1,21 +1,31 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {View} from 'react-native';
|
|
3
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {Dimensions, View} from 'react-native';
|
|
3
|
+
import {validateChildren} from './utils';
|
|
4
4
|
import {CardProps, GridContextProps} from './types';
|
|
5
5
|
import {GridContext} from './index';
|
|
6
6
|
import {GRIDVIEW} from '../Consts';
|
|
7
|
+
import Item from './Item';
|
|
8
|
+
|
|
9
|
+
const Card: React.FC<CardProps> = ({children, style}) => {
|
|
10
|
+
const numberOfColumns = 12;
|
|
11
|
+
const gutterSize = 8;
|
|
12
|
+
const margin = 12;
|
|
7
13
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
usePadding,
|
|
12
|
-
children,
|
|
13
|
-
style,
|
|
14
|
-
}) => {
|
|
15
|
-
const grid = useContext(GridContext);
|
|
14
|
+
const widthSection = Dimensions.get('window').width - margin * 2;
|
|
15
|
+
const totalGutterSize = gutterSize * (numberOfColumns - 1);
|
|
16
|
+
const sizePerSpan = (widthSection - totalGutterSize - 24) / numberOfColumns;
|
|
16
17
|
|
|
18
|
+
const gridContext: GridContextProps = {
|
|
19
|
+
numberOfColumns,
|
|
20
|
+
gutterSize,
|
|
21
|
+
margin,
|
|
22
|
+
sizePerSpan,
|
|
23
|
+
getSizeSpan: span => {
|
|
24
|
+
return span * sizePerSpan + (span - 1) * gutterSize;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
17
27
|
/**
|
|
18
|
-
* render overlay
|
|
28
|
+
* render overlay only dev mode
|
|
19
29
|
*/
|
|
20
30
|
const renderOverlay = () => {
|
|
21
31
|
return (
|
|
@@ -34,55 +44,98 @@ const Card: React.FC<CardProps> = ({
|
|
|
34
44
|
);
|
|
35
45
|
};
|
|
36
46
|
|
|
37
|
-
|
|
47
|
+
/**
|
|
48
|
+
* build a row view in side session
|
|
49
|
+
* @param rows
|
|
50
|
+
* @param cursor
|
|
51
|
+
* @param endRow
|
|
52
|
+
*/
|
|
53
|
+
const addRowView = (
|
|
54
|
+
rows: any[],
|
|
55
|
+
cursor: number = 0,
|
|
56
|
+
endRow: boolean = false,
|
|
57
|
+
) => {
|
|
58
|
+
return (
|
|
59
|
+
<View
|
|
60
|
+
key={`Item${cursor}`}
|
|
61
|
+
style={{
|
|
62
|
+
flexDirection: 'row',
|
|
63
|
+
marginBottom: endRow ? 0 : gridContext.gutterSize,
|
|
64
|
+
}}>
|
|
65
|
+
{rows.map((i: React.ReactElement, index: number) => {
|
|
66
|
+
return (
|
|
67
|
+
<View key={`Item${cursor}${index}`} style={{flexDirection: 'row'}}>
|
|
68
|
+
{index != 0 && (
|
|
69
|
+
<View style={{width: gridContext.gutterSize}}></View>
|
|
70
|
+
)}
|
|
71
|
+
{i}
|
|
72
|
+
</View>
|
|
73
|
+
);
|
|
74
|
+
})}
|
|
75
|
+
</View>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
38
78
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
79
|
+
/**
|
|
80
|
+
* render children content for card
|
|
81
|
+
* @param children
|
|
82
|
+
*/
|
|
83
|
+
const renderView = (
|
|
84
|
+
children: any,
|
|
85
|
+
): React.ReactElement | React.ReactElement[] => {
|
|
86
|
+
const element: React.ReactElement | React.ReactElement[] = [];
|
|
87
|
+
if (Array.isArray(children)) {
|
|
88
|
+
let cursor = 0;
|
|
89
|
+
let rows: any[] = [];
|
|
90
|
+
for (let i = 0; i < children.length; ++i) {
|
|
91
|
+
const item = children[i];
|
|
92
|
+
const totalSpan = rows
|
|
93
|
+
.concat([item])
|
|
94
|
+
.map(i => i.props?.widthSpan)
|
|
95
|
+
.reduce((previousValue, currentValue) => {
|
|
96
|
+
return previousValue + currentValue;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (totalSpan <= gridContext.numberOfColumns) {
|
|
100
|
+
rows.push(item);
|
|
101
|
+
} else {
|
|
102
|
+
cursor += 1;
|
|
103
|
+
element.push(addRowView(rows, cursor));
|
|
104
|
+
rows = [item];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (i == children.length - 1) {
|
|
108
|
+
cursor += 1;
|
|
109
|
+
element.push(addRowView(rows, cursor, true));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
element.push(children);
|
|
114
|
+
}
|
|
115
|
+
return element;
|
|
56
116
|
};
|
|
57
117
|
|
|
118
|
+
const styles: any = style ?? {};
|
|
119
|
+
|
|
58
120
|
return (
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
{children}
|
|
75
|
-
</GridContext.Provider>
|
|
76
|
-
{GRIDVIEW && renderOverlay()}
|
|
77
|
-
</View>
|
|
121
|
+
<GridContext.Provider value={gridContext}>
|
|
122
|
+
<View
|
|
123
|
+
accessibilityLabel={`Card`}
|
|
124
|
+
style={{
|
|
125
|
+
...styles,
|
|
126
|
+
width: widthSection,
|
|
127
|
+
marginHorizontal: gridContext.margin,
|
|
128
|
+
padding: 12,
|
|
129
|
+
flexDirection: 'row',
|
|
130
|
+
flexWrap: 'wrap',
|
|
131
|
+
}}>
|
|
132
|
+
{renderView(validateChildren(children, [Item]))}
|
|
133
|
+
{GRIDVIEW && renderOverlay()}
|
|
134
|
+
</View>
|
|
135
|
+
</GridContext.Provider>
|
|
78
136
|
);
|
|
79
137
|
};
|
|
80
138
|
|
|
81
|
-
Card.defaultProps = {
|
|
82
|
-
widthSpan: 12,
|
|
83
|
-
usePadding: false,
|
|
84
|
-
};
|
|
85
|
-
|
|
86
139
|
Card.displayName = 'Card';
|
|
87
140
|
|
|
88
141
|
export default Card;
|
package/Layout/Item.tsx
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React, {useContext} from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
|
|
4
|
+
import {ItemProps} from './types';
|
|
5
|
+
import {GridContext} from './index';
|
|
6
|
+
import {GRIDVIEW} from '../Consts';
|
|
7
|
+
|
|
8
|
+
const Item: React.FC<ItemProps> = ({
|
|
9
|
+
widthSpan = 12,
|
|
10
|
+
heightSpan,
|
|
11
|
+
children,
|
|
12
|
+
style,
|
|
13
|
+
}) => {
|
|
14
|
+
const grid = useContext(GridContext);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* render overlay view only dev mode
|
|
18
|
+
*/
|
|
19
|
+
const renderOverlay = () => {
|
|
20
|
+
return (
|
|
21
|
+
<View
|
|
22
|
+
pointerEvents={'none'}
|
|
23
|
+
style={{
|
|
24
|
+
position: 'absolute',
|
|
25
|
+
top: 0,
|
|
26
|
+
bottom: 0,
|
|
27
|
+
left: 0,
|
|
28
|
+
right: 0,
|
|
29
|
+
borderColor: 'red',
|
|
30
|
+
borderWidth: 1,
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const styles: any = style ?? {};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<View
|
|
40
|
+
accessibilityLabel={`Item`}
|
|
41
|
+
style={{
|
|
42
|
+
...styles,
|
|
43
|
+
width: grid.getSizeSpan(widthSpan),
|
|
44
|
+
height: heightSpan ? grid.getSizeSpan(heightSpan) : undefined,
|
|
45
|
+
overflow: 'hidden',
|
|
46
|
+
margin: undefined,
|
|
47
|
+
marginTop: undefined,
|
|
48
|
+
marginBottom: undefined,
|
|
49
|
+
marginLeft: undefined,
|
|
50
|
+
marginRight: undefined,
|
|
51
|
+
}}>
|
|
52
|
+
{children}
|
|
53
|
+
{GRIDVIEW && renderOverlay()}
|
|
54
|
+
</View>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
Item.displayName = 'Item';
|
|
59
|
+
|
|
60
|
+
export default Item;
|
|
@@ -4,8 +4,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
|
4
4
|
import React, {useContext} from 'react';
|
|
5
5
|
import {ScreenContainerProps} from '../Navigation/types';
|
|
6
6
|
import {Spacing, Styles} from '../Consts';
|
|
7
|
-
import {Section, validateChildren} from './index';
|
|
8
|
-
|
|
7
|
+
import {Section, Card, validateChildren} from './index';
|
|
9
8
|
import {ApplicationContext} from '../Navigation';
|
|
10
9
|
|
|
11
10
|
const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
@@ -49,14 +48,14 @@ const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
|
49
48
|
* build content for screen
|
|
50
49
|
*/
|
|
51
50
|
const renderContent = () => {
|
|
52
|
-
const results = validateChildren(children, Section);
|
|
51
|
+
const results = validateChildren(children, [Section, Card]);
|
|
53
52
|
if (Array.isArray(results)) {
|
|
54
53
|
return results.map((item, index) => {
|
|
55
54
|
return (
|
|
56
55
|
<View
|
|
57
|
-
key={`
|
|
56
|
+
key={`ScreenItem${index}`}
|
|
58
57
|
style={{
|
|
59
|
-
marginTop:
|
|
58
|
+
marginTop: Spacing.M,
|
|
60
59
|
flex: item.props?.expanded ? 1 : undefined,
|
|
61
60
|
}}>
|
|
62
61
|
{item}
|
package/Layout/Section.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import {Dimensions, View} from 'react-native';
|
|
3
3
|
import {validateChildren} from './utils';
|
|
4
|
-
import Card from './Card';
|
|
5
4
|
import {GridContextProps, SectionProps} from './types';
|
|
6
5
|
import {GridContext} from './index';
|
|
7
6
|
import {GRIDVIEW} from '../Consts';
|
|
7
|
+
import Item from './Item';
|
|
8
8
|
|
|
9
9
|
const Section: React.FC<SectionProps> = ({children, useMargin = true}) => {
|
|
10
10
|
const numberOfColumns = 12;
|
|
@@ -124,12 +124,12 @@ const Section: React.FC<SectionProps> = ({children, useMargin = true}) => {
|
|
|
124
124
|
<View
|
|
125
125
|
accessibilityLabel={`Section`}
|
|
126
126
|
style={{
|
|
127
|
-
width:
|
|
127
|
+
width: widthSection,
|
|
128
128
|
marginHorizontal: gridContext.margin,
|
|
129
129
|
flexDirection: 'row',
|
|
130
130
|
flexWrap: 'wrap',
|
|
131
131
|
}}>
|
|
132
|
-
{renderView(validateChildren(children,
|
|
132
|
+
{renderView(validateChildren(children, [Item]))}
|
|
133
133
|
{GRIDVIEW && renderOverlay()}
|
|
134
134
|
</View>
|
|
135
135
|
</GridContext.Provider>
|
|
@@ -138,7 +138,4 @@ const Section: React.FC<SectionProps> = ({children, useMargin = true}) => {
|
|
|
138
138
|
|
|
139
139
|
Section.displayName = 'Section';
|
|
140
140
|
|
|
141
|
-
Section.defaultProps = {
|
|
142
|
-
useMargin: true,
|
|
143
|
-
};
|
|
144
141
|
export default Section;
|
package/Layout/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ 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';
|
|
7
8
|
|
|
8
9
|
const GridContext = createContext<GridContextProps>({
|
|
9
10
|
numberOfColumns: 12,
|
|
@@ -13,4 +14,4 @@ const GridContext = createContext<GridContextProps>({
|
|
|
13
14
|
getSizeSpan: span => 0,
|
|
14
15
|
});
|
|
15
16
|
|
|
16
|
-
export {GridContext, Card, Section, GridSystem, validateChildren};
|
|
17
|
+
export {GridContext, Card, Section, GridSystem, validateChildren, Item};
|
package/Layout/types.ts
CHANGED
|
@@ -42,7 +42,7 @@ export interface SectionProps extends ViewProps {
|
|
|
42
42
|
useMargin?: boolean;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export interface
|
|
45
|
+
export interface ItemProps extends ViewProps {
|
|
46
46
|
/**
|
|
47
47
|
* Represents the width of the Card component in terms of span numbers (1-12).
|
|
48
48
|
*/
|
|
@@ -52,10 +52,8 @@ export interface CardProps extends ViewProps {
|
|
|
52
52
|
* Optional. Represents the height of the Card component in terms of span numbers (1-12).
|
|
53
53
|
*/
|
|
54
54
|
heightSpan?: SpanNumber;
|
|
55
|
+
}
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
* Defaults to `false` if not provided.
|
|
59
|
-
*/
|
|
60
|
-
usePadding?: boolean;
|
|
57
|
+
export interface CardProps extends ViewProps {
|
|
58
|
+
background?: string;
|
|
61
59
|
}
|
package/Layout/utils.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {Alert} from 'react-native';
|
|
2
2
|
import React, {ReactElement} from 'react';
|
|
3
|
+
import {SectionProps} from './types';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* validate children type
|
|
6
7
|
* @param children
|
|
7
|
-
* @param
|
|
8
|
+
* @param childrenTypes
|
|
8
9
|
*/
|
|
9
10
|
const validateChildren = (
|
|
10
11
|
children:
|
|
@@ -17,30 +18,39 @@ const validateChildren = (
|
|
|
17
18
|
| null
|
|
18
19
|
| undefined
|
|
19
20
|
| boolean,
|
|
20
|
-
|
|
21
|
+
childrenTypes: Array<React.FC<any>>,
|
|
21
22
|
) => {
|
|
22
23
|
if (!__DEV__) return children;
|
|
24
|
+
|
|
23
25
|
let results: React.ReactElement[] = [];
|
|
26
|
+
const validateType = (child: React.ReactElement) => {
|
|
27
|
+
return childrenTypes.some(childrenType => child?.type === childrenType);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const alertWrongType = () => {
|
|
31
|
+
Alert.alert(
|
|
32
|
+
'Component Kits',
|
|
33
|
+
`Wrong children type for this component, expected are ${childrenTypes
|
|
34
|
+
.map(type => type.displayName)
|
|
35
|
+
.join(', ')}.`,
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
24
39
|
if (Array.isArray(children)) {
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
const flattenChildren = children.flat();
|
|
41
|
+
results = flattenChildren.filter((child: React.ReactElement) => {
|
|
42
|
+
if (validateType(child)) {
|
|
27
43
|
return child;
|
|
28
44
|
} else {
|
|
29
|
-
|
|
30
|
-
'Component Kits',
|
|
31
|
-
`Wrong children type for this component, expected is ${childrenType.displayName}.`,
|
|
32
|
-
);
|
|
45
|
+
alertWrongType();
|
|
33
46
|
}
|
|
34
47
|
});
|
|
35
48
|
} else {
|
|
36
49
|
const singleChild: any = children;
|
|
37
|
-
if (singleChild
|
|
50
|
+
if (validateType(singleChild)) {
|
|
38
51
|
results = [singleChild];
|
|
39
52
|
} else {
|
|
40
|
-
|
|
41
|
-
'Component Kits',
|
|
42
|
-
`Wrong children type for this component, expected is ${childrenType.displayName}.`,
|
|
43
|
-
);
|
|
53
|
+
alertWrongType();
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
56
|
|