/** * Copyright (c) 2023-present Plane Software, Inc. and contributors * SPDX-License-Identifier: AGPL-3.0-only * See the LICENSE file for details. */ import { forwardRef, memo, useMemo } from "react"; import { Dialog as BaseDialog } from "@base-ui-components/react"; import { cn } from "../utils/classname"; // enums export enum EDialogWidth { SM = "sm:max-w-sm", MD = "sm:max-w-md", LG = "sm:max-w-lg", XL = "sm:max-w-xl", XXL = "sm:max-w-2xl", XXXL = "sm:max-w-3xl", XXXXL = "sm:max-w-4xl", VXL = "sm:max-w-5xl", VIXL = "sm:max-w-6xl", VIIXL = "sm:max-w-7xl", } // Types export type DialogPosition = "center" | "top"; export interface DialogProps extends React.ComponentProps { children: React.ReactNode; } export interface DialogPanelProps extends React.ComponentProps { width?: EDialogWidth; position?: DialogPosition; children: React.ReactNode; } export interface DialogTitleProps extends React.ComponentProps { children: React.ReactNode; } // Constants const OVERLAY_CLASSNAME = cn("fixed inset-0 z-90 bg-backdrop/70 backdrop-blur-sm"); const BASE_CLASSNAME = "nodedc-glass-modal relative w-full rounded-[28px] border border-subtle/70 bg-surface-1/78 text-left shadow-[0_16px_48px_rgba(0,0,0,0.34)] backdrop-blur-2xl z-100"; // Utility functions const getPositionClassNames = (position: DialogPosition) => cn("fixed isolate z-100", { "top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2": position === "center", "top-8 left-1/2 -translate-x-1/2": position === "top", }); const DialogPortal = memo(function DialogPortal({ children, ...props }: React.ComponentProps) { return ( {children} ); }); DialogPortal.displayName = "DialogPortal"; const DialogOverlay = memo(function DialogOverlay({ className, ...props }: React.ComponentProps) { return ; }); DialogOverlay.displayName = "DialogOverlay"; const DialogComponent = memo(function DialogComponent({ children, ...props }: DialogProps) { return ( {children} ); }); DialogComponent.displayName = "Dialog"; const DialogTrigger = memo(function DialogTrigger({ children, ...props }: React.ComponentProps) { return ( {children} ); }); DialogTrigger.displayName = "DialogTrigger"; const DialogPanel = forwardRef(function DialogPanel( { className, width = EDialogWidth.XXL, children, position = "center", ...props }: DialogPanelProps, ref: React.ForwardedRef> ) { const positionClassNames = useMemo(() => getPositionClassNames(position), [position]); return ( {children} ); }); DialogPanel.displayName = "DialogPanel"; const DialogTitle = memo(function DialogTitle({ className, children, ...props }: DialogTitleProps) { return ( {children} ); }); DialogTitle.displayName = "DialogTitle"; // Create the compound Dialog component with proper typing const Dialog = Object.assign(DialogComponent, { Panel: DialogPanel, Title: DialogTitle, }) as typeof DialogComponent & { Panel: typeof DialogPanel; Title: typeof DialogTitle; }; export { Dialog, DialogTitle, DialogPanel };