mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-30 09:27:13 +00:00
195 lines
6.0 KiB
Vue
195 lines
6.0 KiB
Vue
<template>
|
|
<div id="docsearch">
|
|
<button type="button" class="DocSearch DocSearch-Button" aria-label="Search">
|
|
<svg width="20" height="20" class="d-icon m-auto" viewBox="0 0 20 20">
|
|
<path
|
|
d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
|
|
stroke="currentColor"
|
|
fill="none"
|
|
fill-rule="evenodd"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
function isSpecialClick (event) {
|
|
return event.button === 1 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey
|
|
}
|
|
|
|
export default {
|
|
props: {
|
|
options: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
settings: {
|
|
type: Object,
|
|
required: true
|
|
}
|
|
},
|
|
watch: {
|
|
'$i18n.locale' (newValue) {
|
|
this.update(this.options, newValue)
|
|
},
|
|
options (newValue) {
|
|
this.update(newValue, this.$i18n.locale)
|
|
}
|
|
},
|
|
mounted () {
|
|
this.initialize(this.options, this.$i18n.locale)
|
|
},
|
|
methods: {
|
|
stripTrailingSlash (url) {
|
|
return url.replace(/\/$|\/(?=\?)|\/(?=#)/g, '')
|
|
},
|
|
getRelativePath (absoluteUrl) {
|
|
const { pathname, hash } = new URL(absoluteUrl)
|
|
const url = pathname.replace(this.settings.url, '/') + hash
|
|
return this.stripTrailingSlash(url)
|
|
},
|
|
async initialize (userOptions, code) {
|
|
const lang = this.$i18n.locales.find(locale => locale.code === code)
|
|
|
|
const docsearch = await Promise.all([
|
|
import(/* webpackChunkName: "docsearch" */ '@docsearch/js'),
|
|
import(/* webpackChunkName: "docsearch" */ '@docsearch/css')
|
|
]).then(([docsearch]) => docsearch.default)
|
|
|
|
docsearch({
|
|
...userOptions,
|
|
container: '#docsearch',
|
|
searchParameters: {
|
|
...((!lang)
|
|
? {}
|
|
: {
|
|
facetFilters: [`${userOptions.langAttribute || 'language'}:${lang.iso}`].concat(
|
|
userOptions.facetFilters || []
|
|
)
|
|
})
|
|
},
|
|
navigator: {
|
|
navigate: ({ itemUrl }) => {
|
|
const { pathname: hitPathname } = new URL(window.location.origin + itemUrl)
|
|
|
|
// Vue Router doesn't handle same-page navigation so we use
|
|
// the native browser location API for anchor navigation.
|
|
if (this.$router.history.current.path === hitPathname) {
|
|
window.location.assign(window.location.origin + itemUrl)
|
|
} else {
|
|
this.$router.push(itemUrl)
|
|
}
|
|
}
|
|
},
|
|
transformItems: (items) => {
|
|
return items.map((item) => {
|
|
return {
|
|
...item,
|
|
url: this.getRelativePath(item.url)
|
|
}
|
|
})
|
|
},
|
|
hitComponent: ({ hit, children }) => {
|
|
return {
|
|
type: 'a',
|
|
constructor: undefined,
|
|
__v: 1,
|
|
props: {
|
|
href: hit.url,
|
|
children,
|
|
onClick: (event) => {
|
|
if (isSpecialClick(event)) {
|
|
return
|
|
}
|
|
|
|
// We rely on the native link scrolling when user is
|
|
// already on the right anchor because Vue Router doesn't
|
|
// support duplicated history entries.
|
|
if (this.$router.history.current.fullPath === hit.url) {
|
|
return
|
|
}
|
|
|
|
const { pathname: hitPathname } = new URL(window.location.origin + hit.url)
|
|
|
|
// If the hits goes to another page, we prevent the native link behavior
|
|
// to leverage the Vue Router loading feature.
|
|
if (this.$router.history.current.path !== hitPathname) {
|
|
event.preventDefault()
|
|
}
|
|
|
|
this.$router.push(hit.url)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
},
|
|
update (options, lang) {
|
|
return this.initialize(options, lang)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="postcss">
|
|
.DocSearch {
|
|
--docsearch-primary-color: #00dc82;
|
|
--docsearch-highlight-color: var(--docsearch-primary-color);
|
|
--docsearch-text-color: rgb(113, 113, 122);
|
|
--docsearch-modal-background: theme("colors.gray.100");
|
|
--docsearch-searchbox-shadow: 0 0 0 2px var(--docsearch-primary-color);
|
|
--docsearch-searchbox-background: var(--color-transparent);
|
|
--docsearch-searchbox-focus-background: var(--color-transparent);
|
|
--docsearch-hit-color: var(--color-gray-700);
|
|
--docsearch-hit-shadow: none;
|
|
--docsearch-logo-color: var(--docsearch-text-color);
|
|
--docsearch-muted-color: var(--color-gray-500);
|
|
--docsearch-container-background: rgb(244 244 245 / 55%);
|
|
}
|
|
|
|
.dark {
|
|
& .DocSearch {
|
|
--docsearch-text-color: rgb(146, 173, 173);
|
|
--docsearch-modal-background: theme("colors.secondary-darker");
|
|
--docsearch-modal-shadow: inset 1px 1px 0 0 #052f14, 0 3px 8px 0 #0b160d;
|
|
--docsearch-hit-color: var(--color-gray-300);
|
|
--docsearch-hit-background: theme("colors.secondary-darkest");
|
|
--docsearch-footer-background: theme("colors.secondary-darkest");
|
|
--docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5),
|
|
0 -4px 8px 0 rgba(0, 0, 0, 0.2);
|
|
--docsearch-container-background: rgb(0 30 38 / 64%);
|
|
}
|
|
}
|
|
|
|
.DocSearch-Container {
|
|
@apply blur-8;
|
|
}
|
|
.DocSearch-Modal {
|
|
@apply lg:rounded-xl !important;
|
|
}
|
|
.DocSearch-SearchBar {
|
|
@apply pb-1 !important;
|
|
}
|
|
.DocSearch-Button {
|
|
@apply rounded-sm w-12 h-12 m-auto bg-transparent hover:shadow-none focus:outline-none !important;
|
|
}
|
|
.DocSearch-Button > svg {
|
|
@apply mx-auto !important;
|
|
}
|
|
.DocSearch-Button-Key {
|
|
@apply hidden !important;
|
|
}
|
|
.DocSearch-Button-Placeholder {
|
|
@apply hidden !important;
|
|
}
|
|
.DocSearch-NoResults > .DocSearch-Screen-Icon > svg {
|
|
@apply mx-auto !important;
|
|
}
|
|
.DocSearch-Commands-Key {
|
|
@apply inline-flex items-center justify-center w-auto h-auto p-1 bg-none rounded shadow-none border light:border-gray-500 !important;
|
|
}
|
|
</style>
|