You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
3.0 KiB

  1. <template>
  2. <v-menu
  3. v-if="label"
  4. v-model="showMenu"
  5. offset-y
  6. >
  7. <template v-slot:activator="{ on }">
  8. <span class="highlight bottom" :style="{ borderColor: color }" v-on="on">
  9. <span class="highlight__content">{{ content }}<v-icon class="delete" @click.stop="remove">mdi-close-circle</v-icon></span><span class="highlight__label" :data-label="label" :style="{ backgroundColor: color, color: textColor }" />
  10. </span>
  11. </template>
  12. <v-list
  13. dense
  14. min-width="150"
  15. max-height="400"
  16. class="overflow-y-auto"
  17. >
  18. <v-list-item
  19. v-for="(item, i) in labels"
  20. :key="i"
  21. v-shortkey.once="[item.suffix_key]"
  22. @shortkey="update(item)"
  23. @click="update(item)"
  24. >
  25. <v-list-item-content>
  26. <v-list-item-title v-text="item.text" />
  27. </v-list-item-content>
  28. <v-list-item-action>
  29. <v-list-item-action-text v-text="item.suffix_key" />
  30. </v-list-item-action>
  31. </v-list-item>
  32. </v-list>
  33. </v-menu>
  34. <span v-else>{{ content }}</span>
  35. </template>
  36. <script>
  37. import Vue from 'vue'
  38. import { idealColor } from '~/plugins/utils.js'
  39. Vue.use(require('vue-shortkey'))
  40. export default {
  41. props: {
  42. content: {
  43. type: String,
  44. default: '',
  45. required: true
  46. },
  47. label: {
  48. type: String,
  49. default: ''
  50. },
  51. color: {
  52. type: String,
  53. default: '#64FFDA'
  54. },
  55. labels: {
  56. type: Array,
  57. default: () => [],
  58. required: true
  59. }
  60. },
  61. data() {
  62. return {
  63. showMenu: false
  64. }
  65. },
  66. computed: {
  67. textColor() {
  68. return idealColor(this.color)
  69. }
  70. },
  71. methods: {
  72. update(label) {
  73. this.$emit('update', label)
  74. this.showMenu = false
  75. },
  76. remove() {
  77. this.$emit('remove')
  78. }
  79. }
  80. }
  81. </script>
  82. <style scoped>
  83. .highlight.blue {
  84. background: #edf4fa !important;
  85. }
  86. .highlight.bottom {
  87. display: block;
  88. white-space: normal;
  89. }
  90. .highlight:first-child {
  91. margin-left: 0;
  92. }
  93. .highlight {
  94. border: 2px solid;
  95. margin: 4px 6px 4px 3px;
  96. vertical-align: middle;
  97. box-shadow: 2px 4px 20px rgba(0,0,0,.1);
  98. position: relative;
  99. cursor: default;
  100. min-width: 26px;
  101. line-height: 22px;
  102. display: flex;
  103. }
  104. .highlight .delete {
  105. top:-15px;
  106. left:-13px;
  107. position:absolute;
  108. display: none;
  109. }
  110. .highlight:hover .delete {
  111. display: block;
  112. }
  113. .highlight__content {
  114. display: flex;
  115. flex-wrap: wrap;
  116. align-items: center;
  117. padding: 2px 2px 0px 6px;
  118. }
  119. .highlight.bottom .highlight__content:after {
  120. content: " ";
  121. padding-right: 3px;
  122. }
  123. .highlight__label {
  124. line-height: 14px;
  125. padding-top: 1px;
  126. align-items: center;
  127. justify-content: center;
  128. display: flex;
  129. padding: 0 8px;
  130. text-align: center;
  131. -webkit-user-select: none;
  132. -moz-user-select: none;
  133. -ms-user-select: none;
  134. user-select: none;
  135. color: white;
  136. }
  137. .highlight__label::after {
  138. content: attr(data-label);
  139. display: block;
  140. font-size: 14px;
  141. -webkit-font-smoothing: subpixel-antialiased;
  142. letter-spacing: .1em;
  143. }
  144. </style>