Skip to content

Instantly share code, notes, and snippets.

@jwx
Last active June 10, 2022 19:40
Show Gist options
  • Save jwx/d3d4fd9a6b41facc617f40feb0792f46 to your computer and use it in GitHub Desktop.
Save jwx/d3d4fd9a6b41facc617f40feb0792f46 to your computer and use it in GitHub Desktop.
peasy-ui-demo
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dumber Gist</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
</head>
<!--
Dumber Gist uses dumber bundler, the default bundle file
is /dist/entry-bundle.js.
The starting module is pointed to "main" (data-main attribute on script)
which is your src/main.ts.
-->
<body>
<script src="/dist/entry-bundle.js" data-main="main"></script>
</body>
</html>
{
"dependencies": {
"peasy-ui": "latest"
}
}
import { UI } from 'peasy-ui';
import 'styles.css';
window.addEventListener('DOMContentLoaded', (event) => {
main();
});
const balls = 200;
function main(): void {
console.log('Hello, World!');
let demoUI;
const model = {
color: 'lightgray',
transitionDuration: 0,
list: ['one', 'two', 'three'],
left: false,
right: true,
demo: 'card',
clicked: (_event, model, _boundElement, _boundEvent) => {
model.transitionDuration += 2000;
model.color = 'gold';
},
get hasNoColor() { return (this.color.length ?? '') === 0; },
changed: (_ev, model, element) => {
model.transitionDuration = 0;
model.color = 'lightgreen';
demoUI = selectDemo(model, demoUI);
},
card: {
value: 'The Ace',
position: { x: 50, y: 25 },
faceUp: false,
get rotateY() { return this.faceUp ? 0 : 180; },
flip: () => model.card.faceUp = !model.card.faceUp,
},
balls: [],
todos: [],
get remainingTodos() { return model.todos.filter(todo => !todo.done) },
get doneTodos() { return model.todos.filter(todo => todo.done) },
get hasRemaining() { return model.remainingTodos.length > 0; },
get hasDone() { return model.doneTodos.length > 0; },
addTodo: (_event, model) => {
model.todos.push({ text: model.todo, done: false });
model.todo = '';
model.inputElement.focus();
console.log(model);
},
removeTodo: (_event, model, _element, _at, context) => {
console.log(model, _at, context);
context.$parent.$model.todos = context.$parent.$model.todos.filter(todo => todo !== model.todo);
},
// slots: [],
};
UI.create(document.body, `
<div class="main" style="background-color: \${color}; transition-duration: \${transitionDuration}ms;">
<div \${item <=* list} style="background-color: \${color};">Item: \${item} <button \${click @=> clicked}>Set to gold (\${item})</button></div>
List: \${list[1]}
<div>Color: <input \${value <=> color}> <span>The color is <b>\${color}</b>.</span> <button \${click @=> clicked} \${disabled <== hasNoColor}>Set to gold</button></div>
<div>Checks: <label><input type="checkbox" \${checked <=> left}> Left</label> <label><input type="checkbox" \${checked <=> right}> Right</label> <b>\${left} \${right} <span \${ === left}> Left </span> <span \${ !== right}> Not right </span></b></div>
<div>Demo:
<label><input type="radio" name="demo" \${'card' ==> demo} \${change @=> changed}>Card</label>
<label><input type="radio" name="demo" \${'ball' ==> demo} \${change @=> changed}>Ball</label>
<label><input type="radio" name="demo" \${'todo' ==> demo} \${change @=> changed}>Todo</label>
<b>\${demo}</b>
</div>
<div>Demo:
<select \${change @=> changed} \${ ==> demoElement}>
<option \${'card' ==> demo}>Card</option>
<option \${'ball' ==> demo}>Ball</option>
<option \${'todo' ==> demo}>Todo</option>
</select>
<b>\${demo}</b>
</div>
</div>
`, model);
// Start of demo events
demoUI = selectDemo(model, demoUI);
setTimeout(() => model.color = 'blue', 2000);
setTimeout(() => {
model.demo = 'ball';
demoUI = selectDemo(model, demoUI);
}, 3000);
setTimeout(() => model.color = 'skyblue', 4000);
// setTimeout(() => model.list = model.list.concat({ id: 'four' }), 6000);
setTimeout(() => model.list.push('four'), 6000);
setTimeout(() => { const list = model.list;[list[1], list[2]] = [list[2], list[1]]; }, 7000);
setTimeout(() => { model.list = model.list.filter(item => item !== 'three') }, 8000);
setInterval(() => model.card.flip(), 2500);
// End of demo events
// (Game) loop (very simplified)
setInterval(() => {
for (let i = 0; i < balls; i++) {
updateBall(model.balls[i]);
}
UI.update();
}, 1000 / 60);
}
function runDemo(model) {
}
function updateBall(ball) {
ball.position.x += ball.velocity.x * 1 / 60;
ball.position.y += ball.velocity.y * 1 / 60;
if (ball.position.x < 0) {
ball.position.x = 0;
ball.velocity.x = -ball.velocity.x;
} else if (ball.position.x > 180) {
ball.position.x = 180;
ball.velocity.x = -ball.velocity.x;
}
if (ball.position.y < 0) {
ball.position.y = 0;
ball.velocity.y = -ball.velocity.y;
} else if (ball.position.y > 180) {
ball.position.y = 180;
ball.velocity.y = -ball.velocity.y;
}
}
function selectDemo(model, demoUI) {
// console.log('Selecting demo', model.card, model.ball, model.demo);
const templateCard = `
<div class="border">
<div class="card" \${click @=> card.flip} style="
transform: translate3d(\${card.position.x}px, \${card.position.y}px, 0) rotateY(\${card.rotateY}deg);
">
<div class="card-back" style="background-color: \${color}"></div>
<div class="card-face">\${card.value}</div>
</div>
</div>
`;
model.balls = [];
for (let i = 0; i < balls; i++) {
model.balls.push({
position: { x: random(25, 175), y: random(25, 175) },
velocity: { x: random(100, 200), y: random(100, 200) },
});
}
const templateBall = `
<div class="border">
<div class="ball" \${ball <=* balls} style="background-color: \${color}; transform: translate3d(\${ball.position.x}px, \${ball.position.y}px, 0)"></div>
</div>
`;
const templateTodo = `
<div class="todos">
<div class="input"><form onsubmit="return false;"><input \${value <=> todo} \${==> inputElement}> <button type="submit" \${click @=> addTodo}>Add todo</button></form></div>
<div class="header" \${ === hasRemaining}>Remaining</div>
<div class="todo remaining-todo" \${todo <=* remainingTodos} style="background-color: \${color};"><label><input type="checkbox" \${checked <=> todo.done}> \${todo.text}</label> <button \${click @=> removeTodo}>Remove todo</button></div>
<div class="header" \${ === hasDone}>Done</div>
<div class="todo done-todo" \${todo <=* doneTodos} style="background-color: \${color};"><label><input type="checkbox" \${checked <=> todo.done}> \${todo.text}</label> <button \${click @=> removeTodo}>Remove todo</button></div>
</div>
`;
if (demoUI != null) {
demoUI.destroy();
}
let template;
switch (model.demo) {
case 'ball':
template = templateBall;
break;
case 'card':
template = templateCard;
break;
case 'todo':
template = templateTodo;
break;
}
demoUI = UI.create(document.body, template, model);
return demoUI;
}
function random(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
input {
padding: 3px;
border-radius: 3px;
}
.main {
margin: 10px;
padding: 10px;
}
.border {
display: inline-block;
position: relative;
margin: 10px;
width: 200px;
height: 200px;
border: 2px solid black;
}
.ball {
display: inline-block;
position: absolute;
width: 20px;
height: 20px;
border-radius: 50%;
will-change: transform;
}
.card {
display: inline-block;
width: 100px;
height: 150px;
position: absolute;
left: 0;
top: 0;
border: 1px solid black;
transform-style: preserve-3d;
transition-property: transform;
transition-duration: 500ms;
will-change: transform;
}
.card-back {
position: absolute;
width: 100%;
height: 100%;
color: white;
transform: rotateY(0deg);
}
.card-face {
position: absolute;
width: 100%;
height: 100%;
background-color: gold;
transform: rotateY(180deg) translateZ(0.1px);
display: flex;
align-items: center;
justify-content: center;
}
.todos {
margin: 10px;
}
.todos .input {
margin-bottom: 10px;
}
.todo {
padding: 5px 0px;
}
.done-todo {
text-decoration: line-through;
}
.todo button {
float: right;
margin-right: 1vw;
}
.todos .header {
margin-top: 10px;
margin-left: 3px;
font-weight: bold;
}
/*
.slots {
position:relative;
border: 1px solid black;
padding: 5px;
border-radius: 3px;
height: 20px;
}
.slot {
display: inline-block;
position: absolute;
width: 20px;
height: 20px;
border-radius: 3px;
text-align: center;
transition-duration: 500ms;
}
.slot-0 {
transition-delay: 100ms;
transform: translate3d(-25px, 0px, 0px);
}
.slot-1 {
transition-delay: 200ms;
transform: translate3d(0px, 0px, 0px);
}
.slot-2 {
transition-delay: 300ms;
transform: translate3d(25px, 0px, 0px);
}
.slot-3 {
transition-delay: 400ms;
transform: translate3d(50px, 0px, 0px);
}
.slot-4 {
transition-delay: 500ms;
transform: translate3d(75px, 0px, 0px);
}
.slot-5 {
transition-delay: 600ms;
transform: translate3d(100px, 0px, 0px);
} */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment