preactjs / preact-custom-element

Wrap your component up as a custom element
MIT License
360 stars 52 forks source link

This repo is use the old v0 spec #4

Closed 0xR closed 6 years ago

0xR commented 7 years ago

A warning could be added to the README. Even better would be an upgrade to the new v1 spec.

0xR commented 7 years ago

This seems to work:

import { h, render } from 'preact';

const Empty = () => null;

export default function register(Component, tagName) {
  class PreactComponent extends HTMLElement {
  }
  PreactComponent.prototype._vdomComponent = Component;
  PreactComponent.prototype.connectedCallback = PreactComponent.prototype.attributeChangedCallback = renderElement;
  PreactComponent.prototype.detachedCallback = unRenderElement;

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

function renderElement() {
  this._root = render(
    toVdom(this, this._vdomComponent),
    this,
    this._root
  );
}

function unRenderElement() {
  render(h(Empty), this.shadowRoot, this._root);
}

function toVdom(element, nodeName) {
  if (element.nodeType===3) return element.nodeValue;
  if (element.nodeType!==1) return null;
  let children=[], props={}, i=0, a=element.attributes, cn=element.childNodes;
  for (i=a.length; i--; ) props[a[i].name] = a[i].value;
  for (i=cn.length; i--; ) children[i] = toVdom(cn[i]);
  return h(nodeName || element.nodeName.toLowerCase(), props, children);
}

Note if you're compiling to es5 with babel you need a shim

bspaulding commented 7 years ago

Thanks for your work! A few questions:

  1. What's support look like for v1?
  2. How can we supply versions compatible with v0 and v1 and let the user decide which they require?
  3. As a consumer, what's exceptional about v1 that I would require it over v0?

Thanks! PRs welcome, too! If you like. :)

0xR commented 7 years ago

V0 is a proposal for the custom elements spec which only implemented in Chrome. V1 is the actual standardized spec which is going to be implemented by all browser vendors. Chrome currently supports both v0 and v1 elements natively. Since other browsers are only going to implement the v1 spec it makes sense to only support that standard.

As for what would support look like it is probably close to the code I posted. Note I didn't test whether the attribute changed callback is actually called. So its mostly additional testing across browsers.

Also an addition to the README should be created regarding the shim needed when transpilation to es5 is used.

LostInBrittany commented 6 years ago

I needed a Custom Elements V1 implementation, I used @0xR 's version as base to do a es6 class-based implementation.

As @0xR said, when transpiling to es5, you need native-shim.js (see here for more explanations).

About @bspaulding three questions :

  1. What's support look like for v1?

According to Can I use? the support of v1 shines now: Chrome and Safari already have it, Firefox will have it in next version (Firefox 59). And for current and old Firefox, Edge or old Safari and Chrome, you have the polyfill.

The support of V0 is way poorer, only Chrome implements if, and you can use an old polyfill to make it work in other browsers. And even Chrome will drop the support, as it's an outdated spec.

  1. How can we supply versions compatible with v0 and v1 and let the user decide which they require?

Well, I think you could offer two versions of the packager... or, wait a second (I'm thinking while I write...), two exports! One for v0 and another for v1!

But I am not sure if it would be useful...

  1. As a consumer, what's exceptional about v1 that I would require it over v0?

Well, V1 is already way better supported either natively on Chrome, Safari and soon Firefox or with a faster and leaner polyfill in other browsers.

I'm putting a PR on this, and if you want I can try to put the two exports version, that could allow you to support both v1 and v2.

What do you think ?

bspaulding commented 6 years ago

@0xR @LostInBrittany

Sorry I haven't been active here for a while! Updating to v1 seems like the way to go. A major version bump should be enough, v0 stragglers can stick to that. I don't expect many updates to this lib that will need to be back ported.

I am going to start by setting up CircleCI and some browser tests for this package, then I'll review and merge @LostInBrittany's PR.

Thanks again for being patient with me here!

bspaulding commented 6 years ago

Just release v3.0.0 which implements v1 spec. Sorry this took so long!

There is a test suite now, (well ok just one test case :)), so if you're using this and the update breaks something, please open a PR with a test case!

Thanks for your patience!