import React, { useRef, useState, MouseEvent, useMemo, useImperativeHandle } from 'react' import useScale, { withScale } from '../use-scale' import useTheme from '../use-theme' import ButtonDrip from './button.drip' import ButtonLoading from './button-loading' import { ButtonTypes } from '../utils/prop-types' import { filterPropsWithGroup, getButtonChildrenWithIcon } from './utils' import { useButtonGroupContext } from '../button-group/button-group-context' import { getButtonColors, getButtonCursor, getButtonDripColor, getButtonHoverColors } from './styles' import useClasses from '../use-classes' interface Props { href: React.AnchorHTMLAttributes['href'] type?: ButtonTypes ghost?: boolean loading?: boolean shadow?: boolean auto?: boolean effect?: boolean disabled?: boolean icon?: React.ReactNode iconRight?: React.ReactNode onClick?: React.MouseEventHandler className?: string } const defaultProps = { type: 'default' as ButtonTypes, ghost: false, loading: false, shadow: false, auto: false, effect: true, disabled: false, className: '' } type NativeAttrs = Omit, keyof Props> export type ButtonProps = Props & NativeAttrs const ButtonComponent = React.forwardRef>( (btnProps: ButtonProps, ref: React.Ref) => { const theme = useTheme() const { SCALES } = useScale() const buttonRef = useRef(null) useImperativeHandle(ref, () => buttonRef.current) const [dripShow, setDripShow] = useState(false) const [dripX, setDripX] = useState(0) const [dripY, setDripY] = useState(0) const groupConfig = useButtonGroupContext() const filteredProps = filterPropsWithGroup(btnProps as any, groupConfig) const { children, disabled, type, loading, shadow, ghost, effect, onClick, auto, icon, iconRight, className, ...props } = filteredProps const { bg, border, color } = useMemo( () => getButtonColors(theme.palette, filteredProps), [theme.palette, filteredProps] ) const hover = useMemo( () => getButtonHoverColors(theme.palette, filteredProps), [theme.palette, filteredProps] ) const { cursor, events } = useMemo( () => getButtonCursor(!!disabled, loading), [disabled, loading] ) const dripColor = useMemo( () => getButtonDripColor(theme.palette, filteredProps), [theme.palette, filteredProps] ) /* istanbul ignore next */ const dripCompletedHandle = () => { setDripShow(false) setDripX(0) setDripY(0) } const clickHandler = (event: MouseEvent) => { if (disabled || loading) { event.preventDefault() return } const showDrip = !shadow && !ghost && effect /* istanbul ignore next */ if (showDrip && buttonRef.current) { const rect = buttonRef.current.getBoundingClientRect() setDripShow(true) setDripX(event.clientX - rect.left) setDripY(event.clientY - rect.top) } onClick && (onClick as React.MouseEventHandler)(event) } const childrenWithIcon = useMemo( () => getButtonChildrenWithIcon(!!auto, children, { icon, iconRight }), [auto, children, icon, iconRight] ) const [paddingLeft, paddingRight] = [ auto ? SCALES.pl(1.15) : SCALES.pl(1.375), auto ? SCALES.pr(1.15) : SCALES.pr(1.375) ] return ( {loading && } {childrenWithIcon} {dripShow && ( )} ) } ) ButtonComponent.defaultProps = defaultProps ButtonComponent.displayName = 'HuiButtonLink' const Button = withScale(ButtonComponent) export default Button