85 lines
2.5 KiB
Vue
85 lines
2.5 KiB
Vue
<!--
|
|
|--------------------------------------------------------------------------
|
|
| Agência PSI
|
|
|--------------------------------------------------------------------------
|
|
| Criado e desenvolvido por Leonardo Nohama
|
|
|
|
|
| Tecnologia aplicada à escuta.
|
|
| Estrutura para o cuidado.
|
|
|
|
|
| Arquivo: src/layout/AppSidebar.vue
|
|
| Data: 2026
|
|
| Local: São Carlos/SP — Brasil
|
|
|--------------------------------------------------------------------------
|
|
| © 2026 — Todos os direitos reservados
|
|
|--------------------------------------------------------------------------
|
|
-->
|
|
<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, closeMenuOnNavigate } = useLayout();
|
|
const route = useRoute();
|
|
const sidebarRef = ref(null);
|
|
let outsideClickListener = null;
|
|
|
|
// ✅ rota mudou:
|
|
// - atualiza activePath sempre (desktop e mobile)
|
|
// - fecha menu SOMENTE no mobile (evita "sumir" no desktop / inconsistências)
|
|
watch(
|
|
() => route.path,
|
|
(newPath) => {
|
|
layoutState.activePath = newPath;
|
|
closeMenuOnNavigate?.();
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
|
|
// mantém o outside click só quando overlay está aberto e estamos em desktop
|
|
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');
|
|
const el = sidebarRef.value;
|
|
if (!el) return true;
|
|
|
|
return !(el.isSameNode(event.target) || el.contains(event.target) || topbarButtonEl?.isSameNode(event.target) || topbarButtonEl?.contains(event.target));
|
|
};
|
|
|
|
onBeforeUnmount(() => {
|
|
unbindOutsideClickListener();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div ref="sidebarRef" class="layout-sidebar">
|
|
<AppMenu />
|
|
</div>
|
|
</template>
|