feat(navigation): expose stable read-only workspace navigation API

This commit is contained in:
Masterluke77
2026-07-14 14:41:36 +02:00
parent de1982c0dc
commit 52ba546656
+84
View File
@@ -0,0 +1,84 @@
(() => {
'use strict';
const root = document.documentElement;
if (root.dataset.uxNavigationApiReady === '1') return;
root.dataset.uxNavigationApiReady = '1';
let observer = null;
let lastView = '';
function activeView() {
return document.querySelector('.sidebar-nav .nav-item.active[data-tab]')?.dataset.tab
|| document.querySelector('.tab-content.active')?.id
|| 'dashboard';
}
function navItem(view) {
const normalized = String(view || '').trim();
if (!normalized) return null;
const items = document.querySelectorAll('.sidebar-nav .nav-item[data-tab]');
return [...items].find(item => item.dataset.tab === normalized) || null;
}
function canOpen(view) {
const item = navItem(view);
return Boolean(item
&& !item.hidden
&& !item.classList.contains('hidden')
&& item.getAttribute('aria-hidden') !== 'true'
&& item.getAttribute('aria-disabled') !== 'true');
}
function open(view) {
const item = navItem(view);
if (!canOpen(view) || typeof item?.click !== 'function') return false;
item.click();
return true;
}
function emitChange(source = 'observer') {
const currentView = activeView();
if (currentView === lastView) return;
const previousView = lastView || null;
lastView = currentView;
window.dispatchEvent(new CustomEvent('vendoo:navigation-changed', {
detail: { currentView, previousView, source },
}));
}
const api = {};
Object.defineProperties(api, {
currentView: {
enumerable: true,
get: activeView,
},
canOpen: {
enumerable: true,
value: canOpen,
},
open: {
enumerable: true,
value: open,
},
});
window.VendooNavigation = Object.freeze(api);
function observe() {
const nav = document.querySelector('.sidebar-nav');
if (!nav || observer) return;
lastView = activeView();
observer = new MutationObserver(() => emitChange('observer'));
observer.observe(nav, {
subtree: true,
attributes: true,
attributeFilter: ['class', 'hidden', 'aria-hidden', 'aria-disabled'],
});
}
observe();
window.addEventListener('beforeunload', () => observer?.disconnect(), { once: true });
window.dispatchEvent(new CustomEvent('vendoo:navigation-api-ready', {
detail: { currentView: activeView(), version: '1.44.0' },
}));
})();