Files
tlig-theme/src/demo/demo.js
T

158 lines
6.0 KiB
JavaScript
Raw Normal View History

2026-09-23 15:09:14 +02:00
// Demo page behaviour. Not a build input — see src/demo/demo.scss.
import '../sass/main.scss'
import './demo.scss'
// -- Colour swatches ---------------------------------------------------------
//
// Read from the emitted custom properties rather than from a hand-kept list, so
// the demo cannot drift from the stylesheet: delete a token and its swatch
// disappears on reload.
function emittedTokens (group) {
const names = new Set()
for (const sheet of document.styleSheets) {
let rules
try { rules = sheet.cssRules } catch { continue } // cross-origin
for (const rule of rules) {
if (rule.selectorText !== ':root') continue
for (const prop of rule.style) {
if (prop.startsWith(`--tlig-${group}-`)) names.add(prop)
}
}
}
return [...names]
}
function renderSwatches () {
const root = getComputedStyle(document.documentElement)
const html = emittedTokens('color').map((name) => {
const value = root.getPropertyValue(name).trim()
const short = name.replace('--tlig-color-', '')
return `<figure class="swatch">
<div class="swatch__chip"><div class="swatch__fill" style="background:${value}"></div></div>
<figcaption class="swatch__meta">
<div class="swatch__name">${short}</div>
<div class="swatch__value">${value}</div>
</figcaption>
</figure>`
}).join('')
document.querySelector('#swatches').innerHTML = html
document.querySelector('#swatch-count').textContent = emittedTokens('color').length
}
// -- Script switcher ---------------------------------------------------------
//
// The point of this control: all four papyrus files share one family name and
// are separated by unicode-range, so switching scripts changes no CSS at all.
// The browser picks the font file by codepoint.
const SAMPLES = {
en: {
label: 'English',
heading: 'True Life in God',
line: 'Peace be with you — I am the Alpha and the Omega.',
note: 'Latin — PapyrusLETBold, the original file.',
},
hu: {
// The pangram, not the site's own title: "Igaz Élet Istenben" contains no
// codepoint above U+00FF, so it would be served by the Latin file and
// would demonstrate nothing. ő (U+0151) and ű (U+0171) are the test.
label: 'Magyar',
heading: 'Árvíztűrő tükörfúrógép',
line: 'Igaz Élet Istenben — ő and ű are what the Latin-Extended cut is for.',
note: 'Latin Extended-A — the hu file. The original PapyrusLETBold has no ő or ű.',
},
bg: {
label: 'Български',
heading: 'Истински живот в Бога',
line: 'Мир на вас — Аз съм Алфа и Омега.',
note: 'Cyrillic — the cyrillic and bulgarian cuts.',
},
ru: {
label: 'Русский',
heading: 'Истинная жизнь в Боге',
line: 'Мир вам — Я есмь Альфа и Омега.',
note: 'Cyrillic — same file as Bulgarian, no extra rule.',
},
el: {
label: 'Ελληνικά',
heading: 'Αληθινή εν Θεώ Ζωή',
line: 'Ειρήνη υμίν — Εγώ ειμι το Άλφα και το Ωμέγα.',
note: 'No papyrus cut exists for Greek — this is the fallback face, shown honestly.',
},
}
function setScript (code) {
const sample = SAMPLES[code]
if (!sample) return
document.querySelector('#script-heading').textContent = sample.heading
document.querySelector('#script-line').textContent = sample.line
document.querySelector('#script-note').textContent = sample.note
document.querySelector('#script-heading').lang = code
for (const button of document.querySelectorAll('[data-script]')) {
button.setAttribute('aria-pressed', String(button.dataset.script === code))
}
}
// -- Breakpoint readout ------------------------------------------------------
function trackViewport () {
const output = document.querySelector('#viewport')
const update = () => {
const width = window.innerWidth
const name = width >= 1200 ? 'wide' : width >= 800 ? 'tablet' : 'phone'
output.textContent = `${width}px · ${name}`
}
window.addEventListener('resize', update, { passive: true })
update()
}
2026-09-24 18:06:11 +02:00
// -- Parchment ladder --------------------------------------------------------
//
// Heights the live site ships a bitmap for, then two it does not.
const IMG = '/wp-content/includes/images/menu'
const LADDER = [
{ h: 309, src: `${IMG}/papyrus_submenu_309.png` },
{ h: 351, src: `${IMG}/papyrus_submenu_351_cnd.png` },
{ h: 366, src: `${IMG}/papyrus_submenu_366_cnd.png` },
{ h: 402, src: `${IMG}/papyrus_submenu_402_cnd.png` },
{ h: 450, src: `${IMG}/papyrus_submenu_450_cnd.png` },
{ h: 180, src: null },
{ h: 620, src: null },
]
function renderLadder () {
document.querySelector('#ladder').innerHTML = LADDER.map(({ h, src }) => `
<div class="parchment-row">
<div class="parchment-row__key">${h}px</div>
<p class="parchment-row__caption">original bitmap</p>
${src
? `<img src="${src}" alt="the original ${h}px bitmap" style="height:${h}px">`
: `<div class="parchment-row__none" style="height:${h}px">no bitmap exists for this height</div>`}
<p class="parchment-row__caption">.parchment, from the one 9-slice tile</p>
<div class="parchment" style="height:${h}px; box-sizing:border-box"></div>
</div>`).join('')
}
2026-09-23 15:09:14 +02:00
// -- Wire up -----------------------------------------------------------------
renderSwatches()
2026-09-24 18:06:11 +02:00
renderLadder()
2026-09-23 15:09:14 +02:00
trackViewport()
// `?script=bg` opens straight onto a given script, so a particular cut can be
// linked to or screenshotted without clicking.
const requested = new URLSearchParams(location.search).get('script')
setScript(requested in SAMPLES ? requested : 'en')
for (const button of document.querySelectorAll('[data-script]')) {
button.addEventListener('click', () => setScript(button.dataset.script))
}
const boxes = document.querySelector('#toggle-boxes')
boxes.addEventListener('click', () => {
const on = document.body.classList.toggle('show-boxes')
boxes.setAttribute('aria-pressed', String(on))
})