diff --git a/src/scripts/domWidget.ts b/src/scripts/domWidget.ts index 38979bb81b..11c9c5d730 100644 --- a/src/scripts/domWidget.ts +++ b/src/scripts/domWidget.ts @@ -7,6 +7,7 @@ import { LegacyWidget, LiteGraph } from '@/lib/litegraph/src/litegraph' +import type { NodeId } from '@/lib/litegraph/src/litegraph' import type { IBaseWidget, IWidgetOptions @@ -14,6 +15,7 @@ import type { import type { InputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2' import { useDomWidgetStore } from '@/stores/domWidgetStore' import { usePromotionStore } from '@/stores/promotionStore' +import { useWidgetValueStore } from '@/stores/widgetValueStore' import { generateUUID } from '@/utils/formatUtil' export interface BaseDOMWidget< @@ -150,6 +152,18 @@ abstract class BaseDOMWidgetImpl this.callback?.(this.value) } + override setNodeId(nodeId: NodeId): void { + // Capture the DOM-resolved value before registration, since the base class + // registers _state.value which is undefined for DOM widgets (their value + // lives in the DOM element / options.getValue). + const resolvedValue = this.value + super.setNodeId(nodeId) + const graphId = this.node.graph?.rootGraph.id + if (!graphId) return + const state = useWidgetValueStore().getWidget(graphId, nodeId, this.name) + if (state) state.value = resolvedValue + } + get margin(): number { return this.options.margin ?? BaseDOMWidgetImpl.DEFAULT_MARGIN } diff --git a/src/scripts/domWidgetStore.test.ts b/src/scripts/domWidgetStore.test.ts new file mode 100644 index 0000000000..8cb75e4fb5 --- /dev/null +++ b/src/scripts/domWidgetStore.test.ts @@ -0,0 +1,48 @@ +import { createTestingPinia } from '@pinia/testing' +import { setActivePinia } from 'pinia' +import { beforeEach, describe, expect, it } from 'vitest' + +import { LGraph, LGraphNode } from '@/lib/litegraph/src/litegraph' +import { DOMWidgetImpl } from '@/scripts/domWidget' +import { useWidgetValueStore } from '@/stores/widgetValueStore' + +describe('DOMWidgetImpl store integration', () => { + let graph: LGraph + let node: LGraphNode + let store: ReturnType + + beforeEach(() => { + setActivePinia(createTestingPinia({ stubActions: false })) + store = useWidgetValueStore() + graph = new LGraph() + node = new LGraphNode('TestNode') + node.id = 1 + graph.add(node) + }) + + it('registers DOM-resolved value in store via setNodeId', () => { + const defaultValue = 'You are an expert image-generation engine.' + const element = document.createElement('textarea') + element.value = defaultValue + + const widget = new DOMWidgetImpl({ + node, + name: 'system_prompt', + type: 'customtext', + element, + options: { + getValue: () => element.value as string, + setValue: (v: string) => { + element.value = v + const state = store.getWidget(graph.id, node.id, 'system_prompt') + if (state) state.value = v + } + } + }) + + widget.setNodeId(node.id) + + const state = store.getWidget(graph.id, node.id, 'system_prompt') + expect(state?.value).toBe(defaultValue) + }) +})