@momo-kits/stepper 0.73.3-beta.4 → 0.75.1-beta.1

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/NumberView.tsx ADDED
@@ -0,0 +1,47 @@
1
+ import React, {FC, useContext} from 'react';
2
+ import {TextInput, View} from 'react-native';
3
+ import {StepperValueProps} from './types';
4
+ import {ApplicationContext} from '@momo-kits/foundation';
5
+ import styles from './styles';
6
+
7
+ const NumberView: FC<StepperValueProps> = ({
8
+ value = 0,
9
+ size = 'large',
10
+ editable = false,
11
+ onValueChange,
12
+ disabled,
13
+ }) => {
14
+ const {theme} = useContext(ApplicationContext);
15
+ const sizeStyle =
16
+ size === 'large' ? styles.numberView : styles.numberViewSmall;
17
+
18
+ const formattedNumber = (value: number) => {
19
+ if (isNaN(value)) {
20
+ return '0';
21
+ } else {
22
+ return value.toString();
23
+ }
24
+ };
25
+
26
+ const textColor = disabled
27
+ ? theme.colors.text.disable
28
+ : theme.colors.text.default;
29
+
30
+ const borderColor = disabled
31
+ ? theme.colors.border.disable
32
+ : theme.colors.border.default;
33
+ return (
34
+ <View style={[sizeStyle, {borderColor}]}>
35
+ <TextInput
36
+ editable={editable}
37
+ style={[styles.input, {color: textColor}]}
38
+ value={formattedNumber(value)}
39
+ onChangeText={onValueChange}
40
+ keyboardType={'number-pad'}
41
+ selectionColor={theme.colors.primary}
42
+ />
43
+ </View>
44
+ );
45
+ };
46
+
47
+ export default NumberView;
@@ -0,0 +1,30 @@
1
+ import React, {FC, useContext} from 'react';
2
+ import {TouchableOpacity} from 'react-native';
3
+ import styles from './styles';
4
+ import {StepperButtonProps} from './types';
5
+ import {ApplicationContext, Icon} from '@momo-kits/foundation';
6
+
7
+ const StepperButton: FC<StepperButtonProps> = ({
8
+ disabled = false,
9
+ sign = '+',
10
+ size = 'large',
11
+ onPress,
12
+ }) => {
13
+ const ICON_SIZE = 12;
14
+ const {theme} = useContext(ApplicationContext);
15
+
16
+ const sizeStyle = size === 'large' ? styles.button : styles.smallButton;
17
+ const buttonIcon =
18
+ sign === '-' ? '24_navigation_minus_circle' : '24_navigation_plus_circle';
19
+ const buttonColor = disabled
20
+ ? theme.colors.text.disable
21
+ : theme.colors.primary;
22
+
23
+ return (
24
+ <TouchableOpacity disabled={disabled} onPress={onPress} style={[sizeStyle]}>
25
+ <Icon size={22} color={buttonColor} source={buttonIcon} />
26
+ </TouchableOpacity>
27
+ );
28
+ };
29
+
30
+ export default StepperButton;
package/index.tsx ADDED
@@ -0,0 +1,95 @@
1
+ import React, {FC, useState} from 'react';
2
+ import {View} from 'react-native';
3
+ import StepperButton from './StepperButton';
4
+ import {DisabledStatus, StepperProps} from './types';
5
+ import styles from './styles';
6
+ import NumberView from './NumberView';
7
+
8
+ const Stepper: FC<StepperProps> = ({
9
+ size = 'large',
10
+ defaultValue = 0,
11
+ min = 0,
12
+ max = 100,
13
+ disabled = false,
14
+ step = 1,
15
+ editable = false,
16
+ onValueChange,
17
+ }) => {
18
+ const [value, setValue] = useState(defaultValue);
19
+
20
+ const onPlus = () => {
21
+ let newValue = value + step;
22
+ _onValueChange(newValue.toString());
23
+ };
24
+ const onMinus = () => {
25
+ let newValue = value - step;
26
+ _onValueChange(newValue.toString());
27
+ };
28
+ const _onValueChange = (num: string) => {
29
+ let newValue = parseInt(num);
30
+
31
+ if (isNaN(newValue)) {
32
+ newValue = 0;
33
+ }
34
+
35
+ if (newValue > max) {
36
+ newValue = max;
37
+ }
38
+
39
+ if (newValue < min) {
40
+ newValue = min;
41
+ }
42
+
43
+ setValue(newValue);
44
+ onValueChange?.(newValue);
45
+ };
46
+ const getViewDisabledStatus = () => {
47
+ let disabledStatus: DisabledStatus;
48
+
49
+ if (Array.isArray(disabled)) {
50
+ disabledStatus = {
51
+ plus: disabled[1],
52
+ minus: disabled[0],
53
+ number: disabled[0] && disabled[1],
54
+ };
55
+ } else {
56
+ disabledStatus = {
57
+ plus: disabled,
58
+ minus: disabled,
59
+ number: disabled,
60
+ };
61
+ }
62
+
63
+ if (value === min) {
64
+ disabledStatus.minus = true;
65
+ }
66
+ if (value === max) {
67
+ disabledStatus.plus = true;
68
+ }
69
+ return disabledStatus;
70
+ };
71
+
72
+ const viewStatus = getViewDisabledStatus();
73
+
74
+ return (
75
+ <View style={styles.stepper}>
76
+ <StepperButton
77
+ onPress={onMinus}
78
+ sign={'-'}
79
+ size={size}
80
+ disabled={viewStatus.minus}
81
+ />
82
+ <NumberView
83
+ onValueChange={_onValueChange}
84
+ size={size}
85
+ value={value}
86
+ disabled={viewStatus.number}
87
+ editable={editable}
88
+ />
89
+ <StepperButton onPress={onPlus} size={size} disabled={viewStatus.plus} />
90
+ </View>
91
+ );
92
+ };
93
+
94
+ export default Stepper;
95
+ export type {StepperProps};
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@momo-kits/stepper",
3
- "version": "0.73.3-beta.4",
3
+ "version": "0.75.1-beta.1",
4
4
  "private": false,
5
- "main": "index.js",
5
+ "main": "index.tsx",
6
6
  "dependencies": {},
7
7
  "peerDependencies": {
8
8
  "@momo-kits/core-v2": ">=0.0.5-beta",
package/styles.ts ADDED
@@ -0,0 +1,54 @@
1
+ import {StyleSheet} from 'react-native';
2
+ import {Colors, Radius, Spacing} from '@momo-kits/foundation';
3
+
4
+ export default StyleSheet.create({
5
+ button: {
6
+ width: 36,
7
+ height: 36,
8
+ borderRadius: Radius.XL,
9
+ backgroundColor: Colors.black_03,
10
+ justifyContent: 'center',
11
+ alignItems: 'center',
12
+ },
13
+ smallButton: {
14
+ width: 28,
15
+ height: 28,
16
+ borderRadius: Radius.L,
17
+ backgroundColor: Colors.black_03,
18
+ justifyContent: 'center',
19
+ alignItems: 'center',
20
+ },
21
+ iconWrapper: {
22
+ width: 22,
23
+ height: 22,
24
+ borderWidth: 2,
25
+ borderRadius: Radius.M,
26
+ justifyContent: 'center',
27
+ alignItems: 'center',
28
+ },
29
+ stepper: {
30
+ flexDirection: 'row',
31
+ alignItems: 'center',
32
+ },
33
+ numberView: {
34
+ width: 32,
35
+ height: 28,
36
+ borderWidth: 1,
37
+ borderRadius: Radius.S,
38
+ justifyContent: 'center',
39
+ alignItems: 'center',
40
+ marginHorizontal: Spacing.S,
41
+ },
42
+ numberViewSmall: {
43
+ width: 28,
44
+ height: 24,
45
+ borderWidth: 1,
46
+ borderRadius: Radius.S,
47
+ justifyContent: 'center',
48
+ alignItems: 'center',
49
+ marginHorizontal: Spacing.S,
50
+ },
51
+ input: {
52
+ fontSize: 12,
53
+ },
54
+ });
package/types.ts ADDED
@@ -0,0 +1,31 @@
1
+ export type StepperButtonProps = {
2
+ disabled?: boolean;
3
+ sign?: '+' | '-';
4
+ size?: 'large' | 'small';
5
+ onPress: () => void;
6
+ };
7
+
8
+ export type StepperValueProps = {
9
+ value: number;
10
+ disabled?: boolean;
11
+ size?: 'large' | 'small';
12
+ editable?: boolean;
13
+ onValueChange?: (value: string) => void;
14
+ };
15
+
16
+ export type StepperProps = {
17
+ defaultValue: number;
18
+ min?: number;
19
+ max?: number;
20
+ disabled?: boolean | boolean[];
21
+ step?: number;
22
+ size?: 'large' | 'small';
23
+ editable?: boolean;
24
+ onValueChange?: (value: number) => void;
25
+ };
26
+
27
+ export type DisabledStatus = {
28
+ plus: boolean;
29
+ minus: boolean;
30
+ number: boolean;
31
+ };
package/Stepper.js DELETED
@@ -1,256 +0,0 @@
1
- import {
2
- Colors,
3
- Image,
4
- Radius,
5
- Spacing,
6
- Text,
7
- TouchableOpacity,
8
- } from '@momo-kits/core-v2';
9
- import PropTypes from 'prop-types';
10
- import React, {useState} from 'react';
11
- import {StyleSheet, TextInput as Input, View} from 'react-native';
12
-
13
- const minus =
14
- 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_minus_circle.png';
15
- const plus =
16
- 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_plus_circle.png';
17
-
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;
33
-
34
- const [value, setValue] = useState(defaultValue);
35
-
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
- },
79
- };
80
- }
81
- };
82
-
83
- const validateValue = value => {
84
- if (value < min) value = min;
85
- if (value > max) value = max;
86
- return value;
87
- };
88
-
89
- const onDecrease = () => {
90
- let newValue = value;
91
- if (value > min) {
92
- newValue = value - step;
93
- }
94
- if (newValue < min) newValue = min;
95
-
96
- if (onDecreasePress && typeof onDecreasePress === 'function') {
97
- onDecreasePress(newValue);
98
- }
99
-
100
- setValue(newValue);
101
- };
102
-
103
- const onIncrease = () => {
104
- let newValue = value;
105
- if (value < max) {
106
- newValue = value + step;
107
- }
108
- if (newValue > max) newValue = max;
109
-
110
- if (onIncreasePress && typeof onIncreasePress === 'function') {
111
- onIncreasePress(newValue);
112
- }
113
-
114
- setValue(newValue);
115
- };
116
-
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;
128
-
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
- };
147
-
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
- }
153
-
154
- if (onChange && typeof onChange === 'function') onChange(newValue);
155
-
156
- setValue(newValue);
157
- };
158
-
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>
191
- </View>
192
- )}
193
- </View>
194
- {renderButton('plus', size, plus)}
195
- </View>
196
- </View>
197
- );
198
- };
199
-
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
- });
230
-
231
- 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,
244
- };
245
-
246
- 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,
254
- };
255
-
256
- export default Quantity;
package/Stepper.web.js DELETED
@@ -1,258 +0,0 @@
1
- import React, {Component, useState} from 'react';
2
- import {
3
- View,
4
- StyleSheet,
5
- TouchableOpacity,
6
- Image,
7
- TextInput as Input,
8
- } from 'react-native';
9
- import PropTypes from 'prop-types';
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';
14
-
15
- const minus =
16
- 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_minus_circle.png';
17
- const plus =
18
- 'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_plus_circle.png';
19
-
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);
37
-
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
- }
83
- };
84
-
85
- const validateValue = value => {
86
- if (value < min) value = min;
87
- if (value > max) value = max;
88
- return value;
89
- };
90
-
91
- const onDecrease = () => {
92
- let newValue = value;
93
- if (value > min) {
94
- newValue = value - step;
95
- }
96
- if (newValue < min) newValue = min;
97
-
98
- if (onDecreasePress && typeof onDecreasePress === 'function') {
99
- onDecreasePress(newValue);
100
- }
101
-
102
- setValue(newValue);
103
- };
104
-
105
- const onIncrease = () => {
106
- let newValue = value;
107
- if (value < max) {
108
- newValue = value + step;
109
- }
110
- if (newValue > max) newValue = max;
111
-
112
- if (onIncreasePress && typeof onIncreasePress === 'function') {
113
- onIncreasePress(newValue);
114
- }
115
-
116
- setValue(newValue);
117
- };
118
-
119
- const onPressButton = type => {
120
- if (type === 'plus') {
121
- onIncrease();
122
- } else {
123
- onDecrease();
124
- }
125
- };
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
-
131
- if (onPressButton) {
132
- 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
- ]}
144
- />
145
- </TouchableOpacity>
146
- );
147
- }
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}>
166
- {isInput ? (
167
- <Input
168
- textAlign="center"
169
- 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()}
184
- />
185
- ) : (
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>
194
- )}
195
- </View>
196
- {renderButton('plus', size, plus)}
197
- </View>
198
- </View>
199
- );
200
- };
201
-
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
- });
232
-
233
- Quantity.propTypes = {
234
- size: PropTypes.oneOf(['large', 'medium']),
235
- style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
236
- min: PropTypes.number,
237
- max: PropTypes.number,
238
- defaultValue: PropTypes.number,
239
- onChange: PropTypes.func,
240
- disabled: PropTypes.bool,
241
- isInput: PropTypes.bool,
242
- step: PropTypes.number,
243
- onIncreasePress: PropTypes.func,
244
- onDecreasePress: PropTypes.func,
245
- tintColor: PropTypes.string,
246
- };
247
-
248
- Quantity.defaultProps = {
249
- min: 0,
250
- max: 5,
251
- size: 'medium',
252
- isInput: false,
253
- disabled: false,
254
- step: 1,
255
- tintColor: Colors.pink_03,
256
- };
257
-
258
- export default Quantity;
package/index.js DELETED
@@ -1,3 +0,0 @@
1
- import Stepper from './Stepper';
2
-
3
- export default Stepper;