[TS] Widget typing (#3804)

This commit is contained in:
filtered
2025-05-08 04:38:17 +10:00
committed by GitHub
parent bb1ac32ccd
commit b9d9ce78f9
12 changed files with 51 additions and 65 deletions

View File

@@ -75,7 +75,7 @@
</template>
<script setup lang="ts">
import { IWidget, LGraphNode } from '@comfyorg/litegraph'
import { LGraphNode } from '@comfyorg/litegraph'
import { Tooltip } from 'primevue'
import Button from 'primevue/button'
@@ -101,13 +101,13 @@ const emit = defineEmits<{
const resizeNodeMatchOutput = () => {
console.log('resizeNodeMatchOutput')
const outputWidth = node.widgets?.find((w: IWidget) => w.name === 'width')
const outputHeight = node.widgets?.find((w: IWidget) => w.name === 'height')
const outputWidth = node.widgets?.find((w) => w.name === 'width')
const outputHeight = node.widgets?.find((w) => w.name === 'height')
if (outputWidth && outputHeight && outputHeight.value && outputWidth.value) {
const [oldWidth, oldHeight] = node.size
const scene = node.widgets?.find((w: IWidget) => w.name === 'image')
const scene = node.widgets?.find((w) => w.name === 'image')
const sceneHeight = scene?.computedHeight

View File

@@ -50,7 +50,8 @@ export const useFloatWidget = () => {
Math.max(0, -Math.floor(Math.log10(step)))
const enableRounding = !settingStore.get('Comfy.DisableFloatRounding')
const defaultValue = inputSpec.default ?? 0
/** Assertion {@link inputSpec.default} */
const defaultValue = (inputSpec.default as number | undefined) ?? 0
return node.addWidget(
widgetType,
inputSpec.name,

View File

@@ -55,7 +55,8 @@ export const useIntWidget = () => {
: 'number'
const step = inputSpec.step ?? 1
const defaultValue = inputSpec.default ?? 0
/** Assertion {@link inputSpec.default} */
const defaultValue = (inputSpec.default as number | undefined) ?? 0
const widget = node.addWidget(
widgetType,
inputSpec.name,

View File

@@ -36,7 +36,7 @@ const ext = {
w.type === 'combo' && w.options.values?.length === values.length
)
.find((w) =>
// @ts-ignore Poorly typed; filter above "should" mitigate exceptions
// @ts-expect-error Poorly typed; filter above "should" mitigate exceptions
w.options.values?.every((v, i) => v === values[i])
)?.value

View File

@@ -1,5 +1,4 @@
import { IWidget } from '@comfyorg/litegraph'
import { IStringWidget } from '@comfyorg/litegraph/dist/types/widgets'
import type { IStringWidget } from '@comfyorg/litegraph/dist/types/widgets'
import { nextTick } from 'vue'
import Load3D from '@/components/load3d/Load3D.vue'
@@ -116,7 +115,7 @@ useExtensionService().registerExtension({
fileInput.onchange = async () => {
if (fileInput.files?.length) {
const modelWidget = node.widgets?.find(
(w: IWidget) => w.name === 'model_file'
(w) => w.name === 'model_file'
) as IStringWidget
node.properties['Texture'] = undefined
@@ -139,7 +138,7 @@ useExtensionService().registerExtension({
if (uploadPath && modelWidget) {
if (!modelWidget.options?.values?.includes(uploadPath)) {
// @ts-ignore Fails due to earlier type-assertion of IStringWidget
// @ts-expect-error Fails due to earlier type-assertion of IStringWidget
modelWidget.options?.values?.push(uploadPath)
}
@@ -155,9 +154,7 @@ useExtensionService().registerExtension({
node.addWidget('button', 'clear', 'clear', () => {
useLoad3dService().getLoad3d(node)?.clearModel()
const modelWidget = node.widgets?.find(
(w: IWidget) => w.name === 'model_file'
)
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
if (modelWidget) {
modelWidget.value = ''
@@ -203,12 +200,10 @@ useExtensionService().registerExtension({
const config = new Load3DConfiguration(load3d)
const modelWidget = node.widgets?.find(
(w: IWidget) => w.name === 'model_file'
)
const width = node.widgets?.find((w: IWidget) => w.name === 'width')
const height = node.widgets?.find((w: IWidget) => w.name === 'height')
const sceneWidget = node.widgets?.find((w: IWidget) => w.name === 'image')
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
const width = node.widgets?.find((w) => w.name === 'width')
const height = node.widgets?.find((w) => w.name === 'height')
const sceneWidget = node.widgets?.find((w) => w.name === 'image')
if (modelWidget && width && height && sceneWidget) {
config.configure('input', modelWidget, cameraState, width, height)
@@ -276,7 +271,7 @@ useExtensionService().registerExtension({
fileInput.onchange = async () => {
if (fileInput.files?.length) {
const modelWidget = node.widgets?.find(
(w: IWidget) => w.name === 'model_file'
(w) => w.name === 'model_file'
) as IStringWidget
const uploadPath = await Load3dUtils.uploadFile(
@@ -297,7 +292,7 @@ useExtensionService().registerExtension({
if (uploadPath && modelWidget) {
if (!modelWidget.options?.values?.includes(uploadPath)) {
// @ts-ignore Fails due to earlier type-assertion of IStringWidget
// @ts-expect-error Fails due to earlier type-assertion of IStringWidget
modelWidget.options?.values?.push(uploadPath)
}
@@ -313,9 +308,7 @@ useExtensionService().registerExtension({
node.addWidget('button', 'clear', 'clear', () => {
useLoad3dService().getLoad3d(node)?.clearModel()
const modelWidget = node.widgets?.find(
(w: IWidget) => w.name === 'model_file'
)
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
if (modelWidget) {
modelWidget.value = ''
}
@@ -352,18 +345,16 @@ useExtensionService().registerExtension({
await nextTick()
const sceneWidget = node.widgets?.find((w: IWidget) => w.name === 'image')
const sceneWidget = node.widgets?.find((w) => w.name === 'image')
const load3d = useLoad3dService().getLoad3d(node) as Load3dAnimation
const modelWidget = node.widgets?.find(
(w: IWidget) => w.name === 'model_file'
)
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
let cameraState = node.properties['Camera Info']
const width = node.widgets?.find((w: IWidget) => w.name === 'width')
const height = node.widgets?.find((w: IWidget) => w.name === 'height')
const width = node.widgets?.find((w) => w.name === 'width')
const height = node.widgets?.find((w) => w.name === 'height')
if (modelWidget && width && height && sceneWidget && load3d) {
const config = new Load3DConfiguration(load3d)
@@ -479,9 +470,7 @@ useExtensionService().registerExtension({
let cameraState = message.result[1]
const modelWidget = node.widgets?.find(
(w: IWidget) => w.name === 'model_file'
)
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
if (load3d && modelWidget) {
modelWidget.value = filePath.replaceAll('\\', '/')
@@ -555,9 +544,7 @@ useExtensionService().registerExtension({
const load3d = useLoad3dService().getLoad3d(node)
const modelWidget = node.widgets?.find(
(w: IWidget) => w.name === 'model_file'
)
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
if (load3d && modelWidget) {
modelWidget.value = filePath.replaceAll('\\', '/')

View File

@@ -3,8 +3,6 @@ Preview Any - original implement from
https://github.com/rgthree/rgthree-comfy/blob/main/py/display_any.py
upstream requested in https://github.com/Kosinkadink/rfcs/blob/main/rfcs/0000-corenodes.md#preview-nodes
*/
import { IWidget } from '@comfyorg/litegraph'
import { DOMWidget } from '@/scripts/domWidget'
import { ComfyWidgets } from '@/scripts/widgets'
import { useExtensionService } from '@/services/extensionService'
@@ -37,9 +35,7 @@ useExtensionService().registerExtension({
? void 0
: onExecuted.apply(this, [message])
const previewWidget = this.widgets?.find(
(w: IWidget) => w.name === 'preview'
)
const previewWidget = this.widgets?.find((w) => w.name === 'preview')
if (previewWidget) {
previewWidget.value = message.text[0]

View File

@@ -1,4 +1,3 @@
import { IWidget } from '@comfyorg/litegraph'
import { nextTick } from 'vue'
import Load3D from '@/components/load3d/Load3D.vue'
@@ -61,7 +60,7 @@ useExtensionService().registerExtension({
const load3d = useLoad3dService().getLoad3d(node)
const modelWidget = node.widgets?.find((w: IWidget) => w.name === 'image')
const modelWidget = node.widgets?.find((w) => w.name === 'image')
if (load3d && modelWidget) {
const filePath = fileInfo['subfolder'] + '/' + fileInfo['filename']

View File

@@ -1,4 +1,4 @@
import type { IWidget, LGraphNode } from '@comfyorg/litegraph'
import type { LGraphNode } from '@comfyorg/litegraph'
import type { IStringWidget } from '@comfyorg/litegraph/dist/types/widgets'
import { useNodeDragAndDrop } from '@/composables/node/useNodeDragAndDrop'
@@ -164,11 +164,11 @@ app.registerExtension({
// The widget that allows user to select file.
// @ts-expect-error fixme ts strict error
const audioWidget = node.widgets.find(
(w: IWidget) => w.name === 'audio'
(w) => w.name === 'audio'
) as IStringWidget
// @ts-expect-error fixme ts strict error
const audioUIWidget = node.widgets.find(
(w: IWidget) => w.name === 'audioUI'
(w) => w.name === 'audioUI'
) as unknown as DOMWidget<HTMLAudioElement, string>
const onAudioWidgetUpdate = () => {

View File

@@ -36,7 +36,7 @@ export const zNumericInputOptions = zBaseInputOptions.extend({
min: z.number().optional(),
max: z.number().optional(),
step: z.number().optional(),
// Note: Many node authors are using INT/FLOAT to pass list of INT/FLOAT.
/** Note: Many node authors are using INT/FLOAT to pass list of INT/FLOAT. */
default: z.union([z.number(), z.array(z.number())]).optional(),
display: z.enum(['slider', 'number', 'knob']).optional()
})

View File

@@ -78,7 +78,7 @@ export function addValueControlWidget(
_values?: unknown,
widgetName?: string,
inputData?: InputSpec
): IWidget {
): IComboWidget {
let name = inputData?.[1]?.control_after_generate
if (typeof name !== 'string') {
name = widgetName
@@ -102,7 +102,7 @@ export function addValueControlWidgets(
defaultValue?: string,
options?: Record<string, any>,
inputData?: InputSpec
): IWidget[] {
): [IComboWidget, ...IStringWidget[]] {
if (!defaultValue) defaultValue = 'randomize'
if (!options) options = {}
@@ -118,7 +118,6 @@ export function addValueControlWidgets(
return name
}
const widgets: IWidget[] = []
const valueControl = node.addWidget(
'combo',
getName('control_after_generate', 'controlAfterGenerateName'),
@@ -135,12 +134,12 @@ export function addValueControlWidgets(
// @ts-ignore index with symbol
valueControl[IS_CONTROL_WIDGET] = true
updateControlWidgetLabel(valueControl)
widgets.push(valueControl)
const widgets: [IComboWidget, ...IStringWidget[]] = [valueControl]
const isCombo = targetWidget.type === 'combo'
let comboFilter: IStringWidget
if (isCombo && valueControl.options.values) {
// @ts-ignore Combo widget values may be a dictionary or legacy function type
// @ts-expect-error Combo widget values may be a dictionary or legacy function type
valueControl.options.values.push('increment-wrap')
}
if (isCombo && options.addFilterList !== false) {
@@ -184,7 +183,7 @@ export function addValueControlWidgets(
const lower = filter.toLocaleLowerCase()
check = (item: string) => item.toLocaleLowerCase().includes(lower)
}
// @ts-ignore Combo widget values may be a dictionary or legacy function type
// @ts-expect-error Combo widget values may be a dictionary or legacy function type
values = values.filter((item: string) => check(item))
if (!values.length && targetWidget.options.values?.length) {
console.warn(
@@ -211,17 +210,17 @@ export function addValueControlWidgets(
current_index -= 1
break
case 'randomize':
// @ts-ignore Combo widget values may be a dictionary or legacy function type
// @ts-expect-error Combo widget values may be a dictionary or legacy function type
current_index = Math.floor(Math.random() * current_length)
break
default:
break
}
current_index = Math.max(0, current_index)
// @ts-ignore Combo widget values may be a dictionary or legacy function type
// @ts-expect-error Combo widget values may be a dictionary or legacy function type
current_index = Math.min(current_length - 1, current_index)
if (current_index >= 0) {
// @ts-ignore Combo widget values may be a dictionary or legacy function type
// @ts-expect-error Combo widget values may be a dictionary or legacy function type
let value = values[current_index]
targetWidget.value = value
targetWidget.callback?.(value)

View File

@@ -35,10 +35,7 @@ declare module '@comfyorg/litegraph/dist/types/widgets' {
onRemove?: () => void
beforeQueued?: () => unknown
afterQueued?: () => unknown
serializeValue?: (
node: LGraphNode,
index: number
) => Promise<unknown> | unknown
serializeValue?(node: LGraphNode, index: number): Promise<unknown> | unknown
/**
* Refreshes the widget's value or options from its remote source.
@@ -66,6 +63,14 @@ declare module '@comfyorg/litegraph' {
new (): T
}
interface TextWidget {
dynamicPrompts?: boolean
}
interface BaseWidget {
serializeValue?(node: LGraphNode, index: number): Promise<unknown> | unknown
}
interface LGraphNode {
constructor: LGraphNodeConstructor

View File

@@ -35,11 +35,9 @@ export function isAudioNode(node: LGraphNode | undefined): boolean {
export function addToComboValues(widget: IComboWidget, value: string) {
if (!widget.options) widget.options = { values: [] }
if (!widget.options.values) widget.options.values = []
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore Combo widget values may be a dictionary or legacy function type
// @ts-expect-error Combo widget values may be a dictionary or legacy function type
if (!widget.options.values.includes(value)) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore Combo widget values may be a dictionary or legacy function type
// @ts-expect-error Combo widget values may be a dictionary or legacy function type
widget.options.values.push(value)
}
}