UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

262 lines (261 loc) 8.84 kB
"use client"; import { useMotionComponent } from "../../MotionProvider/index.mjs"; import { useNativeButton } from "../../hooks/useNativeButton.mjs"; import { useAppElement } from "../../ThemeProvider/AppElementContext.mjs"; import { useLayerZIndex } from "../zIndex/useLayerZIndex.mjs"; import { drawerBackdropTransition, getDrawerMotionConfig, pushAxis } from "./constants.mjs"; import { DrawerLayerProvider, useDrawerLayer } from "./DrawerLayerContext.mjs"; import { styles } from "./style.mjs"; import { cloneElement, createContext, createElement, isValidElement, use, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { jsx } from "react/jsx-runtime"; import { cx } from "antd-style"; import { AnimatePresence } from "motion/react"; import { mergeProps } from "@base-ui/react/merge-props"; import { mergeRefs, useMergeRefs } from "react-merge-refs"; import { X } from "lucide-react"; import { Dialog } from "@base-ui/react/dialog"; //#region src/base-ui/Drawer/atoms.tsx const mergeStateClassName = (base, className) => { if (typeof className === "function") return (state) => cx(base, className(state)); return cx(base, className); }; const popupPlacementClass = { bottom: styles.popupBottom, left: styles.popupLeft, right: styles.popupRight, top: styles.popupTop }; const panelPlacementClass = { bottom: styles.panelBottom, left: styles.panelLeft, right: styles.panelRight, top: styles.panelTop }; const panelRoundedClass = { bottom: styles.panelRoundedBottom, left: styles.panelRoundedLeft, right: styles.panelRoundedRight, top: styles.panelRoundedTop }; const DrawerOpenContext = createContext(null); const DrawerActionsContext = createContext(null); const useDrawerOpen = () => use(DrawerOpenContext); const useDrawerActions = () => use(DrawerActionsContext); const AnimatedDrawerRoot = ({ open, children, onExitComplete: onExitCompleteProp, zIndex: explicitZIndex, ...rest }) => { const [isPresent, setIsPresent] = useState(!!open); useEffect(() => { if (open) setIsPresent(true); }, [open]); const handleExitComplete = useCallback(() => { setIsPresent(false); onExitCompleteProp?.(); }, [onExitCompleteProp]); const actions = useMemo(() => ({ onExitComplete: handleExitComplete }), [handleExitComplete]); const { zIndex, ref: popupRef } = useLayerZIndex("modal", explicitZIndex); const layer = useMemo(() => ({ popupRef, zIndex }), [zIndex, popupRef]); if (!isPresent) return null; return /* @__PURE__ */ jsx(DrawerOpenContext, { value: open, children: /* @__PURE__ */ jsx(DrawerActionsContext, { value: actions, children: /* @__PURE__ */ jsx(DrawerLayerProvider, { value: layer, children: /* @__PURE__ */ jsx(Dialog.Root, { modal: true, open: true, ...rest, children }) }) }) }); }; const NonAnimatedDrawerRoot = ({ zIndex: explicitZIndex, children, ...rest }) => { const { zIndex, ref: popupRef } = useLayerZIndex("modal", explicitZIndex); const layer = useMemo(() => ({ popupRef, zIndex }), [zIndex, popupRef]); return /* @__PURE__ */ jsx(DrawerLayerProvider, { value: layer, children: /* @__PURE__ */ jsx(Dialog.Root, { modal: true, ...rest, children }) }); }; const DrawerRoot = ({ open, onExitComplete, ...rest }) => { if (open !== void 0) return /* @__PURE__ */ jsx(AnimatedDrawerRoot, { open, onExitComplete, ...rest }); return /* @__PURE__ */ jsx(NonAnimatedDrawerRoot, { ...rest }); }; const DrawerPortal = ({ container, ...rest }) => { const appElement = useAppElement(); return /* @__PURE__ */ jsx(Dialog.Portal, { container: container ?? appElement ?? void 0, ...rest }); }; const DrawerBackdrop = ({ className, style, ...rest }) => { const open = useDrawerOpen(); const layer = useDrawerLayer(); const Motion = useMotionComponent(); const layerStyle = layer?.zIndex !== void 0 ? { zIndex: layer.zIndex } : void 0; if (open !== null) return /* @__PURE__ */ jsx(Dialog.Backdrop, { ...rest, className: cx(styles.backdrop, className), style: { ...layerStyle, ...style, transition: "none" }, render: /* @__PURE__ */ jsx(Motion.div, { animate: { opacity: open ? 1 : 0 }, initial: { opacity: 0 }, transition: drawerBackdropTransition }) }); return /* @__PURE__ */ jsx(Dialog.Backdrop, { ...rest, className: mergeStateClassName(styles.backdrop, className), style: { ...layerStyle, ...style } }); }; const DrawerPopup = ({ className, children, placement: placementProp = "right", width: widthProp, height: heightProp, flush, pushOffset = 0, motionProps, panelClassName, panelStyle, popupStyle, ref: forwardedRef, ...rest }) => { const open = useDrawerOpen(); const actions = useDrawerActions(); const layer = useDrawerLayer(); const Motion = useMotionComponent(); const composedRef = useMergeRefs([forwardedRef, layer?.popupRef]); const openGeometryRef = useRef({ height: heightProp, placement: placementProp, width: widthProp }); if (open !== false) openGeometryRef.current = { height: heightProp, placement: placementProp, width: widthProp }; const { height, placement, width } = openGeometryRef.current; const sizeStyle = placement === "left" || placement === "right" ? { width } : { height }; const resolvedPopupStyle = { ...layer?.zIndex === void 0 ? void 0 : { zIndex: layer.zIndex + 1 }, ...sizeStyle, ...popupStyle }; const popupBaseClassName = cx(styles.popup, popupPlacementClass[placement]); const resolvedPanelClassName = cx(styles.panel, panelPlacementClass[placement], flush ? styles.panelFlush : panelRoundedClass[placement], panelClassName); if (open !== null && actions) { const motionConfig = getDrawerMotionConfig(placement, pushOffset); return /* @__PURE__ */ jsx(Dialog.Popup, { ...rest, className: cx(popupBaseClassName, className), "data-drawer-anchor": placement, ref: composedRef, style: resolvedPopupStyle, children: /* @__PURE__ */ jsx(AnimatePresence, { onExitComplete: actions.onExitComplete, children: open ? /* @__PURE__ */ createElement(Motion.div, { ...motionConfig, ...motionProps, className: resolvedPanelClassName, "data-drawer-placement": placement, key: "drawer-popup-panel", style: { transition: "none", ...panelStyle } }, children) : null }) }); } const { axis, sign } = pushAxis[placement]; const pushVars = { [axis === "x" ? "--drawer-push-x" : "--drawer-push-y"]: `${pushOffset * sign}px` }; return /* @__PURE__ */ jsx(Dialog.Popup, { ...rest, className: mergeStateClassName(popupBaseClassName, className), "data-drawer-anchor": placement, ref: composedRef, style: resolvedPopupStyle, children: /* @__PURE__ */ jsx("div", { className: resolvedPanelClassName, "data-drawer-placement": placement, style: { ...pushVars, ...panelStyle }, children }) }); }; const DrawerHeader = ({ className, ...rest }) => /* @__PURE__ */ jsx("div", { ...rest, className: cx(styles.header, className) }); const DrawerTitle = ({ className, ...rest }) => /* @__PURE__ */ jsx(Dialog.Title, { ...rest, className: mergeStateClassName(styles.title, className) }); const DrawerDescription = Dialog.Description; const DrawerContent = ({ className, ...rest }) => /* @__PURE__ */ jsx("div", { ...rest, className: cx(styles.content, className) }); const DrawerFooter = ({ className, ...rest }) => /* @__PURE__ */ jsx("div", { ...rest, className: cx(styles.footer, className) }); const DrawerClose = ({ className, children, ...rest }) => /* @__PURE__ */ jsx(Dialog.Close, { ...rest, className: mergeStateClassName(styles.close, className), children: children ?? /* @__PURE__ */ jsx(X, { size: 16 }) }); const DrawerTrigger = ({ children, className, nativeButton, ref: refProp, ...rest }) => { const { isNativeButtonTriggerElement, resolvedNativeButton } = useNativeButton({ children, nativeButton }); const renderer = (props) => { const resolvedProps = (() => { if (isNativeButtonTriggerElement) return props; const { type, ...restProps } = props; return restProps; })(); const mergedProps = mergeProps(children.props, resolvedProps); return cloneElement(children, { ...mergedProps, ref: mergeRefs([ children.ref, props.ref, refProp ]) }); }; if (isValidElement(children)) return /* @__PURE__ */ jsx(Dialog.Trigger, { ...rest, className, nativeButton: resolvedNativeButton, render: renderer }); return /* @__PURE__ */ jsx(Dialog.Trigger, { ...rest, className, nativeButton: resolvedNativeButton, ref: refProp, children }); }; //#endregion export { DrawerBackdrop, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPopup, DrawerPortal, DrawerRoot, DrawerTitle, DrawerTrigger, useDrawerActions, useDrawerOpen }; //# sourceMappingURL=atoms.mjs.map