diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js
new file mode 100644
index 00000000000..1875643d880
--- /dev/null
+++ b/awesome_owl/static/src/card/card.js
@@ -0,0 +1,34 @@
+
+import { Component, useState, xml } from "@odoo/owl";
+
+export class Card extends Component {
+ static template = xml`
+
`;
+ static props = {
+ title: String,
+ slots: {
+ type: Object,
+ shape: {
+ default: true
+ },
+ }
+ }
+
+ setup() {
+ this.state = useState({ title: this.props.title, state: true})
+ }
+
+ toggle() {
+
+ }
+}
diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js
new file mode 100644
index 00000000000..c9fa2e80b23
--- /dev/null
+++ b/awesome_owl/static/src/counter/counter.js
@@ -0,0 +1,21 @@
+
+import { Component, useState } from "@odoo/owl";
+
+export class Counter extends Component {
+ static template = "awesome_owl.counter";
+ static props = {
+ onChange: { type: Function, optional: true }
+ }
+
+ setup() {
+ this.state = useState({ value: 0 });
+ }
+
+ increment() {
+ this.state.value++;
+ if (this.props.onChange) {
+ this.props.onChange();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/awesome_owl/static/src/counter/counter.xml b/awesome_owl/static/src/counter/counter.xml
new file mode 100644
index 00000000000..5d6964079a8
--- /dev/null
+++ b/awesome_owl/static/src/counter/counter.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js
index 657fb8b07bb..e1c315a03aa 100644
--- a/awesome_owl/static/src/playground.js
+++ b/awesome_owl/static/src/playground.js
@@ -1,7 +1,22 @@
/** @odoo-module **/
-import { Component } from "@odoo/owl";
+import { Component, useState, markup } from "@odoo/owl";
+import { Counter } from "./counter/counter";
+import { Card } from "./card/card";
+import { TodoList } from "./todolist/todolist";
export class Playground extends Component {
static template = "awesome_owl.playground";
+ static components = { Counter, Card, TodoList };
+
+
+ setup() {
+ this.someHTML = markup("some content
");
+ this.someText = "some content
";
+ this.sum = useState({ value: 0 });
+ }
+
+ incrementSum() {
+ this.sum.value++;
+ }
}
diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml
index 4fb905d59f9..e73171d4892 100644
--- a/awesome_owl/static/src/playground.xml
+++ b/awesome_owl/static/src/playground.xml
@@ -3,7 +3,19 @@
- hello world
+
+ hello world
+
+
+
+
+
+
+ My little Card
+
+
+
+
diff --git a/awesome_owl/static/src/todolist/todoitem.js b/awesome_owl/static/src/todolist/todoitem.js
new file mode 100644
index 00000000000..1665db70967
--- /dev/null
+++ b/awesome_owl/static/src/todolist/todoitem.js
@@ -0,0 +1,32 @@
+
+import { Component, useState, xml } from "@odoo/owl";
+
+export class TodoItem extends Component {
+ static template = xml`
+
+
+ .
+
+
`;
+ static props = {
+ todo : {
+ id: { type: Number },
+ description: { type: String },
+ isCompleted: { type: Boolean }
+ },
+ toggleState: { type: Function },
+ removeTodo: Function
+ }
+
+ setup() {
+ this.todo = useState({ value: this.props.todo })
+ }
+
+ onChange() {
+ this.props.toggleState(this.props.todo.id)
+ }
+
+ onDelete() {
+ this.props.removeTodo(this.props.todo.id);
+ }
+}
diff --git a/awesome_owl/static/src/todolist/todolist.js b/awesome_owl/static/src/todolist/todolist.js
new file mode 100644
index 00000000000..188dc3f6638
--- /dev/null
+++ b/awesome_owl/static/src/todolist/todolist.js
@@ -0,0 +1,47 @@
+
+import { Component, useState } from "@odoo/owl";
+import { TodoItem } from "./todoitem";
+import { useAutofocus } from "./utils";
+
+export class TodoList extends Component {
+ static template = "awesome_owl.todolist";
+ static components = { TodoItem };
+
+ setup() {
+ this.todos = useState([]);
+
+ useAutofocus("myInput");
+ }
+
+ addTodo(ev) {
+ if (ev.keyCode === 13) {
+ var todoId;
+ if (this.todos.length == 0) {
+ todoId = 1;
+ } else {
+ todoId = this.todos[this.todos.length -1].id + 1;
+ }
+ var content = document.querySelector(".todo_content");
+ if (content.value != "") {
+ this.todos.push({ id: todoId, description: content.value, isCompleted: false });
+ content.value = "";
+ }
+ }
+ }
+
+ toggleState(todoId) {
+ const todo = this.todos.find((todo) => todo.id == todoId)
+ if (todo) {
+ todo.isCompleted = !todo.isCompleted;
+ }
+ }
+
+ removeTodo(todoId) {
+ // find the index of the todo to delete
+ const indexTodo = this.todos.findIndex((elem) => elem.id === todoId);
+ if (indexTodo >= 0) {
+ // remove the todo at index from todos
+ this.todos.splice(indexTodo, 1);
+ }
+ }
+}
diff --git a/awesome_owl/static/src/todolist/todolist.xml b/awesome_owl/static/src/todolist/todolist.xml
new file mode 100644
index 00000000000..e12fb3374e4
--- /dev/null
+++ b/awesome_owl/static/src/todolist/todolist.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/awesome_owl/static/src/todolist/utils.js b/awesome_owl/static/src/todolist/utils.js
new file mode 100644
index 00000000000..69cf11c2d05
--- /dev/null
+++ b/awesome_owl/static/src/todolist/utils.js
@@ -0,0 +1,10 @@
+
+import { useRef, useEffect } from "@odoo/owl";
+
+export function useAutofocus(name) {
+ let ref = useRef(name);
+ useEffect(
+ (el) => el && el.focus(),
+ () => [ref.el]
+ );
+}