index.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import { createPopper as _createPopper, offsetModifier } from '@vant/popperjs';
  3. import { createNamespace, isServer } from '../utils';
  4. import { BORDER_BOTTOM } from '../utils/constant'; // Mixins
  5. import { ClickOutsideMixin } from '../mixins/click-outside'; // Components
  6. import Icon from '../icon';
  7. import Popup from '../popup';
  8. var _createNamespace = createNamespace('popover'),
  9. createComponent = _createNamespace[0],
  10. bem = _createNamespace[1];
  11. export default createComponent({
  12. mixins: [ClickOutsideMixin({
  13. event: 'touchstart',
  14. method: 'onClickOutside'
  15. })],
  16. props: {
  17. value: Boolean,
  18. trigger: String,
  19. overlay: Boolean,
  20. offset: {
  21. type: Array,
  22. default: function _default() {
  23. return [0, 8];
  24. }
  25. },
  26. theme: {
  27. type: String,
  28. default: 'light'
  29. },
  30. actions: {
  31. type: Array,
  32. default: function _default() {
  33. return [];
  34. }
  35. },
  36. placement: {
  37. type: String,
  38. default: 'bottom'
  39. },
  40. getContainer: {
  41. type: [String, Function],
  42. default: 'body'
  43. },
  44. closeOnClickAction: {
  45. type: Boolean,
  46. default: true
  47. }
  48. },
  49. watch: {
  50. value: 'updateLocation',
  51. placement: 'updateLocation'
  52. },
  53. mounted: function mounted() {
  54. this.updateLocation();
  55. },
  56. beforeDestroy: function beforeDestroy() {
  57. if (this.popper) {
  58. if (!isServer) {
  59. window.removeEventListener('animationend', this.updateLocation);
  60. window.removeEventListener('transitionend', this.updateLocation);
  61. }
  62. this.popper.destroy();
  63. this.popper = null;
  64. }
  65. },
  66. methods: {
  67. createPopper: function createPopper() {
  68. var popper = _createPopper(this.$refs.wrapper, this.$refs.popover.$el, {
  69. placement: this.placement,
  70. modifiers: [{
  71. name: 'computeStyles',
  72. options: {
  73. adaptive: false,
  74. gpuAcceleration: false
  75. }
  76. }, _extends({}, offsetModifier, {
  77. options: {
  78. offset: this.offset
  79. }
  80. })]
  81. });
  82. if (!isServer) {
  83. window.addEventListener('animationend', this.updateLocation);
  84. window.addEventListener('transitionend', this.updateLocation);
  85. }
  86. return popper;
  87. },
  88. updateLocation: function updateLocation() {
  89. var _this = this;
  90. this.$nextTick(function () {
  91. if (!_this.value) {
  92. return;
  93. }
  94. if (!_this.popper) {
  95. _this.popper = _this.createPopper();
  96. } else {
  97. _this.popper.setOptions({
  98. placement: _this.placement
  99. });
  100. }
  101. });
  102. },
  103. renderAction: function renderAction(action, index) {
  104. var _this2 = this;
  105. var h = this.$createElement;
  106. var icon = action.icon,
  107. text = action.text,
  108. disabled = action.disabled,
  109. className = action.className;
  110. return h("div", {
  111. "attrs": {
  112. "role": "menuitem"
  113. },
  114. "class": [bem('action', {
  115. disabled: disabled,
  116. 'with-icon': icon
  117. }), className],
  118. "on": {
  119. "click": function click() {
  120. return _this2.onClickAction(action, index);
  121. }
  122. }
  123. }, [icon && h(Icon, {
  124. "attrs": {
  125. "name": icon
  126. },
  127. "class": bem('action-icon')
  128. }), h("div", {
  129. "class": [bem('action-text'), BORDER_BOTTOM]
  130. }, [text])]);
  131. },
  132. onToggle: function onToggle(value) {
  133. this.$emit('input', value);
  134. },
  135. onClickWrapper: function onClickWrapper() {
  136. if (this.trigger === 'click') {
  137. this.onToggle(!this.value);
  138. }
  139. },
  140. onTouchstart: function onTouchstart(event) {
  141. event.stopPropagation();
  142. this.$emit('touchstart', event);
  143. },
  144. onClickAction: function onClickAction(action, index) {
  145. if (action.disabled) {
  146. return;
  147. }
  148. this.$emit('select', action, index);
  149. if (this.closeOnClickAction) {
  150. this.$emit('input', false);
  151. }
  152. },
  153. onClickOutside: function onClickOutside() {
  154. this.$emit('input', false);
  155. },
  156. onOpen: function onOpen() {
  157. this.$emit('open');
  158. },
  159. /* istanbul ignore next */
  160. onOpened: function onOpened() {
  161. this.$emit('opened');
  162. },
  163. onClose: function onClose() {
  164. this.$emit('close');
  165. },
  166. /* istanbul ignore next */
  167. onClosed: function onClosed() {
  168. this.$emit('closed');
  169. }
  170. },
  171. render: function render() {
  172. var h = arguments[0];
  173. return h("span", {
  174. "ref": "wrapper",
  175. "class": bem('wrapper'),
  176. "on": {
  177. "click": this.onClickWrapper
  178. }
  179. }, [h(Popup, {
  180. "ref": "popover",
  181. "attrs": {
  182. "value": this.value,
  183. "overlay": this.overlay,
  184. "position": null,
  185. "transition": "van-popover-zoom",
  186. "lockScroll": false,
  187. "getContainer": this.getContainer
  188. },
  189. "class": bem([this.theme]),
  190. "on": {
  191. "open": this.onOpen,
  192. "close": this.onClose,
  193. "input": this.onToggle,
  194. "opened": this.onOpened,
  195. "closed": this.onClosed
  196. },
  197. "nativeOn": {
  198. "touchstart": this.onTouchstart
  199. }
  200. }, [h("div", {
  201. "class": bem('arrow')
  202. }), h("div", {
  203. "class": bem('content'),
  204. "attrs": {
  205. "role": "menu"
  206. }
  207. }, [this.slots('default') || this.actions.map(this.renderAction)])]), this.slots('reference')]);
  208. }
  209. });