react-hook-form-bound single-file upload field. Wraps the @uxf/ui/file-input primitive and manages its value, isInvalid, and helperText from form state.
Use @uxf/form/file-input for a single-file upload inside a @uxf/form form — it registers the field with react-hook-form via control/name and renders validation errors automatically. For a standalone, manually-controlled file input (outside a form), use the @uxf/ui/file-input twin directly. For multiple files use @uxf/form/dropzone; for an avatar/image preview use @uxf/form/avatar-file-input.
import { Form } from "@uxf/form/form";
import { FileInput, FileInputValue } from "@uxf/form/file-input";
import { FileResponse } from "@uxf/core/types";
import { useForm } from "react-hook-form";
// your uploader: send the file to storage, resolve with the stored file
declare function uploadFile(file: File): Promise<FileResponse>;
interface FormData {
attachment: FileInputValue;
}
function Example() {
const formApi = useForm<FormData>({ defaultValues: { attachment: null } });
return (
<Form formApi={formApi} id="example" onSubmit={(values) => console.log(values)}>
<FileInput control={formApi.control} isClearable label="Attachment" name="attachment" onUploadFile={uploadFile} />
</Form>
);
}
Value is FileInputValue = FileResponse | null (FileResponse from @uxf/core/types) — the field stores the uploaded file object returned by onUploadFile, or null when cleared.
FileInputProps<FormData> = ControlProps<FormData> + the visual props of the @uxf/ui/file-input twin (minus the ones this field manages: isFocused, isInvalid, onChange, value) + the field-specific props below.
| Prop | Type | Default | Description |
|---|---|---|---|
control |
Control<FormData> |
— | Required. The control from useForm. |
name |
FieldPath<FormData> |
— | Required. Field path in the form values. |
onUploadFile |
(file: File, options?) => Promise<FileResponse> |
— | Required (from the twin). Uploads the picked file; resolves to the stored file. |
rules |
RegisterOptions |
— | Extra react-hook-form rules; merged with the built-in required rule below. |
shouldUnregister |
boolean |
— | Unregister the field (drop its value) on unmount. |
isRequired |
boolean |
false |
Adds a required rule and the required indicator. |
requiredMessage |
string |
localized | Message for the required rule (defaults to uxf-form-file-input:validation.required). |
onChange |
(value: FileResponse | null, event?) => void |
— | Called after the field value updates. |
All other props (label, placeholder, size, variant, helperText, isClearable, accept, maxFileSize, uploadButtonLabel, hiddenLabel, onUploadError, onFocus/onBlur, form, id, className, …) are forwarded to the twin — see @uxf/ui/file-input.
isRequired adds a required rule; override its message with requiredMessage.rules; the field-level error is shown as the twin's helperText and sets isInvalid.Form — it reads the form context (formId, and inherits isDisabled / isReadOnly) and needs a react-hook-form control. The field id defaults to ${formId}__${name}.@uxf/ui/file-input, so include that component's stylesheet(s) and the @uxf/ui token layer — see @uxf/ui/file-input.@uxf/ui/file-input