import React, { useState, useEffect, useRef, ReactNode } from 'react' import { DialogContext, DialogContextType } from './DialogContext' import { addOverlay, Backdrop, Input, removeOverlay } from '~/components' import { Dialog } from './Dialog' import { removeAllOverlays } from '..' const Prompt = ({ type = 'prompt', onCancel, onConfirm, ...props }) => { const ref = useRef() const isPrompt = type === 'prompt' const isAlert = type === 'alert' return ( {isPrompt ? ( ) : null} {isAlert ? null : } isPrompt ? onConfirm(ref.current.value) : onConfirm(true) } /> ) } interface DialogItem { id: number children: ReactNode } export const DialogProvider = ({ children, fixed = true }) => { const dialogsRef = useRef() const dialogRef = useRef() if (!dialogRef.current) { let count = 0 const listeners = new Set>>() const update = (length) => { listeners.forEach((fn) => fn(length)) } const dialog = (children, onClose = null) => { const id = count++ // this is only used internally dialog._id = id children = ( { if (event.currentTarget === event.target) { dialogRef.current.close(id) } }} > {children} ) requestAnimationFrame(() => { addOverlay(children, onClose) update( dialogsRef.current.push({ id, children, }) ) }) return id } dialog._id = null const prompt = (type, props) => { return new Promise((resolve) => { if (typeof props === 'string') { props = { title: props, } } dialog.open(, () => resolve(false) ) }) } dialog.open = dialog dialog.close = (id) => { if (typeof id === 'number') { const index = dialogsRef.current.findIndex( ({ id: dialogId }) => dialogId === id ) if (index !== -1) { const removed = dialogsRef.current.splice(index, 1) const { length } = dialogsRef.current dialog._id = length ? dialogsRef.current[length - 1].id : null update(length) removeOverlay(removed?.[0].children) } } else { dialogsRef.current = [] dialog._id = null update(0) removeAllOverlays() } } dialog.prompt = (props) => prompt('prompt', props) dialog.alert = (props) => prompt('alert', props) dialog.confirm = (props) => prompt('confirm', props) dialog.useCount = () => { const [state, setState] = useState(dialogsRef.current.length) useEffect(() => { listeners.add(setState) return () => { listeners.delete(setState) } }, []) return state } // @ts-ignore dialogRef.current = dialog dialogsRef.current = [] } return ( {children} ) }