Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
3.9 kB
2
Indexable
Never
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>
  );
};