npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

diffhtml-components

v1.0.0-beta.30

Published

*Provides a way to use function, class, and stateful components with diffHTML. Inspired by React and other component based frameworks.*

Downloads

30

Readme

<±/> diffHTML Components

Provides a way to use function, class, and stateful components with diffHTML. Inspired by React and other component based frameworks.

Stable Version: 1.0.0-beta.30

The exported class Component is designed to be used as either a vanilla JS class component, or registered as a Web Component.

Refer to the website https://diffhtml.org/components.html for documentation.

Installation

npm install --save diffhtml-components

Getting started

Before you can use this module, you will need to have diffHTML loaded first. This component simply provides the Component class, and respective middleware, which help you create Virtual Trees to structure your code.

You can create components as easy as:

import { html, innerHTML } from 'diffhtml';
import { Component } from 'diffhtml-components';

class MyComponent extends Component {
  render() {
    return html`
      <h1>Rendering a Web Component inside a React-Like Component:</h1>
      <web-component />
    `;
    //return (
    //  <span>Even Supports JSX (use Babel transform)!</span>
    //);
  }
}

// Render as a class.
innerHTML(document.body, html`<${MyComponent} />`);

// If you are in a DOM environment that supports Web Components, then you can
// register your component and it will automatically work.
customElements.define('my-component', MyComponent);

// Now you can render like any other kind of HTML.
innerHTML(document.body, '<my-component />');

Default props

This static definition on either a function or class component provides a specification for incoming props. It borrows from the React concept. These are very important for Web Components as they set up the observable properties. That means you can simply update a property directly on the DOM Node and it will automatically re-render.

Example of default props with a class component:

import { html, innerHTML } from 'diffhtml';
import { Component } from 'diffhtml-components';

class MyComponent extends Component {
  render() {
    const { message } = this.props;
    return html`${message}`;
  }

  static defaultProps = {
    message: 'default',
  }
}

innerHTML(document.body, html`
  <${MyComponent} message="setting props via class" />
`);

// Defining your component as a web component is completely optional and easy,
// just use the standard `customElements.define` function and provide a tag
// name. Now <my-component prop=value>childNodes[]</my-component> should work
// as expected.
customElements.define('my-component', MyComponent);

innerHTML(document.body, html`
  <my-component message="setting props via web component" />
`);

document.body.firstElementChild.message = 'Dynamic!';
// my-component has now automatically re-rendered to display this new state

State

diffHTML Components are stateful and follow the React model of setState. By default your components are given an empty state object that you can use to store any kind of local state for your component. While you can edit this object directly, this will not trigger any kind of component update. To set the new state and trigger a re-render, you will need to use the setState method.

For example:

import { html } from 'diffhtml';
import { Component } from 'diffhtml-components';

class SimpleCounter extends Component {
  render() {
    const { className, label  } = this.props;

    return html`
      <div class=${className}>${label}</div>
    `;
  }

  componentDidMount() {
    // Increment the `tick` state every second.
    this.interval = setInterval(() => this.setState({
      tick: ++this.state.tick,
    }), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }
}

The setState call receives the incoming object, which is merged into the existing this.state and then into a brand new object, which effectively causes your state property to be "immutable".

If you were to call setState in a tight loop, you would notice that the first call would trigger a re-render, but would not render again until the tight loop completes. This is a way to throttle while also allowing setState to be reliable for synchronous operations.

If you do not like the behavior and wish to have more control over setting state and rendering changes, look into forceUpdate below.

Force Update

The forceUpdate() method is implemented and will trigger a no-questions-asked -render of your component. This is a synchronous operation, but if diffHTML has a paused transaction, this will wait until the existing transaction has completed before modifying your component.

This is especially useful if you want to manage state outside of setState and want your components to be reactive.

Examples

The following examples show what real-world usage of these components may look like.

Function components

Using a function component is a good way to have lightweight components without the overhead of a class. You map the incoming attributes as arguments and the return value is a VTree created by html or createTree.

import { html, innerHTML } from 'diffhtml';
import 'diffhtml-components';

function SimpleClock({ now }) {
  return html`
    <strong>The current unix timestamp is:</strong> ${now}
  `;
}

innerHTML(document.body, html`<${SimpleClock} now=${Date.now()} />`);

Class components

Useful when you need minimal React features for new projects. This is not necessarily a good package for React Compatibility inter-op, although it can work to load some components. If you need full parity with React, look to the diffhtml-react-compat.

import { html, innerHTML } from 'diffhtml';
import { Component } from 'diffhtml-components';

class SimpleClock extends Component {
  render() {
    const { now } = this.state;

    return html`
      <strong>The current unix timestamp is:</strong> ${now}
    `;
  }

  constructor(props) {
    super(props);

    this.state = { now: Date.now() };

    // Update very fast.
    setInterval(() => this.setState({ now: Date.now() }), 10);
  }
}

// Render to the `<body />` element.
innerHTML(document.body, html`<${SimpleClock} />`);

Web Components

All diffHTML Components extend HTMLElement and can be registered with the V1 Custom Elements registry. It is optional to utilize them as Web Components. To do so, use the customElements.define function.

Full browser availability

  • Chrome: Stable
  • Firefox: Stable
  • Safari: Stable
  • Edge: Stable

Example:

import { html, innerHTML } from 'diffhtml';
import { Component } from 'diffhtml-components';

class SimpleClock extends Component {
  render() {
    const { now } = this.state;

    return html`
      <strong>The current unix timestamp is:</strong> ${now}
    `;
  }

  constructor(props) {
    super(props);

    this.state = { now: Date.now() };

    // Update very fast.
    setInterval(() => this.setState({ now: Date.now() }), 10);
  }
}

// Required to auto-fill the `observedAttributes` function.
SimpleClock.defaultProps = {
  now: Date.now(),
};

// Register into the browser's element registry.
customElements.define('simple-clock', SimpleClock);

// Render to the `<body />` element.
innerHTML(document.body, html`<simple-clock />`);