import type { EnvironmentId } from "@t3tools/contracts"; import { isProjectFaviconFallbackUrl } from "@t3tools/shared/projectFavicon"; import { FolderIcon } from "lucide-react"; import type { ComponentType } from "react"; import { useState } from "react"; import { useAssetUrl } from "../assets/assetUrls"; const loadedProjectFaviconSrcs = new Set(); export function ProjectFavicon(input: { environmentId: EnvironmentId; cwd: string; className?: string | undefined; fallbackIcon?: ComponentType<{ className?: string }>; }) { const src = useAssetUrl(input.environmentId, { _tag: "project-favicon", cwd: input.cwd, }); const FallbackIcon = input.fallbackIcon ?? FolderIcon; if (!src || isProjectFaviconFallbackUrl(src)) { return ; } return ( ); } function ProjectFaviconFallback({ className, icon: Icon, }: { readonly className?: string | undefined; readonly icon: ComponentType<{ className?: string }>; }) { return ; } function ProjectFaviconImage({ src, className, fallbackIcon: FallbackIcon, }: { readonly src: string; readonly className?: string | undefined; readonly fallbackIcon: ComponentType<{ className?: string }>; }) { const [status, setStatus] = useState<"loading" | "loaded" | "error">(() => loadedProjectFaviconSrcs.has(src) ? "loaded" : "loading", ); return ( <> {status !== "loaded" ? ( ) : null} { loadedProjectFaviconSrcs.add(src); setStatus("loaded"); }} onError={() => setStatus("error")} /> ); }