import { sidePanel, type SidePanelVariantProps } from "@seed-design/css/recipes/side-panel"; import { Drawer } from "@seed-design/react-drawer"; import { Primitive, type PrimitiveProps } from "@seed-design/react-primitive"; import { composeRefs } from "@radix-ui/react-compose-refs"; import { dataAttr } from "@seed-design/dom-utils"; import clsx from "clsx"; import * as React from "react"; import { createRenderTrackingContext } from "../../utils/createRenderTrackingContext"; import { createSlotRecipeContext } from "../../utils/createSlotRecipeContext"; import { useStyleProps, withStyleProps, type StyleProps } from "../../utils/styled"; const { withContext, useClassNames, ClassNamesProvider } = createSlotRecipeContext(sidePanel); const closeButtonTracker = createRenderTrackingContext("SidePanelCloseButton"); //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelRootProps extends SidePanelVariantProps, Pick< Drawer.RootProps, | "children" | "open" | "defaultOpen" | "onOpenChange" | "modal" | "dismissible" | "closeOnEscape" | "closeOnInteractOutside" | "lazyMount" | "unmountOnExit" | "onAnimationEnd" > { /** Direction the side panel slides in from. @default "right" */ direction?: "left" | "right"; } export function SidePanelRoot(props: SidePanelRootProps) { const [variantProps, otherProps] = sidePanel.splitVariantProps({ direction: "right" as const, lazyMount: true, unmountOnExit: true, ...props, }); const classNames = sidePanel(variantProps); return ( ); } //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelTriggerProps extends Drawer.TriggerProps {} export const SidePanelTrigger = Drawer.Trigger; //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelPositionerProps extends Drawer.PositionerProps {} export const SidePanelPositioner = withContext( Drawer.Positioner, "positioner", ); //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelBackdropProps extends Drawer.BackdropProps {} export const SidePanelBackdrop = withContext( Drawer.Backdrop, "backdrop", ); //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelContentProps extends Drawer.ContentProps, Pick {} export const SidePanelContent = withContext( withStyleProps(Drawer.Content), "content", ); //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelHeaderProps extends Drawer.HeaderProps {} export const SidePanelHeader = React.forwardRef( ({ className, ...props }, ref) => { const classNames = useClassNames(); const { isRendered } = closeButtonTracker.useRenderTracking(); return ( ); }, ); SidePanelHeader.displayName = "SidePanelHeader"; //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelTitleProps extends Drawer.TitleProps {} export const SidePanelTitle = withContext( Drawer.Title, "title", ); SidePanelTitle.displayName = "SidePanelTitle"; //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelDescriptionProps extends Drawer.DescriptionProps {} export const SidePanelDescription = withContext( Drawer.Description, "description", ); SidePanelDescription.displayName = "SidePanelDescription"; //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelBodyProps extends PrimitiveProps, Pick< StyleProps, "paddingX" | "height" | "maxHeight" | "minHeight" | "justifyContent" | "alignItems" >, React.HTMLAttributes {} export const SidePanelBody = React.forwardRef( (props, forwardedRef) => { const classNames = useClassNames(); const { style, restProps } = useStyleProps(props); const { className, ...otherProps } = restProps; const ref = React.useRef(null); const [scrolled, setScrolled] = React.useState(false); React.useEffect(() => { const element = ref.current; if (!element) return; const check = () => setScrolled(element.scrollTop > 0); check(); element.addEventListener("scroll", check); const observer = new ResizeObserver(check); observer.observe(element); return () => { element.removeEventListener("scroll", check); observer.disconnect(); }; }, []); return ( ); }, ); SidePanelBody.displayName = "SidePanelBody"; //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelFooterProps extends PrimitiveProps, React.HTMLAttributes {} export const SidePanelFooter = withContext( Primitive.div, "footer", ); //////////////////////////////////////////////////////////////////////////////////// export interface SidePanelCloseButtonProps extends Drawer.CloseButtonProps {} export const SidePanelCloseButton = React.forwardRef( ({ className, ...props }, ref) => { const classNames = useClassNames(); const { trackRef } = closeButtonTracker.useRenderTracking(); return ( ); }, ); SidePanelCloseButton.displayName = "SidePanelCloseButton";