feat(studio): timeline inline expansion + __clipTree runtime primitive#1468
Open
miguel-heygen wants to merge 1 commit into
Open
feat(studio): timeline inline expansion + __clipTree runtime primitive#1468miguel-heygen wants to merge 1 commit into
miguel-heygen wants to merge 1 commit into
Conversation
4a7cda7 to
071ddcd
Compare
When a child element inside a sub-composition is selected, the timeline replaces the parent scene clip with the deepest-level siblings. Deselect or selecting outside collapses back. Expanded clips are fully editable — move, resize, delete, and split — addressed by their real DOM id with timeline time rebased onto the sub-comp they live in. Runtime: - New window.__clipTree API: a read-only hierarchical ClipNode tree (id/parentId/children + backing element) so Studio can derive parent/child relationships for inline expansion. Studio: - useExpandedTimelineElements derives the expanded view from selectedElementId + clipParentMap (pure useMemo, no useEffect). Each child rebases onto its immediate sub-comp host (start + sourceFile), so multi-level nesting targets the right file. - NLELayout routes expanded-clip edits through the same handlers top-level clips use, in local coordinates — edits save to the sub-comp source and reflect via reloadPreview (no separate DOM-patch path). This is the canonical update; there is no reactive observer. - findMatchingTimelineElementId resolves sub-comp children with no top-level element to `sourceFile#id`. - Razor tool enabled by default; studio_razor_split analytics event fired on single and split-all. - O(n²) isElementGsapTargeted extracted to gsapTargetCache.ts with a cached Set+WeakSet O(1) lookup.
071ddcd to
8a3c90e
Compare
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.
Timeline inline expansion + expanded-clip editing
When you select a child element inside a sub-composition, the timeline replaces the parent scene clip with that depth's siblings as individual, editable clips. Deselect (or click the empty preview area) collapses back. Built on a new
window.__clipTreeruntime primitive.Runtime —
packages/core/src/runtime/clipTree.tswindow.__clipTree: hierarchicalClipNodetree (id/parentId/children) built from all[data-start]elements, plusupdateTiming()which patchesdata-start/data-durationon the DOM and invalidates GSAP timelines for instant feedback (no iframe reload).postMessageso Studio sees it on first sync; rebuilt only when the[data-start]element count changes (sub-comps loading), not every transport tick.RuntimeTimelineLikegainsinvalidate?()so the call is typed.getNode/getAbsoluteTime/onChange/postMessage/label/kind/etc. with zero callers — stripped.)Studio
useExpandedTimelineElements— pureuseMemoderiving the expanded view fromselectedElementId+clipParentMap. NouseEffect, no store writes. Each expanded child is rebased onto its own sub-comp host (expandedParentStart+sourceFile), correct at any nesting depth.findMatchingTimelineElementId— returns asourceFile#idqualified id for sub-comp children that have no top-level timeline element, so the expansion hook can resolve them.NLELayout— move/resize/delete/split on expanded clips rebase absolute→local time viaexpandedParentStart, remapid ← domId, and route through the existing source-patch persistence (sourceFile-aware). Move/resize also patch the DOM via__clipTree.updateTimingfor instant feedback. Clicking the empty preview area deselects.gsapTargetCache— O(1) cachedSet+WeakSetGSAP-target lookup replacing the O(n²) inline scan.GSAP / keyframe correctness (traced per path)
All edit paths resolve the target file from the element/selection
sourceFileand scan allwindow.__timelines(which include inlined sub-comp timelines):useRazorSplituseselement.sourceFile. ✅useGsapScriptCommits/StudioPreviewAreauseselection.sourceFile. ✅sourceFile#id, scans all timelines. ✅useExpandedTimelineElements.test.ts, 1-level + 2-level cases).Verification
index.htmland other scenes untouched.findMatchingTimelineElementIdandbuildExpandedElements.Manual-confirm checklist before relying on these (drag/seek paths the automated harness can't drive)
data-start/data-durationpersist to the sub-comp HTML at correct local time.Known limitation
s-key split shortcut looks up the selection in raw (non-expanded) elements, so it no-ops on an expanded clip. The razor-tool click path covers split; left as follow-up.Plan:
docs/plans/2026-06-15-003-feat-expanded-clip-editing-plan.md