Skip to content

Commit

Permalink
feat: tags todomvc demo based on older one
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Carniato committed Apr 26, 2022
1 parent f992a83 commit 724ee21
Show file tree
Hide file tree
Showing 12 changed files with 315 additions and 0 deletions.
3 changes: 3 additions & 0 deletions examples/tags-todomvc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
build
*.log
19 changes: 19 additions & 0 deletions examples/tags-todomvc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "tags-todomvc",
"description": "Marko TodoMVC example",
"version": "1.0.0",
"dependencies": {
"@marko/tags-api-preview": "^0",
"marko": "^5"
},
"devDependencies": {
"@marko/build": "^4",
"@marko/serve": "^4"
},
"private": true,
"scripts": {
"build": "marko-build ./src/pages",
"dev": "marko-serve ./src/pages",
"start": "node ./build/index.js"
}
}
20 changes: 20 additions & 0 deletions examples/tags-todomvc/src/components/todomvc-app/demo.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<const/todos = [
{
title: "Learn marko",
completed: true,
id: 0
},
{
title: "Build an awesome web app",
completed: false,
id: 1
},
{
title: "Profit",
completed: false,
id: 2
}
]
/>

<todomvc-app todos=todos filter="all"/>
85 changes: 85 additions & 0 deletions examples/tags-todomvc/src/components/todomvc-app/index.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<todomvc-store/{
todos,
filter,
setFilter,
addNewTodo,
clearCompleted,
toggleAllTodosCompleted,
updateTodo,
removeTodo
}/>
<section.todoapp>
<todomvc-header addNewTodo=addNewTodo />
<if=todos.length>
<const/filteredTodos = todos.filter(todo => {
if (todo.pending) return true;
if (filter === "active") return !todo.completed;
if (filter === "completed") return todo.completed;
return true;
})/>
<const/remainingCount=todos.length - todos.filter((todo) => todo.completed).length />
<const/handleFilter=((filter) => (e) => {
setFilter(filter);
e.preventDefault();
})/>
<section.main>
<id/toggleId />
<input.toggle-all
id=toggleId
type="checkbox"
checked=(!remainingCount)
onChange(e) {
toggleAllTodosCompleted(e.target.checked);
}>
<label for=toggleId />
<ul.todo-list>
<for|todo| of=filteredTodos by=(todo => todo.id)>
<todomvc-todo-item
todo=todo
updateTodo=updateTodo
removeTodo=removeTodo />
</for>
</ul>
</section>
<footer.footer>
<span.todo-count>
<strong>${remainingCount}</strong> ${remainingCount > 1 ? "items" : "item"} left
</span>
<ul.filters>
<li>
<a
href="#/"
class={ selected: filter === "all" }
onClick=handleFilter("all")>
All
</a>
</li>
<li>
<a
href="#/active"
class={ selected: filter === "active" }
onClick=handleFilter("active")>
Active
</a>
</li>
<li>
<a
href="#/completed"
class={ selected: filter === "completed" }
onClick=handleFilter("completed")>
Completed
</a>
</li>
</ul>
<if=(remainingCount !== todos.length)>
<button.clear-completed onClick=clearCompleted >
Clear completed
</button>
</if>
</footer>
</if>
</section>

<style>
@import url("https://unpkg.com/[email protected]/index.css");
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div.todoapp>
<todomvc-header/>
</div>
<style>
@import url("https://unpkg.com/[email protected]/index.css");
</style>
18 changes: 18 additions & 0 deletions examples/tags-todomvc/src/components/todomvc-header/index.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<attrs/{ addNewTodo } />
<header.header>
<h1>todos</h1>
<form onSubmit(e) {
const titleInput = title();
addNewTodo({ title: titleInput.value });
titleInput.value = "";
e.preventDefault();
}>
<input/title class="new-todo" placeholder="What needs to be done?"/>
</form>
</header>

<style>
.header form {
margin: 0;
}
</style>
47 changes: 47 additions & 0 deletions examples/tags-todomvc/src/components/todomvc-store/index.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<let/nextId=3/>
<let/todos=[{
title: 'Learn marko',
completed: true,
id: 0
},
{
title: 'Build an awesome web app',
completed: false,
id: 1
},
{
title: 'Profit',
completed: false,
id: 2
}]/>
<let/filter="all"/>
<return={
todos,
filter,
setFilter(f) { filter = f },
updateTodo(todoId, newProps) {
todos = todos.map(todo => {
if (todo.id !== todoId) return todo;
return { ...todo, ...newProps }
})
},
clearCompleted() {
todos = todos.filter(todo => !todo.completed);
},
removeTodo(todoId) {
todos = todos.filter(todo => todo.id !== todoId);
},
toggleAllTodosCompleted(completed) {
todos = todos.map((todo) => {
if (todo.completed === completed) return todo;
return { ...todo, completed };
});
},
addNewTodo(todoData) {
todos = [...todos, {
title: todoData.title,
id: 'c' + (nextId++),
completed: false
}];
}
} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export function animateOut(event, node) {
event.preventDefault();
node.classList.add("animate");
var height = node.offsetHeight;
node.style.maxHeight = height + "px";

setTimeout(() => {
node.style.maxHeight = "0px";
node.style.opacity = 0;

setTimeout(() => {
event.detach();
}, 250);
}, 0);
}

export function animateIn(event, node) {
var height = node.offsetHeight;
node.classList.remove("animate");
node.style.maxHeight = "0px";
node.style.opacity = 0;

setTimeout(() => {
node.classList.add("animate");
node.style.maxHeight = height + "px";
node.style.opacity = 1;
}, 10);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<section.main>
<ul.todo-list>
<todomvc-todo-item title="Learn Marko" completed=false id="fake1"/>
<todomvc-todo-item title="Learn Marko" completed=true id="fake2"/>
</ul>
</section>
<style>
@import url("https://unpkg.com/[email protected]/index.css");
</style>
55 changes: 55 additions & 0 deletions examples/tags-todomvc/src/components/todomvc-todo-item/index.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { animateIn, animateOut } from "./animations";

<attrs/{ todo, updateTodo, removeTodo } />
<let/isEditing=false />
<let/editingTitle="" />
<const/saveEdit() {
if (isEditing) {
const el = title();
updateTodo(todo.id, { title: el.value });
isEditing = false;
}
}/>
<const/handleInputKeyDown(e) {
if (e.keyCode === 13 /* ENTER */) {
saveEdit();
} else if (e.keyCode === 27 /* ESC */) {
isEditing = false;
}
}/>

<li
class={ completed: todo.completed, editing: isEditing }
onDetach=animateOut
onAttach=animateIn>
<div.view>
<input.toggle
type="checkbox"
checked=todo.completed
aria-label="Toggle todo completed"
onChange(e) {
var completed = e.target.checked === true;
updateTodo(todo.id, {completed});
}/>
<label onDblClick() {
isEditing = true;
editingTitle = todo.title;
}>
${todo.title}
</label>

<button.destroy
onClick() { removeTodo(todo.id) }
aria-label="Delete todo"
/>
</div>

<input/title
class="edit"
title="Enter the new todo title"
type="text"
value=editingTitle
onBlur=saveEdit
onChange=saveEdit
onKeydown=handleInputKeyDown/>
</li>
17 changes: 17 additions & 0 deletions examples/tags-todomvc/src/components/todomvc-todo-item/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.todo-list li.pending .toggle, .todo-list li.pending button {
visibility: hidden;
}

.todo-list li.pending label {
color: #d9d9d9;
}

.todo-list li {
opacity: 1;
background-color: #fff;
overflow: hidden;
}

.todo-list li.animate {
transition: opacity 250ms ease-in-out, max-height 250ms ease-in-out;
}
8 changes: 8 additions & 0 deletions examples/tags-todomvc/src/pages/index.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<html>
<head>
<title>Marko | TodoMVC</title>
</head>
<body>
<todomvc-app/>
</body>
</html>

0 comments on commit 724ee21

Please sign in to comment.