import { MouseEvent as ReactMouseEvent, RefObject } from 'react'; import React, { FC, useRef, useCallback, useState, } from '../../lib/teact/teact'; import buildClassName from '../../util/buildClassName'; import Spinner from './Spinner'; import RippleEffect from './RippleEffect'; import './Button.scss'; export type OwnProps = { ref?: RefObject; type?: 'button' | 'submit' | 'reset'; children: any; size?: 'default' | 'smaller' | 'tiny'; color?: 'primary' | 'secondary' | 'gray' | 'danger' | 'translucent' | 'translucent-white' | 'dark'; className?: string; round?: boolean; pill?: boolean; fluid?: boolean; isText?: boolean; isLoading?: boolean; ariaLabel?: string; href?: string; download?: string; disabled?: boolean; ripple?: boolean; faded?: boolean; tabIndex?: number; isRtl?: boolean; onClick?: (e: ReactMouseEvent) => void; onContextMenu?: (e: ReactMouseEvent) => void; onMouseDown?: (e: ReactMouseEvent) => void; onMouseEnter?: NoneToVoidFunction; onMouseLeave?: NoneToVoidFunction; onFocus?: NoneToVoidFunction; }; // Longest animation duration; const CLICKED_TIMEOUT = 400; const Button: FC = ({ ref, type = 'button', onClick, onContextMenu, onMouseDown, onMouseEnter, onMouseLeave, onFocus, children, size = 'default', color = 'primary', className, round, pill, fluid, isText, isLoading, ariaLabel, href, download, disabled, ripple, faded, tabIndex, isRtl, }) => { // eslint-disable-next-line no-null/no-null let elementRef = useRef(null); if (ref) { elementRef = ref; } const [isClicked, setIsClicked] = useState(false); const fullClassName = buildClassName( 'Button', className, size, color, round && 'round', pill && 'pill', fluid && 'fluid', disabled && 'disabled', isText && 'text', isLoading && 'loading', ripple && 'has-ripple', faded && 'faded', isClicked && 'clicked', ); const handleClick = useCallback((e: ReactMouseEvent) => { if (!disabled && onClick) { onClick(e); } setIsClicked(true); setTimeout(() => { setIsClicked(false); }, CLICKED_TIMEOUT); }, [disabled, onClick]); const handleMouseDown = useCallback((e: ReactMouseEvent) => { e.preventDefault(); if (!disabled && onMouseDown) { onMouseDown(e); } }, [onMouseDown, disabled]); if (href) { return ( } className={fullClassName} href={href} title={ariaLabel} download={download} tabIndex={tabIndex} dir={isRtl ? 'rtl' : undefined} > {children} {!disabled && ripple && ( )} ); } return ( // eslint-disable-next-line react/button-has-type ); }; export default Button;