/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
"use client";
import { cx, getStyles } from "../../../styles/styler.js";
import { Pressable } from "../Pressable.js";
import { IconSlot } from "../../IconSlot.js";
import { Box } from "../../Box.js";
import { HStack } from "../../HStack.js";
import { VStack } from "../../VStack.js";
import { Scrim } from "../../Scrim.js";
import { exposeAriakitScrollbarWidth } from "../../../utils/exposeAriakitScrollbarWidth.js";
import { ModalContext } from "./ModalContext.js";
import { useModalConfig } from "./UDSModalConfigProvider.js";
import { ModalActions } from "./ModalActions.js";
import { ModalContent } from "./ModalContent.js";
import { ModalDescription } from "./ModalDescription.js";
import { ModalTitle } from "./ModalTitle.js";
import { separateChildren } from "./utils.js";
import { Cross } from "@yahoo/uds-icons";
import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { Dialog, DialogDismiss } from "@ariakit/react";
import { useReducedMotion } from "motion/react";
//#region src/components/client/Modal/Modal.tsx
exposeAriakitScrollbarWidth();
const Modal = ({ children, open, onClose, onOpen, portal = true, modal = true, includeScrim, closeAriaLabel = "Close", slotProps, hideDismissButton = false, reduceMotion: forceReduceMotion = false, closeIcon = Cross, maxWidth = "auto", maxHeight: maxHeightProp = "auto", fullWidth = false, fullHeight = false, title: titleProp, description: descriptionProp, content: contentProp, actions: actionsProp, scrollBehavior = "outside", className, style }) => {
	const prevOpen = useRef(open);
	const positionerRef = useRef(null);
	const { size, variant, animationDuration, animationEasing, gutter } = useModalConfig();
	const { in: durationIn, out: durationOut } = typeof animationDuration === "number" ? {
		in: animationDuration,
		out: animationDuration
	} : animationDuration;
	const { in: easingIn, out: easingOut } = typeof animationEasing === "string" ? {
		in: animationEasing,
		out: animationEasing
	} : animationEasing;
	const { title: modalTitle, description: modalDescription, content: modalContent, actions: modalActions } = separateChildren(children);
	const reducedMotion = useReducedMotion() || forceReduceMotion;
	useEffect(() => {
		if (open && !prevOpen.current) onOpen?.();
		prevOpen.current = open;
	}, [open, onOpen]);
	const [shouldLockScroll, setShouldLockScroll] = useState(open);
	if (open && !shouldLockScroll) setShouldLockScroll(true);
	useEffect(() => {
		if (open) return;
		const duration = reducedMotion ? 0 : durationOut;
		const timer = window.setTimeout(() => setShouldLockScroll(false), duration);
		return () => window.clearTimeout(timer);
	}, [
		open,
		reducedMotion,
		durationOut
	]);
	useLayoutEffect(() => {
		if (!open) return;
		const positioner = positionerRef.current;
		const dialog = positioner?.firstElementChild;
		if (!positioner || !dialog) return;
		positioner.style.zIndex = getComputedStyle(dialog).zIndex;
	}, [open]);
	const hasTitleOrDescription = !!(modalTitle || titleProp || modalDescription || descriptionProp);
	const shouldRenderHeader = !!(!hideDismissButton || hasTitleOrDescription);
	const hasContent = !!(modalContent || contentProp);
	const maxHeight = scrollBehavior === "inside" ? maxHeightProp : void 0;
	const classNames = {
		positioner: getStyles({
			spacing: gutter,
			className: cx("fixed inset-0 z-40", scrollBehavior === "outside" ? "overflow-y-auto" : "overflow-hidden", !reducedMotion && "transition-[opacity,visibility]", open ? "visible opacity-100" : "invisible opacity-0", modal === false && "pointer-events-none")
		}),
		root: getStyles({
			modalSizeRoot: size,
			modalVariantRoot: variant,
			className: cx("z-40", "uds-bgBlurFallback", fullWidth ? "w-full" : "w-fit", fullHeight && scrollBehavior === "inside" ? "h-full" : "h-fit", "m-auto pointer-events-auto", scrollBehavior === "inside" && "overflow-hidden max-h-full", !reducedMotion && "transition-transform")
		}),
		header: getStyles({
			modalSizeSpacingHorizontal: size,
			modalSizeHeader: size,
			flexDirection: "row-reverse",
			justifyContent: "space-between",
			alignItems: hideDismissButton ? "flex-end" : "flex-start"
		}),
		titleDescriptionWrapper: getStyles({ modalSizeTitleDescriptionWrapper: size }),
		closeIconContainer: getStyles({
			modalSizeCloseIconContainer: size,
			borderRadius: "full",
			className: cx(reducedMotion ? "duration-0" : "duration-120", "transition-[background-color]", "bg-carbon-15/0", "hover:bg-carbon-15/10", "active:bg-carbon-15/15", "uds-ring", "[translate:50%_-50%]")
		}),
		closeIcon: getStyles({
			modalSizeCloseIcon: size,
			modalVariantCloseIcon: variant
		})
	};
	const backdrop = includeScrim ?? modal ? /* @__PURE__ */ jsx(Scrim, {
		animateOpacity: true,
		...slotProps?.scrim,
		className: cx(!open && "pointer-events-none", slotProps?.scrim?.className),
		style: {
			...slotProps?.scrim?.style,
			...!reducedMotion ? {
				transitionDuration: `${open ? durationIn : durationOut}ms`,
				transitionTimingFunction: open ? easingIn : easingOut
			} : void 0
		}
	}) : false;
	return /* @__PURE__ */ jsx(Dialog, {
		open,
		onClose,
		portal,
		modal,
		className: classNames.root,
		backdrop,
		preventBodyScroll: modal ? shouldLockScroll : false,
		alwaysVisible: true,
		autoFocusOnShow: (element) => {
			if (scrollBehavior === "outside") {
				element?.focus({ preventScroll: true });
				positionerRef.current?.scrollTo(0, 0);
				return false;
			}
			return true;
		},
		render: (props) => /* @__PURE__ */ jsx(Box, {
			...slotProps?.positioner,
			ref: positionerRef,
			className: cx(classNames.positioner, slotProps?.positioner?.className),
			style: {
				...slotProps?.positioner?.style,
				...!reducedMotion ? {
					transitionDuration: `${open ? durationIn : durationOut}ms`,
					transitionTimingFunction: open ? easingIn : easingOut
				} : void 0
			},
			children: /* @__PURE__ */ jsx(VStack, {
				...props,
				...slotProps?.root,
				className: cx(props.className, className, slotProps?.root?.className),
				style: {
					...props.style,
					...style,
					...slotProps?.root?.style,
					maxWidth,
					maxHeight,
					...!reducedMotion ? {
						transform: open ? "scale(1)" : "scale(0.95)",
						transitionDuration: `${open ? durationIn : durationOut}ms`,
						transitionTimingFunction: open ? easingIn : easingOut
					} : void 0
				}
			})
		}),
		children: /* @__PURE__ */ jsxs(ModalContext.Provider, {
			value: {
				scrollBehavior,
				shouldRenderHeader,
				hasContent
			},
			children: [
				shouldRenderHeader && /* @__PURE__ */ jsxs(HStack, {
					...slotProps?.header,
					className: cx(classNames.header, slotProps?.header?.className),
					children: [!hideDismissButton && /* @__PURE__ */ jsx(DialogDismiss, {
						render: /* @__PURE__ */ jsx(Pressable, {
							"aria-label": closeAriaLabel,
							onClick: (e) => onClose?.(e.nativeEvent),
							...slotProps?.closeIconContainer,
							className: cx(classNames.closeIconContainer, slotProps?.closeIconContainer?.className)
						}),
						children: /* @__PURE__ */ jsx(IconSlot, {
							icon: closeIcon,
							iconProps: {
								color: "inherit",
								...slotProps?.closeIcon,
								className: cx(classNames.closeIcon, slotProps?.closeIcon?.className)
							}
						})
					}), hasTitleOrDescription && /* @__PURE__ */ jsxs(VStack, {
						...slotProps?.titleDescriptionWrapper,
						className: cx(classNames.titleDescriptionWrapper, slotProps?.titleDescriptionWrapper?.className),
						children: [modalTitle || (titleProp ? /* @__PURE__ */ jsx(ModalTitle, { children: titleProp }) : null), modalDescription || (descriptionProp ? /* @__PURE__ */ jsx(ModalDescription, { children: descriptionProp }) : null)]
					})]
				}),
				modalContent || (contentProp ? /* @__PURE__ */ jsx(ModalContent, { children: contentProp }) : /* @__PURE__ */ jsx(Box, { flexGrow: "1" })),
				modalActions || (actionsProp ? /* @__PURE__ */ jsx(ModalActions, { children: actionsProp }) : null)
			]
		})
	});
};
Modal.displayName = "Modal";
//#endregion
export { Modal };
