Remove demo todo route, fix placeholder skeletons styles, and fix pagination controls with GET form.

This commit is contained in:
Bradley Shellnut 2022-12-26 22:53:37 -08:00
parent 2e6c38dc44
commit b662968922
9 changed files with 65 additions and 315 deletions

View file

@ -19,9 +19,9 @@
"@sveltejs/adapter-auto": "^1.0.0",
"@sveltejs/kit": "^1.0.1",
"@types/cookie": "^0.5.1",
"@types/node": "^18.11.17",
"@typescript-eslint/eslint-plugin": "^5.47.0",
"@typescript-eslint/parser": "^5.47.0",
"@types/node": "^18.11.18",
"@typescript-eslint/eslint-plugin": "^5.47.1",
"@typescript-eslint/parser": "^5.47.1",
"autoprefixer": "^10.4.13",
"eslint": "^8.30.0",
"eslint-config-prettier": "^8.5.0",

View file

@ -12,9 +12,9 @@ specifiers:
'@sveltejs/kit': ^1.0.1
'@types/cookie': ^0.5.1
'@types/feather-icons': ^4.29.1
'@types/node': ^18.11.17
'@typescript-eslint/eslint-plugin': ^5.47.0
'@typescript-eslint/parser': ^5.47.0
'@types/node': ^18.11.18
'@typescript-eslint/eslint-plugin': ^5.47.1
'@typescript-eslint/parser': ^5.47.1
autoprefixer: ^10.4.13
cookie: ^0.5.0
eslint: ^8.30.0
@ -63,9 +63,9 @@ devDependencies:
'@sveltejs/adapter-auto': 1.0.0_@sveltejs+kit@1.0.1
'@sveltejs/kit': 1.0.1_svelte@3.55.0+vite@4.0.3
'@types/cookie': 0.5.1
'@types/node': 18.11.17
'@typescript-eslint/eslint-plugin': 5.47.0_ncmi6noazr3nzas7jxykisekym
'@typescript-eslint/parser': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa
'@types/node': 18.11.18
'@typescript-eslint/eslint-plugin': 5.47.1_txmweb6yn7coi7nfrp22gpyqmy
'@typescript-eslint/parser': 5.47.1_lzzuuodtsqwxnvqeq4g4likcqa
autoprefixer: 10.4.13_postcss@8.4.20
eslint: 8.30.0
eslint-config-prettier: 8.5.0_eslint@8.30.0
@ -87,7 +87,7 @@ devDependencies:
svelte-preprocess: 4.10.7_tnndubilh5oonjnlrc3mxe2fxi
tslib: 2.4.1
typescript: 4.9.4
vite: 4.0.3_gneikmxcpj2uc2xuqjosnroj4e
vite: 4.0.3_ovmyjmuuyckt3r3gpaexj2onji
vitest: 0.25.8_sass@1.57.1
packages:
@ -420,7 +420,7 @@ packages:
engines: {node: '>=14'}
hasBin: true
dependencies:
'@types/node': 18.11.17
'@types/node': 18.11.18
playwright-core: 1.29.1
dev: true
@ -476,7 +476,7 @@ packages:
svelte: 3.55.0
tiny-glob: 0.2.9
undici: 5.14.0
vite: 4.0.3_gneikmxcpj2uc2xuqjosnroj4e
vite: 4.0.3_ovmyjmuuyckt3r3gpaexj2onji
transitivePeerDependencies:
- supports-color
dev: true
@ -494,7 +494,7 @@ packages:
magic-string: 0.27.0
svelte: 3.55.0
svelte-hmr: 0.15.1_svelte@3.55.0
vite: 4.0.3_gneikmxcpj2uc2xuqjosnroj4e
vite: 4.0.3_ovmyjmuuyckt3r3gpaexj2onji
vitefu: 0.2.4_vite@4.0.3
transitivePeerDependencies:
- supports-color
@ -522,8 +522,8 @@ packages:
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
dev: true
/@types/node/18.11.17:
resolution: {integrity: sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==}
/@types/node/18.11.18:
resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==}
dev: true
/@types/pug/2.0.6:
@ -533,15 +533,15 @@ packages:
/@types/sass/1.43.1:
resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==}
dependencies:
'@types/node': 18.11.17
'@types/node': 18.11.18
dev: true
/@types/semver/7.3.13:
resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==}
dev: true
/@typescript-eslint/eslint-plugin/5.47.0_ncmi6noazr3nzas7jxykisekym:
resolution: {integrity: sha512-AHZtlXAMGkDmyLuLZsRpH3p4G/1iARIwc/T0vIem2YB+xW6pZaXYXzCBnZSF/5fdM97R9QqZWZ+h3iW10XgevQ==}
/@typescript-eslint/eslint-plugin/5.47.1_txmweb6yn7coi7nfrp22gpyqmy:
resolution: {integrity: sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/parser': ^5.0.0
@ -551,10 +551,10 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/parser': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa
'@typescript-eslint/scope-manager': 5.47.0
'@typescript-eslint/type-utils': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa
'@typescript-eslint/utils': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa
'@typescript-eslint/parser': 5.47.1_lzzuuodtsqwxnvqeq4g4likcqa
'@typescript-eslint/scope-manager': 5.47.1
'@typescript-eslint/type-utils': 5.47.1_lzzuuodtsqwxnvqeq4g4likcqa
'@typescript-eslint/utils': 5.47.1_lzzuuodtsqwxnvqeq4g4likcqa
debug: 4.3.4
eslint: 8.30.0
ignore: 5.2.1
@ -567,8 +567,8 @@ packages:
- supports-color
dev: true
/@typescript-eslint/parser/5.47.0_lzzuuodtsqwxnvqeq4g4likcqa:
resolution: {integrity: sha512-udPU4ckK+R1JWCGdQC4Qa27NtBg7w020ffHqGyAK8pAgOVuNw7YaKXGChk+udh+iiGIJf6/E/0xhVXyPAbsczw==}
/@typescript-eslint/parser/5.47.1_lzzuuodtsqwxnvqeq4g4likcqa:
resolution: {integrity: sha512-9Vb+KIv29r6GPu4EboWOnQM7T+UjpjXvjCPhNORlgm40a9Ia9bvaPJswvtae1gip2QEeVeGh6YquqAzEgoRAlw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
@ -577,9 +577,9 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 5.47.0
'@typescript-eslint/types': 5.47.0
'@typescript-eslint/typescript-estree': 5.47.0_typescript@4.9.4
'@typescript-eslint/scope-manager': 5.47.1
'@typescript-eslint/types': 5.47.1
'@typescript-eslint/typescript-estree': 5.47.1_typescript@4.9.4
debug: 4.3.4
eslint: 8.30.0
typescript: 4.9.4
@ -587,16 +587,16 @@ packages:
- supports-color
dev: true
/@typescript-eslint/scope-manager/5.47.0:
resolution: {integrity: sha512-dvJab4bFf7JVvjPuh3sfBUWsiD73aiftKBpWSfi3sUkysDQ4W8x+ZcFpNp7Kgv0weldhpmMOZBjx1wKN8uWvAw==}
/@typescript-eslint/scope-manager/5.47.1:
resolution: {integrity: sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.47.0
'@typescript-eslint/visitor-keys': 5.47.0
'@typescript-eslint/types': 5.47.1
'@typescript-eslint/visitor-keys': 5.47.1
dev: true
/@typescript-eslint/type-utils/5.47.0_lzzuuodtsqwxnvqeq4g4likcqa:
resolution: {integrity: sha512-1J+DFFrYoDUXQE1b7QjrNGARZE6uVhBqIvdaXTe5IN+NmEyD68qXR1qX1g2u4voA+nCaelQyG8w30SAOihhEYg==}
/@typescript-eslint/type-utils/5.47.1_lzzuuodtsqwxnvqeq4g4likcqa:
resolution: {integrity: sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: '*'
@ -605,8 +605,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 5.47.0_typescript@4.9.4
'@typescript-eslint/utils': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa
'@typescript-eslint/typescript-estree': 5.47.1_typescript@4.9.4
'@typescript-eslint/utils': 5.47.1_lzzuuodtsqwxnvqeq4g4likcqa
debug: 4.3.4
eslint: 8.30.0
tsutils: 3.21.0_typescript@4.9.4
@ -615,13 +615,13 @@ packages:
- supports-color
dev: true
/@typescript-eslint/types/5.47.0:
resolution: {integrity: sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg==}
/@typescript-eslint/types/5.47.1:
resolution: {integrity: sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@typescript-eslint/typescript-estree/5.47.0_typescript@4.9.4:
resolution: {integrity: sha512-LxfKCG4bsRGq60Sqqu+34QT5qT2TEAHvSCCJ321uBWywgE2dS0LKcu5u+3sMGo+Vy9UmLOhdTw5JHzePV/1y4Q==}
/@typescript-eslint/typescript-estree/5.47.1_typescript@4.9.4:
resolution: {integrity: sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
typescript: '*'
@ -629,8 +629,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 5.47.0
'@typescript-eslint/visitor-keys': 5.47.0
'@typescript-eslint/types': 5.47.1
'@typescript-eslint/visitor-keys': 5.47.1
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
@ -641,17 +641,17 @@ packages:
- supports-color
dev: true
/@typescript-eslint/utils/5.47.0_lzzuuodtsqwxnvqeq4g4likcqa:
resolution: {integrity: sha512-U9xcc0N7xINrCdGVPwABjbAKqx4GK67xuMV87toI+HUqgXj26m6RBp9UshEXcTrgCkdGYFzgKLt8kxu49RilDw==}
/@typescript-eslint/utils/5.47.1_lzzuuodtsqwxnvqeq4g4likcqa:
resolution: {integrity: sha512-l90SdwqfmkuIVaREZ2ykEfCezepCLxzWMo5gVfcJsJCaT4jHT+QjgSkYhs5BMQmWqE9k3AtIfk4g211z/sTMVw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
'@types/json-schema': 7.0.11
'@types/semver': 7.3.13
'@typescript-eslint/scope-manager': 5.47.0
'@typescript-eslint/types': 5.47.0
'@typescript-eslint/typescript-estree': 5.47.0_typescript@4.9.4
'@typescript-eslint/scope-manager': 5.47.1
'@typescript-eslint/types': 5.47.1
'@typescript-eslint/typescript-estree': 5.47.1_typescript@4.9.4
eslint: 8.30.0
eslint-scope: 5.1.1
eslint-utils: 3.0.0_eslint@8.30.0
@ -661,11 +661,11 @@ packages:
- typescript
dev: true
/@typescript-eslint/visitor-keys/5.47.0:
resolution: {integrity: sha512-ByPi5iMa6QqDXe/GmT/hR6MZtVPi0SqMQPDx15FczCBXJo/7M8T88xReOALAfpBLm+zxpPfmhuEvPb577JRAEg==}
/@typescript-eslint/visitor-keys/5.47.1:
resolution: {integrity: sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.47.0
'@typescript-eslint/types': 5.47.1
eslint-visitor-keys: 3.3.0
dev: true
@ -2164,7 +2164,7 @@ packages:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: true
/vite/4.0.3_gneikmxcpj2uc2xuqjosnroj4e:
/vite/4.0.3_ovmyjmuuyckt3r3gpaexj2onji:
resolution: {integrity: sha512-HvuNv1RdE7deIfQb8mPk51UKjqptO/4RXZ5yXSAvurd5xOckwS/gg8h9Tky3uSbnjYTgUm0hVCet1cyhKd73ZA==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
@ -2189,7 +2189,7 @@ packages:
terser:
optional: true
dependencies:
'@types/node': 18.11.17
'@types/node': 18.11.18
esbuild: 0.16.8
postcss: 8.4.20
resolve: 1.22.1
@ -2207,7 +2207,7 @@ packages:
vite:
optional: true
dependencies:
vite: 4.0.3_gneikmxcpj2uc2xuqjosnroj4e
vite: 4.0.3_ovmyjmuuyckt3r3gpaexj2onji
dev: true
/vitest/0.25.8_sass@1.57.1:
@ -2234,7 +2234,7 @@ packages:
dependencies:
'@types/chai': 4.3.4
'@types/chai-subset': 1.3.3
'@types/node': 18.11.17
'@types/node': 18.11.18
acorn: 8.8.1
acorn-walk: 8.2.0
chai: 4.3.7
@ -2245,7 +2245,7 @@ packages:
tinybench: 2.3.1
tinypool: 0.3.0
tinyspy: 1.0.2
vite: 4.0.3_gneikmxcpj2uc2xuqjosnroj4e
vite: 4.0.3_ovmyjmuuyckt3r3gpaexj2onji
transitivePeerDependencies:
- less
- sass

View file

@ -1,8 +1,12 @@
<!-- Taken from carbon design system svelte -->
<!-- https://github.com/carbon-design-system/carbon-components-svelte/blob/master/src/SkeletonPlaceholder/SkeletonPlaceholder.svelte -->
<script lang="ts">
export let style: string;
</script>
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
<div
{style}
class:bx--skeleton__placeholder={true}
{...$$restProps}
on:click

View file

@ -33,9 +33,10 @@
let gameToRemove: GameType | SavedGameType;
let numberOfGameSkeleton = 1;
let submitButton: HTMLElement;
let pageSize = 10;
let page = +data?.page || 1;
let totalItems = data?.totalCount || 0;
let pageSize = +data?.limit || 10;
let totalItems = +data?.totalCount || 0;
let offset = +data?.skip || 0;
let page = Math.floor(offset / pageSize) + 1 || 1;
let submitting = $boredState?.loading;
let name = data?.name || '';
let disclosureOpen = errors || false;
@ -77,11 +78,9 @@
}
async function handlePerPageEvent(event: CustomEvent) {
console.log('Per Page Event called', event.detail);
page = 1;
pageSize = event.detail.pageSize;
await tick();
// console.log('New limit value DOM: ', document.getElementById('limit')?.getAttribute('value'));
submitButton.click();
}

View file

@ -1,6 +1,6 @@
import type { Actions, PageServerLoad, RequestEvent } from '../$types';
import { BOARD_GAME_ATLAS_CLIENT_ID } from '$env/static/private';
import { error, fail, type ServerLoadEvent } from '@sveltejs/kit';
import { error, fail } from '@sveltejs/kit';
import type { GameType, Search, SearchQuery } from '$root/lib/types';
import { mapAPIGameToBoredGame } from '$root/lib/util/gameMapper';
import { search_schema } from '$root/lib/zodValidation';

View file

@ -6,6 +6,8 @@
export let data: PageData;
export let form: ActionData;
console.log('data limit', data?.limit);
$: if (data?.games) {
gameStore.removeAll();
gameStore.addAll(data?.games);

View file

@ -1,55 +0,0 @@
import { error } from '@sveltejs/kit';
import { api } from './api';
import type { PageServerLoad, Action } from './$types';
type Todo = {
uid: string;
created_at: Date;
text: string;
done: boolean;
pending_delete: boolean;
};
export const load: PageServerLoad = async ({ locals }) => {
// locals.userid comes from src/hooks.js
const response = await api('GET', `todos/${locals.userid}`);
if (response.status === 404) {
// user hasn't created a todo list.
// start with an empty array
return {
todos: [] as Todo[]
};
}
if (response.status === 200) {
return {
todos: (await response.json()) as Todo[]
};
}
throw error(response.status);
};
export const POST: Action = async ({ request, locals }) => {
const form = await request.formData();
await api('POST', `todos/${locals.userid}`, {
text: form.get('text')
});
};
export const PATCH: Action = async ({ request, locals }) => {
const form = await request.formData();
await api('PATCH', `todos/${locals.userid}/${form.get('uid')}`, {
text: form.has('text') ? form.get('text') : undefined,
done: form.has('done') ? !!form.get('done') : undefined
});
};
export const DELETE: Action = async ({ request, locals }) => {
const form = await request.formData();
await api('DELETE', `todos/${locals.userid}/${form.get('uid')}`);
};

View file

@ -1,180 +0,0 @@
<script lang="ts">
import type { PageData } from './$types';
import { enhance } from '$lib/form';
import { scale } from 'svelte/transition';
import { flip } from 'svelte/animate';
export let data: PageData;
</script>
<svelte:head>
<title>Todos</title>
<meta name="description" content="A todo list app" />
</svelte:head>
<div class="todos">
<h1>Todos</h1>
<form
class="new"
action="/todos"
method="post"
use:enhance={{
result: async ({ form }) => {
form.reset();
}
}}
>
<input name="text" aria-label="Add todo" placeholder="+ tap to add a todo" />
</form>
{#each data.todos as todo (todo.uid)}
<div
class="todo"
class:done={todo.done}
transition:scale|local={{ start: 0.7 }}
animate:flip={{ duration: 200 }}
>
<form
action="/todos?_method=PATCH"
method="post"
use:enhance={{
pending: ({ data }) => {
todo.done = !!data.get('done');
}
}}
>
<input type="hidden" name="uid" value={todo.uid} />
<input type="hidden" name="done" value={todo.done ? '' : 'true'} />
<button class="toggle" aria-label="Mark todo as {todo.done ? 'not done' : 'done'}" />
</form>
<form class="text" action="/todos?_method=PATCH" method="post" use:enhance>
<input type="hidden" name="uid" value={todo.uid} />
<input aria-label="Edit todo" type="text" name="text" value={todo.text} />
<button class="save" aria-label="Save todo" />
</form>
<form
action="/todos?_method=DELETE"
method="post"
use:enhance={{
pending: () => (todo.pending_delete = true)
}}
>
<input type="hidden" name="uid" value={todo.uid} />
<button class="delete" aria-label="Delete todo" disabled={todo.pending_delete} />
</form>
</div>
{/each}
</div>
<style>
.todos {
width: 100%;
max-width: var(--column-width);
margin: var(--column-margin-top) auto 0 auto;
line-height: 1;
}
.new {
margin: 0 0 0.5rem 0;
}
input {
border: 1px solid transparent;
}
input:focus-visible {
box-shadow: inset 1px 1px 6px rgba(0, 0, 0, 0.1);
border: 1px solid #ff3e00 !important;
outline: none;
}
.new input {
font-size: 28px;
width: 100%;
padding: 0.5em 1em 0.3em 1em;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
text-align: center;
}
.todo {
display: grid;
grid-template-columns: 2rem 1fr 2rem;
grid-gap: 0.5rem;
align-items: center;
margin: 0 0 0.5rem 0;
padding: 0.5rem;
background-color: white;
border-radius: 8px;
filter: drop-shadow(2px 4px 6px rgba(0, 0, 0, 0.1));
transform: translate(-1px, -1px);
transition: filter 0.2s, transform 0.2s;
}
.done {
transform: none;
opacity: 0.4;
filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.1));
}
form.text {
position: relative;
display: flex;
align-items: center;
flex: 1;
}
.todo input {
flex: 1;
padding: 0.5em 2em 0.5em 0.8em;
border-radius: 3px;
}
.todo button {
width: 2em;
height: 2em;
border: none;
background-color: transparent;
background-position: 50% 50%;
background-repeat: no-repeat;
}
button.toggle {
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 50%;
box-sizing: border-box;
background-size: 1em auto;
}
.done .toggle {
background-image: url("data:image/svg+xml,%3Csvg width='22' height='16' viewBox='0 0 22 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.5 1.5L7.4375 14.5L1.5 8.5909' stroke='%23676778' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.delete {
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.5 5V22H19.5V5H4.5Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M10 10V16.5' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M14 10V16.5' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M2 5H22' stroke='%23676778' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M8 5L9.6445 2H14.3885L16 5H8Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
opacity: 0.2;
}
.delete:hover,
.delete:focus {
transition: opacity 0.2s;
opacity: 1;
}
.save {
position: absolute;
right: 0;
opacity: 0;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.5 2H3.5C2.67158 2 2 2.67157 2 3.5V20.5C2 21.3284 2.67158 22 3.5 22H20.5C21.3284 22 22 21.3284 22 20.5V3.5C22 2.67157 21.3284 2 20.5 2Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M17 2V11H7.5V2H17Z' fill='white' stroke='white' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M13.5 5.5V7.5' stroke='%23676778' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M5.99844 2H18.4992' stroke='%23676778' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E%0A");
}
.todo input:focus + .save,
.save:focus {
transition: opacity 0.2s;
opacity: 1;
}
</style>

View file

@ -1,20 +0,0 @@
/*
This module is used by the /todos endpoint to
make calls to api.svelte.dev, which stores todos
for each user.
(The data on the todo app will expire periodically; no
guarantees are made. Don't use it to organise your life.)
*/
const base = 'https://api.svelte.dev';
export function api(method: string, resource: string, data?: Record<string, unknown>) {
return fetch(`${base}/${resource}`, {
method,
headers: {
'content-type': 'application/json'
},
body: data && JSON.stringify(data)
});
}