Skip to content

Instantly share code, notes, and snippets.

@MarkTiedemann
Created March 6, 2022 16:54
Show Gist options
  • Select an option

  • Save MarkTiedemann/8dcee13c5022f096d18216258efd069d to your computer and use it in GitHub Desktop.

Select an option

Save MarkTiedemann/8dcee13c5022f096d18216258efd069d to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<body></body>
<script>
class Element extends HTMLElement {
#globalEventListeners = [];
constructor(is, styles, properties, reflectedProperties) {
super();
const style = document.createElement("style");
style.textContent = styles;
const element = document.createElement(is);
for (const [key, value] of Object.entries(properties)) {
if (key in element) {
element[key] = value;
} else if (typeof value === "function") {
addEventListener(key, value);
this.#globalEventListeners.push([key, value]);
}
}
for (const property of reflectedProperties) {
Object.defineProperty(this, property, {
get: () => element[property],
set: (value) => element[property] = value
});
}
this.attachShadow({ mode: "open" }).replaceChildren(style, element);
}
disconnectedCallback() {
for (const [key, value] of this.#globalEventListeners) {
removeEventListener(key, value);
}
}
}
function defineCustomElement(tagName, { is, reflectedProperties, styles }) {
const definition = class extends Element {
constructor(properties) {
super(is, styles, properties, reflectedProperties);
}
}
customElements.define(tagName, definition);
return definition;
}
const xInput = defineCustomElement("x-input", {
is: "input",
reflectedProperties: ["value"],
styles: /*css*/`
input {
border: 1px solid magenta;
}
.large {
font-size: 2em;
}
`
});
function EntryNameInput() {
const input = new xInput({
className: "large",
maxLength: 128,
oninput: () => {
console.log(input.value);
},
onentrynameupdate: ({ detail }) => {
input.value = detail;
}
});
return input;
}
function sendEvent(name, detail) {
dispatchEvent(new CustomEvent(`on${name}`, { detail }))
}
const form = document.createElement("form");
const input = new EntryNameInput();
form.appendChild(input);
document.body.appendChild(form);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment