diff options
author | Ubuntu <github@matdoes.dev> | 2022-02-14 16:33:38 +0000 |
---|---|---|
committer | Ubuntu <github@matdoes.dev> | 2022-02-14 16:33:38 +0000 |
commit | 9f28b6d9160fee5eff92d1d9849191f2f12faeab (patch) | |
tree | 4ae0ce31df50b0d34a240da1be9bdfa0d4bb6a66 /src/lib | |
download | skyblock-stats-9f28b6d9160fee5eff92d1d9849191f2f12faeab.tar.gz skyblock-stats-9f28b6d9160fee5eff92d1d9849191f2f12faeab.tar.bz2 skyblock-stats-9f28b6d9160fee5eff92d1d9849191f2f12faeab.zip |
Initial commit
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/Counter.svelte | 102 | ||||
-rw-r--r-- | src/lib/form.ts | 84 | ||||
-rw-r--r-- | src/lib/header/Header.svelte | 124 | ||||
-rw-r--r-- | src/lib/header/svelte-logo.svg | 1 |
4 files changed, 311 insertions, 0 deletions
diff --git a/src/lib/Counter.svelte b/src/lib/Counter.svelte new file mode 100644 index 0000000..0df76f5 --- /dev/null +++ b/src/lib/Counter.svelte @@ -0,0 +1,102 @@ +<script lang="ts"> + import { spring } from 'svelte/motion'; + + let count = 0; + + const displayed_count = spring(); + $: displayed_count.set(count); + $: offset = modulo($displayed_count, 1); + + function modulo(n: number, m: number) { + // handle negative numbers + return ((n % m) + m) % m; + } +</script> + +<div class="counter"> + <button on:click={() => (count -= 1)} aria-label="Decrease the counter by one"> + <svg aria-hidden="true" viewBox="0 0 1 1"> + <path d="M0,0.5 L1,0.5" /> + </svg> + </button> + + <div class="counter-viewport"> + <div class="counter-digits" style="transform: translate(0, {100 * offset}%)"> + <strong class="hidden" aria-hidden="true">{Math.floor($displayed_count + 1)}</strong> + <strong>{Math.floor($displayed_count)}</strong> + </div> + </div> + + <button on:click={() => (count += 1)} aria-label="Increase the counter by one"> + <svg aria-hidden="true" viewBox="0 0 1 1"> + <path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" /> + </svg> + </button> +</div> + +<style> + .counter { + display: flex; + border-top: 1px solid rgba(0, 0, 0, 0.1); + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + margin: 1rem 0; + } + + .counter button { + width: 2em; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + border: 0; + background-color: transparent; + color: var(--text-color); + font-size: 2rem; + } + + .counter button:hover { + background-color: var(--secondary-color); + } + + svg { + width: 25%; + height: 25%; + } + + path { + vector-effect: non-scaling-stroke; + stroke-width: 2px; + stroke: var(--text-color); + } + + .counter-viewport { + width: 8em; + height: 4em; + overflow: hidden; + text-align: center; + position: relative; + } + + .counter-viewport strong { + position: absolute; + display: flex; + width: 100%; + height: 100%; + font-weight: 400; + color: var(--accent-color); + font-size: 4rem; + align-items: center; + justify-content: center; + } + + .counter-digits { + position: absolute; + width: 100%; + height: 100%; + } + + .hidden { + top: -100%; + user-select: none; + } +</style> diff --git a/src/lib/form.ts b/src/lib/form.ts new file mode 100644 index 0000000..787a397 --- /dev/null +++ b/src/lib/form.ts @@ -0,0 +1,84 @@ +import { invalidate } from '$app/navigation'; + +// this action (https://svelte.dev/tutorial/actions) allows us to +// progressively enhance a <form> that already works without JS +export function enhance( + form: HTMLFormElement, + { + pending, + error, + result + }: { + pending?: ({ data, form }: { data: FormData; form: HTMLFormElement }) => void; + error?: ({ + data, + form, + response, + error + }: { + data: FormData; + form: HTMLFormElement; + response: Response | null; + error: Error | null; + }) => void; + result?: ({ + data, + form, + response + }: { + data: FormData; + response: Response; + form: HTMLFormElement; + }) => void; + } = {} +): { destroy: () => void } { + let current_token: unknown; + + async function handle_submit(e: Event) { + const token = (current_token = {}); + + e.preventDefault(); + + const data = new FormData(form); + + if (pending) pending({ data, form }); + + try { + const response = await fetch(form.action, { + method: form.method, + headers: { + accept: 'application/json' + }, + body: data + }); + + if (token !== current_token) return; + + if (response.ok) { + if (result) result({ data, form, response }); + + const url = new URL(form.action); + url.search = url.hash = ''; + invalidate(url.href); + } else if (error) { + error({ data, form, error: null, response }); + } else { + console.error(await response.text()); + } + } catch (e: any) { + if (error) { + error({ data, form, error: e, response: null }); + } else { + throw e; + } + } + } + + form.addEventListener('submit', handle_submit); + + return { + destroy() { + form.removeEventListener('submit', handle_submit); + } + }; +} diff --git a/src/lib/header/Header.svelte b/src/lib/header/Header.svelte new file mode 100644 index 0000000..9d3120f --- /dev/null +++ b/src/lib/header/Header.svelte @@ -0,0 +1,124 @@ +<script lang="ts"> + import { page } from '$app/stores'; + import logo from './svelte-logo.svg'; +</script> + +<header> + <div class="corner"> + <a href="https://kit.svelte.dev"> + <img src={logo} alt="SvelteKit" /> + </a> + </div> + + <nav> + <svg viewBox="0 0 2 3" aria-hidden="true"> + <path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" /> + </svg> + <ul> + <li class:active={$page.url.pathname === '/'}><a sveltekit:prefetch href="/">Home</a></li> + <li class:active={$page.url.pathname === '/about'}> + <a sveltekit:prefetch href="/about">About</a> + </li> + <li class:active={$page.url.pathname === '/todos'}> + <a sveltekit:prefetch href="/todos">Todos</a> + </li> + </ul> + <svg viewBox="0 0 2 3" aria-hidden="true"> + <path d="M0,0 L0,3 C0.5,3 0.5,3 1,2 L2,0 Z" /> + </svg> + </nav> + + <div class="corner"> + <!-- TODO put something else here? github link? --> + </div> +</header> + +<style> + header { + display: flex; + justify-content: space-between; + } + + .corner { + width: 3em; + height: 3em; + } + + .corner a { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + } + + .corner img { + width: 2em; + height: 2em; + object-fit: contain; + } + + nav { + display: flex; + justify-content: center; + --background: rgba(255, 255, 255, 0.7); + } + + svg { + width: 2em; + height: 3em; + display: block; + } + + path { + fill: var(--background); + } + + ul { + position: relative; + padding: 0; + margin: 0; + height: 3em; + display: flex; + justify-content: center; + align-items: center; + list-style: none; + background: var(--background); + background-size: contain; + } + + li { + position: relative; + height: 100%; + } + + li.active::before { + --size: 6px; + content: ''; + width: 0; + height: 0; + position: absolute; + top: 0; + left: calc(50% - var(--size)); + border: var(--size) solid transparent; + border-top: var(--size) solid var(--accent-color); + } + + nav a { + display: flex; + height: 100%; + align-items: center; + padding: 0 1em; + color: var(--heading-color); + font-weight: 700; + font-size: 0.8rem; + text-transform: uppercase; + letter-spacing: 0.1em; + text-decoration: none; + transition: color 0.2s linear; + } + + a:hover { + color: var(--accent-color); + } +</style> diff --git a/src/lib/header/svelte-logo.svg b/src/lib/header/svelte-logo.svg new file mode 100644 index 0000000..49492a8 --- /dev/null +++ b/src/lib/header/svelte-logo.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.1566,22.8189c-10.4-14.8851-30.94-19.2971-45.7914-9.8348L22.2825,29.6078A29.9234,29.9234,0,0,0,8.7639,49.6506a31.5136,31.5136,0,0,0,3.1076,20.2318A30.0061,30.0061,0,0,0,7.3953,81.0653a31.8886,31.8886,0,0,0,5.4473,24.1157c10.4022,14.8865,30.9423,19.2966,45.7914,9.8348L84.7167,98.3921A29.9177,29.9177,0,0,0,98.2353,78.3493,31.5263,31.5263,0,0,0,95.13,58.117a30,30,0,0,0,4.4743-11.1824,31.88,31.88,0,0,0-5.4473-24.1157" style="fill:#ff3e00"/><path d="M45.8171,106.5815A20.7182,20.7182,0,0,1,23.58,98.3389a19.1739,19.1739,0,0,1-3.2766-14.5025,18.1886,18.1886,0,0,1,.6233-2.4357l.4912-1.4978,1.3363.9815a33.6443,33.6443,0,0,0,10.203,5.0978l.9694.2941-.0893.9675a5.8474,5.8474,0,0,0,1.052,3.8781,6.2389,6.2389,0,0,0,6.6952,2.485,5.7449,5.7449,0,0,0,1.6021-.7041L69.27,76.281a5.4306,5.4306,0,0,0,2.4506-3.631,5.7948,5.7948,0,0,0-.9875-4.3712,6.2436,6.2436,0,0,0-6.6978-2.4864,5.7427,5.7427,0,0,0-1.6.7036l-9.9532,6.3449a19.0329,19.0329,0,0,1-5.2965,2.3259,20.7181,20.7181,0,0,1-22.2368-8.2427,19.1725,19.1725,0,0,1-3.2766-14.5024,17.9885,17.9885,0,0,1,8.13-12.0513L55.8833,23.7472a19.0038,19.0038,0,0,1,5.3-2.3287A20.7182,20.7182,0,0,1,83.42,29.6611a19.1739,19.1739,0,0,1,3.2766,14.5025,18.4,18.4,0,0,1-.6233,2.4357l-.4912,1.4978-1.3356-.98a33.6175,33.6175,0,0,0-10.2037-5.1l-.9694-.2942.0893-.9675a5.8588,5.8588,0,0,0-1.052-3.878,6.2389,6.2389,0,0,0-6.6952-2.485,5.7449,5.7449,0,0,0-1.6021.7041L37.73,51.719a5.4218,5.4218,0,0,0-2.4487,3.63,5.7862,5.7862,0,0,0,.9856,4.3717,6.2437,6.2437,0,0,0,6.6978,2.4864,5.7652,5.7652,0,0,0,1.602-.7041l9.9519-6.3425a18.978,18.978,0,0,1,5.2959-2.3278,20.7181,20.7181,0,0,1,22.2368,8.2427,19.1725,19.1725,0,0,1,3.2766,14.5024,17.9977,17.9977,0,0,1-8.13,12.0532L51.1167,104.2528a19.0038,19.0038,0,0,1-5.3,2.3287" style="fill:#fff"/></svg>
\ No newline at end of file |