emoji_input.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <template>
  2. <div
  3. v-click-outside="onClickOutside"
  4. class="emoji-input"
  5. :class="{ 'with-picker': !hideEmojiButton }"
  6. >
  7. <slot />
  8. <template v-if="enableEmojiPicker">
  9. <button
  10. v-if="!hideEmojiButton"
  11. class="button-unstyled emoji-picker-icon"
  12. type="button"
  13. @click.prevent="togglePicker"
  14. >
  15. <FAIcon :icon="['far', 'smile-beam']" />
  16. </button>
  17. <EmojiPicker
  18. v-if="enableEmojiPicker"
  19. ref="picker"
  20. :class="{ hide: !showPicker }"
  21. :enable-sticker-picker="enableStickerPicker"
  22. class="emoji-picker-panel"
  23. @emoji="insert"
  24. @sticker-uploaded="onStickerUploaded"
  25. @sticker-upload-failed="onStickerUploadFailed"
  26. />
  27. </template>
  28. <div
  29. ref="panel"
  30. class="autocomplete-panel"
  31. :class="{ hide: !showSuggestions }"
  32. >
  33. <div
  34. ref="panel-body"
  35. class="autocomplete-panel-body"
  36. >
  37. <div
  38. v-for="(suggestion, index) in suggestions"
  39. :key="index"
  40. class="autocomplete-item"
  41. :class="{ highlighted: index === highlighted }"
  42. @click.stop.prevent="onClick($event, suggestion)"
  43. >
  44. <span class="image">
  45. <img
  46. v-if="suggestion.img"
  47. :src="suggestion.img"
  48. >
  49. <span v-else>{{ suggestion.replacement }}</span>
  50. </span>
  51. <div class="label">
  52. <span class="displayText">{{ suggestion.displayText }}</span>
  53. <span class="detailText">{{ suggestion.detailText }}</span>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </div>
  59. </template>
  60. <script src="./emoji_input.js"></script>
  61. <style lang="scss">
  62. @import '../../_variables.scss';
  63. .emoji-input {
  64. display: flex;
  65. flex-direction: column;
  66. position: relative;
  67. &.with-picker input {
  68. padding-right: 30px;
  69. }
  70. .emoji-picker-icon {
  71. position: absolute;
  72. top: 0;
  73. right: 0;
  74. margin: .2em .25em;
  75. font-size: 16px;
  76. cursor: pointer;
  77. line-height: 24px;
  78. &:hover i {
  79. color: $fallback--text;
  80. color: var(--text, $fallback--text);
  81. }
  82. }
  83. .emoji-picker-panel {
  84. position: absolute;
  85. z-index: 20;
  86. margin-top: 2px;
  87. &.hide {
  88. display: none
  89. }
  90. }
  91. .autocomplete {
  92. &-panel {
  93. position: absolute;
  94. z-index: 20;
  95. margin-top: 2px;
  96. &.hide {
  97. display: none
  98. }
  99. &-body {
  100. margin: 0 0.5em 0 0.5em;
  101. border-radius: $fallback--tooltipRadius;
  102. border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
  103. box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
  104. box-shadow: var(--popupShadow);
  105. min-width: 75%;
  106. background-color: $fallback--bg;
  107. background-color: var(--popover, $fallback--bg);
  108. color: $fallback--link;
  109. color: var(--popoverText, $fallback--link);
  110. --faint: var(--popoverFaintText, $fallback--faint);
  111. --faintLink: var(--popoverFaintLink, $fallback--faint);
  112. --lightText: var(--popoverLightText, $fallback--lightText);
  113. --postLink: var(--popoverPostLink, $fallback--link);
  114. --postFaintLink: var(--popoverPostFaintLink, $fallback--link);
  115. --icon: var(--popoverIcon, $fallback--icon);
  116. }
  117. }
  118. &-item {
  119. display: flex;
  120. cursor: pointer;
  121. padding: 0.2em 0.4em;
  122. border-bottom: 1px solid rgba(0, 0, 0, 0.4);
  123. height: 32px;
  124. .image {
  125. width: 32px;
  126. height: 32px;
  127. line-height: 32px;
  128. text-align: center;
  129. font-size: 32px;
  130. margin-right: 4px;
  131. img {
  132. width: 32px;
  133. height: 32px;
  134. object-fit: contain;
  135. }
  136. }
  137. .label {
  138. display: flex;
  139. flex-direction: column;
  140. justify-content: center;
  141. margin: 0 0.1em 0 0.2em;
  142. .displayText {
  143. line-height: 1.5;
  144. }
  145. .detailText {
  146. font-size: 9px;
  147. line-height: 9px;
  148. }
  149. }
  150. &.highlighted {
  151. background-color: $fallback--fg;
  152. background-color: var(--selectedMenuPopover, $fallback--fg);
  153. color: var(--selectedMenuPopoverText, $fallback--text);
  154. --faint: var(--selectedMenuPopoverFaintText, $fallback--faint);
  155. --faintLink: var(--selectedMenuPopoverFaintLink, $fallback--faint);
  156. --lightText: var(--selectedMenuPopoverLightText, $fallback--lightText);
  157. --icon: var(--selectedMenuPopoverIcon, $fallback--icon);
  158. }
  159. }
  160. }
  161. input, textarea {
  162. flex: 1 0 auto;
  163. }
  164. }
  165. </style>