Negligible Participation Metric

    comfey

    2.1.0 • Public • Published

    Comfey 2

    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

    Install

    npm i comfey

    DownloadsWeekly Downloads

    37

    Version

    2.1.0

    License

    MIT

    Unpacked Size

    28.5 kB

    Total Files

    19

    Last publish

    Collaborators

    • dejavu1987