import React from 'react'; import { ActivityIndicator, View as ReactNativeView, type ViewStyle } from 'react-native'; import { resolveButtonColors, resolveControlSize, resolveIconSize, } from '../../../../internal/resolvers'; import type { ButtonProps } from '../../../../types/button'; import type { InteractionState } from '../../../../types/pressable'; import type { SurfaceTheme } from '../../../../types/theme'; import { Icon } from '../../../icon/public'; import { View } from '../../../layout/public'; import { Pressable } from '../../../pressable/public'; import { useTheme } from '../../../theme/runtime'; import { Text } from '../../../typography/public'; /*** Renders the primary Surface action control with semantic visual states. */ export function Button({ children, variant = 'solid', color = 'primary', size = 'm', disabled = false, loading = false, leadingIcon, trailingIcon, fullWidth = false, onPress, testID, ...props }: ButtonProps) { const { theme } = useTheme(); const controlSize = resolveControlSize(theme, size); return ( {(state) => ( {children} )} ); } /*** Renders Button content after interaction colors have been resolved. */ function ButtonContent({ children, color, controlSize, fullWidth, leadingIcon, loading, size, state, theme, trailingIcon, variant, }: ButtonContentProps) { const colors = resolveButtonColors(theme, { variant, color, state }); const iconSize = resolveIconSize(theme, size); return ( {loading ? ( ) : ( <> {leadingIcon ? ( ) : null} {children} {trailingIcon ? ( ) : null} )} ); } /*** Resolves the outer Pressable layout style. */ function resolvePressableStyle(fullWidth: boolean): ViewStyle { return { alignSelf: fullWidth ? 'stretch' : 'flex-start' }; } /*** Resolves the themed Button content container style. */ function resolveButtonContentStyle( controlSize: ReturnType, colors: ReturnType, fullWidth: boolean, variant: NonNullable, ): ViewStyle { return { alignItems: 'center', backgroundColor: colors.backgroundColor, borderColor: colors.borderColor, borderWidth: variant === 'solid' ? 0 : 1, flexDirection: 'row', justifyContent: 'center', minHeight: controlSize.minHeight, opacity: colors.opacity, width: fullWidth ? '100%' : undefined, }; } /*** Resolves spacing around a leading or trailing Button icon. */ function resolveAccessoryStyle(spacing: number, position: 'leading' | 'trailing'): ViewStyle { return position === 'leading' ? { marginRight: spacing } : { marginLeft: spacing }; } interface ButtonContentProps { children: ButtonProps['children']; color: NonNullable; controlSize: ReturnType; fullWidth: boolean; leadingIcon: ButtonProps['leadingIcon']; loading: boolean; size: NonNullable; state: InteractionState; theme: SurfaceTheme; trailingIcon: ButtonProps['trailingIcon']; variant: NonNullable; }