Skip to content

Commit 1e01590

Browse files
manuel3108paoloricciutiAdrianGonz97
authored
chore: update demo template to svelte-5 (#58)
* chore: update `demo` template to svelte-5 * chore: fix sverdle route * chore: prevent flash of NaN * fix: properly ssr sverdle component * chore: reintroduce JSDoc comments * chore: fix jsdoc declaration for props * fix: use `$derived.by` for classnames and description * fix: remove unneeded untrack * fix: tests * chore: back to more legible JSDoc without weird non space character * remove optional chaining for `+layout.svelte` * remove optional chaining for `+layout.svelte` * fix tests? * better fix for tests * dedupe * always include `lang="ts"` * update to camelCase * camelCase --------- Co-authored-by: paoloricciuti <[email protected]> Co-authored-by: AdrianGonz97 <[email protected]>
1 parent d97aecd commit 1e01590

File tree

8 files changed

+130
-147
lines changed

8 files changed

+130
-147
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"rollup-plugin-esbuild": "^6.1.1",
3434
"rollup-plugin-preserve-shebangs": "^0.2.0",
3535
"sv": "workspace:*",
36+
"svelte": "^5.0.0-next.1",
3637
"typescript": "^5.6.2",
3738
"typescript-eslint": "^8.5.0",
3839
"unplugin-isolated-decl": "^0.6.5",

packages/create/templates/demo/src/routes/+layout.svelte

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
<script>
1+
<script lang="ts">
22
import Header from './Header.svelte';
33
import '../app.css';
4+
5+
/** @type {{children: import('svelte').Snippet}} */
6+
let { children } = $props();
47
</script>
58

69
<div class="app">
710
<Header />
811

912
<main>
10-
<slot />
13+
{@render children()}
1114
</main>
1215

1316
<footer>

packages/create/templates/demo/src/routes/+page.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
<script>
1+
<script lang="ts">
22
import Counter from './Counter.svelte';
33
import welcome from '$lib/images/svelte-welcome.webp';
4-
import welcome_fallback from '$lib/images/svelte-welcome.png';
4+
import welcomeFallback from '$lib/images/svelte-welcome.png';
55
</script>
66

77
<svelte:head>
@@ -14,7 +14,7 @@
1414
<span class="welcome">
1515
<picture>
1616
<source srcset={welcome} type="image/webp" />
17-
<img src={welcome_fallback} alt="Welcome" />
17+
<img src={welcomeFallback} alt="Welcome" />
1818
</picture>
1919
</span>
2020

packages/create/templates/demo/src/routes/Counter.svelte

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
<script lang="ts">
22
import { spring } from 'svelte/motion';
33
4-
let count = 0;
4+
let count = $state(0);
55
6-
const displayed_count = spring();
7-
$: displayed_count.set(count);
8-
$: offset = modulo($displayed_count, 1);
6+
// svelte-ignore state_referenced_locally
7+
const displayedCount = spring(count);
8+
9+
$effect(() => {
10+
displayedCount.set(count);
11+
});
12+
let offset = $derived(modulo($displayedCount, 1));
913
1014
/**
1115
* @param {number} n
@@ -18,20 +22,20 @@
1822
</script>
1923

2024
<div class="counter">
21-
<button on:click={() => (count -= 1)} aria-label="Decrease the counter by one">
25+
<button onclick={() => (count -= 1)} aria-label="Decrease the counter by one">
2226
<svg aria-hidden="true" viewBox="0 0 1 1">
2327
<path d="M0,0.5 L1,0.5" />
2428
</svg>
2529
</button>
2630

2731
<div class="counter-viewport">
2832
<div class="counter-digits" style="transform: translate(0, {100 * offset}%)">
29-
<strong class="hidden" aria-hidden="true">{Math.floor($displayed_count + 1)}</strong>
30-
<strong>{Math.floor($displayed_count)}</strong>
33+
<strong class="hidden" aria-hidden="true">{Math.floor($displayedCount + 1)}</strong>
34+
<strong>{Math.floor($displayedCount)}</strong>
3135
</div>
3236
</div>
3337

34-
<button on:click={() => (count += 1)} aria-label="Increase the counter by one">
38+
<button onclick={() => (count += 1)} aria-label="Increase the counter by one">
3539
<svg aria-hidden="true" viewBox="0 0 1 1">
3640
<path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" />
3741
</svg>

packages/create/templates/demo/src/routes/Header.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<script>
1+
<script lang="ts">
22
import { page } from '$app/stores';
33
import logo from '$lib/images/svelte-logo.svg';
44
import github from '$lib/images/github.svg';

packages/create/templates/demo/src/routes/sverdle/+page.svelte

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,58 @@
11
<script lang="ts">
2-
import { confetti } from '@neoconfetti/svelte';
32
import { enhance } from '$app/forms';
4-
import type { PageData, ActionData } from './$types';
5-
import { reduced_motion } from './reduced-motion';
3+
import { confetti } from '@neoconfetti/svelte';
4+
import type { ActionData, PageData } from './$types';
5+
import { reducedMotion } from './reduced-motion';
66
7-
/** @type {import('./$types').PageData} */
8-
export let data: PageData;
7+
interface Props {
8+
data: PageData;
9+
form: ActionData;
10+
}
11+
/**
12+
* @typedef {Object} Props
13+
* @property {import('./$types').PageData} data
14+
* @property {import('./$types').ActionData} form
15+
*/
916
10-
/** @type {import('./$types').ActionData} */
11-
export let form: ActionData;
17+
/**
18+
* @type {Props}
19+
*/
20+
let { data, form = $bindable() }: Props = $props();
1221
1322
/** Whether or not the user has won */
14-
$: won = data.answers.at(-1) === 'xxxxx';
23+
let won = $derived(data.answers.at(-1) === 'xxxxx');
1524
1625
/** The index of the current guess */
17-
$: i = won ? -1 : data.answers.length;
26+
let i = $derived(won ? -1 : data.answers.length);
1827
1928
/** The current guess */
20-
$: currentGuess = data.guesses[i] || '';
29+
// svelte-ignore state_referenced_locally
30+
let currentGuess = $state(data.guesses[i] || '');
2131
22-
/** Whether the current guess can be submitted */
23-
$: submittable = currentGuess.length === 5;
24-
25-
/**
26-
* A map of classnames for all letters that have been guessed,
27-
* used for styling the keyboard
28-
* @type {Record<string, 'exact' | 'close' | 'missing'>}
29-
*/
30-
let classnames: Record<string, 'exact' | 'close' | 'missing'>;
31-
32-
/**
33-
* A map of descriptions for all letters that have been guessed,
34-
* used for adding text for assistive technology (e.g. screen readers)
35-
* @type {Record<string, string>}
36-
*/
37-
let description: Record<string, string>;
38-
39-
$: {
40-
classnames = {};
41-
description = {};
32+
$effect(() => {
33+
currentGuess = data.guesses[i] || '';
34+
});
4235
36+
/** Whether the current guess can be submitted */
37+
let submittable = $derived(currentGuess.length === 5);
38+
39+
const { classnames, description } = $derived.by(() => {
40+
/**
41+
* A map of classnames for all letters that have been guessed,
42+
* used for styling the keyboard
43+
* @type {Record<string, 'exact' | 'close' | 'missing'>}
44+
*/
45+
let classnames: Record<string, 'exact' | 'close' | 'missing'> = {};
46+
/**
47+
* A map of descriptions for all letters that have been guessed,
48+
* used for adding text for assistive technology (e.g. screen readers)
49+
* @type {Record<string, string>}
50+
*/
51+
let description: Record<string, string> = {};
4352
data.answers.forEach((answer, i) => {
4453
const guess = data.guesses[i];
45-
4654
for (let i = 0; i < 5; i += 1) {
4755
const letter = guess[i];
48-
4956
if (answer[i] === 'x') {
5057
classnames[letter] = 'exact';
5158
description[letter] = 'correct';
@@ -55,14 +62,16 @@
5562
}
5663
}
5764
});
58-
}
65+
return { classnames, description };
66+
});
5967
6068
/**
6169
* Modify the game state without making a trip to the server,
6270
* if client-side JavaScript is enabled
6371
* @param {MouseEvent} event
6472
*/
6573
function update(event: MouseEvent) {
74+
event.preventDefault();
6675
const key = /** @type {HTMLButtonElement} */ (event.target as HTMLButtonElement).getAttribute(
6776
'data-key'
6877
);
@@ -91,7 +100,7 @@
91100
}
92101
</script>
93102

94-
<svelte:window on:keydown={keydown} />
103+
<svelte:window onkeydown={keydown} />
95104

96105
<svelte:head>
97106
<title>Sverdle</title>
@@ -158,7 +167,7 @@
158167
<button data-key="enter" class:selected={submittable} disabled={!submittable}>enter</button>
159168

160169
<button
161-
on:click|preventDefault={update}
170+
onclick={update}
162171
data-key="backspace"
163172
formaction="?/update"
164173
name="key"
@@ -171,7 +180,7 @@
171180
<div class="row">
172181
{#each row as letter}
173182
<button
174-
on:click|preventDefault={update}
183+
onclick={update}
175184
data-key={letter}
176185
class={classnames[letter]}
177186
disabled={submittable}
@@ -194,7 +203,7 @@
194203
<div
195204
style="position: absolute; left: 50%; top: 30%"
196205
use:confetti={{
197-
particleCount: $reduced_motion ? 0 : undefined,
206+
particleCount: $reducedMotion ? 0 : undefined,
198207
force: 0.7,
199208
stageWidth: window.innerWidth,
200209
stageHeight: window.innerHeight,
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
import { readable } from 'svelte/store';
22
import { browser } from '$app/environment';
33

4-
const reduced_motion_query = '(prefers-reduced-motion: reduce)';
4+
const reducedMotionQuery = '(prefers-reduced-motion: reduce)';
55

6-
const get_initial_motion_preference = () => {
6+
const getInitialMotionPreference = () => {
77
if (!browser) return false;
8-
return window.matchMedia(reduced_motion_query).matches;
8+
return window.matchMedia(reducedMotionQuery).matches;
99
};
1010

11-
export const reduced_motion = readable(get_initial_motion_preference(), (set) => {
11+
export const reducedMotion = readable(getInitialMotionPreference(), (set) => {
1212
if (browser) {
1313
/**
1414
* @param {MediaQueryListEvent} event
1515
*/
16-
const set_reduced_motion = (event: MediaQueryListEvent) => {
16+
const setReducedMotion = (event: MediaQueryListEvent) => {
1717
set(event.matches);
1818
};
19-
const media_query_list = window.matchMedia(reduced_motion_query);
20-
media_query_list.addEventListener('change', set_reduced_motion);
19+
const mediaQueryList = window.matchMedia(reducedMotionQuery);
20+
mediaQueryList.addEventListener('change', setReducedMotion);
2121

2222
return () => {
23-
media_query_list.removeEventListener('change', set_reduced_motion);
23+
mediaQueryList.removeEventListener('change', setReducedMotion);
2424
};
2525
}
2626
});

0 commit comments

Comments
 (0)