refactor: pass single host instead of parents array to widget rows

The promoted-widget side panel only ever has one host SubgraphNode, so
collapse the parents: SubgraphNode[] prop to host?: SubgraphNode across
SectionWidgets/WidgetItem/WidgetActions and drop the [node] wrapper in
TabSubgraphInputs.

Amp-Thread-ID: https://ampcode.com/threads/T-019f2964-7a96-7579-8883-caeb3b2b07da
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
DrJKL
2026-07-03 16:46:31 -07:00
parent ef79a400d3
commit 8bb774f7ca
6 changed files with 23 additions and 30 deletions

View File

@@ -43,12 +43,12 @@ const {
isDraggable = false,
hiddenFavoriteIndicator = false,
showNodeName = false,
parents = [],
host,
enableEmptyState = false,
tooltip
} = defineProps<{
label?: string
parents?: SubgraphNode[]
host?: SubgraphNode
node?: LGraphNode
widgets: { widget: IBaseWidget; node: LGraphNode }[]
showLocateButton?: boolean
@@ -377,7 +377,7 @@ defineExpose({
:is-draggable="isDraggable"
:hidden-favorite-indicator="hiddenFavoriteIndicator"
:show-node-name="showNodeName"
:parents="parents"
:host="host"
@update:widget-value="handleWidgetValueUpdate(node, widget, $event)"
@reset-to-default="handleWidgetReset(node, widget, $event)"
/>

View File

@@ -33,7 +33,7 @@ const captured: { rows: { node: LGraphNode; widget: IBaseWidget }[] } = {
}
const SectionWidgetsStub = {
props: ['widgets', 'node', 'parents'],
props: ['widgets', 'node', 'host'],
setup(props: Record<string, unknown>) {
captured.rows = props.widgets as {
node: LGraphNode

View File

@@ -88,8 +88,6 @@ const advancedInputsWidgets = computed((): NodeWidgetsList => {
)
})
const parents = computed<SubgraphNode[]>(() => [node])
const searchedWidgetsList = shallowRef<NodeWidgetsList>(widgetsList.value)
const isSearching = ref(false)
@@ -140,7 +138,7 @@ const label = computed(() => {
:collapse="firstSectionCollapsed && !isSearching"
:node
:label
:parents
:host="node"
:widgets="searchedWidgetsList"
:is-draggable="!isSearching"
:enable-empty-state="isSearching"
@@ -164,7 +162,7 @@ const label = computed(() => {
ref="advancedInputsSectionRef"
v-model:collapse="advancedInputsCollapsed"
:label="t('rightSidePanel.advancedInputs')"
:parents="parents"
:host="node"
:widgets="advancedInputsWidgets"
show-node-name
class="border-b border-interface-stroke"

View File

@@ -209,19 +209,19 @@ describe('WidgetActions', () => {
expect(onResetToDefault).toHaveBeenCalledWith('option1')
})
it('promotes the widget when "Show input" is clicked on a node with parents', async () => {
it('promotes the widget into the host when "Show input" is clicked', async () => {
const widget = createMockWidget()
const node = createMockNode()
const parents = [fromAny<SubgraphNode, unknown>({ id: 2 })]
const host = fromAny<SubgraphNode, unknown>({ id: 2 })
const { user } = renderWidgetActions(widget, node, { parents })
const { user } = renderWidgetActions(widget, node, { host })
await user.click(screen.getByRole('button', { name: /Show input/ }))
expect(promoteWidget).toHaveBeenCalledWith(node, widget, parents)
expect(promoteWidget).toHaveBeenCalledWith(node, widget, [host])
})
it('does not offer "Show input" without parents', () => {
it('does not offer "Show input" without a host', () => {
renderWidgetActions(createMockWidget(), createMockNode())
expect(
@@ -238,9 +238,9 @@ describe('WidgetActions', () => {
isSubgraphNode: () => true,
getSlotFromWidget: () => ({ widgetId: 'graph-test:1:test_widget' })
})
const parents = [fromAny<SubgraphNode, unknown>({ id: 2 })]
const host = fromAny<SubgraphNode, unknown>({ id: 2 })
renderWidgetActions(widget, node, { parents })
renderWidgetActions(widget, node, { host })
expect(
screen.queryByRole('button', { name: /Show input/ })

View File

@@ -16,14 +16,10 @@ import { useFavoritedWidgetsStore } from '@/stores/workspace/favoritedWidgetsSto
import { getWidgetDefaultValue, promptWidgetLabel } from '@/utils/widgetUtil'
import type { WidgetValue } from '@/utils/widgetUtil'
const {
widget,
node,
parents = []
} = defineProps<{
const { widget, node, host } = defineProps<{
widget: IBaseWidget
node: LGraphNode
parents?: SubgraphNode[]
host?: SubgraphNode
}>()
const emit = defineEmits<{
@@ -36,12 +32,11 @@ const favoritedWidgetsStore = useFavoritedWidgetsStore()
const nodeDefStore = useNodeDefStore()
const { t } = useI18n()
const hasParents = computed(() => parents?.length > 0)
const isLinked = computed(() => {
if (!node.isSubgraphNode()) return false
return inputForWidget(node, widget)?.widgetId != null
})
const canShowInput = computed(() => hasParents.value && !isLinked.value)
const canShowInput = computed(() => host != null && !isLinked.value)
const isFavorited = computed(() =>
favoritedWidgetsStore.isFavorited(node, widget.name)
)
@@ -72,8 +67,8 @@ async function handleRename() {
}
function handleShowInput() {
if (!parents?.length) return
promoteWidget(node, widget, parents)
if (!host) return
promoteWidget(node, widget, [host])
}
function handleToggleFavorite() {

View File

@@ -40,7 +40,7 @@ const {
hiddenFavoriteIndicator = false,
hiddenWidgetActions = false,
showNodeName = false,
parents = []
host
} = defineProps<{
widget: IBaseWidget
node: LGraphNode
@@ -48,7 +48,7 @@ const {
hiddenFavoriteIndicator?: boolean
hiddenWidgetActions?: boolean
showNodeName?: boolean
parents?: SubgraphNode[]
host?: SubgraphNode
}>()
const emit = defineEmits<{
@@ -113,7 +113,7 @@ const displayNodeName = computed((): string | null => {
})
})
const hasParents = computed(() => parents?.length > 0)
const hasHost = computed(() => host != null)
const widgetValue = computed({
get: () => widget.value,
@@ -175,7 +175,7 @@ const displayLabel = customRef((track, trigger) => {
/>
<span
v-if="(showNodeName || hasParents) && displayNodeName"
v-if="(showNodeName || hasHost) && displayNodeName"
class="mx-1 my-0 min-w-10 flex-1 truncate p-0 text-right text-xs text-muted-foreground"
>
{{ displayNodeName }}
@@ -188,7 +188,7 @@ const displayLabel = customRef((track, trigger) => {
v-model:label="displayLabel"
:widget="widget"
:node="node"
:parents="parents"
:host="host"
@reset-to-default="emit('resetToDefault', $event)"
/>
</div>