|
1 | 1 | (() => { |
2 | | - const STORAGE_KEY = "qrcraft_palette_v1"; |
3 | 2 | const STYLE_TAG_ID = "qrcraft-theme-palette-style"; |
4 | 3 |
|
5 | 4 | const presets = [ |
|
23 | 22 | }, |
24 | 23 | ]; |
25 | 24 |
|
26 | | - function safeParse(json) { |
27 | | - try { |
28 | | - return JSON.parse(json); |
29 | | - } catch { |
30 | | - return null; |
31 | | - } |
32 | | - } |
33 | | - |
34 | | - function loadConfig() { |
35 | | - const raw = localStorage.getItem(STORAGE_KEY); |
36 | | - const data = raw ? safeParse(raw) : null; |
37 | | - if (!data || typeof data !== "object") return null; |
38 | | - return data; |
39 | | - } |
40 | | - |
41 | | - function saveConfig(cfg) { |
42 | | - localStorage.setItem(STORAGE_KEY, JSON.stringify(cfg)); |
43 | | - } |
44 | | - |
45 | 25 | function isHexColor(s) { |
46 | 26 | return typeof s === "string" && /^#[0-9a-fA-F]{6}$/.test(s); |
47 | 27 | } |
|
134 | 114 | style.textContent = lines.join("\n"); |
135 | 115 | } |
136 | 116 |
|
137 | | - function applyFromStorage() { |
138 | | - const cfg = loadConfig(); |
139 | | - if (!cfg) return; |
140 | | - applyColors(cfg.primary, cfg.accent); |
141 | | - } |
142 | | - |
143 | 117 | function createHeaderButton() { |
144 | 118 | const btn = document.createElement("button"); |
145 | 119 | btn.type = "button"; |
|
182 | 156 | } |
183 | 157 |
|
184 | 158 | function createDialog() { |
| 159 | + function syncInputsToComputed(primaryInput, accentInput) { |
| 160 | + const p = getCssVar("--md-primary-fg-color"); |
| 161 | + const a = getCssVar("--md-accent-fg-color"); |
| 162 | + const pHex = rgbStringToHex(p) || (isHexColor(p) ? p : null); |
| 163 | + const aHex = rgbStringToHex(a) || (isHexColor(a) ? a : null); |
| 164 | + if (pHex) primaryInput.value = pHex; |
| 165 | + if (aHex) accentInput.value = aHex; |
| 166 | + } |
| 167 | + |
185 | 168 | const overlay = document.createElement("div"); |
186 | 169 | overlay.className = "theme-palette-overlay"; |
187 | 170 | overlay.hidden = true; |
|
280 | 263 | overlay.appendChild(panel); |
281 | 264 |
|
282 | 265 | function open() { |
283 | | - const cfg = loadConfig(); |
284 | | - if (cfg?.primary && isHexColor(cfg.primary)) primaryInput.value = cfg.primary; |
285 | | - if (cfg?.accent && isHexColor(cfg.accent)) accentInput.value = cfg.accent; |
286 | | - if (!cfg) { |
287 | | - const p = getCssVar("--md-primary-fg-color"); |
288 | | - const pHex = rgbStringToHex(p) || (isHexColor(p) ? p : null); |
289 | | - if (pHex) primaryInput.value = pHex; |
290 | | - const aHex = pHex ? lightenHex(pHex, 0.35) : null; |
291 | | - if (aHex) accentInput.value = aHex; |
292 | | - } |
| 266 | + syncInputsToComputed(primaryInput, accentInput); |
293 | 267 | overlay.hidden = false; |
294 | 268 | overlay.style.removeProperty("display"); |
295 | 269 | document.documentElement.classList.add("theme-palette-open"); |
|
301 | 275 | document.documentElement.classList.remove("theme-palette-open"); |
302 | 276 | } |
303 | 277 |
|
304 | | - function applyAndSave(primary, accent) { |
| 278 | + function applyNow(primary, accent) { |
305 | 279 | applyColors(primary, accent); |
306 | | - saveConfig({ primary, accent }); |
307 | 280 | } |
308 | 281 |
|
309 | 282 | panel.addEventListener("click", (e) => { |
|
330 | 303 | const primary = t.dataset.primary; |
331 | 304 | const accent = t.dataset.accent; |
332 | 305 | if (!isHexColor(primary) || !isHexColor(accent)) return; |
333 | | - applyAndSave(primary, accent); |
| 306 | + applyNow(primary, accent); |
334 | 307 | }); |
335 | 308 |
|
336 | 309 | applyBtn.addEventListener("click", () => { |
337 | | - applyAndSave(primaryInput.value, accentInput.value); |
| 310 | + applyNow(primaryInput.value, accentInput.value); |
338 | 311 | }); |
339 | 312 |
|
340 | 313 | resetBtn.addEventListener("click", () => { |
341 | | - localStorage.removeItem(STORAGE_KEY); |
342 | 314 | clearStyleTag(); |
343 | | - const p = getCssVar("--md-primary-fg-color"); |
344 | | - const a = getCssVar("--md-accent-fg-color"); |
345 | | - const pHex = rgbStringToHex(p) || (isHexColor(p) ? p : null); |
346 | | - const aHex = rgbStringToHex(a) || (isHexColor(a) ? a : null); |
347 | | - if (pHex) primaryInput.value = pHex; |
348 | | - if (aHex) accentInput.value = aHex; |
| 315 | + requestAnimationFrame(() => { |
| 316 | + syncInputsToComputed(primaryInput, accentInput); |
| 317 | + }); |
349 | 318 | }); |
350 | 319 |
|
351 | 320 | return { overlay, open, close: closePanel }; |
352 | 321 | } |
353 | 322 |
|
354 | 323 | function mount() { |
355 | | - applyFromStorage(); |
356 | | - |
357 | 324 | if (document.querySelector(".theme-palette-overlay")) return; |
358 | 325 | const { overlay, open } = createDialog(); |
359 | 326 | document.body.appendChild(overlay); |
|
0 commit comments