new-personal-site/components/lib/elements/Search.tsx
2024-12-09 16:36:17 +01:00

111 lines
2.9 KiB
TypeScript

import { twMerge } from "tailwind-merge";
import Input from "../form/Input";
import Button from "../layout/Button";
import Row from "../layout/Row";
import { Search as SearchIcon } from "lucide-react";
import React, {
DetailedHTMLProps,
InputHTMLAttributes,
TextareaHTMLAttributes,
} from "react";
let timeout: any;
export type SearchProps = DetailedHTMLProps<
React.HTMLAttributes<HTMLDivElement>,
HTMLDivElement
> & {
dispatch?: (value?: string) => void;
delay?: number;
inputProps?: DetailedHTMLProps<
InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement
> &
DetailedHTMLProps<
TextareaHTMLAttributes<HTMLTextAreaElement>,
HTMLTextAreaElement
>;
buttonProps?: DetailedHTMLProps<
React.ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
>;
};
/**
* # Search Component
* @className_wrapper twui-search-wrapper
* @className_circle twui-search-input
* @className_circle twui-search-button
*/
export default function Search({
dispatch,
delay = 500,
inputProps,
buttonProps,
...props
}: SearchProps) {
const [input, setInput] = React.useState("");
React.useEffect(() => {
clearTimeout(timeout);
timeout = setTimeout(() => {
dispatch?.(input);
}, delay);
}, [input]);
const inputRef = React.useRef<HTMLInputElement>();
React.useEffect(() => {
if (props.autoFocus) {
inputRef.current?.focus();
}
}, []);
return (
<Row
{...props}
className={twMerge(
"relative xl:flex-nowrap items-stretch gap-0",
"twui-search-wrapper",
props?.className
)}
>
<Input
type="search"
placeholder="Search"
{...inputProps}
value={input}
onChange={(e) => setInput(e.target.value)}
className={twMerge(
"rounded-r-none",
"twui-search-input",
inputProps?.className
)}
wrapperProps={{
className: "rounded-r-none",
}}
componentRef={inputRef}
/>
<Button
{...buttonProps}
variant="outlined"
color="gray"
className={twMerge(
"rounded-l-none my-[1px]",
"twui-search-button",
buttonProps?.className
)}
onClick={() => {
dispatch?.(input);
}}
>
<SearchIcon
className="text-slate-800 dark:text-white"
size={20}
/>
</Button>
</Row>
);
}