InheritedHtmlElements outside of factory

This commit is contained in:
2026-04-01 19:01:37 +02:00
parent a0cce91bd5
commit 39dee782cc

View File

@@ -19,28 +19,19 @@ export function registerComponent(name: string, options?: ElementDefinitionOptio
} }
/** /**
* Safari doesn't support inheriting from HTML tags on web components * Abstract class used to create HTML tags inheriting from HTMLElements
* The technique is to: * You should not use this class outside of typing !
* create a new web component
* create the desired type inside
* pass all attributes to the child component
* store is at as `node` inside the parent
* *
* Since we can't use the generic type to instantiate the node, we create a generator function * Please, see the `inheritHtmlElement` factory if you want to use this class.
*
* ```js
* class MyClass extends inheritHtmlElement("select") {
* // do whatever
* }
* ```
**/ **/
export function inheritHtmlElement<K extends keyof HTMLElementTagNameMap>(tagName: K) { export abstract class InheritedHtmlElement<
return class Inherited extends HTMLElement { K extends keyof HTMLElementTagNameMap,
readonly inheritedTagName = tagName; > extends HTMLElement {
abstract readonly inheritedTagName: K;
protected node: HTMLElementTagNameMap[K]; protected node: HTMLElementTagNameMap[K];
connectedCallback(autoAddNode?: boolean) { connectedCallback(autoAddNode?: boolean) {
this.node = document.createElement(tagName); this.node = document.createElement(this.inheritedTagName);
const attributes: Attr[] = []; // We need to make a copy to delete while iterating const attributes: Attr[] = []; // We need to make a copy to delete while iterating
for (const attr of this.attributes) { for (const attr of this.attributes) {
if (attr.name in this.node) { if (attr.name in this.node) {
@@ -61,5 +52,26 @@ export function inheritHtmlElement<K extends keyof HTMLElementTagNameMap>(tagNam
this.appendChild(this.node); this.appendChild(this.node);
} }
} }
}
/**
* Safari doesn't support inheriting from HTML tags on web components
* The technique is to:
* create a new web component
* create the desired type inside
* pass all attributes to the child component
* store is at as `node` inside the parent
*
* Since we can't use the generic type to instantiate the node, we create a generator function
*
* ```js
* class MyClass extends inheritHtmlElement("select") {
* // do whatever
* }
* ```
**/
export function inheritHtmlElement<K extends keyof HTMLElementTagNameMap>(tagName: K) {
return class InheritedHtmlElementImpl extends InheritedHtmlElement<K> {
readonly inheritedTagName = tagName;
}; };
} }