react-native-material-textinput
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -1,33 +0,31 @@ | ||
import React, { Component } from 'react' | ||
import React from 'react' | ||
import { Text } from 'react-native' | ||
import PropTypes from 'prop-types' | ||
export default class extends Component { | ||
static propTypes = { | ||
error: PropTypes.string, | ||
errorPaddingTop: PropTypes.number, | ||
errorColor: PropTypes.string, | ||
errorFontSize: PropTypes.number | ||
} | ||
const ErrorHelper = ({ error, errorColor, errorPaddingTop, errorFontSize }) => { | ||
return ( | ||
<Text | ||
style={{ | ||
paddingTop: errorPaddingTop, | ||
color: errorColor, | ||
fontSize: errorFontSize | ||
}}> | ||
{error} | ||
</Text> | ||
) | ||
} | ||
static defaultProps = { | ||
errorPaddingTop: 8, | ||
errorColor: '#fc1f4a', | ||
errorFontSize: 12 | ||
} | ||
ErrorHelper.propTypes = { | ||
error: PropTypes.string, | ||
errorPaddingTop: PropTypes.number, | ||
errorColor: PropTypes.string, | ||
errorFontSize: PropTypes.number | ||
} | ||
render() { | ||
let { error, errorColor, errorPaddingTop, errorFontSize } = this.props | ||
ErrorHelper.defaultProps = { | ||
errorPaddingTop: 8, | ||
errorColor: '#fc1f4a', | ||
errorFontSize: 12 | ||
} | ||
return ( | ||
<Text | ||
style={{ | ||
paddingTop: errorPaddingTop, | ||
color: errorColor, | ||
fontSize: errorFontSize | ||
}}> | ||
{error} | ||
</Text> | ||
) | ||
} | ||
} | ||
export default ErrorHelper |
398
lib/Input.js
@@ -1,2 +0,2 @@ | ||
import React, { Component } from 'react' | ||
import React, { useState, useEffect } from 'react' | ||
import { View, TextInput, Platform } from 'react-native' | ||
@@ -9,213 +9,161 @@ import PropTypes from 'prop-types' | ||
export default class extends Component { | ||
static propTypes = { | ||
...TextInput.PropTypes, | ||
...ErrorHelper.PropTypes, | ||
onFocus: PropTypes.func, | ||
onBlur: PropTypes.func, | ||
onChangeText: PropTypes.func, | ||
onContentSizeChange: PropTypes.func, | ||
minHeight: PropTypes.number, | ||
height: PropTypes.number, | ||
maxHeight: PropTypes.number, | ||
marginTop: PropTypes.number, | ||
marginRight: PropTypes.number, | ||
marginBottom: PropTypes.number, | ||
marginLeft: PropTypes.number, | ||
paddingTop: PropTypes.number, | ||
paddingRight: PropTypes.number, | ||
paddingBottom: PropTypes.number, | ||
paddingLeft: PropTypes.number, | ||
color: PropTypes.string, | ||
activeColor: PropTypes.string, | ||
fontFamily: PropTypes.string, | ||
fontSize: PropTypes.number, | ||
fontWeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) | ||
} | ||
const Input = ({ | ||
minHeight, | ||
maxHeight, | ||
marginTop, | ||
marginRight, | ||
marginBottom, | ||
marginLeft, | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
color, | ||
activeColor, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
label, | ||
labelDuration, | ||
labelColor, | ||
labelActiveTop, | ||
labelActiveColor, | ||
labelActiveScale, | ||
placeholder, | ||
placeholderColor, | ||
underlineDuration, | ||
underlineHeight, | ||
underlineColor, | ||
underlineActiveColor, | ||
underlineActiveHeight, | ||
error, | ||
errorColor, | ||
errorPaddingTop, | ||
errorFontSize, | ||
...props | ||
}) => { | ||
const [value, setValue] = useState(null) | ||
const [focused, setFocused] = useState(false) | ||
const [height, setHeight] = useState(fontSize * 1.5) | ||
static defaultProps = { | ||
...ErrorHelper.defaultProps, | ||
onFocus: () => {}, | ||
onBlur: () => {}, | ||
onChangeText: () => {}, | ||
onContentSizeChange: () => {}, | ||
value: null, | ||
marginBottom: 8, | ||
paddingTop: 20, | ||
paddingRight: 0, | ||
paddingBottom: 8, | ||
paddingLeft: 0, | ||
color: 'black', | ||
fontSize: 15, | ||
fontWeight: 'normal' | ||
const getValue = props.value != null ? props.value : value | ||
const hasValue = getValue && getValue.length > 0 | ||
const labelProps = { | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
activeColor, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
label, | ||
labelDuration, | ||
labelColor, | ||
labelActiveTop, | ||
labelActiveColor, | ||
labelActiveScale, | ||
focused, | ||
hasValue, | ||
error, | ||
errorColor | ||
} | ||
constructor(props) { | ||
super(props) | ||
this.state = { | ||
value: null, | ||
focused: false, | ||
height: props.fontSize * 1.5 | ||
} | ||
const placeholderProps = { | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
placeholder, | ||
placeholderColor, | ||
focused, | ||
hasValue | ||
} | ||
const underlineProps = { | ||
activeColor, | ||
underlineDuration, | ||
underlineHeight, | ||
underlineColor, | ||
underlineActiveColor, | ||
underlineActiveHeight, | ||
focused, | ||
error, | ||
errorColor | ||
} | ||
const containerStyle = { | ||
marginTop, | ||
marginRight, | ||
marginBottom, | ||
marginLeft | ||
} | ||
let getHeight = height | ||
if (props.multiline && props.height) { | ||
// Disable autogrow if height prop | ||
getHeight = props.height | ||
} | ||
const inputStyle = { | ||
minHeight, | ||
maxHeight, | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
color, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
...Platform.select({ | ||
ios: { height: paddingTop + paddingBottom + (props.multiline ? getHeight : fontSize * 1.5) }, | ||
android: { | ||
height: props.multiline ? getHeight : fontSize * 1.5 + paddingTop + paddingBottom, | ||
textAlignVertical: 'top' | ||
} | ||
}) | ||
} | ||
const errorProps = { | ||
error, | ||
errorColor, | ||
errorPaddingTop, | ||
errorFontSize | ||
} | ||
render() { | ||
let { focused, height } = this.state | ||
let value = this.props.value != null ? this.props.value : this.state.value | ||
let hasValue = value && value.length > 0 | ||
let active = focused || hasValue | ||
let { | ||
minHeight, | ||
maxHeight, | ||
marginTop, | ||
marginRight, | ||
marginBottom, | ||
marginLeft, | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
color, | ||
activeColor, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
label, | ||
labelDuration, | ||
labelColor, | ||
labelActiveTop, | ||
labelActiveColor, | ||
labelActiveScale, | ||
placeholder, | ||
placeholderColor, | ||
underlineDuration, | ||
underlineHeight, | ||
underlineColor, | ||
underlineActiveColor, | ||
underlineActiveHeight, | ||
error, | ||
errorColor, | ||
errorPaddingTop, | ||
errorFontSize, | ||
...props | ||
} = this.props | ||
let labelProps = { | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
activeColor, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
label, | ||
labelDuration, | ||
labelColor, | ||
labelActiveTop, | ||
labelActiveColor, | ||
labelActiveScale, | ||
focused, | ||
hasValue, | ||
error, | ||
errorColor | ||
} | ||
let placeholderProps = { | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
placeholder, | ||
placeholderColor, | ||
focused, | ||
hasValue | ||
} | ||
let underlineProps = { | ||
activeColor, | ||
underlineDuration, | ||
underlineHeight, | ||
underlineColor, | ||
underlineActiveColor, | ||
underlineActiveHeight, | ||
focused, | ||
error, | ||
errorColor | ||
} | ||
let containerStyle = { | ||
marginTop, | ||
marginRight, | ||
marginBottom, | ||
marginLeft | ||
} | ||
if (props.multiline && props.height) { | ||
// Disable autogrow if height prop | ||
height = props.height | ||
} | ||
let inputStyle = { | ||
minHeight, | ||
maxHeight, | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
color, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
...Platform.select({ | ||
ios: { height: paddingTop + paddingBottom + (props.multiline ? height : fontSize * 1.5) }, | ||
android: { | ||
height: props.multiline ? height : fontSize * 1.5 + paddingTop + paddingBottom, | ||
textAlignVertical: 'top' | ||
} | ||
}) | ||
} | ||
let errorProps = { | ||
error, | ||
errorColor, | ||
errorPaddingTop, | ||
errorFontSize | ||
} | ||
return ( | ||
<View style={containerStyle}> | ||
<Label {...labelProps} /> | ||
{placeholder ? <Placeholder {...placeholderProps} /> : null} | ||
<TextInput | ||
{...props} | ||
style={inputStyle} | ||
underlineColorAndroid="transparent" | ||
onFocus={handleFocus} | ||
onBlur={handleBlur} | ||
onChangeText={handleChangeText} | ||
onContentSizeChange={handleContentSizeChange} | ||
value={getValue} | ||
/> | ||
<Underline {...underlineProps} /> | ||
{error ? <ErrorHelper {...errorProps} /> : null} | ||
</View> | ||
) | ||
return ( | ||
<View style={containerStyle}> | ||
<Label {...labelProps} /> | ||
{placeholder ? <Placeholder {...placeholderProps} /> : null} | ||
<TextInput | ||
{...props} | ||
style={inputStyle} | ||
underlineColorAndroid="transparent" | ||
onFocus={this._handleFocus} | ||
onBlur={this._handleBlur} | ||
onChangeText={this._handleChangeText} | ||
onContentSizeChange={this._handleContentSizeChange} | ||
value={value} | ||
/> | ||
<Underline {...underlineProps} /> | ||
{error ? <ErrorHelper {...errorProps} /> : null} | ||
</View> | ||
) | ||
} | ||
_handleFocus = (...args) => { | ||
let { onFocus } = this.props | ||
this.setState({ focused: true }) | ||
function handleFocus(...args) { | ||
const { onFocus } = props | ||
setFocused(true) | ||
onFocus(...args) | ||
} | ||
_handleBlur = (...args) => { | ||
let { onBlur } = this.props | ||
this.setState({ focused: false }) | ||
function handleBlur(...args) { | ||
const { onBlur } = props | ||
setFocused(false) | ||
onBlur(...args) | ||
} | ||
_handleChangeText = (...args) => { | ||
let { onChangeText, value } = this.props | ||
function handleChangeText(...args) { | ||
const { onChangeText, value } = props | ||
// Make support of uncontrolled component | ||
if (value == null) { | ||
this.setState({ value: args[0] }) | ||
setValue(args[0]) | ||
} | ||
@@ -226,9 +174,7 @@ | ||
_handleContentSizeChange = event => { | ||
let { onContentSizeChange, fontSize } = this.props | ||
let { height } = event.nativeEvent.contentSize | ||
function handleContentSizeChange(event) { | ||
const { onContentSizeChange } = props | ||
const { height } = event.nativeEvent.contentSize | ||
this.setState({ | ||
height: Math.max(fontSize * 1.5, Math.ceil(height)) | ||
}) | ||
setHeight(Math.max(fontSize * 1.5, Math.ceil(height))) | ||
@@ -238,1 +184,45 @@ onContentSizeChange(event) | ||
} | ||
Input.propTypes = { | ||
...TextInput.PropTypes, | ||
...ErrorHelper.PropTypes, | ||
onFocus: PropTypes.func, | ||
onBlur: PropTypes.func, | ||
onChangeText: PropTypes.func, | ||
onContentSizeChange: PropTypes.func, | ||
minHeight: PropTypes.number, | ||
height: PropTypes.number, | ||
maxHeight: PropTypes.number, | ||
marginTop: PropTypes.number, | ||
marginRight: PropTypes.number, | ||
marginBottom: PropTypes.number, | ||
marginLeft: PropTypes.number, | ||
paddingTop: PropTypes.number, | ||
paddingRight: PropTypes.number, | ||
paddingBottom: PropTypes.number, | ||
paddingLeft: PropTypes.number, | ||
color: PropTypes.string, | ||
activeColor: PropTypes.string, | ||
fontFamily: PropTypes.string, | ||
fontSize: PropTypes.number, | ||
fontWeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) | ||
} | ||
Input.defaultProps = { | ||
...ErrorHelper.defaultProps, | ||
onFocus: () => {}, | ||
onBlur: () => {}, | ||
onChangeText: () => {}, | ||
onContentSizeChange: () => {}, | ||
value: null, | ||
marginBottom: 8, | ||
paddingTop: 20, | ||
paddingRight: 0, | ||
paddingBottom: 8, | ||
paddingLeft: 0, | ||
color: 'black', | ||
fontSize: 15, | ||
fontWeight: 'normal' | ||
} | ||
export default Input |
164
lib/Label.js
@@ -1,97 +0,85 @@ | ||
import React, { Component } from 'react' | ||
import React, { useState, useEffect } from 'react' | ||
import { Text, Animated } from 'react-native' | ||
import PropTypes from 'prop-types' | ||
export default class extends Component { | ||
static propTypes = { | ||
label: PropTypes.string, | ||
labelDuration: PropTypes.number, | ||
labelColor: PropTypes.string, | ||
labelActiveColor: PropTypes.string, | ||
labelActiveScale: PropTypes.number, | ||
labelActiveTop: PropTypes.number | ||
} | ||
const Label = ({ | ||
hasValue, | ||
focused, | ||
labelActiveScale, | ||
labelActiveTop, | ||
labelDuration, | ||
paddingTop, | ||
paddingRight, | ||
paddingLeft, | ||
activeColor, | ||
fontSize, | ||
fontFamily, | ||
fontWeight, | ||
label, | ||
labelColor, | ||
labelActiveColor, | ||
error, | ||
errorColor | ||
}) => { | ||
const [animatedScale] = useState(new Animated.Value(hasValue || focused ? labelActiveScale : 1)) | ||
const [animatedTranslate] = useState(new Animated.Value(hasValue || focused ? labelActiveTop : 0)) | ||
static defaultProps = { | ||
labelDuration: 200, | ||
labelColor: 'gray', | ||
labelActiveColor: '#3f51b5', | ||
labelActiveScale: 0.8, | ||
labelActiveTop: -18 | ||
} | ||
useEffect(() => { | ||
Animated.timing(animatedScale, { | ||
toValue: hasValue || focused ? labelActiveScale : 1, | ||
duration: labelDuration, | ||
useNativeDriver: true | ||
}).start() | ||
constructor(props) { | ||
super(props) | ||
Animated.timing(animatedTranslate, { | ||
toValue: hasValue || focused ? labelActiveTop : 0, | ||
duration: labelDuration, | ||
useNativeDriver: true | ||
}).start() | ||
}, [hasValue, focused]) | ||
let { hasValue, focused, labelActiveScale, labelActiveTop } = props | ||
return ( | ||
<Animated.View | ||
style={{ | ||
position: 'absolute', | ||
width: '200%', | ||
marginLeft: '-100%', | ||
top: paddingTop, | ||
transform: [{ translateY: animatedTranslate }, { scale: animatedScale }] | ||
}} | ||
numberOfLines={1}> | ||
<Text | ||
style={{ | ||
left: '50%', | ||
top: 0, | ||
paddingRight, | ||
paddingLeft, | ||
color: error ? errorColor : focused ? activeColor || labelActiveColor : labelColor, | ||
fontFamily, | ||
fontSize, | ||
fontWeight | ||
}}> | ||
{label} | ||
</Text> | ||
</Animated.View> | ||
) | ||
} | ||
this.state = { | ||
animatedScale: new Animated.Value(hasValue || focused ? labelActiveScale : 1), | ||
animatedTranslate: new Animated.Value(hasValue || focused ? labelActiveTop : 0) | ||
} | ||
} | ||
Label.propTypes = { | ||
label: PropTypes.string, | ||
labelDuration: PropTypes.number, | ||
labelColor: PropTypes.string, | ||
labelActiveColor: PropTypes.string, | ||
labelActiveScale: PropTypes.number, | ||
labelActiveTop: PropTypes.number | ||
} | ||
componentWillReceiveProps = nextProps => { | ||
let { animatedScale, animatedTranslate } = this.state | ||
let { labelDuration, labelActiveScale, labelActiveTop, hasValue, focused } = nextProps | ||
Label.defaultProps = { | ||
labelDuration: 200, | ||
labelColor: 'gray', | ||
labelActiveColor: '#3f51b5', | ||
labelActiveScale: 0.8, | ||
labelActiveTop: -18 | ||
} | ||
if (this.props.hasValue !== hasValue || this.props.focused !== focused) { | ||
Animated.timing(animatedScale, { | ||
toValue: hasValue || focused ? labelActiveScale : 1, | ||
duration: labelDuration, | ||
useNativeDriver: true | ||
}).start() | ||
Animated.timing(animatedTranslate, { | ||
toValue: hasValue || focused ? labelActiveTop : 0, | ||
duration: labelDuration, | ||
useNativeDriver: true | ||
}).start() | ||
} | ||
} | ||
render() { | ||
let { | ||
focused, | ||
paddingTop, | ||
paddingRight, | ||
paddingLeft, | ||
activeColor, | ||
fontSize, | ||
fontFamily, | ||
fontWeight, | ||
label, | ||
labelColor, | ||
labelActiveColor, | ||
error, | ||
errorColor | ||
} = this.props | ||
let { animatedScale, animatedTranslate } = this.state | ||
return ( | ||
<Animated.View | ||
style={{ | ||
position: 'absolute', | ||
width: '200%', | ||
marginLeft: '-100%', | ||
top: paddingTop, | ||
transform: [{ translateY: animatedTranslate }, { scale: animatedScale }] | ||
}} | ||
numberOfLines={1}> | ||
<Text | ||
style={{ | ||
left: '50%', | ||
top: 0, | ||
paddingRight, | ||
paddingLeft, | ||
color: error ? errorColor : focused ? activeColor || labelActiveColor : labelColor, | ||
fontFamily, | ||
fontSize, | ||
fontWeight | ||
}}> | ||
{label} | ||
</Text> | ||
</Animated.View> | ||
) | ||
} | ||
} | ||
export default Label |
@@ -1,52 +0,50 @@ | ||
import React, { Component } from 'react' | ||
import React from 'react' | ||
import { Text } from 'react-native' | ||
import PropTypes from 'prop-types' | ||
export default class extends Component { | ||
static propTypes = { | ||
placeholder: PropTypes.string, | ||
placeholderColor: PropTypes.string | ||
} | ||
const Placeholder = ({ | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
placeholder, | ||
placeholderColor, | ||
hasValue, | ||
focused | ||
}) => { | ||
return ( | ||
<Text | ||
style={{ | ||
position: 'absolute', | ||
top: 0, | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
color: placeholderColor, | ||
backgroundColor: 'transparent', | ||
opacity: focused && !hasValue ? 1 : 0, | ||
fontFamily, | ||
fontSize, | ||
fontWeight | ||
}} | ||
pointerEvents="none" | ||
numberOfLines={1}> | ||
{placeholder} | ||
</Text> | ||
) | ||
} | ||
static defaultProps = { | ||
placeholderColor: 'gray' | ||
} | ||
Placeholder.propTypes = { | ||
placeholder: PropTypes.string, | ||
placeholderColor: PropTypes.string | ||
} | ||
render() { | ||
let { | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
fontFamily, | ||
fontSize, | ||
fontWeight, | ||
placeholder, | ||
placeholderColor, | ||
hasValue, | ||
focused | ||
} = this.props | ||
Placeholder.defaultProps = { | ||
placeholderColor: 'gray' | ||
} | ||
return ( | ||
<Text | ||
style={{ | ||
position: 'absolute', | ||
top: 0, | ||
paddingTop, | ||
paddingRight, | ||
paddingBottom, | ||
paddingLeft, | ||
color: placeholderColor, | ||
backgroundColor: 'transparent', | ||
opacity: focused && !hasValue ? 1 : 0, | ||
fontFamily, | ||
fontSize, | ||
fontWeight | ||
}} | ||
pointerEvents="none" | ||
numberOfLines={1}> | ||
{placeholder} | ||
</Text> | ||
) | ||
} | ||
} | ||
export default Placeholder |
@@ -1,101 +0,92 @@ | ||
import React, { Component } from 'react' | ||
import React, { useState, useEffect } from 'react' | ||
import { View, Animated } from 'react-native' | ||
import PropTypes from 'prop-types' | ||
export default class extends Component { | ||
static propTypes = { | ||
underlineDuration: PropTypes.number, | ||
underlineHeight: PropTypes.number, | ||
underlineColor: PropTypes.string, | ||
underlineActiveColor: PropTypes.string, | ||
underlineActiveHeight: PropTypes.number | ||
} | ||
const Underline = ({ | ||
activeColor, | ||
underlineHeight, | ||
underlineColor, | ||
underlineDuration, | ||
underlineActiveColor, | ||
underlineActiveHeight, | ||
error, | ||
errorColor, | ||
focused | ||
}) => { | ||
const [animatedScaleX] = useState(new Animated.Value(error ? 1 : 0.01)) | ||
const [animatedOpacity] = useState(new Animated.Value(error ? 1 : 0)) | ||
static defaultProps = { | ||
underlineDuration: 200, | ||
underlineHeight: 1, | ||
underlineColor: 'gray', | ||
underlineActiveColor: '#3f51b5', | ||
underlineActiveHeight: 2 | ||
} | ||
useEffect(() => { | ||
const isActive = focused || error | ||
let sequence = [] | ||
state = { | ||
animatedScaleX: new Animated.Value(this.props.error ? 1 : 0.01), | ||
animatedOpacity: new Animated.Value(this.props.error ? 1 : 0) | ||
} | ||
if (isActive) { | ||
sequence.push( | ||
Animated.timing(animatedOpacity, { | ||
toValue: 1, | ||
duration: 0, | ||
useNativeDriver: true | ||
}) | ||
) | ||
} | ||
componentWillReceiveProps = nextProps => { | ||
let { animatedScaleX, animatedOpacity } = this.state | ||
let { error, focused, underlineDuration } = nextProps | ||
sequence.push( | ||
Animated.timing(animatedScaleX, { | ||
toValue: isActive ? 1 : 0.01, | ||
duration: underlineDuration, | ||
useNativeDriver: true | ||
}) | ||
) | ||
if (this.props.focused !== focused || this.props.error !== error) { | ||
let isActive = focused || error | ||
let sequence = [] | ||
if (isActive) { | ||
sequence.push( | ||
Animated.timing(animatedOpacity, { | ||
toValue: 1, | ||
duration: 0, | ||
useNativeDriver: true | ||
}) | ||
) | ||
} | ||
if (!isActive) { | ||
sequence.push( | ||
Animated.timing(animatedScaleX, { | ||
toValue: isActive ? 1 : 0.01, | ||
duration: underlineDuration, | ||
Animated.timing(animatedOpacity, { | ||
toValue: 0, | ||
duration: 0, | ||
useNativeDriver: true | ||
}) | ||
) | ||
if (!isActive) { | ||
sequence.push( | ||
Animated.timing(animatedOpacity, { | ||
toValue: 0, | ||
duration: 0, | ||
useNativeDriver: true | ||
}) | ||
) | ||
} | ||
if (isActive) { | ||
Animated.parallel(sequence).start() | ||
} else { | ||
Animated.sequence(sequence).start() | ||
} | ||
} | ||
} | ||
if (isActive) { | ||
Animated.parallel(sequence).start() | ||
} else { | ||
Animated.sequence(sequence).start() | ||
} | ||
}, [focused, error]) | ||
render() { | ||
let { | ||
activeColor, | ||
underlineHeight, | ||
underlineColor, | ||
underlineActiveColor, | ||
underlineActiveHeight, | ||
error, | ||
errorColor, | ||
focused | ||
} = this.props | ||
let { animatedScaleX, animatedOpacity } = this.state | ||
return ( | ||
<View | ||
return ( | ||
<View | ||
style={{ | ||
borderColor: underlineColor, | ||
borderTopWidth: underlineHeight | ||
}}> | ||
<Animated.View | ||
style={{ | ||
borderColor: underlineColor, | ||
borderTopWidth: underlineHeight | ||
}}> | ||
<Animated.View | ||
style={{ | ||
marginTop: -underlineHeight, | ||
transform: [{ scaleX: animatedScaleX }], | ||
opacity: animatedOpacity, | ||
borderColor: (error && errorColor) || activeColor || underlineActiveColor, | ||
borderTopWidth: underlineActiveHeight | ||
}} | ||
/> | ||
</View> | ||
) | ||
} | ||
marginTop: -underlineHeight, | ||
transform: [{ scaleX: animatedScaleX }], | ||
opacity: animatedOpacity, | ||
borderColor: (error && errorColor) || activeColor || underlineActiveColor, | ||
borderTopWidth: underlineActiveHeight | ||
}} | ||
/> | ||
</View> | ||
) | ||
} | ||
Underline.propTypes = { | ||
underlineDuration: PropTypes.number, | ||
underlineHeight: PropTypes.number, | ||
underlineColor: PropTypes.string, | ||
underlineActiveColor: PropTypes.string, | ||
underlineActiveHeight: PropTypes.number | ||
} | ||
Underline.defaultProps = { | ||
underlineDuration: 200, | ||
underlineHeight: 1, | ||
underlineColor: 'gray', | ||
underlineActiveColor: '#3f51b5', | ||
underlineActiveHeight: 2 | ||
} | ||
export default Underline |
{ | ||
"name": "react-native-material-textinput", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "Textual input component for React Native", | ||
@@ -32,4 +32,7 @@ "license": "MIT", | ||
"dependencies": { | ||
"prop-types": "^15.5.10" | ||
"prop-types": "^15.7.2" | ||
}, | ||
"peerDependencies": { | ||
"react": ">=16.8" | ||
} | ||
} |
135
README.md
# Material Design Text Input | ||
[![npm version][npm-img]][npm-url] | ||
[![npm downloads][npm-dls]][npm-url] | ||
[![github issues][issues-img]][issues-url] | ||
Textual input component for React Native (iOS & Android). | ||
@@ -8,22 +12,14 @@ | ||
```javascript | ||
import React, { Component } from 'react' | ||
import React, { useState } from 'react' | ||
import TextInput from 'react-native-material-textinput' | ||
export default class Example extends Component { | ||
state = { | ||
name: '' | ||
} | ||
const Example = () => { | ||
const [name, setName] = useState('') | ||
render() { | ||
let { name } = this.state | ||
const handleInputChange = (value) => setName(value) | ||
return ( | ||
<TextInput | ||
label="Name" | ||
value={name} | ||
onChangeText={name => this.setState({ name })} | ||
/> | ||
) | ||
} | ||
return <TextInput label="Name" value={name} onChangeText={handleInputChange} /> | ||
} | ||
export default Example | ||
``` | ||
@@ -35,73 +31,64 @@ | ||
name | type | default | ||
:-------------------- |:------------------ |:------------------ | ||
label | String | | ||
labelDuration | Number | `200` | ||
labelColor | String | `gray` | ||
labelActiveTop | Number | `-18` | ||
labelActiveColor | String | `#3f51b5` | ||
labelActiveScale | Number | `0.8` | ||
| name | type | default | | ||
| :--------------- | :----- | :-------- | | ||
| label | String | | ||
| labelDuration | Number | `200` | | ||
| labelColor | String | `gray` | | ||
| labelActiveTop | Number | `-18` | | ||
| labelActiveColor | String | `#3f51b5` | | ||
| labelActiveScale | Number | `0.8` | | ||
### Placeholder | ||
Name | Type | Default | ||
:-------------------- |:------------------ |:---------- | ||
placeholder | String | | ||
placeholderColor | String | `gray` | ||
| Name | Type | Default | | ||
| :--------------- | :----- | :------ | | ||
| placeholder | String | | ||
| placeholderColor | String | `gray` | | ||
### Input | ||
Name | Type | Default | ||
:-------------------- |:------------------ |:---------- | ||
minHeight | Number | | ||
height | Number | | ||
maxHeight | Number | | ||
marginTop | Number | | ||
marginRight | Number | | ||
marginBottom | Number | `8` | ||
marginLeft | Number | | ||
paddingTop | Number | `20` | ||
paddingRight | Number | `0` | ||
paddingBottom | Number | `8` | ||
paddingLeft | Number | `0` | ||
color | String | `black` | ||
activeColor | String | | ||
fontFamily | String | | ||
fontSize | Number | `15` | ||
fontWeight | String or Number | `normal` | ||
onFocus | Function | ||
onBlur | Function | ||
onChangeText | Function | ||
onContentSizeChange | Function | ||
| Name | Type | Default | | ||
| :------------------ | :--------------- | :------- | | ||
| minHeight | Number | | ||
| height | Number | | ||
| maxHeight | Number | | ||
| marginTop | Number | | ||
| marginRight | Number | | ||
| marginBottom | Number | `8` | | ||
| marginLeft | Number | | ||
| paddingTop | Number | `20` | | ||
| paddingRight | Number | `0` | | ||
| paddingBottom | Number | `8` | | ||
| paddingLeft | Number | `0` | | ||
| color | String | `black` | | ||
| activeColor | String | | ||
| fontFamily | String | | ||
| fontSize | Number | `15` | | ||
| fontWeight | String or Number | `normal` | | ||
| onFocus | Function | | ||
| onBlur | Function | | ||
| onChangeText | Function | | ||
| onContentSizeChange | Function | | ||
### Underline | ||
Name | Type | Default | ||
:-------------------- |:------------------ |:---------- | ||
underlineDuration | Number | `200` | ||
underlineHeight | Number | `1` | ||
underlineColor | String | `gray` | ||
underlineActiveColor | String | `#3f51b5` | ||
underlineActiveHeight | Number | `2` | ||
| Name | Type | Default | | ||
| :-------------------- | :----- | :-------- | | ||
| underlineDuration | Number | `200` | | ||
| underlineHeight | Number | `1` | | ||
| underlineColor | String | `gray` | | ||
| underlineActiveColor | String | `#3f51b5` | | ||
| underlineActiveHeight | Number | `2` | | ||
### ErrorHelper | ||
Name | Type | Default | ||
:-------------------- |:------------------ |:---------- | ||
error | String | | ||
errorPaddingTop | Number | `8` | ||
errorColor | String | `#fc1f4a` | ||
errorFontSize | Number | `12` | ||
| Name | Type | Default | | ||
| :-------------- | :----- | :-------- | | ||
| error | String | | ||
| errorPaddingTop | Number | `8` | | ||
| errorColor | String | `#fc1f4a` | | ||
| errorFontSize | Number | `12` | | ||
Other [TextInput](https://facebook.github.io/react-native/docs/textinput.html#props) properties will also work | ||
## Example | ||
```bash | ||
git clone https://github.com/perushevandkhmelev-agency/react-native-material-textinput | ||
cd react-native-material-textinput/example | ||
yarn # or npm install | ||
yarn start # or npm start | ||
``` | ||
## License | ||
@@ -112,1 +99,7 @@ | ||
See [LICENSE](LICENSE) | ||
[npm-url]: https://www.npmjs.com/package/react-native-material-textinput | ||
[npm-img]: https://img.shields.io/npm/v/react-native-material-textinput.svg?style=flat | ||
[npm-dls]: https://img.shields.io/npm/dt/react-native-material-textinput.svg?style=flat | ||
[issues-url]: https://github.com/perushevandkhmelev-agency/react-native-material-textinput/issues | ||
[issues-img]: https://img.shields.io/github/issues/perushevandkhmelev-agency/react-native-material-textinput.svg?style=flat |
16902
2
9
445
103
+ Addedreact@19.0.0(transitive)
Updatedprop-types@^15.7.2