ant-design-vue/components/vc-cascader/Menus.vue

157 lines
3.9 KiB
Vue
Raw Normal View History

2018-03-02 08:54:22 +00:00
<script>
import React from 'react'
import PropTypes from 'prop-types'
import arrayTreeFilter from 'array-tree-filter'
import { findDOMNode } from 'react-dom'
class Menus extends React.Component {
constructor (props) {
super(props)
this.menuItems = {}
}
componentDidMount () {
this.scrollActiveItemToView()
}
componentDidUpdate (prevProps) {
if (!prevProps.visible && this.props.visible) {
this.scrollActiveItemToView()
}
}
getOption (option, menuIndex) {
const { prefixCls, expandTrigger } = this.props
const onSelect = this.props.onSelect.bind(this, option, menuIndex)
let expandProps = {
onClick: onSelect,
}
let menuItemCls = `${prefixCls}-menu-item`
const hasChildren = option.children && option.children.length > 0
if (hasChildren || option.isLeaf === false) {
menuItemCls += ` ${prefixCls}-menu-item-expand`
}
if (expandTrigger === 'hover' && hasChildren) {
expandProps = {
onMouseEnter: this.delayOnSelect.bind(this, onSelect),
onMouseLeave: this.delayOnSelect.bind(this),
onClick: onSelect,
}
}
if (this.isActiveOption(option, menuIndex)) {
menuItemCls += ` ${prefixCls}-menu-item-active`
expandProps.ref = this.saveMenuItem(menuIndex)
}
if (option.disabled) {
menuItemCls += ` ${prefixCls}-menu-item-disabled`
}
if (option.loading) {
menuItemCls += ` ${prefixCls}-menu-item-loading`
}
let title = ''
if (option.title) {
title = option.title
} else if (typeof option.label === 'string') {
title = option.label
}
return (
<li
key={option.value}
className={menuItemCls}
title={title}
{...expandProps}
>
{option.label}
</li>
)
}
getActiveOptions (values) {
const activeValue = values || this.props.activeValue
const options = this.props.options
return arrayTreeFilter(options, (o, level) => o.value === activeValue[level])
}
getShowOptions () {
const { options } = this.props
const result = this.getActiveOptions()
.map(activeOption => activeOption.children)
.filter(activeOption => !!activeOption)
result.unshift(options)
return result
}
delayOnSelect (onSelect, ...args) {
if (this.delayTimer) {
clearTimeout(this.delayTimer)
this.delayTimer = null
}
if (typeof onSelect === 'function') {
this.delayTimer = setTimeout(() => {
onSelect(args)
this.delayTimer = null
}, 150)
}
}
scrollActiveItemToView () {
// scroll into view
const optionsLength = this.getShowOptions().length
for (let i = 0; i < optionsLength; i++) {
const itemComponent = this.menuItems[i]
if (itemComponent) {
const target = findDOMNode(itemComponent)
target.parentNode.scrollTop = target.offsetTop
}
}
}
isActiveOption (option, menuIndex) {
const { activeValue = [] } = this.props
return activeValue[menuIndex] === option.value
}
saveMenuItem = (index) => (node) => {
this.menuItems[index] = node
}
render () {
const { prefixCls, dropdownMenuColumnStyle } = this.props
return (
<div>
{this.getShowOptions().map((options, menuIndex) =>
<ul className={`${prefixCls}-menu`} key={menuIndex} style={dropdownMenuColumnStyle}>
{options.map(option => this.getOption(option, menuIndex))}
</ul>
)}
</div>
)
}
}
Menus.defaultProps = {
options: [],
value: [],
activeValue: [],
onSelect () {},
prefixCls: 'rc-cascader-menus',
visible: false,
expandTrigger: 'click',
}
Menus.propTypes = {
value: PropTypes.array,
activeValue: PropTypes.array,
options: PropTypes.array.isRequired,
prefixCls: PropTypes.string,
expandTrigger: PropTypes.string,
onSelect: PropTypes.func,
visible: PropTypes.bool,
dropdownMenuColumnStyle: PropTypes.object,
}
export default Menus
</script>