@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
152 lines (151 loc) • 5.86 kB
JavaScript
"use client";
import { DEFAULT_CONTAINER_MAX_WIDTH } from "./constants.mjs";
import { styles } from "./style.mjs";
import { DrawerBackdrop, DrawerContent, DrawerFooter, DrawerHeader, DrawerPopup, DrawerPortal, DrawerRoot, DrawerTitle } from "./atoms.mjs";
import { DrawerPushProvider, useDrawerPush } from "./DrawerPushContext.mjs";
import { memo, useCallback, useMemo } from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
import { cx } from "antd-style";
import { X } from "lucide-react";
//#region src/base-ui/Drawer/Drawer.tsx
const resolvePushDistance = (push) => {
if (push === false) return 0;
if (push === true) return 180;
return push.distance ?? 180;
};
const FULL_SIZES = /* @__PURE__ */ new Set([
"100%",
"100dvh",
"100dvw",
"100vh",
"100vw"
]);
const Drawer = memo(({ open, placement = "right", width, height, mask = true, maskClosable = true, keyboard = true, closable = true, closeIcon, extra, title, footer, noHeader, sidebar, sidebarWidth = 280, containerMaxWidth = DEFAULT_CONTAINER_MAX_WIDTH, push = true, zIndex, getContainer, className, classNames, style, styles: semanticStyles, afterOpenChange, onClose, children }) => {
const isOpen = open ?? false;
const { childValue, pushed } = useDrawerPush(isOpen);
const pushOffset = pushed ? resolvePushDistance(push) : 0;
const handleOpenChange = useCallback((nextOpen, eventDetails) => {
if (nextOpen || !isOpen) return;
if (!keyboard && eventDetails.reason === "escape-key") return;
if (!maskClosable && eventDetails.reason === "outside-press") return;
onClose?.();
}, [
isOpen,
keyboard,
maskClosable,
onClose
]);
const handleExitComplete = useCallback(() => afterOpenChange?.(false), [afterOpenChange]);
const handleAnimationComplete = useCallback(() => {
if (isOpen) afterOpenChange?.(true);
}, [isOpen, afterOpenChange]);
const isHorizontal = placement === "left" || placement === "right";
const resolvedWidth = isHorizontal ? width ?? 378 : width;
const resolvedHeight = isHorizontal ? height : height ?? 378;
const isFlush = FULL_SIZES.has(String(isHorizontal ? resolvedWidth : resolvedHeight));
const surfaceWeightClass = (() => {
if (isFlush) return void 0;
if (pushed) return styles.panelRecessed;
return mask ? void 0 : styles.panelBoosted;
})();
const showTitle = title !== void 0 && title !== null;
const showHeader = !noHeader && (showTitle || closable || !!extra);
const hasSidebar = !!sidebar;
const containerStyle = useMemo(() => ({ maxWidth: containerMaxWidth }), [containerMaxWidth]);
const closeNode = closable && /* @__PURE__ */ jsx("button", {
"aria-label": "Close",
className: cx(styles.close, classNames?.close),
style: semanticStyles?.close,
type: "button",
onClick: onClose,
children: closeIcon ?? /* @__PURE__ */ jsx(X, { size: 16 })
});
const extraNode = (extra || closeNode) && /* @__PURE__ */ jsxs("div", {
className: cx(styles.extra, !showHeader && styles.extraFloating, classNames?.extra),
style: semanticStyles?.extra,
children: [extra, closeNode]
});
const bodyNode = hasSidebar ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
className: cx(styles.sidebar, classNames?.sidebar),
style: {
width: sidebarWidth,
...semanticStyles?.sidebar
},
children: sidebar
}), /* @__PURE__ */ jsx("div", {
className: cx(styles.sidebarContent, classNames?.sidebarContent),
style: semanticStyles?.sidebarContent,
children
})] }) : children;
return /* @__PURE__ */ jsx(DrawerRoot, {
modal: mask,
open: isOpen,
zIndex,
onExitComplete: handleExitComplete,
onOpenChange: handleOpenChange,
children: /* @__PURE__ */ jsxs(DrawerPortal, {
container: getContainer === false ? void 0 : getContainer ?? void 0,
children: [mask && /* @__PURE__ */ jsx(DrawerBackdrop, {
className: classNames?.backdrop,
style: semanticStyles?.backdrop
}), /* @__PURE__ */ jsx(DrawerPopup, {
className: classNames?.popup,
flush: isFlush,
height: resolvedHeight,
motionProps: { onAnimationComplete: handleAnimationComplete },
panelClassName: cx(surfaceWeightClass, className, classNames?.panel),
panelStyle: {
...style,
...semanticStyles?.panel
},
placement,
popupStyle: semanticStyles?.popup,
pushOffset,
width: resolvedWidth,
children: /* @__PURE__ */ jsxs(DrawerPushProvider, {
value: childValue,
children: [
showHeader ? /* @__PURE__ */ jsx(DrawerHeader, {
className: classNames?.header,
style: semanticStyles?.header,
children: /* @__PURE__ */ jsxs("div", {
className: styles.containerInner,
style: containerStyle,
children: [showTitle ? /* @__PURE__ */ jsx(DrawerTitle, {
className: classNames?.title,
style: semanticStyles?.title,
children: title
}) : /* @__PURE__ */ jsx("span", {}), extraNode]
})
}) : extraNode,
/* @__PURE__ */ jsx(DrawerContent, {
className: cx(hasSidebar && styles.contentSidebar, classNames?.content),
style: semanticStyles?.content,
children: /* @__PURE__ */ jsx("div", {
style: {
...containerStyle,
...semanticStyles?.bodyContent
},
className: cx(styles.bodyContent, hasSidebar && styles.bodyContentSidebar, classNames?.bodyContent),
children: bodyNode
})
}),
footer && /* @__PURE__ */ jsx(DrawerFooter, {
className: classNames?.footer,
style: semanticStyles?.footer,
children: /* @__PURE__ */ jsx("div", {
className: cx(styles.containerInner, styles.containerInnerFooter),
style: containerStyle,
children: footer
})
})
]
})
})]
})
});
});
Drawer.displayName = "Drawer";
//#endregion
export { Drawer as default };
//# sourceMappingURL=Drawer.mjs.map