Giter Club home page Giter Club logo

babel-plugin-hyperhtml's People

Contributors

phpnode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

babel-plugin-hyperhtml's Issues

Enabled slotted invokation: proposing a new transformation

As explained in here, I'd like to know if there's any interest in improving the current transformation or if I should just fork this and try to make it work as intended.

There is a little, but huge, change that opens doors for this transformation in a pretty seamless way.

JSX

const { Component, bind } = hyperHTML;

class Rando extends Component {
  render() {
    return this.html(
      <Sub value={1 + this.props.rand} />
      <Sub value={2 + this.props.rand} />
    );
  }
}

class Sub extends Component {
  render() {
    return this.html(
      <div>
        Value <strong>{this.props.value}</strong>
      </div>
    );
  }
}

const render = bind(document.body);
render(
  <div>
    <Rando rand={Math.random()} />
  </div>
);

should become

const { Component, bind } = hyperHTML;

class Rando extends Component {
  render() {
    return this.html`
      ${node => {
        const comp = Sub.for(node);
        comp.props = {value: 1 + this.props.rand};
        return comp.render();
      }}
      ${node => {
        const comp = Sub.for(node);
        comp.props = {value: 2 + this.props.rand};
        return comp.render();
      }}
    `;
  }
}

class Sub extends Component {
  render() {
    return this.html`
      <div>
        Value <strong>${this.props.value}</strong>
      </div>
    `;
  }
}

const render = bind(document.body);
render`
  <div>
    ${node => {
      const comp = Rando.for(node);
      comp.props = {rand: Math.random()};
      return comp.render();
    }}
  </div>
`;

enabling the following features:

  • no component trashing. Every component is related to their template comment node and created only once.
  • there are props, not just state. When the .render() will be automatically invoked the component would already have updated props (or the same if not computed at runtime).
  • simple and semantic, hiding boilerplate all over, granting unique IDs per each component relation

How to transform

The rule is pretty simple:

<ComponentName attr1={123} attr2=456 attr3={what('ever')} />

Should become

${node => {
  const comp = ComponentName.for(parent);
  comp.props = {attr1: 123, attr2: 456, attr3: what('ever')};
  return comp.render();
}}

So that attributes would be passed as props.

The Template Literal rules

The JSX surrounding parenthesis will mark the beginning and the end of the Template Literal, and holes found outside components should be replaced by ${} instead of {} so that this:

render(
  <div onclick={event => alert(event.target)}>
    <Comp stuff={'cool'} />
  </div>
);

would become

render`
  <div onclick=${event => alert(event.target)}>
    ${node => {
      const comp = Comp.for(node);
      comp.props = {stuff: 'cool'};
      return comp.render();
    }}
  </div>
`;

I hope all details are clear enough.

TBD

I am not sure it makes sense to pass along children, since each component can create those directly in the render method, and use props to define children, i.e.

<ComponentName sub={['first child', 'last child']} />

So, actually, I think for the time being having just the proposed transform would be awesome.

Thank You !!!

You had this idea and I'm trying to make it happen for the whole hyperHTML user-base, which I'm pretty sure would appreciate the possibility of using JSX to simplifying lightweight components usage in hyperHTML instead of Custom Elements.

Thanks in advance for considering this or, eventually, for sharing your thoughts on this.

Best Regards.

Code Pen live here https://codepen.io/WebReflection/pen/MPxBzJ?editors=0010

misleading demo

quick heads-up, the produced code with that extra object won't ever work:

const Greet = _arg => {
  let {name, ...extra} = _arg;
  return wire(_arg)`<div ${extra}><h1>Hi ${name}</h1></div>`;
}

attributes always need to be assigned to a name

avoid new components per each render

the following will create a new Greet every render time

class DemoComponent extends Component {
  render() {
     return this.html`<div class="test">
         ${new Greet({name: "Alice", class: "greeter"})}
         <p>This is some text</p>
       </div>`;
  }
}

It'd be awesome if inner components could be related to their owner. At the end of the day, writing <Greet /> is not less static than a div so ... how about some helper to make it possible?

// used for every component
const comp = (self, i, Class, data) => {
  // either quick and dirty or via WeakMap
  const c = (self.__comp || (self.__comp = []))[i] ||
            (self.__comp[i] = new Class);
  c.setState(data);
  return c;
};

class DemoComponent extends Component {
  get defaultState() { return {class: null, name: ''}; }
  render() {
    return this.html`
      <div class="test">
        ${comp(this, 0, Greet, {name: "Alice", class: "greeter"})}
      <p>This is some text</p>
    </div>`;
  }
}

class Greet extends Component {
  render() {
    return this.html`
      <div class=${this.state.class}>
        <h1>Hi ${this.state.name}</h1>
      </div>`;
  }
}

The i in the comp helper is the index of the component. In this way you update the same component each time instead of creating a new one.

If the setState(data) is not a good pattern, then the component should expose a way to be updated or its render should look for props.

const comp = (self, i, Class, props) => {
  const c = (self.__comp || (self.__comp = []))[i] ||
            (self.__comp[i] = new Class);
  // set props and return the rendered/updated node
  c.props = props;
  return c.render();
};

// ... same code as before ...

class Greet extends Component {
  render() {
    return this.html`
      <div class=${this.props.class}>
        <h1>Hi ${this.props.name}</h1>
      </div>`;
  }
}

Thoughts ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.