import { useTranslation } from 'react-i18next';
import { TouchableOpacity, StyleSheet } from 'react-native';
import {
useRestyle,
spacing,
border,
backgroundColor,
SpacingProps,
BorderProps,
BackgroundColorProps,
createVariant,
VariantProps,
typography,
color,
layout,
LayoutProps,
TypographyProps,
spacingShorthand,
SpacingShorthandProps,
backgroundColorShorthand,
BackgroundColorShorthandProps,
} from '@shopify/restyle';
import { Theme, theme as ThemeValue } from '@styles/theme';
import { Button as ButtonElement, ButtonProps as RNEButtonProps } from 'react-native-elements';
import { TextProps } from '@components-new/text';
import { flatten, mergeAll } from '@utils/lodash';
import { useTheme } from '@hooks/useTheme';
import { ReactNode } from 'react';
import { BoxProps } from '@components-new/atom';
const buttonRestyleFunctions = [
layout,
spacing,
spacingShorthand,
border,
backgroundColor,
backgroundColorShorthand,
createVariant({ themeKey: 'buttonVariants' }),
];
const textRestyleFunctions = [
spacing,
typography,
color,
createVariant({ themeKey: 'textVariants' }),
];
export type ButtonProps = RNEButtonProps &
SpacingProps<Theme> &
SpacingShorthandProps<Theme> &
BorderProps<Theme> &
LayoutProps<Theme> &
BackgroundColorProps<Theme> &
BackgroundColorShorthandProps<Theme> & {
onPress?: () => void;
} & VariantProps<Theme, 'buttonVariants'> & {
labelTx?: string;
label?: string;
labelTxOptions?: Record<string, any>;
labelVariant?: keyof typeof ThemeValue.textVariants;
labelColor?: keyof typeof ThemeValue.colors;
labelProps?: TextProps & TypographyProps<Theme>;
children?: ReactNode;
variant?: 'solid' | 'clear' | 'outline';
_container?: BoxProps;
};
const BUTTON_LABEL_VARIANT_MAP = {
solid: 'buttonSolid',
clear: 'buttonClear',
outline: 'buttonOutline',
};
export const Button = ({
labelTx,
label,
labelTxOptions,
labelVariant,
labelColor,
labelProps,
titleStyle,
onPress,
buttonStyle,
containerStyle,
children,
disabled,
variant = 'solid',
_container,
...rest
}: ButtonProps) => {
const { t } = useTranslation();
const theme = useTheme();
const { style: btnContainerStyle } = useRestyle(buttonRestyleFunctions, { ..._container }) as any;
const { style: buttonRestyle } = useRestyle(buttonRestyleFunctions, { variant, ...rest }) as any;
const { style: titleRestyle } = useRestyle(textRestyleFunctions, {
variant:
labelVariant || BUTTON_LABEL_VARIANT_MAP[variant as keyof typeof BUTTON_LABEL_VARIANT_MAP],
color: labelColor,
...labelProps,
}) as any;
const i18nText = labelTx && t(labelTx as any, labelTxOptions);
const buttonTitle = i18nText || label;
if (children) {
return (
<TouchableOpacity
{...rest}
style={mergeAll(flatten([buttonRestyle, containerStyle]))}
onPress={onPress}
>
{children}
</TouchableOpacity>
);
}
let disabledStyle = {};
if (disabled) {
disabledStyle = { backgroundColor: buttonRestyle[0].backgroundColor, opacity: 0.6 };
}
const loadingProps = {
color: 'white',
};
if (variant === 'clear') {
loadingProps.color = theme.colors.primary;
}
return (
<ButtonElement
activeOpacity={0.8}
loadingProps={loadingProps}
TouchableComponent={TouchableOpacity}
containerStyle={StyleSheet.flatten([{ borderRadius: 0 }, btnContainerStyle, containerStyle])}
buttonStyle={mergeAll(flatten([buttonRestyle, buttonStyle]))}
title={buttonTitle}
disabled={disabled}
disabledStyle={disabledStyle}
disabledTitleStyle={mergeAll(flatten([titleRestyle, titleStyle]))}
titleStyle={mergeAll(flatten([titleRestyle, titleStyle]))}
onPress={onPress}
{...rest}
>
{children}
</ButtonElement>
);
};