Skip to content

Commit

Permalink
rename to DocsSearch; issues
Browse files Browse the repository at this point in the history
  • Loading branch information
bdrtsky committed Jun 21, 2023
1 parent 543cd77 commit 6455683
Show file tree
Hide file tree
Showing 4 changed files with 351 additions and 259 deletions.
2 changes: 1 addition & 1 deletion components/app/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const isBasicLayout = computed(() => route.meta.layout === 'basic')

<div class="section right">
<!-- <AppSearchOLD v-if="hasDocSearch" /> -->
<AppSearch />
<DocsSearch />
<AppTextDirection />
<AppColorMode />
<div class="social-icons">
Expand Down
242 changes: 64 additions & 178 deletions components/app/AppSearch.vue
Original file line number Diff line number Diff line change
@@ -1,194 +1,80 @@
<script setup lang="ts">
import { useFuse } from '@vueuse/integrations/useFuse'
const { navigation } = useContent()
const { element } = useDocSearch()
const show = ref(false)
const q = ref('')
const searchResults = ref([])
const { data: files } = await useLazyAsyncData('components', () => queryContent('components').where({ _type: 'markdown', navigation: { $ne: false } }).find(), { default: () => [] })
const { results } = useFuse(q, files, {
fuseOptions: {
keys: [
'title',
'description',
],
ignoreLocation: true,
threshold: 0,
includeMatches: true,
includeScore: true,
},
matchAllWhenSearchEmpty: false
})
console.log('files', files.value)
console.log('results', results.value)
function findNavItem (children: any, path: string, parent: any) {
for (const child of children) {
if (child._path === path) {
return {
directoryTitle: parent.title,
directoryIcon: parent.icon
}
}
if (child.children) {
const result: any = findNavItem(child.children, path, child)
if (result) {
return result
}
}
}
return undefined
}
function getNavItemMeta (path: string) {
let result
for (const item of navigation.value) {
if (item.children) {
const found = findNavItem(item.children, path, item)
if (found) {
result = found
}
}
}
return result
}
function highlight(text: string, { indices, value }: { indices: number[][], value: string }): string {
if (text === value) {
return ''
}
let content = ''
let nextUnhighlightedIndiceStartingIndex = 0
indices.forEach((indice) => {
const lastIndiceNextIndex = indice[1] + 1
const isMatched = (lastIndiceNextIndex - indice[0]) >= q.value.length
content += [
value.substring(nextUnhighlightedIndiceStartingIndex, indice[0]),
isMatched && '<mark>',
value.substring(indice[0], lastIndiceNextIndex),
isMatched && '</mark>'
].filter(Boolean).join('')
nextUnhighlightedIndiceStartingIndex = lastIndiceNextIndex
})
content += value.substring(nextUnhighlightedIndiceStartingIndex)
const index = content.indexOf('<mark>')
if (index > 60) {
content = `...${content.substring(index - 60)}`
}
return content
}
// console.log('HIGHLIGHT', highlight(q.value, results.value[0].matches[0]))
// watch(q, async (value) => {
// // debouncedSearch()
// console.log('search', value)
// await fuse.value.search(value)
// })
watch(results, (value) => {
console.log('results', value)
})
const onClick = () => element.value.querySelector('button').click()
</script>

<template>
<div>
<button @click="show = !show">
search
<div
class="doc-search"
@click="onClick"
>
<button
type="button"
aria-label="Search"
>
<span class="content">
<Icon name="heroicons-outline:search" />
<span>Search</span>
<span>
<kbd>⌘</kbd>
<kbd>K</kbd>
</span>
</span>
</button>

<Modal v-model="show">
<div class="search-content">
<div
class="search-window"
@click.stop
>
<input
v-model="q"
type="text"
>
<div v-if="results.length">
<div v-for="result in results">
<a
:href="result.item._path"
class="search-link"
>
<span>
{{ getNavItemMeta(result?.item?._path)?.directoryTitle }}
</span>
<span>
{{ result.item.title }}
</span>
<span v-html="highlight(q, result.matches?.[0])" />
</a>
</div>
<!-- <div v-html="highlight(q, results?.[0].matches?.[0])"></div> -->
</div>
</div>
</div>
</Modal>
</div>
</template>

<style scoped lang="ts">
css({
'.search-content': {
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
// alignItems: 'center',
'.search-window': {
padding: '1rem',
border: '1px solid {elements.border.primary.static}',
backgroundColor: '{elements.surface.primary.backgroundColor}',
borderRadius: '0.5rem',
marginTop: '20vh',
width: '640px',
height: 'fit-content',
maxHeight: '320px',
transition: 'all 200ms',
'.search-link': {
my: '0.5rem',
truncate: true,
'.doc-search': {
'&:hover': {
button: {
borderColor: '{color.gray.300}'
}
},
button: {
padding: '{space.2} {space.4}',
'.content': {
borderRadius: '{radii.md}',
display: 'flex',
gap: '0.5rem',
alignItems: 'center',
color: '{elements.text.secondary.color.static}',
borderStyle: 'solid',
borderWidth: '1px',
borderColor: '{color.gray.100}',
fontSize: '{fontSize.xs}',
gap: '{space.2}',
padding: '{space.rem.375}',
'@dark': {
borderColor: '{color.gray.900}',
},
'&:hover': {
color: '{elements.text.secondary.color.hover}',
borderColor: '{color.gray.400}',
'@dark': {
borderColor: '{color.gray.700}',
}
},
span: {
'&:first-child': {
display: 'block',
fontSize: '{fontSize.xs}',
fontWeight: '{fontWeight.medium}',
},
'&:nth-child(2)': {
flex: 'none',
display: 'none',
fontSize: '{fontSize.xs}',
fontWeight: '{fontWeight.semibold}',
'@sm': {
display: 'block'
}
}
}
}
}
}
})
</style>
},

<style scoped>
@media (prefers-reduced-motion: reduce) {
.search-window {
transition: all 0ms !important;
}
}
.modal-enter-active .search-window,
.modal-leave-active .search-window {
transition: transform 200ms $dt('ease.back.out'), opacity 200ms $dt('ease.back.out');
}
.modal-enter-from .search-window,
.modal-leave-to .search-window {
opacity: 0;
transform: translate3d(0, 25px, 0);
}
})
</style>
80 changes: 0 additions & 80 deletions components/app/AppSearchOLD.vue

This file was deleted.

Loading

0 comments on commit 6455683

Please sign in to comment.