86 lines
2.6 KiB
JavaScript
86 lines
2.6 KiB
JavaScript
import { onMounted, onBeforeUnmount, watch, reactive, ref } from '@common/utils/vueTools'
|
|
|
|
|
|
export default ({ visible, location, onHide }) => {
|
|
const transition1 = 'transform, opacity'
|
|
const transition2 = 'transform, opacity, top, left'
|
|
let show = false
|
|
const dom_menu = ref(null)
|
|
const menuStyles = reactive({
|
|
left: 0,
|
|
top: 0,
|
|
opacity: 0,
|
|
transitionProperty: 'transform, opacity',
|
|
transform: 'scale(.8, .7) translate(0,0)',
|
|
pointerEvents: 'none',
|
|
})
|
|
|
|
const handleShow = () => {
|
|
show = true
|
|
menuStyles.opacity = 1
|
|
menuStyles.transform = `scale(1) translate(${handleGetOffsetXY(location.value.x, location.value.y)})`
|
|
menuStyles.pointerEvents = 'auto'
|
|
}
|
|
const handleHide = () => {
|
|
menuStyles.opacity = 0
|
|
menuStyles.transform = 'scale(.8, .7) translate(0, 0)'
|
|
menuStyles.pointerEvents = 'none'
|
|
show = false
|
|
}
|
|
const handleGetOffsetXY = (left, top) => {
|
|
const listWidth = dom_menu.value.clientWidth
|
|
const listHeight = dom_menu.value.clientHeight
|
|
const dom_container_parant = dom_menu.value.offsetParent
|
|
const containerWidth = dom_container_parant.clientWidth
|
|
const containerHeight = dom_container_parant.clientHeight
|
|
const offsetWidth = containerWidth - left - listWidth
|
|
const offsetHeight = containerHeight - top - listHeight
|
|
let x = 0
|
|
let y = 0
|
|
if (containerWidth > listWidth && offsetWidth < 12) {
|
|
x = offsetWidth - 12
|
|
}
|
|
if (containerHeight > listHeight && offsetHeight < 5) {
|
|
y = offsetHeight - 5
|
|
}
|
|
return `${x}px, ${y}px`
|
|
}
|
|
const handleDocumentClick = (event) => {
|
|
if (!show) return
|
|
|
|
if (event.target == dom_menu.value || dom_menu.value.contains(event.target)) return
|
|
|
|
if (show && menuStyles.transitionProperty != transition1) menuStyles.transitionProperty = transition1
|
|
|
|
onHide()
|
|
}
|
|
|
|
watch(visible, visible => {
|
|
visible ? handleShow() : handleHide()
|
|
}, { immediate: true })
|
|
|
|
watch(location, location => {
|
|
menuStyles.left = location.x - window.lx.rootOffset + 2 + 'px'
|
|
menuStyles.top = location.y - window.lx.rootOffset + 'px'
|
|
// nextTick(() => {
|
|
if (show) {
|
|
if (menuStyles.transitionProperty != transition2) menuStyles.transitionProperty = transition2
|
|
menuStyles.transform = `scale(1) translate(${handleGetOffsetXY(location.x, location.y)})`
|
|
}
|
|
// })
|
|
}, { deep: true })
|
|
|
|
onMounted(() => {
|
|
document.addEventListener('click', handleDocumentClick)
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
document.removeEventListener('click', handleDocumentClick)
|
|
})
|
|
|
|
return {
|
|
dom_menu,
|
|
menuStyles,
|
|
}
|
|
}
|