import { jsx, jsxs, Fragment } from "react/jsx-runtime";
import assert from "assert";
import dedent from "dedent";
import { createContext, forwardRef, useContext } from "react";
import { Box } from "../Box/Box.mjs";
import { AvoidWidowIcon } from "../private/AvoidWidowIcon/AvoidWidowIcon.mjs";
import { buildDataAttributes } from "../Accordion/Accordion.mjs";
import { Overlay, Text } from "../Accordion/AccordionItem.mjs";
import { virtualTouchable } from "../private/touchable/virtualTouchable.mjs";
import { useColorContrast, useBackgroundLightness } from "../Box/BackgroundContext.mjs";
import { negativeMargin } from "../../css/negativeMargin/negativeMargin.mjs";
import { useBraidTheme } from "../../../../side-effects/lib/components/BraidProvider/BraidProvider.mjs";
import { focusOverlay, hoverOverlay, invertedBackgroundsLightMode, invertedBackgroundsDarkMode, forceActive, activeOverlay, padToMinHeight, root, standard, small, bleedVerticallyToCapHeight, loadingDot } from "./Button.css.mjs";
const ActionsContext = createContext(null);
const boxShadowForVariant = {
  default: "borderField",
  disabled: "borderNeutralLight",
  focus: "outlineFocus",
  formAccent: "borderFormAccent",
  critical: "borderCritical"
};
const FieldOverlay = ({ variant, ...restProps }) => /* @__PURE__ */ jsx(
  Overlay,
  {
    component: "span",
    borderRadius: "standard",
    boxShadow: boxShadowForVariant[variant],
    transition: "fast",
    ...restProps
  }
);
const validBleedComponents = ["div", "span"];
const Bleed = ({
  space,
  horizontal,
  vertical,
  top,
  bottom,
  left,
  right,
  children,
  component = "div",
  data,
  ...restProps
}) => /* @__PURE__ */ jsx(
  Box,
  {
    component,
    display: component === "span" ? "block" : void 0,
    className: [
      negativeMargin("top", top || vertical || space),
      negativeMargin("bottom", bottom || vertical || space),
      negativeMargin("left", left || horizontal || space),
      negativeMargin("right", right || horizontal || space)
    ],
    ...buildDataAttributes({ data, validateRestProps: restProps }),
    children: /* @__PURE__ */ jsx(
      Box,
      {
        component,
        display: component === "span" ? "block" : void 0,
        position: "relative",
        children
      }
    )
  }
);
const buttonVariants = [
  "solid",
  "ghost",
  "soft",
  "transparent"
];
const buttonTones = [
  "formAccent",
  "brandAccent",
  "critical",
  "neutral"
];
const variants = {
  solid: {
    formAccent: {
      textTone: void 0,
      background: "formAccent",
      backgroundHover: "formAccentHover",
      backgroundActive: "formAccentActive",
      boxShadow: void 0
    },
    brandAccent: {
      textTone: void 0,
      background: "brandAccent",
      backgroundHover: "brandAccentHover",
      backgroundActive: "brandAccentActive",
      boxShadow: void 0
    },
    critical: {
      textTone: void 0,
      background: "critical",
      backgroundHover: "criticalHover",
      backgroundActive: "criticalActive",
      boxShadow: void 0
    },
    neutral: {
      textTone: void 0,
      background: { light: "neutral", dark: "neutralSoft" },
      backgroundHover: { light: "neutralSoftHover", dark: "neutralHover" },
      backgroundActive: { light: "neutralSoftActive", dark: "neutralActive" },
      boxShadow: void 0
    }
  },
  soft: {
    formAccent: {
      textTone: "formAccent",
      background: { light: "formAccentSoft", dark: "customDark" },
      backgroundHover: "formAccentSoftHover",
      backgroundActive: "formAccentSoftActive",
      boxShadow: void 0
    },
    brandAccent: {
      textTone: "brandAccent",
      background: { light: "brandAccentSoft", dark: "customDark" },
      backgroundHover: "brandAccentSoftHover",
      backgroundActive: "brandAccentSoftActive",
      boxShadow: void 0
    },
    critical: {
      textTone: "critical",
      background: { light: "criticalSoft", dark: "customDark" },
      backgroundHover: "criticalSoftHover",
      backgroundActive: "criticalSoftActive",
      boxShadow: void 0
    },
    neutral: {
      textTone: "neutral",
      background: { light: "neutralSoft", dark: "customDark" },
      backgroundHover: "neutralSoftHover",
      backgroundActive: "neutralSoftActive",
      boxShadow: void 0
    }
  },
  transparent: {
    formAccent: {
      textTone: "formAccent",
      background: void 0,
      backgroundHover: "formAccentSoftHover",
      backgroundActive: "formAccentSoftActive",
      boxShadow: void 0
    },
    brandAccent: {
      textTone: "brandAccent",
      background: void 0,
      backgroundHover: "brandAccentSoftHover",
      backgroundActive: "brandAccentSoftActive",
      boxShadow: void 0
    },
    critical: {
      textTone: "critical",
      background: void 0,
      backgroundHover: "criticalSoftHover",
      backgroundActive: "criticalSoftActive",
      boxShadow: void 0
    },
    neutral: {
      textTone: "neutral",
      background: void 0,
      backgroundHover: "neutralSoftHover",
      backgroundActive: "neutralSoftActive",
      boxShadow: void 0
    }
  },
  ghost: {
    formAccent: {
      textTone: "formAccent",
      background: void 0,
      backgroundHover: "formAccentSoftHover",
      backgroundActive: "formAccentSoftActive",
      boxShadow: "borderFormAccent"
    },
    brandAccent: {
      textTone: "brandAccent",
      background: void 0,
      backgroundHover: "brandAccentSoftHover",
      backgroundActive: "brandAccentSoftActive",
      boxShadow: "borderBrandAccent"
    },
    critical: {
      textTone: "critical",
      background: void 0,
      backgroundHover: "criticalSoftHover",
      backgroundActive: "criticalSoftActive",
      boxShadow: "borderCritical"
    },
    neutral: {
      textTone: "neutral",
      background: void 0,
      backgroundHover: "neutralSoftHover",
      backgroundActive: "neutralSoftActive",
      boxShadow: "borderNeutral"
    }
  }
};
const ButtonLoader = () => /* @__PURE__ */ jsxs(Box, { "aria-hidden": true, component: "span", display: "inlineBlock", children: [
  /* @__PURE__ */ jsx(Box, { component: "span", className: loadingDot, children: "." }),
  /* @__PURE__ */ jsx(Box, { component: "span", className: loadingDot, children: "." }),
  /* @__PURE__ */ jsx(Box, { component: "span", className: loadingDot, children: "." })
] });
const transparentPaddingX = "small";
const buttonRadius = "standard";
const resolveToneAndVariant = ({
  variant: variantProp,
  tone: toneProp,
  legacy
}) => {
  if (legacy) {
    return {
      variant: variantProp ?? "solid",
      tone: toneProp ?? "formAccent"
    };
  }
  const fallbackVariant = toneProp ? "solid" : "ghost";
  return {
    variant: variantProp ?? fallbackVariant,
    tone: toneProp ?? "neutral"
  };
};
const ButtonOverlays = ({
  variant: variantProp,
  tone: toneProp,
  keyboardFocusable = true,
  forceActive: forceActive$1 = false,
  radius = buttonRadius
}) => {
  const { variant, tone } = resolveToneAndVariant({
    variant: variantProp,
    tone: toneProp,
    legacy: useBraidTheme().legacy
  });
  const stylesForVariant = variants[variant][tone];
  const colorContrast = useColorContrast();
  const lightness = useBackgroundLightness();
  return /* @__PURE__ */ jsxs(Fragment, { children: [
    keyboardFocusable ? /* @__PURE__ */ jsx(
      FieldOverlay,
      {
        borderRadius: radius,
        variant: "focus",
        onlyVisibleForKeyboardNavigation: true,
        className: focusOverlay
      }
    ) : null,
    /* @__PURE__ */ jsx(
      FieldOverlay,
      {
        borderRadius: radius,
        background: stylesForVariant.backgroundHover && typeof stylesForVariant.backgroundHover !== "string" ? colorContrast(stylesForVariant.backgroundHover) : stylesForVariant.backgroundHover,
        className: [
          hoverOverlay,
          variant !== "solid" && lightness.lightMode === "dark" ? invertedBackgroundsLightMode.hover : null,
          variant !== "solid" && lightness.darkMode === "dark" ? invertedBackgroundsDarkMode.hover : null
        ]
      }
    ),
    /* @__PURE__ */ jsx(
      FieldOverlay,
      {
        borderRadius: radius,
        background: stylesForVariant.backgroundActive && typeof stylesForVariant.backgroundActive !== "string" ? colorContrast(stylesForVariant.backgroundActive) : stylesForVariant.backgroundActive,
        className: [
          forceActive$1 ? forceActive : void 0,
          activeOverlay,
          variant !== "solid" && lightness.lightMode === "dark" ? invertedBackgroundsLightMode.active : null,
          variant !== "solid" && lightness.darkMode === "dark" ? invertedBackgroundsDarkMode.active : null
        ]
      }
    ),
    stylesForVariant.boxShadow ? /* @__PURE__ */ jsx(
      Box,
      {
        component: "span",
        boxShadow: stylesForVariant.boxShadow,
        borderRadius: radius,
        position: "absolute",
        inset: 0,
        pointerEvents: "none"
      }
    ) : null
  ] });
};
const ButtonText = ({
  children,
  loading,
  size: sizeProp,
  icon,
  iconPosition = "leading",
  variant: variantProp,
  tone: toneProp,
  bleed
}) => {
  const { variant, tone } = resolveToneAndVariant({
    variant: variantProp,
    tone: toneProp,
    legacy: useBraidTheme().legacy
  });
  const lightness = useBackgroundLightness();
  const actionsContext = useContext(ActionsContext);
  const isLegacyTheme = useBraidTheme().legacy;
  const size = sizeProp ?? (actionsContext == null ? void 0 : actionsContext.size) ?? "standard";
  const stylesForVariant = variants[variant][tone];
  const shouldReducePaddingX = size === "small" || variant === "transparent";
  const labelPaddingXForTheme = isLegacyTheme ? "medium" : "gutter";
  const labelPaddingX = shouldReducePaddingX ? transparentPaddingX : labelPaddingXForTheme;
  assert(
    !icon || icon.props.size === void 0 && icon.props.tone === void 0,
    "Icons cannot set the 'size' or 'tone' prop when passed to a Button component"
  );
  return /* @__PURE__ */ jsx(
    Box,
    {
      component: "span",
      position: "relative",
      display: "flex",
      justifyContent: "center",
      flexWrap: "wrap",
      overflow: "hidden",
      pointerEvents: "none",
      paddingX: labelPaddingX,
      className: padToMinHeight,
      background: tone === "neutral" && variant !== "solid" ? {
        lightMode: lightness.lightMode === "light" ? "customLight" : "customDark",
        darkMode: lightness.darkMode === "light" ? "customLight" : "customDark"
      } : void 0,
      children: /* @__PURE__ */ jsxs(
        Text,
        {
          tone: stylesForVariant.textTone,
          weight: "medium",
          align: "center",
          size,
          children: [
            icon && iconPosition === "leading" ? /* @__PURE__ */ jsx(
              AvoidWidowIcon,
              {
                iconPosition,
                space: "xsmall",
                className: shouldReducePaddingX || bleed ? null : negativeMargin("left", "xxsmall"),
                children: icon
              }
            ) : null,
            children,
            loading ? /* @__PURE__ */ jsx(ButtonLoader, {}) : null,
            !loading && icon && iconPosition === "trailing" ? /* @__PURE__ */ jsx(
              AvoidWidowIcon,
              {
                iconPosition,
                space: "xsmall",
                className: shouldReducePaddingX || bleed ? null : negativeMargin("right", "xxsmall"),
                children: icon
              }
            ) : null
          ]
        }
      )
    }
  );
};
const useButtonStyles = ({
  variant: variantProp,
  size: sizeProp,
  tone: toneProp,
  loading,
  radius = buttonRadius,
  bleed
}) => {
  const { variant, tone } = resolveToneAndVariant({
    variant: variantProp,
    tone: toneProp,
    legacy: useBraidTheme().legacy
  });
  const actionsContext = useContext(ActionsContext);
  const size = sizeProp ?? (actionsContext == null ? void 0 : actionsContext.size) ?? "standard";
  const stylesForVariant = variants[variant][tone];
  const colorConstrast = useColorContrast();
  const lightness = useBackgroundLightness();
  return {
    borderRadius: radius,
    width: "full",
    position: "relative",
    display: "block",
    transform: { active: "touchable" },
    transition: "touchable",
    outline: "none",
    textAlign: "center",
    userSelect: "none",
    cursor: !loading ? "pointer" : void 0,
    background: stylesForVariant.background && typeof stylesForVariant.background !== "string" ? colorConstrast(stylesForVariant.background) : stylesForVariant.background,
    className: [
      variant === "soft" && lightness.lightMode === "dark" ? invertedBackgroundsLightMode.soft : null,
      variant === "soft" && lightness.darkMode === "dark" ? invertedBackgroundsDarkMode.soft : null,
      root,
      size === "small" ? virtualTouchable({ xAxis: false }) : null,
      size === "standard" ? standard : small,
      bleed ? bleedVerticallyToCapHeight : null
    ]
  };
};
const ButtonContainer = ({
  children,
  bleed,
  variant = "solid"
}) => bleed && variant === "transparent" ? /* @__PURE__ */ jsx(Bleed, { horizontal: transparentPaddingX, children }) : /* @__PURE__ */ jsx(Fragment, { children });
const Button = forwardRef(
  ({
    onClick,
    children,
    size,
    tone,
    icon,
    iconPosition,
    bleedY,
    bleed,
    variant,
    loading,
    type = "button",
    id,
    tabIndex,
    onKeyUp,
    onKeyDown,
    "aria-haspopup": ariaHasPopup,
    "aria-controls": ariaControls,
    "aria-expanded": ariaExpanded,
    "aria-describedby": ariaDescribedBy,
    "aria-label": ariaLabel,
    data,
    ...restProps
  }, ref) => {
    if (process.env.NODE_ENV !== "production") {
      if (typeof bleedY !== "undefined") {
        console.warn(
          dedent`
            The "bleedY" prop has been deprecated and will be removed in a future version. Use "bleed" instead.
               <Button
              %c-   bleedY
              %c+   bleed
               %c/>
          `,
          "color: red",
          "color: green",
          "color: inherit"
        );
      }
    }
    return /* @__PURE__ */ jsx(ButtonContainer, { bleed, variant, children: /* @__PURE__ */ jsxs(
      Box,
      {
        component: "button",
        ref,
        id,
        type,
        tabIndex,
        onKeyUp,
        onKeyDown,
        "aria-haspopup": ariaHasPopup,
        "aria-controls": ariaControls,
        "aria-expanded": ariaExpanded,
        "aria-describedby": ariaDescribedBy,
        "aria-label": ariaLabel,
        onClick,
        disabled: loading,
        ...buildDataAttributes({ data, validateRestProps: restProps }),
        ...useButtonStyles({
          variant,
          tone,
          size,
          bleed: bleed || bleedY,
          loading
        }),
        children: [
          /* @__PURE__ */ jsx(ButtonOverlays, { variant, tone }),
          /* @__PURE__ */ jsx(
            ButtonText,
            {
              variant,
              tone,
              size,
              loading,
              icon,
              iconPosition,
              bleed,
              children
            }
          )
        ]
      }
    ) });
  }
);
Button.displayName = "Button";
export {
  ActionsContext,
  Bleed,
  Button,
  ButtonContainer,
  ButtonOverlays,
  ButtonText,
  FieldOverlay,
  buttonTones,
  buttonVariants,
  useButtonStyles,
  validBleedComponents
};
