Shortcuts.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <template>
  2. <AppSlideOver :show="show" @close="close()">
  3. <template #content>
  4. <div
  5. class="bg-primary border-b border-dividerLight flex p-2 top-0 z-10 sticky items-center justify-between"
  6. >
  7. <h3 class="ml-4 heading">{{ t("app.shortcuts") }}</h3>
  8. <div class="flex">
  9. <ButtonSecondary svg="x" @click.native="close()" />
  10. </div>
  11. </div>
  12. <div class="bg-primary border-b border-dividerLight">
  13. <div class="flex flex-col my-4 mx-6">
  14. <input
  15. v-model="filterText"
  16. type="search"
  17. autocomplete="off"
  18. class="bg-primaryLight border border-dividerLight rounded flex w-full py-2 px-4 focus-visible:border-divider"
  19. :placeholder="`${t('action.search')}`"
  20. />
  21. </div>
  22. </div>
  23. <div
  24. v-if="filterText"
  25. class="divide-dividerLight divide-y flex flex-col flex-1 overflow-auto hide-scrollbar"
  26. >
  27. <div
  28. v-for="(map, mapIndex) in searchResults"
  29. :key="`map-${mapIndex}`"
  30. class="space-y-4 py-4 px-6"
  31. >
  32. <h1 class="font-semibold text-secondaryDark">
  33. {{ t(map.item.section) }}
  34. </h1>
  35. <AppShortcutsEntry
  36. v-for="(shortcut, index) in map.item.shortcuts"
  37. :key="`shortcut-${index}`"
  38. :shortcut="shortcut"
  39. />
  40. </div>
  41. <div
  42. v-if="searchResults.length === 0"
  43. class="flex flex-col text-secondaryLight p-4 items-center justify-center"
  44. >
  45. <i class="opacity-75 pb-2 material-icons">manage_search</i>
  46. <span class="text-center">
  47. {{ t("state.nothing_found") }} "{{ filterText }}"
  48. </span>
  49. </div>
  50. </div>
  51. <div
  52. v-else
  53. class="divide-dividerLight divide-y flex flex-col flex-1 overflow-auto hide-scrollbar"
  54. >
  55. <div
  56. v-for="(map, mapIndex) in mappings"
  57. :key="`map-${mapIndex}`"
  58. class="space-y-4 py-4 px-6"
  59. >
  60. <h1 class="font-semibold text-secondaryDark">
  61. {{ t(map.section) }}
  62. </h1>
  63. <AppShortcutsEntry
  64. v-for="(shortcut, shortcutIndex) in map.shortcuts"
  65. :key="`map-${mapIndex}-shortcut-${shortcutIndex}`"
  66. :shortcut="shortcut"
  67. />
  68. </div>
  69. </div>
  70. </template>
  71. </AppSlideOver>
  72. </template>
  73. <script setup lang="ts">
  74. import { computed, ref } from "@nuxtjs/composition-api"
  75. import Fuse from "fuse.js"
  76. import mappings from "~/helpers/shortcuts"
  77. import { useI18n } from "~/helpers/utils/composables"
  78. const t = useI18n()
  79. defineProps<{
  80. show: boolean
  81. }>()
  82. const options = {
  83. keys: ["shortcuts.label"],
  84. }
  85. const fuse = new Fuse(mappings, options)
  86. const filterText = ref("")
  87. const searchResults = computed(() => fuse.search(filterText.value))
  88. const emit = defineEmits<{
  89. (e: "close"): void
  90. }>()
  91. const close = () => {
  92. filterText.value = ""
  93. emit("close")
  94. }
  95. </script>
  96. <style lang="scss" scoped>
  97. .shortcut-key {
  98. @apply bg-dividerLight;
  99. @apply rounded;
  100. @apply ml-2;
  101. @apply py-1;
  102. @apply px-2;
  103. @apply inline-flex;
  104. }
  105. </style>