211 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
| 
 | |
| import classnames from 'classnames'
 | |
| import Trigger from '../trigger'
 | |
| import PropTypes from '../_util/vue-types'
 | |
| import DropdownMenu from './DropdownMenu'
 | |
| import { isSingleMode } from './util'
 | |
| import BaseMixin from '../_util/BaseMixin'
 | |
| 
 | |
| const BUILT_IN_PLACEMENTS = {
 | |
|   bottomLeft: {
 | |
|     points: ['tl', 'bl'],
 | |
|     offset: [0, 4],
 | |
|     overflow: {
 | |
|       adjustX: 0,
 | |
|       adjustY: 1,
 | |
|     },
 | |
|   },
 | |
|   topLeft: {
 | |
|     points: ['bl', 'tl'],
 | |
|     offset: [0, -4],
 | |
|     overflow: {
 | |
|       adjustX: 0,
 | |
|       adjustY: 1,
 | |
|     },
 | |
|   },
 | |
| }
 | |
| 
 | |
| export default {
 | |
|   name: 'SelectTrigger',
 | |
|   mixins: [BaseMixin],
 | |
|   props: {
 | |
|     // onPopupFocus: PropTypes.func,
 | |
|     // onPopupScroll: PropTypes.func,
 | |
|     dropdownMatchSelectWidth: PropTypes.bool,
 | |
|     defaultActiveFirstOption: PropTypes.bool,
 | |
|     dropdownAlign: PropTypes.object,
 | |
|     visible: PropTypes.bool,
 | |
|     disabled: PropTypes.bool,
 | |
|     showSearch: PropTypes.bool,
 | |
|     dropdownClassName: PropTypes.string,
 | |
|     dropdownStyle: PropTypes.object,
 | |
|     dropdownMenuStyle: PropTypes.object,
 | |
|     multiple: PropTypes.bool,
 | |
|     inputValue: PropTypes.string,
 | |
|     filterOption: PropTypes.any,
 | |
|     options: PropTypes.any,
 | |
|     prefixCls: PropTypes.string,
 | |
|     popupClassName: PropTypes.string,
 | |
|     value: PropTypes.array,
 | |
|     // children: PropTypes.any,
 | |
|     showAction: PropTypes.arrayOf(PropTypes.string),
 | |
|     combobox: PropTypes.bool,
 | |
|     animation: PropTypes.string,
 | |
|     transitionName: PropTypes.string,
 | |
|   },
 | |
|   data () {
 | |
|     return {
 | |
|       dropdownWidth: null,
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   mounted () {
 | |
|     this.$nextTick(() => {
 | |
|       this.setDropdownWidth()
 | |
|     })
 | |
|   },
 | |
| 
 | |
|   updated () {
 | |
|     this.$nextTick(() => {
 | |
|       this.setDropdownWidth()
 | |
|     })
 | |
|   },
 | |
|   methods: {
 | |
|     setDropdownWidth () {
 | |
|       const width = this.$el.offsetWidth
 | |
|       if (width !== this.dropdownWidth) {
 | |
|         this.setState({ dropdownWidth: width })
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     getInnerMenu () {
 | |
|       return this.$refs.dropdownMenuRef && this.$refs.dropdownMenuRef.$refs.menuRef
 | |
|     },
 | |
| 
 | |
|     getPopupDOMNode () {
 | |
|       return this.$refs.triggerRef.getPopupDomNode()
 | |
|     },
 | |
| 
 | |
|     getDropdownElement (newProps) {
 | |
|       const {
 | |
|         value, firstActiveValue, defaultActiveFirstOption,
 | |
|         dropdownMenuStyle, getDropdownPrefixCls,
 | |
|       } = this
 | |
|       const { menuSelect, menuDeselect, popupScroll } = this.$listeners
 | |
|       const dropdownMenuProps = {
 | |
|         props: {
 | |
|           ...newProps.props,
 | |
|           prefixCls: getDropdownPrefixCls(),
 | |
|           value, firstActiveValue, defaultActiveFirstOption, dropdownMenuStyle,
 | |
|         },
 | |
|         on: {
 | |
|           ...newProps.on,
 | |
|           menuSelect,
 | |
|           menuDeselect,
 | |
|           popupScroll,
 | |
|         },
 | |
|         ref: 'dropdownMenuRef',
 | |
|       }
 | |
|       return (
 | |
|         <DropdownMenu {...dropdownMenuProps} />
 | |
|       )
 | |
|     },
 | |
| 
 | |
|     getDropdownTransitionName () {
 | |
|       const props = this.$props
 | |
|       let transitionName = props.transitionName
 | |
|       if (!transitionName && props.animation) {
 | |
|         transitionName = `${this.getDropdownPrefixCls()}-${props.animation}`
 | |
|       }
 | |
|       return transitionName
 | |
|     },
 | |
| 
 | |
|     getDropdownPrefixCls () {
 | |
|       return `${this.prefixCls}-dropdown`
 | |
|     },
 | |
|   },
 | |
| 
 | |
|   render () {
 | |
|     const { $props, $slots, $listeners } = this
 | |
|     const {
 | |
|       multiple,
 | |
|       visible,
 | |
|       inputValue,
 | |
|       dropdownAlign,
 | |
|       disabled,
 | |
|       showSearch,
 | |
|       dropdownClassName,
 | |
|       dropdownStyle,
 | |
|       dropdownMatchSelectWidth,
 | |
|       options,
 | |
|       getPopupContainer,
 | |
|       showAction,
 | |
|     } = $props
 | |
|     const { mouseenter, mouseleave, popupFocus, dropdownVisibleChange } = $listeners
 | |
|     const dropdownPrefixCls = this.getDropdownPrefixCls()
 | |
|     const popupClassName = {
 | |
|       [dropdownClassName]: !!dropdownClassName,
 | |
|       [`${dropdownPrefixCls}--${multiple ? 'multiple' : 'single'}`]: 1,
 | |
|     }
 | |
|     const popupElement = this.getDropdownElement({
 | |
|       props: {
 | |
|         menuItems: options,
 | |
|         multiple,
 | |
|         inputValue,
 | |
|         visible,
 | |
|       }, on: {
 | |
|         popupFocus,
 | |
|       },
 | |
|     })
 | |
|     let hideAction
 | |
|     if (disabled) {
 | |
|       hideAction = []
 | |
|     } else if (isSingleMode($props) && !showSearch) {
 | |
|       hideAction = ['click']
 | |
|     } else {
 | |
|       hideAction = ['blur']
 | |
|     }
 | |
|     const popupStyle = { ...dropdownStyle }
 | |
|     const widthProp = dropdownMatchSelectWidth ? 'width' : 'minWidth'
 | |
|     if (this.dropdownWidth) {
 | |
|       popupStyle[widthProp] = `${this.dropdownWidth}px`
 | |
|     }
 | |
|     const triggerProps = {
 | |
|       props: {
 | |
|         ...$props,
 | |
|         showAction: disabled ? [] : showAction,
 | |
|         hideAction,
 | |
|         ref: 'triggerRef',
 | |
|         popupPlacement: 'bottomLeft',
 | |
|         builtinPlacements: BUILT_IN_PLACEMENTS,
 | |
|         prefixCls: dropdownPrefixCls,
 | |
|         popupTransitionName: this.getDropdownTransitionName(),
 | |
|         popupAlign: dropdownAlign,
 | |
|         popupVisible: visible,
 | |
|         getPopupContainer,
 | |
|         popupClassName: classnames(popupClassName),
 | |
|         popupStyle,
 | |
|       },
 | |
|       on: {
 | |
|         popupVisibleChange: dropdownVisibleChange,
 | |
|       },
 | |
|       ref: 'triggerRef',
 | |
|     }
 | |
|     if (mouseenter) {
 | |
|       triggerProps.on.mouseenter = mouseenter
 | |
|     }
 | |
|     if (mouseleave) {
 | |
|       triggerProps.on.mouseleave = mouseleave
 | |
|     }
 | |
|     return (
 | |
|       <Trigger {...triggerProps}>
 | |
|         {$slots.default}
 | |
|         <template slot='popup'>
 | |
|           {popupElement}
 | |
|         </template>
 | |
|       </Trigger>
 | |
|     )
 | |
|   },
 | |
| }
 | |
| 
 |