Skip to content

Commit 61eb66d

Browse files
authored
docs: Use Vite v8 for lower memory consumption (#2315)
1 parent 0877765 commit 61eb66d

21 files changed

Lines changed: 859 additions & 490 deletions

apps/typegpu-docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"@types/react": "^19.1.8",
3737
"@types/react-dom": "^19.1.6",
3838
"arktype": "catalog:",
39-
"astro": "^6.0.4",
39+
"astro": "^6.0.8",
4040
"classnames": "^2.5.1",
4141
"expressive-code-twoslash": "^0.5.3",
4242
"fuse.js": "catalog:frontend",
Lines changed: 97 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,114 @@
11
---
2+
23
---
34

45
<div data-challenges-signup-popover="true" class="contents">
56
<slot />
6-
<dialog data-success="false" class="group fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 border border-gray-300 dark:border-gray-700 p-6 rounded-none shadow-lg max-w-md w-full backdrop:bg-black/20 dark:backdrop:bg-black/50 backdrop:backdrop-blur-md">
7-
<form method="dialog" class="hidden group-[[data-success='false']]:block">
8-
<p class="text-justify text-base mb-12">Sign up to be notified when the <strong>ShaderHunt</strong> platform is available, along with interactive examples teaching TypeGPU from the ground up.</p>
9-
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Your name (required)</label>
10-
<input type="text" id="name" name="name" required class="w-full mb-8 px-3 py-2 border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400" />
11-
<label for="email" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Your email (required)</label>
12-
<input type="email" id="email" name="email" required class="w-full mb-8 px-3 py-2 border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400" />
7+
<dialog
8+
data-success="false"
9+
class="group fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 border border-gray-300 dark:border-gray-700 p-6 rounded-none shadow-lg max-w-md w-full backdrop:bg-black/20 dark:backdrop:bg-black/50 backdrop:backdrop-blur-md"
10+
>
11+
<form
12+
method="dialog"
13+
class="hidden group-[[data-success='false']]:block"
14+
>
15+
<p class="text-justify text-base mb-12">
16+
Sign up to be notified when the <strong>ShaderHunt</strong> platform
17+
is available, along with interactive examples teaching TypeGPU from
18+
the ground up.
19+
</p>
20+
<label
21+
for="name"
22+
class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"
23+
>Your name (required)</label
24+
>
25+
<input
26+
type="text"
27+
id="name"
28+
name="name"
29+
required
30+
class="w-full mb-8 px-3 py-2 border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400"
31+
/>
32+
<label
33+
for="email"
34+
class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"
35+
>Your email (required)</label
36+
>
37+
<input
38+
type="email"
39+
id="email"
40+
name="email"
41+
required
42+
class="w-full mb-8 px-3 py-2 border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400"
43+
/>
1344
<div class="mb-4"></div>
1445
<div class="flex items-start mb-4">
15-
<input type="checkbox" id="updates-agree" name="updates-agree" required class="relative appearance-none border-2 border-accent-600 rounded-none w-4 h-4 aspect-square mt-1 mr-3 checked:bg-accent-600 checked:border-accent-600 focus:outline-none focus:ring-2 focus:ring-accent-500 after:content-['✓'] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:flex after:items-center after:justify-center after:text-white after:text-xs after:font-bold checked:after:opacity-100 after:opacity-0" />
16-
<label for="updates-agree" class="text-sm text-gray-700 dark:text-gray-300">I agree to receive updates, news, and marketing materials related to ShaderHunt. You can unsubscribe at any time. See our <a target="_blank" rel="noreferrer" href="https://swmansion.com/privacy" class="text-black dark:text-white">Privacy Policy</a> for details. (required)</label>
46+
<input
47+
type="checkbox"
48+
id="updates-agree"
49+
name="updates-agree"
50+
required
51+
class="relative appearance-none border-2 border-accent-600 rounded-none w-4 h-4 aspect-square mt-1 mr-3 checked:bg-accent-600 checked:border-accent-600 focus:outline-none focus:ring-2 focus:ring-accent-500 after:content-['✓'] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:flex after:items-center after:justify-center after:text-white after:text-xs after:font-bold checked:after:opacity-100 after:opacity-0"
52+
/>
53+
<label
54+
for="updates-agree"
55+
class="text-sm text-gray-700 dark:text-gray-300"
56+
>I agree to receive updates, news, and marketing materials
57+
related to ShaderHunt. You can unsubscribe at any time. See
58+
our <a
59+
target="_blank"
60+
rel="noreferrer"
61+
href="https://swmansion.com/privacy"
62+
class="text-black dark:text-white">Privacy Policy</a
63+
> for details. (required)</label
64+
>
1765
</div>
1866

1967
<div class="flex items-start mb-4">
20-
<input type="checkbox" id="newsletter-agree" name="newsletter-agree" class="relative appearance-none border-2 border-accent-600 rounded-none w-4 h-4 aspect-square mt-1 mr-3 checked:bg-accent-600 checked:border-accent-600 focus:outline-none focus:ring-2 focus:ring-accent-500 after:content-['✓'] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:flex after:items-center after:justify-center after:text-white after:text-xs after:font-bold checked:after:opacity-100 after:opacity-0" />
21-
<label for="newsletter-agree" class="text-sm text-gray-700 dark:text-gray-300">I agree to receive the monthly Software Mansion newsletter with updates on TypeGPU and other React Native, AI, and multimedia projects. You can unsubscribe anytime. See our <a target="_blank" rel="noreferrer" href="https://swmansion.com/privacy" class="text-black dark:text-white">Privacy Policy</a> for details.</label>
68+
<input
69+
type="checkbox"
70+
id="newsletter-agree"
71+
name="newsletter-agree"
72+
class="relative appearance-none border-2 border-accent-600 rounded-none w-4 h-4 aspect-square mt-1 mr-3 checked:bg-accent-600 checked:border-accent-600 focus:outline-none focus:ring-2 focus:ring-accent-500 after:content-['✓'] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:flex after:items-center after:justify-center after:text-white after:text-xs after:font-bold checked:after:opacity-100 after:opacity-0"
73+
/>
74+
<label
75+
for="newsletter-agree"
76+
class="text-sm text-gray-700 dark:text-gray-300"
77+
>I agree to receive the monthly Software Mansion newsletter
78+
with updates on TypeGPU and other React Native, AI, and
79+
multimedia projects. You can unsubscribe anytime. See our <a
80+
target="_blank"
81+
rel="noreferrer"
82+
href="https://swmansion.com/privacy"
83+
class="text-black dark:text-white">Privacy Policy</a
84+
> for details.</label
85+
>
2286
</div>
23-
<button type="submit" class="mt-4 w-full px-4 py-2 bg-accent-600 dark:bg-accent-700 text-white font-medium border-none rounded-none hover:bg-accent-700 dark:hover:bg-accent-800 focus:outline-none focus:ring-2 focus:ring-accent-500 dark:focus:ring-accent-400">Get Notified</button>
87+
<button
88+
type="submit"
89+
class="mt-4 w-full px-4 py-2 bg-accent-600 dark:bg-accent-700 text-white font-medium border-none rounded-none hover:bg-accent-700 dark:hover:bg-accent-800 focus:outline-none focus:ring-2 focus:ring-accent-500 dark:focus:ring-accent-400"
90+
>Get Notified</button
91+
>
2492
</form>
2593
<div class="hidden group-[[data-success='true']]:block">
26-
<p class="text-2xl font-bold text-center text-gray-700 dark:text-gray-300 mb-5">Thank you for signing up for ShaderHunt updates!</p>
27-
<p class="text-sm text-center text-gray-700 dark:text-gray-300 my-3">You should receive a confirmation email shortly.</p>
28-
<button data-close type="button" class="mt-4 w-full px-4 py-2 bg-accent-600 dark:bg-accent-700 text-white font-medium border-none rounded-none hover:bg-accent-700 dark:hover:bg-accent-800 focus:outline-none focus:ring-2 focus:ring-accent-500 dark:focus:ring-accent-400">Close</button>
94+
<p
95+
class="text-2xl font-bold text-center text-gray-700 dark:text-gray-300 mb-5"
96+
>
97+
Thank you for signing up for ShaderHunt updates!
98+
</p>
99+
<p
100+
class="text-sm text-center text-gray-700 dark:text-gray-300 my-3"
101+
>
102+
You should receive a confirmation email shortly.
103+
</p>
104+
<button
105+
data-close
106+
type="button"
107+
class="mt-4 w-full px-4 py-2 bg-accent-600 dark:bg-accent-700 text-white font-medium border-none rounded-none hover:bg-accent-700 dark:hover:bg-accent-800 focus:outline-none focus:ring-2 focus:ring-accent-500 dark:focus:ring-accent-400"
108+
>Close</button
109+
>
29110
</div>
30111
</dialog>
31112
</div>
32113

33-
<script>
34-
const popovers = document.querySelectorAll('[data-challenges-signup-popover="true"]');
35-
36-
class DialogBox {
37-
readonly dialogElement: HTMLDialogElement;
38-
39-
constructor(popover: Element) {
40-
const linkElement: HTMLAnchorElement|null = popover.querySelector('a');
41-
const dialogElement: HTMLDialogElement|null = popover.querySelector('dialog');
42-
const formElement: HTMLFormElement|null = popover.querySelector('form');
43-
const closeButton: HTMLButtonElement|null = popover.querySelector('button[data-close]');
44-
45-
if (!linkElement || !dialogElement || !formElement || !closeButton) {
46-
throw new Error(`Missing required elements: link: ${linkElement ? '✅' : '🚫'}, dialog: ${dialogElement ? '✅' : '🚫'}, form: ${formElement ? '✅' : '🚫'}, closeButton: ${closeButton ? '✅' : '🚫'}`);
47-
}
48-
49-
this.dialogElement = dialogElement;
50-
this.dialogElement.dataset.success = 'false';
51-
52-
linkElement.addEventListener('click', (e) => {
53-
e.preventDefault();
54-
window.location.hash = '#challenges-signup';
55-
dialogElement?.showModal();
56-
});
57-
58-
dialogElement.addEventListener('close', () => {
59-
if (window.location.hash === '#challenges-signup') {
60-
window.location.hash = '';
61-
}
62-
});
63-
64-
formElement.addEventListener('submit', async (e) => {
65-
e.preventDefault();
66-
const formData = new FormData(formElement);
67-
const data = {
68-
name: formData.get('name'),
69-
email: formData.get('email'),
70-
newsletterAgree: formData.get('newsletter-agree') === 'on'
71-
};
72-
73-
try {
74-
const response = await fetch('https://swmansion.dev/api/shaderhunt/signin', {
75-
method: 'POST',
76-
headers: {
77-
'Content-Type': 'application/json'
78-
},
79-
body: JSON.stringify(data)
80-
});
81-
console.log(await response.text());
82-
if (response.ok) {
83-
formElement.reset();
84-
dialogElement.dataset.success = 'true';
85-
} else {
86-
alert('Error submitting form. Please try again.');
87-
}
88-
} catch (error) {
89-
alert('Network error. Please try again.');
90-
}
91-
});
92-
93-
closeButton.addEventListener('click', () => {
94-
dialogElement.close();
95-
});
96-
}
97-
}
98-
99-
const dialogBoxes = Array.from(popovers).map((popover) => new DialogBox(popover));
100-
101-
function isElementVisible(element: Element): boolean {
102-
// Check if the element or any of its ancestors have display: none
103-
let current: Element | null = element;
104-
while (current) {
105-
const style = window.getComputedStyle(current);
106-
if (style.display === 'none') {
107-
return false;
108-
}
109-
current = current.parentElement;
110-
}
111-
return true;
112-
}
113-
114-
function getVisibleDialogBox(): DialogBox | undefined {
115-
// Find a dialog box whose link element is actually visible
116-
for (let i = 0; i < dialogBoxes.length; i++) {
117-
const popover = popovers[i];
118-
const linkElement = popover?.querySelector('a');
119-
if (linkElement && isElementVisible(linkElement)) {
120-
return dialogBoxes[i];
121-
}
122-
}
123-
// Fallback to first dialog box if none are visibly rendered
124-
return dialogBoxes[0];
125-
}
126-
127-
// Check if URL hash indicates popover should be open
128-
if (window.location.hash === '#challenges-signup') {
129-
const visibleDialogBox = getVisibleDialogBox();
130-
if (!visibleDialogBox) {
131-
throw new Error('Expected at least one dialog box');
132-
}
133-
visibleDialogBox.dialogElement.showModal();
134-
}
135-
</script>
114+
<script src="./challenges-signup-popover.ts"></script>
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
const popovers = document.querySelectorAll('[data-challenges-signup-popover="true"]');
2+
3+
class DialogBox {
4+
readonly dialogElement: HTMLDialogElement;
5+
6+
constructor(popover: Element) {
7+
const linkElement: HTMLAnchorElement | null = popover.querySelector('a');
8+
const dialogElement: HTMLDialogElement | null = popover.querySelector('dialog');
9+
const formElement: HTMLFormElement | null = popover.querySelector('form');
10+
const closeButton: HTMLButtonElement | null = popover.querySelector('button[data-close]');
11+
12+
if (!linkElement || !dialogElement || !formElement || !closeButton) {
13+
throw new Error(
14+
`Missing required elements: link: ${linkElement ? '✅' : '🚫'}, dialog: ${dialogElement ? '✅' : '🚫'}, form: ${formElement ? '✅' : '🚫'}, closeButton: ${closeButton ? '✅' : '🚫'}`,
15+
);
16+
}
17+
18+
this.dialogElement = dialogElement;
19+
this.dialogElement.dataset.success = 'false';
20+
21+
linkElement.addEventListener('click', (e) => {
22+
e.preventDefault();
23+
window.location.hash = '#challenges-signup';
24+
this.dialogElement.dataset.success = 'false';
25+
dialogElement?.showModal();
26+
});
27+
28+
dialogElement.addEventListener('close', () => {
29+
this.dialogElement.dataset.success = 'false';
30+
if (window.location.hash === '#challenges-signup') {
31+
window.location.hash = '';
32+
}
33+
});
34+
35+
formElement.addEventListener('submit', async (e) => {
36+
e.preventDefault();
37+
const formData = new FormData(formElement);
38+
const data = {
39+
name: formData.get('name'),
40+
email: formData.get('email'),
41+
newsletterAgree: formData.get('newsletter-agree') === 'on',
42+
};
43+
44+
try {
45+
const response = await fetch('https://swmansion.dev/api/shaderhunt/signin', {
46+
method: 'POST',
47+
headers: {
48+
'Content-Type': 'application/json',
49+
},
50+
body: JSON.stringify(data),
51+
});
52+
if (response.ok) {
53+
formElement.reset();
54+
dialogElement.dataset.success = 'true';
55+
} else {
56+
alert('Error submitting form. Please try again.');
57+
}
58+
} catch (error) {
59+
alert('Network error. Please try again.');
60+
console.error(error);
61+
}
62+
});
63+
64+
closeButton.addEventListener('click', () => {
65+
dialogElement.close();
66+
});
67+
}
68+
}
69+
70+
const dialogBoxes = Array.from(popovers).map((popover) => new DialogBox(popover));
71+
72+
function isElementVisible(element: Element): boolean {
73+
// Check if the element or any of its ancestors have display: none
74+
let current: Element | null = element;
75+
while (current) {
76+
const style = window.getComputedStyle(current);
77+
if (style.display === 'none') {
78+
return false;
79+
}
80+
current = current.parentElement;
81+
}
82+
return true;
83+
}
84+
85+
function getVisibleDialogBox(): DialogBox | undefined {
86+
// Find a dialog box whose link element is actually visible
87+
for (let i = 0; i < dialogBoxes.length; i++) {
88+
const popover = popovers[i];
89+
const linkElement = popover?.querySelector('a');
90+
if (linkElement && isElementVisible(linkElement)) {
91+
return dialogBoxes[i];
92+
}
93+
}
94+
// Fallback to first dialog box if none are visibly rendered
95+
return dialogBoxes[0];
96+
}
97+
98+
// Check if URL hash indicates popover should be open
99+
if (window.location.hash === '#challenges-signup') {
100+
const visibleDialogBox = getVisibleDialogBox();
101+
if (!visibleDialogBox) {
102+
throw new Error('Expected at least one dialog box');
103+
}
104+
visibleDialogBox.dialogElement.showModal();
105+
}

apps/typegpu-docs/src/examples/exampleContent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type {
1111

1212
function extractUrlFromViteImport(importFn: () => void): [URL | undefined, boolean] {
1313
const filePath = String(importFn);
14-
const match = filePath.match(/\(\)\s*=>\s*import\("([^"]+)"\)/);
14+
const match = filePath.match(/\(\)\s*=>\s*import\(["`']([^"`']+)["`']\)/);
1515

1616
if (match?.[1]) {
1717
const isRelative = match[1].startsWith('./');

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
],
6868
"overrides": {
6969
"rollup": "catalog:",
70+
"vite": "8.0.2",
7071
"typescript": "catalog:types",
7172
"three": "catalog:example"
7273
}

0 commit comments

Comments
 (0)