"use client" import { useState } from "react" import { Text, TextField } from "react-aria-components" import { Controller, type RegisterOptions, useFormContext, } from "react-hook-form" import { useIntl, type IntlShape } from "react-intl" import { MaterialIcon, type MaterialIconProps } from "../Icons/MaterialIcon" import { Input } from "../Input" import { Typography } from "../Typography" import { NewPasswordValidation } from "./NewPasswordValidation" import styles from "./passwordInput.module.css" const defaultErrorFormatter = ( _intl: IntlShape, errorMessage?: string ): string => errorMessage ?? "" interface PasswordInputProps extends React.InputHTMLAttributes { label?: string registerOptions?: RegisterOptions visibilityToggleable?: boolean isNewPassword?: boolean errorFormatter?: (intl: IntlShape, errorMessage?: string) => string /** Helper text displayed below the input (hidden when there's an error) */ description?: string descriptionIcon?: MaterialIconProps["icon"] autoComplete?: string } export const PasswordInput = ({ name = "password", label, "aria-label": ariaLabel, disabled = false, placeholder, registerOptions = {}, visibilityToggleable = true, isNewPassword = false, className = "", errorFormatter, description = "", descriptionIcon = "info", autoComplete, }: PasswordInputProps) => { const { control } = useFormContext() const intl = useIntl() const [isPasswordVisible, setIsPasswordVisible] = useState(false) const formatErrorMessage = errorFormatter ?? defaultErrorFormatter // Automatically set autocomplete based on isNewPassword if not explicitly provided const autocompleteValue = autoComplete ?? (isNewPassword ? "new-password" : "current-password") return ( { const errors = isNewPassword ? Object.values(formState.errors[name]?.types ?? []).flat() : [] // Use field.name as base for all IDs - it's already unique per form field const errorId = `${field.name}-error` const requirementsId = `${field.name}-requirements` const inputId = field.name // Already used on line 85 // Build aria-describedby dynamically based on what exists const describedBy = [ fieldState.error ? errorId : null, isNewPassword && field.value ? requirementsId : null, ] .filter(Boolean) .join(" ") || undefined const hasError = !!fieldState.error const showRequirements = isNewPassword && !!field.value const showDescription = description && !fieldState.error return (
{visibilityToggleable ? ( ) : null}
{showDescription ? ( {description} ) : null} {showRequirements ? ( ) : null} {hasError && (!isNewPassword || !field.value) ? ( ) : null}
) }} /> ) } function ErrorMessage({ errorMessage, formatErrorMessage, id, }: { errorMessage?: string formatErrorMessage: (intl: IntlShape, errorMessage?: string) => string id: string }) { const intl = useIntl() return ( ) }