[TS] Fix input spec types in widgets (#2817)

This commit is contained in:
Chenlei Hu
2025-03-02 21:01:50 -05:00
committed by GitHub
parent a8bb6c4daa
commit d37ac3aa16
6 changed files with 42 additions and 20 deletions

View File

@@ -1,6 +1,6 @@
import type { LGraphNode } from '@comfyorg/litegraph'
import type { InputSpec } from '@/schemas/nodeDefSchema'
import { type InputSpec, isBooleanInputSpec } from '@/schemas/nodeDefSchema'
import type { ComfyWidgetConstructor } from '@/scripts/widgets'
export const useBooleanWidget = () => {
@@ -9,7 +9,11 @@ export const useBooleanWidget = () => {
inputName: string,
inputData: InputSpec
) => {
const inputOptions = inputData[1]
if (!isBooleanInputSpec(inputData)) {
throw new Error(`Invalid input data: ${inputData}`)
}
const inputOptions = inputData[1] ?? {}
const defaultVal = inputOptions?.default ?? false
const options = {
on: inputOptions?.label_on,
@@ -17,7 +21,6 @@ export const useBooleanWidget = () => {
}
return {
// @ts-expect-error InputSpec is not typed correctly
widget: node.addWidget('toggle', inputName, defaultVal, () => {}, options)
}
}

View File

@@ -1,7 +1,11 @@
import type { LGraphNode } from '@comfyorg/litegraph'
import type { IComboWidget } from '@comfyorg/litegraph/dist/types/widgets'
import type { InputSpec } from '@/schemas/nodeDefSchema'
import {
type InputSpec,
isComboInputSpec,
isComboInputSpecV2
} from '@/schemas/nodeDefSchema'
import { addValueControlWidgets } from '@/scripts/widgets'
import type { ComfyWidgetConstructor } from '@/scripts/widgets'
import { useWidgetStore } from '@/stores/widgetStore'
@@ -14,26 +18,32 @@ export const useComboWidget = () => {
inputName: string,
inputData: InputSpec
) => {
if (!isComboInputSpec(inputData)) {
throw new Error(`Invalid input data: ${inputData}`)
}
const widgetStore = useWidgetStore()
const { remote, options } = inputData[1] || {}
const inputOptions = inputData[1] ?? {}
const comboOptions =
(isComboInputSpecV2(inputData) ? inputOptions.options : inputData[0]) ??
[]
const defaultValue = widgetStore.getDefaultValue(inputData)
const res = {
widget: node.addWidget('combo', inputName, defaultValue, () => {}, {
// @ts-expect-error InputSpec is not typed correctly
values: options ?? inputData[0]
values: comboOptions
}) as IComboWidget
}
if (remote) {
if (inputOptions.remote) {
const remoteWidget = useRemoteWidget({
inputData,
defaultValue,
node,
widget: res.widget
})
// @ts-expect-error InputSpec is not typed correctly
if (remote.refresh_button) remoteWidget.addRefreshButton()
if (inputOptions.remote.refresh_button) remoteWidget.addRefreshButton()
const origOptions = res.widget.options
res.widget.options = new Proxy(
@@ -47,7 +57,7 @@ export const useComboWidget = () => {
)
}
if (inputData[1]?.control_after_generate) {
if (inputOptions.control_after_generate) {
res.widget.linkedWidgets = addValueControlWidgets(
node,
res.widget,

View File

@@ -1,6 +1,6 @@
import type { IWidget, LGraphNode } from '@comfyorg/litegraph'
import type { InputSpec } from '@/schemas/nodeDefSchema'
import { type InputSpec, isStringInputSpec } from '@/schemas/nodeDefSchema'
import type { ComfyWidgetConstructor } from '@/scripts/widgets'
import { useSettingStore } from '@/stores/settingStore'
import type { ComfyApp } from '@/types'
@@ -64,15 +64,20 @@ export const useStringWidget = () => {
inputData: InputSpec,
app: ComfyApp
) => {
const defaultVal = inputData[1]?.default || ''
const multiline = !!inputData[1]?.multiline
if (!isStringInputSpec(inputData)) {
throw new Error(`Invalid input data: ${inputData}`)
}
const inputOptions = inputData[1] ?? {}
const defaultVal = inputOptions.default ?? ''
const multiline = inputOptions.multiline
let res: { widget: IWidget }
if (multiline) {
res = addMultilineWidget(
node,
inputName,
{ defaultVal, ...inputData[1] },
{ defaultVal, ...inputOptions },
app
)
} else {
@@ -81,9 +86,9 @@ export const useStringWidget = () => {
}
}
if (inputData[1]?.dynamicPrompts != undefined)
// @ts-expect-error InputSpec is not typed correctly
res.widget.dynamicPrompts = inputData[1].dynamicPrompts
if (inputOptions.dynamicPrompts != undefined) {
res.widget.dynamicPrompts = inputOptions.dynamicPrompts
}
return res
}

View File

@@ -69,7 +69,8 @@ const zComboInputOptions = zBaseInputOptions.extend({
image_folder: z.enum(['input', 'output', 'temp']).optional(),
allow_batch: z.boolean().optional(),
video_upload: z.boolean().optional(),
remote: zRemoteWidgetConfig.optional()
remote: zRemoteWidgetConfig.optional(),
options: z.array(z.union([z.string(), z.number()])).optional()
})
const zIntInputSpec = z.tuple([z.literal('INT'), zIntInputOptions.optional()])

View File

@@ -21,6 +21,9 @@ export const useWidgetStore = defineStore('widget', () => {
function getWidgetType(type: string, inputName: string) {
if (type === 'COMBO') {
return 'COMBO'
/**
* @deprecated Group node logic. Remove once group node feature is removed.
*/
} else if (`${type}:${inputName}` in widgets.value) {
return `${type}:${inputName}`
} else if (type in widgets.value) {

View File

@@ -41,7 +41,7 @@ describe('useComboWidget', () => {
undefined, // default value
expect.any(Function), // callback
expect.objectContaining({
values: 'COMBO'
values: []
})
)
expect(widget).toEqual({