import { createContext, useCallback, useContext, useMemo, useReducer, useRef, useState, type MouseEvent, type PropsWithChildren, type SyntheticEvent, } from 'react' import { getFormLabelProps } from '@pluralsight/headless-styles' import { AlertDialog, AlertDialogFooter, AlertDialogHeader, AlertDialogHeading, AlertDialogText, AlertDialogCancel, AlertDialogConfirm, Flex, Show, AlertDialogBody, Input, Label, FormControlProvider, } from '../../index.ts' import { useInitialAlertOptions } from '../shared/alert.hooks.ts' import { addPromptOptions, promptReducer, initialPromptOptions, removePromptOptions, } from './reducer.ts' import type { PromptContextProps, PromptDialogAlertOptions } from './types.ts' const PromptContext = createContext(null) // export function PromptProvider( props: PropsWithChildren>, ) { const initialOptions = useInitialAlertOptions(initialPromptOptions) const [options, dispatch] = useReducer< typeof promptReducer, PromptDialogAlertOptions >( promptReducer, initialOptions, // React types bug workaround undefined as unknown as () => never, ) const [inputValue, setInputValue] = useState('') const dialogRef = useRef(null) const resolveRef = useRef<(value: string) => void>(() => null) const invalid = options.kind === 'destructive' && inputValue !== options.promptValidationKey function cleanup() { document.body.removeAttribute('data-modal-open') setInputValue('') removePromptOptions(dispatch) } function handleCancel(e: MouseEvent) { const target = e.target as HTMLButtonElement e.preventDefault() console.log('handleConfirm') dialogRef.current?.close(target.value) cleanup() } const handleClose = useCallback((e: SyntheticEvent) => { const target = e.target as HTMLDialogElement cleanup() resolveRef.current(target?.returnValue) }, []) function handleInputChange(e: SyntheticEvent) { const target = e.target as HTMLInputElement setInputValue(target.value) } const value = useMemo(() => { async function fetchConfirmResponse(): Promise> { return new Promise((resolve) => { resolveRef.current = resolve }) } async function prompt(options: PromptDialogAlertOptions) { addPromptOptions(dispatch, options) document.body.setAttribute('data-modal-open', 'true') dialogRef.current?.showModal() return fetchConfirmResponse() } return { prompt, } }, []) return ( {props.children} {options.heading}
{options.text}
{options.promptValidationKey ?? 'Validation'} } >
Cancel {options.kind === 'destructive' ? 'Confirm' : 'OK'}
) } // useConfirm() export function usePrompt() { const context = useContext(PromptContext) if (!context) { throw new Error('usePrompt must be used within a PromptProvider.') } return context }