Deja Vu is a set of small libraries (each minfies and compresses to under a kilobyte, the whole bundle, uncompressed in any form is less than 6kb) under a meant to make it pleasant to make small JS doodads. There are currently 4 libraries:
deja.attach(deja.q1("#app"), {
"#my-app-title": {t: "Deja Example"},
"#my-app-button": { on: { click: () => { console.log("clicked!"); } } },
}
const el = deja.attach({
title: "#my-app-title",
color: ["#my-app-title", "style.background-color"]
})
el.title = "new title";
el.color = "blue";
template tags to build out more dynamic pages.
<div id="todos"> </div>
<template id="todo">
<div class="todo">
<input type="check" name="completed" />
<input type="text" name="description"/>
</div>
</template>
const todos = deja.q1("#todos");
const addTodo = (description) => {
const newTodo = deja.from("#todo");
const me = deja.attach(newTodo, {
root: ".todo",
"[name=description]": {t: description },
"[name=completed]": { on: { click() { me.$root.remove() } } }
});
todos.append(newTodo);
}
Doptics (or dom-optics) is a utility focused on answering the question of what the "default" value to get and set on a given DOM node should be. For the most part, this is mapped to `innerText`, but for form inputs and `output`, it's mapped to `value`. Doptics also lets you define your own lens types.
doptics.add("number", (x) => x.toString(), (x) => parseNumber(x));
doptics.add("date", (x) => x.toString(), (x) => x && new Date(...x.split("-")));
Chalk is a join-capable tuplespace. It's meant to facilitate communication between parts of a larger program. You can wait on a single message:
const board = chalk();
board.msg("sending", "a", "message");
board.when("sending a $message", ({ message }) => {
console.log("Got: " + message);
});
You can wait for only the -first- message to match a pattern
board.msg("only", "sent", "once");
board.once("only sent once", () => {
console.log("Got the message, now this handler will be removed");
});
Being join-capable means you can wait for multiple message patterns. If you want to, you can also require those messages to share values.
board.when("open $door with $key", "have $key", ({ door, key }) => {
door.open(key);
});
let myKey = {};
board.msg("have", myKey);
let myDoor = { state: "closed", open(key) {
if (key === myKey) {
myDoor.state = "open";
}
}}
board.msg("open", myDoor, "with", myKey);
vu is a list/table-managing wrapper around Deja. It provides a setup for managing a list of data wrapped up in an object that exposes methods for working with the list that sync changes to the DOM as well.
const board = chalk();
let tests_ui = vu({
el: deja.q1("#suites"),
data: [],
item({suite, tests}, suite_ui, become) {
let results = [];
for (const [name, t] of Object.entries(tests)) {
try {
t();
results.push({ passed: true, name });
} catch(ex) {
results.push({ passed: false, name, reason: ex.message });
}
}
become("#test-suite", {
".suite-name": {t: suite+": "},
results: ".test-results",
});
let results_ui = vu({ el: suite_ui.$results, data: results,
item(result, _, become) {
become("#test-result", {
".test-name": {t: result.name},
".test-pass-fail": {
t: (result.passed ? "Passed" : "Failed: " + result.reason)
}
})
}}
);
board.when("filter is $filter", (_) => {
results_ui.filter(r => r.name.includes(_.filter));
});
}
});
deja.attach("body", {
"#search": { on: { input(e) {
board.msg("filter", "is", e.target.value);
}}},
});
globalThis.test = (suite, tests) => {
tests_ui.push({suite, tests});
}
// For global scope
globalThis.assert = (cond, msg) => { if (!cond) throw new Error(msg); };
All of the examples below are written with the expectation that you can view and read the source on them.