Skip to content

Instantly share code, notes, and snippets.

@guiseek
Created May 12, 2023 02:45
Show Gist options
  • Save guiseek/d767b1a15548f9ef55913356745ddc08 to your computer and use it in GitHub Desktop.
Save guiseek/d767b1a15548f9ef55913356745ddc08 to your computer and use it in GitHub Desktop.
Custom Element @define Decorator
export const noop = () => null
export function pickFn<
T extends CustomElementConstructor,
K extends keyof T = keyof T
>(target: T, key: K) {
return target[key] ?? noop
}
export function define(
name: `${string}-${string}`,
mode: ShadowRootMode = 'open'
) {
return <T extends CustomElementConstructor>(target: T) => {
const connected = pickFn(target, 'connectedCallback')
const disconnected = pickFn(target, 'disconnectedCallback')
const attributeChanged = pickFn(target, 'attributeChangedCallback')
target.prototype.connectedCallback = function () {
this.shadow = this.attachShadow({mode})
if (this.connected) this.connected(this)
connected.call(this)
}
target.prototype.attributeChangedCallback = function (
name: string,
previous: string | null,
next: string | null
) {
if (this[name]) this[name] = next
if (this.attributeChanged) {
this.attributeChanged(name, previous, next)
}
attributeChanged.call(this, name, previous, next)
}
target.prototype.disconnectedCallback = function () {
if (this.disconnected) this.disconnected(this)
disconnected.call(this)
}
customElements.define(name, target)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment