import * as SheetPrimitive from "@radix-ui/react-dialog"; import { FocusScope } from "@radix-ui/react-focus-scope"; import { cva } from "class-variance-authority"; import * as React from "react"; import { Button, Icon, ScrollArea } from "@sparkle/components"; import { XMarkIcon } from "@sparkle/icons/app"; import { cn } from "@sparkle/lib/utils"; const Sheet = SheetPrimitive.Root; const SheetTrigger = SheetPrimitive.Trigger; const SheetClose = SheetPrimitive.Close; const SheetPortal = SheetPrimitive.Portal; const SheetOverlay = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )); SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; const SHEET_SIZES = ["md", "lg", "xl"] as const; type SheetSizeType = (typeof SHEET_SIZES)[number]; const SHEET_SIDES = ["top", "bottom", "left", "right"] as const; type SheetSideType = (typeof SHEET_SIDES)[number]; const sizeClasses: Record = { md: "sm:s-max-w-md", lg: "sm:s-max-w-xl", xl: "sm:s-max-w-3xl", }; const sheetVariants = cva( cn( "s-fixed s-z-50 s-overflow-hidden s-flex s-flex-col s-h-full s-w-full", "s-bg-background dark:s-bg-background-night", "s-transition s-ease-in-out data-[state=open]:s-animate-in data-[state=closed]:s-animate-out data-[state=closed]:s-duration-300 data-[state=open]:s-duration-500" ), { variants: { side: { top: cn( "s-inset-x-0 s-top-0 data-[state=closed]:s-slide-out-to-top data-[state=open]:s-slide-in-from-top", "s-border-b dark:s-border-border-night s-border-border" ), bottom: cn( "s-inset-x-0 s-bottom-0 data-[state=closed]:s-slide-out-to-bottom data-[state=open]:s-slide-in-from-bottom", "s-border-t dark:s-border-border-night s-border-border" ), left: cn( "s-inset-y-0 s-left-0 data-[state=closed]:s-slide-out-to-left data-[state=open]:s-slide-in-from-left", "s-border-r dark:s-border-border-night s-border-border" ), right: cn( "s-inset-y-0 s-right-0 data-[state=closed]:s-slide-out-to-right data-[state=open]:s-slide-in-from-right", "s-border-l dark:s-border-border-night s-border-border" ), }, size: sizeClasses, }, defaultVariants: { side: "right", size: "md", }, } ); interface SheetContentProps extends React.ComponentPropsWithoutRef< typeof SheetPrimitive.Content > { size?: SheetSizeType; trapFocusScope?: boolean; side?: SheetSideType; preventAutoFocusOnClose?: boolean; preventAutoFocusOnOpen?: boolean; } const SheetContent = React.forwardRef< React.ElementRef, SheetContentProps >( ( { className, children, size, side, trapFocusScope, preventAutoFocusOnClose = true, preventAutoFocusOnOpen = true, onCloseAutoFocus, onOpenAutoFocus, ...props }, ref ) => { const handleCloseAutoFocus = React.useCallback( (event: Event) => { if (preventAutoFocusOnClose) { event.preventDefault(); } onCloseAutoFocus?.(event); }, [preventAutoFocusOnClose, onCloseAutoFocus] ); const handleOpenAutoFocus = React.useCallback( (event: Event) => { if (preventAutoFocusOnOpen) { event.preventDefault(); } onOpenAutoFocus?.(event); }, [preventAutoFocusOnOpen, onOpenAutoFocus] ); const onKeyDownCapture = React.useCallback( (e: React.KeyboardEvent) => { if ((e.metaKey || e.ctrlKey) && e.key === "Enter") { const root = e.currentTarget as HTMLElement; const target = root.querySelector( '[data-sheet-save="true"]:not(:disabled)' ); if (target) { e.preventDefault(); target.click(); } } }, [] ); return ( {children} ); } ); SheetContent.displayName = SheetPrimitive.Content.displayName; interface SheetHeaderProps extends React.HTMLAttributes { hideButton?: boolean; } const SheetHeader = ({ className, children, hideButton = false, ...props }: SheetHeaderProps) => (
{children} {!hideButton &&
); SheetHeader.displayName = "SheetHeader"; interface SheetContainerProps extends React.HTMLAttributes { noScroll?: boolean; } const ScrollContainer = ({ noScroll, className, children, }: { noScroll?: boolean; className?: string; children: React.ReactNode; }) => { if (noScroll) { return
{children}
; } return {children}; }; const SheetContainer = ({ children, noScroll, className, }: SheetContainerProps) => { return (
{children}
); }; SheetContainer.displayName = "SheetContainer"; interface SheetFooterProps extends React.HTMLAttributes { leftButtonProps?: React.ComponentProps; rightButtonProps?: React.ComponentProps; rightEndButtonProps?: React.ComponentProps; sheetCloseClassName?: string; } const SheetFooter = ({ className, children, leftButtonProps, rightButtonProps, rightEndButtonProps, sheetCloseClassName, ...props }: SheetFooterProps) => { return (
{children}
{leftButtonProps && (leftButtonProps.disabled ? (
); }; SheetFooter.displayName = "SheetFooter"; interface SheetTitleProps extends React.ComponentPropsWithoutRef< typeof SheetPrimitive.Title > { icon?: React.ComponentType; } const SheetTitle = React.forwardRef< React.ElementRef, SheetTitleProps >(({ className, icon, ...props }, ref) => ( <> {icon && } )); SheetTitle.displayName = SheetPrimitive.Title.displayName; const SheetDescription = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( )); SheetDescription.displayName = SheetPrimitive.Description.displayName; export { Sheet, SheetClose, SheetContainer, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, };