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";