import { createContext, useCallback, useContext, useMemo, useReducer, useRef, type MouseEvent, type PropsWithChildren, type SyntheticEvent, } from 'react' import { stringToBoolean } from '../../utils/helpers.ts' import { AlertDialog, AlertDialogFooter, AlertDialogHeader, AlertDialogHeading, AlertDialogText, AlertDialogCancel, AlertDialogConfirm, Flex, Show, } from '../../index.ts' import { useInitialAlertOptions } from '../shared/alert.hooks.ts' import { addConfirmOptions, confirmReducer, initialConfirmOptions, removeConfirmOptions, } from './reducer.ts' import type { ConfirmContextProps, ConfirmDialogAlertOptions } from './types.ts' const ConfirmContext = createContext(null) // export function ConfirmProvider( props: PropsWithChildren>, ) { const initialOptions = useInitialAlertOptions(initialConfirmOptions) const [options, dispatch] = useReducer< typeof confirmReducer, ConfirmDialogAlertOptions >( confirmReducer, initialOptions, // React types bug workaround undefined as unknown as () => never, ) const dialogRef = useRef(null) const resolveRef = useRef<(value: boolean) => void>(() => null) function cleanup() { document.body.removeAttribute('data-modal-open') removeConfirmOptions(dispatch) } function handleCancel(e: MouseEvent) { const target = e.target as HTMLButtonElement e.preventDefault() dialogRef.current?.close(target.value) cleanup() } const handleClose = useCallback((e: SyntheticEvent) => { const target = e.target as HTMLDialogElement cleanup() resolveRef.current(stringToBoolean(target?.returnValue)) }, []) const value = useMemo(() => { async function fetchConfirmResponse(): Promise> { return new Promise((resolve) => { resolveRef.current = resolve }) } async function confirm(options: ConfirmDialogAlertOptions) { addConfirmOptions(dispatch, options) document.body.setAttribute('data-modal-open', 'true') dialogRef.current?.showModal() return fetchConfirmResponse() } return { confirm, } }, []) return ( {props.children} {options.heading} {options.text}
Cancel Confirm
) } // useConfirm() export function useConfirm() { const context = useContext(ConfirmContext) if (!context) { throw new Error('useConfirm must be used within a ConfirmProvider.') } return context }