1 | import { useContext, useCallback, useMemo } from 'react';
|
2 | import { SECRET_INTERNAL_getStoreContext, useAtom, atom } from 'jotai';
|
3 |
|
4 | function useUpdateAtom(anAtom) {
|
5 | const StoreContext = SECRET_INTERNAL_getStoreContext(anAtom.scope);
|
6 | const [, updateAtom] = useContext(StoreContext);
|
7 | const setAtom = useCallback((update) => updateAtom(anAtom, update), [updateAtom, anAtom]);
|
8 | return setAtom;
|
9 | }
|
10 |
|
11 | function useAtomValue(anAtom) {
|
12 | return useAtom(anAtom)[0];
|
13 | }
|
14 |
|
15 | const RESET = Symbol();
|
16 | function atomWithReset(initialValue) {
|
17 | const anAtom = atom(initialValue, (get, set, update) => {
|
18 | if (update === RESET) {
|
19 | set(anAtom, initialValue);
|
20 | } else {
|
21 | set(anAtom, typeof update === "function" ? update(get(anAtom)) : update);
|
22 | }
|
23 | });
|
24 | return anAtom;
|
25 | }
|
26 |
|
27 | function useResetAtom(anAtom) {
|
28 | const StoreContext = SECRET_INTERNAL_getStoreContext(anAtom.scope);
|
29 | const [, updateAtom] = useContext(StoreContext);
|
30 | const setAtom = useCallback(() => updateAtom(anAtom, RESET), [updateAtom, anAtom]);
|
31 | return setAtom;
|
32 | }
|
33 |
|
34 | function useReducerAtom(anAtom, reducer) {
|
35 | const [state, setState] = useAtom(anAtom);
|
36 | const dispatch = useCallback((action) => {
|
37 | setState((prev) => reducer(prev, action));
|
38 | }, [setState, reducer]);
|
39 | return [state, dispatch];
|
40 | }
|
41 |
|
42 | function atomWithReducer(initialValue, reducer) {
|
43 | const anAtom = atom(initialValue, (get, set, action) => set(anAtom, reducer(get(anAtom), action)));
|
44 | return anAtom;
|
45 | }
|
46 |
|
47 | function atomFamily(initializeAtom, areEqual) {
|
48 | let shouldRemove = null;
|
49 | const atoms = new Map();
|
50 | const createAtom = (param) => {
|
51 | let item;
|
52 | if (areEqual === void 0) {
|
53 | item = atoms.get(param);
|
54 | } else {
|
55 | for (let [key, value] of atoms) {
|
56 | if (areEqual(key, param)) {
|
57 | item = value;
|
58 | break;
|
59 | }
|
60 | }
|
61 | }
|
62 | if (item !== void 0) {
|
63 | if (shouldRemove == null ? void 0 : shouldRemove(item[1], param)) {
|
64 | atoms.delete(param);
|
65 | } else {
|
66 | return item[0];
|
67 | }
|
68 | }
|
69 | const newAtom = initializeAtom(param);
|
70 | atoms.set(param, [newAtom, Date.now()]);
|
71 | return newAtom;
|
72 | };
|
73 | createAtom.remove = (param) => {
|
74 | if (areEqual === void 0) {
|
75 | atoms.delete(param);
|
76 | } else {
|
77 | for (let [key] of atoms) {
|
78 | if (areEqual(key, param)) {
|
79 | atoms.delete(key);
|
80 | break;
|
81 | }
|
82 | }
|
83 | }
|
84 | };
|
85 | createAtom.setShouldRemove = (fn) => {
|
86 | shouldRemove = fn;
|
87 | if (!shouldRemove)
|
88 | return;
|
89 | for (let [key, value] of atoms) {
|
90 | if (shouldRemove(value[1], key)) {
|
91 | atoms.delete(key);
|
92 | }
|
93 | }
|
94 | };
|
95 | return createAtom;
|
96 | }
|
97 |
|
98 | const getWeakCacheItem = (cache, deps) => {
|
99 | const [dep, ...rest] = deps;
|
100 | const entry = cache.get(dep);
|
101 | if (!entry) {
|
102 | return;
|
103 | }
|
104 | if (!rest.length) {
|
105 | return entry[1];
|
106 | }
|
107 | return getWeakCacheItem(entry[0], rest);
|
108 | };
|
109 | const setWeakCacheItem = (cache, deps, item) => {
|
110 | const [dep, ...rest] = deps;
|
111 | let entry = cache.get(dep);
|
112 | if (!entry) {
|
113 | entry = [new WeakMap()];
|
114 | cache.set(dep, entry);
|
115 | }
|
116 | if (!rest.length) {
|
117 | entry[1] = item;
|
118 | return;
|
119 | }
|
120 | setWeakCacheItem(entry[0], rest, item);
|
121 | };
|
122 |
|
123 | const selectAtomCache = new WeakMap();
|
124 | function selectAtom(anAtom, selector, equalityFn = Object.is) {
|
125 | const deps = [anAtom, selector, equalityFn];
|
126 | const cachedAtom = getWeakCacheItem(selectAtomCache, deps);
|
127 | if (cachedAtom) {
|
128 | return cachedAtom;
|
129 | }
|
130 | let initialized = false;
|
131 | let prevSlice;
|
132 | const derivedAtom = atom((get) => {
|
133 | const slice = selector(get(anAtom));
|
134 | if (initialized && equalityFn(prevSlice, slice)) {
|
135 | return prevSlice;
|
136 | }
|
137 | initialized = true;
|
138 | prevSlice = slice;
|
139 | return slice;
|
140 | });
|
141 | derivedAtom.scope = anAtom.scope;
|
142 | setWeakCacheItem(selectAtomCache, deps, derivedAtom);
|
143 | return derivedAtom;
|
144 | }
|
145 |
|
146 | function useAtomCallback(callback, scope) {
|
147 | const anAtom = useMemo(() => atom(null, (get, set, [arg, resolve, reject]) => {
|
148 | try {
|
149 | resolve(callback(get, set, arg));
|
150 | } catch (e) {
|
151 | reject(e);
|
152 | }
|
153 | }), [callback]);
|
154 | anAtom.scope = scope;
|
155 | const [, invoke] = useAtom(anAtom);
|
156 | return useCallback((arg) => new Promise((resolve, reject) => {
|
157 | invoke([arg, resolve, reject]);
|
158 | }), [invoke]);
|
159 | }
|
160 |
|
161 | const freezeAtomCache = new WeakMap();
|
162 | const deepFreeze = (obj) => {
|
163 | if (typeof obj !== "object" || obj === null)
|
164 | return;
|
165 | Object.freeze(obj);
|
166 | const propNames = Object.getOwnPropertyNames(obj);
|
167 | for (const name of propNames) {
|
168 | const value = obj[name];
|
169 | deepFreeze(value);
|
170 | }
|
171 | return obj;
|
172 | };
|
173 | function freezeAtom(anAtom) {
|
174 | const deps = [anAtom];
|
175 | const cachedAtom = getWeakCacheItem(freezeAtomCache, deps);
|
176 | if (cachedAtom) {
|
177 | return cachedAtom;
|
178 | }
|
179 | const frozenAtom = atom((get) => deepFreeze(get(anAtom)), (_get, set, arg) => set(anAtom, arg));
|
180 | frozenAtom.scope = anAtom.scope;
|
181 | setWeakCacheItem(freezeAtomCache, deps, frozenAtom);
|
182 | return frozenAtom;
|
183 | }
|
184 | function freezeAtomCreator(createAtom) {
|
185 | return (...params) => {
|
186 | const anAtom = createAtom(...params);
|
187 | const origRead = anAtom.read;
|
188 | anAtom.read = (get) => deepFreeze(origRead(get));
|
189 | return anAtom;
|
190 | };
|
191 | }
|
192 |
|
193 | const splitAtomCache = new WeakMap();
|
194 | const isWritable = (atom2) => !!atom2.write;
|
195 | const isFunction = (x) => typeof x === "function";
|
196 | function splitAtom(arrAtom, keyExtractor) {
|
197 | const deps = keyExtractor ? [arrAtom, keyExtractor] : [arrAtom];
|
198 | const cachedAtom = getWeakCacheItem(splitAtomCache, deps);
|
199 | if (cachedAtom) {
|
200 | return cachedAtom;
|
201 | }
|
202 | let currentAtomList;
|
203 | let currentKeyList;
|
204 | const keyToAtom = (key) => {
|
205 | const index = currentKeyList == null ? void 0 : currentKeyList.indexOf(key);
|
206 | if (index === void 0 || index === -1) {
|
207 | return void 0;
|
208 | }
|
209 | return currentAtomList == null ? void 0 : currentAtomList[index];
|
210 | };
|
211 | const read = (get) => {
|
212 | let nextAtomList = [];
|
213 | let nextKeyList = [];
|
214 | get(arrAtom).forEach((item, index) => {
|
215 | const key = keyExtractor ? keyExtractor(item) : index;
|
216 | nextKeyList[index] = key;
|
217 | const cachedAtom2 = keyToAtom(key);
|
218 | if (cachedAtom2) {
|
219 | nextAtomList[index] = cachedAtom2;
|
220 | return;
|
221 | }
|
222 | const read2 = (get2) => {
|
223 | const index2 = currentKeyList == null ? void 0 : currentKeyList.indexOf(key);
|
224 | if (index2 === void 0 || index2 === -1) {
|
225 | throw new Error("index not found");
|
226 | }
|
227 | return get2(arrAtom)[index2];
|
228 | };
|
229 | const write2 = (get2, set, update) => {
|
230 | const index2 = currentKeyList == null ? void 0 : currentKeyList.indexOf(key);
|
231 | if (index2 === void 0 || index2 === -1) {
|
232 | throw new Error("index not found");
|
233 | }
|
234 | const prev = get2(arrAtom);
|
235 | const nextItem = isFunction(update) ? update(prev[index2]) : update;
|
236 | set(arrAtom, [
|
237 | ...prev.slice(0, index2),
|
238 | nextItem,
|
239 | ...prev.slice(index2 + 1)
|
240 | ]);
|
241 | };
|
242 | const itemAtom = isWritable(arrAtom) ? atom(read2, write2) : atom(read2);
|
243 | itemAtom.scope = arrAtom.scope;
|
244 | nextAtomList[index] = itemAtom;
|
245 | });
|
246 | currentKeyList = nextKeyList;
|
247 | if (currentAtomList && currentAtomList.length === nextAtomList.length && currentAtomList.every((x, i) => x === nextAtomList[i])) {
|
248 | return currentAtomList;
|
249 | }
|
250 | return currentAtomList = nextAtomList;
|
251 | };
|
252 | const write = (get, set, atomToRemove) => {
|
253 | const index = get(splittedAtom).indexOf(atomToRemove);
|
254 | if (index >= 0) {
|
255 | const prev = get(arrAtom);
|
256 | set(arrAtom, [
|
257 | ...prev.slice(0, index),
|
258 | ...prev.slice(index + 1)
|
259 | ]);
|
260 | }
|
261 | };
|
262 | const splittedAtom = isWritable(arrAtom) ? atom(read, write) : atom(read);
|
263 | splittedAtom.scope = arrAtom.scope;
|
264 | setWeakCacheItem(splitAtomCache, deps, splittedAtom);
|
265 | return splittedAtom;
|
266 | }
|
267 |
|
268 | function atomWithDefault(getDefault) {
|
269 | const EMPTY = Symbol();
|
270 | const overwrittenAtom = atom(EMPTY);
|
271 | const anAtom = atom((get) => {
|
272 | const overwritten = get(overwrittenAtom);
|
273 | if (overwritten !== EMPTY) {
|
274 | return overwritten;
|
275 | }
|
276 | return getDefault(get);
|
277 | }, (get, set, update) => set(overwrittenAtom, typeof update === "function" ? update(get(anAtom)) : update));
|
278 | return anAtom;
|
279 | }
|
280 |
|
281 | var __defProp = Object.defineProperty;
|
282 | var __defProps = Object.defineProperties;
|
283 | var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
284 | var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
285 | var __hasOwnProp = Object.prototype.hasOwnProperty;
|
286 | var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
287 | var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value;
|
288 | var __spreadValues = (a, b) => {
|
289 | for (var prop in b || (b = {}))
|
290 | if (__hasOwnProp.call(b, prop))
|
291 | __defNormalProp(a, prop, b[prop]);
|
292 | if (__getOwnPropSymbols)
|
293 | for (var prop of __getOwnPropSymbols(b)) {
|
294 | if (__propIsEnum.call(b, prop))
|
295 | __defNormalProp(a, prop, b[prop]);
|
296 | }
|
297 | return a;
|
298 | };
|
299 | var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
300 | const waitForAllCache = new WeakMap();
|
301 | function waitForAll(atoms) {
|
302 | const cachedAtom = Array.isArray(atoms) && getWeakCacheItem(waitForAllCache, atoms);
|
303 | if (cachedAtom) {
|
304 | return cachedAtom;
|
305 | }
|
306 | const unwrappedAtoms = unwrapAtoms(atoms);
|
307 | const derivedAtom = atom((get) => {
|
308 | const promises = [];
|
309 | const values = unwrappedAtoms.map((anAtom, index) => {
|
310 | try {
|
311 | return get(anAtom);
|
312 | } catch (e) {
|
313 | if (e instanceof Promise) {
|
314 | promises[index] = e;
|
315 | } else {
|
316 | throw e;
|
317 | }
|
318 | }
|
319 | });
|
320 | if (promises.length) {
|
321 | throw Promise.all(promises);
|
322 | }
|
323 | return wrapResults(atoms, values);
|
324 | });
|
325 | const waitForAllScope = unwrappedAtoms[0].scope;
|
326 | derivedAtom.scope = waitForAllScope;
|
327 | validateAtomScopes(waitForAllScope, unwrappedAtoms);
|
328 | if (Array.isArray(atoms)) {
|
329 | setWeakCacheItem(waitForAllCache, atoms, derivedAtom);
|
330 | }
|
331 | return derivedAtom;
|
332 | }
|
333 | const unwrapAtoms = (atoms) => Array.isArray(atoms) ? atoms : Object.getOwnPropertyNames(atoms).map((key) => atoms[key]);
|
334 | const wrapResults = (atoms, results) => Array.isArray(atoms) ? results : Object.getOwnPropertyNames(atoms).reduce((out, key, idx) => __spreadProps(__spreadValues({}, out), {[key]: results[idx]}), {});
|
335 | function validateAtomScopes(scope, atoms) {
|
336 | if (scope && !atoms.every((a) => a.scope === scope)) {
|
337 | console.warn("Different scopes were found for atoms supplied to waitForAll. This is unsupported and will result in unexpected behavior.");
|
338 | }
|
339 | }
|
340 |
|
341 | function atomWithHash(key, initialValue, serialize = JSON.stringify, deserialize = JSON.parse) {
|
342 | const anAtom = atom(initialValue, (get, set, update) => {
|
343 | const newValue = typeof update === "function" ? update(get(anAtom)) : update;
|
344 | set(anAtom, newValue);
|
345 | const searchParams = new URLSearchParams(location.hash.slice(1));
|
346 | searchParams.set(key, serialize(newValue));
|
347 | location.hash = searchParams.toString();
|
348 | });
|
349 | anAtom.onMount = (setAtom) => {
|
350 | const callback = () => {
|
351 | const searchParams = new URLSearchParams(location.hash.slice(1));
|
352 | const str = searchParams.get(key);
|
353 | if (str !== null) {
|
354 | setAtom(deserialize(str));
|
355 | }
|
356 | };
|
357 | window.addEventListener("hashchange", callback);
|
358 | callback();
|
359 | return () => {
|
360 | window.removeEventListener("hashchange", callback);
|
361 | };
|
362 | };
|
363 | return anAtom;
|
364 | }
|
365 |
|
366 | const defaultStorage = {
|
367 | getItem: (key) => {
|
368 | const storedValue = localStorage.getItem(key);
|
369 | if (storedValue === null) {
|
370 | throw new Error("no value stored");
|
371 | }
|
372 | return JSON.parse(storedValue);
|
373 | },
|
374 | setItem: (key, newValue) => {
|
375 | localStorage.setItem(key, JSON.stringify(newValue));
|
376 | }
|
377 | };
|
378 | function atomWithStorage(key, initialValue, storage = defaultStorage) {
|
379 | const getInitialValue = () => {
|
380 | try {
|
381 | return storage.getItem(key);
|
382 | } catch {
|
383 | return initialValue;
|
384 | }
|
385 | };
|
386 | const baseAtom = atom(initialValue);
|
387 | baseAtom.onMount = (setAtom) => {
|
388 | const value = getInitialValue();
|
389 | if (value instanceof Promise) {
|
390 | value.then(setAtom);
|
391 | } else {
|
392 | setAtom(value);
|
393 | }
|
394 | };
|
395 | const anAtom = atom((get) => get(baseAtom), (get, set, update) => {
|
396 | const newValue = typeof update === "function" ? update(get(baseAtom)) : update;
|
397 | set(baseAtom, newValue);
|
398 | storage.setItem(key, newValue);
|
399 | });
|
400 | return anAtom;
|
401 | }
|
402 |
|
403 | export { RESET, atomFamily, atomWithDefault, atomWithHash, atomWithReducer, atomWithReset, atomWithStorage, freezeAtom, freezeAtomCreator, selectAtom, splitAtom, useAtomCallback, useAtomValue, useReducerAtom, useResetAtom, useUpdateAtom, waitForAll };
|