dropdown.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import { resolveDirective as _resolveDirective, createVNode as _createVNode } from "vue";
  3. import { computed, defineComponent } from 'vue';
  4. import RcDropdown from '../vc-dropdown';
  5. import DropdownButton from './dropdown-button';
  6. import { cloneElement } from '../_util/vnode';
  7. import classNames from '../_util/classNames';
  8. import { isValidElement, initDefaultProps } from '../_util/props-util';
  9. import { dropdownProps } from './props';
  10. import RightOutlined from "@ant-design/icons-vue/es/icons/RightOutlined";
  11. import useConfigInject from '../config-provider/hooks/useConfigInject';
  12. import devWarning from '../vc-util/devWarning';
  13. import omit from '../_util/omit';
  14. import getPlacements from '../_util/placements';
  15. import warning from '../_util/warning';
  16. import useStyle from './style';
  17. import { useProvideOverride } from '../menu/src/OverrideContext';
  18. const Dropdown = defineComponent({
  19. compatConfig: {
  20. MODE: 3
  21. },
  22. name: 'ADropdown',
  23. inheritAttrs: false,
  24. props: initDefaultProps(dropdownProps(), {
  25. mouseEnterDelay: 0.15,
  26. mouseLeaveDelay: 0.1,
  27. placement: 'bottomLeft',
  28. trigger: 'hover'
  29. }),
  30. // emits: ['visibleChange', 'update:visible'],
  31. slots: Object,
  32. setup(props, _ref) {
  33. let {
  34. slots,
  35. attrs,
  36. emit
  37. } = _ref;
  38. const {
  39. prefixCls,
  40. rootPrefixCls,
  41. direction,
  42. getPopupContainer
  43. } = useConfigInject('dropdown', props);
  44. const [wrapSSR, hashId] = useStyle(prefixCls);
  45. // Warning for deprecated usage
  46. if (process.env.NODE_ENV !== 'production') {
  47. [['visible', 'open'], ['onVisibleChange', 'onOpenChange'], ['onUpdate:visible', 'onUpdate:open']].forEach(_ref2 => {
  48. let [deprecatedName, newName] = _ref2;
  49. warning(props[deprecatedName] === undefined, 'Dropdown', `\`${deprecatedName}\` is deprecated which will be removed in next major version, please use \`${newName}\` instead.`);
  50. });
  51. }
  52. const transitionName = computed(() => {
  53. const {
  54. placement = '',
  55. transitionName
  56. } = props;
  57. if (transitionName !== undefined) {
  58. return transitionName;
  59. }
  60. if (placement.includes('top')) {
  61. return `${rootPrefixCls.value}-slide-down`;
  62. }
  63. return `${rootPrefixCls.value}-slide-up`;
  64. });
  65. useProvideOverride({
  66. prefixCls: computed(() => `${prefixCls.value}-menu`),
  67. expandIcon: computed(() => {
  68. return _createVNode("span", {
  69. "class": `${prefixCls.value}-menu-submenu-arrow`
  70. }, [_createVNode(RightOutlined, {
  71. "class": `${prefixCls.value}-menu-submenu-arrow-icon`
  72. }, null)]);
  73. }),
  74. mode: computed(() => 'vertical'),
  75. selectable: computed(() => false),
  76. onClick: () => {},
  77. validator: _ref3 => {
  78. let {
  79. mode
  80. } = _ref3;
  81. // Warning if use other mode
  82. warning(!mode || mode === 'vertical', 'Dropdown', `mode="${mode}" is not supported for Dropdown's Menu.`);
  83. }
  84. });
  85. const renderOverlay = () => {
  86. var _a, _b, _c;
  87. // rc-dropdown already can process the function of overlay, but we have check logic here.
  88. // So we need render the element to check and pass back to rc-dropdown.
  89. const overlay = props.overlay || ((_a = slots.overlay) === null || _a === void 0 ? void 0 : _a.call(slots));
  90. const overlayNode = Array.isArray(overlay) ? overlay[0] : overlay;
  91. if (!overlayNode) return null;
  92. const overlayProps = overlayNode.props || {};
  93. // Warning if use other mode
  94. devWarning(!overlayProps.mode || overlayProps.mode === 'vertical', 'Dropdown', `mode="${overlayProps.mode}" is not supported for Dropdown's Menu.`);
  95. // menu cannot be selectable in dropdown defaultly
  96. const {
  97. selectable = false,
  98. expandIcon = (_c = (_b = overlayNode.children) === null || _b === void 0 ? void 0 : _b.expandIcon) === null || _c === void 0 ? void 0 : _c.call(_b)
  99. } = overlayProps;
  100. const overlayNodeExpandIcon = typeof expandIcon !== 'undefined' && isValidElement(expandIcon) ? expandIcon : _createVNode("span", {
  101. "class": `${prefixCls.value}-menu-submenu-arrow`
  102. }, [_createVNode(RightOutlined, {
  103. "class": `${prefixCls.value}-menu-submenu-arrow-icon`
  104. }, null)]);
  105. const fixedModeOverlay = isValidElement(overlayNode) ? cloneElement(overlayNode, {
  106. mode: 'vertical',
  107. selectable,
  108. expandIcon: () => overlayNodeExpandIcon
  109. }) : overlayNode;
  110. return fixedModeOverlay;
  111. };
  112. const placement = computed(() => {
  113. const placement = props.placement;
  114. if (!placement) {
  115. return direction.value === 'rtl' ? 'bottomRight' : 'bottomLeft';
  116. }
  117. if (placement.includes('Center')) {
  118. const newPlacement = placement.slice(0, placement.indexOf('Center'));
  119. devWarning(!placement.includes('Center'), 'Dropdown', `You are using '${placement}' placement in Dropdown, which is deprecated. Try to use '${newPlacement}' instead.`);
  120. return newPlacement;
  121. }
  122. return placement;
  123. });
  124. const mergedVisible = computed(() => {
  125. return typeof props.visible === 'boolean' ? props.visible : props.open;
  126. });
  127. const handleVisibleChange = val => {
  128. emit('update:visible', val);
  129. emit('visibleChange', val);
  130. emit('update:open', val);
  131. emit('openChange', val);
  132. };
  133. return () => {
  134. var _a, _b;
  135. const {
  136. arrow,
  137. trigger,
  138. disabled,
  139. overlayClassName
  140. } = props;
  141. const child = (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)[0];
  142. const dropdownTrigger = cloneElement(child, _extends({
  143. class: classNames((_b = child === null || child === void 0 ? void 0 : child.props) === null || _b === void 0 ? void 0 : _b.class, {
  144. [`${prefixCls.value}-rtl`]: direction.value === 'rtl'
  145. }, `${prefixCls.value}-trigger`)
  146. }, disabled ? {
  147. disabled
  148. } : {}));
  149. const overlayClassNameCustomized = classNames(overlayClassName, hashId.value, {
  150. [`${prefixCls.value}-rtl`]: direction.value === 'rtl'
  151. });
  152. const triggerActions = disabled ? [] : trigger;
  153. let alignPoint;
  154. if (triggerActions && triggerActions.includes('contextmenu')) {
  155. alignPoint = true;
  156. }
  157. const builtinPlacements = getPlacements({
  158. arrowPointAtCenter: typeof arrow === 'object' && arrow.pointAtCenter,
  159. autoAdjustOverflow: true
  160. });
  161. const dropdownProps = omit(_extends(_extends(_extends({}, props), attrs), {
  162. visible: mergedVisible.value,
  163. builtinPlacements,
  164. overlayClassName: overlayClassNameCustomized,
  165. arrow: !!arrow,
  166. alignPoint,
  167. prefixCls: prefixCls.value,
  168. getPopupContainer: getPopupContainer === null || getPopupContainer === void 0 ? void 0 : getPopupContainer.value,
  169. transitionName: transitionName.value,
  170. trigger: triggerActions,
  171. onVisibleChange: handleVisibleChange,
  172. placement: placement.value
  173. }), ['overlay', 'onUpdate:visible']);
  174. return wrapSSR(_createVNode(RcDropdown, dropdownProps, {
  175. default: () => [dropdownTrigger],
  176. overlay: renderOverlay
  177. }));
  178. };
  179. }
  180. });
  181. Dropdown.Button = DropdownButton;
  182. export default Dropdown;