PowerSearch.vue 2.6 KB

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