add dropdown
parent
aa1bcfe5db
commit
804a1eba18
|
@ -45,7 +45,14 @@ export function cloneVNodes (vnodes, deep) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cloneElement (n, nodeProps, clone) {
|
export function cloneElement (n, nodeProps, clone) {
|
||||||
const node = clone ? cloneVNode(n, true) : n
|
let ele = n
|
||||||
|
if (Array.isArray(n)) {
|
||||||
|
ele = filterEmpty(n)[0]
|
||||||
|
}
|
||||||
|
if (!ele) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const node = clone ? cloneVNode(ele, true) : ele
|
||||||
const { props = {}, key, on = {}} = nodeProps
|
const { props = {}, key, on = {}} = nodeProps
|
||||||
const data = node.data || {}
|
const data = node.data || {}
|
||||||
const { style = data.style,
|
const { style = data.style,
|
||||||
|
@ -95,6 +102,10 @@ export function filterEmpty (children = []) {
|
||||||
return children.filter(c => c.tag || c.text.trim() !== '')
|
return children.filter(c => c.tag || c.text.trim() !== '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPropsData (ele) {
|
||||||
|
return ele.componentOptions && ele.componentOptions.propsData
|
||||||
|
}
|
||||||
|
|
||||||
export function getEvents (child) {
|
export function getEvents (child) {
|
||||||
let events = {}
|
let events = {}
|
||||||
if (child.componentOptions && child.componentOptions.listeners) {
|
if (child.componentOptions && child.componentOptions.listeners) {
|
||||||
|
@ -102,5 +113,5 @@ export function getEvents (child) {
|
||||||
} else if (child.data && child.data.on) {
|
} else if (child.data && child.data.on) {
|
||||||
events = child.data.on
|
events = child.data.on
|
||||||
}
|
}
|
||||||
return events
|
return { ...events }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { filterEmpty } from '../_util/vnode'
|
import { filterEmpty } from '../_util/vnode'
|
||||||
export default {
|
const ButtonGroupProps = {
|
||||||
name: 'ButtonGroup',
|
|
||||||
props: {
|
|
||||||
prefixCls: {
|
prefixCls: {
|
||||||
default: 'ant-btn-group',
|
default: 'ant-btn-group',
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -12,7 +10,11 @@ export default {
|
||||||
return ['small', 'large', 'default'].includes(value)
|
return ['small', 'large', 'default'].includes(value)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
|
export { ButtonGroupProps }
|
||||||
|
export default {
|
||||||
|
name: 'ButtonGroup',
|
||||||
|
props: ButtonGroupProps,
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
sizeMap: {
|
sizeMap: {
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<cn>
|
||||||
|
#### 基本
|
||||||
|
最简单的下拉菜单。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Basic
|
||||||
|
The most basic dropdown menu.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown>
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Hover me <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item>
|
||||||
|
<a href="javascript:;">1st menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a href="javascript:;">2nd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a href="javascript:;">3rd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
```
|
|
@ -0,0 +1,22 @@
|
||||||
|
<cn>
|
||||||
|
#### 右键菜单
|
||||||
|
默认是移入触发菜单,可以鼠标右键触发。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Context Menu
|
||||||
|
The default trigger mode is `hover`, you can change it to `right click`.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown :trigger="['contextmenu']">
|
||||||
|
<span style="user-select: none">Right Click on Me</span>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd menu item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
```
|
|
@ -0,0 +1,59 @@
|
||||||
|
<cn>
|
||||||
|
#### 带下拉框的按钮
|
||||||
|
左边是按钮,右边是额外的相关功能菜单。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Button with dropdown menu
|
||||||
|
A button is on the left, and a related functional menu is on the right.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-dropdown-button @click="handleMenuClick">
|
||||||
|
Dropdown
|
||||||
|
<a-menu slot="overlay" @click="handleMenuClick">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown-button>
|
||||||
|
<a-dropdown-button
|
||||||
|
@click="handleButtonClick"
|
||||||
|
disabled
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
Dropdown
|
||||||
|
<a-menu slot="overlay" @click="handleMenuClick">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown-button>
|
||||||
|
<a-dropdown>
|
||||||
|
<a-menu slot="overlay" @click="handleMenuClick">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
<a-button style="margin-left: 8px">
|
||||||
|
Button <a-icon type="down" />
|
||||||
|
</a-button>
|
||||||
|
</a-dropdown>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
handleButtonClick(e) {
|
||||||
|
console.log('click left button', e);
|
||||||
|
},
|
||||||
|
handleMenuClick(e) {
|
||||||
|
console.log('click', e);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
|
@ -0,0 +1,34 @@
|
||||||
|
<cn>
|
||||||
|
#### 触发事件
|
||||||
|
点击菜单项后会触发事件,用户可以通过相应的菜单项 key 进行不同的操作。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Click event
|
||||||
|
An event will be triggered when you click menu items, in which you can make different operations according to item's key.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown>
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Hover me, Click menu item <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay" @click="onClick">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd menu item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
onClick({ key }) {
|
||||||
|
console.log(`Click on item ${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
|
@ -0,0 +1,46 @@
|
||||||
|
<script>
|
||||||
|
import Basic from './basic'
|
||||||
|
import ContextMenu from './context-menu'
|
||||||
|
import DropdownButton from './dropdown-button'
|
||||||
|
import Event from './event'
|
||||||
|
import Item from './item'
|
||||||
|
import OverlayVisible from './overlay-visible'
|
||||||
|
import Placement from './placement'
|
||||||
|
import SubMenu from './sub-menu'
|
||||||
|
import Trigger from './trigger'
|
||||||
|
import CN from '../index.zh-CN.md'
|
||||||
|
import US from '../index.en-US.md'
|
||||||
|
const md = {
|
||||||
|
cn: `# 下拉菜单
|
||||||
|
向下弹出的列表。
|
||||||
|
## 何时使用
|
||||||
|
当页面上的操作命令过多时,用此组件可以收纳操作元素。点击或移入触点,会出现一个下拉菜单。可在列表中进行选择,并执行相应的命令。
|
||||||
|
## 代码演示`,
|
||||||
|
us: `# Dropdown
|
||||||
|
A dropdown list.
|
||||||
|
## When To Use
|
||||||
|
If there are too many operations to display, you can wrap them in a \`Dropdown\`. By clicking/hovering on the trigger, a dropdown menu should appear, which allows you to choose one option and execute relevant actions.`,
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<md cn={md.cn} us={md.us}/>
|
||||||
|
<Basic />
|
||||||
|
<ContextMenu />
|
||||||
|
<DropdownButton />
|
||||||
|
<Event />
|
||||||
|
<Item/>
|
||||||
|
<OverlayVisible />
|
||||||
|
<Placement />
|
||||||
|
<SubMenu />
|
||||||
|
<Trigger />
|
||||||
|
<api>
|
||||||
|
<CN slot='cn' />
|
||||||
|
<US/>
|
||||||
|
</api>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<cn>
|
||||||
|
#### 其他元素
|
||||||
|
分割线和不可用菜单项。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Other elements
|
||||||
|
Divider and disabled menu item.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown>
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Hover me <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item key="0">
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">1st menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item key="1">
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">2nd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-divider />
|
||||||
|
<a-menu-item key="3" disabled>3rd menu item(disabled)</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
```
|
|
@ -0,0 +1,41 @@
|
||||||
|
<cn>
|
||||||
|
#### 菜单隐藏方式
|
||||||
|
默认是点击关闭菜单,可以关闭此功能。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### The way of hiding menu.
|
||||||
|
The default is to close the menu when you click on menu items, this feature can be turned off.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown v-model="visible">
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Hover me <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay" @click="handleMenuClick">
|
||||||
|
<a-menu-item key="1">Clicking me will not close the menu.</a-menu-item>
|
||||||
|
<a-menu-item key="2">Clicking me will not close the menu also.</a-menu-item>
|
||||||
|
<a-menu-item key="3">Clicking me will close the menu</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleMenuClick (e) {
|
||||||
|
if (e.key === '3') {
|
||||||
|
this.visible = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
|
@ -0,0 +1,49 @@
|
||||||
|
<cn>
|
||||||
|
#### 弹出位置
|
||||||
|
支持 6 个弹出位置。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Placement
|
||||||
|
Support 6 placements.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div id="components-dropdown-demo-placement">
|
||||||
|
<template v-for="(placement, index) in placements">
|
||||||
|
<a-dropdown :placement="placement">
|
||||||
|
<a-button>{{placement}}</a-button>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">1st menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">2nd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">3rd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
<br v-if="index === 2"/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
placements: ['bottomLeft', 'bottomCenter', 'bottomRight', 'topLeft', 'topCenter', 'topRight'],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
#components-dropdown-demo-placement .ant-btn {
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
|
@ -0,0 +1,31 @@
|
||||||
|
<cn>
|
||||||
|
#### 多级菜单
|
||||||
|
传入的菜单里有多个层级。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Cascading menu
|
||||||
|
The menu has multiple levels.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown>
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Cascading menu <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item>1st menu item</a-menu-item>
|
||||||
|
<a-menu-item>2nd menu item</a-menu-item>
|
||||||
|
<a-sub-menu title="sub menu" key="test">
|
||||||
|
<a-menu-item>3rd menu item</a-menu-item>
|
||||||
|
<a-menu-item>4th menu item</a-menu-item>
|
||||||
|
</a-sub-menu>
|
||||||
|
<a-sub-menu title="disabled sub menu" disabled>
|
||||||
|
<a-menu-item>5d menu item</a-menu-item>
|
||||||
|
<a-menu-item>6th menu item</a-menu-item>
|
||||||
|
</a-sub-menu>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
```
|
|
@ -0,0 +1,29 @@
|
||||||
|
<cn>
|
||||||
|
#### 触发方式
|
||||||
|
默认是移入触发菜单,可以点击触发。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Trigger mode
|
||||||
|
The default trigger mode is `hover`, you can change it to `click`.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown :trigger="['click']">
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Click me <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item key="0">
|
||||||
|
<a href="http://www.alipay.com/">1st menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item key="1">
|
||||||
|
<a href="http://www.taobao.com/">2nd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-divider />
|
||||||
|
<a-menu-item key="3">3rd menu item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
```
|
|
@ -0,0 +1,81 @@
|
||||||
|
<script>
|
||||||
|
import Button from '../button'
|
||||||
|
import { ButtonGroupProps } from '../button/button-group'
|
||||||
|
import Icon from '../icon'
|
||||||
|
import Dropdown from './dropdown'
|
||||||
|
import PropTypes from '../_util/vue-types'
|
||||||
|
import { hasProp, getComponentFromProp } from '../_util/props-util'
|
||||||
|
import getDropdownProps from './getDropdownProps'
|
||||||
|
const DropdownProps = getDropdownProps()
|
||||||
|
const ButtonGroup = Button.Group
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
...ButtonGroupProps,
|
||||||
|
...DropdownProps,
|
||||||
|
type: PropTypes.oneOf(['primary', 'ghost', 'dashed', 'default']).def('default'),
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
prefixCls: PropTypes.string.def('ant-dropdown-button'),
|
||||||
|
placement: DropdownProps.placement.def('bottomRight'),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick (e) {
|
||||||
|
this.$emit('click', e)
|
||||||
|
},
|
||||||
|
onVisibleChange (val) {
|
||||||
|
this.$emit('visibleChange', val)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'visible',
|
||||||
|
event: 'visibleChange',
|
||||||
|
},
|
||||||
|
render () {
|
||||||
|
const {
|
||||||
|
type, disabled,
|
||||||
|
prefixCls, trigger, align,
|
||||||
|
visible, placement, getPopupContainer,
|
||||||
|
...restProps
|
||||||
|
} = this.$props
|
||||||
|
|
||||||
|
const dropdownProps = {
|
||||||
|
props: {
|
||||||
|
align,
|
||||||
|
disabled,
|
||||||
|
trigger: disabled ? [] : trigger,
|
||||||
|
placement,
|
||||||
|
getPopupContainer,
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
visibleChange: this.onVisibleChange,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if (hasProp(this, 'visible')) {
|
||||||
|
dropdownProps.visible = visible
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ButtonGroup
|
||||||
|
{...restProps}
|
||||||
|
class={prefixCls}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type={type}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={this.onClick}
|
||||||
|
>
|
||||||
|
{this.$slots.default}
|
||||||
|
</Button>
|
||||||
|
<Dropdown {...dropdownProps}>
|
||||||
|
<template slot='overlay'>
|
||||||
|
{getComponentFromProp(this, 'overlay')}
|
||||||
|
</template>
|
||||||
|
<Button type={type}>
|
||||||
|
<Icon type='down' />
|
||||||
|
</Button>
|
||||||
|
</Dropdown>
|
||||||
|
</ButtonGroup>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,76 @@
|
||||||
|
<script>
|
||||||
|
import RcDropdown from './src/dropdown'
|
||||||
|
import DropdownButton from './dropdown-button'
|
||||||
|
// import warning from '../_util/warning'
|
||||||
|
import PropTypes from '../_util/vue-types'
|
||||||
|
import { cloneElement, getPropsData } from '../_util/vnode'
|
||||||
|
import { getOptionProps } from '../_util/props-util'
|
||||||
|
import getDropdownProps from './getDropdownProps'
|
||||||
|
const DropdownProps = getDropdownProps()
|
||||||
|
const Dropdown = {
|
||||||
|
props: {
|
||||||
|
...DropdownProps,
|
||||||
|
prefixCls: PropTypes.string.def('ant-dropdown'),
|
||||||
|
mouseEnterDelay: PropTypes.number.def(0.15),
|
||||||
|
mouseLeaveDelay: PropTypes.number.def(0.1),
|
||||||
|
placement: DropdownProps.placement.def('bottomLeft'),
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'visible',
|
||||||
|
event: 'visibleChange',
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getTransitionName () {
|
||||||
|
const { placement = '', transitionName } = this.$props
|
||||||
|
if (transitionName !== undefined) {
|
||||||
|
return transitionName
|
||||||
|
}
|
||||||
|
if (placement.indexOf('top') >= 0) {
|
||||||
|
return 'slide-down'
|
||||||
|
}
|
||||||
|
return 'slide-up'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { $slots, prefixCls, trigger, disabled, $listeners } = this
|
||||||
|
const dropdownTrigger = cloneElement($slots.default, {
|
||||||
|
class: `${prefixCls}-trigger`,
|
||||||
|
disabled,
|
||||||
|
})
|
||||||
|
const overlay = $slots.overlay && $slots.overlay[0]
|
||||||
|
// menu cannot be selectable in dropdown defaultly
|
||||||
|
const overlayProps = overlay && getPropsData(overlay)
|
||||||
|
const selectable = (overlayProps && 'selectable' in overlayProps)
|
||||||
|
? overlayProps.selectable : false
|
||||||
|
const fixedModeOverlay = cloneElement(overlay, {
|
||||||
|
props: {
|
||||||
|
mode: 'vertical',
|
||||||
|
selectable,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const dropdownProps = {
|
||||||
|
props: {
|
||||||
|
...getOptionProps(this),
|
||||||
|
transitionName: this.getTransitionName(),
|
||||||
|
trigger: disabled ? [] : trigger,
|
||||||
|
},
|
||||||
|
on: $listeners,
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<RcDropdown
|
||||||
|
{...dropdownProps}
|
||||||
|
>
|
||||||
|
{dropdownTrigger}
|
||||||
|
<template slot='overlay'>
|
||||||
|
{fixedModeOverlay}
|
||||||
|
</template>
|
||||||
|
</RcDropdown>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Dropdown.Button = DropdownButton
|
||||||
|
export default Dropdown
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,13 @@
|
||||||
|
import PropTypes from '../_util/vue-types'
|
||||||
|
export default () => ({
|
||||||
|
trigger: PropTypes.array.def(['hover']),
|
||||||
|
overlay: PropTypes.any,
|
||||||
|
visible: PropTypes.bool,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
align: PropTypes.object,
|
||||||
|
getPopupContainer: PropTypes.func,
|
||||||
|
prefixCls: PropTypes.string,
|
||||||
|
transitionName: PropTypes.string,
|
||||||
|
placement: PropTypes.oneOf(['topLeft', 'topCenter', 'topRight', 'bottomLeft', 'bottomCenter', 'bottomRight']),
|
||||||
|
forceRender: PropTypes.bool,
|
||||||
|
})
|
|
@ -0,0 +1,43 @@
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Dropdown
|
||||||
|
|
||||||
|
| Property | Description | Type | Default |
|
||||||
|
| -------- | ----------- | ---- | ------- |
|
||||||
|
| disabled | whether the dropdown menu is disabled | boolean | - |
|
||||||
|
| getPopupContainer | to set the container of the dropdown menu. The default is to create a `div` element in `body`, you can reset it to the scrolling area and make a relative reposition. [example](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | Function(triggerNode) | `() => document.body` |
|
||||||
|
| overlay(slot) | the dropdown menu | [Menu](#/components/us/menu) | - |
|
||||||
|
| placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||||
|
| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||||
|
| visible(v-model) | whether the dropdown menu is visible | boolean | - |
|
||||||
|
|
||||||
|
### events
|
||||||
|
| Events Name | Description | Arguments |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| visibleChange | a callback function takes an argument: `visible`, is executed when the visible state is changed | function(visible) |
|
||||||
|
|
||||||
|
You should use [Menu](#/components/us/menu/) as `overlay`. The menu items and dividers are also available by using `Menu.Item` and `Menu.Divider`.
|
||||||
|
|
||||||
|
> Warning: You must set a unique `key` for `Menu.Item`.
|
||||||
|
>
|
||||||
|
> Menu of Dropdown is unselectable by default, you can make it selectable via `<Menu selectable>`.
|
||||||
|
|
||||||
|
### Dropdown.Button
|
||||||
|
|
||||||
|
| Property | Description | Type | Default |
|
||||||
|
| -------- | ----------- | ---- | ------- |
|
||||||
|
| disabled | whether the dropdown menu is disabled | boolean | - |
|
||||||
|
| overlay(slot) | the dropdown menu | [Menu](#/components/us/menu) | - |
|
||||||
|
| placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||||
|
| size | size of the button, the same as [Button](#/components/us/button) | string | `default` |
|
||||||
|
| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||||
|
| type | type of the button, the same as [Button](#/components/us/button) | string | `default` |
|
||||||
|
| visible | whether the dropdown menu is visible | boolean | - |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Dropdown.Button events
|
||||||
|
| Events Name | Description | Arguments |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| click | a callback function, the same as [Button](#/components/us/button), which will be executed when you click the button on the left | Function |
|
||||||
|
| visibleChange | a callback function takes an argument: `visible`, is executed when the visible state is changed | Function |
|
|
@ -0,0 +1,8 @@
|
||||||
|
import Dropdown from './dropdown'
|
||||||
|
import DropdownButton from './dropdown-button'
|
||||||
|
|
||||||
|
export { DropDownProps } from './dropdown'
|
||||||
|
export { DropdownButtonProps } from './dropdown-button'
|
||||||
|
|
||||||
|
Dropdown.Button = DropdownButton
|
||||||
|
export default Dropdown
|
|
@ -0,0 +1,42 @@
|
||||||
|
## API
|
||||||
|
|
||||||
|
属性如下
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| disabled | 菜单是否禁用 | boolean | - |
|
||||||
|
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | `() => document.body` |
|
||||||
|
| overlay(slot) | 菜单 | [Menu](#/components/cn/menu) | - |
|
||||||
|
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||||
|
| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||||
|
| visible(v-model) | 菜单是否显示 | boolean | - |
|
||||||
|
|
||||||
|
`overlay` 菜单使用 [Menu](#/components/cn/menu/),还包括菜单项 `Menu.Item`,分割线 `Menu.Divider`。
|
||||||
|
|
||||||
|
> 注意: Menu.Item 必须设置唯一的 key 属性。
|
||||||
|
>
|
||||||
|
> Dropdown 下的 Menu 默认不可选中。如果需要菜单可选中,可以指定 `<Menu selectable>`.
|
||||||
|
|
||||||
|
### 事件
|
||||||
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| visibleChange | 菜单显示状态改变时调用,参数为 visible | function(visible) |
|
||||||
|
|
||||||
|
|
||||||
|
### Dropdown.Button
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| disabled | 菜单是否禁用 | boolean | - |
|
||||||
|
| overlay(slot) | 菜单 | [Menu](#/components/cn/menu/) | - |
|
||||||
|
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||||
|
| size | 按钮大小,和 [Button](#/components/cn/button/) 一致 | string | 'default' |
|
||||||
|
| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||||
|
| type | 按钮类型,和 [Button](#/components/cn/button/) 一致 | string | 'default' |
|
||||||
|
| visible(v-model) | 菜单是否显示 | boolean | - |
|
||||||
|
|
||||||
|
### Dropdown.Button事件
|
||||||
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| click | 点击左侧按钮的回调,和 [Button](#/components/cn/button/) 一致 | Function |
|
||||||
|
| visibleChange | 菜单显示状态改变时调用,参数为 visible | function(visible) |
|
|
@ -0,0 +1,157 @@
|
||||||
|
<script>
|
||||||
|
import PropTypes from '../../_util/vue-types'
|
||||||
|
import Trigger from '../../trigger'
|
||||||
|
import placements from './placements'
|
||||||
|
import { hasProp } from '../../_util/props-util'
|
||||||
|
import BaseMixin from '../../_util/BaseMixin'
|
||||||
|
import { cloneElement, getEvents } from '../../_util/vnode'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [BaseMixin],
|
||||||
|
props: {
|
||||||
|
minOverlayWidthMatchTrigger: PropTypes.bool.def(true),
|
||||||
|
prefixCls: PropTypes.string.def('rc-dropdown'),
|
||||||
|
transitionName: PropTypes.string,
|
||||||
|
overlayClassName: PropTypes.string.def(''),
|
||||||
|
animation: PropTypes.any,
|
||||||
|
align: PropTypes.object,
|
||||||
|
overlayStyle: PropTypes.object.def({}),
|
||||||
|
placement: PropTypes.string.def('bottomLeft'),
|
||||||
|
trigger: PropTypes.array.def(['hover']),
|
||||||
|
showAction: PropTypes.array.def([]),
|
||||||
|
hideAction: PropTypes.array.def([]),
|
||||||
|
getPopupContainer: PropTypes.func,
|
||||||
|
visible: PropTypes.bool,
|
||||||
|
defaultVisible: PropTypes.bool.def(false),
|
||||||
|
mouseEnterDelay: PropTypes.number.def(0.15),
|
||||||
|
mouseLeaveDelay: PropTypes.number.def(0.1),
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
let sVisible = this.defaultVisible
|
||||||
|
if (hasProp(this, 'visible')) {
|
||||||
|
sVisible = this.visible
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
sVisible,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
visible (val) {
|
||||||
|
if (val !== undefined) {
|
||||||
|
this.setState({
|
||||||
|
sVisible: val,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick (e) {
|
||||||
|
// do no call onVisibleChange, if you need click to hide, use onClick and control visible
|
||||||
|
if (!hasProp(this, 'visible')) {
|
||||||
|
this.setState({
|
||||||
|
sVisible: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.$emit('overlayClick', e)
|
||||||
|
if (this.childOriginEvents.click) {
|
||||||
|
this.childOriginEvents.click(e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onVisibleChange (visible) {
|
||||||
|
if (!hasProp(this, 'visible')) {
|
||||||
|
this.setState({
|
||||||
|
sVisible: visible,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.__emit('visibleChange', visible)
|
||||||
|
},
|
||||||
|
|
||||||
|
getMenuElement () {
|
||||||
|
const child = this.$slots.overlay[0]
|
||||||
|
const events = getEvents(child)
|
||||||
|
if (!events._ANT_DROPDOWN_EVENT_HACK) {
|
||||||
|
this.childOriginEvents = events
|
||||||
|
}
|
||||||
|
const { prefixCls } = this.$props
|
||||||
|
const extraOverlayProps = {
|
||||||
|
prefixCls: `${prefixCls}-menu`,
|
||||||
|
}
|
||||||
|
const overlay = this.$slots.overlay[0]
|
||||||
|
return cloneElement(overlay, {
|
||||||
|
props: extraOverlayProps,
|
||||||
|
on: {
|
||||||
|
click: this.onClick,
|
||||||
|
_ANT_DROPDOWN_EVENT_HACK: () => {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
getPopupDomNode () {
|
||||||
|
return this.$refs.trigger.getPopupDomNode()
|
||||||
|
},
|
||||||
|
|
||||||
|
afterVisibleChange (visible) {
|
||||||
|
if (visible && this.$props.minOverlayWidthMatchTrigger) {
|
||||||
|
const overlayNode = this.getPopupDomNode()
|
||||||
|
const rootNode = this.$el
|
||||||
|
if (rootNode && overlayNode && rootNode.offsetWidth > overlayNode.offsetWidth) {
|
||||||
|
overlayNode.style.width = `${rootNode.offsetWidth}px`
|
||||||
|
if (this.$refs.trigger &&
|
||||||
|
this.$refs.trigger._component &&
|
||||||
|
this.$refs.trigger._component.alignInstance) {
|
||||||
|
this.$refs.trigger._component.alignInstance.forceAlign()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const {
|
||||||
|
prefixCls,
|
||||||
|
transitionName, animation,
|
||||||
|
align, placement, getPopupContainer,
|
||||||
|
showAction, hideAction,
|
||||||
|
overlayClassName, overlayStyle,
|
||||||
|
trigger, ...otherProps
|
||||||
|
} = this.$props
|
||||||
|
|
||||||
|
const triggerProps = {
|
||||||
|
props: {
|
||||||
|
...otherProps,
|
||||||
|
prefixCls,
|
||||||
|
popupClassName: overlayClassName,
|
||||||
|
popupStyle: overlayStyle,
|
||||||
|
builtinPlacements: placements,
|
||||||
|
action: trigger,
|
||||||
|
showAction,
|
||||||
|
hideAction,
|
||||||
|
popupPlacement: placement,
|
||||||
|
popupAlign: align,
|
||||||
|
popupTransitionName: transitionName,
|
||||||
|
popupAnimation: animation,
|
||||||
|
popupVisible: this.sVisible,
|
||||||
|
afterPopupVisibleChange: this.afterVisibleChange,
|
||||||
|
getPopupContainer: getPopupContainer,
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
popupVisibleChange: this.onVisibleChange,
|
||||||
|
},
|
||||||
|
ref: 'trigger',
|
||||||
|
}
|
||||||
|
const child = this.$slots.default && this.$slots.default[0]
|
||||||
|
return (
|
||||||
|
<Trigger {...triggerProps}>
|
||||||
|
{child && !child.tag
|
||||||
|
? <span>{child}</span>
|
||||||
|
: child}
|
||||||
|
<template slot='popup'>
|
||||||
|
{this.$slots.overlay && this.getMenuElement()}
|
||||||
|
</template>
|
||||||
|
</Trigger>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,2 @@
|
||||||
|
import Dropdown from './Dropdown'
|
||||||
|
export default Dropdown
|
|
@ -0,0 +1,47 @@
|
||||||
|
const autoAdjustOverflow = {
|
||||||
|
adjustX: 1,
|
||||||
|
adjustY: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetOffset = [0, 0]
|
||||||
|
|
||||||
|
export const placements = {
|
||||||
|
topLeft: {
|
||||||
|
points: ['bl', 'tl'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, -4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
topCenter: {
|
||||||
|
points: ['bc', 'tc'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, -4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
topRight: {
|
||||||
|
points: ['br', 'tr'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, -4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
bottomLeft: {
|
||||||
|
points: ['tl', 'bl'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, 4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
bottomCenter: {
|
||||||
|
points: ['tc', 'bc'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, 4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
bottomRight: {
|
||||||
|
points: ['tr', 'br'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, 4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default placements
|
|
@ -0,0 +1,5 @@
|
||||||
|
import '../../style/index.less'
|
||||||
|
import './index.less'
|
||||||
|
|
||||||
|
// style dependencies
|
||||||
|
import '../../button/style'
|
|
@ -0,0 +1,250 @@
|
||||||
|
@import "../../style/themes/default";
|
||||||
|
@import "../../style/mixins/index";
|
||||||
|
|
||||||
|
@dropdown-prefix-cls: ~"@{ant-prefix}-dropdown";
|
||||||
|
|
||||||
|
.@{dropdown-prefix-cls} {
|
||||||
|
.reset-component;
|
||||||
|
position: absolute;
|
||||||
|
left: -9999px;
|
||||||
|
top: -9999px;
|
||||||
|
z-index: @zindex-dropdown;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
&-wrap {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.@{ant-prefix}-btn > .@{iconfont-css-prefix}-down {
|
||||||
|
.iconfont-size-under-12px(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{iconfont-css-prefix}-down:before {
|
||||||
|
transition: transform .2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-wrap-open {
|
||||||
|
.@{iconfont-css-prefix}-down:before {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-hidden,
|
||||||
|
&-menu-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-menu {
|
||||||
|
outline: none;
|
||||||
|
position: relative;
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
text-align: left;
|
||||||
|
background-color: @component-background;
|
||||||
|
border-radius: @border-radius-base;
|
||||||
|
box-shadow: @box-shadow-base;
|
||||||
|
background-clip: padding-box;
|
||||||
|
|
||||||
|
&-item-group-title {
|
||||||
|
color: @text-color-secondary;
|
||||||
|
padding: 5px @control-padding-horizontal;
|
||||||
|
transition: all .3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu-popup {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-item,
|
||||||
|
&-submenu-title {
|
||||||
|
padding: 5px @control-padding-horizontal;
|
||||||
|
margin: 0;
|
||||||
|
clear: both;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
font-weight: normal;
|
||||||
|
color: @text-color;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all .3s;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
> a {
|
||||||
|
color: @text-color;
|
||||||
|
display: block;
|
||||||
|
padding: 5px @control-padding-horizontal;
|
||||||
|
margin: -5px -@control-padding-horizontal;
|
||||||
|
transition: all .3s;
|
||||||
|
&:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-selected,
|
||||||
|
&-selected > a {
|
||||||
|
color: @primary-color;
|
||||||
|
background-color: @item-active-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: @item-hover-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-disabled {
|
||||||
|
color: @disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @disabled-color;
|
||||||
|
background-color: @component-background;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child,
|
||||||
|
&:first-child > a {
|
||||||
|
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child,
|
||||||
|
&:last-child > a {
|
||||||
|
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:only-child,
|
||||||
|
&:only-child > a {
|
||||||
|
border-radius: @border-radius-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-divider {
|
||||||
|
height: 1px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: @border-color-split;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
.@{dropdown-prefix-cls}-menu-submenu-arrow {
|
||||||
|
position: absolute;
|
||||||
|
right: @padding-xs;
|
||||||
|
&:after {
|
||||||
|
font-family: "anticon" !important;
|
||||||
|
font-style: normal;
|
||||||
|
content: "\e61f";
|
||||||
|
color: @text-color-secondary;
|
||||||
|
.iconfont-size-under-12px(10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu-title {
|
||||||
|
padding-right: 26px;
|
||||||
|
&:first-child,
|
||||||
|
&:last-child {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu-vertical {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu-vertical > & {
|
||||||
|
top: 0;
|
||||||
|
left: 100%;
|
||||||
|
position: absolute;
|
||||||
|
min-width: 100%;
|
||||||
|
margin-left: 4px;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu&-submenu-disabled .@{dropdown-prefix-cls}-menu-submenu-title {
|
||||||
|
&,
|
||||||
|
.@{dropdown-prefix-cls}-menu-submenu-arrow:after {
|
||||||
|
color: @disabled-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-submenu:first-child &-submenu-title {
|
||||||
|
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu:last-child &-submenu-title {
|
||||||
|
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-down-enter.slide-down-enter-active&-placement-bottomLeft,
|
||||||
|
&.slide-down-appear.slide-down-appear-active&-placement-bottomLeft,
|
||||||
|
&.slide-down-enter.slide-down-enter-active&-placement-bottomCenter,
|
||||||
|
&.slide-down-appear.slide-down-appear-active&-placement-bottomCenter,
|
||||||
|
&.slide-down-enter.slide-down-enter-active&-placement-bottomRight,
|
||||||
|
&.slide-down-appear.slide-down-appear-active&-placement-bottomRight {
|
||||||
|
animation-name: antSlideUpIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-enter.slide-up-enter-active&-placement-topLeft,
|
||||||
|
&.slide-up-appear.slide-up-appear-active&-placement-topLeft,
|
||||||
|
&.slide-up-enter.slide-up-enter-active&-placement-topCenter,
|
||||||
|
&.slide-up-appear.slide-up-appear-active&-placement-topCenter,
|
||||||
|
&.slide-up-enter.slide-up-enter-active&-placement-topRight,
|
||||||
|
&.slide-up-appear.slide-up-appear-active&-placement-topRight {
|
||||||
|
animation-name: antSlideDownIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-down-leave.slide-down-leave-active&-placement-bottomLeft,
|
||||||
|
&.slide-down-leave.slide-down-leave-active&-placement-bottomCenter,
|
||||||
|
&.slide-down-leave.slide-down-leave-active&-placement-bottomRight {
|
||||||
|
animation-name: antSlideUpOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-leave.slide-up-leave-active&-placement-topLeft,
|
||||||
|
&.slide-up-leave.slide-up-leave-active&-placement-topCenter,
|
||||||
|
&.slide-up-leave.slide-up-leave-active&-placement-topRight {
|
||||||
|
animation-name: antSlideDownOut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{dropdown-prefix-cls}-trigger,
|
||||||
|
.@{dropdown-prefix-cls}-link {
|
||||||
|
.@{iconfont-css-prefix}-down {
|
||||||
|
.iconfont-size-under-12px(10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{dropdown-prefix-cls}-button {
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&.@{ant-prefix}-btn-group > .@{ant-prefix}-btn:last-child:not(:first-child) {
|
||||||
|
padding-left: @padding-xs;
|
||||||
|
padding-right: @padding-xs;
|
||||||
|
}
|
||||||
|
.@{iconfont-css-prefix}-down {
|
||||||
|
.iconfont-size-under-12px(10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/ant-design/ant-design/issues/4903
|
||||||
|
.@{dropdown-prefix-cls}-menu-dark {
|
||||||
|
&,
|
||||||
|
.@{dropdown-prefix-cls}-menu {
|
||||||
|
background: @menu-dark-bg;
|
||||||
|
}
|
||||||
|
.@{dropdown-prefix-cls}-menu-item,
|
||||||
|
.@{dropdown-prefix-cls}-menu-submenu-title,
|
||||||
|
.@{dropdown-prefix-cls}-menu-item > a {
|
||||||
|
color: @text-color-secondary-dark;
|
||||||
|
.@{dropdown-prefix-cls}-menu-submenu-arrow:after {
|
||||||
|
color: @text-color-secondary-dark;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.@{dropdown-prefix-cls}-menu-item-selected {
|
||||||
|
&,
|
||||||
|
&:hover,
|
||||||
|
> a {
|
||||||
|
background: @primary-color;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,15 @@ export { default as Popover } from './popover'
|
||||||
|
|
||||||
export { default as Popconfirm } from './popconfirm'
|
export { default as Popconfirm } from './popconfirm'
|
||||||
|
|
||||||
export { default as Menu } from './menu'
|
import Menu from './menu'
|
||||||
|
const MenuItem = Menu.Item
|
||||||
|
const SubMenu = Menu.SubMenu
|
||||||
|
const MenuDivider = Menu.Divider
|
||||||
|
const MenuItemGroup = Menu.ItemGroup
|
||||||
|
export { Menu, MenuItem, SubMenu, MenuDivider, MenuItemGroup }
|
||||||
|
|
||||||
export { default as Card } from './card'
|
export { default as Card } from './card'
|
||||||
|
|
||||||
|
import Dropdown from './dropdown'
|
||||||
|
const DropdownButton = Dropdown.Button
|
||||||
|
export { Dropdown, DropdownButton }
|
||||||
|
|
|
@ -14,3 +14,4 @@ import './tooltip/style'
|
||||||
import './popover/style'
|
import './popover/style'
|
||||||
import './popconfirm/style'
|
import './popconfirm/style'
|
||||||
import './menu/style'
|
import './menu/style'
|
||||||
|
import './dropdown/style'
|
||||||
|
|
|
@ -18,7 +18,7 @@ function returnDocument () {
|
||||||
return window.document
|
return window.document
|
||||||
}
|
}
|
||||||
const ALL_HANDLERS = ['click', 'mousedown', 'touchStart', 'mouseenter',
|
const ALL_HANDLERS = ['click', 'mousedown', 'touchStart', 'mouseenter',
|
||||||
'mouseleave', 'focus', 'blur', 'contextMenu']
|
'mouseleave', 'focus', 'blur', 'contextmenu']
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Trigger',
|
name: 'Trigger',
|
||||||
|
@ -124,7 +124,7 @@ export default {
|
||||||
// https://github.com/react-component/trigger/issues/50
|
// https://github.com/react-component/trigger/issues/50
|
||||||
if (state.sPopupVisible) {
|
if (state.sPopupVisible) {
|
||||||
let currentDocument
|
let currentDocument
|
||||||
if (!this.clickOutsideHandler && (this.isClickToHide() || this.isContextMenuToShow())) {
|
if (!this.clickOutsideHandler && (this.isClickToHide() || this.isContextmenuToShow())) {
|
||||||
currentDocument = props.getDocument()
|
currentDocument = props.getDocument()
|
||||||
this.clickOutsideHandler = addEventListener(currentDocument,
|
this.clickOutsideHandler = addEventListener(currentDocument,
|
||||||
'mousedown', this.onDocumentClick)
|
'mousedown', this.onDocumentClick)
|
||||||
|
@ -135,16 +135,16 @@ export default {
|
||||||
this.touchOutsideHandler = addEventListener(currentDocument,
|
this.touchOutsideHandler = addEventListener(currentDocument,
|
||||||
'touchstart', this.onDocumentClick)
|
'touchstart', this.onDocumentClick)
|
||||||
}
|
}
|
||||||
// close popup when trigger type contains 'onContextMenu' and document is scrolling.
|
// close popup when trigger type contains 'onContextmenu' and document is scrolling.
|
||||||
if (!this.contextMenuOutsideHandler1 && this.isContextMenuToShow()) {
|
if (!this.contextmenuOutsideHandler1 && this.isContextmenuToShow()) {
|
||||||
currentDocument = currentDocument || props.getDocument()
|
currentDocument = currentDocument || props.getDocument()
|
||||||
this.contextMenuOutsideHandler1 = addEventListener(currentDocument,
|
this.contextmenuOutsideHandler1 = addEventListener(currentDocument,
|
||||||
'scroll', this.onContextMenuClose)
|
'scroll', this.onContextmenuClose)
|
||||||
}
|
}
|
||||||
// close popup when trigger type contains 'onContextMenu' and window is blur.
|
// close popup when trigger type contains 'onContextmenu' and window is blur.
|
||||||
if (!this.contextMenuOutsideHandler2 && this.isContextMenuToShow()) {
|
if (!this.contextmenuOutsideHandler2 && this.isContextmenuToShow()) {
|
||||||
this.contextMenuOutsideHandler2 = addEventListener(window,
|
this.contextmenuOutsideHandler2 = addEventListener(window,
|
||||||
'blur', this.onContextMenuClose)
|
'blur', this.onContextmenuClose)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -203,14 +203,14 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onContextMenu (e) {
|
onContextmenu (e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
this.fireEvents('contextMenu', e)
|
this.fireEvents('contextmenu', e)
|
||||||
this.setPopupVisible(true)
|
this.setPopupVisible(true)
|
||||||
},
|
},
|
||||||
|
|
||||||
onContextMenuClose () {
|
onContextmenuClose () {
|
||||||
if (this.isContextMenuToShow()) {
|
if (this.isContextmenuToShow()) {
|
||||||
this.close()
|
this.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -401,14 +401,14 @@ export default {
|
||||||
this.clickOutsideHandler = null
|
this.clickOutsideHandler = null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.contextMenuOutsideHandler1) {
|
if (this.contextmenuOutsideHandler1) {
|
||||||
this.contextMenuOutsideHandler1.remove()
|
this.contextmenuOutsideHandler1.remove()
|
||||||
this.contextMenuOutsideHandler1 = null
|
this.contextmenuOutsideHandler1 = null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.contextMenuOutsideHandler2) {
|
if (this.contextmenuOutsideHandler2) {
|
||||||
this.contextMenuOutsideHandler2.remove()
|
this.contextmenuOutsideHandler2.remove()
|
||||||
this.contextMenuOutsideHandler2 = null
|
this.contextmenuOutsideHandler2 = null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.touchOutsideHandler) {
|
if (this.touchOutsideHandler) {
|
||||||
|
@ -433,9 +433,9 @@ export default {
|
||||||
return action.indexOf('click') !== -1 || showAction.indexOf('click') !== -1
|
return action.indexOf('click') !== -1 || showAction.indexOf('click') !== -1
|
||||||
},
|
},
|
||||||
|
|
||||||
isContextMenuToShow () {
|
isContextmenuToShow () {
|
||||||
const { action, showAction } = this.$props
|
const { action, showAction } = this.$props
|
||||||
return action.indexOf('contextMenu') !== -1 || showAction.indexOf('contextMenu') !== -1
|
return action.indexOf('contextmenu') !== -1 || showAction.indexOf('contextmenu') !== -1
|
||||||
},
|
},
|
||||||
|
|
||||||
isClickToHide () {
|
isClickToHide () {
|
||||||
|
@ -485,20 +485,20 @@ export default {
|
||||||
}
|
}
|
||||||
const child = children[0]
|
const child = children[0]
|
||||||
const events = getEvents(child)
|
const events = getEvents(child)
|
||||||
// 黑科技,vue暂未发现保留原事件的方法,使用_ANT_EVENT_HACK来判断事件是否更新
|
// 黑科技,vue暂未发现保留原事件的方法,使用_ANT_TRIGGER_EVENT_HACK来判断事件是否更新
|
||||||
if (!events._ANT_EVENT_HACK) {
|
if (!events._ANT_TRIGGER_EVENT_HACK) {
|
||||||
this.childOriginEvents = events
|
this.childOriginEvents = events
|
||||||
}
|
}
|
||||||
const newChildProps = {
|
const newChildProps = {
|
||||||
props: {},
|
props: {},
|
||||||
on: { _ANT_EVENT_HACK: () => {} },
|
on: { _ANT_TRIGGER_EVENT_HACK: () => {} },
|
||||||
key: 'trigger',
|
key: 'trigger',
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isContextMenuToShow()) {
|
if (this.isContextmenuToShow()) {
|
||||||
newChildProps.on.contextMenu = this.onContextMenu
|
newChildProps.on.contextmenu = this.onContextmenu
|
||||||
} else {
|
} else {
|
||||||
newChildProps.on.contextMenu = this.createTwoChains('contextMenu')
|
newChildProps.on.contextmenu = this.createTwoChains('contextmenu')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isClickToHide() || this.isClickToShow()) {
|
if (this.isClickToHide() || this.isClickToShow()) {
|
||||||
|
|
|
@ -16,4 +16,5 @@ export { default as rate } from 'antd/rate/demo/index.vue'
|
||||||
export { default as tabs } from 'antd/tabs/demo/index.vue'
|
export { default as tabs } from 'antd/tabs/demo/index.vue'
|
||||||
export { default as tag } from 'antd/tag/demo/index.vue'
|
export { default as tag } from 'antd/tag/demo/index.vue'
|
||||||
export { default as tooltip } from 'antd/tooltip/demo/index.vue'
|
export { default as tooltip } from 'antd/tooltip/demo/index.vue'
|
||||||
|
export { default as dropdown } from 'antd/dropdown/demo/index.vue'
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Demo from './components/demo.vue'
|
import Demo from './components/demo.vue'
|
||||||
const AsyncComp = () => {
|
const AsyncComp = () => {
|
||||||
return {
|
return {
|
||||||
component: import(`../components/avatar/demo/index.vue`),
|
component: import(`../components/dropdown/demo/sub-menu.md`),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default [
|
export default [
|
||||||
|
|
Loading…
Reference in New Issue