import { forwardRef, type ForwardRefRenderFunction, useId, useImperativeHandle, useRef, type HTMLAttributes, } from 'react'; import { useIntl } from 'react-intl'; import { type FormSubmitHandler, useForm } from '../../../../utils/hooks'; import { Button, Form, Icon, Input, Label, Notice } from '../../../atoms'; import { LabelledField } from '../../../molecules'; import styles from './search-form.module.scss'; export type SearchFormData = { query: string }; export type SearchFormSubmit = FormSubmitHandler; export type SearchFormProps = Omit< HTMLAttributes, 'children' | 'onSubmit' > & { /** * Should the label be visually hidden? * * @default false */ isLabelHidden?: boolean; /** * A callback function to handle search form submit. */ onSubmit?: SearchFormSubmit; }; export type SearchFormRef = { /** * A method to focus the search input. */ focus: () => void; }; const SearchFormWithRef: ForwardRefRenderFunction< SearchFormRef, SearchFormProps > = ({ isLabelHidden = false, onSubmit, ...props }, ref) => { const intl = useIntl(); const { messages, submit, submitStatus, update, values } = useForm({ initialValues: { query: '' }, submitHandler: onSubmit, }); const id = useId(); const inputRef = useRef(null); const formClass = `${styles.form} ${ styles[isLabelHidden ? 'form--no-label' : 'form--has-label'] }`; const labels = { button: intl.formatMessage({ defaultMessage: 'Search', description: 'SearchForm: button accessible name', id: 'WMqQrv', }), field: intl.formatMessage({ defaultMessage: 'Search for:', description: 'SearchForm: field accessible label', id: 'X8oujO', }), }; useImperativeHandle( ref, () => { return { focus() { inputRef.current?.focus(); }, }; }, [] ); return (
} label={ } /> {messages?.error && submitStatus === 'FAILED' ? ( {messages.error} ) : null}
); }; /** * SearchForm component * * Render a search form. */ export const SearchForm = forwardRef(SearchFormWithRef);