PowerSearch.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <template>
  2. <SmartModal
  3. v-if="show"
  4. max-width="sm:max-w-md"
  5. full-width
  6. @close="$emit('hide-modal')"
  7. >
  8. <template #body>
  9. <input
  10. id="command"
  11. v-model="search"
  12. v-focus
  13. type="text"
  14. autocomplete="off"
  15. name="command"
  16. :placeholder="`${$t('app.type_a_command_search')}`"
  17. class="
  18. bg-transparent
  19. border-b border-dividerLight
  20. flex flex-shrink-0
  21. text-secondaryDark text-base
  22. p-6
  23. "
  24. />
  25. <AppFuse
  26. v-if="search && show"
  27. :input="fuse"
  28. :search="search"
  29. @action="runAction"
  30. />
  31. <div
  32. v-else
  33. class="
  34. divide-y divide-dividerLight
  35. flex flex-col
  36. space-y-4
  37. flex-1
  38. overflow-auto
  39. hide-scrollbar
  40. "
  41. >
  42. <div
  43. v-for="(map, mapIndex) in mappings"
  44. :key="`map-${mapIndex}`"
  45. class="flex flex-col"
  46. >
  47. <h5 class="my-2 text-secondaryLight py-2 px-6">
  48. {{ $t(map.section) }}
  49. </h5>
  50. <AppPowerSearchEntry
  51. v-for="(shortcut, shortcutIndex) in map.shortcuts"
  52. :key="`map-${mapIndex}-shortcut-${shortcutIndex}`"
  53. :shortcut="shortcut"
  54. :active="shortcutsItems.indexOf(shortcut) === selectedEntry"
  55. @action="runAction"
  56. @mouseover.native="selectedEntry = shortcutsItems.indexOf(shortcut)"
  57. />
  58. </div>
  59. </div>
  60. </template>
  61. </SmartModal>
  62. </template>
  63. <script setup lang="ts">
  64. import { ref, computed, watch } from "@nuxtjs/composition-api"
  65. import { HoppAction, invokeAction } from "~/helpers/actions"
  66. import { spotlight as mappings, fuse } from "~/helpers/shortcuts"
  67. import { useArrowKeysNavigation } from "~/helpers/powerSearchNavigation"
  68. const props = defineProps<{
  69. show: boolean
  70. }>()
  71. const emit = defineEmits<{
  72. (e: "hide-modal"): void
  73. }>()
  74. const search = ref("")
  75. const hideModal = () => {
  76. search.value = ""
  77. emit("hide-modal")
  78. }
  79. const runAction = (command: HoppAction) => {
  80. invokeAction(command)
  81. hideModal()
  82. }
  83. const shortcutsItems = computed(() =>
  84. mappings.reduce(
  85. (shortcuts, section) => [...shortcuts, ...section.shortcuts],
  86. []
  87. )
  88. )
  89. const { bindArrowKeysListerners, unbindArrowKeysListerners, selectedEntry } =
  90. useArrowKeysNavigation(shortcutsItems, {
  91. onEnter: runAction,
  92. })
  93. watch(
  94. () => props.show,
  95. (show) => {
  96. if (show) bindArrowKeysListerners()
  97. else unbindArrowKeysListerners()
  98. }
  99. )
  100. </script>