|
54 | 54 | return { r, g, b }; |
55 | 55 | } |
56 | 56 |
|
| 57 | + function clampByte(n) { |
| 58 | + if (typeof n !== "number" || Number.isNaN(n)) return 0; |
| 59 | + return Math.max(0, Math.min(255, Math.round(n))); |
| 60 | + } |
| 61 | + |
| 62 | + function rgbStringToHex(s) { |
| 63 | + if (typeof s !== "string") return null; |
| 64 | + const v = s.trim(); |
| 65 | + const m = /^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*[\d.]+\s*)?\)$/.exec(v); |
| 66 | + if (!m) return null; |
| 67 | + const r = clampByte(Number(m[1])); |
| 68 | + const g = clampByte(Number(m[2])); |
| 69 | + const b = clampByte(Number(m[3])); |
| 70 | + return ( |
| 71 | + "#" + |
| 72 | + r.toString(16).padStart(2, "0") + |
| 73 | + g.toString(16).padStart(2, "0") + |
| 74 | + b.toString(16).padStart(2, "0") |
| 75 | + ).toUpperCase(); |
| 76 | + } |
| 77 | + |
| 78 | + function getCssVar(name) { |
| 79 | + const root = document.documentElement; |
| 80 | + if (!(root instanceof HTMLElement)) return ""; |
| 81 | + return getComputedStyle(root).getPropertyValue(name).trim(); |
| 82 | + } |
| 83 | + |
| 84 | + function lightenHex(hex, amount01) { |
| 85 | + const rgb = hexToRgb(hex); |
| 86 | + if (!rgb) return null; |
| 87 | + const t = typeof amount01 === "number" ? Math.max(0, Math.min(1, amount01)) : 0; |
| 88 | + const r = clampByte(rgb.r + (255 - rgb.r) * t); |
| 89 | + const g = clampByte(rgb.g + (255 - rgb.g) * t); |
| 90 | + const b = clampByte(rgb.b + (255 - rgb.b) * t); |
| 91 | + return ("#" + r.toString(16).padStart(2, "0") + g.toString(16).padStart(2, "0") + b.toString(16).padStart(2, "0")).toUpperCase(); |
| 92 | + } |
| 93 | + |
57 | 94 | function ensureStyleTag() { |
58 | 95 | const existing = document.getElementById(STYLE_TAG_ID); |
59 | 96 | if (existing instanceof HTMLStyleElement) return existing; |
|
97 | 134 | style.textContent = lines.join("\n"); |
98 | 135 | } |
99 | 136 |
|
100 | | - function applyFromStorage() { |
| 137 | + function applyDefaultsFromTheme() { |
| 138 | + const primary = getCssVar("--md-primary-fg-color"); |
| 139 | + const primaryHex = rgbStringToHex(primary) || (isHexColor(primary) ? primary.toUpperCase() : null); |
| 140 | + if (!primaryHex) return; |
| 141 | + |
| 142 | + const accentHex = lightenHex(primaryHex, 0.35) || primaryHex; |
| 143 | + applyColors(primaryHex, accentHex); |
| 144 | + } |
| 145 | + |
| 146 | + function applyFromStorageOrThemeDefaults() { |
101 | 147 | const cfg = loadConfig(); |
102 | | - if (!cfg) return; |
| 148 | + if (!cfg) { |
| 149 | + applyDefaultsFromTheme(); |
| 150 | + return; |
| 151 | + } |
103 | 152 | applyColors(cfg.primary, cfg.accent); |
104 | 153 | } |
105 | 154 |
|
|
246 | 295 | const cfg = loadConfig(); |
247 | 296 | if (cfg?.primary && isHexColor(cfg.primary)) primaryInput.value = cfg.primary; |
248 | 297 | if (cfg?.accent && isHexColor(cfg.accent)) accentInput.value = cfg.accent; |
| 298 | + if (!cfg) { |
| 299 | + const p = getCssVar("--md-primary-fg-color"); |
| 300 | + const pHex = rgbStringToHex(p) || (isHexColor(p) ? p : null); |
| 301 | + if (pHex) primaryInput.value = pHex; |
| 302 | + const aHex = pHex ? lightenHex(pHex, 0.35) : null; |
| 303 | + if (aHex) accentInput.value = aHex; |
| 304 | + } |
249 | 305 | overlay.hidden = false; |
250 | 306 | overlay.style.removeProperty("display"); |
251 | 307 | document.documentElement.classList.add("theme-palette-open"); |
|
296 | 352 | resetBtn.addEventListener("click", () => { |
297 | 353 | localStorage.removeItem(STORAGE_KEY); |
298 | 354 | clearStyleTag(); |
299 | | - primaryInput.value = "#6750A4"; |
300 | | - accentInput.value = "#EFB8C8"; |
| 355 | + applyFromStorageOrThemeDefaults(); |
| 356 | + const p = getCssVar("--md-primary-fg-color"); |
| 357 | + const pHex = rgbStringToHex(p) || (isHexColor(p) ? p : null) || "#6750A4"; |
| 358 | + const aHex = lightenHex(pHex, 0.35) || "#EFB8C8"; |
| 359 | + primaryInput.value = pHex; |
| 360 | + accentInput.value = aHex; |
301 | 361 | }); |
302 | 362 |
|
303 | 363 | return { overlay, open, close: closePanel }; |
304 | 364 | } |
305 | 365 |
|
306 | 366 | function mount() { |
307 | | - applyFromStorage(); |
| 367 | + applyFromStorageOrThemeDefaults(); |
308 | 368 |
|
309 | 369 | if (document.querySelector(".theme-palette-overlay")) return; |
310 | 370 | const { overlay, open } = createDialog(); |
|
0 commit comments