diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js
new file mode 100644
index 00000000000..84950c3b758
--- /dev/null
+++ b/awesome_owl/static/src/card/card.js
@@ -0,0 +1,17 @@
+import { useState, Component } from "@odoo/owl";
+
+export class Card extends Component {
+ static template = "awesome_owl.card";
+ static props = {
+ title: String,
+ slots: { type: Object, optional: true },
+ };
+
+ setup() {
+ this.state = useState({ visible: true });
+ }
+
+ toggleVisible() {
+ this.state.visible = !this.state.visible;
+ }
+}
diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml
new file mode 100644
index 00000000000..57ff80c37b6
--- /dev/null
+++ b/awesome_owl/static/src/card/card.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js
new file mode 100644
index 00000000000..d6d92784524
--- /dev/null
+++ b/awesome_owl/static/src/counter/counter.js
@@ -0,0 +1,22 @@
+import { useState, Component } 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: 1 });
+ }
+
+ increment() {
+ this.state.value++;
+ if (this.props.onChange) {
+ this.props.onChange();
+ }
+ }
+}
diff --git a/awesome_owl/static/src/counter/counter.xml b/awesome_owl/static/src/counter/counter.xml
new file mode 100644
index 00000000000..08590167539
--- /dev/null
+++ b/awesome_owl/static/src/counter/counter.xml
@@ -0,0 +1,9 @@
+
+
+
+
+ Counter:
+
+
+
+
diff --git a/awesome_owl/static/src/main.js b/awesome_owl/static/src/main.js
index 1aaea902b55..1af6c827e0b 100644
--- a/awesome_owl/static/src/main.js
+++ b/awesome_owl/static/src/main.js
@@ -4,9 +4,8 @@ import { Playground } from "./playground";
const config = {
dev: true,
- name: "Owl Tutorial"
+ name: "Owl Tutorial",
};
// Mount the Playground component when the document.body is ready
whenReady(() => mountComponent(Playground, document.body, config));
-
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js
index 4ac769b0aa5..560db73de0a 100644
--- a/awesome_owl/static/src/playground.js
+++ b/awesome_owl/static/src/playground.js
@@ -1,5 +1,20 @@
-import { Component } from "@odoo/owl";
+import { markup, useState, Component } from "@odoo/owl";
+import { Counter } from "./counter/counter";
+import { Card } from "./card/card";
+import { TodoList } from "./todo/todo-list";
export class Playground extends Component {
static template = "awesome_owl.playground";
+ static components = { Counter, Card, TodoList };
+
+ setup() {
+ this.state = useState({ sum: 2 });
+ }
+
+ incrementSum() {
+ this.state.sum++;
+ }
+
+ someHtmlEscaped = "
My content
";
+ someHtml = markup("My content
");
}
diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml
index 4fb905d59f9..5699ac0c128 100644
--- a/awesome_owl/static/src/playground.xml
+++ b/awesome_owl/static/src/playground.xml
@@ -2,9 +2,22 @@
-
- hello world
-
+
+
+
+
+
+
+
+
+
+
+
+ The sum is
+
+
+
+
diff --git a/awesome_owl/static/src/todo/todo-item.js b/awesome_owl/static/src/todo/todo-item.js
new file mode 100644
index 00000000000..1f0af4ad808
--- /dev/null
+++ b/awesome_owl/static/src/todo/todo-item.js
@@ -0,0 +1,13 @@
+import { Component } from "@odoo/owl";
+
+export class TodoItem extends Component {
+ static template = "awesome_owl.todo-item";
+ static props = {
+ todo: {
+ type: Object,
+ shape: { id: Number, description: String, isCompleted: Boolean },
+ },
+ toggleState: Function,
+ removeTodo: Function,
+ };
+}
diff --git a/awesome_owl/static/src/todo/todo-item.xml b/awesome_owl/static/src/todo/todo-item.xml
new file mode 100644
index 00000000000..eb48b99669c
--- /dev/null
+++ b/awesome_owl/static/src/todo/todo-item.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/awesome_owl/static/src/todo/todo-list.js b/awesome_owl/static/src/todo/todo-list.js
new file mode 100644
index 00000000000..e623b4b98ee
--- /dev/null
+++ b/awesome_owl/static/src/todo/todo-list.js
@@ -0,0 +1,42 @@
+import { useState, Component } from "@odoo/owl";
+import { TodoItem } from "./todo-item";
+import { useAutoFocus } from "../utils";
+
+export class TodoList extends Component {
+ static template = "awesome_owl.todo-list";
+ static components = { TodoItem };
+
+ setup() {
+ this.state = useState({ todos: [], nextId: 1 });
+ useAutoFocus("new-todo-input");
+ }
+
+ input_event_handler(event) {
+ // keyCode is deprecated, use key instead
+ if (event.key === "Enter") {
+ if (event.target.value) {
+ this.state.todos.push({
+ id: this.state.nextId,
+ description: event.target.value,
+ isCompleted: false,
+ });
+ this.state.nextId++;
+ event.target.value = "";
+ }
+ }
+ }
+
+ toggleState(todoId) {
+ const selectedTodo = this.state.todos.find((todo) => todo.id === todoId);
+ if (selectedTodo) {
+ selectedTodo.isCompleted = !selectedTodo.isCompleted;
+ }
+ }
+
+ removeTodo(todoId) {
+ const index = this.state.todos.findIndex((todo) => todo.id === todoId);
+ if (index >= 0) {
+ this.state.todos.splice(index, 1);
+ }
+ }
+}
diff --git a/awesome_owl/static/src/todo/todo-list.xml b/awesome_owl/static/src/todo/todo-list.xml
new file mode 100644
index 00000000000..f38db5b98f1
--- /dev/null
+++ b/awesome_owl/static/src/todo/todo-list.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js
new file mode 100644
index 00000000000..e68b3d8b822
--- /dev/null
+++ b/awesome_owl/static/src/utils.js
@@ -0,0 +1,9 @@
+import { useEffect, useRef } from "@odoo/owl";
+
+export function useAutoFocus(name) {
+ const ref = useRef(name);
+ useEffect(
+ (el) => el && el.focus(),
+ () => [ref.el]
+ );
+}