import { styleUsesStudioOffset, styleUsesStudioSize, styleUsesStudioRotation, restoreInlineDisplay, } from "./manualEditsDom"; import { STUDIO_OFFSET_X_PROP, STUDIO_OFFSET_Y_PROP, STUDIO_WIDTH_PROP, STUDIO_HEIGHT_PROP, STUDIO_ROTATION_PROP, STUDIO_PATH_OFFSET_ATTR, STUDIO_BOX_SIZE_ATTR, STUDIO_ROTATION_ATTR, STUDIO_ORIGINAL_TRANSLATE_ATTR, STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR, STUDIO_ORIGINAL_WIDTH_ATTR, STUDIO_ORIGINAL_HEIGHT_ATTR, STUDIO_ORIGINAL_MIN_WIDTH_ATTR, STUDIO_ORIGINAL_MIN_HEIGHT_ATTR, STUDIO_ORIGINAL_MAX_WIDTH_ATTR, STUDIO_ORIGINAL_MAX_HEIGHT_ATTR, STUDIO_ORIGINAL_FLEX_BASIS_ATTR, STUDIO_ORIGINAL_FLEX_GROW_ATTR, STUDIO_ORIGINAL_FLEX_SHRINK_ATTR, STUDIO_ORIGINAL_BOX_SIZING_ATTR, STUDIO_ORIGINAL_SCALE_ATTR, STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR, STUDIO_ORIGINAL_DISPLAY_ATTR, STUDIO_ORIGINAL_ROTATE_ATTR, STUDIO_ORIGINAL_INLINE_ROTATE_ATTR, STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR, STUDIO_ROTATION_DRAFT_ATTR, } from "./manualEditsTypes"; import type { StudioBoxSizeSnapshot, StudioRotationSnapshot, StudioPathOffsetSnapshot, } from "./manualEditsTypes"; /* ── Capture ──────────────────────────────────────────────────────── */ export function captureStudioBoxSize(element: HTMLElement): StudioBoxSizeSnapshot { return { width: element.style.getPropertyValue("width"), height: element.style.getPropertyValue("height"), minWidth: element.style.getPropertyValue("min-width"), minHeight: element.style.getPropertyValue("min-height"), maxWidth: element.style.getPropertyValue("max-width"), maxHeight: element.style.getPropertyValue("max-height"), flexBasis: element.style.getPropertyValue("flex-basis"), flexGrow: element.style.getPropertyValue("flex-grow"), flexShrink: element.style.getPropertyValue("flex-shrink"), boxSizing: element.style.getPropertyValue("box-sizing"), scale: element.style.getPropertyValue("scale"), transformOrigin: element.style.getPropertyValue("transform-origin"), display: element.style.getPropertyValue("display"), studioWidth: element.style.getPropertyValue(STUDIO_WIDTH_PROP), studioHeight: element.style.getPropertyValue(STUDIO_HEIGHT_PROP), marker: element.getAttribute(STUDIO_BOX_SIZE_ATTR), originalWidth: element.getAttribute(STUDIO_ORIGINAL_WIDTH_ATTR), originalHeight: element.getAttribute(STUDIO_ORIGINAL_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), originalMaxHeight: element.getAttribute(STUDIO_ORIGINAL_MAX_HEIGHT_ATTR), originalFlexBasis: element.getAttribute(STUDIO_ORIGINAL_FLEX_BASIS_ATTR), originalFlexGrow: element.getAttribute(STUDIO_ORIGINAL_FLEX_GROW_ATTR), originalFlexShrink: element.getAttribute(STUDIO_ORIGINAL_FLEX_SHRINK_ATTR), originalBoxSizing: element.getAttribute(STUDIO_ORIGINAL_BOX_SIZING_ATTR), originalScale: element.getAttribute(STUDIO_ORIGINAL_SCALE_ATTR), originalTransformOrigin: element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR), originalDisplay: element.getAttribute(STUDIO_ORIGINAL_DISPLAY_ATTR), }; } export function captureStudioRotation(element: HTMLElement): StudioRotationSnapshot { return { rotate: element.style.getPropertyValue("rotate"), transformOrigin: element.style.getPropertyValue("transform-origin"), studioRotation: element.style.getPropertyValue(STUDIO_ROTATION_PROP), marker: element.getAttribute(STUDIO_ROTATION_ATTR), draftMarker: element.getAttribute(STUDIO_ROTATION_DRAFT_ATTR), originalRotate: element.getAttribute(STUDIO_ORIGINAL_ROTATE_ATTR), originalInlineRotate: element.getAttribute(STUDIO_ORIGINAL_INLINE_ROTATE_ATTR), originalTransformOrigin: element.getAttribute(STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR), }; } export function captureStudioPathOffset(element: HTMLElement): StudioPathOffsetSnapshot { return { translate: element.style.getPropertyValue("translate"), x: element.style.getPropertyValue(STUDIO_OFFSET_X_PROP), y: element.style.getPropertyValue(STUDIO_OFFSET_Y_PROP), marker: element.getAttribute(STUDIO_PATH_OFFSET_ATTR), originalTranslate: element.getAttribute(STUDIO_ORIGINAL_TRANSLATE_ATTR), originalInlineTranslate: element.getAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR), }; } /* ── Restore helpers ──────────────────────────────────────────────── */ function restoreAttribute(element: HTMLElement, attribute: string, value: string | null): void { if (value == null) element.removeAttribute(attribute); else element.setAttribute(attribute, value); } function restoreStyleProperty(element: HTMLElement, property: string, value: string): void { if (value) element.style.setProperty(property, value); else element.style.removeProperty(property); } export function restoreStudioBoxSize(element: HTMLElement, previous: StudioBoxSizeSnapshot): void { restoreStyleProperty(element, "width", previous.width); restoreStyleProperty(element, "height", previous.height); restoreStyleProperty(element, "min-width", previous.minWidth); restoreStyleProperty(element, "min-height", previous.minHeight); restoreStyleProperty(element, "max-width", previous.maxWidth); restoreStyleProperty(element, "max-height", previous.maxHeight); restoreStyleProperty(element, "flex-basis", previous.flexBasis); restoreStyleProperty(element, "flex-grow", previous.flexGrow); restoreStyleProperty(element, "flex-shrink", previous.flexShrink); restoreStyleProperty(element, "box-sizing", previous.boxSizing); restoreStyleProperty(element, "scale", previous.scale); restoreStyleProperty(element, "transform-origin", previous.transformOrigin); restoreStyleProperty(element, "display", previous.display); restoreStyleProperty(element, STUDIO_WIDTH_PROP, previous.studioWidth); restoreStyleProperty(element, STUDIO_HEIGHT_PROP, previous.studioHeight); 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_MIN_WIDTH_ATTR, previous.originalMinWidth); restoreAttribute(element, STUDIO_ORIGINAL_MIN_HEIGHT_ATTR, previous.originalMinHeight); restoreAttribute(element, STUDIO_ORIGINAL_MAX_WIDTH_ATTR, previous.originalMaxWidth); restoreAttribute(element, STUDIO_ORIGINAL_MAX_HEIGHT_ATTR, previous.originalMaxHeight); restoreAttribute(element, STUDIO_ORIGINAL_FLEX_BASIS_ATTR, previous.originalFlexBasis); restoreAttribute(element, STUDIO_ORIGINAL_FLEX_GROW_ATTR, previous.originalFlexGrow); restoreAttribute(element, STUDIO_ORIGINAL_FLEX_SHRINK_ATTR, previous.originalFlexShrink); restoreAttribute(element, STUDIO_ORIGINAL_BOX_SIZING_ATTR, previous.originalBoxSizing); restoreAttribute(element, STUDIO_ORIGINAL_SCALE_ATTR, previous.originalScale); restoreAttribute( element, STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR, previous.originalTransformOrigin, ); restoreAttribute(element, STUDIO_ORIGINAL_DISPLAY_ATTR, previous.originalDisplay); } export function restoreStudioRotation( element: HTMLElement, previous: StudioRotationSnapshot, ): void { restoreStyleProperty(element, "rotate", previous.rotate); restoreStyleProperty(element, "transform-origin", previous.transformOrigin); restoreStyleProperty(element, STUDIO_ROTATION_PROP, previous.studioRotation); restoreAttribute(element, STUDIO_ROTATION_ATTR, previous.marker); restoreAttribute(element, STUDIO_ROTATION_DRAFT_ATTR, previous.draftMarker); restoreAttribute(element, STUDIO_ORIGINAL_ROTATE_ATTR, previous.originalRotate); restoreAttribute(element, STUDIO_ORIGINAL_INLINE_ROTATE_ATTR, previous.originalInlineRotate); restoreAttribute( element, STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR, previous.originalTransformOrigin, ); } export function restoreStudioPathOffset( element: HTMLElement, previous: StudioPathOffsetSnapshot, ): void { if (previous.translate) element.style.setProperty("translate", previous.translate); else element.style.removeProperty("translate"); if (previous.x) element.style.setProperty(STUDIO_OFFSET_X_PROP, previous.x); else element.style.removeProperty(STUDIO_OFFSET_X_PROP); if (previous.y) element.style.setProperty(STUDIO_OFFSET_Y_PROP, previous.y); else element.style.removeProperty(STUDIO_OFFSET_Y_PROP); restoreAttribute(element, STUDIO_PATH_OFFSET_ATTR, previous.marker); restoreAttribute(element, STUDIO_ORIGINAL_TRANSLATE_ATTR, previous.originalTranslate); restoreAttribute( element, STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR, previous.originalInlineTranslate, ); // Restore GSAP x/y if a draft was applied via gsap.set during drag const baseX = element.getAttribute("data-hf-drag-gsap-base-x"); const baseY = element.getAttribute("data-hf-drag-gsap-base-y"); if (baseX != null || baseY != null) { const win = element.ownerDocument.defaultView as | (Window & { gsap?: { set: (el: Element, vars: Record) => void } }) | null; if (win?.gsap) { const x = Number.parseFloat(baseX ?? "0") || 0; const y = Number.parseFloat(baseY ?? "0") || 0; win.gsap.set(element, { x, y }); } element.removeAttribute("data-hf-drag-gsap-base-x"); element.removeAttribute("data-hf-drag-gsap-base-y"); } } /* ── Clear functions ──────────────────────────────────────────────── */ type BoxSizeProperty = | "width" | "height" | "min-width" | "min-height" | "max-width" | "max-height" | "flex-basis" | "flex-grow" | "flex-shrink" | "box-sizing" | "scale" | "transform-origin" | "display"; function restoreOriginalBoxSizeProperty( element: HTMLElement, property: BoxSizeProperty, attribute: string, ): void { const original = element.getAttribute(attribute); if (original == null || original === "") element.style.removeProperty(property); else element.style.setProperty(property, original); element.removeAttribute(attribute); } function restoreOriginalRotationProperty(element: HTMLElement): void { const original = element.getAttribute(STUDIO_ORIGINAL_INLINE_ROTATE_ATTR); if (original == null || original === "") element.style.removeProperty("rotate"); else element.style.setProperty("rotate", original); element.removeAttribute(STUDIO_ORIGINAL_INLINE_ROTATE_ATTR); element.removeAttribute(STUDIO_ORIGINAL_ROTATE_ATTR); const originalTransformOrigin = element.getAttribute( STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR, ); if (originalTransformOrigin != null) { if (originalTransformOrigin === "") element.style.removeProperty("transform-origin"); else element.style.setProperty("transform-origin", originalTransformOrigin); } element.removeAttribute(STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR); } function restoreOriginalTranslateProperty(element: HTMLElement): void { const original = element.getAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR); if (original == null || original === "") element.style.removeProperty("translate"); else element.style.setProperty("translate", original); element.removeAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR); element.removeAttribute(STUDIO_ORIGINAL_TRANSLATE_ATTR); } export function clearStudioPathOffset(element: HTMLElement): void { if ( element.hasAttribute(STUDIO_PATH_OFFSET_ATTR) || styleUsesStudioOffset(element.style.getPropertyValue("translate")) ) { restoreOriginalTranslateProperty(element); } restoreInlineDisplay(element); element.style.removeProperty(STUDIO_OFFSET_X_PROP); element.style.removeProperty(STUDIO_OFFSET_Y_PROP); element.removeAttribute(STUDIO_PATH_OFFSET_ATTR); element.removeAttribute(STUDIO_ORIGINAL_TRANSLATE_ATTR); element.removeAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR); } export function clearStudioRotation(element: HTMLElement): void { if ( element.hasAttribute(STUDIO_ROTATION_ATTR) || styleUsesStudioRotation(element.style.getPropertyValue("rotate")) ) { restoreOriginalRotationProperty(element); } restoreInlineDisplay(element); element.style.removeProperty(STUDIO_ROTATION_PROP); element.removeAttribute(STUDIO_ROTATION_ATTR); element.removeAttribute(STUDIO_ROTATION_DRAFT_ATTR); element.removeAttribute(STUDIO_ORIGINAL_ROTATE_ATTR); element.removeAttribute(STUDIO_ORIGINAL_INLINE_ROTATE_ATTR); element.removeAttribute(STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR); } export function clearStudioBoxSize(element: HTMLElement): void { if ( element.hasAttribute(STUDIO_BOX_SIZE_ATTR) || styleUsesStudioSize(element.style.getPropertyValue("width")) || styleUsesStudioSize(element.style.getPropertyValue("height")) || element.hasAttribute(STUDIO_ORIGINAL_SCALE_ATTR) ) { restoreOriginalBoxSizeProperty(element, "width", STUDIO_ORIGINAL_WIDTH_ATTR); restoreOriginalBoxSizeProperty(element, "height", STUDIO_ORIGINAL_HEIGHT_ATTR); restoreOriginalBoxSizeProperty(element, "min-width", STUDIO_ORIGINAL_MIN_WIDTH_ATTR); restoreOriginalBoxSizeProperty(element, "min-height", STUDIO_ORIGINAL_MIN_HEIGHT_ATTR); restoreOriginalBoxSizeProperty(element, "max-width", STUDIO_ORIGINAL_MAX_WIDTH_ATTR); restoreOriginalBoxSizeProperty(element, "max-height", STUDIO_ORIGINAL_MAX_HEIGHT_ATTR); restoreOriginalBoxSizeProperty(element, "flex-basis", STUDIO_ORIGINAL_FLEX_BASIS_ATTR); restoreOriginalBoxSizeProperty(element, "flex-grow", STUDIO_ORIGINAL_FLEX_GROW_ATTR); restoreOriginalBoxSizeProperty(element, "flex-shrink", STUDIO_ORIGINAL_FLEX_SHRINK_ATTR); restoreOriginalBoxSizeProperty(element, "box-sizing", STUDIO_ORIGINAL_BOX_SIZING_ATTR); restoreOriginalBoxSizeProperty(element, "scale", STUDIO_ORIGINAL_SCALE_ATTR); restoreOriginalBoxSizeProperty( element, "transform-origin", STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR, ); restoreOriginalBoxSizeProperty(element, "display", STUDIO_ORIGINAL_DISPLAY_ATTR); } restoreInlineDisplay(element); element.style.removeProperty(STUDIO_WIDTH_PROP); element.style.removeProperty(STUDIO_HEIGHT_PROP); element.removeAttribute(STUDIO_BOX_SIZE_ATTR); }