atomaric 0.0.29 → 0.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -29
- package/build/atomaric.js +173 -131
- package/build/atomaric.umd.cjs +1 -1
- package/package.json +44 -44
- package/types/model.d.ts +162 -149
package/README.md
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
## 🕹️Installation
|
|
2
|
-
|
|
3
|
-
```sh
|
|
4
|
-
npm install atomaric
|
|
5
|
-
```
|
|
6
|
-
|
|
7
|
-
## usage
|
|
8
|
-
|
|
9
|
-
```tsx
|
|
10
|
-
import { atom, useAtom, configureAtomaric } from 'atomaric';
|
|
11
|
-
import { useSyncExternalStore } from 'react';
|
|
12
|
-
|
|
13
|
-
configureAtomaric({ useSyncExternalStore }); // do this before all
|
|
14
|
-
|
|
15
|
-
const nameAtom = atom(
|
|
16
|
-
'World',
|
|
17
|
-
'greats:name', // optional localStorage key
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
function App() {
|
|
21
|
-
const [name, setIsOpen] = useAtom(nameAtom);
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<div onClick={() => setIsOpen(isOpen => (name === 'World' ? 'Man' : 'World'))}>
|
|
25
|
-
Hello <span className="color-accent">{name}</span>
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
```
|
|
1
|
+
## 🕹️Installation
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
npm install atomaric
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
## usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { atom, useAtom, configureAtomaric } from 'atomaric';
|
|
11
|
+
import { useSyncExternalStore } from 'react';
|
|
12
|
+
|
|
13
|
+
configureAtomaric({ useSyncExternalStore }); // do this before all
|
|
14
|
+
|
|
15
|
+
const nameAtom = atom(
|
|
16
|
+
'World',
|
|
17
|
+
'greats:name', // optional localStorage key
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
function App() {
|
|
21
|
+
const [name, setIsOpen] = useAtom(nameAtom);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div onClick={() => setIsOpen(isOpen => (name === 'World' ? 'Man' : 'World'))}>
|
|
25
|
+
Hello <span className="color-accent">{name}</span>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
```
|
package/build/atomaric.js
CHANGED
|
@@ -1,192 +1,234 @@
|
|
|
1
|
-
const
|
|
2
|
-
let
|
|
3
|
-
typeof
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
const v = (e, r, l) => {
|
|
2
|
+
let d = null;
|
|
3
|
+
typeof e == "number" ? d = _(
|
|
4
|
+
r,
|
|
5
|
+
(s) => ({
|
|
6
|
+
increment: (n) => {
|
|
7
|
+
s.set(+s.get() + (n ?? 0));
|
|
7
8
|
}
|
|
8
|
-
}
|
|
9
|
-
) : typeof
|
|
10
|
-
|
|
9
|
+
})
|
|
10
|
+
) : typeof e == "boolean" ? d = _(
|
|
11
|
+
r,
|
|
12
|
+
(s) => ({
|
|
11
13
|
toggle: () => {
|
|
12
|
-
|
|
14
|
+
s.set(!s.get());
|
|
13
15
|
}
|
|
14
|
-
}
|
|
15
|
-
) : Array.isArray(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
})
|
|
17
|
+
) : Array.isArray(e) ? d = _(
|
|
18
|
+
r,
|
|
19
|
+
(s) => ({
|
|
20
|
+
push: (...n) => {
|
|
21
|
+
s.set(s.get().concat(n));
|
|
19
22
|
},
|
|
20
|
-
unshift: (...
|
|
21
|
-
|
|
23
|
+
unshift: (...n) => {
|
|
24
|
+
s.set(n.concat(s.get()));
|
|
22
25
|
},
|
|
23
|
-
update: (
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
+
update: (n) => {
|
|
27
|
+
const c = s.get().slice();
|
|
28
|
+
n(c), s.set(c);
|
|
26
29
|
},
|
|
27
|
-
filter: (
|
|
28
|
-
|
|
30
|
+
filter: (n) => {
|
|
31
|
+
s.set(s.get().filter(n ?? B));
|
|
32
|
+
},
|
|
33
|
+
toggle: (n, c) => {
|
|
34
|
+
const g = s.get().slice(), f = g.indexOf(n);
|
|
35
|
+
f < 0 ? c ? g.unshift(n) : g.push(n) : g.splice(f, 1), s.set(g);
|
|
29
36
|
}
|
|
30
|
-
}
|
|
31
|
-
) :
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
})
|
|
38
|
+
) : e instanceof Set ? d = _(
|
|
39
|
+
r,
|
|
40
|
+
(s) => ({
|
|
41
|
+
add: (n) => {
|
|
42
|
+
s.set(new Set(s.get()).add(n));
|
|
35
43
|
},
|
|
36
|
-
delete: (
|
|
37
|
-
const
|
|
38
|
-
|
|
44
|
+
delete: (n) => {
|
|
45
|
+
const c = new Set(s.get());
|
|
46
|
+
c.delete(n), s.set(c);
|
|
39
47
|
},
|
|
40
|
-
toggle: (
|
|
41
|
-
const
|
|
42
|
-
|
|
48
|
+
toggle: (n) => {
|
|
49
|
+
const c = new Set(s.get());
|
|
50
|
+
c.has(n) ? c.delete(n) : c.add(n), s.set(c);
|
|
43
51
|
},
|
|
44
52
|
clear: () => {
|
|
45
|
-
|
|
53
|
+
s.set(/* @__PURE__ */ new Set());
|
|
54
|
+
},
|
|
55
|
+
update: (n) => {
|
|
56
|
+
const c = new Set(s.get());
|
|
57
|
+
n(c), s.set(c);
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
) : e instanceof Object && (d = _(
|
|
61
|
+
r,
|
|
62
|
+
(s) => ({
|
|
63
|
+
setPartial: (n) => s.set((c) => ({
|
|
64
|
+
...c,
|
|
65
|
+
...typeof n == "function" ? n(s.get()) : n
|
|
66
|
+
})),
|
|
67
|
+
update: (n) => {
|
|
68
|
+
const c = { ...s.get() };
|
|
69
|
+
n(c), s.set(c);
|
|
46
70
|
},
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
71
|
+
setDeepPartial: (n, c, g = ".") => {
|
|
72
|
+
if (n.includes(g)) {
|
|
73
|
+
let f = n.split(g);
|
|
74
|
+
const p = f[f.length - 1];
|
|
75
|
+
f = f.slice(0, -1);
|
|
76
|
+
const D = { ...s.get() };
|
|
77
|
+
let a = D;
|
|
78
|
+
for (const w of f) {
|
|
79
|
+
const A = a[w];
|
|
80
|
+
if (A == null || typeof A != "object") {
|
|
81
|
+
s.do.setPartial({ [n]: c });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
a = a[w] = Array.isArray(A) ? [...A] : { ...A };
|
|
85
|
+
}
|
|
86
|
+
a[p] = c, s.set(D);
|
|
87
|
+
} else s.do.setPartial({ [n]: c });
|
|
50
88
|
}
|
|
51
|
-
}
|
|
52
|
-
) : n instanceof Object && (i = y(
|
|
53
|
-
{
|
|
54
|
-
setPartial: (s) => e.set((r) => ({
|
|
55
|
-
...r,
|
|
56
|
-
...typeof s == "function" ? s(e.get()) : s
|
|
57
|
-
}))
|
|
58
|
-
}
|
|
89
|
+
})
|
|
59
90
|
));
|
|
60
|
-
const
|
|
61
|
-
(s,
|
|
62
|
-
() =>
|
|
63
|
-
|
|
64
|
-
(s,
|
|
65
|
-
) : null,
|
|
66
|
-
return
|
|
67
|
-
(s) => Object.defineProperty(
|
|
68
|
-
),
|
|
69
|
-
},
|
|
70
|
-
class
|
|
71
|
-
constructor(
|
|
72
|
-
const
|
|
73
|
-
let
|
|
74
|
-
},
|
|
75
|
-
const t =
|
|
76
|
-
return
|
|
91
|
+
const h = typeof l == "object" && l != null && "do" in l ? l.do(
|
|
92
|
+
(s, n) => r.set(s, n),
|
|
93
|
+
() => r.get(),
|
|
94
|
+
r,
|
|
95
|
+
(s, n, c) => r.setDeferred(s, n, c)
|
|
96
|
+
) : null, b = {};
|
|
97
|
+
return h && Object.keys(h).forEach((s) => Object.defineProperty(b, s, { get: () => h[s] })), d && Object.keys(d).forEach(
|
|
98
|
+
(s) => Object.defineProperty(b, s, { get: () => d[s] })
|
|
99
|
+
), b;
|
|
100
|
+
}, B = (e) => e, _ = (e, r, l) => r(e);
|
|
101
|
+
class G {
|
|
102
|
+
constructor(r, l) {
|
|
103
|
+
const d = (t) => n = t, h = () => n, b = /* @__PURE__ */ new Set(), s = (t) => t(f());
|
|
104
|
+
let n = r, c, g = () => {
|
|
105
|
+
}, f = () => h(), p = null, D = () => {
|
|
106
|
+
const t = v(r, a, l);
|
|
107
|
+
return D = () => t, t;
|
|
77
108
|
};
|
|
78
|
-
const
|
|
79
|
-
get: (t,
|
|
80
|
-
set:
|
|
81
|
-
}),
|
|
82
|
-
const
|
|
83
|
-
if (!(
|
|
84
|
-
|
|
109
|
+
const a = new Proxy(this, {
|
|
110
|
+
get: (t, u) => u === "do" ? D() : t[u],
|
|
111
|
+
set: U
|
|
112
|
+
}), w = (t, u) => {
|
|
113
|
+
const S = typeof t == "function" ? t(f()) : t;
|
|
114
|
+
if (!(S === f() || S === void 0 || typeof S == "number" && isNaN(S))) {
|
|
115
|
+
d(S), b.forEach(s, this);
|
|
85
116
|
try {
|
|
86
|
-
|
|
117
|
+
P.postMessage({ key: i, value: h() });
|
|
87
118
|
} catch {
|
|
88
119
|
}
|
|
89
|
-
|
|
120
|
+
u !== !0 && g(S);
|
|
90
121
|
}
|
|
91
122
|
};
|
|
92
|
-
this.set = (t,
|
|
93
|
-
|
|
123
|
+
this.set = (t, u) => w(t, u), this.get = () => f(), this.initialValue = r, this.isInitialValue = () => r === h(), this.subscribe = (t) => (b.add(t), () => {
|
|
124
|
+
b.delete(t);
|
|
94
125
|
}), this.reset = () => {
|
|
95
|
-
|
|
126
|
+
w(r, !0), b.forEach(s, this);
|
|
96
127
|
};
|
|
97
|
-
const
|
|
98
|
-
|
|
128
|
+
const A = (t, u) => {
|
|
129
|
+
w(t, u), c = void 0;
|
|
99
130
|
};
|
|
100
|
-
if (this.setDeferred = (t,
|
|
101
|
-
|
|
102
|
-
}, l == null) return
|
|
103
|
-
let
|
|
131
|
+
if (this.setDeferred = (t, u = 500, S, H = !0) => {
|
|
132
|
+
H && c === void 0 && w(t, S), clearTimeout(c), c = setTimeout(A, u, t, S);
|
|
133
|
+
}, l == null) return a;
|
|
134
|
+
let y = null, T = null, I = !0, E = !0, C = !1, z = -1, $ = r instanceof Set ? (t) => new Set(t) : (t) => t, j = r instanceof Set ? (t) => {
|
|
104
135
|
if (t instanceof Set) return Array.from(t);
|
|
105
136
|
throw console.error(t), "The value is not Set instance";
|
|
106
137
|
} : (t) => t;
|
|
107
138
|
if (typeof l == "string")
|
|
108
|
-
|
|
139
|
+
y = l;
|
|
109
140
|
else if ("storeKey" in l)
|
|
110
|
-
I = l.warnOnDuplicateStoreKey ?? I,
|
|
111
|
-
else return
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
return
|
|
115
|
-
}
|
|
116
|
-
let
|
|
117
|
-
if (
|
|
118
|
-
if (
|
|
119
|
-
|
|
141
|
+
I = l.warnOnDuplicateStoreKey ?? I, E = l.listenStorageChanges ?? E, y = l.storeKey, $ = l.unzipValue ?? $, j = l.zipValue ?? j, C = l.unchangable ?? C, T = l.exp ?? T;
|
|
142
|
+
else return a;
|
|
143
|
+
const i = `${L}${y}`, V = T === null || !(T(a, i in o) instanceof Date) ? (t) => JSON.stringify([j(t)]) : (t) => (p ?? (p = {}), p.exp = T(a, i in o).getTime() + 0.2866, p.exp - Date.now() < 24 * 60 * 60 * 1e3 && (clearTimeout(z), clearTimeout(M[i]), z = setTimeout(() => this.reset(), p.exp - Date.now())), JSON.stringify([j(t), p])), F = (t) => {
|
|
144
|
+
const u = JSON.parse(t);
|
|
145
|
+
return p = u[1], $(u[0]);
|
|
146
|
+
};
|
|
147
|
+
let J = !0;
|
|
148
|
+
if (N[i] = a, o[`atom/${y}`] && (o[i] || (o[i] = `[${o[`atom/${y}`]}]`), delete o[`atom/${y}`]), f = () => {
|
|
149
|
+
if (f = h, J) {
|
|
150
|
+
J = !1;
|
|
120
151
|
try {
|
|
121
|
-
i
|
|
152
|
+
d(i in o ? F(o[i]) : r);
|
|
122
153
|
} catch {
|
|
123
|
-
console.warn("Invalid json value",
|
|
154
|
+
console.warn("Invalid json value", o[i]);
|
|
124
155
|
}
|
|
125
156
|
}
|
|
126
|
-
return
|
|
127
|
-
},
|
|
128
|
-
if (t ===
|
|
157
|
+
return h();
|
|
158
|
+
}, g = (t) => {
|
|
159
|
+
if (t === r) {
|
|
129
160
|
this.reset();
|
|
130
161
|
return;
|
|
131
162
|
}
|
|
132
|
-
|
|
163
|
+
o[i] = V(t);
|
|
133
164
|
}, this.reset = () => {
|
|
134
|
-
delete
|
|
135
|
-
}, I &&
|
|
136
|
-
if (
|
|
137
|
-
let t = !1,
|
|
138
|
-
|
|
139
|
-
clearTimeout(
|
|
165
|
+
delete o[i], w(r, !0);
|
|
166
|
+
}, I && x[i] !== void 0 && console.warn("Duplicate Atom key", y), E)
|
|
167
|
+
if (C) {
|
|
168
|
+
let t = !1, u;
|
|
169
|
+
m[i] = this, x[i] = () => {
|
|
170
|
+
clearTimeout(u), u = setTimeout(() => t = !1, 10), !t && (t = !0, o[i] = V(h()));
|
|
140
171
|
};
|
|
141
172
|
} else
|
|
142
|
-
|
|
173
|
+
x[i] = (t) => {
|
|
143
174
|
if (t.newValue === null) {
|
|
144
175
|
this.reset();
|
|
145
176
|
return;
|
|
146
177
|
}
|
|
147
178
|
try {
|
|
148
|
-
|
|
179
|
+
w(F(t.newValue));
|
|
149
180
|
} catch {
|
|
150
181
|
console.warn("Invalid json value", t.newValue);
|
|
151
182
|
}
|
|
152
183
|
};
|
|
153
|
-
return
|
|
184
|
+
return a;
|
|
154
185
|
}
|
|
155
186
|
}
|
|
156
|
-
let
|
|
187
|
+
let P;
|
|
157
188
|
try {
|
|
158
|
-
|
|
159
|
-
var
|
|
160
|
-
(
|
|
189
|
+
P = new BroadcastChannel("updateHere"), P.addEventListener("message", (e) => {
|
|
190
|
+
var r;
|
|
191
|
+
(r = m[e.data.key]) == null || r.set(e.data.value, !0);
|
|
161
192
|
});
|
|
162
193
|
} catch {
|
|
163
194
|
}
|
|
164
|
-
const
|
|
165
|
-
throw `${
|
|
195
|
+
const o = window.localStorage, x = {}, m = {}, U = (e, r) => {
|
|
196
|
+
throw `${r} is readonly property`;
|
|
166
197
|
};
|
|
167
|
-
window.addEventListener("storage", (
|
|
168
|
-
var
|
|
169
|
-
|
|
198
|
+
window.addEventListener("storage", (e) => {
|
|
199
|
+
var r;
|
|
200
|
+
e.key === null || e.newValue === e.oldValue || (r = x[e.key]) == null || r.call(x, e);
|
|
170
201
|
});
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
202
|
+
const W = o.setItem.bind(o), q = o.removeItem.bind(o);
|
|
203
|
+
o.setItem = (e, r) => {
|
|
204
|
+
m[e] === void 0 && W.call(o, e, r);
|
|
174
205
|
};
|
|
175
|
-
|
|
176
|
-
|
|
206
|
+
o.removeItem = (e) => {
|
|
207
|
+
m[e] === void 0 && q.call(o, e);
|
|
177
208
|
};
|
|
178
|
-
|
|
209
|
+
const Q = /"exp":(\d+)\.2866/, L = "atom\\", N = {}, M = {};
|
|
210
|
+
setTimeout(() => {
|
|
211
|
+
Object.keys(o).forEach((e) => {
|
|
212
|
+
var l;
|
|
213
|
+
if (!e.startsWith(L) || typeof o[e] != "string") return;
|
|
214
|
+
const r = +((l = o[e].match(Q)) == null ? void 0 : l[1]);
|
|
215
|
+
r && r - Date.now() < 24 * 60 * 60 * 1e3 && (M[e] = setTimeout(() => {
|
|
216
|
+
N[e] ? N[e].reset() : delete o[e];
|
|
217
|
+
}, r - Date.now()));
|
|
218
|
+
});
|
|
219
|
+
}, 1e3);
|
|
220
|
+
let R = () => {
|
|
179
221
|
throw "call configureAtomaric() before all!";
|
|
180
222
|
};
|
|
181
|
-
const
|
|
223
|
+
const Z = (e) => R = e.useSyncExternalStore, X = (e) => R(e.subscribe, e.get), Y = (e) => e.set, k = (e) => e.setDeferred, K = (e) => e.get, O = (e) => e.do, ee = (e) => [X(e), Y(e)], te = (e, r) => new G(e, r);
|
|
182
224
|
export {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
225
|
+
G as Atom,
|
|
226
|
+
te as atom,
|
|
227
|
+
Z as configureAtomaric,
|
|
228
|
+
ee as useAtom,
|
|
229
|
+
O as useAtomDo,
|
|
230
|
+
K as useAtomGet,
|
|
231
|
+
Y as useAtomSet,
|
|
232
|
+
k as useAtomSetDeferred,
|
|
233
|
+
X as useAtomValue
|
|
192
234
|
};
|
package/build/atomaric.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(d,D){typeof exports=="object"&&typeof module<"u"?D(exports):typeof define=="function"&&define.amd?define(["exports"],D):(d=typeof globalThis<"u"?globalThis:d||self,D(d.atomaric={}))})(this,function(d){"use strict";const D=(e,r,i)=>{let g=null;typeof e=="number"?g=j(r,s=>({increment:n=>{s.set(+s.get()+(n??0))}})):typeof e=="boolean"?g=j(r,s=>({toggle:()=>{s.set(!s.get())}})):Array.isArray(e)?g=j(r,s=>({push:(...n)=>{s.set(s.get().concat(n))},unshift:(...n)=>{s.set(n.concat(s.get()))},update:n=>{const c=s.get().slice();n(c),s.set(c)},filter:n=>{s.set(s.get().filter(n??q))},toggle:(n,c)=>{const h=s.get().slice(),f=h.indexOf(n);f<0?c?h.unshift(n):h.push(n):h.splice(f,1),s.set(h)}})):e instanceof Set?g=j(r,s=>({add:n=>{s.set(new Set(s.get()).add(n))},delete:n=>{const c=new Set(s.get());c.delete(n),s.set(c)},toggle:n=>{const c=new Set(s.get());c.has(n)?c.delete(n):c.add(n),s.set(c)},clear:()=>{s.set(new Set)},update:n=>{const c=new Set(s.get());n(c),s.set(c)}})):e instanceof Object&&(g=j(r,s=>({setPartial:n=>s.set(c=>({...c,...typeof n=="function"?n(s.get()):n})),update:n=>{const c={...s.get()};n(c),s.set(c)},setDeepPartial:(n,c,h=".")=>{if(n.includes(h)){let f=n.split(h);const m=f[f.length-1];f=f.slice(0,-1);const _={...s.get()};let a=_;for(const S of f){const p=a[S];if(p==null||typeof p!="object"){s.do.setPartial({[n]:c});return}a=a[S]=Array.isArray(p)?[...p]:{...p}}a[m]=c,s.set(_)}else s.do.setPartial({[n]:c})}})));const w=typeof i=="object"&&i!=null&&"do"in i?i.do((s,n)=>r.set(s,n),()=>r.get(),r,(s,n,c)=>r.setDeferred(s,n,c)):null,b={};return w&&Object.keys(w).forEach(s=>Object.defineProperty(b,s,{get:()=>w[s]})),g&&Object.keys(g).forEach(s=>Object.defineProperty(b,s,{get:()=>g[s]})),b},q=e=>e,j=(e,r,i)=>r(e);class F{constructor(r,i){const g=t=>n=t,w=()=>n,b=new Set,s=t=>t(f());let n=r,c,h=()=>{},f=()=>w(),m=null,_=()=>{const t=D(r,a,i);return _=()=>t,t};const a=new Proxy(this,{get:(t,u)=>u==="do"?_():t[u],set:Q}),S=(t,u)=>{const A=typeof t=="function"?t(f()):t;if(!(A===f()||A===void 0||typeof A=="number"&&isNaN(A))){g(A),b.forEach(s,this);try{C.postMessage({key:l,value:w()})}catch{}u!==!0&&h(A)}};this.set=(t,u)=>S(t,u),this.get=()=>f(),this.initialValue=r,this.isInitialValue=()=>r===w(),this.subscribe=t=>(b.add(t),()=>{b.delete(t)}),this.reset=()=>{S(r,!0),b.forEach(s,this)};const p=(t,u)=>{S(t,u),c=void 0};if(this.setDeferred=(t,u=500,A,W=!0)=>{W&&c===void 0&&S(t,A),clearTimeout(c),c=setTimeout(p,u,t,A)},i==null)return a;let y=null,I=null,$=!0,N=!0,V=!1,L=-1,z=r instanceof Set?t=>new Set(t):t=>t,E=r instanceof Set?t=>{if(t instanceof Set)return Array.from(t);throw console.error(t),"The value is not Set instance"}:t=>t;if(typeof i=="string")y=i;else if("storeKey"in i)$=i.warnOnDuplicateStoreKey??$,N=i.listenStorageChanges??N,y=i.storeKey,z=i.unzipValue??z,E=i.zipValue??E,V=i.unchangable??V,I=i.exp??I;else return a;const l=`${J}${y}`,R=I===null||!(I(a,l in o)instanceof Date)?t=>JSON.stringify([E(t)]):t=>(m??(m={}),m.exp=I(a,l in o).getTime()+.2866,m.exp-Date.now()<24*60*60*1e3&&(clearTimeout(L),clearTimeout(M[l]),L=setTimeout(()=>this.reset(),m.exp-Date.now())),JSON.stringify([E(t),m])),B=t=>{const u=JSON.parse(t);return m=u[1],z(u[0])};let U=!0;if(P[l]=a,o[`atom/${y}`]&&(o[l]||(o[l]=`[${o[`atom/${y}`]}]`),delete o[`atom/${y}`]),f=()=>{if(f=w,U){U=!1;try{g(l in o?B(o[l]):r)}catch{console.warn("Invalid json value",o[l])}}return w()},h=t=>{if(t===r){this.reset();return}o[l]=R(t)},this.reset=()=>{delete o[l],S(r,!0)},$&&T[l]!==void 0&&console.warn("Duplicate Atom key",y),N)if(V){let t=!1,u;x[l]=this,T[l]=()=>{clearTimeout(u),u=setTimeout(()=>t=!1,10),!t&&(t=!0,o[l]=R(w()))}}else T[l]=t=>{if(t.newValue===null){this.reset();return}try{S(B(t.newValue))}catch{console.warn("Invalid json value",t.newValue)}};return a}}let C;try{C=new BroadcastChannel("updateHere"),C.addEventListener("message",e=>{var r;(r=x[e.data.key])==null||r.set(e.data.value,!0)})}catch{}const o=window.localStorage,T={},x={},Q=(e,r)=>{throw`${r} is readonly property`};window.addEventListener("storage",e=>{var r;e.key===null||e.newValue===e.oldValue||(r=T[e.key])==null||r.call(T,e)});const X=o.setItem.bind(o),Y=o.removeItem.bind(o);o.setItem=(e,r)=>{x[e]===void 0&&X.call(o,e,r)},o.removeItem=e=>{x[e]===void 0&&Y.call(o,e)};const Z=/"exp":(\d+)\.2866/,J="atom\\",P={},M={};setTimeout(()=>{Object.keys(o).forEach(e=>{var i;if(!e.startsWith(J)||typeof o[e]!="string")return;const r=+((i=o[e].match(Z))==null?void 0:i[1]);r&&r-Date.now()<24*60*60*1e3&&(M[e]=setTimeout(()=>{P[e]?P[e].reset():delete o[e]},r-Date.now()))})},1e3);let v=()=>{throw"call configureAtomaric() before all!"};const k=e=>v=e.useSyncExternalStore,G=e=>v(e.subscribe,e.get),H=e=>e.set,K=e=>e.setDeferred,O=e=>e.get,ee=e=>e.do,te=e=>[G(e),H(e)],se=(e,r)=>new F(e,r);d.Atom=F,d.atom=se,d.configureAtomaric=k,d.useAtom=te,d.useAtomDo=ee,d.useAtomGet=O,d.useAtomSet=H,d.useAtomSetDeferred=K,d.useAtomValue=G,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "atomaric",
|
|
3
|
-
"description": "Manage your project state",
|
|
4
|
-
"version": "0.0.
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./build/atomaric.umd.cjs",
|
|
7
|
-
"module": "./build/atomaric.js",
|
|
8
|
-
"types": "./types/model.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./types/model.d.ts",
|
|
12
|
-
"require": "./build/atomaric.umd.cjs",
|
|
13
|
-
"import": "./build/atomaric.js"
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"build",
|
|
18
|
-
"types"
|
|
19
|
-
],
|
|
20
|
-
"keywords": [
|
|
21
|
-
"react",
|
|
22
|
-
"state",
|
|
23
|
-
"manager"
|
|
24
|
-
],
|
|
25
|
-
"scripts": {
|
|
26
|
-
"start": "vite --port 8378 --host",
|
|
27
|
-
"build": "tsc && vite build",
|
|
28
|
-
"preview": "vite preview"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@types/md5": "^2.3.5",
|
|
32
|
-
"@types/node": "^22.15.1",
|
|
33
|
-
"@types/react": "^19.1.2",
|
|
34
|
-
"@types/react-dom": "^19.1.8",
|
|
35
|
-
"@vitejs/plugin-react": "^4.7.0",
|
|
36
|
-
"react": "^19.1.0",
|
|
37
|
-
"react-dom": "^19.1.1",
|
|
38
|
-
"vite": "^6.3.1",
|
|
39
|
-
"vite-plugin-eslint": "^1.8.1"
|
|
40
|
-
},
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"typescript": "~5.7.2"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "atomaric",
|
|
3
|
+
"description": "Manage your project state",
|
|
4
|
+
"version": "0.0.32",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./build/atomaric.umd.cjs",
|
|
7
|
+
"module": "./build/atomaric.js",
|
|
8
|
+
"types": "./types/model.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./types/model.d.ts",
|
|
12
|
+
"require": "./build/atomaric.umd.cjs",
|
|
13
|
+
"import": "./build/atomaric.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"build",
|
|
18
|
+
"types"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"react",
|
|
22
|
+
"state",
|
|
23
|
+
"manager"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"start": "vite --port 8378 --host",
|
|
27
|
+
"build": "tsc && vite build",
|
|
28
|
+
"preview": "vite preview"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/md5": "^2.3.5",
|
|
32
|
+
"@types/node": "^22.15.1",
|
|
33
|
+
"@types/react": "^19.1.2",
|
|
34
|
+
"@types/react-dom": "^19.1.8",
|
|
35
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
36
|
+
"react": "^19.1.0",
|
|
37
|
+
"react-dom": "^19.1.1",
|
|
38
|
+
"vite": "^6.3.1",
|
|
39
|
+
"vite-plugin-eslint": "^1.8.1"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"typescript": "~5.7.2"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/types/model.d.ts
CHANGED
|
@@ -1,149 +1,162 @@
|
|
|
1
|
-
import { useSyncExternalStore } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
unchangable
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
export type
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export type
|
|
84
|
-
/** like the
|
|
85
|
-
|
|
86
|
-
/** like the
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
:
|
|
97
|
-
|
|
98
|
-
: Value
|
|
99
|
-
|
|
100
|
-
: Value
|
|
101
|
-
|
|
102
|
-
:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
export function
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
1
|
+
import { useSyncExternalStore } from 'react';
|
|
2
|
+
import { Path, PathValue } from '../src/model';
|
|
3
|
+
|
|
4
|
+
type Sunscriber<Value> = (value: Value) => void;
|
|
5
|
+
|
|
6
|
+
export type AtomStoreKey = `${string}${string}:${string}${string}`;
|
|
7
|
+
|
|
8
|
+
export type AtomOptions<Value, Actions extends Record<string, Function> = {}> = {
|
|
9
|
+
/** **default: true** */
|
|
10
|
+
warnOnDuplicateStoreKey?: boolean;
|
|
11
|
+
/** will update value if localStorage value is changed
|
|
12
|
+
* **default: true**
|
|
13
|
+
*/
|
|
14
|
+
listenStorageChanges?: boolean;
|
|
15
|
+
|
|
16
|
+
/** zip Value to stringifiable value */
|
|
17
|
+
zipValue?: (value: Value) => any;
|
|
18
|
+
/** unzip stringifiable value to Value */
|
|
19
|
+
unzipValue?: (packedValue: any) => Value;
|
|
20
|
+
|
|
21
|
+
/** make your localStorage value unchangable */
|
|
22
|
+
unchangable?: true;
|
|
23
|
+
/** return value expire Date */
|
|
24
|
+
exp?: (self: Atom<Value>, isValueWasStoraged: boolean) => Date;
|
|
25
|
+
} & (
|
|
26
|
+
| {
|
|
27
|
+
/** save in localStorage by this key */
|
|
28
|
+
storeKey: AtomStoreKey;
|
|
29
|
+
}
|
|
30
|
+
| {
|
|
31
|
+
/** declare your custom actions */
|
|
32
|
+
do: (
|
|
33
|
+
set: (value: Value | ((value: Value) => Value), isPreventSave?: boolean) => void,
|
|
34
|
+
get: () => Value,
|
|
35
|
+
self: Atom<Value>,
|
|
36
|
+
setDeferred: (value: Value | ((value: Value) => Value), debounceMs?: number, isPreventSave?: boolean) => void,
|
|
37
|
+
) => Actions;
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export type AtomSetMethod<Value> = (value: Value | ((prev: Value) => Value), isPreventSave?: boolean) => void;
|
|
42
|
+
export type AtomSetDeferredMethod<Value> = (
|
|
43
|
+
value: Value | ((prev: Value) => Value),
|
|
44
|
+
debounceMs?: number,
|
|
45
|
+
isPreventSave?: boolean,
|
|
46
|
+
isInitInvoke?: boolean,
|
|
47
|
+
) => void;
|
|
48
|
+
|
|
49
|
+
export type AtomSubscribeMethod<Value> = (subscriber: Sunscriber<Value>) => () => void;
|
|
50
|
+
|
|
51
|
+
export type UpdateAction<Value> = {
|
|
52
|
+
/** transform current taken value */
|
|
53
|
+
update: (updater: (value: Value) => void) => void;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type NumberActions<Value> = {
|
|
57
|
+
/** pass the 2 to increment on 2, pass the -2 to decrement on 2
|
|
58
|
+
* **default: 1**
|
|
59
|
+
*/
|
|
60
|
+
increment: (delta?: number) => void;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export type ObjectActions<Value> = UpdateAction<Value> & {
|
|
64
|
+
/** pass partial object to update some field values */
|
|
65
|
+
setPartial: (value: Partial<Value> | ((value: Value) => Partial<Value>)) => void;
|
|
66
|
+
/** pass partial value to update some deep values by flat path */
|
|
67
|
+
setDeepPartial: <
|
|
68
|
+
ValuePath extends Path<Value, Sep>,
|
|
69
|
+
Val extends PathValue<Value, Sep, ValuePath>,
|
|
70
|
+
Sep extends string = '.',
|
|
71
|
+
>(
|
|
72
|
+
path: ValuePath,
|
|
73
|
+
value: Partial<Val> | ((value: Val) => Partial<Val>),
|
|
74
|
+
separator?: Sep,
|
|
75
|
+
) => void;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type BooleanActions = {
|
|
79
|
+
/** toggle current value between true/false */
|
|
80
|
+
toggle: () => void;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type SetActions<Value> = UpdateAction<Value> & {
|
|
84
|
+
/** like the Set.prototype.add() method */
|
|
85
|
+
add: (value: Value) => void;
|
|
86
|
+
/** like the Set.prototype.delete() method */
|
|
87
|
+
delete: (value: Value) => void;
|
|
88
|
+
/** will add value if it doesn't exist, otherwise delete */
|
|
89
|
+
toggle: (value: Value) => void;
|
|
90
|
+
/** like the Set.prototype.clear() method */
|
|
91
|
+
clear: () => void;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export type ArrayActions<Value> = UpdateAction<Value[]> & {
|
|
95
|
+
/** like the Array.prototype.push() method */
|
|
96
|
+
push: (...values: Value[]) => void;
|
|
97
|
+
/** like the Array.prototype.unshift() method */
|
|
98
|
+
unshift: (...values: Value[]) => void;
|
|
99
|
+
/** like the Array.prototype.filter() method, but callback is optional - (it) => !!it */
|
|
100
|
+
filter: (filter?: (value: Value, index: number, array: Value[]) => any) => void;
|
|
101
|
+
/** will add value if it doesn't exist, otherwise delete */
|
|
102
|
+
toggle: (value: Value, isAddInStart?: boolean) => void;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type DefaultActions<Value> = Value extends Set<infer Val>
|
|
106
|
+
? SetActions<Val>
|
|
107
|
+
: Value extends boolean
|
|
108
|
+
? BooleanActions
|
|
109
|
+
: Value extends (infer Val)[]
|
|
110
|
+
? ArrayActions<Val>
|
|
111
|
+
: Value extends number
|
|
112
|
+
? NumberActions<Value>
|
|
113
|
+
: Value extends object
|
|
114
|
+
? ObjectActions<Value>
|
|
115
|
+
: {};
|
|
116
|
+
|
|
117
|
+
declare class Atom<Value, Actions extends Record<string, Function> = {}> {
|
|
118
|
+
constructor(initialValue: Value, storeKeyOrOptions: StoreKeyOrOptions<Value, Actions> | undefined);
|
|
119
|
+
|
|
120
|
+
/** initial value */
|
|
121
|
+
readonly initialValue: Value;
|
|
122
|
+
/** get current value */
|
|
123
|
+
readonly get: () => Value;
|
|
124
|
+
/** set current value */
|
|
125
|
+
readonly set: AtomSetMethod<Value>;
|
|
126
|
+
/** set current value with debounce */
|
|
127
|
+
readonly setDeferred: AtomSetDeferredMethod<Value>;
|
|
128
|
+
/** set current value as default (initial) */
|
|
129
|
+
readonly reset: () => void;
|
|
130
|
+
/** subscribe on value changes */
|
|
131
|
+
readonly subscribe: AtomSubscribeMethod<Value>;
|
|
132
|
+
/** your custom actions */
|
|
133
|
+
readonly do: Actions & DefaultActions<Value>;
|
|
134
|
+
/** check is current value not changed */
|
|
135
|
+
readonly isInitialValue: () => boolean;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function useAtom<Value>(atom: Atom<Value>): [Value, AtomSetMethod<Value>];
|
|
139
|
+
|
|
140
|
+
/** observable atom value */
|
|
141
|
+
export function useAtomValue<Value>(atom: Atom<Value>): Value;
|
|
142
|
+
|
|
143
|
+
export function useAtomSet<Value>(atom: Atom<Value>): AtomSetMethod<Value>;
|
|
144
|
+
export function useAtomSetDeferred<Value>(atom: Atom<Value>): AtomSetDeferredMethod<Value>;
|
|
145
|
+
export function useAtomGet<Value>(atom: Atom<Value>): () => Value;
|
|
146
|
+
|
|
147
|
+
/** get your custom actions */
|
|
148
|
+
export function useAtomDo<Value, Actions extends Record<string, Function> = {}>(
|
|
149
|
+
atom: Atom<Value, Actions>,
|
|
150
|
+
): Actions & DefaultActions<Value>;
|
|
151
|
+
|
|
152
|
+
export type StoreKeyOrOptions<Value, Actions extends Record<string, Function> = {}> =
|
|
153
|
+
| AtomStoreKey
|
|
154
|
+
| AtomOptions<Value, Actions>;
|
|
155
|
+
|
|
156
|
+
export function atom<Value, Actions extends Record<string, Function> = {}>(
|
|
157
|
+
value: Value,
|
|
158
|
+
storeKeyOrOptions?: StoreKeyOrOptions<Value, Actions>,
|
|
159
|
+
): Atom<Value, Actions>;
|
|
160
|
+
|
|
161
|
+
/** invoke this function before all atom usages */
|
|
162
|
+
export function configureAtomaric(options: { useSyncExternalStore: typeof useSyncExternalStore }): void;
|