import PropTypes from 'prop-types' import React, { useCallback, useRef } from 'react' import { Platform, StyleSheet, TextInput, TextInputProps, NativeSyntheticEvent, TextInputContentSizeChangeEventData, } from 'react-native' import { MIN_COMPOSER_HEIGHT, DEFAULT_PLACEHOLDER } from './Constant' import Color from './Color' import { StylePropType } from './utils' import { useCallbackOne } from 'use-memo-one' export interface ComposerProps { composerHeight?: number text?: string placeholder?: string placeholderTextColor?: string textInputProps?: Partial textInputStyle?: TextInputProps['style'] textInputAutoFocus?: boolean keyboardAppearance?: TextInputProps['keyboardAppearance'] multiline?: boolean disableComposer?: boolean onTextChanged?(text: string): void onInputSizeChanged?(layout: { width: number; height: number }): void } export function Composer ({ composerHeight = MIN_COMPOSER_HEIGHT, disableComposer = false, keyboardAppearance = 'default', multiline = true, onInputSizeChanged, onTextChanged, placeholder = DEFAULT_PLACEHOLDER, placeholderTextColor = Color.defaultColor, text = '', textInputAutoFocus = false, textInputProps, textInputStyle, }: ComposerProps): React.ReactElement { const dimensionsRef = useRef<{ width: number; height: number }>() const determineInputSizeChange = useCallbackOne( (dimensions: { width: number; height: number }) => { // Support earlier versions of React Native on Android. if (!dimensions) return if ( !dimensionsRef.current || (dimensionsRef.current && (dimensionsRef.current.width !== dimensions.width || dimensionsRef.current.height !== dimensions.height)) ) { dimensionsRef.current = dimensions onInputSizeChanged?.(dimensions) } }, [onInputSizeChanged] ) const handleContentSizeChange = useCallback(({ nativeEvent: { contentSize }}: NativeSyntheticEvent) => determineInputSizeChange(contentSize) , [determineInputSizeChange]) return ( ) } Composer.propTypes = { composerHeight: PropTypes.number, text: PropTypes.string, placeholder: PropTypes.string, placeholderTextColor: PropTypes.string, textInputProps: PropTypes.object, onTextChanged: PropTypes.func, onInputSizeChanged: PropTypes.func, multiline: PropTypes.bool, disableComposer: PropTypes.bool, textInputStyle: StylePropType, textInputAutoFocus: PropTypes.bool, keyboardAppearance: PropTypes.string, } const styles = StyleSheet.create({ textInput: { flex: 1, marginLeft: 10, fontSize: 16, lineHeight: 22, ...Platform.select({ web: { paddingTop: 6, paddingLeft: 4, }, }), marginTop: Platform.select({ ios: 6, android: 0, web: 6, }), marginBottom: Platform.select({ ios: 5, android: 3, web: 4, }), }, })