@tra-tech/react-native-kitra
Version:
UI kit for React Native
227 lines (226 loc) • 9.52 kB
JavaScript
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import React, { useEffect, useRef, useState } from 'react';
import { TextInput as RNTextInput, View, TouchableOpacity, StyleSheet, Text } from 'react-native';
import Animated, { interpolate, interpolateColor, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
import { opacity } from '../../utilities';
import { applyDefaults } from '../../core/KitraProvider';
const AnimatedTextInput = Animated.createAnimatedComponent(RNTextInput);
const TextInput = _ref => {
let {
theme,
typography,
inputStyle,
editable = true,
size = 'medium',
helperText = '',
variant = 'filled',
labelContainerStyle,
containerStyle,
count = false,
onChangeText,
label,
inputContainerStyle,
labelStyle,
helperTextStyle,
error = false,
errorMessage,
left,
right,
labelColor = {
focus: theme === null || theme === void 0 ? void 0 : theme.primary,
default: theme === null || theme === void 0 ? void 0 : theme.primary
},
onFocus,
onEndEditing,
...props
} = _ref;
const inputRef = useRef(null);
const [counts, setCounts] = useState(0);
const textInputOffset = useSharedValue(props.defaultValue || props.placeholder || props.value ? 0 : 1);
const fontStyles = {
large: typography === null || typography === void 0 ? void 0 : typography.body.regular,
medium: typography === null || typography === void 0 ? void 0 : typography.body.sregular,
small: typography === null || typography === void 0 ? void 0 : typography.body.xsregular
};
const sizeStyles = {
large: {
padding: 15,
height: 51
},
medium: {
padding: 12,
height: 42
},
small: {
padding: 10,
height: 36
}
};
const labelStyles = {
large: {
focused: typography === null || typography === void 0 ? void 0 : typography.body.regular,
default: typography === null || typography === void 0 ? void 0 : typography.body.sregular
},
medium: {
focused: typography === null || typography === void 0 ? void 0 : typography.body.sregular,
default: typography === null || typography === void 0 ? void 0 : typography.body.xsregular
},
small: {
focused: typography === null || typography === void 0 ? void 0 : typography.body.xsregular,
default: typography === null || typography === void 0 ? void 0 : typography.body.xxsregular
}
};
// label'ın konum ve fontsize animasyonu
const labelPositionAnimation = useAnimatedStyle(() => {
const topInterpolate = interpolate(textInputOffset.value, [0, 1], [variant === 'filled' ? 2 : -labelStyles[size].focused.lineHeight + labelStyles[size].focused.lineHeight / 2, sizeStyles[size].padding]);
return {
top: topInterpolate
};
});
const borderAnimation = useAnimatedStyle(() => {
const topInterpolate = interpolateColor(textInputOffset.value, [0, 1], [(theme === null || theme === void 0 ? void 0 : theme.primary) || '#000000', (theme === null || theme === void 0 ? void 0 : theme.grey) || '#FFFFFF']);
return {
borderColor: topInterpolate
};
});
const labelFontAnimation = useAnimatedStyle(() => {
const fontSize = interpolate(textInputOffset.value, [0, 1], [labelStyles[size].default.fontSize, labelStyles[size].focused.fontSize]);
const lineHeight = interpolate(textInputOffset.value, [0, 1], [labelStyles[size].default.lineHeight, labelStyles[size].focused.lineHeight]);
const color = interpolateColor(textInputOffset.value, [0, 1],
// @ts-ignore
[error ? theme === null || theme === void 0 ? void 0 : theme.error : labelColor.focus || '#000000', error ? theme === null || theme === void 0 ? void 0 : theme.error : labelColor.default || '#FFFFFF']);
return {
fontSize,
lineHeight,
color
};
});
useEffect(() => {
var _props$defaultValue2;
if (props.value) {
var _props$value, _props$value2, _props$value3, _props$defaultValue;
setCounts((_props$value = props.value) !== null && _props$value !== void 0 && _props$value.length ? (_props$value2 = props.value) === null || _props$value2 === void 0 ? void 0 : _props$value2.length : 0);
textInputOffset.value = (_props$value3 = props.value) !== null && _props$value3 !== void 0 && _props$value3.length || (_props$defaultValue = props.defaultValue) !== null && _props$defaultValue !== void 0 && _props$defaultValue.length ? withTiming(0) : withTiming(1);
} else if (!((_props$defaultValue2 = props.defaultValue) !== null && _props$defaultValue2 !== void 0 && _props$defaultValue2.length)) {
textInputOffset.value = withTiming(1);
}
}, [props.value]);
useEffect(() => {
setCounts(props.defaultValue ? props.defaultValue.length : 0);
}, []);
const onFocusInput = () => {
textInputOffset.value = withTiming(0);
};
const onEndEditingInput = () => {
textInputOffset.value = counts === 0 ? withTiming(1) : withTiming(0);
};
return /*#__PURE__*/React.createElement(View, {
style: [{
flexGrow: 1,
maxHeight: sizeStyles[size].height
}, containerStyle]
}, /*#__PURE__*/React.createElement(Animated.View, {
style: [{
opacity: editable ? 1 : 0.5,
borderRadius: 5,
borderWidth: 1,
height: sizeStyles[size].height,
backgroundColor: theme === null || theme === void 0 ? void 0 : theme.white
},
// @ts-ignore
borderAnimation, inputContainerStyle, error && {
backgroundColor: opacity(theme === null || theme === void 0 ? void 0 : theme.error, 15)
}]
}, /*#__PURE__*/React.createElement(View, {
style: {
flex: 1,
flexDirection: 'row',
height: sizeStyles[size].height
}
}, /*#__PURE__*/React.createElement(View, {
style: {
alignSelf: 'center',
marginLeft: sizeStyles[size].padding,
marginRight: 5
}
}, left && left), /*#__PURE__*/React.createElement(View, {
style: {
flex: 1,
flexDirection: 'row'
}
}, /*#__PURE__*/React.createElement(AnimatedTextInput, _extends({
ref: inputRef,
editable: editable,
style: [{
marginTop: fontStyles[size].lineHeight / 2,
fontSize: fontStyles[size].fontSize,
fontFamily: labelStyles[size].default.fontFamily,
lineHeight: fontStyles[size].lineHeight,
flexDirection: 'row',
flex: 1
}, inputStyle],
onChangeText: event => {
setCounts((event === null || event === void 0 ? void 0 : event.length) || 0);
onChangeText && onChangeText(event);
},
onFocus: x => {
onFocusInput();
onFocus === null || onFocus === void 0 ? void 0 : onFocus(x);
},
onEndEditing: x => {
onEndEditingInput();
onEndEditing === null || onEndEditing === void 0 ? void 0 : onEndEditing(x);
}
}, props)), label ? /*#__PURE__*/React.createElement(Animated.View, {
style: [{
position: 'absolute',
paddingHorizontal: 4,
backgroundColor: theme === null || theme === void 0 ? void 0 : theme.white
}, labelContainerStyle, error && {
backgroundColor: opacity((theme === null || theme === void 0 ? void 0 : theme.error) || 'transparent', 0)
}, labelPositionAnimation]
}, /*#__PURE__*/React.createElement(TouchableOpacity, {
onPress: () => {
var _inputRef$current;
return (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
},
activeOpacity: 0.9
}, /*#__PURE__*/React.createElement(Animated.Text, {
style: [{
color: theme === null || theme === void 0 ? void 0 : theme.primary,
fontFamily: labelStyles[size].default.fontFamily
}, labelStyle, labelFontAnimation]
}, label))) : null), /*#__PURE__*/React.createElement(View, {
style: {
alignSelf: 'center',
marginRight: sizeStyles[size].padding,
marginLeft: 5
}
}, right && right))), /*#__PURE__*/React.createElement(View, {
style: [styles.helperContainer, {
flexDirection: 'row',
display: error || !!helperText || count ? 'flex' : 'none',
alignSelf: 'stretch'
}]
}, /*#__PURE__*/React.createElement(Text, {
style: [labelStyles[size].default, helperTextStyle, {
color: error ? theme === null || theme === void 0 ? void 0 : theme.error : (helperTextStyle === null || helperTextStyle === void 0 ? void 0 : helperTextStyle.color) || (theme === null || theme === void 0 ? void 0 : theme.grey)
}]
}, error ? `${errorMessage || ''}` : `${helperText}`), count ? /*#__PURE__*/React.createElement(Text, {
style: [labelStyles[size].default, helperTextStyle, {
color: error ? theme === null || theme === void 0 ? void 0 : theme.error : (helperTextStyle === null || helperTextStyle === void 0 ? void 0 : helperTextStyle.color) || (theme === null || theme === void 0 ? void 0 : theme.grey)
}]
}, `${counts}/${props.maxLength}`) : null));
};
const styles = StyleSheet.create({
inputContainer: {
alignItems: 'center'
},
helperContainer: {
flexDirection: 'row',
paddingHorizontal: 5,
justifyContent: 'space-between'
}
});
export default applyDefaults(TextInput);
//# sourceMappingURL=TextInput.js.map