mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 19:21:54 +00:00
nits and test fixes
This commit is contained in:
@@ -44,7 +44,7 @@ export class ComfyNodeSearchBox {
|
|||||||
'.comfy-vue-node-search-container input[type="text"]'
|
'.comfy-vue-node-search-container input[type="text"]'
|
||||||
)
|
)
|
||||||
this.dropdown = page.locator(
|
this.dropdown = page.locator(
|
||||||
'.comfy-vue-node-search-container .p-autocomplete-list'
|
'.comfy-vue-node-search-container .comfy-autocomplete-list'
|
||||||
)
|
)
|
||||||
this.filterSelectionPanel = new ComfyNodeSearchFilterSelectionPanel(page)
|
this.filterSelectionPanel = new ComfyNodeSearchFilterSelectionPanel(page)
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ export class ComfyNodeSearchBox {
|
|||||||
await this.input.fill(nodeName)
|
await this.input.fill(nodeName)
|
||||||
await this.dropdown.waitFor({ state: 'visible' })
|
await this.dropdown.waitFor({ state: 'visible' })
|
||||||
await this.dropdown
|
await this.dropdown
|
||||||
.locator('li')
|
.locator('.option-container')
|
||||||
.nth(options?.suggestionIndex || 0)
|
.nth(options?.suggestionIndex || 0)
|
||||||
.click()
|
.click()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,24 +61,32 @@
|
|||||||
ref="inputRef"
|
ref="inputRef"
|
||||||
v-model="currentQuery"
|
v-model="currentQuery"
|
||||||
class="text-base h-5 bg-transparent border-0 focus:outline-0 flex-1"
|
class="text-base h-5 bg-transparent border-0 focus:outline-0 flex-1"
|
||||||
|
type="text"
|
||||||
autofocus
|
autofocus
|
||||||
:placeholder="t('g.searchNodes') + '...'"
|
:placeholder="t('g.searchNodes') + '...'"
|
||||||
@keydown.enter.prevent="onAddNode(hoveredSuggestion)"
|
@keydown.enter.prevent="onAddNode(hoveredSuggestion)"
|
||||||
|
@keydown.down.prevent="updateIndexBy(1)"
|
||||||
|
@keydown.up.prevent="updateIndexBy(-1)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-bind="containerProps"
|
v-bind="containerProps"
|
||||||
class="bg-comfy-menu-bg p-1 rounded-lg border-border-subtle border max-h-150"
|
class="bg-comfy-menu-bg p-1 rounded-lg border-border-subtle border max-h-150"
|
||||||
>
|
>
|
||||||
<div v-bind="wrapperProps">
|
<div v-bind="wrapperProps" class="comfy-autocomplete-list">
|
||||||
<NodeSearchItem
|
<NodeSearchItem
|
||||||
v-for="{ data: option, index } in virtualList"
|
v-for="{ data: option, index } in virtualList"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="hover:bg-secondary-background-hover p-1 rounded-sm"
|
:class="
|
||||||
|
cn(
|
||||||
|
'p-1 rounded-sm',
|
||||||
|
hoveredIndex === index && 'bg-secondary-background-hover'
|
||||||
|
)
|
||||||
|
"
|
||||||
:node-def="option"
|
:node-def="option"
|
||||||
:current-query="debouncedQuery"
|
:current-query="debouncedQuery"
|
||||||
@click="onAddNode(option)"
|
@click="onAddNode(option)"
|
||||||
@pointerover="setHoverSuggestion(index)"
|
@pointerover="hoveredIndex = index"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -93,9 +101,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { refDebounced, useVirtualList } from '@vueuse/core'
|
import { refDebounced, useVirtualList } from '@vueuse/core'
|
||||||
import { debounce } from 'es-toolkit/compat'
|
|
||||||
import Dialog from 'primevue/dialog'
|
import Dialog from 'primevue/dialog'
|
||||||
import { computed, nextTick, ref, useTemplateRef } from 'vue'
|
import { computed, nextTick, ref, useTemplateRef, watchEffect } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import NodePreview from '@/components/node/NodePreview.vue'
|
import NodePreview from '@/components/node/NodePreview.vue'
|
||||||
@@ -107,6 +114,7 @@ import { useTelemetry } from '@/platform/telemetry'
|
|||||||
import type { ComfyNodeDefImpl } from '@/stores/nodeDefStore'
|
import type { ComfyNodeDefImpl } from '@/stores/nodeDefStore'
|
||||||
import { useNodeDefStore, useNodeFrequencyStore } from '@/stores/nodeDefStore'
|
import { useNodeDefStore, useNodeFrequencyStore } from '@/stores/nodeDefStore'
|
||||||
import type { FuseFilterWithValue } from '@/utils/fuseUtil'
|
import type { FuseFilterWithValue } from '@/utils/fuseUtil'
|
||||||
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
|
|
||||||
import SearchFilterChip from '../common/SearchFilterChip.vue'
|
import SearchFilterChip from '../common/SearchFilterChip.vue'
|
||||||
|
|
||||||
@@ -124,7 +132,6 @@ const { filters, searchLimit = 64 } = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const nodeSearchFilterVisible = ref(false)
|
const nodeSearchFilterVisible = ref(false)
|
||||||
const hoveredSuggestion = ref<ComfyNodeDefImpl>()
|
|
||||||
const currentQuery = ref('')
|
const currentQuery = ref('')
|
||||||
const debouncedQuery = refDebounced(currentQuery, 100, { maxWait: 400 })
|
const debouncedQuery = refDebounced(currentQuery, 100, { maxWait: 400 })
|
||||||
const inputRef = useTemplateRef('inputRef')
|
const inputRef = useTemplateRef('inputRef')
|
||||||
@@ -132,20 +139,17 @@ const inputRef = useTemplateRef('inputRef')
|
|||||||
const nodeDefStore = useNodeDefStore()
|
const nodeDefStore = useNodeDefStore()
|
||||||
const nodeFrequencyStore = useNodeFrequencyStore()
|
const nodeFrequencyStore = useNodeFrequencyStore()
|
||||||
|
|
||||||
// Debounced search tracking (500ms as per implementation plan)
|
watchEffect(() => {
|
||||||
const debouncedTrackSearch = debounce((query: string) => {
|
const query = debouncedQuery.value
|
||||||
if (query.trim()) {
|
if (query.trim()) {
|
||||||
telemetry?.trackNodeSearch({ query })
|
telemetry?.trackNodeSearch({ query })
|
||||||
}
|
}
|
||||||
}, 500)
|
})
|
||||||
|
|
||||||
const suggestions = computed(() => {
|
const suggestions = computed(() => {
|
||||||
const query = debouncedQuery.value
|
const query = debouncedQuery.value
|
||||||
const queryIsEmpty = query === '' && filters.length === 0
|
const queryIsEmpty = query === '' && filters.length === 0
|
||||||
|
|
||||||
// Track search queries with debounce
|
|
||||||
debouncedTrackSearch(query)
|
|
||||||
|
|
||||||
return queryIsEmpty
|
return queryIsEmpty
|
||||||
? nodeFrequencyStore.topNodeDefs
|
? nodeFrequencyStore.topNodeDefs
|
||||||
: [
|
: [
|
||||||
@@ -188,12 +192,14 @@ const onRemoveFilter = async (
|
|||||||
emit('removeFilter', filterAndValue)
|
emit('removeFilter', filterAndValue)
|
||||||
inputRef.value?.focus()
|
inputRef.value?.focus()
|
||||||
}
|
}
|
||||||
const setHoverSuggestion = (index: number) => {
|
const hoveredIndex = ref<number>()
|
||||||
if (index === -1) {
|
const hoveredSuggestion = computed(() =>
|
||||||
hoveredSuggestion.value = undefined
|
hoveredIndex.value ? suggestions.value[hoveredIndex.value] : undefined
|
||||||
return
|
)
|
||||||
}
|
function updateIndexBy(delta: number) {
|
||||||
const value = suggestions.value[index]
|
hoveredIndex.value = Math.max(
|
||||||
hoveredSuggestion.value = value
|
0,
|
||||||
|
Math.min(suggestions.value.length, (hoveredIndex.value ?? 0) + delta)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
mask: { class: 'node-search-box-dialog-mask' },
|
mask: { class: 'node-search-box-dialog-mask' },
|
||||||
transition: {
|
transition: {
|
||||||
enterFromClass: 'opacity-0',
|
enterFromClass: 'opacity-0',
|
||||||
// 100ms is the duration of the transition in the dialog component
|
|
||||||
enterActiveClass: 'transition-all duration-20 ease-out',
|
enterActiveClass: 'transition-all duration-20 ease-out',
|
||||||
leaveActiveClass: 'transition-all duration-20 ease-in',
|
leaveActiveClass: 'transition-all duration-20 ease-in',
|
||||||
leaveToClass: 'opacity-0 scale-75'
|
leaveToClass: 'opacity-0 scale-75'
|
||||||
|
|||||||
Reference in New Issue
Block a user