feat(studio): render queue, layout restructure, home page, hover preview (#95)

## Summary
- Add render queue panel with progress tracking, download, and delete actions
- Restructure App layout: home page with project picker, session-based routing
- Add ExpandOnHover component for preview-on-hover interactions (uses motion/react)
- CompositionsTab now supports hover preview with expanded iframe view
- Vite config: guard setInterval cleanup to dev-only (fixes CI build timeout)
- Add favicon and update studio package deps

## Test plan
- [x] Render queue shows progress, completes, and allows download
- [x] Home page lists projects and navigates to session view
- [x] ExpandOnHover shows expanded preview on mouse hover with spring animation
- [x] `vite build` exits cleanly (no hanging process from setInterval)

🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
Miguel Ángel
2026-03-28 21:28:43 +01:00
committed by GitHub
parent 9ae239d177
commit 40bd159103
24 changed files with 2495 additions and 796 deletions
@@ -1,4 +1,5 @@
import { memo, useRef, useState, useCallback, useEffect } from "react";
import { useMountEffect } from "../../hooks/useMountEffect";
interface VideoThumbnailProps {
videoSrc: string;
@@ -55,15 +56,15 @@ export const VideoThumbnail = memo(function VideoThumbnail({
roRef.current.observe(target);
}, []);
useEffect(
() => () => {
ioRef.current?.disconnect();
roRef.current?.disconnect();
},
[],
);
useMountEffect(() => () => {
ioRef.current?.disconnect();
roRef.current?.disconnect();
});
// Extract frames progressively — each frame appears as soon as it's ready
// Extract frames progressively — each frame appears as soon as it's ready.
// Note: useEffect with deps is acceptable — syncs with external video element API,
// requires cleanup (cancel extraction, revoke URLs) when inputs change.
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
if (!visible || extractingRef.current) return;
extractingRef.current = true;