Skip to content

Commit

Permalink
feat: allow LumeElement.defineElement() to be called repeatedly wit…
Browse files Browse the repository at this point in the history
…hout errors and it will not try to re-define an already defined element class, allow it to be called multiple times with different `name`s to define the same custom element using alternative tag names, allow a custom registry to be passed in for use cases like ShadowRoot-scoped custom element registries

Also improved inline documentation of some features.

BREAKING:

`LumeElement`'s `static defineElement()` method no longer throws an error when called repeatedly with the same name or no name, which changes runtime behavior if anyone was previously relying on catching this error with `try-catch`. If you previous had logic in a catch block to detect already-defined elements, you can instead use `customElements.get(name)` to perform the check instead of using try-catch.
  • Loading branch information
trusktr committed Jul 30, 2023
1 parent f1d11d6 commit c8d0d76
Showing 1 changed file with 34 additions and 3 deletions.
37 changes: 34 additions & 3 deletions src/LumeElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,22 @@ const HTMLElement =
// tried, but TS has been updated for abstract mixin support.

class LumeElement extends HTMLElement {
/** The default tag name of the elements this class is instantiated for. */
static elementName: string = ''

static defineElement(name?: string) {
customElements.define(name || this.elementName, this)
/**
* Define this class for the given element `name`, or using its default name
* (`elementName`) if no `name` given. Defaults to using the global
* `customElements` registry unless another registry is provided (for
* example a ShadowRoot-scoped registry).
*/
static defineElement(name: string = '', registry: CustomElementRegistry = customElements) {
if (registry.get(name)) return
else {
if (name) registry.define(name, this)
// Allow the same element to be defined more than once using alternative names.
else registry.define(this.elementName, class extends this {})
}
}

/** Non-decorator users can use this to specify which props are reactive. */
Expand Down Expand Up @@ -141,9 +153,28 @@ class LumeElement extends HTMLElement {
}
}

/**
* If a subclass provides this, it should return DOM. It is called with
* Solid.js `render()`, so it can also contain Solid.js reactivity (signals
* and effects) and templating (DOM-returning reactive JSX or html template
* literals).
*/
protected declare template?: Template

/**
* If provided, this style gets created once per ShadowRoot of each element
* instantiated from this class. The expression can access `this` for string
* interpolation.
*/
protected declare css?: string | (() => string)
protected static css?: string | (() => string)

/**
* If provided, this style gets created a single time for all elements
* instantiated from this class, instead of once per element. If you do not
* need to interpolate values into the string using `this`, then use this
* static property for more performance compared to the instance property.
*/
protected declare static css?: string | (() => string)

/**
* When `true`, the custom element will have a `ShadowRoot`. Set to `false`
Expand Down

0 comments on commit c8d0d76

Please sign in to comment.