Fix Studio DOM picking and timeline thumbnails#529
Merged
miguel-heygen merged 1 commit intonextfrom Apr 28, 2026
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Manual DOM editing in Studio had a few rough edges that showed up when testing the latest alpha like a video editor would:
matrix(1, 0, 0, 1, 0, 0)were treated as transform-driven and could not be moved/resized directly, even when their layout was otherwise absolute px geometry.__node__index_*could lose their connection back to the real DOM node, which also blocked precise selector thumbnails and reliable timeline patch targets.What this fixes
none, identitymatrix(...), and identitymatrix3d(...)transforms as directly editable for DOM move/resize capability checks.selectorandselectorIndexthrough Studio timeline thumbnails and the core thumbnail API.querySelectorAll(selector)[selectorIndex]when generating cropped thumbnails in both Vite Studio preview and the CLI Studio server..clipselectors when a more specific class exists.captiondo not trigger caption-runtime warnings.Root cause
The DOM editor was using a strict
transform === "none"check. GSAP and browsers commonly leave identity transforms as computed matrices, so visually untransformed absolute elements were incorrectly downgraded into the layout-controlled path.The selected-box picker also mixed two intents on the same pointer path: click-to-repick and drag-to-move. Movable boxes started a gesture on pointerdown, which could suppress the normal click path before the exact child picker ran.
For thumbnails, Studio had the backend cropper but did not consistently pass enough identity information from timeline clips to the thumbnail route. Runtime manifests can emit synthetic ids for anonymous DOM clips, so the Studio side needed a DOM fallback to recover the actual element, selector, and occurrence index.
Verification
Local checks
bun run --filter @hyperframes/studio test src/components/editor/domEditing.test.ts src/player/components/timelineEditing.test.ts src/player/components/CompositionThumbnail.test.ts src/player/hooks/useTimelinePlayer.test.ts-> 66 tests passbun run --filter @hyperframes/core test src/lint/rules/captions.test.ts src/studio-api/routes/thumbnail.test.ts-> 10 tests passbun run --filter @hyperframes/studio typecheckbun run --filter @hyperframes/core typecheckbun run --filter @hyperframes/cli typecheckbunx oxlint packages/cli/src/server/studioServer.ts packages/core/src/lint/rules/captions.test.ts packages/core/src/lint/rules/captions.ts packages/core/src/studio-api/routes/thumbnail.test.ts packages/core/src/studio-api/routes/thumbnail.ts packages/core/src/studio-api/types.ts packages/studio/src/App.tsx packages/studio/src/components/editor/DomEditOverlay.tsx packages/studio/src/components/editor/domEditing.test.ts packages/studio/src/components/editor/domEditing.ts packages/studio/src/player/components/CompositionThumbnail.tsx packages/studio/src/player/components/CompositionThumbnail.test.ts packages/studio/src/player/components/timelineEditing.test.ts packages/studio/src/player/components/timelineEditing.ts packages/studio/src/player/hooks/useTimelinePlayer.test.ts packages/studio/src/player/hooks/useTimelinePlayer.ts packages/studio/vite.config.ts-> 0 warnings, 0 errorsgit diff --checkbun run --filter @hyperframes/studio buildBrowser verification
agent-browserto select an absolute layer with computedmatrix(1, 0, 0, 1, 0, 0)and verify normal X/Y/W/H controls were available.#identity-cardto#identity-title.selectorandselectorIndex, loaded successfully, and returned distinct cropped JPEGs.data-start/ track changes were written back.matrix-visual,matrix-code) to the scratch project and verified:hyperframes lint /tmp/hf-dom-edit-fix-verify-> 0 errors, 0 warningshyperframes compositions /tmp/hf-dom-edit-fix-verifylistedmain,matrix-visual, andmatrix-code/thumbnail/compositions/...matrix-visualshowed its inner clips and selector-specific thumbnailsagent-browser.Notes
/tmp/hf-dom-edit-fix-verifyand is intentionally not committed.qa-artifacts/and are intentionally not committed.agent-browser dblclickdid not reliably trigger timeline composition drill-in; sidebar composition navigation worked and verified the drilled-in composition path.