|
|
|
<script>
|
|
|
|
import { quintOut } from 'svelte/easing';
|
|
|
|
import { crossfade } from 'svelte/transition';
|
|
|
|
import { flip } from 'svelte/animate';
|
|
|
|
|
|
|
|
const [send, receive] = crossfade({
|
|
|
|
duration: d => Math.sqrt(d * 200),
|
|
|
|
|
|
|
|
fallback(node, params) {
|
|
|
|
const style = getComputedStyle(node);
|
|
|
|
const transform = style.transform === 'none' ? '' : style.transform;
|
|
|
|
|
|
|
|
return {
|
|
|
|
duration: 600,
|
|
|
|
easing: quintOut,
|
|
|
|
css: t => `
|
|
|
|
transform: ${transform} scale(${t});
|
|
|
|
opacity: ${t}
|
|
|
|
`
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
let uid = 1;
|
|
|
|
|
|
|
|
let todos = [
|
|
|
|
{ id: uid++, done: false, description: 'write some docs' },
|
|
|
|
{ id: uid++, done: false, description: 'start writing blog post' },
|
|
|
|
{ id: uid++, done: true, description: 'buy some milk' },
|
|
|
|
{ id: uid++, done: false, description: 'mow the lawn' },
|
|
|
|
{ id: uid++, done: false, description: 'feed the turtle' },
|
|
|
|
{ id: uid++, done: false, description: 'fix some bugs' },
|
|
|
|
];
|
|
|
|
|
|
|
|
function add(input) {
|
|
|
|
const todo = {
|
|
|
|
id: uid++,
|
|
|
|
done: false,
|
|
|
|
description: input.value
|
|
|
|
};
|
|
|
|
|
|
|
|
todos = [todo, ...todos];
|
|
|
|
input.value = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
function remove(todo) {
|
|
|
|
todos = todos.filter(t => t !== todo);
|
|
|
|
}
|
|
|
|
|
|
|
|
function mark(todo, done) {
|
|
|
|
todo.done = done;
|
|
|
|
remove(todo);
|
|
|
|
todos = todos.concat(todo);
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<div class='board'>
|
|
|
|
<input
|
|
|
|
placeholder="what needs to be done?"
|
|
|
|
on:keydown={e => e.which === 13 && add(e.target)}
|
|
|
|
>
|
|
|
|
|
|
|
|
<div class='left'>
|
|
|
|
<h2>todo</h2>
|
|
|
|
{#each todos.filter(t => !t.done) as todo (todo.id)}
|
|
|
|
<label
|
|
|
|
in:receive="{{key: todo.id}}"
|
|
|
|
out:send="{{key: todo.id}}"
|
|
|
|
animate:flip
|
|
|
|
>
|
|
|
|
<input type=checkbox on:change={() => mark(todo, true)}>
|
|
|
|
{todo.description}
|
|
|
|
<button on:click="{() => remove(todo)}">remove</button>
|
|
|
|
</label>
|
|
|
|
{/each}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class='right'>
|
|
|
|
<h2>done</h2>
|
|
|
|
{#each todos.filter(t => t.done) as todo (todo.id)}
|
|
|
|
<label
|
|
|
|
class="done"
|
|
|
|
in:receive="{{key: todo.id}}"
|
|
|
|
out:send="{{key: todo.id}}"
|
|
|
|
animate:flip
|
|
|
|
>
|
|
|
|
<input type=checkbox checked on:change={() => mark(todo, false)}>
|
|
|
|
{todo.description}
|
|
|
|
<button on:click="{() => remove(todo)}">remove</button>
|
|
|
|
</label>
|
|
|
|
{/each}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.board {
|
|
|
|
display: grid;
|
|
|
|
grid-template-columns: 1fr 1fr;
|
|
|
|
grid-gap: 1em;
|
|
|
|
max-width: 36em;
|
|
|
|
margin: 0 auto;
|
|
|
|
}
|
|
|
|
|
|
|
|
.board > input {
|
|
|
|
font-size: 1.4em;
|
|
|
|
grid-column: 1/3;
|
|
|
|
}
|
|
|
|
|
|
|
|
h2 {
|
|
|
|
font-size: 2em;
|
|
|
|
font-weight: 200;
|
|
|
|
user-select: none;
|
|
|
|
margin: 0 0 0.5em 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
label {
|
|
|
|
position: relative;
|
|
|
|
line-height: 1.2;
|
|
|
|
padding: 0.5em 2.5em 0.5em 2em;
|
|
|
|
margin: 0 0 0.5em 0;
|
|
|
|
border-radius: 2px;
|
|
|
|
user-select: none;
|
|
|
|
border: 1px solid hsl(240, 8%, 70%);
|
|
|
|
background-color:hsl(240, 8%, 93%);
|
|
|
|
color: #333;
|
|
|
|
}
|
|
|
|
|
|
|
|
input[type="checkbox"] {
|
|
|
|
position: absolute;
|
|
|
|
left: 0.5em;
|
|
|
|
top: 0.6em;
|
|
|
|
margin: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.done {
|
|
|
|
border: 1px solid hsl(240, 8%, 90%);
|
|
|
|
background-color:hsl(240, 8%, 98%);
|
|
|
|
}
|
|
|
|
|
|
|
|
button {
|
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
right: 0.2em;
|
|
|
|
width: 2em;
|
|
|
|
height: 100%;
|
|
|
|
background: no-repeat 50% 50% url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23676778' d='M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M17,7H14.5L13.5,6H10.5L9.5,7H7V9H17V7M9,18H15A1,1 0 0,0 16,17V10H8V17A1,1 0 0,0 9,18Z'%3E%3C/path%3E%3C/svg%3E");
|
|
|
|
background-size: 1.4em 1.4em;
|
|
|
|
border: none;
|
|
|
|
opacity: 0;
|
|
|
|
transition: opacity 0.2s;
|
|
|
|
text-indent: -9999px;
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
label:hover button {
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
</style>
|