/** * usePrompt — application-level prompt dialog replacing native browser prompt(). * * Usage: * const { prompt, PromptDialog } = usePrompt(); * const value = await prompt('Bitte Namen eingeben:', { title: 'Umbenennen' }); * if (value !== null) { ... } * // Render once in the component tree. */ import React, { useState, useCallback, useRef } from 'react'; export interface PromptOptions { title?: string; confirmLabel?: string; cancelLabel?: string; placeholder?: string; defaultValue?: string; variant?: 'primary' | 'danger'; } interface PromptState { message: string; options: Required; resolve: (value: string | null) => void; } const _defaults: Required = { title: 'Eingabe', confirmLabel: 'OK', cancelLabel: 'Abbrechen', placeholder: '', defaultValue: '', variant: 'primary', }; export function usePrompt() { const [state, setState] = useState(null); const resolveRef = useRef<((v: string | null) => void) | null>(null); const inputRef = useRef(null); const prompt = useCallback((message: string, options?: PromptOptions): Promise => { return new Promise((resolve) => { resolveRef.current = resolve; setState({ message, options: { ..._defaults, ...options }, resolve, }); }); }, []); const _handleConfirm = useCallback(() => { const val = inputRef.current?.value ?? ''; resolveRef.current?.(val); resolveRef.current = null; setState(null); }, []); const _handleCancel = useCallback(() => { resolveRef.current?.(null); resolveRef.current = null; setState(null); }, []); const PromptDialog: React.FC = useCallback(() => { if (!state) return null; const { message, options } = state; const isDanger = options.variant === 'danger'; return (
e.stopPropagation()} style={{ background: 'var(--surface-color, #1a1a2e)', border: '1px solid var(--border-color, var(--color-border, #333))', borderRadius: '12px', padding: '1.5rem', minWidth: 360, maxWidth: 500, boxShadow: '0 8px 32px rgba(0,0,0,0.4)', display: 'flex', flexDirection: 'column', gap: '1.25rem', }} >

{options.title}

{message}

{ if (e.key === 'Enter') _handleConfirm(); if (e.key === 'Escape') _handleCancel(); }} style={{ padding: '10px 14px', borderRadius: '8px', border: '1px solid var(--border-color, var(--color-border, #ccc))', background: 'var(--input-bg, var(--bg-primary, #ffffff))', color: 'var(--text-primary, #1a1a1a)', fontSize: '0.9rem', outline: 'none', width: '100%', boxSizing: 'border-box', }} />
); }, [state, _handleConfirm, _handleCancel]); return { prompt, PromptDialog }; }