UNPKG

@ohu-mobile/core

Version:
491 lines (490 loc) 18.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.popupProps = exports.default = exports.POPUP_EVENT = void 0; var _dom = require("../_utils/dom"); var _manager = _interopRequireDefault(require("./manager")); var _debounce = _interopRequireDefault(require("../_utils/debounce")); var _utils = require("./utils"); var _variables = require("../_config/variables"); var _defineComponent = require("../_utils/defineComponent"); var _bindEvent = _interopRequireDefault(require("../_utils/bindEvent")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } var popupProps = exports.popupProps = { visible: Boolean, anchor: _defineComponent.props.ofType().optional, transformOrigin: _defineComponent.props.ofType().optional, marginThreshold: (0, _defineComponent.props)(Number).default(12), edgeDetect: (0, _defineComponent.props)(Boolean).default(true), lockScroll: (0, _defineComponent.props)(Boolean).default(true), position: _defineComponent.props.ofType().default('center'), mask: (0, _defineComponent.props)(Boolean).default(true), maskFrosted: (0, _defineComponent.props)(Boolean).default(false), maskClosable: (0, _defineComponent.props)(Boolean).default(true), maskAnimate: _defineComponent.props.ofStringLiterals('mask-fade', 'none').default('mask-fade'), partialMask: _defineComponent.props.ofStringLiterals('top', 'bottom').optional, closeOnMaskTouched: (0, _defineComponent.props)(Boolean).default(false), fullscreen: (0, _defineComponent.props)(Boolean).default(false), animate: _defineComponent.props.ofType().default('none'), targetStyle: _defineComponent.props.ofType().optional, targetClass: _defineComponent.props.ofType().optional, scrollBody: (0, _defineComponent.props)(Boolean).default(false), tapThrough: (0, _defineComponent.props)(Boolean).default(false), zIndex: Number, round: (0, _defineComponent.props)(Boolean).default(false), hideOnDeactivated: (0, _defineComponent.props)(Boolean).default(true) }; var positionTransitionMap = { top: "".concat(_variables.$prefix, "slide-up"), bottom: "".concat(_variables.$prefix, "slide-down"), left: "".concat(_variables.$prefix, "slide-left"), right: "".concat(_variables.$prefix, "slide-right") }; var createPopup = (0, _defineComponent.defineComponent)('popup-main'); var POPUP_EVENT = exports.POPUP_EVENT = 'visibleChange'; var Popup = createPopup.create({ model: { prop: 'visible', event: POPUP_EVENT }, props: popupProps, data: function data() { return { wrapperVisible: this.visible, documentVisible: false, docRect: null, docEl: null, docPos: null, anchorEl: null, anchorRect: null, maskZIndex: 0, documentZIndex: 0, touchData: { scrollY: 0, pageY: 0, scrollEl: null, maxHeight: 0 }, rootStyle: {} }; }, watch: { visible: function visible(newValue) { newValue ? this.open() : this.close(); } }, computed: { isAnchorMode: function isAnchorMode() { return !!this.anchor; }, documentClass: function documentClass() { return this.$bem.block('popup').is([this.fullscreen && 'fullscreen', this.round && 'round']).addClasses(this.targetClass); }, documentTransition: function documentTransition() { if (this.animate === 'none' && typeof this.position === 'string' && this.position !== 'center') { return positionTransitionMap[this.position]; } return "".concat(_variables.$prefix).concat(this.animate); } }, created: function created() { var _this = this; this.$on('hook:activated', function () { _this.rootStyle = {}; if (_this.hideOnDeactivated && _manager.default.isLock > 0) { document.body.style.overflow = 'hidden'; } }); this.$on('hook:deactivated', function () { if (_this.hideOnDeactivated) { _this.rootStyle = { display: 'none' }; if (_manager.default.isLock > 0) { document.body.style.overflow = ''; } } }); var resizeHandler = (0, _debounce.default)(function () { if (_this.documentVisible) { _this.computeDocAndAnchorRect(); } }); this.$on('hook:mounted', function () { _this.visible ? _this.open() : _this.close(); (0, _bindEvent.default)(_this, 'resize', resizeHandler); (0, _bindEvent.default)(_this, 'scroll', resizeHandler); }); this.$on('hook:beforeDestroy', function () { if (_this.documentVisible) { _this.close(); } }); }, methods: { // ⬇️ open api close: function close() { if (this.documentVisible) { this.documentVisible = false; this.$emit(POPUP_EVENT, this.documentVisible); this.$emit('close', this.documentVisible); this.startScroll(); } }, open: function open() { if (this.documentVisible) return; var maskZIndex; var documentZIndex; if (this.zIndex !== undefined) { maskZIndex = this.zIndex; documentZIndex = this.zIndex + 1; } else { var result = _manager.default.getPopupZIndex(); maskZIndex = result.maskZIndex; documentZIndex = result.documentZIndex; } this.maskZIndex = maskZIndex; this.documentZIndex = documentZIndex; this.documentVisible = true; this.stopScroll(); this.$emit('open', { visible: this.documentVisible, documentZIndex: this.documentZIndex, maskZIndex: this.maskZIndex }); }, // ⬆️ open api stopScroll: function stopScroll() { if (this.lockScroll) { _manager.default.isLock += 1; document.body.style.overflow = 'hidden'; } }, startScroll: function startScroll() { if (_manager.default.isLock === 0) return; if (this.lockScroll) { _manager.default.isLock -= 1; if (_manager.default.isLock <= 0) { document.body.style.overflow = ''; } } }, onMaskClick: function onMaskClick(e) { e.stopPropagation(); if (this.maskClosable) { this.close(); } }, onWrapperTouchstart: function onWrapperTouchstart(e) { if (this.closeOnMaskTouched) { this.close(); return; } var event = e.touches[0]; var el = e.target; var rootEl = this.$refs.document; if (rootEl) { var scrollEl = (0, _dom.getScrollEventTarget)(el, rootEl); this.touchData.scrollEl = scrollEl; this.touchData.pageY = event.pageY; this.touchData.scrollY = scrollEl.scrollTop; this.touchData.maxHeight = scrollEl.scrollHeight - scrollEl.clientHeight; } }, onWrapperTouchmove: function onWrapperTouchmove(e) { if (this.scrollBody) return; var scrollEl = this.touchData.scrollEl; var event = e.touches[0]; if (scrollEl) { var _this$touchData = this.touchData, pageY = _this$touchData.pageY, maxHeight = _this$touchData.maxHeight; var scrollTop = scrollEl.scrollTop; var distanceY = event.pageY - pageY; if (distanceY > 0 && scrollTop <= 0) { e.cancelable && e.preventDefault(); return; } if (distanceY < 0 && scrollTop + 1 >= maxHeight) { e.cancelable && e.preventDefault(); return; } } }, onWrapperTouchend: function onWrapperTouchend() { this.touchData.maxHeight = 0; this.touchData.pageY = 0; this.touchData.scrollEl = null; this.touchData.scrollY = 0; }, onAfterDocumentLeave: function onAfterDocumentLeave() { this.wrapperVisible = false; this.$emit('afterLeave', this.wrapperVisible); }, onBeforeDocumentEnter: function onBeforeDocumentEnter() { this.wrapperVisible = true; }, onDocumentClick: function onDocumentClick(e) { e.stopPropagation(); }, onDocumentTouch: function onDocumentTouch(e) { if (this.closeOnMaskTouched) { e.stopPropagation(); } }, onDocumentEnter: function onDocumentEnter(doc) { var _this2 = this; this.docEl = doc; this.$nextTick(function () { _this2.computeDocAndAnchorRect(); var enterEvent = {}; if (_this2.docRect) { enterEvent.doc = Object.assign({}, _this2.docPos, _this2.docRect); } if (_this2.anchorRect) { enterEvent.anchor = _this2.anchorRect; } _this2.$emit('enter', enterEvent); }); }, onDocumentAfterEnter: function onDocumentAfterEnter() { this.$emit('afterOpen'); }, computeDocAndAnchorRect: function computeDocAndAnchorRect() { if (this.docEl) { // use offsetWidth and offsetHeight, when getBoudingClientRect is not correct. this.docRect = (0, _utils.computeRect)(this.docEl); } if (this.anchor) { if (this.anchor instanceof Function) { this.anchorEl = this.anchor(); } else { this.anchorEl = this.anchor; } if (this.anchorEl) { this.anchorRect = this.anchorEl.getBoundingClientRect(); } } this.docPos = this.computeDocumentPosition(); }, renderMask: function renderMask() { var h = this.$createElement; var maskCls = this.$bem.block('mask').is(this.maskFrosted && 'frosted'); var maskStyle = { zIndex: this.maskZIndex.toString(), top: '0px', left: '0px' }; if (this.docPos) { if (this.partialMask === 'bottom') { maskStyle.height = 'auto'; maskStyle.top = "".concat(this.docPos.top, "px"); maskStyle.bottom = '0'; } else if (this.partialMask === 'top') { maskStyle.height = 'auto'; maskStyle.bottom = "".concat(this.docPos.bottom, "px"); maskStyle.top = '0'; } } var maskNode = h("div", { "directives": [{ name: "show", value: this.documentVisible }], "class": maskCls, "style": maskStyle }); if (this.maskAnimate !== 'none') { maskNode = h("transition", { "attrs": { "name": _variables.$prefix + this.maskAnimate } }, [maskNode]); } if (this.mask) { return maskNode; } }, computeDocumentPosition: function computeDocumentPosition() { var position = this.position, isAnchorMode = this.isAnchorMode; var top = 0; var left = 0; var transformOriginStr = ''; if (isAnchorMode) { var anchorRect = this.anchorRect, docRect = this.docRect; if (anchorRect) { // transform anchor position var anchorPos = (0, _utils.getAnchorPosition)(position); var anchorTop = anchorRect.top; var anchorLeft = anchorRect.left; if (anchorPos.horizontal === 'center') { anchorLeft = anchorLeft + anchorRect.width / 2; } else if (anchorPos.horizontal === 'right') { anchorLeft = anchorLeft + anchorRect.width; } if (anchorPos.vertical === 'center') { anchorTop = anchorTop + anchorRect.height / 2; } else if (anchorPos.vertical === 'bottom') { anchorTop = anchorTop + anchorRect.height; } var transformOrigin = (0, _utils.getTransformOrigin)(anchorPos, this.transformOrigin); transformOriginStr = (transformOrigin.vertical || 'top') + ' ' + (transformOrigin.horizontal || 'left'); var docOffsetX = 0; var docOffsetY = 0; if (docRect) { if (transformOrigin.horizontal === 'right') { docOffsetX = docRect.width; } else if (transformOrigin.horizontal === 'center') { docOffsetX = docRect.width / 2; } if (transformOrigin.vertical === 'bottom') { docOffsetY = docRect.height; } else if (transformOrigin.vertical === 'center') { docOffsetY = docRect.height / 2; } } top = anchorTop - docOffsetY; left = anchorLeft - docOffsetX; } } else if ((0, _utils.isAnyPosition)(position)) { position.left !== undefined && (left = position.left); position.top !== undefined && (top = position.top); } var lowerEdge = window.innerHeight - top; var rightEdge = window.innerWidth - left; if (this.docRect) { lowerEdge = lowerEdge - this.docRect.height; rightEdge = rightEdge - this.docRect.width; } // container edge detect if (this.edgeDetect) { var widthThreshold = window.innerWidth - this.marginThreshold; var heightThreshold = window.innerHeight - this.marginThreshold; if (this.docRect) { var bottom = top + this.docRect.height; var right = left + this.docRect.width; if (top < this.marginThreshold) { top = this.marginThreshold; } else if (bottom > heightThreshold) { top = heightThreshold - this.docRect.height; } if (left < this.marginThreshold) { left = this.marginThreshold; } else if (right > widthThreshold) { left = widthThreshold - this.docRect.width; } } } return { top: top, left: left, bottom: lowerEdge, right: rightEdge, transformOrigin: transformOriginStr }; }, getDocumentStyle: function getDocumentStyle() { var docStyle = {}; if (this.isAnchorMode) { docStyle = { position: 'absolute' }; if (this.docPos) { docStyle.top = "".concat(this.docPos.top, "px"); docStyle.left = "".concat(this.docPos.left, "px"); docStyle.transformOrigin = this.docPos.transformOrigin; } } if (this.targetStyle) { docStyle = _objectSpread(_objectSpread({}, docStyle), this.targetStyle); } return docStyle; }, renderDocument: function renderDocument() { var h = this.$createElement; var wrapperCls = this.$bem.block('popup-wrapper'); wrapperCls.is([this.tapThrough && 'tap-through', this.scrollBody && 'scrollable']); if (!this.isAnchorMode) { var _getAnchorPosition = (0, _utils.getAnchorPosition)(this.position), horizontal = _getAnchorPosition.horizontal, vertical = _getAnchorPosition.vertical; if (horizontal || vertical) { wrapperCls.has('position'); } if (horizontal) { wrapperCls.is("x-".concat(horizontal)); } if (vertical && !this.scrollBody) { wrapperCls.is("y-".concat(vertical)); } } var wrapperStyle = { zIndex: this.documentZIndex }; return h("div", { "directives": [{ name: "show", value: this.wrapperVisible }], "class": wrapperCls, "style": wrapperStyle, "attrs": { "role": "dialog", "tabindex": -1 }, "on": { "click": this.onMaskClick, "touchstart": this.onWrapperTouchstart, "touchmove": this.onWrapperTouchmove, "touchend": this.onWrapperTouchend } }, [h("transition", { "attrs": { "name": this.documentTransition }, "on": { "beforeEnter": this.onBeforeDocumentEnter, "enter": this.onDocumentEnter, "afterEnter": this.onDocumentAfterEnter, "afterLeave": this.onAfterDocumentLeave } }, [h("div", { "directives": [{ name: "show", value: this.documentVisible }], "attrs": { "role": "document" }, "ref": "document", "class": this.documentClass, "style": this.getDocumentStyle(), "on": { "touchstart": this.onDocumentTouch, "touchmove": this.onDocumentTouch, "touchend": this.onDocumentTouch, "click": this.onDocumentClick } }, [this.$slots.default])])]); } }, render: function render() { var h = arguments[0]; return h("div", { "attrs": { "role": "presentation" }, "style": this.rootStyle }, [this.renderMask(), this.renderDocument()]); } }); var _default = exports.default = Popup;