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

cyclow

v0.5.3

Published

A reactive frontend framework for JavaScript

Downloads

4

Readme

cyclow is a reactive frontend framework for JavaScript. It's inspired by another frameworks like Cycle.js and TSERS. It uses graflow as stream library.

Example

This a simple counter example:

  import { Block, run } from 'cyclow'

  const Counter = () => Block({
    on: {
      'in.init':  () => state => 0,
      'dom.click': () => state => state + 1
    },
    view: state => ({
      tag: 'button',
      on: {click: 'click'},
      content: `Count: ${state}`
    })
  })

  run(Counter)

Try it online!

More samples

You can build and open samples in a browser:

  git clone https://github.com/pmros/cyclow
  cd cyclow
  npm install
  npm run samples

Samples include a TodoMVC sample.

You can find even more samples at JS Comp and compare them with another implementations using frameworks like React, Angular or Cycle.

Why cyclow?

There are many JavaScript frameworks so... why another one? Well I really like Cycle.js. It's a nice reactive framework. TSERS is like Cycle.js and it adds a simple state manager and another features. But both are too pure (in the functional programmming sense) for me.

With cyclow instead of thinking in a big global model and pure functions, you have to think in components with inputs, outputs and their own state (something like an electronic circuit). I think cyclow is more intuitive and easier while it's still reactive and quite declarative. You can compare cyclow and Cycle.js samples at JS Comp.

cyclow goal is to help you to create applications that are:

  • Declarative
  • Easy to code
  • Easy to read
  • Scalable

How it works

A cyclow app consits of a block. A block is composed of other blocks. A block is graflow component, it receives messages and send messages async.

Every block contains this default blocks:

  • in
  • events
  • state
  • view
  • dom
  • out

In adition, you can add your own blocks or custom blocks with blocks Block option.

Every block inside a block is connected through a bus block, sending and receiving messages. Bus connect blocks forming a cycle.

Messages has three parts:

  • Block
  • Signal
  • Value

You can handle messages with on Block option.

Finally, you can transform state into a Virtual DOM Element with view Block option. Virtual DOM Element will be converted into a real DOM by the renderer.

How To

How to set the initial state?

At the beginning, every block receives an init signal from in block. So you can handle this message to set a initial state.

From the counter example:

  on: {
    'in.init': () => state => 0
  }

In this case, the handler takes no params () and returns a state transformation state => 0. It's a function that takes the current state and returns the next state.

How to handle DOM events?

First, you have to catch the DOM event in view Block option. From counter exaple:

  view: state => ({
    tag: 'button',
    on: {click: 'click'},
    content: `Count: ${state}`
  })

Then, you can handle DOM event as a normal block message (from dom block):

  on: {
    'dom.click': () => state => state + 1
  }

If you need DOM event information, see Inputbox sample:

on: {
  ...
  'dom.text': newText => text => newText,
},
view: text => ({content: [
  {tag: 'input',
    attrs: {id: 'myInput', value: text},
    on: {keyup: (e, next) => next({text: e.target.value})}
  }
  ...
]})

How to compose blocks?

See Composition sample:

  blocks: {field: Field()},
  on: {
    'in.init': () => [{'field.init': 'Enter name'}, state => ({current: 'Steve'})],
    'field.submission': submission => state => ({current: submission})
  }

How to focus a DOM element?

See Inputbox sample:

  on: {
    'dom.focus': () => ({'dom.action': node => node.firstElementChild.focus()})
  }

How to use LocalStorage to save the state?

See TodoMVC sample:

  on: {
    'in.init': () => state => JSON.parse(localStorage.getItem('todomvc')) || initial(),
    state: state => { localStorage.setItem('todomvc', JSON.stringify(state)) }
  }

How to debug a cyclow app?

You can log every message through bus block:

  on: {
    bus: msg => {
      console.log('Message', msg)
      return msg
    }
  }

Virtual DOM Element

cyclow represents DOM elements as Virtual DOM Elements, that is a simple Javascript object with the following (optional) properties:

  • tag: HTML tag (default is div)
  • attrs: Attributes (like id, class or style).
  • on: Events handlers (like click). It can be just an event message or a function that receive the DOM event and a function to send an event message.
  • content: Content can be just text, a Virtual DOM Element or an array of Virtual DOM Elements.

This is a virtual DOM element example:

  {
    tag: 'input',
    attrs: { id: 'myInput' },
    on: { keyup: (e, next) => next({text: e.target.value}) }
  }

Renderer

A renderer is just a component factory. It creates a component that takes a Virtual DOM Element as a input and it converts into a Real DOM Element and it updates the HTML document. cyclow uses snabbdom as default renderer.

A renderer is a function that it takes target, that the DOM element id where you want to insert into the Virtual DOM Element. If you don't specify target, cyclow will append the app at the end of body.

API

run(MainComponent, options={})

Arguments:

  • MainComponent: A component factory.
  • options:
    • target (document.body by default)
    • renderer (SnabbdomRenderer by default)
    • init ({} by default)

Block(options)

Arguments:

  • options:
    • blocks
    • on
    • view

Returns: A graflow component

TODO

  • [x] Virtual DOM diff and patching
  • [x] A way to focus a DOM element
  • [x] A TodoMVC sample
  • [x] A cool logo
  • [ ] JavaScript Standard Style
  • [ ] More documentation
  • [ ] More samples
  • [ ] Functional tests