// ============================================ // DEMO RENDERER - Generic rendering for command and skill demos // ============================================ import { getCommandDemo } from './demos/commands/index.js'; import { getSkillDemo } from './demos/skills/index.js'; /** * Initialize a command demo's JS after its HTML has been inserted into the DOM. * Call this after innerHTML is set and split compare is initialized. */ export function initCommandDemo(commandId, container) { const demo = getCommandDemo(commandId); if (demo && typeof demo.init === 'function') { const demoArea = container.querySelector('.split-after .split-content') || container; console.log('[initCommandDemo]', commandId, 'demoArea:', demoArea); demo.init(demoArea); } } /** * Render a command demo with split-screen comparison */ export function renderCommandDemo(commandId) { const demo = getCommandDemo(commandId); if (!demo) { // impeccable has multiple modes — show a usage guide if (commandId === 'impeccable') { return `
Three ways to use /impeccable
/impeccable freeform
Use on any task. Loads full design intelligence, anti-patterns, and reference knowledge into the current context.
/impeccable teach one-time setup
Scans your codebase, interviews you about brand and audience, then saves a Design Context that all other commands use automatically.
/impeccable craft build a feature
Runs /shape to plan UX first, loads the right references, then builds and iterates visually until the result delights.
Start with /impeccable teach once per project. Then use the other modes as needed.
`; } // shape is a planning skill — show the process if (commandId === 'shape') { return `
Design before you build
1. Discovery
Interviews you about purpose, audience, content, constraints, and anti-goals. Adapts questions based on your answers.
2. Design Brief
Synthesizes a 9-section brief: feature summary, primary action, design direction, layout strategy, key states, interaction model, content needs, recommended references, and open questions.
3. Handoff
The confirmed brief guides /impeccable craft or any other implementation approach. No code written, just the thinking that makes code good.
Use standalone or as the first step of /impeccable craft.
`; } return `
Visual demo for /${commandId} coming soon
`; } // Use split-screen comparison return `
${demo.before}
${demo.after || demo.before}
${demo.caption}
`; } /** * Render a skill demo (with tabs if multiple demos) */ export function renderSkillDemo(skillId) { const skill = getSkillDemo(skillId); if (!skill || !skill.tabs || skill.tabs.length === 0) { return `

Demo for ${skillId.replace(/-/g, ' ')} coming soon

`; } const showTabs = skill.tabs.length > 1; const tabs = showTabs ? skill.tabs.map((tab, i) => ` `).join('') : ''; const panels = skill.tabs.map((tab, i) => `
${renderSkillTabDemo(skillId, tab)}
`).join(''); return `
${showTabs ? `
${tabs}
` : ''}
${panels}
`; } /** * Render a single skill tab demo */ function renderSkillTabDemo(skillId, tab) { const hasToggle = tab.hasToggle !== false; const demoId = `${skillId}-${tab.id}`; return `
${hasToggle ? `
Before After
` : ''}
${tab.before}
${tab.caption}
`; } /** * Setup demo tab switching */ export function setupDemoTabs() { document.querySelectorAll('.demo-tab').forEach(tab => { tab.addEventListener('click', () => { const tabId = tab.dataset.demoTab; const container = tab.closest('.demo-tabbed-container'); container.querySelectorAll('.demo-tab').forEach(t => t.classList.remove('active')); tab.classList.add('active'); container.querySelectorAll('.demo-panel').forEach(p => p.classList.remove('active')); container.querySelector(`[data-demo-panel="${tabId}"]`)?.classList.add('active'); }); }); }