@@ -2,14 +2,65 @@ import { action } from '@ember/object';
22import Component from '@glimmer/component' ;
33import { tracked } from '@glimmer/tracking' ;
44
5+ import { autoUpdate , computePosition , flip , offset , shift } from '@floating-ui/dom' ;
6+ import { modifier } from 'ember-modifier' ;
7+
58export default class Tooltip extends Component {
6- @tracked hidden = true ;
9+ @tracked anchorElement = null ;
10+ @tracked visible = false ;
711
8- @ action hide ( ) {
9- this . hidden = true ;
12+ get containerElement ( ) {
13+ return document . querySelector ( '#tooltip-container' ) ;
1014 }
1115
1216 @action show ( ) {
13- this . hidden = false ;
17+ this . visible = true ;
18+ }
19+
20+ @action hide ( ) {
21+ this . visible = false ;
1422 }
23+
24+ onInsertAnchor = modifier ( ( anchor , [ component ] ) => {
25+ component . anchorElement = anchor . parentElement ;
26+
27+ let events = [
28+ [ 'mouseenter' , component . show ] ,
29+ [ 'mouseleave' , component . hide ] ,
30+ [ 'focus' , component . show ] ,
31+ [ 'blur' , component . hide ] ,
32+ ] ;
33+
34+ for ( let [ event , listener ] of events ) {
35+ component . anchorElement . addEventListener ( event , listener ) ;
36+ }
37+
38+ return ( ) => {
39+ for ( let [ event , listener ] of events ) {
40+ component . anchorElement ?. removeEventListener ( event , listener ) ;
41+ }
42+ } ;
43+ } ) ;
44+
45+ attachTooltip = modifier ( ( floatingElement , [ component ] , { side = 'top' } = { } ) => {
46+ let referenceElement = component . anchorElement ;
47+
48+ async function update ( ) {
49+ let middleware = [ offset ( 5 ) , flip ( ) , shift ( { padding : 5 } ) ] ;
50+
51+ let { x, y } = await computePosition ( referenceElement , floatingElement , {
52+ placement : side ,
53+ middleware,
54+ } ) ;
55+
56+ Object . assign ( floatingElement . style , {
57+ left : `${ x } px` ,
58+ top : `${ y } px` ,
59+ } ) ;
60+ }
61+
62+ let cleanup = autoUpdate ( referenceElement , floatingElement , update ) ;
63+
64+ return ( ) => cleanup ( ) ;
65+ } ) ;
1566}
0 commit comments