"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"