// packages/block-editor/src/components/iframe/use-scale-canvas.js
import { useEffect, useRef, useCallback } from "@wordpress/element";
import { useReducedMotion, useResizeObserver } from "@wordpress/compose";
function calculateScale({
  frameSize,
  containerWidth,
  maxContainerWidth,
  scaleContainerWidth
}) {
  return (Math.min(containerWidth, maxContainerWidth) - frameSize * 2) / scaleContainerWidth;
}
function computeScrollHeightNext(transitionFrom, transitionTo) {
  const { scaleValue: prevScale, scrollHeight: prevScrollHeight } = transitionFrom;
  const { frameSize, scaleValue } = transitionTo;
  return prevScrollHeight * (scaleValue / prevScale) + frameSize * 2;
}
function computeScrollTopNext(transitionFrom, transitionTo) {
  const {
    containerHeight: prevContainerHeight,
    frameSize: prevFrameSize,
    scaleValue: prevScale,
    scrollTop: prevScrollTop
  } = transitionFrom;
  const { containerHeight, frameSize, scaleValue, scrollHeight } = transitionTo;
  let scrollTopNext = prevScrollTop;
  scrollTopNext = (scrollTopNext + prevContainerHeight / 2 - prevFrameSize) / prevScale - prevContainerHeight / 2;
  scrollTopNext = (scrollTopNext + containerHeight / 2) * scaleValue + frameSize - containerHeight / 2;
  scrollTopNext = prevScrollTop <= prevFrameSize ? 0 : scrollTopNext;
  const maxScrollTop = scrollHeight - containerHeight;
  return Math.round(
    Math.min(Math.max(0, scrollTopNext), Math.max(0, maxScrollTop))
  );
}
function getAnimationKeyframes(transitionFrom, transitionTo) {
  const {
    scaleValue: prevScale,
    frameSize: prevFrameSize,
    scrollTop
  } = transitionFrom;
  const { scaleValue, frameSize, scrollTop: scrollTopNext } = transitionTo;
  return [
    {
      translate: `0 0`,
      scale: prevScale,
      paddingTop: `${prevFrameSize / prevScale}px`,
      paddingBottom: `${prevFrameSize / prevScale}px`
    },
    {
      translate: `0 ${scrollTop - scrollTopNext}px`,
      scale: scaleValue,
      paddingTop: `${frameSize / scaleValue}px`,
      paddingBottom: `${frameSize / scaleValue}px`
    }
  ];
}
function useScaleCanvas({
  frameSize,
  iframeDocument,
  maxContainerWidth = 750,
  scale
}) {
  const [contentResizeListener, { height: contentHeight }] = useResizeObserver();
  const [
    containerResizeListener,
    { width: containerWidth, height: containerHeight }
  ] = useResizeObserver();
  const initialContainerWidthRef = useRef(0);
  const isZoomedOut = scale !== 1;
  const prefersReducedMotion = useReducedMotion();
  const isAutoScaled = scale === "auto-scaled";
  const startAnimationRef = useRef(false);
  const animationRef = useRef(null);
  useEffect(() => {
    if (!isZoomedOut) {
      initialContainerWidthRef.current = containerWidth;
    }
  }, [containerWidth, isZoomedOut]);
  const scaleContainerWidth = Math.max(
    initialContainerWidthRef.current,
    containerWidth
  );
  const scaleValue = isAutoScaled ? calculateScale({
    frameSize,
    containerWidth,
    maxContainerWidth,
    scaleContainerWidth
  }) : scale;
  const transitionFromRef = useRef({
    scaleValue,
    frameSize,
    containerHeight: 0,
    scrollTop: 0,
    scrollHeight: 0
  });
  const transitionToRef = useRef({
    scaleValue,
    frameSize,
    containerHeight: 0,
    scrollTop: 0,
    scrollHeight: 0
  });
  const startZoomOutAnimation = useCallback(() => {
    const { scrollTop } = transitionFromRef.current;
    const { scrollTop: scrollTopNext } = transitionToRef.current;
    iframeDocument.documentElement.style.setProperty(
      "--wp-block-editor-iframe-zoom-out-scroll-top",
      `${scrollTop}px`
    );
    iframeDocument.documentElement.style.setProperty(
      "--wp-block-editor-iframe-zoom-out-scroll-top-next",
      `${scrollTopNext}px`
    );
    iframeDocument.documentElement.style.setProperty(
      "--wp-block-editor-iframe-zoom-out-overflow-behavior",
      transitionFromRef.current.scrollHeight === transitionFromRef.current.containerHeight ? "auto" : "scroll"
    );
    iframeDocument.documentElement.classList.add("zoom-out-animation");
    return iframeDocument.documentElement.animate(
      getAnimationKeyframes(
        transitionFromRef.current,
        transitionToRef.current
      ),
      {
        easing: "cubic-bezier(0.46, 0.03, 0.52, 0.96)",
        duration: 400
      }
    );
  }, [iframeDocument]);
  const finishZoomOutAnimation = useCallback(() => {
    startAnimationRef.current = false;
    animationRef.current = null;
    iframeDocument.documentElement.style.setProperty(
      "--wp-block-editor-iframe-zoom-out-scale",
      transitionToRef.current.scaleValue
    );
    iframeDocument.documentElement.style.setProperty(
      "--wp-block-editor-iframe-zoom-out-frame-size",
      `${transitionToRef.current.frameSize}px`
    );
    iframeDocument.documentElement.classList.remove("zoom-out-animation");
    iframeDocument.documentElement.scrollTop = transitionToRef.current.scrollTop;
    iframeDocument.documentElement.style.removeProperty(
      "--wp-block-editor-iframe-zoom-out-scroll-top"
    );
    iframeDocument.documentElement.style.removeProperty(
      "--wp-block-editor-iframe-zoom-out-scroll-top-next"
    );
    iframeDocument.documentElement.style.removeProperty(
      "--wp-block-editor-iframe-zoom-out-overflow-behavior"
    );
    transitionFromRef.current = transitionToRef.current;
  }, [iframeDocument]);
  const previousIsZoomedOut = useRef(false);
  useEffect(() => {
    if (!iframeDocument) {
      return;
    }
    const trigger = previousIsZoomedOut.current !== isZoomedOut;
    previousIsZoomedOut.current = isZoomedOut;
    if (!trigger) {
      return;
    }
    startAnimationRef.current = true;
    if (!isZoomedOut) {
      return;
    }
    iframeDocument.documentElement.classList.add("is-zoomed-out");
    return () => {
      iframeDocument.documentElement.classList.remove("is-zoomed-out");
    };
  }, [iframeDocument, isZoomedOut]);
  useEffect(() => {
    if (!iframeDocument) {
      return;
    }
    if (isAutoScaled && transitionFromRef.current.scaleValue !== 1) {
      transitionFromRef.current.scaleValue = calculateScale({
        frameSize: transitionFromRef.current.frameSize,
        containerWidth,
        maxContainerWidth,
        scaleContainerWidth: containerWidth
      });
    }
    if (scaleValue < 1) {
      if (!startAnimationRef.current) {
        iframeDocument.documentElement.style.setProperty(
          "--wp-block-editor-iframe-zoom-out-scale",
          scaleValue
        );
        iframeDocument.documentElement.style.setProperty(
          "--wp-block-editor-iframe-zoom-out-frame-size",
          `${frameSize}px`
        );
      }
      iframeDocument.documentElement.style.setProperty(
        "--wp-block-editor-iframe-zoom-out-content-height",
        `${contentHeight}px`
      );
      iframeDocument.documentElement.style.setProperty(
        "--wp-block-editor-iframe-zoom-out-inner-height",
        `${containerHeight}px`
      );
      iframeDocument.documentElement.style.setProperty(
        "--wp-block-editor-iframe-zoom-out-container-width",
        `${containerWidth}px`
      );
      iframeDocument.documentElement.style.setProperty(
        "--wp-block-editor-iframe-zoom-out-scale-container-width",
        `${scaleContainerWidth}px`
      );
    }
    if (startAnimationRef.current) {
      startAnimationRef.current = false;
      if (animationRef.current) {
        animationRef.current.reverse();
        const tempTransitionFrom = transitionFromRef.current;
        const tempTransitionTo = transitionToRef.current;
        transitionFromRef.current = tempTransitionTo;
        transitionToRef.current = tempTransitionFrom;
      } else {
        transitionFromRef.current.scrollTop = iframeDocument.documentElement.scrollTop;
        transitionFromRef.current.scrollHeight = iframeDocument.documentElement.scrollHeight;
        transitionFromRef.current.containerHeight = containerHeight;
        transitionToRef.current = {
          scaleValue,
          frameSize,
          containerHeight: iframeDocument.documentElement.clientHeight
          // use clientHeight to get the actual height of the new container after zoom state changes have rendered, as it will be the most up-to-date.
        };
        transitionToRef.current.scrollHeight = computeScrollHeightNext(
          transitionFromRef.current,
          transitionToRef.current
        );
        transitionToRef.current.scrollTop = computeScrollTopNext(
          transitionFromRef.current,
          transitionToRef.current
        );
        animationRef.current = startZoomOutAnimation();
        if (prefersReducedMotion) {
          finishZoomOutAnimation();
        } else {
          animationRef.current.onfinish = finishZoomOutAnimation;
        }
      }
    }
  }, [
    startZoomOutAnimation,
    finishZoomOutAnimation,
    prefersReducedMotion,
    isAutoScaled,
    scaleValue,
    frameSize,
    iframeDocument,
    contentHeight,
    containerWidth,
    containerHeight,
    maxContainerWidth,
    scaleContainerWidth
  ]);
  return {
    isZoomedOut,
    scaleContainerWidth,
    contentResizeListener,
    containerResizeListener
  };
}
export {
  useScaleCanvas
};
//# sourceMappingURL=use-scale-canvas.mjs.map
