bluedither 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,8 @@
1
- (()=>{var m=structuredClone(window.__BD_TOKENS__||JSON.parse(document.querySelector('script[type="application/json"][data-bluedither-tokens]')?.textContent||"{}")),A=structuredClone(window.__BD_DEFAULTS__||JSON.parse(document.querySelector('script[type="application/json"][data-bluedither-defaults]')?.textContent||"{}")),O=!!(window.__BD_TOKENS__&&window.__BD_DEFAULTS__)||!!window.__BD_TUNER_SERVER_MODE__,z=["Arial","Arial Black","Bebas Neue Pro","Consolas","Courier New","Georgia","Helvetica","Impact","Lucida Console","Segoe UI","Tahoma","Times New Roman","Trebuchet MS","Verdana","SF Pro Display","SF Mono","Cascadia Code","Menlo","Monaco"],j=["Bebas Neue","Space Mono","Inter","Roboto","Roboto Mono","Roboto Condensed","Open Sans","Montserrat","Lato","Oswald","Raleway","Poppins","Nunito","Playfair Display","Merriweather","Source Sans 3","Source Code Pro","PT Sans","PT Serif","PT Mono","Ubuntu","Ubuntu Mono","Fira Sans","Fira Code","Fira Mono","Work Sans","Noto Sans","Noto Serif","DM Sans","DM Serif Display","DM Mono","IBM Plex Sans","IBM Plex Mono","IBM Plex Serif","JetBrains Mono","Inconsolata","Space Grotesk","Archivo","Archivo Black","Barlow","Barlow Condensed","Lexend","Outfit","Sora","Manrope","Bitter","Crimson Text","Libre Baskerville","Abril Fatface","Anton","Permanent Marker","Righteous","Orbitron","Teko","Rubik","Quicksand","Cabin","Karla","Josefin Sans","Comfortaa","Fredoka","Geologica","Instrument Sans","Instrument Serif"],q=[...new Set([...z,...j])].sort();function v(n,r,e){let i=r.split("."),t=n;for(let d=0;d<i.length-1;d++)t=t[i[d]];t[i[i.length-1]]=e}function L(n,r){return r.split(".").reduce((e,i)=>e?.[i],n)}function k(n,r){document.documentElement.style.setProperty(n,r)}function S(n,r){let e=window.__BD_SHADER__;e&&e.updateParams({[n]:r})}function I(n){let r=m.layout.designWidth,e=n/16,i=n/r*100;return`clamp(${(e*.55).toFixed(4)}rem, ${i.toFixed(4)}vw, ${e.toFixed(4)}rem)`}function $(n){let r="bd-gf-"+n.replace(/\s+/g,"-").toLowerCase();if(document.getElementById(r))return;let e=document.createElement("link");e.id=r,e.rel="stylesheet",e.href=`https://fonts.googleapis.com/css2?family=${encodeURIComponent(n)}:wght@400;700&display=swap`,document.head.appendChild(e)}var x=document.createElement("div");x.id="bd-tuner";var P=document.createElement("button");P.id="bd-tuner-toggle";P.textContent="Tuner";P.onclick=()=>x.classList.remove("collapsed");document.body.appendChild(x);document.body.appendChild(P);x.innerHTML=`
2
- <div class="bd-tuner-title">
3
- <span>BlueDither Tuner</span>
4
- <div style="display:flex;gap:8px;align-items:center;">
5
- <button id="bd-tuner-reset" title="Reset to defaults">&#8635;</button>
6
- <button id="bd-tuner-close" title="Close">&times;</button>
7
- </div>
8
- </div>
9
- `;x.querySelector("#bd-tuner-close").onclick=()=>x.classList.add("collapsed");x.querySelector("#bd-tuner-reset").onclick=async()=>{confirm("Reset all tokens to defaults?")&&(Object.assign(m,structuredClone(A)),await H(),location.reload())};function E(n){let r=document.createElement("div");return r.className="bd-tuner-section",r.innerHTML=`<div class="bd-tuner-section-label">${n}</div>`,x.appendChild(r),r}function C(n,r,e,i,t){let d=L(m,e)||"#000000",a=document.createElement("div");a.className="bd-tuner-row",a.innerHTML=`
1
+ (()=>{if(!window.__BD_TUNER_LOADED__){let w=function(n,r,e){let i=r.split("."),t=n;for(let d=0;d<i.length-1;d++)t=t[i[d]];t[i[i.length-1]]=e},L=function(n,r){return r.split(".").reduce((e,i)=>e?.[i],n)},k=function(n,r){document.documentElement.style.setProperty(n,r)},v=function(n,r){let e=window.__BD_SHADER__;e&&e.updateParams({[n]:r})},U=function(n){let r=b.layout.designWidth,e=n/16,i=n/r*100;return`clamp(${(e*.55).toFixed(4)}rem, ${i.toFixed(4)}vw, ${e.toFixed(4)}rem)`},$=function(n){let r="bd-gf-"+n.replace(/\s+/g,"-").toLowerCase();if(document.getElementById(r))return;let e=document.createElement("link");e.id=r,e.rel="stylesheet",e.href=`https://fonts.googleapis.com/css2?family=${encodeURIComponent(n)}:wght@400;700&display=swap`,document.head.appendChild(e)},_=function(n){let r=document.createElement("div");return r.className="bd-tuner-section",r.innerHTML=`<div class="bd-tuner-section-label">${n}</div>`,f.appendChild(r),r},C=function(n,r,e,i,t){let d=L(b,e)||"#000000",a=document.createElement("div");a.className="bd-tuner-row",a.innerHTML=`
10
2
  <span class="bd-tuner-label">${r}</span>
11
3
  <span class="bd-tuner-input"><input type="color" value="${d.substring(0,7)}"></span>
12
4
  <span class="bd-tuner-value">${d.substring(0,7)}</span>
13
- `;let s=a.querySelector("input"),c=a.querySelector(".bd-tuner-value");return s.addEventListener("input",l=>{let b=l.target.value;v(m,e,b),c.textContent=b,i&&k(i,b),t&&t(b)}),n.appendChild(a),{setValue(l){v(m,e,l),s.value=l.substring(0,7),c.textContent=l.substring(0,7),i&&k(i,l)}}}function g(n,r,e,i,t,d,a){let s=L(m,e),c=document.createElement("div");c.className="bd-tuner-row bd-tuner-row-stacked",c.innerHTML=`
5
+ `;let s=a.querySelector("input"),c=a.querySelector(".bd-tuner-value");return s.addEventListener("input",l=>{let g=l.target.value;w(b,e,g),c.textContent=g,i&&k(i,g),t&&t(g)}),n.appendChild(a),{setValue(l){w(b,e,l),s.value=l.substring(0,7),c.textContent=l.substring(0,7),i&&k(i,l)}}},m=function(n,r,e,i,t,d,a){let s=L(b,e),c=document.createElement("div");c.className="bd-tuner-row bd-tuner-row-stacked",c.innerHTML=`
14
6
  <div class="bd-tuner-row-top">
15
7
  <span class="bd-tuner-label">${r}</span>
16
8
  <div class="bd-tuner-px-input-wrap">
@@ -19,24 +11,32 @@
19
11
  </div>
20
12
  </div>
21
13
  <input type="range" class="bd-tuner-slider" min="${i}" max="${t}" step="${d}" value="${s}">
22
- `;let l=c.querySelector(".bd-tuner-px-num"),b=c.querySelector(".bd-tuner-slider");function p(o){if(o=Math.max(i,Math.min(t,o)),v(m,e,o),l.value=o,b.value=o,a){let w=I(o);(Array.isArray(a)?a:[a]).forEach(f=>k(f,w))}}l.addEventListener("input",o=>p(parseFloat(o.target.value)||0)),b.addEventListener("input",o=>p(parseFloat(o.target.value))),l.addEventListener("keydown",o=>{if(o.key==="ArrowUp"||o.key==="ArrowDown"){o.preventDefault();let w=o.shiftKey?10:1,f=(o.key==="ArrowUp"?d:-d)*w;p(parseFloat(l.value)+f)}}),n.appendChild(c)}function M(n,r,e,i,t,d,a){let s=L(m,e),c=document.createElement("div");c.className="bd-tuner-row bd-tuner-row-stacked",c.innerHTML=`
14
+ `;let l=c.querySelector(".bd-tuner-px-num"),g=c.querySelector(".bd-tuner-slider");function u(o){if(o=Math.max(i,Math.min(t,o)),w(b,e,o),l.value=o,g.value=o,a){let S=U(o);(Array.isArray(a)?a:[a]).forEach(h=>k(h,S))}}l.addEventListener("input",o=>u(parseFloat(o.target.value)||0)),g.addEventListener("input",o=>u(parseFloat(o.target.value))),l.addEventListener("keydown",o=>{if(o.key==="ArrowUp"||o.key==="ArrowDown"){o.preventDefault();let S=o.shiftKey?10:1,h=(o.key==="ArrowUp"?d:-d)*S;u(parseFloat(l.value)+h)}}),n.appendChild(c)},P=function(n,r,e,i,t,d,a){let s=L(b,e),c=document.createElement("div");c.className="bd-tuner-row bd-tuner-row-stacked",c.innerHTML=`
23
15
  <div class="bd-tuner-row-top">
24
16
  <span class="bd-tuner-label">${r}</span>
25
17
  <span class="bd-tuner-value">${s}</span>
26
18
  </div>
27
19
  <input type="range" class="bd-tuner-slider" min="${i}" max="${t}" step="${d}" value="${s}">
28
- `;let l=c.querySelector(".bd-tuner-slider"),b=c.querySelector(".bd-tuner-value");l.addEventListener("input",p=>{let o=parseFloat(p.target.value);v(m,e,o),b.textContent=o,a&&a(o)}),n.appendChild(c)}function B(n,r,e,i){let t=L(m,e),d=document.createElement("div");d.className="bd-tuner-row",d.innerHTML=`
20
+ `;let l=c.querySelector(".bd-tuner-slider"),g=c.querySelector(".bd-tuner-value");l.addEventListener("input",u=>{let o=parseFloat(u.target.value);w(b,e,o),g.textContent=o,a&&a(o)}),n.appendChild(c)},D=function(n,r,e,i){let t=L(b,e),d=document.createElement("div");d.className="bd-tuner-row",d.innerHTML=`
29
21
  <span class="bd-tuner-label">${r}</span>
30
22
  <span class="bd-tuner-input bd-tuner-font-input">
31
23
  <input type="text" class="bd-tuner-font-search" value="${t}" placeholder="Search fonts...">
32
24
  <div class="bd-tuner-font-dropdown"></div>
33
25
  </span>
34
- `;let a=d.querySelector(".bd-tuner-font-search"),s=d.querySelector(".bd-tuner-font-dropdown"),c=b=>z.some(p=>p.toLowerCase()===b.toLowerCase());function l(b=""){let p=q.filter(o=>o.toLowerCase().includes(b.toLowerCase())).slice(0,20);s.innerHTML=p.map(o=>{let w=c(o)?' <span style="opacity:0.4;font-size:9px">SYSTEM</span>':"";return`<div class="bd-tuner-font-option" data-font="${o}" style="font-family:'${o}',system-ui">${o}${w}</div>`}).join(""),p.filter(o=>!c(o)).forEach($),s.querySelectorAll(".bd-tuner-font-option").forEach(o=>{o.addEventListener("mousedown",w=>{w.preventDefault();let f=o.dataset.font;a.value=f,v(m,e,f),c(f)||$(f),k(i,`"${f}", system-ui, sans-serif`),s.classList.remove("open")})})}a.addEventListener("focus",()=>{l(a.value),s.classList.add("open")}),a.addEventListener("input",()=>{l(a.value),s.classList.add("open")}),a.addEventListener("blur",()=>{setTimeout(()=>s.classList.remove("open"),150)}),a.addEventListener("keydown",b=>{if(b.key==="Enter"){let p=a.value.trim();p&&(v(m,e,p),c(p)||$(p),k(i,`"${p}", system-ui, sans-serif`),s.classList.remove("open"),a.blur())}}),n.appendChild(d)}function N(n,r,e,i,t){let d=L(m,e),a=document.createElement("div");a.className="bd-tuner-row bd-tuner-row-stacked",a.innerHTML=`
26
+ `;let a=d.querySelector(".bd-tuner-font-search"),s=d.querySelector(".bd-tuner-font-dropdown"),c=g=>z.some(u=>u.toLowerCase()===g.toLowerCase());function l(g=""){let u=q.filter(o=>o.toLowerCase().includes(g.toLowerCase())).slice(0,20);s.innerHTML=u.map(o=>{let S=c(o)?' <span style="opacity:0.4;font-size:9px">SYSTEM</span>':"";return`<div class="bd-tuner-font-option" data-font="${o}" style="font-family:'${o}',system-ui">${o}${S}</div>`}).join(""),u.filter(o=>!c(o)).forEach($),s.querySelectorAll(".bd-tuner-font-option").forEach(o=>{o.addEventListener("mousedown",S=>{S.preventDefault();let h=o.dataset.font;a.value=h,w(b,e,h),c(h)||$(h),k(i,`"${h}", system-ui, sans-serif`),s.classList.remove("open")})})}a.addEventListener("focus",()=>{l(a.value),s.classList.add("open")}),a.addEventListener("input",()=>{l(a.value),s.classList.add("open")}),a.addEventListener("blur",()=>{setTimeout(()=>s.classList.remove("open"),150)}),a.addEventListener("keydown",g=>{if(g.key==="Enter"){let u=a.value.trim();u&&(w(b,e,u),c(u)||$(u),k(i,`"${u}", system-ui, sans-serif`),s.classList.remove("open"),a.blur())}}),n.appendChild(d)},B=function(n,r,e,i,t){let d=L(b,e),a=document.createElement("div");a.className="bd-tuner-row bd-tuner-row-stacked",a.innerHTML=`
35
27
  <span class="bd-tuner-label">${r}</span>
36
28
  <div class="bd-tuner-segmented">
37
29
  ${i.map(s=>`<button class="bd-tuner-seg-btn${s===d?" active":""}" data-val="${s}">${s}</button>`).join("")}
38
30
  </div>
39
- `,a.querySelectorAll(".bd-tuner-seg-btn").forEach(s=>{s.addEventListener("click",()=>{a.querySelectorAll(".bd-tuner-seg-btn").forEach(l=>l.classList.remove("active")),s.classList.add("active");let c=s.dataset.val;v(m,e,c),t&&t(c)})}),n.appendChild(a)}var T=E("Colors");C(T,"Background","colors.background","--bd-color-background");var D;C(T,"Primary","colors.primary","--bd-color-primary",n=>{D.setValue(n),S("colorFront",n)});C(T,"Text","colors.text","--bd-color-text");C(T,"CTA Background","colors.ctaBackground","--bd-color-cta-bg");C(T,"CTA Text","colors.ctaText","--bd-color-cta-text");D=C(T,"Shader Front","colors.shaderFront",null,n=>S("colorFront",n));var y=E("Typography");B(y,"Primary Font","typography.primaryFont","--bd-font-primary");B(y,"Secondary Font","typography.secondaryFont","--bd-font-secondary");g(y,"Headline Size","typography.headline.referencePx",32,300,1,"--bd-headline-size");g(y,"Headline LH","typography.headline.lineHeightPx",24,280,1,"--bd-headline-lh");g(y,"Sub Size","typography.subHeadline.referencePx",10,48,1,"--bd-subheadline-size");g(y,"Sub LH","typography.subHeadline.lineHeightPx",12,80,1,"--bd-subheadline-lh");g(y,"Logo Size","typography.logo.referencePx",12,80,1,"--bd-logo-size");g(y,"Nav Size","typography.navItem.referencePx",10,48,1,"--bd-nav-size");var h=E("Spacing");g(h,"Header Pad X","spacing.headerPaddingX",0,80,1,"--bd-header-px");g(h,"Header Pad Y","spacing.headerPaddingY",0,60,1,"--bd-header-py");g(h,"Hero Pad Top","spacing.heroPaddingTop",0,120,1,"--bd-hero-pt");g(h,"Hero Pad Bottom","spacing.heroPaddingBottom",0,120,1,"--bd-hero-pb");g(h,"Hero Pad X","spacing.heroPaddingX",0,120,1,"--bd-hero-px");g(h,"Nav Gap","spacing.navGap",0,100,1,"--bd-nav-gap");g(h,"CTA Pad X","spacing.ctaPaddingX",0,60,1,"--bd-cta-px");g(h,"CTA Pad Y","spacing.ctaPaddingY",0,30,1,"--bd-cta-py");g(h,"CTA Radius","spacing.ctaBorderRadius",0,32,1,"--bd-cta-radius");var F=E("Shader");N(F,"Shape","shader.shape",["warp","simplex","dots","wave","ripple","swirl","sphere"],n=>S("shape",n));N(F,"Dither Type","shader.type",["random","2x2","4x4","8x8"],n=>S("type",n));M(F,"Speed","shader.speed",0,2,.01,n=>S("speed",n));M(F,"Scale","shader.scale",.1,5,.01,n=>S("scale",n));M(F,"Dither Size","shader.size",.5,10,.1,n=>S("size",n));var U=E("Opacity");M(U,"Nav Links","opacity.navLinks",0,1,.01,n=>k("--bd-nav-opacity",n));var u=document.createElement("button");u.id="bd-tuner-commit";u.textContent="Commit Changes";var _=null;async function H(){let n=JSON.stringify(m,null,2);try{let t=await fetch("/__bluedither/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:n});if(t.ok&&(await t.json()).ok)return"saved"}catch{}try{let t=await fetch("http://localhost:3344/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:n});if(t.ok&&(await t.json()).ok)return"saved"}catch{}if(O)try{let t=await fetch("/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:n});if(t.ok&&(await t.json()).ok)return"saved"}catch{}if(window.showSaveFilePicker)try{_||(_=await window.showSaveFilePicker({suggestedName:"tokens.json",types:[{description:"JSON",accept:{"application/json":[".json"]}}]}));let t=await _.createWritable();return await t.write(n),await t.close(),"saved"}catch(t){if(t.name==="AbortError")return"cancelled";_=null}let r=new Blob([n],{type:"application/json"}),e=URL.createObjectURL(r),i=document.createElement("a");return i.href=e,i.download="tokens.json",i.click(),URL.revokeObjectURL(e),"downloaded"}u.onclick=async()=>{u.textContent="Saving...",u.disabled=!0;try{let n=await H();if(n==="cancelled"){u.textContent="Commit Changes",u.disabled=!1;return}u.textContent=n==="saved"?"Saved!":"Downloaded!",u.classList.add("success"),setTimeout(()=>{u.textContent="Commit Changes",u.classList.remove("success"),u.disabled=!1},2e3)}catch(n){u.textContent="Error: "+n.message,u.disabled=!1,setTimeout(()=>{u.textContent="Commit Changes"},3e3)}};x.appendChild(u);var R=document.createElement("style");R.textContent=`/* =============================================
31
+ `,a.querySelectorAll(".bd-tuner-seg-btn").forEach(s=>{s.addEventListener("click",()=>{a.querySelectorAll(".bd-tuner-seg-btn").forEach(l=>l.classList.remove("active")),s.classList.add("active");let c=s.dataset.val;w(b,e,c),t&&t(c)})}),n.appendChild(a)};window.__BD_TUNER_LOADED__=!0;let b=structuredClone(window.__BD_TOKENS__||JSON.parse(document.querySelector('script[type="application/json"][data-bluedither-tokens]')?.textContent||"{}")),O=structuredClone(window.__BD_DEFAULTS__||JSON.parse(document.querySelector('script[type="application/json"][data-bluedither-defaults]')?.textContent||"{}")),H=!!(window.__BD_TOKENS__&&window.__BD_DEFAULTS__)||!!window.__BD_TUNER_SERVER_MODE__,z=["Arial","Arial Black","Bebas Neue Pro","Consolas","Courier New","Georgia","Helvetica","Impact","Lucida Console","Segoe UI","Tahoma","Times New Roman","Trebuchet MS","Verdana","SF Pro Display","SF Mono","Cascadia Code","Menlo","Monaco"],j=["Bebas Neue","Space Mono","Inter","Roboto","Roboto Mono","Roboto Condensed","Open Sans","Montserrat","Lato","Oswald","Raleway","Poppins","Nunito","Playfair Display","Merriweather","Source Sans 3","Source Code Pro","PT Sans","PT Serif","PT Mono","Ubuntu","Ubuntu Mono","Fira Sans","Fira Code","Fira Mono","Work Sans","Noto Sans","Noto Serif","DM Sans","DM Serif Display","DM Mono","IBM Plex Sans","IBM Plex Mono","IBM Plex Serif","JetBrains Mono","Inconsolata","Space Grotesk","Archivo","Archivo Black","Barlow","Barlow Condensed","Lexend","Outfit","Sora","Manrope","Bitter","Crimson Text","Libre Baskerville","Abril Fatface","Anton","Permanent Marker","Righteous","Orbitron","Teko","Rubik","Quicksand","Cabin","Karla","Josefin Sans","Comfortaa","Fredoka","Geologica","Instrument Sans","Instrument Serif"],q=[...new Set([...z,...j])].sort(),f=document.createElement("div");f.id="bd-tuner";let F=document.createElement("button");F.id="bd-tuner-toggle",F.textContent="Tuner",F.onclick=()=>f.classList.remove("collapsed"),document.body.appendChild(f),document.body.appendChild(F),f.innerHTML=`
32
+ <div class="bd-tuner-title">
33
+ <span>BlueDither Tuner</span>
34
+ <div style="display:flex;gap:8px;align-items:center;">
35
+ <button id="bd-tuner-reset" title="Reset to defaults">&#8635;</button>
36
+ <button id="bd-tuner-close" title="Close">&times;</button>
37
+ </div>
38
+ </div>
39
+ `,f.querySelector("#bd-tuner-close").onclick=()=>f.classList.add("collapsed"),f.querySelector("#bd-tuner-reset").onclick=async()=>{confirm("Reset all tokens to defaults?")&&(Object.assign(b,structuredClone(O)),await R(),location.reload())};let T=_("Colors");C(T,"Background","colors.background","--bd-bg");let N;C(T,"Primary","colors.primary","--bd-primary",n=>{N.setValue(n),v("colorFront",n)}),C(T,"Text","colors.text","--bd-text"),C(T,"CTA Background","colors.ctaBackground","--bd-cta-bg"),C(T,"CTA Text","colors.ctaText","--bd-cta-text"),N=C(T,"Shader Front","colors.shaderFront",null,n=>v("colorFront",n));let y=_("Typography");D(y,"Primary Font","typography.primaryFont","--bd-font-primary"),D(y,"Secondary Font","typography.secondaryFont","--bd-font-secondary"),m(y,"Headline Size","typography.headline.referencePx",32,300,1,"--bd-headline-size"),m(y,"Headline LH","typography.headline.lineHeightPx",24,280,1,"--bd-headline-lh"),m(y,"Sub Size","typography.subHeadline.referencePx",10,48,1,"--bd-sub-size"),m(y,"Sub LH","typography.subHeadline.lineHeightPx",12,80,1,"--bd-sub-lh"),m(y,"Logo Size","typography.logo.referencePx",12,80,1,"--bd-logo-size"),m(y,"Nav Size","typography.navItem.referencePx",10,48,1,"--bd-nav-size");let x=_("Spacing");m(x,"Header Pad X","spacing.headerPaddingX",0,80,1,"--bd-header-px"),m(x,"Header Pad Y","spacing.headerPaddingY",0,60,1,"--bd-header-py"),m(x,"Hero Pad Top","spacing.heroPaddingTop",0,120,1,"--bd-hero-pt"),m(x,"Hero Pad Bottom","spacing.heroPaddingBottom",0,120,1,"--bd-hero-pb"),m(x,"Hero Pad X","spacing.heroPaddingX",0,120,1,"--bd-hero-px"),m(x,"Nav Gap","spacing.navGap",0,100,1,"--bd-nav-gap"),m(x,"CTA Pad X","spacing.ctaPaddingX",0,60,1,"--bd-cta-px"),m(x,"CTA Pad Y","spacing.ctaPaddingY",0,30,1,"--bd-cta-py"),m(x,"CTA Radius","spacing.ctaBorderRadius",0,32,1,"--bd-cta-radius");let E=_("Shader");B(E,"Shape","shader.shape",["warp","simplex","dots","wave","ripple","swirl","sphere"],n=>v("shape",n)),B(E,"Dither Type","shader.type",["random","2x2","4x4","8x8"],n=>v("type",n)),P(E,"Speed","shader.speed",0,2,.01,n=>v("speed",n)),P(E,"Scale","shader.scale",.1,5,.01,n=>v("scale",n)),P(E,"Dither Size","shader.size",.5,10,.1,n=>v("size",n));let I=_("Opacity");P(I,"Nav Links","opacity.navLinks",0,1,.01,n=>k("--bd-nav-opacity",n));let p=document.createElement("button");p.id="bd-tuner-commit",p.textContent="Commit Changes";let M=null;async function R(){let n=JSON.stringify(b,null,2);try{let t=await fetch("/__bluedither/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:n});if(t.ok&&(await t.json()).ok)return"saved"}catch{}try{let t=await fetch("http://localhost:3344/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:n});if(t.ok&&(await t.json()).ok)return"saved"}catch{}if(H)try{let t=await fetch("/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:n});if(t.ok&&(await t.json()).ok)return"saved"}catch{}if(window.showSaveFilePicker)try{M||(M=await window.showSaveFilePicker({suggestedName:"tokens.json",types:[{description:"JSON",accept:{"application/json":[".json"]}}]}));let t=await M.createWritable();return await t.write(n),await t.close(),"saved"}catch(t){if(t.name==="AbortError")return"cancelled";M=null}let r=new Blob([n],{type:"application/json"}),e=URL.createObjectURL(r),i=document.createElement("a");return i.href=e,i.download="tokens.json",i.click(),URL.revokeObjectURL(e),"downloaded"}p.onclick=async()=>{p.textContent="Saving...",p.disabled=!0;try{let n=await R();if(n==="cancelled"){p.textContent="Commit Changes",p.disabled=!1;return}p.textContent=n==="saved"?"Saved!":"Downloaded!",p.classList.add("success"),setTimeout(()=>{p.textContent="Commit Changes",p.classList.remove("success"),p.disabled=!1},2e3)}catch(n){p.textContent="Error: "+n.message,p.disabled=!1,setTimeout(()=>{p.textContent="Commit Changes"},3e3)}},f.appendChild(p)}var A=document.createElement("style");A.textContent=`/* =============================================
40
40
  BlueDither Fine-Tuner \u2014 Overlay Panel v2
41
41
  ============================================= */
42
42
 
@@ -398,4 +398,4 @@
398
398
  background: rgba(255, 255, 255, 0.1);
399
399
  border-radius: 2px;
400
400
  }
401
- `;document.head.appendChild(R);})();
401
+ `;document.head.appendChild(A);})();
@@ -10,6 +10,10 @@
10
10
  */
11
11
 
12
12
  (async function () {
13
+ // Prevent double-init (React StrictMode re-fires effects in dev)
14
+ if (window.__BD_INJECT_LOADED__) return;
15
+ window.__BD_INJECT_LOADED__ = true;
16
+
13
17
  // Find the base path to bluedither/ directory
14
18
  const scriptEl = document.currentScript;
15
19
  const scriptSrc = scriptEl?.src || '';
@@ -9,6 +9,10 @@
9
9
  * - Real-time shader parameter updates
10
10
  */
11
11
 
12
+ // Prevent double-init (React StrictMode re-fires effects in dev)
13
+ if (!window.__BD_TUNER_LOADED__) {
14
+ window.__BD_TUNER_LOADED__ = true;
15
+
12
16
  const tokens = structuredClone(
13
17
  window.__BD_TOKENS__ ||
14
18
  JSON.parse(document.querySelector('script[type="application/json"][data-bluedither-tokens]')?.textContent || '{}')
@@ -341,17 +345,17 @@ function addSegmented(section, label, tokenPath, options, extraCb) {
341
345
 
342
346
  // ── Colors ──
343
347
  const colorsSection = addSection('Colors');
344
- addColor(colorsSection, 'Background', 'colors.background', '--bd-color-background');
348
+ addColor(colorsSection, 'Background', 'colors.background', '--bd-bg');
345
349
  // Shader Front is declared first (but appended later) so Primary can reference it
346
350
  let shaderFrontHandle;
347
- addColor(colorsSection, 'Primary', 'colors.primary', '--bd-color-primary', (v) => {
351
+ addColor(colorsSection, 'Primary', 'colors.primary', '--bd-primary', (v) => {
348
352
  // Sync shader front color: update token, UI, and live shader
349
353
  shaderFrontHandle.setValue(v);
350
354
  updateShader('colorFront', v);
351
355
  });
352
- addColor(colorsSection, 'Text', 'colors.text', '--bd-color-text');
353
- addColor(colorsSection, 'CTA Background', 'colors.ctaBackground', '--bd-color-cta-bg');
354
- addColor(colorsSection, 'CTA Text', 'colors.ctaText', '--bd-color-cta-text');
356
+ addColor(colorsSection, 'Text', 'colors.text', '--bd-text');
357
+ addColor(colorsSection, 'CTA Background', 'colors.ctaBackground', '--bd-cta-bg');
358
+ addColor(colorsSection, 'CTA Text', 'colors.ctaText', '--bd-cta-text');
355
359
  shaderFrontHandle = addColor(colorsSection, 'Shader Front', 'colors.shaderFront', null, (v) => updateShader('colorFront', v));
356
360
 
357
361
  // ── Typography ──
@@ -360,8 +364,8 @@ addFontDropdown(typoSection, 'Primary Font', 'typography.primaryFont', '--bd-fon
360
364
  addFontDropdown(typoSection, 'Secondary Font', 'typography.secondaryFont', '--bd-font-secondary');
361
365
  addPxField(typoSection, 'Headline Size', 'typography.headline.referencePx', 32, 300, 1, '--bd-headline-size');
362
366
  addPxField(typoSection, 'Headline LH', 'typography.headline.lineHeightPx', 24, 280, 1, '--bd-headline-lh');
363
- addPxField(typoSection, 'Sub Size', 'typography.subHeadline.referencePx', 10, 48, 1, '--bd-subheadline-size');
364
- addPxField(typoSection, 'Sub LH', 'typography.subHeadline.lineHeightPx', 12, 80, 1, '--bd-subheadline-lh');
367
+ addPxField(typoSection, 'Sub Size', 'typography.subHeadline.referencePx', 10, 48, 1, '--bd-sub-size');
368
+ addPxField(typoSection, 'Sub LH', 'typography.subHeadline.lineHeightPx', 12, 80, 1, '--bd-sub-lh');
365
369
  addPxField(typoSection, 'Logo Size', 'typography.logo.referencePx', 12, 80, 1, '--bd-logo-size');
366
370
  addPxField(typoSection, 'Nav Size', 'typography.navItem.referencePx', 10, 48, 1, '--bd-nav-size');
367
371
 
@@ -499,3 +503,4 @@ commitBtn.onclick = async () => {
499
503
  }
500
504
  };
501
505
  panel.appendChild(commitBtn);
506
+ } // end guard
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bluedither",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "A bold, dithered-shader hero theme for Claude Code — skill + fine-tuner",
5
5
  "type": "module",
6
6
  "bin": {