import React, {MouseEvent, forwardRef, ReactNode, useState, useMemo, CSSProperties, MouseEventHandler} from 'react'; import {Colors, Palette, PaletteType} from '@core0/theme'; import {Icon, IconType} from '@core0/icon'; import {Spinner} from '@core0/spinner'; import {Tooltip} from '@core0/tooltip'; import {useFormContext} from '@core0/contexts'; import cls from 'classnames'; import cn from './abstractButton.module.styl'; export interface AbstractButtonProps { color?: PaletteType; spinnerColor?: string; inverse?: boolean; icon?: IconType; iconSize?: 'small' | 'regular'; iconPlacement?: 'left' | 'right'; label?: string; children?: ReactNode | Element[]; showLoadingOnClick?: boolean; loading?: boolean; tooltip?: string | ReactNode; submit?: boolean; type?: 'submit' | 'reset' | 'button'; disabled?: boolean; className?: string; style?: CSSProperties; onClick?: MouseEventHandler; } export const AbstractButton = forwardRef((props, hostElmRef) => { const { onClick = () => {}, type = 'button', className = '', disabled = false, label, icon, iconSize, iconPlacement = 'left', style = {}, children, showLoadingOnClick = false, loading = false, tooltip, color, spinnerColor, inverse = false, submit = false } = props; const ctx = useFormContext(); const [localLoading, setLocalLoading] = useState(false); const isLoading = loading || localLoading; const spinnerStyle = useMemo(() => { if (inverse) { return {'--spinner-bg': Colors.white} as CSSProperties; } if (color) { return {'--spinner-bg': Palette[color].main} as CSSProperties; } return {}; }, [inverse, color]) async function buttonClickHandler(evt: MouseEvent) { evt.stopPropagation(); if (!disabled) { if (showLoadingOnClick) setLocalLoading(true); if (submit && ctx != null) ctx.submit(); await onClick(evt); if (showLoadingOnClick) setLocalLoading(false); } } return ( ); });