Skip to content

Commit e5c4db8

Browse files
authored
🐎: Scaffolding for a benchmarking tool (#805)
1 parent eeebc28 commit e5c4db8

File tree

11 files changed

+687
-28
lines changed

11 files changed

+687
-28
lines changed

apps/typegpu-docs/package.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
"classnames": "^2.5.1",
2828
"jotai": "^2.8.4",
2929
"jotai-location": "^0.5.5",
30+
"lucide-react": "^0.474.0",
3031
"lz-string": "^1.5.0",
3132
"monaco-editor": "^0.50.0",
33+
"motion": "^12.0.5",
3234
"react": "^18.3.1",
3335
"react-dom": "^18.3.1",
3436
"remeda": "^2.3.0",
@@ -37,6 +39,7 @@
3739
"starlight-blog": "^0.12.0",
3840
"starlight-typedoc": "^0.17.0",
3941
"tailwindcss": "^3.4.6",
42+
"tinybench": "^3.1.0",
4043
"typed-binary": "^4.0.0",
4144
"typedoc": "^0.27.1",
4245
"typedoc-plugin-markdown": "^4.3.0",
@@ -49,6 +52,7 @@
4952
"@types/babel__template": "^7.4.4",
5053
"@types/babel__traverse": "^7.20.6",
5154
"@webgpu/types": "^0.1.43",
52-
"astro-vtbot": "^1.8.2"
55+
"astro-vtbot": "^1.8.2",
56+
"tailwindcss-motion": "^1.0.1"
5357
}
5458
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
'use client';
2+
3+
import type { Variants } from 'motion/react';
4+
import { motion, useAnimation } from 'motion/react';
5+
6+
const lidVariants: Variants = {
7+
normal: { y: 0 },
8+
animate: { y: -1.1 },
9+
};
10+
11+
const springTransition = {
12+
type: 'spring',
13+
stiffness: 500,
14+
damping: 30,
15+
};
16+
17+
const DeleteIcon = () => {
18+
const controls = useAnimation();
19+
20+
return (
21+
<div
22+
className="cursor-pointer select-none p-2 hover:bg-accent rounded-md transition-colors duration-200 flex items-center justify-center"
23+
onMouseEnter={() => controls.start('animate')}
24+
onMouseLeave={() => controls.start('normal')}
25+
>
26+
<svg
27+
xmlns="http://www.w3.org/2000/svg"
28+
width="24"
29+
height="24"
30+
viewBox="0 0 24 24"
31+
fill="none"
32+
stroke="currentColor"
33+
strokeWidth="2"
34+
strokeLinecap="round"
35+
strokeLinejoin="round"
36+
>
37+
<title>Delete</title>
38+
<motion.g
39+
variants={lidVariants}
40+
animate={controls}
41+
transition={springTransition}
42+
>
43+
<path d="M3 6h18" />
44+
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
45+
</motion.g>
46+
<motion.path
47+
d="M19 8v12c0 1-1 2-2 2H7c-1 0-2-1-2-2V8"
48+
variants={{
49+
normal: { d: 'M19 8v12c0 1-1 2-2 2H7c-1 0-2-1-2-2V8' },
50+
animate: { d: 'M19 9v12c0 1-1 2-2 2H7c-1 0-2-1-2-2V9' },
51+
}}
52+
animate={controls}
53+
transition={springTransition}
54+
/>
55+
<motion.line
56+
x1="10"
57+
x2="10"
58+
y1="11"
59+
y2="17"
60+
variants={{
61+
normal: { y1: 11, y2: 17 },
62+
animate: { y1: 11.5, y2: 17.5 },
63+
}}
64+
animate={controls}
65+
transition={springTransition}
66+
/>
67+
<motion.line
68+
x1="14"
69+
x2="14"
70+
y1="11"
71+
y2="17"
72+
variants={{
73+
normal: { y1: 11, y2: 17 },
74+
animate: { y1: 11.5, y2: 17.5 },
75+
}}
76+
animate={controls}
77+
transition={springTransition}
78+
/>
79+
</svg>
80+
</div>
81+
);
82+
};
83+
84+
export { DeleteIcon };

apps/typegpu-docs/src/layouts/PageLayout.astro

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
22
import '../tailwind.css';
33
import '../fonts/font-face.css';
4-
const { title } = Astro.props;
4+
const { title, theme = 'light' } = Astro.props;
55
---
66

7-
<html>
7+
<html data-theme={theme}>
88
<head>
99
<title>{title ? `${title} |` : ''} TypeGPU</title>
1010
<meta charset="UTF-8" />
@@ -49,6 +49,14 @@ const { title } = Astro.props;
4949
margin: 0;
5050
}
5151

52+
[data-theme='dark'] body {
53+
background-color: #171724;
54+
color: white;
55+
}
56+
57+
[data-theme='light'] body {
58+
background-color: white;
59+
}
5260
</style>
5361
</head>
5462
<body>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { atom } from 'jotai';
2+
import { atomWithLocation } from 'jotai-location';
3+
4+
const locationAtom = atomWithLocation();
5+
6+
export const stringParam = {
7+
encode: (val: string) => val,
8+
decode: (val: string) => val,
9+
};
10+
11+
export const boolParam = {
12+
encode: (val: boolean) => (val ? '1' : '0'),
13+
decode: (val: string) => val === '1',
14+
};
15+
16+
export const numberParam = {
17+
encode: (val: number) => String(val),
18+
decode: (val: string) => Number.parseFloat(val),
19+
};
20+
21+
export const objParam = {
22+
encode: JSON.stringify,
23+
decode: JSON.parse,
24+
};
25+
26+
export const typeToParam = {
27+
string: stringParam,
28+
boolean: boolParam,
29+
number: numberParam,
30+
object: objParam,
31+
};
32+
33+
export const atomWithUrl = <T>(
34+
key: string,
35+
defaultValue: T,
36+
options?: { encode: (val: T) => string; decode: (val: string) => unknown },
37+
) => {
38+
const optionsOrInferred =
39+
options ??
40+
typeToParam[typeof defaultValue as keyof typeof typeToParam] ??
41+
objParam;
42+
43+
const { encode, decode } = optionsOrInferred;
44+
45+
return atom(
46+
(get) => {
47+
const location = get(locationAtom);
48+
return location.searchParams?.has(key)
49+
? (decode(location.searchParams.get(key) ?? '') as T)
50+
: defaultValue;
51+
},
52+
(get, set, newValue: T) => {
53+
const prev = get(locationAtom);
54+
const searchParams = new URLSearchParams(prev.searchParams);
55+
searchParams.set(key, encode(newValue));
56+
57+
set(
58+
locationAtom,
59+
{
60+
...prev,
61+
searchParams: searchParams,
62+
},
63+
{ replace: true },
64+
);
65+
},
66+
);
67+
};

0 commit comments

Comments
 (0)