import { forwardRef, memo, ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { useFilePicker } from '../../hooks'; import type { DocumentResult, DocumentPickerOptions } from '../../utils'; import { TextInput, type TextInputProps } from '../TextInput'; import { ActivityIndicator } from '../ActivityIndicator'; import { IconButton } from '../IconButton'; export type OmitProp = | 'editable' | 'multiline' | 'onChangeText' | 'keyboardType' | 'defaultValue' | 'value' | 'left' | 'right'; export type Props = Omit & DocumentPickerOptions & { /** * Allows multiple files to be selected from the system UI. * @default false */ multiple?: boolean; /** * Displays the Spinner on the right side in place of the default upload icon * @default false */ loading?: boolean; left?: ReactNode; right?: ReactNode; /** * To Control the value */ value?: DocumentResult | DocumentResult[]; /** * The Callback function to return the selected files as an array or object */ onChange?: (result: DocumentResult | DocumentResult[]) => any; /** * To replace the default progress indicator */ progressIndicator?: ReactNode; }; const FilePicker = ( { loading, right: rightProp, progressIndicator, type, multiple, transitionStyle, mode, presentationStyle, value, onChange = () => {}, onCancel, onError, ...rest }: Props, ref: any, ) => { const [displayText, setDisplayText] = useState(''); const { openFilePicker } = useFilePicker({ type, mode, multiple, transitionStyle, presentationStyle, onCancel, onError, }); const onSetInputValue = useCallback( (response: DocumentResult | DocumentResult[] | undefined) => { if (Array.isArray(response)) { if (response.length > 1) { setDisplayText(`${response.length} file${response.length > 1 ? 's' : ''}`); return; } setDisplayText(response[0].name || ''); return; } setDisplayText(response?.name || ''); }, [], ); const onPress = useCallback(() => { openFilePicker(response => { onSetInputValue(response); onChange?.(response); }); }, [onChange, onSetInputValue, openFilePicker]); const rightElement = useMemo(() => { if (!loading) { return ( <> {rightProp || ( )} ); } else { return <>{progressIndicator || }; } }, [loading, onPress, progressIndicator, rightProp]); // if the value changes, we only want file name or the length of the array to display the text useEffect(() => { onSetInputValue(value); }, [onSetInputValue, value]); return ( ); }; export default memo(forwardRef(FilePicker));