import * as React from 'react'; import { isFunction } from '@aws-amplify/ui'; import { ESCAPE_KEY, ENTER_KEY } from '../shared/constants'; import { UseSearchFieldProps } from '../types'; import { useComposeRefsCallback } from '../../hooks/useComposeRefsCallback'; const DEFAULT_KEYS = new Set([ESCAPE_KEY, ENTER_KEY]); type ClearHandler = React.MouseEventHandler; type ClickHandler = React.MouseEventHandler; type KeyDownHandler = React.KeyboardEventHandler; type ChangeHandler = React.ChangeEventHandler; interface UseSearchField { composedValue: string; onClearHandler: ClearHandler; onClick: ClickHandler; onKeyDown: KeyDownHandler; handleOnChange: ChangeHandler; composedRefs: React.Ref; } export const useSearchField = ({ defaultValue = '', value, onChange, onClear, onSubmit, externalRef, }: UseSearchFieldProps): UseSearchField => { const isControlled = value !== undefined; const [internalValue, setInternalValue] = React.useState(defaultValue); const composedValue = isControlled ? value : internalValue; const internalRef = React.useRef(null); const composedRefs = useComposeRefsCallback({ externalRef, internalRef, }); const onClearHandler = React.useCallback(() => { if (!isControlled) { setInternalValue(''); } internalRef?.current?.focus(); if (isFunction(onClear)) { onClear(); } }, [isControlled, setInternalValue, onClear]); const onSubmitHandler = React.useCallback( (value: string) => { if (isFunction(onSubmit)) { onSubmit(value); } }, [onSubmit] ); const onKeyDown: KeyDownHandler = React.useCallback( (event) => { const { key } = event; if (!DEFAULT_KEYS.has(key)) { return; } event.preventDefault(); if (key === ESCAPE_KEY) { onClearHandler(); } else if (key === ENTER_KEY) { onSubmitHandler(composedValue); } }, [composedValue, onClearHandler, onSubmitHandler] ); const handleOnChange: ChangeHandler = React.useCallback( (event) => { if (!isControlled) { setInternalValue(event.target.value); } if (isFunction(onChange)) { onChange(event); } }, [isControlled, onChange, setInternalValue] ); const onClick = React.useCallback(() => { onSubmitHandler(composedValue); }, [onSubmitHandler, composedValue]); return { composedValue, onClearHandler, onKeyDown, onClick, handleOnChange, composedRefs, }; };