UNPKG

@rc-component/drawer

Version:
333 lines (316 loc) 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _classnames = _interopRequireDefault(require("classnames")); var _motion = _interopRequireDefault(require("@rc-component/motion")); var _KeyCode = _interopRequireDefault(require("@rc-component/util/lib/KeyCode")); var _pickAttrs = _interopRequireDefault(require("@rc-component/util/lib/pickAttrs")); var React = _interopRequireWildcard(require("react")); var _context = _interopRequireDefault(require("./context")); var _DrawerPanel = _interopRequireDefault(require("./DrawerPanel")); var _useDrag = _interopRequireDefault(require("./hooks/useDrag")); var _util = require("./util"); var _util2 = require("@rc-component/util"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } const sentinelStyle = { width: 0, height: 0, overflow: 'hidden', outline: 'none', position: 'absolute' }; const DrawerPopup = (props, ref) => { const { prefixCls, open, placement, inline, push, forceRender, autoFocus, keyboard, // classNames classNames: drawerClassNames, // Root rootClassName, rootStyle, zIndex, // Drawer className, id, style, motion, width, height, size, maxSize, children, // Mask mask, maskClosable, maskMotion, maskClassName, maskStyle, // Events afterOpenChange, onClose, onMouseEnter, onMouseOver, onMouseLeave, onClick, onKeyDown, onKeyUp, styles, drawerRender, resizable, defaultSize } = props; // ================================ Refs ================================ const panelRef = React.useRef(null); const sentinelStartRef = React.useRef(null); const sentinelEndRef = React.useRef(null); React.useImperativeHandle(ref, () => panelRef.current); const onPanelKeyDown = event => { const { keyCode, shiftKey } = event; switch (keyCode) { // Tab active case _KeyCode.default.TAB: { if (keyCode === _KeyCode.default.TAB) { if (!shiftKey && document.activeElement === sentinelEndRef.current) { sentinelStartRef.current?.focus({ preventScroll: true }); } else if (shiftKey && document.activeElement === sentinelStartRef.current) { sentinelEndRef.current?.focus({ preventScroll: true }); } } break; } // Close case _KeyCode.default.ESC: { if (onClose && keyboard) { event.stopPropagation(); onClose(event); } break; } } }; // ========================== Control =========================== // Auto Focus React.useEffect(() => { if (open && autoFocus) { panelRef.current?.focus({ preventScroll: true }); } }, [open]); // ============================ Push ============================ const [pushed, setPushed] = React.useState(false); const parentContext = React.useContext(_context.default); // Merge push distance let pushConfig; if (typeof push === 'boolean') { pushConfig = push ? {} : { distance: 0 }; } else { pushConfig = push || {}; } const pushDistance = pushConfig?.distance ?? parentContext?.pushDistance ?? 180; const mergedContext = React.useMemo(() => ({ pushDistance, push: () => { setPushed(true); }, pull: () => { setPushed(false); } }), [pushDistance]); // ========================= ScrollLock ========================= // Tell parent to push React.useEffect(() => { if (open) { parentContext?.push?.(); } else { parentContext?.pull?.(); } }, [open]); // Clean up React.useEffect(() => () => { parentContext?.pull?.(); }, []); // ============================ Mask ============================ const maskNode = /*#__PURE__*/React.createElement(_motion.default, _extends({ key: "mask" }, maskMotion, { visible: mask && open }), ({ className: motionMaskClassName, style: motionMaskStyle }, maskRef) => /*#__PURE__*/React.createElement("div", { className: (0, _classnames.default)(`${prefixCls}-mask`, motionMaskClassName, drawerClassNames?.mask, maskClassName), style: { ...motionMaskStyle, ...maskStyle, ...styles?.mask }, onClick: maskClosable && open ? onClose : undefined, ref: maskRef })); // =========================== Panel ============================ const motionProps = typeof motion === 'function' ? motion(placement) : motion; // ============================ Size ============================ const [currentSize, setCurrentSize] = React.useState(); const isHorizontal = placement === 'left' || placement === 'right'; // Aggregate size logic with backward compatibility using useMemo const mergedSize = React.useMemo(() => { const legacySize = isHorizontal ? width : height; const nextMergedSize = size ?? legacySize ?? currentSize ?? defaultSize ?? (isHorizontal ? 378 : undefined); return (0, _util.parseWidthHeight)(nextMergedSize); }, [size, width, height, defaultSize, isHorizontal, currentSize]); // >>> Style const wrapperStyle = React.useMemo(() => { const nextWrapperStyle = {}; if (pushed && pushDistance) { switch (placement) { case 'top': nextWrapperStyle.transform = `translateY(${pushDistance}px)`; break; case 'bottom': nextWrapperStyle.transform = `translateY(${-pushDistance}px)`; break; case 'left': nextWrapperStyle.transform = `translateX(${pushDistance}px)`; break; default: nextWrapperStyle.transform = `translateX(${-pushDistance}px)`; break; } } if (isHorizontal) { nextWrapperStyle.width = (0, _util.parseWidthHeight)(mergedSize); } else { nextWrapperStyle.height = (0, _util.parseWidthHeight)(mergedSize); } return nextWrapperStyle; }, [pushed, pushDistance, placement, isHorizontal, mergedSize]); // =========================== Resize =========================== const wrapperRef = React.useRef(null); const onInternalResize = (0, _util2.useEvent)(size => { setCurrentSize(size); resizable?.onResize?.(size); }); const { dragElementProps, isDragging } = (0, _useDrag.default)({ prefixCls: `${prefixCls}-resizable`, direction: placement, className: drawerClassNames?.dragger, style: styles?.dragger, maxSize, containerRef: wrapperRef, currentSize: mergedSize, onResize: onInternalResize, onResizeStart: resizable?.onResizeStart, onResizeEnd: resizable?.onResizeEnd }); // =========================== Events =========================== const eventHandlers = { onMouseEnter, onMouseOver, onMouseLeave, onClick, onKeyDown, onKeyUp }; // =========================== Render ========================== // >>>>> Panel const panelNode = /*#__PURE__*/React.createElement(_motion.default, _extends({ key: "panel" }, motionProps, { visible: open, forceRender: forceRender, onVisibleChanged: nextVisible => { afterOpenChange?.(nextVisible); }, removeOnLeave: false, leavedClassName: `${prefixCls}-content-wrapper-hidden` }), ({ className: motionClassName, style: motionStyle }, motionRef) => { const content = /*#__PURE__*/React.createElement(_DrawerPanel.default, _extends({ id: id, containerRef: motionRef, prefixCls: prefixCls, className: (0, _classnames.default)(className, drawerClassNames?.section), style: { ...style, ...styles?.section } }, (0, _pickAttrs.default)(props, { aria: true }), eventHandlers), children); return /*#__PURE__*/React.createElement("div", _extends({ ref: wrapperRef, className: (0, _classnames.default)(`${prefixCls}-content-wrapper`, isDragging && `${prefixCls}-content-wrapper-dragging`, drawerClassNames?.wrapper, !isDragging && motionClassName), style: { ...motionStyle, ...wrapperStyle, ...styles?.wrapper } }, (0, _pickAttrs.default)(props, { data: true })), resizable && /*#__PURE__*/React.createElement("div", dragElementProps), drawerRender ? drawerRender(content) : content); }); // >>>>> Container const containerStyle = { ...rootStyle }; if (zIndex) { containerStyle.zIndex = zIndex; } return /*#__PURE__*/React.createElement(_context.default.Provider, { value: mergedContext }, /*#__PURE__*/React.createElement("div", { className: (0, _classnames.default)(prefixCls, `${prefixCls}-${placement}`, rootClassName, { [`${prefixCls}-open`]: open, [`${prefixCls}-inline`]: inline }), style: containerStyle, tabIndex: -1, ref: panelRef, onKeyDown: onPanelKeyDown }, maskNode, /*#__PURE__*/React.createElement("div", { tabIndex: 0, ref: sentinelStartRef, style: sentinelStyle, "aria-hidden": "true", "data-sentinel": "start" }), panelNode, /*#__PURE__*/React.createElement("div", { tabIndex: 0, ref: sentinelEndRef, style: sentinelStyle, "aria-hidden": "true", "data-sentinel": "end" }))); }; const RefDrawerPopup = /*#__PURE__*/React.forwardRef(DrawerPopup); if (process.env.NODE_ENV !== 'production') { RefDrawerPopup.displayName = 'DrawerPopup'; } var _default = exports.default = RefDrawerPopup;