Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/renderer/core/layout/slots/useDomSlotRegistration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,23 @@ const cleanupFunctions = new WeakMap<
}
>()

export function useDomSlotRegistration(
nodeId: string,
slotIndex: number,
isInput: boolean,
interface SlotRegistrationOptions {
nodeId: string
slotIndex: number
isInput: boolean
element: Ref<HTMLElement | null>
transform?: TransformState
) {
}

export function useDomSlotRegistration(options: SlotRegistrationOptions) {
const { nodeId, slotIndex, isInput, element: elRef, transform } = options

// Early return if no nodeId
if (!nodeId || nodeId === '') {
return {
slotElRef: ref<HTMLElement | null>(null),
remeasure: () => {}
}
}

const elRef = ref<HTMLElement | null>(null)
const slotKey = getSlotKey(nodeId, slotIndex, isInput)
// Track if this component is mounted
const componentToken = {}
Expand Down Expand Up @@ -221,7 +223,6 @@ export function useDomSlotRegistration(
})

return {
slotElRef: elRef,
// Expose for forced remeasure on structural changes
remeasure: () => scheduleMeasurement(measureAndCacheOffset)
}
Expand Down
47 changes: 30 additions & 17 deletions src/renderer/extensions/vueNodes/components/InputSlot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,25 @@
<div v-if="renderError" class="node-error p-1 text-red-500 text-xs">⚠️</div>
<div
v-else
class="lg-slot lg-slot--input flex items-center cursor-crosshair group"
class="lg-slot lg-slot--input flex items-center cursor-crosshair group rounded-r-lg"
:class="{
'opacity-70': readonly,
'lg-slot--connected': connected,
'lg-slot--compatible': compatible,
'lg-slot--dot-only': dotOnly,
'pr-2 hover:bg-black/5': !dotOnly
'pr-6 hover:bg-black/5 hover:dark:bg-white/5': !dotOnly
}"
:style="{
height: slotHeight + 'px'
}"
@pointerdown="handleClick"
>
<!-- Connection Dot -->
<div class="w-5 h-5 flex items-center justify-center group/slot">
<div
ref="slotElRef"
class="w-2 h-2 rounded-full bg-white transition-all duration-150 group-hover/slot:w-2.5 group-hover/slot:h-2.5 group-hover/slot:border-2 group-hover/slot:border-white"
:style="{
backgroundColor: slotColor
}"
/>
</div>
<SlotConnectionDot
ref="connectionDotRef"
:color="slotColor"
class="-translate-x-1/2"
/>

<!-- Slot Name -->
<span
Expand All @@ -37,7 +33,7 @@
</template>

<script setup lang="ts">
import { computed, inject, onErrorCaptured, ref } from 'vue'
import { type Ref, computed, inject, onErrorCaptured, ref, watch } from 'vue'

import { useErrorHandling } from '@/composables/useErrorHandling'
import { getSlotColor } from '@/constants/slotColors'
Expand All @@ -52,6 +48,8 @@ import {
useDomSlotRegistration
} from '@/renderer/core/layout/slots/useDomSlotRegistration'

import SlotConnectionDot from './SlotConnectionDot.vue'

interface InputSlotProps {
node?: LGraphNode
nodeId?: string
Expand Down Expand Up @@ -97,10 +95,25 @@ const transformState = inject<TransformState | undefined>(
undefined
)

const { slotElRef } = useDomSlotRegistration(
props.nodeId ?? '',
props.index,
true,
transformState
const connectionDotRef = ref<{ slotElRef: Ref<HTMLElement> }>()
const slotElRef = ref<HTMLElement | null>(null)

// Watch for connection dot ref changes and sync the element ref
watch(
connectionDotRef,
(newValue) => {
if (newValue?.slotElRef) {
slotElRef.value = newValue.slotElRef.value
}
},
{ immediate: true }
)

useDomSlotRegistration({
nodeId: props.nodeId ?? '',
slotIndex: props.index,
isInput: true,
element: slotElRef,
transform: transformState
})
</script>
10 changes: 5 additions & 5 deletions src/renderer/extensions/vueNodes/components/LGraphNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
cn(
'bg-white dark-theme:bg-[#15161A]',
'min-w-[445px]',
'lg-node absolute border-2 border-solid rounded-2xl',
'lg-node absolute border border-solid rounded-2xl',
{
'border-blue-500 ring-2 ring-blue-300': selected,
'border-[#e1ded5] dark-theme:border-[#292A30]': !selected,
Expand All @@ -36,8 +36,8 @@
>
<div class="flex items-center">
<template v-if="isCollapsed">
<MultiSlotPoint class="absolute left-0 -translate-x-1/2" />
<MultiSlotPoint class="absolute right-0 translate-x-1/2" />
<SlotConnectionDot multi class="absolute left-0 -translate-x-1/2" />
<SlotConnectionDot multi class="absolute right-0 translate-x-1/2" />
</template>
<!-- Header only updates on title/color changes -->
<NodeHeader
Expand Down Expand Up @@ -118,11 +118,11 @@ import { useNodeLayout } from '@/renderer/extensions/vueNodes/layout/useNodeLayo
import { LODLevel, useLOD } from '@/renderer/extensions/vueNodes/lod/useLOD'
import { cn } from '@/utils/tailwindUtil'

import MultiSlotPoint from './MultiSlotPoint.vue'
import NodeContent from './NodeContent.vue'
import NodeHeader from './NodeHeader.vue'
import NodeSlots from './NodeSlots.vue'
import NodeWidgets from './NodeWidgets.vue'
import SlotConnectionDot from './SlotConnectionDot.vue'

// Extended props for main node component
interface LGraphNodeProps {
Expand Down Expand Up @@ -209,7 +209,7 @@ const hasCustomContent = computed(() => {
})

// Computed classes and conditions for better reusability
const separatorClasses = 'bg-[#e1ded5] dark-theme:bg-[#292A30] h-[1px] mx-4'
const separatorClasses = 'bg-[#e1ded5] dark-theme:bg-[#292A30] h-[1px] mx-0'

// Common condition computations to avoid repetition
const shouldShowWidgets = computed(
Expand Down
12 changes: 0 additions & 12 deletions src/renderer/extensions/vueNodes/components/MultiSlotPoint.vue

This file was deleted.

4 changes: 2 additions & 2 deletions src/renderer/extensions/vueNodes/components/NodeSlots.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
⚠️ Node Slots Error
</div>
<div v-else class="lg-node-slots flex justify-between">
<div v-if="filteredInputs.length" class="flex flex-col">
<div v-if="filteredInputs.length" class="flex flex-col gap-1">
<InputSlot
v-for="(input, index) in filteredInputs"
:key="`input-${index}`"
Expand All @@ -18,7 +18,7 @@
/>
</div>

<div v-if="filteredOutputs.length" class="flex flex-col ml-auto">
<div v-if="filteredOutputs.length" class="flex flex-col gap-1 ml-auto">
<OutputSlot
v-for="(output, index) in filteredOutputs"
:key="`output-${index}`"
Expand Down
47 changes: 30 additions & 17 deletions src/renderer/extensions/vueNodes/components/OutputSlot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
<div v-if="renderError" class="node-error p-1 text-red-500 text-xs">⚠️</div>
<div
v-else
class="lg-slot lg-slot--output flex items-center cursor-crosshair justify-end group"
class="lg-slot lg-slot--output flex items-center cursor-crosshair justify-end group rounded-l-lg"
:class="{
'opacity-70': readonly,
'lg-slot--connected': connected,
'lg-slot--compatible': compatible,
'lg-slot--dot-only': dotOnly,
'pl-2 hover:bg-black/5': !dotOnly,
'pl-6 hover:bg-black/5 hover:dark:bg-white/5': !dotOnly,
'justify-center': dotOnly
}"
:style="{
Expand All @@ -25,20 +25,16 @@
</span>

<!-- Connection Dot -->
<div class="w-5 h-5 flex items-center justify-center group/slot">
<div
ref="slotElRef"
class="w-2 h-2 rounded-full bg-white transition-all duration-150 group-hover/slot:w-2.5 group-hover/slot:h-2.5 group-hover/slot:border-2 group-hover/slot:border-white"
:style="{
backgroundColor: slotColor
}"
/>
</div>
<SlotConnectionDot
ref="connectionDotRef"
:color="slotColor"
class="translate-x-1/2"
/>
</div>
</template>

<script setup lang="ts">
import { computed, inject, onErrorCaptured, ref } from 'vue'
import { type Ref, computed, inject, onErrorCaptured, ref, watch } from 'vue'

import { useErrorHandling } from '@/composables/useErrorHandling'
import { getSlotColor } from '@/constants/slotColors'
Expand All @@ -50,6 +46,8 @@ import {
useDomSlotRegistration
} from '@/renderer/core/layout/slots/useDomSlotRegistration'

import SlotConnectionDot from './SlotConnectionDot.vue'

interface OutputSlotProps {
node?: LGraphNode
nodeId?: string
Expand Down Expand Up @@ -96,10 +94,25 @@ const transformState = inject<TransformState | undefined>(
undefined
)

const { slotElRef } = useDomSlotRegistration(
props.nodeId ?? '',
props.index,
false,
transformState
const connectionDotRef = ref<{ slotElRef: Ref<HTMLElement> }>()
const slotElRef = ref<HTMLElement | null>(null)

// Watch for connection dot ref changes and sync the element ref
watch(
connectionDotRef,
(newValue) => {
if (newValue?.slotElRef) {
slotElRef.value = newValue.slotElRef.value
}
},
{ immediate: true }
)

useDomSlotRegistration({
nodeId: props.nodeId ?? '',
slotIndex: props.index,
isInput: false,
element: slotElRef,
transform: transformState
})
</script>
38 changes: 38 additions & 0 deletions src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script setup lang="ts">
import { ref } from 'vue'

import { type ClassValue, cn } from '@/utils/tailwindUtil'

const props = defineProps<{
color?: string
multi?: boolean
class?: ClassValue
}>()

const slotElRef = ref<HTMLElement>()

defineExpose({
slotElRef
})
</script>

<template>
<div
:class="
cn('size-6 flex items-center justify-center group/slot', props.class)
"
>
<div
ref="slotElRef"
:style="{ backgroundColor: color }"
:class="
cn(
'bg-[#5B5E7D] rounded-full',
'transition-all duration-150',
'cursor-crosshair group-hover/slot:border-2 group-hover/slot:border-white group-hover/slot:scale-125',
multi ? 'w-3 h-6' : 'size-3'
)
"
/>
</div>
</template>
2 changes: 2 additions & 0 deletions src/utils/tailwindUtil.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import clsx, { type ClassArray } from 'clsx'
import { twMerge } from 'tailwind-merge'

export type { ClassValue, ClassArray, ClassDictionary } from 'clsx'

export function cn(...inputs: ClassArray) {
return twMerge(clsx(inputs))
}