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

catbee-web-components

v1.0.0-rc.16

Published

Catbee web components renderer

Downloads

111

Readme

Catbee Web Components

Build Status

DocumentRenderer implementaion based on Web Components, spiced by Appstate and Baobab for state management. You can use it with any template engine (jade, handlebars, dust) and not worry about browser rendering because it uses morphdom for partial DOM updates instead of full-page rerendering.

Getting Started

Web components is one of the implementations of Catbee view layer. It should be registered as Catbee service and provided root document component. Below is a code example for integration in browser.

const catbee = require('catbee');
const components = require('catbee-web-components');
const cat = catbee.create();

// Describe first component
const component = {
  constructor: class Document {
    template () {
      return 'Hello world';
    }
  }
}

components.register(cat.locator, component);

cat.startWhenReady();

Similarly, it can be integrated on server.

const catbee = require('catbee');
const components = require('catbee-web-components');
const express = require('express');

const cat = catbee.create();
const app = express();

// Describe first component
const component = {
  constructor: class Document {
    template () {
      return 'Hello world';
    }
  }
}

components.register(cat.locator, component);

app.use(cat.getMiddleware());
app.listen(3000);

Instalation

npm install catbee-web-components --save

Registration

const components = require('catbee-web-components');
components.register(locator, root);

Component detection

Catbee Web Components marks tag as component if it has cat-* prefix. Head is special name, and can be used without prefix.

Component Specification

class Component {
  constructor (locator) {
    // Every component get locator as argument in constructor, 
    // it's can be used for resolve services (config, uhr, api, etc...)
    this._config = locator.resolve('config');
  }
  
  // Template is a function that is called when you render component to HTML string
  // It accepts ctx as a first argument, and should return string.
  // You can use any template language that can be compiled to function.
  // For example, you can use Handlebars require hook on server, 
  // and webpack loader for client side bundle, with the following code:
  // 
  // constructor () {
  //   this.template = require('./template.hbs');
  // }
  template (ctx) {
    return `
      <!DOCTYPE html>
      <html lang="en">
      <head></head>
      <body>
        <a class="link">Hello ${ctx.world}</a>
        <cat-main></cat-main>
        <script src="/build.js"></script>
      </body>
      </html>
    `
  }
  
  render () {
    // This method creates ctx for template function
    // You should return Object or Promise resolved by Object
    // Also here you can make any DOM manipulation, because at this point 
    // all nodes are already in DOM.
    return { 
      world: 'Earth'
    }
  }
  
  bind () {
    // This method should return DOM event bindings map as Promise or Object
    return {
      click: {
        'a.link': (e) => console.log(e.currentTarget)
      }
    }
  }
  
  unbind () {
    // This method can be used as dispose component hook.
    // It's called before DOM gets disposed and event listeners detached.
  }
}

module.exports = {
  // This is component descriptor.
  // It's provide information about component context usage
  constrcutor: Component,
  children: [
    // Here should be described all chidren components (cat-*)
    // Document and head, it's special names used by library for better dev expirience.
    {
      name: "head",
      component: require('./headDescriptor') // You should head descriptor, same object as exports here
    },
    {
      name: "main",
      component: require('./mainDescriptor'),
      watcher: {
        value: ['path', 'to', 'value']
      }, // Bind to component part of data tree. Use this.$context.getWatcherData() to get it.
      props: {
        size: 'big'
      } // Pass to component some static props. Will be avaliable as this.$context.props
    }
  ]
}

Shared context

Catbee sets as the property $context for every instance of each signal action and component.

  • this.$context.isBrowser – true if code is being executed in the browser.
  • this.$context.isServer – true if code is being executed on the server.
  • this.$context.userAgent – the current user agent string of the environment.
  • this.$context.cookie – the current cookie wrapper object.
  • this.$context.location – the current URI object that contains the current location.
  • this.$context.referrer – the current URI object that contains the current referrer.
  • this.$context.locator – the Service Locator of the application.
  • this.$context.redirect('String') – redirects to a specified location string. If used while rendering the document or head component, this action will be accomplished using HTTP headers and status codes on the server, else via an inline <script> tag.
  • this.$context.notFound() – hands over request handling to the next express/connect middleware. If used while rendering the document or head component, this action will be accomplished using HTTP headers and status codes on the server, else via an inline <script> tag.

Component context

Every component's $context is extended with the following properties & methods:

  • this.$context.getWatcherData() - return Promise resolved by state tree projection data.
  • this.$context.signal(actions, args) - run appstate signal with actions array and args object.
  • this.$context.state - the current application state reference.
  • this.$context.props - the set of props passed by parent component.
  • this.$context.element – the current DOM element that represents the current component.
  • this.$context.attributes – the set of attributes which component's DOM element has at the moment.
  • this.$context.getComponentById('id') – gets another component object by ID of its element.
  • this.$context.getComponentByElement(domElement) – gets another component's object by its DOM element.
  • this.$context.createComponent('tagName', descriptor, attributesObject) – creates a new component's instance and returns a promise of its DOM element.
  • this.$context.collectGarbage() – collects all components which have been created using the createComponent('tagName', attributesObject) method and are not attached to the DOM at the moment.
  • this.$context.forceUpdate() - rerender component. Client-side only.

Component Slots

Slots it's part of W3C Web Components specification. Slots allow you inject content from parent-to-child. Catbee support bare-bone version of this feature.

Example:

// Child.js
class Child {
  template () {
    return '<slot></slot>'
  }
}

module.exports = {
  constructor: Child
}

// Parent.js
class Parent {
  template () {
    return '<cat-child>Content injection</cat-child>';
  }
}

module.exports = {
  constructor: Parent,
  children: [
    {
      name: 'child',
      component: require('./Child')
    }
  ]
}

// Result HTML
<cat-parent>
  <cat-child><slot>Content injected</slot></cat-child>
</cat-parent>

Features supported:

  • Inject components (should be described in parent)
  • Default values if content not provided

Data flow

Library provides built-in data-flow system.

Data Flow

Core things:

  • Components are stateless
  • Components can't directly change state
  • Components send signals
  • Signals run actions that mutate state
  • Components watch tree branches
  • State send updates to components when a branch was changed
  • Component rerenders when watched branches were changed