UNPKG

18.3 kBJavaScriptView Raw
1import { atom } from 'jotai/vanilla';
2
3const RESET = Symbol();
4
5function 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
16function 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
24function atomFamily(initializeAtom, areEqual) {
25 let shouldRemove = null;
26 const atoms = /* @__PURE__ */ 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
75const getCached$2 = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
76const cache1$4 = /* @__PURE__ */ new WeakMap();
77const memo3 = (create, dep1, dep2, dep3) => {
78 const cache2 = getCached$2(() => /* @__PURE__ */ new WeakMap(), cache1$4, dep1);
79 const cache3 = getCached$2(() => /* @__PURE__ */ new WeakMap(), cache2, dep2);
80 return getCached$2(create, cache3, dep3);
81};
82function 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
110const cache1$3 = /* @__PURE__ */ new WeakMap();
111const memo1$1 = (create, dep1) => (cache1$3.has(dep1) ? cache1$3 : cache1$3.set(dep1, create())).get(dep1);
112const 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};
123function 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}
132function 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
141const getCached$1 = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
142const cache1$2 = /* @__PURE__ */ new WeakMap();
143const memo2$1 = (create, dep1, dep2) => {
144 const cache2 = getCached$1(() => /* @__PURE__ */ new WeakMap(), cache1$2, dep1);
145 return getCached$1(create, cache2, dep2);
146};
147const cacheKeyForEmptyKeyExtractor = {};
148const isWritable = (atom2) => !!atom2.write;
149const isFunction = (x) => typeof x === "function";
150function splitAtom(arrAtom, keyExtractor) {
151 return memo2$1(
152 () => {
153 const mappingCache = /* @__PURE__ */ 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
276const updateValue = (prevValue, update) => typeof update === "function" ? update(prevValue) : update;
277function 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
307const NO_STORAGE_VALUE = Symbol();
308function 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}
356const defaultStorage = createJSONStorage(
357 () => typeof window !== "undefined" ? window.localStorage : void 0
358);
359function 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
389function 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
487const cache1$1 = /* @__PURE__ */ new WeakMap();
488const memo1 = (create, dep1) => (cache1$1.has(dep1) ? cache1$1 : cache1$1.set(dep1, create())).get(dep1);
489const LOADING = { state: "loading" };
490function loadable(anAtom) {
491 return memo1(() => {
492 const loadableCache = /* @__PURE__ */ 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
524const getCached = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
525const cache1 = /* @__PURE__ */ new WeakMap();
526const memo2 = (create, dep1, dep2) => {
527 const cache2 = getCached(() => /* @__PURE__ */ new WeakMap(), cache1, dep1);
528 return getCached(create, cache2, dep2);
529};
530const defaultFallback = () => void 0;
531function unwrap(anAtom, fallback = defaultFallback) {
532 return memo2(
533 () => {
534 const promiseErrorCache = /* @__PURE__ */ new WeakMap();
535 const promiseResultCache = /* @__PURE__ */ 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
582export { 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 };