import useForwardedRef from "@hooks/useForwardedRef"; import { FieldDomProps } from "../../../types"; import { PressResponder } from "@react-aria/interactions"; import React from "react"; export interface FileTriggerProps extends FieldDomProps { children?: React.ReactNode; /** Configure if the input should accept files or directories * * [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/webkitdirectory) */ accept?: "files" | "directories"; /** Whether or not the input allows multiple files to be selected * * [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/multiple) */ allowsMultiple?: boolean; /** Array of accepted file types * * [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept) */ acceptedFileTypes?: string[]; /** Specifies that a new file should be captured from the device camera * Typically only works on mobile devices * * [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/capture) */ captureMode?: "user" | "environment"; /** Callback function that is called when a file is selected */ onSelect?: (files: FileList) => void; } /** FileTrigger component. Provides the ability to trigger file selection * for any child pressable component */ export const FileTrigger = React.forwardRef(function FileTrigger( props: FileTriggerProps, ref: React.ForwardedRef ) { const { children, allowsMultiple, acceptedFileTypes = [], captureMode, accept, name, } = props; const inputRef = useForwardedRef(ref); return ( <> { // Clear out the input for repeat file selection if (inputRef.current?.value) inputRef.current.value = ""; inputRef.current?.click(); }} > {children} 0 ? acceptedFileTypes.join(",") : undefined } multiple={allowsMultiple} capture={captureMode} onChange={(e) => props.onSelect?.(e.target.files!)} // @ts-expect-error - webkitdirectory is not a standard attribute // But it is supported by most modern browsers webkitdirectory={accept === "directory" ? "true" : undefined} /> ); });