mirror of
https://github.com/SrIzan10/starters.git
synced 2026-05-01 11:05:16 +00:00
67 lines
1.9 KiB
TypeScript
67 lines
1.9 KiB
TypeScript
import { forwardRef, ComponentPropsWithoutRef, PropsWithoutRef } from "react"
|
|
import { useField, UseFieldConfig } from "react-final-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">
|
|
fieldProps?: UseFieldConfig<string>
|
|
}
|
|
|
|
export const LabeledTextField = forwardRef<HTMLInputElement, LabeledTextFieldProps>(
|
|
({ name, label, outerProps, fieldProps, labelProps, ...props }, ref) => {
|
|
const {
|
|
input,
|
|
meta: { touched, error, submitError, submitting },
|
|
} = useField(name, {
|
|
parse:
|
|
props.type === "number"
|
|
? (Number as any)
|
|
: // Converting `""` to `null` ensures empty values will be set to null in the DB
|
|
(v) => (v === "" ? null : v),
|
|
...fieldProps,
|
|
})
|
|
|
|
const normalizedError = Array.isArray(error) ? error.join(", ") : error || submitError
|
|
|
|
return (
|
|
<div {...outerProps}>
|
|
<label {...labelProps}>
|
|
{label}
|
|
<input {...input} disabled={submitting} {...props} ref={ref} />
|
|
</label>
|
|
|
|
{touched && normalizedError && (
|
|
<div role="alert" style={{ color: "red" }}>
|
|
{normalizedError}
|
|
</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
|