48dfed5352868902a0a3a1e7d6911fdd823c9e3a4d1c96d5ae8a162c756b2d5f7d20c1164f969bb62b787804305f5972d04c77d01e3d001964be5bd3571def-exec 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <script>
  2. import { onLeftClick, isPromise } from '../utils'
  3. import SingleValue from './SingleValue'
  4. import MultiValue from './MultiValue'
  5. import DeleteIcon from './icons/Delete'
  6. import ArrowIcon from './icons/Arrow'
  7. export default {
  8. name: 'vue-treeselect--control',
  9. inject: [ 'instance' ],
  10. computed: {
  11. /* eslint-disable valid-jsdoc */
  12. /**
  13. * Should show the "×" button that resets value?
  14. * @return {boolean}
  15. */
  16. shouldShowX() {
  17. const { instance } = this
  18. return (
  19. instance.clearable &&
  20. !instance.disabled &&
  21. instance.hasValue &&
  22. (this.hasUndisabledValue || instance.allowClearingDisabled)
  23. )
  24. },
  25. /**
  26. * Should show the arrow button that toggles menu?
  27. * @return {boolean}
  28. */
  29. shouldShowArrow() {
  30. const { instance } = this
  31. if (!instance.alwaysOpen) return true
  32. // Even with `alwaysOpen: true`, sometimes the menu is still closed,
  33. // e.g. when the control is disabled.
  34. return !instance.menu.isOpen
  35. },
  36. /**
  37. * Has any undisabled option been selected?
  38. * @type {boolean}
  39. */
  40. hasUndisabledValue() {
  41. const { instance } = this
  42. return (
  43. instance.hasValue &&
  44. instance.internalValue.some(id => !instance.getNode(id).isDisabled)
  45. )
  46. },
  47. /* eslint-enable valid-jsdoc */
  48. },
  49. methods: {
  50. renderX() {
  51. const { instance } = this
  52. const title = instance.multiple ? instance.clearAllText : instance.clearValueText
  53. if (!this.shouldShowX) return null
  54. return (
  55. <div class="vue-treeselect__x-container" title={title} onMousedown={this.handleMouseDownOnX}>
  56. <DeleteIcon class="vue-treeselect__x" />
  57. </div>
  58. )
  59. },
  60. renderArrow() {
  61. const { instance } = this
  62. const arrowClass = {
  63. 'vue-treeselect__control-arrow': true,
  64. 'vue-treeselect__control-arrow--rotated': instance.menu.isOpen,
  65. }
  66. if (!this.shouldShowArrow) return null
  67. return (
  68. <div class="vue-treeselect__control-arrow-container" onMousedown={this.handleMouseDownOnArrow}>
  69. <ArrowIcon class={arrowClass} />
  70. </div>
  71. )
  72. },
  73. handleMouseDownOnX: onLeftClick(function handleMouseDownOnX(evt) {
  74. /**
  75. * We don't use async/await here because we don't want
  76. * to rely on Babel polyfill or regenerator runtime.
  77. * See: https://babeljs.io/docs/plugins/transform-regenerator/
  78. * We also don't want to assume there is a global `Promise`
  79. * class, since we are targeting to support IE9 without the
  80. * need of any polyfill.
  81. */
  82. evt.stopPropagation()
  83. evt.preventDefault()
  84. const { instance } = this
  85. const result = instance.beforeClearAll()
  86. const handler = shouldClear => {
  87. if (shouldClear) instance.clear()
  88. }
  89. if (isPromise(result)) {
  90. // The handler will be called async.
  91. result.then(handler)
  92. } else {
  93. // Keep the same behavior here.
  94. setTimeout(() => handler(result), 0)
  95. // Also, note that IE9 requires:
  96. // setTimeout(() => fn(...args), delay)
  97. // Instead of:
  98. // setTimeout(fn, delay, ...args)
  99. }
  100. }),
  101. handleMouseDownOnArrow: onLeftClick(function handleMouseDownOnArrow(evt) {
  102. evt.preventDefault()
  103. evt.stopPropagation()
  104. const { instance } = this
  105. // Focus the input or prevent blurring.
  106. instance.focusInput()
  107. instance.toggleMenu()
  108. }),
  109. // This is meant to be called by child `<Value />` component.
  110. renderValueContainer(children) {
  111. return (
  112. <div class="vue-treeselect__value-container">
  113. {children}
  114. </div>
  115. )
  116. },
  117. },
  118. render() {
  119. const { instance } = this
  120. const ValueContainer = instance.single ? SingleValue : MultiValue
  121. return (
  122. <div class="vue-treeselect__control" onMousedown={instance.handleMouseDown}>
  123. <ValueContainer ref="value-container" />
  124. {this.renderX()}
  125. {this.renderArrow()}
  126. </div>
  127. )
  128. },
  129. }
  130. </script>