@frauschert/yas
Version:
Yet Another State - A lightweight and type-safe state management solution for React
106 lines (105 loc) • 2.22 kB
JavaScript
import { useSyncExternalStore as h, useCallback as y } from "react";
function S(t, r) {
if (t === r) return !0;
if (typeof t != "object" || t === null || typeof r != "object" || r === null)
return !1;
const n = Object.keys(t), e = Object.keys(r);
if (n.length !== e.length) return !1;
for (const c of n)
if (!e.includes(c) || !S(
t[c],
r[c]
))
return !1;
return !0;
}
function k(t, r, ...n) {
let e = t, c = t;
const u = /* @__PURE__ */ new Set(), s = r || S;
function p() {
return e;
}
function d() {
return t;
}
function g() {
return c;
}
let f = (a) => {
const o = a(e);
c = e, e = o, u.forEach((i) => i(e, c));
};
const l = {
getState: p,
getInitialState: d,
getPreviousState: g,
setState: f,
subscribe: (a) => (u.add(a), () => {
u.delete(a);
})
};
if (n.length > 0) {
const a = n.slice().reverse().reduce(
(o, i) => i(l)(o),
(o) => f(() => o)
);
f = (o) => {
const i = o(e);
s(e, i) || a(i);
};
}
return { ...l, setState: f };
}
function b(t) {
return (r) => h(
t.subscribe,
y(() => r(t.getState()), [t, r])
);
}
function m(t) {
return (r) => Object.fromEntries(
Object.entries(r).map(([n, e]) => [
n,
(...c) => t.setState((u) => e(u, ...c))
])
);
}
function E({
initialState: t,
actions: r,
equalityFn: n,
middleware: e = []
}) {
const c = k(t, n, ...e), u = b(c), s = m(c)(r);
return { useStore: u, actions: s, api: c };
}
function O(t, r = 50) {
const n = [], e = [];
return {
...t,
setState: (u) => {
const s = t.getState();
t.setState(u), n.push(s), n.length > r && n.shift(), e.length = 0;
},
undo: () => {
if (!n.length) return;
const u = t.getState(), s = n.pop();
e.push(u), t.setState(() => s);
},
redo: () => {
if (!e.length) return;
const u = t.getState(), s = e.pop();
n.push(u), t.setState(() => s);
},
canUndo: () => n.length > 0,
canRedo: () => e.length > 0,
clearHistory: () => {
n.length = 0, e.length = 0;
}
};
}
export {
E as create,
k as createStore,
O as makeUndoable
};