import React from 'react'; import { i18next } from '@tencentcloud/uikit-base-component-react'; import { createRoot } from 'react-dom/client'; import { Dialog } from './Dialog'; import type { DialogOpenOptions } from './types'; const CLOSE_ANIMATION_DURATION = 220; const defaultOptions = (): DialogOpenOptions => ({ title: '', description: '', content: '', confirmText: i18next.t('Dialog.confirm') || 'Confirm', cancelText: i18next.t('Dialog.cancel') || 'Cancel', confirmLoading: false, confirmDisabled: false, cancelDisabled: false, showClose: true, maskClosable: true, escClosable: true, appendTo: null, width: 420, className: '', }); let container: HTMLDivElement | null = null; let root: ReturnType | null = null; let destroyTimer: ReturnType | null = null; let currentOptions: DialogOpenOptions = defaultOptions(); let open = false; let confirmLoading = false; const clearDestroyTimer = () => { if (destroyTimer) { clearTimeout(destroyTimer); destroyTimer = null; } }; const normalizeOptions = (options: DialogOpenOptions): DialogOpenOptions => ({ ...defaultOptions(), ...options, }); const renderDialog = () => { if (!root) { return; } root.render( React.createElement(Dialog, { ...currentOptions, open, confirmLoading: confirmLoading || !!currentOptions.confirmLoading, onOpenChange: (nextOpen: boolean) => { open = nextOpen; if (!nextOpen) { confirmLoading = false; scheduleDestroy(); } renderDialog(); }, onConfirm: handleConfirm, onCancel: () => currentOptions.onCancel?.(), onClose: () => currentOptions.onClose?.(), }), ); }; const ensureMounted = () => { clearDestroyTimer(); if (container && root) { return; } container = document.createElement('div'); root = createRoot(container); document.body.appendChild(container); }; function removeContainer() { if (!container || !root) { return; } const currentContainer = container; const currentRoot = root; currentContainer.style.visibility = 'hidden'; currentContainer.style.pointerEvents = 'none'; container = null; root = null; setTimeout(() => { currentRoot.unmount(); if (currentContainer.parentNode) { currentContainer.parentNode.removeChild(currentContainer); } }, 0); } function scheduleDestroy() { clearDestroyTimer(); destroyTimer = setTimeout(removeContainer, CLOSE_ANIMATION_DURATION); } const close = () => { if (!open && !root) { return; } open = false; confirmLoading = false; renderDialog(); scheduleDestroy(); }; async function handleConfirm() { const result = currentOptions.onConfirm?.(); if (!currentOptions.onConfirm) { close(); return; } if (!(result instanceof Promise)) { if (result !== false) { close(); } return; } confirmLoading = true; renderDialog(); try { const shouldClose = await result; if (shouldClose !== false) { close(); } } finally { confirmLoading = false; renderDialog(); } } const openDialog = (options: DialogOpenOptions) => { ensureMounted(); currentOptions = normalizeOptions(options); confirmLoading = false; open = true; renderDialog(); }; export const dialog = { open: openDialog, close, };