UNPKG

ant-design-vue

Version:

An enterprise-class UI design language and Vue-based implementation

694 lines (587 loc) 24.8 kB
import { isVNode as _isVNode, createVNode as _createVNode } from "vue"; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _extends() { _extends = Object.assign || 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); } var __rest = this && this.__rest || function (s, e) { var t = {}; for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; } if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import classnames from '../../_util/classNames'; import { Teleport, nextTick, defineComponent } from 'vue'; import BaseMixin from '../../_util/BaseMixin'; import { initDefaultProps, getSlot } from '../../_util/props-util'; import getScrollBarSize from '../../_util/getScrollBarSize'; import { IDrawerProps } from './IDrawerPropTypes'; import KeyCode from '../../_util/KeyCode'; import { dataToArray, transitionEnd, transitionStr, addEventListener, removeEventListener, transformArguments, isNumeric } from './utils'; import supportsPassive from '../../_util/supportsPassive'; import { cloneElement } from '../../_util/vnode'; function _isSlot(s) { return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !_isVNode(s); } function noop() {} var currentDrawer = {}; var windowIsUndefined = !(typeof window !== 'undefined' && window.document && window.document.createElement); var Drawer = defineComponent({ name: 'Drawer', mixins: [BaseMixin], inheritAttrs: false, props: initDefaultProps(IDrawerProps, { prefixCls: 'drawer', placement: 'left', getContainer: 'body', level: 'all', duration: '.3s', ease: 'cubic-bezier(0.78, 0.14, 0.15, 0.86)', firstEnter: false, showMask: true, handler: true, maskStyle: {}, wrapperClassName: '' }), data: function data() { this.levelDom = []; this.contentDom = null; this.maskDom = null; this.handlerdom = null; this.mousePos = null; this.sFirstEnter = this.firstEnter; this.timeout = null; this.children = null; this.dom = null; this.drawerId = Number((Date.now() + Math.random()).toString().replace('.', Math.round(Math.random() * 9))).toString(16); var open = this.open !== undefined ? this.open : !!this.defaultOpen; currentDrawer[this.drawerId] = open; this.orignalOpen = this.open; this.preProps = _extends({}, this.$props); return { sOpen: open, isOpenChange: undefined, passive: undefined, container: undefined }; }, watch: { open: function (_open) { function open(_x) { return _open.apply(this, arguments); } open.toString = function () { return _open.toString(); }; return open; }(function (val) { var _this = this; if (val !== undefined && val !== this.preProps.open) { this.isOpenChange = true; // 没渲染 dom 时,获取默认数据; if (!this.container) { this.getDefault(this.$props); } this.setState({ sOpen: open }); } this.preProps.open = val; if (val) { nextTick(function () { _this.domFocus(); }); } }), placement: function placement(val) { if (val !== this.preProps.placement) { // test 的 bug, 有动画过场,删除 dom this.contentDom = null; } this.preProps.placement = val; }, level: function level(val) { if (this.preProps.level !== val) { this.getParentAndLevelDom(this.$props); } this.preProps.level = val; } }, mounted: function mounted() { var _this2 = this; nextTick(function () { if (!windowIsUndefined) { _this2.passive = supportsPassive ? { passive: false } : false; } var open = _this2.getOpen(); if (_this2.handler || open || _this2.sFirstEnter) { _this2.getDefault(_this2.$props); if (open) { _this2.isOpenChange = true; nextTick(function () { _this2.domFocus(); }); } _this2.$forceUpdate(); } }); }, updated: function updated() { var _this3 = this; nextTick(function () { // dom 没渲染时,重走一遍。 if (!_this3.sFirstEnter && _this3.container) { _this3.$forceUpdate(); _this3.sFirstEnter = true; } }); }, beforeUnmount: function beforeUnmount() { delete currentDrawer[this.drawerId]; delete this.isOpenChange; if (this.container) { if (this.sOpen) { this.setLevelDomTransform(false, true); } document.body.style.overflow = ''; } this.sFirstEnter = false; clearTimeout(this.timeout); }, methods: { domFocus: function domFocus() { if (this.dom) { this.dom.focus(); } }, onKeyDown: function onKeyDown(e) { if (e.keyCode === KeyCode.ESC) { e.stopPropagation(); this.__emit('close', e); } }, onMaskTouchEnd: function onMaskTouchEnd(e) { this.__emit('close', e); this.onTouchEnd(e, true); }, onIconTouchEnd: function onIconTouchEnd(e) { this.__emit('handleClick', e); this.onTouchEnd(e); }, onTouchEnd: function onTouchEnd(e, close) { if (this.open !== undefined) { return; } var open = close || this.sOpen; this.isOpenChange = true; this.setState({ sOpen: !open }); }, onWrapperTransitionEnd: function onWrapperTransitionEnd(e) { if (e.target === this.contentWrapper && e.propertyName.match(/transform$/)) { var _open2 = this.getOpen(); this.dom.style.transition = ''; if (!_open2 && this.getCurrentDrawerSome()) { document.body.style.overflowX = ''; if (this.maskDom) { this.maskDom.style.left = ''; this.maskDom.style.width = ''; } } if (this.afterVisibleChange) { this.afterVisibleChange(!!_open2); } } }, getDefault: function getDefault(props) { this.getParentAndLevelDom(props); if (props.getContainer || props.parent) { this.container = this.defaultGetContainer(); } }, getCurrentDrawerSome: function getCurrentDrawerSome() { return !Object.keys(currentDrawer).some(function (key) { return currentDrawer[key]; }); }, getSelfContainer: function getSelfContainer() { return this.container; }, getParentAndLevelDom: function getParentAndLevelDom(props) { var _this4 = this; if (windowIsUndefined) { return; } var level = props.level, getContainer = props.getContainer; this.levelDom = []; if (getContainer) { if (typeof getContainer === 'string') { var dom = document.querySelectorAll(getContainer)[0]; this.parent = dom; } if (typeof getContainer === 'function') { this.parent = getContainer(); } if (_typeof(getContainer) === 'object' && getContainer instanceof window.HTMLElement) { this.parent = getContainer; } } if (!getContainer && this.container) { this.parent = 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.nodeName !== 'LINK' && child !== _this4.container) { _this4.levelDom.push(child); } }); } else if (level) { dataToArray(level).forEach(function (key) { document.querySelectorAll(key).forEach(function (item) { _this4.levelDom.push(item); }); }); } }, setLevelDomTransform: function setLevelDomTransform(open, openTransition, placementName, value) { var _this5 = this; var _this$$props = this.$props, placement = _this$$props.placement, levelMove = _this$$props.levelMove, duration = _this$$props.duration, ease = _this$$props.ease, getContainer = _this$$props.getContainer; if (!windowIsUndefined) { this.levelDom.forEach(function (dom) { if (_this5.isOpenChange || openTransition) { /* eslint no-param-reassign: "error" */ dom.style.transition = "transform ".concat(duration, " ").concat(ease); addEventListener(dom, transitionEnd, _this5.trnasitionEnd); var levelValue = open ? value : 0; if (levelMove) { var $levelMove = transformArguments(levelMove, { target: dom, open: open }); levelValue = open ? $levelMove[0] : $levelMove[1] || 0; } var $value = typeof levelValue === 'number' ? "".concat(levelValue, "px") : levelValue; var placementPos = placement === 'left' || placement === 'top' ? $value : "-".concat($value); dom.style.transform = levelValue ? "".concat(placementName, "(").concat(placementPos, ")") : ''; dom.style.msTransform = levelValue ? "".concat(placementName, "(").concat(placementPos, ")") : ''; } }); // 处理 body 滚动 if (getContainer === 'body') { var eventArray = ['touchstart']; var domArray = [document.body, this.maskDom, this.handlerdom, this.contentDom]; var right = document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight) && window.innerWidth > document.body.offsetWidth ? getScrollBarSize(1) : 0; var widthTransition = "width ".concat(duration, " ").concat(ease); var trannsformTransition = "transform ".concat(duration, " ").concat(ease); if (open && document.body.style.overflow !== 'hidden') { document.body.style.overflow = 'hidden'; if (right) { document.body.style.position = 'relative'; document.body.style.width = "calc(100% - ".concat(right, "px)"); this.dom.style.transition = 'none'; switch (placement) { case 'right': this.dom.style.transform = "translateX(-".concat(right, "px)"); this.dom.style.msTransform = "translateX(-".concat(right, "px)"); break; case 'top': case 'bottom': this.dom.style.width = "calc(100% - ".concat(right, "px)"); this.dom.style.transform = 'translateZ(0)'; break; default: break; } clearTimeout(this.timeout); this.timeout = setTimeout(function () { _this5.dom.style.transition = "".concat(trannsformTransition, ",").concat(widthTransition); _this5.dom.style.width = ''; _this5.dom.style.transform = ''; _this5.dom.style.msTransform = ''; }); } // 手机禁滚 domArray.forEach(function (item, i) { if (!item) { return; } addEventListener(item, eventArray[i] || 'touchmove', i ? _this5.removeMoveHandler : _this5.removeStartHandler, _this5.passive); }); } else if (this.getCurrentDrawerSome()) { document.body.style.overflow = ''; if ((this.isOpenChange || openTransition) && right) { document.body.style.position = ''; document.body.style.width = ''; if (transitionStr) { document.body.style.overflowX = 'hidden'; } this.dom.style.transition = 'none'; var heightTransition; switch (placement) { case 'right': { this.dom.style.transform = "translateX(".concat(right, "px)"); this.dom.style.msTransform = "translateX(".concat(right, "px)"); this.dom.style.width = '100%'; widthTransition = "width 0s ".concat(ease, " ").concat(duration); if (this.maskDom) { this.maskDom.style.left = "-".concat(right, "px"); this.maskDom.style.width = "calc(100% + ".concat(right, "px)"); } break; } case 'top': case 'bottom': { this.dom.style.width = "calc(100% + ".concat(right, "px)"); this.dom.style.height = '100%'; this.dom.style.transform = 'translateZ(0)'; heightTransition = "height 0s ".concat(ease, " ").concat(duration); break; } default: break; } clearTimeout(this.timeout); this.timeout = setTimeout(function () { _this5.dom.style.transition = "".concat(trannsformTransition, ",").concat(heightTransition ? "".concat(heightTransition, ",") : '').concat(widthTransition); _this5.dom.style.transform = ''; _this5.dom.style.msTransform = ''; _this5.dom.style.width = ''; _this5.dom.style.height = ''; }); } domArray.forEach(function (item, i) { if (!item) { return; } removeEventListener(item, eventArray[i] || 'touchmove', i ? _this5.removeMoveHandler : _this5.removeStartHandler, _this5.passive); }); } } } var onChange = this.$attrs.onChange; if (onChange && this.isOpenChange && this.sFirstEnter) { onChange(open); this.isOpenChange = false; } }, getChildToRender: function getChildToRender(open) { var _classnames, _this6 = this; var _this$$props2 = this.$props, prefixCls = _this$$props2.prefixCls, placement = _this$$props2.placement, handler = _this$$props2.handler, showMask = _this$$props2.showMask, maskStyle = _this$$props2.maskStyle, width = _this$$props2.width, height = _this$$props2.height, wrapStyle = _this$$props2.wrapStyle, keyboard = _this$$props2.keyboard, maskClosable = _this$$props2.maskClosable; var _a = this.$attrs, cls = _a.class, style = _a.style, restAttrs = __rest(_a, ["class", "style"]); var children = getSlot(this); var wrapperClassname = classnames(prefixCls, (_classnames = {}, _defineProperty(_classnames, "".concat(prefixCls, "-").concat(placement), true), _defineProperty(_classnames, "".concat(prefixCls, "-open"), open), _defineProperty(_classnames, 'no-mask', !showMask), _defineProperty(_classnames, cls, cls), _classnames)); var isOpenChange = this.isOpenChange; var isHorizontal = placement === 'left' || placement === 'right'; var placementName = "translate".concat(isHorizontal ? 'X' : 'Y'); // 百分比与像素动画不同步,第一次打用后全用像素动画。 // const defaultValue = !this.contentDom || !level ? '100%' : `${value}px`; var placementPos = placement === 'left' || placement === 'top' ? '-100%' : '100%'; var transform = open ? '' : "".concat(placementName, "(").concat(placementPos, ")"); if (isOpenChange === undefined || isOpenChange) { var contentValue = this.contentDom ? this.contentDom.getBoundingClientRect()[isHorizontal ? 'width' : 'height'] : 0; var value = (isHorizontal ? width : height) || contentValue; this.setLevelDomTransform(open, false, placementName, value); } var handlerChildren; if (handler !== false) { var handlerDefalut = _createVNode("div", { "class": "drawer-handle", "onClick": function onClick() {} }, [_createVNode("i", { "class": "drawer-handle-icon" }, null)]); var handlerSlot = this.handler; var handlerSlotVnode = handlerSlot || handlerDefalut; var handleIconClick = handlerSlotVnode.props && handlerSlotVnode.props.onClick; handlerChildren = cloneElement(handlerSlotVnode, { onClick: function onClick(e) { handleIconClick && handleIconClick(e); _this6.onIconTouchEnd(e); }, ref: function ref(c) { _this6.handlerdom = c; } }); } var domContProps = _extends(_extends({}, restAttrs), { class: wrapperClassname, onTransitionend: this.onWrapperTransitionEnd, onKeydown: open && keyboard ? this.onKeyDown : noop, style: _extends(_extends({}, wrapStyle), style) }); return _createVNode("div", _objectSpread(_objectSpread({ "ref": function ref(c) { _this6.dom = c; } }, domContProps), {}, { "tabindex": -1 }), [showMask && _createVNode("div", { "key": open, "class": "".concat(prefixCls, "-mask"), "onClick": maskClosable ? this.onMaskTouchEnd : noop, "style": maskStyle, "ref": function ref(c) { _this6.maskDom = c; } }, null), _createVNode("div", { "class": "".concat(prefixCls, "-content-wrapper"), "style": { transform: transform, msTransform: transform, width: isNumeric(width) ? "".concat(width, "px") : width, height: isNumeric(height) ? "".concat(height, "px") : height }, "ref": function ref(c) { _this6.contentWrapper = c; } }, [_createVNode("div", { "class": "".concat(prefixCls, "-content"), "ref": function ref(c) { _this6.contentDom = c; }, "onTouchstart": open ? this.removeStartHandler : noop, "onTouchmove": open ? this.removeMoveHandler : noop }, _isSlot(children) ? children : { default: function _default() { return [children]; } }), handlerChildren])]); }, getOpen: function getOpen() { return this.open !== undefined ? this.open : this.sOpen; }, getTouchParentScroll: function getTouchParentScroll(root, currentTarget, differX, differY) { if (!currentTarget || currentTarget === document) { return false; } // root 为 drawer-content 设定了 overflow, 判断为 root 的 parent 时结束滚动; if (currentTarget === root.parentNode) { return true; } var isY = Math.max(Math.abs(differX), Math.abs(differY)) === Math.abs(differY); var isX = Math.max(Math.abs(differX), Math.abs(differY)) === Math.abs(differX); var scrollY = currentTarget.scrollHeight - currentTarget.clientHeight; var scrollX = currentTarget.scrollWidth - currentTarget.clientWidth; /** * <div style="height: 300px"> * <div style="height: 900px"></div> * </div> * 在没设定 overflow: auto 或 scroll 时,currentTarget 里获取不到 scrollTop 或 scrollLeft, * 预先用 scrollTo 来滚动,如果取出的值跟滚动前取出不同,则 currnetTarget 被设定了 overflow; 否则就是上面这种。 */ var t = currentTarget.scrollTop; var l = currentTarget.scrollLeft; if (currentTarget.scrollTo) { currentTarget.scrollTo(currentTarget.scrollLeft + 1, currentTarget.scrollTop + 1); } var currentT = currentTarget.scrollTop; var currentL = currentTarget.scrollLeft; if (currentTarget.scrollTo) { currentTarget.scrollTo(currentTarget.scrollLeft - 1, currentTarget.scrollTop - 1); } if (isY && (!scrollY || !(currentT - t) || scrollY && (currentTarget.scrollTop >= scrollY && differY < 0 || currentTarget.scrollTop <= 0 && differY > 0)) || isX && (!scrollX || !(currentL - l) || scrollX && (currentTarget.scrollLeft >= scrollX && differX < 0 || currentTarget.scrollLeft <= 0 && differX > 0))) { return this.getTouchParentScroll(root, currentTarget.parentNode, differX, differY); } return false; }, removeStartHandler: function removeStartHandler(e) { if (e.touches.length > 1) { return; } this.startPos = { x: e.touches[0].clientX, y: e.touches[0].clientY }; }, removeMoveHandler: function removeMoveHandler(e) { if (e.changedTouches.length > 1) { return; } var currentTarget = e.currentTarget; var differX = e.changedTouches[0].clientX - this.startPos.x; var differY = e.changedTouches[0].clientY - this.startPos.y; if (currentTarget === this.maskDom || currentTarget === this.handlerdom || currentTarget === this.contentDom && this.getTouchParentScroll(currentTarget, e.target, differX, differY)) { e.preventDefault(); } }, trnasitionEnd: function trnasitionEnd(e) { removeEventListener(e.target, transitionEnd, this.trnasitionEnd); e.target.style.transition = ''; }, defaultGetContainer: function defaultGetContainer() { if (windowIsUndefined) { return null; } var container = document.createElement('div'); this.parent.appendChild(container); if (this.wrapperClassName) { container.className = this.wrapperClassName; } return container; } }, render: function render() { var _this7 = this; var _this$$props3 = this.$props, getContainer = _this$$props3.getContainer, wrapperClassName = _this$$props3.wrapperClassName, handler = _this$$props3.handler, forceRender = _this$$props3.forceRender; var open = this.getOpen(); var portal = null; currentDrawer[this.drawerId] = open ? this.container : open; var children = this.getChildToRender(this.sFirstEnter ? open : false); if (!getContainer) { return _createVNode("div", { "class": wrapperClassName, "ref": function ref(c) { _this7.container = c; } }, _isSlot(children) ? children : { default: function _default() { return [children]; } }); } if (!this.container || !open && !this.sFirstEnter) { return null; } // 如果有 handler 为内置强制渲染; var $forceRender = !!handler || forceRender; if ($forceRender || open || this.dom) { portal = _createVNode(Teleport, { "to": this.getSelfContainer() }, _isSlot(children) ? children : { default: function _default() { return [children]; } }); } return portal; } }); export default Drawer;