import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState, } from "react";
import FadeIn from "../FadeIn";
import Styles from "./Collapsable.module.scss";
import { AnchoredTooltipAlignment, updateTooltipPosition, } from "../AnchoredTooltip/AnchoredTooltip";
import { useOneUIConfig } from "../../context/OneUIProvider";
function _Collapsable({ children, title, className, onToggleOpen: _onToggleOpen, open: _open, id, mode = "block", contentClassName, onContentClick, keepUnderlayingElement, onClickOut, ...props }, ref) {
    const globalClassName = useOneUIConfig("component.collapsable.className", "");
    const [localOpen, setLocalOpen] = useState(!!_open);
    const open = _open === undefined ? localOpen : _open;
    const onToggleOpen = _onToggleOpen === undefined ? setLocalOpen : _onToggleOpen;
    const contentRef = useRef(null);
    const toggleRef = useRef(null);
    useEffect(() => {
        if (open && onClickOut) {
            window.addEventListener("click", onClickOut);
            return () => window.removeEventListener("click", onClickOut);
        }
    }, [!!onClickOut, open]);
    function redimension(canShrink = false) {
        const el = contentRef.current;
        const contentEl = el.firstElementChild;
        if (open) {
            el.style.marginTop = ``;
            el.style.height =
                Math.min(canShrink ? contentEl.clientHeight : Number.POSITIVE_INFINITY, el.scrollHeight, visualViewport.height - 16) + "px";
            el.parentElement.style.position = "relative";
            if (mode === "float") {
                el.style.minHeight = el.style.height;
                const { shouldAnchorToBottom } = updateTooltipPosition(el, toggleRef.current, true, "alignTo" in props ? props.alignTo : AnchoredTooltipAlignment.CENTER, "anchorTo" in props ? props.anchorTo : undefined);
                el.style.minHeight = "";
                if (!shouldAnchorToBottom) {
                    el.style.marginTop = el.style.height;
                }
                const transitionStart = ({ currentTarget, target, propertyName, }) => {
                    if (currentTarget === target &&
                        propertyName == "height" &&
                        !shouldAnchorToBottom) {
                        el.classList.add(Styles.transitionMarginTop);
                        el.style.marginTop = "0px";
                    }
                };
                el.addEventListener("transitionstart", transitionStart);
                return () => el.removeEventListener("transitionstart", transitionStart);
            }
            const onTransitionEnd = () => {
                el.style.height = "auto";
            };
            el.addEventListener("transitionend", onTransitionEnd);
            el.addEventListener("transitionend", () => el.removeEventListener("transitionend", onTransitionEnd));
            return () => {
                el.removeEventListener("transitionend", onTransitionEnd);
            };
        }
        else {
            el.style.height = el.clientHeight + "px";
            setTimeout(() => {
                if (el.style.marginTop === "0px")
                    el.style.marginTop = `${el.clientHeight}px`;
                el.style.height = 0 + "px";
            }, 100);
            const onTransitionEnd = () => {
                el.parentElement.style.position = "initial";
                el.classList.remove(Styles.transitionMarginTop);
                el.removeEventListener("transitionend", onTransitionEnd);
            };
            el.addEventListener("transitionend", onTransitionEnd);
            return () => {
                el.removeEventListener("transitionend", onTransitionEnd);
            };
        }
    }
    useImperativeHandle(ref, () => ({
        redimension: () => redimension(true),
    }));
    useLayoutEffect(() => {
        redimension();
    }, [open]);
    const propsToSpread = { ...props };
    delete propsToSpread.alignTo;
    delete propsToSpread.anchorTo;
    return (_jsxs("div", { className: `${Styles.container} ${open ? Styles.open : Styles.closed} ${className} ${globalClassName}`, ...propsToSpread, children: [_jsx("div", { ref: toggleRef, onClick: (e) => {
                    e.stopPropagation();
                    onToggleOpen(!open);
                }, id: _collapsableId("header", id), children: typeof title === "function" ? title(open) : title }), _jsx("div", { onClick: (e) => {
                    e.stopPropagation();
                    if (onContentClick)
                        onContentClick(e);
                }, ref: contentRef, className: `${Styles.content} ${Styles[mode] || ""} ${contentClassName}`, id: _collapsableId("content", id), children: _jsx(FadeIn, { children: open || keepUnderlayingElement ? children : null }) })] }));
}
function _collapsableId(type, id) {
    return id ? `collapsable_${type}_${id}` : undefined;
}
class _CollapsableInterface {
    _id;
    constructor(id) {
        this._id = id;
    }
    _getElements() {
        return {
            header: document.getElementById(_collapsableId("header", this._id)),
            content: document.getElementById(_collapsableId("content", this._id)),
        };
    }
    open(onOpened) {
        const { header, content } = this._getElements();
        if ((content?.clientHeight || 0) === 0) {
            header.click();
            content.addEventListener("transitionend", function _handler() {
                content.removeEventListener("transitionend", _handler);
                onOpened();
            });
        }
        else {
            onOpened();
        }
    }
    getElement(type) {
        return document.getElementById(_collapsableId(type, this._id));
    }
}
/**
 * A helper function for interacting with collapsables without a reference
 */
export function CollapsableInterface(id) {
    return new _CollapsableInterface(id);
}
/**
 * Allows collapsing and expanding the wrapped content
 **/
const Collapsable = forwardRef(_Collapsable);
/**
 * A component that lets users hide or show content by clicking a header.
 * It creates a toggleable section where content can be expanded to show more
 * information or collapsed to save space.
 **/
export default Collapsable;
//# sourceMappingURL=Collapsable.js.map