feat: cookbook

This commit is contained in:
2025-11-28 14:38:51 +01:00
parent 245dd97532
commit 6895fa4a82
66 changed files with 1093 additions and 3386 deletions

View File

@@ -0,0 +1,85 @@
<script lang="ts">
import type { PageData } from "./$types";
let { data }: { data: PageData } = $props();
$effect(() => {
console.log(data);
});
</script>
<details>
<summary>Full Log</summary>
{#each data.data as item, i}
{#if "press" in item}
<div class="press">{item.press}</div>
{:else if "release" in item}
<div class="release">{item.release}</div>
{:else if "keys" in item}
<div class="report">
<span class="icon">keyboard</span>
<div class="modifiers">
{item.modifiers.toString(2)}
</div>
<div class="keys">{item.keys.join(", ")}</div>
</div>
{:else if "out" in item}
<pre class="out">{item.out}</pre>
{:else if "in" in item}
<pre class="in">{item.in}</pre>
{:else if "tick" in item}
<div class="tick"><span class="icon">timer_play</span>{item.tick}ms</div>
{:else}
<div>Unknown log item at index {i}</div>
{/if}
{/each}
</details>
<style lang="scss">
details {
margin-top: 1rem;
border: 1px solid var(--md-sys-color-outline);
border-radius: 0.5rem;
background-color: var(--md-sys-color-surface-variant);
padding: 1rem;
}
.report {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 0.5rem;
border-radius: 0.25rem;
background-color: var(--md-sys-color-primary-container);
padding: 0.5rem;
color: var(--md-sys-color-on-primary-container);
}
.out {
color: var(--md-sys-color-primary);
}
.in {
color: var(--md-sys-color-secondary);
}
.tick {
display: flex;
align-items: center;
gap: 0.5rem;
border-radius: 0.25rem;
padding: 0.2rem 0.5rem;
width: fit-content;
color: var(--md-sys-color-tertiary);
font-size: 0.6rem;
}
.icon {
font-size: inherit;
}
input[type="range"] {
margin-bottom: 1rem;
width: 100%;
}
</style>

View File

@@ -0,0 +1,49 @@
import type { PageLoad } from "./$types";
import { browser } from "$app/environment";
import { fromBase64 } from "$lib/serialization/base64";
export interface ReplaySerialIn {
in: string;
}
export interface ReplaySerialOut {
out: string;
}
export interface ReplaySerialReport {
modifiers: number;
keys: number[];
}
export interface ReplaySerialPress {
press: number;
}
export interface ReplaySerialRelease {
release: number;
}
export interface ReplayTick {
tick: number;
}
export type ReplayDataItem =
| ReplayTick
| ReplaySerialIn
| ReplaySerialOut
| ReplaySerialReport
| ReplaySerialPress
| ReplaySerialRelease;
export const load = (async ({ url, fetch }) => {
const replay = browser && new URLSearchParams(url.search).get("data");
if (!replay) {
return undefined;
}
const stream = (await fromBase64(replay, fetch))
.stream()
.pipeThrough(new DecompressionStream("deflate"));
return {
data: JSON.parse(await new Response(stream).text()) as ReplayDataItem[],
};
}) satisfies PageLoad;