@momo-kits/step 0.0.64-beta → 0.0.65-alpha.8

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.
@@ -0,0 +1,252 @@
1
+ import { Colors, IconSource, Image, Spacing, Text } from '@momo-kits/core-v2';
2
+ import PropTypes from 'prop-types';
3
+ import React from 'react';
4
+ import { StyleSheet, View } from 'react-native';
5
+
6
+ const HorizontalStep = (props) => {
7
+ const {
8
+ steps = {},
9
+ currentStep,
10
+ type,
11
+ activeCircleColor,
12
+ inactiveCircleColor,
13
+ checkedCircleColor,
14
+ activeBorderColor,
15
+ inactiveBorderColor,
16
+ activeLineColor,
17
+ inactiveLineColor,
18
+ style,
19
+ size = 'default',
20
+ checkIcon,
21
+ errorIcon,
22
+ } = props;
23
+
24
+ let CIRCLE_SIZE = 24;
25
+ let CIRCLE_TEXT_SIZE = 12;
26
+ let ICON_SIZE = 16;
27
+ let TITLE_SIZE = { size: 14, lineHeight: 20 };
28
+ let SUBTITLE_SIZE = { size: 10, lineHeight: 14 };
29
+ let CONTENT_SIZE = { size: 12, lineHeight: 16 };
30
+ const ICON_URL = checkIcon || IconSource.ic_check_24;
31
+ const ERROR_ICON_URL = errorIcon || IconSource.ic_close_x_24;
32
+ if (size === 'small') {
33
+ CIRCLE_SIZE = 16;
34
+ CIRCLE_TEXT_SIZE = 8;
35
+ ICON_SIZE = 12;
36
+ TITLE_SIZE = { size: 12, lineHeight: 16 };
37
+ SUBTITLE_SIZE = { size: 10, lineHeight: 14 };
38
+ CONTENT_SIZE = { size: 10, lineHeight: 14 };
39
+ }
40
+
41
+ const renderCircle = (error, index) => {
42
+ let circleColor = inactiveCircleColor;
43
+ let borderColor = inactiveBorderColor;
44
+
45
+ if (index < currentStep) circleColor = checkedCircleColor;
46
+ else if (index === currentStep) circleColor = activeCircleColor;
47
+
48
+ if (index <= currentStep) borderColor = activeBorderColor;
49
+
50
+ if (error) {
51
+ circleColor = Colors.red_03;
52
+ borderColor = Colors.red_08;
53
+ }
54
+ return (
55
+ <View
56
+ style={[
57
+ styles.circle,
58
+ {
59
+ width: CIRCLE_SIZE,
60
+ height: CIRCLE_SIZE,
61
+ borderRadius: CIRCLE_SIZE / 2,
62
+ borderColor: borderColor,
63
+ backgroundColor: circleColor,
64
+ },
65
+ ]}>
66
+ {renderCircleContent(error, index)}
67
+ </View>
68
+ );
69
+ };
70
+
71
+ const renderCircleContent = (error, index) => {
72
+ const icon = error ? ERROR_ICON_URL : ICON_URL;
73
+ if (type === 'check') {
74
+ return (
75
+ <Image
76
+ source={icon}
77
+ style={[
78
+ styles.icon,
79
+ { width: ICON_SIZE, height: ICON_SIZE },
80
+ ]}
81
+ />
82
+ );
83
+ } else if (type === 'combine') {
84
+ return index < currentStep ? (
85
+ <Image
86
+ source={icon}
87
+ style={[
88
+ styles.icon,
89
+ { width: ICON_SIZE, height: ICON_SIZE },
90
+ ]}
91
+ />
92
+ ) : (
93
+ <Text
94
+ style={[
95
+ styles.circleText,
96
+ {
97
+ fontSize: CIRCLE_TEXT_SIZE,
98
+ lineHeight: CIRCLE_TEXT_SIZE + 2,
99
+ },
100
+ ]}>
101
+ {index + 1}
102
+ </Text>
103
+ );
104
+ }
105
+ return (
106
+ <Text
107
+ style={[
108
+ styles.circleText,
109
+ {
110
+ fontSize: CIRCLE_TEXT_SIZE,
111
+ lineHeight: CIRCLE_TEXT_SIZE + 2,
112
+ },
113
+ ]}>
114
+ {index + 1}
115
+ </Text>
116
+ );
117
+ };
118
+
119
+ const renderLine = (index) => {
120
+ let lineColor =
121
+ index < currentStep ? activeLineColor : inactiveLineColor;
122
+
123
+ if (index === -1 || index === steps.length - 1)
124
+ lineColor = 'transparent';
125
+
126
+ return <View style={[styles.line, { backgroundColor: lineColor }]} />;
127
+ };
128
+
129
+ const renderStepPart = (item, index) => {
130
+ const { title, subTitle, content, error } = item;
131
+ const weight = index === currentStep ? '600' : '400';
132
+ const disabledColor = Colors.black_09;
133
+ const errorColor = Colors.error;
134
+ return (
135
+ <View key={index.toString()} style={styles.stepPart}>
136
+ <Text
137
+ style={[
138
+ styles.subTitle,
139
+ {
140
+ fontSize: SUBTITLE_SIZE.size,
141
+ lineHeight: SUBTITLE_SIZE.lineHeight,
142
+ color:
143
+ index < currentStep && !error
144
+ ? disabledColor
145
+ : Colors.black_12,
146
+ },
147
+ ]}>
148
+ {subTitle}
149
+ </Text>
150
+ <View
151
+ style={{
152
+ flexDirection: 'row',
153
+ alignItems: 'center',
154
+ }}>
155
+ {renderLine(index - 1)}
156
+ {renderCircle(error, index)}
157
+ {renderLine(index)}
158
+ </View>
159
+ <Text
160
+ style={[
161
+ styles.title,
162
+ {
163
+ lineHeight: TITLE_SIZE.lineHeight,
164
+ fontSize: TITLE_SIZE.size,
165
+ fontWeight: weight,
166
+ color: error
167
+ ? errorColor
168
+ : index < currentStep
169
+ ? disabledColor
170
+ : null,
171
+ },
172
+ ]}>
173
+ {title}
174
+ </Text>
175
+ <Text
176
+ style={[
177
+ styles.contentText,
178
+ {
179
+ fontSize: CONTENT_SIZE.size,
180
+ lineHeight: CONTENT_SIZE.lineHeight,
181
+ color:
182
+ index < currentStep && !error
183
+ ? disabledColor
184
+ : Colors.black_12,
185
+ },
186
+ ]}>
187
+ {content}
188
+ </Text>
189
+ </View>
190
+ );
191
+ };
192
+
193
+ return (
194
+ <View style={style}>
195
+ <View style={styles.container}>
196
+ {steps.map((item, index) => {
197
+ return renderStepPart(item, index);
198
+ })}
199
+ </View>
200
+ </View>
201
+ );
202
+ };
203
+
204
+ export default HorizontalStep;
205
+
206
+ const styles = StyleSheet.create({
207
+ container: { flexDirection: 'row', width: '100%' },
208
+ circleContainer: {
209
+ flexDirection: 'column',
210
+ alignItems: 'center',
211
+ height: '100%',
212
+ },
213
+ circle: {
214
+ borderWidth: 2,
215
+ justifyContent: 'center',
216
+ alignItems: 'center',
217
+ margin: Spacing.XS,
218
+ },
219
+ contentContainer: { marginLeft: Spacing.S, flex: 1 },
220
+ content: { marginVertical: Spacing.XS },
221
+ contentText: {
222
+ color: Colors.black_12,
223
+ },
224
+ header: {
225
+ flexDirection: 'row',
226
+ justifyContent: 'space-between',
227
+ alignItems: 'center',
228
+ },
229
+ title: {
230
+ marginBottom: Spacing.XS,
231
+ },
232
+ subTitle: {
233
+ color: Colors.black_12,
234
+ },
235
+ line: {
236
+ height: 2,
237
+ borderRadius: 1,
238
+ flex: 1,
239
+ },
240
+ icon: {
241
+ tintColor: Colors.white,
242
+ },
243
+ circleText: {
244
+ color: Colors.white,
245
+ fontWeight: '600',
246
+ },
247
+ stepPart: {
248
+ flexDirection: 'column',
249
+ alignItems: 'center',
250
+ flex: 1,
251
+ },
252
+ });
@@ -0,0 +1,207 @@
1
+ import React from 'react';
2
+ import { StyleSheet, View, Image } from 'react-native';
3
+ import PropTypes from 'prop-types';
4
+ import Colors from '../../core/colors';
5
+ import Text from '../../core/components/typography';
6
+ import Spacing from '../../core/spacing';
7
+ import { Icons as IconSource } from '../../core/icons';
8
+
9
+ const CIRCLE_SIZE = 24;
10
+ const CIRCLE_TEXT_SIZE = 12;
11
+ const ICON_SIZE = 16;
12
+ const ICON_URL = IconSource.ic_check_24;
13
+ const TITLE_SIZE = { size: 12, lineHeight: 16 };
14
+ const SUBTITLE_SIZE = { size: 10, lineHeight: 14 };
15
+ const CONTENT_SIZE = { size: 12, lineHeight: 16 };
16
+
17
+ function HorizontalStep(props) {
18
+ HorizontalStep.displayName = 'HorizontalStep';
19
+ const {
20
+ steps = {},
21
+ currentStep,
22
+ type,
23
+ activeCircleColor,
24
+ inactiveCircleColor,
25
+ checkedCircleColor,
26
+ activeBorderColor,
27
+ inactiveBorderColor,
28
+ activeLineColor,
29
+ inactiveLineColor,
30
+ style,
31
+ } = props;
32
+ const { titles = [], subTitles = [], contents = [] } = steps;
33
+
34
+ const renderCircle = (index) => {
35
+ let circleColor = inactiveCircleColor;
36
+ let borderColor = inactiveBorderColor;
37
+
38
+ if (index < currentStep) circleColor = checkedCircleColor;
39
+ else if (index === currentStep) circleColor = activeCircleColor;
40
+
41
+ if (index <= currentStep) borderColor = activeBorderColor;
42
+
43
+ return (
44
+ <View
45
+ style={[
46
+ styles.circle,
47
+ {
48
+ borderColor: borderColor,
49
+ backgroundColor: circleColor,
50
+ },
51
+ ]}>
52
+ {renderCircleContent(index)}
53
+ </View>
54
+ );
55
+ };
56
+
57
+ const renderCircleContent = (index) => {
58
+ if (type === 'check') {
59
+ return <Image source={ICON_URL} style={styles.icon} />;
60
+ } else if (type === 'combine') {
61
+ return index < currentStep ? (
62
+ <Image source={ICON_URL} style={styles.icon} />
63
+ ) : (
64
+ <Text style={styles.circleText}>{index + 1}</Text>
65
+ );
66
+ }
67
+ return <Text style={styles.circleText}>{index + 1}</Text>;
68
+ };
69
+
70
+ const renderLine = (index) => {
71
+ let lineColor =
72
+ index < currentStep ? activeLineColor : inactiveLineColor;
73
+
74
+ if (index === -1 || index === steps.length - 1)
75
+ lineColor = 'transparent';
76
+
77
+ return (
78
+ <View style={[styles.line, { backgroundColor: lineColor }]}></View>
79
+ );
80
+ };
81
+
82
+ const renderStepPart = (item, index) => {
83
+ const { title, subTitle, content } = item;
84
+ const weight = index === currentStep ? '600' : '400';
85
+ return (
86
+ <View key={index.toString()} style={styles.stepPart}>
87
+ <Text style={styles.subTitle}>{subTitle}</Text>
88
+ <View
89
+ style={{
90
+ flexDirection: 'row',
91
+ alignItems: 'center',
92
+ }}>
93
+ {renderLine(index - 1)}
94
+ {renderCircle(index)}
95
+ {renderLine(index)}
96
+ </View>
97
+ <Text style={[styles.title, { fontWeight: weight }]}>
98
+ {title}
99
+ </Text>
100
+ <Text style={styles.contentText}>{content}</Text>
101
+ </View>
102
+ );
103
+ };
104
+
105
+ return (
106
+ <View style={style}>
107
+ <View style={styles.container}>
108
+ {steps.map((item, index) => {
109
+ return renderStepPart(item, index);
110
+ })}
111
+ </View>
112
+ </View>
113
+ );
114
+ }
115
+
116
+ export default HorizontalStep;
117
+
118
+ const styles = StyleSheet.create({
119
+ container: { flexDirection: 'row', width: '100%' },
120
+ circleContainer: {
121
+ flexDirection: 'column',
122
+ alignItems: 'center',
123
+ height: '100%',
124
+ },
125
+ circle: {
126
+ width: CIRCLE_SIZE,
127
+ height: CIRCLE_SIZE,
128
+ borderRadius: CIRCLE_SIZE / 2,
129
+ borderWidth: 2,
130
+ justifyContent: 'center',
131
+ alignItems: 'center',
132
+ margin: Spacing.XS,
133
+ },
134
+ contentContainer: { marginLeft: Spacing.S, flex: 1 },
135
+ content: { marginVertical: Spacing.XS },
136
+ contentText: {
137
+ fontSize: CONTENT_SIZE.size,
138
+ lineHeight: CONTENT_SIZE.lineHeight,
139
+ color: Colors.black_12,
140
+ },
141
+ header: {
142
+ flexDirection: 'row',
143
+ justifyContent: 'space-between',
144
+ alignItems: 'center',
145
+ },
146
+ title: {
147
+ lineHeight: TITLE_SIZE.lineHeight,
148
+ fontSize: TITLE_SIZE.size,
149
+ marginBottom: Spacing.XS,
150
+ },
151
+ subTitle: {
152
+ fontSize: SUBTITLE_SIZE.size,
153
+ lineHeight: SUBTITLE_SIZE.lineHeight,
154
+ color: Colors.black_12,
155
+ },
156
+ line: {
157
+ height: 2,
158
+ borderRadius: 1,
159
+ flex: 1,
160
+ },
161
+ icon: {
162
+ width: ICON_SIZE,
163
+ height: ICON_SIZE,
164
+ tintColor: Colors.white,
165
+ },
166
+ circleText: {
167
+ fontSize: CIRCLE_TEXT_SIZE,
168
+ color: Colors.white,
169
+ fontWeight: '600',
170
+ },
171
+ stepPart: {
172
+ flexDirection: 'column',
173
+ alignItems: 'center',
174
+ flex: 1,
175
+ },
176
+ });
177
+
178
+ HorizontalStep.propTypes = {
179
+ steps: PropTypes.arrayOf({
180
+ title: PropTypes.string.isRequired,
181
+ subTitle: PropTypes.string,
182
+ content: PropTypes.string,
183
+ }),
184
+ currentStep: PropTypes.number,
185
+ type: PropTypes.oneOf(['check', 'combine', 'text']),
186
+ activeCircleColor: PropTypes.string,
187
+ inactiveCircleColor: PropTypes.string,
188
+ checkedCircleColor: PropTypes.string,
189
+ activeBorderColor: PropTypes.string,
190
+ inactiveBorderColor: PropTypes.string,
191
+ activeLineColor: PropTypes.string,
192
+ inactiveLineColor: PropTypes.string,
193
+ style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
194
+ };
195
+
196
+ HorizontalStep.defaultProps = {
197
+ step: [{ title: '', subTitle: '', content: '' }],
198
+ currentStep: 0,
199
+ type: 'check',
200
+ activeCircleColor: Colors.pink_05_b,
201
+ inactiveCircleColor: Colors.black_06,
202
+ checkedCircleColor: '#f382c0',
203
+ activeBorderColor: Colors.pink_09,
204
+ inactiveBorderColor: Colors.black_04,
205
+ activeLineColor: '#fbd5ea',
206
+ inactiveLineColor: Colors.black_04,
207
+ };