@cdek-it/react-native-ui-kit 1.0.0-beta.7 → 1.0.0-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.
|
@@ -1,14 +1,25 @@
|
|
|
1
|
-
import { memo, useCallback, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
1
|
+
import { memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
2
2
|
import { Pressable, View, TextInput, } from 'react-native';
|
|
3
3
|
import { StyleSheet } from 'react-native-unistyles';
|
|
4
4
|
import { InputOtpItem } from './InputOtpItem';
|
|
5
|
-
export const InputOtp = memo(({ length, onChange, disabled = false, error = false, testOnly_pressed, inputRef: propsInputRef, testID, value = '', onFocus, onBlur, ...rest }) => {
|
|
5
|
+
export const InputOtp = memo(({ length, onChange, disabled = false, error = false, testOnly_pressed, inputRef: propsInputRef, testID, value = '', onFocus, onBlur, editable, ...rest }) => {
|
|
6
6
|
const [isFocused, setIsFocused] = useState(false);
|
|
7
7
|
const inputRef = useRef(null);
|
|
8
|
+
const isInputEditable = !disabled && editable !== false;
|
|
8
9
|
useImperativeHandle(propsInputRef, () => inputRef.current);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (!isInputEditable) {
|
|
12
|
+
setIsFocused(false);
|
|
13
|
+
if (inputRef.current?.isFocused()) {
|
|
14
|
+
inputRef.current.blur();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}, [isInputEditable]);
|
|
9
18
|
const handlePress = useCallback(() => {
|
|
10
|
-
|
|
11
|
-
|
|
19
|
+
if (isInputEditable) {
|
|
20
|
+
inputRef.current?.focus();
|
|
21
|
+
}
|
|
22
|
+
}, [isInputEditable]);
|
|
12
23
|
const handleChange = useCallback((text) => {
|
|
13
24
|
const sanitizedText = text.replace(/[^0-9]/g, '');
|
|
14
25
|
onChange(sanitizedText);
|
|
@@ -28,7 +39,7 @@ export const InputOtp = memo(({ length, onChange, disabled = false, error = fals
|
|
|
28
39
|
<View style={styles.content}>
|
|
29
40
|
{renderArray.map((key, index) => (<InputOtpItem disabled={disabled} error={error} focused={isFocused ? index === activeIndex : false} key={key} pressed={pressed} testID={`${testID}Item`} value={value[index]}/>))}
|
|
30
41
|
</View>
|
|
31
|
-
<TextInput keyboardType='number-pad' maxLength={length} ref={inputRef} style={styles.input} testID={`${testID}HiddenInput`} value={value} onBlur={handleBlur} onChangeText={handleChange} onFocus={handleFocus} {...rest}/>
|
|
42
|
+
<TextInput editable={isInputEditable} keyboardType='number-pad' maxLength={length} ref={inputRef} style={styles.input} testID={`${testID}HiddenInput`} value={value} onBlur={handleBlur} onChangeText={handleChange} onFocus={handleFocus} {...rest}/>
|
|
32
43
|
</>)}
|
|
33
44
|
</Pressable>);
|
|
34
45
|
});
|
|
@@ -1,34 +1,32 @@
|
|
|
1
|
-
import { memo
|
|
1
|
+
import { memo } from 'react';
|
|
2
2
|
import { View, Text } from 'react-native';
|
|
3
|
-
import Animated
|
|
3
|
+
import Animated from 'react-native-reanimated';
|
|
4
4
|
import { StyleSheet } from 'react-native-unistyles';
|
|
5
5
|
const CURSOR_ANIMATION_DURATION = 500;
|
|
6
|
+
const cursorAnimationStyle = {
|
|
7
|
+
animationName: { from: { opacity: 1 }, to: { opacity: 0.2 } },
|
|
8
|
+
animationDuration: CURSOR_ANIMATION_DURATION,
|
|
9
|
+
animationDirection: 'alternate',
|
|
10
|
+
animationIterationCount: 'infinite',
|
|
11
|
+
animationTimingFunction: 'ease',
|
|
12
|
+
};
|
|
6
13
|
export const InputOtpItem = memo(({ value, error, pressed, disabled, focused, testID }) => {
|
|
7
|
-
const opacity = useSharedValue(1);
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
if (focused) {
|
|
10
|
-
opacity.value = withRepeat(withTiming(0.2, {
|
|
11
|
-
duration: CURSOR_ANIMATION_DURATION,
|
|
12
|
-
easing: Easing.ease,
|
|
13
|
-
}), -1, true);
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
opacity.value = 1;
|
|
17
|
-
}
|
|
18
|
-
}, [focused, opacity]);
|
|
19
|
-
const cursorBlinking = useAnimatedStyle(() => ({ opacity: opacity.value }));
|
|
20
14
|
return (<View style={[
|
|
21
15
|
styles.container,
|
|
22
16
|
error && styles.error,
|
|
23
17
|
pressed && styles.pressed,
|
|
24
18
|
disabled && styles.disabled,
|
|
25
19
|
]}>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
{focused ? (<View style={styles.textRow} testID={`${testID}CursorRow`}>
|
|
21
|
+
<Text style={styles.text} testID={testID}>
|
|
22
|
+
{value}
|
|
23
|
+
</Text>
|
|
24
|
+
<Animated.Text style={[styles.text, styles.cursor, cursorAnimationStyle]} testID={`${testID}Cursor`}>
|
|
29
25
|
|
|
|
30
|
-
</Animated.Text>
|
|
31
|
-
|
|
26
|
+
</Animated.Text>
|
|
27
|
+
</View>) : (<Text style={styles.text} testID={testID}>
|
|
28
|
+
{value}
|
|
29
|
+
</Text>)}
|
|
32
30
|
</View>);
|
|
33
31
|
});
|
|
34
32
|
const styles = StyleSheet.create(({ theme, border, fonts, typography }) => ({
|
|
@@ -42,14 +40,16 @@ const styles = StyleSheet.create(({ theme, border, fonts, typography }) => ({
|
|
|
42
40
|
alignItems: 'center',
|
|
43
41
|
justifyContent: 'center',
|
|
44
42
|
},
|
|
43
|
+
textRow: { flexDirection: 'row', alignItems: 'center' },
|
|
45
44
|
text: {
|
|
46
45
|
fontSize: typography.Size['text-2xl'],
|
|
47
46
|
fontFamily: fonts.primary,
|
|
48
47
|
fontWeight: '400',
|
|
49
48
|
color: theme.Form.InputText.inputTextColor,
|
|
49
|
+
includeFontPadding: false,
|
|
50
50
|
},
|
|
51
51
|
pressed: { borderColor: theme.Form.InputText.inputHoverBorderColor },
|
|
52
52
|
error: { borderColor: theme.Form.InputText.inputErrorBorderColor },
|
|
53
53
|
disabled: { mixBlendMode: 'luminosity', opacity: 0.6 },
|
|
54
|
-
cursor: { color: theme.Form.InputText.inputTextColor },
|
|
54
|
+
cursor: { color: theme.Form.InputText.inputTextColor, marginBottom: 3 },
|
|
55
55
|
}));
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { memo, useCallback, useState } from 'react';
|
|
2
2
|
import { Pressable, View, } from 'react-native';
|
|
3
|
-
import Animated
|
|
3
|
+
import Animated from 'react-native-reanimated';
|
|
4
4
|
import { StyleSheet } from 'react-native-unistyles';
|
|
5
|
+
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
|
5
6
|
export const RadioButton = memo(({ onPress, checked = false, disabled = false, state = 'default', testID, ...rest }) => {
|
|
6
7
|
const [pressed, setPressed] = useState(false);
|
|
7
8
|
radioStyles.useVariants({
|
|
@@ -13,49 +14,43 @@ export const RadioButton = memo(({ onPress, checked = false, disabled = false, s
|
|
|
13
14
|
const onPressIn = useCallback(() => setPressed(true), []);
|
|
14
15
|
const onPressOut = useCallback(() => setPressed(false), []);
|
|
15
16
|
return (<View>
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
<View style={radioStyles.center}/>
|
|
19
|
-
</
|
|
17
|
+
<Animated.View pointerEvents='none' style={radioStyles.outline}/>
|
|
18
|
+
<AnimatedPressable disabled={disabled} style={radioStyles.container} testID={testID || 'RadioButton_Pressable'} onPress={onPress} onPressIn={onPressIn} onPressOut={onPressOut} {...rest}>
|
|
19
|
+
<Animated.View style={radioStyles.center}/>
|
|
20
|
+
</AnimatedPressable>
|
|
20
21
|
</View>);
|
|
21
22
|
});
|
|
22
|
-
const radioStyles = StyleSheet.create(({ theme }) => ({
|
|
23
|
+
const radioStyles = StyleSheet.create(({ theme, border }) => ({
|
|
23
24
|
container: {
|
|
24
25
|
width: theme.Form.RadioButton.radiobuttonWidth,
|
|
25
26
|
height: theme.Form.RadioButton.radiobuttonHeight,
|
|
26
|
-
borderRadius:
|
|
27
|
+
borderRadius: border.Radius['rounded-full'],
|
|
28
|
+
borderWidth: 1,
|
|
27
29
|
alignItems: 'center',
|
|
28
30
|
justifyContent: 'center',
|
|
29
|
-
|
|
31
|
+
transitionProperty: ['borderColor', 'backgroundColor'],
|
|
32
|
+
transitionDuration: 100,
|
|
30
33
|
variants: {
|
|
31
34
|
checked: {
|
|
32
35
|
true: {
|
|
33
36
|
borderColor: theme.Form.RadioButton.radiobuttonActiveBorderColor,
|
|
34
37
|
backgroundColor: theme.Form.RadioButton.radiobuttonActiveBorderColor,
|
|
35
|
-
borderWidth: 5,
|
|
36
38
|
},
|
|
37
39
|
false: {
|
|
38
40
|
borderColor: theme.Form.InputText.inputBorderColor,
|
|
39
|
-
borderWidth: 1,
|
|
40
41
|
backgroundColor: theme.Form.InputText.inputBg,
|
|
41
42
|
},
|
|
42
43
|
},
|
|
43
|
-
pressed: {
|
|
44
|
-
true: { borderColor: theme.Form.InputText.inputHoverBorderColor },
|
|
45
|
-
false: {},
|
|
46
|
-
},
|
|
47
|
-
state: {
|
|
48
|
-
danger: { borderColor: theme.Form.InputText.inputErrorBorderColor },
|
|
49
|
-
},
|
|
44
|
+
pressed: { true: {}, false: {} },
|
|
50
45
|
disabled: {
|
|
51
46
|
true: {
|
|
52
47
|
borderColor: theme.Form.InputText.inputBorderColor,
|
|
53
48
|
backgroundColor: theme.Button.Disabled.disabledButtonBg,
|
|
54
49
|
opacity: 0.6,
|
|
55
|
-
borderWidth: 1,
|
|
56
50
|
},
|
|
57
51
|
false: {},
|
|
58
52
|
},
|
|
53
|
+
state: { danger: {}, default: {} },
|
|
59
54
|
},
|
|
60
55
|
compoundVariants: [
|
|
61
56
|
{
|
|
@@ -63,26 +58,28 @@ const radioStyles = StyleSheet.create(({ theme }) => ({
|
|
|
63
58
|
pressed: 'true',
|
|
64
59
|
styles: {
|
|
65
60
|
borderColor: theme.Form.RadioButton.radiobuttonActiveHoverBorderColor,
|
|
66
|
-
backgroundColor: theme.Form.RadioButton.
|
|
67
|
-
borderWidth: 5,
|
|
61
|
+
backgroundColor: theme.Form.RadioButton.radiobuttonActiveHoverBg,
|
|
68
62
|
},
|
|
69
63
|
},
|
|
70
64
|
{
|
|
71
|
-
state: 'danger',
|
|
72
65
|
checked: 'true',
|
|
66
|
+
disabled: 'true',
|
|
73
67
|
styles: {
|
|
74
|
-
borderColor: theme.Form.
|
|
68
|
+
borderColor: theme.Form.RadioButton.radiobuttonActiveBorderColor,
|
|
75
69
|
backgroundColor: theme.Form.RadioButton.radiobuttonActiveBorderColor,
|
|
76
|
-
borderWidth: 1,
|
|
77
70
|
},
|
|
78
71
|
},
|
|
79
72
|
{
|
|
80
|
-
|
|
81
|
-
disabled: '
|
|
73
|
+
state: 'danger',
|
|
74
|
+
disabled: 'false',
|
|
75
|
+
checked: 'false',
|
|
76
|
+
styles: { borderColor: theme.Form.InputText.inputErrorBorderColor },
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
checked: 'false',
|
|
80
|
+
pressed: 'true',
|
|
82
81
|
styles: {
|
|
83
|
-
borderColor: theme.Form.RadioButton.
|
|
84
|
-
backgroundColor: theme.Form.RadioButton.radiobuttonActiveBorderColor,
|
|
85
|
-
borderWidth: 5,
|
|
82
|
+
borderColor: theme.Form.RadioButton.radiobuttonActiveHoverBorderColor,
|
|
86
83
|
},
|
|
87
84
|
},
|
|
88
85
|
],
|
|
@@ -90,28 +87,27 @@ const radioStyles = StyleSheet.create(({ theme }) => ({
|
|
|
90
87
|
center: {
|
|
91
88
|
width: theme.Form.RadioButton.radiobuttonIconSize,
|
|
92
89
|
height: theme.Form.RadioButton.radiobuttonIconSize,
|
|
93
|
-
borderRadius:
|
|
90
|
+
borderRadius: border.Radius['rounded-full'],
|
|
94
91
|
backgroundColor: theme.Form.InputText.inputBg,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
},
|
|
99
|
-
compoundVariants: [
|
|
100
|
-
{
|
|
101
|
-
disabled: 'true',
|
|
102
|
-
checked: 'false',
|
|
103
|
-
styles: { backgroundColor: 'transparent' },
|
|
104
|
-
},
|
|
105
|
-
],
|
|
92
|
+
transitionProperty: ['opacity'],
|
|
93
|
+
transitionDuration: 100,
|
|
94
|
+
variants: { checked: { false: { opacity: 0 }, true: { opacity: 1 } } },
|
|
106
95
|
},
|
|
107
96
|
outline: {
|
|
108
97
|
position: 'absolute',
|
|
98
|
+
top: -theme.General.focusShadowWidth,
|
|
99
|
+
left: -theme.General.focusShadowWidth,
|
|
109
100
|
width: theme.Form.RadioButton.radiobuttonWidth +
|
|
110
101
|
theme.General.focusShadowWidth * 2,
|
|
111
102
|
height: theme.Form.RadioButton.radiobuttonHeight +
|
|
112
103
|
theme.General.focusShadowWidth * 2,
|
|
113
|
-
borderRadius:
|
|
114
|
-
theme.General.focusShadowWidth * 2,
|
|
104
|
+
borderRadius: border.Radius['rounded-full'],
|
|
115
105
|
backgroundColor: theme.General.focusOutlineErrorColor,
|
|
106
|
+
transitionProperty: 'opacity',
|
|
107
|
+
transitionDuration: 100,
|
|
108
|
+
variants: {
|
|
109
|
+
state: { danger: { opacity: 1 }, default: { opacity: 0 } },
|
|
110
|
+
disabled: { true: { opacity: 0 } },
|
|
111
|
+
},
|
|
116
112
|
},
|
|
117
113
|
}));
|
package/package.json
CHANGED