@momo-kits/stepper 0.0.65-alpha.20 → 0.0.65-alpha.23

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 (3) hide show
  1. package/Stepper.js +325 -225
  2. package/Stepper.web.js +260 -199
  3. package/package.json +2 -2
package/Stepper.js CHANGED
@@ -1,256 +1,356 @@
1
- import {
2
- Colors,
3
- Image,
4
- Radius,
5
- Spacing,
6
- Text,
7
- TouchableOpacity,
8
- } from '@momo-kits/core-v2';
1
+ import React, { Component } from 'react';
2
+ import { View, StyleSheet, TextInput, Keyboard } from 'react-native';
9
3
  import PropTypes from 'prop-types';
10
- import React, {useState} from 'react';
11
- import {StyleSheet, TextInput as Input, View} from 'react-native';
4
+ import { Text, Colors, Image, TouchableOpacity } from '@momo-kits/core';
12
5
 
13
6
  const minus =
14
- 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_minus_circle.png';
7
+ 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_minus_circle.png';
15
8
  const plus =
16
- 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_plus_circle.png';
9
+ 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_plus_circle.png';
17
10
 
18
- const Quantity = props => {
19
- const {
20
- disabled,
21
- min = 0,
22
- max = 5,
23
- defaultValue = 0,
24
- size,
25
- onChange,
26
- onIncreasePress,
27
- onDecreasePress,
28
- isInput = false,
29
- step = 1,
30
- style,
31
- tintColor,
32
- } = props;
11
+ const styles = StyleSheet.create({
12
+ container: {
13
+ flexDirection: 'row',
14
+ },
15
+ icon: {
16
+ height: 24,
17
+ width: 24,
18
+ resizeMode: 'contain',
19
+ tintColor: Colors.pink_03,
20
+ },
21
+ text: {
22
+ color: Colors.black_17,
23
+ },
24
+ numberBox: {
25
+ justifyContent: 'center',
26
+ alignItems: 'center',
27
+ marginHorizontal: 6,
28
+ backgroundColor: Colors.white,
29
+ },
30
+ button: {
31
+ justifyContent: 'center',
32
+ alignItems: 'center',
33
+ backgroundColor: Colors.white,
34
+ borderColor: 'transparent',
35
+ },
36
+ borderBox: {
37
+ borderColor: Colors.black_04,
38
+ borderWidth: 1,
39
+ borderRadius: 6,
40
+ },
41
+ disabledIcon: {
42
+ tintColor: Colors.black_09,
43
+ },
44
+ disabledBox: {
45
+ borderColor: Colors.black_03,
46
+ backgroundColor: Colors.black_03,
47
+ },
48
+ });
33
49
 
34
- const [value, setValue] = useState(defaultValue);
50
+ const getStyle = (type) => {
51
+ const objStyle = {
52
+ large: {
53
+ size: {
54
+ ...styles.borderBox,
55
+ width: 32, // height: 26
56
+ },
57
+ icon: {
58
+ width: 24,
59
+ height: 24,
60
+ resizeMode: 'contain',
61
+ },
62
+ text: 'Title',
63
+ },
64
+ medium: {
65
+ size: {
66
+ ...styles.borderBox,
67
+ width: 28, // height: 24
68
+ },
69
+ icon: {
70
+ width: 24,
71
+ height: 24,
72
+ resizeMode: 'contain',
73
+ },
74
+ text: 'SubTitle',
75
+ },
76
+ small: {
77
+ size: {
78
+ ...styles.borderBox,
79
+ width: 20, // height: 16
80
+ },
81
+ icon: {
82
+ width: 16,
83
+ height: 16,
84
+ resizeMode: 'contain',
85
+ },
86
+ text: 'Caption',
87
+ },
88
+ };
89
+ return objStyle[type] || objStyle.medium;
90
+ };
35
91
 
36
- const getStyle = size => {
37
- switch (size) {
38
- case 'medium':
39
- return {
40
- button: {
41
- width: 28,
42
- height: 28,
43
- borderRadius: Radius.M + Radius.XXS,
44
- },
45
- icon: {
46
- width: 24,
47
- height: 24,
48
- },
49
- input: {
50
- minWidth: 28,
51
- minHeight: 24,
52
- borderRadius: Radius.S,
53
- },
54
- text: {
55
- fontSize: 12,
56
- lineHeight: 16,
57
- },
58
- };
59
- case 'large':
60
- return {
61
- button: {
62
- width: 36,
63
- height: 36,
64
- borderRadius: Radius.L + Radius.XXS,
65
- },
66
- icon: {
67
- width: 24,
68
- height: 24,
69
- },
70
- input: {
71
- minWidth: 32,
72
- minHeight: 26,
73
- borderRadius: Radius.S,
74
- },
75
- text: {
76
- fontSize: 12,
77
- lineHeight: 16,
78
- },
92
+ const getSize = (type) => {
93
+ const objStyle = {
94
+ large: {
95
+ size: {
96
+ width: 32,
97
+ height: 24, // height: 26
98
+ },
99
+ },
100
+ medium: {
101
+ size: {
102
+ width: 28,
103
+ height: 24, // height: 24
104
+ },
105
+ },
106
+ small: {
107
+ size: {
108
+ width: 20,
109
+ height: 16, // height: 16
110
+ },
111
+ },
112
+ };
113
+ return objStyle[type] || objStyle.medium;
114
+ };
115
+
116
+ export default class Quantity extends Component {
117
+ constructor(props) {
118
+ super(props);
119
+ this.state = {
120
+ value: props.defaultValue || props.min,
121
+ ownUpdate: false,
79
122
  };
80
123
  }
81
- };
82
-
83
- const validateValue = value => {
84
- if (value < min) value = min;
85
- if (value > max) value = max;
86
- return value;
87
- };
88
124
 
89
- const onDecrease = () => {
90
- let newValue = value;
91
- if (value > min) {
92
- newValue = value - step;
125
+ componentDidMount() {
126
+ Keyboard.addListener(
127
+ 'keyboardDidHide',
128
+ this.checkData(
129
+ this.state.value,
130
+ 'increase',
131
+ this.props.min,
132
+ this.props.max,
133
+ ),
134
+ );
93
135
  }
94
- if (newValue < min) newValue = min;
95
136
 
96
- if (onDecreasePress && typeof onDecreasePress === 'function') {
97
- onDecreasePress(newValue);
137
+ componentWillUnmount() {
138
+ Keyboard.removeAllListeners('keyboardDidHide');
98
139
  }
99
140
 
100
- setValue(newValue);
101
- };
102
-
103
- const onIncrease = () => {
104
- let newValue = value;
105
- if (value < max) {
106
- newValue = value + step;
141
+ static getDerivedStateFromProps(nextProps, prevState) {
142
+ const { value = undefined } = this?.props || {};
143
+ if (prevState.ownUpdate) {
144
+ return {
145
+ ownUpdate: false,
146
+ };
147
+ }
148
+ if (nextProps.value !== value && nextProps.value !== prevState.value) {
149
+ return { value: nextProps.value };
150
+ }
151
+ return null;
107
152
  }
108
- if (newValue > max) newValue = max;
109
153
 
110
- if (onIncreasePress && typeof onIncreasePress === 'function') {
111
- onIncreasePress(newValue);
112
- }
154
+ onChangeValue = (value, type) => {
155
+ const { onChange } = this.props;
156
+ return (
157
+ onChange && typeof onChange === 'function' && onChange(value, type)
158
+ );
159
+ };
113
160
 
114
- setValue(newValue);
115
- };
161
+ getValue = (key, step) => {
162
+ const { isIncreaseValue, isDecreaseValue } = this.props;
163
+ const value = {
164
+ increase: isIncreaseValue ? parseInt(step) : 0,
165
+ decrease: isDecreaseValue ? parseInt(step) : 0,
166
+ };
167
+ return value[key];
168
+ };
116
169
 
117
- const onPressButton = type => {
118
- if (type === 'plus') {
119
- onIncrease();
120
- } else {
121
- onDecrease();
122
- }
123
- };
124
- const renderButton = (type, size, icon) => {
125
- let disabledStatus = props.disabled;
126
- if (type === 'plus' && value === max) disabledStatus = true;
127
- if (type === 'minus' && value === min) disabledStatus = true;
170
+ setValue = (newValue = 0, type) => {
171
+ this.setState(
172
+ {
173
+ value: newValue,
174
+ ownUpdate: true,
175
+ },
176
+ () => {
177
+ this.onChangeValue(newValue, type);
178
+ },
179
+ );
180
+ };
128
181
 
129
- if (onPressButton) {
130
- return (
131
- <TouchableOpacity
132
- disabled={disabledStatus}
133
- onPress={() => onPressButton(type)}
134
- style={[getStyle(size)?.button, styles.button]}>
135
- <Image
136
- source={icon}
137
- style={[
138
- getStyle(size)?.icon,
139
- {tintColor},
140
- disabledStatus && styles.disabledButton,
141
- ]}
142
- />
143
- </TouchableOpacity>
144
- );
145
- }
146
- };
182
+ checkData = (value, type, min, max) => () => {
183
+ if (value < min) {
184
+ this.setState({ value: min, ownUpdate: true }, () => {
185
+ this.onChangeValue(value, type);
186
+ });
187
+ } else if (value > max) {
188
+ this.setState({ value: max, ownUpdate: true }, () => {
189
+ this.onChangeValue(value, type);
190
+ });
191
+ }
147
192
 
148
- const onChangeText = value => {
149
- let newValue = validateValue(parseInt(value)) || '0';
150
- if (value.length > 1 && value[0] === 0) {
151
- newValue = value.substring(1);
152
- }
193
+ console.log(value, min, max);
194
+ };
153
195
 
154
- if (onChange && typeof onChange === 'function') onChange(newValue);
196
+ onPress =
197
+ (isIncrease = true, step) =>
198
+ () => {
199
+ const { isChangeValue, onConditionCheck } = this.props;
200
+ const { value } = this.state;
201
+ const type = isIncrease ? 'increase' : 'decrease';
202
+ if (isChangeValue && value !== '') {
203
+ const newValue = isIncrease
204
+ ? parseInt(value) + this.getValue('increase', step)
205
+ : parseInt(value) - this.getValue('decrease', step);
206
+ if (typeof onConditionCheck === 'function') {
207
+ const passCondition = onConditionCheck(newValue, type);
208
+ if (passCondition) {
209
+ this.setValue(newValue, type);
210
+ }
211
+ } else {
212
+ this.setValue(newValue, type);
213
+ }
214
+ } else {
215
+ this.onChangeValue(value, type);
216
+ }
217
+ };
155
218
 
156
- setValue(newValue);
157
- };
219
+ render() {
220
+ const { value } = this.state;
221
+ const {
222
+ style,
223
+ valueStyle,
224
+ size,
225
+ tintColor,
226
+ isIncreaseValue,
227
+ isSingle,
228
+ iconStyle,
229
+ isInput,
230
+ disabled,
231
+ step,
232
+ } = this.props;
233
+ const { min } = this.props || 1;
234
+ const { max } = this.props || 999;
235
+ if (isSingle && value === 0) {
236
+ return (
237
+ <View style={[styles.container, style]}>
238
+ <IconButton
239
+ tintColor={tintColor}
240
+ size={size}
241
+ disabled={value >= max || !isIncreaseValue}
242
+ onPress={this.onPress(true, step)}
243
+ icon={plus}
244
+ />
245
+ </View>
246
+ );
247
+ }
248
+ const TextComp = Text[getStyle(size).text];
158
249
 
159
- return (
160
- <View style={style}>
161
- <View style={styles.container}>
162
- {renderButton('minus', size, minus)}
163
- <View style={styles.inputContainer}>
164
- {isInput ? (
165
- <Input
166
- textAlign="center"
167
- keyboardType="number-pad"
168
- inputMode="numeric"
169
- selectionColor={Colors.pink_03}
170
- style={[
171
- getStyle(size)?.input,
172
- styles.input,
173
- disabled && styles.disabledInput,
174
- {
175
- fontSize: size === 'small' ? 10 : 12,
176
- color: Colors.black_17,
177
- },
178
- ]}
179
- value={value.toString()}
180
- onChangeText={onChangeText}
181
- defaultValue={defaultValue.toString()}
182
- />
183
- ) : (
184
- <View
185
- style={[
186
- getStyle(size)?.input,
187
- styles.input,
188
- disabled && styles.disabledInput,
189
- ]}>
190
- <Text style={getStyle(size)?.text}>{value.toString()}</Text>
250
+ return (
251
+ <View style={[styles.container, style]}>
252
+ <IconButton
253
+ style={iconStyle}
254
+ tintColor={tintColor}
255
+ size={size}
256
+ disabled={value === min || disabled}
257
+ onPress={this.onPress(false, step)}
258
+ icon={minus}
259
+ />
260
+ <View
261
+ style={[styles.numberBox, getStyle(size).size, valueStyle]}>
262
+ {isInput ? (
263
+ <TextInput
264
+ style={[
265
+ {
266
+ textAlignVertical: 'center',
267
+ padding: 0,
268
+ },
269
+ getSize(size).size,
270
+ ]}
271
+ underlineColorAndroid="transparent"
272
+ value={value.toString()}
273
+ textAlign="center"
274
+ maxLength={3}
275
+ keyboardType="number-pad"
276
+ editable={!disabled}
277
+ onChangeText={(text) => {
278
+ if (text[0] !== '0') {
279
+ this.setValue(text);
280
+ }
281
+ }}
282
+ onEndEditing={this.checkData(
283
+ value,
284
+ 'increase',
285
+ min,
286
+ max,
287
+ )}
288
+ />
289
+ ) : (
290
+ <TextComp weight="bold" style={styles.text}>
291
+ {value.toString()}
292
+ </TextComp>
293
+ )}
294
+ </View>
295
+ <IconButton
296
+ tintColor={tintColor}
297
+ style={iconStyle}
298
+ size={size}
299
+ disabled={value >= max || !isIncreaseValue || disabled}
300
+ onPress={this.onPress(true, step)}
301
+ icon={plus}
302
+ />
191
303
  </View>
192
- )}
193
- </View>
194
- {renderButton('plus', size, plus)}
195
- </View>
196
- </View>
197
- );
198
- };
304
+ );
305
+ }
306
+ }
199
307
 
200
- const styles = StyleSheet.create({
201
- button: {
202
- backgroundColor: Colors.black_03,
203
- justifyContent: 'center',
204
- alignItems: 'center',
205
- },
206
- icon: {},
207
- container: {
208
- flexDirection: 'row',
209
- },
210
- input: {
211
- borderWidth: 1,
212
- borderColor: Colors.black_04,
213
- marginHorizontal: Spacing.M,
214
- justifyContent: 'center',
215
- alignItems: 'center',
216
- paddingHorizontal: Spacing.XS,
217
- paddingVertical: Spacing.ZERO,
218
- },
219
- inputContainer: {
220
- alignItems: 'center',
221
- justifyContent: 'center',
222
- },
223
- disabledButton: {
224
- tintColor: Colors.black_08,
225
- },
226
- disabledInput: {
227
- opacity: 0.4,
228
- },
229
- });
308
+ const IconButton = ({ disabled, onPress, icon, size, tintColor, style }) => (
309
+ <TouchableOpacity
310
+ style={[getStyle(size).size, styles.button, style]} // disabled && styles.disabledBox
311
+ disabled={disabled}
312
+ onPress={onPress}>
313
+ <Image
314
+ source={icon}
315
+ style={[
316
+ getStyle(size).icon,
317
+ { tintColor },
318
+ disabled && styles.disabledIcon,
319
+ ]}
320
+ />
321
+ </TouchableOpacity>
322
+ );
230
323
 
231
324
  Quantity.propTypes = {
232
- size: PropTypes.oneOf(['large', 'medium']),
233
- style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
234
- min: PropTypes.number,
235
- max: PropTypes.number,
236
- defaultValue: PropTypes.number,
237
- onChange: PropTypes.func,
238
- disabled: PropTypes.bool,
239
- isInput: PropTypes.bool,
240
- step: PropTypes.number,
241
- onIncreasePress: PropTypes.func,
242
- onDecreasePress: PropTypes.func,
243
- tintColor: PropTypes.string,
325
+ size: PropTypes.oneOf(['large', 'medium', 'small']),
326
+ style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
327
+ valueStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
328
+ min: PropTypes.number,
329
+ max: PropTypes.number,
330
+ value: PropTypes.number,
331
+ defaultValue: PropTypes.number,
332
+ onChange: PropTypes.func,
333
+ isChangeValue: PropTypes.bool,
334
+ isIncreaseValue: PropTypes.bool,
335
+ isDecreaseValue: PropTypes.bool,
336
+ isSingle: PropTypes.bool,
337
+ disabled: PropTypes.bool,
338
+ tintColor: PropTypes.string,
339
+ iconStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
340
+ isInput: PropTypes.bool,
341
+ step: PropTypes.number,
244
342
  };
245
343
 
246
344
  Quantity.defaultProps = {
247
- min: 0,
248
- max: 5,
249
- size: 'medium',
250
- isInput: false,
251
- disabled: false,
252
- step: 1,
253
- tintColor: Colors.pink_03,
345
+ min: 1,
346
+ max: 100,
347
+ isChangeValue: true,
348
+ isIncreaseValue: true,
349
+ isDecreaseValue: true,
350
+ isSingle: false,
351
+ size: 'medium',
352
+ tintColor: Colors.pink_05_b,
353
+ isInput: false,
354
+ disabled: false,
355
+ step: 1,
254
356
  };
255
-
256
- export default Quantity;
package/Stepper.web.js CHANGED
@@ -1,258 +1,319 @@
1
- import React, {Component, useState} from 'react';
1
+ import React, {Component} from 'react';
2
2
  import {
3
3
  View,
4
4
  StyleSheet,
5
5
  TouchableOpacity,
6
6
  Image,
7
- TextInput as Input,
7
+ TextInput,
8
8
  } from 'react-native';
9
9
  import PropTypes from 'prop-types';
10
10
  import Text from '../../core/components/typography';
11
- import Colors from '../../core-v2/colors';
12
- import Radius from '../../core-v2/radius';
13
- import Spacing from '../../core-v2/spacing';
11
+ import Colors from '../../core/colors';
14
12
 
15
13
  const minus =
16
14
  'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_minus_circle.png';
17
15
  const plus =
18
16
  'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_plus_circle.png';
19
17
 
20
- const Quantity = props => {
21
- const {
22
- disabled,
23
- min = 0,
24
- max = 5,
25
- defaultValue = 0,
26
- size,
27
- onChange,
28
- onIncreasePress,
29
- onDecreasePress,
30
- isInput = false,
31
- step = 1,
32
- style,
33
- tintColor,
34
- } = props;
35
-
36
- const [value, setValue] = useState(defaultValue);
18
+ const styles = StyleSheet.create({
19
+ container: {
20
+ flexDirection: 'row',
21
+ },
22
+ icon: {
23
+ height: 24,
24
+ width: 24,
25
+ resizeMode: 'contain',
26
+ tintColor: Colors.pink_03,
27
+ },
28
+ text: {
29
+ color: Colors.black_17,
30
+ },
31
+ numberBox: {
32
+ justifyContent: 'center',
33
+ alignItems: 'center',
34
+ marginHorizontal: 6,
35
+ backgroundColor: Colors.white,
36
+ },
37
+ button: {
38
+ justifyContent: 'center',
39
+ alignItems: 'center',
40
+ backgroundColor: Colors.white,
41
+ borderColor: 'transparent',
42
+ },
43
+ borderBox: {
44
+ borderColor: Colors.black_04,
45
+ borderWidth: 1,
46
+ borderRadius: 6,
47
+ },
48
+ disabledIcon: {
49
+ tintColor: Colors.black_09,
50
+ },
51
+ disabledBox: {
52
+ borderColor: Colors.black_03,
53
+ backgroundColor: Colors.black_03,
54
+ },
55
+ });
37
56
 
38
- const getStyle = size => {
39
- switch (size) {
40
- case 'medium':
41
- return {
42
- button: {
43
- width: 28,
44
- height: 28,
45
- borderRadius: Radius.M + Radius.XXS,
46
- },
47
- icon: {
48
- width: 24,
49
- height: 24,
50
- },
51
- input: {
52
- minWidth: 28,
53
- minHeight: 24,
54
- borderRadius: Radius.S,
55
- },
56
- text: {
57
- fontSize: 12,
58
- lineHeight: 16,
59
- },
60
- };
61
- case 'large':
62
- return {
63
- button: {
64
- width: 36,
65
- height: 36,
66
- borderRadius: Radius.L + Radius.XXS,
67
- },
68
- icon: {
69
- width: 24,
70
- height: 24,
71
- },
72
- input: {
73
- minWidth: 32,
74
- minHeight: 26,
75
- borderRadius: Radius.S,
76
- },
77
- text: {
78
- fontSize: 12,
79
- lineHeight: 16,
80
- },
81
- };
82
- }
57
+ const getStyle = type => {
58
+ const objStyle = {
59
+ large: {
60
+ size: {
61
+ ...styles.borderBox,
62
+ width: 32, // height: 26
63
+ },
64
+ icon: {
65
+ width: 24,
66
+ height: 24,
67
+ resizeMode: 'contain',
68
+ },
69
+ text: 'Title',
70
+ },
71
+ medium: {
72
+ size: {
73
+ ...styles.borderBox,
74
+ width: 28, // height: 24
75
+ },
76
+ icon: {
77
+ width: 24,
78
+ height: 24,
79
+ resizeMode: 'contain',
80
+ },
81
+ text: 'SubTitle',
82
+ },
83
+ small: {
84
+ size: {
85
+ ...styles.borderBox,
86
+ width: 20, // height: 16
87
+ },
88
+ icon: {
89
+ width: 16,
90
+ height: 16,
91
+ resizeMode: 'contain',
92
+ },
93
+ text: 'Caption',
94
+ },
83
95
  };
96
+ return objStyle[type] || objStyle.medium;
97
+ };
84
98
 
85
- const validateValue = value => {
86
- if (value < min) value = min;
87
- if (value > max) value = max;
88
- return value;
99
+ const getSize = type => {
100
+ const objStyle = {
101
+ large: {
102
+ size: {
103
+ width: 32,
104
+ height: 24, // height: 26
105
+ },
106
+ },
107
+ medium: {
108
+ size: {
109
+ width: 28,
110
+ height: 24, // height: 24
111
+ },
112
+ },
113
+ small: {
114
+ size: {
115
+ width: 20,
116
+ height: 16, // height: 16
117
+ },
118
+ },
89
119
  };
120
+ return objStyle[type] || objStyle.medium;
121
+ };
90
122
 
91
- const onDecrease = () => {
92
- let newValue = value;
93
- if (value > min) {
94
- newValue = value - step;
95
- }
96
- if (newValue < min) newValue = min;
123
+ export default class Quantity extends Component {
124
+ constructor(props) {
125
+ super(props);
126
+ this.state = {
127
+ value: props.defaultValue || props.min,
128
+ ownUpdate: false,
129
+ };
130
+ }
97
131
 
98
- if (onDecreasePress && typeof onDecreasePress === 'function') {
99
- onDecreasePress(newValue);
132
+ static getDerivedStateFromProps(nextProps, prevState) {
133
+ const {value = undefined} = this?.props || {};
134
+ if (prevState.ownUpdate) {
135
+ return {
136
+ ownUpdate: false,
137
+ };
100
138
  }
101
-
102
- setValue(newValue);
103
- };
104
-
105
- const onIncrease = () => {
106
- let newValue = value;
107
- if (value < max) {
108
- newValue = value + step;
139
+ if (nextProps.value !== value && nextProps.value !== prevState.value) {
140
+ return {value: nextProps.value};
109
141
  }
110
- if (newValue > max) newValue = max;
142
+ return null;
143
+ }
111
144
 
112
- if (onIncreasePress && typeof onIncreasePress === 'function') {
113
- onIncreasePress(newValue);
114
- }
145
+ onChangeValue = (value, type) => {
146
+ const {onChange} = this.props;
147
+ return onChange && typeof onChange === 'function' && onChange(value, type);
148
+ };
115
149
 
116
- setValue(newValue);
150
+ getValue = (key, step) => {
151
+ const {isIncreaseValue, isDecreaseValue} = this.props;
152
+ const value = {
153
+ increase: isIncreaseValue ? step : 0,
154
+ decrease: isDecreaseValue ? step : 0,
155
+ };
156
+ return value[key];
117
157
  };
118
158
 
119
- const onPressButton = type => {
120
- if (type === 'plus') {
121
- onIncrease();
159
+ setValue = (newValue = 0, type) => {
160
+ const {isInput, isIncreaseValue, max, min} = this.props;
161
+ const onValue = (newValue, type) => {
162
+ this.setState(
163
+ {
164
+ value: newValue,
165
+ ownUpdate: true,
166
+ },
167
+ () => {
168
+ this.onChangeValue(newValue, type);
169
+ },
170
+ );
171
+ };
172
+
173
+ if (isInput) {
174
+ if (newValue <= max && isIncreaseValue && newValue >= min) {
175
+ onValue(newValue, type);
176
+ }
122
177
  } else {
123
- onDecrease();
178
+ onValue(newValue, type);
124
179
  }
125
180
  };
126
- const renderButton = (type, size, icon) => {
127
- let disabledStatus = props.disabled;
128
- if (type === 'plus' && value === max) disabledStatus = true;
129
- if (type === 'minus' && value === min) disabledStatus = true;
130
181
 
131
- if (onPressButton) {
182
+ onPress =
183
+ (isIncrease = true, step) =>
184
+ () => {
185
+ const {isChangeValue, onConditionCheck} = this.props;
186
+ const {value} = this.state;
187
+ const type = isIncrease ? 'increase' : 'decrease';
188
+ if (isChangeValue) {
189
+ const newValue = isIncrease
190
+ ? value + this.getValue('increase', step)
191
+ : value - this.getValue('decrease', step);
192
+ if (typeof onConditionCheck === 'function') {
193
+ const passCondition = onConditionCheck(newValue, type);
194
+ if (passCondition) {
195
+ this.setValue(newValue, type);
196
+ }
197
+ } else {
198
+ this.setValue(newValue, type);
199
+ }
200
+ } else {
201
+ this.onChangeValue(value, type);
202
+ }
203
+ };
204
+
205
+ render() {
206
+ const {value} = this.state;
207
+ const {
208
+ style,
209
+ max,
210
+ valueStyle,
211
+ size,
212
+ tintColor,
213
+ isIncreaseValue,
214
+ isSingle,
215
+ iconStyle,
216
+ isInput,
217
+ } = this.props;
218
+ const {min} = this.props || 1;
219
+ if (isSingle && value === 0) {
132
220
  return (
133
- <TouchableOpacity
134
- disabled={disabledStatus}
135
- onPress={() => onPressButton(type)}
136
- style={[getStyle(size)?.button, styles.button]}>
137
- <Image
138
- source={icon}
139
- style={[
140
- getStyle(size)?.icon,
141
- disabledStatus && styles.disabledButton,
142
- {tintColor},
143
- ]}
221
+ <View style={[styles.container, style]}>
222
+ <IconButton
223
+ tintColor={tintColor}
224
+ size={size}
225
+ disabled={value >= max || !isIncreaseValue}
226
+ onPress={this.onPress(true)}
227
+ icon={plus}
144
228
  />
145
- </TouchableOpacity>
229
+ </View>
146
230
  );
147
231
  }
148
- };
149
-
150
- const onChangeText = value => {
151
- let newValue = validateValue(parseInt(value)) || '0';
152
- if (value.length > 1 && value[0] === 0) {
153
- newValue = value.substring(1);
154
- }
155
-
156
- if (onChange && typeof onChange === 'function') onChange(newValue);
157
-
158
- setValue(newValue);
159
- };
160
-
161
- return (
162
- <View style={style}>
163
- <View style={styles.container}>
164
- {renderButton('minus', size, minus)}
165
- <View style={styles.inputContainer}>
232
+ const TextComp = Text[getStyle(size).text];
233
+ return (
234
+ <View style={[styles.container, style]}>
235
+ <IconButton
236
+ style={iconStyle}
237
+ tintColor={tintColor}
238
+ size={size}
239
+ disabled={value === min}
240
+ onPress={this.onPress(false)}
241
+ icon={minus}
242
+ />
243
+ <View style={[styles.numberBox, getStyle(size).size, valueStyle]}>
166
244
  {isInput ? (
167
- <Input
245
+ <TextInput
246
+ style={[{textAlignVertical: 'center'}, getSize(size).size]}
247
+ underlineColorAndroid="transparent"
248
+ value={value.toString()}
168
249
  textAlign="center"
250
+ maxLength={3}
169
251
  keyboardType="number-pad"
170
- inputMode="numeric"
171
- selectionColor={Colors.pink_03}
172
- style={[
173
- getStyle(size)?.input,
174
- styles.input,
175
- disabled && styles.disabledInput,
176
- {
177
- fontSize: size === 'small' ? 10 : 12,
178
- color: Colors.black_17,
179
- },
180
- ]}
181
- value={value.toString()}
182
- onChangeText={onChangeText}
183
- defaultValue={defaultValue.toString()}
252
+ onChangeText={text => this.setValue(text)}
184
253
  />
185
254
  ) : (
186
- <View
187
- style={[
188
- getStyle(size)?.input,
189
- styles.input,
190
- disabled && styles.disabledInput,
191
- ]}>
192
- <Text style={getStyle(size)?.text}>{value.toString()}</Text>
193
- </View>
255
+ <TextComp weight="bold" style={styles.text}>
256
+ {value}
257
+ </TextComp>
194
258
  )}
195
259
  </View>
196
- {renderButton('plus', size, plus)}
260
+ <IconButton
261
+ tintColor={tintColor}
262
+ style={iconStyle}
263
+ size={size}
264
+ disabled={value >= max || !isIncreaseValue}
265
+ onPress={this.onPress(true)}
266
+ icon={plus}
267
+ />
197
268
  </View>
198
- </View>
199
- );
200
- };
269
+ );
270
+ }
271
+ }
201
272
 
202
- const styles = StyleSheet.create({
203
- button: {
204
- backgroundColor: Colors.black_03,
205
- justifyContent: 'center',
206
- alignItems: 'center',
207
- },
208
- icon: {},
209
- container: {
210
- flexDirection: 'row',
211
- },
212
- input: {
213
- borderWidth: 1,
214
- borderColor: Colors.black_04,
215
- marginHorizontal: Spacing.M,
216
- justifyContent: 'center',
217
- alignItems: 'center',
218
- paddingHorizontal: Spacing.XS,
219
- paddingVertical: Spacing.ZERO,
220
- },
221
- inputContainer: {
222
- alignItems: 'center',
223
- justifyContent: 'center',
224
- },
225
- disabledButton: {
226
- tintColor: Colors.black_08,
227
- },
228
- disabledInput: {
229
- opacity: 0.4,
230
- },
231
- });
273
+ const IconButton = ({disabled, onPress, icon, size, tintColor, style}) => (
274
+ <TouchableOpacity
275
+ style={[getStyle(size).size, styles.button, style]} // disabled && styles.disabledBox
276
+ disabled={disabled}
277
+ onPress={onPress}>
278
+ <Image
279
+ source={icon}
280
+ style={[
281
+ getStyle(size).icon,
282
+ {tintColor},
283
+ disabled && styles.disabledIcon,
284
+ ]}
285
+ />
286
+ </TouchableOpacity>
287
+ );
232
288
 
233
289
  Quantity.propTypes = {
234
- size: PropTypes.oneOf(['large', 'medium']),
290
+ size: PropTypes.oneOf(['large', 'medium', 'small']),
235
291
  style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
292
+ valueStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
236
293
  min: PropTypes.number,
237
294
  max: PropTypes.number,
295
+ value: PropTypes.number,
238
296
  defaultValue: PropTypes.number,
239
297
  onChange: PropTypes.func,
240
- disabled: PropTypes.bool,
298
+ isChangeValue: PropTypes.bool,
299
+ isIncreaseValue: PropTypes.bool,
300
+ isDecreaseValue: PropTypes.bool,
301
+ isSingle: PropTypes.bool,
302
+ tintColor: PropTypes.string,
303
+ iconStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
241
304
  isInput: PropTypes.bool,
242
305
  step: PropTypes.number,
243
- onIncreasePress: PropTypes.func,
244
- onDecreasePress: PropTypes.func,
245
- tintColor: PropTypes.string,
246
306
  };
247
307
 
248
308
  Quantity.defaultProps = {
249
- min: 0,
250
- max: 5,
309
+ min: 1,
310
+ max: 100,
311
+ isChangeValue: true,
312
+ isIncreaseValue: true,
313
+ isDecreaseValue: true,
314
+ isSingle: false,
251
315
  size: 'medium',
316
+ tintColor: Colors.pink_05_b,
252
317
  isInput: false,
253
- disabled: false,
254
318
  step: 1,
255
- tintColor: Colors.pink_03,
256
319
  };
257
-
258
- export default Quantity;
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@momo-kits/stepper",
3
- "version": "0.0.65-alpha.20",
3
+ "version": "0.0.65-alpha.23",
4
4
  "private": false,
5
5
  "main": "index.js",
6
6
  "dependencies": {},
7
7
  "peerDependencies": {
8
- "@momo-kits/core-v2": ">=0.0.5-beta",
8
+ "@momo-kits/core": ">=0.0.5-beta",
9
9
  "prop-types": "^15.7.2",
10
10
  "react": "16.9.0",
11
11
  "react-native": ">=0.55"