import PropTypes from 'prop-types'; import { clsm } from '../../utils'; import { forwardRef } from 'react'; import { Link, useLocation } from 'react-router-dom'; import { motion } from 'framer-motion'; import Spinner from '../Spinner'; import { BUTTON_BASE_CLASSES as baseClasses, BUTTON_LINK_CLASSES as linkClasses, BUTTON_VARIANT_CLASSES as variantClasses, BUTTON_HOVER_CLASSES as hoverClasses } from './ButtonTheme'; const Button = forwardRef( ( { 'data-testid': dataTestId, animationProps, ariaControls, ariaDisabled, ariaLabel, ariaSelected, children, className, customStyles, disableHover, id, isDisabled, isLoading, name, onClick, onFocus, onKeyDown, onMouseDown, role, state, saveLocationFromState, tabIndex, to, type, variant }, ref ) => { const location = useLocation(); const commonProps = { ...(!!ariaControls ? { 'aria-controls': ariaControls } : {}), ...(!!ariaLabel ? { 'aria-label': ariaLabel } : {}), ...(!!role ? { role: role } : {}), ...(ariaSelected !== null ? { 'aria-selected': ariaSelected } : {}), ...(tabIndex !== null ? { tabIndex } : {}), 'aria-disabled': ariaDisabled, 'data-testid': dataTestId, id, name, ref, onClick, style: customStyles }; const classes = clsm([ 'button', variant, ...baseClasses, ...variantClasses[variant], ...(disableHover ? [] : hoverClasses[variant]), type === 'nav' && linkClasses, className ]); if (type === 'nav') { if (!to) { throw new Error("Button with type 'nav' requires a valid 'to' prop."); } return ( {children} ); } return ( {isLoading ? : children} ); } ); Button.defaultProps = { 'data-testid': undefined, animationProps: undefined, ariaControls: '', ariaDisabled: false, ariaLabel: '', ariaSelected: null, className: '', customStyles: {}, disableHover: false, id: undefined, isDisabled: false, isLoading: false, state: {}, name: '', onBlur: undefined, onClick: undefined, onFocus: undefined, onKeyDown: undefined, onMouseDown: undefined, role: '', saveLocationFromState: false, tabIndex: null, to: '', type: 'button', variant: 'primary', width: '' }; Button.propTypes = { 'data-testid': PropTypes.string, animationProps: PropTypes.object, ariaControls: PropTypes.string, ariaDisabled: PropTypes.bool, ariaLabel: PropTypes.string, ariaSelected: PropTypes.bool, children: PropTypes.node.isRequired, className: PropTypes.string, customStyles: PropTypes.object, state: PropTypes.object, disableHover: PropTypes.bool, id: PropTypes.string, isDisabled: PropTypes.bool, isLoading: PropTypes.bool, name: PropTypes.string, onClick: PropTypes.func, onFocus: PropTypes.func, onKeyDown: PropTypes.func, onMouseDown: PropTypes.func, role: PropTypes.string, saveLocationFromState: PropTypes.bool, tabIndex: PropTypes.number, to: PropTypes.string, type: PropTypes.oneOf(['button', 'submit', 'reset', 'nav']), variant: PropTypes.oneOf([ 'primary', 'secondary', 'tertiary', 'destructive', 'icon', 'primaryText', 'secondaryText', 'tertiaryText' ]) }; export default Button;