import Color from 'color'; import isNil from 'lodash/isNil'; import React, { memo, useMemo } from 'react'; import type { ViewStyle, TextStyle, StyleProp } from 'react-native'; import { Text, TouchableOpacity, StyleSheet } from 'react-native'; import Flex from '../flex'; import { getDefaultValue, renderTextLikeJSX } from '../helpers'; import { useDebounceFn } from '../hooks'; import Loading from '../loading'; import Theme from '../theme'; import type { ButtonProps } from './interface'; import { varCreator, styleCreator } from './style'; /** * Button 按钮 * @description 按钮用于触发一个操作,如提交表单。 */ const Button: React.FC = ({ children, style, text, subtext, textStyle, type = 'primary', danger = false, size = 'l', hairline = false, disabled = false, loading = false, loadingText, square = false, round = false, renderLeftIcon, color, textColor, onPressDebounceWait = 0, ...restProps }) => { const TOKENS = Theme.useThemeTokens(); const CV = Theme.createVar(TOKENS, varCreator); // @ts-ignore const STYLES = Theme.createStyle(CV, styleCreator); // @ts-ignore const { run: runOnPress } = useDebounceFn(restProps.onPress, { wait: onPressDebounceWait, }); color = getDefaultValue( color, danger ? CV.button_danger_color : CV.button_primary_color ); textColor = getDefaultValue(textColor, TOKENS.white); const [_backgroundColor, _borderColor, _textColor, _borderWidth] = useMemo(() => { switch (type) { case 'hazy': { const hazyColor = Color(color) .lightness(CV.button_hazy_lightness) .hex(); return [hazyColor, hazyColor, color, 0]; } case 'outline': { return [ CV.button_ghost_background_color, CV.button_border_color, color, 1, ]; } case 'ghost': { return [CV.button_ghost_background_color, color, color, 1]; } case 'link': return [ CV.button_ghost_background_color, CV.button_ghost_background_color, color, 0, ]; case 'primary': default: return [color, color, textColor, 0]; } }, [ CV.button_border_color, CV.button_ghost_background_color, CV.button_hazy_lightness, color, textColor, type, ]); const buttonStyles: StyleProp = [ STYLES.button, STYLES.button_column, { height: CV[`button_${size}_height`], backgroundColor: _backgroundColor, borderColor: _borderColor, borderWidth: _borderWidth ? hairline ? StyleSheet.hairlineWidth : _borderWidth : _borderWidth, }, // @ts-ignore STYLES[`button_${size}_padding_horizontal`], square ? STYLES.button_square : null, round ? STYLES.button_round : null, disabled ? STYLES.button_disabled : null, loading ? STYLES.button_loading : null, style, ]; const commonTextStyle = StyleSheet.flatten([ STYLES.text, { fontSize: CV[`button_${size}_font_size`], color: _textColor, marginLeft: renderLeftIcon ? CV.button_icon_gap : 0, }, ]); const textStyleSummary = StyleSheet.flatten([ commonTextStyle, textStyle, ]); const iconSize = CV[`button_${size}_loading_size`] || 24; const iconColor = textStyleSummary.color as string; const contextJSX = loading ? ( {loadingText} ) : ( <> {renderLeftIcon ? renderLeftIcon(iconColor, iconSize) : null} {!isNil(text) ? text : children} {renderTextLikeJSX( subtext, [ { color: '#999999', lineHeight: CV.button_subtext_line_height, fontSize: CV.button_subtext_font_size, opacity: CV.button_subtext_opacity, }, ], { numberOfLines: 1, } )} ); return ( {contextJSX} ); }; export default memo(Button);