autocomplete styling
This commit is contained in:
29
src/components/Autocomplete.vue
Normal file
29
src/components/Autocomplete.vue
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import SearchResult from '@/components/Search/SearchResult.vue'
|
||||||
|
import { notes, findNotesByByTitle, activeNote } from '@/composables/useNotes'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
autocompleteText: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const results = computed<Note[]>(() => {
|
||||||
|
return (
|
||||||
|
props.autocompleteText ? findNotesByByTitle(props.autocompleteText) : notes.value
|
||||||
|
).filter((note) => note.id !== activeNote.value?.id)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<ul
|
||||||
|
tabindex="0"
|
||||||
|
class="menu mt-2 w-full rounded-md border-[1px] bg-base-100 p-2 text-[0.875rem] text-black shadow-md"
|
||||||
|
>
|
||||||
|
<li class="flex flex-row">
|
||||||
|
<a class="active flex-1 px-2 py-1">
|
||||||
|
<span class="flex-1">{{ props.autocompleteText }}</span>
|
||||||
|
<i class="fas fa-plus-circle ml-auto text-white" />
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<SearchResult v-for="result in results" :result="result" />
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
@@ -15,6 +15,7 @@ import AutoformatPlugin from '@ckeditor/ckeditor5-autoformat/src/autoformat'
|
|||||||
import ContextedPlugin from '@/ckeditor/ContextedPlugin'
|
import ContextedPlugin from '@/ckeditor/ContextedPlugin'
|
||||||
import { mdToHtml } from '@/utils/markdown'
|
import { mdToHtml } from '@/utils/markdown'
|
||||||
import { activeNote, getNoteByTitle } from '@/composables/useNotes'
|
import { activeNote, getNoteByTitle } from '@/composables/useNotes'
|
||||||
|
import Autocomplete from '@/components/Autocomplete.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
note: Note
|
note: Note
|
||||||
@@ -92,13 +93,12 @@ const handleAutocomplete = (event: any) => {
|
|||||||
@click="handleClick"
|
@click="handleClick"
|
||||||
@contexted-link-autocomplete="handleAutocomplete"
|
@contexted-link-autocomplete="handleAutocomplete"
|
||||||
></CKEditor>
|
></CKEditor>
|
||||||
<div
|
<Autocomplete
|
||||||
class="absolute mt-1 border-red-500 bg-primary text-white"
|
|
||||||
:style="autocompleteStyle"
|
|
||||||
v-if="showAutocomplete"
|
v-if="showAutocomplete"
|
||||||
>
|
:autocomplete-text="autocompleteText"
|
||||||
{{ autocompleteText }}
|
:style="autocompleteStyle"
|
||||||
</div>
|
class="absolute mt-1 w-[250px]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch, computed } from 'vue'
|
import { ref, watch, computed } from 'vue'
|
||||||
|
import SearchResult from '@/components/Search/SearchResult.vue'
|
||||||
import { notes, findNotes, activeNote } from '@/composables/useNotes'
|
import { notes, findNotes, activeNote } from '@/composables/useNotes'
|
||||||
import { formatDate } from '@/utils/helpers'
|
|
||||||
|
|
||||||
const active = ref(false)
|
const active = ref(false)
|
||||||
watch(active, () => {
|
watch(active, () => {
|
||||||
@@ -62,26 +62,13 @@ const handleKeydown = (event: KeyboardEvent) => {
|
|||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="menu mt-1 w-full rounded-md bg-base-100 p-2 text-black shadow"
|
class="menu mt-1 w-full rounded-md bg-base-100 p-2 text-black shadow"
|
||||||
>
|
>
|
||||||
<li v-for="result in results" v-if="results.length > 0" class="flex flex-row">
|
<SearchResult
|
||||||
<a
|
v-for="result in results"
|
||||||
class="flex-1 items-center px-2 py-1"
|
v-if="results.length > 0"
|
||||||
@click.stop.prevent="() => goToNote(result)"
|
:result="result"
|
||||||
@mousedown.prevent
|
:active-result="activeResult"
|
||||||
:class="{
|
@go-to-note="() => goToNote(result)"
|
||||||
disabled: activeNote?.id === result.id,
|
/>
|
||||||
active: activeResult?.id === result.id,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="badge-ghost badge badge-sm mr-0.5"
|
|
||||||
v-if="activeNote?.id === result.id"
|
|
||||||
>
|
|
||||||
current
|
|
||||||
</span>
|
|
||||||
<span class="flex-1">{{ result.title }}</span>
|
|
||||||
<span>{{ formatDate(result.modified) }}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li v-else><a>No notes found</a></li>
|
<li v-else><a>No notes found</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
35
src/components/Search/SearchResult.vue
Normal file
35
src/components/Search/SearchResult.vue
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { activeNote } from '@/composables/useNotes'
|
||||||
|
import { formatDate } from '@/utils/helpers'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
result: Note
|
||||||
|
activeResult?: Note
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'goToNote'): void
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<li class="flex flex-row">
|
||||||
|
<a
|
||||||
|
class="flex-1 items-center px-2 py-1"
|
||||||
|
@click.stop.prevent="() => emit('goToNote')"
|
||||||
|
@mousedown.prevent
|
||||||
|
:class="{
|
||||||
|
disabled: activeNote?.id === result.id,
|
||||||
|
active: props.activeResult?.id === result.id,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="badge-ghost badge badge-sm mr-0.5"
|
||||||
|
v-if="activeNote?.id === result.id"
|
||||||
|
>
|
||||||
|
current
|
||||||
|
</span>
|
||||||
|
<span class="flex-1">{{ result.title }}</span>
|
||||||
|
<span>{{ formatDate(result.modified) }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Hamburger from '@/components/Hamburger.vue'
|
import Hamburger from '@/components/Hamburger.vue'
|
||||||
import SearchBar from '@/components/SearchBar.vue'
|
import SearchBar from '@/components/Search/SearchBar.vue'
|
||||||
import Logo from './Logo.vue'
|
import Logo from './Logo.vue'
|
||||||
import { addNote, activeNote, rootNote } from '@/composables/useNotes'
|
import { addNote, activeNote, rootNote } from '@/composables/useNotes'
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ export const getNoteByTitle = (title: string) => {
|
|||||||
return notes.value.find((note) => note.title === title)
|
return notes.value.find((note) => note.title === title)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const findNotesByByTitle = (title: string) => {
|
||||||
|
const titleLowerCase = title.toLowerCase()
|
||||||
|
return notes.value.filter((note) => note.title.toLowerCase().includes(titleLowerCase))
|
||||||
|
}
|
||||||
|
|
||||||
export const findNotes = (query: string): Note[] => {
|
export const findNotes = (query: string): Note[] => {
|
||||||
const removeMdFromText = (mdText: string): string => {
|
const removeMdFromText = (mdText: string): string => {
|
||||||
const div = document.createElement('div')
|
const div = document.createElement('div')
|
||||||
|
|||||||
Reference in New Issue
Block a user