import { TextInput, Platform, StyleSheet } from 'react-native'; import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState, } from 'react'; import { interpolate, useAnimatedStyle, useSharedValue, withTiming, } from 'react-native-reanimated'; import { fonts, colors } from '../../theme/theme'; import { Box, ReanimatedBox } from '../Box'; import { Text } from '../Text'; import type { TextAreaProps, TextAreaRef } from './interfaces'; /** * @label TextArea label * @input All props of TextInput component and "defaultLines" prop to show the number of lines in the TextArea * @props All props of Box component **/ export const TextArea = forwardRef( ({ label, input, ...props }, ref) => { const overInput = useSharedValue(0); const [value, setValue] = useState(input?.defaultValue); useImperativeHandle(ref, () => ({ setImperativeValue: setValue })); const defaultLines = input?.defaultLines ?? 3; const spacingPlatform = Platform.OS === 'ios' ? 32 : 24; const minHeight = 16 * defaultLines + 8; const marginTop = Platform.OS === 'ios' ? -4 : 12; const Animate = useCallback( (focus?: boolean) => { if (value) overInput.value = 1; else overInput.value = focus ? 1 : 0; }, [overInput, value] ); const animatedBoxStyles = useAnimatedStyle(() => { const scaleInterpolation = interpolate(overInput.value, [0, 1], [1, 0.8]); const translateYInterpolation = interpolate( overInput.value, [0, 1], [6, -2] ); const translateXInterpolation = interpolate( overInput.value, [0, 1], [4, -12] ); return { transform: [ { scale: withTiming(scaleInterpolation, { duration: 300 }) }, { translateY: withTiming(translateYInterpolation, { duration: 300 }), }, { translateX: withTiming(translateXInterpolation, { duration: 300 }), }, ], }; }); useEffect(() => Animate(), [Animate, value]); return ( {label} { Animate(true); input?.onFocus?.(e); }} onBlur={(e) => { Animate(); input?.onBlur?.(e); }} {...input} onChangeText={(val) => { setValue(val); input?.onChangeText?.(val); }} value={value} /> ); } ); const styles = StyleSheet.create({ textInput: { flex: 1, borderRadius: 4, padding: 0, fontSize: 16, textAlignVertical: 'top', fontFamily: fonts.caustenRoundRegular, lineHeight: 20, color: colors.black, }, });