Skip to content

Instantly share code, notes, and snippets.

@dustinboston
Last active October 29, 2019 00:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dustinboston/d95238aa411090afe68e4bb8ce9cbc6a to your computer and use it in GitHub Desktop.
Save dustinboston/d95238aa411090afe68e4bb8ce9cbc6a to your computer and use it in GitHub Desktop.
Poor Man's React
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Poor Man's React</title>
<link rel="stylesheet" href="./css/styles.css" />
</head>
<body>
<my-app></my-app>
<script type="module" src="./app.mjs"></script>
</body>
</html>
import html from '../lib/html.js';
import './header.mjs';
window.customElements.define(
'my-app',
class extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = html`
<my-header></my-header>
<main>
This is a test
</main>
`;
}
}
);
function dash(name) {
return name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
export function css(obj) {
return Object.keys(obj)
.map(prop => `${dash(prop)}: ${obj[prop]};`)
.join(';');
}
export default function stylesheet(obj) {
const s = {};
for (let prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
s[prop] = css(obj[prop]);
}
}
return s;
}
import html from './html.js';
import stylesheet from './css.js';
const css = stylesheet({
header: {
display: 'flex'
},
h1: {
flexGrow: 1
}
})
window.customElements.define(
'my-header',
class extends HTMLElement {
logoutUrl = '#logout';
constructor() {
super();
this.innerHTML = html`
<header style="${css.header}">
<h1 style="${css.h1}">hello</h1>
<button>Logout</button>
</header>
`;
}
logout() {
window.location.href = this.logoutUrl;
}
connectedCallback() {
const button = this.querySelector('button');
button.addEventListener('click', this.logout.bind(this));
}
}
);
/**
* @see https://blog.jim-nielsen.com/2019/jsx-like-syntax-for-tagged-template-literals/
*/
export default function html(strings, ...values) {
let out = "";
strings.forEach((string, i) => {
const value = values[i];
// Array - Join to string and output with value
if (Array.isArray(value)) {
out += string + value.join("");
}
// String - Output with value
else if (typeof value === "string") {
out += string + value;
}
// Number - Coerce to string and output with value
// This would happen anyway, but for clarity's sake on what's happening here
else if (typeof value === "number") {
out += string + String(value);
}
// object, undefined, null, boolean - Don't output a value.
else {
out += string;
}
});
return out;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment