ether-admin/node_modules/ant-design-vue/lib/vc-trigger/Trigger.js

684 lines
22 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _vue = require("vue");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _interface = require("./interface");
var _contains = _interopRequireDefault(require("../vc-util/Dom/contains"));
var _raf = _interopRequireDefault(require("../_util/raf"));
var _propsUtil = require("../_util/props-util");
var _addEventListener = _interopRequireDefault(require("../vc-util/Dom/addEventListener"));
var _Popup = _interopRequireDefault(require("./Popup"));
var _alignUtil = require("./utils/alignUtil");
var _BaseMixin = _interopRequireDefault(require("../_util/BaseMixin"));
var _PortalWrapper = _interopRequireDefault(require("../_util/PortalWrapper"));
var _classNames = _interopRequireDefault(require("../_util/classNames"));
var _vnode = require("../_util/vnode");
var _supportsPassive = _interopRequireDefault(require("../_util/supportsPassive"));
var _context = require("./context");
const ALL_HANDLERS = ['onClick', 'onMousedown', 'onTouchstart', 'onMouseenter', 'onMouseleave', 'onFocus', 'onBlur', 'onContextmenu'];
var _default = exports.default = (0, _vue.defineComponent)({
compatConfig: {
MODE: 3
},
name: 'Trigger',
mixins: [_BaseMixin.default],
inheritAttrs: false,
props: (0, _interface.triggerProps)(),
setup(props) {
const align = (0, _vue.computed)(() => {
const {
popupPlacement,
popupAlign,
builtinPlacements
} = props;
if (popupPlacement && builtinPlacements) {
return (0, _alignUtil.getAlignFromPlacement)(builtinPlacements, popupPlacement, popupAlign);
}
return popupAlign;
});
const popupRef = (0, _vue.shallowRef)(null);
const setPopupRef = val => {
popupRef.value = val;
};
return {
vcTriggerContext: (0, _vue.inject)('vcTriggerContext', {}),
popupRef,
setPopupRef,
triggerRef: (0, _vue.shallowRef)(null),
align,
focusTime: null,
clickOutsideHandler: null,
contextmenuOutsideHandler1: null,
contextmenuOutsideHandler2: null,
touchOutsideHandler: null,
attachId: null,
delayTimer: null,
hasPopupMouseDown: false,
preClickTime: null,
preTouchTime: null,
mouseDownTimeout: null,
childOriginEvents: {}
};
},
data() {
const props = this.$props;
let popupVisible;
if (this.popupVisible !== undefined) {
popupVisible = !!props.popupVisible;
} else {
popupVisible = !!props.defaultPopupVisible;
}
ALL_HANDLERS.forEach(h => {
this[`fire${h}`] = e => {
this.fireEvents(h, e);
};
});
return {
prevPopupVisible: popupVisible,
sPopupVisible: popupVisible,
point: null
};
},
watch: {
popupVisible(val) {
if (val !== undefined) {
this.prevPopupVisible = this.sPopupVisible;
this.sPopupVisible = val;
}
}
},
created() {
(0, _vue.provide)('vcTriggerContext', {
onPopupMouseDown: this.onPopupMouseDown,
onPopupMouseenter: this.onPopupMouseenter,
onPopupMouseleave: this.onPopupMouseleave
});
(0, _context.useProvidePortal)(this);
},
deactivated() {
this.setPopupVisible(false);
},
mounted() {
this.$nextTick(() => {
this.updatedCal();
});
},
updated() {
this.$nextTick(() => {
this.updatedCal();
});
},
beforeUnmount() {
this.clearDelayTimer();
this.clearOutsideHandler();
clearTimeout(this.mouseDownTimeout);
_raf.default.cancel(this.attachId);
},
methods: {
updatedCal() {
const props = this.$props;
const state = this.$data;
// We must listen to `mousedown` or `touchstart`, edge case:
// https://github.com/ant-design/ant-design/issues/5804
// https://github.com/react-component/calendar/issues/250
// https://github.com/react-component/trigger/issues/50
if (state.sPopupVisible) {
let currentDocument;
if (!this.clickOutsideHandler && (this.isClickToHide() || this.isContextmenuToShow())) {
currentDocument = props.getDocument(this.getRootDomNode());
this.clickOutsideHandler = (0, _addEventListener.default)(currentDocument, 'mousedown', this.onDocumentClick);
}
// always hide on mobile
if (!this.touchOutsideHandler) {
currentDocument = currentDocument || props.getDocument(this.getRootDomNode());
this.touchOutsideHandler = (0, _addEventListener.default)(currentDocument, 'touchstart', this.onDocumentClick, _supportsPassive.default ? {
passive: false
} : false);
}
// close popup when trigger type contains 'onContextmenu' and document is scrolling.
if (!this.contextmenuOutsideHandler1 && this.isContextmenuToShow()) {
currentDocument = currentDocument || props.getDocument(this.getRootDomNode());
this.contextmenuOutsideHandler1 = (0, _addEventListener.default)(currentDocument, 'scroll', this.onContextmenuClose);
}
// close popup when trigger type contains 'onContextmenu' and window is blur.
if (!this.contextmenuOutsideHandler2 && this.isContextmenuToShow()) {
this.contextmenuOutsideHandler2 = (0, _addEventListener.default)(window, 'blur', this.onContextmenuClose);
}
} else {
this.clearOutsideHandler();
}
},
onMouseenter(e) {
const {
mouseEnterDelay
} = this.$props;
this.fireEvents('onMouseenter', e);
this.delaySetPopupVisible(true, mouseEnterDelay, mouseEnterDelay ? null : e);
},
onMouseMove(e) {
this.fireEvents('onMousemove', e);
this.setPoint(e);
},
onMouseleave(e) {
this.fireEvents('onMouseleave', e);
this.delaySetPopupVisible(false, this.$props.mouseLeaveDelay);
},
onPopupMouseenter() {
const {
vcTriggerContext = {}
} = this;
if (vcTriggerContext.onPopupMouseenter) {
vcTriggerContext.onPopupMouseenter();
}
this.clearDelayTimer();
},
onPopupMouseleave(e) {
var _a;
if (e && e.relatedTarget && !e.relatedTarget.setTimeout && (0, _contains.default)((_a = this.popupRef) === null || _a === void 0 ? void 0 : _a.getElement(), e.relatedTarget)) {
return;
}
if (this.isMouseLeaveToHide()) {
this.delaySetPopupVisible(false, this.$props.mouseLeaveDelay);
}
const {
vcTriggerContext = {}
} = this;
if (vcTriggerContext.onPopupMouseleave) {
vcTriggerContext.onPopupMouseleave(e);
}
},
onFocus(e) {
this.fireEvents('onFocus', e);
// incase focusin and focusout
this.clearDelayTimer();
if (this.isFocusToShow()) {
this.focusTime = Date.now();
this.delaySetPopupVisible(true, this.$props.focusDelay);
}
},
onMousedown(e) {
this.fireEvents('onMousedown', e);
this.preClickTime = Date.now();
},
onTouchstart(e) {
this.fireEvents('onTouchstart', e);
this.preTouchTime = Date.now();
},
onBlur(e) {
if (!(0, _contains.default)(e.target, e.relatedTarget || document.activeElement)) {
this.fireEvents('onBlur', e);
this.clearDelayTimer();
if (this.isBlurToHide()) {
this.delaySetPopupVisible(false, this.$props.blurDelay);
}
}
},
onContextmenu(e) {
e.preventDefault();
this.fireEvents('onContextmenu', e);
this.setPopupVisible(true, e);
},
onContextmenuClose() {
if (this.isContextmenuToShow()) {
this.close();
}
},
onClick(event) {
this.fireEvents('onClick', event);
// focus will trigger click
if (this.focusTime) {
let preTime;
if (this.preClickTime && this.preTouchTime) {
preTime = Math.min(this.preClickTime, this.preTouchTime);
} else if (this.preClickTime) {
preTime = this.preClickTime;
} else if (this.preTouchTime) {
preTime = this.preTouchTime;
}
if (Math.abs(preTime - this.focusTime) < 20) {
return;
}
this.focusTime = 0;
}
this.preClickTime = 0;
this.preTouchTime = 0;
// Only prevent default when all the action is click.
// https://github.com/ant-design/ant-design/issues/17043
// https://github.com/ant-design/ant-design/issues/17291
if (this.isClickToShow() && (this.isClickToHide() || this.isBlurToHide()) && event && event.preventDefault) {
event.preventDefault();
}
if (event && event.domEvent) {
event.domEvent.preventDefault();
}
const nextVisible = !this.$data.sPopupVisible;
if (this.isClickToHide() && !nextVisible || nextVisible && this.isClickToShow()) {
this.setPopupVisible(!this.$data.sPopupVisible, event);
}
},
onPopupMouseDown() {
const {
vcTriggerContext = {}
} = this;
this.hasPopupMouseDown = true;
clearTimeout(this.mouseDownTimeout);
this.mouseDownTimeout = setTimeout(() => {
this.hasPopupMouseDown = false;
}, 0);
if (vcTriggerContext.onPopupMouseDown) {
vcTriggerContext.onPopupMouseDown(...arguments);
}
},
onDocumentClick(event) {
if (this.$props.mask && !this.$props.maskClosable) {
return;
}
const target = event.target;
const root = this.getRootDomNode();
const popupNode = this.getPopupDomNode();
if (
// mousedown on the target should also close popup when action is contextMenu.
// https://github.com/ant-design/ant-design/issues/29853
(!(0, _contains.default)(root, target) || this.isContextMenuOnly()) && !(0, _contains.default)(popupNode, target) && !this.hasPopupMouseDown) {
// https://github.com/vuejs/core/issues/4462
// vue 动画bug导致 https://github.com/vueComponent/ant-design-vue/issues/5259
// 改成延时解决
this.delaySetPopupVisible(false, 0.1);
}
},
getPopupDomNode() {
var _a;
// for test
return ((_a = this.popupRef) === null || _a === void 0 ? void 0 : _a.getElement()) || null;
},
getRootDomNode() {
var _a, _b, _c, _d;
const {
getTriggerDOMNode
} = this.$props;
if (getTriggerDOMNode) {
const domNode = ((_b = (_a = this.triggerRef) === null || _a === void 0 ? void 0 : _a.$el) === null || _b === void 0 ? void 0 : _b.nodeName) === '#comment' ? null : (0, _propsUtil.findDOMNode)(this.triggerRef);
return (0, _propsUtil.findDOMNode)(getTriggerDOMNode(domNode));
}
try {
const domNode = ((_d = (_c = this.triggerRef) === null || _c === void 0 ? void 0 : _c.$el) === null || _d === void 0 ? void 0 : _d.nodeName) === '#comment' ? null : (0, _propsUtil.findDOMNode)(this.triggerRef);
if (domNode) {
return domNode;
}
} catch (err) {
// Do nothing
}
return (0, _propsUtil.findDOMNode)(this);
},
handleGetPopupClassFromAlign(align) {
const className = [];
const props = this.$props;
const {
popupPlacement,
builtinPlacements,
prefixCls,
alignPoint,
getPopupClassNameFromAlign
} = props;
if (popupPlacement && builtinPlacements) {
className.push((0, _alignUtil.getAlignPopupClassName)(builtinPlacements, prefixCls, align, alignPoint));
}
if (getPopupClassNameFromAlign) {
className.push(getPopupClassNameFromAlign(align));
}
return className.join(' ');
},
getPopupAlign() {
const props = this.$props;
const {
popupPlacement,
popupAlign,
builtinPlacements
} = props;
if (popupPlacement && builtinPlacements) {
return (0, _alignUtil.getAlignFromPlacement)(builtinPlacements, popupPlacement, popupAlign);
}
return popupAlign;
},
getComponent() {
const mouseProps = {};
if (this.isMouseEnterToShow()) {
mouseProps.onMouseenter = this.onPopupMouseenter;
}
if (this.isMouseLeaveToHide()) {
mouseProps.onMouseleave = this.onPopupMouseleave;
}
mouseProps.onMousedown = this.onPopupMouseDown;
mouseProps[_supportsPassive.default ? 'onTouchstartPassive' : 'onTouchstart'] = this.onPopupMouseDown;
const {
handleGetPopupClassFromAlign,
getRootDomNode,
$attrs
} = this;
const {
prefixCls,
destroyPopupOnHide,
popupClassName,
popupAnimation,
popupTransitionName,
popupStyle,
mask,
maskAnimation,
maskTransitionName,
zIndex,
stretch,
alignPoint,
mobile,
arrow,
forceRender
} = this.$props;
const {
sPopupVisible,
point
} = this.$data;
const popupProps = (0, _extends2.default)((0, _extends2.default)({
prefixCls,
arrow,
destroyPopupOnHide,
visible: sPopupVisible,
point: alignPoint ? point : null,
align: this.align,
animation: popupAnimation,
getClassNameFromAlign: handleGetPopupClassFromAlign,
stretch,
getRootDomNode,
mask,
zIndex,
transitionName: popupTransitionName,
maskAnimation,
maskTransitionName,
class: popupClassName,
style: popupStyle,
onAlign: $attrs.onPopupAlign || _interface.noop
}, mouseProps), {
ref: this.setPopupRef,
mobile,
forceRender
});
return (0, _vue.createVNode)(_Popup.default, popupProps, {
default: this.$slots.popup || (() => (0, _propsUtil.getComponent)(this, 'popup'))
});
},
attachParent(popupContainer) {
_raf.default.cancel(this.attachId);
const {
getPopupContainer,
getDocument
} = this.$props;
const domNode = this.getRootDomNode();
let mountNode;
if (!getPopupContainer) {
mountNode = getDocument(this.getRootDomNode()).body;
} else if (domNode || getPopupContainer.length === 0) {
// Compatible for legacy getPopupContainer with domNode argument.
// If no need `domNode` argument, will call directly.
// https://codesandbox.io/s/eloquent-mclean-ss93m?file=/src/App.js
mountNode = getPopupContainer(domNode);
}
if (mountNode) {
mountNode.appendChild(popupContainer);
} else {
// Retry after frame render in case parent not ready
this.attachId = (0, _raf.default)(() => {
this.attachParent(popupContainer);
});
}
},
getContainer() {
const {
$props: props
} = this;
const {
getDocument
} = props;
const popupContainer = getDocument(this.getRootDomNode()).createElement('div');
// Make sure default popup container will never cause scrollbar appearing
// https://github.com/react-component/trigger/issues/41
popupContainer.style.position = 'absolute';
popupContainer.style.top = '0';
popupContainer.style.left = '0';
popupContainer.style.width = '100%';
this.attachParent(popupContainer);
return popupContainer;
},
setPopupVisible(sPopupVisible, event) {
const {
alignPoint,
sPopupVisible: prevPopupVisible,
onPopupVisibleChange
} = this;
this.clearDelayTimer();
if (prevPopupVisible !== sPopupVisible) {
if (!(0, _propsUtil.hasProp)(this, 'popupVisible')) {
this.setState({
sPopupVisible,
prevPopupVisible
});
}
onPopupVisibleChange && onPopupVisibleChange(sPopupVisible);
}
// Always record the point position since mouseEnterDelay will delay the show
if (alignPoint && event && sPopupVisible) {
this.setPoint(event);
}
},
setPoint(point) {
const {
alignPoint
} = this.$props;
if (!alignPoint || !point) return;
this.setState({
point: {
pageX: point.pageX,
pageY: point.pageY
}
});
},
handlePortalUpdate() {
if (this.prevPopupVisible !== this.sPopupVisible) {
this.afterPopupVisibleChange(this.sPopupVisible);
}
},
delaySetPopupVisible(visible, delayS, event) {
const delay = delayS * 1000;
this.clearDelayTimer();
if (delay) {
const point = event ? {
pageX: event.pageX,
pageY: event.pageY
} : null;
this.delayTimer = setTimeout(() => {
this.setPopupVisible(visible, point);
this.clearDelayTimer();
}, delay);
} else {
this.setPopupVisible(visible, event);
}
},
clearDelayTimer() {
if (this.delayTimer) {
clearTimeout(this.delayTimer);
this.delayTimer = null;
}
},
clearOutsideHandler() {
if (this.clickOutsideHandler) {
this.clickOutsideHandler.remove();
this.clickOutsideHandler = null;
}
if (this.contextmenuOutsideHandler1) {
this.contextmenuOutsideHandler1.remove();
this.contextmenuOutsideHandler1 = null;
}
if (this.contextmenuOutsideHandler2) {
this.contextmenuOutsideHandler2.remove();
this.contextmenuOutsideHandler2 = null;
}
if (this.touchOutsideHandler) {
this.touchOutsideHandler.remove();
this.touchOutsideHandler = null;
}
},
createTwoChains(event) {
let fn = () => {};
const events = (0, _propsUtil.getEvents)(this);
if (this.childOriginEvents[event] && events[event]) {
return this[`fire${event}`];
}
fn = this.childOriginEvents[event] || events[event] || fn;
return fn;
},
isClickToShow() {
const {
action,
showAction
} = this.$props;
return action.indexOf('click') !== -1 || showAction.indexOf('click') !== -1;
},
isContextMenuOnly() {
const {
action
} = this.$props;
return action === 'contextmenu' || action.length === 1 && action[0] === 'contextmenu';
},
isContextmenuToShow() {
const {
action,
showAction
} = this.$props;
return action.indexOf('contextmenu') !== -1 || showAction.indexOf('contextmenu') !== -1;
},
isClickToHide() {
const {
action,
hideAction
} = this.$props;
return action.indexOf('click') !== -1 || hideAction.indexOf('click') !== -1;
},
isMouseEnterToShow() {
const {
action,
showAction
} = this.$props;
return action.indexOf('hover') !== -1 || showAction.indexOf('mouseenter') !== -1;
},
isMouseLeaveToHide() {
const {
action,
hideAction
} = this.$props;
return action.indexOf('hover') !== -1 || hideAction.indexOf('mouseleave') !== -1;
},
isFocusToShow() {
const {
action,
showAction
} = this.$props;
return action.indexOf('focus') !== -1 || showAction.indexOf('focus') !== -1;
},
isBlurToHide() {
const {
action,
hideAction
} = this.$props;
return action.indexOf('focus') !== -1 || hideAction.indexOf('blur') !== -1;
},
forcePopupAlign() {
var _a;
if (this.$data.sPopupVisible) {
(_a = this.popupRef) === null || _a === void 0 ? void 0 : _a.forceAlign();
}
},
fireEvents(type, e) {
if (this.childOriginEvents[type]) {
this.childOriginEvents[type](e);
}
const event = this.$props[type] || this.$attrs[type];
if (event) {
event(e);
}
},
close() {
this.setPopupVisible(false);
}
},
render() {
const {
$attrs
} = this;
const children = (0, _propsUtil.filterEmpty)((0, _propsUtil.getSlot)(this));
const {
alignPoint,
getPopupContainer
} = this.$props;
const child = children[0];
this.childOriginEvents = (0, _propsUtil.getEvents)(child);
const newChildProps = {
key: 'trigger'
};
if (this.isContextmenuToShow()) {
newChildProps.onContextmenu = this.onContextmenu;
} else {
newChildProps.onContextmenu = this.createTwoChains('onContextmenu');
}
if (this.isClickToHide() || this.isClickToShow()) {
newChildProps.onClick = this.onClick;
newChildProps.onMousedown = this.onMousedown;
newChildProps[_supportsPassive.default ? 'onTouchstartPassive' : 'onTouchstart'] = this.onTouchstart;
} else {
newChildProps.onClick = this.createTwoChains('onClick');
newChildProps.onMousedown = this.createTwoChains('onMousedown');
newChildProps[_supportsPassive.default ? 'onTouchstartPassive' : 'onTouchstart'] = this.createTwoChains('onTouchstart');
}
if (this.isMouseEnterToShow()) {
newChildProps.onMouseenter = this.onMouseenter;
if (alignPoint) {
newChildProps.onMousemove = this.onMouseMove;
}
} else {
newChildProps.onMouseenter = this.createTwoChains('onMouseenter');
}
if (this.isMouseLeaveToHide()) {
newChildProps.onMouseleave = this.onMouseleave;
} else {
newChildProps.onMouseleave = this.createTwoChains('onMouseleave');
}
if (this.isFocusToShow() || this.isBlurToHide()) {
newChildProps.onFocus = this.onFocus;
newChildProps.onBlur = this.onBlur;
} else {
newChildProps.onFocus = this.createTwoChains('onFocus');
newChildProps.onBlur = e => {
if (e && (!e.relatedTarget || !(0, _contains.default)(e.target, e.relatedTarget))) {
this.createTwoChains('onBlur')(e);
}
};
}
const childrenClassName = (0, _classNames.default)(child && child.props && child.props.class, $attrs.class);
if (childrenClassName) {
newChildProps.class = childrenClassName;
}
const trigger = (0, _vnode.cloneElement)(child, (0, _extends2.default)((0, _extends2.default)({}, newChildProps), {
ref: 'triggerRef'
}), true, true);
const portal = (0, _vue.createVNode)(_PortalWrapper.default, {
"key": "portal",
"getContainer": getPopupContainer && (() => getPopupContainer(this.getRootDomNode())),
"didUpdate": this.handlePortalUpdate,
"visible": this.$data.sPopupVisible
}, {
default: this.getComponent
});
return (0, _vue.createVNode)(_vue.Fragment, null, [trigger, portal]);
}
});