Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 86 additions & 47 deletions web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,65 @@ const tabList = document.querySelector('.tab-bar[role="tablist"]');
if (tabList instanceof HTMLElement && !tabList.hasAttribute('aria-orientation')) {
tabList.setAttribute('aria-orientation', 'horizontal');
}
const tabButtons = Array.from(document.querySelectorAll('[data-root-tab]'));
const tabPanels = Array.from(document.querySelectorAll('[data-root-panel]'));

tabButtons.forEach((button) => {
const tabId = button.dataset.rootTab;
if (tabId && !button.dataset.tab) {
button.dataset.tab = tabId;
}
});
const tabPanelMap = new Map();
tabPanels.forEach((panel) => {
const panelId = panel.dataset.rootPanel || panel.dataset.tab;
if (panelId) {
const normalizedId = panelId.toLowerCase();
tabPanelMap.set(normalizedId, panel);
if (!panel.dataset.tab) {
panel.dataset.tab = panelId;
}
}
});
const tabHeadings = new Map();
tabPanels.forEach((panel) => {
const panelId = panel.dataset.rootPanel || panel.dataset.tab;
if (!panelId) {
return;
}
const heading = panel.querySelector('[data-tab-heading]');
if (heading instanceof HTMLElement) {
tabHeadings.set(panelId.toLowerCase(), heading);
}
});
const tabOrder = ['visuals', 'config', 'console', 'json', 'fixtures', 'logs'];
const consoleTabButton = tabButtons.find((button) => button.dataset.tab === 'console');
const jsonTabButton = tabButtons.find((button) => button.dataset.tab === 'json');
const fixturesTabButton = tabButtons.find((button) => button.dataset.tab === 'fixtures');
let tabButtons = [];
let tabPanels = [];
let tabPanelMap = new Map();
let tabHeadings = new Map();
let consoleTabButton;
let jsonTabButton;
let fixturesTabButton;
let jsonTabBadge;
let fixturesTabBadge;

function collectRootTabElements() {
tabButtons = Array.from(document.querySelectorAll('[data-root-tab]'));
tabPanels = Array.from(document.querySelectorAll('[data-root-panel]'));

tabButtons.forEach((button) => {
const tabId = button.dataset.rootTab;
if (tabId && !button.dataset.tab) {
button.dataset.tab = tabId;
}
});

tabPanelMap = new Map();
tabPanels.forEach((panel) => {
const panelId = panel.dataset.rootPanel || panel.dataset.tab;
if (panelId) {
const normalizedId = panelId.toLowerCase();
tabPanelMap.set(normalizedId, panel);
if (!panel.dataset.tab) {
panel.dataset.tab = panelId;
}
}
});

tabHeadings = new Map();
tabPanels.forEach((panel) => {
const panelId = panel.dataset.rootPanel || panel.dataset.tab;
if (!panelId) {
return;
}
const heading = panel.querySelector('[data-tab-heading]');
if (heading instanceof HTMLElement) {
tabHeadings.set(panelId.toLowerCase(), heading);
}
});

consoleTabButton = tabButtons.find(
(button) => (button.dataset.rootTab || button.dataset.tab || '').toLowerCase() === 'console'
);
jsonTabButton = tabButtons.find(
(button) => (button.dataset.rootTab || button.dataset.tab || '').toLowerCase() === 'json'
);
fixturesTabButton = tabButtons.find(
(button) => (button.dataset.rootTab || button.dataset.tab || '').toLowerCase() === 'fixtures'
);
}

collectRootTabElements();

if (typeof window !== 'undefined') {
window.WYRD_DEBUG = DEBUG;
}
Expand Down Expand Up @@ -1039,7 +1060,8 @@ function focusTabPanel(targetTab) {
}
}

function applyActiveTab(targetTab, options = {}) {
function goToRootTab(targetTab, options = {}) {
console.info('[root-tabs] switching to', targetTab);
const { focusPanel = false } = options;
if (typeof targetTab !== 'string') {
return;
Expand Down Expand Up @@ -1089,44 +1111,61 @@ function initRootTabs() {
return;
}

collectRootTabElements();

const tabs = tabButtons;
const panels = tabPanels;

console.info(
'[root-tabs] found tabs:',
tabs.map((tab) => tab.dataset.rootTab || tab.dataset.tab || '')
);
console.info(
'[root-tabs] found panels:',
panels.map((panel) => panel.dataset.rootPanel || panel.dataset.tab || '')
);

document.body.dataset.rootTabsHydrated = '1';

if (tabButtons.length === 0 || tabPanels.length === 0) {
if (tabs.length === 0 || panels.length === 0) {
return;
}

tabButtons.forEach((button) => {
button.addEventListener('click', () => {
const targetId = button.dataset.rootTab || button.dataset.tab;
tabs.forEach((tab) => {
tab.addEventListener('click', (event) => {
console.info('[root-tabs] click on', tab.dataset.rootTab || tab.dataset.tab);
event.preventDefault();
const targetId = tab.dataset.rootTab || tab.dataset.tab;
if (targetId) {
applyActiveTab(targetId, { focusPanel: true });
goToRootTab(targetId, { focusPanel: true });
}
});
});

const defaultTabButton =
tabButtons.find((button) => button.classList.contains('root-tab--active')) ||
tabButtons.find((button) => button.classList.contains('active')) ||
tabButtons[0];
tabs.find((button) => button.classList.contains('root-tab--active')) ||
tabs.find((button) => button.classList.contains('active')) ||
tabs[0];

const defaultTarget =
defaultTabButton?.dataset.rootTab ||
defaultTabButton?.dataset.tab ||
tabOrder[0];

if (defaultTarget) {
applyActiveTab(defaultTarget, { focusPanel: false });
goToRootTab(defaultTarget, { focusPanel: false });
} else if (tabOrder.length > 0) {
goToRootTab(tabOrder[0], { focusPanel: false });
}
}

registerIntentHandler(INTENT_TYPES.NAVIGATE_TAB, (payload = {}) => {
const target =
typeof payload.tab === 'string' ? payload.tab.toLowerCase() : undefined;
const target = typeof payload.tab === 'string' ? payload.tab : undefined;
if (!target) {
return;
}
const shouldFocus = payload.focusPanel === true;
applyActiveTab(target, { focusPanel: shouldFocus });
goToRootTab(target, { focusPanel: shouldFocus });
});

initRootTabs();
Expand Down