mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-04 21:22:07 +00:00
## Summary Make the preview node match recent LGraphNode.vue look. Also add support to click from search. ## Changes - **What**: NodeSearchBox.vue, LGraphNodePreview.vue, nodeDefStore.ts ## Screenshots (if applicable) https://github.com/user-attachments/assets/ed46d641-66bf-4e23-a207-9102609a7a4a ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7146-fix-vue-nodes-preview-node-to-match-lg-and-add-node-when-clicked-2bf6d73d3650814383b2c786e2ab4d02) by [Unito](https://www.unito.io)
112 lines
3.1 KiB
Vue
112 lines
3.1 KiB
Vue
<template>
|
|
<div
|
|
:data-node-id="nodeData.id"
|
|
class="bg-component-node-background lg-node absolute pb-1 contain-style contain-layout w-[350px] rounded-2xl touch-none flex flex-col border-1 border-solid outline-transparent outline-2 border-node-stroke"
|
|
>
|
|
<div
|
|
class="flex flex-col justify-center items-center relative pointer-events-none"
|
|
>
|
|
<NodeHeader :node-data="nodeData" />
|
|
</div>
|
|
<div
|
|
class="flex flex-1 flex-col gap-1 pb-2 pointer-events-none"
|
|
:data-testid="`node-body-${nodeData.id}`"
|
|
>
|
|
<NodeSlots :node-data="nodeData" />
|
|
|
|
<NodeWidgets
|
|
v-if="nodeData.widgets?.length"
|
|
:node-data="nodeData"
|
|
class="pointer-events-none"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
|
|
import type { VueNodeData } from '@/composables/graph/useGraphNodeManager'
|
|
import type {
|
|
INodeInputSlot,
|
|
INodeOutputSlot
|
|
} from '@/lib/litegraph/src/interfaces'
|
|
import { RenderShape } from '@/lib/litegraph/src/litegraph'
|
|
import NodeHeader from '@/renderer/extensions/vueNodes/components/NodeHeader.vue'
|
|
import NodeSlots from '@/renderer/extensions/vueNodes/components/NodeSlots.vue'
|
|
import NodeWidgets from '@/renderer/extensions/vueNodes/components/NodeWidgets.vue'
|
|
import type { ComfyNodeDef as ComfyNodeDefV2 } from '@/schemas/nodeDef/nodeDefSchemaV2'
|
|
import { useWidgetStore } from '@/stores/widgetStore'
|
|
|
|
const { nodeDef } = defineProps<{
|
|
nodeDef: ComfyNodeDefV2
|
|
}>()
|
|
|
|
const widgetStore = useWidgetStore()
|
|
|
|
// Convert nodeDef into VueNodeData
|
|
const nodeData = computed<VueNodeData>(() => {
|
|
const widgets = Object.entries(nodeDef.inputs || {})
|
|
.filter(([_, input]) => widgetStore.inputIsWidget(input))
|
|
.map(([name, input]) => ({
|
|
name,
|
|
type: input.widgetType || input.type,
|
|
value:
|
|
input.default !== undefined
|
|
? input.default
|
|
: input.type === 'COMBO' &&
|
|
Array.isArray(input.options) &&
|
|
input.options.length > 0
|
|
? input.options[0]
|
|
: '',
|
|
options: {
|
|
hidden: input.hidden,
|
|
advanced: input.advanced,
|
|
values: input.type === 'COMBO' ? input.options : undefined // For combo widgets
|
|
}
|
|
}))
|
|
|
|
const inputs: INodeInputSlot[] = Object.entries(nodeDef.inputs || {})
|
|
.filter(([_, input]) => !widgetStore.inputIsWidget(input))
|
|
.map(([name, input]) => ({
|
|
name,
|
|
type: input.type,
|
|
shape: input.isOptional ? RenderShape.HollowCircle : undefined,
|
|
boundingRect: [0, 0, 0, 0],
|
|
link: null
|
|
}))
|
|
|
|
const outputs: INodeOutputSlot[] = (nodeDef.outputs || []).map((output) => {
|
|
if (typeof output === 'string') {
|
|
return {
|
|
name: output,
|
|
type: output,
|
|
boundingRect: [0, 0, 0, 0],
|
|
links: []
|
|
}
|
|
}
|
|
return {
|
|
...output,
|
|
boundingRect: [0, 0, 0, 0],
|
|
links: []
|
|
}
|
|
})
|
|
|
|
return {
|
|
id: `preview-${nodeDef.name}`,
|
|
title: nodeDef.display_name || nodeDef.name,
|
|
type: nodeDef.name,
|
|
mode: 0, // Normal mode
|
|
selected: false,
|
|
executing: false,
|
|
widgets,
|
|
inputs,
|
|
outputs,
|
|
|
|
flags: {
|
|
collapsed: false
|
|
}
|
|
}
|
|
})
|
|
</script>
|