import React, { useCallback, useEffect, useRef, useState } from "react";
import { useId } from "../../utils-external/index.js";
import { useControllableState, useEventCallback, useTransitionStatus, } from "../../utils/hooks/index.js";
import { DialogBody } from "../body/DialogBody.js";
import { DialogCloseTrigger, } from "../close-trigger/DialogCloseTrigger.js";
import { DialogDescription, } from "../description/DialogDescription.js";
import { DialogFooter } from "../footer/DialogFooter.js";
import { DialogHeader } from "../header/DialogHeader.js";
import { DialogPopup } from "../popup/DialogPopup.js";
import { DialogTitle } from "../title/DialogTitle.js";
import { DialogTrigger, } from "../trigger/DialogTrigger.js";
import { DialogContextProvider, useDialogContext } from "./DialogRoot.context.js";
/**
 * Dialog component for displaying modal content on top of an application.
 * @see [📝 Documentation](https://aksel.nav.no/komponenter/core/dialog)
 * @see 🏷️ {@link DialogProps}
 * @example
 * ```jsx
 *  <Dialog>
 *    <Dialog.Trigger>
 *      <Button>Open dialog</Button>
 *    </Dialog.Trigger>
 *    <Dialog.Popup>
 *      <Dialog.Header>
 *        <Dialog.Title>Dialog title</Dialog.Title>
 *        <Dialog.Description>Dialog description</Dialog.Description>
 *      </Dialog.Header>
 *      <Dialog.Body>
 *        Dialog body content
 *      </Dialog.Body>
 *      <Dialog.Footer>
 *        <Dialog.CloseTrigger>
 *          <Button>Close dialog</Button>
 *        </Dialog.CloseTrigger>
 *      </Dialog.Footer>
 *    </Dialog.Popup>
 *  </Dialog>
 * ```
 */
export const Dialog = (props) => {
    var _a;
    const { children, defaultOpen = false, open: openParam, onOpenChange, onOpenChangeComplete, size = "medium", } = props;
    const [open, setOpenStateInternal] = useControllableState({
        defaultValue: defaultOpen,
        value: openParam,
    });
    const { mounted, setMounted, transitionStatus } = useTransitionStatus(open);
    const popupRef = useRef(null);
    const [triggerElement, setTriggerElement] = useState(null);
    const [popupElement, setPopupElement] = useState(null);
    const defaultId = useId();
    const [titleId, setTitleId] = useState();
    const [ownNestedOpenDialogs, setOwnNestedOpenDialogs] = useState(0);
    const nestedDialogOpened = useCallback((nestedCount) => {
        setOwnNestedOpenDialogs(nestedCount + 1);
    }, []);
    const nestedDialogClosed = useCallback(() => {
        setOwnNestedOpenDialogs(0);
    }, []);
    const parentContext = useDialogContext(false);
    /**
     * Notify parent dialog about nested dialogs opening/closing.
     * This allows us to better hide/obscure parent dialogs when nested dialogs are opened.
     *
     * This pattern is not good for deep nesting since the context updates will cause cascading renders
     * but should work fine for 1-2 levels of nesting which is the most common use case here.
     */
    useEffect(() => {
        if (open && parentContext) {
            parentContext.nestedDialogOpened(ownNestedOpenDialogs);
            return () => parentContext.nestedDialogClosed();
        }
    }, [open, parentContext, ownNestedOpenDialogs]);
    /**
     * Passing the original event to onOpenChange to allow preventing the state change
     */
    const setOpen = useEventCallback((nextOpen, originalEvent) => {
        onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(nextOpen, originalEvent);
        if (originalEvent === null || originalEvent === void 0 ? void 0 : originalEvent.defaultPrevented) {
            return;
        }
        setOpenStateInternal(nextOpen);
    });
    return (React.createElement(DialogContextProvider, { open: open, setOpen: setOpen, mounted: mounted, transitionStatus: transitionStatus, popupRef: popupRef, setPopupElement: setPopupElement, popupElement: popupElement, popupId: (_a = popupElement === null || popupElement === void 0 ? void 0 : popupElement.id) !== null && _a !== void 0 ? _a : defaultId, setTriggerElement: setTriggerElement, triggerElement: triggerElement, nested: !!parentContext, nestedDialogOpened: nestedDialogOpened, nestedDialogClosed: nestedDialogClosed, nestedOpenDialogCount: ownNestedOpenDialogs, size: size, titleId: titleId, setTitleId: setTitleId, onOpenChangeComplete: onOpenChangeComplete, setMounted: setMounted }, children));
};
Dialog.Trigger = DialogTrigger;
Dialog.CloseTrigger = DialogCloseTrigger;
Dialog.Header = DialogHeader;
Dialog.Title = DialogTitle;
Dialog.Description = DialogDescription;
Dialog.Body = DialogBody;
Dialog.Footer = DialogFooter;
Dialog.Popup = DialogPopup;
export default Dialog;
export { DialogTrigger, DialogCloseTrigger, DialogHeader, DialogTitle, DialogDescription, DialogBody, DialogFooter, DialogPopup, };
//# sourceMappingURL=DialogRoot.js.map