import React, { useCallback } from "react"; import { IconButton } from "../icon-button"; import { Text } from "../text"; import { Icons } from "../icons"; import { StyledDialog, StyledTrigger, StyledClose, StyledContent, StyledOverlay, StyledPortal, StyledTitle, StyledDescription, StyledHeader, Content, } from "./dialog.styled"; import type { TextProps } from "../text"; type StitchesDialogProps = React.ComponentProps; export interface DialogProps { /** * The content of the dialog. */ children: React.ReactNode; /** * Whenever dialog should be forcibly opened or closed. Skip to let the dialog manage its own state. */ open?: StitchesDialogProps["open"]; /** * Callback fired when the dialog open state changes. */ onOpenChange?: StitchesDialogProps["onOpenChange"]; /** * Defines the placement of the dialog. */ side?: React.ComponentProps["side"]; /** * Optional ReactNode to be placed at the start of the header */ startItem?: React.ReactNode; /** * The title of the dialog, rendered on the top. */ title?: string | undefined; /** * If `true` will horizontally center title */ centerTitle?: boolean; /** * The description of the dialog, rendered below the title. */ description?: string; /** * Whether the default close button should be rendered or not. */ showCloseButton?: boolean; /** * Whether the default close button should be rendered or not. */ showHeader?: boolean; /** * Whether the overlay should be opaque or not. */ hasOpaqueOverlay?: boolean; /** * The trigger of the dialog. It will be rendered in place where the element is rendered. */ trigger?: React.ReactNode; /** * Props to be passed to the __StyledDialog__ */ rootProps?: Omit, "open" | "onOpenChange">; /** * Props to be passed to the __StyledTrigger__ */ triggerProps?: React.ComponentProps; /** * Props to be passed to the __StyledPortal__ */ portalProps?: React.ComponentProps; /** * Props to be passed to the __StyledOverlay__ */ overlayProps?: Omit, "opaque">; /** * Props to be passed to the __StyledContent__ */ contentProps?: Omit, "side">; /** * Props to be passed to the __StyledTitle__ */ titleProps?: Omit, "asChild">; /** * Props to be passed to the ____ inside the __StyledTitle__ */ titleTextProps?: Omit; /** * Props to be passed to the __StyledDescription__ */ descriptionProps?: React.ComponentProps; /** * Props to be passed to the __StyledClose__ */ closeProps?: Omit, "hide" | "asChild">; /** * Control over the close icon button variant */ closeButtonVariant?: React.ComponentProps["variant"]; /** * Control over the close icon button size */ closeButtonSize?: React.ComponentProps["size"]; /** * Whether the dialog should be closed when clicking outside of it. */ closeOnClickOutside?: boolean; /** * Content rendered outside the visual container of the dialog */ nonTransformedContent?: React.ReactNode; } // eslint-disable-next-line max-lines-per-function export const Dialog: React.FC = ({ open, onOpenChange, children, hasOpaqueOverlay = true, side = "center", startItem, title, centerTitle, description, showCloseButton = false, showHeader = true, trigger, rootProps, triggerProps, portalProps, overlayProps, contentProps, titleProps, titleTextProps, descriptionProps, closeProps, closeButtonVariant = "secondary", closeButtonSize = "m", closeOnClickOutside = true, nonTransformedContent, ...htmlElementAttributes }) => { const { onPointerDownOutside, css, ...restContentProps } = contentProps ?? {}; const handlePointerDownOutside = useCallback( ( e: Parameters["onPointerDownOutside"]>>[0] ) => { onPointerDownOutside?.(e); if (!closeOnClickOutside) { e.preventDefault(); } }, [closeOnClickOutside, onPointerDownOutside] ); return ( {trigger && {trigger}} {showHeader && ( {startItem} {title && ( {title} )} {showCloseButton && ( )} )} {description && ( {description} )} {children} {nonTransformedContent} ); };