Tooltip.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import _defineProperty from 'babel-runtime/helpers/defineProperty';
  2. import _extends from 'babel-runtime/helpers/extends';
  3. import { cloneElement } from '../_util/vnode';
  4. import VcTooltip from '../vc-tooltip';
  5. import _getPlacements from './placements';
  6. import PropTypes from '../_util/vue-types';
  7. import { hasProp, getComponentFromProp, getClass, getStyle, isValidElement, getListeners } from '../_util/props-util';
  8. import { ConfigConsumerProps } from '../config-provider/configConsumerProps';
  9. import abstractTooltipProps from './abstractTooltipProps';
  10. var splitObject = function splitObject(obj, keys) {
  11. var picked = {};
  12. var omitted = _extends({}, obj);
  13. keys.forEach(function (key) {
  14. if (obj && key in obj) {
  15. picked[key] = obj[key];
  16. delete omitted[key];
  17. }
  18. });
  19. return { picked: picked, omitted: omitted };
  20. };
  21. var props = abstractTooltipProps();
  22. export default {
  23. name: 'ATooltip',
  24. model: {
  25. prop: 'visible',
  26. event: 'visibleChange'
  27. },
  28. props: _extends({}, props, {
  29. title: PropTypes.any
  30. }),
  31. inject: {
  32. configProvider: { 'default': function _default() {
  33. return ConfigConsumerProps;
  34. } }
  35. },
  36. data: function data() {
  37. return {
  38. sVisible: !!this.$props.visible || !!this.$props.defaultVisible
  39. };
  40. },
  41. watch: {
  42. visible: function visible(val) {
  43. this.sVisible = val;
  44. }
  45. },
  46. methods: {
  47. onVisibleChange: function onVisibleChange(visible) {
  48. if (!hasProp(this, 'visible')) {
  49. this.sVisible = this.isNoTitle() ? false : visible;
  50. }
  51. if (!this.isNoTitle()) {
  52. this.$emit('visibleChange', visible);
  53. }
  54. },
  55. getPopupDomNode: function getPopupDomNode() {
  56. return this.$refs.tooltip.getPopupDomNode();
  57. },
  58. getPlacements: function getPlacements() {
  59. var _$props = this.$props,
  60. builtinPlacements = _$props.builtinPlacements,
  61. arrowPointAtCenter = _$props.arrowPointAtCenter,
  62. autoAdjustOverflow = _$props.autoAdjustOverflow;
  63. return builtinPlacements || _getPlacements({
  64. arrowPointAtCenter: arrowPointAtCenter,
  65. verticalArrowShift: 8,
  66. autoAdjustOverflow: autoAdjustOverflow
  67. });
  68. },
  69. // Fix Tooltip won't hide at disabled button
  70. // mouse events don't trigger at disabled button in Chrome
  71. // https://github.com/react-component/tooltip/issues/18
  72. getDisabledCompatibleChildren: function getDisabledCompatibleChildren(ele) {
  73. var h = this.$createElement;
  74. var options = ele.componentOptions && ele.componentOptions.Ctor.options || {};
  75. 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) {
  76. // Pick some layout related style properties up to span
  77. // Prevent layout bugs like https://github.com/ant-design/ant-design/issues/5254
  78. var _splitObject = splitObject(getStyle(ele), ['position', 'left', 'right', 'top', 'bottom', 'float', 'display', 'zIndex']),
  79. picked = _splitObject.picked,
  80. omitted = _splitObject.omitted;
  81. var spanStyle = _extends({
  82. display: 'inline-block' }, picked, {
  83. cursor: 'not-allowed',
  84. width: ele.componentOptions.propsData.block ? '100%' : null
  85. });
  86. var buttonStyle = _extends({}, omitted, {
  87. pointerEvents: 'none'
  88. });
  89. var spanCls = getClass(ele);
  90. var child = cloneElement(ele, {
  91. style: buttonStyle,
  92. 'class': null
  93. });
  94. return h(
  95. 'span',
  96. { style: spanStyle, 'class': spanCls },
  97. [child]
  98. );
  99. }
  100. return ele;
  101. },
  102. isNoTitle: function isNoTitle() {
  103. var title = getComponentFromProp(this, 'title');
  104. return !title && title !== 0;
  105. },
  106. getOverlay: function getOverlay() {
  107. var title = getComponentFromProp(this, 'title');
  108. if (title === 0) {
  109. return title;
  110. }
  111. return title || '';
  112. },
  113. // 动态设置动画点
  114. onPopupAlign: function onPopupAlign(domNode, align) {
  115. var placements = this.getPlacements();
  116. // 当前返回的位置
  117. var placement = Object.keys(placements).filter(function (key) {
  118. return placements[key].points[0] === align.points[0] && placements[key].points[1] === align.points[1];
  119. })[0];
  120. if (!placement) {
  121. return;
  122. }
  123. // 根据当前坐标设置动画点
  124. var rect = domNode.getBoundingClientRect();
  125. var transformOrigin = {
  126. top: '50%',
  127. left: '50%'
  128. };
  129. if (placement.indexOf('top') >= 0 || placement.indexOf('Bottom') >= 0) {
  130. transformOrigin.top = rect.height - align.offset[1] + 'px';
  131. } else if (placement.indexOf('Top') >= 0 || placement.indexOf('bottom') >= 0) {
  132. transformOrigin.top = -align.offset[1] + 'px';
  133. }
  134. if (placement.indexOf('left') >= 0 || placement.indexOf('Right') >= 0) {
  135. transformOrigin.left = rect.width - align.offset[0] + 'px';
  136. } else if (placement.indexOf('right') >= 0 || placement.indexOf('Left') >= 0) {
  137. transformOrigin.left = -align.offset[0] + 'px';
  138. }
  139. domNode.style.transformOrigin = transformOrigin.left + ' ' + transformOrigin.top;
  140. }
  141. },
  142. render: function render() {
  143. var h = arguments[0];
  144. var $props = this.$props,
  145. $data = this.$data,
  146. $slots = this.$slots;
  147. var customizePrefixCls = $props.prefixCls,
  148. openClassName = $props.openClassName,
  149. getPopupContainer = $props.getPopupContainer;
  150. var getContextPopupContainer = this.configProvider.getPopupContainer;
  151. var getPrefixCls = this.configProvider.getPrefixCls;
  152. var prefixCls = getPrefixCls('tooltip', customizePrefixCls);
  153. var children = ($slots['default'] || []).filter(function (c) {
  154. return c.tag || c.text.trim() !== '';
  155. });
  156. children = children.length === 1 ? children[0] : children;
  157. var sVisible = $data.sVisible;
  158. // Hide tooltip when there is no title
  159. if (!hasProp(this, 'visible') && this.isNoTitle()) {
  160. sVisible = false;
  161. }
  162. if (!children) {
  163. return null;
  164. }
  165. var child = this.getDisabledCompatibleChildren(isValidElement(children) ? children : h('span', [children]));
  166. var childCls = _defineProperty({}, openClassName || prefixCls + '-open', true);
  167. var tooltipProps = {
  168. props: _extends({}, $props, {
  169. prefixCls: prefixCls,
  170. getTooltipContainer: getPopupContainer || getContextPopupContainer,
  171. builtinPlacements: this.getPlacements(),
  172. overlay: this.getOverlay(),
  173. visible: sVisible
  174. }),
  175. ref: 'tooltip',
  176. on: _extends({}, getListeners(this), {
  177. visibleChange: this.onVisibleChange,
  178. popupAlign: this.onPopupAlign
  179. })
  180. };
  181. return h(
  182. VcTooltip,
  183. tooltipProps,
  184. [sVisible ? cloneElement(child, { 'class': childCls }) : child]
  185. );
  186. }
  187. };