+
+ ${Counter()}
+
+ ${TextInput()}
+
+
+`
+
+
+const appState = new Reactive({
+ count: 0,
+ text: ''
+});
+// run code to compile the templated virtualDomBody into a play body
+const templatedVirtualDom = eval(compileToString(virtualDomBody))
+
+// equivalent to mounted() on svelte or vue
+window.addEventListener('load', () => {
+ const documentBody = document.getElementById('app')
+ if (!documentBody) {
+ throw new Error
+ }
+ documentBody.innerHTML = templatedVirtualDom
+ Object.keys(appState.contents).forEach((e) => {
+ if (e === undefined) return
+ console.log(e)
+ const querySelector = "data-token-" + e.split("").map(c => c.charCodeAt(0).toString(16).padStart(2, "0")).join("")
+ const listeningElements = document.querySelectorAll(`[${querySelector}]`)
+ listeningElements.forEach((elm) => {
+ appState.listen(e, (change) => elm.textContent = change);
+ })
+ })
+ let elms = documentBody.querySelectorAll('*[d-click]')
+ elms.forEach((e) => {
+ const clickFunction = e.getAttribute("d-click")
+ if (!clickFunction) return;
+ e.addEventListener('click', () => {
+ eval(clickFunction)
+ })
+ })
+
+ let modelElms = document.querySelectorAll('*[d-model]')
+ modelElms.forEach((e) => {
+ const modelName = e.getAttribute("d-model")
+ if (!modelName) return;
+ e.addEventListener('input', (event: any) => {
+ appState.contents[modelName] = event.target.value
+ })
+ })
+})
\ No newline at end of file
diff --git a/day4/src/style.css b/day4/src/style.css
new file mode 100644
index 0000000..17ec19c
--- /dev/null
+++ b/day4/src/style.css
@@ -0,0 +1,13 @@
+html,
+body {
+ background-color: #101010;
+ color: #FEFEFE;
+ font-family: Helvetica, Arial, Sans-Serif;
+ padding: 0;
+ margin: 0;
+ min-height: 100vh;
+}
+
+.container__count {
+ box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
+}
\ No newline at end of file