import { isReactText, isString } from "../utils/assertion.js";
import { activeClassName } from "../utils/consts.js";
import { filterUndefined } from "../utils/object.js";
import { cs } from "../utils/styles.js";
import { useStyleConfig } from "../core/theme.js";
import styled from "../core/styled.js";
import vui from "../core/vui.js";
import { useButtonGroupContext } from "../buttonGroup/context.js";
import { ButtonProvider } from "./context.js";
import ButtonIcon from "./buttonIcon.js";
import ButtonText from "./buttonText.js";
import { buttonStateMapping, loadingIconProps } from "./consts.js";
import { Fragment, useCallback, useMemo } from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";

//#region src/button/button.tsx
const DEFAULT_BORDER_WIDTH = 1;
const DEFAULT_BOX_SHADOW = "md";
const DEFAULT_DISABLED_OPACITY = .5;
const BUTTON_TYPE = "button";
const FOCUS_RING_SIZE = 3;
const MENU_FOCUS_BORDER_WIDTH = 3;
const ContentWrapper = styled.span`
  visibility: hidden;
`;
const StateWrapper = styled.span`
  bottom: 0;
  display: flex;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
`;
const ButtonBase = styled.buttonBox`
  align-items: center;
  display: inline-flex;
  flex-shrink: 0;
  font-weight: var(--vui-button-font-weight, medium);
  justify-content: center;
  line-height: normal;
  overflow: hidden;
  position: relative;
  transition-duration: var(--vui-button-transition-duration, fast);
  user-select: none;
  width: fit-content;

  /* Menu variant active hover states
   * Note: Colors defined in theme.ts menuLight/menuDark variants
   * Using CSS variables here for performance (avoiding theme lookup on every render)
   */
  &.vui-button-variant-menuLight.vui-active:hover {
    background-color: var(--color-sky-blue-90); /* theme: menuLight.hoverBg */
    color: var(--color-sea-blue-35); /* theme: menuLight.hoverColor */
    border-left-color: var(--color-sea-blue-35); /* theme: menuLight.hoverBorderColor */
  }
  
  &.vui-button-variant-menuDark.vui-active:hover {
    background-color: var(--color-sea-blue-35); /* theme: menuDark.hoverBg */
    color: var(--color-eucalyptus-70); /* theme: menuDark.activeColor */
    border-left-color: var(--color-eucalyptus-70); /* theme: menuDark.hoverBorderColor */
  }

  /* Menu variant focus states - default removes focus ring
   * Used when focusAsBorder class is NOT present (standard focus ring behavior)
   */
  &.vui-button-variant-menuDark:not(.focusAsBorder):focus,
  &.vui-button-variant-menuDark:not(.focusAsBorder):focus-visible,
  &.vui-button-variant-menuLight:not(.focusAsBorder):focus,
  &.vui-button-variant-menuLight:not(.focusAsBorder):focus-visible {
    box-shadow: none;
    outline: none;
  }

  /* Menu variant focus states - with border indicator for accessibility
   * Used when focusAsBorder class IS present (alternative focus indication via border)
   * Color: theme menuLight/menuDark.focusBorderBottomColor
   */
  &.vui-button-variant-menuDark.focusAsBorder:focus,
  &.vui-button-variant-menuDark.focusAsBorder:focus-visible,
  &.vui-button-variant-menuLight.focusAsBorder:focus,
  &.vui-button-variant-menuLight.focusAsBorder:focus-visible {
    transition: border-bottom 0s linear;
    border-bottom: ${MENU_FOCUS_BORDER_WIDTH}px solid var(--color-sky-blue-90); /* theme: focusBorderBottomColor */
  }
`;
/**
* Extracts a numeric value from various input types (number, string, etc.)
* @param value - Value to extract number from
* @param fallback - Default value if extraction fails
* @returns Extracted number or fallback
*/
const extractNumericValue = (value, fallback = DEFAULT_BORDER_WIDTH) => {
	if (typeof value === "number") return value;
	if (typeof value === "string") {
		const parsed = parseInt(value, 10);
		if (!isNaN(parsed)) return parsed;
	}
	return fallback;
};
/**
* Consolidated hook for computing all button styles and props.
* Combines theme resolution, spacing, state-based styles, and className generation.
* Reduces memoization overhead by computing all derived values in a single pass.
*
* @param mergedProps - Combined props from ButtonGroup context and component props
* @param variant - Resolved variant object with theme overrides
* @param borderWidthProp - Optional border width override from props
* @param icon - Main icon (replaces all content when present)
* @param iconLeft - Left icon slot
* @param iconRight - Right icon slot
* @param isLoading - Loading state flag
* @param isSplit - Deprecated: Split layout mode
* @param disabled - Disabled state flag
* @param isActive - Active state flag
* @param isRound - Round/pill-shaped borders flag
* @param isElevated - Box shadow elevation flag
* @param hasState - Whether button has a state overlay
* @param isFullWidth - Full width layout flag
* @param className - Additional CSS classes
* @param variantProp - Variant name for class generation
* @returns Computed styles, spacing, props, and className
*/
const useButtonComputed = (mergedProps, variant, borderWidthProp, icon, iconLeft, iconRight, isLoading, isSplit, disabled, isActive, isRound, isElevated, hasState, isFullWidth, className, variantProp) => {
	const styles = useStyleConfig("Button", {
		...mergedProps,
		...variant
	}) || {};
	return useMemo(() => {
		const container = styles.container || {};
		const { borderWidth = DEFAULT_BORDER_WIDTH, h = 32, spaceX = 0, ...buttonStyles } = container;
		const normalizedStyles = {
			...buttonStyles,
			borderColor: buttonStyles.borderColor ?? buttonStyles.bg,
			activeBorderColor: buttonStyles.activeBorderColor ?? buttonStyles.activeBg,
			activeColor: buttonStyles.activeColor ?? buttonStyles.color,
			focusBg: buttonStyles.focusBg ?? buttonStyles.bg,
			focusBorderColor: buttonStyles.focusBorderColor ?? buttonStyles.activeBorderColor ?? buttonStyles.borderColor,
			focusColor: buttonStyles.focusColor ?? buttonStyles.color,
			hoverBorderColor: buttonStyles.hoverBorderColor ?? buttonStyles.hoverBg,
			hoverColor: buttonStyles.hoverColor ?? buttonStyles.color
		};
		const border = extractNumericValue(borderWidthProp) || borderWidth || DEFAULT_BORDER_WIDTH;
		const spaceXItem = spaceX - border;
		const spaceXText = spaceX * 2 - border;
		return {
			styles,
			borderWidth,
			h,
			spaceX,
			buttonStyles: normalizedStyles,
			spacing: {
				borderWidth: border,
				pl: `var(--vui-button-px-start, ${icon || iconLeft || isLoading ? spaceXItem : spaceXText}px)`,
				pr: `var(--vui-button-px-end, ${icon || iconRight ? spaceXItem : spaceXText}px)`
			},
			disabledProps: disabled ? filterUndefined({
				"aria-disabled": disabled,
				bg: container?.disabledBg ?? void 0,
				borderColor: container?.disabledBorderColor ?? void 0,
				color: container?.disabledColor ?? void 0,
				hoverBg: container?.disabledBg ?? normalizedStyles.bg,
				hoverBorderColor: container?.disabledBorderColor ?? normalizedStyles.borderColor,
				hoverColor: container?.disabledColor ?? normalizedStyles.color,
				activeBg: container?.disabledBg ?? normalizedStyles.bg,
				cursor: "not-allowed",
				opacity: container?.disabledOpacity ?? DEFAULT_DISABLED_OPACITY
			}) : {},
			activeProps: isActive ? filterUndefined({
				bg: container?.activeBg,
				borderBg: container?.activeBorderBg,
				color: container?.activeColor
			}) : {},
			aliasedProps: filterUndefined({
				borderRadius: isRound ? h / 2 : `var(--vui-button-border-radius, ${container?.borderRadius || 0}px)`,
				boxShadow: isElevated ? `var(--vui-button-box-shadow, ${DEFAULT_BOX_SHADOW})` : void 0,
				minW: icon ? 0 : `var(--vui-button-min-w, auto)`,
				pointerEvents: hasState ? "none" : void 0,
				w: isFullWidth ? "100%" : void 0
			}),
			buttonClassName: cs("vui-button", className, isActive && activeClassName, variantProp ? `vui-button-variant-${variantProp}` : void 0)
		};
	}, [
		styles,
		mergedProps,
		variant,
		borderWidthProp,
		icon,
		iconLeft,
		iconRight,
		isLoading,
		isSplit,
		disabled,
		isActive,
		isRound,
		isElevated,
		hasState,
		isFullWidth,
		className,
		variantProp
	]);
};
/**
* Unified icon renderer for all button icon positions.
* Converts string icon names to ButtonIcon components with appropriate margins.
*
* @param iconProp - Icon name string or React element
* @param position - Icon position: 'main' (center), 'left', or 'right'
* @param isLoading - Whether to show loading spinner (only applies to left position)
* @returns Rendered icon or null
*/
const renderButtonIcon = (iconProp, position = "main", isLoading = false) => {
	if (position === "left" && isLoading) return /* @__PURE__ */ jsx(ButtonIcon, {
		...loadingIconProps,
		ml: 0
	});
	if (!iconProp) return null;
	if (!isString(iconProp)) return iconProp;
	switch (position) {
		case "left": return /* @__PURE__ */ jsx(ButtonIcon, {
			name: iconProp,
			ml: 0
		});
		case "right": return /* @__PURE__ */ jsx(ButtonIcon, {
			name: iconProp,
			mr: 0
		});
		default: return /* @__PURE__ */ jsx(ButtonIcon, { name: iconProp });
	}
};
/**
* Renders the button content (text or children).
* Wraps text strings in ButtonText component with optional truncation.
*
* @param children - React children content
* @param text - Text string to render
* @param isTruncated - Whether to enable text truncation
* @returns Rendered content
*/
const renderContent = (children, text, isTruncated) => {
	if (children) return children;
	if (isReactText(text)) return /* @__PURE__ */ jsx(ButtonText, {
		isTruncated,
		text
	});
	return text;
};
/**
* Button Component
*
* A versatile button component that supports multiple states, sizes, variants, and behaviors.
* Part of the VUI design system with built-in accessibility features.
*
*/
const Button = vui((props, ref) => {
	const mergedProps = {
		...useButtonGroupContext(),
		...props
	};
	const { borderWidth: borderWidthProp, children, className, colorScheme, disabled, dropDownIcon = "falAngleDown", icon, iconLeft, iconRight: iconRightProp, isActive, isDropDown, isElevated, isFullWidth, isLoading, isRound, isSplit, isTruncated, size, state = "", stateMapping, text, title, variant: variantProp, ...rest } = mergedProps;
	const hasState = useMemo(() => Boolean(state) && state !== "idle", [state]);
	const states = useMemo(() => ({
		...buttonStateMapping,
		...stateMapping
	}), [stateMapping]);
	const stateData = useMemo(() => states[state] ?? {}, [states, state]);
	const { iconProps: stateIconProps, ...stateProps } = stateData;
	const iconRight = useMemo(() => isDropDown ? "falAngleDown" : iconRightProp, [isDropDown, iconRightProp]);
	const variantForTheme = useMemo(() => filterUndefined({ variant: stateData?.variant ?? variantProp }), [stateData?.variant, variantProp]);
	const computed = useButtonComputed(mergedProps, variantForTheme, borderWidthProp, icon, iconLeft, iconRight, isLoading ?? false, isSplit ?? false, disabled ?? false, isActive ?? false, isRound ?? false, isElevated ?? false, hasState, isFullWidth ?? false, className, variantProp);
	const hasTextContent = Boolean(children || text);
	const contextValue = useMemo(() => filterUndefined({
		disabled,
		size,
		variant: variantForTheme.variant,
		isDropDown,
		hasTextContent
	}), [
		disabled,
		size,
		variantForTheme.variant,
		isDropDown,
		hasTextContent
	]);
	const Content = useMemo(() => hasState ? ContentWrapper : Fragment, [hasState]);
	const handleStateClick = useCallback((e) => {
		e.stopPropagation();
	}, []);
	const finalVariant = stateData?.variant ?? variantProp;
	const borderWidth = computed.spacing.borderWidth;
	const plValue = computed.spacing.pl;
	const prValue = computed.spacing.pr;
	const hValue = computed.h;
	const disabledPropsWithVars = useMemo(() => {
		if (!computed.disabledProps || Object.keys(computed.disabledProps).length === 0) return {};
		const { bg, borderColor, color, opacity, ...otherDisabledProps } = computed.disabledProps;
		return {
			...otherDisabledProps,
			...bg !== void 0 && { bg: `var(--vui-button-disabled-bg, ${bg})` },
			...borderColor !== void 0 && { borderColor: `var(--vui-button-disabled-border-color, ${borderColor})` },
			...color !== void 0 && { color: `var(--vui-button-disabled-color, ${color})` },
			...opacity !== void 0 && { opacity: `var(--vui-button-disabled-opacity, ${opacity})` }
		};
	}, [computed.disabledProps]);
	const finalProps = useMemo(() => ({
		borderWidth: `var(--vui-button-border-width, ${borderWidth}px)`,
		className: computed.buttonClassName,
		disabled,
		focusRing: FOCUS_RING_SIZE,
		h: `var(--vui-button-h, ${hValue}px)`,
		pl: plValue,
		pr: prValue,
		ref,
		title: title || "",
		type: BUTTON_TYPE,
		variant: finalVariant,
		...computed.buttonStyles,
		...computed.activeProps,
		...disabledPropsWithVars,
		...computed.aliasedProps,
		...rest
	}), [
		borderWidth,
		plValue,
		prValue,
		computed.buttonClassName,
		computed.buttonStyles,
		computed.activeProps,
		disabledPropsWithVars,
		computed.aliasedProps,
		hValue,
		disabled,
		ref,
		title,
		finalVariant,
		rest
	]);
	const mainIcon = renderButtonIcon(icon, "main");
	const leftIcon = renderButtonIcon(iconLeft, "left", isLoading ?? false);
	const rightIcon = renderButtonIcon(iconRight, "right");
	const contentElement = renderContent(children, text, isTruncated ?? false);
	return /* @__PURE__ */ jsx(ButtonProvider, {
		value: contextValue,
		children: /* @__PURE__ */ jsxs(ButtonBase, {
			...finalProps,
			children: [hasState && /* @__PURE__ */ jsx(StateWrapper, {
				onClick: handleStateClick,
				...stateProps,
				children: /* @__PURE__ */ jsx(ButtonIcon, {
					m: "auto",
					...stateIconProps
				})
			}), /* @__PURE__ */ jsxs(Content, { children: [
				mainIcon,
				!icon && /* @__PURE__ */ jsxs(Fragment$1, { children: [
					leftIcon,
					contentElement,
					rightIcon
				] }),
				icon && isDropDown && rightIcon
			] })]
		})
	});
});
Button.Icon = ButtonIcon;
Button.Text = ButtonText;
Button.displayName = "Button";

//#endregion
export { ButtonBase, Button as default };
globalThis.__vuiVersion__ = "4.0.0-beta.1"
//# sourceMappingURL=button.js.map