Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow creating a CustomElement without defining the tagName #55

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,23 @@ FullName.propTypes = {
register(FullName, 'full-name');
```

### Creating a CustomElements without registering a tag name

If authoring a custom-elements library, you might want to expose your CustomElements without registering their tag name, to let your users register their own tags.

This can be achieved by calling the `toCustomElements` function on the default export:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This can be achieved by calling the `toCustomElements` function on the default export:
This can be achieved by calling the named export `createCustomElement`:


```js
import register from 'preact-custom-element'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import register from 'preact-custom-element'
import { toCustomElement } from 'preact-custom-element'


function MyComponent({ name = "World" }) {
return <span>Hello {name}!</span>
}

export const MyElement = register.toCustomElement(MyComponent, ['name'])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const MyElement = register.toCustomElement(MyComponent, ['name'])
export const MyElement = createCustomElement(MyComponent, ['name'])

```

`toCustomElement` has the same signature as `register`, omitting the second parameter (tag name).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`toCustomElement` has the same signature as `register`, omitting the second parameter (tag name).
`createCustomElement` has the same signature as `register`, omitting the second parameter (tag name).


## Related

Expand Down
10 changes: 9 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { h, cloneElement, render, hydrate } from 'preact';

export default function register(Component, tagName, propNames, options) {
function toCustomElement(Component, propNames, options) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function toCustomElement(Component, propNames, options) {
export function createCustomElement(Component, propNames, options) {

function PreactElement() {
const inst = Reflect.construct(HTMLElement, [], PreactElement);
inst._vdomComponent = Component;
Expand Down Expand Up @@ -49,12 +49,20 @@ export default function register(Component, tagName, propNames, options) {
});
});

return PreactElement;
}

export default function register(Component, tagName, propNames, options) {
const PreactElement = toCustomElement(Component, propNames, options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const PreactElement = toCustomElement(Component, propNames, options);
const PreactElement = createCustomElement(Component, propNames, options);


return customElements.define(
tagName || Component.tagName || Component.displayName || Component.name,
PreactElement
);
}

register.toCustomElement = toCustomElement;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
register.toCustomElement = toCustomElement;


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

function ContextProvider(props) {
this.getChildContext = () => props.context;
// eslint-disable-next-line no-unused-vars
Expand Down
28 changes: 28 additions & 0 deletions src/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,32 @@ describe('web components', () => {
});
assert.equal(getShadowHTML(), '<p>Active theme: sunny</p>');
});

function ManualRegistration() {
return <div>I'm manually registered</div>;
}

it('allows manual deferred registration by just exposing the element', async () => {
const CustomElement = registerElement.toCustomElement(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const CustomElement = registerElement.toCustomElement(
const CustomElement = createCustomElement(

will need to add an import up top obv

ManualRegistration,
[],
{ shadow: false }
);

const el = document.createElement('x-manually-registered');

root.appendChild(el);
assert.equal(
root.innerHTML,
'<x-manually-registered></x-manually-registered>'
);

window.customElements.define('x-manually-registered', CustomElement);

root.appendChild(el);
assert.equal(
root.innerHTML,
"<x-manually-registered><div>I'm manually registered</div></x-manually-registered>"
);
});
});