button.taro.tsx 3.2 KB
Newer Older
O
oasis-cloud 已提交
1 2
import React, { CSSProperties, useCallback } from 'react'
import classNames from 'classnames'
3
import { ButtonProps as MiniProgramButtonProps } from '@tarojs/components'
O
oasis-cloud 已提交
4
import { Loading } from '@nutui/icons-react-taro'
O
oasis-cloud 已提交
5
import { BasicComponent, ComponentDefaults } from '@/utils/typings'
6

7 8
type OmitMiniProgramButtonProps = Omit<
  MiniProgramButtonProps,
O
oasis-cloud 已提交
9
  'size' | 'type' | 'onClick' | 'style'
10
>
O
oasis-cloud 已提交
11 12 13 14 15 16 17 18 19 20 21 22

export type ButtonType =
  | 'default'
  | 'primary'
  | 'info'
  | 'success'
  | 'warning'
  | 'danger'
export type ButtonSize = 'large' | 'normal' | 'small'
export type ButtonShape = 'square' | 'round'
export type ButtonFill = 'solid' | 'outline' | 'none'

O
oasis-cloud 已提交
23 24 25
export interface ButtonProps
  extends BasicComponent,
    OmitMiniProgramButtonProps {
X
xiaoyatong 已提交
26 27 28 29
  color: string
  shape: ButtonShape
  type: ButtonType
  size: ButtonSize
O
oasis-cloud 已提交
30
  fill: ButtonFill
X
xiaoyatong 已提交
31
  block: boolean
O
oasis-cloud 已提交
32 33
  loading: boolean
  disabled: boolean
O
oasis-cloud 已提交
34
  icon: React.ReactNode
X
xiaoyatong 已提交
35 36 37
  onClick: (e: MouseEvent) => void
}

O
oasis-cloud 已提交
38
const prefixCls = 'nut-button'
39

X
xiaoyatong 已提交
40
const defaultProps = {
41
  ...ComponentDefaults,
X
xiaoyatong 已提交
42
  color: '',
O
oasis-cloud 已提交
43 44
  type: 'default',
  size: 'normal',
X
xiaoyatong 已提交
45
  shape: 'round',
O
oasis-cloud 已提交
46
  fill: 'solid',
X
xiaoyatong 已提交
47 48 49
  loading: false,
  disabled: false,
  block: false,
O
oasis-cloud 已提交
50
  icon: null,
X
xiaoyatong 已提交
51 52
  onClick: (e: MouseEvent) => {},
} as ButtonProps
O
oasis-cloud 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
export const Button = React.forwardRef<HTMLButtonElement, Partial<ButtonProps>>(
  (props, ref) => {
    const {
      color,
      shape,
      fill,
      loading,
      disabled,
      type,
      size,
      block,
      icon,
      children,
      onClick,
      className,
      style,
      ...rest
    } = {
      ...defaultProps,
      ...props,
    }
    const getStyle = useCallback(() => {
      const style: CSSProperties = {}
      if (props.color) {
        if (fill && fill === 'outline') {
          style.color = color
          style.background = '#fff'
          if (!color?.includes('gradient')) {
            style.borderColor = color
          }
        } else {
          style.color = '#fff'
          style.background = color
X
xiaoyatong 已提交
86 87
        }
      }
O
oasis-cloud 已提交
88 89
      return style
    }, [color])
X
xiaoyatong 已提交
90

O
oasis-cloud 已提交
91 92 93 94
    const handleClick = (e: any) => {
      if (!loading && !disabled && onClick) {
        onClick(e)
      }
X
xiaoyatong 已提交
95 96
    }

O
oasis-cloud 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    return (
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      // eslint-disable-next-line react/button-has-type
      <button
        {...rest}
        ref={ref}
        className={classNames(
          prefixCls,
          className,
          props.type ? `${prefixCls}--${type}` : null,
          props.fill ? `${prefixCls}--${fill}` : null,
          {
            [`${prefixCls}--${size}`]: size,
            [`${prefixCls}--${shape}`]: shape,
            [`${prefixCls}--block`]: block,
            [`${prefixCls}--disabled`]: disabled,
            [`${prefixCls}--loading`]: loading,
          }
116
        )}
O
oasis-cloud 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
        style={{ ...getStyle(), ...style }}
        onClick={(e) => handleClick(e)}
      >
        <div className="nut-button__warp">
          {loading && <Loading className="nut-icon-loading" />}
          {!loading && icon ? icon : null}
          {children && (
            <div className={icon || loading ? 'nut-button-text' : ''}>
              {children}
            </div>
          )}
        </div>
      </button>
    )
  }
)
X
xiaoyatong 已提交
133 134

Button.displayName = 'NutButton'