import { ChangeEvent, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { cn } from "@root/lib/utils"; // Новые импорты import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { CaseSensitive, WholeWord, Regex } from "lucide-react"; // Иконки из lucide-react export type SearchState = { text: string; matchCase: boolean; matchWholeWord: boolean; useRegularExpression: boolean; }; type SearchProps = { placeholder?: string; onSearch: (match: (content: string) => boolean, state: SearchState) => void; }; export const BaseSearchBox = (props: SearchProps) => { const { t } = useTranslation(); const [text, setText] = useState(""); const [matchCase, setMatchCase] = useState(false); const [matchWholeWord, setMatchWholeWord] = useState(false); const [useRegularExpression, setUseRegularExpression] = useState(false); const [errorMessage, setErrorMessage] = useState(""); const createMatcher = useMemo(() => { return (searchText: string) => { try { setErrorMessage(""); // Сбрасываем ошибку при новой попытке return (content: string) => { if (!searchText) return true; const flags = matchCase ? "" : "i"; if (useRegularExpression) { return new RegExp(searchText, flags).test(content); } let pattern = searchText.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); // Экранируем спецсимволы if (matchWholeWord) { pattern = `\\b${pattern}\\b`; } return new RegExp(pattern, flags).test(content); }; } catch (err: any) { setErrorMessage(err.message); return () => true; // Возвращаем "безопасный" матчер в случае ошибки } }; }, [matchCase, matchWholeWord, useRegularExpression]); useEffect(() => { props.onSearch(createMatcher(text), { text, matchCase, matchWholeWord, useRegularExpression, }); }, [matchCase, matchWholeWord, useRegularExpression, createMatcher]); // Убрали text из зависимостей const handleChange = (e: ChangeEvent) => { const value = e.target.value; setText(value); props.onSearch(createMatcher(value), { text: value, matchCase, matchWholeWord, useRegularExpression, }); }; const getToggleVariant = (isActive: boolean) => isActive ? "secondary" : "ghost"; return (
{/* Добавляем правый отступ, чтобы текст не заезжал под иконки */} {/* Контейнер для иконок, абсолютно спозиционированный справа */}

{t("Match Case")}

{t("Match Whole Word")}

{t("Use Regular Expression")}

{/* Отображение ошибки под полем ввода */} {errorMessage && (

{errorMessage}

)}
); };