add day 4

This commit is contained in:
Zoe
2022-09-26 15:15:57 -05:00
parent 1c28d2a045
commit 213b42bb9c
12 changed files with 1096 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
import minus from '../icons/minus.svg'
import plus from '../icons/plus.svg'
import refresh from '../icons/refresh.svg'
export const Counter = () => {
return `
<div class="mb-2">
<h2 class="text-xl font-semibold text-center">count is: {count}</h2>
</div>
<div class="flex justify-center">
<button d-click="appState.contents.count--" class="transition-colors p-3 active:bg-red-700 hover:bg-red-600 hover:text-zinc-100 mr-1">
<img src=${minus} alt="minus" />
</button>
<button d-click="appState.contents.count = 0" class="transition-colors p-3 active:bg-zinc-800 hover:bg-zinc-900 hover:text-red-100 mr-1">
<img src=${refresh} alt="reset">
</button>
<button d-click="appState.contents.count++" class="transition-colors p-3 active:bg-green-700 hover:bg-green-600 hover:text-green-100">
<img src=${plus} alt="plus" />
</button>
</div>
`
}

View File

@@ -0,0 +1,10 @@
export const TextInput = () => {
return `
<div class="mb-2">
<h2 class="text-xl font-semibold text-center">Input is: {text}</h2>
</div>
<div class="flex justify-center">
<input placeholder="text..." class="py-2 px-4 resize-none bg-zinc-800 rounded-md shadow-md my-2 border border-zinc-800 placeholder:italic placeholder:text-gray-300" d-model="text" />
</div>
`
}

1
day4/src/icons/minus.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -11 24 24" width="24" fill="white"><path d="M1 0h12a1 1 0 0 1 0 2H1a1 1 0 1 1 0-2z"></path></svg>

After

Width:  |  Height:  |  Size: 149 B

1
day4/src/icons/plus.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4.5 -4.5 24 24" width="24" fill="white"><path d="M8.9 6.9v-5a1 1 0 1 0-2 0v5h-5a1 1 0 1 0 0 2h5v5a1 1 0 1 0 2 0v-5h5a1 1 0 1 0 0-2h-5z"></path></svg>

After

Width:  |  Height:  |  Size: 199 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1.5 -2.5 24 24" width="24" fill="white"><path d="M17.83 4.194l.42-1.377a1 1 0 1 1 1.913.585l-1.17 3.825a1 1 0 0 1-1.248.664l-3.825-1.17a1 1 0 1 1 .585-1.912l1.672.511A7.381 7.381 0 0 0 3.185 6.584l-.26.633a1 1 0 1 1-1.85-.758l.26-.633A9.381 9.381 0 0 1 17.83 4.194zM2.308 14.807l-.327 1.311a1 1 0 1 1-1.94-.484l.967-3.88a1 1 0 0 1 1.265-.716l3.828.954a1 1 0 0 1-.484 1.941l-1.786-.445a7.384 7.384 0 0 0 13.216-1.792 1 1 0 1 1 1.906.608 9.381 9.381 0 0 1-5.38 5.831 9.386 9.386 0 0 1-11.265-3.328z"></path></svg>

After

Width:  |  Height:  |  Size: 561 B

View File

@@ -0,0 +1,38 @@
export class Reactive {
constructor(obj) {
this.contents = obj;
this.listeners = {};
this.makeReactive(obj);
}
makeReactive(obj) {
Object.keys(obj).forEach(prop => this.makePropReactive(obj, prop));
}
makePropReactive(obj, key) {
let value = obj[key];
// Gotta be careful with this here
const that = this;
Object.defineProperty(obj, key, {
get() {
return value;
},
set(newValue) {
value = newValue;
that.notify(key)
}
})
}
listen(prop, handler) {
if (!this.listeners[prop]) this.listeners[prop] = [];
this.listeners[prop].push(handler);
}
notify(prop) {
this.listeners[prop].forEach(listener => listener(this.contents[prop]));
}
}

View File

@@ -0,0 +1,40 @@
export const compileToString = (template) => {
const ast = parse(template);
let fnStr = `\`\``;
ast.map(t => {
// checking to see if it is an interpolation
if (t.startsWith("{") && t.endsWith("}")) {
// append it to fnStr
const uuid = t.split(/{|}/).filter(Boolean)[0].trim().split("").map(c => c.charCodeAt(0).toString(16).padStart(2, "0")).join("");
fnStr = fnStr.substring(0, fnStr.length - 1) + `<span data-token-${uuid}>\``;
fnStr += `+appState.contents.${t.split(/{|}/).filter(Boolean)[0].trim()}`;
} else {
// append the string to the fnStr
fnStr += `+\`${t}\``;
}
});
return fnStr;
}
var parse = (template) => {
let result = /{(.*?)}/g.exec(template);
const arr = [];
let firstPos;
while (result) {
firstPos = result.index;
if (firstPos !== 0) {
arr.push(template.substring(0, firstPos));
template = template.slice(firstPos);
}
arr.push(result[0]);
template = template.slice(result[0].length);
result = /{(.*?)}/g.exec(template);
}
if (template) arr.push(template);
return arr;
}

58
day4/src/main.ts Normal file
View File

@@ -0,0 +1,58 @@
import './style.css';
import { Reactive } from './lib/ReactiveObject'
import { compileToString } from './lib/templateRenderer'
import { Counter } from './components/counter';
import { TextInput } from './components/textInput';
const virtualDomBody = `
<div class="grid place-items-center p-3 content-center min-h-screen">
<div class="p-6 max-h-3/6 border-neutral-800 rounded-lg container__count border">
${Counter()}
<br/>
${TextInput()}
</div>
</div>
`
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
})
})
})

13
day4/src/style.css Normal file
View File

@@ -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;
}