UNPKG

@rc-component/drawer

Version:
108 lines (102 loc) 3.01 kB
import Portal from '@rc-component/portal'; import useLayoutEffect from "@rc-component/util/es/hooks/useLayoutEffect"; import * as React from 'react'; import { RefContext } from "./context"; import DrawerPopup from "./DrawerPopup"; import { warnCheck } from "./util"; const Drawer = props => { const { open = false, prefixCls = 'rc-drawer', placement = 'right', autoFocus = true, keyboard = true, width = 378, mask = true, maskClosable = true, getContainer, forceRender, afterOpenChange, destroyOnClose, onMouseEnter, onMouseOver, onMouseLeave, onClick, onKeyDown, onKeyUp, // Refs panelRef } = props; const [animatedVisible, setAnimatedVisible] = React.useState(false); // ============================= Warn ============================= if (process.env.NODE_ENV !== 'production') { warnCheck(props); } // ============================= Open ============================= const [mounted, setMounted] = React.useState(false); useLayoutEffect(() => { setMounted(true); }, []); const mergedOpen = mounted ? open : false; // ============================ Focus ============================= const popupRef = React.useRef(null); const lastActiveRef = React.useRef(null); useLayoutEffect(() => { if (mergedOpen) { lastActiveRef.current = document.activeElement; } }, [mergedOpen]); // ============================= Open ============================= const internalAfterOpenChange = nextVisible => { setAnimatedVisible(nextVisible); afterOpenChange?.(nextVisible); if (!nextVisible && lastActiveRef.current && !popupRef.current?.contains(lastActiveRef.current)) { lastActiveRef.current?.focus({ preventScroll: true }); } }; // =========================== Context ============================ const refContext = React.useMemo(() => ({ panel: panelRef }), [panelRef]); // ============================ Render ============================ if (!forceRender && !animatedVisible && !mergedOpen && destroyOnClose) { return null; } const eventHandlers = { onMouseEnter, onMouseOver, onMouseLeave, onClick, onKeyDown, onKeyUp }; const drawerPopupProps = { ...props, open: mergedOpen, prefixCls, placement, autoFocus, keyboard, width, mask, maskClosable, inline: getContainer === false, afterOpenChange: internalAfterOpenChange, ref: popupRef, ...eventHandlers }; return /*#__PURE__*/React.createElement(RefContext.Provider, { value: refContext }, /*#__PURE__*/React.createElement(Portal, { open: mergedOpen || forceRender || animatedVisible, autoDestroy: false, getContainer: getContainer, autoLock: mask && (mergedOpen || animatedVisible) }, /*#__PURE__*/React.createElement(DrawerPopup, drawerPopupProps))); }; if (process.env.NODE_ENV !== 'production') { Drawer.displayName = 'Drawer'; } export default Drawer;