@cdek-it/react-native-ui-kit 0.6.9 → 1.0.0-beta.0
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/README.md +9 -0
- package/dist/components/Accordion/Accordion.js +9 -10
- package/dist/components/Avatar/Avatar.js +7 -9
- package/dist/components/Badge/Badge.js +28 -20
- package/dist/components/Button/BaseButton.d.ts +3 -3
- package/dist/components/Button/BaseButton.js +12 -41
- package/dist/components/Button/Button.js +6 -4
- package/dist/components/Button/ButtonBadge.js +13 -12
- package/dist/components/Button/ButtonSeverity.js +6 -4
- package/dist/components/Button/index.d.ts +1 -1
- package/dist/components/Button/types.d.ts +2 -25
- package/dist/components/Button/utils/ButtonActivityIndicator.d.ts +3 -3
- package/dist/components/Button/utils/ButtonActivityIndicator.js +16 -12
- package/dist/components/Button/utils/ButtonContainer.d.ts +15 -6
- package/dist/components/Button/utils/ButtonContainer.js +424 -4
- package/dist/components/Button/utils/ButtonIcon.d.ts +8 -4
- package/dist/components/Button/utils/ButtonIcon.js +147 -4
- package/dist/components/Button/utils/ButtonLabel.d.ts +9 -4
- package/dist/components/Button/utils/ButtonLabel.js +139 -4
- package/dist/components/Button/utils/ButtonLeftArea.d.ts +9 -4
- package/dist/components/Button/utils/ButtonLeftArea.js +3 -3
- package/dist/components/Button/utils/ButtonPressedContext.d.ts +1 -0
- package/dist/components/Button/utils/ButtonPressedContext.js +2 -0
- package/dist/components/Button/utils/ButtonRightArea.d.ts +9 -3
- package/dist/components/Button/utils/ButtonRightArea.js +3 -3
- package/dist/components/Button/utils/ButtonVariantContext.d.ts +6 -0
- package/dist/components/Button/utils/ButtonVariantContext.js +4 -0
- package/dist/components/Checkbox/Checkbox.d.ts +6 -7
- package/dist/components/Checkbox/Checkbox.js +74 -22
- package/dist/components/Chip/Chip.js +13 -7
- package/dist/components/Dialog/DialogComponent.js +2 -3
- package/dist/components/Dialog/DialogHeader.js +17 -13
- package/dist/components/Divider/Divider.js +6 -6
- package/dist/components/Input/InputGroup.js +6 -13
- package/dist/components/Input/InputGroupAddon.js +5 -5
- package/dist/components/Input/InputOtp/InputOtp.js +2 -3
- package/dist/components/Input/InputOtp/InputOtpItem.js +2 -3
- package/dist/components/Input/InputSwitch/InputSwitch.js +2 -2
- package/dist/components/Input/InputSwitch/styles/useHandleStyles.js +13 -11
- package/dist/components/Input/InputSwitch/styles/useSliderStyles.d.ts +6 -5
- package/dist/components/Input/InputSwitch/styles/useSliderStyles.js +36 -29
- package/dist/components/Input/InputTextBase/InputTextBase.d.ts +0 -5
- package/dist/components/Input/InputTextBase/InputTextBase.js +41 -26
- package/dist/components/Input/InputTextBase/useInputStyles.d.ts +6 -5
- package/dist/components/Input/InputTextBase/useInputStyles.js +6 -9
- package/dist/components/Input/index.d.ts +0 -1
- package/dist/components/Input/index.js +0 -1
- package/dist/components/List/Base/ListBase.js +9 -12
- package/dist/components/MenuItem/MenuItemAccessory.js +5 -5
- package/dist/components/MenuItem/MenuItemIcon.js +4 -5
- package/dist/components/MenuItem/Template/MenuItemTemplate.js +8 -5
- package/dist/components/Message/Message.js +54 -38
- package/dist/components/ProgressBar/ProgressBar.js +2 -3
- package/dist/components/ProgressSpinner/ProgressSpinner.js +3 -4
- package/dist/components/RadioButton/RadioButton.js +87 -104
- package/dist/components/Rating/Rating.js +2 -3
- package/dist/components/Rating/RatingClear.js +10 -11
- package/dist/components/Rating/RatingItem.js +23 -24
- package/dist/components/Rating/RatingItemContainer.js +2 -3
- package/dist/components/SelectButton/SelectButton.js +2 -3
- package/dist/components/SelectButton/SelectButtonItem.js +22 -49
- package/dist/components/Skeleton/Skeleton.js +2 -3
- package/dist/components/Slider/Slider.js +4 -6
- package/dist/components/Tabs/TabItem/TabItem.js +12 -21
- package/dist/components/Tabs/Tabs.js +2 -3
- package/dist/components/Tag/Tag.js +44 -29
- package/dist/components/Timer/Timer.js +2 -3
- package/dist/components/Timer/TimerFlip.js +2 -3
- package/dist/components/ToggleButton/ToggleButton.js +159 -35
- package/dist/components/Typography/Anchor.js +11 -7
- package/dist/components/Typography/Body.js +2 -3
- package/dist/components/Typography/Caption.js +9 -4
- package/dist/components/Typography/Service.js +13 -7
- package/dist/components/Typography/Subtitle.js +3 -6
- package/dist/components/Typography/Title.js +3 -6
- package/dist/hooks/useChangeTheme.d.ts +2 -1
- package/dist/hooks/useChangeTheme.js +10 -3
- package/dist/hooks/useFonts.d.ts +2 -1
- package/dist/hooks/useFonts.js +3 -3
- package/dist/hooks/useTheme.d.ts +2 -1
- package/dist/hooks/useTheme.js +6 -4
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/theme/ThemeContext.d.ts +9 -7
- package/dist/theme/ThemeContext.js +21 -14
- package/dist/theme/darkTheme.js +1 -0
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/index.js +1 -1
- package/dist/theme/lightTheme.js +1 -0
- package/dist/theme/types.d.ts +1 -0
- package/dist/utils/SvgUniversal.d.ts +9 -14
- package/dist/utils/SvgUniversal.js +10 -2
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +18 -8
- package/dist/components/Button/styles/index.d.ts +0 -2
- package/dist/components/Button/styles/index.js +0 -2
- package/dist/components/Button/styles/useBasicButtonStyles.d.ts +0 -98
- package/dist/components/Button/styles/useBasicButtonStyles.js +0 -81
- package/dist/components/Button/styles/useDangerButtonStyles.d.ts +0 -63
- package/dist/components/Button/styles/useDangerButtonStyles.js +0 -57
- package/dist/components/Button/styles/useInfoButtonStyles.d.ts +0 -63
- package/dist/components/Button/styles/useInfoButtonStyles.js +0 -56
- package/dist/components/Button/styles/useSeverityButtonStyles.d.ts +0 -64
- package/dist/components/Button/styles/useSeverityButtonStyles.js +0 -29
- package/dist/components/Button/styles/useSuccessButtonStyles.d.ts +0 -63
- package/dist/components/Button/styles/useSuccessButtonStyles.js +0 -61
- package/dist/components/Button/styles/useWarningButtonStyles.d.ts +0 -63
- package/dist/components/Button/styles/useWarningButtonStyles.js +0 -61
- package/dist/components/Button/utils/useButtonContainerCallbackStyle.d.ts +0 -3
- package/dist/components/Button/utils/useButtonContainerCallbackStyle.js +0 -141
- package/dist/components/Button/utils/useButtonLabelStyle.d.ts +0 -3
- package/dist/components/Button/utils/useButtonLabelStyle.js +0 -40
- package/dist/components/Button/utils/useIconStyle.d.ts +0 -7
- package/dist/components/Button/utils/useIconStyle.js +0 -35
- package/dist/components/Button/utils/useTypeBasedStyle.d.ts +0 -2
- package/dist/components/Button/utils/useTypeBasedStyle.js +0 -4
- package/dist/components/Checkbox/hooks/usePressableStyles.d.ts +0 -15
- package/dist/components/Checkbox/hooks/usePressableStyles.js +0 -91
- package/dist/components/Input/FloatLabel.d.ts +0 -22
- package/dist/components/Input/FloatLabel.js +0 -19
- package/dist/components/ToggleButton/hooks/useIconSize.d.ts +0 -14
- package/dist/components/ToggleButton/hooks/useIconSize.js +0 -26
- package/dist/components/ToggleButton/hooks/useLabelSize.d.ts +0 -8
- package/dist/components/ToggleButton/hooks/useLabelSize.js +0 -19
- package/dist/components/ToggleButton/hooks/useStateStyles.d.ts +0 -11
- package/dist/components/ToggleButton/hooks/useStateStyles.js +0 -92
- package/dist/utils/makeStyles.d.ts +0 -11
- package/dist/utils/makeStyles.js +0 -19
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import { memo } from 'react';
|
|
2
2
|
import { Pressable, Text } from 'react-native';
|
|
3
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
3
4
|
import { SvgUniversal } from '../../utils/SvgUniversal';
|
|
4
|
-
import { makeStyles } from '../../utils/makeStyles';
|
|
5
5
|
/**
|
|
6
6
|
* Служебный компонент для группировки инпута
|
|
7
7
|
* @link https://www.figma.com/design/4TYeki0MDLhfPGJstbIicf/UI-kit-PrimeFace-(DS)?node-id=484-5932&m=dev
|
|
8
8
|
* @see InputGroup
|
|
9
9
|
*/
|
|
10
10
|
export const InputGroupAddon = memo(({ content, onPress, position, disabled }) => {
|
|
11
|
-
const styles = useStyles();
|
|
12
11
|
return (<Pressable collapsable={false} disabled={disabled} style={[
|
|
13
12
|
styles.container,
|
|
14
13
|
styles[position],
|
|
15
14
|
disabled && styles.disabled,
|
|
16
15
|
]} testID='InputGroupAddon_Pressable' onPress={onPress}>
|
|
17
|
-
{typeof content === 'string' ? (<Text style={styles.text}>{content}</Text>) : (<SvgUniversal
|
|
16
|
+
{typeof content === 'string' ? (<Text style={styles.text}>{content}</Text>) : (<SvgUniversal {...styles.icon} source={content} uniProps={({ theme }) => ({
|
|
17
|
+
color: theme.Form.InputGroup.inputGroupTextColor,
|
|
18
|
+
})}/>)}
|
|
18
19
|
</Pressable>);
|
|
19
20
|
});
|
|
20
|
-
const
|
|
21
|
+
const styles = StyleSheet.create(({ theme, typography, fonts }) => ({
|
|
21
22
|
container: {
|
|
22
23
|
paddingVertical: theme.Form.InputText.inputPaddingTopBottom,
|
|
23
24
|
paddingHorizontal: theme.Form.InputText.inputPaddingLeftRight,
|
|
@@ -52,6 +53,5 @@ const useStyles = makeStyles(({ theme, typography, fonts }) => ({
|
|
|
52
53
|
icon: {
|
|
53
54
|
width: typography.Size['text-base'],
|
|
54
55
|
height: typography.Size['text-base'],
|
|
55
|
-
color: theme.Form.InputGroup.inputGroupTextColor,
|
|
56
56
|
},
|
|
57
57
|
}));
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { memo, useCallback, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
2
2
|
import { Pressable, View, TextInput, } from 'react-native';
|
|
3
|
-
import {
|
|
3
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
4
4
|
import { InputOtpItem } from './InputOtpItem';
|
|
5
5
|
export const InputOtp = memo(({ length, onChange, disabled = false, error = false, testOnly_pressed, inputRef: propsInputRef, testID, value = '', onFocus, onBlur, ...rest }) => {
|
|
6
|
-
const styles = useStyles();
|
|
7
6
|
const [isFocused, setIsFocused] = useState(false);
|
|
8
7
|
const inputRef = useRef(null);
|
|
9
8
|
useImperativeHandle(propsInputRef, () => inputRef.current);
|
|
@@ -33,7 +32,7 @@ export const InputOtp = memo(({ length, onChange, disabled = false, error = fals
|
|
|
33
32
|
</>)}
|
|
34
33
|
</Pressable>);
|
|
35
34
|
});
|
|
36
|
-
const
|
|
35
|
+
const styles = StyleSheet.create(({ spacing }) => ({
|
|
37
36
|
container: {},
|
|
38
37
|
content: { flexDirection: 'row', gap: spacing.Gap['gap-2'] },
|
|
39
38
|
input: { position: 'absolute', width: 1, height: 1, opacity: 0 },
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { memo, useEffect } from 'react';
|
|
2
2
|
import { View, Text } from 'react-native';
|
|
3
3
|
import Animated, { Easing, useAnimatedStyle, useSharedValue, withRepeat, withTiming, } from 'react-native-reanimated';
|
|
4
|
-
import {
|
|
4
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
5
5
|
const CURSOR_ANIMATION_DURATION = 500;
|
|
6
6
|
export const InputOtpItem = memo(({ value, error, pressed, disabled, focused, testID }) => {
|
|
7
|
-
const styles = useStyles();
|
|
8
7
|
const opacity = useSharedValue(1);
|
|
9
8
|
useEffect(() => {
|
|
10
9
|
if (focused) {
|
|
@@ -32,7 +31,7 @@ export const InputOtpItem = memo(({ value, error, pressed, disabled, focused, te
|
|
|
32
31
|
</Text>
|
|
33
32
|
</View>);
|
|
34
33
|
});
|
|
35
|
-
const
|
|
34
|
+
const styles = StyleSheet.create(({ theme, border, fonts, typography }) => ({
|
|
36
35
|
container: {
|
|
37
36
|
minHeight: theme.Button.Common.buttonHeight,
|
|
38
37
|
minWidth: theme.Button.Common.buttonHeight,
|
|
@@ -3,12 +3,12 @@ import { Pressable } from 'react-native';
|
|
|
3
3
|
import Animated from 'react-native-reanimated';
|
|
4
4
|
import { useHandleStyles, useSliderStyles } from './styles';
|
|
5
5
|
export const InputSwitch = memo(({ checked, onCheckedChange, disabled = false, danger = false, ...props }) => {
|
|
6
|
-
const { sliderStyle,
|
|
6
|
+
const { containerStyle, sliderStyle, onPressIn, onPressOut } = useSliderStyles(checked, disabled, danger);
|
|
7
7
|
const { handleStyle } = useHandleStyles(checked);
|
|
8
8
|
const handlePress = useCallback(() => {
|
|
9
9
|
onCheckedChange?.(!checked);
|
|
10
10
|
}, [checked, onCheckedChange]);
|
|
11
|
-
return (<Pressable disabled={disabled} style={
|
|
11
|
+
return (<Pressable disabled={disabled} style={containerStyle} onPress={handlePress} onPressIn={onPressIn} onPressOut={onPressOut} {...props}>
|
|
12
12
|
<Animated.View style={sliderStyle}>
|
|
13
13
|
<Animated.View style={handleStyle}/>
|
|
14
14
|
</Animated.View>
|
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
2
|
-
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { StyleSheet as RNStyleSheet } from 'react-native';
|
|
3
3
|
import { useSharedValue, withTiming } from 'react-native-reanimated';
|
|
4
|
-
import {
|
|
4
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
5
5
|
export const useHandleStyles = (checked) => {
|
|
6
|
-
const styles =
|
|
7
|
-
const
|
|
6
|
+
const styles = handleStyles;
|
|
7
|
+
const handleOnLeft = styles.handleOn.left;
|
|
8
|
+
const handleOffLeft = styles.handleOff.left;
|
|
9
|
+
const calculateHandleLeftPosition = useCallback((checked) => (checked ? handleOnLeft : handleOffLeft), [handleOffLeft, handleOnLeft]);
|
|
8
10
|
const calculateHandleBackground = useCallback((checked) => checked ? styles.handleOn.backgroundColor : styles.handle.backgroundColor, [styles.handle.backgroundColor, styles.handleOn.backgroundColor]);
|
|
9
11
|
const handleLeftPosition = useSharedValue(calculateHandleLeftPosition(checked));
|
|
10
|
-
const
|
|
12
|
+
const handleBackground = useSharedValue(calculateHandleBackground(checked));
|
|
11
13
|
useEffect(() => {
|
|
12
14
|
handleLeftPosition.value = withTiming(calculateHandleLeftPosition(checked));
|
|
13
|
-
|
|
15
|
+
handleBackground.value = withTiming(calculateHandleBackground(checked));
|
|
14
16
|
}, [
|
|
15
17
|
calculateHandleBackground,
|
|
16
18
|
calculateHandleLeftPosition,
|
|
17
19
|
checked,
|
|
18
20
|
handleLeftPosition,
|
|
19
|
-
|
|
21
|
+
handleBackground,
|
|
20
22
|
]);
|
|
21
|
-
const handleStyle = useMemo(() =>
|
|
23
|
+
const handleStyle = useMemo(() => RNStyleSheet.flatten([
|
|
22
24
|
styles.handle,
|
|
23
|
-
{ left: handleLeftPosition, backgroundColor:
|
|
24
|
-
]), [handleLeftPosition,
|
|
25
|
+
{ left: handleLeftPosition, backgroundColor: handleBackground },
|
|
26
|
+
]), [handleLeftPosition, handleBackground, styles.handle]);
|
|
25
27
|
return { handleStyle };
|
|
26
28
|
};
|
|
27
|
-
const
|
|
29
|
+
const handleStyles = StyleSheet.create(({ theme, border }) => ({
|
|
28
30
|
handle: {
|
|
29
31
|
height: theme.Form.inputSwitch.inputSwitchHandleHeight,
|
|
30
32
|
width: theme.Form.inputSwitch.inputSwitchHandleWidth,
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { type PressableStateCallbackType } from 'react-native';
|
|
2
1
|
export declare const useSliderStyles: (checked: boolean, disabled: boolean, danger: boolean) => {
|
|
2
|
+
containerStyle: {
|
|
3
|
+
height: number;
|
|
4
|
+
width: number;
|
|
5
|
+
};
|
|
3
6
|
sliderStyle: {
|
|
4
7
|
padding: number;
|
|
5
8
|
height: number;
|
|
@@ -10,8 +13,6 @@ export declare const useSliderStyles: (checked: boolean, disabled: boolean, dang
|
|
|
10
13
|
backgroundColor: import("react-native-reanimated").SharedValue<string>;
|
|
11
14
|
borderColor: import("react-native-reanimated").SharedValue<string>;
|
|
12
15
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
width: number;
|
|
16
|
-
};
|
|
16
|
+
onPressIn: () => void;
|
|
17
|
+
onPressOut: () => void;
|
|
17
18
|
};
|
|
@@ -1,33 +1,40 @@
|
|
|
1
|
-
import { useCallback, useEffect, useMemo } from 'react';
|
|
2
|
-
import { StyleSheet } from 'react-native';
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { StyleSheet as RNStyleSheet } from 'react-native';
|
|
3
3
|
import { useSharedValue, withTiming } from 'react-native-reanimated';
|
|
4
|
-
import {
|
|
4
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
5
5
|
export const useSliderStyles = (checked, disabled, danger) => {
|
|
6
|
-
const styles =
|
|
6
|
+
const styles = switchStyles;
|
|
7
|
+
const [pressed, setPressed] = useState(false);
|
|
8
|
+
const sliderDisabledBg = styles.sliderDisabled.backgroundColor;
|
|
9
|
+
const sliderOffBg = styles.sliderOff.backgroundColor;
|
|
10
|
+
const sliderOnBg = styles.sliderOn.backgroundColor;
|
|
11
|
+
const sliderOnDisabledBg = styles.sliderOnDisabled.backgroundColor;
|
|
12
|
+
const sliderOnPressedBg = styles.sliderOnPressed.backgroundColor;
|
|
13
|
+
const sliderPressedBg = styles.sliderPressed.backgroundColor;
|
|
7
14
|
const calculateSliderBackground = useCallback((checked, disabled, pressed) => {
|
|
8
15
|
if (disabled) {
|
|
9
16
|
if (checked) {
|
|
10
|
-
return
|
|
17
|
+
return sliderOnDisabledBg;
|
|
11
18
|
}
|
|
12
|
-
return
|
|
19
|
+
return sliderDisabledBg;
|
|
13
20
|
}
|
|
14
21
|
if (pressed) {
|
|
15
22
|
if (checked) {
|
|
16
|
-
return
|
|
23
|
+
return sliderOnPressedBg;
|
|
17
24
|
}
|
|
18
|
-
return
|
|
25
|
+
return sliderPressedBg;
|
|
19
26
|
}
|
|
20
27
|
if (checked) {
|
|
21
|
-
return
|
|
28
|
+
return sliderOnBg;
|
|
22
29
|
}
|
|
23
|
-
return
|
|
30
|
+
return sliderOffBg;
|
|
24
31
|
}, [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
sliderDisabledBg,
|
|
33
|
+
sliderOffBg,
|
|
34
|
+
sliderOnBg,
|
|
35
|
+
sliderOnDisabledBg,
|
|
36
|
+
sliderOnPressedBg,
|
|
37
|
+
sliderPressedBg,
|
|
31
38
|
]);
|
|
32
39
|
const calculateSliderBorderColor = useCallback((danger) => {
|
|
33
40
|
if (danger && !disabled) {
|
|
@@ -41,26 +48,26 @@ export const useSliderStyles = (checked, disabled, danger) => {
|
|
|
41
48
|
]);
|
|
42
49
|
const sliderBackground = useSharedValue(calculateSliderBackground(checked, disabled, false));
|
|
43
50
|
const sliderBorderColor = useSharedValue(calculateSliderBorderColor(danger));
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
sliderBackground.value = withTiming(calculateSliderBackground(checked, disabled, pressed));
|
|
53
|
+
}, [calculateSliderBackground, checked, disabled, pressed, sliderBackground]);
|
|
44
54
|
useEffect(() => {
|
|
45
55
|
sliderBorderColor.value = withTiming(calculateSliderBorderColor(danger));
|
|
46
56
|
}, [calculateSliderBorderColor, danger, sliderBorderColor]);
|
|
47
|
-
const sliderStyle = useMemo(() =>
|
|
57
|
+
const sliderStyle = useMemo(() => RNStyleSheet.flatten([
|
|
48
58
|
styles.slider,
|
|
49
59
|
{ backgroundColor: sliderBackground, borderColor: sliderBorderColor },
|
|
50
60
|
]), [sliderBackground, sliderBorderColor, styles.slider]);
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
styles.container,
|
|
60
|
-
]);
|
|
61
|
-
return { sliderStyle, onPressedChange };
|
|
61
|
+
const onPressIn = useCallback(() => setPressed(true), []);
|
|
62
|
+
const onPressOut = useCallback(() => setPressed(false), []);
|
|
63
|
+
return {
|
|
64
|
+
containerStyle: styles.container,
|
|
65
|
+
sliderStyle,
|
|
66
|
+
onPressIn,
|
|
67
|
+
onPressOut,
|
|
68
|
+
};
|
|
62
69
|
};
|
|
63
|
-
const
|
|
70
|
+
const switchStyles = StyleSheet.create(({ theme, border }) => ({
|
|
64
71
|
container: {
|
|
65
72
|
height: theme.Form.inputSwitch.inputSwitchHeight,
|
|
66
73
|
width: theme.Form.inputSwitch.inputSwitchWidth,
|
|
@@ -2,10 +2,5 @@ import type { InputTextBaseProps } from './types';
|
|
|
2
2
|
interface PrivateInputTextBaseProps {
|
|
3
3
|
loading?: boolean;
|
|
4
4
|
}
|
|
5
|
-
/**
|
|
6
|
-
* Базовое поле
|
|
7
|
-
* @link https://www.figma.com/design/4TYeki0MDLhfPGJstbIicf/UI-kit-PrimeFace-(DS)?node-id=484-5470&m=dev
|
|
8
|
-
* @see InputText
|
|
9
|
-
*/
|
|
10
5
|
export declare const InputTextBase: import("react").NamedExoticComponent<InputTextBaseProps & PrivateInputTextBaseProps>;
|
|
11
6
|
export {};
|
|
@@ -5,36 +5,44 @@ import { TextInput, View, Text, TouchableOpacity, Pressable, } from 'react-nativ
|
|
|
5
5
|
import Animated, { interpolate, useAnimatedStyle, useSharedValue, withTiming, } from 'react-native-reanimated';
|
|
6
6
|
import { useLoadingRotationAnimation } from '../../../hooks/useLoadingRotationAnimation';
|
|
7
7
|
import { useMakeTestId } from '../../../hooks/useMakeTestId';
|
|
8
|
+
import { SvgUniversal } from '../../../utils/SvgUniversal';
|
|
8
9
|
import { InputTextBaseTestId } from './testIds';
|
|
9
|
-
import {
|
|
10
|
+
import { inputStyles, useInputContainerMinHeight } from './useInputStyles';
|
|
10
11
|
/**
|
|
11
12
|
* Базовое поле
|
|
12
13
|
* @link https://www.figma.com/design/4TYeki0MDLhfPGJstbIicf/UI-kit-PrimeFace-(DS)?node-id=484-5470&m=dev
|
|
13
14
|
* @see InputText
|
|
14
15
|
*/
|
|
16
|
+
const inputIconUniProps = ({ theme }) => ({
|
|
17
|
+
color: theme.Form.InputText.inputIconColor,
|
|
18
|
+
});
|
|
15
19
|
export const InputTextBase = memo(
|
|
16
|
-
// eslint-disable-next-line max-lines-per-function
|
|
20
|
+
// eslint-disable-next-line max-lines-per-function, max-statements
|
|
17
21
|
({ state, clearable = true, secureTextEntry: secureTextEntryProp = false, inputRef: propsInputRef, disabled, containerStyle, loading, renderTextInput, clearButtonAccessibilityLabel, floatLabel = false, placeholder, editable = true, size, ...otherProps
|
|
18
22
|
// TODO: разделить float label и обычный инпут -> добавить во float label поддержку font scale
|
|
19
23
|
// eslint-disable-next-line complexity
|
|
20
24
|
}) => {
|
|
21
|
-
const styles =
|
|
25
|
+
const styles = inputStyles;
|
|
26
|
+
const containerMinHeightStyle = useInputContainerMinHeight(size);
|
|
22
27
|
const inputRef = useRef(null);
|
|
23
28
|
const [valueState, setValueState] = useState('');
|
|
24
29
|
const [isFocused, setIsFocused] = useState(otherProps.autoFocus || false);
|
|
25
30
|
const labelAnimation = useSharedValue(0);
|
|
31
|
+
const propsOnFocus = otherProps.onFocus;
|
|
32
|
+
const propsOnBlur = otherProps.onBlur;
|
|
33
|
+
const propsOnChangeText = otherProps.onChangeText;
|
|
26
34
|
const onFocus = useCallback((e) => {
|
|
27
35
|
setIsFocused(true);
|
|
28
|
-
|
|
29
|
-
}, [
|
|
36
|
+
propsOnFocus?.(e);
|
|
37
|
+
}, [propsOnFocus]);
|
|
30
38
|
const onBlur = useCallback((e) => {
|
|
31
39
|
setIsFocused(false);
|
|
32
|
-
|
|
33
|
-
}, [
|
|
40
|
+
propsOnBlur?.(e);
|
|
41
|
+
}, [propsOnBlur]);
|
|
34
42
|
const onChangeText = useCallback((nextValue) => {
|
|
35
|
-
|
|
43
|
+
propsOnChangeText?.(nextValue);
|
|
36
44
|
setValueState(nextValue);
|
|
37
|
-
}, [
|
|
45
|
+
}, [propsOnChangeText]);
|
|
38
46
|
const clear = useCallback(() => {
|
|
39
47
|
onChangeText('');
|
|
40
48
|
}, [onChangeText]);
|
|
@@ -44,13 +52,21 @@ export const InputTextBase = memo(
|
|
|
44
52
|
inputRef.current?.focus();
|
|
45
53
|
}, []);
|
|
46
54
|
const loadingAnimatedStyle = useLoadingRotationAnimation(loading);
|
|
55
|
+
// Extract primitive values before the worklet closure to avoid
|
|
56
|
+
// capturing the unistyles HostObject (non-serializable) in the worklet.
|
|
57
|
+
const labelTop = styles.label.top;
|
|
58
|
+
const labelReducedTop = styles.labelReducedSize.top;
|
|
59
|
+
const labelPaddingVertical = styles.label.paddingVertical;
|
|
60
|
+
const labelReducedPaddingVertical = styles.labelReducedSize.paddingVertical;
|
|
61
|
+
const labelFontSize = styles.label.fontSize;
|
|
62
|
+
const labelReducedFontSize = styles.labelReducedSize.fontSize;
|
|
63
|
+
const labelFontFamily = styles.label.fontFamily;
|
|
64
|
+
const labelReducedFontFamily = styles.labelReducedSize.fontFamily;
|
|
47
65
|
const labelAnimatedStyle = useAnimatedStyle(() => ({
|
|
48
|
-
top: interpolate(labelAnimation.value, [0, 1], [
|
|
49
|
-
paddingVertical: interpolate(labelAnimation.value, [0, 1], [
|
|
50
|
-
fontSize: interpolate(labelAnimation.value, [0, 1], [
|
|
51
|
-
fontFamily: labelAnimation.value > 0.5
|
|
52
|
-
? styles.labelReducedSize.fontFamily
|
|
53
|
-
: styles.label.fontFamily,
|
|
66
|
+
top: interpolate(labelAnimation.value, [0, 1], [labelTop, labelReducedTop]),
|
|
67
|
+
paddingVertical: interpolate(labelAnimation.value, [0, 1], [labelPaddingVertical, labelReducedPaddingVertical]),
|
|
68
|
+
fontSize: interpolate(labelAnimation.value, [0, 1], [labelFontSize, labelReducedFontSize]),
|
|
69
|
+
fontFamily: labelAnimation.value > 0.5 ? labelReducedFontFamily : labelFontFamily,
|
|
54
70
|
}));
|
|
55
71
|
useEffect(() => {
|
|
56
72
|
labelAnimation.value = withTiming(isFocused || value ? 1 : 0, {
|
|
@@ -58,9 +74,7 @@ export const InputTextBase = memo(
|
|
|
58
74
|
});
|
|
59
75
|
}, [isFocused, labelAnimation, value]);
|
|
60
76
|
const iconSize = useMemo(() => (floatLabel ? styles.iconSizeFloatLabel : styles.iconSize), [floatLabel, styles.iconSize, styles.iconSizeFloatLabel]);
|
|
61
|
-
useImperativeHandle(propsInputRef, () => (inputRef.current
|
|
62
|
-
? Object.assign(inputRef.current, { clear })
|
|
63
|
-
: null), [inputRef, clear]);
|
|
77
|
+
useImperativeHandle(propsInputRef, () => inputRef.current ? Object.assign(inputRef.current, { clear }) : null, [inputRef, clear]);
|
|
64
78
|
const { makeTestId } = useMakeTestId(otherProps.testID || InputTextBaseTestId.default);
|
|
65
79
|
const [userDefinedSecureTextEntry, setUserDefinedSecureTextEntry] = useState(true);
|
|
66
80
|
const secureTextEntry = useMemo(() => secureTextEntryProp === 'toggleable'
|
|
@@ -109,19 +123,20 @@ export const InputTextBase = memo(
|
|
|
109
123
|
disabled,
|
|
110
124
|
editable,
|
|
111
125
|
secureTextEntry,
|
|
112
|
-
styles.inputFont,
|
|
113
|
-
styles.floatLabelInput,
|
|
114
|
-
styles.input,
|
|
115
|
-
styles.inputWithRightContent,
|
|
116
126
|
hasRightContent,
|
|
117
127
|
value,
|
|
118
128
|
onBlur,
|
|
119
129
|
onChangeText,
|
|
120
130
|
onFocus,
|
|
131
|
+
styles.inputFont,
|
|
132
|
+
styles.floatLabelInput,
|
|
133
|
+
styles.input,
|
|
134
|
+
styles.inputWithRightContent,
|
|
121
135
|
]);
|
|
122
136
|
const input = useMemo(() => renderTextInput ? (renderTextInput(texInputProps)) : (<TextInput {...texInputProps} ref={inputRef}/>), [renderTextInput, texInputProps]);
|
|
123
137
|
return (<Pressable accessible={false} disabled={disabled} style={[
|
|
124
138
|
styles.container,
|
|
139
|
+
containerMinHeightStyle,
|
|
125
140
|
floatLabel && styles.containerFloatLabel,
|
|
126
141
|
isFocused && styles.containerFocused,
|
|
127
142
|
containerStyle,
|
|
@@ -153,18 +168,18 @@ export const InputTextBase = memo(
|
|
|
153
168
|
|
|
154
169
|
{hasRightContent ? (<View style={styles.rightContainer}>
|
|
155
170
|
{loading ? (<Animated.View style={[styles.rightButtonContainer, loadingAnimatedStyle]} testID={makeTestId(InputTextBaseTestId.loading)}>
|
|
156
|
-
<
|
|
171
|
+
<SvgUniversal {...iconSize} source={IconLoader2} uniProps={inputIconUniProps}/>
|
|
157
172
|
</Animated.View>) : null}
|
|
158
173
|
|
|
159
174
|
{showClearButton ? (<TouchableOpacity accessibilityLabel={clearButtonAccessibilityLabel} hitSlop={rightButtonHitSlop} style={styles.rightButtonContainer} testID={makeTestId(InputTextBaseTestId.clearButton)} onPress={clear}>
|
|
160
|
-
<
|
|
175
|
+
<SvgUniversal {...iconSize} source={IconX} uniProps={inputIconUniProps}/>
|
|
161
176
|
</TouchableOpacity>) : null}
|
|
162
177
|
|
|
163
178
|
{showSecureToggle ? (<TouchableOpacity hitSlop={rightButtonHitSlop} style={styles.rightButtonContainer} testID={makeTestId(InputTextBaseTestId.secureInputButton)} onPress={toggleUserDefinedSecureTextEntry}>
|
|
164
|
-
|
|
179
|
+
<SvgUniversal {...iconSize} source={userDefinedSecureTextEntry ? IconEye : IconEyeOff} uniProps={inputIconUniProps}/>
|
|
165
180
|
</TouchableOpacity>) : null}
|
|
166
181
|
|
|
167
|
-
{disabled ? (<
|
|
182
|
+
{disabled ? (<SvgUniversal {...iconSize} source={IconLock} testID={makeTestId(InputTextBaseTestId.disabledIcon)} uniProps={inputIconUniProps}/>) : null}
|
|
168
183
|
</View>) : null}
|
|
169
184
|
</Pressable>);
|
|
170
185
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { InputTextBaseProps } from './types';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const useInputContainerMinHeight: (size?: InputTextBaseProps["size"]) => {
|
|
3
|
+
minHeight: number;
|
|
4
|
+
};
|
|
5
|
+
export declare const inputStyles: {
|
|
3
6
|
container: {
|
|
4
|
-
minHeight: number;
|
|
5
7
|
flexDirection: "row";
|
|
6
8
|
borderWidth: number;
|
|
7
9
|
borderRadius: number;
|
|
@@ -77,9 +79,6 @@ export declare const useInputStyle: (size?: InputTextBaseProps["size"]) => {
|
|
|
77
79
|
rightButtonContainer: {
|
|
78
80
|
justifyContent: "center";
|
|
79
81
|
};
|
|
80
|
-
rightIcon: {
|
|
81
|
-
color: string;
|
|
82
|
-
};
|
|
83
82
|
iconSize: {
|
|
84
83
|
width: number;
|
|
85
84
|
height: number;
|
|
@@ -111,4 +110,6 @@ export declare const useInputStyle: (size?: InputTextBaseProps["size"]) => {
|
|
|
111
110
|
hidden: {
|
|
112
111
|
opacity: number;
|
|
113
112
|
};
|
|
113
|
+
} & {
|
|
114
|
+
useVariants: (variants: never) => void;
|
|
114
115
|
};
|
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
export const
|
|
4
|
-
const styles = useStyles();
|
|
5
|
-
const containerMinHeight = useContainerMinHeight();
|
|
2
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
3
|
+
export const useInputContainerMinHeight = (size = 'base') => {
|
|
6
4
|
const minHeight = useMemo(() => {
|
|
7
5
|
if (typeof size === 'number') {
|
|
8
6
|
return Math.max(size, containerMinHeight.base.minHeight);
|
|
9
7
|
}
|
|
10
8
|
return containerMinHeight[size].minHeight;
|
|
11
|
-
}, [size
|
|
12
|
-
return {
|
|
9
|
+
}, [size]);
|
|
10
|
+
return { minHeight };
|
|
13
11
|
};
|
|
14
|
-
const
|
|
12
|
+
const containerMinHeight = StyleSheet.create(({ theme }) => ({
|
|
15
13
|
base: { minHeight: theme.InputSize.base['min-height'] },
|
|
16
14
|
large: { minHeight: theme.InputSize.large['min-height'] },
|
|
17
15
|
xlarge: { minHeight: theme.InputSize.xlarge['min-height'] },
|
|
18
16
|
}));
|
|
19
|
-
const
|
|
17
|
+
export const inputStyles = StyleSheet.create(({ theme, border, typography, spacing, fonts }) => ({
|
|
20
18
|
container: {
|
|
21
19
|
flexDirection: 'row',
|
|
22
20
|
borderWidth: border.Width.border,
|
|
@@ -85,7 +83,6 @@ const useStyles = makeStyles(({ theme, border, typography, spacing, fonts }) =>
|
|
|
85
83
|
alignItems: 'center',
|
|
86
84
|
},
|
|
87
85
|
rightButtonContainer: { justifyContent: 'center' },
|
|
88
|
-
rightIcon: { color: theme.Form.InputText.inputIconColor },
|
|
89
86
|
iconSize: {
|
|
90
87
|
width: typography.Size['text-base'],
|
|
91
88
|
height: typography.Size['text-base'],
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { InputGroup } from './InputGroup';
|
|
2
2
|
export { InputText } from './InputText';
|
|
3
|
-
export { FloatLabel } from './FloatLabel';
|
|
4
3
|
export { InputSwitch } from './InputSwitch';
|
|
5
4
|
export type { InputTextBaseProps } from './InputTextBase/types';
|
|
6
5
|
export { InputOtp } from './InputOtp/InputOtp';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
|
-
import { View, Pressable
|
|
2
|
+
import { View, Pressable } from 'react-native';
|
|
3
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
3
4
|
import { SvgUniversal } from '../../../utils/SvgUniversal';
|
|
4
|
-
import { makeStyles } from '../../../utils/makeStyles';
|
|
5
5
|
import { Subtitle, Body, Caption } from '../../Typography';
|
|
6
6
|
/**
|
|
7
7
|
* Базовый элемент списка
|
|
@@ -9,13 +9,10 @@ import { Subtitle, Body, Caption } from '../../Typography';
|
|
|
9
9
|
* Фигма https://www.figma.com/design/2ZnL6XPKEpxAHvrlbRvnMu/Template-Tailwind-CSS-(DS)?node-id=641-2254&m=dev
|
|
10
10
|
*/
|
|
11
11
|
export const ListBase = memo(({ iconAlignment = 'top', text: title, title: subtitle, caption, LeftIcon, leftIconColor, RightIcon, rightIconColor, extra, divider, disabled = false, onPress, style, testID, ...rest }) => {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
alignSelf: iconAlignment === 'top' ? 'flex-start' : undefined,
|
|
17
|
-
};
|
|
18
|
-
}, [styles.leftIcon, iconAlignment]);
|
|
12
|
+
const leftIconStyle = useMemo(() => [
|
|
13
|
+
styles.leftIcon,
|
|
14
|
+
iconAlignment === 'top' ? { alignSelf: 'flex-start' } : null,
|
|
15
|
+
], [iconAlignment]);
|
|
19
16
|
const fullDivider = divider === 'full' ? styles.divider : {};
|
|
20
17
|
const contentDivider = divider === 'content' ? styles.divider : {};
|
|
21
18
|
const accessibilityLabel = useMemo(() => [subtitle, title].join(' '), [subtitle, title]);
|
|
@@ -28,7 +25,7 @@ export const ListBase = memo(({ iconAlignment = 'top', text: title, title: subti
|
|
|
28
25
|
pressed && styles.pressed,
|
|
29
26
|
]} {...rest}>
|
|
30
27
|
{LeftIcon ? (<View style={leftIconStyle}>
|
|
31
|
-
<SvgUniversal source={LeftIcon} testID={ListBaseTestId.leftIcon} {
|
|
28
|
+
<SvgUniversal color={leftIconColor} height={styles.icon.height} source={LeftIcon} testID={ListBaseTestId.leftIcon} width={styles.icon.width}/>
|
|
32
29
|
</View>) : null}
|
|
33
30
|
<View style={[styles.content, contentDivider]}>
|
|
34
31
|
<View style={styles.labelContainer}>
|
|
@@ -40,7 +37,7 @@ export const ListBase = memo(({ iconAlignment = 'top', text: title, title: subti
|
|
|
40
37
|
</View>
|
|
41
38
|
<View style={styles.rightSection}>
|
|
42
39
|
{extra ? (<View style={styles.extraContainer}>{extra}</View>) : null}
|
|
43
|
-
{RightIcon ? (<SvgUniversal source={RightIcon} testID={ListBaseTestId.rightIcon} {
|
|
40
|
+
{RightIcon ? (<SvgUniversal color={rightIconColor} height={styles.icon.height} source={RightIcon} testID={ListBaseTestId.rightIcon} width={styles.icon.width}/>) : null}
|
|
44
41
|
</View>
|
|
45
42
|
</View>
|
|
46
43
|
</View>)}
|
|
@@ -52,7 +49,7 @@ const ListBaseTestId = {
|
|
|
52
49
|
rightIcon: 'RightIcon',
|
|
53
50
|
title: 'Title',
|
|
54
51
|
};
|
|
55
|
-
const
|
|
52
|
+
const styles = StyleSheet.create(({ spacing, typography, theme, background }) => ({
|
|
56
53
|
container: {
|
|
57
54
|
flexDirection: 'row',
|
|
58
55
|
paddingLeft: spacing.Padding['p-4'],
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { IconLock } from '@tabler/icons-react-native';
|
|
2
2
|
import { memo, useMemo } from 'react';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
4
5
|
import { SvgUniversal } from '../../utils/SvgUniversal';
|
|
5
|
-
import { makeStyles } from '../../utils/makeStyles';
|
|
6
6
|
/**
|
|
7
7
|
* Аксессуар элемента меню. Выводится в крайней левой или крайней правой позиции пункта меню.
|
|
8
8
|
*/
|
|
9
9
|
export const MenuItemAccessory = memo(({ Icon, disabled }) => {
|
|
10
|
-
const styles = useStyles();
|
|
11
10
|
const IconComponent = useMemo(() => (disabled ? IconLock : Icon), [Icon, disabled]);
|
|
12
11
|
return (<View style={styles.container}>
|
|
13
|
-
<SvgUniversal source={IconComponent} {
|
|
12
|
+
<SvgUniversal {...styles.icon} source={IconComponent} uniProps={({ theme }) => ({
|
|
13
|
+
color: theme.Menu.Item.menuitemIconColor,
|
|
14
|
+
})}/>
|
|
14
15
|
</View>);
|
|
15
16
|
});
|
|
16
|
-
const
|
|
17
|
+
const styles = StyleSheet.create(({ theme }) => ({
|
|
17
18
|
container: { justifyContent: 'center' },
|
|
18
19
|
icon: {
|
|
19
20
|
width: theme.Menu.Item.menuitemSubmenuIconFontSize,
|
|
20
21
|
height: theme.Menu.Item.menuitemSubmenuIconFontSize,
|
|
21
|
-
color: theme.Menu.Item.menuitemIconColor,
|
|
22
22
|
},
|
|
23
23
|
}));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useMemo, useState } from 'react';
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, } from 'react-native';
|
|
3
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
3
4
|
import { SvgUniversal } from '../../utils/SvgUniversal';
|
|
4
|
-
import { makeStyles } from '../../utils/makeStyles';
|
|
5
5
|
import { Badge } from '../Badge/Badge';
|
|
6
6
|
/**
|
|
7
7
|
* Иконка в составе элемента меню. Состоит из центрирующего враппера, иконки и опционального бейджа (точки)
|
|
@@ -10,7 +10,6 @@ import { Badge } from '../Badge/Badge';
|
|
|
10
10
|
* @param badgeSeverity - Цвет бейджа (undefined если бейдж не нужен)
|
|
11
11
|
*/
|
|
12
12
|
export const MenuItemIcon = ({ Icon, style, badgeSeverity, }) => {
|
|
13
|
-
const styles = useStyles();
|
|
14
13
|
const [badgePosition, setBadgePosition] = useState({ top: 0, right: 0 });
|
|
15
14
|
const onLayout = useCallback((event) => {
|
|
16
15
|
const { width, height } = event.nativeEvent.layout;
|
|
@@ -19,7 +18,7 @@ export const MenuItemIcon = ({ Icon, style, badgeSeverity, }) => {
|
|
|
19
18
|
const badgeStyle = useMemo(() => StyleSheet.flatten([
|
|
20
19
|
styles.badge,
|
|
21
20
|
{ top: badgePosition.top, right: badgePosition.right },
|
|
22
|
-
]), [badgePosition.right, badgePosition.top
|
|
21
|
+
]), [badgePosition.right, badgePosition.top]);
|
|
23
22
|
return (<View style={styles.container}>
|
|
24
23
|
<View>
|
|
25
24
|
<SvgUniversal source={Icon} {...style}/>
|
|
@@ -27,7 +26,7 @@ export const MenuItemIcon = ({ Icon, style, badgeSeverity, }) => {
|
|
|
27
26
|
</View>
|
|
28
27
|
</View>);
|
|
29
28
|
};
|
|
30
|
-
const
|
|
29
|
+
const styles = StyleSheet.create(() => ({
|
|
31
30
|
container: { justifyContent: 'center', position: 'relative' },
|
|
32
31
|
badge: { position: 'absolute' },
|
|
33
32
|
}));
|