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

comfey

v2.2.0

Published

Tiny micro mini data binding library inspired by react hook useState

Downloads

426

Readme

Comfey 2 StandWithUkraine RussianWarship

SWUbanner

Comfey is a tiny javascript state management library inspired by React hook useState.Comfey provides a simple data binding library to update your HTML using simple valid HTML data attributes.

Read more in Comfey Wiki

Features

  • 0 dependencies / Lightweight v1.0.0 is 35 lines of code
  • Looks like react hook useState
  • No loops, event driven
  • (Optional) Simple HTML5 data attributes to bind the html elements to the states
  • Finite State Machine as a plugin

Table of content

Install

Using NPM

npm install comfey

Using Yarn

yarn add comfey

Initialize component

Instantiate Comfey - optionally passing in a ViewUpdater.

import Comfey from 'comfey';
const myComponent = new Comfey();

Initialize state

Use .useState() method to initialize a state, useState() accepts 3 parameters. Returns getter and setter functions

/**
 *
 * @param {string} state name of the state
 * @param {any} initialVal initial value
 * @param {function} watcher watcher function that will be called everytime the value of the state changes
 *
 * @returns {Array<[function, function]>} getterFunction and SetterFunction
 */

Example:

const [count, setCount] = app.useState('count', 3, countWatcher);

Watch

Watch gets newValue, oldValue and name of the state and is invoked everytime the state changes.

function countWatcher(newVal, oldVal, stateName) {
  // Do something when value of count state changes
}

Templating

Comfey offers a DOM updater as a separate library. Which will let you use simple HTML data attributes to bind your state data to your DOM.

Create a new Instance of ComfeyDom by

import Comfey, { ComfeyDom } from 'comfey';
const viewUpdater = new ComfeyDom(document.getElementById('app'), DEBUG);

// Now pass in the viewUpdater (ComfeyDom instance) to Comfey's constructor
const app = new Comfey(viewUpdater);

Bind state value to an element

Use data-bind attribute with stateName as its value to bind the innerHTML of the element to the state's value.

Visibility

  • data-bind-visible
  • data-bind-hidden

Bind visible and hidden accepts value to compare.

Example

data-bind-visible="numberStatus::medium"

means the element will be visible if the state numberStatus is set to medium value.

Class

  • data-bind-class

Bind class accepts value to compare, but will not interpolate the bound value as a classname.

Example

data-bind-class="currentPage::active::home"

means the element will get active class if the state currentPage is set to home value.

More bind-class DEMOs

Bind attributes

You can bind an attribute to a state's value w/ data-bind-attr. Data bind attributes can take values delimited by :: which will make each delimited string an argument. The argument pattern looks like

<state>::<dynamic-attr>::<value>

Example:

data-bind-attr="count::style::font-size: $rem"

means, a dynamic attribute will be added to the HTML element when the state count has a value, the attribute added will be style attribute and the value for the style attribute will be

font-size: <StateValue>rem

Multi Apps

You can have any number of applications on a page. Instanciate a new Comfey whenever you need.

  • Multiple apps can use duplicate state names
  • they will be scoped within each app
  • You will have to scope your javascript as well
  • Just avoid declaring getters and setters globally

Example

import Comfey, { ComfeyDom } from 'comfey';
// scoped code blocks can use same getters / setters, etc names if desired.
// name uniquely if needs to be in the same scope

(() => {
  const view = new ComfeyDom(document.getElementById('app1'), COMFEY_DEBUG);
  const app = new Comfey(view, COMFEY_DEBUG);
  const [, setActive] = app.useState('stateActive', false);

  setInterval(() => {
    setActive(Math.random() > 0.5);
  }, 1000);
})();

(() => {
  const view = new ComfeyDom(document.getElementById('app2'), COMFEY_DEBUG);
  const app = new Comfey(view, COMFEY_DEBUG);
  const [, setActive] = app.useState('stateActive', false);

  setInterval(() => {
    setActive(Math.random() > 0.5);
  }, 1000);
})();

More Multi App DEMOs

Examples

Counter Example

CodeSandbox

<div id="my-component">
  <div>
    Count:
    <span data-bind="count">
      <!--   This placeholder will be updated with value of count state -->
    </span>
  </div>
  <div>Show plus: <span data-bind="showPlus">x</span></div>
  <div>Hide minus: <span data-bind="hideMinus">x</span></div>
  <div class="buttons">
    <!--   Increment button will be visible if showPlus state is set to true   -->
    <button id="increment" data-bind-visible="showPlus">+</button>
    <button id="decrement" data-bind-hidden="hideMinus">-</button>

    <!-- Bind attribute, state :: attr :: value, $ for stateValue placeholder -->
    <button id="increment" data-bind-attr="disablePlus::disabled::">+</button>
    <div>
      Count:<span
        data-bind-attr="count::style::font-size: $rem"
        data-bind="count"
        >x</span
      >
    </div>
    <div>
      NumberStatus:
      <span data-bind-visible="numberStatus::medium">Medium</span>
      <span data-bind-visible="numberStatus::max">Max</span>
      <span data-bind-visible="numberStatus::min">Min</span>
    </div>
  </div>
</div>
import Comfey, { ComfeyDom } from 'comfey';

const app = new Comfey(new ComfeyDom(document.getElementById('app')));

// Select buttons
const btnIncrement = document.getElementById('increment');
const btnDecrement = document.getElementById('decrement');

// Initialize states
const [, setShowPlus] = app.useState('showPlus', true);
const [, setHideMinus] = app.useState('hideMinus', false);
const [count, setCount] = app.useState('count', 3, countWatcher);

function countWatcher(newVal) {
  if (newVal > 4) {
    setShowPlus(false);
  } else {
    setShowPlus(true);
    if (newVal < 1) {
      setHideMinus(true);
    } else {
      setHideMinus(false);
    }
  }
}

// Button behaviours
btnIncrement.addEventListener('click', () => {
  setCount(count() + 1);
});
btnDecrement.addEventListener('click', () => {
  setCount(count() - 1);
});

Comfey - Pokemon buddy game

Codesandbox

Multi level navigation

Codesandbox

Change log

v2.0

  • ViewUpdater abstracted, no more DOM manipulation code in main library.
  • Empty instantiation of Comfey will ignore view update (Headless Mode) as opposed to falling back to document
  • ComfeyDom introduced to support DOM manipulation, which can be optionally passed in to Comfey constructor. See examples above or in /demo/ directory.
  • Comfey is an ESM module