/** * CapCut-style asset preview overlay rendered inside PreviewPane. * * Shown when the user clicks an asset card that has NOT yet been added to the * timeline. Displays the media (image / video / audio) as a compact floating * card over the canvas — the canvas stays visible behind a barely-tinted * click-catcher — without modifying the composition (no undo entry, no file * mutation). * * Dismiss: X button, Escape key, click outside the card, or any playhead * activity (starting playback / seeking) — the canvas refocuses. * Switching to another not-added asset replaces the current preview. */ import { useEffect, useCallback } from "react"; import { VIDEO_EXT, IMAGE_EXT } from "../../utils/mediaTypes"; import { useAssetPreviewStore } from "../../utils/assetPreviewStore"; import { usePlayerStore } from "../../player/store/playerStore"; import { shouldDismissAssetPreview } from "../../utils/assetPreviewDismiss"; import { resolveMediaPreviewUrl } from "../../player/components/thumbnailUtils"; function basename(path: string): string { return path.split("/").pop() ?? path; } type AssetKind = "image" | "video" | "audio"; function resolveAssetKind(path: string): AssetKind { if (VIDEO_EXT.test(path)) return "video"; if (IMAGE_EXT.test(path)) return "image"; return "audio"; } /** The media element for a previewed asset, chosen by kind. */ function AssetPreviewMedia({ kind, serveUrl, name, }: { kind: AssetKind; serveUrl: string; name: string; }) { if (kind === "image") { return ( {name} ); } if (kind === "video") { return (