kaneo (minimalist kanban) fork to experiment adding a tangled integration github.com/usekaneo/kaneo
at main 241 lines 6.7 kB view raw
1"use client"; 2 3import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"; 4import { XIcon } from "lucide-react"; 5import * as React from "react"; 6import { Button } from "@/components/ui/button"; 7import { ScrollArea } from "@/components/ui/scroll-area"; 8import { cn } from "@/lib/cn"; 9 10const DialogCreateHandle = DialogPrimitive.createHandle; 11 12const Dialog = DialogPrimitive.Root; 13 14const DialogPortal = DialogPrimitive.Portal; 15 16function DialogTrigger({ 17 asChild = false, 18 children, 19 render, 20 ...props 21}: DialogPrimitive.Trigger.Props & { asChild?: boolean }) { 22 const resolvedRender = 23 asChild && React.isValidElement(children) ? children : render; 24 25 return ( 26 <DialogPrimitive.Trigger 27 data-slot="dialog-trigger" 28 render={resolvedRender} 29 {...props} 30 > 31 {asChild ? undefined : children} 32 </DialogPrimitive.Trigger> 33 ); 34} 35 36function DialogClose({ 37 asChild = false, 38 children, 39 render, 40 ...props 41}: DialogPrimitive.Close.Props & { asChild?: boolean }) { 42 const resolvedRender = 43 asChild && React.isValidElement(children) ? children : render; 44 45 return ( 46 <DialogPrimitive.Close 47 data-slot="dialog-close" 48 render={resolvedRender} 49 {...props} 50 > 51 {asChild ? undefined : children} 52 </DialogPrimitive.Close> 53 ); 54} 55 56function DialogBackdrop({ 57 className, 58 ...props 59}: DialogPrimitive.Backdrop.Props) { 60 return ( 61 <DialogPrimitive.Backdrop 62 className={cn( 63 "fixed inset-0 z-50 bg-black/32 backdrop-blur-sm transition-all duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0", 64 className, 65 )} 66 data-slot="dialog-backdrop" 67 {...props} 68 /> 69 ); 70} 71 72function DialogViewport({ 73 className, 74 ...props 75}: DialogPrimitive.Viewport.Props) { 76 return ( 77 <DialogPrimitive.Viewport 78 className={cn( 79 "fixed inset-0 z-50 grid grid-rows-[1fr_auto_3fr] justify-items-center p-4", 80 className, 81 )} 82 data-slot="dialog-viewport" 83 {...props} 84 /> 85 ); 86} 87 88function DialogPopup({ 89 className, 90 children, 91 showCloseButton = true, 92 bottomStickOnMobile = true, 93 ...props 94}: DialogPrimitive.Popup.Props & { 95 showCloseButton?: boolean; 96 bottomStickOnMobile?: boolean; 97}) { 98 return ( 99 <DialogPortal> 100 <DialogBackdrop /> 101 <DialogViewport 102 className={cn( 103 bottomStickOnMobile && 104 "max-sm:grid-rows-[1fr_auto] max-sm:p-0 max-sm:pt-12", 105 )} 106 > 107 <DialogPrimitive.Popup 108 className={cn( 109 "-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-full min-h-0 w-full min-w-0 max-w-lg scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", 110 bottomStickOnMobile && 111 "max-sm:max-w-none max-sm:rounded-none max-sm:border-x-0 max-sm:border-t max-sm:border-b-0 max-sm:opacity-[calc(1-min(var(--nested-dialogs),1))] max-sm:data-ending-style:translate-y-4 max-sm:data-starting-style:translate-y-4 max-sm:before:hidden max-sm:before:rounded-none", 112 className, 113 )} 114 data-slot="dialog-popup" 115 {...props} 116 > 117 {children} 118 {showCloseButton && ( 119 <DialogPrimitive.Close 120 aria-label="Close" 121 className="absolute end-2 top-2" 122 render={<Button size="icon" variant="ghost" />} 123 > 124 <XIcon /> 125 </DialogPrimitive.Close> 126 )} 127 </DialogPrimitive.Popup> 128 </DialogViewport> 129 </DialogPortal> 130 ); 131} 132 133function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { 134 return ( 135 <div 136 className={cn( 137 "flex flex-col gap-2 p-6 in-[[data-slot=dialog-popup]:has([data-slot=dialog-panel])]:pb-3 max-sm:pb-4", 138 className, 139 )} 140 data-slot="dialog-header" 141 {...props} 142 /> 143 ); 144} 145 146function DialogFooter({ 147 className, 148 variant = "default", 149 ...props 150}: React.ComponentProps<"div"> & { 151 variant?: "default" | "bare"; 152}) { 153 return ( 154 <div 155 className={cn( 156 "flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end sm:rounded-b-[calc(var(--radius-2xl)-1px)]", 157 variant === "default" && "border-t bg-muted/72 py-4", 158 variant === "bare" && 159 "in-[[data-slot=dialog-popup]:has([data-slot=dialog-panel])]:pt-3 pt-4 pb-6", 160 className, 161 )} 162 data-slot="dialog-footer" 163 {...props} 164 /> 165 ); 166} 167 168function DialogTitle({ 169 asChild = false, 170 className, 171 children, 172 render, 173 ...props 174}: DialogPrimitive.Title.Props & { asChild?: boolean }) { 175 const resolvedRender = 176 asChild && React.isValidElement(children) ? children : render; 177 178 return ( 179 <DialogPrimitive.Title 180 className={cn( 181 "font-heading font-semibold text-xl leading-none", 182 className, 183 )} 184 data-slot="dialog-title" 185 render={resolvedRender} 186 {...props} 187 > 188 {asChild ? undefined : children} 189 </DialogPrimitive.Title> 190 ); 191} 192 193function DialogDescription({ 194 className, 195 ...props 196}: DialogPrimitive.Description.Props) { 197 return ( 198 <DialogPrimitive.Description 199 className={cn("text-muted-foreground text-sm", className)} 200 data-slot="dialog-description" 201 {...props} 202 /> 203 ); 204} 205 206function DialogPanel({ 207 className, 208 scrollFade = true, 209 ...props 210}: React.ComponentProps<"div"> & { scrollFade?: boolean }) { 211 return ( 212 <ScrollArea scrollFade={scrollFade}> 213 <div 214 className={cn( 215 "p-6 in-[[data-slot=dialog-popup]:has([data-slot=dialog-header])]:pt-1 in-[[data-slot=dialog-popup]:has([data-slot=dialog-footer]:not(.border-t))]:pb-1", 216 className, 217 )} 218 data-slot="dialog-panel" 219 {...props} 220 /> 221 </ScrollArea> 222 ); 223} 224 225export { 226 DialogCreateHandle, 227 Dialog, 228 DialogTrigger, 229 DialogPortal, 230 DialogClose, 231 DialogBackdrop, 232 DialogBackdrop as DialogOverlay, 233 DialogPopup, 234 DialogPopup as DialogContent, 235 DialogHeader, 236 DialogFooter, 237 DialogTitle, 238 DialogDescription, 239 DialogPanel, 240 DialogViewport, 241};