/* @oracle/oraclejet-preact: undefined */
import { jsxs, Fragment, jsx } from 'preact/jsx-runtime';
import { useRef, useCallback } from 'preact/hooks';
import { c as classNames } from './classNames-4e12b00d.js';
import { baseStyle, styles } from './PRIVATE_Resizable/themes/ResizableStyles.css.js';
import { g as getContainingBlockElem } from './positionUtils-f26caad9.js';

var ResizeEdge;
(function (ResizeEdge) {
    ResizeEdge[ResizeEdge["NONE"] = 0] = "NONE";
    ResizeEdge[ResizeEdge["N"] = 1] = "N";
    ResizeEdge[ResizeEdge["NE"] = 2] = "NE";
    ResizeEdge[ResizeEdge["E"] = 3] = "E";
    ResizeEdge[ResizeEdge["SE"] = 4] = "SE";
    ResizeEdge[ResizeEdge["S"] = 5] = "S";
    ResizeEdge[ResizeEdge["SW"] = 6] = "SW";
    ResizeEdge[ResizeEdge["W"] = 7] = "W";
    ResizeEdge[ResizeEdge["NW"] = 8] = "NW";
})(ResizeEdge || (ResizeEdge = {}));
/**
 * A component that adds resize capability to a component. Fires the onResize event whenever
 * a potential resize gesture is detected. It is up to the consuming component to update its
 * position and dimensions when appropriate.
 */
function Resizable({ onResize, onResizeStart, onResizeEnd, containerRef }) {
    const isResizing = useRef(false);
    const resizingEdge = useRef(ResizeEdge.NONE);
    const startPosition = useRef();
    const initialParentClientRect = useRef({ x: 0, y: 0, width: 0, height: 0 });
    const initialMousePosition = useRef({ x: 0, y: 0 });
    const findPos = (element) => {
        let elem = element;
        let curLeft = 0;
        let curTop = 0;
        if (elem.offsetParent) {
            do {
                curLeft += elem.offsetLeft;
                curTop += elem.offsetTop;
            } while ((elem = elem.offsetParent));
        }
        return { left: curLeft, top: curTop };
    };
    /**
     * Constrains rect to the current containing block
     */
    const constrainRect = useCallback((srcRect) => {
        const elem = containerRef?.current;
        const result = {
            x: srcRect.x,
            y: srcRect.y,
            width: srcRect.width,
            height: srcRect.height
        };
        if (!elem)
            return result;
        const containingBlock = getContainingBlockElem(elem);
        const boundingRect = containingBlock?.getBoundingClientRect();
        const dialogRect = elem.getBoundingClientRect();
        const limitLeft = boundingRect ? boundingRect.left : 0;
        const limitTop = boundingRect ? boundingRect.top : 0;
        const limitRight = boundingRect ? boundingRect.right : window.innerWidth;
        const limitBottom = boundingRect ? boundingRect.bottom : window.innerHeight;
        if (result.y < limitTop) {
            result.y = limitTop;
            result.height = dialogRect.height;
        }
        if (result.y + result.height > limitBottom) {
            result.height = dialogRect.height;
        }
        if (result.x < limitLeft) {
            result.x = limitLeft;
            result.width = dialogRect.width;
        }
        if (result.x + result.width > limitRight) {
            result.width = dialogRect.width;
        }
        return result;
    }, [containerRef]);
    /**
     * Calculates the new rect coordinates for a given mouse event
     */
    const getNewRect = useCallback((event) => {
        let left = 0;
        let width = 0;
        let top = 0;
        let height = 0;
        switch (resizingEdge.current) {
            case ResizeEdge.N:
                top = event.pageY - initialMousePosition.current.y;
                height = initialMousePosition.current.y - event.pageY;
                break;
            case ResizeEdge.E:
                width = event.pageX - initialMousePosition.current.x;
                break;
            case ResizeEdge.S:
                height = event.pageY - initialMousePosition.current.y;
                break;
            case ResizeEdge.W:
                left = event.pageX - initialMousePosition.current.x;
                width = initialMousePosition.current.x - event.pageX;
                break;
            case ResizeEdge.NE:
                top = event.pageY - initialMousePosition.current.y;
                width = event.pageX - initialMousePosition.current.x;
                height = initialMousePosition.current.y - event.pageY;
                break;
            case ResizeEdge.SE:
                width = event.pageX - initialMousePosition.current.x;
                height = event.pageY - initialMousePosition.current.y;
                break;
            case ResizeEdge.SW:
                left = event.pageX - initialMousePosition.current.x;
                width = initialMousePosition.current.x - event.pageX;
                height = event.pageY - initialMousePosition.current.y;
                break;
            case ResizeEdge.NW:
                left = event.pageX - initialMousePosition.current.x;
                top = event.pageY - initialMousePosition.current.y;
                width = initialMousePosition.current.x - event.pageX;
                height = initialMousePosition.current.y - event.pageY;
                break;
        }
        const newRect = {
            x: initialParentClientRect.current.x + left,
            y: initialParentClientRect.current.y + top,
            width: initialParentClientRect.current.width + width,
            height: initialParentClientRect.current.height + height
        };
        const newConstrainedRect = constrainRect(newRect);
        return newConstrainedRect;
    }, [constrainRect]);
    /**
     * Handles mousedown events while the 'resize' mode is active.
     */
    const handleResize = useCallback((event) => {
        if (!isResizing.current)
            return;
        if (!startPosition.current)
            return;
        const newRect = getNewRect(event);
        onResize?.(newRect);
        event.stopPropagation();
        event.preventDefault();
    }, [onResize, getNewRect]);
    /**
     * Handles mouseup event to exit the 'resize' mode.
     */
    const endResize = (event) => {
        isResizing.current = false;
        document.removeEventListener('mousemove', handleResize, true);
        document.removeEventListener('mouseup', endResize, true);
        const newRect = getNewRect(event);
        onResizeEnd?.(newRect);
        resizingEdge.current = ResizeEdge.NONE;
        event.preventDefault();
        event.stopPropagation();
    };
    /**
     * Handles mousedown event to enter the 'resize mode.
     */
    const startResize = (event) => {
        const elem = event.currentTarget;
        if (!elem || !elem.parentElement)
            return;
        const pos = findPos(elem.parentElement);
        isResizing.current = true;
        document.addEventListener('mousemove', handleResize, true);
        document.addEventListener('mouseup', endResize, true);
        initialParentClientRect.current = elem.parentElement.getBoundingClientRect();
        startPosition.current = { x: pos.left, y: pos.top };
        initialMousePosition.current = { x: event.pageX, y: event.pageY };
        const newRect = getNewRect(event);
        onResizeStart?.(newRect);
    };
    const startResizeN = (event) => {
        startResize(event);
        if (isResizing.current) {
            resizingEdge.current = ResizeEdge.N;
        }
    };
    const startResizeE = (event) => {
        startResize(event);
        if (isResizing.current) {
            resizingEdge.current = ResizeEdge.E;
        }
    };
    const startResizeS = (event) => {
        startResize(event);
        if (isResizing.current) {
            resizingEdge.current = ResizeEdge.S;
        }
    };
    const startResizeW = (event) => {
        startResize(event);
        if (isResizing.current) {
            resizingEdge.current = ResizeEdge.W;
        }
    };
    const startResizeNE = (event) => {
        startResize(event);
        if (isResizing.current) {
            resizingEdge.current = ResizeEdge.NE;
        }
    };
    const startResizeSE = (event) => {
        startResize(event);
        if (isResizing.current) {
            resizingEdge.current = ResizeEdge.SE;
        }
    };
    const startResizeSW = (event) => {
        startResize(event);
        if (isResizing.current) {
            resizingEdge.current = ResizeEdge.SW;
        }
    };
    const startResizeNW = (event) => {
        startResize(event);
        if (isResizing.current) {
            resizingEdge.current = ResizeEdge.NW;
        }
    };
    return (jsxs(Fragment, { children: [jsx("div", { class: classNames([baseStyle, styles.handleN]), onMouseDown: startResizeN }), jsx("div", { class: classNames([baseStyle, styles.handleE]), onMouseDown: startResizeE }), jsx("div", { class: classNames([baseStyle, styles.handleS]), onMouseDown: startResizeS }), jsx("div", { class: classNames([baseStyle, styles.handleW]), onMouseDown: startResizeW }), jsx("div", { class: classNames([baseStyle, styles.handleNE]), onMouseDown: startResizeNE }), jsx("div", { class: classNames([baseStyle, styles.handleSE]), onMouseDown: startResizeSE }), jsx("div", { class: classNames([baseStyle, styles.handleSW]), onMouseDown: startResizeSW }), jsx("div", { class: classNames([baseStyle, styles.handleNW]), onMouseDown: startResizeNW })] }));
}

export { Resizable as R };
//# sourceMappingURL=Resizable-ea74f2fd.js.map
