@momo-kits/step 0.0.60-rc.6 → 0.0.60-rc.7

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.
@@ -1,434 +1,251 @@
1
- import { Colors, IconSource, Image, Text } from '@momo-kits/core';
1
+ import { Colors, IconSource, Image, Spacing } from '@momo-kits/core-v2';
2
+ import { Text } from '@momo-kits/core';
2
3
  import PropTypes from 'prop-types';
3
- import React, { Component } from 'react';
4
- import { Dimensions, StyleSheet, View } from 'react-native';
5
- import { IS_VALID_URL } from './Step.constants';
4
+ import React from 'react';
5
+ import { StyleSheet, View } from 'react-native';
6
+
7
+ const HorizontalStep = (props) => {
8
+ const {
9
+ steps = {},
10
+ currentStep,
11
+ type,
12
+ activeCircleColor,
13
+ inactiveCircleColor,
14
+ checkedCircleColor,
15
+ activeBorderColor,
16
+ inactiveBorderColor,
17
+ activeLineColor,
18
+ inactiveLineColor,
19
+ style,
20
+ size = 'default',
21
+ checkIcon,
22
+ errorIcon,
23
+ } = props;
24
+
25
+ let CIRCLE_SIZE = 24;
26
+ let CIRCLE_TEXT_SIZE = 12;
27
+ let ICON_SIZE = 16;
28
+ let TITLE_SIZE = { size: 14, lineHeight: 20 };
29
+ let SUBTITLE_SIZE = { size: 10, lineHeight: 14 };
30
+ let CONTENT_SIZE = { size: 12, lineHeight: 16 };
31
+ const ICON_URL = checkIcon || IconSource.ic_check_24;
32
+ const ERROR_ICON_URL = errorIcon || IconSource.ic_close_x_24;
33
+ if (size === 'small') {
34
+ CIRCLE_SIZE = 16;
35
+ CIRCLE_TEXT_SIZE = 8;
36
+ ICON_SIZE = 12;
37
+ TITLE_SIZE = { size: 12, lineHeight: 16 };
38
+ SUBTITLE_SIZE = { size: 10, lineHeight: 14 };
39
+ CONTENT_SIZE = { size: 10, lineHeight: 14 };
40
+ }
6
41
 
7
- const CIRCLE_SIZE = 24;
8
- const SCREEN_WIDTH = Dimensions.get('window').width;
42
+ const renderCircle = (error, index) => {
43
+ let circleColor = inactiveCircleColor;
44
+ let borderColor = inactiveBorderColor;
9
45
 
10
- const styles = StyleSheet.create({
11
- circle: {
12
- width: CIRCLE_SIZE,
13
- height: CIRCLE_SIZE,
14
- borderRadius: CIRCLE_SIZE / 2,
15
- borderWidth: 2,
16
- padding: 4,
17
- },
18
- iconImage: {
19
- width: 16,
20
- height: 16,
21
- position: 'absolute',
22
- top: 2,
23
- left: 2,
24
- },
25
- titleDefault: {
26
- fontSize: 14,
27
- color: Colors.black_12,
28
- fontWeight: 'normal',
29
- },
30
- titleActive: {
31
- fontSize: 14,
32
- color: Colors.black_17,
33
- fontWeight: 'bold',
34
- },
35
- description: {
36
- fontSize: 12,
37
- color: Colors.black_12,
38
- marginBottom: 16,
39
- paddingTop: 4,
40
- paddingLeft: 11,
41
- },
42
- date: {
43
- fontSize: 10,
44
- color: Colors.black_12,
45
- },
46
- number: {
47
- fontSize: 12,
48
- color: 'white',
49
- textAlign: 'center',
50
- lineHeight: 13,
51
- },
52
- lineHorizontal: {
53
- height: 2,
54
- width: '100%',
55
- },
56
- minHeight: {
57
- minHeight: 12,
58
- marginBottom: 4,
59
- },
60
- });
61
- export default class HorizontalStep extends Component {
62
- constructor(props) {
63
- super(props);
64
- this.state = {
65
- width: 0,
66
- height: 0,
67
- };
68
- }
46
+ if (index < currentStep) circleColor = checkedCircleColor;
47
+ else if (index === currentStep) circleColor = activeCircleColor;
69
48
 
70
- onLayout = (e) => {
71
- this.setState({
72
- width: e.nativeEvent.layout.width,
73
- height: e.nativeEvent.layout.height,
74
- });
75
- };
49
+ if (index <= currentStep) borderColor = activeBorderColor;
76
50
 
77
- _renderCircleImage = ({
78
- icon = '',
79
- circleColor = '',
80
- circleBorderColor = '',
81
- }) => {
51
+ if (error) {
52
+ circleColor = Colors.red_03;
53
+ borderColor = Colors.red_08;
54
+ }
82
55
  return (
83
- <View>
84
- <View
85
- style={[
86
- styles.circle,
87
- {
88
- backgroundColor: circleColor,
89
- borderColor: circleBorderColor,
90
- },
91
- ]}>
92
- <Image
93
- source={icon}
94
- style={[styles.iconImage, { tintColor: '#ffffff' }]}
95
- />
96
- </View>
56
+ <View
57
+ style={[
58
+ styles.circle,
59
+ {
60
+ width: CIRCLE_SIZE,
61
+ height: CIRCLE_SIZE,
62
+ borderRadius: CIRCLE_SIZE / 2,
63
+ borderColor: borderColor,
64
+ backgroundColor: circleColor,
65
+ },
66
+ ]}>
67
+ {renderCircleContent(error, index)}
97
68
  </View>
98
69
  );
99
70
  };
100
71
 
101
- _renderCircleText = ({
102
- circleColor = '',
103
- circleBorderColor = '',
104
- index = 0,
105
- }) => {
106
- return (
107
- <View>
108
- <View
72
+ const renderCircleContent = (error, index) => {
73
+ const icon = error ? ERROR_ICON_URL : ICON_URL;
74
+ if (type === 'check') {
75
+ return (
76
+ <Image
77
+ source={icon}
109
78
  style={[
110
- styles.circle,
111
- {
112
- backgroundColor: circleColor,
113
- borderColor: circleBorderColor,
114
- },
115
- ]}>
116
- <Text style={styles.number}>{index + 1}</Text>
117
- </View>
118
- </View>
119
- );
120
- };
121
-
122
- _renderDateOrValue = ({
123
- date = '',
124
- isActiveState = false,
125
- circleChecked = false,
126
- minHeight = 0,
127
- dateStyle = {},
128
- index = 0,
129
- }) => {
130
- // Init states in render function
131
- let resultComponent = <></>;
132
- if (!date) {
133
- return resultComponent;
134
- }
135
- if (isActiveState || circleChecked) {
136
- resultComponent = (
79
+ styles.icon,
80
+ { width: ICON_SIZE, height: ICON_SIZE },
81
+ ]}
82
+ />
83
+ );
84
+ } else if (type === 'combine') {
85
+ return index < currentStep ? (
86
+ <Image
87
+ source={icon}
88
+ style={[
89
+ styles.icon,
90
+ { width: ICON_SIZE, height: ICON_SIZE },
91
+ ]}
92
+ />
93
+ ) : (
137
94
  <Text
138
95
  style={[
139
- styles.date,
140
- dateStyle,
141
- { minHeight: 12, marginBottom: 4 },
96
+ styles.circleText,
97
+ {
98
+ fontSize: CIRCLE_TEXT_SIZE,
99
+ },
142
100
  ]}>
143
- {date[index]}
101
+ {index + 1}
144
102
  </Text>
145
103
  );
146
- } else {
147
- resultComponent = <View style={minHeight}></View>;
148
104
  }
149
- return resultComponent;
150
- };
151
-
152
- _renderCircle = ({
153
- circleColor = '',
154
- circleBorderColor = '',
155
- isActiveState = false,
156
- circleUnchecked = false,
157
- iconActive = '',
158
- iconUnchecked = '',
159
- icon = {},
160
- index = 0,
161
- }) => {
162
- let resultComponent = <></>;
163
- if (!isActiveState) {
164
- if (circleUnchecked) {
165
- if (IS_VALID_URL.test(iconUnchecked)) {
166
- resultComponent = this._renderCircleImage({
167
- icon,
168
- circleColor,
169
- circleBorderColor,
170
- });
171
- } else {
172
- resultComponent = this._renderCircleText({
173
- circleColor,
174
- circleBorderColor,
175
- index,
176
- });
177
- }
178
- } else {
179
- resultComponent = this._renderCircleImage({
180
- icon,
181
- circleColor,
182
- circleBorderColor,
183
- });
184
- }
185
- } else {
186
- // This is active case
187
- // If icon diff "" & regex http or https url so will render image component
188
- if (IS_VALID_URL.test(iconActive)) {
189
- resultComponent = this._renderCircleImage({
190
- icon,
191
- circleColor,
192
- circleBorderColor,
193
- });
194
- } else {
195
- // Otherwise render index number in text component
196
- resultComponent = resultComponent = this._renderCircleText({
197
- circleColor,
198
- circleBorderColor,
199
- index,
200
- });
201
- }
202
- }
203
- return resultComponent;
204
- };
205
-
206
- _renderTitle = ({ textFontStyle = {}, titleStyle = {}, value = {} }) => {
207
- let resultComponent = (
208
- <View>
209
- <Text.Caption
210
- style={[{ marginTop: 4 }, textFontStyle, titleStyle]}>
211
- {value}
212
- </Text.Caption>
213
- </View>
105
+ return (
106
+ <Text
107
+ style={[
108
+ styles.circleText,
109
+ {
110
+ fontSize: CIRCLE_TEXT_SIZE,
111
+ },
112
+ ]}>
113
+ {index + 1}
114
+ </Text>
214
115
  );
215
- return resultComponent;
216
116
  };
217
117
 
218
- _renderDescription = ({ items = {}, descriptionStyle = {}, index = 0 }) => {
219
- let resultComponent = <></>;
220
-
221
- if (items) {
222
- resultComponent = (
223
- <View>
224
- <Text style={[{ fontSize: 10 }, descriptionStyle]}>
225
- {items[index]}
226
- </Text>
227
- </View>
228
- );
229
- }
230
- return resultComponent;
231
- };
118
+ const renderLine = (index) => {
119
+ let lineColor =
120
+ index < currentStep ? activeLineColor : inactiveLineColor;
232
121
 
233
- _renderLine = ({
234
- titles = {},
235
- index = 0,
236
- lineRight = 0,
237
- lineWidth = 0,
238
- lineActive = '',
239
- date,
240
- }) => {
241
- let resultComponent = <></>;
122
+ if (index === -1 || index === steps.length - 1)
123
+ lineColor = 'transparent';
242
124
 
243
- if (titles?.length - 1 !== index) {
244
- resultComponent = (
245
- <View
246
- style={{
247
- position: 'absolute',
248
- right: lineRight,
249
- width: lineWidth,
250
- zIndex: -1,
251
- }}>
252
- <View
253
- style={[
254
- styles.lineHorizontal,
255
- {
256
- backgroundColor: lineActive,
257
- },
258
- date ? { marginTop: 27 } : { marginTop: 27 - 16 },
259
- /* subtracting spacing from date */
260
- ]}
261
- />
262
- </View>
263
- );
264
- }
265
- return resultComponent;
125
+ return <View style={[styles.line, { backgroundColor: lineColor }]} />;
266
126
  };
267
127
 
268
- circleColumn = (value, index) => {
269
- const {
270
- currentStep,
271
- titles,
272
- iconActive,
273
- iconChecked,
274
- iconUnchecked,
275
- circleColorActive,
276
- circleColorChecked,
277
- circleColorUnchecked,
278
- circleBorderColorActive,
279
- circleBorderColorChecked,
280
- circleBorderColorUnchecked,
281
- lineColorActive,
282
- lineColorInActive,
283
- items,
284
- date,
285
- isVertical,
286
- titleStyle,
287
- descriptionStyle,
288
- dateStyle,
289
- } = this.props;
290
-
291
- // Three circle states
292
- const isActiveState = currentStep == index + 1;
293
- const circleChecked = currentStep > index + 1;
294
- const circleUnchecked = currentStep < index + 1;
295
-
296
- // Default properties is inactive state
297
- let icon = {};
298
- let circleColor = circleColorUnchecked || Colors.black_06;
299
- let circleBorderColor = circleBorderColorUnchecked || Colors.black_04;
300
- let textFontStyle = styles.titleDefault;
301
- let lineActive = lineColorInActive || Colors.black_04;
302
- let minHeight = !isVertical && styles.minHeight;
303
- let accessibilityLabel = 'uncheck';
304
- let tintColor = '#ffd6e7';
305
-
306
- // This is all properties in active state
307
- if (isActiveState) {
308
- icon = iconActive || index + 1;
309
- circleColor = circleColorActive || '#d82d8b';
310
- circleBorderColor = circleBorderColorActive || Colors.pink_09;
311
- textFontStyle = styles.titleActive;
312
- accessibilityLabel = 'checking';
313
- }
314
-
315
- if (circleChecked) {
316
- icon = iconChecked || IconSource.ic_check_24;
317
- lineActive = lineColorActive || tintColor;
318
- circleColor = circleColorChecked || '#ffadd2';
319
- circleBorderColor = circleBorderColorChecked || Colors.pink_09;
320
- accessibilityLabel = 'checked';
321
- }
322
-
323
- if (circleUnchecked) {
324
- icon = iconUnchecked || index + 1;
325
- }
326
-
327
- const lineWidth = Math.round(
328
- (SCREEN_WIDTH - 10 - CIRCLE_SIZE - 4) / titles.length,
329
- );
330
- const lineRight = parseInt(`-${lineWidth / 2}`);
331
-
128
+ const renderStepPart = (item, index) => {
129
+ const { title, subTitle, content, error } = item;
130
+ const weight = index === currentStep ? '600' : '400';
131
+ const disabledColor = Colors.black_09;
132
+ const errorColor = Colors.error;
332
133
  return (
333
- <View
334
- key={index}
335
- style={{
336
- flexDirection: 'row',
337
- flex: 1,
338
- justifyContent: 'center',
339
- width: lineWidth,
340
- // backgroundColor: 'red'
341
- }}>
134
+ <View key={index.toString()} style={styles.stepPart}>
135
+ <Text
136
+ style={[
137
+ styles.subTitle,
138
+ {
139
+ fontSize: SUBTITLE_SIZE.size,
140
+ lineHeight: SUBTITLE_SIZE.lineHeight,
141
+ color:
142
+ index < currentStep && !error
143
+ ? disabledColor
144
+ : Colors.black_12,
145
+ },
146
+ ]}>
147
+ {subTitle}
148
+ </Text>
342
149
  <View
343
- accessibilityLabel={accessibilityLabel}
344
150
  style={{
345
- flexDirection: 'column',
151
+ flexDirection: 'row',
346
152
  alignItems: 'center',
347
153
  }}>
348
- {this._renderDateOrValue({
349
- date,
350
- isActiveState,
351
- circleChecked,
352
- minHeight,
353
- dateStyle,
354
- index,
355
- })}
356
- {this._renderCircle({
357
- circleColor,
358
- circleBorderColor,
359
- isActiveState,
360
- circleUnchecked,
361
- iconActive,
362
- iconUnchecked,
363
- icon,
364
- index,
365
- })}
366
- {this._renderTitle({
367
- textFontStyle,
368
- titleStyle,
369
- value,
370
- })}
371
- {this._renderDescription({
372
- items,
373
- descriptionStyle,
374
- index,
375
- })}
154
+ {renderLine(index - 1)}
155
+ {renderCircle(error, index)}
156
+ {renderLine(index)}
376
157
  </View>
377
- {this._renderLine({
378
- titles,
379
- index,
380
- lineRight,
381
- lineWidth,
382
- lineActive,
383
- date,
384
- })}
158
+ <Text
159
+ style={[
160
+ styles.title,
161
+ {
162
+ lineHeight: TITLE_SIZE.lineHeight,
163
+ fontSize: TITLE_SIZE.size,
164
+ fontWeight: weight,
165
+ color: error
166
+ ? errorColor
167
+ : index < currentStep
168
+ ? disabledColor
169
+ : null,
170
+ },
171
+ ]}>
172
+ {title}
173
+ </Text>
174
+ <Text
175
+ style={[
176
+ styles.contentText,
177
+ {
178
+ fontSize: CONTENT_SIZE.size,
179
+ lineHeight: CONTENT_SIZE.lineHeight,
180
+ color:
181
+ index < currentStep && !error
182
+ ? disabledColor
183
+ : Colors.black_12,
184
+ },
185
+ ]}>
186
+ {content}
187
+ </Text>
385
188
  </View>
386
189
  );
387
190
  };
388
191
 
389
- renderCircle = () => {
390
- const { titles = [[]] } = this.props;
391
- return titles.map(this.circleColumn);
392
- };
393
-
394
- render() {
395
- const { style = {} } = this.props;
396
- return (
397
- <View style={[style]} onLayout={this.onLayout}>
398
- <View
399
- style={{
400
- flexDirection: 'row',
401
- }}>
402
- {this.renderCircle()}
403
- </View>
192
+ return (
193
+ <View style={style}>
194
+ <View style={styles.container}>
195
+ {steps.map((item, index) => {
196
+ return renderStepPart(item, index);
197
+ })}
404
198
  </View>
405
- );
406
- }
407
- }
408
-
409
- HorizontalStep.propTypes = {
410
- titles: PropTypes.array,
411
- currentStep: PropTypes.number,
412
- style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
413
- items: PropTypes.array,
414
- isVertical: PropTypes.bool,
415
- iconActive: PropTypes.any,
416
- iconChecked: PropTypes.any,
417
- iconUnchecked: PropTypes.any,
418
- circleColorActive: PropTypes.string,
419
- circleColorChecked: PropTypes.string,
420
- circleColorUnchecked: PropTypes.string,
421
- circleBorderColorActive: PropTypes.string,
422
- circleBorderColorChecked: PropTypes.string,
423
- circleBorderColorUnchecked: PropTypes.string,
424
- lineColorActive: PropTypes.string,
425
- lineColorInActive: PropTypes.string,
426
- titleStyle: PropTypes.object,
427
- descriptionStyle: PropTypes.object,
428
- dateStyle: PropTypes.object,
199
+ </View>
200
+ );
429
201
  };
430
202
 
431
- HorizontalStep.defaultProps = {
432
- titles: [],
433
- currentStep: 0,
434
- };
203
+ export default HorizontalStep;
204
+
205
+ const styles = StyleSheet.create({
206
+ container: { flexDirection: 'row', width: '100%' },
207
+ circleContainer: {
208
+ flexDirection: 'column',
209
+ alignItems: 'center',
210
+ height: '100%',
211
+ },
212
+ circle: {
213
+ borderWidth: 2,
214
+ justifyContent: 'center',
215
+ alignItems: 'center',
216
+ margin: Spacing.XS,
217
+ },
218
+ contentContainer: { marginLeft: Spacing.S, flex: 1 },
219
+ content: { marginVertical: Spacing.XS },
220
+ contentText: {
221
+ color: Colors.black_12,
222
+ },
223
+ header: {
224
+ flexDirection: 'row',
225
+ justifyContent: 'space-between',
226
+ alignItems: 'center',
227
+ },
228
+ title: {
229
+ marginBottom: Spacing.XS,
230
+ },
231
+ subTitle: {
232
+ color: Colors.black_12,
233
+ },
234
+ line: {
235
+ height: 2,
236
+ borderRadius: 1,
237
+ flex: 1,
238
+ },
239
+ icon: {
240
+ tintColor: Colors.white,
241
+ },
242
+ circleText: {
243
+ color: Colors.white,
244
+ fontWeight: '600',
245
+ },
246
+ stepPart: {
247
+ flexDirection: 'column',
248
+ alignItems: 'center',
249
+ flex: 1,
250
+ },
251
+ });