1.3.0 • Published 11 months ago

witting v1.3.0

Weekly downloads
-
License
MIT
Repository
-
Last release
11 months ago

Witting

v1.1.0

Witting is a minimal single-file library for state management.


Installation

> npm i witting

Usage

witting provides the following interfaces:


First, import witting:

import * as witting from "witting";
import { functionInDemand } from "witting";

var witting = require("witting");

Creates a state and gets the core value:

const stuff: State<string> = createState("anything");
// or const stuff = State("anything");

console.log(stuff.get());
> "anything"

Sets the core value:

stuff.set("something");
console.log(stuff.get());
> "something"

Attends and prepare to react before and to changes:

const { neglect } = stuff.attend(
    (state) => {
        console.log("after a change.");
    },
    (becoming, current) => {
        console.log("before a change.");
    }
);
stuff.set("everything");
> "before a change."
> "after a change."

The callbacks will not be invoked if set the same value:

stuff.set("everything");
> [nothing gets printed]

The callbacks will also not be invoked after being neglected:

neglect();
stuff.set("nothing");
> [nothing gets printed]

Creates a state register:

const { addState, getState, delState } = openStateRegister();

Registers values "mona" and "lisa" as States with keys "person1" and "person2". The second argument can be either the value or a state with the value itself:

addState("person1", createState("Mona"));
addState("person2", "Lisa").attend((state) => console.log("My name is now " + state));

Retrieves the state of key "person2" and set a value to it:

getState("person2").set("Belle");
> "My name is now Belle"

Removes the state of key "person2":

delState("person2");
console.log(getState("person2"));
> undefined

Creates multiple states from an array of values and stores them in an internal state register. getState() is exposed so that the states can be accessed:

const { getState } = createStates(["foo", "bar", "chocolate"]);

To retrieve them, strings of their indices are passed to getState():

getState("1").set("fool");

The argument can also be a linear object other than an array. With this, custom keys can be associated with the states:

const { getState } = createStates({
    rigel: 8.005,
    sirius: 230,
    ross: 5000,
});

Suppose we have a template element:

<template id="traffic-light">
    <div class="traffic-light wrapper" data-color="red">
        <span class="message">stop</span>
    </div>
    <style>
        .traffic-light.wrapper[data-color = "red"] {
            background-color: red;
        }
        .traffic-light.wrapper[data-color = "yellow"] {
            background-color: yellow;
        }
        .traffic-light.wrapper[data-color = "green"] {
            background-color: greend;
        }
    <style>
</template>

Binds Witting state with respective objects, by exposing a setState() onto the object:

function TrafficLightComponent(): HTMLElement & Witting {
    const template = document.getElementByID("traffic-light") as HTMLTemplateElement;
    const component = template.content.cloneNode(true) as HTMLElement;

    const wrapper = component.querySelector(".wrapper") as HTMLElement;
    const message = component.querySelector(".message") as HTMLElement;

    const { privateGetter: getState } = createStates({
        text: "stop",
    });
    privateGetter("text").attend((state) => {
        message.textContent = state;
    });

    const { publicGetter: getState } = createStates({
        color: "red",
    });
    publicGetter("color").attend((state) => {
        const text = privateGetter("text");
        switch(state) {
            case "red": text.setState("stop"); break;
            case "yellow": text.setState("wait"); break;
            case "green": text.setState("go"); break;
            default: break;
        };
        wrapper.setAttribute("data-color", state);
    });

    // inducing `Witting` on `component`
    induceWitting(component, publicGetter);
    return component as HTMLElement & Witting;
}

The above code is a rough implementation of a TrafficLightComponent which changes color and associated messages.

TrafficLightComponent possess 2 states: the private text and public color. text's value depends upon color's value and gets displayed as textContent of the component.

color may be mutated outside of the component such as in a handler of "click" event. But color itself shouldn't be exposed to the outside.

By inducing Witting on TrafficLightComponent and exposing a setState() on the component directly, color can now be mutated from the outside without the need to appear explicitly on the outside.

const trafficLight = TrafficLightComponent();
const changeButton = document.createElement("button");

let pressCount = 0;
changeButton.addEventListener("click", () => {
    pressCount += 1;
    pressCount %= 3;

    switch(pressCount) {
        case 0: trafficLight.setState("red"); break;
        case 1: trafficLight.setState("yellow"); break;
        case 2: trafficLight.setState("green");
    };
});

document.append(trafficLight, changeButton);

Every time changeButton gets clicked, the color of wrapper will change circling through "red", "yellow" and "green" and the text will change accordingly.

induceWitting() attaches two methods to the objects that gets induced Witting: isWitting() which always return true and setState() which allows mutating the internal public state owned by the object.


Checks if the argument is Witting or not:

console.log(isWitting(trafficLight));
console.log(isWitting(2));
> true
> false

Note: being Witting is owning some internal states and exposing a method for mutating them along with a method which tells the object is Witting. The condition is achieved by calling and passing the object to induceWitting().


License

The core files of the library are covered by MIT license.

All rights reserved. © 2023 Sai Aung Kyaw Htet

Dev-dependencies are covered by respective licenses and all the credits and copyrights go to respective authors.

1.3.0

11 months ago

1.2.0

11 months ago

1.1.0

11 months ago

1.0.0

11 months ago