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
2 changes: 0 additions & 2 deletions src/components/graph/GraphCanvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
canvasStore.canvas to be initialized. -->
<template v-if="comfyAppReady">
<TitleEditor />
<!-- SelectionToolbox is now standalone, no parent overlay needed -->
<!-- LiteGraph already draws selection borders in canvas -->
<SelectionToolbox v-if="selectionToolboxEnabled" />
<DomWidgets />
</template>
Expand Down
90 changes: 50 additions & 40 deletions src/components/graph/SelectionToolbox.vue
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
<template>
<Panel
v-show="visible"
class="selection-toolbox rounded-lg z-40"
:class="{ 'animate-slide-up': shouldAnimate }"
:style="style"
:pt="{
header: 'hidden',
content: 'p-0 flex flex-row'
}"
@wheel="canvasInteractions.handleWheel"
>
<ExecuteButton />
<ColorPickerButton />
<BypassButton />
<PinButton />
<Load3DViewerButton />
<MaskEditorButton />
<ConvertToSubgraphButton />
<DeleteButton />
<RefreshSelectionButton />
<ExtensionCommandButton
v-for="command in extensionToolboxCommands"
:key="command.id"
:command="command"
/>
<HelpButton />
</Panel>
<Transition name="slide-up">
<Panel
v-show="visible"
class="selection-toolbox fixed left-0 top-0 rounded-lg z-40"
:style="style"
:pt="{
header: 'hidden',
content: 'p-0 flex flex-row'
}"
@wheel="canvasInteractions.handleWheel"
>
<ExecuteButton />
<ColorPickerButton />
<BypassButton />
<PinButton />
<Load3DViewerButton />
<MaskEditorButton />
<ConvertToSubgraphButton />
<DeleteButton />
<RefreshSelectionButton />
<ExtensionCommandButton
v-for="command in extensionToolboxCommands"
:key="command.id"
:command="command"
/>
<HelpButton />
</Panel>
</Transition>
</template>

<script setup lang="ts">
import Panel from 'primevue/panel'
import { computed, ref, watch } from 'vue'
import { computed } from 'vue'

import BypassButton from '@/components/graph/selectionToolbox/BypassButton.vue'
import ColorPickerButton from '@/components/graph/selectionToolbox/ColorPickerButton.vue'
Expand All @@ -44,7 +45,6 @@ import MaskEditorButton from '@/components/graph/selectionToolbox/MaskEditorButt
import PinButton from '@/components/graph/selectionToolbox/PinButton.vue'
import RefreshSelectionButton from '@/components/graph/selectionToolbox/RefreshSelectionButton.vue'
import { useSelectionToolboxPosition } from '@/composables/canvas/useSelectionToolboxPosition'
import { useRetriggerableAnimation } from '@/composables/element/useRetriggerableAnimation'
import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions'
import { useExtensionService } from '@/services/extensionService'
import { type ComfyCommandImpl, useCommandStore } from '@/stores/commandStore'
Expand All @@ -55,19 +55,8 @@ const canvasStore = useCanvasStore()
const extensionService = useExtensionService()
const canvasInteractions = useCanvasInteractions()

// Get position and visibility from the new composable
const { style, visible } = useSelectionToolboxPosition()

// Track selection changes for animation
const selectionUpdateCount = ref(0)
watch(visible, () => {
selectionUpdateCount.value++
})

const { shouldAnimate } = useRetriggerableAnimation(selectionUpdateCount, {
animateOnMount: true
})

const extensionToolboxCommands = computed<ComfyCommandImpl[]>(() => {
const commandIds = new Set<string>(
canvasStore.selectedItems
Expand All @@ -84,3 +73,24 @@ const extensionToolboxCommands = computed<ComfyCommandImpl[]>(() => {
.filter((command): command is ComfyCommandImpl => command !== undefined)
})
</script>

<style scoped>
.selection-toolbox {
transform: translateY(-120%);
}

.slide-up-enter-active,
.slide-up-leave-active {
transition: all 0.3s ease-out;
}

.slide-up-enter-from {
transform: translateY(-100%);
opacity: 0;
}

.slide-up-leave-to {
transform: translateY(-100%);
opacity: 0;
}
</style>
47 changes: 14 additions & 33 deletions src/composables/canvas/useSelectionToolboxPosition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,9 @@ export function useSelectionToolboxPosition() {
// World position of selection center
const worldPosition = ref({ x: 0, y: 0, width: 0, height: 0 })

// Visibility state
const visible = ref(false)

// Style for toolbox positioning
const style = ref<CSSProperties>({
position: 'fixed',
left: '0',
top: '0',
visibility: 'hidden'
})
const style = ref<CSSProperties>({})

/**
* Update position based on selection
Expand All @@ -37,33 +30,26 @@ export function useSelectionToolboxPosition() {

if (!selectableItems.size) {
visible.value = false
style.value = {
...style.value,
visibility: 'hidden'
}
return
}

visible.value = true
const bounds = createBounds(selectableItems)

if (bounds) {
// Store world coordinates
// bounds = [x, y, width, height]
worldPosition.value = {
x: bounds[0] + bounds[2] / 2, // Center X of bounds
y: bounds[1], // Top Y of bounds
width: bounds[2],
height: bounds[3]
}
if (!bounds) {
return
}

updateTransform()
worldPosition.value = {
x: bounds[0] + bounds[2] / 2,
y: bounds[1],
width: bounds[2],
height: bounds[3]
}

updateTransform()
}

/**
* Update transform based on canvas state
*/
const updateTransform = () => {
if (!visible.value) return

Expand All @@ -77,16 +63,11 @@ export function useSelectionToolboxPosition() {
const screenY = (worldPosition.value.y + offset[1]) * scale + canvasRect.top

// Position the toolbox above the selection bounds
// The -50% centers it horizontally, and we subtract pixels to position above
const toolboxOffset = 45 // Pixels above the selection
// The -50% centers it horizontally,
const toolboxOffset = 45

style.value = {
position: 'fixed',
left: '0',
top: '0',
transform: `translate(${screenX}px, ${screenY - toolboxOffset}px) translateX(-50%)`,
visibility: 'visible',
willChange: 'transform'
transform: `translate(${screenX}px, ${screenY - toolboxOffset}px) translateX(-50%)`
}
}

Expand Down
Loading