UNPKG

ten-design-vue

Version:

ten-vue

566 lines (487 loc) 18.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _vue = _interopRequireDefault(require("vue")); var _debounce = _interopRequireDefault(require("lodash/debounce")); var _domHelper = _interopRequireDefault(require("../scripts/utils/dom-helper")); var _getElSlots = _interopRequireDefault(require("../scripts/mixins/get-el-slots")); var _emitter = _interopRequireDefault(require("../scripts/mixins/emitter")); var _resizeObserver = require("../scripts/utils/resize-observer"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } var name = 'ten-popup'; function getDirMatch(direction) { /* eslint-disable */ var dirMatch = direction.match(/((top|bottom|center|left|right)[\s-]*)/gi); dirMatch = !dirMatch ? ['top', 'center'] : dirMatch.map(function (dir) { return dir.replace(/[\s-]/g, ''); }); /* eslint-enable */ if (dirMatch.length === 1) { dirMatch[1] = 'center'; } if (dirMatch[0] === 'left' && dirMatch[1] === 'right' || dirMatch[0] === 'right' && dirMatch[1] === 'left' || dirMatch[0] === 'top' && dirMatch[1] === 'bottom' || dirMatch[0] === 'bottom' && dirMatch[1] === 'top') { dirMatch[1] = 'center'; } if (dirMatch[0] === 'center') { if (dirMatch[1] === 'center') { dirMatch = ['top', 'center']; } dirMatch.reverse(); } else if (dirMatch[0] === dirMatch[1]) { dirMatch[1] = 'center'; } dirMatch[0] = dirMatch[0].trim(); dirMatch[1] = dirMatch[1].trim(); return dirMatch; } var _default = { name: name, mixins: [_getElSlots.default, _emitter.default], model: { prop: 'show', event: 'change' }, props: { /** * 弹窗方向 */ direction: { type: String, default: 'top center' }, /** * 是否显示 */ show: Boolean, /** * 隐藏时是否销毁 */ destroy: { type: Boolean, default: true }, disabled: Boolean, /** * 获取弹窗内容宽度 */ width: [Number, Function], /** * 设置弹窗偏移量,{ x, y } */ offset: Object, /** * 触发方式 */ triggerType: { validator: function validator(val) { return ['click', 'hover', 'manual'].indexOf(val) > -1; }, default: 'click' }, /** * 弹框 class */ popupClass: [String, Object, Array], /** * 类型 * @member default | bubble */ type: { type: String, default: 'default' } }, data: function data() { return { popupShowed: false }; }, watch: { show: { immediate: true, handler: function handler(val) { this.popupShowed = val; } }, disabled: function disabled(v) { if (v && this.popupShowed && this.triggerType !== 'manual') { this.popupShowed = false; } } }, render: function render(h) { // eslint-disable-line var triggerSlots = this.$scopedSlots.trigger ? this.$scopedSlots.trigger() : null; var defaultSlot = this.$scopedSlots.default ? this.$scopedSlots.default() : null; var trigger = null; if (triggerSlots) { for (var i = 0; i < triggerSlots.length; i++) { if (triggerSlots[i].tag) { trigger = triggerSlots[i]; break; } } } this.popupComponent.content = this.popupShowed || !this.destroy ? defaultSlot : null; this.popupComponent.destroy = this.destroy; this.popupComponent.show = this.popupShowed && trigger; this.popupComponent.popupClass = this.popupClass; this.popupComponent.type = this.type; var dirMatch = getDirMatch(this.direction); this.popupComponent.dir = dirMatch; return trigger; }, beforeCreate: function beforeCreate() { var _this = this; var h = this.$createElement; var resize = function resize() { _this.resize(); }; var visibleT = 0; this.globalEventBinded = false; this.popupElemEventBinded = false; this.popupComponent = new _vue.default({ parent: this, data: function data() { return { type: 'default', content: null, dataContent: null, popupClass: '', dir: [], show: false, destroy: false }; }, watch: { content: { handler: function handler(v) { var _this2 = this; clearTimeout(visibleT); if (v) { this.dataContent = v; } else { visibleT = setTimeout(function () { _this2.dataContent = null; }, 300); } }, immediate: true } }, methods: { onAfterLeave: function onAfterLeave() { if (this.destroy) { try { document.body.removeChild(this.$el); } catch (e) {} } } }, updated: function updated() { if (this.$refs.popup) { (0, _resizeObserver.removeResizeListener)(this.$refs.popup, resize); (0, _resizeObserver.addResizeListener)(this.$refs.popup, resize); this.$refs.popup.tenPopupParentNode = this.$parent.$el; } }, beforeDestroy: function beforeDestroy() { if (this.$refs.popup) { (0, _resizeObserver.removeResizeListener)(this.$refs.popup, resize); this.$refs.popup.tenPopupParentNode = null; } }, render: function render(h) { var _this3 = this; // eslint-disable-line var popupClass = ['ten-popup', "ten-popup--p-".concat(this.dir[0], "-").concat(this.dir[1]), "ten-popup--type-".concat(this.type), this.popupClass]; return this.dataContent ? // appear确保初次渲染的时候依然有过渡动画 h("transition", { attrs: { name: "ten-flow-in__popup", appear: true }, on: { "afterLeave": function afterLeave() { _this3.onAfterLeave(); } } }, [h("div", { "class": popupClass, directives: [{ name: "show", value: this.show && this.content }], ref: "popup" }, [this.dataContent])]) : null; } }); this.popupComponent.$mount(); }, mounted: function mounted() { this.bindTriggerElemEvent(); this.afterRender(); this.setPopupPosition = (0, _debounce.default)(this.setPopupPosition.bind(this), 16); }, updated: function updated() { this.bindTriggerElemEvent(); this.afterRender(); }, beforeDestroy: function beforeDestroy() { this.unbindGlobalEvent(); this.removePopupElem(); this.popupComponent.$destroy(); }, methods: { afterRender: function afterRender() { if (this.popupShowed) { this.appendPopupElem(); this.bindPopupElemEvent(); if (this.triggerType === 'click' || this.triggerType === 'manual') { this.bindGlobalEvent(); } this.dirMatch = getDirMatch(this.direction); this.$nextTick(function () { this.setPopupPosition(); }); } else { this.unbindGlobalEvent(); this.unbindPopupElemEvent(); } }, appendPopupElem: function appendPopupElem() { try { if (this.popupComponent.$el.parentNode === document.body) { return; } document.body.appendChild(this.popupComponent.$el); this.broadcastAll('do-layout'); } catch (e) {} }, removePopupElem: function removePopupElem() { try { document.body.removeChild(this.popupComponent.$el); } catch (e) {} }, bindTriggerElemEvent: function bindTriggerElemEvent() { this.triggerElem = this.$el; if (this.triggerElem) { if (this.triggerType === 'click') { this.triggerElem.addEventListener('click', this.onClick); } if (this.triggerType === 'hover') { this.triggerElem.addEventListener('mouseenter', this.onMouseenter); this.triggerElem.addEventListener('mouseleave', this.onMouseleave); } } }, bindPopupElemEvent: function bindPopupElemEvent() { if (this.popupComponent.$el && !this.popupElemEventBinded) { this.popupElemEventBinded = true; if (this.triggerType === 'hover') { this.popupComponent.$el.addEventListener('mouseenter', this.onMouseenter); this.popupComponent.$el.addEventListener('mouseleave', this.onMouseleave); } } }, unbindPopupElemEvent: function unbindPopupElemEvent() { if (this.popupComponent.$el) { this.popupElemEventBinded = false; if (this.triggerType === 'hover') { this.popupComponent.$el.removeEventListener('mouseenter', this.onMouseenter); this.popupComponent.$el.removeEventListener('mouseleave', this.onMouseleave); } } }, bindGlobalEvent: function bindGlobalEvent() { if (!this.globalEventBinded) { this.globalEventBinded = true; window.addEventListener('resize', this.setPopupPosition); window.addEventListener('scroll', this.setPopupPosition); document.addEventListener('scroll', this.setPopupPosition, true); document.addEventListener('click', this.onClickOutside); document.addEventListener('keydown', this.onKeydown); } }, unbindGlobalEvent: function unbindGlobalEvent() { this.globalEventBinded = false; window.removeEventListener('resize', this.setPopupPosition); window.removeEventListener('scroll', this.setPopupPosition); document.removeEventListener('scroll', this.setPopupPosition, true); document.removeEventListener('click', this.onClickOutside); document.removeEventListener('keydown', this.onKeydown); }, setPopupPosition: function setPopupPosition() { this.popupElem = this.popupComponent.$el; var show = this.popupShowed; var padding = 0; var dirMatch = _toConsumableArray(this.dirMatch); // const padding = 16; var triggerElem = this.triggerElem; var isTriggerFixed = getComputedStyle(triggerElem).position === 'fixed'; // console.log('setPopupPosition', triggerElem, this.popupElem); if (!show || !triggerElem || !this.popupElem || triggerElem.nodeType !== 1 || this.popupElem.nodeType !== 1) { return; } var winHeight = window.innerHeight; var winWidth = window.innerWidth; var triggerElemRect = triggerElem.getBoundingClientRect(); var popupElemRect = this.popupElem.getBoundingClientRect(); var popupStyle = { position: isTriggerFixed ? 'fixed' : 'absolute' }; var popupElemRectWidth = popupElemRect.width; if (typeof this.width !== 'undefined') { var width = this.width; var w; if (typeof width === 'function') { w = width(triggerElem); } else { w = width; } popupElemRectWidth = w + padding * 2; popupStyle.width = w + padding * 2; } // If there is not enough space in the specified direction, set it to the opposite direction if (dirMatch[0] === 'top' && popupElemRect.height > triggerElemRect.top && popupElemRect.height < winHeight - triggerElemRect.top - triggerElemRect.height) { dirMatch[0] = 'bottom'; } if (dirMatch[0] === 'bottom' && popupElemRect.height > winHeight - triggerElemRect.top - triggerElemRect.height && popupElemRect.height < triggerElemRect.top) { dirMatch[0] = 'top'; } if (dirMatch[0] === 'left' && popupElemRectWidth > triggerElemRect.left && popupElemRectWidth < winWidth - triggerElemRect.left - triggerElemRect.width) { dirMatch[0] = 'right'; } if (dirMatch[0] === 'right' && popupElemRectWidth > winWidth - triggerElemRect.left - triggerElemRect.width && popupElemRectWidth < triggerElemRect.left) { dirMatch[0] = 'left'; } if (dirMatch[1] === 'top' && popupElemRect.height > winHeight - triggerElemRect.top) { dirMatch[1] = 'bottom'; } else if (dirMatch[1] === 'bottom' && popupElemRect.height > triggerElemRect.top + triggerElemRect.height) { dirMatch[1] = 'top'; } if (dirMatch[1] === 'left' && popupElemRectWidth > winWidth - triggerElemRect.left) { dirMatch[1] = 'right'; } else if (dirMatch[1] === 'right' && popupElemRectWidth > triggerElemRect.left + triggerElemRect.width) { dirMatch[1] = 'left'; } if (dirMatch[0] === 'bottom' || dirMatch[0] === 'top') { if (dirMatch[1] === 'center' && popupElemRectWidth) { var leftSpaceRemain = triggerElemRect.left + triggerElemRect.width / 2; var rightSpaceRemain = winWidth - leftSpaceRemain; if (popupElemRectWidth / 2 > leftSpaceRemain && popupElemRectWidth / 2 < rightSpaceRemain) { dirMatch[1] = 'left'; } else if (popupElemRectWidth / 2 > rightSpaceRemain && popupElemRectWidth / 2 < leftSpaceRemain) { dirMatch[1] = 'right'; } } } // style if (dirMatch[0] === 'top') { popupStyle.top = triggerElemRect.top - popupElemRect.height; } else if (dirMatch[0] === 'bottom') { popupStyle.top = triggerElemRect.top + triggerElemRect.height; } else if (dirMatch[0] === 'left') { popupStyle.left = triggerElemRect.left - popupElemRectWidth; } else if (dirMatch[0] === 'right') { popupStyle.left = triggerElemRect.left + triggerElemRect.width; } if (dirMatch[1] === 'top') { popupStyle.top = triggerElemRect.top - padding; } else if (dirMatch[1] === 'bottom') { popupStyle.top = triggerElemRect.top + triggerElemRect.height - popupElemRect.height + padding; } else if (dirMatch[1] === 'left') { popupStyle.left = triggerElemRect.left - padding; } else if (dirMatch[1] === 'right') { popupStyle.left = triggerElemRect.left + triggerElemRect.width - popupElemRectWidth + padding; } else { /* eslint-disable */ // center if (dirMatch[0] === 'top' || dirMatch[0] === 'bottom') { popupStyle.left = triggerElemRect.left - (popupElemRectWidth - triggerElemRect.width) / 2; } else { popupStyle.top = triggerElemRect.top - (popupElemRect.height - triggerElemRect.height) / 2; } /* eslint-enable */ } if (dirMatch[0] === 'top') { popupStyle.top = triggerElemRect.top - popupElemRect.height; } else if (dirMatch[0] === 'bottom') { popupStyle.top = triggerElemRect.top + triggerElemRect.height; } else if (dirMatch[0] === 'center') { popupStyle.top = triggerElemRect.top - (popupElemRect.height - triggerElemRect.height) / 2; } if (!isTriggerFixed) { popupStyle.top += window.scrollY || window.pageYOffset; popupStyle.left += window.scrollX || window.pageXOffset; } if (this.offset) { popupStyle.top += this.offset.y || 0; popupStyle.left += this.offset.x || 0; } _domHelper.default.css(this.popupElem, popupStyle); // class for style arrow this.popupElem.className = this.popupElem.className.replace(/ten-popup--p-[\w-]+/g, '').replace(/\s+/g, ' '); this.popupElem.classList.add("ten-popup--p-".concat(dirMatch[0], "-").concat(dirMatch[1])); }, resize: function resize() { this.setPopupPosition(); }, onClick: function onClick() { this.togglePopup(); }, onMouseenter: function onMouseenter() { clearTimeout(this.mouseleaveT); this.showPopup(); }, onMouseleave: function onMouseleave() { var _this4 = this; this.mouseleaveT = setTimeout(function () { _this4.hidePopup(); }, 150); }, onClickOutside: function onClickOutside(e) { if (!this.popupShowed || _domHelper.default.contains(this.popupElem, e.target) || _domHelper.default.contains(this.triggerElem, e.target)) { return; } this.hidePopup(); }, onKeydown: function onKeydown(e) { if (e.keyCode === 27) { this.hidePopup(); } }, togglePopup: function togglePopup() { this.popupShowed ? this.hidePopup() : this.showPopup(); }, showPopup: function showPopup() { if (this.disabled) { return; } if (this.triggerType !== 'manual') { this.popupShowed = true; } /** * 弹窗显示变换回调 */ this.$emit('change', true); }, hidePopup: function hidePopup() { if (this.disabled) { return; } if (this.triggerType !== 'manual') { this.popupShowed = false; } /** * 弹窗显示变换回调 * @param {Boolean} visible */ this.$emit('change', false); } } }; exports.default = _default;