UNPKG

27.1 kBJavaScriptView Raw
1import { createContext, useState, useEffect, useRef, createElement, useContext, useReducer, useDebugValue, useCallback } from 'react';
2import { atom as atom$1 } from 'jotai/vanilla';
3
4const SUSPENSE_PROMISE = Symbol();
5const isSuspensePromise = (promise) => !!promise[SUSPENSE_PROMISE];
6const isSuspensePromiseAlreadyCancelled = (suspensePromise) => !suspensePromise[SUSPENSE_PROMISE].c;
7const cancelSuspensePromise = (suspensePromise) => {
8 var _a;
9 const { b: basePromise, c: cancelPromise } = suspensePromise[SUSPENSE_PROMISE];
10 if (cancelPromise) {
11 cancelPromise();
12 (_a = promiseAbortMap.get(basePromise)) == null ? void 0 : _a();
13 }
14};
15const isEqualSuspensePromise = (oldSuspensePromise, newSuspensePromise) => {
16 const oldOriginalPromise = oldSuspensePromise[SUSPENSE_PROMISE].o;
17 const newOriginalPromise = newSuspensePromise[SUSPENSE_PROMISE].o;
18 return oldOriginalPromise === newOriginalPromise || oldSuspensePromise === newOriginalPromise || isSuspensePromise(oldOriginalPromise) && isEqualSuspensePromise(oldOriginalPromise, newSuspensePromise);
19};
20const createSuspensePromise = (basePromise, promise) => {
21 const suspensePromiseExtra = {
22 b: basePromise,
23 o: promise,
24 c: null
25 };
26 const suspensePromise = new Promise((resolve) => {
27 suspensePromiseExtra.c = () => {
28 suspensePromiseExtra.c = null;
29 resolve();
30 };
31 promise.finally(suspensePromiseExtra.c);
32 });
33 suspensePromise[SUSPENSE_PROMISE] = suspensePromiseExtra;
34 return suspensePromise;
35};
36const copySuspensePromise = (suspensePromise) => createSuspensePromise(
37 suspensePromise[SUSPENSE_PROMISE].b,
38 suspensePromise[SUSPENSE_PROMISE].o
39);
40const promiseAbortMap = /* @__PURE__ */ new WeakMap();
41const registerPromiseAbort = (basePromise, abort) => {
42 promiseAbortMap.set(basePromise, abort);
43};
44
45const hasInitialValue = (atom) => "init" in atom;
46const READ_ATOM = "r";
47const WRITE_ATOM = "w";
48const COMMIT_ATOM = "c";
49const SUBSCRIBE_ATOM = "s";
50const RESTORE_ATOMS = "h";
51const DEV_SUBSCRIBE_STATE = "n";
52const DEV_GET_MOUNTED_ATOMS = "l";
53const DEV_GET_ATOM_STATE = "a";
54const DEV_GET_MOUNTED = "m";
55const createStore = (initialValues) => {
56 const committedAtomStateMap = /* @__PURE__ */ new WeakMap();
57 const mountedMap = /* @__PURE__ */ new WeakMap();
58 const pendingMap = /* @__PURE__ */ new Map();
59 let stateListeners;
60 let mountedAtoms;
61 if (process.env.NODE_ENV !== "production") {
62 stateListeners = /* @__PURE__ */ new Set();
63 mountedAtoms = /* @__PURE__ */ new Set();
64 }
65 if (initialValues) {
66 for (const [atom, value] of initialValues) {
67 const atomState = {
68 v: value,
69 r: 0,
70 y: true,
71 d: /* @__PURE__ */ new Map()
72 };
73 if (process.env.NODE_ENV !== "production") {
74 Object.freeze(atomState);
75 if (!hasInitialValue(atom)) {
76 console.warn(
77 "Found initial value for derived atom which can cause unexpected behavior",
78 atom
79 );
80 }
81 }
82 committedAtomStateMap.set(atom, atomState);
83 }
84 }
85 const suspensePromiseCacheMap = /* @__PURE__ */ new WeakMap();
86 const addSuspensePromiseToCache = (version, atom, suspensePromise) => {
87 let cache = suspensePromiseCacheMap.get(atom);
88 if (!cache) {
89 cache = /* @__PURE__ */ new Map();
90 suspensePromiseCacheMap.set(atom, cache);
91 }
92 suspensePromise.then(() => {
93 if (cache.get(version) === suspensePromise) {
94 cache.delete(version);
95 if (!cache.size) {
96 suspensePromiseCacheMap.delete(atom);
97 }
98 }
99 });
100 cache.set(version, suspensePromise);
101 };
102 const cancelAllSuspensePromiseInCache = (atom) => {
103 const versionSet = /* @__PURE__ */ new Set();
104 const cache = suspensePromiseCacheMap.get(atom);
105 if (cache) {
106 suspensePromiseCacheMap.delete(atom);
107 cache.forEach((suspensePromise, version) => {
108 cancelSuspensePromise(suspensePromise);
109 versionSet.add(version);
110 });
111 }
112 return versionSet;
113 };
114 const versionedAtomStateMapMap = /* @__PURE__ */ new WeakMap();
115 const getVersionedAtomStateMap = (version) => {
116 let versionedAtomStateMap = versionedAtomStateMapMap.get(version);
117 if (!versionedAtomStateMap) {
118 versionedAtomStateMap = /* @__PURE__ */ new Map();
119 versionedAtomStateMapMap.set(version, versionedAtomStateMap);
120 }
121 return versionedAtomStateMap;
122 };
123 const getAtomState = (version, atom) => {
124 if (version) {
125 const versionedAtomStateMap = getVersionedAtomStateMap(version);
126 let atomState = versionedAtomStateMap.get(atom);
127 if (!atomState) {
128 atomState = getAtomState(version.p, atom);
129 if (atomState && "p" in atomState && isSuspensePromiseAlreadyCancelled(atomState.p)) {
130 atomState = void 0;
131 }
132 if (atomState) {
133 versionedAtomStateMap.set(atom, atomState);
134 }
135 }
136 return atomState;
137 }
138 return committedAtomStateMap.get(atom);
139 };
140 const setAtomState = (version, atom, atomState) => {
141 if (process.env.NODE_ENV !== "production") {
142 Object.freeze(atomState);
143 }
144 if (version) {
145 const versionedAtomStateMap = getVersionedAtomStateMap(version);
146 versionedAtomStateMap.set(atom, atomState);
147 } else {
148 const prevAtomState = committedAtomStateMap.get(atom);
149 committedAtomStateMap.set(atom, atomState);
150 if (!pendingMap.has(atom)) {
151 pendingMap.set(atom, prevAtomState);
152 }
153 }
154 };
155 const createReadDependencies = (version, prevReadDependencies = /* @__PURE__ */ new Map(), dependencies) => {
156 if (!dependencies) {
157 return prevReadDependencies;
158 }
159 const readDependencies = /* @__PURE__ */ new Map();
160 let changed = false;
161 dependencies.forEach((atom) => {
162 var _a;
163 const revision = ((_a = getAtomState(version, atom)) == null ? void 0 : _a.r) || 0;
164 readDependencies.set(atom, revision);
165 if (prevReadDependencies.get(atom) !== revision) {
166 changed = true;
167 }
168 });
169 if (prevReadDependencies.size === readDependencies.size && !changed) {
170 return prevReadDependencies;
171 }
172 return readDependencies;
173 };
174 const setAtomValue = (version, atom, value, dependencies, suspensePromise) => {
175 const atomState = getAtomState(version, atom);
176 if (atomState) {
177 if (suspensePromise && (!("p" in atomState) || !isEqualSuspensePromise(atomState.p, suspensePromise))) {
178 return atomState;
179 }
180 if ("p" in atomState) {
181 cancelSuspensePromise(atomState.p);
182 }
183 }
184 const nextAtomState = {
185 v: value,
186 r: (atomState == null ? void 0 : atomState.r) || 0,
187 y: true,
188 d: createReadDependencies(version, atomState == null ? void 0 : atomState.d, dependencies)
189 };
190 let changed = !(atomState == null ? void 0 : atomState.y);
191 if (!atomState || !("v" in atomState) || !Object.is(atomState.v, value)) {
192 changed = true;
193 ++nextAtomState.r;
194 if (nextAtomState.d.has(atom)) {
195 nextAtomState.d = new Map(nextAtomState.d).set(atom, nextAtomState.r);
196 }
197 } else if (nextAtomState.d !== atomState.d && (nextAtomState.d.size !== atomState.d.size || !Array.from(nextAtomState.d.keys()).every((a) => atomState.d.has(a)))) {
198 changed = true;
199 Promise.resolve().then(() => {
200 flushPending(version);
201 });
202 }
203 if (atomState && !changed) {
204 return atomState;
205 }
206 setAtomState(version, atom, nextAtomState);
207 return nextAtomState;
208 };
209 const setAtomReadError = (version, atom, error, dependencies, suspensePromise) => {
210 const atomState = getAtomState(version, atom);
211 if (atomState) {
212 if (suspensePromise && (!("p" in atomState) || !isEqualSuspensePromise(atomState.p, suspensePromise))) {
213 return atomState;
214 }
215 if ("p" in atomState) {
216 cancelSuspensePromise(atomState.p);
217 }
218 }
219 const nextAtomState = {
220 e: error,
221 r: ((atomState == null ? void 0 : atomState.r) || 0) + 1,
222 y: true,
223 d: createReadDependencies(version, atomState == null ? void 0 : atomState.d, dependencies)
224 };
225 setAtomState(version, atom, nextAtomState);
226 return nextAtomState;
227 };
228 const setAtomSuspensePromise = (version, atom, suspensePromise, dependencies) => {
229 const atomState = getAtomState(version, atom);
230 if (atomState && "p" in atomState) {
231 if (isEqualSuspensePromise(atomState.p, suspensePromise) && !isSuspensePromiseAlreadyCancelled(atomState.p)) {
232 if (!atomState.y) {
233 return { ...atomState, y: true };
234 }
235 return atomState;
236 }
237 cancelSuspensePromise(atomState.p);
238 }
239 addSuspensePromiseToCache(version, atom, suspensePromise);
240 const nextAtomState = {
241 p: suspensePromise,
242 r: ((atomState == null ? void 0 : atomState.r) || 0) + 1,
243 y: true,
244 d: createReadDependencies(version, atomState == null ? void 0 : atomState.d, dependencies)
245 };
246 setAtomState(version, atom, nextAtomState);
247 return nextAtomState;
248 };
249 const setAtomPromiseOrValue = (version, atom, promiseOrValue, dependencies) => {
250 if (promiseOrValue instanceof Promise) {
251 const suspensePromise = createSuspensePromise(
252 promiseOrValue,
253 promiseOrValue.then((value) => {
254 setAtomValue(version, atom, value, dependencies, suspensePromise);
255 }).catch((e) => {
256 if (e instanceof Promise) {
257 if (isSuspensePromise(e)) {
258 return e.then(() => {
259 readAtomState(version, atom, true);
260 });
261 }
262 return e;
263 }
264 setAtomReadError(version, atom, e, dependencies, suspensePromise);
265 })
266 );
267 return setAtomSuspensePromise(
268 version,
269 atom,
270 suspensePromise,
271 dependencies
272 );
273 }
274 return setAtomValue(
275 version,
276 atom,
277 promiseOrValue,
278 dependencies
279 );
280 };
281 const setAtomInvalidated = (version, atom) => {
282 const atomState = getAtomState(version, atom);
283 if (atomState) {
284 const nextAtomState = {
285 ...atomState,
286 y: false
287 };
288 setAtomState(version, atom, nextAtomState);
289 } else if (process.env.NODE_ENV !== "production") {
290 console.warn("[Bug] could not invalidate non existing atom", atom);
291 }
292 };
293 const readAtomState = (version, atom, force) => {
294 if (!force) {
295 const atomState = getAtomState(version, atom);
296 if (atomState) {
297 if (atomState.y && "p" in atomState && !isSuspensePromiseAlreadyCancelled(atomState.p)) {
298 return atomState;
299 }
300 atomState.d.forEach((_, a) => {
301 if (a !== atom) {
302 if (!mountedMap.has(a)) {
303 readAtomState(version, a);
304 } else {
305 const aState = getAtomState(version, a);
306 if (aState && !aState.y) {
307 readAtomState(version, a);
308 }
309 }
310 }
311 });
312 if (Array.from(atomState.d).every(([a, r]) => {
313 const aState = getAtomState(version, a);
314 return aState && !("p" in aState) && aState.r === r;
315 })) {
316 if (!atomState.y) {
317 return { ...atomState, y: true };
318 }
319 return atomState;
320 }
321 }
322 }
323 const dependencies = /* @__PURE__ */ new Set();
324 try {
325 const promiseOrValue = atom.read((a) => {
326 dependencies.add(a);
327 const aState = a === atom ? getAtomState(version, a) : readAtomState(version, a);
328 if (aState) {
329 if ("e" in aState) {
330 throw aState.e;
331 }
332 if ("p" in aState) {
333 throw aState.p;
334 }
335 return aState.v;
336 }
337 if (hasInitialValue(a)) {
338 return a.init;
339 }
340 throw new Error("no atom init");
341 });
342 return setAtomPromiseOrValue(version, atom, promiseOrValue, dependencies);
343 } catch (errorOrPromise) {
344 if (errorOrPromise instanceof Promise) {
345 const suspensePromise = isSuspensePromise(errorOrPromise) && isSuspensePromiseAlreadyCancelled(errorOrPromise) ? copySuspensePromise(errorOrPromise) : createSuspensePromise(errorOrPromise, errorOrPromise);
346 return setAtomSuspensePromise(
347 version,
348 atom,
349 suspensePromise,
350 dependencies
351 );
352 }
353 return setAtomReadError(version, atom, errorOrPromise, dependencies);
354 }
355 };
356 const readAtom = (readingAtom, version) => {
357 const atomState = readAtomState(version, readingAtom);
358 return atomState;
359 };
360 const addAtom = (version, addingAtom) => {
361 let mounted = mountedMap.get(addingAtom);
362 if (!mounted) {
363 mounted = mountAtom(version, addingAtom);
364 }
365 return mounted;
366 };
367 const canUnmountAtom = (atom, mounted) => !mounted.l.size && (!mounted.t.size || mounted.t.size === 1 && mounted.t.has(atom));
368 const delAtom = (version, deletingAtom) => {
369 const mounted = mountedMap.get(deletingAtom);
370 if (mounted && canUnmountAtom(deletingAtom, mounted)) {
371 unmountAtom(version, deletingAtom);
372 }
373 };
374 const invalidateDependents = (version, atom) => {
375 const mounted = mountedMap.get(atom);
376 mounted == null ? void 0 : mounted.t.forEach((dependent) => {
377 if (dependent !== atom) {
378 setAtomInvalidated(version, dependent);
379 invalidateDependents(version, dependent);
380 }
381 });
382 };
383 const writeAtomState = (version, atom, update) => {
384 let isSync = true;
385 const writeGetter = (a, options) => {
386 const aState = readAtomState(version, a);
387 if ("e" in aState) {
388 throw aState.e;
389 }
390 if ("p" in aState) {
391 if (options == null ? void 0 : options.unstable_promise) {
392 return aState.p.then(() => {
393 const s = getAtomState(version, a);
394 if (s && "p" in s && s.p === aState.p) {
395 return new Promise((resolve) => setTimeout(resolve)).then(
396 () => writeGetter(a, options)
397 );
398 }
399 return writeGetter(a, options);
400 });
401 }
402 if (process.env.NODE_ENV !== "production") {
403 console.info(
404 "Reading pending atom state in write operation. We throw a promise for now.",
405 a
406 );
407 }
408 throw aState.p;
409 }
410 if ("v" in aState) {
411 return aState.v;
412 }
413 if (process.env.NODE_ENV !== "production") {
414 console.warn(
415 "[Bug] no value found while reading atom in write operation. This is probably a bug.",
416 a
417 );
418 }
419 throw new Error("no value found");
420 };
421 const setter = (a, v) => {
422 let promiseOrVoid2;
423 if (a === atom) {
424 if (!hasInitialValue(a)) {
425 throw new Error("atom not writable");
426 }
427 const versionSet = cancelAllSuspensePromiseInCache(a);
428 versionSet.forEach((cancelledVersion) => {
429 if (cancelledVersion !== version) {
430 setAtomPromiseOrValue(cancelledVersion, a, v);
431 }
432 });
433 const prevAtomState = getAtomState(version, a);
434 const nextAtomState = setAtomPromiseOrValue(version, a, v);
435 if (prevAtomState !== nextAtomState) {
436 invalidateDependents(version, a);
437 }
438 } else {
439 promiseOrVoid2 = writeAtomState(version, a, v);
440 }
441 if (!isSync) {
442 flushPending(version);
443 }
444 return promiseOrVoid2;
445 };
446 const promiseOrVoid = atom.write(writeGetter, setter, update);
447 isSync = false;
448 return promiseOrVoid;
449 };
450 const writeAtom = (writingAtom, update, version) => {
451 const promiseOrVoid = writeAtomState(version, writingAtom, update);
452 flushPending(version);
453 return promiseOrVoid;
454 };
455 const isActuallyWritableAtom = (atom) => !!atom.write;
456 const mountAtom = (version, atom, initialDependent) => {
457 const mounted = {
458 t: new Set(initialDependent && [initialDependent]),
459 l: /* @__PURE__ */ new Set()
460 };
461 mountedMap.set(atom, mounted);
462 if (process.env.NODE_ENV !== "production") {
463 mountedAtoms.add(atom);
464 }
465 const atomState = readAtomState(void 0, atom);
466 atomState.d.forEach((_, a) => {
467 const aMounted = mountedMap.get(a);
468 if (aMounted) {
469 aMounted.t.add(atom);
470 } else {
471 if (a !== atom) {
472 mountAtom(version, a, atom);
473 }
474 }
475 });
476 if (isActuallyWritableAtom(atom) && atom.onMount) {
477 const setAtom = (update) => writeAtom(atom, update, version);
478 const onUnmount = atom.onMount(setAtom);
479 version = void 0;
480 if (onUnmount) {
481 mounted.u = onUnmount;
482 }
483 }
484 return mounted;
485 };
486 const unmountAtom = (version, atom) => {
487 var _a;
488 const onUnmount = (_a = mountedMap.get(atom)) == null ? void 0 : _a.u;
489 if (onUnmount) {
490 onUnmount();
491 }
492 mountedMap.delete(atom);
493 if (process.env.NODE_ENV !== "production") {
494 mountedAtoms.delete(atom);
495 }
496 const atomState = getAtomState(version, atom);
497 if (atomState) {
498 if ("p" in atomState) {
499 cancelSuspensePromise(atomState.p);
500 }
501 atomState.d.forEach((_, a) => {
502 if (a !== atom) {
503 const mounted = mountedMap.get(a);
504 if (mounted) {
505 mounted.t.delete(atom);
506 if (canUnmountAtom(a, mounted)) {
507 unmountAtom(version, a);
508 }
509 }
510 }
511 });
512 } else if (process.env.NODE_ENV !== "production") {
513 console.warn("[Bug] could not find atom state to unmount", atom);
514 }
515 };
516 const mountDependencies = (version, atom, atomState, prevReadDependencies) => {
517 const dependencies = new Set(atomState.d.keys());
518 prevReadDependencies == null ? void 0 : prevReadDependencies.forEach((_, a) => {
519 if (dependencies.has(a)) {
520 dependencies.delete(a);
521 return;
522 }
523 const mounted = mountedMap.get(a);
524 if (mounted) {
525 mounted.t.delete(atom);
526 if (canUnmountAtom(a, mounted)) {
527 unmountAtom(version, a);
528 }
529 }
530 });
531 dependencies.forEach((a) => {
532 const mounted = mountedMap.get(a);
533 if (mounted) {
534 mounted.t.add(atom);
535 } else if (mountedMap.has(atom)) {
536 mountAtom(version, a, atom);
537 }
538 });
539 };
540 const flushPending = (version) => {
541 if (version) {
542 const versionedAtomStateMap = getVersionedAtomStateMap(version);
543 versionedAtomStateMap.forEach((atomState, atom) => {
544 const committedAtomState = committedAtomStateMap.get(atom);
545 if (atomState !== committedAtomState) {
546 const mounted = mountedMap.get(atom);
547 mounted == null ? void 0 : mounted.l.forEach((listener) => listener(version));
548 }
549 });
550 return;
551 }
552 while (pendingMap.size) {
553 const pending = Array.from(pendingMap);
554 pendingMap.clear();
555 pending.forEach(([atom, prevAtomState]) => {
556 const atomState = getAtomState(void 0, atom);
557 if (atomState && atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
558 mountDependencies(void 0, atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
559 }
560 if (prevAtomState && !prevAtomState.y && (atomState == null ? void 0 : atomState.y)) {
561 return;
562 }
563 const mounted = mountedMap.get(atom);
564 mounted == null ? void 0 : mounted.l.forEach((listener) => listener());
565 });
566 }
567 if (process.env.NODE_ENV !== "production") {
568 stateListeners.forEach((l) => l());
569 }
570 };
571 const commitVersionedAtomStateMap = (version) => {
572 const versionedAtomStateMap = getVersionedAtomStateMap(version);
573 versionedAtomStateMap.forEach((atomState, atom) => {
574 const prevAtomState = committedAtomStateMap.get(atom);
575 if (!prevAtomState || atomState.r > prevAtomState.r || atomState.y !== prevAtomState.y || atomState.r === prevAtomState.r && atomState.d !== prevAtomState.d) {
576 committedAtomStateMap.set(atom, atomState);
577 if (atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
578 mountDependencies(version, atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
579 }
580 }
581 });
582 };
583 const commitAtom = (_atom, version) => {
584 if (version) {
585 commitVersionedAtomStateMap(version);
586 }
587 flushPending(void 0);
588 };
589 const subscribeAtom = (atom, callback, version) => {
590 const mounted = addAtom(version, atom);
591 const listeners = mounted.l;
592 listeners.add(callback);
593 return () => {
594 listeners.delete(callback);
595 delAtom(version, atom);
596 };
597 };
598 const restoreAtoms = (values, version) => {
599 for (const [atom, value] of values) {
600 if (hasInitialValue(atom)) {
601 setAtomPromiseOrValue(version, atom, value);
602 invalidateDependents(version, atom);
603 }
604 }
605 flushPending(version);
606 };
607 if (process.env.NODE_ENV !== "production") {
608 return {
609 [READ_ATOM]: readAtom,
610 [WRITE_ATOM]: writeAtom,
611 [COMMIT_ATOM]: commitAtom,
612 [SUBSCRIBE_ATOM]: subscribeAtom,
613 [RESTORE_ATOMS]: restoreAtoms,
614 [DEV_SUBSCRIBE_STATE]: (l) => {
615 stateListeners.add(l);
616 return () => {
617 stateListeners.delete(l);
618 };
619 },
620 [DEV_GET_MOUNTED_ATOMS]: () => mountedAtoms.values(),
621 [DEV_GET_ATOM_STATE]: (a) => committedAtomStateMap.get(a),
622 [DEV_GET_MOUNTED]: (a) => mountedMap.get(a)
623 };
624 }
625 return {
626 [READ_ATOM]: readAtom,
627 [WRITE_ATOM]: writeAtom,
628 [COMMIT_ATOM]: commitAtom,
629 [SUBSCRIBE_ATOM]: subscribeAtom,
630 [RESTORE_ATOMS]: restoreAtoms
631 };
632};
633const createStoreForExport = (initialValues) => {
634 const store = createStore(initialValues);
635 const get = (atom) => {
636 const atomState = store[READ_ATOM](atom);
637 if ("e" in atomState) {
638 throw atomState.e;
639 }
640 if ("p" in atomState) {
641 return void 0;
642 }
643 return atomState.v;
644 };
645 const asyncGet = (atom) => new Promise((resolve, reject) => {
646 const atomState = store[READ_ATOM](atom);
647 if ("e" in atomState) {
648 reject(atomState.e);
649 } else if ("p" in atomState) {
650 resolve(atomState.p.then(() => asyncGet(atom)));
651 } else {
652 resolve(atomState.v);
653 }
654 });
655 const set = (atom, update) => store[WRITE_ATOM](atom, update);
656 const sub = (atom, callback) => store[SUBSCRIBE_ATOM](atom, callback);
657 return {
658 get,
659 asyncGet,
660 set,
661 sub,
662 SECRET_INTERNAL_store: store
663 };
664};
665
666const createScopeContainer = (initialValues, unstable_createStore) => {
667 const store = unstable_createStore ? unstable_createStore(initialValues).SECRET_INTERNAL_store : createStore(initialValues);
668 return { s: store };
669};
670const ScopeContextMap = /* @__PURE__ */ new Map();
671const getScopeContext = (scope) => {
672 if (!ScopeContextMap.has(scope)) {
673 ScopeContextMap.set(scope, createContext(createScopeContainer()));
674 }
675 return ScopeContextMap.get(scope);
676};
677
678const Provider = ({
679 children,
680 initialValues,
681 scope,
682 unstable_createStore,
683 unstable_enableVersionedWrite
684}) => {
685 const [version, setVersion] = useState({});
686 useEffect(() => {
687 const scopeContainer = scopeContainerRef.current;
688 if (scopeContainer.w) {
689 scopeContainer.s[COMMIT_ATOM](null, version);
690 delete version.p;
691 scopeContainer.v = version;
692 }
693 }, [version]);
694 const scopeContainerRef = useRef();
695 if (!scopeContainerRef.current) {
696 const scopeContainer = createScopeContainer(
697 initialValues,
698 unstable_createStore
699 );
700 if (unstable_enableVersionedWrite) {
701 let retrying = 0;
702 scopeContainer.w = (write) => {
703 setVersion((parentVersion) => {
704 const nextVersion = retrying ? parentVersion : { p: parentVersion };
705 write(nextVersion);
706 return nextVersion;
707 });
708 };
709 scopeContainer.v = version;
710 scopeContainer.r = (fn) => {
711 ++retrying;
712 fn();
713 --retrying;
714 };
715 }
716 scopeContainerRef.current = scopeContainer;
717 }
718 const ScopeContainerContext = getScopeContext(scope);
719 return createElement(
720 ScopeContainerContext.Provider,
721 {
722 value: scopeContainerRef.current
723 },
724 children
725 );
726};
727
728function atom(read, write) {
729 return atom$1(read, write);
730}
731
732function useAtomValue(atom, scope) {
733 const ScopeContext = getScopeContext(scope);
734 const scopeContainer = useContext(ScopeContext);
735 const { s: store, v: versionFromProvider } = scopeContainer;
736 const getAtomValue = (version2) => {
737 const atomState = store[READ_ATOM](atom, version2);
738 if (process.env.NODE_ENV !== "production" && !atomState.y) {
739 throw new Error("should not be invalidated");
740 }
741 if ("e" in atomState) {
742 throw atomState.e;
743 }
744 if ("p" in atomState) {
745 throw atomState.p;
746 }
747 if ("v" in atomState) {
748 return atomState.v;
749 }
750 throw new Error("no atom value");
751 };
752 const [[version, valueFromReducer, atomFromReducer], rerenderIfChanged] = useReducer(
753 (prev, nextVersion) => {
754 const nextValue = getAtomValue(nextVersion);
755 if (Object.is(prev[1], nextValue) && prev[2] === atom) {
756 return prev;
757 }
758 return [nextVersion, nextValue, atom];
759 },
760 versionFromProvider,
761 (initialVersion) => {
762 const initialValue = getAtomValue(initialVersion);
763 return [initialVersion, initialValue, atom];
764 }
765 );
766 let value = valueFromReducer;
767 if (atomFromReducer !== atom) {
768 rerenderIfChanged(version);
769 value = getAtomValue(version);
770 }
771 useEffect(() => {
772 const { v: versionFromProvider2 } = scopeContainer;
773 if (versionFromProvider2) {
774 store[COMMIT_ATOM](atom, versionFromProvider2);
775 }
776 const unsubscribe = store[SUBSCRIBE_ATOM](
777 atom,
778 rerenderIfChanged,
779 versionFromProvider2
780 );
781 rerenderIfChanged(versionFromProvider2);
782 return unsubscribe;
783 }, [store, atom, scopeContainer]);
784 useEffect(() => {
785 store[COMMIT_ATOM](atom, version);
786 });
787 useDebugValue(value);
788 return value;
789}
790
791function useSetAtom(atom, scope) {
792 const ScopeContext = getScopeContext(scope);
793 const { s: store, w: versionedWrite } = useContext(ScopeContext);
794 const setAtom = useCallback(
795 (update) => {
796 if (process.env.NODE_ENV !== "production" && !("write" in atom)) {
797 throw new Error("not writable atom");
798 }
799 const write = (version) => store[WRITE_ATOM](atom, update, version);
800 return versionedWrite ? versionedWrite(write) : write();
801 },
802 [store, versionedWrite, atom]
803 );
804 return setAtom;
805}
806
807function useAtom(atom, scope) {
808 if ("scope" in atom) {
809 console.warn(
810 "atom.scope is deprecated. Please do useAtom(atom, scope) instead."
811 );
812 scope = atom.scope;
813 }
814 return [
815 useAtomValue(atom, scope),
816 useSetAtom(atom, scope)
817 ];
818}
819
820export { Provider, getScopeContext as SECRET_INTERNAL_getScopeContext, registerPromiseAbort as SECRET_INTERNAL_registerPromiseAbort, atom, createStoreForExport as unstable_createStore, useAtom, useAtomValue, useSetAtom };