import React from 'react'; import {Button, Popover} from '@gravity-ui/uikit'; import type {ButtonProps, PopoverProps} from '@gravity-ui/uikit'; import {CriticalActionDialog} from '../CriticalActionDialog/CriticalActionDialog'; import {isErrorWithRetry} from '../CriticalActionDialog/utils'; interface ButtonWithConfirmDialogProps { children: React.ReactNode; onConfirmAction: (isRetry?: boolean) => Promise; onConfirmActionSuccess?: | ((isDialogOpen: boolean) => Promise) | ((isDialogOpen: boolean) => void); onDialogOpen?: () => VoidFunction; dialogHeader: string; dialogText?: string; dialogWarning?: string; retryButtonText?: string; applyButtonText?: string; buttonDisabled?: ButtonProps['disabled']; buttonView?: ButtonProps['view']; applyButtonView?: ButtonProps['view']; buttonWidth?: ButtonProps['width']; buttonClassName?: ButtonProps['className']; withPopover?: boolean; popoverContent?: PopoverProps['content']; popoverPlacement?: PopoverProps['placement']; popoverDisabled?: PopoverProps['disabled']; } export function ButtonWithConfirmDialog({ children, onConfirmAction, onConfirmActionSuccess, onDialogOpen, dialogHeader, dialogText, dialogWarning, applyButtonText, retryButtonText, buttonDisabled = false, buttonView = 'action', buttonWidth, buttonClassName, withPopover = false, popoverContent, popoverPlacement = 'right', popoverDisabled = true, applyButtonView, }: ButtonWithConfirmDialogProps) { const [isConfirmDialogVisible, setIsConfirmDialogVisible] = React.useState(false); const [buttonLoading, setButtonLoading] = React.useState(false); const [withRetry, setWithRetry] = React.useState(false); const dialogInteraction = React.useRef<{open: boolean; release?: VoidFunction}>(); const releaseDialog = React.useCallback(() => { const interaction = dialogInteraction.current; dialogInteraction.current = undefined; interaction?.release?.(); }, []); React.useEffect(() => releaseDialog, [releaseDialog]); const handleConfirmAction = async (isRetry?: boolean) => { setButtonLoading(true); await onConfirmAction(isRetry); }; const handleConfirmActionSuccess = async () => { setWithRetry(false); try { await onConfirmActionSuccess?.(dialogInteraction.current?.open ?? false); } finally { setButtonLoading(false); } }; const handleConfirmActionError = (error: unknown) => { setWithRetry(isErrorWithRetry(error)); setButtonLoading(false); }; const renderButton = () => { return ( ); }; // keep : if button is disabled, popover won't open without this wrapper const renderContent = () => { if (withPopover) { return ( {renderButton()} ); } return renderButton(); }; return ( { if (dialogInteraction.current) { dialogInteraction.current.open = false; } setIsConfirmDialogVisible(false); }} onTransitionOutComplete={releaseDialog} /> {renderContent()} ); }