| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- import React, {
- type JSX,
- useCallback,
- useEffect,
- useMemo,
- useRef,
- } from 'react';
- import type { GetInputProps } from '../interfaces/downshift';
- type Props = {
- searchKeyword: string;
- onChange?: (text: string) => void;
- onSubmit?: () => void;
- getInputProps: GetInputProps;
- };
- export const SearchForm = (props: Props): JSX.Element => {
- const { searchKeyword, onChange, onSubmit, getInputProps } = props;
- const inputRef = useRef<HTMLInputElement>(null);
- const changeSearchTextHandler = useCallback(
- (e: React.ChangeEvent<HTMLInputElement>) => {
- onChange?.(e.target.value);
- },
- [onChange],
- );
- const submitHandler = useCallback(
- (e: React.FormEvent<HTMLFormElement>) => {
- e.preventDefault();
- const isEmptyKeyword = searchKeyword.trim().length === 0;
- if (isEmptyKeyword) {
- return;
- }
- onSubmit?.();
- },
- [searchKeyword, onSubmit],
- );
- // Prevent Downshift from intercepting Home/End keys so they move
- // the cursor within the input field instead of navigating the list
- const keyDownHandler = useCallback(
- (e: React.KeyboardEvent<HTMLInputElement>) => {
- if (e.key === 'Home' || e.key === 'End') {
- (e.nativeEvent as { preventDownshiftDefault?: boolean }).preventDownshiftDefault = true;
- }
- },
- [],
- );
- const inputOptions = useMemo(() => {
- return getInputProps({
- type: 'text',
- placeholder: 'Search...',
- className: 'form-control',
- ref: inputRef,
- value: searchKeyword,
- onChange: changeSearchTextHandler,
- onKeyDown: keyDownHandler,
- });
- }, [getInputProps, searchKeyword, changeSearchTextHandler, keyDownHandler]);
- useEffect(() => {
- if (inputRef.current != null) {
- inputRef.current.focus();
- }
- });
- return (
- <form
- className="w-100 position-relative"
- onSubmit={submitHandler}
- data-testid="search-form"
- >
- <input {...inputOptions} />
- <button
- type="button"
- className="btn btn-neutral-secondary text-muted position-absolute bottom-0 end-0 w-auto h-100 border-0"
- onClick={() => {
- onChange?.('');
- }}
- >
- <span className="material-symbols-outlined p-0">cancel</span>
- </button>
- </form>
- );
- };
|