fix(core): scope selector arrays within compositions (#4035)

Co-authored-by: heygengenesis[bot] <262951085+heygengenesis[bot]@users.noreply.github.com>
Co-authored-by: miguel.sierra <229591595+miguel-heygen@users.noreply.github.com>
This commit is contained in:
heygengenesis[bot]
2026-09-18 11:12:52 -04:00
committed by GitHub
co-authored by miguel.sierra
parent e36a53d6b6
commit 27303658c1
2 changed files with 47 additions and 2 deletions
@@ -384,6 +384,44 @@ window.__timelines.scene = tl;
expect(gsapTargets).toEqual([["Scene"], ["Scene"]]);
});
it("scopes each selector in a GSAP target array to the composition root", () => {
const { document } = parseHTML(`
<div data-composition-id="scene">
<h1 class="title">Scene title</h1>
<p class="subtitle">Scene subtitle</p>
</div>
<div data-composition-id="other">
<h1 class="title">Other title</h1>
<p class="subtitle">Other subtitle</p>
</div>
`);
const targetCompositions: Array<string | null> = [];
const fakeWindow = {
document,
__timelines: {},
gsap: {
to(targets: Array<string | Element>) {
const resolvedTargets = targets.flatMap((target) =>
typeof target === "string" ? Array.from(document.querySelectorAll(target)) : [target],
);
targetCompositions.push(
...resolvedTargets.map((target) =>
target.closest("[data-composition-id]")?.getAttribute("data-composition-id"),
),
);
},
},
};
const wrapped = wrapScopedCompositionScript(
`gsap.to(['.title', '.subtitle'], { opacity: 1 });`,
"scene",
);
new Function("window", "gsap", wrapped)(fakeWindow, fakeWindow.gsap);
expect(targetCompositions).toEqual(["scene", "scene"]);
});
it("scopes getElementById when duplicate IDs exist across composition roots", () => {
const { document } = parseHTML(`
<div data-composition-id="scene-a"><canvas id="gl-canvas"></canvas></div>
@@ -524,8 +524,15 @@ export function wrapScopedCompositionScript(
})
: window;
var __hfResolveGsapTarget = function(target) {
if (typeof target !== "string") return target;
return __hfQueryAll(target);
if (typeof target === "string") return __hfQueryAll(target);
if (!Array.isArray(target)) return target;
return target.reduce(function(resolved, item) {
if (typeof item === "string") {
return resolved.concat(Array.prototype.slice.call(__hfQueryAll(item)));
}
resolved.push(item);
return resolved;
}, []);
};
var __hfScopeTimeline = function(timeline) {
if (!timeline || timeline.__hfScopedCompositionRoot === __hfFindRoot()) return timeline;