|
1 | | -"use client"; |
2 | | - |
3 | | -import * as React from "react"; |
4 | | -import { Dialog as DialogPrimitive } from "radix-ui"; |
5 | | -import { X } from "lucide-react"; |
6 | | -import { cn } from "@/utils/ui"; |
7 | | -import { useOverlayOpenChange } from "./use-overlay-open-change"; |
8 | | - |
9 | | -function Dialog({ |
10 | | - open, |
11 | | - onOpenChange, |
12 | | - ...props |
13 | | -}: React.ComponentProps<typeof DialogPrimitive.Root>) { |
14 | | - const handleOpenChange = useOverlayOpenChange({ |
15 | | - source: "dialog", |
16 | | - open, |
17 | | - onOpenChange, |
18 | | - }); |
19 | | - return ( |
20 | | - <DialogPrimitive.Root open={open} onOpenChange={handleOpenChange} {...props} /> |
21 | | - ); |
22 | | -} |
23 | | - |
24 | | -const DialogTrigger = DialogPrimitive.Trigger; |
25 | | - |
26 | | -const DialogPortal = DialogPrimitive.Portal; |
27 | | - |
28 | | -const DialogClose = DialogPrimitive.Close; |
29 | | - |
30 | | -const DialogOverlay = React.forwardRef< |
31 | | - React.ElementRef<typeof DialogPrimitive.Overlay>, |
32 | | - React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> |
33 | | ->(({ className, ...props }, ref) => ( |
34 | | - <DialogPrimitive.Overlay |
35 | | - ref={ref} |
36 | | - className={cn( |
37 | | - "fixed inset-0 z-250 backdrop-blur-sm bg-black/10", |
38 | | - className, |
39 | | - )} |
40 | | - {...props} |
41 | | - /> |
42 | | -)); |
43 | | -DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; |
44 | | - |
45 | | -const DialogContent = React.forwardRef< |
46 | | - React.ElementRef<typeof DialogPrimitive.Content>, |
47 | | - React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> |
48 | | ->(({ className, children, ...props }, ref) => ( |
49 | | - <DialogPortal> |
50 | | - <DialogOverlay /> |
51 | | - <DialogPrimitive.Content |
52 | | - ref={ref} |
53 | | - className={cn( |
54 | | - "bg-popover fixed top-[50%] left-[50%] z-250 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200", |
55 | | - className, |
56 | | - )} |
57 | | - onCloseAutoFocus={(e) => { |
58 | | - e.stopPropagation(); |
59 | | - e.preventDefault(); |
60 | | - }} |
61 | | - {...props} |
62 | | - > |
63 | | - {children} |
64 | | - <DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-6 right-6 cursor-pointer opacity-70 hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none"> |
65 | | - <X className="size-5 text-muted-foreground" /> |
66 | | - <span className="sr-only">Close</span> |
67 | | - </DialogPrimitive.Close> |
68 | | - </DialogPrimitive.Content> |
69 | | - </DialogPortal> |
70 | | -)); |
71 | | -DialogContent.displayName = DialogPrimitive.Content.displayName; |
72 | | - |
73 | | -const DialogHeader = ({ |
74 | | - className, |
75 | | - ...props |
76 | | -}: React.HTMLAttributes<HTMLDivElement>) => ( |
77 | | - <div |
78 | | - className={cn("flex flex-col space-y-2 text-left border-b p-6", className)} |
79 | | - {...props} |
80 | | - /> |
81 | | -); |
82 | | -DialogHeader.displayName = "DialogHeader"; |
83 | | - |
84 | | -const DialogBody = ({ |
85 | | - className, |
86 | | - ...props |
87 | | -}: React.HTMLAttributes<HTMLDivElement>) => ( |
88 | | - <div className={cn("p-6 flex flex-col gap-4", className)} {...props} /> |
89 | | -); |
90 | | -DialogBody.displayName = "DialogBody"; |
91 | | - |
92 | | -const DialogFooter = ({ |
93 | | - className, |
94 | | - ...props |
95 | | -}: React.HTMLAttributes<HTMLDivElement>) => ( |
96 | | - <div |
97 | | - className={cn( |
98 | | - "flex gap-3 flex-col-reverse sm:flex-row sm:justify-end p-6 py-5 border-t", |
99 | | - className, |
100 | | - )} |
101 | | - {...props} |
102 | | - /> |
103 | | -); |
104 | | -DialogFooter.displayName = "DialogFooter"; |
105 | | - |
106 | | -const DialogTitle = React.forwardRef< |
107 | | - React.ElementRef<typeof DialogPrimitive.Title>, |
108 | | - React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> |
109 | | ->(({ className, ...props }, ref) => ( |
110 | | - <DialogPrimitive.Title |
111 | | - ref={ref} |
112 | | - className={cn( |
113 | | - "text-lg leading-none font-semibold tracking-tight", |
114 | | - className, |
115 | | - )} |
116 | | - {...props} |
117 | | - /> |
118 | | -)); |
119 | | -DialogTitle.displayName = DialogPrimitive.Title.displayName; |
120 | | - |
121 | | -const DialogDescription = React.forwardRef< |
122 | | - React.ElementRef<typeof DialogPrimitive.Description>, |
123 | | - React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> |
124 | | ->(({ className, ...props }, ref) => ( |
125 | | - <DialogPrimitive.Description |
126 | | - ref={ref} |
127 | | - className={cn("text-muted-foreground text-sm", className)} |
128 | | - {...props} |
129 | | - /> |
130 | | -)); |
131 | | -DialogDescription.displayName = DialogPrimitive.Description.displayName; |
132 | | - |
133 | | -export { |
134 | | - Dialog, |
135 | | - DialogPortal, |
136 | | - DialogOverlay, |
137 | | - DialogTrigger, |
138 | | - DialogClose, |
139 | | - DialogContent, |
140 | | - DialogHeader, |
141 | | - DialogBody, |
142 | | - DialogFooter, |
143 | | - DialogTitle, |
144 | | - DialogDescription, |
145 | | -}; |
| 1 | +"use client"; |
| 2 | + |
| 3 | +import * as React from "react"; |
| 4 | +import { Dialog as DialogPrimitive } from "radix-ui"; |
| 5 | +import { X } from "lucide-react"; |
| 6 | +import { cn } from "@/utils/ui"; |
| 7 | +import { useOverlayOpenChange } from "./use-overlay-open-change"; |
| 8 | + |
| 9 | +function Dialog({ |
| 10 | + open, |
| 11 | + onOpenChange, |
| 12 | + ...props |
| 13 | +}: React.ComponentProps<typeof DialogPrimitive.Root>) { |
| 14 | + const handleOpenChange = useOverlayOpenChange({ |
| 15 | + open, |
| 16 | + onOpenChange, |
| 17 | + }); |
| 18 | + return ( |
| 19 | + <DialogPrimitive.Root |
| 20 | + open={open} |
| 21 | + onOpenChange={handleOpenChange} |
| 22 | + {...props} |
| 23 | + /> |
| 24 | + ); |
| 25 | +} |
| 26 | + |
| 27 | +const DialogTrigger = DialogPrimitive.Trigger; |
| 28 | + |
| 29 | +const DialogPortal = DialogPrimitive.Portal; |
| 30 | + |
| 31 | +const DialogClose = DialogPrimitive.Close; |
| 32 | + |
| 33 | +const DialogOverlay = React.forwardRef< |
| 34 | + React.ElementRef<typeof DialogPrimitive.Overlay>, |
| 35 | + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> |
| 36 | +>(({ className, ...props }, ref) => ( |
| 37 | + <DialogPrimitive.Overlay |
| 38 | + ref={ref} |
| 39 | + className={cn( |
| 40 | + "fixed inset-0 z-250 backdrop-blur-sm bg-black/10", |
| 41 | + className, |
| 42 | + )} |
| 43 | + {...props} |
| 44 | + /> |
| 45 | +)); |
| 46 | +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; |
| 47 | + |
| 48 | +const DialogContent = React.forwardRef< |
| 49 | + React.ElementRef<typeof DialogPrimitive.Content>, |
| 50 | + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> |
| 51 | +>(({ className, children, ...props }, ref) => ( |
| 52 | + <DialogPortal> |
| 53 | + <DialogOverlay /> |
| 54 | + <DialogPrimitive.Content |
| 55 | + ref={ref} |
| 56 | + className={cn( |
| 57 | + "bg-popover fixed top-[50%] left-[50%] z-250 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200", |
| 58 | + className, |
| 59 | + )} |
| 60 | + onCloseAutoFocus={(e) => { |
| 61 | + e.stopPropagation(); |
| 62 | + e.preventDefault(); |
| 63 | + }} |
| 64 | + {...props} |
| 65 | + > |
| 66 | + {children} |
| 67 | + <DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-6 right-6 cursor-pointer opacity-70 hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none"> |
| 68 | + <X className="size-5 text-muted-foreground" /> |
| 69 | + <span className="sr-only">Close</span> |
| 70 | + </DialogPrimitive.Close> |
| 71 | + </DialogPrimitive.Content> |
| 72 | + </DialogPortal> |
| 73 | +)); |
| 74 | +DialogContent.displayName = DialogPrimitive.Content.displayName; |
| 75 | + |
| 76 | +const DialogHeader = ({ |
| 77 | + className, |
| 78 | + ...props |
| 79 | +}: React.HTMLAttributes<HTMLDivElement>) => ( |
| 80 | + <div |
| 81 | + className={cn("flex flex-col space-y-2 text-left border-b p-6", className)} |
| 82 | + {...props} |
| 83 | + /> |
| 84 | +); |
| 85 | +DialogHeader.displayName = "DialogHeader"; |
| 86 | + |
| 87 | +const DialogBody = ({ |
| 88 | + className, |
| 89 | + ...props |
| 90 | +}: React.HTMLAttributes<HTMLDivElement>) => ( |
| 91 | + <div className={cn("p-6 flex flex-col gap-4", className)} {...props} /> |
| 92 | +); |
| 93 | +DialogBody.displayName = "DialogBody"; |
| 94 | + |
| 95 | +const DialogFooter = ({ |
| 96 | + className, |
| 97 | + ...props |
| 98 | +}: React.HTMLAttributes<HTMLDivElement>) => ( |
| 99 | + <div |
| 100 | + className={cn( |
| 101 | + "flex gap-3 flex-col-reverse sm:flex-row sm:justify-end p-6 py-5 border-t", |
| 102 | + className, |
| 103 | + )} |
| 104 | + {...props} |
| 105 | + /> |
| 106 | +); |
| 107 | +DialogFooter.displayName = "DialogFooter"; |
| 108 | + |
| 109 | +const DialogTitle = React.forwardRef< |
| 110 | + React.ElementRef<typeof DialogPrimitive.Title>, |
| 111 | + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> |
| 112 | +>(({ className, ...props }, ref) => ( |
| 113 | + <DialogPrimitive.Title |
| 114 | + ref={ref} |
| 115 | + className={cn( |
| 116 | + "text-lg leading-none font-semibold tracking-tight", |
| 117 | + className, |
| 118 | + )} |
| 119 | + {...props} |
| 120 | + /> |
| 121 | +)); |
| 122 | +DialogTitle.displayName = DialogPrimitive.Title.displayName; |
| 123 | + |
| 124 | +const DialogDescription = React.forwardRef< |
| 125 | + React.ElementRef<typeof DialogPrimitive.Description>, |
| 126 | + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> |
| 127 | +>(({ className, ...props }, ref) => ( |
| 128 | + <DialogPrimitive.Description |
| 129 | + ref={ref} |
| 130 | + className={cn("text-muted-foreground text-sm", className)} |
| 131 | + {...props} |
| 132 | + /> |
| 133 | +)); |
| 134 | +DialogDescription.displayName = DialogPrimitive.Description.displayName; |
| 135 | + |
| 136 | +export { |
| 137 | + Dialog, |
| 138 | + DialogPortal, |
| 139 | + DialogOverlay, |
| 140 | + DialogTrigger, |
| 141 | + DialogClose, |
| 142 | + DialogContent, |
| 143 | + DialogHeader, |
| 144 | + DialogBody, |
| 145 | + DialogFooter, |
| 146 | + DialogTitle, |
| 147 | + DialogDescription, |
| 148 | +}; |
0 commit comments