62 lines
1.9 KiB
Vue
62 lines
1.9 KiB
Vue
<script setup lang="ts">
|
|
import { notes, findNotesByByTitle, activeNote } from '@/composables/useNotes'
|
|
|
|
const props = defineProps<{
|
|
autocompleteText: string
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
createLink: [title: string]
|
|
}>()
|
|
|
|
const results = computed<Note[]>(() => {
|
|
return (props.autocompleteText ? findNotesByByTitle(props.autocompleteText) : notes.value)
|
|
.filter((note) => note.id !== activeNote.value?.id)
|
|
.slice(0, 10)
|
|
})
|
|
|
|
const activeResult = ref<Note>()
|
|
|
|
const changeActiveResult = (direction: number) => {
|
|
const index = results.value.findIndex((note) => note.id === activeResult.value?.id)
|
|
const newIndex =
|
|
index + direction < results.value.length
|
|
? index + direction >= -1
|
|
? index + direction
|
|
: results.value.length - 1
|
|
: -1
|
|
activeResult.value = newIndex >= 0 ? results.value[newIndex] : undefined
|
|
}
|
|
|
|
const handleKeypress = (event: { [key: string]: number }) => {
|
|
const keyCode = event.keyCode
|
|
const keyCodes = {
|
|
cycle: [38, 40],
|
|
confirm: [13]
|
|
}
|
|
if (keyCodes.cycle.includes(keyCode)) {
|
|
const direction = keyCode === 38 ? -1 : 1
|
|
changeActiveResult(direction)
|
|
} else if (keyCodes.confirm.includes(keyCode)) {
|
|
const contextedLink = activeResult.value ? activeResult.value.title : props.autocompleteText
|
|
emit('createLink', contextedLink)
|
|
}
|
|
}
|
|
defineExpose({ handleKeypress })
|
|
</script>
|
|
<template>
|
|
<UIMenu class="border-[1px] p-2 text-[0.875rem] text-black shadow-md" compact>
|
|
<UIMenuItem :active="!activeResult" @click="emit('createLink', props.autocompleteText)">
|
|
<span class="flex-grow">{{ props.autocompleteText }}</span>
|
|
<i class="fas fa-plus-circle ml-auto text-white" />
|
|
</UIMenuItem>
|
|
<SearchResult
|
|
v-for="result in results"
|
|
:key="result.id"
|
|
:result="result"
|
|
:active-result="activeResult"
|
|
@go-to-note="emit('createLink', result.title)"
|
|
/>
|
|
</UIMenu>
|
|
</template>
|