import { ref, onMounted, onUnmounted } from 'vue' const ENIGMA_ROOT = '.enigma' function getLayoutNodes() { const root = document.querySelector(ENIGMA_ROOT) if (!root) return null return { sideMenu: root.querySelector('.side-menu'), content: root.querySelector('.content'), } } function isCompactLayout() { return getLayoutNodes()?.sideMenu?.classList.contains('side-menu--collapsed') ?? false } function applyCompactLayout(collapsed: boolean) { const nodes = getLayoutNodes() if (!nodes?.sideMenu || !nodes.content) return nodes.sideMenu.classList.toggle('side-menu--collapsed', collapsed) nodes.content.classList.toggle('content--compact', collapsed) } function persistCompactMenu(collapsed: boolean) { queueMicrotask(() => { localStorage.setItem('compactMenu', collapsed.toString()) }) } export const useSideMenu = () => { const mobileMenuOpen = ref(false) const scrolled = ref(false) const toggleCompactMenu = (event: MouseEvent) => { event.preventDefault() const collapsed = !isCompactLayout() applyCompactLayout(collapsed) persistCompactMenu(collapsed) } const openMobileMenu = (event: MouseEvent) => { event.preventDefault() mobileMenuOpen.value = true } const closeMobileMenu = (event: MouseEvent) => { event.preventDefault() mobileMenuOpen.value = false } const onScrollContent = (event: Event) => { const target = event.target as HTMLElement scrolled.value = target.scrollTop > 0 } const onResize = () => { if (window.innerWidth <= 1600) { applyCompactLayout(true) persistCompactMenu(true) } } onMounted(() => { applyCompactLayout(localStorage.getItem('compactMenu') === 'true') window.addEventListener('resize', onResize) onResize() }) onUnmounted(() => { window.removeEventListener('resize', onResize) }) return { mobileMenuOpen, scrolled, toggleCompactMenu, openMobileMenu, closeMobileMenu, onScrollContent, } }