"use strict";

import { forwardRef, useCallback, useEffect, useRef } from "react";
import { Pressable, StyleSheet } from "react-native";
import ReactNativeHapticFeedback from "react-native-haptic-feedback";
import Animated, { LayoutAnimationConfig, useReducedMotion } from "react-native-reanimated";
import { enterTransitionInnerContent, enterTransitionInnerContentSmall, exitTransitionInnerContent } from "../../../core";
import { useScaleAnimation } from "../../../hooks";
import { AnimatedIcon, AnimatedIconWithColorTransition } from "../../icons";
import { LoadingSpinner } from "../../loadingSpinner";
import { AnimatedIOText } from "../../typography";
import { buttonTextFontSize, buttonTextLineHeight } from "../../typography/ButtonText";
import { useButtonAnimatedStyles, useButtonColorMap } from "./styles";
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
export const IOButton = /*#__PURE__*/forwardRef(({
  variant = "solid",
  color = "primary",
  label,
  fullWidth = false,
  disabled = false,
  loading = false,
  numberOfLines = 1,
  textAlign = "auto",
  icon,
  iconPosition = "start",
  onPress,
  accessibilityLabel,
  accessibilityHint,
  accessibilityRole = "button",
  testID
}, ref) => {
  const mapColorStates = useButtonColorMap(variant);
  const {
    progress,
    onPressIn,
    onPressOut,
    scaleAnimatedStyle
  } = useScaleAnimation();
  const {
    buttonAnimatedStyle,
    labelAnimatedStyle,
    iconColorAnimatedStyle
  } = useButtonAnimatedStyles(variant, color, progress);
  const reducedMotion = useReducedMotion();
  const isLinkButton = variant === "link";

  // ---------------------------------------
  // VISUAL ATTRIBUTES
  // ---------------------------------------
  const btnIconSizeMap = {
    solid: 20,
    outline: 20,
    link: 24
  };
  const btnBorderWidthMap = {
    solid: 0,
    outline: 2,
    link: 0
  };
  const btnPaddingHorizontalMap = {
    default: 24,
    fullWidth: 16,
    link: 0
  };
  const btnLinkHitSlop = {
    top: 14,
    right: 24,
    bottom: 14,
    left: 24
  };
  const btnIconSize = btnIconSizeMap[variant];
  const btnBorderWidth = btnBorderWidthMap[variant];
  const btnBorderRadius = 8;
  const btnSizeDefault = 48;
  const ICON_MARGIN = 8;
  const DISABLED_OPACITY = 0.5;

  // Background color
  const backgroundColor = disabled ? mapColorStates[color].background.disabled : mapColorStates[color].background.default;

  // Label & Icons colors
  const foregroundColor = disabled ? mapColorStates[color]?.foreground?.disabled : mapColorStates[color]?.foreground?.default;

  // ---------------------------------------
  // BUTTON INNER LOGIC
  // ---------------------------------------

  /* Prevent the component from triggering the `isEntering' transition
       on the on the first render. Solution from this discussion:
       https://github.com/software-mansion/react-native-reanimated/discussions/2513
    */
  const isMounted = useRef(false);
  useEffect(() => {
    // eslint-disable-next-line functional/immutable-data
    isMounted.current = true;
  }, []);
  const handleOnPress = useCallback(event => {
    /* Don't call `onPress` if the button is
      in loading state */
    if (loading) {
      return;
    }
    ReactNativeHapticFeedback.trigger("impactLight");
    onPress(event);
  }, [loading, onPress]);

  // ---------------------------------------
  // BUTTON INNER CONTENT
  // ---------------------------------------
  const renderButtonContent = () => /*#__PURE__*/_jsxs(_Fragment, {
    children: [loading && /*#__PURE__*/_jsx(LayoutAnimationConfig, {
      skipExiting: true,
      children: /*#__PURE__*/_jsx(Animated.View, {
        style: styles.buttonInner,
        entering: isMounted.current ? enterTransitionInnerContentSmall : undefined,
        exiting: exitTransitionInnerContent,
        children: /*#__PURE__*/_jsx(LoadingSpinner, {
          color: foregroundColor
        })
      })
    }), !loading && /*#__PURE__*/_jsxs(Animated.View, {
      style: [styles.buttonInner, {
        columnGap: ICON_MARGIN
      }, iconPosition === "end" && {
        flexDirection: "row-reverse"
      }],
      entering: isMounted.current ? enterTransitionInnerContent : undefined,
      children: [icon && (!disabled ? /*#__PURE__*/_jsx(AnimatedIconWithColorTransition, {
        allowFontScaling: true,
        name: icon,
        animatedProps: iconColorAnimatedStyle,
        size: btnIconSize
      }) : /*#__PURE__*/_jsx(AnimatedIcon, {
        allowFontScaling: true,
        name: icon,
        color: mapColorStates[color]?.foreground?.disabled,
        size: btnIconSize
      })), /*#__PURE__*/_jsx(AnimatedIOText, {
        weight: "Semibold",
        size: buttonTextFontSize,
        lineHeight: isLinkButton ? buttonTextLineHeight : undefined,
        accessible: false,
        accessibilityElementsHidden: true,
        importantForAccessibility: "no-hide-descendants",
        numberOfLines: numberOfLines,
        ellipsizeMode: "tail",
        style: [{
          textAlign
        }, disabled ? {
          color: mapColorStates[color]?.foreground?.disabled
        } : {
          color: mapColorStates[color]?.foreground?.default
        }, !disabled && labelAnimatedStyle],
        children: label
      })]
    })]
  });
  return /*#__PURE__*/_jsx(Pressable, {
    ref: ref,
    accessible: true
    // Using || operator because empty string is not an accepted value
    ,
    accessibilityLabel: accessibilityLabel || label,
    accessibilityHint: accessibilityHint,
    accessibilityRole: accessibilityRole,
    accessibilityState: {
      busy: loading,
      disabled: disabled || false
    },
    onPress: handleOnPress,
    onPressIn: onPressIn,
    onPressOut: onPressOut,
    disabled: disabled,
    hitSlop: isLinkButton ? btnLinkHitSlop : undefined,
    style: isLinkButton ? {
      alignSelf: "flex-start"
    } : fullWidth ? {
      flexShrink: 0,
      alignSelf: "stretch"
    } : {
      flexShrink: 1,
      alignSelf: "auto"
    },
    testID: testID,
    children: /*#__PURE__*/_jsx(Animated.View, {
      style: [styles.button,
      /* Prevent Reanimated from overriding background colors
          if button is disabled */
      !disabled && !reducedMotion && scaleAnimatedStyle, !disabled && buttonAnimatedStyle, {
        paddingHorizontal: isLinkButton ? btnPaddingHorizontalMap.link : fullWidth ? btnPaddingHorizontalMap.fullWidth : btnPaddingHorizontalMap.default
      }, {
        height: isLinkButton ? undefined : btnSizeDefault,
        backgroundColor,
        borderWidth: btnBorderWidth,
        borderRadius: btnBorderRadius,
        borderColor: foregroundColor
      }, disabled ? {
        opacity: DISABLED_OPACITY
      } : {}],
      children: renderButtonContent()
    })
  });
});
const styles = StyleSheet.create({
  button: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    textAlignVertical: "center",
    // Prop supported on Android only
    borderCurve: "continuous",
    overflow: "hidden",
    elevation: 0
  },
  buttonInner: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center"
  }
});
//# sourceMappingURL=IOButton.js.map