useNavigateOptions.ts 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { ref } from 'vue'
  3. import type { Ref } from 'vue'
  4. // we don't use useTraverOptions here because we don't FOCUS elements, just traverse
  5. export default function useNavigateOptions(
  6. items: Ref<unknown[]>,
  7. onSelect: (item: unknown) => void,
  8. ) {
  9. const selectedIndex = ref(0)
  10. const focus = (index: number) => {
  11. const element = document.querySelector(`#mention-${index}`)
  12. element?.scrollIntoView({ block: 'nearest' })
  13. }
  14. const goNext = () => {
  15. if (selectedIndex.value === items.value.length - 1) {
  16. selectedIndex.value = 0
  17. } else {
  18. selectedIndex.value += 1
  19. }
  20. focus(selectedIndex.value)
  21. return selectedIndex.value in items.value
  22. }
  23. const goPrevious = () => {
  24. if (selectedIndex.value === 0) {
  25. selectedIndex.value = items.value.length - 1
  26. } else {
  27. selectedIndex.value -= 1
  28. }
  29. focus(selectedIndex.value)
  30. return selectedIndex.value in items.value
  31. }
  32. const selectItem = (index?: number) => {
  33. const item = items.value[index || selectedIndex.value]
  34. if (item) {
  35. onSelect(item)
  36. return true
  37. }
  38. return false
  39. }
  40. const onKeyDown = (event: KeyboardEvent) => {
  41. if (event.key === 'ArrowDown') {
  42. return goNext()
  43. }
  44. if (event.key === 'ArrowUp') {
  45. return goPrevious()
  46. }
  47. if (event.key === 'Enter' || event.key === 'Tab') {
  48. return selectItem()
  49. }
  50. return false
  51. }
  52. return {
  53. onKeyDown,
  54. selectedIndex,
  55. selectItem,
  56. }
  57. }