1.0.30 • Published 4 months ago
@supercat1337/store v1.0.30
Store.js
Cross-browser storage for all use cases.
A store is simply an object with that allow interested parties to read the store value and be notified whenever it changes.
- tiny (bundle size is 13 kb)
- agnostic
- reactive
- support for instant and delayed reactions
- fully documented
- pure JavaScript (typed with JSDoc)
Installation
$ npm install @supercat1337/store
You can find many code examples in our documentation
Basic example: counter with debounce
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Store demo</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous"
/>
</head>
<body>
<div class="container mt-5">
<div class="d-flex flex-column align-items-center">
<h1 class="mb-3">c = a + b (debounce 0.1 second)</h1>
<div class="mb-3">
<button class="btn btn-outline-secondary" id="a_dec_button">
-
</button>
<div
id="a_counter_value"
class="d-inline-block text-center"
style="width: 100px;"
>
0
</div>
<button class="btn btn-outline-secondary" id="a_inc_button">
+
</button>
</div>
<div class="mb-3">
<button class="btn btn-outline-secondary" id="b_dec_button">
-
</button>
<div
id="b_counter_value"
class="d-inline-block text-center"
style="width: 100px;"
>
0
</div>
<button class="btn btn-outline-secondary" id="b_inc_button">
+
</button>
</div>
<div>=</div>
<div class="mb-3">
<div
id="c_counter_value"
class="d-inline-block text-center"
style="width: 100px;"
>
0
</div>
</div>
</div>
</div>
<script src="index.js" type="module"></script>
</body>
</html>
index.js
// @ts-check
import { Store } from "@supercat1337/store";
var a_counter_value = /** @type {HTMLElement} */ (
document.querySelector("#a_counter_value")
);
var a_button_dec = document.querySelector("#a_dec_button");
var a_button_inc = document.querySelector("#a_inc_button");
var b_counter_value = /** @type {HTMLElement} */ (
document.querySelector("#b_counter_value")
);
var b_button_dec = document.querySelector("#b_dec_button");
var b_button_inc = document.querySelector("#b_inc_button");
var c_counter_value = /** @type {HTMLElement} */ (
document.querySelector("#c_counter_value")
);
var store = new Store();
var a = store.createAtom(0);
var b = store.createAtom(0);
var c = store.createComputed(() => {
return a.value + b.value;
});
a.subscribe(() => {
a_counter_value.innerText = a.value;
}, 100);
b.subscribe(() => {
b_counter_value.innerText = b.value;
}, 100);
c.subscribe(() => {
c_counter_value.innerText = c.value;
}, 100);
a_button_dec?.addEventListener("click", () => {
a.value--;
});
a_button_inc?.addEventListener("click", () => {
a.value++;
});
b_button_dec?.addEventListener("click", () => {
b.value--;
});
b_button_inc?.addEventListener("click", () => {
b.value++;
});
Also you can work with arrays
// @ts-check
import { Store } from "@supercat1337/store";
var store = new Store();
var a = store.createCollection([]);
var b = store.createComputed(() => {
return a.value.length;
});
b.subscribe((details) => {
console.log(`b = ${details.value}`);
});
var arr = a.value;
arr.push(1);
// outputs: b = 1
arr.push(2);
// outputs: b = 2
arr.pop();
// outputs: b = 1
And objects
// @ts-check
import { Store } from "@supercat1337/store";
class State {
counter1 = 0;
counter2 = 0;
counter3 = 0;
incr1 = () => {
this.counter1++;
};
incr2 = () => {
this.counter2++;
};
incr3 = () => {
this.counter3++;
};
}
const store = new Store();
const state = store.observeObject(new State());
const counter1div = document.createElement("div");
const counter2div = document.createElement("div");
const counter3div = document.createElement("div");
const btn1 = document.createElement("button");
btn1.innerText = "inct 1";
btn1.addEventListener("click", state.incr1);
const btn2 = document.createElement("button");
btn2.innerText = "inct 2";
btn2.addEventListener("click", () => {
state.counter2++;
});
document.body.appendChild(counter1div);
document.body.appendChild(counter2div);
document.body.appendChild(counter3div);
document.body.appendChild(btn1);
document.body.appendChild(btn2);
(async () => {
await store.when(() => state.counter1 >= 3);
alert("Another cool thing is when");
})();
// Trigger when counter1 or counter2 changed
store.autorun(() => {
counter1div.innerHTML = `counter 1: ${state.counter1}`;
counter2div.innerHTML = `counter 2: ${state.counter2}`;
});
// Trigger when counter3 changed (another way)
store.reaction(
() => [state.counter3],
() => {
counter3div.innerHTML = `counter 3: ${state.counter3}`;
}
);
setInterval(state.incr3, 1000);
1.0.30
4 months ago
1.0.22
1 year ago
1.0.21
1 year ago
1.0.26
12 months ago
1.0.25
12 months ago
1.0.24
1 year ago
1.0.23
1 year ago
1.0.29
10 months ago
1.0.28
10 months ago
1.0.27
12 months ago
1.0.20
1 year ago
1.0.19
1 year ago
1.0.18
1 year ago
1.0.17
1 year ago
1.0.16
1 year ago
1.0.15
1 year ago
1.0.11
1 year ago
1.0.10
1 year ago
1.0.14
1 year ago
1.0.12
1 year ago
1.0.9
1 year ago
1.0.8
1 year ago
1.0.7
1 year ago
1.0.6
1 year ago
1.0.5
1 year ago
1.0.2
1 year ago
1.0.1
1 year ago
1.0.4
1 year ago
1.0.3
1 year ago
1.0.0
1 year ago