mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-06 16:10:09 +00:00
fix: viewport overflow in manager
This commit is contained in:
@@ -27,9 +27,12 @@
|
||||
|
||||
<Popover
|
||||
ref="popoverRef"
|
||||
append-to="body"
|
||||
:pt="{
|
||||
root: { class: 'no-arrow-popover' },
|
||||
content: { class: 'p-0 shadow-lg' }
|
||||
}"
|
||||
@show="fixPopoverIntoViewport"
|
||||
>
|
||||
<PackVersionSelectorPopover
|
||||
:installed-version="installedVersion"
|
||||
@@ -44,7 +47,7 @@
|
||||
<script setup lang="ts">
|
||||
import Popover from 'primevue/popover'
|
||||
import { valid as validSemver } from 'semver'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
|
||||
import type { components } from '@/types/comfyRegistryTypes'
|
||||
import PackVersionSelectorPopover from '@/workbench/extensions/manager/components/manager/PackVersionSelectorPopover.vue'
|
||||
@@ -65,6 +68,7 @@ const {
|
||||
|
||||
const { isUpdateAvailable } = usePackUpdateStatus(() => nodePack)
|
||||
const popoverRef = ref()
|
||||
const lastTargetEl = ref<HTMLElement | null>(null)
|
||||
|
||||
const managerStore = useComfyManagerStore()
|
||||
|
||||
@@ -87,6 +91,7 @@ const installedVersion = computed(() => {
|
||||
})
|
||||
|
||||
const toggleVersionSelector = (event: Event) => {
|
||||
lastTargetEl.value = event.currentTarget as HTMLElement
|
||||
popoverRef.value.toggle(event)
|
||||
}
|
||||
|
||||
@@ -94,6 +99,59 @@ const closeVersionSelector = () => {
|
||||
popoverRef.value.hide()
|
||||
}
|
||||
|
||||
const fixPopoverIntoViewport = async () => {
|
||||
await nextTick()
|
||||
|
||||
const popoverEl: HTMLElement | undefined =
|
||||
popoverRef.value?.container ?? popoverRef.value?.$el
|
||||
const targetEl = lastTargetEl.value
|
||||
if (!popoverEl || !targetEl) return
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
const boundaryEl =
|
||||
targetEl.closest('.p-dialog') ??
|
||||
targetEl.closest('.manager-dialog') ??
|
||||
targetEl.closest('[role="dialog"]') ??
|
||||
document.documentElement
|
||||
|
||||
const boundary = boundaryEl.getBoundingClientRect()
|
||||
const targetRect = targetEl.getBoundingClientRect()
|
||||
|
||||
popoverEl.style.transform = ''
|
||||
|
||||
const rect = popoverEl.getBoundingClientRect()
|
||||
|
||||
const M = 8 // keep away from dialog edge
|
||||
const GAP = 10
|
||||
|
||||
const spaceBelow = boundary.bottom - targetRect.bottom
|
||||
const spaceAbove = targetRect.top - boundary.top
|
||||
|
||||
// Decide side (below by default; flip to above if needed)
|
||||
const placeAbove = spaceBelow < rect.height + GAP && spaceAbove > spaceBelow
|
||||
|
||||
// 1) Top with a GAP (prevents covering trigger)
|
||||
let top = placeAbove
|
||||
? targetRect.top - rect.height - GAP
|
||||
: targetRect.bottom + GAP
|
||||
|
||||
// Clamp vertically
|
||||
top = Math.min(top, boundary.bottom - rect.height - M)
|
||||
top = Math.max(top, boundary.top + M)
|
||||
|
||||
// 2) Left (align to trigger, then clamp)
|
||||
let left = targetRect.left
|
||||
left = Math.min(left, boundary.right - rect.width - M)
|
||||
left = Math.max(left, boundary.left + M)
|
||||
|
||||
// Apply position
|
||||
popoverEl.style.top = `${Math.round(top)}px`
|
||||
popoverEl.style.left = `${Math.round(left)}px`
|
||||
|
||||
popoverEl.classList.toggle('p-popover-flipped', placeAbove)
|
||||
})
|
||||
}
|
||||
|
||||
// If the card is unselected, automatically close the version selector popover
|
||||
watch(
|
||||
() => isSelected,
|
||||
@@ -104,3 +162,11 @@ watch(
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.no-arrow-popover::before,
|
||||
.no-arrow-popover::after,
|
||||
.no-arrow-popover .p-popover-arrow {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user