diff --git a/package-lock.json b/package-lock.json index 843965a..afe25be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,9 @@ "workspaces": [ "packages/*" ], + "dependencies": { + "react-hook-form": "^7.53.0" + }, "devDependencies": { "@babel/core": "7.25.2", "@emotion/react": "11.13.3", @@ -17439,19 +17442,18 @@ "dev": true }, "node_modules/react-hook-form": { - "version": "7.30.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.30.0.tgz", - "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==", - "peer": true, + "version": "7.53.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.0.tgz", + "integrity": "sha512-M1n3HhqCww6S2hxLxciEXy2oISPnAzxY7gvwVPrtlczTM/1dDadXgUxDpHMrMTblDOcm/AXtXxHwZ3jpg1mqKQ==", "engines": { - "node": ">=12.22.0" + "node": ">=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/react-hook-form" }, "peerDependencies": { - "react": "^16.8.0 || ^17 || ^18" + "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "node_modules/react-is": { @@ -33724,10 +33726,9 @@ } }, "react-hook-form": { - "version": "7.30.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.30.0.tgz", - "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==", - "peer": true, + "version": "7.53.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.0.tgz", + "integrity": "sha512-M1n3HhqCww6S2hxLxciEXy2oISPnAzxY7gvwVPrtlczTM/1dDadXgUxDpHMrMTblDOcm/AXtXxHwZ3jpg1mqKQ==", "requires": {} }, "react-is": { diff --git a/package.json b/package.json index 673c533..f3bd890 100644 --- a/package.json +++ b/package.json @@ -58,5 +58,8 @@ "vite": "5.4.2", "vite-plugin-dts": "^4.0.3", "vitest": "^2.0.5" + }, + "dependencies": { + "react-hook-form": "7.53.0" } -} \ No newline at end of file +} diff --git a/packages/mui/src/SimpleFileUpload.tsx b/packages/mui/src/SimpleFileUpload.tsx new file mode 100644 index 0000000..f166cec --- /dev/null +++ b/packages/mui/src/SimpleFileUpload.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import { + useController, + FieldValues, + UseControllerProps, + FieldPath, +} from 'react-hook-form'; +import FormControl, { FormControlProps } from '@mui/material/FormControl'; +import InputLabel, { InputLabelProps } from '@mui/material/InputLabel'; +import Input, { InputProps } from '@mui/material/Input'; +import FormHelperText from '@mui/material/FormHelperText'; + +export type SimpleFileUploadProps< + TName extends FieldPath, + TFieldValues extends FieldValues = FieldValues, +> = UseControllerProps & + Omit & { + label: string; + accept: string; + disabled?: boolean; + InputLabelProps?: InputLabelProps; + FormControlProps?: FormControlProps; + }; + +export function SimpleFileUpload< + TName extends FieldPath, + TFieldValues extends FieldValues, +>({ + control, + name, + rules, + label, + accept, + disabled = false, + InputLabelProps: inputLabelProps, + FormControlProps: formControlProps, + ...props +}: SimpleFileUploadProps) { + const { + field: { onChange, ref }, + fieldState: { error }, + } = useController({ + name, + control, + rules, + }); + + const handleFileChange = (event: React.ChangeEvent) => { + const file = event.target.files?.[0] || null; + + if (file) { + const fileData = { + size: file.size, + name: file.name, + type: file.type, + }; + onChange(fileData); + } else { + onChange(null); + } + }; + + return ( + + {label && ( + + {label} + + )} + + {error && {error.message}} + + ); +} + +SimpleFileUpload.displayName = 'MuiReactHookFormSimpleFileUpload'; diff --git a/src/stories/SimpleFileUpload.stories.tsx b/src/stories/SimpleFileUpload.stories.tsx new file mode 100644 index 0000000..01d00f4 --- /dev/null +++ b/src/stories/SimpleFileUpload.stories.tsx @@ -0,0 +1,75 @@ +import Stack from '@mui/material/Stack'; +import { StoryFn, Meta } from '@storybook/react'; +import { useForm } from 'react-hook-form'; + +import { SimpleFileUpload } from '../../packages/mui/src/SimpleFileUpload'; +import { Form } from './Form'; + +export default { + title: 'Core/SimpleFileUpload', + component: SimpleFileUpload, + parameters: { + layout: 'fullscreen', + }, + argTypes: { onSubmit: { action: 'submit' } }, +} as Meta; + +const Template: StoryFn = (args: any) => { + const formProps = useForm<{ + file: File | null; + }>({ + defaultValues: { + file: null, + }, + }); + + return ( +
+ + + +
+ ); +}; + +export const Default = { + render: Template, + args: { + label: 'Default', + accept: 'image/*', + }, +}; + +export const Required = { + render: Template, + args: { + label: 'Required', + accept: 'image/*', + rules: { required: 'File is required' }, + }, +}; + +export const Disabled = { + render: Template, + args: { + label: 'Disabled', + accept: 'image/*', + disabled: true, + }, +}; + +export const AcceptPDF = { + render: Template, + args: { + label: 'Accept PDF', + accept: 'application/pdf', + }, +};