Skip to content

Commit

Permalink
Example: Update Svelte example
Browse files Browse the repository at this point in the history
  • Loading branch information
1aron committed Dec 9, 2024
1 parent 67ae9cb commit 73a2e89
Show file tree
Hide file tree
Showing 24 changed files with 1,779 additions and 1,264 deletions.
16 changes: 8 additions & 8 deletions examples/svelte-with-runtime-rendering/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
"devDependencies": {
"@fontsource/fira-mono": "^4.5.10",
"@neoconfetti/svelte": "^1.0.0",
"@sveltejs/adapter-auto": "^3.1.1",
"@sveltejs/kit": "^2.5.1",
"@sveltejs/vite-plugin-svelte": "^3.0.2",
"svelte": "^4.2.12",
"svelte-check": "^3.6.4",
"tslib": "^2.6.2",
"typescript": "^5.3.3",
"vite": "^5.1.4"
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"globals": "^15.0.0",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^6.0.0"
},
"type": "module"
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { dev } from '$app/environment'
import { dev } from '$app/environment';

// we don't need any JS on this page, though we'll load
// it in dev so that we get hot module replacement
export const csr = dev
export const csr = dev;

// since there's no dynamic data here, we can prerender
// it so that it gets served as a static asset in production
export const prerender = true
export const prerender = true;
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const actions = {
game.guesses[i] += key;
}

cookies.set('sverdle', game.toString());
cookies.set('sverdle', game.toString(), { path: '/' });
},

/**
Expand All @@ -60,10 +60,10 @@ export const actions = {
return fail(400, { badGuess: true });
}

cookies.set('sverdle', game.toString());
cookies.set('sverdle', game.toString(), { path: '/' });
},

restart: async ({ cookies }) => {
cookies.delete('sverdle');
cookies.delete('sverdle', { path: '/' });
}
} satisfies Actions;
Original file line number Diff line number Diff line change
@@ -1,44 +1,47 @@
<script lang="ts">
import { confetti } from '@neoconfetti/svelte';
import { enhance } from '$app/forms';
import type { PageData, ActionData } from './$types';
import { reduced_motion } from './reduced-motion';
export let data: PageData;
import { confetti } from '@neoconfetti/svelte';
import type { ActionData, PageData } from './$types';
import { reducedMotion } from './reduced-motion';
export let form: ActionData;
interface Props {
data: PageData;
form: ActionData;
}
let { data, form = $bindable() }: Props = $props();
/** Whether or not the user has won */
$: won = data.answers.at(-1) === 'xxxxx';
let won = $derived(data.answers.at(-1) === 'xxxxx');
/** The index of the current guess */
$: i = won ? -1 : data.answers.length;
/** Whether the current guess can be submitted */
$: submittable = data.guesses[i]?.length === 5;
/**
* A map of classnames for all letters that have been guessed,
* used for styling the keyboard
*/
let classnames: Record<string, 'exact' | 'close' | 'missing'>;
let i = $derived(won ? -1 : data.answers.length);
/**
* A map of descriptions for all letters that have been guessed,
* used for adding text for assistive technology (e.g. screen readers)
*/
let description: Record<string, string>;
/** The current guess */
// svelte-ignore state_referenced_locally
let currentGuess = $state(data.guesses[i] || '');
$: {
classnames = {};
description = {};
$effect(() => {
currentGuess = data.guesses[i] || '';
});
/** Whether the current guess can be submitted */
let submittable = $derived(currentGuess.length === 5);
const { classnames, description } = $derived.by(() => {
/**
* A map of classnames for all letters that have been guessed,
* used for styling the keyboard
*/
let classnames: Record<string, 'exact' | 'close' | 'missing'> = {};
/**
* A map of descriptions for all letters that have been guessed,
* used for adding text for assistive technology (e.g. screen readers)
*/
let description: Record<string, string> = {};
data.answers.forEach((answer, i) => {
const guess = data.guesses[i];
for (let i = 0; i < 5; i += 1) {
const letter = guess[i];
if (answer[i] === 'x') {
classnames[letter] = 'exact';
description[letter] = 'correct';
Expand All @@ -48,23 +51,24 @@
}
}
});
}
return { classnames, description };
});
/**
* Modify the game state without making a trip to the server,
* if client-side JavaScript is enabled
*/
function update(event: MouseEvent) {
const guess = data.guesses[i];
event.preventDefault();
const key = (event.target as HTMLButtonElement).getAttribute(
'data-key'
);
if (key === 'backspace') {
data.guesses[i] = guess.slice(0, -1);
currentGuess = currentGuess.slice(0, -1);
if (form?.badGuess) form.badGuess = false;
} else if (guess.length < 5) {
data.guesses[i] += key;
} else if (currentGuess.length < 5) {
currentGuess += key;
}
}
Expand All @@ -75,13 +79,15 @@
function keydown(event: KeyboardEvent) {
if (event.metaKey) return;
if (event.key === 'Enter' && !submittable) return;
document
.querySelector(`[data-key="${event.key}" i]`)
?.dispatchEvent(new MouseEvent('click', { cancelable: true }));
}
</script>

<svelte:window on:keydown={keydown} />
<svelte:window onkeydown={keydown} />

<svelte:head>
<title>Sverdle</title>
Expand All @@ -91,7 +97,7 @@
<h1 class="visually-hidden">Sverdle</h1>

<form
method="POST"
method="post"
action="?/enter"
use:enhance={() => {
// prevent default callback from resetting the form
Expand All @@ -103,14 +109,15 @@
<a class="how-to-play" href="/sverdle/how-to-play">How to play</a>

<div class="grid" class:playing={!won} class:bad-guess={form?.badGuess}>
{#each Array(6) as _, row}
{#each Array.from(Array(6).keys()) as row (row)}
{@const current = row === i}
<h2 class="visually-hidden">Row {row + 1}</h2>
<div class="row" class:current>
{#each Array(5) as _, column}
{#each Array.from(Array(5).keys()) as column (column)}
{@const guess = current ? currentGuess : data.guesses[row]}
{@const answer = data.answers[row]?.[column]}
{@const value = data.guesses[row]?.[column] ?? ''}
{@const selected = current && column === data.guesses[row].length}
{@const value = guess?.[column] ?? ''}
{@const selected = current && column === guess.length}
{@const exact = answer === 'x'}
{@const close = answer === 'c'}
{@const missing = answer === '_'}
Expand Down Expand Up @@ -147,7 +154,7 @@
<button data-key="enter" class:selected={submittable} disabled={!submittable}>enter</button>

<button
on:click|preventDefault={update}
onclick={update}
data-key="backspace"
formaction="?/update"
name="key"
Expand All @@ -160,10 +167,10 @@
<div class="row">
{#each row as letter}
<button
on:click|preventDefault={update}
onclick={update}
data-key={letter}
class={classnames[letter]}
disabled={data.guesses[i].length === 5}
disabled={submittable}
formaction="?/update"
name="key"
value={letter}
Expand All @@ -183,13 +190,13 @@
<div
style="position: absolute; left: 50%; top: 30%"
use:confetti={{
particleCount: $reduced_motion ? 0 : undefined,
particleCount: $reducedMotion ? 0 : undefined,
force: 0.7,
stageWidth: window.innerWidth,
stageHeight: window.innerHeight,
colors: ['#ff3e00', '#40b3ff', '#676778']
}}
/>
></div>
{/if}

<style>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { readable } from 'svelte/store';
import { browser } from '$app/environment';

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

const get_initial_motion_preference = () => {
const getInitialMotionPreference = () => {
if (!browser) return false;
return window.matchMedia(reduced_motion_query).matches;
return window.matchMedia(reducedMotionQuery).matches;
};

export const reduced_motion = readable(get_initial_motion_preference(), (set) => {
export const reducedMotion = readable(getInitialMotionPreference(), (set) => {
if (browser) {
const set_reduced_motion = (event: MediaQueryListEvent) => {
const setReducedMotion = (event: MediaQueryListEvent) => {
set(event.matches);
};
const media_query_list = window.matchMedia(reduced_motion_query);
media_query_list.addEventListener('change', set_reduced_motion);
const mediaQueryList = window.matchMedia(reducedMotionQuery);
mediaQueryList.addEventListener('change', setReducedMotion);

return () => {
media_query_list.removeEventListener('change', set_reduced_motion);
mediaQueryList.removeEventListener('change', setReducedMotion);
};
}
});
18 changes: 9 additions & 9 deletions examples/svelte-with-static-extraction/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
},
"devDependencies": {
"@fontsource/fira-mono": "^4.5.10",
"@master/css-extractor.vite": "workspace:^",
"@master/css-runtime": "workspace:^",
"@fontsource/fira-mono": "^4.5.10",
"@neoconfetti/svelte": "^1.0.0",
"@sveltejs/adapter-auto": "^3.1.1",
"@sveltejs/kit": "^2.5.1",
"@sveltejs/vite-plugin-svelte": "^3.0.2",
"svelte": "^4.2.12",
"svelte-check": "^3.6.4",
"tslib": "^2.6.2",
"typescript": "^5.3.3",
"vite": "^5.1.4"
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"globals": "^15.0.0",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^6.0.0"
},
"type": "module"
}
68 changes: 37 additions & 31 deletions examples/svelte-with-static-extraction/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script>
import Counter from './Counter.svelte';
import welcome from '$lib/images/svelte-welcome.webp';
import welcome_fallback from '$lib/images/svelte-welcome.png';
import Counter from "./Counter.svelte";
import welcome from "$lib/images/svelte-welcome.webp";
import welcome_fallback from "$lib/images/svelte-welcome.png";
</script>

<svelte:head>
Expand All @@ -17,7 +17,13 @@
<img src={welcome_fallback} alt="Welcome" />
</picture>
</span>
<img src="/[email protected]" alt="Master Logo" class="mt:-2vw block mx:auto max-w:50%" width="300" height="35" />
<img
src="/[email protected]"
alt="Master Logo"
class="mt:-2vw block mx:auto max-w:50%"
width="300"
height="35"
/>
<span class="sr-only">Svelte Kit and Master CSS</span>
</h1>

Expand All @@ -29,31 +35,31 @@
</section>

<style>
section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex: 0.6;
}
h1 {
width: 100%;
}
.welcome {
display: block;
position: relative;
width: 100%;
height: 0;
padding: 0 0 calc(100% * 495 / 2048) 0;
}
.welcome img {
position: absolute;
width: 100%;
height: 100%;
top: 0;
display: block;
}
section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex: 0.6;
}
h1 {
width: 100%;
}
.welcome {
display: block;
position: relative;
width: 100%;
height: 0;
padding: 0 0 calc(100% * 495 / 2048) 0;
}
.welcome img {
position: absolute;
width: 100%;
height: 100%;
top: 0;
display: block;
}
</style>
Loading

0 comments on commit 73a2e89

Please sign in to comment.