Files
ComfyUI_frontend/src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue
AustinMroz 4a5e7c8bcb Further dynamic input fixes (#8026)
- Fix deserialization of matchtype inputs spawned by autogrow.
- Rotate multitype slot indicators to align with design changes.
- Fix several instance of incorrect group matching
- MatchType reactively updates input type in vue
- Support the "hollow circle" optional input indicator in vue
- Custom combo sends index of selection to backend

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8026-Further-dynamic-input-fixes-2e76d73d3650819680fef327a94f4294)
by [Unito](https://www.unito.io)
2026-01-22 00:02:49 -08:00

128 lines
3.4 KiB
Vue

<script setup lang="ts">
import { computed, useTemplateRef } from 'vue'
import { getSlotColor } from '@/constants/slotColors'
import type { INodeSlot } from '@/lib/litegraph/src/litegraph'
import { cn } from '@/utils/tailwindUtil'
import type { ClassValue } from '@/utils/tailwindUtil'
const props = defineProps<{
slotData?: INodeSlot
class?: ClassValue
hasError?: boolean
multi?: boolean
}>()
const clipPath = computed(() => {
switch (props.slotData?.shape) {
case 6:
return 'url(#square)'
case 7:
return 'url(#hollow)'
default:
return undefined
}
})
const slotElRef = useTemplateRef('slot-el')
const types = computed(() => {
if (props.hasError) return ['var(--color-error)']
//TODO Support connected/disconnected colors?
if (!props.slotData) return [getSlotColor()]
if (props.slotData.type === '*') return ['']
const typesSet = new Set(
`${props.slotData.type}`.split(',').map(getSlotColor)
)
return [...typesSet].slice(0, 3)
})
defineExpose({
slotElRef
})
const slotClass = computed(() =>
cn(
'bg-slate-300 rounded-full slot-dot',
'transition-all duration-150',
'border border-solid border-node-component-slot-dot-outline',
props.multi
? 'w-3 h-6'
: 'size-3 cursor-crosshair group-hover/slot:[--node-component-slot-dot-outline-opacity-mult:5] group-hover/slot:scale-125'
)
)
</script>
<template>
<div
:class="
cn(
'after:absolute after:inset-y-0 after:w-5/2 relative size-6 flex items-center justify-center group/slot',
props.class
)
"
>
<div
v-if="types.length === 1 && slotData?.shape == undefined"
ref="slot-el"
:style="{ backgroundColor: types.length === 1 ? types[0] : undefined }"
:class="slotClass"
/>
<svg
v-else
ref="slot-el"
:class="slotClass"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<clipPath id="square">
<rect x="20" y="20" width="60" height="60" />
</clipPath>
<clipPath id="hollow">
<path
d="M-50 50
A100 100 0 0 1 150 50
A100 100 0 0 1 -50 50
M30 50
A20 20 0 0 0 70 50
A20 20 0 0 0 30 50"
/>
</clipPath>
</defs>
<circle
v-if="types.length === 1"
:clip-path
cx="50"
cy="50"
r="50"
:fill="types[0]"
/>
<g v-else-if="types.length === 2" :clip-path stroke-width="4">
<path d="M0 50 A 50 50 0 0 1 100 50" :fill="types[0]" />
<path d="M100 50 A 50 50 0 0 1 0 50" :fill="types[1]" />
<path d="M0 50L100 50" stroke="var(--inner-stroke, black)" />
<path
d="M50 2A48 48 0 0 1 50 98A48 48 0 0 1 50 2"
fill="transparent"
stroke="var(--outer-stroke, transparent)"
/>
</g>
<g v-else :clip-path stroke-width="4">
<path d="M0 50A50 50 0 0 0 75 93L50 50" :fill="types[0]" />
<path d="M75 93A50 50 0 0 0 75 7L50 50" :fill="types[1]" />
<path d="M75 7A50 50 0 0 0 0 50L50 50" :fill="types[2]" />
<path
d="M50 50L0 50M50 50L75 93M50 50L75 7"
stroke="var(--inner-stroke, black)"
/>
<path
d="M50 2A48 48 0 0 1 50 98A48 48 0 0 1 50 2"
fill="transparent"
stroke="var(--outer-stroke, transparent)"
/>
</g>
</svg>
</div>
</template>