Skip to content

Commit d1b65da

Browse files
committed
move type declarations to jsdoc comments
1 parent 105850e commit d1b65da

File tree

4 files changed

+65
-93
lines changed

4 files changed

+65
-93
lines changed

README.md

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -71,29 +71,6 @@ FullName.propTypes = {
7171
register(FullName, 'full-name');
7272
```
7373

74-
### Using the shadow DOM
75-
76-
It is possible to attach a shadow root to the custom element to have your component rendered in a separate subtree.
77-
Customization of the shadow root `mode` is also possible on element basis.
78-
Read more about the shadow DOM on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot).
79-
80-
```tsx
81-
function WithShadow(props) {
82-
return <span>Hello from shadow root!</span>;
83-
}
84-
85-
// use shadow root in "open" mode
86-
register(FullName, 'full-name', [], {
87-
shadow: true,
88-
});
89-
90-
// use shadow root in "closed" mode
91-
register(FullName, 'full-name-encapsulated', [], {
92-
shadow: true,
93-
mode: 'closed',
94-
});
95-
```
96-
9774
## Related
9875

9976
[preact-shadow-dom](https://github.com/bspaulding/preact-shadow-dom)

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"description": "Wrap your component up as a custom element",
55
"main": "dist/preact-custom-element.js",
66
"module": "dist/preact-custom-element.esm.js",
7+
"types": "dist/index.d.ts",
78
"unpkg": "dist/preact-custom-element.umd.js",
89
"source": "src/index.js",
910
"scripts": {

src/index.js

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,52 @@
11
import { h, cloneElement, render, hydrate } from 'preact';
22

3+
/**
4+
* @typedef {import('preact').FunctionComponent<any> | import('preact').ComponentClass<any> | import('preact').FunctionalComponent<any> } ComponentDefinition
5+
* @typedef {{ shadow: false } | { shadow: true, mode: 'open' | 'closed'}} Options
6+
* @typedef {HTMLElement & { _root: ShadowRoot | HTMLElement, _vdomComponent: ComponentDefinition, _vdom: ReturnType<typeof import("preact").h> | null }} PreactCustomElement
7+
*/
8+
9+
/**
10+
* Register a preact component as web-component.
11+
* @param {ComponentDefinition} Component The preact component to register
12+
* @param {string} [tagName] The HTML element tag-name (must contain a hyphen and be lowercase)
13+
* @param {string[]} [propNames] HTML element attributes to observe
14+
* @param {Options} [options] Additional element options
15+
* @example
16+
* ```ts
17+
* // use custom web-component class
18+
* class PreactWebComponent extends Component {
19+
* static tagName = 'my-web-component';
20+
* render() {
21+
* return <p>Hello world!</p>
22+
* }
23+
* }
24+
*
25+
* register(PreactComponent);
26+
*
27+
* // use a preact component
28+
* function PreactComponent({ prop }) {
29+
* return <p>Hello {prop}!</p>
30+
* }
31+
*
32+
* register(PreactComponent, 'my-component');
33+
* register(PreactComponent, 'my-component', ['prop']);
34+
* register(PreactComponent, 'my-component', ['prop'], {
35+
* shadow: true,
36+
* mode: 'closed'
37+
* });
38+
* ```
39+
*/
340
export default function register(Component, tagName, propNames, options) {
441
function PreactElement() {
5-
const inst = Reflect.construct(HTMLElement, [], PreactElement);
42+
const inst = /** @type {PreactCustomElement} */ (
43+
Reflect.construct(HTMLElement, [], PreactElement)
44+
);
645
inst._vdomComponent = Component;
746
inst._root =
8-
options && options.shadow ? inst.attachShadow({ mode: options.mode || 'open' }) : inst;
47+
options && options.shadow
48+
? inst.attachShadow({ mode: options.mode || 'open' })
49+
: inst;
950
return inst;
1051
}
1152
PreactElement.prototype = Object.create(HTMLElement.prototype);
@@ -14,6 +55,9 @@ export default function register(Component, tagName, propNames, options) {
1455
PreactElement.prototype.attributeChangedCallback = attributeChangedCallback;
1556
PreactElement.prototype.disconnectedCallback = disconnectedCallback;
1657

58+
/**
59+
* @type {string[]}
60+
*/
1761
propNames =
1862
propNames ||
1963
Component.observedAttributes ||
@@ -62,6 +106,9 @@ function ContextProvider(props) {
62106
return cloneElement(children, rest);
63107
}
64108

109+
/**
110+
* @this {PreactCustomElement}
111+
*/
65112
function connectedCallback() {
66113
// Obtain a reference to the previous context by pinging the nearest
67114
// higher up node that was rendered with Preact. If one Preact component
@@ -84,10 +131,22 @@ function connectedCallback() {
84131
(this.hasAttribute('hydrate') ? hydrate : render)(this._vdom, this._root);
85132
}
86133

134+
/**
135+
* Camel-cases a string
136+
* @param {string} str The string to transform to camelCase
137+
* @returns camel case version of the string
138+
*/
87139
function toCamelCase(str) {
88140
return str.replace(/-(\w)/g, (_, c) => (c ? c.toUpperCase() : ''));
89141
}
90142

143+
/**
144+
* Changed whenver an attribute of the HTML element changed
145+
* @this {PreactCustomElement}
146+
* @param {string} name The attribute name
147+
* @param {unknown} oldValue The old value or undefined
148+
* @param {unknown} newValue The new value
149+
*/
91150
function attributeChangedCallback(name, oldValue, newValue) {
92151
if (!this._vdom) return;
93152
// Attributes use `null` as an empty value whereas `undefined` is more
@@ -102,6 +161,9 @@ function attributeChangedCallback(name, oldValue, newValue) {
102161
render(this._vdom, this._root);
103162
}
104163

164+
/**
165+
* @this {PreactCustomElement}
166+
*/
105167
function disconnectedCallback() {
106168
render((this._vdom = null), this._root);
107169
}

types/index.d.ts

Lines changed: 0 additions & 68 deletions
This file was deleted.

0 commit comments

Comments
 (0)