1
1
<script lang="ts" setup>
2
2
import type { Query } from ' @/composables/graphql'
3
3
4
+ const props = defineProps <{
5
+ query? : string
6
+ }>()
7
+
4
8
const router = useRouter ()
5
9
6
10
const { locale } = useI18n ()
7
11
12
+ const comboEl = shallowRef <HTMLDivElement >()
8
13
const inputEl = shallowRef <HTMLInputElement >()
9
14
10
15
function setCursorPos(pos : number ) {
@@ -84,7 +89,7 @@ const popularTags = computed<ComboTag[]>(() =>
84
89
}
85
90
}) || [])
86
91
87
- const query = ref (' ' )
92
+ const query = ref (props . query || ' ' )
88
93
const cursor = ref (0 )
89
94
90
95
const queryKeywordStart = computed (() => {
@@ -157,7 +162,7 @@ function siteOrKeywordFilter(query: string) {
157
162
158
163
const { data : queryData, refresh, pending } = useLazyFetch <QueryResult []>(
159
164
() => ` https://patchyvideo.com/be/autocomplete/ql?q=${queryKeyword .value } ` ,
160
- { immediate: false , watch: false },
165
+ { immediate: Boolean ( props . query ) , watch: false },
161
166
)
162
167
watchThrottled (queryKeyword , (value ) => {
163
168
if (value )
@@ -206,6 +211,17 @@ const completesWithKeyword = computed<ComboTag[]>(
206
211
)
207
212
208
213
const inFocus = ref (false )
214
+ function onBodyClick(event : MouseEvent ) {
215
+ if (comboEl .value && ! comboEl .value .contains (event .target as Node ))
216
+ inFocus .value = false
217
+ }
218
+ onMounted (() => {
219
+ document .addEventListener (' click' , onBodyClick )
220
+ })
221
+ onUnmounted (() => {
222
+ document .removeEventListener (' click' , onBodyClick )
223
+ })
224
+
209
225
const active = ref (- 1 )
210
226
const activeCombo = computed (() => completesWithKeyword .value [active .value ])
211
227
@@ -258,8 +274,10 @@ function onKeyDown(e: KeyboardEvent) {
258
274
e .preventDefault ()
259
275
e .stopPropagation ()
260
276
if (activeCombo .value ) {
277
+ // activeCombo.value.tag will be undefined after setting query.value
278
+ const tag = activeCombo .value .tag
261
279
query .value = ` ${queryPrefix .value }${activeCombo .value .tag }${querySuffix .value || ' ' } `
262
- const pos = queryPrefix .value .length + activeCombo . value . tag .length + 1
280
+ const pos = queryPrefix .value .length + tag .length + 1
263
281
nextTick (() => setCursorPos (pos ))
264
282
active .value = - 1
265
283
}
@@ -279,15 +297,14 @@ function onComboClick(combo: ComboTag) {
279
297
</script >
280
298
281
299
<template >
282
- <div class =" relative" >
300
+ <div ref = " comboEl " class =" relative" >
283
301
<div class =" flex items-center rounded-md border-2 border-purple-200 dark:border-gray-700 dark:bg-gray-800" >
284
302
<input
285
303
ref =" inputEl"
286
304
v-model =" query"
287
305
class =" focus:outline-none w-full ml-4 py-1 dark:bg-gray-800"
288
306
placeholder =" 搜索你想看的内容"
289
307
@focus =" () => inFocus = true"
290
- @blur =" () => inFocus = false"
291
308
@keydown =" onKeyDown"
292
309
@keyup =" (e) => cursor = (e.target as HTMLInputElement).selectionStart || 0"
293
310
>
@@ -307,7 +324,7 @@ function onComboClick(combo: ComboTag) {
307
324
<div
308
325
v-show =" inFocus"
309
326
static
310
- class =" absolute w-[calc(100%-1rem)] max-h-80vh mt-2 ml-2 rounded-lg ring-2 ring-purple-300 bg-white overflow-auto"
327
+ class =" absolute w-[calc(100%-1rem)] max-h-80vh mt-2 ml-2 rounded-lg ring-2 ring-purple-300 dark:ring-gray-600 bg-white dark:bg-gray-800 overflow-auto"
311
328
>
312
329
<div
313
330
v-if =" completesWithKeyword.length === 0"
@@ -319,7 +336,7 @@ function onComboClick(combo: ComboTag) {
319
336
<li
320
337
v-for =" (combo, index) in completesWithKeyword"
321
338
:key =" combo.id"
322
- class =" px-2 py-1 w-full list-none border-b border-purple-200 last:border-b-0 transition-colors duration-75 cursor-pointer"
339
+ class =" px-2 py-1 w-full list-none border-b border-purple-200 dark:border-gray-600 last:border-b-0 transition-colors duration-75 cursor-pointer"
323
340
:class =" { 'bg-purple-200 bg-opacity-10': active === index }"
324
341
@click =" onComboClick(combo)"
325
342
>
0 commit comments