2021-05-09 21:59:03 +02:00
|
|
|
import { StyleConstants } from '@utils/styles/constants'
|
|
|
|
import layoutAnimation from '@utils/styles/layoutAnimation'
|
|
|
|
import { useTheme } from '@utils/styles/ThemeManager'
|
|
|
|
import React, {
|
|
|
|
Dispatch,
|
|
|
|
SetStateAction,
|
|
|
|
useEffect,
|
|
|
|
useRef,
|
|
|
|
useState
|
|
|
|
} from 'react'
|
2022-05-07 00:52:32 +02:00
|
|
|
import { Platform, TextInput, TextInputProps, View } from 'react-native'
|
2021-05-09 21:59:03 +02:00
|
|
|
import Animated, { useAnimatedStyle, withTiming } from 'react-native-reanimated'
|
2021-05-12 15:40:55 +02:00
|
|
|
import { ComponentEmojis, EmojisButton, EmojisList } from './Emojis'
|
|
|
|
import EmojisContext from './Emojis/helpers/EmojisContext'
|
2022-05-07 00:52:32 +02:00
|
|
|
import CustomText from './Text'
|
2021-05-09 21:59:03 +02:00
|
|
|
|
|
|
|
export interface Props {
|
|
|
|
autoFocus?: boolean
|
|
|
|
|
|
|
|
title?: string
|
|
|
|
|
|
|
|
multiline?: boolean
|
|
|
|
|
|
|
|
emoji?: boolean
|
|
|
|
|
|
|
|
value?: string
|
|
|
|
setValue:
|
|
|
|
| Dispatch<SetStateAction<string | undefined>>
|
|
|
|
| Dispatch<SetStateAction<string>>
|
2021-05-10 23:41:48 +02:00
|
|
|
|
|
|
|
options?: Omit<
|
|
|
|
TextInputProps,
|
|
|
|
| 'autoFocus'
|
|
|
|
| 'onFocus'
|
|
|
|
| 'onBlur'
|
|
|
|
| 'style'
|
|
|
|
| 'onChangeText'
|
|
|
|
| 'onSelectionChange'
|
|
|
|
| 'keyboardAppearance'
|
|
|
|
| 'textAlignVertical'
|
|
|
|
>
|
2021-05-09 21:59:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const Input: React.FC<Props> = ({
|
|
|
|
autoFocus = true,
|
|
|
|
title,
|
|
|
|
multiline = false,
|
|
|
|
emoji = false,
|
|
|
|
value,
|
2021-05-10 23:41:48 +02:00
|
|
|
setValue,
|
|
|
|
options
|
2021-05-09 21:59:03 +02:00
|
|
|
}) => {
|
2022-02-12 14:51:01 +01:00
|
|
|
const { colors, mode } = useTheme()
|
2021-05-09 21:59:03 +02:00
|
|
|
|
|
|
|
const animateTitle = useAnimatedStyle(() => {
|
|
|
|
if (value) {
|
|
|
|
return {
|
|
|
|
fontSize: withTiming(StyleConstants.Font.Size.S),
|
|
|
|
paddingHorizontal: withTiming(StyleConstants.Spacing.XS),
|
|
|
|
left: withTiming(StyleConstants.Spacing.S),
|
|
|
|
top: withTiming(-(StyleConstants.Font.Size.S / 2) - 2),
|
2022-02-12 14:51:01 +01:00
|
|
|
backgroundColor: withTiming(colors.backgroundDefault)
|
2021-05-09 21:59:03 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
fontSize: withTiming(StyleConstants.Font.Size.M),
|
|
|
|
paddingHorizontal: withTiming(0),
|
|
|
|
left: withTiming(StyleConstants.Spacing.S),
|
|
|
|
top: withTiming(StyleConstants.Spacing.S + 1),
|
2022-02-12 14:51:01 +01:00
|
|
|
backgroundColor: withTiming(colors.backgroundDefaultTransparent)
|
2021-05-09 21:59:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}, [mode, value])
|
|
|
|
|
|
|
|
const selectionRange = useRef<{ start: number; end: number }>(
|
|
|
|
value
|
|
|
|
? {
|
|
|
|
start: value.length,
|
|
|
|
end: value.length
|
|
|
|
}
|
|
|
|
: { start: 0, end: 0 }
|
|
|
|
)
|
|
|
|
|
|
|
|
const [inputFocused, setInputFocused] = useState(false)
|
|
|
|
useEffect(() => {
|
|
|
|
layoutAnimation()
|
|
|
|
}, [inputFocused])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<ComponentEmojis
|
|
|
|
enabled={emoji}
|
|
|
|
value={value}
|
|
|
|
setValue={setValue}
|
|
|
|
selectionRange={selectionRange}
|
2021-05-11 21:38:48 +02:00
|
|
|
maxLength={options?.maxLength}
|
2021-05-09 21:59:03 +02:00
|
|
|
>
|
2021-05-10 23:41:48 +02:00
|
|
|
<View
|
2022-05-07 00:52:32 +02:00
|
|
|
style={{
|
|
|
|
borderWidth: 1,
|
|
|
|
marginVertical: StyleConstants.Spacing.S,
|
|
|
|
padding: StyleConstants.Spacing.S,
|
|
|
|
borderColor: colors.border,
|
|
|
|
flexDirection: multiline ? 'column' : 'row',
|
|
|
|
alignItems: 'stretch'
|
|
|
|
}}
|
2021-05-10 23:41:48 +02:00
|
|
|
>
|
2021-05-09 21:59:03 +02:00
|
|
|
<EmojisContext.Consumer>
|
|
|
|
{({ emojisDispatch }) => (
|
|
|
|
<TextInput
|
|
|
|
autoFocus={autoFocus}
|
|
|
|
onFocus={() => setInputFocused(true)}
|
|
|
|
onBlur={() => {
|
|
|
|
setInputFocused(false)
|
|
|
|
emojisDispatch({ type: 'activate', payload: false })
|
|
|
|
}}
|
2022-05-07 00:52:32 +02:00
|
|
|
style={{
|
|
|
|
flex: 1,
|
|
|
|
fontSize: StyleConstants.Font.Size.M,
|
|
|
|
color: colors.primaryDefault,
|
|
|
|
minHeight:
|
|
|
|
Platform.OS === 'ios' && multiline
|
|
|
|
? StyleConstants.Font.LineHeight.M * 5
|
|
|
|
: undefined
|
|
|
|
}}
|
2021-05-09 21:59:03 +02:00
|
|
|
onChangeText={setValue}
|
2022-08-07 01:18:10 +02:00
|
|
|
onSelectionChange={({ nativeEvent: { selection } }) =>
|
|
|
|
(selectionRange.current = selection)
|
|
|
|
}
|
2021-05-09 21:59:03 +02:00
|
|
|
value={value}
|
|
|
|
{...(multiline && {
|
|
|
|
multiline,
|
|
|
|
numberOfLines: Platform.OS === 'android' ? 5 : undefined
|
|
|
|
})}
|
2021-05-10 23:41:48 +02:00
|
|
|
keyboardAppearance={mode}
|
|
|
|
textAlignVertical='top'
|
|
|
|
{...options}
|
2021-05-09 21:59:03 +02:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</EmojisContext.Consumer>
|
|
|
|
{title ? (
|
|
|
|
<Animated.Text
|
2022-05-07 00:52:32 +02:00
|
|
|
style={[
|
|
|
|
animateTitle,
|
|
|
|
{ position: 'absolute', color: colors.secondary }
|
|
|
|
]}
|
2021-05-09 21:59:03 +02:00
|
|
|
>
|
|
|
|
{title}
|
|
|
|
</Animated.Text>
|
|
|
|
) : null}
|
2021-05-23 22:53:06 +02:00
|
|
|
<View style={{ flexDirection: 'row', alignSelf: 'flex-end' }}>
|
2021-05-10 23:41:48 +02:00
|
|
|
{options?.maxLength && value?.length ? (
|
2022-05-07 00:52:32 +02:00
|
|
|
<CustomText
|
|
|
|
fontStyle='S'
|
|
|
|
style={{
|
|
|
|
paddingLeft: StyleConstants.Spacing.XS,
|
|
|
|
color: colors.secondary
|
|
|
|
}}
|
|
|
|
>
|
2021-05-10 23:41:48 +02:00
|
|
|
{value?.length} / {options.maxLength}
|
2022-05-07 00:52:32 +02:00
|
|
|
</CustomText>
|
2021-05-10 23:41:48 +02:00
|
|
|
) : null}
|
|
|
|
{inputFocused ? <EmojisButton /> : null}
|
|
|
|
</View>
|
2021-05-09 21:59:03 +02:00
|
|
|
</View>
|
|
|
|
<EmojisList />
|
|
|
|
</ComponentEmojis>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Input
|