import React from "react";
import { ActivityIndicator, Pressable, Text as RNText } from "react-native";
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated";
import { useColorScheme } from "nativewind";
import { cn } from "../utils/cn";
import { withClickTracking } from "../services/telemetry";
const sizeClass = { sm: "h-10 px-4", default: "h-12 px-4", lg: "h-14 px-6" };
const textSizeClass = { sm: "text-sm", default: "text-base", lg: "text-lg" };
// Colours are driven by the active theme's CSS variables (`--primary`,
// `--destructive`, …) so each consuming app's palette flows through without
// the component hardcoding anything.
//
// Each also carries an explicit `dark:` variant matching that same CSS
// variable's `.dark` value one-for-one (see styles/globals.css) — belt and
// suspenders for native, where a bare CSS-var utility with no `dark:` variant
// has been observed stuck on its light value regardless of actual system
// theme, while genuine `dark:`-prefixed utilities react correctly (matches
// the codebase's already-working pattern in components/text.tsx). Values
// omitted below (destructive-foreground) are identical light/dark in
// globals.css, so no variant is needed.
const bgClass = {
    default: "bg-primary dark:bg-white",
    destructive: "bg-destructive dark:bg-red-900",
    outline: "border border-border dark:border-neutral-800 bg-transparent",
    ghost: "bg-transparent",
};
const fgClass = {
    default: "text-primary-foreground dark:text-black",
    destructive: "text-destructive-foreground",
    outline: "text-foreground dark:text-white",
    ghost: "text-foreground dark:text-white",
};
export function Button({ variant = "default", size = "default", className, textClassName, children, isLoading = false, disabled = false, spinnerColor, telemetryId, onPress, onPressIn, onPressOut, ...props }) {
    const { colorScheme } = useColorScheme();
    const isDark = colorScheme === "dark";
    const isDisabled = disabled || isLoading;
    // Wrapped rather than reported from a press listener so a disabled or
    // loading button records nothing: Pressable does not fire onPress in either
    // state, and counting presses the user never actually completed would
    // overstate every funnel it appears in.
    const handlePress = withClickTracking(telemetryId, onPress);
    // Reanimated feedback shared by every button: hover (web) lifts slightly,
    // press dips + dims — two distinct, layered responses.
    const pressed = useSharedValue(0);
    const hovered = useSharedValue(0);
    const pressStyle = useAnimatedStyle(() => ({
        transform: [{ scale: 1 + hovered.value * 0.025 - pressed.value * 0.06 }],
        opacity: 1 - pressed.value * 0.08,
    }));
    const spinner = spinnerColor ??
        (variant === "default"
            ? isDark
                ? "#000000"
                : "#FFFFFF"
            : variant === "destructive"
                ? "#FFFFFF"
                : isDark
                    ? "#FFFFFF"
                    : "#000000");
    return (<Animated.View style={pressStyle} className={isDisabled ? "opacity-50" : undefined}>
      <Pressable className={cn("flex-row items-center justify-center rounded-lg", sizeClass[size], bgClass[variant], className)} disabled={isDisabled} onPress={handlePress} onPressIn={(e) => {
            pressed.value = withTiming(1, { duration: 90 });
            onPressIn?.(e);
        }} onPressOut={(e) => {
            pressed.value = withTiming(0, { duration: 150 });
            onPressOut?.(e);
        }} onHoverIn={() => (hovered.value = withTiming(1, { duration: 120 }))} onHoverOut={() => (hovered.value = withTiming(0, { duration: 160 }))} {...props} focusable={!isDisabled} accessibilityState={{ disabled: isDisabled, busy: isLoading }}>
        {isLoading ? (<ActivityIndicator size="small" color={spinner}/>) : typeof children === "string" ? (<RNText className={cn("font-sans-medium", textSizeClass[size], fgClass[variant], textClassName)}>
            {children}
          </RNText>) : (children)}
      </Pressable>
    </Animated.View>);
}
export function IconButton({ size = "default", children, className, telemetryId, onPress, ...props }) {
    // IconButton accepts ButtonProps, so telemetryId type-checks on it whether or
    // not it is honoured. Wiring it here means a tagged icon button reports,
    // rather than silently being the one control that never appears.
    const handlePress = withClickTracking(telemetryId, onPress);
    const dim = { sm: 40, default: 48, lg: 56 }[size];
    const isDisabled = props.disabled || props.isLoading;
    const pressed = useSharedValue(0);
    const hovered = useSharedValue(0);
    const pressStyle = useAnimatedStyle(() => ({
        transform: [{ scale: 1 + hovered.value * 0.06 - pressed.value * 0.08 }],
    }));
    return (<Animated.View style={pressStyle} className={isDisabled ? "opacity-50" : undefined}>
      <Pressable className={cn("items-center justify-center rounded-lg", className)} style={{ width: dim, height: dim }} disabled={isDisabled} onPress={handlePress} onPressIn={() => (pressed.value = withTiming(1, { duration: 90 }))} onPressOut={() => (pressed.value = withTiming(0, { duration: 150 }))} onHoverIn={() => (hovered.value = withTiming(1, { duration: 120 }))} onHoverOut={() => (hovered.value = withTiming(0, { duration: 160 }))} {...props} focusable={!isDisabled} accessibilityState={{ disabled: isDisabled, busy: props.isLoading }}>
        {children}
      </Pressable>
    </Animated.View>);
}
//# sourceMappingURL=button.jsx.map