diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-12 21:26:16 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-12 21:26:16 -0500 |
| commit | 7e081036a5a29316b702a58b28a1ce21c685d4a4 (patch) | |
| tree | 0c8ebfa224ca689cadc2d89cccda8d31686679c2 /docs/prototypes/panel-widget-gallery.html | |
| parent | 933a5f8658498bbcaa9bf47006a94c8b260e80a5 (diff) | |
| download | archsetup-7e081036a5a29316b702a58b28a1ce21c685d4a4.tar.gz archsetup-7e081036a5a29316b702a58b28a1ce21c685d4a4.zip | |
refactor(gallery): extract controls N01-N10 into GW builders
Rocker, transport cluster, preset bank, dual knob, encoder, key switch, crossfader, thumbwheel, DIP bank, and jog wheel move into widgets.js; their inline onclick globals (transport/preset/keyTurn/dip) become listeners inside the builders. Transport takes an explicit animate option so reduced-motion behavior is the consumer's call; its initial paint leaves reel play-state to CSS, matching load behavior. Probes green plus the per-widget behavioral pass (43 checks).
Diffstat (limited to 'docs/prototypes/panel-widget-gallery.html')
| -rw-r--r-- | docs/prototypes/panel-widget-gallery.html | 97 |
1 files changed, 11 insertions, 86 deletions
diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html index a6d40c9..947fd16 100644 --- a/docs/prototypes/panel-widget-gallery.html +++ b/docs/prototypes/panel-widget-gallery.html @@ -1584,60 +1584,34 @@ card(C,'25','Slide-rule dial', (st,rd)=>GW.slideRule(st,{onChange:(v,t)=>rd(t)}), '<b>value on a printed scale.</b> A lit pointer glides a warm-backlit strip. Click a mark to jump, or focus it and press ←/→ (↑/↓); readout shows it.'); card(C,'N01','Rocker power switch', - `<span class="rocker on" id="rocker"><span class="half top">ON</span><span class="half bot">OFF</span></span>`, + (st,rd)=>GW.rocker(st,{on:true,onChange:(v,t)=>rd(t)}), '<b>hard on / off, lit legend.</b> A master power paddle — the pressed half glows. Click to rock.'); card(C,'N02','Transport cluster', - `<div style="display:flex;flex-direction:column;gap:6px;align-items:center"> - <div class="reels"><span class="reel spin"><i></i><i></i><i></i></span><span class="reel spin"><i></i><i></i><i></i></span></div> - <div class="transport" id="tport"> - <button class="tbtn" data-t="rew" onclick="transport(this)">⏮</button> - <button class="tbtn on" data-t="play" onclick="transport(this)">▶</button> - <button class="tbtn" data-t="stop" onclick="transport(this)">⏹</button> - <button class="tbtn rec" data-t="rec" onclick="transport(this)">⏺</button> - </div></div>`, + (st,rd)=>GW.transport(st,{mode:'play',animate:!reduced,onChange:(m,t)=>rd(t)}), '<b>run / pause / capture.</b> One mode lit at a time, reels turn while it plays. Click a button.'); card(C,'N03','Radio preset bank', - `<div class="radiobank" id="rbank"> - <button class="preset on" onclick="preset(this)">WIFI</button> - <button class="preset" onclick="preset(this)">ETH</button> - <button class="preset" onclick="preset(this)">CELL</button> - <button class="preset" onclick="preset(this)">OFF</button> - </div>`, + (st,rd)=>GW.presetBank(st,{onChange:(i,t)=>rd(t)}), '<b>pick one, the rest release.</b> The car-radio preset row — mechanically exclusive. Click one.'); card(C,'N04','Concentric dual knob', - `<span class="dualknob"> - <span class="outer" id="dko"><span class="tick" style="transform:rotate(-120deg)"></span><span class="tick" style="transform:rotate(120deg)"></span></span> - <span class="inner" id="dki"><span class="ind"></span></span> - </span>`, + (st,rd)=>GW.dualKnob(st,{outer:50,inner:50,onChange:(o,i)=>rd('bass '+Math.round(o)+' · treble '+Math.round(i))}), '<b>two values on one spindle.</b> Bass / treble, coarse / fine. Drag the outer ring or inner cap — each is independent.'); card(C,'N05','Rotary encoder + LED ring', - `<span class="encoder" id="enc"></span>`, + (st,rd)=>GW.encoder(st,{value:7,onChange:(v,t)=>rd(t)}), '<b>endless dial, lit position.</b> A detentless encoder; the LED arc lights to the level and the value keeps accumulating. Drag to turn.'); card(C,'N06','Keyed mode switch', - `<span class="keylock" id="keylock6"> - <span class="kpos" style="left:16%;top:64%">OFF</span><span class="kpos on" style="left:50%;top:12%">ON</span><span class="kpos" style="left:84%;top:64%">RUN</span> - <span class="body" onclick="keyTurn()"><span class="bit" id="kbit"></span><span class="barrel"></span></span> - </span>`, + (st,rd)=>GW.keySwitch(st,{index:1,onChange:(i,t)=>rd(t)}), '<b>guarded three-position mode.</b> Off · on · run. The key-bit points at the live position. Click to turn.'); card(C,'N07','Center-detented crossfader', - `<div class="xfader" id="xf"> - <div class="slot"></div><div class="detent"></div> - <span class="end" style="left:0">A</span><span class="end" style="right:0">B</span> - <div class="cap" id="xfcap" style="left:50%"></div> - </div>`, + (st,rd)=>GW.crossfader(st,{onChange:(v,t)=>rd(t)}), '<b>throw to either side of zero.</b> A fader notched at center — balance, L/R mix. Drag; readout shows the signed value.'); card(C,'N08','Thumbwheel', - `<div class="thumbw"><span class="thumbwheel" id="thumbwheel"></span><span class="win" id="thval">42</span></div>`, + (st,rd)=>GW.thumbwheel(st,{value:42,onChange:(v,t)=>rd(t)}), '<b>ribbed edge-wheel, one value.</b> A knurled wheel with a windowed number. Drag up/down to roll.'); card(C,'N09','DIP-switch bank', - `<span class="dip" id="dips"> - <span class="dipsw on" onclick="dip(this)"><i></i></span><span class="dipsw" onclick="dip(this)"><i></i></span> - <span class="dipsw on" onclick="dip(this)"><i></i></span><span class="dipsw on" onclick="dip(this)"><i></i></span> - <span class="dipsw" onclick="dip(this)"><i></i></span><span class="dipsw" onclick="dip(this)"><i></i></span> - </span>`, + (st,rd)=>GW.dipBank(st,{onChange:(w,t)=>rd(t)}), '<b>a bank of hard flags.</b> Hardware slide switches — up is on. Click each to flip; readout is the binary word.'); card(C,'N10','Jog / shuttle wheel', - `<span class="jog" id="jog10"><span class="shuttle" style="--sh:40deg"></span><span class="inner" id="jogi"><span class="dimple"></span></span></span>`, + (st,rd)=>GW.jogWheel(st,{onChange:(v,t)=>rd(t)}), '<b>scrub fine, shuttle fast.</b> The edit-deck wheel. Drag to jog the inner wheel; readout shows the position.'); card(C,'R02','Calibrated vernier dial', `<svg id="vern" class="rsvg drag" viewBox="0 0 150 150" width="150" height="150"></svg>`, @@ -1928,56 +1902,7 @@ card(I,'R52','Blinkenlights front panel', /* ============ CONTROL WIRING ============ */ /* 01 toggle */ -/* 01-09, 24, 25 extracted to widgets.js (GW.*) — wired at their card records */ -/* N01 rocker */ -$('rocker').onclick=()=>{$('rocker').classList.toggle('on');setRd('N01',$('rocker').classList.contains('on')?'ON':'OFF');}; -setRd('N01','ON'); -/* N02 transport */ -function transport(b){b.parentElement.querySelectorAll('.tbtn').forEach(x=>x.classList.remove('on'));b.classList.add('on'); - const playing=b.dataset.t==='play';document.querySelectorAll('.reel.spin').forEach(r=>r.style.animationPlayState=playing&&!reduced?'running':'paused'); - setRd('N02',{rew:'REW',play:'PLAY',stop:'STOP',rec:'REC'}[b.dataset.t]);} -setRd('N02','PLAY'); -/* N03 radio preset */ -function preset(b){b.parentElement.querySelectorAll('.preset').forEach(x=>x.classList.remove('on'));b.classList.add('on');setRd('N03',b.textContent);} -setRd('N03','WIFI'); -/* N04 concentric dual knob */ -let dkoV=50,dkiV=50; -function setDual(){$('dko').style.transform=`rotate(${-150+dkoV/100*300}deg)`;$('dki').style.transform=`rotate(${-150+dkiV/100*300}deg)`; - setRd('N04','bass '+Math.round(dkoV)+' · treble '+Math.round(dkiV));} -dragDelta($('dko'),()=>dkoV,v=>{dkoV=v;setDual();},{min:0,max:100}); -dragDelta($('dki'),()=>dkiV,v=>{dkiV=v;setDual();},{min:0,max:100,stop:true}); -setDual(); -/* N05 encoder */ -let encV=7; -function paintEnc(){const leds=$('enc').querySelectorAll('.led');const lit=((Math.floor(encV)%12)+12)%12; - leds.forEach((l,i)=>l.classList.toggle('on',i<=lit));} -function setEnc(v){encV=v;paintEnc();const ind=$('enc').querySelector('.knob .ind');if(ind)ind.parentElement.style.transform=`rotate(${encV*30}deg)`; - setRd('N05','pos '+Math.round(encV));} -(function(){const enc=$('enc');const R=27,cx=33,cy=33; - for(let i=0;i<12;i++){const a=(i*30-90)*Math.PI/180;const d=document.createElement('span');d.className='led'; - d.style.left=(cx+R*Math.cos(a))+'px';d.style.top=(cy+R*Math.sin(a))+'px';enc.appendChild(d);} - const k=document.createElement('span');k.className='knob';k.innerHTML='<span class="ind"></span>';enc.appendChild(k);})(); -dragDelta($('enc'),()=>encV,setEnc,{min:0,max:100000,sens:0.25});setEnc(7); -/* N06 keylock */ -let keyIdx=1;const keyAng=[-70,0,70];const keyNm=['OFF','ON','RUN']; -function keyTurn(){keyIdx=(keyIdx+1)%3;$('kbit').style.transform=`rotate(${keyAng[keyIdx]}deg)`; - $('keylock6').querySelectorAll('.kpos').forEach((p,i)=>p.classList.toggle('on',i===keyIdx));setRd('N06',keyNm[keyIdx]);} -setRd('N06','ON'); -/* N07 crossfader */ -function setXf(p){$('xfcap').style.left=p+'%';const v=Math.round(p-50);setRd('N07',(v>0?'+':'')+v);} -dragX($('xf'),setXf);setXf(50); -/* N08 thumbwheel */ -let thumbV=42; -function setThumb(v){thumbV=Math.round(v);const s=(((thumbV%100)+100)%100);$('thval').textContent=String(s).padStart(2,'0');setRd('N08','value '+s);} -dragDelta($('thumbwheel'),()=>thumbV,setThumb,{min:0,max:99,sens:0.2});setThumb(42); -/* N09 DIP */ -function dipUpd(){const bits=[...$('dips').querySelectorAll('.dipsw')].map(x=>x.classList.contains('on')?'1':'0').join('');setRd('N09',bits);} -function dip(s){s.classList.toggle('on');dipUpd();} -dipUpd(); -/* N10 jog */ -let jogV=0; -function setJog(v){jogV=v;$('jogi').style.transform=`rotate(${jogV*4}deg)`;setRd('N10','pos '+Math.round(jogV));} -dragDelta($('jog10'),()=>jogV,setJog,{min:-100000,max:100000,sens:0.5});setJog(0); +/* 01-09, 24, 25, N01-N10 extracted to widgets.js (GW.*) — wired at their card records */ /* ============ METER WIRING (drag-driven) ============ */ /* 10 needle gauge */ |
