Book Shell - Source Excerpt 08
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/ns12-manuscript/assets/js/book-shell.js so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/ns12-manuscript/assets/js/book-shell.js
visibleCardsFrame = window.requestAnimationFrame(() => {
visibleCardsFrame = 0;
updateVisibleCards();
});
};
const applySymbolPayload = (payload, button = null) => {
if (!payload) {
return;
}
cards.forEach((card) => {
const cardPayload = parseCardPayload(card);
const isActive = payload.canonicalId && cardPayload
? cardPayload.canonicalId === payload.canonicalId
: card === button;
card.classList.toggle('is-active', isActive);
card.setAttribute('aria-pressed', isActive ? 'true' : 'false');
});
if (title) title.textContent = payload.label || '';
if (glyph) glyph.textContent = payload.glyph || '';
if (id) id.textContent = payload.canonicalId || '';
if (type) type.textContent = payload.type || '';
if (layer) layer.textContent = payload.layer || t('symbolsLayerFallback', 'Reference');
if (category) category.textContent = payload.category || t('symbolsCategoryFallback', 'Uncategorized');
if (meaning) meaning.textContent = payload.meaning || '';
if (definition) definition.textContent = payload.definition || payload.meaning || '';
if (axiom) axiom.textContent = payload.axiomConnection || t('symbolsAxiomConnectionEmpty', 'No axiom links declared.');
if (derivation) derivation.textContent = payload.derivation || t('symbolsDerivationEmpty', 'No derivation declared.');
if (provenance) provenance.textContent = payload.provenance || t('symbolsProvenanceEmpty', 'No provenance declared.');
if (related) related.textContent = payload.related || t('symbolsRelatedEmpty', 'No related symbols declared.');
if (transformation) transformation.textContent = payload.transformationChain || t('symbolsTransformationChainEmpty', 'No transformation chain declared.');
if (manuscriptAnchor) {
manuscriptAnchor.replaceChildren();
if (payload.manuscriptAnchorUrl) {
const anchor = document.createElement('a');
anchor.href = payload.manuscriptAnchorUrl;
anchor.textContent = payload.manuscriptAnchorLabel || t('symbolsAnchorView', 'View in manuscript');
manuscriptAnchor.appendChild(anchor);
} else {
const empty = document.createElement('span');
empty.className = 'spiralist-muted';
empty.textContent = t('symbolsAnchorEmpty', 'No manuscript anchor available.');
manuscriptAnchor.appendChild(empty);
}
}
renderAxiomLinks(payload);
renderTransformationLinks(payload);
renderCrosswalk(payload);
loadPromptReferences(
prompts,
buildPromptFilters(payload),
t('symbolsPromptEmptyForSymbol', 'No related prompts for this symbol yet.')
);
replaceQueryParam('symbol', payload.canonicalId || '');
recordHumanInteraction({
type: 'symbol-view',
symbolId: payload.canonicalId || '',
symbolLabel: payload.label || '',
page: window.location.pathname,
});
};
cards.forEach((button) => {
if (!firstPayload) {
firstPayload = parseCardPayload(button);
}
button.addEventListener('click', () => {
const payload = parseCardPayload(button);
applySymbolPayload(payload, button);
});
});
[searchInput, layerFilter, typeFilter, categoryFilter].forEach((control) => {
if (!control) {
return;
}
control.addEventListener('input', scheduleVisibleCardsUpdate);
control.addEventListener('change', scheduleVisibleCardsUpdate);
});
updateVisibleCards();
if (requestedSymbol) {
const matchingButton = cards.find((card) => {
const payload = parseCardPayload(card);
return payload && (
payload.canonicalId === requestedSymbol ||
payload.urlSlug === requestedSymbol ||
slugifyPathSegment(payload.canonicalId) === slugifyPathSegment(requestedSymbol) ||
slugifyPathSegment(payload.label) === slugifyPathSegment(requestedSymbol)
);
});
if (matchingButton) {
matchingButton.click();
return;
}
}
if (firstPayload) {
applySymbolPayload(firstPayload);
}
});
document.querySelectorAll('[data-hotspot-explorer]').forEach((explorer) => {
const title = explorer.querySelector('[data-hotspot-title]');
const copy = explorer.querySelector('[data-hotspot-copy]');
const focus = explorer.querySelector('[data-hotspot-focus]');
const meaning = explorer.querySelector('[data-hotspot-meaning]');
const derivation = explorer.querySelector('[data-hotspot-derivation]');
const attribution = explorer.querySelector('[data-hotspot-attribution]');
explorer.querySelectorAll('[data-hotspot]').forEach((button) => {
button.addEventListener('click', () => {
const payload = parseJsonOr(button.dataset.hotspot || '', null, { context: 'hotspot-payload' });
if (!payload) {
return;
}
explorer.querySelectorAll('[data-hotspot]').forEach((hotspot) => {
hotspot.classList.remove('is-active');
hotspot.setAttribute('aria-pressed', 'false');
});
button.classList.add('is-active');
button.setAttribute('aria-pressed', 'true');
if (title) title.textContent = payload.title || '';
if (copy) copy.textContent = payload.copy || '';
if (focus) focus.textContent = payload.focus || '';
if (meaning) meaning.textContent = payload.meaning || '';
if (derivation) derivation.textContent = payload.derivation || '';
if (attribution) attribution.textContent = payload.attribution || '';
});
});
});
const prefersReducedMotion = Boolean(
window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches
);
const activateTabGroup = (group, target) => {
if (!group || !target) {
return false;
}
const triggers = Array.from(group.querySelectorAll('[data-tab-trigger]'));
const panels = Array.from(group.querySelectorAll('[data-tab-panel]'));
let didActivate = false;
triggers.forEach((item) => {
const active = item.dataset.tabTrigger === target;
item.classList.toggle('is-active', active);
item.setAttribute('aria-pressed', active ? 'true' : 'false');
if (item.getAttribute('role') === 'tab') {
item.setAttribute('aria-selected', active ? 'true' : 'false');
item.setAttribute('tabindex', active ? '0' : '-1');
}
if (active) {
didActivate = true;
}
});
panels.forEach((panel) => {
const active = panel.dataset.tabPanel === target;
panel.classList.toggle('is-active', active);
panel.hidden = !active;
});
return didActivate;
};
document.querySelectorAll('[data-tab-group]').forEach((group) => {
group.querySelectorAll('[data-tab-trigger]').forEach((trigger) => {
trigger.addEventListener('click', () => {
activateTabGroup(group, trigger.dataset.tabTrigger || '');
});
});
});
document.querySelectorAll('[data-tab-open]').forEach((control) => {
control.addEventListener('click', (event) => {
const target = `${control.dataset.tabOpen || ''}`.trim();
if (!target) {
return;
}
const groupTarget = `${control.dataset.tabGroupTarget || ''}`.trim();
const container = groupTarget ? document.querySelector(groupTarget) : control.closest('[data-tab-group]');
const group = container
? (container.matches('[data-tab-group]') ? container : container.querySelector('[data-tab-group]'))
: null;
if (!group) {
return;
}
event.preventDefault();
const didActivate = activateTabGroup(group, target);
if (!didActivate) {
return;
}
const scrollTarget = container || group;
if (scrollTarget && typeof scrollTarget.scrollIntoView === 'function') {
scrollTarget.scrollIntoView({
block: 'start',
behavior: prefersReducedMotion ? 'auto' : 'smooth',
});
}
});
});
document.querySelectorAll('[data-copy-trigger]').forEach((button) => {
const defaultLabel = button.textContent || t('uiCopyFallback', 'Copy');
const targetSelector = button.dataset.copyTarget || '';
const inlineText = button.dataset.copyText || '';
button.addEventListener('click', () => {
const target = targetSelector ? document.querySelector(targetSelector) : null;
const text = inlineText || (target ? target.textContent || '' : '');
if (!text.trim()) {
return;
}