fix: prevent promoted textarea from being disabled on SubgraphNode

PromotedWidgetSlot now overrides computedDisabled to always return false, since the slot should remain interactive even though its associated input is internally linked.

PromotedDomWidgetAdapter proxy also intercepts computedDisabled to prevent the DOM widget from inheriting the interior widget's disabled state.

Amp-Thread-ID: https://ampcode.com/threads/T-019c5575-c485-767b-a7d1-adccefa4f60e
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-02-12 21:30:44 -08:00
parent 6049332d4e
commit 6073ba35a8
3 changed files with 13 additions and 13 deletions

View File

@@ -45,6 +45,7 @@ export function createPromotedDomWidgetAdapter<V extends object | string>(
return hostNode
case 'promoted':
case 'serialize':
case 'computedDisabled':
return false
case 'innerWidget':
return target

View File

@@ -551,22 +551,11 @@ describe('PromotedWidgetSlot', () => {
expect(slot._displayValue).toBe('Disconnected')
})
it('returns empty string when computedDisabled', () => {
const store = useWidgetValueStore()
store.registerWidget({
nodeId: '5',
name: 'seed',
type: 'number',
value: 42,
options: {},
disabled: false,
promoted: true
})
it('is never computedDisabled (promoted slots stay interactive)', () => {
const subNode = createMockSubgraphNode()
const slot = new PromotedWidgetSlot(subNode, '5', 'seed')
slot.computedDisabled = true
expect(slot._displayValue).toBe('')
expect(slot.computedDisabled).toBe(false)
})
})
})

View File

@@ -78,6 +78,16 @@ export class PromotedWidgetSlot extends BaseWidget<IBaseWidget> {
enumerable: true
})
// The SubgraphNode's input slots are internally linked, which causes
// `updateComputedDisabled()` to set `computedDisabled = true` on all
// matching widgets. The promoted slot should always remain interactive.
Object.defineProperty(this, 'computedDisabled', {
get: () => false,
set: () => {},
configurable: true,
enumerable: true
})
this.callback = (value, canvas, _node, pos, e) => {
const resolved = this.resolve()
if (!resolved) return