'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _defineProperty2 = require('babel-runtime/helpers/defineProperty'); var _defineProperty3 = _interopRequireDefault(_defineProperty2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _reactDom = require('react-dom'); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _classnames2 = require('classnames'); var _classnames3 = _interopRequireDefault(_classnames2); var _utils = require('./utils'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var windowIsUndefined = typeof window === 'undefined'; var Drawer = function (_React$PureComponent) { (0, _inherits3['default'])(Drawer, _React$PureComponent); function Drawer(props) { (0, _classCallCheck3['default'])(this, Drawer); var _this = (0, _possibleConstructorReturn3['default'])(this, (Drawer.__proto__ || Object.getPrototypeOf(Drawer)).call(this, props)); _this.levelDom = []; _this.contextDom = null; _this.maskDom = null; _this.mousePos = null; _this.getParentAndLevelDom = function () { if (windowIsUndefined) { return; } var _this$props = _this.props, level = _this$props.level, getContainer = _this$props.getContainer; _this.levelDom = []; _this.parent = getContainer && document.querySelectorAll(getContainer)[0] || _this.container.parentNode; if (level === 'all') { var children = Array.prototype.slice.call(_this.parent.children); children.forEach(function (child) { if (child.nodeName !== 'SCRIPT' && child.nodeName !== 'STYLE' && child !== _this.container) { _this.levelDom.push(child); } }); } else if (level) { (0, _utils.dataToArray)(_this.props.level).forEach(function (key) { document.querySelectorAll(key).forEach(function (item) { _this.levelDom.push(item); }); }); } }; _this.trnasitionEnd = function (e) { var dom = e.target; dom.removeEventListener(_utils.transitionEnd, _this.trnasitionEnd); dom.style.transition = ''; }; _this.onTouchEnd = function (e, close) { if (_this.props.open !== undefined) { return; } if (e) { e.preventDefault(); } var open = close || _this.state.open; _this.isOpenChange = true; _this.setState({ open: !open }); }; _this.onMaskTouchEnd = function (e) { _this.props.onMaskClick(e); _this.onTouchEnd(e, true); }; _this.onIconTouchEnd = function (e) { _this.props.onHandleClick(e); _this.onTouchEnd(e); }; _this.onScrollTouchStart = function (e) { if (e.touches.length > 1) { return; } var touchs = e.touches[0]; _this.mousePos = { x: touchs.pageX, y: touchs.pageY }; }; _this.onScrollTouchEnd = function () { _this.mousePos = null; }; _this.getScollDom = function (dom) { var doms = []; var setScrollDom = function setScrollDom(d) { if (!d) { return; } if (d.scrollHeight > d.clientHeight || d.scrollWidth > d.clientWidth) { doms.push(d); } if (d !== _this.contextDom && d !== _this.maskDom) { setScrollDom(d.parentNode); } }; setScrollDom(dom); return doms[doms.length - 1]; }; _this.getIsHandleDom = function (dom) { if (dom.className === _this.props.className + '-handle') { return true; } if (dom.parentNode) { return _this.getIsHandleDom(dom.parentNode); } return false; }; _this.removeScroll = function (e) { if (!_this.props.showMask) { return; } var dom = e.target; var scrollDom = _this.getScollDom(dom); if (dom === _this.maskDom || _this.getIsHandleDom(dom) || !scrollDom) { e.preventDefault(); e.returnValue = false; return; } var y = e.deltaY; var x = e.deltaX; if (e.type === 'touchmove') { if (e.touches.length > 1 || !_this.mousePos) { return; } var touches = e.touches[0]; // 上滑为正,下滑为负 y = _this.mousePos.y - touches.pageY; x = _this.mousePos.x - touches.pageX; } // 竖向 var scrollTop = scrollDom.scrollTop; var height = scrollDom.clientHeight; var scrollHeight = scrollDom.scrollHeight; var isScrollY = scrollHeight - height > 2; var maxOrMinScrollY = isScrollY && (scrollTop <= 0 && y < 0 || scrollTop + height >= scrollHeight && y > 0); // 横向 var width = scrollDom.clientWidth; var scrollLeft = scrollDom.scrollLeft; var scrollWidth = scrollDom.scrollWidth; var isScrollX = scrollWidth - width > 2; var maxOrMinScrollX = scrollWidth - width > 2 && (scrollLeft <= 0 && x < 0 || scrollLeft + width >= scrollWidth && x > 0); if (!isScrollY && !isScrollX || maxOrMinScrollY || maxOrMinScrollX) { e.preventDefault(); e.returnValue = false; return; } }; _this.setLevelDomTransform = function (open, openTransition, placementName, value) { var _this$props2 = _this.props, placement = _this$props2.placement, levelTransition = _this$props2.levelTransition, onChange = _this$props2.onChange; _this.levelDom.forEach(function (dom) { if (_this.isOpenChange || openTransition) { dom.style.transition = levelTransition; dom.addEventListener(_utils.transitionEnd, _this.trnasitionEnd); } var placementPos = placement === 'left' || placement === 'top' ? value : -value; dom.style.transform = open ? placementName + '(' + placementPos + 'px)' : ''; }); // 处理 body 滚动 if (!windowIsUndefined) { if (open) { document.body.addEventListener('mousewheel', _this.removeScroll); document.body.addEventListener('touchmove', _this.removeScroll); } else { document.body.removeEventListener('mousewheel', _this.removeScroll); document.body.removeEventListener('touchmove', _this.removeScroll); } } if (onChange && _this.isOpenChange) { onChange(open); _this.isOpenChange = false; } }; _this.getChildToRender = function () { var _classnames; var open = _this.props.open !== undefined ? _this.props.open : _this.state.open; var _this$props3 = _this.props, className = _this$props3.className, prefixCls = _this$props3.prefixCls, style = _this$props3.style, placement = _this$props3.placement, children = _this$props3.children, handleChild = _this$props3.handleChild, handleStyle = _this$props3.handleStyle, showMask = _this$props3.showMask, maskStyle = _this$props3.maskStyle; var wrapperClassname = (0, _classnames3['default'])(prefixCls, (_classnames = {}, (0, _defineProperty3['default'])(_classnames, prefixCls + '-' + placement, true), (0, _defineProperty3['default'])(_classnames, prefixCls + '-open', open), (0, _defineProperty3['default'])(_classnames, className, !!className), _classnames)); var value = _this.contextDom ? _this.contextDom.getBoundingClientRect()[placement === 'left' || placement === 'right' ? 'width' : 'height'] : 0; var placementName = 'translate' + (placement === 'left' || placement === 'right' ? 'X' : 'Y'); // 百分比与像素动画不同步,第一次打用后全用像素动画。 var defaultValue = !_this.contextDom ? '100%' : value + 'px'; var placementPos = placement === 'left' || placement === 'top' ? '-' + defaultValue : defaultValue; var transform = open ? '' : placementName + '(' + placementPos + ')'; if (_this.isOpenChange === undefined || _this.isOpenChange) { _this.setLevelDomTransform(open, false, placementName, value); } return _react2['default'].createElement( 'div', { className: wrapperClassname, style: style }, showMask && _react2['default'].createElement('div', { className: prefixCls + '-mask', onClick: _this.onMaskTouchEnd, style: maskStyle, ref: function ref(c) { _this.maskDom = c; } }), _react2['default'].createElement( 'div', { className: prefixCls + '-content-wrapper', style: { transform: transform } }, _react2['default'].createElement( 'div', { className: prefixCls + '-content', onTouchStart: _this.onScrollTouchStart, onTouchEnd: _this.onScrollTouchEnd, ref: function ref(c) { _this.contextDom = c; } }, children ), handleChild && _react2['default'].createElement( 'div', { className: prefixCls + '-handle', onClick: _this.onIconTouchEnd, style: handleStyle }, handleChild ) ) ); }; _this.defaultGetContainer = function () { if (windowIsUndefined) { return null; } var container = document.createElement('div'); _this.parent.appendChild(container); if (_this.props.wrapperClassName) { container.className = _this.props.wrapperClassName; } return container; }; if (props.onIconClick || props.parent || props.iconChild || props.width) { console.warn('rc-drawer-menu API has been changed, please look at the releases, ' + 'https://github.com/react-component/drawer-menu/releases'); } _this.state = { open: props.open !== undefined ? props.open : !!props.defaultOpen }; return _this; } (0, _createClass3['default'])(Drawer, [{ key: 'componentDidMount', value: function componentDidMount() { this.getParentAndLevelDom(); if (this.props.getContainer || this.props.parent) { this.container = this.defaultGetContainer(); } this.forceUpdate(); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { var open = nextProps.open, placement = nextProps.placement, children = nextProps.children; if (open !== undefined && open !== this.props.open) { this.isOpenChange = true; this.setState({ open: open }); } if (placement !== this.props.placement || children !== this.props.children) { // test 的 bug, 有动画过场,删除 dom this.contextDom = null; } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { if (this.container) { this.setLevelDomTransform(false, true); // 拦不住。。直接删除; if (this.props.getContainer) { this.container.parentNode.removeChild(this.container); } } } }, { key: 'render', value: function render() { var _this2 = this; var children = this.getChildToRender(); if (!this.props.getContainer) { return _react2['default'].createElement( 'div', { className: this.props.wrapperClassName, ref: function ref(c) { _this2.container = c; } }, children ); } if (!this.container) { return null; } return (0, _reactDom.createPortal)(children, this.container); } }]); return Drawer; }(_react2['default'].PureComponent); Drawer.propTypes = { wrapperClassName: _propTypes2['default'].string, open: _propTypes2['default'].bool, bodyStyle: _propTypes2['default'].object, defaultOpen: _propTypes2['default'].bool, placement: _propTypes2['default'].string, level: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].array]), levelTransition: _propTypes2['default'].string, getContainer: _propTypes2['default'].string, handleChild: _propTypes2['default'].any, handleStyle: _propTypes2['default'].object, onChange: _propTypes2['default'].func, onMaskClick: _propTypes2['default'].func, onHandleClick: _propTypes2['default'].func, showMask: _propTypes2['default'].bool, maskStyle: _propTypes2['default'].object }; Drawer.defaultProps = { className: '', prefixCls: 'drawer', placement: 'left', getContainer: 'body', level: 'all', levelTransition: 'transform .3s cubic-bezier(0.78, 0.14, 0.15, 0.86)', onChange: function onChange() {}, onMaskClick: function onMaskClick() {}, onHandleClick: function onHandleClick() {}, handleChild: _react2['default'].createElement('i', { className: 'drawer-handle-icon' }), handleStyle: {}, showMask: true, maskStyle: {} }; exports['default'] = Drawer; module.exports = exports['default'];