- New light UI: fixed 220px sidebar, single scrolling page, 8 named sections - Static files split by concern: style.css, app.js, loader.js, nav.js - Each page section is its own partial in static/sections/s-*.html - loader.js fetches all section partials in parallel, then loads app.js and nav.js - All original functionality, element IDs, and API endpoints preserved Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
68 lines
2.4 KiB
JavaScript
68 lines
2.4 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
const TAB_SECTION_MAP = {
|
|
library: 's-voices',
|
|
source: 's-clone',
|
|
save: 's-clone',
|
|
design: 's-design',
|
|
custom: 's-design',
|
|
getvoices: 's-studio',
|
|
generation: 's-tryout',
|
|
'stt-tts': 's-tryout',
|
|
routing: 's-routing',
|
|
integrations: 's-connect',
|
|
howto: 's-connect',
|
|
settings: 's-settings'
|
|
};
|
|
|
|
function updateNavActive(sectionId) {
|
|
document.querySelectorAll('[data-nav-section]').forEach(function (item) {
|
|
item.classList.toggle('active', item.dataset.navSection === sectionId);
|
|
});
|
|
}
|
|
|
|
window.navTo = function (sectionId) {
|
|
var el = document.getElementById(sectionId);
|
|
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
updateNavActive(sectionId);
|
|
// Fire lazy-loader side-effects
|
|
var tabName = Object.keys(TAB_SECTION_MAP).find(function (k) {
|
|
return TAB_SECTION_MAP[k] === sectionId;
|
|
});
|
|
if (tabName) window.switchTab(tabName);
|
|
};
|
|
|
|
// Override switchTab — redirect tab switches to scroll-based navigation
|
|
window.switchTab = function (name) {
|
|
if (name === 'library' && typeof loadVoiceLibrary === 'function') loadVoiceLibrary();
|
|
if ((name === 'integrations' || name === 'howto') && typeof renderIntegrationSnippets === 'function') {
|
|
if (typeof loadVoiceLibrary === 'function' && !(window._voices && window._voices.length)) loadVoiceLibrary();
|
|
renderIntegrationSnippets();
|
|
}
|
|
if (name === 'routing' && typeof loadRoutingTab === 'function') loadRoutingTab();
|
|
if (name === 'getvoices' && typeof loadGetVoices === 'function') loadGetVoices();
|
|
|
|
var sectionId = TAB_SECTION_MAP[name];
|
|
if (sectionId) {
|
|
var el = document.getElementById(sectionId);
|
|
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
updateNavActive(sectionId);
|
|
}
|
|
return true;
|
|
};
|
|
|
|
// IntersectionObserver: highlight sidebar item for the section in view
|
|
var sections = ['s-voices', 's-clone', 's-design', 's-studio', 's-tryout', 's-routing', 's-connect', 's-settings'];
|
|
var io = new IntersectionObserver(function (entries) {
|
|
entries.forEach(function (entry) {
|
|
if (entry.isIntersecting) updateNavActive(entry.target.id);
|
|
});
|
|
}, { threshold: 0.15 });
|
|
|
|
sections.forEach(function (id) {
|
|
var el = document.getElementById(id);
|
|
if (el) io.observe(el);
|
|
});
|
|
})();
|