@@ -44,6 +44,7 @@ import { onMounted, type PropType, ref, useAttrs, watch , type HTMLAttributes }
4444import { getFallbackId , type LinkableByIdProps ,type TailwindClassProp } from " ../shared/props.js"
4545
4646import { twMerge } from " ../../helpers/twMerge.js"
47+ import { castType } from " @alanscodelog/utils"
4748
4849const fallbackId = getFallbackId ()
4950// eslint-disable-next-line no-use-before-define
@@ -86,22 +87,33 @@ const getVeilBoundingRect = (el: HTMLElement): Omit<DOMRect, "toJSON"> => {
8687}
8788const recompute = (): void => {
8889 requestAnimationFrame (() => {
89- if (! buttonEl .value || ! popupEl .value || ! dialogEl .value ) {
90+ const allAreCenterScreen = props .preferredHorizontal [0 ] === " center-screen" && props .preferredVertical [0 ] === " center-screen"
91+ if ((! buttonEl .value && ! allAreCenterScreen ) || ! popupEl .value || ! dialogEl .value ) {
9092 pos .value = {} as any
9193 return
9294 }
9395 const finalPos: { x: number , y: number , maxWidth? : number , maxHeight? : number } = {} as any
9496
95- const el = buttonEl .value .getBoundingClientRect ()
97+ const el = buttonEl .value ? .getBoundingClientRect ()
9698 const veil = getVeilBoundingRect (props .useBackdrop ? dialogEl .value : document .body )
9799 const popup = popupEl .value .getBoundingClientRect ()
98100
99- const spaceLeft = (el .x + el .width ) - veil .x
100- const spaceRight = (veil .x + veil .width ) - el .x
101- const spaceLeftFromCenter = (el .x + (el .width / 2 )) - veil .x
102- const spaceRightFromCenter = (veil .x + veil .width ) - (el .x + (el .width / 2 ))
103- const spaceTop = el .y - veil .y
104- const spaceBottom = (veil .y + veil .height ) - (el .y + el .height )
101+ const space = {
102+ left: 0 ,
103+ right: 0 ,
104+ leftFromCenter: 0 ,
105+ rightFromCenter: 0 ,
106+ top: 0 ,
107+ bottom: 0 ,
108+ }
109+ if (el ) {
110+ space .left = (el .x + el .width ) - veil .x
111+ space .right = (veil .x + veil .width ) - (el .x + el .width )
112+ space .leftFromCenter = (el .x + (el .width / 2 )) - veil .x
113+ space .rightFromCenter = (veil .x + veil .width ) - (el .x + (el .width / 2 ))
114+ space .top = el .y - veil .y
115+ space .bottom = (veil .y + veil .height ) - (el .y + el .height )
116+ }
105117
106118 const { preferredHorizontal, preferredVertical } = props
107119 let maxWidth: number | undefined
@@ -119,29 +131,33 @@ const recompute = (): void => {
119131 }
120132 break
121133 case " center" :
122- if (spaceLeftFromCenter >= (popup .width / 2 ) &&
123- spaceRightFromCenter >= (popup .width / 2 )) {
134+ castType <DOMRect >(el )
135+ if (space .leftFromCenter >= (popup .width / 2 ) &&
136+ space .rightFromCenter >= (popup .width / 2 )) {
124137 finalPos .x = el .x + (el .width / 2 ) - (popup .width / 2 )
125138 break outerloop
126139 }
127140 // todo temp fix when it's too wide, will prefer left
128- if (((spaceRightFromCenter + spaceLeftFromCenter ) <= popup .width )) {
141+ if (((space . rightFromCenter + space . leftFromCenter ) <= popup .width )) {
129142 finalPos .x = 0
130143 break outerloop
131144 }
132145 break
133146 case " right" :
134- if (spaceRight >= popup .width ) {
147+ castType <DOMRect >(el )
148+ if (space .right >= popup .width ) {
135149 finalPos .x = el .x ; break outerloop
136150 }
137151 break
138152 case " left" :
139- if (spaceLeft >= popup .width ) {
153+ castType <DOMRect >(el )
154+ if (space .left >= popup .width ) {
140155 finalPos .x = (el .x + el .width ) - popup .width ; break outerloop
141156 }
142157 break
143158 case " either" : {
144- if (spaceRight >= spaceLeft ) {
159+ castType <DOMRect >(el )
160+ if (space .right >= space .left ) {
145161 finalPos .x = el .x ; break outerloop
146162 } else { finalPos .x = (el .x + el .width ) - popup .width ; break outerloop }
147163 }
@@ -159,17 +175,20 @@ const recompute = (): void => {
159175 }
160176 break
161177 case " top" :
162- if (spaceTop >= popup .height ) {
178+ castType <DOMRect >(el )
179+ if (space .top >= popup .height ) {
163180 finalPos .y = el .y - popup .height ; break outerloop
164181 }
165182 break
166183 case " bottom" :
167- if (spaceBottom >= popup .height ) {
184+ castType <DOMRect >(el )
185+ if (space .bottom >= popup .height ) {
168186 finalPos .y = el .y + el .height ; break outerloop
169187 }
170188 break
171189 case " either" : {
172- if (spaceTop >= spaceBottom ) {
190+ castType <DOMRect >(el )
191+ if (space .top >= space .bottom ) {
173192 finalPos .y = el .y - popup .height ; break outerloop
174193 } else { finalPos .y = el .y + el .height ; break outerloop }
175194 }
@@ -212,7 +231,7 @@ const unbindListeners = () => {
212231 window .removeEventListener (" resize" , recompute )
213232}
214233
215- watch ([() => modelValue . value , () => popupEl . value ], () => {
234+ watch ([modelValue , popupEl ], () => {
216235 if (modelValue .value ) {
217236 show ()
218237 recompute ()
0 commit comments