You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
59 lines
1.6 KiB
59 lines
1.6 KiB
import { forwardRef, PropsWithoutRef, ComponentPropsWithoutRef } from "react" |
|
import { useFormContext } from "react-hook-form" |
|
|
|
export interface LabeledTextFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["input"]> { |
|
/** Field name. */ |
|
name: string |
|
/** Field label. */ |
|
label: string |
|
/** Field type. Doesn't include radio buttons and checkboxes */ |
|
type?: "text" | "password" | "email" | "number" |
|
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]> |
|
labelProps?: ComponentPropsWithoutRef<"label"> |
|
} |
|
|
|
export const LabeledTextField = forwardRef<HTMLInputElement, LabeledTextFieldProps>( |
|
({ label, outerProps, labelProps, name, ...props }, ref) => { |
|
const { |
|
register, |
|
formState: { isSubmitting, errors }, |
|
} = useFormContext() |
|
const error = Array.isArray(errors[name]) |
|
? errors[name].join(", ") |
|
: errors[name]?.message || errors[name] |
|
|
|
return ( |
|
<div {...outerProps}> |
|
<label {...labelProps}> |
|
{label} |
|
<input disabled={isSubmitting} {...register(name)} {...props} /> |
|
</label> |
|
|
|
{error && ( |
|
<div role="alert" style={{ color: "red" }}> |
|
{error} |
|
</div> |
|
)} |
|
|
|
<style jsx>{` |
|
label { |
|
display: flex; |
|
flex-direction: column; |
|
align-items: start; |
|
font-size: 1rem; |
|
} |
|
input { |
|
font-size: 1rem; |
|
padding: 0.25rem 0.5rem; |
|
border-radius: 3px; |
|
border: 1px solid purple; |
|
appearance: none; |
|
margin-top: 0.5rem; |
|
} |
|
`}</style> |
|
</div> |
|
) |
|
} |
|
) |
|
|
|
export default LabeledTextField
|
|
|