|
| 1 | +--- |
| 2 | +import Editor from '../components/Editor.astro'; |
| 3 | +import '../styles/global.css'; |
| 4 | +--- |
| 5 | + |
| 6 | +<!doctype html> |
| 7 | +<html lang="en"> |
| 8 | + <head> |
| 9 | + <meta charset="UTF-8" /> |
| 10 | + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| 11 | + <meta name="description" content="Muco - Code to Music. Write code, generate ambient music." /> |
| 12 | + <title>Muco</title> |
| 13 | + <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> |
| 14 | + <link rel="preconnect" href="https://fonts.googleapis.com" /> |
| 15 | + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> |
| 16 | + <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" /> |
| 17 | + </head> |
| 18 | + <body> |
| 19 | + <div class="app"> |
| 20 | + <header class="header"> |
| 21 | + <div class="logo"> |
| 22 | + <span class="logo-text">muco</span> |
| 23 | + <span class="logo-tagline">code → music</span> |
| 24 | + </div> |
| 25 | + <button id="settings-toggle" class="settings-button" aria-label="Toggle settings"> |
| 26 | + <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 27 | + <circle cx="12" cy="12" r="3"></circle> |
| 28 | + <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path> |
| 29 | + </svg> |
| 30 | + </button> |
| 31 | + </header> |
| 32 | + |
| 33 | + <main class="editor-wrapper"> |
| 34 | + <Editor /> |
| 35 | + </main> |
| 36 | + |
| 37 | + <aside id="settings-panel" class="settings-panel hidden"> |
| 38 | + <div class="settings-header"> |
| 39 | + <h2>Settings</h2> |
| 40 | + <button id="settings-close" class="close-button" aria-label="Close settings"> |
| 41 | + <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 42 | + <line x1="18" y1="6" x2="6" y2="18"></line> |
| 43 | + <line x1="6" y1="6" x2="18" y2="18"></line> |
| 44 | + </svg> |
| 45 | + </button> |
| 46 | + </div> |
| 47 | + |
| 48 | + <div class="settings-content"> |
| 49 | + <div class="setting-group"> |
| 50 | + <label for="theme-select">Theme</label> |
| 51 | + <select id="theme-select"></select> |
| 52 | + </div> |
| 53 | + |
| 54 | + <div class="setting-group"> |
| 55 | + <label for="language-select">Language</label> |
| 56 | + <select id="language-select"></select> |
| 57 | + </div> |
| 58 | + |
| 59 | + <div class="setting-group"> |
| 60 | + <label class="toggle-label"> |
| 61 | + <span>Vim Mode</span> |
| 62 | + <button id="vim-toggle" class="toggle-button" aria-pressed="false"> |
| 63 | + <span class="toggle-track"> |
| 64 | + <span class="toggle-thumb"></span> |
| 65 | + </span> |
| 66 | + </button> |
| 67 | + </label> |
| 68 | + </div> |
| 69 | + </div> |
| 70 | + |
| 71 | + <div class="settings-footer"> |
| 72 | + <p class="hint">Start typing to hear your code come alive</p> |
| 73 | + </div> |
| 74 | + </aside> |
| 75 | + </div> |
| 76 | + |
| 77 | + <script> |
| 78 | + import { setTheme, setLanguage, toggleVim, themeRegistry, languageRegistry } from '../scripts/editor'; |
| 79 | + import { getThemesByGroup } from '../scripts/themes/index'; |
| 80 | + |
| 81 | + // Settings panel toggle |
| 82 | + const settingsToggle = document.getElementById('settings-toggle'); |
| 83 | + const settingsPanel = document.getElementById('settings-panel'); |
| 84 | + const settingsClose = document.getElementById('settings-close'); |
| 85 | + |
| 86 | + settingsToggle?.addEventListener('click', () => { |
| 87 | + settingsPanel?.classList.toggle('hidden'); |
| 88 | + }); |
| 89 | + |
| 90 | + settingsClose?.addEventListener('click', () => { |
| 91 | + settingsPanel?.classList.add('hidden'); |
| 92 | + }); |
| 93 | + |
| 94 | + // Theme select |
| 95 | + const themeSelect = document.getElementById('theme-select') as HTMLSelectElement; |
| 96 | + if (themeSelect) { |
| 97 | + const groups = getThemesByGroup(); |
| 98 | + groups.forEach((themes, groupName) => { |
| 99 | + const optgroup = document.createElement('optgroup'); |
| 100 | + optgroup.label = groupName; |
| 101 | + themes.forEach(theme => { |
| 102 | + const option = document.createElement('option'); |
| 103 | + option.value = theme.id; |
| 104 | + option.textContent = theme.name; |
| 105 | + optgroup.appendChild(option); |
| 106 | + }); |
| 107 | + themeSelect.appendChild(optgroup); |
| 108 | + }); |
| 109 | + |
| 110 | + // Set default based on system preference |
| 111 | + const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches; |
| 112 | + themeSelect.value = isDark ? 'midnight' : 'dawn'; |
| 113 | + |
| 114 | + themeSelect.addEventListener('change', () => { |
| 115 | + setTheme(themeSelect.value); |
| 116 | + }); |
| 117 | + } |
| 118 | + |
| 119 | + // Language select |
| 120 | + const languageSelect = document.getElementById('language-select') as HTMLSelectElement; |
| 121 | + if (languageSelect) { |
| 122 | + languageRegistry.forEach(lang => { |
| 123 | + const option = document.createElement('option'); |
| 124 | + option.value = lang.id; |
| 125 | + option.textContent = lang.name; |
| 126 | + languageSelect.appendChild(option); |
| 127 | + }); |
| 128 | + |
| 129 | + languageSelect.addEventListener('change', () => { |
| 130 | + setLanguage(languageSelect.value); |
| 131 | + }); |
| 132 | + } |
| 133 | + |
| 134 | + // Vim toggle |
| 135 | + const vimToggle = document.getElementById('vim-toggle'); |
| 136 | + if (vimToggle) { |
| 137 | + vimToggle.addEventListener('click', () => { |
| 138 | + const enabled = toggleVim(); |
| 139 | + vimToggle.setAttribute('aria-pressed', String(enabled)); |
| 140 | + vimToggle.classList.toggle('active', enabled); |
| 141 | + }); |
| 142 | + } |
| 143 | + |
| 144 | + // Close settings on escape |
| 145 | + document.addEventListener('keydown', (e) => { |
| 146 | + if (e.key === 'Escape' && !settingsPanel?.classList.contains('hidden')) { |
| 147 | + settingsPanel?.classList.add('hidden'); |
| 148 | + } |
| 149 | + }); |
| 150 | + </script> |
| 151 | + </body> |
| 152 | +</html> |
0 commit comments