@@ -20,25 +20,6 @@ type Key = {
2020
2121const states = new WeakMap ( )
2222
23- function isTopLayer ( el : Element ) {
24- try {
25- if ( el . matches ( ':popover-open' ) ) return true
26- } catch {
27- /* fall through */
28- }
29- try {
30- if ( el . matches ( 'dialog:modal' ) ) return true
31- } catch {
32- /* fall through */
33- }
34- try {
35- if ( el . matches ( ':fullscreen' ) ) return true
36- } catch {
37- /* fall through */
38- }
39- return false
40- }
41-
4223class TextExpander {
4324 expander : TextExpanderElement
4425 input : HTMLInputElement | HTMLTextAreaElement
@@ -103,18 +84,7 @@ class TextExpander {
10384
10485 this . expander . dispatchEvent ( new Event ( 'text-expander-activate' ) )
10586
106- let { top, left} = new InputRange ( this . input , match . position ) . getBoundingClientRect ( )
107- if ( isTopLayer ( menu ) ) {
108- const rect = this . input . getBoundingClientRect ( )
109- top += rect . top
110- left += rect . left
111- if ( getComputedStyle ( menu ) . position === 'absolute' ) {
112- top += window . scrollY
113- left += window . scrollX
114- }
115- }
116- menu . style . top = `${ top } px`
117- menu . style . left = `${ left } px`
87+ this . positionMenu ( menu , match . position )
11888
11989 this . combobox . start ( )
12090 menu . addEventListener ( 'combobox-commit' , this . oncommit )
@@ -124,6 +94,27 @@ class TextExpander {
12494 this . combobox . navigate ( 1 )
12595 }
12696
97+ private positionMenu ( menu : HTMLElement , position : number ) {
98+ const caretRect = new InputRange ( this . input , position ) . getBoundingClientRect ( )
99+ const targetPosition = { left : caretRect . left , top : caretRect . top + caretRect . height }
100+
101+ const currentPosition = menu . getBoundingClientRect ( )
102+
103+ const delta = {
104+ left : targetPosition . left - currentPosition . left ,
105+ top : targetPosition . top - currentPosition . top
106+ }
107+
108+ if ( delta . left !== 0 || delta . top !== 0 ) {
109+ // Use computedStyle to avoid nesting calc() deeper and deeper
110+ const currentStyle = getComputedStyle ( menu )
111+
112+ // Using `calc` avoids having to parse the current pixel value
113+ menu . style . left = currentStyle . left ? `calc(${ currentStyle . left } + ${ delta . left } px)` : `${ delta . left } px`
114+ menu . style . top = currentStyle . top ? `calc(${ currentStyle . top } + ${ delta . top } px)` : `${ delta . top } px`
115+ }
116+ }
117+
127118 private deactivate ( ) {
128119 const menu = this . menu
129120 if ( ! menu || ! this . combobox ) return false
0 commit comments