mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-23 16:24:06 +00:00
Auto expand tree on search in node library tab (#558)
* Add custom nodelib searchbox * Auto expand on search * Support alphabetical sort in filtered tree
This commit is contained in:
@@ -1,35 +1,45 @@
|
||||
<template>
|
||||
<IconField :class="props.class">
|
||||
<InputIcon class="pi pi-search" />
|
||||
<InputIcon :class="props.icon" />
|
||||
<InputText
|
||||
class="search-box-input"
|
||||
@input="handleInput"
|
||||
:modelValue="props.modelValue"
|
||||
:placeholder="$t('searchSettings') + '...'"
|
||||
:placeholder="props.placeholder"
|
||||
/>
|
||||
</IconField>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { debounce } from 'lodash'
|
||||
import IconField from 'primevue/iconfield'
|
||||
import InputIcon from 'primevue/inputicon'
|
||||
import InputText from 'primevue/inputtext'
|
||||
import { debounce } from 'lodash'
|
||||
|
||||
const props = defineProps<{
|
||||
interface Props {
|
||||
class?: string
|
||||
modelValue: string
|
||||
}>()
|
||||
const emit = defineEmits(['update:modelValue', 'search'])
|
||||
const emitSearch = debounce((event: KeyboardEvent) => {
|
||||
const target = event.target as HTMLInputElement
|
||||
emit('search', target.value)
|
||||
}, 300)
|
||||
placeholder?: string
|
||||
icon?: string
|
||||
debounceTime?: number
|
||||
}
|
||||
|
||||
const handleInput = (event: KeyboardEvent) => {
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
placeholder: 'Search...',
|
||||
icon: 'pi pi-search',
|
||||
debounceTime: 300
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'search'])
|
||||
|
||||
const emitSearch = debounce((value: string) => {
|
||||
emit('search', value)
|
||||
}, props.debounceTime)
|
||||
|
||||
const handleInput = (event: Event) => {
|
||||
const target = event.target as HTMLInputElement
|
||||
emit('update:modelValue', target.value)
|
||||
emitSearch(event)
|
||||
emitSearch(target.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<template>
|
||||
<div class="settings-container">
|
||||
<div class="settings-sidebar">
|
||||
<SettingSearchBox
|
||||
<SearchBox
|
||||
class="settings-search-box"
|
||||
v-model:modelValue="searchQuery"
|
||||
@search="handleSearch"
|
||||
:placeholder="$t('searchSettings') + '...'"
|
||||
/>
|
||||
<Listbox
|
||||
v-model="activeCategory"
|
||||
@@ -66,7 +67,7 @@ import Divider from 'primevue/divider'
|
||||
import { SettingTreeNode, useSettingStore } from '@/stores/settingStore'
|
||||
import { SettingParams } from '@/types/settingTypes'
|
||||
import SettingGroup from './setting/SettingGroup.vue'
|
||||
import SettingSearchBox from './setting/SettingSearchBox.vue'
|
||||
import SearchBox from '@/components/common/SearchBox.vue'
|
||||
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
||||
import { flattenTree } from '@/utils/treeUtil'
|
||||
|
||||
|
||||
@@ -14,13 +14,17 @@
|
||||
</ToggleButton>
|
||||
</template>
|
||||
<template #body>
|
||||
<SearchBox
|
||||
class="node-lib-search-box"
|
||||
v-model:modelValue="searchQuery"
|
||||
@search="handleSearch"
|
||||
:placeholder="$t('searchNodes') + '...'"
|
||||
/>
|
||||
<TreePlus
|
||||
class="node-lib-tree"
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
selectionMode="single"
|
||||
:value="renderedRoot.children"
|
||||
:filter="true"
|
||||
filterMode="lenient"
|
||||
dragSelector=".p-tree-node-leaf"
|
||||
:pt="{
|
||||
nodeLabel: 'node-lib-tree-node-label',
|
||||
@@ -85,10 +89,11 @@ import { computed, ref, nextTick } from 'vue'
|
||||
import type { TreeNode } from 'primevue/treenode'
|
||||
import TreePlus from '@/components/primevueOverride/TreePlus.vue'
|
||||
import NodePreview from '@/components/node/NodePreview.vue'
|
||||
import SearchBox from '@/components/common/SearchBox.vue'
|
||||
import SidebarTabTemplate from '@/components/sidebar/tabs/SidebarTabTemplate.vue'
|
||||
import { useSettingStore } from '@/stores/settingStore'
|
||||
import { app } from '@/scripts/app'
|
||||
import { ComfyNodeDef } from '@/types/apiTypes'
|
||||
import { buildTree, sortedTree } from '@/utils/treeUtil'
|
||||
|
||||
const nodeDefStore = useNodeDefStore()
|
||||
const alphabeticalSort = ref(false)
|
||||
@@ -101,6 +106,7 @@ const hoveredComfyNode = computed<ComfyNodeDefImpl | null>(() => {
|
||||
return nodeDefStore.nodeDefsByName[hoveredComfyNodeName.value] || null
|
||||
})
|
||||
const previewRef = ref<InstanceType<typeof NodePreview> | null>(null)
|
||||
const searchQuery = ref<string>('')
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
const sidebarLocation = computed<'left' | 'right'>(() =>
|
||||
@@ -112,9 +118,10 @@ const nodePreviewStyle = ref<Record<string, string>>({
|
||||
left: '0px'
|
||||
})
|
||||
|
||||
const root = computed(() =>
|
||||
alphabeticalSort.value ? nodeDefStore.sortedNodeTree : nodeDefStore.nodeTree
|
||||
)
|
||||
const root = computed(() => {
|
||||
const root = filteredRoot.value || nodeDefStore.nodeTree
|
||||
return alphabeticalSort.value ? sortedTree(root) : root
|
||||
})
|
||||
const renderedRoot = computed(() => {
|
||||
return fillNodeInfo(root.value)
|
||||
})
|
||||
@@ -176,6 +183,35 @@ const toggleNode = (id: string) => {
|
||||
const insertNode = (nodeDef: ComfyNodeDefImpl) => {
|
||||
app.addNodeOnGraph(nodeDef, { pos: app.getCanvasCenter() })
|
||||
}
|
||||
|
||||
const filteredRoot = ref<TreeNode | null>(null)
|
||||
const handleSearch = (query: string) => {
|
||||
if (query.length < 3) {
|
||||
filteredRoot.value = null
|
||||
expandedKeys.value = {}
|
||||
return
|
||||
}
|
||||
|
||||
const matchedNodes = nodeDefStore.nodeSearchService.searchNode(query, [], {
|
||||
limit: 64
|
||||
})
|
||||
|
||||
filteredRoot.value = buildTree(matchedNodes, (nodeDef: ComfyNodeDefImpl) => [
|
||||
...nodeDef.category.split('/'),
|
||||
nodeDef.display_name
|
||||
])
|
||||
expandNode(filteredRoot.value)
|
||||
}
|
||||
|
||||
const expandNode = (node: TreeNode) => {
|
||||
if (node.children && node.children.length) {
|
||||
expandedKeys.value[node.key] = true
|
||||
|
||||
for (let child of node.children) {
|
||||
expandNode(child)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -185,3 +221,9 @@ const insertNode = (nodeDef: ComfyNodeDefImpl) => {
|
||||
margin-left: var(--p-tree-node-gap);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
:deep(.node-lib-search-box) {
|
||||
@apply mx-4 mt-4;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user