import type React from 'react'; import { useMemo, useRef } from 'react'; import { Dialog as BaseDialog } from '@base-ui/react/dialog'; import { i18next } from '@tencentcloud/uikit-base-component-react'; import cs from 'classnames'; import { X as IconX } from 'lucide-react'; import { Button } from '../Button'; import classes from './Dialog.module.scss'; import type { DialogProps } from './types'; type OpenChangeDetails = { reason?: 'outside-press' | 'escape-key' | 'close-press' | 'focus-out' | 'imperative-action' | 'none' | 'trigger-press'; cancel?: () => void; }; function Dialog(props: DialogProps) { const { open = false, onOpenChange, onConfirm, onCancel, onClose, title, description, content, footer, children, confirmText, cancelText, confirmLoading = false, confirmDisabled = false, cancelDisabled = false, showClose = true, maskClosable = true, escClosable = true, appendTo, width = 420, className, style, viewportClassName, viewportStyle, initialFocus, finalFocus = false, } = props; const { t } = i18next; const closingByActionRef = useRef<'cancel' | 'close' | null>(null); const mergedConfirmText = confirmText ?? t('Dialog.confirm'); const mergedCancelText = cancelText ?? t('Dialog.cancel'); const closeAriaLabel = t('Dialog.close'); const bodyContent = children ?? content ?? description; const shouldWrapDescription = children === undefined && ( typeof bodyContent === 'string' || typeof bodyContent === 'number' ); const shouldRenderHeader = !!title || showClose; const shouldRenderFooter = (footer !== undefined || !!mergedCancelText || !!mergedConfirmText) && footer !== null; const popupStyle = useMemo(() => ({ width: typeof width === 'number' ? `${width}px` : width, ...style, }), [style, width]); const requestClose = (type: 'cancel' | 'close') => { closingByActionRef.current = type; if (type === 'cancel') { onCancel?.(); } else { onClose?.(); } onOpenChange?.(false); }; const renderDefaultFooter = () => ( <> {mergedCancelText ? ( ) : null} {mergedConfirmText ? ( ) : null} ); const footerContent = footer ?? renderDefaultFooter(); const handleOpenChange = (nextOpen: boolean, details?: OpenChangeDetails) => { if (!nextOpen) { if (details?.reason === 'outside-press' && !maskClosable) { details.cancel?.(); return; } if (details?.reason === 'escape-key' && !escClosable) { details.cancel?.(); return; } if (closingByActionRef.current) { closingByActionRef.current = null; onOpenChange?.(false); return; } onClose?.(); } onOpenChange?.(nextOpen); }; return ( {shouldRenderHeader && (
{title && ( {title} )}
{showClose && ( )}
)} {bodyContent && (
{shouldWrapDescription ? ( {bodyContent} ) : bodyContent}
)} {shouldRenderFooter && (
{footerContent}
)}
); } export { Dialog };