Download src/modules/preview/PreviewStack.tsx from lekmikdok/termix: direct link, hf CLI and curl.
- Browser
- Download file 2.43 kB
-
https://huggingface.co/spaces/lekmikdok/termix/resolve/main/src/modules/preview/PreviewStack.tsx
- Command line
-
hf download hf://spaces/lekmikdok/termix/src/modules/preview/PreviewStack.tsx
-
curl -L -o PreviewStack.tsx https://huggingface.co/spaces/lekmikdok/termix/resolve/main/src/modules/preview/PreviewStack.tsx
2.43 kB
| 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<number, (h: PreviewPaneHandle | null) => void>(), | |
| ); | |
| const urlCallbacks = useRef(new Map<number, (url: string) => 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 ( | |
| <div className="relative h-full w-full"> | |
| {previews.map((t) => { | |
| const visible = t.id === activeId; | |
| return ( | |
| <div | |
| key={t.id} | |
| className={cn( | |
| "absolute inset-0", | |
| !visible && "invisible pointer-events-none", | |
| )} | |
| aria-hidden={!visible} | |
| > | |
| <PreviewPane | |
| ref={getRefCallback(t.id)} | |
| url={t.url} | |
| visible={visible} | |
| onUrlChange={getUrlCallback(t.id)} | |
| /> | |
| </div> | |
| ); | |
| })} | |
| </div> | |
| ); | |
| } | |