0.0.1.2
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
"use client"
|
||||
|
||||
import { useState, createContext, useContext, ReactNode } from "react"
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/components/ui/alert-dialog"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
|
||||
type DialogType = "alert" | "confirm" | "prompt"
|
||||
|
||||
interface DialogConfig {
|
||||
type: DialogType
|
||||
title?: string
|
||||
message: string
|
||||
defaultValue?: string
|
||||
confirmText?: string
|
||||
cancelText?: string
|
||||
variant?: "default" | "destructive"
|
||||
onConfirm?: (value?: string) => void
|
||||
onCancel?: () => void
|
||||
}
|
||||
|
||||
interface DialogContextType {
|
||||
showAlert: (message: string, title?: string) => Promise<void>
|
||||
showConfirm: (message: string, title?: string, variant?: "default" | "destructive") => Promise<boolean>
|
||||
showPrompt: (message: string, defaultValue?: string, title?: string) => Promise<string | null>
|
||||
}
|
||||
|
||||
const DialogContext = createContext<DialogContextType | undefined>(undefined)
|
||||
|
||||
export function DialogProvider({ children }: { children: ReactNode }) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [config, setConfig] = useState<DialogConfig | null>(null)
|
||||
const [inputValue, setInputValue] = useState("")
|
||||
|
||||
const showAlert = (message: string, title?: string): Promise<void> => {
|
||||
return new Promise((resolve) => {
|
||||
setConfig({
|
||||
type: "alert",
|
||||
title: title || "提示",
|
||||
message,
|
||||
confirmText: "确定",
|
||||
onConfirm: () => {
|
||||
setOpen(false)
|
||||
resolve()
|
||||
},
|
||||
})
|
||||
setOpen(true)
|
||||
})
|
||||
}
|
||||
|
||||
const showConfirm = (
|
||||
message: string,
|
||||
title?: string,
|
||||
variant: "default" | "destructive" = "default"
|
||||
): Promise<boolean> => {
|
||||
return new Promise((resolve) => {
|
||||
setConfig({
|
||||
type: "confirm",
|
||||
title: title || "确认",
|
||||
message,
|
||||
confirmText: "确定",
|
||||
cancelText: "取消",
|
||||
variant,
|
||||
onConfirm: () => {
|
||||
setOpen(false)
|
||||
resolve(true)
|
||||
},
|
||||
onCancel: () => {
|
||||
setOpen(false)
|
||||
resolve(false)
|
||||
},
|
||||
})
|
||||
setOpen(true)
|
||||
})
|
||||
}
|
||||
|
||||
const showPrompt = (
|
||||
message: string,
|
||||
defaultValue: string = "",
|
||||
title?: string
|
||||
): Promise<string | null> => {
|
||||
return new Promise((resolve) => {
|
||||
setInputValue(defaultValue)
|
||||
setConfig({
|
||||
type: "prompt",
|
||||
title: title || "输入",
|
||||
message,
|
||||
defaultValue,
|
||||
confirmText: "确定",
|
||||
cancelText: "取消",
|
||||
onConfirm: (value) => {
|
||||
setOpen(false)
|
||||
resolve(value || null)
|
||||
},
|
||||
onCancel: () => {
|
||||
setOpen(false)
|
||||
resolve(null)
|
||||
},
|
||||
})
|
||||
setOpen(true)
|
||||
})
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (config?.type === "prompt") {
|
||||
config.onConfirm?.(inputValue)
|
||||
} else {
|
||||
config?.onConfirm?.()
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
config?.onCancel?.()
|
||||
}
|
||||
|
||||
return (
|
||||
<DialogContext.Provider value={{ showAlert, showConfirm, showPrompt }}>
|
||||
{children}
|
||||
<AlertDialog open={open} onOpenChange={setOpen}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>{config?.title}</AlertDialogTitle>
|
||||
<AlertDialogDescription className="whitespace-pre-wrap">
|
||||
{config?.message}
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
|
||||
{config?.type === "prompt" && (
|
||||
<div className="py-4">
|
||||
<Label htmlFor="prompt-input" className="sr-only">
|
||||
输入值
|
||||
</Label>
|
||||
<Input
|
||||
id="prompt-input"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
handleConfirm()
|
||||
}
|
||||
}}
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<AlertDialogFooter>
|
||||
{config?.type !== "alert" && (
|
||||
<AlertDialogCancel onClick={handleCancel}>
|
||||
{config?.cancelText || "取消"}
|
||||
</AlertDialogCancel>
|
||||
)}
|
||||
<AlertDialogAction
|
||||
onClick={handleConfirm}
|
||||
className={config?.variant === "destructive" ? "bg-destructive text-destructive-foreground hover:bg-destructive/90" : ""}
|
||||
>
|
||||
{config?.confirmText || "确定"}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</DialogContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useDialog() {
|
||||
const context = useContext(DialogContext)
|
||||
if (!context) {
|
||||
throw new Error("useDialog must be used within a DialogProvider")
|
||||
}
|
||||
return context
|
||||
}
|
||||
Reference in New Issue
Block a user