import React, { forwardRef } from 'react'; import type { TextInput as RNTextInput, TextInputProps as NativeTextInputProps, StyleProp, ViewStyle, TextStyle, } from 'react-native'; import type { ToolbarMessageState } from './StyledToolbar'; import { StyledInput, StyledInputContainer, StyledPrefix, StyledSuffix, ToolbarMessageWrapper, } from './StyledToolbar'; import { useTheme } from '../../theme'; export type ToolbarMessageHandles = Pick< RNTextInput, 'focus' | 'clear' | 'blur' | 'isFocused' | 'setNativeProps' >; export interface ToolbarMessageProps extends NativeTextInputProps { /** * Element to render on the left side of the input, before the user's cursor. */ prefix?: React.ReactNode; /** * Element to render on the right side of the input. */ suffix?: React.ReactNode; /** * Additional wrapper style. */ style?: StyleProp; /** * Input text style. */ textStyle?: StyleProp; /** * Testing id of the component. */ testID?: string; /** * Accessibility label for the input (Android). */ accessibilityLabelledBy?: string; /** * Placeholder text to display. * */ placeholder?: string; /** * Whether the input is editable. * */ editable?: boolean; /** * Whether the input is disabled. */ disabled?: boolean; /** * The max length of the input. * If the max length is set, the input will display the current length and the max length. * */ maxLength?: number; /** * Component ref. */ ref?: React.Ref; } export const getState = ({ disabled, editable, isEmptyValue, }: { disabled?: boolean; editable?: boolean; isEmptyValue?: boolean; }): ToolbarMessageState => { switch (true) { case disabled: return 'disabled'; case !editable: return 'readonly'; case !isEmptyValue: return 'filled'; default: return 'default'; } }; const ToolbarMessage = forwardRef( (props, forwardedRef) => { const { prefix, suffix, style, testID, value, defaultValue, disabled, editable = true, textStyle, ...nativeProps } = props; const theme = useTheme(); const innerTextInput = React.useRef(null); const displayText = (value !== undefined ? value : defaultValue) ?? ''; const isEmptyValue = displayText.length === 0; React.useImperativeHandle( forwardedRef, () => ({ isFocused: () => innerTextInput.current?.isFocused() || false, getNativeTextInputRef: () => innerTextInput.current, setNativeProps: (args: NativeTextInputProps) => innerTextInput.current?.setNativeProps(args), focus: () => innerTextInput.current?.focus(), blur: () => innerTextInput.current?.blur(), clear: () => innerTextInput.current?.clear(), }), [innerTextInput.current] ); const state = getState({ disabled, editable, isEmptyValue, }); return ( {prefix && ( {prefix} )} { innerTextInput.current = rnTextInputRef; }} style={textStyle} placeholderTextColor={theme.__hd__.toolbar.colors.placeholder} /> {suffix && ( {suffix} )} ); } ); export default ToolbarMessage;