fixed incorrect html with multiple interactive elements inside label fixed inconsistent placeholder attribute handling between browsers removed active state so not to prevent iOS from focusing inputs
98 lines
2.8 KiB
TypeScript
98 lines
2.8 KiB
TypeScript
"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 } from "react-intl"
|
|
|
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
|
|
|
import AriaInputWithLabel from "@/components/TempDesignSystem/Form/Input/AriaInputWithLabel"
|
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
|
|
|
import { getErrorMessage } from "./errors"
|
|
|
|
import styles from "./input.module.css"
|
|
|
|
import type { InputProps } from "./input"
|
|
|
|
const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
|
{
|
|
"aria-label": ariaLabel,
|
|
autoComplete,
|
|
className = "",
|
|
disabled = false,
|
|
helpText = "",
|
|
label,
|
|
maxLength,
|
|
name,
|
|
placeholder,
|
|
readOnly = false,
|
|
registerOptions = {},
|
|
type = "text",
|
|
hideError,
|
|
},
|
|
ref
|
|
) {
|
|
const intl = useIntl()
|
|
const { control } = useFormContext()
|
|
let numberAttributes: HTMLAttributes<HTMLInputElement> = {}
|
|
if (type === "number") {
|
|
numberAttributes.onWheel = function (evt: WheelEvent<HTMLInputElement>) {
|
|
evt.currentTarget.blur()
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Controller
|
|
disabled={disabled}
|
|
control={control}
|
|
name={name}
|
|
rules={registerOptions}
|
|
render={({ field, fieldState }) => (
|
|
<TextField
|
|
aria-label={ariaLabel}
|
|
className={className}
|
|
isDisabled={field.disabled}
|
|
isInvalid={fieldState.invalid}
|
|
isRequired={!!registerOptions.required}
|
|
name={field.name}
|
|
onBlur={field.onBlur}
|
|
onChange={field.onChange}
|
|
validationBehavior="aria"
|
|
value={field.value}
|
|
>
|
|
<AriaInputWithLabel
|
|
{...field}
|
|
ref={ref}
|
|
aria-labelledby={field.name}
|
|
autoComplete={autoComplete}
|
|
id={field.name}
|
|
label={label}
|
|
maxLength={maxLength}
|
|
placeholder={placeholder}
|
|
readOnly={readOnly}
|
|
required={!!registerOptions.required}
|
|
type={type}
|
|
/>
|
|
{helpText && !fieldState.error ? (
|
|
<Caption asChild color="black">
|
|
<Text className={styles.helpText} slot="description">
|
|
<MaterialIcon icon="check" size={20} />
|
|
{helpText}
|
|
</Text>
|
|
</Caption>
|
|
) : null}
|
|
{fieldState.error && !hideError ? (
|
|
<Caption className={styles.error} fontOnly>
|
|
<MaterialIcon icon="info" color="Icon/Feedback/Error" />
|
|
{getErrorMessage(intl, fieldState.error.message)}
|
|
</Caption>
|
|
) : null}
|
|
</TextField>
|
|
)}
|
|
/>
|
|
)
|
|
})
|
|
export default Input
|