@ohu-mobile/core
Version:
491 lines (490 loc) • 18.3 kB
JavaScript
"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;