203 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Vue
		
	
	
| import omit from 'omit.js'
 | |
| import debounce from 'lodash/debounce'
 | |
| import PropTypes from '../_util/vue-types'
 | |
| import { conductExpandParent, convertTreeToEntities } from '../vc-tree/src/util'
 | |
| import Tree, { TreeProps } from './Tree'
 | |
| import { calcRangeKeys, getFullKeyList } from './util'
 | |
| import Icon from '../icon'
 | |
| import BaseMixin from '../_util/BaseMixin'
 | |
| import { initDefaultProps, getOptionProps } from '../_util/props-util'
 | |
| 
 | |
| // export type ExpandAction = false | 'click' | 'doubleClick';
 | |
| 
 | |
| // export interface DirectoryTreeProps extends TreeProps {
 | |
| //   expandAction?: ExpandAction;
 | |
| // }
 | |
| 
 | |
| // export interface DirectoryTreeState {
 | |
| //   expandedKeys?: string[];
 | |
| //   selectedKeys?: string[];
 | |
| // }
 | |
| 
 | |
| function getIcon (props, h) {
 | |
|   const { isLeaf, expanded } = props
 | |
|   if (isLeaf) {
 | |
|     return <Icon type='file' />
 | |
|   }
 | |
|   return <Icon type={expanded ? 'folder-open' : 'folder'} />
 | |
| }
 | |
| 
 | |
| export default {
 | |
|   mixins: [BaseMixin],
 | |
|   name: 'ADirectoryTree',
 | |
|   model: {
 | |
|     prop: 'checkedKeys',
 | |
|     event: 'check',
 | |
|   },
 | |
|   props: initDefaultProps({ ...TreeProps(), expandAction: PropTypes.oneOf([false, 'click', 'doubleclick']) }, {
 | |
|     prefixCls: 'ant-tree',
 | |
|     showIcon: true,
 | |
|     expandAction: 'click',
 | |
|   }),
 | |
| 
 | |
|   // state: DirectoryTreeState;
 | |
|   // onDebounceExpand: (event, node: AntTreeNode) => void;
 | |
| 
 | |
|   // // Shift click usage
 | |
|   // lastSelectedKey?: string;
 | |
|   // cachedSelectedKeys?: string[];
 | |
| 
 | |
|   data () {
 | |
|     const props = getOptionProps(this)
 | |
|     const { defaultExpandAll, defaultExpandParent, expandedKeys, defaultExpandedKeys } = props
 | |
|     const { keyEntities } = convertTreeToEntities(this.$slots.default)
 | |
|     const state = {}
 | |
|     // Selected keys
 | |
|     state._selectedKeys = props.selectedKeys || props.defaultSelectedKeys || []
 | |
| 
 | |
|     // Expanded keys
 | |
|     if (defaultExpandAll) {
 | |
|       state._expandedKeys = getFullKeyList(this.$slots.default)
 | |
|     } else if (defaultExpandParent) {
 | |
|       state._expandedKeys = conductExpandParent(expandedKeys || defaultExpandedKeys, keyEntities)
 | |
|     } else {
 | |
|       state._expandedKeys = expandedKeys || defaultExpandedKeys
 | |
|     }
 | |
| 
 | |
|     this.onDebounceExpand = debounce(this.expandFolderNode, 200, {
 | |
|       leading: true,
 | |
|     })
 | |
|     return {
 | |
|       _selectedKeys: [],
 | |
|       _expandedKeys: [],
 | |
|       ...state,
 | |
|     }
 | |
|   },
 | |
|   watch: {
 | |
|     expandedKeys (val) {
 | |
|       this.setState({ _expandedKeys: val })
 | |
|     },
 | |
|     selectedKeys (val) {
 | |
|       this.setState({ _selectedKeys: val })
 | |
|     },
 | |
|   },
 | |
|   methods: {
 | |
|     onExpand (expandedKeys, info) {
 | |
|       this.setUncontrolledState({ _expandedKeys: expandedKeys })
 | |
| 
 | |
|       this.$emit('expand', expandedKeys, info)
 | |
| 
 | |
|       return undefined
 | |
|     },
 | |
| 
 | |
|     onClick (event, node) {
 | |
|       const { expandAction } = this.$props
 | |
| 
 | |
|       // Expand the tree
 | |
|       if (expandAction === 'click') {
 | |
|         this.onDebounceExpand(event, node)
 | |
|       }
 | |
|       this.$emit('click', event, node)
 | |
|     },
 | |
| 
 | |
|     onDoubleClick (event, node) {
 | |
|       const { expandAction } = this.$props
 | |
| 
 | |
|       // Expand the tree
 | |
|       if (expandAction === 'doubleclick') {
 | |
|         this.onDebounceExpand(event, node)
 | |
|       }
 | |
| 
 | |
|       this.$emit('doubleclick', event, node)
 | |
|     },
 | |
| 
 | |
|     onSelect (keys, event) {
 | |
|       const { multiple } = this.$props
 | |
|       const children = this.$slots.default || []
 | |
|       const { _expandedKeys: expandedKeys = [], _selectedKeys: selectedKeys = [] } = this.$data
 | |
|       const { node, nativeEvent } = event
 | |
|       const { eventKey = '' } = node
 | |
| 
 | |
|       const newState = {}
 | |
|       // Windows / Mac single pick
 | |
|       const ctrlPick = nativeEvent.ctrlKey || nativeEvent.metaKey
 | |
|       const shiftPick = nativeEvent.shiftKey
 | |
| 
 | |
|       // Generate new selected keys
 | |
|       let newSelectedKeys = selectedKeys.slice()
 | |
|       if (multiple && ctrlPick) {
 | |
|       // Control click
 | |
|         newSelectedKeys = keys
 | |
|         this.lastSelectedKey = eventKey
 | |
|         this.cachedSelectedKeys = newSelectedKeys
 | |
|       } else if (multiple && shiftPick) {
 | |
|       // Shift click
 | |
|         newSelectedKeys = Array.from(new Set([
 | |
|           ...this.cachedSelectedKeys || [],
 | |
|           ...calcRangeKeys(children, expandedKeys, eventKey, this.lastSelectedKey),
 | |
|         ]))
 | |
|       } else {
 | |
|       // Single click
 | |
|         newSelectedKeys = [eventKey]
 | |
|         this.lastSelectedKey = eventKey
 | |
|         this.cachedSelectedKeys = newSelectedKeys
 | |
|       }
 | |
|       newState._selectedKeys = newSelectedKeys
 | |
| 
 | |
|       this.$emit('select', newSelectedKeys, event)
 | |
| 
 | |
|       this.setUncontrolledState(newState)
 | |
|     },
 | |
| 
 | |
|     expandFolderNode  (event, node) {
 | |
|       const { isLeaf } = node
 | |
| 
 | |
|       if (isLeaf || event.shiftKey || event.metaKey || event.ctrlKey) {
 | |
|         return
 | |
|       }
 | |
| 
 | |
|       if (this.$refs.tree.$refs.tree) {
 | |
|         // Get internal vc-tree
 | |
|         const internalTree = this.$refs.tree.$refs.tree
 | |
| 
 | |
|         // Call internal rc-tree expand function
 | |
|         // https://github.com/ant-design/ant-design/issues/12567
 | |
|         internalTree.onNodeExpand(event, node)
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     setUncontrolledState (state) {
 | |
|       const newState = omit(state, Object.keys(getOptionProps(this)).map(p => `_${p}`))
 | |
|       if (Object.keys(newState).length) {
 | |
|         this.setState(newState)
 | |
|       }
 | |
|     },
 | |
|   },
 | |
| 
 | |
|   render () {
 | |
|     const { prefixCls, ...props } = getOptionProps(this)
 | |
|     const { _expandedKeys: expandedKeys, _selectedKeys: selectedKeys } = this.$data
 | |
|     const treeProps = {
 | |
|       props: {
 | |
|         icon: getIcon,
 | |
|         ...props,
 | |
|         prefixCls,
 | |
|         expandedKeys,
 | |
|         selectedKeys,
 | |
|       },
 | |
|       ref: 'tree',
 | |
|       class: `${prefixCls}-directory`,
 | |
|       on: {
 | |
|         ...this.$listeners,
 | |
|         select: this.onSelect,
 | |
|         click: this.onClick,
 | |
|         doubleclick: this.onDoubleClick,
 | |
|         expand: this.onExpand,
 | |
|       },
 | |
|     }
 | |
|     return (
 | |
|       <Tree {...treeProps}>{this.$slots.default}</Tree>
 | |
|     )
 | |
|   },
 | |
| }
 |