67 lines
1.8 KiB
Vue
67 lines
1.8 KiB
Vue
<script setup>
|
|
import { useLayout } from '@/layout/composables/layout';
|
|
import { onBeforeUnmount, ref, watch } from 'vue';
|
|
import { useRoute } from 'vue-router';
|
|
import AppMenu from './AppMenu.vue';
|
|
|
|
const { layoutState, isDesktop, hasOpenOverlay } = useLayout();
|
|
const route = useRoute();
|
|
const sidebarRef = ref(null);
|
|
let outsideClickListener = null;
|
|
|
|
watch(
|
|
() => route.path,
|
|
(newPath) => {
|
|
if (isDesktop()) layoutState.activePath = null;
|
|
else layoutState.activePath = newPath;
|
|
|
|
layoutState.overlayMenuActive = false;
|
|
layoutState.mobileMenuActive = false;
|
|
layoutState.menuHoverActive = false;
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
|
|
watch(hasOpenOverlay, (newVal) => {
|
|
if (isDesktop()) {
|
|
if (newVal) bindOutsideClickListener();
|
|
else unbindOutsideClickListener();
|
|
}
|
|
});
|
|
|
|
const bindOutsideClickListener = () => {
|
|
if (!outsideClickListener) {
|
|
outsideClickListener = (event) => {
|
|
if (isOutsideClicked(event)) {
|
|
layoutState.overlayMenuActive = false;
|
|
}
|
|
};
|
|
|
|
document.addEventListener('click', outsideClickListener);
|
|
}
|
|
};
|
|
|
|
const unbindOutsideClickListener = () => {
|
|
if (outsideClickListener) {
|
|
document.removeEventListener('click', outsideClickListener);
|
|
outsideClickListener = null;
|
|
}
|
|
};
|
|
|
|
const isOutsideClicked = (event) => {
|
|
const topbarButtonEl = document.querySelector('.layout-menu-button');
|
|
|
|
return !(sidebarRef.value.isSameNode(event.target) || sidebarRef.value.contains(event.target) || topbarButtonEl?.isSameNode(event.target) || topbarButtonEl?.contains(event.target));
|
|
};
|
|
|
|
onBeforeUnmount(() => {
|
|
unbindOutsideClickListener();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div ref="sidebarRef" class="layout-sidebar">
|
|
<AppMenu />
|
|
</div>
|
|
</template>
|