Popup.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _typeof2 = require('babel-runtime/helpers/typeof');
  6. var _typeof3 = _interopRequireDefault(_typeof2);
  7. var _extends2 = require('babel-runtime/helpers/extends');
  8. var _extends3 = _interopRequireDefault(_extends2);
  9. var _vueTypes = require('../_util/vue-types');
  10. var _vueTypes2 = _interopRequireDefault(_vueTypes);
  11. var _vcAlign = require('../vc-align');
  12. var _vcAlign2 = _interopRequireDefault(_vcAlign);
  13. var _PopupInner = require('./PopupInner');
  14. var _PopupInner2 = _interopRequireDefault(_PopupInner);
  15. var _LazyRenderBox = require('./LazyRenderBox');
  16. var _LazyRenderBox2 = _interopRequireDefault(_LazyRenderBox);
  17. var _cssAnimation = require('../_util/css-animation');
  18. var _cssAnimation2 = _interopRequireDefault(_cssAnimation);
  19. var _BaseMixin = require('../_util/BaseMixin');
  20. var _BaseMixin2 = _interopRequireDefault(_BaseMixin);
  21. var _propsUtil = require('../_util/props-util');
  22. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  23. exports['default'] = {
  24. name: 'VCTriggerPopup',
  25. mixins: [_BaseMixin2['default']],
  26. props: {
  27. visible: _vueTypes2['default'].bool,
  28. getClassNameFromAlign: _vueTypes2['default'].func,
  29. getRootDomNode: _vueTypes2['default'].func,
  30. align: _vueTypes2['default'].any,
  31. destroyPopupOnHide: _vueTypes2['default'].bool,
  32. prefixCls: _vueTypes2['default'].string,
  33. getContainer: _vueTypes2['default'].func,
  34. transitionName: _vueTypes2['default'].string,
  35. animation: _vueTypes2['default'].any,
  36. maskAnimation: _vueTypes2['default'].string,
  37. maskTransitionName: _vueTypes2['default'].string,
  38. mask: _vueTypes2['default'].bool,
  39. zIndex: _vueTypes2['default'].number,
  40. popupClassName: _vueTypes2['default'].any,
  41. popupStyle: _vueTypes2['default'].object.def(function () {
  42. return {};
  43. }),
  44. stretch: _vueTypes2['default'].string,
  45. point: _vueTypes2['default'].shape({
  46. pageX: _vueTypes2['default'].number,
  47. pageY: _vueTypes2['default'].number
  48. })
  49. },
  50. data: function data() {
  51. this.domEl = null;
  52. return {
  53. // Used for stretch
  54. stretchChecked: false,
  55. targetWidth: undefined,
  56. targetHeight: undefined
  57. };
  58. },
  59. mounted: function mounted() {
  60. var _this = this;
  61. this.$nextTick(function () {
  62. _this.rootNode = _this.getPopupDomNode();
  63. _this.setStretchSize();
  64. });
  65. },
  66. // 如添加会导致动画失效,如放开会导致快速输入时闪动 https://github.com/vueComponent/ant-design-vue/issues/1327,
  67. // 目前方案是保留动画,闪动问题(动画多次执行)进一步定位
  68. // beforeUpdate() {
  69. // if (this.domEl && this.domEl.rcEndListener) {
  70. // this.domEl.rcEndListener();
  71. // this.domEl = null;
  72. // }
  73. // },
  74. updated: function updated() {
  75. var _this2 = this;
  76. this.$nextTick(function () {
  77. _this2.setStretchSize();
  78. });
  79. },
  80. beforeDestroy: function beforeDestroy() {
  81. if (this.$el.parentNode) {
  82. this.$el.parentNode.removeChild(this.$el);
  83. } else if (this.$el.remove) {
  84. this.$el.remove();
  85. }
  86. },
  87. methods: {
  88. onAlign: function onAlign(popupDomNode, align) {
  89. var props = this.$props;
  90. var currentAlignClassName = props.getClassNameFromAlign(align);
  91. // FIX: https://github.com/react-component/trigger/issues/56
  92. // FIX: https://github.com/react-component/tooltip/issues/79
  93. if (this.currentAlignClassName !== currentAlignClassName) {
  94. this.currentAlignClassName = currentAlignClassName;
  95. popupDomNode.className = this.getClassName(currentAlignClassName);
  96. }
  97. var listeners = (0, _propsUtil.getListeners)(this);
  98. listeners.align && listeners.align(popupDomNode, align);
  99. },
  100. // Record size if stretch needed
  101. setStretchSize: function setStretchSize() {
  102. var _$props = this.$props,
  103. stretch = _$props.stretch,
  104. getRootDomNode = _$props.getRootDomNode,
  105. visible = _$props.visible;
  106. var _$data = this.$data,
  107. stretchChecked = _$data.stretchChecked,
  108. targetHeight = _$data.targetHeight,
  109. targetWidth = _$data.targetWidth;
  110. if (!stretch || !visible) {
  111. if (stretchChecked) {
  112. this.setState({ stretchChecked: false });
  113. }
  114. return;
  115. }
  116. var $ele = getRootDomNode();
  117. if (!$ele) return;
  118. var height = $ele.offsetHeight;
  119. var width = $ele.offsetWidth;
  120. if (targetHeight !== height || targetWidth !== width || !stretchChecked) {
  121. this.setState({
  122. stretchChecked: true,
  123. targetHeight: height,
  124. targetWidth: width
  125. });
  126. }
  127. },
  128. getPopupDomNode: function getPopupDomNode() {
  129. return this.$refs.popupInstance ? this.$refs.popupInstance.$el : null;
  130. },
  131. getTargetElement: function getTargetElement() {
  132. return this.$props.getRootDomNode();
  133. },
  134. // `target` on `rc-align` can accept as a function to get the bind element or a point.
  135. // ref: https://www.npmjs.com/package/rc-align
  136. getAlignTarget: function getAlignTarget() {
  137. var point = this.$props.point;
  138. if (point) {
  139. return point;
  140. }
  141. return this.getTargetElement;
  142. },
  143. getMaskTransitionName: function getMaskTransitionName() {
  144. var props = this.$props;
  145. var transitionName = props.maskTransitionName;
  146. var animation = props.maskAnimation;
  147. if (!transitionName && animation) {
  148. transitionName = props.prefixCls + '-' + animation;
  149. }
  150. return transitionName;
  151. },
  152. getTransitionName: function getTransitionName() {
  153. var props = this.$props;
  154. var transitionName = props.transitionName;
  155. var animation = props.animation;
  156. if (!transitionName) {
  157. if (typeof animation === 'string') {
  158. transitionName = '' + animation;
  159. } else if (animation && animation.props && animation.props.name) {
  160. transitionName = animation.props.name;
  161. }
  162. }
  163. return transitionName;
  164. },
  165. getClassName: function getClassName(currentAlignClassName) {
  166. return this.$props.prefixCls + ' ' + this.$props.popupClassName + ' ' + currentAlignClassName;
  167. },
  168. getPopupElement: function getPopupElement() {
  169. var _this3 = this;
  170. var h = this.$createElement;
  171. var props = this.$props,
  172. $slots = this.$slots,
  173. getTransitionName = this.getTransitionName;
  174. var _$data2 = this.$data,
  175. stretchChecked = _$data2.stretchChecked,
  176. targetHeight = _$data2.targetHeight,
  177. targetWidth = _$data2.targetWidth;
  178. var align = props.align,
  179. visible = props.visible,
  180. prefixCls = props.prefixCls,
  181. animation = props.animation,
  182. popupStyle = props.popupStyle,
  183. getClassNameFromAlign = props.getClassNameFromAlign,
  184. destroyPopupOnHide = props.destroyPopupOnHide,
  185. stretch = props.stretch;
  186. var className = this.getClassName(this.currentAlignClassName || getClassNameFromAlign(align));
  187. // const hiddenClassName = `${prefixCls}-hidden`
  188. if (!visible) {
  189. this.currentAlignClassName = null;
  190. }
  191. var sizeStyle = {};
  192. if (stretch) {
  193. // Stretch with target
  194. if (stretch.indexOf('height') !== -1) {
  195. sizeStyle.height = typeof targetHeight === 'number' ? targetHeight + 'px' : targetHeight;
  196. } else if (stretch.indexOf('minHeight') !== -1) {
  197. sizeStyle.minHeight = typeof targetHeight === 'number' ? targetHeight + 'px' : targetHeight;
  198. }
  199. if (stretch.indexOf('width') !== -1) {
  200. sizeStyle.width = typeof targetWidth === 'number' ? targetWidth + 'px' : targetWidth;
  201. } else if (stretch.indexOf('minWidth') !== -1) {
  202. sizeStyle.minWidth = typeof targetWidth === 'number' ? targetWidth + 'px' : targetWidth;
  203. }
  204. // Delay force align to makes ui smooth
  205. if (!stretchChecked) {
  206. // sizeStyle.visibility = 'hidden'
  207. setTimeout(function () {
  208. if (_this3.$refs.alignInstance) {
  209. _this3.$refs.alignInstance.forceAlign();
  210. }
  211. }, 0);
  212. }
  213. }
  214. var popupInnerProps = {
  215. props: {
  216. prefixCls: prefixCls,
  217. visible: visible
  218. // hiddenClassName,
  219. },
  220. 'class': className,
  221. on: (0, _propsUtil.getListeners)(this),
  222. ref: 'popupInstance',
  223. style: (0, _extends3['default'])({}, sizeStyle, popupStyle, this.getZIndexStyle())
  224. };
  225. var transitionProps = {
  226. props: {
  227. appear: true,
  228. css: false
  229. }
  230. };
  231. var transitionName = getTransitionName();
  232. var useTransition = !!transitionName;
  233. var transitionEvent = {
  234. beforeEnter: function beforeEnter() {
  235. // el.style.display = el.__vOriginalDisplay
  236. // this.$refs.alignInstance.forceAlign();
  237. },
  238. enter: function enter(el, done) {
  239. // render 后 vue 会移除通过animate动态添加的 class导致动画闪动,延迟两帧添加动画class,可以进一步定位或者重写 transition 组件
  240. _this3.$nextTick(function () {
  241. if (_this3.$refs.alignInstance) {
  242. _this3.$refs.alignInstance.$nextTick(function () {
  243. _this3.domEl = el;
  244. (0, _cssAnimation2['default'])(el, transitionName + '-enter', done);
  245. });
  246. } else {
  247. done();
  248. }
  249. });
  250. },
  251. beforeLeave: function beforeLeave() {
  252. _this3.domEl = null;
  253. },
  254. leave: function leave(el, done) {
  255. (0, _cssAnimation2['default'])(el, transitionName + '-leave', done);
  256. }
  257. };
  258. if ((typeof animation === 'undefined' ? 'undefined' : (0, _typeof3['default'])(animation)) === 'object') {
  259. useTransition = true;
  260. var _animation$on = animation.on,
  261. on = _animation$on === undefined ? {} : _animation$on,
  262. _animation$props = animation.props,
  263. _props = _animation$props === undefined ? {} : _animation$props;
  264. transitionProps.props = (0, _extends3['default'])({}, transitionProps.props, _props);
  265. transitionProps.on = (0, _extends3['default'])({}, transitionEvent, on);
  266. } else {
  267. transitionProps.on = transitionEvent;
  268. }
  269. if (!useTransition) {
  270. transitionProps = {};
  271. }
  272. if (destroyPopupOnHide) {
  273. return h(
  274. 'transition',
  275. transitionProps,
  276. [visible ? h(
  277. _vcAlign2['default'],
  278. {
  279. attrs: {
  280. target: this.getAlignTarget(),
  281. monitorWindowResize: true,
  282. align: align
  283. },
  284. key: 'popup',
  285. ref: 'alignInstance', on: {
  286. 'align': this.onAlign
  287. }
  288. },
  289. [h(
  290. _PopupInner2['default'],
  291. popupInnerProps,
  292. [$slots['default']]
  293. )]
  294. ) : null]
  295. );
  296. }
  297. return h(
  298. 'transition',
  299. transitionProps,
  300. [h(
  301. _vcAlign2['default'],
  302. {
  303. directives: [{
  304. name: 'show',
  305. value: visible
  306. }],
  307. attrs: {
  308. target: this.getAlignTarget(),
  309. monitorWindowResize: true,
  310. disabled: !visible,
  311. align: align
  312. },
  313. key: 'popup',
  314. ref: 'alignInstance', on: {
  315. 'align': this.onAlign
  316. }
  317. },
  318. [h(
  319. _PopupInner2['default'],
  320. popupInnerProps,
  321. [$slots['default']]
  322. )]
  323. )]
  324. );
  325. },
  326. getZIndexStyle: function getZIndexStyle() {
  327. var style = {};
  328. var props = this.$props;
  329. if (props.zIndex !== undefined) {
  330. style.zIndex = props.zIndex;
  331. }
  332. return style;
  333. },
  334. getMaskElement: function getMaskElement() {
  335. var h = this.$createElement;
  336. var props = this.$props;
  337. var maskElement = null;
  338. if (props.mask) {
  339. var maskTransition = this.getMaskTransitionName();
  340. maskElement = h(_LazyRenderBox2['default'], {
  341. directives: [{
  342. name: 'show',
  343. value: props.visible
  344. }],
  345. style: this.getZIndexStyle(),
  346. key: 'mask',
  347. 'class': props.prefixCls + '-mask',
  348. attrs: { visible: props.visible
  349. }
  350. });
  351. if (maskTransition) {
  352. maskElement = h(
  353. 'transition',
  354. {
  355. attrs: { appear: true, name: maskTransition }
  356. },
  357. [maskElement]
  358. );
  359. }
  360. }
  361. return maskElement;
  362. }
  363. },
  364. render: function render() {
  365. var h = arguments[0];
  366. var getMaskElement = this.getMaskElement,
  367. getPopupElement = this.getPopupElement;
  368. return h('div', [getMaskElement(), getPopupElement()]);
  369. }
  370. };