import React from 'react' import { Pressable, StyleSheet } from 'react-native' import type { PressableProps } from 'react-native' import { useTheme } from '../../hooks' import { platformFontWeightMedium } from '../../utils' import { Text } from './text' import type { TextProps } from './text' import { getColorKey, useButtonColorOptionMap } from './utils/button_colors' import type { ButtonAppearanceUnion } from './utils/button_colors' // ================================= // ====== Component ================ // ================================= export interface TextButtonProps extends PressableProps { /** * Specifies whether fonts should be scaled down automatically to fit given style constraints. */ adjustsFontSizeToFit?: boolean /** * Specifies whether fonts should scale to respect the device's text size accessibility settings. The default is true. */ allowFontScaling?: boolean /** * Updates the button's colors */ appearance?: ButtonAppearanceUnion /** * Renders text within a `Text` */ children?: TextProps['children'] /** * Specifies the maximum size a font can reach when allowFontScaling is enabled. */ maxFontSizeMultiplier?: number /** * Specifies smallest possible scale a font can reach when adjustsFontSizeToFit is enabled. (values 0.01-1.0). */ minimumFontScale?: number /** * Changes the styles and size of the text. */ variant?: TextProps['variant'] /** * Changes the styles and size of the text. */ textStyle?: TextProps['style'] } export function TextButton({ adjustsFontSizeToFit = false, allowFontScaling = true, appearance = 'interaction', disabled = false, children, maxFontSizeMultiplier, minimumFontScale, variant = 'plain', style, textStyle, ...props }: TextButtonProps) { const styles = useStyles({ appearance, disabled }) const overrideStyles = StyleSheet.flatten(style) // Ensures the pressed styles still get applied return ( ({ ...(pressed ? styles.pressed : null), ...overrideStyles, })} // Android & iOS intentionally get the same pressed style hitSlop={10} {...props} > {children} ) } // ================================= // ====== Styles =================== // ================================= const useStyles = ({ appearance = 'interaction', disabled = false }: Partial) => { const { colors } = useTheme() const colorKey = getColorKey({ disabled, appearance }) const colorOptionMap = useButtonColorOptionMap() return StyleSheet.create({ text: { fontWeight: platformFontWeightMedium, color: colorOptionMap[colorKey], }, disabled: { color: colors.textColorDefaultDisabled, }, pressed: { opacity: 0.5, }, }) }