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> <template>
<Popover v-slot="{ open, close }" :class="wrapperClass"> <Popover v-slot="{ open, close }" :class="wrapperClass" @mouseleave="onMouseLeave">
<PopoverButton ref="trigger" as="div"> <PopoverButton ref="trigger" as="div" @mouseover="onMouseOver">
<slot :open="open" :close="close"> <slot :open="open" :close="close">
<button>Open</button> <button>Open</button>
</slot> </slot>
</PopoverButton> </PopoverButton>
<div v-if="open" ref="container" :class="containerClass"> <div v-if="open" ref="container" :class="containerClass" @mouseover="onMouseOver">
<transition <transition
appear appear
enter-active-class="transition ease-out duration-200" enter-active-class="transition ease-out duration-200"
@@ -44,6 +44,13 @@ export default {
type: String, type: String,
default: 'fixed' default: 'fixed'
}, },
mode: {
type: String,
default: 'click',
validator: (value) => {
return ['click', 'hover'].includes(value)
}
},
wrapperClass: { wrapperClass: {
type: String, type: String,
default: 'relative' 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 { return {
trigger, trigger,
container container,
onMouseOver,
onMouseLeave
} }
} }
} }