useConfirm.tsx 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { Button } from "@/components/ui/button"
  2. import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "."
  3. import ReactDOM from "react-dom"
  4. import i18next from "i18next"
  5. import { useRef, useState } from "react"
  6. import { TipIcon } from "@/components/bs-icons/tip"
  7. import { Cross2Icon } from "@radix-ui/react-icons"
  8. import { createRoot } from "react-dom/client"
  9. interface ConfirmParams {
  10. title?: string
  11. desc: string | React.ReactNode
  12. canelTxt?: string
  13. okTxt?: string
  14. showClose?: boolean
  15. onClose?: () => void
  16. onCancel?: () => void
  17. onOk?: (next) => void
  18. }
  19. let openFn = (_: ConfirmParams) => { }
  20. function ConfirmWrapper() {
  21. const [open, setOpen] = useState(false)
  22. const paramRef = useRef(null)
  23. openFn = (params: ConfirmParams) => {
  24. paramRef.current = params
  25. setOpen(true)
  26. }
  27. const close = () => {
  28. paramRef.current?.onClose?.()
  29. setOpen(false)
  30. }
  31. const handleCancelClick = () => {
  32. paramRef.current?.onCancel?.()
  33. close()
  34. }
  35. const handleOkClick = () => {
  36. paramRef.current?.onOk
  37. ? paramRef.current?.onOk?.(close)
  38. : close()
  39. }
  40. if (!paramRef.current) return null
  41. const { title, desc, okTxt, canelTxt, showClose = true } = paramRef.current
  42. return (
  43. <AlertDialog open={open} onOpenChange={setOpen}>
  44. <AlertDialogContent>
  45. <AlertDialogHeader className="relative">
  46. <div><TipIcon /></div>
  47. {showClose && <Cross2Icon onClick={close} className="absolute right-0 top-[-0.5rem] cursor-pointer text-gray-400 hover:text-gray-600"></Cross2Icon>}
  48. <AlertDialogTitle>{title}</AlertDialogTitle>
  49. <AlertDialogDescription>
  50. {desc}
  51. </AlertDialogDescription>
  52. </AlertDialogHeader>
  53. <AlertDialogFooter>
  54. <AlertDialogCancel onClick={handleCancelClick} className="px-11">{canelTxt}</AlertDialogCancel>
  55. <AlertDialogAction onClick={handleOkClick} className="px-11">{okTxt}</AlertDialogAction>
  56. </AlertDialogFooter>
  57. </AlertDialogContent>
  58. </AlertDialog>
  59. )
  60. }
  61. (function () {
  62. // 挂载组件
  63. let el = document.getElementById('#confirm-wrap');
  64. if (!el) {
  65. el = document.createElement('div')
  66. el.id = 'confirm-wrap'
  67. document.body.append(el)
  68. }
  69. // ReactDOM.render(<ConfirmWrapper />, el);
  70. const root = createRoot(el);
  71. root.render(<ConfirmWrapper />);
  72. })();
  73. const bsConfirm = (params: ConfirmParams) => {
  74. const resource = i18next.getResourceBundle(i18next.language, 'bs')
  75. openFn({
  76. title: resource.prompt,
  77. canelTxt: resource.cancel,
  78. okTxt: resource.confirmButton,
  79. ...params,
  80. })
  81. }
  82. export { bsConfirm }