mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 06:15:39 -04:00
- useTimeAgo: replace per-instance intervals with shared useSyncExternalStore ticker - useTiltEffect: gate to fine-pointer devices, skip motion graphs on touch - Carousel: bake WheelGesturesPlugin into primitive, remove from all consumers - TitleSeasons: use memoized Set + precomputed progress map instead of Array.includes - useSearch: stabilize results identity with useMemo - CommandPalette: hoist shortcut grouping to module scope, stabilize effect deps - StarRating: hoist static spring transition to module constant - Settings toggles: use useOptimistic + useTransition for auto-rollback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
40 lines
869 B
TypeScript
40 lines
869 B
TypeScript
import { useMemo } from "react";
|
|
import useSWR from "swr";
|
|
import { fetcher } from "@/lib/swr/fetcher";
|
|
|
|
interface SearchResponse {
|
|
results: {
|
|
tmdbId: number;
|
|
type: "movie" | "tv" | "person";
|
|
title: string;
|
|
posterPath: string | null;
|
|
profilePath?: string | null;
|
|
releaseDate: string | null;
|
|
voteAverage: number;
|
|
knownFor?: string[];
|
|
knownForDepartment?: string;
|
|
}[];
|
|
}
|
|
|
|
export function useSearch(debouncedQuery: string) {
|
|
const trimmed = debouncedQuery.trim();
|
|
const { data, isLoading } = useSWR<SearchResponse>(
|
|
trimmed ? `/api/search?query=${encodeURIComponent(trimmed)}` : null,
|
|
fetcher,
|
|
{
|
|
revalidateOnFocus: false,
|
|
dedupingInterval: 2_000,
|
|
},
|
|
);
|
|
|
|
const results = useMemo(
|
|
() => data?.results?.slice(0, 8) ?? [],
|
|
[data?.results],
|
|
);
|
|
|
|
return {
|
|
results,
|
|
isLoading,
|
|
};
|
|
}
|