Files
hyperframes/docs/packages/studio.mdx
T
Miguel Ángel 2cf3558f8e fix(studio): only expose front trim for offsettable clips (#413)
## Summary
- hide the leading trim handle for timeline clips that cannot offset their own content
- keep leading trim available for media clips backed by playback offset metadata or source duration
- map visual row priority like a normal timeline editor: top timeline rows render above lower rows

## Why This Is Needed
Generic GSAP/DOM timeline clips do not have a playback-offset model like media clips do.

That means a left trim affordance on those clips is misleading today:
- users reasonably expect front trim to remove the beginning of the animation
- the current model can only shorten the clip window, not start the motion halfway through

Instead of exposing a control that implies unsupported behavior, this PR keeps true front trim only on clips that can actually offset their content.

The PR also fixes the stacking convention so the timeline matches normal editor expectations:
- visually higher track row = higher render priority
- visually lower track row = lower render priority

## Current Flow By Element Type
### Generic motion / DOM clips
Examples: `section`, `div`, `aside`, GSAP-driven cards and overlays.

Current supported flow:
- drag the whole clip horizontally to change `data-start`
- right-trim to shorten the end of the clip window
- move between tracks to change `data-track-index`

Not supported yet:
- true front trim that removes the beginning of the animation itself

Behavior after this PR:
- no interactive left trim handle is shown
- right trim still works
- horizontal move still works

### Media clips
Examples: `video` / `audio` clips, or wrappers carrying `data-media-start` / `data-playback-start`.

Current supported flow:
- drag the whole clip horizontally to change `data-start`
- left trim advances clip start and playback offset together
- right trim shortens `data-duration`

Behavior after this PR:
- both left and right trim handles remain available
- left trim persists `data-start` plus `data-media-start` / `data-playback-start`
- right trim persists `data-duration`

## Z-Index Rule
This PR now follows the normal timeline-editor convention:
- top visual row on the timeline = highest `z-index`
- lower visual rows = lower `z-index`

Concretely, because Studio renders tracks in ascending numeric order from top to bottom, lower numeric track values now map to higher `z-index` values.

## Validation
### Automated
- `bun test packages/studio/src/player/components/timelineEditing.test.ts packages/studio/src/player/components/Timeline.test.ts packages/studio/src/player/store/playerStore.test.ts packages/studio/src/utils/sourcePatcher.test.ts`
- `bun run --filter @hyperframes/studio typecheck`

### Browser verification
Verified with `agent-browser` on `timeline-edit-playground`:
- generic motion clips no longer expose an interactive left trim handle
- media clips still expose both trim handles
- left trim on `media-card` persisted `data-start` and `data-media-start`
- right trim on `media-card` persisted `data-duration` only
- moving `title-card` from the bottom row to the top row persisted the highest `z-index` for the top-row clips
- recordings:
  - `/tmp/trim-fix-artifacts/trim-flow.webm`
  - `/tmp/trim-fix-artifacts/z-index-flow.webm`
2026-04-22 17:11:15 +02:00

271 lines
8.6 KiB
Plaintext

---
title: "@hyperframes/studio"
description: "Visual composition editor with live preview, timeline view, and hot reload."
---
The studio package provides a browser-based visual editor for creating and previewing Hyperframes compositions. It gives you a real-time preview of your video, a visual timeline of all clips, and player controls for seeking and playback — all updating live as you edit your HTML.
```bash
npm install @hyperframes/studio
```
## When to Use
**Use `@hyperframes/studio` when you need to:**
- Build a custom composition editor UI (e.g., embedded in your own web application)
- Integrate the Hyperframes preview player into a larger product
- Extend the editor with custom panels, toolbars, or integrations
**Use a different package if you want to:**
- Preview compositions during development — use the [CLI](/packages/cli) (`npx hyperframes preview`), which launches the studio for you
- Render compositions to MP4 — use the [CLI](/packages/cli) or [producer](/packages/producer)
- Capture frames programmatically — use the [engine](/packages/engine)
<Tip>
**For most development workflows, you do not need to install the studio directly.** Running `npx hyperframes preview` starts the studio automatically with hot reload. Install `@hyperframes/studio` only if you are embedding the editor into your own application.
</Tip>
## Running the Studio
### Via the CLI (recommended)
```bash
npx hyperframes preview
```
This starts the studio development server, opens your composition in the browser, and watches for file changes. This is the easiest way to get a live preview.
### From the monorepo
```bash
# From the root
bun run dev
# Or target the studio package directly
bun run --filter @hyperframes/studio dev
```
## Package Exports
The studio has two entry points:
| Import | Description |
|--------|-------------|
| `@hyperframes/studio` | React components, hooks, and types |
| `@hyperframes/studio/tailwind-preset` | Tailwind CSS preset for studio styling |
Peer dependencies: `react` (18 or 19), `react-dom` (18 or 19), `zustand` (4 or 5).
## Components
### Layout
```typescript
import { NLELayout, NLEPreview, CompositionBreadcrumb } from '@hyperframes/studio';
import type { CompositionLevel } from '@hyperframes/studio';
// Main NLE (Non-Linear Editor) layout container
<NLELayout>
{/* Preview, timeline, and editor panels */}
</NLELayout>
// Preview panel
<NLEPreview />
// Breadcrumb navigation for nested compositions
<CompositionBreadcrumb levels={levels} />
```
### Player & Timeline
```typescript
import {
Player,
PlayerControls,
Timeline,
PreviewPanel,
AgentActivityTrack,
} from '@hyperframes/studio';
import type { AgentActivity, TimelineElement, ActiveEdits } from '@hyperframes/studio';
// Embed the preview player
<Player />
// Playback controls (play, pause, seek, frame-step)
<PlayerControls />
// Timeline editor with scrubber
<Timeline />
// Preview display area
<PreviewPanel />
// Activity visualization track (for agent workflows)
<AgentActivityTrack activities={activities} />
```
### Editor Components
```typescript
import { SourceEditor, PropertyPanel, FileTree } from '@hyperframes/studio';
// Code editor (CodeMirror-based) for HTML, CSS, and JavaScript
<SourceEditor />
// Property inspector for selected elements
<PropertyPanel />
// Project file browser
<FileTree />
```
### Full Application
```typescript
import { StudioApp } from '@hyperframes/studio';
// The complete studio application (wraps all components)
<StudioApp />
```
## Hooks
### `useTimelinePlayer`
Manages player state and playback control:
```typescript
import { useTimelinePlayer } from '@hyperframes/studio';
const player = useTimelinePlayer();
// player.play(), player.pause(), player.seek(time), player.stepForward(), player.stepBackward()
```
### `usePlayerStore`
Zustand store for player state:
```typescript
import { usePlayerStore, liveTime, formatTime } from '@hyperframes/studio';
const store = usePlayerStore();
// Access current time, duration, playing state, etc.
// Format time for display
const display = formatTime(liveTime.current);
```
### `useCodeEditor`
Code editor state and editing functions:
```typescript
import { useCodeEditor } from '@hyperframes/studio';
const editor = useCodeEditor();
// editor.code, editor.setCode(), editor.diff, editor.onChange()
```
### `useElementPicker`
Element selection from the preview:
```typescript
import { useElementPicker } from '@hyperframes/studio';
const picker = useElementPicker();
// picker.selectedElement, picker.selectElement(id), picker.clearSelection()
```
## Features
### Live Preview
The studio renders your composition in an iframe using the Hyperframes runtime. What you see in the preview is exactly what will be captured during rendering — the same runtime code, the same seek logic, the same clip lifecycle.
Changes to your HTML are picked up automatically through hot reload, so you can edit `index.html` in your editor and see the result in the browser within milliseconds.
<Note>
The *visual* output of preview matches render exactly. Real-time *playback smoothness* depends on your hardware, because preview actually plays the composition in your browser at 30/60fps. Render doesn't have that constraint — it captures each frame individually via a seek-driven pipeline, so expensive frames make the render slower but never drop. If you see stutter in preview but the rendered mp4 is clean, that's expected. See [Performance](/guides/performance) for the patterns that most often cause it.
</Note>
### Timeline View
The timeline panel provides a visual representation of your composition's structure:
- Each clip appears as a colored bar on its track
- Bar position and width reflect `data-start` and `data-duration`
- Visually higher rows render in front; lower rows render underneath
- Relative timing references (e.g., `data-start="intro"`) are resolved and displayed as absolute positions
This makes it easy to understand the temporal structure of complex compositions with many overlapping clips.
### Timeline Editing
The timeline supports move and trim actions that persist directly back into your HTML source.
For a full breakdown of:
- what timeline editing can do today
- how each action maps to `data-start`, `data-duration`, `data-track-index`, and `z-index`
- which clip types support start trim
- current limitations and mental models
see [Timeline Editing](/guides/timeline-editing).
### Player Controls
The studio includes a full set of playback controls:
- **Play / Pause** — start and stop playback
- **Seek** — click anywhere on the timeline to jump to that point
- **Scrub** — drag the playhead to scrub through the composition frame by frame
- **Frame step** — advance or rewind one frame at a time for precise positioning
### Hot Reload
File changes are detected and applied without restarting the server. The preview maintains its current playback position when possible, so you can tweak an animation at the 5-second mark without having to seek back to it after every save.
## Architecture
The studio is a React application with the following structure:
1. **Iframe preview** — your composition HTML is loaded in an isolated iframe with the Hyperframes runtime injected. This ensures the preview uses the same rendering path as production.
2. **Runtime bridge** — the studio communicates with the iframe via `postMessage` to control playback (play, pause, seek) and receive state updates (current time, duration, readiness).
3. **Timeline component** — parses the composition using `@hyperframes/core` to extract clip timing data and renders the visual timeline panel.
4. **File watcher** — a development server (Vite-based) watches your project files and triggers hot module replacement when changes are detected.
## Tailwind CSS Preset
The studio exports a Tailwind CSS preset for consistent styling:
```typescript
// tailwind.config.ts
import studioPreset from '@hyperframes/studio/tailwind-preset';
export default {
presets: [studioPreset],
// ... your config
};
```
## Related Packages
<CardGroup cols={2}>
<Card title="CLI" icon="terminal" href="/packages/cli">
Launches the studio via `npx hyperframes preview` — the easiest way to preview compositions.
</Card>
<Card title="Core" icon="cube" href="/packages/core">
Types, parsing, and runtime that the studio uses for preview and timeline rendering.
</Card>
<Card title="Producer" icon="film" href="/packages/producer">
Renders the compositions you build in the studio to finished MP4 files.
</Card>
<Card title="Engine" icon="gear" href="/packages/engine">
The capture engine that powers production rendering of your compositions.
</Card>
</CardGroup>