liusuyi
2023-04-24 4737f1e038743ced243c9e52423404d9034d6107
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<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>