import React, { forwardRef, useState } from "react"; import clsx from "clsx"; import "./FilledButton.scss"; import { AbortError } from "../errors"; import Spinner from "./Spinner"; import { isPromiseLike } from "../utils"; import { tablerCheckIcon } from "./icons"; export type ButtonVariant = "filled" | "outlined" | "icon"; export type ButtonColor = | "primary" | "danger" | "warning" | "muted" | "success"; export type ButtonSize = "medium" | "large"; export type FilledButtonProps = { label: string; children?: React.ReactNode; onClick?: (event: React.MouseEvent) => void; status?: null | "loading" | "success"; variant?: ButtonVariant; color?: ButtonColor; size?: ButtonSize; className?: string; fullWidth?: boolean; icon?: React.ReactNode; }; export const FilledButton = forwardRef( ( { children, icon, onClick, label, variant = "filled", color = "primary", size = "medium", fullWidth, className, status, }, ref, ) => { const [isLoading, setIsLoading] = useState(false); const _onClick = async (event: React.MouseEvent) => { const ret = onClick?.(event); if (isPromiseLike(ret)) { // delay loading state to prevent flicker in case of quick response const timer = window.setTimeout(() => { setIsLoading(true); }, 50); try { await ret; } catch (error: any) { if (!(error instanceof AbortError)) { throw error; } else { console.warn(error); } } finally { clearTimeout(timer); setIsLoading(false); } } }; const _status = isLoading ? "loading" : status; color = _status === "success" ? "success" : color; return ( ); }, );