Skip to content
14 changes: 14 additions & 0 deletions packages/studio/src/components/editor/manualEditsDom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR,
STUDIO_ORIGINAL_WIDTH_ATTR,
STUDIO_ORIGINAL_HEIGHT_ATTR,
STUDIO_ORIGINAL_BOX_WIDTH_ATTR,
STUDIO_ORIGINAL_BOX_HEIGHT_ATTR,
STUDIO_ORIGINAL_MIN_WIDTH_ATTR,
STUDIO_ORIGINAL_MIN_HEIGHT_ATTR,
STUDIO_ORIGINAL_MAX_WIDTH_ATTR,
Expand Down Expand Up @@ -358,6 +360,18 @@ function writeStudioBoxSizeVars(
element: HTMLElement,
size: { width: number; height: number },
): 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)) {
element.setAttribute(STUDIO_ORIGINAL_WIDTH_ATTR, element.style.getPropertyValue("width"));
element.setAttribute(STUDIO_ORIGINAL_HEIGHT_ATTR, element.style.getPropertyValue("height"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR,
STUDIO_ORIGINAL_WIDTH_ATTR,
STUDIO_ORIGINAL_HEIGHT_ATTR,
STUDIO_ORIGINAL_BOX_WIDTH_ATTR,
STUDIO_ORIGINAL_BOX_HEIGHT_ATTR,
STUDIO_ORIGINAL_MIN_WIDTH_ATTR,
STUDIO_ORIGINAL_MIN_HEIGHT_ATTR,
STUDIO_ORIGINAL_MAX_WIDTH_ATTR,
Expand Down Expand Up @@ -222,6 +224,9 @@ describe("buildBoxSizePatches / buildClearBoxSizePatches", () => {
{ type: "attribute", property: STUDIO_ORIGINAL_WIDTH_ATTR, value: null },
{ type: "inline-style", property: "height", value: "150px" },
{ type: "attribute", property: STUDIO_ORIGINAL_HEIGHT_ATTR, value: null },
// Measurements, so they are cleared without restoring a style.
{ type: "attribute", property: STUDIO_ORIGINAL_BOX_WIDTH_ATTR, value: null },
{ type: "attribute", property: STUDIO_ORIGINAL_BOX_HEIGHT_ATTR, value: null },
{ type: "inline-style", property: "min-width", value: "0px" },
{ type: "attribute", property: STUDIO_ORIGINAL_MIN_WIDTH_ATTR, value: null },
{ type: "inline-style", property: "min-height", value: "0px" },
Expand Down Expand Up @@ -257,11 +262,25 @@ describe("buildBoxSizePatches / buildClearBoxSizePatches", () => {

it("clear: bare element emits only null ops — no style restores fire when orig attrs are absent", () => {
const ops = buildClearBoxSizePatches(div());
// 3 fixed (studio-width, studio-height, box-size marker) + 14 attr-null pushes (one per BOX_SIZE_ORIG_ATTR)
expect(ops).toHaveLength(17);
// 3 fixed (studio-width, studio-height, box-size marker) + 16 attr-null pushes (one per BOX_SIZE_ORIG_ATTR)
expect(ops).toHaveLength(19);
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", () => {
const e = populatedBoxEl();
assertClearCoversKeys(buildBoxSizePatches(e), buildClearBoxSizePatches(e));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR,
STUDIO_ORIGINAL_WIDTH_ATTR,
STUDIO_ORIGINAL_HEIGHT_ATTR,
STUDIO_ORIGINAL_BOX_WIDTH_ATTR,
STUDIO_ORIGINAL_BOX_HEIGHT_ATTR,
STUDIO_ORIGINAL_MIN_WIDTH_ATTR,
STUDIO_ORIGINAL_MIN_HEIGHT_ATTR,
STUDIO_ORIGINAL_MAX_WIDTH_ATTR,
Expand Down Expand Up @@ -135,6 +137,9 @@ const BOX_SIZE_STYLE_PROPS = [
const BOX_SIZE_ORIG_ATTRS: ReadonlyArray<[string, string]> = [
[STUDIO_ORIGINAL_WIDTH_ATTR, "width"],
[STUDIO_ORIGINAL_HEIGHT_ATTR, "height"],
// Records a measurement rather than a style, so it restores nothing.
[STUDIO_ORIGINAL_BOX_WIDTH_ATTR, ""],
[STUDIO_ORIGINAL_BOX_HEIGHT_ATTR, ""],
[STUDIO_ORIGINAL_MIN_WIDTH_ATTR, "min-width"],
[STUDIO_ORIGINAL_MIN_HEIGHT_ATTR, "min-height"],
[STUDIO_ORIGINAL_MAX_WIDTH_ATTR, "max-width"],
Expand Down
6 changes: 6 additions & 0 deletions packages/studio/src/components/editor/manualEditsSnapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR,
STUDIO_ORIGINAL_WIDTH_ATTR,
STUDIO_ORIGINAL_HEIGHT_ATTR,
STUDIO_ORIGINAL_BOX_WIDTH_ATTR,
STUDIO_ORIGINAL_BOX_HEIGHT_ATTR,
STUDIO_ORIGINAL_MIN_WIDTH_ATTR,
STUDIO_ORIGINAL_MIN_HEIGHT_ATTR,
STUDIO_ORIGINAL_MAX_WIDTH_ATTR,
Expand Down Expand Up @@ -60,6 +62,8 @@ export function captureStudioBoxSize(element: HTMLElement): StudioBoxSizeSnapsho
marker: element.getAttribute(STUDIO_BOX_SIZE_ATTR),
originalWidth: element.getAttribute(STUDIO_ORIGINAL_WIDTH_ATTR),
originalHeight: element.getAttribute(STUDIO_ORIGINAL_HEIGHT_ATTR),
originalBoxWidth: element.getAttribute(STUDIO_ORIGINAL_BOX_WIDTH_ATTR),
originalBoxHeight: element.getAttribute(STUDIO_ORIGINAL_BOX_HEIGHT_ATTR),
originalMinWidth: element.getAttribute(STUDIO_ORIGINAL_MIN_WIDTH_ATTR),
originalMinHeight: element.getAttribute(STUDIO_ORIGINAL_MIN_HEIGHT_ATTR),
originalMaxWidth: element.getAttribute(STUDIO_ORIGINAL_MAX_WIDTH_ATTR),
Expand Down Expand Up @@ -128,6 +132,8 @@ export function restoreStudioBoxSize(element: HTMLElement, previous: StudioBoxSi
restoreAttribute(element, STUDIO_BOX_SIZE_ATTR, previous.marker);
restoreAttribute(element, STUDIO_ORIGINAL_WIDTH_ATTR, previous.originalWidth);
restoreAttribute(element, STUDIO_ORIGINAL_HEIGHT_ATTR, previous.originalHeight);
restoreAttribute(element, STUDIO_ORIGINAL_BOX_WIDTH_ATTR, previous.originalBoxWidth);
restoreAttribute(element, STUDIO_ORIGINAL_BOX_HEIGHT_ATTR, previous.originalBoxHeight);
restoreAttribute(element, STUDIO_ORIGINAL_MIN_WIDTH_ATTR, previous.originalMinWidth);
restoreAttribute(element, STUDIO_ORIGINAL_MIN_HEIGHT_ATTR, previous.originalMinHeight);
restoreAttribute(element, STUDIO_ORIGINAL_MAX_WIDTH_ATTR, previous.originalMaxWidth);
Expand Down
14 changes: 14 additions & 0 deletions packages/studio/src/components/editor/manualEditsTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ export const STUDIO_ORIGINAL_TRANSLATE_ATTR = "data-hf-studio-original-translate
export const STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR = "data-hf-studio-original-inline-translate";
export const STUDIO_ORIGINAL_WIDTH_ATTR = "data-hf-studio-original-width";
export const STUDIO_ORIGINAL_HEIGHT_ATTR = "data-hf-studio-original-height";
/**
* The element's laid-out box before a resize draft touched it, in CSS pixels.
*
* The two attributes above record the element's INLINE width and height so a
* reset can put them back, and are empty for the usual case of an element sized
* by the stylesheet. That made them useless as a measurement, and the resize
* intercept, which needs the original box to work out a scale, fell back to a
* hardcoded guess and produced a wildly wrong one. These record the measurement
* instead, and restore nothing.
*/
export const STUDIO_ORIGINAL_BOX_WIDTH_ATTR = "data-hf-studio-original-box-width";
export const STUDIO_ORIGINAL_BOX_HEIGHT_ATTR = "data-hf-studio-original-box-height";
export const STUDIO_ORIGINAL_MIN_WIDTH_ATTR = "data-hf-studio-original-min-width";
export const STUDIO_ORIGINAL_MIN_HEIGHT_ATTR = "data-hf-studio-original-min-height";
export const STUDIO_ORIGINAL_MAX_WIDTH_ATTR = "data-hf-studio-original-max-width";
Expand Down Expand Up @@ -70,6 +82,8 @@ export interface StudioBoxSizeSnapshot {
marker: string | null;
originalWidth: string | null;
originalHeight: string | null;
originalBoxWidth: string | null;
originalBoxHeight: string | null;
originalMinWidth: string | null;
originalMinHeight: string | null;
originalMaxWidth: string | null;
Expand Down
Loading
Loading