Mercurial
view design_system/src/components/story.js @ 259:667156fcd3e3
Add dev-only cyberpunk JRPG page
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Wed, 05 Aug 2026 09:19:41 -0700 |
| parents | 2b6e732087ff |
| children |
line wrap: on
line source
function normalizeSource(source) { const lines = source.replace(/^\n|\n\s*$/g, "").split("\n"); const indentation = lines .filter(line => line.trim()) .map(line => line.match(/^\s*/)[0].length); const minimum = indentation.length ? Math.min(...indentation) : 0; return lines.map(line => line.slice(minimum)).join("\n"); } /** * Renders a declarative component example and its copyable HTML source. * * @extends {HTMLElement} */ export class ZenStory extends HTMLElement { connectedCallback() { if (this.dataset.ready === "true") return; const template = this.querySelector(":scope > template"); if (!template) return; this.dataset.ready = "true"; const heading = document.createElement("header"); const title = document.createElement("h3"); title.textContent = this.getAttribute("name") || "Example"; heading.append(title); const copy = document.createElement("button"); copy.type = "button"; copy.textContent = "Copy HTML"; copy.addEventListener("click", async () => { try { await navigator.clipboard.writeText( normalizeSource(template.innerHTML), ); copy.textContent = "Copied"; } catch { copy.textContent = "Copy unavailable"; } setTimeout(() => { copy.textContent = "Copy HTML"; }, 1200); }); heading.append(copy); const canvas = document.createElement("div"); canvas.className = "story-canvas"; canvas.append(template.content.cloneNode(true)); const source = document.createElement("pre"); const code = document.createElement("code"); code.textContent = normalizeSource(template.innerHTML); source.append(code); this.prepend(heading, canvas, source); } } if (!customElements.get("zen-story")) { customElements.define("zen-story", ZenStory); }