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,
},
})
}