mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 14:50:02 +00:00
fix(studio): cover legacy resize boxes
This commit is contained in:
@@ -360,15 +360,21 @@ function writeStudioBoxSizeVars(
|
|||||||
element: HTMLElement,
|
element: HTMLElement,
|
||||||
size: { width: number; height: number },
|
size: { width: number; height: number },
|
||||||
): void {
|
): void {
|
||||||
|
// Keep the measurement on its own migration-safe guard. Elements drafted by
|
||||||
|
// an older Studio can already carry the box-size marker without these newer
|
||||||
|
// attributes; the next resize still reaches this function before its width
|
||||||
|
// and height are overwritten, so this is the last honest layout box to save.
|
||||||
|
// Offset sizes are layout values, so a running scale animation does not
|
||||||
|
// distort them.
|
||||||
|
if (!element.hasAttribute(STUDIO_ORIGINAL_BOX_WIDTH_ATTR)) {
|
||||||
|
element.setAttribute(STUDIO_ORIGINAL_BOX_WIDTH_ATTR, String(element.offsetWidth));
|
||||||
|
}
|
||||||
|
if (!element.hasAttribute(STUDIO_ORIGINAL_BOX_HEIGHT_ATTR)) {
|
||||||
|
element.setAttribute(STUDIO_ORIGINAL_BOX_HEIGHT_ATTR, String(element.offsetHeight));
|
||||||
|
}
|
||||||
if (!element.hasAttribute(STUDIO_BOX_SIZE_ATTR)) {
|
if (!element.hasAttribute(STUDIO_BOX_SIZE_ATTR)) {
|
||||||
element.setAttribute(STUDIO_ORIGINAL_WIDTH_ATTR, element.style.getPropertyValue("width"));
|
element.setAttribute(STUDIO_ORIGINAL_WIDTH_ATTR, element.style.getPropertyValue("width"));
|
||||||
element.setAttribute(STUDIO_ORIGINAL_HEIGHT_ATTR, element.style.getPropertyValue("height"));
|
element.setAttribute(STUDIO_ORIGINAL_HEIGHT_ATTR, element.style.getPropertyValue("height"));
|
||||||
// Measured here and only here: this branch runs once, before the draft
|
|
||||||
// writes a width, so it is the last moment the element still has the box
|
|
||||||
// the user started with. Offset sizes are layout, so a scale animation
|
|
||||||
// running on the element does not distort them.
|
|
||||||
element.setAttribute(STUDIO_ORIGINAL_BOX_WIDTH_ATTR, String(element.offsetWidth));
|
|
||||||
element.setAttribute(STUDIO_ORIGINAL_BOX_HEIGHT_ATTR, String(element.offsetHeight));
|
|
||||||
element.setAttribute(
|
element.setAttribute(
|
||||||
STUDIO_ORIGINAL_MIN_WIDTH_ATTR,
|
STUDIO_ORIGINAL_MIN_WIDTH_ATTR,
|
||||||
element.style.getPropertyValue("min-width"),
|
element.style.getPropertyValue("min-width"),
|
||||||
|
|||||||
@@ -267,6 +267,20 @@ describe("buildBoxSizePatches / buildClearBoxSizePatches", () => {
|
|||||||
expect(ops.every((op) => op.value === null)).toBe(true);
|
expect(ops.every((op) => op.value === null)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("backfills the measured box on a legacy element that already has the resize marker", () => {
|
||||||
|
const e = div();
|
||||||
|
e.setAttribute(STUDIO_BOX_SIZE_ATTR, "true");
|
||||||
|
Object.defineProperties(e, {
|
||||||
|
offsetWidth: { configurable: true, value: 630 },
|
||||||
|
offsetHeight: { configurable: true, value: 252 },
|
||||||
|
});
|
||||||
|
|
||||||
|
applyStudioBoxSize(e, { width: 320, height: 128 });
|
||||||
|
|
||||||
|
expect(e.getAttribute(STUDIO_ORIGINAL_BOX_WIDTH_ATTR)).toBe("630");
|
||||||
|
expect(e.getAttribute(STUDIO_ORIGINAL_BOX_HEIGHT_ATTR)).toBe("252");
|
||||||
|
});
|
||||||
|
|
||||||
it("build/clear symmetry: clear addresses every {type,property} key that build emits", () => {
|
it("build/clear symmetry: clear addresses every {type,property} key that build emits", () => {
|
||||||
const e = populatedBoxEl();
|
const e = populatedBoxEl();
|
||||||
assertClearCoversKeys(buildBoxSizePatches(e), buildClearBoxSizePatches(e));
|
assertClearCoversKeys(buildBoxSizePatches(e), buildClearBoxSizePatches(e));
|
||||||
|
|||||||
@@ -77,6 +77,21 @@ interface ResizeCase {
|
|||||||
positionWrite?: "static-set" | "keyframed-tween" | "none";
|
positionWrite?: "static-set" | "keyframed-tween" | "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createResizeElement(testCase: ResizeCase): HTMLElement {
|
||||||
|
const el = document.createElement("div");
|
||||||
|
el.id = "clip";
|
||||||
|
if (testCase.inlineSized) {
|
||||||
|
el.setAttribute("data-hf-studio-original-width", `${testCase.box.w}px`);
|
||||||
|
el.setAttribute("data-hf-studio-original-height", `${testCase.box.h}px`);
|
||||||
|
} else {
|
||||||
|
el.setAttribute("data-hf-studio-original-box-width", `${testCase.box.w}`);
|
||||||
|
el.setAttribute("data-hf-studio-original-box-height", `${testCase.box.h}`);
|
||||||
|
el.setAttribute("data-hf-studio-original-width", "");
|
||||||
|
el.setAttribute("data-hf-studio-original-height", "");
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
function scaleTween(longhand: boolean): GsapAnimation {
|
function scaleTween(longhand: boolean): GsapAnimation {
|
||||||
const at = (v: number) => (longhand ? { scaleX: v, scaleY: v } : { scale: v });
|
const at = (v: number) => (longhand ? { scaleX: v, scaleY: v } : { scale: v });
|
||||||
return {
|
return {
|
||||||
@@ -180,17 +195,7 @@ function persistedScale(calls: unknown[][]): { x: number; y: number } | null {
|
|||||||
|
|
||||||
async function runCase(testCase: ResizeCase) {
|
async function runCase(testCase: ResizeCase) {
|
||||||
const rotation = testCase.rotation ?? 0;
|
const rotation = testCase.rotation ?? 0;
|
||||||
const el = document.createElement("div");
|
const el = createResizeElement(testCase);
|
||||||
el.id = "clip";
|
|
||||||
if (testCase.inlineSized) {
|
|
||||||
el.setAttribute("data-hf-studio-original-width", `${testCase.box.w}px`);
|
|
||||||
el.setAttribute("data-hf-studio-original-height", `${testCase.box.h}px`);
|
|
||||||
} else {
|
|
||||||
el.setAttribute("data-hf-studio-original-box-width", `${testCase.box.w}`);
|
|
||||||
el.setAttribute("data-hf-studio-original-box-height", `${testCase.box.h}`);
|
|
||||||
el.setAttribute("data-hf-studio-original-width", "");
|
|
||||||
el.setAttribute("data-hf-studio-original-height", "");
|
|
||||||
}
|
|
||||||
// What the gesture stamps at drag start, and the draft it leaves applied.
|
// What the gesture stamps at drag start, and the draft it leaves applied.
|
||||||
el.setAttribute("data-hf-drag-gsap-base-x", `${testCase.base.x}`);
|
el.setAttribute("data-hf-drag-gsap-base-x", `${testCase.base.x}`);
|
||||||
el.setAttribute("data-hf-drag-gsap-base-y", `${testCase.base.y}`);
|
el.setAttribute("data-hf-drag-gsap-base-y", `${testCase.base.y}`);
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ it("non-uniform drag commits scaleX/scaleY longhands", async () => {
|
|||||||
* left it rendering at 7532px, over three times where it was dropped, and the
|
* left it rendering at 7532px, over three times where it was dropped, and the
|
||||||
* next drag compounded it.
|
* next drag compounded it.
|
||||||
*/
|
*/
|
||||||
|
// fallow-ignore-next-line code-duplication
|
||||||
it("scales from the element's real box, not a hardcoded fallback", async () => {
|
it("scales from the element's real box, not a hardcoded fallback", async () => {
|
||||||
const el = document.createElement("div");
|
const el = document.createElement("div");
|
||||||
el.id = "clip";
|
el.id = "clip";
|
||||||
@@ -339,6 +340,7 @@ it("scales from the element's real box, not a hardcoded fallback", async () => {
|
|||||||
* and the longhands won. The resize computed the right number, wrote it, and
|
* and the longhands won. The resize computed the right number, wrote it, and
|
||||||
* the element snapped straight back to its old size on release.
|
* the element snapped straight back to its old size on release.
|
||||||
*/
|
*/
|
||||||
|
// fallow-ignore-next-line code-duplication
|
||||||
it("does not mix the scale shorthand into a tween that speaks longhands", async () => {
|
it("does not mix the scale shorthand into a tween that speaks longhands", async () => {
|
||||||
const el = document.createElement("div");
|
const el = document.createElement("div");
|
||||||
el.id = "clip";
|
el.id = "clip";
|
||||||
|
|||||||
Reference in New Issue
Block a user