File size: 1,550 Bytes
c126239 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | <script lang="ts">
/** Playback control over generated decoding steps. */
let {
total,
index = $bindable(),
intervalMs = 420,
}: { total: number; index: number; intervalMs?: number } = $props();
let playing = $state(false);
let timer: ReturnType<typeof setInterval> | null = null;
function stop() {
if (timer) clearInterval(timer);
timer = null;
playing = false;
}
function toggle() {
if (playing) {
stop();
return;
}
if (index >= total - 1) index = 0;
playing = true;
timer = setInterval(() => {
if (index >= total - 1) {
stop();
return;
}
index = index + 1;
}, intervalMs);
}
$effect(() => () => stop());
</script>
<div class="player">
<button onclick={toggle} disabled={total === 0}>{playing ? 'pause' : 'play'}</button>
<button onclick={() => { stop(); index = Math.max(0, index - 1); }} disabled={index <= 0}>
prev
</button>
<button
onclick={() => { stop(); index = Math.min(total - 1, index + 1); }}
disabled={index >= total - 1}>next</button
>
<input
type="range"
min="0"
max={Math.max(0, total - 1)}
bind:value={index}
oninput={stop}
disabled={total === 0}
/>
<span class="mono small dim">step {total === 0 ? 0 : index + 1} / {total}</span>
</div>
<style>
.player {
display: flex;
align-items: center;
gap: 6px;
}
.player button {
padding: 3px 9px;
font-size: 12.5px;
}
input[type='range'] {
flex: 1;
min-width: 100px;
}
</style>
|