154 lines
4.3 KiB
Vue
154 lines
4.3 KiB
Vue
<script>
|
||
import { onLeftClick, isPromise } from '../utils'
|
||
import SingleValue from './SingleValue'
|
||
import MultiValue from './MultiValue'
|
||
import DeleteIcon from './icons/Delete'
|
||
import ArrowIcon from './icons/Arrow'
|
||
|
||
export default {
|
||
name: 'vue-treeselect--control',
|
||
inject: [ 'instance' ],
|
||
|
||
computed: {
|
||
/* eslint-disable valid-jsdoc */
|
||
/**
|
||
* Should show the "×" button that resets value?
|
||
* @return {boolean}
|
||
*/
|
||
shouldShowX() {
|
||
const { instance } = this
|
||
|
||
return (
|
||
instance.clearable &&
|
||
!instance.disabled &&
|
||
instance.hasValue &&
|
||
(this.hasUndisabledValue || instance.allowClearingDisabled)
|
||
)
|
||
},
|
||
|
||
/**
|
||
* Should show the arrow button that toggles menu?
|
||
* @return {boolean}
|
||
*/
|
||
shouldShowArrow() {
|
||
const { instance } = this
|
||
|
||
if (!instance.alwaysOpen) return true
|
||
// Even with `alwaysOpen: true`, sometimes the menu is still closed,
|
||
// e.g. when the control is disabled.
|
||
return !instance.menu.isOpen
|
||
},
|
||
|
||
/**
|
||
* Has any undisabled option been selected?
|
||
* @type {boolean}
|
||
*/
|
||
hasUndisabledValue() {
|
||
const { instance } = this
|
||
|
||
return (
|
||
instance.hasValue &&
|
||
instance.internalValue.some(id => !instance.getNode(id).isDisabled)
|
||
)
|
||
},
|
||
/* eslint-enable valid-jsdoc */
|
||
},
|
||
|
||
methods: {
|
||
renderX() {
|
||
const { instance } = this
|
||
const title = instance.multiple ? instance.clearAllText : instance.clearValueText
|
||
|
||
if (!this.shouldShowX) return null
|
||
|
||
return (
|
||
<div class="vue-treeselect__x-container" title={title} onMousedown={this.handleMouseDownOnX}>
|
||
<DeleteIcon class="vue-treeselect__x" />
|
||
</div>
|
||
)
|
||
},
|
||
|
||
renderArrow() {
|
||
const { instance } = this
|
||
const arrowClass = {
|
||
'vue-treeselect__control-arrow': true,
|
||
'vue-treeselect__control-arrow--rotated': instance.menu.isOpen,
|
||
}
|
||
|
||
if (!this.shouldShowArrow) return null
|
||
|
||
return (
|
||
<div class="vue-treeselect__control-arrow-container" onMousedown={this.handleMouseDownOnArrow}>
|
||
<ArrowIcon class={arrowClass} />
|
||
</div>
|
||
)
|
||
},
|
||
|
||
handleMouseDownOnX: onLeftClick(function handleMouseDownOnX(evt) {
|
||
/**
|
||
* We don't use async/await here because we don't want
|
||
* to rely on Babel polyfill or regenerator runtime.
|
||
* See: https://babeljs.io/docs/plugins/transform-regenerator/
|
||
* We also don't want to assume there is a global `Promise`
|
||
* class, since we are targeting to support IE9 without the
|
||
* need of any polyfill.
|
||
*/
|
||
|
||
evt.stopPropagation()
|
||
evt.preventDefault()
|
||
|
||
const { instance } = this
|
||
const result = instance.beforeClearAll()
|
||
const handler = shouldClear => {
|
||
if (shouldClear) instance.clear()
|
||
}
|
||
|
||
if (isPromise(result)) {
|
||
// The handler will be called async.
|
||
result.then(handler)
|
||
} else {
|
||
// Keep the same behavior here.
|
||
setTimeout(() => handler(result), 0)
|
||
// Also, note that IE9 requires:
|
||
// setTimeout(() => fn(...args), delay)
|
||
// Instead of:
|
||
// setTimeout(fn, delay, ...args)
|
||
}
|
||
}),
|
||
|
||
handleMouseDownOnArrow: onLeftClick(function handleMouseDownOnArrow(evt) {
|
||
evt.preventDefault()
|
||
evt.stopPropagation()
|
||
|
||
const { instance } = this
|
||
|
||
// Focus the input or prevent blurring.
|
||
instance.focusInput()
|
||
instance.toggleMenu()
|
||
}),
|
||
|
||
// This is meant to be called by child `<Value />` component.
|
||
renderValueContainer(children) {
|
||
return (
|
||
<div class="vue-treeselect__value-container">
|
||
{children}
|
||
</div>
|
||
)
|
||
},
|
||
},
|
||
|
||
render() {
|
||
const { instance } = this
|
||
const ValueContainer = instance.single ? SingleValue : MultiValue
|
||
|
||
return (
|
||
<div class="vue-treeselect__control" onMousedown={instance.handleMouseDown}>
|
||
<ValueContainer ref="value-container" />
|
||
{this.renderX()}
|
||
{this.renderArrow()}
|
||
</div>
|
||
)
|
||
},
|
||
}
|
||
</script>
|