1 | import { atom } from 'jotai/vanilla';
|
2 |
|
3 | const RESET = Symbol();
|
4 |
|
5 | function atomWithReset(initialValue) {
|
6 | const anAtom = atom(
|
7 | initialValue,
|
8 | (get, set, update) => {
|
9 | const nextValue = typeof update === "function" ? update(get(anAtom)) : update;
|
10 | set(anAtom, nextValue === RESET ? initialValue : nextValue);
|
11 | }
|
12 | );
|
13 | return anAtom;
|
14 | }
|
15 |
|
16 | function atomWithReducer(initialValue, reducer) {
|
17 | const anAtom = atom(
|
18 | initialValue,
|
19 | (get, set, action) => set(anAtom, reducer(get(anAtom), action))
|
20 | );
|
21 | return anAtom;
|
22 | }
|
23 |
|
24 | function atomFamily(initializeAtom, areEqual) {
|
25 | let shouldRemove = null;
|
26 | const atoms = new Map();
|
27 | const createAtom = (param) => {
|
28 | let item;
|
29 | if (areEqual === void 0) {
|
30 | item = atoms.get(param);
|
31 | } else {
|
32 | for (const [key, value] of atoms) {
|
33 | if (areEqual(key, param)) {
|
34 | item = value;
|
35 | break;
|
36 | }
|
37 | }
|
38 | }
|
39 | if (item !== void 0) {
|
40 | if (shouldRemove == null ? void 0 : shouldRemove(item[1], param)) {
|
41 | createAtom.remove(param);
|
42 | } else {
|
43 | return item[0];
|
44 | }
|
45 | }
|
46 | const newAtom = initializeAtom(param);
|
47 | atoms.set(param, [newAtom, Date.now()]);
|
48 | return newAtom;
|
49 | };
|
50 | createAtom.remove = (param) => {
|
51 | if (areEqual === void 0) {
|
52 | atoms.delete(param);
|
53 | } else {
|
54 | for (const [key] of atoms) {
|
55 | if (areEqual(key, param)) {
|
56 | atoms.delete(key);
|
57 | break;
|
58 | }
|
59 | }
|
60 | }
|
61 | };
|
62 | createAtom.setShouldRemove = (fn) => {
|
63 | shouldRemove = fn;
|
64 | if (!shouldRemove)
|
65 | return;
|
66 | for (const [key, value] of atoms) {
|
67 | if (shouldRemove(value[1], key)) {
|
68 | atoms.delete(key);
|
69 | }
|
70 | }
|
71 | };
|
72 | return createAtom;
|
73 | }
|
74 |
|
75 | const getCached$2 = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
|
76 | const cache1$4 = new WeakMap();
|
77 | const memo3 = (create, dep1, dep2, dep3) => {
|
78 | const cache2 = getCached$2(() => new WeakMap(), cache1$4, dep1);
|
79 | const cache3 = getCached$2(() => new WeakMap(), cache2, dep2);
|
80 | return getCached$2(create, cache3, dep3);
|
81 | };
|
82 | function selectAtom(anAtom, selector, equalityFn = Object.is) {
|
83 | return memo3(
|
84 | () => {
|
85 | const EMPTY = Symbol();
|
86 | const selectValue = ([value, prevSlice]) => {
|
87 | const slice = selector(value);
|
88 | if (prevSlice !== EMPTY && equalityFn(prevSlice, slice)) {
|
89 | return prevSlice;
|
90 | }
|
91 | return slice;
|
92 | };
|
93 | const derivedAtom = atom((get) => {
|
94 | const prev = get(derivedAtom);
|
95 | const value = get(anAtom);
|
96 | if (value instanceof Promise || prev instanceof Promise) {
|
97 | return Promise.all([value, prev]).then(selectValue);
|
98 | }
|
99 | return selectValue([value, prev]);
|
100 | });
|
101 | derivedAtom.init = EMPTY;
|
102 | return derivedAtom;
|
103 | },
|
104 | anAtom,
|
105 | selector,
|
106 | equalityFn
|
107 | );
|
108 | }
|
109 |
|
110 | const cache1$3 = new WeakMap();
|
111 | const memo1$1 = (create, dep1) => (cache1$3.has(dep1) ? cache1$3 : cache1$3.set(dep1, create())).get(dep1);
|
112 | const deepFreeze = (obj) => {
|
113 | if (typeof obj !== "object" || obj === null)
|
114 | return;
|
115 | Object.freeze(obj);
|
116 | const propNames = Object.getOwnPropertyNames(obj);
|
117 | for (const name of propNames) {
|
118 | const value = obj[name];
|
119 | deepFreeze(value);
|
120 | }
|
121 | return obj;
|
122 | };
|
123 | function freezeAtom(anAtom) {
|
124 | return memo1$1(() => {
|
125 | const frozenAtom = atom(
|
126 | (get) => deepFreeze(get(anAtom)),
|
127 | (_get, set, arg) => set(anAtom, arg)
|
128 | );
|
129 | return frozenAtom;
|
130 | }, anAtom);
|
131 | }
|
132 | function freezeAtomCreator(createAtom) {
|
133 | return (...params) => {
|
134 | const anAtom = createAtom(...params);
|
135 | const origRead = anAtom.read;
|
136 | anAtom.read = (get, options) => deepFreeze(origRead(get, options));
|
137 | return anAtom;
|
138 | };
|
139 | }
|
140 |
|
141 | const getCached$1 = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
|
142 | const cache1$2 = /* @__PURE__ */ new WeakMap();
|
143 | const memo2$1 = (create, dep1, dep2) => {
|
144 | const cache2 = getCached$1(() => new WeakMap(), cache1$2, dep1);
|
145 | return getCached$1(create, cache2, dep2);
|
146 | };
|
147 | const cacheKeyForEmptyKeyExtractor = {};
|
148 | const isWritable = (atom2) => !!atom2.write;
|
149 | const isFunction = (x) => typeof x === "function";
|
150 | function splitAtom(arrAtom, keyExtractor) {
|
151 | return memo2$1(
|
152 | () => {
|
153 | const mappingCache = new WeakMap();
|
154 | const getMapping = (arr, prev) => {
|
155 | let mapping = mappingCache.get(arr);
|
156 | if (mapping) {
|
157 | return mapping;
|
158 | }
|
159 | const prevMapping = prev && mappingCache.get(prev);
|
160 | const atomList = [];
|
161 | const keyList = [];
|
162 | arr.forEach((item, index) => {
|
163 | const key = keyExtractor ? keyExtractor(item) : index;
|
164 | keyList[index] = key;
|
165 | const cachedAtom = prevMapping && prevMapping.atomList[prevMapping.keyList.indexOf(key)];
|
166 | if (cachedAtom) {
|
167 | atomList[index] = cachedAtom;
|
168 | return;
|
169 | }
|
170 | const read = (get) => {
|
171 | const prev2 = get(mappingAtom);
|
172 | const currArr = get(arrAtom);
|
173 | const mapping2 = getMapping(currArr, prev2 == null ? void 0 : prev2.arr);
|
174 | const index2 = mapping2.keyList.indexOf(key);
|
175 | if (index2 < 0 || index2 >= currArr.length) {
|
176 | const prevItem = arr[getMapping(arr).keyList.indexOf(key)];
|
177 | if (prevItem) {
|
178 | return prevItem;
|
179 | }
|
180 | throw new Error("splitAtom: index out of bounds for read");
|
181 | }
|
182 | return currArr[index2];
|
183 | };
|
184 | const write = (get, set, update) => {
|
185 | const prev2 = get(mappingAtom);
|
186 | const arr2 = get(arrAtom);
|
187 | const mapping2 = getMapping(arr2, prev2 == null ? void 0 : prev2.arr);
|
188 | const index2 = mapping2.keyList.indexOf(key);
|
189 | if (index2 < 0 || index2 >= arr2.length) {
|
190 | throw new Error("splitAtom: index out of bounds for write");
|
191 | }
|
192 | const nextItem = isFunction(update) ? update(arr2[index2]) : update;
|
193 | set(arrAtom, [
|
194 | ...arr2.slice(0, index2),
|
195 | nextItem,
|
196 | ...arr2.slice(index2 + 1)
|
197 | ]);
|
198 | };
|
199 | atomList[index] = isWritable(arrAtom) ? atom(read, write) : atom(read);
|
200 | });
|
201 | if (prevMapping && prevMapping.keyList.length === keyList.length && prevMapping.keyList.every((x, i) => x === keyList[i])) {
|
202 | mapping = prevMapping;
|
203 | } else {
|
204 | mapping = { arr, atomList, keyList };
|
205 | }
|
206 | mappingCache.set(arr, mapping);
|
207 | return mapping;
|
208 | };
|
209 | const mappingAtom = atom((get) => {
|
210 | const prev = get(mappingAtom);
|
211 | const arr = get(arrAtom);
|
212 | const mapping = getMapping(arr, prev == null ? void 0 : prev.arr);
|
213 | return mapping;
|
214 | });
|
215 | mappingAtom.init = void 0;
|
216 | const splittedAtom = isWritable(arrAtom) ? atom(
|
217 | (get) => get(mappingAtom).atomList,
|
218 | (get, set, action) => {
|
219 | switch (action.type) {
|
220 | case "remove": {
|
221 | const index = get(splittedAtom).indexOf(action.atom);
|
222 | if (index >= 0) {
|
223 | const arr = get(arrAtom);
|
224 | set(arrAtom, [
|
225 | ...arr.slice(0, index),
|
226 | ...arr.slice(index + 1)
|
227 | ]);
|
228 | }
|
229 | break;
|
230 | }
|
231 | case "insert": {
|
232 | const index = action.before ? get(splittedAtom).indexOf(action.before) : get(splittedAtom).length;
|
233 | if (index >= 0) {
|
234 | const arr = get(arrAtom);
|
235 | set(arrAtom, [
|
236 | ...arr.slice(0, index),
|
237 | action.value,
|
238 | ...arr.slice(index)
|
239 | ]);
|
240 | }
|
241 | break;
|
242 | }
|
243 | case "move": {
|
244 | const index1 = get(splittedAtom).indexOf(action.atom);
|
245 | const index2 = action.before ? get(splittedAtom).indexOf(action.before) : get(splittedAtom).length;
|
246 | if (index1 >= 0 && index2 >= 0) {
|
247 | const arr = get(arrAtom);
|
248 | if (index1 < index2) {
|
249 | set(arrAtom, [
|
250 | ...arr.slice(0, index1),
|
251 | ...arr.slice(index1 + 1, index2),
|
252 | arr[index1],
|
253 | ...arr.slice(index2)
|
254 | ]);
|
255 | } else {
|
256 | set(arrAtom, [
|
257 | ...arr.slice(0, index2),
|
258 | arr[index1],
|
259 | ...arr.slice(index2, index1),
|
260 | ...arr.slice(index1 + 1)
|
261 | ]);
|
262 | }
|
263 | }
|
264 | break;
|
265 | }
|
266 | }
|
267 | }
|
268 | ) : atom((get) => get(mappingAtom).atomList);
|
269 | return splittedAtom;
|
270 | },
|
271 | arrAtom,
|
272 | keyExtractor || cacheKeyForEmptyKeyExtractor
|
273 | );
|
274 | }
|
275 |
|
276 | const updateValue = (prevValue, update) => typeof update === "function" ? update(prevValue) : update;
|
277 | function atomWithDefault(getDefault) {
|
278 | const EMPTY = Symbol();
|
279 | const overwrittenAtom = atom(EMPTY);
|
280 | const anAtom = atom(
|
281 | (get, options) => {
|
282 | const overwritten = get(overwrittenAtom);
|
283 | if (overwritten !== EMPTY) {
|
284 | return overwritten;
|
285 | }
|
286 | return getDefault(get, options);
|
287 | },
|
288 | (get, set, update) => {
|
289 | if (update === RESET) {
|
290 | return set(overwrittenAtom, EMPTY);
|
291 | }
|
292 | const prevValue = get(anAtom);
|
293 | if (prevValue instanceof Promise) {
|
294 | return prevValue.then(
|
295 | (v) => set(overwrittenAtom, updateValue(v, update))
|
296 | );
|
297 | }
|
298 | return set(
|
299 | overwrittenAtom,
|
300 | updateValue(prevValue, update)
|
301 | );
|
302 | }
|
303 | );
|
304 | return anAtom;
|
305 | }
|
306 |
|
307 | const NO_STORAGE_VALUE = Symbol();
|
308 | function createJSONStorage(getStringStorage) {
|
309 | let lastStr;
|
310 | let lastValue;
|
311 | const storage = {
|
312 | getItem: (key) => {
|
313 | var _a, _b;
|
314 | const parse = (str2) => {
|
315 | str2 = str2 || "";
|
316 | if (lastStr !== str2) {
|
317 | try {
|
318 | lastValue = JSON.parse(str2);
|
319 | } catch {
|
320 | return NO_STORAGE_VALUE;
|
321 | }
|
322 | lastStr = str2;
|
323 | }
|
324 | return lastValue;
|
325 | };
|
326 | const str = (_b = (_a = getStringStorage()) == null ? void 0 : _a.getItem(key)) != null ? _b : null;
|
327 | if (str instanceof Promise) {
|
328 | return str.then(parse);
|
329 | }
|
330 | return parse(str);
|
331 | },
|
332 | setItem: (key, newValue) => {
|
333 | var _a;
|
334 | return (_a = getStringStorage()) == null ? void 0 : _a.setItem(key, JSON.stringify(newValue));
|
335 | },
|
336 | removeItem: (key) => {
|
337 | var _a;
|
338 | return (_a = getStringStorage()) == null ? void 0 : _a.removeItem(key);
|
339 | }
|
340 | };
|
341 | if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
|
342 | storage.subscribe = (key, callback) => {
|
343 | const storageEventCallback = (e) => {
|
344 | if (e.key === key && e.newValue) {
|
345 | callback(JSON.parse(e.newValue));
|
346 | }
|
347 | };
|
348 | window.addEventListener("storage", storageEventCallback);
|
349 | return () => {
|
350 | window.removeEventListener("storage", storageEventCallback);
|
351 | };
|
352 | };
|
353 | }
|
354 | return storage;
|
355 | }
|
356 | const defaultStorage = createJSONStorage(
|
357 | () => typeof window !== "undefined" ? window.localStorage : void 0
|
358 | );
|
359 | function atomWithStorage(key, initialValue, storage = defaultStorage) {
|
360 | const baseAtom = atom(initialValue);
|
361 | baseAtom.onMount = (setAtom) => {
|
362 | const value = storage.getItem(key);
|
363 | if (value instanceof Promise) {
|
364 | value.then((v) => setAtom(v === NO_STORAGE_VALUE ? initialValue : v));
|
365 | } else {
|
366 | setAtom(value === NO_STORAGE_VALUE ? initialValue : value);
|
367 | }
|
368 | let unsub;
|
369 | if (storage.subscribe) {
|
370 | unsub = storage.subscribe(key, setAtom);
|
371 | }
|
372 | return unsub;
|
373 | };
|
374 | const anAtom = atom(
|
375 | (get) => get(baseAtom),
|
376 | (get, set, update) => {
|
377 | const nextValue = typeof update === "function" ? update(get(baseAtom)) : update;
|
378 | if (nextValue === RESET) {
|
379 | set(baseAtom, initialValue);
|
380 | return storage.removeItem(key);
|
381 | }
|
382 | set(baseAtom, nextValue);
|
383 | return storage.setItem(key, nextValue);
|
384 | }
|
385 | );
|
386 | return anAtom;
|
387 | }
|
388 |
|
389 | function atomWithObservable(getObservable, options) {
|
390 | const returnResultData = (result) => {
|
391 | if ("e" in result) {
|
392 | throw result.e;
|
393 | }
|
394 | return result.d;
|
395 | };
|
396 | const observableResultAtom = atom((get) => {
|
397 | var _a;
|
398 | let observable = getObservable(get);
|
399 | const itself = (_a = observable[Symbol.observable]) == null ? void 0 : _a.call(observable);
|
400 | if (itself) {
|
401 | observable = itself;
|
402 | }
|
403 | let resolve;
|
404 | const makePending = () => new Promise((r) => {
|
405 | resolve = r;
|
406 | });
|
407 | const initialResult = options && "initialValue" in options ? {
|
408 | d: typeof options.initialValue === "function" ? options.initialValue() : options.initialValue
|
409 | } : makePending();
|
410 | let setResult;
|
411 | let lastResult;
|
412 | const listener = (result) => {
|
413 | lastResult = result;
|
414 | resolve == null ? void 0 : resolve(result);
|
415 | setResult == null ? void 0 : setResult(result);
|
416 | };
|
417 | let subscription;
|
418 | let timer;
|
419 | const isNotMounted = () => !setResult;
|
420 | const start = () => {
|
421 | if (subscription) {
|
422 | clearTimeout(timer);
|
423 | subscription.unsubscribe();
|
424 | }
|
425 | subscription = observable.subscribe({
|
426 | next: (d) => listener({ d }),
|
427 | error: (e) => listener({ e }),
|
428 | complete: () => {
|
429 | }
|
430 | });
|
431 | if (isNotMounted() && (options == null ? void 0 : options.unstable_timeout)) {
|
432 | timer = setTimeout(() => {
|
433 | if (subscription) {
|
434 | subscription.unsubscribe();
|
435 | subscription = void 0;
|
436 | }
|
437 | }, options.unstable_timeout);
|
438 | }
|
439 | };
|
440 | start();
|
441 | const resultAtom = atom(lastResult || initialResult);
|
442 | resultAtom.onMount = (update) => {
|
443 | setResult = update;
|
444 | if (lastResult) {
|
445 | update(lastResult);
|
446 | }
|
447 | if (subscription) {
|
448 | clearTimeout(timer);
|
449 | } else {
|
450 | start();
|
451 | }
|
452 | return () => {
|
453 | setResult = void 0;
|
454 | if (subscription) {
|
455 | subscription.unsubscribe();
|
456 | subscription = void 0;
|
457 | }
|
458 | };
|
459 | };
|
460 | return [resultAtom, observable, makePending, start, isNotMounted];
|
461 | });
|
462 | const observableAtom = atom(
|
463 | (get) => {
|
464 | const [resultAtom] = get(observableResultAtom);
|
465 | const result = get(resultAtom);
|
466 | if (result instanceof Promise) {
|
467 | return result.then(returnResultData);
|
468 | }
|
469 | return returnResultData(result);
|
470 | },
|
471 | (get, set, data) => {
|
472 | const [resultAtom, observable, makePending, start, isNotMounted] = get(observableResultAtom);
|
473 | if ("next" in observable) {
|
474 | if (isNotMounted()) {
|
475 | set(resultAtom, makePending());
|
476 | start();
|
477 | }
|
478 | observable.next(data);
|
479 | } else {
|
480 | throw new Error("observable is not subject");
|
481 | }
|
482 | }
|
483 | );
|
484 | return observableAtom;
|
485 | }
|
486 |
|
487 | const cache1$1 = new WeakMap();
|
488 | const memo1 = (create, dep1) => (cache1$1.has(dep1) ? cache1$1 : cache1$1.set(dep1, create())).get(dep1);
|
489 | const LOADING = { state: "loading" };
|
490 | function loadable(anAtom) {
|
491 | return memo1(() => {
|
492 | const loadableCache = new WeakMap();
|
493 | const refreshAtom = atom(0);
|
494 | const derivedAtom = atom(
|
495 | (get, { setSelf }) => {
|
496 | get(refreshAtom);
|
497 | const promise = get(anAtom);
|
498 | if (!(promise instanceof Promise)) {
|
499 | return { state: "hasData", data: promise };
|
500 | }
|
501 | const cached = loadableCache.get(promise);
|
502 | if (cached) {
|
503 | return cached;
|
504 | }
|
505 | loadableCache.set(promise, LOADING);
|
506 | promise.then(
|
507 | (data) => {
|
508 | loadableCache.set(promise, { state: "hasData", data });
|
509 | },
|
510 | (error) => {
|
511 | loadableCache.set(promise, { state: "hasError", error });
|
512 | }
|
513 | ).finally(setSelf);
|
514 | return LOADING;
|
515 | },
|
516 | (_get, set) => {
|
517 | set(refreshAtom, (c) => c + 1);
|
518 | }
|
519 | );
|
520 | return atom((get) => get(derivedAtom));
|
521 | }, anAtom);
|
522 | }
|
523 |
|
524 | const getCached = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
|
525 | const cache1 = /* @__PURE__ */ new WeakMap();
|
526 | const memo2 = (create, dep1, dep2) => {
|
527 | const cache2 = getCached(() => new WeakMap(), cache1, dep1);
|
528 | return getCached(create, cache2, dep2);
|
529 | };
|
530 | const defaultFallback = () => void 0;
|
531 | function unwrap(anAtom, fallback = defaultFallback) {
|
532 | return memo2(
|
533 | () => {
|
534 | const promiseErrorCache = new WeakMap();
|
535 | const promiseResultCache = new WeakMap();
|
536 | const refreshAtom = atom(0);
|
537 | const promiseAndValueAtom = atom(
|
538 | (get, { setSelf }) => {
|
539 | get(refreshAtom);
|
540 | const prev = get(promiseAndValueAtom);
|
541 | const promise = get(anAtom);
|
542 | if (promise === (prev == null ? void 0 : prev.p)) {
|
543 | if (promiseErrorCache.has(promise)) {
|
544 | throw promiseErrorCache.get(promise);
|
545 | }
|
546 | if (promiseResultCache.has(promise)) {
|
547 | return {
|
548 | p: promise,
|
549 | v: promiseResultCache.get(promise)
|
550 | };
|
551 | }
|
552 | }
|
553 | if (promise !== (prev == null ? void 0 : prev.p)) {
|
554 | promise.then(
|
555 | (v) => promiseResultCache.set(promise, v),
|
556 | (e) => promiseErrorCache.set(promise, e)
|
557 | ).finally(setSelf);
|
558 | }
|
559 | if (prev && "v" in prev) {
|
560 | return { p: promise, f: fallback(prev.v) };
|
561 | }
|
562 | return { p: promise, f: fallback() };
|
563 | },
|
564 | (_get, set) => {
|
565 | set(refreshAtom, (c) => c + 1);
|
566 | }
|
567 | );
|
568 | promiseAndValueAtom.init = void 0;
|
569 | return atom((get) => {
|
570 | const state = get(promiseAndValueAtom);
|
571 | if ("v" in state) {
|
572 | return state.v;
|
573 | }
|
574 | return state.f;
|
575 | });
|
576 | },
|
577 | anAtom,
|
578 | fallback
|
579 | );
|
580 | }
|
581 |
|
582 | export { RESET, atomFamily, atomWithDefault, atomWithObservable, atomWithReducer, atomWithReset, atomWithStorage, createJSONStorage, freezeAtom, freezeAtomCreator, loadable, selectAtom, splitAtom, NO_STORAGE_VALUE as unstable_NO_STORAGE_VALUE, unwrap as unstable_unwrap };
|