import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useSearchParams } from "react-router"; import ButtonPrimary from "../buttons/ButtonPrimary"; import clsx from "clsx"; import { TextInput } from "~/ui/components/TextInput"; interface Props { onNew?: () => void; onNewRoute?: string; placeholder?: string; size?: "xs" | "sm" | "lg"; className?: string; } // Subframe migration (strangler shim): renders Subframe TextInput with type="search" // (built-in search icon) behind the original API. The debounced URL-sync logic is // unchanged. Subframe's own SearchInput is presentational only and cannot back a // controlled field. See docs/subframe/COMPONENT-MAPPING.md. export default function InputSearchWithURL({ onNew, onNewRoute, placeholder, size = "lg", className }: Props) { const [searchParams, setSearchParams] = useSearchParams(); const { t } = useTranslation(); const [search, setSearch] = useState(searchParams.get("q")?.toString() ?? ""); const [debouncedSearch, setDebouncedSearch] = useState(searchParams.get("q")?.toString() ?? ""); useEffect(() => { const timer = setTimeout(() => setDebouncedSearch(search), 500); return () => clearTimeout(timer); }, [search]); useEffect(() => { const query = searchParams.get("q") ?? ""; if (query !== debouncedSearch) { searchParams.set("q", debouncedSearch); if (searchParams.get("page")) { searchParams.set("page", "1"); } if (searchParams.get("pageSize")) { // searchParams.delete("pageSize"); } setSearchParams(searchParams, { preventScrollReset: true, }); } }, [debouncedSearch, searchParams, setSearchParams]); const resolvedPlaceholder = placeholder ?? t("shared.searchDot"); return (
setSearch(e.currentTarget.value)} autoComplete="off" /> {onNew && {t("shared.new")}} {onNewRoute && {t("shared.new")}}
); }