react-native-material-textfield
Version:
136 lines (111 loc) • 3.03 kB
JavaScript
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
import { Animated } from 'react-native';
export default class Label extends PureComponent {
static defaultProps = {
numberOfLines: 1,
active: false,
focused: false,
errored: false,
restricted: false,
};
static propTypes = {
active: PropTypes.bool,
focused: PropTypes.bool,
errored: PropTypes.bool,
restricted: PropTypes.bool,
baseSize: PropTypes.number.isRequired,
fontSize: PropTypes.number.isRequired,
activeFontSize: PropTypes.number.isRequired,
basePadding: PropTypes.number.isRequired,
tintColor: PropTypes.string.isRequired,
baseColor: PropTypes.string.isRequired,
errorColor: PropTypes.string.isRequired,
animationDuration: PropTypes.number.isRequired,
style: Animated.Text.propTypes.style,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]),
};
constructor(props) {
super(props);
this.state = {
input: new Animated.Value(this.inputState()),
focus: new Animated.Value(this.focusState()),
};
}
componentWillReceiveProps(props) {
let { focus, input } = this.state;
let { active, focused, errored, animationDuration: duration } = this.props;
if (focused ^ props.focused || active ^ props.active) {
let toValue = this.inputState(props);
Animated
.timing(input, { toValue, duration })
.start();
}
if (focused ^ props.focused || errored ^ props.errored) {
let toValue = this.focusState(props);
Animated
.timing(focus, { toValue, duration })
.start();
}
}
inputState({ focused, active } = this.props) {
return active || focused? 1 : 0;
}
focusState({ focused, errored } = this.props) {
return errored? -1 : (focused? 1 : 0);
}
render() {
let { focus, input } = this.state;
let {
children,
restricted,
fontSize,
activeFontSize,
errorColor,
baseColor,
tintColor,
baseSize,
basePadding,
style,
errored,
active,
focused,
animationDuration,
...props
} = this.props;
let color = restricted?
errorColor:
focus.interpolate({
inputRange: [-1, 0, 1],
outputRange: [errorColor, baseColor, tintColor],
});
let top = input.interpolate({
inputRange: [0, 1],
outputRange: [
baseSize + fontSize * 0.25,
baseSize - basePadding - activeFontSize,
],
});
let textStyle = {
fontSize: input.interpolate({
inputRange: [0, 1],
outputRange: [fontSize, activeFontSize],
}),
color,
};
let containerStyle = {
position: 'absolute',
top,
};
return (
<Animated.View style={containerStyle}>
<Animated.Text style={[style, textStyle]} {...props}>
{children}
</Animated.Text>
</Animated.View>
);
}
}