diff --git a/components/tooltip/Tooltip.jsx b/components/tooltip/Tooltip.jsx
index 4cc15af6b..ccf580e03 100644
--- a/components/tooltip/Tooltip.jsx
+++ b/components/tooltip/Tooltip.jsx
@@ -1,15 +1,16 @@
-import { inject, cloneVNode, isVNode } from 'vue';
+import { inject } from 'vue';
import VcTooltip from '../vc-tooltip';
import getPlacements from './placements';
import PropTypes from '../_util/vue-types';
import {
hasProp,
getComponent,
- getClass,
getStyle,
filterEmpty,
getSlot,
+ isValidElement,
} from '../_util/props-util';
+import { cloneElement } from '../_util/vnode';
import { ConfigConsumerProps } from '../config-provider';
import abstractTooltipProps from './abstractTooltipProps';
@@ -27,6 +28,7 @@ const splitObject = (obj, keys) => {
const props = abstractTooltipProps();
export default {
name: 'ATooltip',
+ inheritAttrs: false,
model: {
prop: 'visible',
event: 'visibleChange',
@@ -80,18 +82,14 @@ export default {
// mouse events don't trigger at disabled button in Chrome
// https://github.com/react-component/tooltip/issues/18
getDisabledCompatibleChildren(ele) {
- const options = (ele.componentOptions && ele.componentOptions.Ctor.options) || {};
-
if (
- ((options.__ANT_BUTTON === true ||
- options.__ANT_SWITCH === true ||
- options.__ANT_CHECKBOX === true) &&
- (ele.componentOptions.propsData.disabled ||
- ele.componentOptions.propsData.disabled === '')) ||
- (ele.tag === 'button' &&
- ele.data &&
- ele.data.attrs &&
- ele.data.attrs.disabled !== undefined)
+ ((typeof ele.type === 'object' &&
+ (ele.type.__ANT_BUTTON === true ||
+ ele.type.__ANT_SWITCH === true ||
+ ele.type.__ANT_CHECKBOX === true)) ||
+ ele.type === 'button') &&
+ ele.props &&
+ (ele.props.disabled || ele.props.disabled === '')
) {
// Pick some layout related style properties up to span
// Prevent layout bugs like https://github.com/ant-design/ant-design/issues/5254
@@ -115,16 +113,14 @@ export default {
...omitted,
pointerEvents: 'none',
};
- const spanCls = getClass(ele);
- const child = cloneVNode(ele, {
- style: buttonStyle,
- class: null,
- });
- return (
-
- {child}
-
+ const child = cloneElement(
+ ele,
+ {
+ style: buttonStyle,
+ },
+ true,
);
+ return {child};
}
return ele;
},
@@ -191,10 +187,11 @@ export default {
return null;
}
const child = this.getDisabledCompatibleChildren(
- isVNode(children) ? children : {children},
+ isValidElement(children) ? children : {children},
);
const childCls = {
[openClassName || `${prefixCls}-open`]: true,
+ [child.props && child.props.class]: child.props && child.props.class,
};
const tooltipProps = {
...$attrs,
@@ -210,7 +207,7 @@ export default {
};
return (
- {sVisible ? cloneVNode(child, { class: childCls }) : child}
+ {sVisible ? cloneElement(child, { class: childCls }) : child}
);
},
diff --git a/components/vc-tooltip/Content.jsx b/components/vc-tooltip/Content.jsx
index ddcf3b8c4..2665d3555 100644
--- a/components/vc-tooltip/Content.jsx
+++ b/components/vc-tooltip/Content.jsx
@@ -1,6 +1,7 @@
import PropTypes from '../_util/vue-types';
export default {
+ name: 'Content',
props: {
prefixCls: PropTypes.string,
overlay: PropTypes.any,
diff --git a/components/vc-tooltip/Tooltip.jsx b/components/vc-tooltip/Tooltip.jsx
index 5f28d4168..7dc609a75 100644
--- a/components/vc-tooltip/Tooltip.jsx
+++ b/components/vc-tooltip/Tooltip.jsx
@@ -5,6 +5,8 @@ import Content from './Content';
import { hasProp, getComponent, getOptionProps } from '../_util/props-util';
function noop() {}
export default {
+ name: 'Tooltip',
+ inheritAttrs: false,
props: {
trigger: PropTypes.any.def(['hover']),
defaultVisible: PropTypes.bool,
@@ -91,12 +93,8 @@ export default {
onPopupVisibleChange: $attrs.onVisibleChange || noop,
onPopupAlign: $attrs.onPopupAlign || noop,
ref: 'trigger',
+ popup: this.getPopupElement(),
};
- return (
-
- {this.getPopupElement()}
- {this.$slots.default && this.$slots.default()}
-
- );
+ return {this.$slots.default && this.$slots.default()[0]};
},
};
diff --git a/components/vc-trigger/LazyRenderBox.jsx b/components/vc-trigger/LazyRenderBox.jsx
index df7c1932d..36c936027 100644
--- a/components/vc-trigger/LazyRenderBox.jsx
+++ b/components/vc-trigger/LazyRenderBox.jsx
@@ -1,20 +1,22 @@
import PropTypes from '../_util/vue-types';
export default {
+ name: 'LazyRenderBox',
+ inheritAttrs: false,
props: {
visible: PropTypes.bool,
hiddenClassName: PropTypes.string,
},
render() {
- const { hiddenClassName, visible } = this.$props;
+ const { hiddenClassName } = this.$props;
const child = this.$slots.default && this.$slots.default();
if (hiddenClassName || (child && child.length > 1)) {
- const cls = '';
- if (!visible && hiddenClassName) {
- // cls += ` ${hiddenClassName}`
- }
- return
{child}
;
+ // const cls = '';
+ // if (!visible && hiddenClassName) {
+ // // cls += ` ${hiddenClassName}`
+ // }
+ return {child}
;
}
- return child;
+ return child && child[0];
},
};
diff --git a/components/vc-trigger/Popup.jsx b/components/vc-trigger/Popup.jsx
index 7f7390d1d..32d04f94e 100644
--- a/components/vc-trigger/Popup.jsx
+++ b/components/vc-trigger/Popup.jsx
@@ -5,7 +5,7 @@ import PopupInner from './PopupInner';
import LazyRenderBox from './LazyRenderBox';
import animate from '../_util/css-animation';
import BaseMixin from '../_util/BaseMixin';
-import { getListeners } from '../_util/props-util';
+import { getListeners, splitAttrs } from '../_util/props-util';
export default {
name: 'VCTriggerPopup',
@@ -35,6 +35,7 @@ export default {
},
data() {
this.domEl = null;
+ this.currentAlignClassName = undefined;
return {
// Used for stretch
stretchChecked: false,
@@ -152,12 +153,15 @@ export default {
},
getClassName(currentAlignClassName) {
- return `${this.$props.prefixCls} ${this.$props.popupClassName} ${currentAlignClassName}`;
+ return `${this.$props.prefixCls} ${this.$attrs.class || ''} ${
+ this.$props.popupClassName
+ } ${currentAlignClassName}`;
},
getPopupElement() {
- const { $props: props, $slots, getTransitionName } = this;
+ const { $props: props, $attrs, $slots, getTransitionName } = this;
const { stretchChecked, targetHeight, targetWidth } = this.$data;
-
+ const { style = {} } = $attrs;
+ const onEvents = splitAttrs($attrs).onEvents;
const {
align,
visible,
@@ -200,30 +204,26 @@ export default {
}
}
const popupInnerProps = {
- props: {
- prefixCls,
- visible,
- // hiddenClassName,
- },
+ prefixCls,
+ visible,
+ // hiddenClassName,
class: className,
- on: getListeners(this),
+ ...onEvents,
ref: 'popupInstance',
- style: { ...sizeStyle, ...popupStyle, ...this.getZIndexStyle() },
+ style: { ...sizeStyle, ...popupStyle, ...style, ...this.getZIndexStyle() },
};
let transitionProps = {
- props: {
- appear: true,
- css: false,
- },
+ appear: true,
+ css: false,
};
const transitionName = getTransitionName();
let useTransition = !!transitionName;
const transitionEvent = {
- beforeEnter: () => {
+ onBeforeEnter: () => {
// el.style.display = el.__vOriginalDisplay
// this.$refs.alignInstance.forceAlign();
},
- enter: (el, done) => {
+ onEnter: (el, done) => {
// render 后 vue 会移除通过animate动态添加的 class导致动画闪动,延迟两帧添加动画class,可以进一步定位或者重写 transition 组件
this.$nextTick(() => {
if (this.$refs.alignInstance) {
@@ -236,21 +236,17 @@ export default {
}
});
},
- beforeLeave: () => {
+ onBeforeLeave: () => {
this.domEl = null;
},
- leave: (el, done) => {
+ onLeave: (el, done) => {
animate(el, `${transitionName}-leave`, done);
},
};
-
+ transitionProps = { ...transitionProps, ...transitionEvent };
if (typeof animation === 'object') {
useTransition = true;
- const { on = {}, props = {} } = animation;
- transitionProps.props = { ...transitionProps.props, ...props };
- transitionProps.on = { ...transitionEvent, ...on };
- } else {
- transitionProps.on = transitionEvent;
+ transitionProps = { ...transitionProps, ...animation };
}
if (!useTransition) {
transitionProps = {};
@@ -267,7 +263,7 @@ export default {
align={align}
onAlign={this.onAlign}
>
- {$slots.default}
+ {$slots.default && $slots.default()}
) : null}
@@ -285,7 +281,7 @@ export default {
align={align}
onAlign={this.onAlign}
>
- {$slots.default}
+ {$slots.default && $slots.default()}
);
diff --git a/components/vc-trigger/Trigger.jsx b/components/vc-trigger/Trigger.jsx
index 3c959fad1..d052ee767 100644
--- a/components/vc-trigger/Trigger.jsx
+++ b/components/vc-trigger/Trigger.jsx
@@ -1,15 +1,8 @@
-import { cloneVNode, inject, provide } from 'vue';
-import ref from 'vue-ref';
+import { inject, provide } from 'vue';
+import antRef from '../_util/ant-ref';
import PropTypes from '../_util/vue-types';
import contains from '../vc-util/Dom/contains';
-import {
- hasProp,
- getComponentFromProp,
- getEvents,
- filterEmpty,
- getSlot,
- getListeners,
-} from '../_util/props-util';
+import { hasProp, getComponent, getEvents, filterEmpty, getSlot } from '../_util/props-util';
import { requestAnimationTimeout, cancelAnimationTimeout } from '../_util/requestAnimationTimeout';
import addEventListener from '../vc-util/Dom/addEventListener';
import warning from '../_util/warning';
@@ -17,6 +10,9 @@ import Popup from './Popup';
import { getAlignFromPlacement, getAlignPopupClassName, noop } from './utils';
import BaseMixin from '../_util/BaseMixin';
import Portal from '../_util/Portal';
+import classNames from 'classnames';
+import { cloneElement } from '../_util/vnode';
+import createRefHooks from '../_util/createRefHooks';
function returnEmptyString() {
return '';
@@ -38,7 +34,7 @@ const ALL_HANDLERS = [
export default {
name: 'Trigger',
- directives: { 'ant-ref': ref },
+ directives: { 'ant-ref': antRef },
mixins: [BaseMixin],
inheritAttrs: false,
props: {
@@ -89,6 +85,7 @@ export default {
this.fireEvents(h, e);
};
});
+ this._component = null;
return {
prevPopupVisible: popupVisible,
sPopupVisible: popupVisible,
@@ -328,8 +325,7 @@ export default {
},
getRootDomNode() {
- return this.$el;
- // return this.$el.children[0] || this.$el
+ return this.$refs.trigger.$el || this.$refs.trigger;
},
handleGetPopupClassFromAlign(align) {
@@ -367,14 +363,14 @@ export default {
const self = this;
const mouseProps = {};
if (this.isMouseEnterToShow()) {
- mouseProps.mouseenter = self.onPopupMouseenter;
+ mouseProps.onMouseenter = self.onPopupMouseenter;
}
if (this.isMouseLeaveToHide()) {
- mouseProps.mouseleave = self.onPopupMouseleave;
+ mouseProps.onMouseleave = self.onPopupMouseleave;
}
- mouseProps.mousedown = this.onPopupMouseDown;
- mouseProps.touchstart = this.onPopupMouseDown;
- const { handleGetPopupClassFromAlign, getRootDomNode, getContainer } = self;
+ mouseProps.onMousedown = this.onPopupMouseDown;
+ mouseProps.onTouchstart = this.onPopupMouseDown;
+ const { handleGetPopupClassFromAlign, getRootDomNode, getContainer, $attrs } = self;
const {
prefixCls,
destroyPopupOnHide,
@@ -393,34 +389,31 @@ export default {
const { sPopupVisible, point } = this.$data;
const align = this.getPopupAlign();
const popupProps = {
- props: {
- prefixCls,
- destroyPopupOnHide,
- visible: sPopupVisible,
- point: alignPoint && point,
- action,
- align,
- animation: popupAnimation,
- getClassNameFromAlign: handleGetPopupClassFromAlign,
- stretch,
- getRootDomNode,
- mask,
- zIndex,
- transitionName: popupTransitionName,
- maskAnimation,
- maskTransitionName,
- getContainer,
- popupClassName,
- popupStyle,
- },
- on: {
- align: getListeners(this).popupAlign || noop,
- ...mouseProps,
- },
+ prefixCls,
+ destroyPopupOnHide,
+ visible: sPopupVisible,
+ point: alignPoint && point,
+ action,
+ align,
+ animation: popupAnimation,
+ getClassNameFromAlign: handleGetPopupClassFromAlign,
+ stretch,
+ getRootDomNode,
+ mask,
+ zIndex,
+ transitionName: popupTransitionName,
+ maskAnimation,
+ maskTransitionName,
+ getContainer,
+ popupClassName,
+ popupStyle,
+ onAlign: $attrs.onPopupAlign || noop,
+ ...mouseProps,
+ ...createRefHooks(this.savePopup),
};
return (
-
- {getComponentFromProp(self, 'popup')}
+
+ {getComponent(self, 'popup')}
);
},
@@ -521,7 +514,7 @@ export default {
createTwoChains(event) {
let fn = () => {};
- const events = getListeners(this);
+ const events = getEvents(this);
if (this.childOriginEvents[event] && events[event]) {
return this[`fire${event}`];
}
@@ -564,8 +557,8 @@ export default {
return action.indexOf('focus') !== -1 || hideAction.indexOf('blur') !== -1;
},
forcePopupAlign() {
- if (this.$data.sPopupVisible && this._component && this._component.$refs.alignInstance) {
- this._component.$refs.alignInstance.forceAlign();
+ if (this.$data.sPopupVisible && this._component && this._component.refs.alignInstance) {
+ this._component.refs.alignInstance.forceAlign();
}
},
fireEvents(type, e) {
@@ -591,7 +584,7 @@ export default {
this.childOriginEvents = getEvents(this);
const newChildProps = {
key: 'trigger',
- class: $attrs.class,
+ ref: 'trigger',
};
if (this.isContextmenuToShow()) {
@@ -634,8 +627,11 @@ export default {
}
};
}
-
- const trigger = cloneVNode(child, newChildProps);
+ const childrenClassName = classNames(child && child.props && child.props.class, $attrs.class);
+ if (childrenClassName) {
+ newChildProps.class = childrenClassName;
+ }
+ const trigger = cloneElement(child, newChildProps);
let portal;
// prevent unmounting after it's rendered
if (sPopupVisible || this._component || forceRender) {
diff --git a/components/vc-trigger/t.js b/components/vc-trigger/t.js
deleted file mode 100644
index 14aa67a21..000000000
--- a/components/vc-trigger/t.js
+++ /dev/null
@@ -1,654 +0,0 @@
-import { cloneVNode, inject, provide } from 'vue';
-import ref from 'vue-ref';
-import PropTypes from '../_util/vue-types';
-import contains from '../vc-util/Dom/contains';
-import {
- hasProp,
- getComponentFromProp,
- getEvents,
- filterEmpty,
- getSlot,
- getListeners,
-} from '../_util/props-util';
-import { requestAnimationTimeout, cancelAnimationTimeout } from '../_util/requestAnimationTimeout';
-import addEventListener from '../vc-util/Dom/addEventListener';
-import warning from '../_util/warning';
-import Popup from './Popup';
-import { getAlignFromPlacement, getAlignPopupClassName, noop } from './utils';
-import BaseMixin from '../_util/BaseMixin';
-import Portal from '../_util/Portal';
-
-function returnEmptyString() {
- return '';
-}
-
-function returnDocument() {
- return window.document;
-}
-const ALL_HANDLERS = [
- 'click',
- 'mousedown',
- 'touchstart',
- 'mouseenter',
- 'mouseleave',
- 'focus',
- 'blur',
- 'contextmenu',
-];
-
-export default {
- name: 'Trigger',
- directives: { 'ant-ref': ref },
- mixins: [BaseMixin],
- props: {
- action: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]).def([]),
- showAction: PropTypes.any.def([]),
- hideAction: PropTypes.any.def([]),
- getPopupClassNameFromAlign: PropTypes.any.def(returnEmptyString),
- // onPopupVisibleChange: PropTypes.func.def(noop),
- afterPopupVisibleChange: PropTypes.func.def(noop),
- popup: PropTypes.any,
- popupStyle: PropTypes.object.def(() => ({})),
- prefixCls: PropTypes.string.def('rc-trigger-popup'),
- popupClassName: PropTypes.string.def(''),
- popupPlacement: PropTypes.string,
- builtinPlacements: PropTypes.object,
- popupTransitionName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
- popupAnimation: PropTypes.any,
- mouseEnterDelay: PropTypes.number.def(0),
- mouseLeaveDelay: PropTypes.number.def(0.1),
- zIndex: PropTypes.number,
- focusDelay: PropTypes.number.def(0),
- blurDelay: PropTypes.number.def(0.15),
- getPopupContainer: PropTypes.func,
- getDocument: PropTypes.func.def(returnDocument),
- forceRender: PropTypes.bool,
- destroyPopupOnHide: PropTypes.bool.def(false),
- mask: PropTypes.bool.def(false),
- maskClosable: PropTypes.bool.def(true),
- // onPopupAlign: PropTypes.func.def(noop),
- popupAlign: PropTypes.object.def(() => ({})),
- popupVisible: PropTypes.bool,
- defaultPopupVisible: PropTypes.bool.def(false),
- maskTransitionName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
- maskAnimation: PropTypes.string,
- stretch: PropTypes.string,
- alignPoint: PropTypes.bool, // Maybe we can support user pass position in the future
- },
- data() {
- const props = this.$props;
- let popupVisible;
- if (hasProp(this, 'popupVisible')) {
- 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() {
- provide('vcTriggerContext', this);
- },
- setup() {
- return {
- vcTriggerContext: inject('configProvider', {}),
- savePopupRef: inject('vcTriggerContext', noop),
- dialogContext: inject('dialogContext', null),
- };
- },
- deactivated() {
- this.setPopupVisible(false);
- },
- mounted() {
- this.$nextTick(() => {
- this.updatedCal();
- });
- },
-
- updated() {
- this.$nextTick(() => {
- this.updatedCal();
- });
- },
-
- beforeDestroy() {
- this.clearDelayTimer();
- this.clearOutsideHandler();
- clearTimeout(this.mouseDownTimeout);
- },
- 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.clickOutsideHandler = addEventListener(
- currentDocument,
- 'mousedown',
- this.onDocumentClick,
- );
- }
- // always hide on mobile
- if (!this.touchOutsideHandler) {
- currentDocument = currentDocument || props.getDocument();
- this.touchOutsideHandler = addEventListener(
- currentDocument,
- 'touchstart',
- this.onDocumentClick,
- );
- }
- // close popup when trigger type contains 'onContextmenu' and document is scrolling.
- if (!this.contextmenuOutsideHandler1 && this.isContextmenuToShow()) {
- currentDocument = currentDocument || props.getDocument();
- this.contextmenuOutsideHandler1 = addEventListener(
- currentDocument,
- 'scroll',
- this.onContextmenuClose,
- );
- }
- // close popup when trigger type contains 'onContextmenu' and window is blur.
- if (!this.contextmenuOutsideHandler2 && this.isContextmenuToShow()) {
- this.contextmenuOutsideHandler2 = addEventListener(
- window,
- 'blur',
- this.onContextmenuClose,
- );
- }
- } else {
- this.clearOutsideHandler();
- }
- },
- onMouseenter(e) {
- const { mouseEnterDelay } = this.$props;
- this.fireEvents('mouseenter', e);
- this.delaySetPopupVisible(true, mouseEnterDelay, mouseEnterDelay ? null : e);
- },
-
- onMouseMove(e) {
- this.fireEvents('mousemove', e);
- this.setPoint(e);
- },
-
- onMouseleave(e) {
- this.fireEvents('mouseleave', e);
- this.delaySetPopupVisible(false, this.$props.mouseLeaveDelay);
- },
-
- onPopupMouseenter() {
- this.clearDelayTimer();
- },
-
- onPopupMouseleave(e) {
- if (
- e &&
- e.relatedTarget &&
- !e.relatedTarget.setTimeout &&
- this._component &&
- this._component.getPopupDomNode &&
- contains(this._component.getPopupDomNode(), e.relatedTarget)
- ) {
- return;
- }
- this.delaySetPopupVisible(false, this.$props.mouseLeaveDelay);
- },
-
- onFocus(e) {
- this.fireEvents('focus', e);
- // incase focusin and focusout
- this.clearDelayTimer();
- if (this.isFocusToShow()) {
- this.focusTime = Date.now();
- this.delaySetPopupVisible(true, this.$props.focusDelay);
- }
- },
-
- onMousedown(e) {
- this.fireEvents('mousedown', e);
- this.preClickTime = Date.now();
- },
-
- onTouchstart(e) {
- this.fireEvents('touchstart', e);
- this.preTouchTime = Date.now();
- },
-
- onBlur(e) {
- if (!contains(e.target, e.relatedTarget || document.activeElement)) {
- this.fireEvents('blur', e);
- this.clearDelayTimer();
- if (this.isBlurToHide()) {
- this.delaySetPopupVisible(false, this.$props.blurDelay);
- }
- }
- },
-
- onContextmenu(e) {
- e.preventDefault();
- this.fireEvents('contextmenu', e);
- this.setPopupVisible(true, e);
- },
-
- onContextmenuClose() {
- if (this.isContextmenuToShow()) {
- this.close();
- }
- },
-
- onClick(event) {
- this.fireEvents('click', 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(...args) {
- const { vcTriggerContext = {} } = this;
- this.hasPopupMouseDown = true;
-
- clearTimeout(this.mouseDownTimeout);
- this.mouseDownTimeout = setTimeout(() => {
- this.hasPopupMouseDown = false;
- }, 0);
-
- if (vcTriggerContext.onPopupMouseDown) {
- vcTriggerContext.onPopupMouseDown(...args);
- }
- },
-
- onDocumentClick(event) {
- if (this.$props.mask && !this.$props.maskClosable) {
- return;
- }
- const target = event.target;
- const root = this.$el;
- if (!contains(root, target) && !this.hasPopupMouseDown) {
- this.close();
- }
- },
- getPopupDomNode() {
- if (this._component && this._component.getPopupDomNode) {
- return this._component.getPopupDomNode();
- }
- return null;
- },
-
- getRootDomNode() {
- return this.$el;
- // return this.$el.children[0] || this.$el
- },
-
- handleGetPopupClassFromAlign(align) {
- const className = [];
- const props = this.$props;
- const {
- popupPlacement,
- builtinPlacements,
- prefixCls,
- alignPoint,
- getPopupClassNameFromAlign,
- } = props;
- if (popupPlacement && builtinPlacements) {
- className.push(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 getAlignFromPlacement(builtinPlacements, popupPlacement, popupAlign);
- }
- return popupAlign;
- },
- savePopup(node) {
- this._component = node;
- this.savePopupRef(node);
- },
- getComponent() {
- const self = this;
- const mouseProps = {};
- if (this.isMouseEnterToShow()) {
- mouseProps.mouseenter = self.onPopupMouseenter;
- }
- if (this.isMouseLeaveToHide()) {
- mouseProps.mouseleave = self.onPopupMouseleave;
- }
- mouseProps.mousedown = this.onPopupMouseDown;
- mouseProps.touchstart = this.onPopupMouseDown;
- const { handleGetPopupClassFromAlign, getRootDomNode, getContainer } = self;
- const {
- prefixCls,
- destroyPopupOnHide,
- popupClassName,
- action,
- popupAnimation,
- popupTransitionName,
- popupStyle,
- mask,
- maskAnimation,
- maskTransitionName,
- zIndex,
- stretch,
- alignPoint,
- } = self.$props;
- const { sPopupVisible, point } = this.$data;
- const align = this.getPopupAlign();
- const popupProps = {
- props: {
- prefixCls,
- destroyPopupOnHide,
- visible: sPopupVisible,
- point: alignPoint && point,
- action,
- align,
- animation: popupAnimation,
- getClassNameFromAlign: handleGetPopupClassFromAlign,
- stretch,
- getRootDomNode,
- mask,
- zIndex,
- transitionName: popupTransitionName,
- maskAnimation,
- maskTransitionName,
- getContainer,
- popupClassName,
- popupStyle,
- },
- on: {
- align: getListeners(this).popupAlign || noop,
- ...mouseProps,
- },
- };
- return (
-
- {getComponentFromProp(self, 'popup')}
-
- );
- },
-
- getContainer() {
- const { $props: props, dialogContext } = this;
- const popupContainer = document.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%';
- const mountNode = props.getPopupContainer
- ? props.getPopupContainer(this.$el, dialogContext)
- : props.getDocument().body;
- mountNode.appendChild(popupContainer);
- this.popupContainer = popupContainer;
- return popupContainer;
- },
-
- setPopupVisible(sPopupVisible, event) {
- const { alignPoint, sPopupVisible: prevPopupVisible } = this;
- this.clearDelayTimer();
- if (prevPopupVisible !== sPopupVisible) {
- if (!hasProp(this, 'popupVisible')) {
- this.setState({
- sPopupVisible,
- prevPopupVisible,
- });
- }
- const listeners = getListeners(this);
- listeners.popupVisibleChange && listeners.popupVisibleChange(sPopupVisible);
- }
- // Always record the point position since mouseEnterDelay will delay the show
- if (alignPoint && event) {
- 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 = requestAnimationTimeout(() => {
- this.setPopupVisible(visible, point);
- this.clearDelayTimer();
- }, delay);
- } else {
- this.setPopupVisible(visible, event);
- }
- },
-
- clearDelayTimer() {
- if (this.delayTimer) {
- cancelAnimationTimeout(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 = getListeners(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;
- },
-
- 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() {
- if (this.$data.sPopupVisible && this._component && this._component.$refs.alignInstance) {
- this._component.$refs.alignInstance.forceAlign();
- }
- },
- fireEvents(type, e) {
- if (this.childOriginEvents[type]) {
- this.childOriginEvents[type](e);
- }
- this.__emit(type, e);
- },
-
- close() {
- this.setPopupVisible(false);
- },
- },
- render() {
- const { sPopupVisible } = this;
- const children = filterEmpty(getSlot(this));
- const { forceRender, alignPoint } = this.$props;
-
- if (children.length > 1) {
- warning(false, 'Trigger $slots.default.length > 1, just support only one default', true);
- }
- const child = children[0];
- this.childOriginEvents = getEvents(child);
- const newChildProps = {
- props: {},
- on: {},
- key: 'trigger',
- };
-
- if (this.isContextmenuToShow()) {
- newChildProps.on.contextmenu = this.onContextmenu;
- } else {
- newChildProps.on.contextmenu = this.createTwoChains('contextmenu');
- }
-
- if (this.isClickToHide() || this.isClickToShow()) {
- newChildProps.on.click = this.onClick;
- newChildProps.on.mousedown = this.onMousedown;
- newChildProps.on.touchstart = this.onTouchstart;
- } else {
- newChildProps.on.click = this.createTwoChains('click');
- newChildProps.on.mousedown = this.createTwoChains('mousedown');
- newChildProps.on.touchstart = this.createTwoChains('onTouchstart');
- }
- if (this.isMouseEnterToShow()) {
- newChildProps.on.mouseenter = this.onMouseenter;
- if (alignPoint) {
- newChildProps.on.mousemove = this.onMouseMove;
- }
- } else {
- newChildProps.on.mouseenter = this.createTwoChains('mouseenter');
- }
- if (this.isMouseLeaveToHide()) {
- newChildProps.on.mouseleave = this.onMouseleave;
- } else {
- newChildProps.on.mouseleave = this.createTwoChains('mouseleave');
- }
-
- if (this.isFocusToShow() || this.isBlurToHide()) {
- newChildProps.on.focus = this.onFocus;
- newChildProps.on.blur = this.onBlur;
- } else {
- newChildProps.on.focus = this.createTwoChains('focus');
- newChildProps.on.blur = e => {
- if (e && (!e.relatedTarget || !contains(e.target, e.relatedTarget))) {
- this.createTwoChains('blur')(e);
- }
- };
- }
-
- const trigger = cloneVNode(child, newChildProps);
- let portal;
- // prevent unmounting after it's rendered
- if (sPopupVisible || this._component || forceRender) {
- portal = (
-
- );
- }
- return [portal, trigger];
- },
-};
diff --git a/examples/index.js b/examples/index.js
index 411e1b710..6ec0cdff0 100644
--- a/examples/index.js
+++ b/examples/index.js
@@ -17,6 +17,7 @@ import PageHeader from 'ant-design-vue/page-header';
import Skeleton from 'ant-design-vue/skeleton';
import Empty from 'ant-design-vue/empty';
import Timeline from 'ant-design-vue/timeline';
+import Tooltip from 'ant-design-vue/tooltip';
import 'ant-design-vue/style.js';
createApp(App)
@@ -36,4 +37,5 @@ createApp(App)
.use(Spin)
.use(Empty)
.use(Timeline)
+ .use(Tooltip)
.mount('#app');