"use client"
import { forwardRef, type HTMLAttributes, type WheelEvent } from "react"
import { Text, TextField } from "react-aria-components"
import { Controller, useFormContext } from "react-hook-form"
import { useIntl, type IntlShape } from "react-intl"
import { cx } from "class-variance-authority"
import { Error } from "../ErrorMessage/Error"
import { mergeRefs } from "../utils/mergeRefs"
import { MaterialIcon, MaterialIconProps } from "../../Icons/MaterialIcon"
import { Input } from "../../Input"
import styles from "./input.module.css"
import type { FormInputProps } from "./input"
const defaultErrorFormatter = (
_intl: IntlShape,
errorMessage?: string
): string => errorMessage ?? ""
export const FormInput = forwardRef(
function FormInput(
{
autoComplete,
className = "",
description = "",
descriptionIcon = "info" as MaterialIconProps["icon"],
disabled = false,
errorFormatter,
hideError,
inputMode,
label,
labelPosition = "floating",
maxLength,
name,
id,
placeholder,
readOnly = false,
registerOptions = {},
type = "text",
validationState,
...props
},
ref
) {
const intl = useIntl()
const { control } = useFormContext()
const formatErrorMessage = errorFormatter ?? defaultErrorFormatter
// Number input: prevent scroll from changing value
const numberAttributes: HTMLAttributes =
type === "number"
? {
onWheel: (evt: WheelEvent) => {
evt.currentTarget.blur()
},
}
: {}
return (
{
const isDisabled = disabled || field.disabled
const hasError = fieldState.invalid && !hideError
const showDescription = description && !fieldState.error
return (
// Note: No aria-label needed on TextField since the Input component
// always renders a visible label that provides the accessible name
{showDescription ? (
{description}
) : null}
{hasError && fieldState.error ? (
{formatErrorMessage(intl, fieldState.error.message)}
) : null}
)
}}
/>
)
}
)
FormInput.displayName = "FormInput"