DrawerPopup.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  2. import _extends from "@babel/runtime/helpers/esm/extends";
  3. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  4. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  5. import classNames from 'classnames';
  6. import CSSMotion from 'rc-motion';
  7. import KeyCode from "rc-util/es/KeyCode";
  8. import pickAttrs from "rc-util/es/pickAttrs";
  9. import * as React from 'react';
  10. import DrawerContext from "./context";
  11. import DrawerPanel from "./DrawerPanel";
  12. import { parseWidthHeight } from "./util";
  13. var sentinelStyle = {
  14. width: 0,
  15. height: 0,
  16. overflow: 'hidden',
  17. outline: 'none',
  18. position: 'absolute'
  19. };
  20. function DrawerPopup(props, ref) {
  21. var _ref, _pushConfig$distance, _pushConfig;
  22. var prefixCls = props.prefixCls,
  23. open = props.open,
  24. placement = props.placement,
  25. inline = props.inline,
  26. push = props.push,
  27. forceRender = props.forceRender,
  28. autoFocus = props.autoFocus,
  29. keyboard = props.keyboard,
  30. drawerClassNames = props.classNames,
  31. rootClassName = props.rootClassName,
  32. rootStyle = props.rootStyle,
  33. zIndex = props.zIndex,
  34. className = props.className,
  35. id = props.id,
  36. style = props.style,
  37. motion = props.motion,
  38. width = props.width,
  39. height = props.height,
  40. children = props.children,
  41. mask = props.mask,
  42. maskClosable = props.maskClosable,
  43. maskMotion = props.maskMotion,
  44. maskClassName = props.maskClassName,
  45. maskStyle = props.maskStyle,
  46. afterOpenChange = props.afterOpenChange,
  47. onClose = props.onClose,
  48. onMouseEnter = props.onMouseEnter,
  49. onMouseOver = props.onMouseOver,
  50. onMouseLeave = props.onMouseLeave,
  51. onClick = props.onClick,
  52. onKeyDown = props.onKeyDown,
  53. onKeyUp = props.onKeyUp,
  54. styles = props.styles,
  55. drawerRender = props.drawerRender;
  56. // ================================ Refs ================================
  57. var panelRef = React.useRef();
  58. var sentinelStartRef = React.useRef();
  59. var sentinelEndRef = React.useRef();
  60. React.useImperativeHandle(ref, function () {
  61. return panelRef.current;
  62. });
  63. var onPanelKeyDown = function onPanelKeyDown(event) {
  64. var keyCode = event.keyCode,
  65. shiftKey = event.shiftKey;
  66. switch (keyCode) {
  67. // Tab active
  68. case KeyCode.TAB:
  69. {
  70. if (keyCode === KeyCode.TAB) {
  71. if (!shiftKey && document.activeElement === sentinelEndRef.current) {
  72. var _sentinelStartRef$cur;
  73. (_sentinelStartRef$cur = sentinelStartRef.current) === null || _sentinelStartRef$cur === void 0 || _sentinelStartRef$cur.focus({
  74. preventScroll: true
  75. });
  76. } else if (shiftKey && document.activeElement === sentinelStartRef.current) {
  77. var _sentinelEndRef$curre;
  78. (_sentinelEndRef$curre = sentinelEndRef.current) === null || _sentinelEndRef$curre === void 0 || _sentinelEndRef$curre.focus({
  79. preventScroll: true
  80. });
  81. }
  82. }
  83. break;
  84. }
  85. // Close
  86. case KeyCode.ESC:
  87. {
  88. if (onClose && keyboard) {
  89. event.stopPropagation();
  90. onClose(event);
  91. }
  92. break;
  93. }
  94. }
  95. };
  96. // ========================== Control ===========================
  97. // Auto Focus
  98. React.useEffect(function () {
  99. if (open && autoFocus) {
  100. var _panelRef$current;
  101. (_panelRef$current = panelRef.current) === null || _panelRef$current === void 0 || _panelRef$current.focus({
  102. preventScroll: true
  103. });
  104. }
  105. }, [open]);
  106. // ============================ Push ============================
  107. var _React$useState = React.useState(false),
  108. _React$useState2 = _slicedToArray(_React$useState, 2),
  109. pushed = _React$useState2[0],
  110. setPushed = _React$useState2[1];
  111. var parentContext = React.useContext(DrawerContext);
  112. // Merge push distance
  113. var pushConfig;
  114. if (typeof push === 'boolean') {
  115. pushConfig = push ? {} : {
  116. distance: 0
  117. };
  118. } else {
  119. pushConfig = push || {};
  120. }
  121. var pushDistance = (_ref = (_pushConfig$distance = (_pushConfig = pushConfig) === null || _pushConfig === void 0 ? void 0 : _pushConfig.distance) !== null && _pushConfig$distance !== void 0 ? _pushConfig$distance : parentContext === null || parentContext === void 0 ? void 0 : parentContext.pushDistance) !== null && _ref !== void 0 ? _ref : 180;
  122. var mergedContext = React.useMemo(function () {
  123. return {
  124. pushDistance: pushDistance,
  125. push: function push() {
  126. setPushed(true);
  127. },
  128. pull: function pull() {
  129. setPushed(false);
  130. }
  131. };
  132. }, [pushDistance]);
  133. // ========================= ScrollLock =========================
  134. // Tell parent to push
  135. React.useEffect(function () {
  136. if (open) {
  137. var _parentContext$push;
  138. parentContext === null || parentContext === void 0 || (_parentContext$push = parentContext.push) === null || _parentContext$push === void 0 || _parentContext$push.call(parentContext);
  139. } else {
  140. var _parentContext$pull;
  141. parentContext === null || parentContext === void 0 || (_parentContext$pull = parentContext.pull) === null || _parentContext$pull === void 0 || _parentContext$pull.call(parentContext);
  142. }
  143. }, [open]);
  144. // Clean up
  145. React.useEffect(function () {
  146. return function () {
  147. var _parentContext$pull2;
  148. parentContext === null || parentContext === void 0 || (_parentContext$pull2 = parentContext.pull) === null || _parentContext$pull2 === void 0 || _parentContext$pull2.call(parentContext);
  149. };
  150. }, []);
  151. // ============================ Mask ============================
  152. var maskNode = /*#__PURE__*/React.createElement(CSSMotion, _extends({
  153. key: "mask"
  154. }, maskMotion, {
  155. visible: mask && open
  156. }), function (_ref2, maskRef) {
  157. var motionMaskClassName = _ref2.className,
  158. motionMaskStyle = _ref2.style;
  159. return /*#__PURE__*/React.createElement("div", {
  160. className: classNames("".concat(prefixCls, "-mask"), motionMaskClassName, drawerClassNames === null || drawerClassNames === void 0 ? void 0 : drawerClassNames.mask, maskClassName),
  161. style: _objectSpread(_objectSpread(_objectSpread({}, motionMaskStyle), maskStyle), styles === null || styles === void 0 ? void 0 : styles.mask),
  162. onClick: maskClosable && open ? onClose : undefined,
  163. ref: maskRef
  164. });
  165. });
  166. // =========================== Panel ============================
  167. var motionProps = typeof motion === 'function' ? motion(placement) : motion;
  168. var wrapperStyle = {};
  169. if (pushed && pushDistance) {
  170. switch (placement) {
  171. case 'top':
  172. wrapperStyle.transform = "translateY(".concat(pushDistance, "px)");
  173. break;
  174. case 'bottom':
  175. wrapperStyle.transform = "translateY(".concat(-pushDistance, "px)");
  176. break;
  177. case 'left':
  178. wrapperStyle.transform = "translateX(".concat(pushDistance, "px)");
  179. break;
  180. default:
  181. wrapperStyle.transform = "translateX(".concat(-pushDistance, "px)");
  182. break;
  183. }
  184. }
  185. if (placement === 'left' || placement === 'right') {
  186. wrapperStyle.width = parseWidthHeight(width);
  187. } else {
  188. wrapperStyle.height = parseWidthHeight(height);
  189. }
  190. var eventHandlers = {
  191. onMouseEnter: onMouseEnter,
  192. onMouseOver: onMouseOver,
  193. onMouseLeave: onMouseLeave,
  194. onClick: onClick,
  195. onKeyDown: onKeyDown,
  196. onKeyUp: onKeyUp
  197. };
  198. var panelNode = /*#__PURE__*/React.createElement(CSSMotion, _extends({
  199. key: "panel"
  200. }, motionProps, {
  201. visible: open,
  202. forceRender: forceRender,
  203. onVisibleChanged: function onVisibleChanged(nextVisible) {
  204. afterOpenChange === null || afterOpenChange === void 0 || afterOpenChange(nextVisible);
  205. },
  206. removeOnLeave: false,
  207. leavedClassName: "".concat(prefixCls, "-content-wrapper-hidden")
  208. }), function (_ref3, motionRef) {
  209. var motionClassName = _ref3.className,
  210. motionStyle = _ref3.style;
  211. var content = /*#__PURE__*/React.createElement(DrawerPanel, _extends({
  212. id: id,
  213. containerRef: motionRef,
  214. prefixCls: prefixCls,
  215. className: classNames(className, drawerClassNames === null || drawerClassNames === void 0 ? void 0 : drawerClassNames.content),
  216. style: _objectSpread(_objectSpread({}, style), styles === null || styles === void 0 ? void 0 : styles.content)
  217. }, pickAttrs(props, {
  218. aria: true
  219. }), eventHandlers), children);
  220. return /*#__PURE__*/React.createElement("div", _extends({
  221. className: classNames("".concat(prefixCls, "-content-wrapper"), drawerClassNames === null || drawerClassNames === void 0 ? void 0 : drawerClassNames.wrapper, motionClassName),
  222. style: _objectSpread(_objectSpread(_objectSpread({}, wrapperStyle), motionStyle), styles === null || styles === void 0 ? void 0 : styles.wrapper)
  223. }, pickAttrs(props, {
  224. data: true
  225. })), drawerRender ? drawerRender(content) : content);
  226. });
  227. // =========================== Render ===========================
  228. var containerStyle = _objectSpread({}, rootStyle);
  229. if (zIndex) {
  230. containerStyle.zIndex = zIndex;
  231. }
  232. return /*#__PURE__*/React.createElement(DrawerContext.Provider, {
  233. value: mergedContext
  234. }, /*#__PURE__*/React.createElement("div", {
  235. className: classNames(prefixCls, "".concat(prefixCls, "-").concat(placement), rootClassName, _defineProperty(_defineProperty({}, "".concat(prefixCls, "-open"), open), "".concat(prefixCls, "-inline"), inline)),
  236. style: containerStyle,
  237. tabIndex: -1,
  238. ref: panelRef,
  239. onKeyDown: onPanelKeyDown
  240. }, maskNode, /*#__PURE__*/React.createElement("div", {
  241. tabIndex: 0,
  242. ref: sentinelStartRef,
  243. style: sentinelStyle,
  244. "aria-hidden": "true",
  245. "data-sentinel": "start"
  246. }), panelNode, /*#__PURE__*/React.createElement("div", {
  247. tabIndex: 0,
  248. ref: sentinelEndRef,
  249. style: sentinelStyle,
  250. "aria-hidden": "true",
  251. "data-sentinel": "end"
  252. })));
  253. }
  254. var RefDrawerPopup = /*#__PURE__*/React.forwardRef(DrawerPopup);
  255. if (process.env.NODE_ENV !== 'production') {
  256. RefDrawerPopup.displayName = 'DrawerPopup';
  257. }
  258. export default RefDrawerPopup;