feat(Popover): handle hovering mode (#47)

This commit is contained in:
Sylvain Marroufin
2022-04-11 15:26:33 +02:00
committed by GitHub
parent 289de07ba1
commit c431f8b4a1

View File

@@ -1,12 +1,12 @@
<template>
<Popover v-slot="{ open, close }" :class="wrapperClass">
<PopoverButton ref="trigger" as="div">
<Popover v-slot="{ open, close }" :class="wrapperClass" @mouseleave="onMouseLeave">
<PopoverButton ref="trigger" as="div" @mouseover="onMouseOver">
<slot :open="open" :close="close">
<button>Open</button>
</slot>
</PopoverButton>
<div v-if="open" ref="container" :class="containerClass">
<div v-if="open" ref="container" :class="containerClass" @mouseover="onMouseOver">
<transition
appear
enter-active-class="transition ease-out duration-200"
@@ -44,6 +44,13 @@ export default {
type: String,
default: 'fixed'
},
mode: {
type: String,
default: 'click',
validator: (value) => {
return ['click', 'hover'].includes(value)
}
},
wrapperClass: {
type: String,
default: 'relative'
@@ -82,9 +89,58 @@ export default {
}]
})
const popoverApi = ref(null)
let openTimeout = null
let closeTimeout = null
onMounted(() => {
setTimeout(() => {
const popoverProvides = trigger.value?.$.provides
const popoverProvidesSymbols = Object.getOwnPropertySymbols(popoverProvides)
popoverApi.value = popoverProvidesSymbols.length && popoverProvides[popoverProvidesSymbols[0]]
}, 0)
})
function onMouseOver () {
if (props.mode !== 'hover' || !popoverApi.value) {
return
}
// cancel programmed closing
if (closeTimeout) {
clearTimeout(closeTimeout)
closeTimeout = null
}
// dropdown already open
if (popoverApi.value.popoverState === 0) {
return
}
openTimeout = openTimeout || setTimeout(() => {
popoverApi.value.togglePopover && popoverApi.value.togglePopover()
openTimeout = null
}, 200)
}
function onMouseLeave () {
if (props.mode !== 'hover' || !popoverApi.value) {
return
}
// cancel programmed opening
if (openTimeout) {
clearTimeout(openTimeout)
openTimeout = null
}
// dropdown already closed
if (popoverApi.value.popoverState === 1) {
return
}
closeTimeout = closeTimeout || setTimeout(() => {
popoverApi.value.closePopover && popoverApi.value.closePopover()
closeTimeout = null
}, 100)
}
return {
trigger,
container
container,
onMouseOver,
onMouseLeave
}
}
}