PowerSearch.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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="bg-transparent border-b border-dividerLight flex flex-shrink-0 text-base text-secondaryDark p-6"
  18. />
  19. <AppFuse
  20. v-if="search && show"
  21. :input="fuse"
  22. :search="search"
  23. @action="runAction"
  24. />
  25. <div
  26. v-else
  27. class="divide-dividerLight divide-y flex flex-col space-y-4 flex-1 overflow-auto hide-scrollbar"
  28. >
  29. <div
  30. v-for="(map, mapIndex) in mappings"
  31. :key="`map-${mapIndex}`"
  32. class="flex flex-col"
  33. >
  34. <h5 class="my-2 text-secondaryLight py-2 px-6">
  35. {{ t(map.section) }}
  36. </h5>
  37. <AppPowerSearchEntry
  38. v-for="(shortcut, shortcutIndex) in map.shortcuts"
  39. :key="`map-${mapIndex}-shortcut-${shortcutIndex}`"
  40. :shortcut="shortcut"
  41. :active="shortcutsItems.indexOf(shortcut) === selectedEntry"
  42. @action="runAction"
  43. @mouseover.native="selectedEntry = shortcutsItems.indexOf(shortcut)"
  44. />
  45. </div>
  46. </div>
  47. </template>
  48. </SmartModal>
  49. </template>
  50. <script setup lang="ts">
  51. import { ref, computed, watch } from "@nuxtjs/composition-api"
  52. import { HoppAction, invokeAction } from "~/helpers/actions"
  53. import { spotlight as mappings, fuse } from "~/helpers/shortcuts"
  54. import { useArrowKeysNavigation } from "~/helpers/powerSearchNavigation"
  55. import { useI18n } from "~/helpers/utils/composables"
  56. const t = useI18n()
  57. const props = defineProps<{
  58. show: boolean
  59. }>()
  60. const emit = defineEmits<{
  61. (e: "hide-modal"): void
  62. }>()
  63. const search = ref("")
  64. const hideModal = () => {
  65. search.value = ""
  66. emit("hide-modal")
  67. }
  68. const runAction = (command: HoppAction) => {
  69. invokeAction(command)
  70. hideModal()
  71. }
  72. const shortcutsItems = computed(() =>
  73. mappings.reduce(
  74. (shortcuts, section) => [...shortcuts, ...section.shortcuts],
  75. []
  76. )
  77. )
  78. const { bindArrowKeysListerners, unbindArrowKeysListerners, selectedEntry } =
  79. useArrowKeysNavigation(shortcutsItems, {
  80. onEnter: runAction,
  81. })
  82. watch(
  83. () => props.show,
  84. (show) => {
  85. if (show) bindArrowKeysListerners()
  86. else unbindArrowKeysListerners()
  87. }
  88. )
  89. </script>