/**
 * Copyright IBM Corp. 2020, 2026
 *
 * This source code is licensed under the Apache-2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 */

import { __toESM } from "../../_virtual/_rolldown/runtime.js";
import { require_classnames } from "../../node_modules/classnames/index.js";
import pconsole_default from "../../global/js/utils/pconsole.js";
import { pkg } from "../../settings.js";
import { useIsomorphicEffect } from "../../global/js/hooks/useIsomorphicEffect.js";
import { usePreviousValue } from "../../global/js/hooks/usePreviousValue.js";
import { useFocus } from "../../global/js/hooks/useFocus.js";
import { deprecateProp } from "../../global/js/utils/props-helper.js";
import { usePortalTarget } from "../../global/js/hooks/usePortalTarget.js";
import { useResizeObserver } from "../../global/js/hooks/useResizeObserver.js";
import { ActionSet } from "../ActionSet/ActionSet.js";
import { getNodeTextContent } from "../../global/js/utils/getNodeTextContent.js";
import { Wrap } from "../../global/js/utils/Wrap.js";
import { useMergedRefs } from "../../global/js/hooks/useMergedRefs.js";
import { useId } from "../../global/js/utils/useId.js";
import { TearsheetPresence, TearsheetPresenceContext, useExclusiveTearsheetPresenceContext } from "./TearsheetPresence.js";
import React, { useContext, useEffect, useRef, useState } from "react";
import PropTypes from "prop-types";
import { Button, ComposedModal, Layer, ModalHeader, Section, unstable_FeatureFlags, useFeatureFlag, usePrefix } from "@carbon/react";

//#region src/components/Tearsheet/TearsheetShell.tsx
/**
* Copyright IBM Corp. 2020, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
var import_classnames = /* @__PURE__ */ __toESM(require_classnames());
const bc = `${pkg.prefix}--tearsheet`;
const componentName = "TearsheetShell";
const maxDepth = 3;
const stack = {
	open: [],
	all: [],
	sizes: []
};
const tearsheetShellWideProps = [
	"headerActions",
	"influencer",
	"influencerPosition",
	"influencerWidth",
	"navigation"
];
const tearsheetIsPassive = (actions) => !actions || !actions?.length;
const tearsheetHasCloseIcon = (actions, hasCloseIcon) => hasCloseIcon ?? tearsheetIsPassive(actions);
/**
* Since the Tearsheet has an H3 heading, any headings inside the Tearsheet should start at H4.
* This is a helper to do that.
*/
const SectionLevel3 = ({ children, ...rest }) => /* @__PURE__ */ React.createElement(Section, {
	level: 3,
	...rest
}, children);
/**
*  TearSheetShell is used internally by TearSheet and TearSheetNarrow
*
* The component is not public.
*
* See the canvas tab for the component API details.
* */
const TearsheetShell = React.forwardRef(({ open, ...props }, ref) => {
	const id = useId();
	const enablePresence = useFeatureFlag("enable-presence");
	const hasPresenceContext = Boolean(useContext(TearsheetPresenceContext));
	const hasPresenceOptIn = enablePresence || hasPresenceContext;
	const exclusivePresenceContext = useExclusiveTearsheetPresenceContext(id);
	if (hasPresenceOptIn && !exclusivePresenceContext) return /* @__PURE__ */ React.createElement(TearsheetPresence, {
		open: open ?? false,
		_presenceId: id,
		_autoEnablePresence: hasPresenceContext
	}, /* @__PURE__ */ React.createElement(TearsheetShellDialog, {
		open: true,
		ref,
		...props
	}));
	return /* @__PURE__ */ React.createElement(TearsheetShellDialog, {
		ref,
		open,
		...props
	});
});
const TearsheetShellDialog = React.forwardRef(({ actions, decorator, ariaLabel, children, className, closeIconDescription = "Close", currentStep, description, hasCloseIcon, hasError, headerActions, influencer, influencerPosition, influencerWidth, label, navigation, onClose, open: externalOpen, portalTarget: portalTargetIn, selectorPrimaryFocus, selectorsFloatingMenus = [], size, slug: deprecated_slug, title, verticalPosition, launcherButtonRef, ...rest }, ref) => {
	const carbonPrefix = usePrefix();
	const bcModalHeader = `${carbonPrefix}--modal-header`;
	const renderPortalUse = usePortalTarget(portalTargetIn);
	const localRef = useRef(void 0);
	const resizer = useRef(null);
	const modalBodyRef = useRef(null);
	const modalRef = ref || localRef;
	const { width } = useResizeObserver(resizer);
	const { keyDownListener, claimFocus } = useFocus(modalRef, selectorPrimaryFocus);
	modalRef.current;
	const wide = size === "wide";
	const presenceContext = useContext(TearsheetPresenceContext);
	const mergedRefs = useMergedRefs([modalRef, presenceContext?.presenceRef]);
	const enablePresence = useFeatureFlag("enable-presence") || presenceContext?.autoEnablePresence;
	const open = externalOpen || enablePresence;
	const prevOpen = usePreviousValue(open);
	const [depth, setDepth] = useState(0);
	const [position, setPosition] = useState(0);
	const prevDepth = useRef(void 0);
	useEffect(() => {
		prevDepth.current = depth;
	});
	const isPassive = tearsheetIsPassive(actions);
	const effectiveHasCloseIcon = tearsheetHasCloseIcon(actions, hasCloseIcon);
	function handleStackChange(newDepth, newPosition) {
		setDepth(newDepth);
		setPosition(newPosition);
	}
	useEffect(() => {
		if (open) claimFocus();
	}, [
		open,
		currentStep,
		effectiveHasCloseIcon,
		claimFocus
	]);
	useEffect(() => {
		if (!enablePresence && prevOpen && !open && launcherButtonRef?.current) setTimeout(() => {
			launcherButtonRef?.current?.focus();
		}, 10);
	}, [
		enablePresence,
		open,
		prevOpen,
		launcherButtonRef
	]);
	useEffect(() => {
		const launcherButton = launcherButtonRef?.current;
		if (!enablePresence || !launcherButton) return;
		return () => {
			setTimeout(() => {
				launcherButton.focus();
			}, 10);
		};
	}, [enablePresence, launcherButtonRef]);
	useEffect(() => {
		requestAnimationFrame(() => {
			if (open && depth === position && !modalRef?.current?.contains(document.activeElement)) claimFocus();
		});
	}, [
		claimFocus,
		depth,
		modalRef,
		position
	]);
	useEffect(() => {
		if (hasError && !modalRef?.current?.contains(document.activeElement)) claimFocus();
	}, [
		claimFocus,
		hasError,
		modalRef
	]);
	useEffect(() => {
		const isPresent = open && !presenceContext?.isExiting;
		const notify = () => stack.all.forEach((handler) => {
			handler(Math.min(stack.open.length, maxDepth), stack.open.indexOf(handler) + 1);
		});
		stack.all.push(handleStackChange);
		stack.sizes.push(size);
		if (isPresent) {
			stack.open.push(handleStackChange);
			notify();
		}
		return function cleanup() {
			stack.all.splice(stack.all.indexOf(handleStackChange), 1);
			stack.sizes.splice(stack.sizes.indexOf(size), 1);
			const openIndex = stack.open.indexOf(handleStackChange);
			if (openIndex >= 0) {
				stack.open.splice(openIndex, 1);
				notify();
			}
		};
	}, [
		open,
		presenceContext?.isExiting,
		size
	]);
	const areAllSameSizeVariant = () => new Set(stack.sizes).size === 1;
	useIsomorphicEffect(() => {
		const setScaleValues = () => {
			if (!areAllSameSizeVariant()) return {
				[`--${bc}--stacking-scale-factor-single`]: 1,
				[`--${bc}--stacking-scale-factor-double`]: 1
			};
			return {
				[`--${bc}--stacking-scale-factor-single`]: (width - 32) / width,
				[`--${bc}--stacking-scale-factor-double`]: (width - 64) / width
			};
		};
		if (modalRef.current) Object.entries(setScaleValues()).map(([key, value]) => {
			modalRef.current.style.setProperty(key, String(value));
		});
	}, [modalRef, width]);
	if (position <= depth) {
		const includeHeader = label || title || description || headerActions || navigation || effectiveHasCloseIcon;
		const includeActions = actions && actions?.length > 0;
		const areAllSameSizeVariant = () => new Set(stack.sizes).size === 1;
		return renderPortalUse(/* @__PURE__ */ React.createElement(unstable_FeatureFlags, { enableExperimentalFocusWrapWithoutSentinels: true }, /* @__PURE__ */ React.createElement(ComposedModal, {
			...rest,
			"aria-label": ariaLabel || getNodeTextContent(title),
			className: (0, import_classnames.default)(bc, className, {
				[`${bc}--stacked-${position}-of-${depth}`]: depth > 1 || depth === 1 && (prevDepth?.current ?? 0) > 1,
				[`${bc}--wide`]: wide,
				[`${bc}--narrow`]: !wide,
				[`${bc}--has-slug`]: deprecated_slug,
				[`${bc}--has-ai-label`]: !!decorator && decorator["type"]?.displayName === "AILabel",
				[`${bc}--has-decorator`]: !!decorator && decorator["type"]?.displayName !== "AILabel",
				[`${bc}--has-close`]: effectiveHasCloseIcon,
				["is-visible"]: enablePresence,
				[`${bc}--tearsheet-enable-presence`]: presenceContext?.autoEnablePresence
			}),
			decorator: decorator || deprecated_slug,
			containerClassName: (0, import_classnames.default)(`${bc}__container`, {
				[`${bc}__container--lower`]: verticalPosition === "lower",
				[`${bc}__container--mixed-size-stacking`]: !areAllSameSizeVariant()
			}),
			onClose,
			open,
			selectorPrimaryFocus,
			onKeyDown: keyDownListener,
			preventCloseOnClickOutside: !isPassive,
			ref: mergedRefs,
			selectorsFloatingMenus: [
				`.${carbonPrefix}--overflow-menu-options`,
				`.${carbonPrefix}--tooltip`,
				".flatpickr-calendar",
				`.${bc}__container`,
				`.${carbonPrefix}--menu`,
				...selectorsFloatingMenus
			],
			size: "sm",
			"data-tearsheet-exiting": presenceContext?.isExiting || void 0
		}, includeHeader && /* @__PURE__ */ React.createElement(ModalHeader, {
			className: (0, import_classnames.default)(`${bc}__header`, {
				[`${bc}__header--with-close-icon`]: effectiveHasCloseIcon,
				[`${bc}__header--with-nav`]: navigation
			}),
			closeClassName: (0, import_classnames.default)({ [`${bc}__header--no-close-icon`]: !effectiveHasCloseIcon }),
			closeModal: onClose,
			iconDescription: effectiveHasCloseIcon ? closeIconDescription : void 0
		}, /* @__PURE__ */ React.createElement(Wrap, {
			className: `${bc}__header-content`,
			element: wide ? Layer : void 0
		}, /* @__PURE__ */ React.createElement(Wrap, { className: `${bc}__header-fields` }, /* @__PURE__ */ React.createElement(Wrap, { className: `${bcModalHeader}__label` }, label), /* @__PURE__ */ React.createElement(Wrap, {
			element: "h3",
			className: (0, import_classnames.default)(`${bcModalHeader}__heading`, `${bc}__heading`)
		}, title), /* @__PURE__ */ React.createElement(Wrap, { className: `${bc}__header-description` }, description)), /* @__PURE__ */ React.createElement(Wrap, { className: `${bc}__header-actions` }, headerActions)), /* @__PURE__ */ React.createElement(Wrap, { className: `${bc}__header-navigation` }, navigation)), /* @__PURE__ */ React.createElement(Wrap, {
			ref: modalBodyRef,
			className: `${carbonPrefix}--modal-content ${bc}__body`
		}, /* @__PURE__ */ React.createElement(Wrap, {
			className: (0, import_classnames.default)({
				[`${bc}__influencer`]: true,
				[`${bc}__influencer--wide`]: influencerWidth === "wide"
			}),
			neverRender: influencerPosition === "right",
			element: SectionLevel3
		}, /* @__PURE__ */ React.createElement(Wrap, {
			element: Layer,
			className: `${bc}__layer`
		}, influencer)), /* @__PURE__ */ React.createElement(Wrap, { className: `${bc}__right` }, /* @__PURE__ */ React.createElement(Wrap, {
			className: `${bc}__main`,
			alwaysRender: includeActions
		}, /* @__PURE__ */ React.createElement(Wrap, {
			className: `${bc}__content`,
			alwaysRender: !!(influencer && influencerPosition === "right"),
			element: SectionLevel3
		}, wide ? children : /* @__PURE__ */ React.createElement(Wrap, {
			element: Layer,
			className: `${bc}__layer`
		}, children)), /* @__PURE__ */ React.createElement(Wrap, {
			className: (0, import_classnames.default)({
				[`${bc}__influencer`]: true,
				[`${bc}__influencer--wide`]: influencerWidth === "wide"
			}),
			neverRender: influencerPosition !== "right",
			element: SectionLevel3
		}, /* @__PURE__ */ React.createElement(Wrap, {
			element: Layer,
			className: `${bc}__layer`
		}, influencer))), includeActions && /* @__PURE__ */ React.createElement(Wrap, { className: `${bc}__button-container` }, /* @__PURE__ */ React.createElement(ActionSet, {
			actions,
			buttonSize: wide ? "2xl" : void 0,
			className: `${bc}__buttons`,
			size: wide ? "2xl" : "lg",
			"aria-hidden": !open
		})))), /* @__PURE__ */ React.createElement("div", {
			className: `${bc}__resize-detector`,
			ref: resizer
		}))));
	} else {
		pconsole_default.warn("Tearsheet not rendered: maximum stacking depth exceeded.");
		return null;
	}
});
TearsheetShell.displayName = componentName;
const portalType = typeof Element === "undefined" ? PropTypes.object : PropTypes.instanceOf(Element);
const deprecatedProps = {
	slug: deprecateProp(PropTypes.node, "Property replaced by `decorator`"),
	verticalPosition: PropTypes.oneOf(["normal", "lower"])
};
TearsheetShell.propTypes = {
	actions: PropTypes.arrayOf(PropTypes.shape({
		...Button.propTypes,
		kind: PropTypes.oneOf([
			"ghost",
			"danger--ghost",
			"secondary",
			"danger",
			"primary"
		]),
		label: PropTypes.string,
		loading: PropTypes.bool,
		onClick: Button.propTypes.onClick
	})),
	children: PropTypes.node,
	className: PropTypes.string,
	closeIconDescription: PropTypes.string,
	decorator: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]),
	description: PropTypes.node,
	hasCloseIcon: PropTypes.bool,
	headerActions: PropTypes.element,
	influencer: PropTypes.element,
	influencerPosition: PropTypes.oneOf(["left", "right"]),
	influencerWidth: PropTypes.oneOf(["narrow", "wide"]),
	label: PropTypes.node,
	launcherButtonRef: PropTypes.any,
	navigation: PropTypes.element,
	onClose: PropTypes.func,
	open: PropTypes.bool,
	portalTarget: portalType,
	selectorPrimaryFocus: PropTypes.string,
	selectorsFloatingMenus: PropTypes.arrayOf(PropTypes.string),
	size: PropTypes.oneOf(["narrow", "wide"]).isRequired,
	title: PropTypes.node,
	...deprecatedProps
};

//#endregion
export { TearsheetShell, portalType, tearsheetShellWideProps };