/* eslint-disable */ // Renders model list, history list, bars, compare grid, theme & lang toggles, tweaks panel. const { useEffect, useState, useRef } = React; // ---------- 1. Model list ---------- function renderModels() { const list = document.getElementById('modelList'); if (!list) return; list.innerHTML = window.TOOLLY_MODELS.map(m => `
${m.name}
${m.free ? 'FREE' : ''}
${m.vendor}
${m.tags.map(t => `${t}`).join('')}
`).join(''); list.querySelectorAll('.model-card').forEach(el => { el.addEventListener('click', () => { if (window.TOOLLY_COMPARE_ACTIVE) { el.classList.toggle('compare'); } else { list.querySelectorAll('.model-card.selected').forEach(s => s.classList.remove('selected')); el.classList.add('selected'); const m = window.TOOLLY_MODELS.find(x => x.id === el.dataset.id); if (m) { document.querySelector('.sm-name').textContent = m.name; document.querySelector('.sm-avatar').className = `sm-avatar ${m.ava}`; document.querySelector('.sm-avatar').textContent = m.initial; document.querySelector('.selected-model-card .mname').textContent = m.name.split(' · ').pop(); document.querySelector('.selected-model-card .mvendor').textContent = `${m.vendor}`; } } }); }); } // ---------- 2. History ---------- function renderHistory() { const el = document.getElementById('historyList'); if (!el) return; el.innerHTML = window.TOOLLY_HISTORY.map(h => `
${h.time} ${h.model} ${h.ms} ms
${h.preset} ${h.status === 'ok' ? '' : ''}
`).join(''); } // ---------- 3. Sparkline bars ---------- function renderBars() { const el = document.getElementById('bars'); if (!el) return; const peak = Math.max(...window.TOOLLY_BARS); el.innerHTML = window.TOOLLY_BARS.map(v => { const h = Math.max(6, Math.round((v / peak) * 100)); const isPeak = v === peak; return ``; }).join(''); } // ---------- 4. Compare grid ---------- function renderCompare() { const el = document.getElementById('compareGrid'); if (!el) return; el.innerHTML = window.TOOLLY_COMPARE.map(c => `
${c.initial}
${c.name}
${c.ms}ms
${c.body.replace(/\n/g, '
')}
${c.toks} toks ✓ 정상 ${c.vendor}
`).join(''); } // ---------- 5. Tabs (right pane + presets + compare toggle) ---------- function wireTabs() { document.querySelectorAll('.rt').forEach(btn => { btn.addEventListener('click', () => { const tab = btn.dataset.tab; document.querySelectorAll('.rt').forEach(b => b.classList.toggle('active', b === btn)); document.querySelectorAll('[data-tabbody]').forEach(b => { b.classList.toggle('hidden', b.dataset.tabbody !== tab); }); }); }); document.querySelectorAll('.preset-tabs .pt').forEach(btn => { btn.addEventListener('click', () => { document.querySelectorAll('.preset-tabs .pt').forEach(b => b.classList.toggle('active', b === btn)); }); }); // 필터 칩 document.querySelectorAll('.filter-chips .chip').forEach(chip => { chip.addEventListener('click', () => { document.querySelectorAll('.filter-chips .chip').forEach(c => c.classList.remove('active')); chip.classList.add('active'); if (typeof window.filterModels === 'function') window.filterModels(); }); }); const ct = document.getElementById('compareToggle'); if (ct) { ct.addEventListener('click', () => { const on = ct.classList.toggle('on'); window.TOOLLY_COMPARE_ACTIVE = on; document.getElementById('singleMode').classList.toggle('hidden', on); document.getElementById('compareMode').classList.toggle('hidden', !on); document.querySelectorAll('.model-card.compare').forEach(m => m.classList.remove('compare')); }); } } // ---------- 6. i18n ---------- function applyLang(lang) { const dict = window.TOOLLY_I18N[lang] || {}; document.querySelectorAll('[data-i18n]').forEach(el => { const k = el.dataset.i18n; if (dict[k]) el.textContent = dict[k]; }); document.querySelectorAll('[data-i18n-ph]').forEach(el => { const k = el.dataset.i18nPh; if (dict[k]) el.placeholder = dict[k]; }); document.documentElement.lang = lang; } function wireLang() { document.querySelectorAll('#langToggle button').forEach(btn => { btn.addEventListener('click', () => { document.querySelectorAll('#langToggle button').forEach(b => b.classList.toggle('active', b === btn)); applyLang(btn.dataset.lang); }); }); } // ---------- 7. Theme ---------- function applyTheme(t) { document.documentElement.setAttribute('data-theme', t); const btn = document.getElementById('themeToggle'); if (btn) { btn.innerHTML = t === 'dark' ? '' : ''; } } // ---------- 8. Tweaks panel ---------- const ACCENTS = [ { id: 'amber', label: '앰버', l: 0.66, c: 0.155, h: 48, l2: 0.74, h2: 60 }, { id: 'orange', label: '오렌지', l: 0.66, c: 0.18, h: 35, l2: 0.72, h2: 50 }, { id: 'rose', label: '로즈', l: 0.66, c: 0.16, h: 15, l2: 0.74, h2: 25 }, { id: 'green', label: '세이지', l: 0.62, c: 0.10, h: 145, l2: 0.70, h2: 160 }, { id: 'blue', label: '블루', l: 0.60, c: 0.14, h: 240, l2: 0.68, h2: 220 }, { id: 'plum', label: '플럼', l: 0.55, c: 0.15, h: 305, l2: 0.65, h2: 290 }, ]; function applyAccent(id) { const a = ACCENTS.find(x => x.id === id) || ACCENTS[0]; const r = document.documentElement.style; r.setProperty('--accent', `oklch(${a.l} ${a.c} ${a.h})`); r.setProperty('--accent-2', `oklch(${a.l2} ${a.c} ${a.h2})`); r.setProperty('--accent-soft', `oklch(${(0.94 - 0.62*0)} ${a.c * 0.3} ${a.h})`); r.setProperty('--accent-ink', `oklch(0.32 ${a.c * 0.7} ${a.h})`); } const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "accent": "amber", "theme": "light", "lang": "ko" }/*EDITMODE-END*/; function TweaksApp() { const [t, setT] = window.useTweaks(TWEAK_DEFAULTS); const { TweaksPanel, TweakSection, TweakRadio } = window; useEffect(() => { applyAccent(t.accent); }, [t.accent]); useEffect(() => { applyTheme(t.theme); }, [t.theme]); useEffect(() => { applyLang(t.lang); document.querySelectorAll('#langToggle button').forEach(b => { b.classList.toggle('active', b.dataset.lang === t.lang); }); }, [t.lang]); // sync top-bar buttons → tweak state useEffect(() => { const onLang = (e) => { const b = e.target.closest('#langToggle button'); if (b) setT('lang', b.dataset.lang); }; const onTheme = () => setT('theme', t.theme === 'dark' ? 'light' : 'dark'); document.getElementById('langToggle')?.addEventListener('click', onLang); document.getElementById('themeToggle')?.addEventListener('click', onTheme); return () => { document.getElementById('langToggle')?.removeEventListener('click', onLang); document.getElementById('themeToggle')?.removeEventListener('click', onTheme); }; }, [t.theme]); return (
{ACCENTS.map(a => ( ))}
setT('theme', v)} options={['light','dark']} /> setT('lang', v)} options={['ko','en']} />
); } // ---------- INIT ---------- renderModels(); renderHistory(); renderBars(); renderCompare(); wireTabs(); wireLang(); applyLang('ko'); applyTheme('light'); // mount tweaks const root = ReactDOM.createRoot(document.getElementById('tweaks-root')); root.render();