@@ -26,33 +26,38 @@ let toastTimer: ReturnType<typeof setTimeout> | undefined
2626const initX = ref (0 )
2727const initY = ref (0 )
2828
29- watch (
30- () => [props .matched , props .mouse ] as const ,
31- ([matched , mouse ]) => {
32- if (! matched || ! mouse )
33- return
34- initX .value = Math .max (PANEL_MARGIN , Math .min (mouse .x , window .innerWidth - PANEL_WIDTH - PANEL_MARGIN ))
35- initY .value = Math .max (PANEL_MARGIN , Math .min (mouse .y , window .innerHeight - PANEL_HEIGHT - PANEL_MARGIN ))
36- },
37- )
38-
3929const el = useTemplateRef <HTMLElement >(' el' )
4030const draggingEl = useTemplateRef <HTMLElement >(' draggingEl' )
4131
42- const { x, y, style, isDragging } = useDraggable (el , {
32+ const { x, y, style : panelStyle , isDragging } = useDraggable (el , {
4333 initialValue: {
4434 x: initX .value ,
4535 y: initY .value ,
4636 },
37+ preventDefault: true ,
38+ stopPropagation: true ,
4739 handle: draggingEl ,
4840})
4941
50- watch ([initX , initY ], () => {
51- if (! props .matched )
52- return
53- x .value = initX .value
54- y .value = initY .value
55- })
42+ const rect = computed (() => props .matched ?.rect || props .matched ?.el ?.getBoundingClientRect ())
43+
44+ watch (
45+ () => rect .value ,
46+ (rect ) => {
47+ if (! rect )
48+ return
49+ // Position panel below the element, or above if not enough space below
50+ const preferredX = rect .left
51+ const preferredY = rect .bottom + PANEL_MARGIN / 2
52+ const fitsBelow = preferredY + PANEL_HEIGHT + PANEL_MARGIN < window .innerHeight
53+ initX .value = Math .max (PANEL_MARGIN , Math .min (preferredX , window .innerWidth - PANEL_WIDTH - PANEL_MARGIN ))
54+ initY .value = fitsBelow
55+ ? Math .max (PANEL_MARGIN , preferredY )
56+ : Math .max (PANEL_MARGIN , rect .top - PANEL_HEIGHT - PANEL_MARGIN / 2 )
57+ x .value = initX .value
58+ y .value = initY .value
59+ },
60+ )
5661
5762const hasMoved = computed (() => x .value !== initX .value || y .value !== initY .value )
5863
@@ -171,7 +176,7 @@ function buildComponentTree(): string {
171176}
172177
173178async function copyAgentInfo() {
174- if (! props .matched )
179+ if (! rect . value || ! props .matched )
175180 return
176181
177182 try {
@@ -224,15 +229,14 @@ async function copyAgentInfo() {
224229
225230<template >
226231 <div
227- v-if =" props.matched"
232+ v-if =" rect && props.matched"
228233 ref =" el"
229234 class =" fixed relative z-9999999 w-400px flex flex-col of-hidden rounded-lg bg-glass text-sm color-base shadow-lg ring-1 ring-base backdrop-blur duration-200"
230- :style =" style "
235+ :style =" panelStyle "
231236 :class =" [
232237 isDragging ? 'transition-none' : 'transition-opacity',
233238 props.matched ? 'op100' : 'op0 pointer-events-none',
234239 ]"
235- v-bind =" $attrs"
236240 >
237241 <!-- <div
238242 class="pointer-events-none absolute inset-0 z-10 transition-opacity duration-300"
0 commit comments