'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { createContext, useContext, useLayoutEffect, useRef, useState, } from 'react';
import { Dialog } from '@base-ui/react/dialog';
import { ArrowLeftIcon, XIcon } from '@graphprotocol/gds-react/icons';
import { useControlled, useCSSPropsPolyfill, useGDS } from "../hooks/index.js";
import { cn, getCSSPropsAttributes } from "../utils/index.js";
import { Portal } from "./base/Portal.js";
import { Transition } from "./base/Transition.js";
import { Button } from "./Button.js";
import { ButtonGroup } from "./ButtonGroup.js";
import { Divider } from "./Divider.js";
import { ModalMeta } from "./Modal.meta.js";
import { Stepper } from "./Stepper.js";
const ModalContext = createContext(null);
export const ModalRoot = ({ ref: passedRef, variant, size, trigger, open: controlledOpen, defaultOpen, onOpenChange, dismissible: passedDismissible, role, steps: passedSteps = 1, currentStep: controlledCurrentStep, onCurrentStepChange, className, style, children, ...props }) => {
    const { dirProps } = useGDS();
    const [cssPropsPolyfillRef, cssPropsPolyfillAttributes] = useCSSPropsPolyfill(ModalMeta, {
        variant,
        size,
    });
    const cssPropsAttributes = getCSSPropsAttributes(ModalMeta, { variant, size }, style);
    const cssPropsClassName = cn(`
    u:default-size-medium
    u:default-variant-dialog
    u:max-xs:default-variant-drawer
    u:max-2xs:prop-size-small
  `);
    const hasTrigger = trigger !== undefined;
    const [open, setOpen] = useControlled(controlledOpen, defaultOpen ?? !hasTrigger, onOpenChange);
    // TODO: Allow swiping down to close when `variant` is `drawer` and `dismissible` is `true`
    const dismissible = passedDismissible ?? (hasTrigger || onOpenChange !== undefined);
    const steps = (typeof passedSteps === 'number'
        ? Array.from({ length: Math.max(1, passedSteps) }, (_, i) => i)
        : passedSteps.length === 0
            ? [0]
            : passedSteps);
    const [currentStep, setCurrentStep] = useControlled(controlledCurrentStep, steps[0], onCurrentStepChange);
    let currentStepIndex = steps.indexOf(currentStep);
    currentStepIndex = currentStepIndex === -1 ? null : currentStepIndex;
    const previousStepIndex = useRef(currentStepIndex);
    const currentStepDirection = useRef('left');
    if (currentStepIndex !== previousStepIndex.current) {
        currentStepDirection.current =
            (currentStepIndex ?? steps.length) > (previousStepIndex.current ?? steps.length)
                ? 'left'
                : 'right';
        previousStepIndex.current = currentStepIndex;
    }
    return (_jsx(ModalContext.Provider, { value: {
            open,
            setOpen,
            dismissible,
            steps,
            currentStep,
            setCurrentStep: (step) => {
                if (typeof step === 'number' && steps[step]) {
                    setCurrentStep(steps[step]);
                }
                else if (steps.includes(step)) {
                    setCurrentStep(step);
                }
            },
            currentStepIndex,
            currentStepDirection: currentStepDirection.current,
        }, children: _jsxs(Dialog.Root, { open: open, onOpenChange: (newOpen) => {
                if (!newOpen && !dismissible)
                    return;
                setOpen(newOpen);
            }, disablePointerDismissal: !dismissible, children: [hasTrigger ? (_jsx(Dialog.Trigger, { render: typeof trigger !== 'function'
                        ? trigger
                        : (renderProps) => {
                            // Don't pass event handlers and other potentially too specific props (e.g. `type`)
                            const filteredRenderProps = Object.fromEntries(Object.entries(renderProps).filter(([prop]) => prop === 'ref' ||
                                prop === 'id' ||
                                prop === 'className' ||
                                prop.startsWith('aria-') ||
                                prop.startsWith('data-')));
                            return trigger(filteredRenderProps, {
                                open,
                                setOpen,
                                openModal: () => setOpen(true),
                                currentStep,
                                setCurrentStep,
                            });
                        } })) : null, _jsx(Portal, { children: _jsx("div", { ref: cssPropsPolyfillRef, className: cn('gds-modal i:invisible', cssPropsClassName, className), ...cssPropsAttributes, ...cssPropsPolyfillAttributes, ...dirProps, ...props }) }), _jsx(Dialog.Portal, { children: _jsxs("div", { ref: passedRef, 
                        /**
                         * Establishing the root element as a size query container so that consumers can use
                         * `w-*` and `h-*` utilities on it to set the size of the nested `Dialog.Popup`, thanks
                         * to `cqi` & `cqb` units as well as some (probably too clever) math tricks. For
                         * instance, if a width is set on the root, `max(100cqi,100vw-100cqi*9999)` (used to
                         * calculate the popup's `max-width`) returns that width (100cqi, since it's guaranteed
                         * to be larger than 100vw minus 9999 times that value), but if no width is set on the
                         * root, then it returns 100vw because 100cqi, even 9999 times, is 0.
                         */
                        className: cn(`gds-modal @container-[size] pointer-events-none absolute top-0 left-0 u:text-16 u:text-muted i:invisible i:*:visible`, cssPropsClassName, className), ...cssPropsAttributes, ...cssPropsPolyfillAttributes, ...dirProps, ...props, children: [_jsx(Dialog.Backdrop, { className: `
                fixed inset-0 bg-backdrop transition
                data-ending-style:opacity-0
                data-open:pointer-events-previous
                data-starting-style:opacity-0
                @prop-variant-dialog/modal:duration-200
                @prop-variant-drawer/modal:duration-400
              ` }), _jsx(Dialog.Popup, { role: role ?? (dismissible ? 'dialog' : 'alertdialog'), className: `
                fixed inset-0 m-auto h-max
                max-h-[min(max(100cqb,100vh-100cqb*9999),var(--strict-max-height))]
                min-h-[min(100cqb,var(--strict-max-height))]
                max-w-[min(max(100cqi,100vw-100cqi*9999),var(--strict-max-width))]
                min-w-[min(100cqi,var(--strict-max-width))]
                origin-bottom rounded-t-(--gds-modal-radius-top) rounded-b-(--gds-modal-radius-bottom)
                border border-muted bg-muted outline-0 transition
                [--strict-max-height:max(100vh-2*var(--gds-modal-margin-y))]
                [--strict-max-width:calc(100vw-2*var(--gds-modal-margin-x))]
                data-open:pointer-events-previous
                @prop-variant-dialog/modal:duration-200
                @prop-variant-dialog/modal:data-ending-style:scale-[97%]
                @prop-variant-dialog/modal:data-ending-style:opacity-0
                @prop-variant-dialog/modal:data-starting-style:scale-[97%]
                @prop-variant-dialog/modal:data-starting-style:opacity-0
                @prop-variant-drawer/modal:mb-0
                @prop-variant-drawer/modal:border-b-0
                @prop-variant-drawer/modal:duration-400
                @prop-variant-drawer/modal:[--strict-max-height:max(100vh-var(--gds-modal-margin-y))]
                @prop-variant-drawer/modal:data-ending-style:translate-y-full
                @prop-variant-drawer/modal:data-starting-style:translate-y-full
                @prop-size-small/modal:w-80
                @prop-size-medium/modal:w-130
                @prop-size-large/modal:w-160
                i:@prop-variant-drawer/modal:max-xs:w-full
              `, children: _jsx("div", { className: `
                  max-h-[inherit] min-h-[inherit] overflow-x-clip overflow-y-auto gradient-mask-y px-(--gds-modal-padding-x) py-(--gds-modal-padding-y)
                  has-nested/modal-slot:flex
                  has-nested/modal-slot:flex-col
                  has-nested/modal-slot:overflow-y-clip
                  has-nested/modal-slot:p-0
                `, children: typeof children === 'function'
                                        ? children({
                                            open,
                                            setOpen,
                                            closeModal: () => setOpen(false),
                                            currentStep,
                                            setCurrentStep,
                                        })
                                        : children }) })] }) })] }) }));
};
ModalRoot.displayName = 'Modal';
export const ModalHeader = ({ title, buttonBefore: passedButtonBefore, buttonAfter: passedButtonAfter, stepper: passedStepper, className, ...props }) => {
    const modalContext = useContext(ModalContext);
    const stepCount = modalContext?.steps.length ?? 0;
    const currentStep = modalContext?.currentStep ?? 0;
    const currentStepIndex = modalContext?.currentStepIndex ?? null;
    const currentStepDirection = modalContext?.currentStepDirection ?? 'left';
    const stepper = passedStepper !== undefined
        ? passedStepper && passedStepper.count >= 1
            ? passedStepper
            : null
        : stepCount > 1 && currentStepIndex !== null
            ? { count: stepCount, currentIndex: currentStepIndex }
            : null;
    const buttonTransitionClassName = cn(`
    min-w-5 shrink-0
    **:button:default-variant-naked
    style-nested/transition-content:items-center
    style-nested/transition-content:justify-center
    @prop-size-small/modal:**:button:default-size-small
    @prop-size-medium/modal:**:button:default-size-medium
    @prop-size-large/modal:**:button:default-size-medium
  `);
    const buttonBefore = passedButtonBefore !== undefined ? (passedButtonBefore) : modalContext && currentStepIndex !== null && currentStepIndex > 0 ? (_jsx(Button, { onClick: () => modalContext.setCurrentStep(currentStepIndex - 1), children: _jsx(ArrowLeftIcon, { alt: "Back" }) })) : null;
    const buttonAfter = passedButtonAfter !== undefined ? (passedButtonAfter) : modalContext && modalContext.dismissible ? (_jsx(Dialog.Close, { render: _jsx(Button, { tooltip: null, children: _jsx(XIcon, { alt: "Close" }) }) })) : null;
    return (_jsxs("div", { className: cn('nested/modal-slot shrink-0', className), ...props, children: [_jsxs("div", { className: `
          flex items-center gap-4
          @prop-size-small/modal:h-12
          @prop-size-small/modal:px-4
          @prop-size-medium/modal:h-16
          @prop-size-medium/modal:px-6
          @prop-size-large/modal:h-16
          @prop-size-large/modal:px-6
        `, children: [_jsx(Transition, { layout: "flex-col", mode: "exit-enter", animateSize: false, className: buttonTransitionClassName, children: buttonBefore }), _jsx(Dialog.Title, { className: `
            flex-1 text-center font-medium text-default
            @prop-size-small/modal:text-14
            @prop-size-medium/modal:text-16
            @prop-size-large/modal:text-16
          `, children: _jsx(Transition, { "data-direction": currentStepDirection, className: `
              data-[direction=left]:var-[enter-translate-x=32px]
              data-[direction=left]:var-[exit-translate-x=-32px]
              data-[direction=right]:var-[enter-translate-x=-32px]
              data-[direction=right]:var-[exit-translate-x=32px]
              style-nested/transition-content:truncate
            `, children: _jsx("span", { children: title ? title : _jsx(_Fragment, { children: "\u00A0" }) }, currentStep) }) }), _jsx(Transition, { layout: "flex-col", mode: "exit-enter", animateSize: false, className: buttonTransitionClassName, children: buttonAfter })] }), _jsx(Transition, { children: stepper ? _jsx(Stepper, { ...stepper, className: "-mt-px" }) : _jsx(Divider, { variant: "muted" }) })] }));
};
ModalHeader.displayName = 'Modal.Header';
export const ModalBody = ({ className, children, ...props }) => {
    const modalContext = useContext(ModalContext);
    const currentStep = modalContext?.currentStep ?? 0;
    return (_jsx("div", { className: cn('nested/modal-slot root-flex grow flex-col', className), ...props, children: _jsx(Transition, { layout: "flex-col", mode: "exit-enter", animateSize: "clip", children: _jsx("div", { className: "max-h-full overflow-x-clip overflow-y-auto gradient-mask-y", children: _jsx("div", { className: "px-(--gds-modal-padding-x) py-(--gds-modal-padding-y)", children: children }) }, currentStep) }) }));
};
ModalBody.displayName = 'Modal.Body';
export const ModalFooter = ({ primaryButton, secondaryButton, className, children, ...props }) => {
    const modalContext = useContext(ModalContext);
    const currentStep = modalContext?.currentStep ?? 0;
    const isEmpty = !children && !primaryButton && !secondaryButton;
    return (_jsxs("div", { className: cn('nested/modal-slot shrink-0', className), ...props, children: [_jsx(Transition, { children: !isEmpty ? _jsx(Divider, { variant: "muted" }) : null }), _jsx(Transition, { mode: "exit-enter", children: !isEmpty ? (_jsxs("div", { className: "flex flex-col gap-4 px-(--gds-modal-padding-x) py-(--gds-modal-padding-y)", children: [children ? _jsx("div", { className: "text-14 text-muted", children: children }) : null, primaryButton || secondaryButton ? (_jsxs(ButtonGroup, { fullWidth: true, "data-has-primary-button": Boolean(primaryButton) || undefined, "data-has-secondary-button": Boolean(secondaryButton) || undefined, className: `
                  data-has-primary-button:**:button:last:default-variant-primary
                  data-has-secondary-button:**:button:default-variant-tertiary
                  @prop-size-small/modal:prop-size-small
                  @prop-size-medium/modal:prop-size-medium
                  @prop-size-large/modal:prop-size-medium
                `, children: [secondaryButton, primaryButton] })) : null] }, currentStep)) : null })] }));
};
ModalFooter.displayName = 'Modal.Footer';
const ModalStepContext = createContext(null);
export const ModalStep = ({ children }) => {
    const stepContext = useContext(ModalStepContext);
    const isConsumer = stepContext !== null;
    const version = useRef(0);
    const content = useRef(null);
    const [, setForceRerender] = useState({});
    /**
     * If we're in a consumer and the provider's version is the same as it was after the previous
     * render, we know the current render was not triggered by the provider (since the provider always
     * increases its version when it renders), which means it's safe to re-render the provider, and
     * necessary for the updated content to be displayed.
     */
    useLayoutEffect(() => {
        if (isConsumer) {
            if (version.current === stepContext.version) {
                stepContext.forceRerender();
            }
            else {
                version.current = stepContext.version;
            }
        }
    });
    if (isConsumer) {
        stepContext.setContent(children);
        return null;
    }
    else {
        version.current++;
        const setContent = (updatedContent) => {
            content.current = updatedContent;
        };
        const forceRerender = () => setForceRerender({});
        return (_jsxs(_Fragment, { children: [_jsx(ModalStepContext.Provider, { value: { version: version.current, setContent, forceRerender }, children: children }), _jsx(StableElement, { render: () => content.current })] }));
    }
};
ModalStep.displayName = 'Modal.Step';
const StableElement = ({ render }) => render();
//# sourceMappingURL=Modal.parts.js.map