1- import type { FloatingTooltip } from '../state/floating-tooltip '
2- import { useDebounceFn } from '@vueuse/core '
3- import { computed , defineComponent , h , ref , watch } from 'vue '
4- import { useFloatingTooltip } from '../state/floating-tooltip '
1+ import type { PropType } from 'vue '
2+ import type { FloatingPopoverProps } from '../state/floating-tooltip '
3+ import { useDebounceFn , useElementBounding } from '@vueuse/core '
4+ import { computed , defineComponent , h , reactive , ref , watch } from 'vue '
55
66// @unocss -include
77
@@ -10,56 +10,62 @@ const GAP = 10
1010
1111const FloatingTooltipComponent = defineComponent ( {
1212 name : 'FloatingTooltip' ,
13- setup ( ) {
14- const current = useFloatingTooltip ( )
15- const box = ref < FloatingTooltip | null > ( null )
13+ props : {
14+ item : {
15+ type : Object as PropType < FloatingPopoverProps | null | undefined > ,
16+ required : false ,
17+ } ,
18+ } ,
19+ setup ( props ) {
20+ const el = ref ( props . item ?. el )
21+ const rect = reactive ( useElementBounding ( el ) )
1622
1723 // guess alignment of the tooltip based on viewport position
1824 const align = computed < 'bottom' | 'left' | 'right' | 'top' > ( ( ) => {
19- if ( ! box . value )
25+ if ( ! props . item ?. el )
2026 return 'bottom'
2127 const vw = window . innerWidth
2228 const vh = window . innerHeight
23- if ( box . value . left < DETECT_MARGIN )
29+ if ( rect . left < DETECT_MARGIN )
2430 return 'right'
25- if ( box . value . left + box . value . width > vw - DETECT_MARGIN )
31+ if ( rect . left + rect . width > vw - DETECT_MARGIN )
2632 return 'left'
27- if ( box . value . top < DETECT_MARGIN )
33+ if ( rect . top < DETECT_MARGIN )
2834 return 'bottom'
29- if ( box . value . top + box . value . height > vh - DETECT_MARGIN )
35+ if ( rect . top + rect . height > vh - DETECT_MARGIN )
3036 return 'top'
3137 return 'bottom'
3238 } )
3339
3440 const style = computed ( ( ) => {
35- if ( ! box . value )
41+ if ( ! props . item ?. el )
3642 return { }
3743 switch ( align . value ) {
3844 case 'bottom' : {
3945 return {
40- left : `${ box . value . left + box . value . width / 2 } px` ,
41- top : `${ box . value . top + box . value . height + GAP } px` ,
46+ left : `${ rect . left + rect . width / 2 } px` ,
47+ top : `${ rect . top + rect . height + GAP } px` ,
4248 transform : 'translateX(-50%)' ,
4349 }
4450 }
4551 case 'top' : {
4652 return {
47- left : `${ box . value . left + box . value . width / 2 } px` ,
48- bottom : `${ window . innerHeight - box . value . top + GAP } px` ,
53+ left : `${ rect . left + rect . width / 2 } px` ,
54+ bottom : `${ window . innerHeight - rect . top + GAP } px` ,
4955 transform : 'translateX(-50%)' ,
5056 }
5157 }
5258 case 'left' : {
5359 return {
54- right : `${ window . innerWidth - box . value . left + GAP } px` ,
55- top : `${ box . value . top + box . value . height / 2 } px` ,
60+ right : `${ window . innerWidth - rect . left + GAP } px` ,
61+ top : `${ rect . top + rect . height / 2 } px` ,
5662 transform : 'translateY(-50%)' ,
5763 }
5864 }
5965 case 'right' : {
6066 return {
61- left : `${ box . value . left + box . value . width + GAP } px` ,
62- top : `${ box . value . top + box . value . height / 2 } px` ,
67+ left : `${ rect . left + rect . width + GAP } px` ,
68+ top : `${ rect . top + rect . height / 2 } px` ,
6369 transform : 'translateY(-50%)' ,
6470 }
6571 }
@@ -70,15 +76,18 @@ const FloatingTooltipComponent = defineComponent({
7076 } )
7177
7278 const clearThrottled = useDebounceFn ( ( ) => {
73- if ( current . value == null )
74- box . value = null
79+ if ( props . item ?. el == null )
80+ el . value = undefined
7581 } , 800 )
7682
7783 watch (
78- current ,
84+ ( ) => props . item ,
7985 ( value ) => {
8086 if ( value ) {
81- box . value = { ...value }
87+ if ( el . value !== value . el )
88+ el . value = value . el
89+ else
90+ rect . update ( )
8291 }
8392 else {
8493 clearThrottled ( )
@@ -87,17 +96,17 @@ const FloatingTooltipComponent = defineComponent({
8796 )
8897
8998 return ( ) => {
90- if ( ! box . value ?. render )
99+ if ( ! props . item ?. content )
91100 return null
92101
93- const content = typeof box . value . render === 'string' ? h ( 'span' , box . value . render ) : box . value . render ( )
102+ const content = typeof props . item . content === 'string' ? h ( 'span' , props . item . content ) : props . item . content ( )
94103
95104 return h (
96105 'div' ,
97106 {
98107 class : [
99108 'fixed z-floating-tooltip text-xs transition-all duration-300 w-max bg-glass border border-base rounded px2 p1' ,
100- current ? 'op100' : 'op0 pointer-events-none' ,
109+ props . item ? 'op100' : 'op0 pointer-events-none' ,
101110 ] ,
102111 style : style . value ,
103112 } ,
0 commit comments