import { cn } from "@/lib/utils"; import type { PreviewTab, Tab } from "@/modules/tabs"; import { useEffect, useRef } from "react"; import { PreviewPane, type PreviewPaneHandle } from "./PreviewPane"; type Props = { tabs: Tab[]; activeId: number; onUrlChange: (id: number, url: string) => void; registerHandle: (id: number, handle: PreviewPaneHandle | null) => void; }; export function PreviewStack({ tabs, activeId, onUrlChange, registerHandle, }: Props) { const previews = tabs.filter((t): t is PreviewTab => t.kind === "preview"); const registerRef = useRef(registerHandle); const urlChangeRef = useRef(onUrlChange); useEffect(() => { registerRef.current = registerHandle; }, [registerHandle]); useEffect(() => { urlChangeRef.current = onUrlChange; }, [onUrlChange]); const refCallbacks = useRef( new Map void>(), ); const urlCallbacks = useRef(new Map void>()); const getRefCallback = (id: number) => { let cb = refCallbacks.current.get(id); if (!cb) { cb = (h: PreviewPaneHandle | null) => registerRef.current(id, h); refCallbacks.current.set(id, cb); } return cb; }; const getUrlCallback = (id: number) => { let cb = urlCallbacks.current.get(id); if (!cb) { cb = (url: string) => urlChangeRef.current(id, url); urlCallbacks.current.set(id, cb); } return cb; }; useEffect(() => { const live = new Set(previews.map((t) => t.id)); for (const id of refCallbacks.current.keys()) { if (!live.has(id)) refCallbacks.current.delete(id); } for (const id of urlCallbacks.current.keys()) { if (!live.has(id)) urlCallbacks.current.delete(id); } }, [previews]); if (previews.length === 0) return null; return (
{previews.map((t) => { const visible = t.id === activeId; return (
); })}
); }