Landing page: add PM_X-1 Explorer pane

Adds the Explorer to index.html's VERSIONS list between the Kit and Teacher
panes. file: "/info-explorer.html" since there's no explorer.html widget yet;
the existing replace("/", "/info-") logic is wrapped in an idempotent infoOf()
helper so "Specs & info" doesn't double-prefix it.

info-explorer.html also gets the standard ?embed=1 handler (matches every
other info-*.html), so the landing-page iframe preview strips chrome + auto-
sizes when the pane is selected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Me Here 2026-05-30 20:49:55 -05:00
parent 3192f3debc
commit e80ff9d564
2 changed files with 14 additions and 2 deletions

View file

@ -139,12 +139,16 @@ const SAMPLES = {}; let state = { bpm:120, volume:0.85 }, meters = [], muteWindo
const VERSIONS = [ const VERSIONS = [
{ key:"editor", file:"/editor.html", name:"PM_E1 Editor", chip:"app", h:620, sum:"Design grooves: stack meter lanes, perstep accents/ghosts/mutes, swing &amp; polyrhythm, set lists, perlane dB gain." }, { key:"editor", file:"/editor.html", name:"PM_E1 Editor", chip:"app", h:620, sum:"Design grooves: stack meter lanes, perstep accents/ghosts/mutes, swing &amp; polyrhythm, set lists, perlane dB gain." },
{ key:"kit", file:"/kit.html", name:"PM_K1 Kit", chip:"hw", h:560, sum:"Build it today — a Raspberry Pi Pico on the 52Pi touchscreen kit; tap the 3.5″ screen, joystick tempo, RGB beat light, buzzer. MicroPython firmware included." }, { key:"kit", file:"/kit.html", name:"PM_K1 Kit", chip:"hw", h:560, sum:"Build it today — a Raspberry Pi Pico on the 52Pi touchscreen kit; tap the 3.5″ screen, joystick tempo, RGB beat light, buzzer. MicroPython firmware included." },
{ key:"explorer", file:"/info-explorer.html", name:"PM_X1 Explorer", chip:"hw", h:560, sum:"Offtheshelf — the Pimoroni Explorer (RP2350, 2.8″ LCD, 6 buttons, piezo) as a buttondriven sibling to the Kit. Edit on the web with Live sync; the device mirrors play/stop/tempo/track changes both ways." },
{ key:"teacher", file:"/teacher.html", name:"PM_T1 Teacher", chip:"hw", h:440, sum:"Studio / lesson desk console — colour TFT of every lane, arcade buttons, instrument passthrough." }, { key:"teacher", file:"/teacher.html", name:"PM_T1 Teacher", chip:"hw", h:440, sum:"Studio / lesson desk console — colour TFT of every lane, arcade buttons, instrument passthrough." },
{ key:"stage", file:"/stage.html", name:"PM_S1 Stage", chip:"hw", h:430, sum:"Live foot pedal — two footswitches, expressionpedal tempo, a big floorreadable RGB beat light." }, { key:"stage", file:"/stage.html", name:"PM_S1 Stage", chip:"hw", h:430, sum:"Live foot pedal — two footswitches, expressionpedal tempo, a big floorreadable RGB beat light." },
{ key:"micro", file:"/micro.html", name:"PM_P1 Practice", chip:"hw", h:240, sum:"Inline practice bar — clickable thumbroller, amber 14segment, instrument in/out passthrough." }, { key:"micro", file:"/micro.html", name:"PM_P1 Practice", chip:"hw", h:240, sum:"Inline practice bar — clickable thumbroller, amber 14segment, instrument in/out passthrough." },
{ key:"showcase", file:"/showcase.html",name:"PM_D1 Display", chip:"hw", h:540, sum:"Pyramid display piece — an RGBlight pendulum combining every lane's subdivisions &amp; accents." }, { key:"showcase", file:"/showcase.html",name:"PM_D1 Display", chip:"hw", h:540, sum:"Pyramid display piece — an RGBlight pendulum combining every lane's subdivisions &amp; accents." },
{ key:"initial", file:"/player.html", name:"PM_C1 Concept", chip:"", h:440, sum:"The idealized concept render — full multilane display and setlist navigation." }, { key:"initial", file:"/player.html", name:"PM_C1 Concept", chip:"", h:440, sum:"The idealized concept render — full multilane display and setlist navigation." },
]; ];
// "Specs & info" link helper - usually swaps /<dev>.html for /info-<dev>.html, but if the
// pane already POINTS at the info page (PM_X-1 has no separate widget yet), keep it as is.
const infoOf = (f) => f.startsWith("/info-") ? f : f.replace("/", "/info-");
const DEFAULT_PROG = (typeof SEED_SETLISTS !== "undefined" && SEED_SETLISTS[0] && SEED_SETLISTS[0].items[0] && SEED_SETLISTS[0].items[0][1]) || "v1;t120;kick:4;snare:4=.X.X;hat:4/2"; const DEFAULT_PROG = (typeof SEED_SETLISTS !== "undefined" && SEED_SETLISTS[0] && SEED_SETLISTS[0].items[0] && SEED_SETLISTS[0].items[0][1]) || "v1;t120;kick:4;snare:4=.X.X;hat:4/2";
let cur = "editor", userEditing = false; let cur = "editor", userEditing = false;
@ -158,7 +162,7 @@ function renderPanes() {
<p>${v.sum}</p> <p>${v.sum}</p>
<div class="links"> <div class="links">
<a class="open" href="${v.file}" target="_blank" rel="noopener" onclick="event.stopPropagation()">Open ↗</a> <a class="open" href="${v.file}" target="_blank" rel="noopener" onclick="event.stopPropagation()">Open ↗</a>
<a class="open" href="${v.file.replace("/", "/info-")}" target="_blank" rel="noopener" onclick="event.stopPropagation()">Specs &amp; info ⓘ</a> <a class="open" href="${infoOf(v.file)}" target="_blank" rel="noopener" onclick="event.stopPropagation()">Specs &amp; info ⓘ</a>
</div> </div>
</div>`).join(""); </div>`).join("");
$("panes").querySelectorAll(".pane").forEach((el) => { $("panes").querySelectorAll(".pane").forEach((el) => {
@ -172,7 +176,7 @@ function loadVersion(key, prog) {
$("panes").querySelectorAll(".pane").forEach((p) => p.classList.toggle("active", p.dataset.key === key)); $("panes").querySelectorAll(".pane").forEach((p) => p.classList.toggle("active", p.dataset.key === key));
$("vpName").innerHTML = "<b>" + v.name + "</b>"; $("vpName").innerHTML = "<b>" + v.name + "</b>";
$("vpOpen").href = v.file; $("vpOpen").href = v.file;
$("vpInfo").href = v.file.replace("/", "/info-"); $("vpInfo").href = infoOf(v.file);
vp.style.height = (v.h || 440) + "px"; vp.style.height = (v.h || 440) + "px";
vp.src = v.file + "?embed=1" + (prog ? "#p=" + encodeURIComponent(prog) : ""); vp.src = v.file + "?embed=1" + (prog ? "#p=" + encodeURIComponent(prog) : "");
if (prog && !userEditing) box.value = prog; if (prog && !userEditing) box.value = prog;

View file

@ -6,6 +6,14 @@
<title>VARASYS PM_X-1 Explorer - wiring, parts &amp; firmware (Pimoroni Explorer / RP2350)</title> <title>VARASYS PM_X-1 Explorer - wiring, parts &amp; firmware (Pimoroni Explorer / RP2350)</title>
<meta name="description" content="PM_X-1 Explorer - the Pimoroni Explorer (PIM744, RP2350) as a 6-button polymeter metronome with live-sync to the web editor. Pinout, parts list, and the precompiled CircuitPython firmware bundle." /> <meta name="description" content="PM_X-1 Explorer - the Pimoroni Explorer (PIM744, RP2350) as a 6-button polymeter metronome with live-sync to the web editor. Pinout, parts list, and the precompiled CircuitPython firmware bundle." />
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml;base64,@BUILD:favicon@"> <link rel="icon" type="image/svg+xml" href="data:image/svg+xml;base64,@BUILD:favicon@">
<script>
/* ?embed=1 -> strip site chrome (base.css [data-embed]) + auto-size to the host iframe */
(function(){ if(!/[?&]embed=1/.test(location.search)) return;
document.documentElement.dataset.embed="1";
function ph(){ try{ parent.postMessage({type:"varasys-h",h:Math.ceil(document.documentElement.getBoundingClientRect().height)},"*"); }catch(e){} }
addEventListener("load",ph); addEventListener("resize",ph); setTimeout(ph,300); setTimeout(ph,1000);
})();
</script>
<script> <script>
(function(){ try{ var p = localStorage.getItem("metronome.theme"); (function(){ try{ var p = localStorage.getItem("metronome.theme");
if (p!=="light" && p!=="dark" && p!=="system") p = "system"; if (p!=="light" && p!=="dark" && p!=="system") p = "system";