feat(gsap): read timelines authored inline (acorn read path) (#1760)

* feat(studio): element groups — source mutations

Wrap/unwrap source mutations (group geometry, the wrap-elements / unwrap-elements
routes) that the studio group feature is built on. Studio UI lands in the next PR.

* fix(studio): hoverable group interior + non-sticky drill-in

Two group selection bugs with animated members:

1) Empty space inside a group's overlay didn't hover/select the group. Members
   animated outside the wrapper's static box (110px box vs 340px member union),
   so elementsFromPoint hit only the full-bleed background there. Add a
   member-union hit-test fallback: a point inside a group's live member bounds
   resolves to that group (innermost wins).

2) After drilling into a group and selecting a child, nothing else was
   selectable — out-of-scope resolved to null. Make drill-in non-sticky:
   interacting outside the drilled group re-resolves normally and exits the
   drill-in, so a later click on the group selects it as a unit again.

* feat(studio): enable animation editing for static inline timelines

The unsupported-pattern banner now clears for static window.__timelines["id"] =
gsap.timeline() (the parser reports it editable), and the banner copy is retargeted
to the genuinely-unsupported case: computed/dynamic keys (window.__timelines[var]).
This commit is contained in:
Miguel Ángel
2026-06-27 11:27:53 -04:00
committed by GitHub
parent 1eed7a9b1f
commit 2e02bcf77a
7 changed files with 488 additions and 67 deletions
@@ -46,9 +46,9 @@ export const GsapAnimationSection = memo(function GsapAnimationSection({
)}
{unsupportedTimelinePattern && (
<p className="mb-2 rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-amber-400">
This composition uses a timeline assignment pattern (window.__timelines[...]) that the
editor doesn&apos;t support. Use a variable declaration (const tl = gsap.timeline()) to
enable editing.
This timeline uses a computed key (window.__timelines[variable]) the editor can&apos;t
resolve statically. Use a string-literal key (window.__timelines[&quot;id&quot;]) or a
variable declaration (const tl = gsap.timeline()) to enable editing.
</p>
)}
{multipleTimelines || unsupportedTimelinePattern ? null : (