react-native-ui-lib
Version:
<p align="center"> <img src="https://user-images.githubusercontent.com/1780255/105469025-56759000-5ca0-11eb-993d-3568c1fd54f4.png" height="250px" style="display:block"/> </p> <p align="center">UI Toolset & Components Library for React Native</p> <p a
101 lines (96 loc) • 3.19 kB
JavaScript
import _pt from "prop-types";
import React, { useContext, useEffect, useRef, useCallback, useState, useMemo } from 'react';
import { Animated, StyleSheet, Platform } from 'react-native';
import { ValidationMessagePosition } from "./types";
import { getColorByState } from "./Presenter";
import { Colors } from "../../style";
import { Constants } from "../../commons/new";
import View from "../../components/view";
import Text from "../../components/text";
import FieldContext from "./FieldContext";
const FLOATING_PLACEHOLDER_SCALE = 0.875;
const FloatingPlaceholder = ({
placeholder,
floatingPlaceholderColor = Colors.grey40,
floatingPlaceholderStyle,
floatOnFocus,
validationMessagePosition,
extraOffset = 0,
testID
}) => {
const context = useContext(FieldContext);
const [placeholderOffset, setPlaceholderOffset] = useState({
top: 0,
left: 0
});
const animation = useRef(new Animated.Value(Number(context.isFocused))).current;
const hidePlaceholder = !context.isValid && validationMessagePosition === ValidationMessagePosition.TOP;
const animatedStyle = useMemo(() => {
return {
transform: [{
scale: interpolateValue(animation, [1, FLOATING_PLACEHOLDER_SCALE])
}, {
translateX: interpolateValue(animation, [0, -placeholderOffset.left - extraOffset / FLOATING_PLACEHOLDER_SCALE])
}, {
translateY: interpolateValue(animation, [0, -placeholderOffset.top])
}]
};
}, [placeholderOffset, extraOffset]);
useEffect(() => {
const toValue = floatOnFocus ? context.isFocused || context.hasValue : context.hasValue;
Animated.timing(animation, {
toValue: Number(toValue),
duration: 200,
useNativeDriver: true
}).start();
}, [floatOnFocus, context.isFocused, context.hasValue]);
const onPlaceholderLayout = useCallback(event => {
const {
width,
height
} = event.nativeEvent.layout;
let translate = width / 2 - width * FLOATING_PLACEHOLDER_SCALE / 2;
translate = Constants.isRTL ? -translate : translate;
setPlaceholderOffset({
left: translate / FLOATING_PLACEHOLDER_SCALE,
top: height
});
}, []);
return <View absF style={hidePlaceholder && styles.hidden}>
<Text animated color={getColorByState(floatingPlaceholderColor, context)} style={[styles.placeholder, floatingPlaceholderStyle, animatedStyle]} onLayout={onPlaceholderLayout} testID={testID}>
{placeholder}
</Text>
</View>;
};
FloatingPlaceholder.propTypes = {
/**
* The placeholder for the field
*/
placeholder: _pt.string,
/**
* Should placeholder float on focus or when start typing
*/
floatOnFocus: _pt.bool,
extraOffset: _pt.number,
testID: _pt.string.isRequired
};
const styles = StyleSheet.create({
placeholder: { ...Platform.select({
android: {
textAlignVertical: 'center',
flex: 1
}
})
},
hidden: {
opacity: 0
}
});
function interpolateValue(animatedValue, outputRange) {
return animatedValue.interpolate({
inputRange: [0, 1],
outputRange
});
}
FloatingPlaceholder.displayName = 'Incubator.TextField';
export default FloatingPlaceholder;