/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
"use client";
import { BUTTON_GAP_VAR, BUTTON_SCALE_EFFECT_HOVER, BUTTON_SCALE_EFFECT_PRESSED, BUTTON_SCALE_EFFECT_REST } from "../../css-tokens/dist/index.js";
import { cx, getStyles } from "../../styles/styler.js";
import { createSlot } from "../../utils/createSlot.js";
import { Icon } from "../Icon.js";
import { IconSlot } from "../IconSlot.js";
import { generateDefaultClassName } from "../../automated-config/dist/utils/generateDefaultClassName.js";
import "./buttonConstants.js";
import { SpringMotionConfig } from "./SpringMotionConfig.js";
import { Progress } from "@yahoo/uds-icons";
import { cloneElement, forwardRef, isValidElement, useImperativeHandle, useMemo, useRef } from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
import { AnimatePresence, m, useReducedMotion } from "motion/react";
//#region src/components/client/Button.tsx
const iconContainerMotionVariants = {
	hide: {
		display: "none",
		width: "0px",
		opacity: 0
	},
	loading: {
		display: "flex",
		width: "auto",
		opacity: 1
	},
	icon: {
		display: "flex",
		width: "auto",
		opacity: 1
	}
};
const SCALE_DOWN = .7;
const hiddenState = {
	scale: SCALE_DOWN,
	opacity: 0
};
const visibleState = {
	scale: [
		SCALE_DOWN,
		SCALE_DOWN,
		1
	],
	opacity: [
		0,
		0,
		1
	],
	transition: { times: [
		0,
		.5,
		1
	] }
};
const iconMotionVariants = {
	hide: hiddenState,
	icon: visibleState,
	loading: hiddenState
};
const loadingMotionVariants = {
	hide: hiddenState,
	icon: hiddenState,
	loading: visibleState
};
function getGapVariant({ startIcon, endIcon, loading }) {
	if (loading || startIcon || endIcon) return "withIcon";
	return "withoutIcon";
}
function getStartVariant({ loading, startIcon }) {
	if (loading) return "loading";
	if (startIcon) return "icon";
	return "hide";
}
const defaultVariantRootClass = generateDefaultClassName("button", "variant", "root");
const defaultVariantIconClass = generateDefaultClassName("button", "variant", "icon");
const defaultSizeRootClass = generateDefaultClassName("button", "size", "root");
const defaultSizeIconClass = generateDefaultClassName("button", "size", "icon");
/**
* **🖲️ A button element that can be used to trigger an action**
*
* @componentType Client component
*
* @description A button is a fundamental component used to trigger an action or event. Buttons are interactive elements that users can click, tap, or otherwise engage with to submit forms, open dialogues, or perform any other interaction within an application or website. Consider an IconButton for buttons that only contain an icon.
*
* @see The {@link https://uds.build/docs/components/button Button Docs} for more info
*
* @example
* ```tsx
* 'use client';
* import { Button, HStack } from "@yahoo/uds";
*
* export function Demo() {
*   return (
*     <HStack gap="2">
*       <Button onClick={console.log}>Save</Button>
*       <Button variant="secondary" onClick={console.log}>Cancel</Button>
*     </HStack>
*   )
* }
* ```
*
*
* @usage
* Buttons should be used to clearly indicate and initiate actions that users can take.
*
* @related [Icon](https://uds.build/docs/components/icon), [IconButton](https://uds.build/docs/components/icon-button), [Pressable](https://uds.build/docs/components/pressable)
**/
const Button = forwardRef(function Button({ size, variant, startIcon, endIcon, iconVariant, loading, disableEffects, children, asChild = false, slotProps, type = "button", className, width, ...rest }, forwardedRef) {
	const ref = useRef(null);
	useImperativeHandle(forwardedRef, () => ref.current);
	const { className: startIconClassName, ...startIconSlotProps } = slotProps?.startIcon ?? {};
	const { className: endIconClassName, ...endIconSlotProps } = slotProps?.endIcon ?? {};
	const { className: contentClassName, ...contentSlotProps } = slotProps?.content ?? {};
	const prefersReducedMotion = useReducedMotion();
	const disableMotion = !!disableEffects || !!rest?.disabled;
	const layoutVariant = prefersReducedMotion ? "smooth" : "subtle";
	const endVariant = endIcon ? "icon" : "hide";
	const gapVariant = getGapVariant({
		startIcon,
		endIcon,
		loading
	});
	const startVariant = getStartVariant({
		loading,
		startIcon
	});
	const Slot = useMemo(() => createSlot(), []);
	const MotionSlot = useMemo(() => m.create(Slot), [Slot]);
	const buttonVariants = useMemo(() => ({
		rest: { scale: disableMotion ? 1 : `var(${BUTTON_SCALE_EFFECT_REST})` },
		hover: { scale: disableMotion ? 1 : `var(${BUTTON_SCALE_EFFECT_HOVER})` },
		pressed: { scale: disableMotion ? 1 : `var(${BUTTON_SCALE_EFFECT_PRESSED})` },
		withIcon: { columnGap: `var(${BUTTON_GAP_VAR})` },
		withoutIcon: { columnGap: "0px" }
	}), [disableMotion]);
	const rootSizeClass = useMemo(() => size ? getStyles({ buttonSizeRoot: size }) : defaultSizeRootClass, [size]);
	const rootVariantClass = useMemo(() => variant ? getStyles({ buttonVariantRoot: variant }) : defaultVariantRootClass, [variant]);
	const iconSizeClass = useMemo(() => size ? getStyles({ buttonSizeIcon: size }) : defaultSizeIconClass, [size]);
	const iconVariantClass = useMemo(() => variant ? getStyles({ buttonVariantIcon: variant }) : defaultVariantIconClass, [variant]);
	const styles = useMemo(() => ({
		root: getStyles({
			width,
			className: cx([
				"uds-ring",
				"uds-hit-target",
				"inline-flex overflow-hidden justify-center items-center whitespace-nowrap select-none",
				"[transform-origin:center]",
				"[backface-visibility:hidden]",
				"[transition-property:color,background-color,border-color,box-shadow,text-decoration-color,fill,stroke]",
				"[transition-timing-function:cubic-bezier(0,0,0.2,1)]",
				"[transition-duration:220ms]",
				rootSizeClass,
				rootVariantClass,
				rest?.disabled && "cursor-not-allowed",
				loading && "uds-button-loading",
				disableEffects && "uds-button-without-effects",
				gapVariant === "withIcon" && "uds-button-with-gap",
				className
			])
		}),
		iconContainer: "flex overflow-clip uds-button-icon-container",
		icon: getStyles({ className: cx([iconSizeClass, iconVariantClass]) }),
		loadingIcon: getStyles({ className: cx([
			"animate-spin",
			iconSizeClass,
			iconVariantClass
		]) }),
		content: cx(["truncate"])
	}), [
		className,
		disableEffects,
		gapVariant,
		iconSizeClass,
		iconVariantClass,
		loading,
		rest?.disabled,
		rootSizeClass,
		rootVariantClass,
		width
	]);
	const startContent = useMemo(() => /* @__PURE__ */ jsx(m.span, {
		className: styles.iconContainer,
		initial: false,
		variants: iconContainerMotionVariants,
		animate: startVariant,
		children: /* @__PURE__ */ jsxs(AnimatePresence, {
			initial: false,
			mode: "popLayout",
			children: [loading && /* @__PURE__ */ jsx(m.span, {
				variants: loadingMotionVariants,
				initial: "hide",
				animate: "loading",
				exit: "hide",
				children: /* @__PURE__ */ jsx(Icon, {
					className: styles.loadingIcon,
					size: "sm",
					name: Progress,
					variant: iconVariant,
					color: "current"
				})
			}, "loading"), startIcon && !loading && /* @__PURE__ */ jsx(m.span, {
				variants: iconMotionVariants,
				initial: "hide",
				animate: "icon",
				exit: "hide",
				children: /* @__PURE__ */ jsx(IconSlot, {
					className: cx(styles.icon, startIconClassName),
					icon: startIcon,
					iconProps: {
						size: "sm",
						variant: iconVariant,
						color: "current"
					},
					...startIconSlotProps
				})
			})]
		})
	}), [
		styles,
		iconVariant,
		loading,
		startIcon,
		startVariant,
		startIconClassName,
		startIconSlotProps
	]);
	const endContent = useMemo(() => /* @__PURE__ */ jsx(m.span, {
		className: styles.iconContainer,
		initial: false,
		variants: iconContainerMotionVariants,
		animate: endVariant,
		children: /* @__PURE__ */ jsx(AnimatePresence, {
			initial: false,
			mode: "popLayout",
			children: endIcon && /* @__PURE__ */ jsx(m.span, {
				variants: iconMotionVariants,
				initial: "hide",
				animate: "icon",
				exit: "hide",
				children: /* @__PURE__ */ jsx(IconSlot, {
					className: cx(styles.icon, endIconClassName),
					icon: endIcon,
					iconProps: {
						size: "sm",
						variant: iconVariant,
						color: "current"
					},
					...endIconSlotProps
				})
			})
		})
	}), [
		endIcon,
		styles,
		iconVariant,
		endVariant,
		endIconClassName,
		endIconSlotProps
	]);
	if (asChild && isValidElement(children)) {
		const childProps = children.props;
		return /* @__PURE__ */ jsx(SpringMotionConfig, {
			layoutSpeed: "3",
			layoutVariant,
			children: /* @__PURE__ */ jsx(MotionSlot, {
				type,
				className: styles.root,
				initial: ["rest", gapVariant],
				animate: [
					"hide",
					"rest",
					gapVariant
				],
				variants: buttonVariants,
				whileHover: "hover",
				whileTap: "pressed",
				...rest,
				children: cloneElement(children, childProps, /* @__PURE__ */ jsxs(Fragment$1, { children: [
					startContent,
					/* @__PURE__ */ jsx("span", {
						className: cx(styles.content, contentClassName),
						...contentSlotProps,
						children: children.props.children
					}),
					endContent
				] }))
			})
		});
	}
	return /* @__PURE__ */ jsx(SpringMotionConfig, {
		layoutSpeed: "3",
		layoutVariant,
		children: /* @__PURE__ */ jsxs(m.button, {
			ref,
			type,
			className: styles.root,
			initial: ["rest", gapVariant],
			animate: [
				"hide",
				"rest",
				gapVariant
			],
			variants: buttonVariants,
			whileHover: "hover",
			whileTap: "pressed",
			...rest,
			children: [
				startContent,
				/* @__PURE__ */ jsx("span", {
					className: cx(styles.content, contentClassName),
					...contentSlotProps,
					children
				}),
				endContent
			]
		})
	});
});
Button.displayName = "Button";
//#endregion
export { Button, iconMotionVariants, loadingMotionVariants };
