feat: dropdown widgets vue node ui (#5624)

- Load media dropdown widgets
- Load models dropdown widgets

I added a lot of feedback effects during interactions.
I tried my best to break the Dropdown into small components.
To make it more flexible, I provided many configurable props and
v-model.

<img width="1000" alt="CleanShot 2025-09-18 at 01 54 38"
src="https://github.com/user-attachments/assets/1a413078-1547-44b8-8b48-1ce8f8e764b5"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5624-feat-dropdown-widgets-vue-node-ui-2716d73d36508115a52bc1fb6d6376d0)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Christian Byrne <cbyrne@comfy.org>
This commit is contained in:
Rizumu Ayaka
2025-09-27 03:04:39 +08:00
committed by GitHub
parent 9f19d8fb4b
commit c96f719f91
19 changed files with 1270 additions and 51 deletions

View File

@@ -9,6 +9,8 @@ import type { INodeOutputSlot } from '@/lib/litegraph/src/interfaces'
import type { INodeInputSlot } from '@/lib/litegraph/src/interfaces'
import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations'
import { LayoutSource } from '@/renderer/core/layout/types'
import type { InputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'
import { useNodeDefStore } from '@/stores/nodeDefStore'
import type { WidgetValue } from '@/types/simplifiedWidget'
import type { LGraph, LGraphNode } from '../../lib/litegraph/src/litegraph'
@@ -20,6 +22,7 @@ export interface SafeWidgetData {
label?: string
options?: Record<string, unknown>
callback?: ((value: unknown) => void) | undefined
spec?: InputSpec
}
export interface VueNodeData {
@@ -53,6 +56,7 @@ export interface GraphNodeManager {
export function useGraphNodeManager(graph: LGraph): GraphNodeManager {
// Get layout mutations composable
const { createNode, deleteNode, setSource } = useLayoutMutations()
const nodeDefStore = useNodeDefStore()
// Safe reactive data extracted from LiteGraph nodes
const vueNodeData = reactive(new Map<string, VueNodeData>())
@@ -82,6 +86,7 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager {
) {
value = widget.options.values[0]
}
const spec = nodeDefStore.getInputSpecForWidget(node, widget.name)
return {
name: widget.name,
@@ -89,15 +94,14 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager {
value: value,
label: widget.label,
options: widget.options ? { ...widget.options } : undefined,
callback: widget.callback
callback: widget.callback,
spec
}
} catch (error) {
return {
name: widget.name || 'unknown',
type: widget.type || 'text',
value: undefined, // Already a valid WidgetValue
options: undefined,
callback: undefined
value: undefined
}
}
})