| import React, { useEffect, useRef, useState } from 'react' |
| import { createPortal } from 'react-dom' |
| import { useTranslation } from 'react-i18next' |
| import Button from '../button' |
|
|
| export type IConfirm = { |
| className?: string |
| isShow: boolean |
| type?: 'info' | 'warning' |
| title: string |
| content?: React.ReactNode |
| confirmText?: string | null |
| onConfirm: () => void |
| cancelText?: string |
| onCancel: () => void |
| isLoading?: boolean |
| isDisabled?: boolean |
| showConfirm?: boolean |
| showCancel?: boolean |
| maskClosable?: boolean |
| } |
|
|
| function Confirm({ |
| isShow, |
| type = 'warning', |
| title, |
| content, |
| confirmText, |
| cancelText, |
| onConfirm, |
| onCancel, |
| showConfirm = true, |
| showCancel = true, |
| isLoading = false, |
| isDisabled = false, |
| maskClosable = true, |
| }: IConfirm) { |
| const { t } = useTranslation() |
| const dialogRef = useRef<HTMLDivElement>(null) |
| const [isVisible, setIsVisible] = useState(isShow) |
|
|
| const confirmTxt = confirmText || `${t('common.operation.confirm')}` |
| const cancelTxt = cancelText || `${t('common.operation.cancel')}` |
|
|
| useEffect(() => { |
| const handleKeyDown = (event: KeyboardEvent) => { |
| if (event.key === 'Escape') |
| onCancel() |
| } |
|
|
| document.addEventListener('keydown', handleKeyDown) |
| return () => { |
| document.removeEventListener('keydown', handleKeyDown) |
| } |
| }, [onCancel]) |
|
|
| const handleClickOutside = (event: MouseEvent) => { |
| if (maskClosable && dialogRef.current && !dialogRef.current.contains(event.target as Node)) |
| onCancel() |
| } |
|
|
| useEffect(() => { |
| document.addEventListener('mousedown', handleClickOutside) |
| return () => { |
| document.removeEventListener('mousedown', handleClickOutside) |
| } |
| }, [maskClosable]) |
|
|
| useEffect(() => { |
| if (isShow) { |
| setIsVisible(true) |
| } |
| else { |
| const timer = setTimeout(() => setIsVisible(false), 200) |
| return () => clearTimeout(timer) |
| } |
| }, [isShow]) |
|
|
| if (!isVisible) |
| return null |
|
|
| return createPortal( |
| <div className={'fixed inset-0 flex items-center justify-center z-[10000000] bg-background-overlay'} |
| onClick={(e) => { |
| e.preventDefault() |
| e.stopPropagation() |
| }}> |
| <div ref={dialogRef} className={'relative w-full max-w-[480px] overflow-hidden'}> |
| <div className='flex flex-col items-start max-w-full rounded-2xl border-[0.5px] border-solid border-components-panel-border shadows-shadow-lg bg-components-panel-bg'> |
| <div className='flex pt-6 pl-6 pr-6 pb-4 flex-col items-start gap-2 self-stretch'> |
| <div className='title-2xl-semi-bold text-text-primary'>{title}</div> |
| <div className='system-md-regular text-text-tertiary w-full'>{content}</div> |
| </div> |
| <div className='flex p-6 gap-2 justify-end items-start self-stretch'> |
| {showCancel && <Button onClick={onCancel}>{cancelTxt}</Button>} |
| {showConfirm && <Button variant={'primary'} destructive={type !== 'info'} loading={isLoading} disabled={isDisabled} onClick={onConfirm}>{confirmTxt}</Button>} |
| </div> |
| </div> |
| </div> |
| </div>, document.body, |
| ) |
| } |
|
|
| export default React.memo(Confirm) |
|
|