Skip to content

Commit f6aa9a0

Browse files
committed
Merge branch 'main' into feat/typegpu-react
2 parents 5c54cf4 + cfeb3c6 commit f6aa9a0

94 files changed

Lines changed: 4476 additions & 1210 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,6 @@ on:
1010
- checks_requested
1111

1212
jobs:
13-
check-circular-deps:
14-
runs-on: ubuntu-latest
15-
steps:
16-
- uses: actions/checkout@v4
17-
18-
- name: Install pnpm
19-
uses: pnpm/action-setup@v4
20-
with:
21-
run_install: false
22-
23-
- name: Use Node.js
24-
uses: actions/setup-node@v4
25-
with:
26-
node-version: 22.x
27-
cache: 'pnpm'
28-
29-
- name: Install dpdm
30-
run: pnpm install -g dpdm
31-
32-
- name: Check circular dependencies
33-
run: dpdm --exit-code circular:1 packages/**/index.ts -T
34-
35-
lint-and-format:
36-
runs-on: ubuntu-latest
37-
steps:
38-
- uses: actions/checkout@v4
39-
- uses: biomejs/setup-biome@v2
40-
- uses: denoland/setup-deno@v2
41-
with:
42-
deno-version: v2.x # Run with latest stable Deno.
43-
- name: Lint
44-
run: biome ci --formatter-enabled=false --organize-imports-enabled=false .
45-
- name: Check formatting
46-
run: deno fmt --check
47-
4813
build-and-test:
4914
runs-on: ubuntu-latest
5015
steps:

apps/typegpu-docs/astro.config.mjs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,27 @@ const DEV = import.meta.env.DEV;
2727
export default defineConfig({
2828
site: 'https://docs.swmansion.com',
2929
base: 'TypeGPU',
30+
server: {
31+
// Required for '@rolldown/browser' to work in dev mode.
32+
// Since the service worker is hosted on the /TypeGPU path,
33+
// fetches from /@fs/ fail due to CORS. This fixes that.
34+
headers: {
35+
'Cross-Origin-Embedder-Policy': 'require-corp',
36+
'Cross-Origin-Opener-Policy': 'same-origin',
37+
},
38+
},
3039
markdown: {
3140
remarkPlugins: [remarkMath],
3241
rehypePlugins: [rehypeMathJax],
3342
},
3443
vite: {
44+
define: {
45+
// Required for '@rolldown/browser' to work.
46+
'process.env.NODE_DEBUG_NATIVE': '""',
47+
},
48+
optimizeDeps: {
49+
exclude: ['@rolldown/browser'],
50+
},
3551
// Allowing query params, for invalidation
3652
plugins: [
3753
wasm(),
@@ -48,6 +64,7 @@ export default defineConfig({
4864
ssr: {
4965
noExternal: [
5066
'wgsl-wasm-transpiler-bundler',
67+
'@rolldown/browser',
5168
],
5269
},
5370
},

apps/typegpu-docs/package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@
1313
"@astrojs/check": "^0.9.4",
1414
"@astrojs/react": "^4.3.1",
1515
"@astrojs/sitemap": "^3.6.0",
16-
"@astrojs/starlight": "^0.35.2",
16+
"@astrojs/starlight": "^0.36.1",
1717
"@astrojs/starlight-tailwind": "^4.0.1",
1818
"@astrojs/tailwind": "^6.0.2",
1919
"@babel/standalone": "^7.27.0",
2020
"@loaders.gl/core": "^4.3.4",
2121
"@loaders.gl/obj": "^4.3.4",
2222
"@monaco-editor/react": "^4.7.0",
23-
"@radix-ui/react-select": "^2.2.5",
23+
"@radix-ui/react-select": "^2.2.6",
2424
"@radix-ui/react-slider": "^1.3.5",
25+
"@rolldown/browser": "1.0.0-beta.43",
2526
"@stackblitz/sdk": "^1.11.0",
2627
"@tailwindcss/vite": "^4.1.13",
2728
"@typegpu/color": "workspace:*",
@@ -31,7 +32,7 @@
3132
"@types/react": "^19.1.8",
3233
"@types/react-dom": "^19.1.6",
3334
"arktype": "catalog:",
34-
"astro": "^5.13.7",
35+
"astro": "^5.14.5",
3536
"classnames": "^2.5.1",
3637
"expressive-code-twoslash": "^0.5.3",
3738
"fuse.js": "catalog:frontend",
@@ -41,7 +42,7 @@
4142
"lz-string": "^1.5.0",
4243
"monaco-editor": "^0.53.0",
4344
"morphcharts": "^1.3.2",
44-
"motion": "^12.23.7",
45+
"motion": "^12.23.24",
4546
"pathe": "^2.0.3",
4647
"react": "^19.1.0",
4748
"react-dom": "^19.1.0",
@@ -50,7 +51,7 @@
5051
"remeda": "^2.21.2",
5152
"sharp": "^0.34.2",
5253
"starlight-blog": "^0.23.2",
53-
"starlight-typedoc": "^0.19.0",
54+
"starlight-typedoc": "^0.21.4",
5455
"tinybench": "^3.1.0",
5556
"typedoc": "^0.28.13",
5657
"typedoc-plugin-markdown": "^4.3.0",
@@ -75,6 +76,6 @@
7576
"tailwindcss-motion": "^1.1.1",
7677
"vite-imagetools": "catalog:frontend",
7778
"vite-plugin-wasm": "^3.5.0",
78-
"yaml": "^2.8.0"
79+
"yaml": "^2.8.1"
7980
}
8081
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */
2+
3+
// This service worker is responsible for intercepting fetch requests to
4+
// assets hosted on the same origin, and attaching CORS headers that
5+
// allow SharedArrayBuffer to function (required by @rolldown/browser).
6+
7+
let coepCredentialless = false;
8+
if (typeof window === 'undefined') {
9+
self.addEventListener('install', () => self.skipWaiting());
10+
self.addEventListener(
11+
'activate',
12+
(event) => event.waitUntil(self.clients.claim()),
13+
);
14+
15+
self.addEventListener('message', (ev) => {
16+
if (!ev.data) {
17+
return;
18+
}
19+
20+
if (ev.data.type === 'deregister') {
21+
self.registration
22+
.unregister()
23+
.then(() => {
24+
return self.clients.matchAll();
25+
})
26+
.then((clients) => {
27+
for (const client of clients) {
28+
client.navigate(client.url);
29+
}
30+
});
31+
} else if (ev.data.type === 'coepCredentialless') {
32+
coepCredentialless = ev.data.value;
33+
}
34+
});
35+
36+
self.addEventListener('fetch', (event) => {
37+
const r = event.request;
38+
if (r.cache === 'only-if-cached' && r.mode !== 'same-origin') {
39+
return;
40+
}
41+
42+
const request = (coepCredentialless && r.mode === 'no-cors')
43+
? new Request(r, {
44+
credentials: 'omit',
45+
})
46+
: r;
47+
event.respondWith(
48+
fetch(request)
49+
.then((response) => {
50+
if (response.status === 0) {
51+
return response;
52+
}
53+
54+
const newHeaders = new Headers(response.headers);
55+
newHeaders.set(
56+
'Cross-Origin-Embedder-Policy',
57+
coepCredentialless ? 'credentialless' : 'require-corp',
58+
);
59+
if (!coepCredentialless) {
60+
newHeaders.set('Cross-Origin-Resource-Policy', 'cross-origin');
61+
}
62+
newHeaders.set('Cross-Origin-Opener-Policy', 'same-origin');
63+
64+
return new Response(response.body, {
65+
status: response.status,
66+
statusText: response.statusText,
67+
headers: newHeaders,
68+
});
69+
})
70+
.catch((e) => console.error(e)),
71+
);
72+
});
73+
} else {
74+
(() => {
75+
const reloadedBySelf = window.sessionStorage.getItem('coiReloadedBySelf');
76+
window.sessionStorage.removeItem('coiReloadedBySelf');
77+
const coepDegrading = reloadedBySelf === 'coepdegrade';
78+
79+
// You can customize the behavior of this script through a global `coi` variable.
80+
const coi = {
81+
shouldRegister: () => !reloadedBySelf,
82+
shouldDeregister: () => false,
83+
coepCredentialless: () => true,
84+
coepDegrade: () => true,
85+
doReload: () => window.location.reload(),
86+
quiet: false,
87+
...window.coi,
88+
};
89+
90+
const n = navigator;
91+
const controlling = !!n.serviceWorker && !!n.serviceWorker.controller;
92+
93+
// Record the failure if the page is served by serviceWorker.
94+
if (controlling && !window.crossOriginIsolated) {
95+
window.sessionStorage.setItem('coiCoepHasFailed', 'true');
96+
}
97+
const coepHasFailed = window.sessionStorage.getItem('coiCoepHasFailed');
98+
99+
if (controlling) {
100+
// Reload only on the first failure.
101+
const reloadToDegrade = coi.coepDegrade() && !(
102+
coepDegrading || window.crossOriginIsolated
103+
);
104+
n.serviceWorker.controller.postMessage({
105+
type: 'coepCredentialless',
106+
value: (reloadToDegrade || coepHasFailed && coi.coepDegrade())
107+
? false
108+
: coi.coepCredentialless(),
109+
});
110+
if (reloadToDegrade) {
111+
!coi.quiet && console.log('Reloading page to degrade COEP.');
112+
window.sessionStorage.setItem('coiReloadedBySelf', 'coepdegrade');
113+
coi.doReload('coepdegrade');
114+
}
115+
116+
if (coi.shouldDeregister()) {
117+
n.serviceWorker.controller.postMessage({ type: 'deregister' });
118+
}
119+
}
120+
121+
// If we're already coi: do nothing. Perhaps it's due to this script doing its job, or COOP/COEP are
122+
// already set from the origin server. Also if the browser has no notion of crossOriginIsolated, just give up here.
123+
if (window.crossOriginIsolated !== false || !coi.shouldRegister()) return;
124+
125+
if (!window.isSecureContext) {
126+
!coi.quiet &&
127+
console.log(
128+
'COOP/COEP Service Worker not registered, a secure context is required.',
129+
);
130+
return;
131+
}
132+
133+
// In some environments (e.g. Firefox private mode) this won't be available
134+
if (!n.serviceWorker) {
135+
!coi.quiet &&
136+
console.error(
137+
'COOP/COEP Service Worker not registered, perhaps due to private mode.',
138+
);
139+
return;
140+
}
141+
142+
n.serviceWorker.register(window.document.currentScript.src).then(
143+
(registration) => {
144+
!coi.quiet &&
145+
console.log(
146+
'COOP/COEP Service Worker registered',
147+
registration.scope,
148+
);
149+
150+
registration.addEventListener('updatefound', () => {
151+
!coi.quiet &&
152+
console.log(
153+
'Reloading page to make use of updated COOP/COEP Service Worker.',
154+
);
155+
window.sessionStorage.setItem('coiReloadedBySelf', 'updatefound');
156+
coi.doReload();
157+
});
158+
159+
// If the registration is active, but it's not controlling the page
160+
if (registration.active && !n.serviceWorker.controller) {
161+
!coi.quiet &&
162+
console.log(
163+
'Reloading page to make use of COOP/COEP Service Worker.',
164+
);
165+
window.sessionStorage.setItem('coiReloadedBySelf', 'notcontrolling');
166+
coi.doReload();
167+
}
168+
},
169+
(err) => {
170+
!coi.quiet &&
171+
console.error('COOP/COEP Service Worker failed to register:', err);
172+
},
173+
);
174+
})();
175+
}

apps/typegpu-docs/src/components/CodeEditor.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import Editor, {
33
type Monaco,
44
type OnMount,
55
} from '@monaco-editor/react';
6-
// biome-ignore lint/correctness/noUnusedImports: <its a namespace, Biome>
76
import type { editor } from 'monaco-editor';
87
import { entries, filter, fromEntries, isTruthy, map, pipe } from 'remeda';
98
import { SANDBOX_MODULES } from '../utils/examples/sandboxModules.ts';
@@ -17,7 +16,7 @@ function handleEditorWillMount(monaco: Monaco) {
1716
entries(SANDBOX_MODULES),
1817
map(([key, moduleDef]) => {
1918
if ('reroute' in moduleDef.typeDef) {
20-
return [key, moduleDef.typeDef.reroute] as const;
19+
return [key, [moduleDef.typeDef.reroute]] as [string, string[]];
2120
}
2221
return null;
2322
}),

apps/typegpu-docs/src/components/ExampleView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,11 @@ function useResizableCanvas(exampleHtmlRef: RefObject<HTMLDivElement | null>) {
249249
}
250250

251251
for (const prop of canvas.style) {
252-
// @ts-ignore
252+
// @ts-expect-error
253253
newCanvas.style[prop] = canvas.style[prop];
254254
}
255255
for (const attribute of canvas.attributes) {
256-
// @ts-ignore
256+
// @ts-expect-error
257257
newCanvas[attribute.name] = attribute.value;
258258
}
259259
newCanvas.className = 'absolute w-full h-full';

apps/typegpu-docs/src/components/SearchableExampleList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ function ExamplesGrid({ examples }: { examples: Example[] }) {
1212
);
1313
}
1414

15-
const DEV = globalThis.process.env.NODE_ENV === 'development';
16-
const TEST = globalThis.process.env.NODE_ENV === 'test';
15+
const DEV = process.env.NODE_ENV === 'development';
16+
const TEST = process.env.NODE_ENV === 'test';
1717

1818
export function SearchableExampleList(
1919
{ excludeTags = [], scrollContainerRef }: {

apps/typegpu-docs/src/components/design/DeleteIcon.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const DeleteIcon = () => {
1818
const controls = useAnimation();
1919

2020
return (
21+
// biome-ignore lint/a11y/noStaticElementInteractions: This is just an animation
2122
<div
2223
className='flex cursor-pointer select-none items-center justify-center rounded-md p-2 transition-colors duration-200 hover:bg-accent'
2324
onMouseEnter={() => controls.start('animate')}

apps/typegpu-docs/src/components/stackblitz/openInStackBlitz.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ import typegpuPackageJson from 'typegpu/package.json' with {
1919
import unpluginPackageJson from 'unplugin-typegpu/package.json' with {
2020
type: 'json',
2121
};
22+
// biome-ignore lint/correctness/useImportExtensions: dude it's there
2223
import pnpmWorkspace from '../../../../../pnpm-workspace.yaml?raw';
2324
import typegpuDocsPackageJson from '../../../package.json' with {
2425
type: 'json',
2526
};
2627
import type { Example } from '../../utils/examples/types.ts';
28+
// biome-ignore lint/correctness/useImportExtensions: dude it's there
2729
import index from './stackBlitzIndex.ts?raw';
2830

2931
const pnpmWorkspaceYaml = type({

apps/typegpu-docs/src/components/stackblitz/stackBlitzIndex.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ if (body.firstChild) {
6666
}
6767

6868
// Execute example
69-
// @ts-ignore
69+
// @ts-expect-error
7070
const example = await import('./src/index.ts');
7171

7272
// Create example controls

0 commit comments

Comments
 (0)