1- import { default as docsearch } from '@docsearch/js'
21import { usePageLang , useRouteLocale } from '@vuepress/client'
3- import { isArray } from '@vuepress/shared'
4- import { computed , defineComponent , h , onMounted , watch } from 'vue'
5- import type { PropType } from 'vue'
2+ import {
3+ computed ,
4+ defineComponent ,
5+ h ,
6+ onMounted ,
7+ type PropType ,
8+ ref ,
9+ watch ,
10+ } from 'vue'
611import type { DocsearchOptions } from '../../shared/index.js'
7- import { useDocsearchShim } from '../composables/index.js'
12+ import {
13+ useDocsearchHotkeyListener ,
14+ useDocsearchShim ,
15+ } from '../composables/index.js'
16+ import {
17+ getFacetFilters ,
18+ getSearchButtonTemplate ,
19+ pollToOpenDocsearch ,
20+ preconnectToAlgolia ,
21+ } from '../utils/index.js'
822
923declare const __DOCSEARCH_INJECT_STYLES__ : boolean
1024declare const __DOCSEARCH_OPTIONS__ : DocsearchOptions
11- const options = __DOCSEARCH_OPTIONS__
25+
26+ const optionsDefault = __DOCSEARCH_OPTIONS__
1227
1328if ( __DOCSEARCH_INJECT_STYLES__ ) {
1429 import ( '@docsearch/css' )
@@ -27,77 +42,79 @@ export const Docsearch = defineComponent({
2742 options : {
2843 type : Object as PropType < DocsearchOptions > ,
2944 required : false ,
30- default : ( ) => options ,
45+ default : ( ) => optionsDefault ,
3146 } ,
3247 } ,
3348
3449 setup ( props ) {
35- const routeLocale = useRouteLocale ( )
36- const lang = usePageLang ( )
3750 const docsearchShim = useDocsearchShim ( )
51+ const lang = usePageLang ( )
52+ const routeLocale = useRouteLocale ( )
53+
54+ const hasInitialized = ref ( false )
55+ const hasTriggered = ref ( false )
3856
3957 // resolve docsearch options for current locale
40- const optionsLocale = computed ( ( ) => ( {
58+ const options = computed ( ( ) => ( {
4159 ...props . options ,
4260 ...props . options . locales ?. [ routeLocale . value ] ,
4361 } ) )
4462
45- const facetFilters : string [ ] = [ ]
46-
47- const initialize = ( ) : void => {
48- const rawFacetFilters =
49- optionsLocale . value . searchParameters ?. facetFilters ?? [ ]
50- facetFilters . splice (
51- 0 ,
52- facetFilters . length ,
53- `lang:${ lang . value } ` ,
54- ...( isArray ( rawFacetFilters ) ? rawFacetFilters : [ rawFacetFilters ] )
55- )
63+ /**
64+ * Import docsearch js and initialize
65+ */
66+ const initialize = async ( ) : Promise < void > => {
67+ const { default : docsearch } = await import ( '@docsearch/js' )
5668 // @ts -expect-error: https://github.com/microsoft/TypeScript/issues/50690
5769 docsearch ( {
5870 ...docsearchShim ,
59- ...optionsLocale . value ,
71+ ...options . value ,
6072 container : `#${ props . containerId } ` ,
6173 searchParameters : {
62- ...optionsLocale . value . searchParameters ,
63- facetFilters,
74+ ...options . value . searchParameters ,
75+ facetFilters : getFacetFilters (
76+ options . value . searchParameters ?. facetFilters ,
77+ lang . value
78+ ) ,
6479 } ,
6580 } )
81+ // mark as initialized
82+ hasInitialized . value = true
6683 }
6784
68- onMounted ( ( ) => {
85+ /**
86+ * Trigger docsearch initialization and open it
87+ */
88+ const trigger = ( ) : void => {
89+ if ( hasTriggered . value || hasInitialized . value ) return
90+ // mark as triggered
91+ hasTriggered . value = true
92+ // initialize and open
6993 initialize ( )
94+ pollToOpenDocsearch ( )
95+ // re-initialize when route locale changes
96+ watch ( routeLocale , initialize )
97+ }
7098
71- // re-initialize if the options is changed
72- watch (
73- [ routeLocale , optionsLocale ] ,
74- (
75- [ curRouteLocale , curPropsLocale ] ,
76- [ prevRouteLocale , prevPropsLocale ]
77- ) => {
78- if ( curRouteLocale === prevRouteLocale ) return
79- if (
80- JSON . stringify ( curPropsLocale ) !== JSON . stringify ( prevPropsLocale )
81- ) {
82- initialize ( )
83- }
84- }
85- )
99+ // trigger when hotkey is pressed
100+ useDocsearchHotkeyListener ( trigger )
86101
87- // modify the facetFilters in place to avoid re-initializing docsearch
88- // when page lang is changed
89- watch ( lang , ( curLang , prevLang ) => {
90- if ( curLang !== prevLang ) {
91- const prevIndex = facetFilters . findIndex (
92- ( item ) => item === `lang:${ prevLang } `
93- )
94- if ( prevIndex > - 1 ) {
95- facetFilters . splice ( prevIndex , 1 , `lang:${ curLang } ` )
96- }
97- }
98- } )
99- } )
102+ // preconnect to algolia
103+ onMounted ( ( ) => preconnectToAlgolia ( options . value . appId ) )
100104
101- return ( ) => h ( 'div' , { id : props . containerId } )
105+ return ( ) => [
106+ h ( 'div' , {
107+ id : props . containerId ,
108+ style : { display : hasInitialized . value ? 'block' : 'none' } ,
109+ } ) ,
110+ hasInitialized . value
111+ ? null
112+ : h ( 'div' , {
113+ onClick : trigger ,
114+ innerHTML : getSearchButtonTemplate (
115+ options . value . translations ?. button
116+ ) ,
117+ } ) ,
118+ ]
102119 } ,
103120} )
0 commit comments