@@ -20,25 +20,6 @@ type Key = {
20
20
21
21
const states = new WeakMap ( )
22
22
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
-
42
23
class TextExpander {
43
24
expander : TextExpanderElement
44
25
input : HTMLInputElement | HTMLTextAreaElement
@@ -103,18 +84,7 @@ class TextExpander {
103
84
104
85
this . expander . dispatchEvent ( new Event ( 'text-expander-activate' ) )
105
86
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 )
118
88
119
89
this . combobox . start ( )
120
90
menu . addEventListener ( 'combobox-commit' , this . oncommit )
@@ -124,6 +94,27 @@ class TextExpander {
124
94
this . combobox . navigate ( 1 )
125
95
}
126
96
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
+
127
118
private deactivate ( ) {
128
119
const menu = this . menu
129
120
if ( ! menu || ! this . combobox ) return false
0 commit comments