mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-23 17:08:10 -07:00
next: ai part 1
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
const FILL_MS = 2_000;
|
||||
const DRAIN_MS = 600;
|
||||
|
||||
/** @param {number} value */
|
||||
function clampProgress(value) {
|
||||
return Math.max(0, Math.min(1, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLButtonElement} button
|
||||
* @param {() => void} onHold
|
||||
* @param {number} [fillMs]
|
||||
*/
|
||||
export function bindHold(button, onHold, fillMs = FILL_MS) {
|
||||
/** @type {number | undefined} */
|
||||
let frame;
|
||||
let holding = false;
|
||||
let progress = 0;
|
||||
let previous = 0;
|
||||
|
||||
function render() {
|
||||
button.style.setProperty("--hold-progress", String(progress));
|
||||
button.style.setProperty("--hold-progress-width", `${progress * 100}%`);
|
||||
button.toggleAttribute("data-active", progress > 0);
|
||||
}
|
||||
|
||||
function stop() {
|
||||
if (frame === undefined) return;
|
||||
|
||||
cancelAnimationFrame(frame);
|
||||
frame = undefined;
|
||||
}
|
||||
|
||||
/** @param {number} now */
|
||||
function tick(now) {
|
||||
const elapsed = now - previous;
|
||||
const rate = elapsed / (holding ? fillMs : DRAIN_MS);
|
||||
|
||||
previous = now;
|
||||
progress = clampProgress(progress + (holding ? rate : -rate));
|
||||
render();
|
||||
|
||||
if (holding && progress === 1) {
|
||||
stop();
|
||||
holding = false;
|
||||
progress = 0;
|
||||
button.removeAttribute("data-holding");
|
||||
render();
|
||||
onHold();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!holding && progress === 0) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
frame = requestAnimationFrame(tick);
|
||||
}
|
||||
|
||||
function run() {
|
||||
if (frame !== undefined) return;
|
||||
|
||||
previous = performance.now();
|
||||
frame = requestAnimationFrame(tick);
|
||||
}
|
||||
|
||||
function release() {
|
||||
if (!holding) return;
|
||||
|
||||
holding = false;
|
||||
button.removeAttribute("data-holding");
|
||||
run();
|
||||
}
|
||||
|
||||
function hold() {
|
||||
stop();
|
||||
holding = true;
|
||||
button.dataset.holding = "";
|
||||
run();
|
||||
}
|
||||
|
||||
render();
|
||||
|
||||
button.addEventListener("pointerdown", (event) => {
|
||||
if (event.button !== 0) return;
|
||||
|
||||
button.setPointerCapture(event.pointerId);
|
||||
hold();
|
||||
});
|
||||
button.addEventListener("pointerup", release);
|
||||
button.addEventListener("pointercancel", release);
|
||||
button.addEventListener("lostpointercapture", release);
|
||||
button.addEventListener("keydown", (event) => {
|
||||
if (event.repeat || (event.key !== " " && event.key !== "Enter")) return;
|
||||
|
||||
event.preventDefault();
|
||||
hold();
|
||||
});
|
||||
button.addEventListener("keyup", (event) => {
|
||||
if (event.key === " " || event.key === "Enter") release();
|
||||
});
|
||||
button.addEventListener("blur", release);
|
||||
}
|
||||
Reference in New Issue
Block a user