(function () {
"use strict";
const R=window.REBASE, slides=R.slides, $=id=>document.getElementById(id);
const presenter=new URLSearchParams(location.search).has("presenter");
const state={index:0,step:0,demo:null,view:"example",backend:0,library:null,libraryWide:false,libraryScroll:0,methods:false};
let held=0,started=null,toastTimeout,channel;
if(presenter) document.body.classList.add("presenter");
try { channel=new BroadcastChannel("simple-rebase-"+location.pathname); } catch (_) {}
const current=()=>slides[state.index];
const view=()=>current().views?.find(v=>v.id===state.view);
const steps=()=>view()?.steps??current().steps;
const elapsed=()=>held+(started===null?0:Date.now()-started);
const clock=ms=>Math.floor(ms/60000).toString().padStart(2,"0")+":"+Math.floor(ms/1000%60).toString().padStart(2,"0");
const starts=i=>slides.slice(0,i).reduce((n,s)=>n+s.minutes,0);
function fit() {
const box=$("viewport").getBoundingClientRect();
document.documentElement.style.setProperty("--scale",Math.min(box.width/1440,box.height/900));
}
function readHash() {
const [id,step,tab]=location.hash.slice(1).split("/");
const index=slides.findIndex(s=>s.id===id);
if(index>=0) {
state.index=index;
state.view=slides[index].views?.some(v=>v.id===tab)?tab:"example";
state.step=Math.max(0,Math.min(steps(),Number(step)||0));
state.demo=null;
}
}
function broadcast() {
if(!presenter && channel) channel.postMessage({type:"state",state:{...state},elapsed:elapsed(),running:started!==null});
}
function render(remote=false) {
const s=current(), count=slides.filter(x=>!x.optional).length;
const v=view(), builds=steps();
const tabs=s.views?'':"";
const number=s.optional?"BONUS":slides.slice(0,state.index+1).filter(x=>!x.optional).length;
$("slide").className="slide"+(s.still?" still":"");
$("slide").dataset.id=s.id;
$("slide").dataset.step=state.step;
$("slide").dataset.view=state.view;
$("slide").innerHTML='
Select and copy the text below.
'); $("manual-copy").value=text;$("manual-copy").focus();$("manual-copy").select(); } } } function overview() { openDialog('Builds advance only when you ask. The talk timer keeps running while you switch to the graph viewer. For demos: Copy code → switch to viewer → paste → Compile.
'); } function toggleNotes() { if(presenter) return; $("notes").hidden=!$("notes").hidden; $("notes-toggle").setAttribute("aria-pressed",String(!$("notes").hidden)); } function openPresenter() { const url=new URL(location.href);url.searchParams.set("presenter","1"); const child=window.open(url,"simple-rebase-presenter","width=1400,height=850"); if(!child) toast("Allow popups for presenter mode, or press N for notes."); } async function fullscreen() { try {if(document.fullscreenElement) await document.exitFullscreen();else await document.documentElement.requestFullscreen();} catch (_) {toast("Use your browser’s fullscreen command.");} } function blank() {$("blackout").hidden=!$("blackout").hidden;} $("previous").addEventListener("click",()=>action("previous")); $("next").addEventListener("click",()=>action("next")); $("overview").addEventListener("click",overview); $("help").addEventListener("click",help); $("notes-toggle").addEventListener("click",toggleNotes); $("presenter").addEventListener("click",openPresenter); $("timer").addEventListener("click",()=>action("timer")); $("timer-reset").addEventListener("click",()=>action("reset")); $("fullscreen").addEventListener("click",fullscreen); $("dialog-close").addEventListener("click",()=>$("dialog").close()); $("dialog").addEventListener("click",e=>{if(e.target===$("dialog")) $("dialog").close();}); document.addEventListener("click",e=>{ const b=e.target.closest("[data-copy],[data-command],[data-graph],[data-goto],[data-demo],button[data-view],button[data-backend],[data-language],[data-library-path],[data-language-copy]"); if(!b) return; if(b.dataset.goto) {if($("dialog").open) $("dialog").close();action("goto",b.dataset.goto);} if(b.dataset.demo) action("demo",b.dataset.demo); if(b.dataset.backend!==undefined) action("backend",b.dataset.backend); if(b.dataset.language) action("language",b.dataset.language); if(b.dataset.libraryPath!==undefined) action("library-path",b.dataset.libraryPath); if(b.dataset.languageCopy) copy(b.dataset.languageCopy==='methods'?R.library.methods:R.library.files[state.library],b.dataset.languageCopy==='methods'?'Methods example':'Source file'); if(b.dataset.view) action("view",b.dataset.view); if(b.dataset.copy) copy(R.demos.find(d=>d.id===b.dataset.copy).code,"Demo code"); if(b.dataset.command) { const d=R.demos.find(d=>d.id===b.dataset.command); copy("make -C "+(d.viewerChapter||d.chapter)+" view","Viewer command"); } if(b.dataset.graph) { const d=R.demos.find(d=>d.id===b.dataset.graph); openDialog('Captured from '+d.chapter+' after its viewer compilation phases. '+R.escape(d.inputs)+'.
'); } }); document.addEventListener("scroll",e=>{ if(!e.target.matches?.('[data-library-scroll]')) return; const top=e.target.scrollTop; if(Math.abs(top-state.libraryScroll)>1) action("library-scroll",top); },true); document.addEventListener("keydown",e=>{ if(e.ctrlKey||e.altKey||e.metaKey||e.repeat) return; if(e.target.closest("textarea,input,select,[contenteditable=true]")) return; if(!$("blackout").hidden) { if(e.key==="b"||e.key==="B"||e.key==="Escape") {$("blackout").hidden=true;e.preventDefault();} return; } if($("dialog").open) return; if(e.target.closest('.library-text,.library-list') && ['ArrowUp','ArrowDown','ArrowLeft','ArrowRight','PageUp','PageDown','Home','End',' '].includes(e.key)) return; let handled=true; switch(e.key) { case "ArrowRight": action("next");break; case " ": if(e.target.closest("button,a")) {handled=false;break;} action("next");break; case "ArrowLeft": action("previous");break; case "PageDown": action("next-slide");break; case "PageUp": action("previous-slide");break; case "Home": action("goto","title");break; case "End": action("goto","close");break; case "o": case "O": overview();break; case "l": case "L": action("cycle-view");break; case "n": case "N": toggleNotes();break; case "p": case "P": openPresenter();break; case "t": case "T": action("timer");break; case "f": case "F": fullscreen();break; case "b": case "B": blank();break; case "?": help();break; case "Escape": if(!presenter) {$("notes").hidden=true;$("notes-toggle").setAttribute("aria-pressed","false");} break; default: handled=false; } if(handled) e.preventDefault(); }); if(channel) channel.onmessage=e=>{ const m=e.data; if(m.type==="request"&&!presenter) broadcast(); if(m.type==="command"&&!presenter) action(m.name,m.value,true); if(m.type==="state"&&presenter) { const changed=JSON.stringify(state)!==JSON.stringify(m.state); const scrollOnly=changed && JSON.stringify({...state,libraryScroll:m.state.libraryScroll})===JSON.stringify(m.state); Object.assign(state,m.state); held=m.elapsed;started=m.running?Date.now():null; if(changed && !scrollOnly) render(true); else { const source=$("slide").querySelector('[data-library-scroll]'); if(scrollOnly && source) source.scrollTop=state.libraryScroll; tick(); } } }; window.addEventListener("resize",fit); window.addEventListener("hashchange",()=>{if(!presenter){readHash();render();}}); readHash();render(); if(presenter) {$("notes").hidden=false;if(channel) channel.postMessage({type:"request"});} setInterval(()=>{tick();if(!presenter&&started!==null) broadcast();},1000); // Small public surface for rehearsal and offline export tools. R.go=id=>action("goto",id); R.state=()=>({...state,elapsed:elapsed(),running:started!==null}); })();