/* @oracle/oraclejet-preact: undefined */
'use strict';

var hooks = require('preact/hooks');
var arrayUtils = require('./arrayUtils-7d8dcfc3.js');
var Layer = require('./Layer-2352de5e.js');
var useModal = require('./useModal-0739a528.js');

/**
 * Checks if the mouse event target is inside of any of the specified containers, or if it
 * occurs in a layer whose 'logicalParent' belongs to one of the containers.
 *
 * @param event a mouse event associated with the potential "outside click" action
 * @param ref an array of references to elements that are considered "inside"
 * @returns 'true' if the event occurs "outside" of the specified list of containers
 */
const isPointOutside = (event, ref) => {
    const target = event.target;
    // if the event has no target, consider it "inside"
    if (!target) {
        return false;
    }
    const doc = getDocument(target);
    if (!doc.contains(target)) {
        return false;
    }
    // if the target is contained in any of the target containers, it is not "outside"
    if (ref.some((elRef) => elRef.current?.contains(target))) {
        return false;
    }
    // the event target can also occur in a popup layer that belongs to an "inside" container
    const findLogicalParent = (elem) => {
        let elemParent = elem.parentElement;
        while (elemParent) {
            if (elemParent[Layer.LOGICAL_PARENT]) {
                return elemParent[Layer.LOGICAL_PARENT];
            }
            elemParent = elemParent.parentElement;
        }
        return null;
    };
    const logicalParent = findLogicalParent(target);
    // TODO: logical parents could also be nested, search for potential higher-level logical parents too
    if (logicalParent) {
        if (ref.some((elRef) => elRef.current?.contains(logicalParent))) {
            return false;
        }
    }
    // if the click target is a modal overlay and it is part of target's modal layer
    // then it's an outside click. Otherwise, treat the click as an "inside" click because
    // it is a click on another modal which must be above our elem
    if (target[useModal.MODAL_OVERLAY]) {
        if (!ref.some((elRef) => {
            const modalParent = elRef.current?.closest('[data-oj-layer="modal"]');
            return modalParent && modalParent.contains(target);
        })) {
            return false;
        }
    }
    // if the target is a child of a modal layer other than any of the refs,
    // the click occurs in another modal layer which must be above our elem
    const modalParent = target.closest('[data-oj-layer="modal"]');
    if (modalParent &&
        !ref.some((elRef) => modalParent.contains(elRef.current))) {
        return false;
    }
    return true;
};
const getDocument = (node) => node?.ownerDocument ?? document;
const useOutsideClick = ({ isDisabled: disabled = false, ref, handler }) => {
    // use ref to store mutable data and not cause a re-render
    const mouseDownTargetRef = hooks.useRef(null);
    hooks.useEffect(() => {
        const refs = arrayUtils.coerceArray(ref);
        if (!handler ||
            disabled ||
            (refs.length > 0 && refs.findIndex((elRef) => elRef.current === null) > -1))
            return;
        const onMouseDown = (event) => {
            mouseDownTargetRef.current = event.target;
        };
        const onMouseUp = (event) => {
            if (mouseDownTargetRef.current === event.target && isPointOutside(event, refs)) {
                handler?.(event);
            }
            mouseDownTargetRef.current = null;
        };
        const firstElRef = refs[0];
        const doc = getDocument(firstElRef.current);
        if (doc) {
            doc.addEventListener('mousedown', onMouseDown, true);
            doc.addEventListener('mouseup', onMouseUp, true);
            return () => {
                doc.removeEventListener('mousedown', onMouseDown, true);
                doc.removeEventListener('mouseup', onMouseUp, true);
            };
        }
        return undefined;
    }, [disabled, handler, ref]);
};

exports.useOutsideClick = useOutsideClick;
//# sourceMappingURL=useOutsideClick-8e9209c6.js.map
