aboutsummaryrefslogtreecommitdiff
path: root/docs/prototypes/panel-widget-gallery.html
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-12 21:08:41 -0500
committerCraig Jennings <c@cjennings.net>2026-07-12 21:08:41 -0500
commitacee657f802bd71c2a0cc999c0f1eeaa82c12651 (patch)
treea83365227542c30dce5363462939dc58acb84c85 /docs/prototypes/panel-widget-gallery.html
parent3ae44b636f5f55e9fe50e15fdfe7fe6ddfb6d1a9 (diff)
downloadarchsetup-acee657f802bd71c2a0cc999c0f1eeaa82c12651.tar.gz
archsetup-acee657f802bd71c2a0cc999c0f1eeaa82c12651.zip
refactor(gallery): extract the shared engine into widgets.js
First componentization batch per the component-generation spec: widgets.js is a classic script exposing the GW namespace (svgEl, polar, drag helpers, seg7, buildBars, VU law, SCREEN_FAMS) plus a css-injection scaffold that grows as builders move in. The gallery loads it via a relative script src and destructures the helpers, so file:// keeps working. Probes green.
Diffstat (limited to 'docs/prototypes/panel-widget-gallery.html')
-rw-r--r--docs/prototypes/panel-widget-gallery.html77
1 files changed, 6 insertions, 71 deletions
diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html
index 1ffd302..d6e847b 100644
--- a/docs/prototypes/panel-widget-gallery.html
+++ b/docs/prototypes/panel-widget-gallery.html
@@ -692,8 +692,10 @@ h2::after{content:"";height:1px;background:var(--wash);flex:1}
<div class="palgrid" id="palette"></div>
</div>
+<script src="widgets.js"></script>
<script>
const $ = id => document.getElementById(id);
+const {svgEl,polar,dragX,dragY,dragDelta,seg7,buildBars,VUDB,vuDb,SCREEN_FAMS}=GW;
const reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
document.querySelectorAll('.szbar .key').forEach(b=>b.addEventListener('click',()=>{
document.body.dataset.size=b.dataset.sz;
@@ -777,32 +779,7 @@ const PALETTE=[
white = monochrome LCD/CRT white
Exploration data, deliberately NOT in tokens.json yet — families get tokenized once picked,
the same way amber earned its tokens. Values keyed by the CSS custom property they drive. */
-const SCREEN_FAMS={
- green:{'--scr-hi':'#7fe0a0','--scr-ink':'#58b87e','--scr-dim':'#3d5c46',
- '--scr-bg1':'#0a120c','--scr-bg2':'#050c07','--scr-bgc':'#04140a','--scr-bge':'#020a05','--scr-brd':'#123018',
- '--scr-grat':'rgba(111,206,51,.18)','--scr-gratc':'rgba(111,206,51,.35)','--scr-glow':'rgba(127,224,160,.8)',
- '--crt-face1':'#b9d8c0','--crt-face2':'#8bb296','--crt-glow':'#eef7ee'},
- amber:{'--scr-hi':'#ffbe54','--scr-ink':'#e2a038','--scr-dim':'#7d5c16',
- '--scr-bg1':'#140d06','--scr-bg2':'#0a0705','--scr-bgc':'#140d06','--scr-bge':'#0a0603','--scr-brd':'#33230e',
- '--scr-grat':'rgba(226,160,56,.18)','--scr-gratc':'rgba(226,160,56,.35)','--scr-glow':'rgba(255,190,84,.8)',
- '--crt-face1':'#d8cba6','--crt-face2':'#b3a276','--crt-glow':'#ffe7c0'},
- red:{'--scr-hi':'#ff9a4c','--scr-ink':'#e0742e','--scr-dim':'#5c3416',
- '--scr-bg1':'#140a05','--scr-bg2':'#0c0603','--scr-bgc':'#140a05','--scr-bge':'#0a0502','--scr-brd':'#331c0c',
- '--scr-grat':'rgba(224,116,46,.18)','--scr-gratc':'rgba(224,116,46,.35)','--scr-glow':'rgba(255,154,76,.8)',
- '--crt-face1':'#d8b9a6','--crt-face2':'#b39276','--crt-glow':'#ffdcc0'},
- blue:{'--scr-hi':'#cfe4ff','--scr-ink':'#94b8d8','--scr-dim':'#3a4c60',
- '--scr-bg1':'#0a0e14','--scr-bg2':'#05080c','--scr-bgc':'#0a1018','--scr-bge':'#04070c','--scr-brd':'#16283a',
- '--scr-grat':'rgba(148,184,216,.18)','--scr-gratc':'rgba(148,184,216,.35)','--scr-glow':'rgba(207,228,255,.8)',
- '--crt-face1':'#c2d2dd','--crt-face2':'#93a8b6','--crt-glow':'#eaf2ff'},
- vfd:{'--scr-hi':'#63e6c8','--scr-ink':'#46b89e','--scr-dim':'#1e4a40',
- '--scr-bg1':'#06100d','--scr-bg2':'#040b09','--scr-bgc':'#041410','--scr-bge':'#020a08','--scr-brd':'#0e3028',
- '--scr-grat':'rgba(70,184,158,.18)','--scr-gratc':'rgba(70,184,158,.35)','--scr-glow':'rgba(99,230,200,.8)',
- '--crt-face1':'#b0d8cd','--crt-face2':'#84ada2','--crt-glow':'#dcfff5'},
- white:{'--scr-hi':'#f2f4f2','--scr-ink':'#c8cac8','--scr-dim':'#5a5c5a',
- '--scr-bg1':'#0b0c0b','--scr-bg2':'#070807','--scr-bgc':'#0d0e0d','--scr-bge':'#060706','--scr-brd':'#2a2c2a',
- '--scr-grat':'rgba(200,202,200,.18)','--scr-gratc':'rgba(200,202,200,.35)','--scr-glow':'rgba(242,244,242,.7)',
- '--crt-face1':'#d0d2d0','--crt-face2':'#a8aaa8','--crt-glow':'#f7f7f7'},
-};
+/* SCREEN_FAMS lives in widgets.js (GW.SCREEN_FAMS) */
function screenChips(no,el,fams,def){
const cardEl=el.closest('.card'); if(!cardEl)return;
const row=document.createElement('div'); row.className='famchips';
@@ -1559,42 +1536,7 @@ function card(host, no, name, html, note){
host.appendChild(c); return c;
}
function setRd(no,txt){const e=$('rd-'+no);if(e)e.textContent=txt;}
-function buildBars(el,n){el.innerHTML='';for(let k=0;k<n;k++)el.appendChild(document.createElement('i'));}
-
-/* ---- pointer-drag helpers ---- */
-function dragX(el,onPct){ el.style.touchAction='none';
- const at=e=>{const r=el.getBoundingClientRect();onPct(Math.max(0,Math.min(100,(e.clientX-r.left)/r.width*100)));};
- el.addEventListener('pointerdown',e=>{el.setPointerCapture(e.pointerId);at(e);
- const mv=ev=>at(ev),up=()=>{el.removeEventListener('pointermove',mv);el.removeEventListener('pointerup',up);el.removeEventListener('pointercancel',up);};
- el.addEventListener('pointermove',mv);el.addEventListener('pointerup',up);el.addEventListener('pointercancel',up);e.preventDefault();});
-}
-function dragY(el,onPct){ el.style.touchAction='none';
- const at=e=>{const r=el.getBoundingClientRect();onPct(Math.max(0,Math.min(100,(r.bottom-e.clientY)/r.height*100)));};
- el.addEventListener('pointerdown',e=>{el.setPointerCapture(e.pointerId);at(e);
- const mv=ev=>at(ev),up=()=>{el.removeEventListener('pointermove',mv);el.removeEventListener('pointerup',up);el.removeEventListener('pointercancel',up);};
- el.addEventListener('pointermove',mv);el.addEventListener('pointerup',up);el.addEventListener('pointercancel',up);e.preventDefault();});
-}
-function dragDelta(el,get,set,opts){ opts=opts||{}; el.style.touchAction='none';
- const min=opts.min==null?0:opts.min, max=opts.max==null?100:opts.max, sens=opts.sens||((max-min)/160);
- el.addEventListener('pointerdown',e=>{if(opts.stop)e.stopPropagation();el.setPointerCapture(e.pointerId);
- const y0=e.clientY, v0=get();
- const mv=ev=>{let v=v0+(y0-ev.clientY)*sens;set(Math.max(min,Math.min(max,v)));};
- const up=()=>{el.removeEventListener('pointermove',mv);el.removeEventListener('pointerup',up);el.removeEventListener('pointercancel',up);};
- el.addEventListener('pointermove',mv);el.addEventListener('pointerup',up);el.addEventListener('pointercancel',up);e.preventDefault();});
-}
-
-/* ---- seven-segment digit builder ---- */
-const SEG={'0':'abcdef','1':'bc','2':'abged','3':'abgcd','4':'fbgc','5':'afgcd','6':'afgedc','7':'abc','8':'abcdefg','9':'abcdfg','-':'g',' ':''};
-function hseg(cy){return `5,${cy} 7,${cy-2} 17,${cy-2} 19,${cy} 17,${cy+2} 7,${cy+2}`;}
-function vseg(cx,ty,by){return `${cx},${ty} ${cx-2},${ty+2} ${cx-2},${by-2} ${cx},${by} ${cx+2},${by-2} ${cx+2},${ty+2}`;}
-const SEGPTS={a:hseg(3),g:hseg(22),d:hseg(41),f:vseg(5,4,21),b:vseg(19,4,21),e:vseg(5,23,40),c:vseg(19,23,40)};
-function seg7(ch,cls){
- const lit=SEG[ch]||''; let s=`<svg class="seg7 ${cls||''}" viewBox="0 0 24 44">`;
- for(const k of 'abcdefg'){const on=lit.includes(k);
- const col=on?(cls==='red'?'var(--sevred)':'var(--sevgrn)'):'var(--sevoff)';
- s+=`<polygon points="${SEGPTS[k]}" fill="${col}"/>`;}
- return s+'</svg>';
-}
+/* drag helpers, seg7, buildBars live in widgets.js (GW) */
/* ============ CONTROLS ============ */
const C=$('controls');
@@ -2224,13 +2166,9 @@ setRd('N24','click to cycle');
conns=['0-5','2-7'];draw();window.addEventListener('resize',draw);})();
/* ============ REFERENCE-BATCH (R) WIDGETS — SVG builders ============ */
-const SVGNS='http://www.w3.org/2000/svg';
-function svgEl(parent,tag,attrs){const e=document.createElementNS(SVGNS,tag);
- for(const k in attrs)e.setAttribute(k,attrs[k]);parent.appendChild(e);return e;}
-function polar(cx,cy,r,deg){const a=deg*Math.PI/180;return [cx+r*Math.sin(a),cy-r*Math.cos(a)];}
+/* svgEl, polar, VUDB live in widgets.js (GW) */
/* R01 moving-coil VU: pivot below the face, authentic nonlinear dB scale */
-const VUDB=[[-20,0],[-10,.20],[-7,.31],[-5,.40],[-3,.50],[-2,.58],[-1,.66],[0,.75],[1,.84],[2,.91],[3,1]];
const mcvu={t:.35,needle:null};
(function(){const s=$('mcvu'),cx=75,cy=112,sweep=t=>-43+t*86;
const defs=svgEl(s,'defs',{});
@@ -2353,10 +2291,7 @@ function setBake(v){bakeV=v;bakeIdx.setAttribute('transform',`rotate(${v*2.7-135
setRd('R04',(v/10).toFixed(1)+' / 10');}
dragDelta($('bakek'),()=>bakeV,setBake,{min:0,max:100,sens:0.25});setBake(63);
-/* shared: interpolate a dB reading from a 0..1 sweep position (VU law) */
-function vuDb(t){let i=0;while(i<VUDB.length-2&&VUDB[i+1][1]<t)i++;
- const [d1,t1]=VUDB[i],[d2,t2]=VUDB[i+1];
- return d1+(d2-d1)*Math.max(0,Math.min(1,(t-t1)/(t2-t1)));}
+/* vuDb (VU law) lives in widgets.js (GW) */
/* R05 filter slider bank: one fader per band, arrow caps on black tracks */
const FB_FREQ=[78,136,235,406,701,1210,2090,3620];