mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 17:27:09 +00:00
fix(lint): flag autoAlpha on clip elements (#3692)
This commit is contained in:
@@ -481,6 +481,53 @@ describe("GSAP rules", () => {
|
||||
expect(finding?.message).toContain("visibility");
|
||||
});
|
||||
|
||||
it("ERRORS when GSAP animates autoAlpha on a clip element", async () => {
|
||||
const html = `
|
||||
<html><body>
|
||||
<div data-composition-id="c1" data-width="1920" data-height="1080">
|
||||
<div id="incoming" class="clip" data-start="1.01" data-duration="5" data-track-index="1">
|
||||
<p>Incoming scene</p>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
window.__timelines = window.__timelines || {};
|
||||
const tl = gsap.timeline({ paused: true });
|
||||
tl.fromTo("#incoming", { autoAlpha: 0 }, { autoAlpha: 1, duration: 0.3 }, 1.01);
|
||||
window.__timelines["c1"] = tl;
|
||||
</script>
|
||||
</body></html>`;
|
||||
|
||||
const result = await lintHyperframeHtml(html);
|
||||
const finding = result.findings.find((f) => f.code === "gsap_animates_clip_element");
|
||||
|
||||
expect(finding).toBeDefined();
|
||||
expect(finding?.severity).toBe("error");
|
||||
expect(finding?.message).toContain("autoAlpha");
|
||||
expect(finding?.fixHint).toContain("child");
|
||||
});
|
||||
|
||||
it("does NOT flag autoAlpha on content inside a clip", async () => {
|
||||
const html = `
|
||||
<html><body>
|
||||
<div data-composition-id="c1" data-width="1920" data-height="1080">
|
||||
<div id="incoming" class="clip" data-start="1.01" data-duration="5" data-track-index="1">
|
||||
<p id="content">Incoming scene</p>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
window.__timelines = window.__timelines || {};
|
||||
const tl = gsap.timeline({ paused: true });
|
||||
tl.fromTo("#content", { autoAlpha: 0 }, { autoAlpha: 1, duration: 0.3 }, 1.01);
|
||||
window.__timelines["c1"] = tl;
|
||||
</script>
|
||||
</body></html>`;
|
||||
|
||||
const result = await lintHyperframeHtml(html);
|
||||
const finding = result.findings.find((f) => f.code === "gsap_animates_clip_element");
|
||||
|
||||
expect(finding).toBeUndefined();
|
||||
});
|
||||
|
||||
it("ERRORS when GSAP animates display on a clip element", async () => {
|
||||
const html = `
|
||||
<html><body>
|
||||
|
||||
@@ -1365,24 +1365,25 @@ export const gsapRules: LintRule<LintContext>[] = [
|
||||
});
|
||||
}
|
||||
|
||||
// gsap_animates_clip_element — only error when GSAP animates visibility/display
|
||||
// gsap_animates_clip_element — GSAP must not compete with the framework's
|
||||
// clip visibility window. autoAlpha owns visibility as well as opacity.
|
||||
for (const win of gsapWindows) {
|
||||
const sel = win.targetSelector;
|
||||
const clipInfo = clipIds.get(sel) || clipClasses.get(sel);
|
||||
if (!clipInfo) continue;
|
||||
const conflictingProps = win.properties.filter(
|
||||
(p) => p === "visibility" || p === "display",
|
||||
(p) => p === "visibility" || p === "display" || p === "autoAlpha",
|
||||
);
|
||||
if (conflictingProps.length === 0) continue;
|
||||
const elDesc = `<${clipInfo.tag}${clipInfo.id ? ` id="${clipInfo.id}"` : ""} class="${clipInfo.classes}">`;
|
||||
findings.push({
|
||||
code: "gsap_animates_clip_element",
|
||||
severity: "error",
|
||||
message: `GSAP animation sets ${conflictingProps.join(", ")} on a clip element. Selector "${sel}" resolves to element ${elDesc}. The framework manages clip visibility via ${conflictingProps.join("/")} — do not animate these properties on clip elements.`,
|
||||
message: `GSAP animation sets ${conflictingProps.join(", ")} on a clip element. Selector "${sel}" resolves to element ${elDesc}. The framework manages clip visibility, and autoAlpha writes visibility as well as opacity — do not animate these properties on clip elements.`,
|
||||
selector: sel,
|
||||
elementId: clipInfo.id || undefined,
|
||||
fixHint:
|
||||
"Remove the visibility/display tween, or move the content into a child <div> and target that instead.",
|
||||
"Remove the visibility/display/autoAlpha tween, or move the content into a child <div> and target that instead.",
|
||||
snippet: truncateSnippet(win.raw),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user