Files
web/components/TempDesignSystem/Form/Phone/index.tsx
2024-06-19 14:51:00 +02:00

139 lines
3.9 KiB
TypeScript

"use client"
import "react-international-phone/style.css"
import { parsePhoneNumber } from "libphonenumber-js"
import {
Input as AriaInput,
Label as AriaLabel,
TextField,
} from "react-aria-components"
import { useController, useFormContext, useWatch } from "react-hook-form"
import {
CountrySelector,
DialCodePreview,
ParsedCountry,
usePhoneInput,
} from "react-international-phone"
import { useIntl } from "react-intl"
import { ChevronDownIcon } from "@/components/Icons"
import ErrorMessage from "@/components/TempDesignSystem/Form/ErrorMessage"
import Label from "@/components/TempDesignSystem/Form/Label"
import Body from "@/components/TempDesignSystem/Text/Body"
import styles from "./phone.module.css"
import type { ChangeEvent } from "react"
import type { PhoneProps } from "./phone"
export default function Phone({
ariaLabel = "Phone number input",
disabled = false,
label,
name = "phoneNumber",
placeholder = "",
registerOptions = {
required: true,
},
}: PhoneProps) {
const { formatMessage } = useIntl()
const { control, setValue } = useFormContext()
const phone = useWatch({ name })
const { field, fieldState, formState } = useController({
control,
disabled,
name,
rules: registerOptions,
})
const { country, handlePhoneValueChange, inputValue, setCountry } =
usePhoneInput({
defaultCountry:
parsePhoneNumber(
formState.defaultValues?.phoneNumber
).country?.toLowerCase() ?? "sv",
disableCountryGuess: true,
forceDialCode: true,
value: phone,
})
function handleSelectCountry(value: ParsedCountry) {
setCountry(value.iso2)
}
function handleChange(evt: ChangeEvent<HTMLInputElement>) {
handlePhoneValueChange(evt)
setValue(name, evt.target.value)
}
return (
<div className={styles.phone}>
<CountrySelector
dropdownArrowClassName={styles.arrow}
flagClassName={styles.flag}
onSelect={handleSelectCountry}
preferredCountries={["de", "dk", "fi", "no", "se", "gb"]}
selectedCountry={country.iso2}
renderButtonWrapper={(props) => (
<button
{...props.rootProps}
className={styles.select}
tabIndex={0}
type="button"
>
<Label required={!!registerOptions.required} size="small">
{formatMessage({ id: "Country code" })}
</Label>
<div className={styles.selectContainer}>
{props.children}
<Body asChild fontOnly>
<DialCodePreview
className={styles.dialCode}
dialCode={country.dialCode}
prefix="+"
/>
</Body>
<ChevronDownIcon
className={styles.chevron}
color="grey80"
height={18}
width={18}
/>
</div>
</button>
)}
/>
<TextField
aria-label={ariaLabel}
defaultValue={field.value}
isDisabled={disabled ?? field.disabled}
isInvalid={fieldState.invalid}
isRequired={!!registerOptions?.required}
name={field.name}
type="tel"
>
<AriaLabel className={styles.inputContainer} htmlFor={field.name}>
<Body asChild fontOnly>
<AriaInput
className={styles.input}
id={field.name}
name={field.name}
onBlur={field.onBlur}
onChange={handleChange}
placeholder={placeholder}
ref={field.ref}
required={!!registerOptions.required}
value={inputValue}
/>
</Body>
<Label required={!!registerOptions.required}>{label}</Label>
</AriaLabel>
<ErrorMessage errors={formState.errors} name={field.name} />
</TextField>
<ErrorMessage errors={formState.errors} name={name} />
</div>
)
}