@@ -8,43 +8,57 @@ import { h, cloneElement, render, hydrate } from 'preact';
88 * @type {import('./index.d.ts').default }
99 */
1010export default function register ( Component , tagName , propNames , options ) {
11- function PreactElement ( ) {
12- const inst = /** @type {PreactCustomElement } */ (
13- Reflect . construct ( HTMLElement , [ ] , PreactElement )
14- ) ;
15- inst . _vdomComponent = Component ;
16-
17- if ( options && options . shadow ) {
18- inst . _root = inst . attachShadow ( {
19- mode : options . mode || 'open' ,
20- serializable : options . serializable ?? false ,
21- } ) ;
22-
23- if ( options . adoptedStyleSheets ) {
24- inst . _root . adoptedStyleSheets = options . adoptedStyleSheets ;
11+ propNames ??= Component . observedAttributes || [ ] ;
12+
13+ class PreactElement extends HTMLElement {
14+ static formAssociated = Component . formAssociated || false ;
15+ static observedAttributes = propNames ;
16+
17+ constructor ( ) {
18+ super ( ) ;
19+
20+ this . _vdomComponent = Component ;
21+ if ( options && options . shadow ) {
22+ this . _root = this . attachShadow ( {
23+ mode : options . mode || 'open' ,
24+ serializable : options . serializable ?? false ,
25+ } ) ;
26+
27+ if ( options . adoptedStyleSheets ) {
28+ this . _root . adoptedStyleSheets = options . adoptedStyleSheets ;
29+ }
30+ } else {
31+ this . _root = this ;
2532 }
26- } else {
27- inst . _root = inst ;
2833 }
2934
30- return inst ;
31- }
32- PreactElement . prototype = Object . create ( HTMLElement . prototype ) ;
33- PreactElement . prototype . constructor = PreactElement ;
34- PreactElement . prototype . connectedCallback = function ( ) {
35- connectedCallback . call ( this , options ) ;
36- } ;
37- PreactElement . prototype . attributeChangedCallback = attributeChangedCallback ;
38- PreactElement . prototype . disconnectedCallback = disconnectedCallback ;
35+ connectedCallback ( ) {
36+ connectedCallback . call ( this , options ) ;
37+ }
3938
40- /**
41- * @type {string[] }
42- */
43- propNames = propNames || Component . observedAttributes || [ ] ;
44- PreactElement . observedAttributes = propNames ;
39+ /**
40+ * Changed whenever an attribute of the HTML element changed
41+ *
42+ * @param {string } name The attribute name
43+ * @param {unknown } oldValue The old value or undefined
44+ * @param {unknown } newValue The new value
45+ */
46+ attributeChangedCallback ( name , oldValue , newValue ) {
47+ if ( ! this . _vdom ) return ;
48+ // Attributes use `null` as an empty value whereas `undefined` is more
49+ // common in pure JS components, especially with default parameters.
50+ // When calling `node.removeAttribute()` we'll receive `null` as the new
51+ // value. See issue #50.
52+ newValue = newValue == null ? undefined : newValue ;
53+ const props = { } ;
54+ props [ name ] = newValue ;
55+ this . _vdom = cloneElement ( this . _vdom , props ) ;
56+ render ( this . _vdom , this . _root ) ;
57+ }
4558
46- if ( Component . formAssociated ) {
47- PreactElement . formAssociated = true ;
59+ disconnectedCallback ( ) {
60+ render ( ( this . _vdom = null ) , this . _root ) ;
61+ }
4862 }
4963
5064 // Keep DOM properties and Preact props in sync
@@ -115,33 +129,6 @@ function connectedCallback(options) {
115129 ( this . hasAttribute ( 'hydrate' ) ? hydrate : render ) ( this . _vdom , this . _root ) ;
116130}
117131
118- /**
119- * Changed whenver an attribute of the HTML element changed
120- * @this {PreactCustomElement}
121- * @param {string } name The attribute name
122- * @param {unknown } oldValue The old value or undefined
123- * @param {unknown } newValue The new value
124- */
125- function attributeChangedCallback ( name , oldValue , newValue ) {
126- if ( ! this . _vdom ) return ;
127- // Attributes use `null` as an empty value whereas `undefined` is more
128- // common in pure JS components, especially with default parameters.
129- // When calling `node.removeAttribute()` we'll receive `null` as the new
130- // value. See issue #50.
131- newValue = newValue == null ? undefined : newValue ;
132- const props = { } ;
133- props [ name ] = newValue ;
134- this . _vdom = cloneElement ( this . _vdom , props ) ;
135- render ( this . _vdom , this . _root ) ;
136- }
137-
138- /**
139- * @this {PreactCustomElement}
140- */
141- function disconnectedCallback ( ) {
142- render ( ( this . _vdom = null ) , this . _root ) ;
143- }
144-
145132/**
146133 * Pass an event listener to each `<slot>` that "forwards" the current
147134 * context value to the rendered child. The child will trigger a custom
0 commit comments