UNPKG

66.7 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
7var react = _interopDefault(require('react'));
8var reactDom = _interopDefault(require('react-dom'));
9
10/**
11 * Copyright 2004-present Facebook. All Rights Reserved.
12 *
13 * Utilities for working with built-in Maps and Sets without mutating them.
14 *
15 * @emails oncall+perf_viz
16 *
17 * @format
18 */
19
20function setByAddingToSet(set, v) {
21 const next = new Set(set);
22 next.add(v);
23 return next;
24}
25
26function setByDeletingFromSet(set, v) {
27 const next = new Set(set);
28 next.delete(v);
29 return next;
30}
31
32function mapBySettingInMap(map, k, v) {
33 const next = new Map(map);
34 next.set(k, v);
35 return next;
36}
37
38function mapByUpdatingInMap(map, k, updater) {
39 const next = new Map(map);
40 next.set(k, updater(next.get(k)));
41 return next;
42}
43
44function mapByDeletingFromMap(map, k) {
45 const next = new Map(map);
46 next.delete(k);
47 return next;
48}
49
50var Recoil_CopyOnWrite = {
51 setByAddingToSet,
52 setByDeletingFromSet,
53 mapBySettingInMap,
54 mapByUpdatingInMap,
55 mapByDeletingFromMap
56};
57
58/**
59 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
60 *
61 * @emails oncall+perf_viz
62 *
63 * @format
64 */
65
66function isNode(object) {
67 var _ownerDocument, _doc$defaultView;
68
69 const doc = object != null ? (_ownerDocument = object.ownerDocument) !== null && _ownerDocument !== void 0 ? _ownerDocument : object : document;
70 const defaultView = (_doc$defaultView = doc.defaultView) !== null && _doc$defaultView !== void 0 ? _doc$defaultView : window;
71 return !!(object != null && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));
72}
73
74var Recoil_isNode = isNode;
75
76/**
77 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
78 *
79 * @emails oncall+perf_viz
80 *
81 * @format
82 */
83
84// Split declaration and implementation to allow this function to pretend to
85// check for actual instance of Promise instead of something with a `then`
86// method.
87// eslint-disable-next-line no-redeclare
88function isPromise(p) {
89 return !!p && typeof p.then === 'function';
90}
91
92var Recoil_isPromise = isPromise;
93
94function shouldNotBeFrozen(value) {
95 // Primitives and functions:
96 if (value === null || typeof value !== 'object') {
97 return true;
98 } // React elements:
99
100
101 switch (typeof value.$$typeof) {
102 case 'symbol':
103 return true;
104
105 case 'number':
106 return true;
107 } // Immutable structures:
108
109
110 if (value['@@__IMMUTABLE_ITERABLE__@@'] != null || value['@@__IMMUTABLE_KEYED__@@'] != null || value['@@__IMMUTABLE_INDEXED__@@'] != null || value['@@__IMMUTABLE_ORDERED__@@'] != null || value['@@__IMMUTABLE_RECORD__@@'] != null) {
111 return true;
112 } // DOM nodes:
113
114
115 if (Recoil_isNode(value)) {
116 return true;
117 }
118
119 if (Recoil_isPromise(value)) {
120 return true;
121 }
122
123 return false;
124} // Recursively freeze a value to enforce it is read-only.
125// This may also have minimal performance improvements for enumerating
126// objects (based on browser implementations, of course)
127
128
129function deepFreezeValue(value) {
130 if (typeof value !== 'object' || shouldNotBeFrozen(value)) {
131 return;
132 }
133
134 Object.freeze(value); // Make all properties read-only
135
136 for (const prop in value) {
137 if (value.hasOwnProperty(prop)) {
138 deepFreezeValue(value[prop]);
139 }
140 }
141
142 Object.seal(value); // This also makes existing properties non-configurable.
143}
144
145var Recoil_deepFreezeValue = deepFreezeValue;
146
147/**
148 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
149 *
150 * @emails oncall+perf_viz
151 *
152 * @format
153 */
154
155function nullthrows(x, message) {
156 if (x != null) {
157 return x;
158 }
159
160 throw new Error(message !== null && message !== void 0 ? message : 'Got unexpected null or undefined');
161}
162
163var Recoil_nullthrows = nullthrows;
164
165// TODO Convert Loadable to a Class to allow for runtime type detection.
166// Containing static factories of withValue(), withError(), withPromise(), and all()
167
168
169const loadableAccessors = {
170 getValue() {
171 if (this.state !== 'hasValue') {
172 throw this.contents; // Throw Error, or Promise for the loading state
173 }
174
175 return this.contents;
176 },
177
178 toPromise() {
179 return this.state === 'hasValue' ? Promise.resolve(this.contents) : this.state === 'hasError' ? Promise.reject(this.contents) : this.contents;
180 },
181
182 valueMaybe() {
183 return this.state === 'hasValue' ? this.contents : undefined;
184 },
185
186 valueOrThrow() {
187 if (this.state !== 'hasValue') {
188 throw new Error(`Loadable expected value, but in "${this.state}" state`);
189 }
190
191 return this.contents;
192 },
193
194 errorMaybe() {
195 return this.state === 'hasError' ? this.contents : undefined;
196 },
197
198 errorOrThrow() {
199 if (this.state !== 'hasError') {
200 throw new Error(`Loadable expected error, but in "${this.state}" state`);
201 }
202
203 return this.contents;
204 },
205
206 promiseMaybe() {
207 return this.state === 'loading' ? this.contents : undefined;
208 },
209
210 promiseOrThrow() {
211 if (this.state !== 'loading') {
212 throw new Error(`Loadable expected promise, but in "${this.state}" state`);
213 }
214
215 return this.contents;
216 },
217
218 // TODO Unit tests
219 // TODO Convert Loadable to a Class to better support chaining
220 // by returning a Loadable from a map function
221 map(map) {
222 if (this.state === 'hasError') {
223 return this;
224 }
225
226 if (this.state === 'hasValue') {
227 try {
228 const next = map(this.contents); // TODO if next instanceof Loadable, then return next
229
230 return Recoil_isPromise(next) ? loadableWithPromise(next) : loadableWithValue(next);
231 } catch (e) {
232 return Recoil_isPromise(e) ? // If we "suspended", then try again.
233 // errors and subsequent retries will be handeled in 'loading' case
234 loadableWithPromise(e.next(() => map(this.contents))) : loadableWithError(e);
235 }
236 }
237
238 if (this.state === 'loading') {
239 return loadableWithPromise(this.contents // TODO if map returns a loadable, then return the value or promise or throw the error
240 .then(map).catch(e => {
241 if (Recoil_isPromise(e)) {
242 // we were "suspended," try again
243 return e.then(() => map(this.contents));
244 }
245
246 throw e;
247 }));
248 }
249
250 throw new Error('Invalid Loadable state');
251 }
252
253};
254
255function loadableWithValue(value) {
256 // Build objects this way since Flow doesn't support disjoint unions for class properties
257 return Object.freeze({
258 state: 'hasValue',
259 contents: value,
260 ...loadableAccessors
261 });
262}
263
264function loadableWithError(error) {
265 return Object.freeze({
266 state: 'hasError',
267 contents: error,
268 ...loadableAccessors
269 });
270}
271
272function loadableWithPromise(promise) {
273 return Object.freeze({
274 state: 'loading',
275 contents: promise,
276 ...loadableAccessors
277 });
278}
279
280function loadableLoading() {
281 return loadableWithPromise(new Promise(() => {}));
282}
283
284function loadableAll(inputs) {
285 return inputs.every(i => i.state === 'hasValue') ? loadableWithValue(inputs.map(i => i.contents)) : inputs.some(i => i.state === 'hasError') ? loadableWithError( // $FlowIssue #44070740 Array.find should refine parameter
286 Recoil_nullthrows(inputs.find(i => i.state === 'hasError'), 'Invalid loadable passed to loadableAll').contents) : loadableWithPromise( Promise.all(inputs.map(i => i.contents)));
287}
288
289var Recoil_Loadable = {
290 loadableWithValue,
291 loadableWithError,
292 loadableWithPromise,
293 loadableLoading,
294 loadableAll
295};
296
297function _defineProperty(obj, key, value) {
298 if (key in obj) {
299 Object.defineProperty(obj, key, {
300 value: value,
301 enumerable: true,
302 configurable: true,
303 writable: true
304 });
305 } else {
306 obj[key] = value;
307 }
308
309 return obj;
310}
311
312/**
313 * Copyright 2004-present Facebook. All Rights Reserved.
314 *
315 * @emails oncall+perf_viz
316 *
317 * @format
318 */
319
320// eslint-disable-next-line no-unused-vars
321class AbstractRecoilValue {
322 constructor(newKey) {
323 _defineProperty(this, "key", void 0);
324
325 this.key = newKey;
326 }
327
328}
329
330class RecoilState extends AbstractRecoilValue {}
331
332class RecoilValueReadOnly extends AbstractRecoilValue {}
333
334var Recoil_RecoilValueClasses = {
335 AbstractRecoilValue,
336 RecoilState,
337 RecoilValueReadOnly
338};
339
340var Recoil_RecoilValueClasses_1 = Recoil_RecoilValueClasses.AbstractRecoilValue;
341var Recoil_RecoilValueClasses_2 = Recoil_RecoilValueClasses.RecoilState;
342var Recoil_RecoilValueClasses_3 = Recoil_RecoilValueClasses.RecoilValueReadOnly;
343
344var Recoil_RecoilValueClasses$1 = /*#__PURE__*/Object.freeze({
345 __proto__: null,
346 AbstractRecoilValue: Recoil_RecoilValueClasses_1,
347 RecoilState: Recoil_RecoilValueClasses_2,
348 RecoilValueReadOnly: Recoil_RecoilValueClasses_3
349});
350
351/**
352 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
353 *
354 * @emails oncall+perf_viz
355 *
356 * @format
357 */
358
359function sprintf(format, ...args) {
360 let index = 0;
361 return format.replace(/%s/g, () => String(args[index++]));
362}
363
364var Recoil_sprintf = sprintf;
365
366function expectationViolation(format, ...args) {
367 if (__DEV__) {
368 const message = Recoil_sprintf.call(null, format, ...args);
369 const error = new Error(message);
370 error.name = 'Expectation Violation';
371 console.error(error);
372 }
373}
374
375var Recoil_expectationViolation = expectationViolation;
376
377/**
378 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
379 *
380 * @emails oncall+perf_viz
381 *
382 * @format
383 */
384
385function recoverableViolation(message, projectName, {
386 error
387}) {
388 if (__DEV__) {
389 console.error(message, error);
390 }
391
392 return null;
393}
394
395var Recoil_recoverableViolation = recoverableViolation;
396
397class DefaultValue {}
398
399const DEFAULT_VALUE = new DefaultValue();
400
401class RecoilValueNotReady extends Error {
402 constructor(key) {
403 super(`Tried to set the value of Recoil selector ${key} using an updater function, but it is an async selector in a pending or error state; this is not supported.`);
404 }
405
406}
407
408// flowlint-next-line unclear-type:off
409const nodes = new Map();
410/* eslint-disable no-redeclare */
411
412function registerNode(node) {
413 if (nodes.has(node.key)) {
414 const message = `Duplicate atom key "${node.key}". This is a FATAL ERROR in
415 production. But it is safe to ignore this warning if it occured because of
416 hot module replacement.`;
417
418 if (__DEV__) {
419
420 {
421 Recoil_expectationViolation(message, 'recoil');
422 }
423 } else {
424 Recoil_recoverableViolation(message);
425 }
426 }
427
428 nodes.set(node.key, node);
429 return node.set == null ? new Recoil_RecoilValueClasses$1.RecoilValueReadOnly(node.key) : new Recoil_RecoilValueClasses$1.RecoilState(node.key);
430}
431/* eslint-enable no-redeclare */
432
433
434class NodeMissingError extends Error {} // flowlint-next-line unclear-type:off
435
436
437function getNode(key) {
438 const node = nodes.get(key);
439
440 if (node == null) {
441 throw new NodeMissingError(`Missing definition for RecoilValue: "${key}""`);
442 }
443
444 return node;
445}
446
447var Recoil_Node = {
448 nodes,
449 registerNode,
450 getNode,
451 NodeMissingError,
452 DefaultValue,
453 DEFAULT_VALUE,
454 RecoilValueNotReady
455};
456
457/**
458 * Copyright 2004-present Facebook. All Rights Reserved.
459 *
460 * This is a stub for some integration into FB internal stuff
461 */
462var SchedulerTracing = {};
463
464// flowlint-line untyped-import:off
465
466
467function trace(message, node, fn) {
468 if (__DEV__) {
469 if (SchedulerTracing.unstable_trace !== undefined && window.performance !== undefined) {
470 return SchedulerTracing.unstable_trace(`Recoil: ${message} for node: ${typeof node === 'string' ? node : node.key}`, window.performance.now(), fn);
471 }
472 }
473
474 return fn();
475}
476
477function wrap(fn) {
478 if (__DEV__) {
479 if (SchedulerTracing.unstable_wrap !== undefined) {
480 return SchedulerTracing.unstable_wrap(fn);
481 }
482 }
483
484 return fn;
485}
486
487var Recoil_Tracing = {
488 trace,
489 wrap
490};
491
492const {
493 mapByDeletingFromMap: mapByDeletingFromMap$1,
494 mapBySettingInMap: mapBySettingInMap$1,
495 mapByUpdatingInMap: mapByUpdatingInMap$1,
496 setByAddingToSet: setByAddingToSet$1
497} = Recoil_CopyOnWrite;
498
499const {
500 getNode: getNode$1
501} = Recoil_Node;
502
503 // flowlint-next-line unclear-type:off
504
505
506const emptyMap = Object.freeze(new Map()); // flowlint-next-line unclear-type:off
507
508const emptySet = Object.freeze(new Set());
509
510class ReadOnlyRecoilValueError extends Error {} // Get the current value loadable of a node and update the state.
511// Update dependencies and subscriptions for selectors.
512// Update saved value validation for atoms.
513
514
515function getNodeLoadable(store, state, key) {
516 return getNode$1(key).get(store, state);
517} // Peek at the current value loadable for a node.
518// NOTE: This will ignore updating the state for subscriptions so use sparingly!!
519
520
521function peekNodeLoadable(store, state, key) {
522 return getNodeLoadable(store, state, key)[1];
523} // Write value directly to state bypassing the Node interface as the node
524// definitions may not have been loaded yet when processing the initial snapshot.
525
526
527function setUnvalidatedAtomValue(state, key, newValue) {
528 return { ...state,
529 atomValues: mapByDeletingFromMap$1(state.atomValues, key),
530 nonvalidatedAtoms: mapBySettingInMap$1(state.nonvalidatedAtoms, key, newValue),
531 dirtyAtoms: setByAddingToSet$1(state.dirtyAtoms, key)
532 };
533} // Set a node value and return the set of nodes that were actually written.
534// That does not include any downstream nodes which are dependent on them.
535
536
537function setNodeValue(store, state, key, newValue) {
538 const node = getNode$1(key);
539
540 if (node.set == null) {
541 throw new ReadOnlyRecoilValueError(`Attempt to set read-only RecoilValue: ${key}`);
542 }
543
544 const [newState, writtenNodes] = node.set(store, state, newValue);
545 return [newState, writtenNodes];
546} // Find all of the recursively dependent nodes
547
548
549function getDownstreamNodes(state, keys) {
550 const dependentNodes = new Set();
551 const visitedNodes = new Set();
552 const visitingNodes = Array.from(keys);
553
554 for (let key = visitingNodes.pop(); key; key = visitingNodes.pop()) {
555 var _state$nodeToNodeSubs;
556
557 dependentNodes.add(key);
558 visitedNodes.add(key);
559 const subscribedNodes = (_state$nodeToNodeSubs = state.nodeToNodeSubscriptions.get(key)) !== null && _state$nodeToNodeSubs !== void 0 ? _state$nodeToNodeSubs : emptySet;
560
561 for (const downstreamNode of subscribedNodes) {
562 if (!visitedNodes.has(downstreamNode)) {
563 visitingNodes.push(downstreamNode);
564 }
565 }
566 }
567
568 return dependentNodes;
569}
570
571let subscriptionID = 0;
572
573function subscribeComponentToNode(state, key, callback) {
574 const subID = subscriptionID++;
575 const newState = { ...state,
576 nodeToComponentSubscriptions: mapByUpdatingInMap$1(state.nodeToComponentSubscriptions, key, subsForAtom => mapBySettingInMap$1(subsForAtom !== null && subsForAtom !== void 0 ? subsForAtom : emptyMap, subID, ['TODO debug name', callback]))
577 };
578
579 function release(state) {
580 const newState = { ...state,
581 nodeToComponentSubscriptions: mapByUpdatingInMap$1(state.nodeToComponentSubscriptions, key, subsForAtom => mapByDeletingFromMap$1(subsForAtom !== null && subsForAtom !== void 0 ? subsForAtom : emptyMap, subID))
582 };
583 return newState;
584 }
585
586 return [newState, release];
587} // Fire or enqueue callbacks to rerender components that are subscribed to
588// nodes affected by the updatedNodes
589
590
591function fireNodeSubscriptions(store, updatedNodes, when) {
592 var _store$getState$nextT;
593
594 /*
595 This is called in two conditions: When an atom is set (with 'enqueue') and
596 when an async selector resolves (with 'now'). When an atom is set, we want
597 to use the latest dependencies that may have become dependencies due to
598 earlier changes in a batch. But if an async selector happens to resolve during
599 a batch, it should use the currently rendered output, and then the end of the
600 batch will trigger any further subscriptions due to new deps in the new state.
601 */
602 const state = when === 'enqueue' ? (_store$getState$nextT = store.getState().nextTree) !== null && _store$getState$nextT !== void 0 ? _store$getState$nextT : store.getState().currentTree : store.getState().currentTree;
603 const dependentNodes = getDownstreamNodes(state, updatedNodes);
604
605 for (const key of dependentNodes) {
606 var _state$nodeToComponen;
607
608 ((_state$nodeToComponen = state.nodeToComponentSubscriptions.get(key)) !== null && _state$nodeToComponen !== void 0 ? _state$nodeToComponen : []).forEach(([debugName, cb]) => {
609 when === 'enqueue' ? store.getState().queuedComponentCallbacks.push(cb) : cb(state);
610 });
611 } // Wake all suspended components so the right one(s) can try to re-render.
612 // We need to wake up components not just when some asynchronous selector
613 // resolved (when === 'now'), but also when changing synchronous values because
614 // they may cause a selector to change from asynchronous to synchronous, in
615 // which case there would be no follow-up asynchronous resolution to wake us up.
616 // TODO OPTIMIZATION Only wake up related downstream components
617
618
619 Recoil_Tracing.trace('value became available, waking components', Array.from(updatedNodes).join(', '), () => {
620 const resolvers = store.getState().suspendedComponentResolvers;
621 resolvers.forEach(r => r());
622 resolvers.clear();
623 });
624}
625
626function detectCircularDependencies(state, stack) {
627 if (!stack.length) {
628 return;
629 }
630
631 const leaf = stack[stack.length - 1];
632 const downstream = state.nodeToNodeSubscriptions.get(leaf);
633
634 if (!(downstream === null || downstream === void 0 ? void 0 : downstream.size)) {
635 return;
636 }
637
638 const root = stack[0];
639
640 if (downstream.has(root)) {
641 throw new Error(`Recoil selector has circular dependencies: ${[...stack, root].reverse().join(' \u2192 ')}`);
642 }
643
644 for (const next of downstream) {
645 detectCircularDependencies(state, [...stack, next]);
646 }
647}
648
649var Recoil_FunctionalCore = {
650 getNodeLoadable,
651 peekNodeLoadable,
652 setNodeValue,
653 setUnvalidatedAtomValue,
654 subscribeComponentToNode,
655 fireNodeSubscriptions,
656 detectCircularDependencies
657};
658
659const {
660 getNodeLoadable: getNodeLoadable$1,
661 peekNodeLoadable: peekNodeLoadable$1,
662 setNodeValue: setNodeValue$1,
663 setUnvalidatedAtomValue: setUnvalidatedAtomValue$1,
664 subscribeComponentToNode: subscribeComponentToNode$1
665} = Recoil_FunctionalCore;
666
667
668
669const {
670 RecoilValue,
671 AbstractRecoilValue: AbstractRecoilValue$1,
672 RecoilValueReadOnly: RecoilValueReadOnly$1,
673 RecoilState: RecoilState$1
674} = Recoil_RecoilValueClasses$1;
675
676// NOTE: This will not update state with node subscriptions, so use sparingly!!!
677function peekRecoilValueAsLoadable(store, {
678 key
679}) {
680 const state = store.getState().currentTree; // TODO with useMutableSource should use the tree from the individual component
681
682 return peekNodeLoadable$1(store, state, key);
683}
684
685function getRecoilValueAsLoadable(store, {
686 key
687}) {
688 let result; // Save any state changes during read, such as validating atoms,
689 // updated selector subscriptions/dependencies, &c.
690
691 Recoil_Tracing.trace('get RecoilValue', key, () => store.replaceState(Recoil_Tracing.wrap(state => {
692 const [newState, loadable] = getNodeLoadable$1(store, state, key);
693 result = loadable;
694 return newState;
695 })));
696 return result; // flowlint-line unclear-type:off
697}
698
699function setRecoilValue(store, {
700 key
701}, newValue) {
702 Recoil_Tracing.trace('set RecoilValue', key, () => store.replaceState(Recoil_Tracing.wrap(state => {
703 const [newState, writtenNodes] = setNodeValue$1(store, state, key, newValue);
704 store.fireNodeSubscriptions(writtenNodes, 'enqueue');
705 return newState;
706 })));
707}
708
709function setUnvalidatedRecoilValue(store, {
710 key
711}, newValue) {
712 Recoil_Tracing.trace('set unvalidated persisted atom', key, () => store.replaceState(Recoil_Tracing.wrap(state => {
713 const newState = setUnvalidatedAtomValue$1(state, key, newValue);
714 store.fireNodeSubscriptions(new Set([key]), 'enqueue');
715 return newState;
716 })));
717}
718
719function subscribeToRecoilValue(store, {
720 key
721}, callback) {
722 let newState, releaseFn;
723 Recoil_Tracing.trace('subscribe component to RecoilValue', key, () => store.replaceState(Recoil_Tracing.wrap(state => {
724 [newState, releaseFn] = subscribeComponentToNode$1(state, key, callback);
725 return newState;
726 })));
727 return {
728 release: store => store.replaceState(releaseFn)
729 };
730}
731
732function isRecoilValue(x) {
733 return x instanceof RecoilState$1 || x instanceof RecoilValueReadOnly$1;
734}
735
736var Recoil_RecoilValue = {
737 AbstractRecoilValue: AbstractRecoilValue$1,
738 RecoilState: RecoilState$1,
739 peekRecoilValueAsLoadable,
740 getRecoilValueAsLoadable,
741 setRecoilValue,
742 setUnvalidatedRecoilValue,
743 subscribeToRecoilValue,
744 isRecoilValue
745};
746
747// @fb-only: import type {ScopeRules} from './Recoil_ScopedAtom';
748const {
749 mapByDeletingFromMap: mapByDeletingFromMap$2,
750 mapBySettingInMap: mapBySettingInMap$2,
751 setByAddingToSet: setByAddingToSet$2
752} = Recoil_CopyOnWrite;
753
754
755
756const {
757 loadableWithValue: loadableWithValue$1
758} = Recoil_Loadable;
759
760const {
761 DEFAULT_VALUE: DEFAULT_VALUE$1,
762 DefaultValue: DefaultValue$1,
763 registerNode: registerNode$1
764} = Recoil_Node;
765
766const {
767 isRecoilValue: isRecoilValue$1
768} = Recoil_RecoilValue; // @fb-only: const {scopedAtom} = require('./Recoil_ScopedAtom');
769
770
771
772
773
774
775 // It would be nice if this didn't have to be defined at the Recoil level, but I don't want to make
776// the api cumbersome. One way to do this would be to have a selector mark the atom as persisted.
777// Note that this should also allow for special URL handling. (Although the persistence observer could
778// have this as a separate configuration.)
779
780
781function baseAtom(options) {
782 const {
783 key,
784 persistence_UNSTABLE: persistence
785 } = options;
786 return registerNode$1({
787 key,
788 options,
789 get: (_store, state) => {
790 if (state.atomValues.has(key)) {
791 // atom value is stored in state
792 return [state, Recoil_nullthrows(state.atomValues.get(key))];
793 } else if (state.nonvalidatedAtoms.has(key)) {
794 if (persistence == null) {
795 Recoil_expectationViolation(`Tried to restore a persisted value for atom ${key} but it has no persistence settings.`);
796 return [state, loadableWithValue$1(options.default)];
797 }
798
799 const nonvalidatedValue = state.nonvalidatedAtoms.get(key);
800 const validatedValue = persistence.validator(nonvalidatedValue, DEFAULT_VALUE$1);
801 return validatedValue instanceof DefaultValue$1 ? [{ ...state,
802 nonvalidatedAtoms: mapByDeletingFromMap$2(state.nonvalidatedAtoms, key)
803 }, loadableWithValue$1(options.default)] : [{ ...state,
804 atomValues: mapBySettingInMap$2(state.atomValues, key, loadableWithValue$1(validatedValue)),
805 nonvalidatedAtoms: mapByDeletingFromMap$2(state.nonvalidatedAtoms, key)
806 }, loadableWithValue$1(validatedValue)];
807 } else {
808 return [state, loadableWithValue$1(options.default)];
809 }
810 },
811 set: (_store, state, newValue) => {
812 if (options.dangerouslyAllowMutability !== true) {
813 Recoil_deepFreezeValue(newValue);
814 }
815
816 return [{ ...state,
817 dirtyAtoms: setByAddingToSet$2(state.dirtyAtoms, key),
818 atomValues: newValue instanceof DefaultValue$1 ? mapByDeletingFromMap$2(state.atomValues, key) : mapBySettingInMap$2(state.atomValues, key, loadableWithValue$1(newValue)),
819 nonvalidatedAtoms: mapByDeletingFromMap$2(state.nonvalidatedAtoms, key)
820 }, new Set([key])];
821 }
822 });
823}
824
825function atom(options) {
826 const {
827 default: optionsDefault,
828 // @fb-only: scopeRules_APPEND_ONLY_READ_THE_DOCS,
829 ...restOptions
830 } = options;
831
832 if (isRecoilValue$1(optionsDefault) || Recoil_isPromise(optionsDefault)) {
833 return atomWithFallback({ ...restOptions,
834 default: optionsDefault // @fb-only: scopeRules_APPEND_ONLY_READ_THE_DOCS,
835
836 }); // @fb-only: } else if (scopeRules_APPEND_ONLY_READ_THE_DOCS) {
837 // @fb-only: return scopedAtom<T>({
838 // @fb-only: ...restOptions,
839 // @fb-only: default: optionsDefault,
840 // @fb-only: scopeRules_APPEND_ONLY_READ_THE_DOCS,
841 // @fb-only: });
842 } else {
843 return baseAtom({ ...restOptions,
844 default: optionsDefault
845 });
846 }
847}
848
849function atomWithFallback(options) {
850 const base = atom({ ...options,
851 default: DEFAULT_VALUE$1,
852 persistence_UNSTABLE: options.persistence_UNSTABLE === undefined ? undefined : { ...options.persistence_UNSTABLE,
853 validator: storedValue => storedValue instanceof DefaultValue$1 ? storedValue : Recoil_nullthrows(options.persistence_UNSTABLE).validator(storedValue, DEFAULT_VALUE$1)
854 }
855 });
856 return selector({
857 key: `${options.key}__withFallback`,
858 get: ({
859 get
860 }) => {
861 const baseValue = get(base);
862 return baseValue instanceof DefaultValue$1 ? options.default : baseValue;
863 },
864 set: ({
865 set
866 }, newValue) => set(base, newValue),
867 dangerouslyAllowMutability: options.dangerouslyAllowMutability
868 });
869}
870
871var Recoil_atom = atom;
872
873/**
874 * Copyright 2004-present Facebook. All Rights Reserved.
875 *
876 * @emails oncall+comparison_view
877 *
878 * @format
879 */
880
881function enqueueExecution(s, f) {
882 f();
883}
884
885var Recoil_Queue = {
886 enqueueExecution
887};
888
889const {
890 useContext,
891 useEffect,
892 useRef,
893 useState
894} = react;
895
896const {
897 fireNodeSubscriptions: fireNodeSubscriptions$1,
898 setNodeValue: setNodeValue$2,
899 setUnvalidatedAtomValue: setUnvalidatedAtomValue$2
900} = Recoil_FunctionalCore;
901
902
903
904
905
906function notInAContext() {
907 throw new Error('This component must be used inside a <RecoilRoot> component.');
908}
909
910const defaultStore = Object.freeze({
911 getState: notInAContext,
912 replaceState: notInAContext,
913 subscribeToTransactions: notInAContext,
914 addTransactionMetadata: notInAContext,
915 fireNodeSubscriptions: notInAContext
916});
917
918function startNextTreeIfNeeded(storeState) {
919 if (storeState.nextTree === null) {
920 storeState.nextTree = { ...storeState.currentTree,
921 dirtyAtoms: new Set(),
922 transactionMetadata: {}
923 };
924 }
925}
926
927const AppContext = react.createContext({
928 current: defaultStore
929});
930
931const useStoreRef = () => useContext(AppContext);
932/*
933 * The purpose of the Batcher is to observe when React batches end so that
934 * Recoil state changes can be batched. Whenever Recoil state changes, we call
935 * setState on the batcher. Then we wait for that change to be committed, which
936 * signifies the end of the batch. That's when we respond to the Recoil change.
937 */
938
939
940function Batcher(props) {
941 const storeRef = useStoreRef();
942 const [_, setState] = useState([]);
943 props.setNotifyBatcherOfChange(() => setState({}));
944 useEffect(() => {
945 // enqueueExecution runs this function immediately; it is only used to
946 // manipulate the order of useEffects during tests, since React seems to
947 // call useEffect in an unpredictable order sometimes.
948 Recoil_Queue.enqueueExecution('Batcher', () => {
949 const storeState = storeRef.current.getState();
950 const {
951 currentTree,
952 nextTree
953 } = storeState; // Ignore commits that are not because of Recoil transactions -- namely,
954 // because something above RecoilRoot re-rendered:
955
956 if (nextTree === null) {
957 return;
958 } // Inform transaction subscribers of the transaction:
959
960
961 const dirtyAtoms = nextTree.dirtyAtoms;
962
963 if (dirtyAtoms.size) {
964 // NOTE that this passes the committed (current, aka previous) tree,
965 // whereas the nextTree is retrieved from storeRef by the transaction subscriber.
966 // (This interface can be cleaned up, TODO)
967 storeState.transactionSubscriptions.forEach(sub => sub(storeRef.current, currentTree));
968 } // Inform components that depend on dirty atoms of the transaction:
969 // FIXME why is this StoreState but dirtyAtoms is TreeState? Seems like they should be the same.
970
971
972 storeState.queuedComponentCallbacks.forEach(cb => cb(nextTree));
973 storeState.queuedComponentCallbacks.splice(0, storeState.queuedComponentCallbacks.length); // nextTree is now committed -- note that copying and reset occurs when
974 // a transaction begins, in startNextTreeIfNeeded:
975
976 storeState.currentTree = nextTree;
977 storeState.nextTree = null;
978 });
979 });
980 return null;
981}
982
983if (__DEV__) {
984 if (!window.$recoilDebugStates) {
985 window.$recoilDebugStates = [];
986 }
987}
988
989function makeEmptyTreeState() {
990 return {
991 isSnapshot: false,
992 transactionMetadata: {},
993 atomValues: new Map(),
994 nonvalidatedAtoms: new Map(),
995 dirtyAtoms: new Set(),
996 nodeDeps: new Map(),
997 nodeToNodeSubscriptions: new Map(),
998 nodeToComponentSubscriptions: new Map()
999 };
1000}
1001
1002function makeEmptyStoreState() {
1003 return {
1004 currentTree: makeEmptyTreeState(),
1005 nextTree: null,
1006 transactionSubscriptions: new Map(),
1007 queuedComponentCallbacks: [],
1008 suspendedComponentResolvers: new Set()
1009 };
1010}
1011
1012function initialStoreState(store, initializeState) {
1013 const initial = makeEmptyStoreState();
1014
1015 if (initializeState) {
1016 initializeState({
1017 set: (atom, value) => {
1018 initial.currentTree = setNodeValue$2(store, initial.currentTree, atom.key, value)[0];
1019 },
1020 setUnvalidatedAtomValues: atomValues => {
1021 atomValues.forEach((v, k) => {
1022 initial.currentTree = setUnvalidatedAtomValue$2(initial.currentTree, k, v);
1023 });
1024 }
1025 });
1026 }
1027
1028 return initial;
1029}
1030
1031let nextID = 0;
1032
1033function RecoilRoot({
1034 initializeState,
1035 children
1036}) {
1037 let storeState; // eslint-disable-line prefer-const
1038
1039 const subscribeToTransactions = callback => {
1040 const id = nextID++;
1041 storeRef.current.getState().transactionSubscriptions.set(id, callback);
1042 return {
1043 release: () => {
1044 storeRef.current.getState().transactionSubscriptions.delete(id);
1045 }
1046 };
1047 };
1048
1049 const addTransactionMetadata = metadata => {
1050 startNextTreeIfNeeded(storeRef.current.getState());
1051
1052 for (const k of Object.keys(metadata)) {
1053 Recoil_nullthrows(storeRef.current.getState().nextTree).transactionMetadata[k] = metadata[k];
1054 }
1055 };
1056
1057 function fireNodeSubscriptionsForStore(updatedNodes, when) {
1058 fireNodeSubscriptions$1(storeRef.current, updatedNodes, when);
1059 }
1060
1061 const replaceState = replacer => {
1062 const storeState = storeRef.current.getState();
1063 startNextTreeIfNeeded(storeState); // Use replacer to get the next state:
1064
1065 const nextTree = Recoil_nullthrows(storeState.nextTree);
1066 const replaced = replacer(nextTree);
1067
1068 if (replaced === nextTree) {
1069 return;
1070 } // Save changes to nextTree and schedule a React update:
1071
1072
1073 if (__DEV__) {
1074 window.$recoilDebugStates.push(replaced); // TODO this shouldn't happen here because it's not batched
1075 }
1076
1077 storeState.nextTree = replaced;
1078 Recoil_nullthrows(notifyBatcherOfChange.current)();
1079 };
1080
1081 const notifyBatcherOfChange = useRef(null);
1082
1083 function setNotifyBatcherOfChange(x) {
1084 notifyBatcherOfChange.current = x;
1085 }
1086
1087 const store = {
1088 getState: () => storeState.current,
1089 replaceState,
1090 subscribeToTransactions,
1091 addTransactionMetadata,
1092 fireNodeSubscriptions: fireNodeSubscriptionsForStore
1093 };
1094 const storeRef = useRef(store);
1095 storeState = useRef(initialStoreState(store, initializeState));
1096 return /*#__PURE__*/react.createElement(AppContext.Provider, {
1097 value: storeRef
1098 }, /*#__PURE__*/react.createElement(Batcher, {
1099 setNotifyBatcherOfChange: setNotifyBatcherOfChange
1100 }), children);
1101}
1102
1103var Recoil_RecoilRoot_react = {
1104 useStoreRef,
1105 RecoilRoot
1106};
1107
1108/**
1109 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
1110 *
1111 * @emails oncall+perf_viz
1112 *
1113 * @format
1114 */
1115/**
1116 * Returns a set containing all of the values from the first set that are not
1117 * present in any of the subsequent sets.
1118 *
1119 * Note: this is written procedurally (i.e., without filterSet) for performant
1120 * use in tight loops.
1121 */
1122
1123function differenceSets(set, ...setsWithValuesToRemove) {
1124 const ret = new Set();
1125
1126 FIRST: for (const value of set) {
1127 for (const otherSet of setsWithValuesToRemove) {
1128 if (otherSet.has(value)) {
1129 continue FIRST;
1130 }
1131 }
1132
1133 ret.add(value);
1134 }
1135
1136 return ret;
1137}
1138
1139var Recoil_differenceSets = differenceSets;
1140
1141/**
1142 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
1143 *
1144 * @emails oncall+perf_viz
1145 *
1146 * @format
1147 */
1148/**
1149 * Returns a map containing all of the keys + values from the original map where
1150 * the given callback returned true.
1151 */
1152
1153function filterMap(map, callback) {
1154 const result = new Map();
1155
1156 for (const [key, value] of map) {
1157 if (callback(value, key)) {
1158 result.set(key, value);
1159 }
1160 }
1161
1162 return result;
1163}
1164
1165var Recoil_filterMap = filterMap;
1166
1167/**
1168 * Copyright 2004-present Facebook. All Rights Reserved.
1169 *
1170 * Returns the set of values that are present in all the given sets, preserving
1171 * the order of the first set.
1172 *
1173 * Note: this is written procedurally (i.e., without filterSet) for performant
1174 * use in tight loops.
1175 *
1176 *
1177 * @format
1178 */
1179
1180function intersectSets(first, ...rest) {
1181 const ret = new Set();
1182
1183 FIRST: for (const value of first) {
1184 for (const otherSet of rest) {
1185 if (!otherSet.has(value)) {
1186 continue FIRST;
1187 }
1188 }
1189
1190 ret.add(value);
1191 }
1192
1193 return ret;
1194}
1195
1196var Recoil_intersectSets = intersectSets;
1197
1198/**
1199 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
1200 *
1201 * @emails oncall+perf_viz
1202 *
1203 * @format
1204 */
1205
1206function invariant(condition, message) {
1207 if (!condition) {
1208 throw new Error(message);
1209 }
1210}
1211
1212var Recoil_invariant = invariant;
1213
1214/**
1215 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
1216 *
1217 * @emails oncall+perf_viz
1218 *
1219 * @format
1220 */
1221/**
1222 * Returns a new Map object with the same keys as the original, but with the
1223 * values replaced with the output of the given callback function.
1224 */
1225
1226function mapMap(map, callback) {
1227 const result = new Map();
1228 map.forEach((value, key) => {
1229 result.set(key, callback(value, key));
1230 });
1231 return result;
1232}
1233
1234var Recoil_mapMap = mapMap;
1235
1236/**
1237 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
1238 *
1239 * @emails oncall+perf_viz
1240 *
1241 * @format
1242 */
1243
1244function mergeMaps(...maps) {
1245 const result = new Map();
1246
1247 for (let i = 0; i < maps.length; i++) {
1248 const iterator = maps[i].keys();
1249 let nextKey;
1250
1251 while (!(nextKey = iterator.next()).done) {
1252 // $FlowFixMe - map/iterator knows nothing about flow types
1253 result.set(nextKey.value, maps[i].get(nextKey.value));
1254 }
1255 }
1256 /* $FlowFixMe(>=0.66.0 site=www,mobile) This comment suppresses an error
1257 * found when Flow v0.66 was deployed. To see the error delete this comment
1258 * and run Flow. */
1259
1260
1261 return result;
1262}
1263
1264var Recoil_mergeMaps = mergeMaps;
1265
1266const {
1267 useCallback,
1268 useEffect: useEffect$1,
1269 useMemo,
1270 useRef: useRef$1,
1271 useState: useState$1
1272} = react;
1273
1274
1275
1276const {
1277 setByAddingToSet: setByAddingToSet$3
1278} = Recoil_CopyOnWrite;
1279
1280const {
1281 getNodeLoadable: getNodeLoadable$2,
1282 peekNodeLoadable: peekNodeLoadable$2,
1283 setNodeValue: setNodeValue$3
1284} = Recoil_FunctionalCore;
1285
1286const {
1287 DEFAULT_VALUE: DEFAULT_VALUE$2,
1288 RecoilValueNotReady: RecoilValueNotReady$1,
1289 getNode: getNode$2,
1290 nodes: nodes$1
1291} = Recoil_Node;
1292
1293const {
1294 useStoreRef: useStoreRef$1
1295} = Recoil_RecoilRoot_react;
1296
1297const {
1298 AbstractRecoilValue: AbstractRecoilValue$2,
1299 getRecoilValueAsLoadable: getRecoilValueAsLoadable$1,
1300 setRecoilValue: setRecoilValue$1,
1301 setUnvalidatedRecoilValue: setUnvalidatedRecoilValue$1,
1302 subscribeToRecoilValue: subscribeToRecoilValue$1
1303} = Recoil_RecoilValue;
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325function cloneState(state, opts) {
1326 return {
1327 isSnapshot: opts.isSnapshot,
1328 transactionMetadata: { ...state.transactionMetadata
1329 },
1330 atomValues: new Map(state.atomValues),
1331 nonvalidatedAtoms: new Map(state.nonvalidatedAtoms),
1332 dirtyAtoms: new Set(state.dirtyAtoms),
1333 nodeDeps: new Map(state.nodeDeps),
1334 nodeToNodeSubscriptions: Recoil_mapMap(state.nodeToNodeSubscriptions, keys => new Set(keys)),
1335 nodeToComponentSubscriptions: Recoil_mapMap(state.nodeToComponentSubscriptions, subsByAtom => new Map(subsByAtom))
1336 };
1337}
1338
1339function handleLoadable(loadable, atom, storeRef) {
1340 // We can't just throw the promise we are waiting on to Suspense. If the
1341 // upstream dependencies change it may produce a state in which the component
1342 // can render, but it would still be suspended on a Promise that may never resolve.
1343 if (loadable.state === 'hasValue') {
1344 return loadable.contents;
1345 } else if (loadable.state === 'loading') {
1346 const promise = new Promise(resolve => {
1347 storeRef.current.getState().suspendedComponentResolvers.add(resolve);
1348 });
1349 throw promise;
1350 } else if (loadable.state === 'hasError') {
1351 throw loadable.contents;
1352 } else {
1353 throw new Error(`Invalid value of loadable atom "${atom.key}"`);
1354 }
1355}
1356
1357function valueFromValueOrUpdater(store, state, recoilValue, valueOrUpdater) {
1358 if (typeof valueOrUpdater === 'function') {
1359 // Updater form: pass in the current value. Throw if the current value
1360 // is unavailable (namely when updating an async selector that's
1361 // pending or errored):
1362 const current = peekNodeLoadable$2(store, state, recoilValue.key);
1363
1364 if (current.state === 'loading') {
1365 throw new RecoilValueNotReady$1(recoilValue.key);
1366 } else if (current.state === 'hasError') {
1367 throw current.contents;
1368 } // T itself may be a function, so our refinement is not sufficient:
1369
1370
1371 return valueOrUpdater(current.contents); // flowlint-line unclear-type:off
1372 } else {
1373 return valueOrUpdater;
1374 }
1375}
1376
1377function useInterface() {
1378 const storeRef = useStoreRef$1();
1379 const [_, forceUpdate] = useState$1([]);
1380 const recoilValuesUsed = useRef$1(new Set());
1381 recoilValuesUsed.current = new Set(); // Track the RecoilValues used just during this render
1382
1383 const previousSubscriptions = useRef$1(new Set());
1384 const subscriptions = useRef$1(new Map());
1385 const unsubscribeFrom = useCallback(key => {
1386 const sub = subscriptions.current.get(key);
1387
1388 if (sub) {
1389 sub.release(storeRef.current);
1390 subscriptions.current.delete(key);
1391 }
1392 }, [storeRef, subscriptions]);
1393 useEffect$1(() => {
1394 const store = storeRef.current;
1395
1396 function updateState(_state, key) {
1397 if (!subscriptions.current.has(key)) {
1398 return;
1399 }
1400
1401 forceUpdate([]);
1402 }
1403
1404 Recoil_differenceSets(recoilValuesUsed.current, previousSubscriptions.current).forEach(key => {
1405 if (subscriptions.current.has(key)) {
1406 Recoil_expectationViolation(`Double subscription to RecoilValue "${key}"`);
1407 return;
1408 }
1409
1410 const sub = subscribeToRecoilValue$1(store, new AbstractRecoilValue$2(key), state => {
1411 Recoil_Tracing.trace('RecoilValue subscription fired', key, () => {
1412 updateState(state, key);
1413 });
1414 });
1415 subscriptions.current.set(key, sub);
1416 Recoil_Tracing.trace('initial update on subscribing', key, () => {
1417 updateState(store.getState(), key);
1418 });
1419 });
1420 Recoil_differenceSets(previousSubscriptions.current, recoilValuesUsed.current).forEach(key => {
1421 unsubscribeFrom(key);
1422 });
1423 previousSubscriptions.current = recoilValuesUsed.current;
1424 });
1425 useEffect$1(() => {
1426 const subs = subscriptions.current;
1427 return () => subs.forEach((_, key) => unsubscribeFrom(key));
1428 }, [unsubscribeFrom]);
1429 return useMemo(() => {
1430 function useSetRecoilState(recoilState) {
1431 return newValueOrUpdater => {
1432 var _storeState$nextTree;
1433
1434 const storeState = storeRef.current.getState();
1435 const newValue = valueFromValueOrUpdater(storeRef.current, (_storeState$nextTree = storeState.nextTree) !== null && _storeState$nextTree !== void 0 ? _storeState$nextTree : storeState.currentTree, recoilState, newValueOrUpdater);
1436 setRecoilValue$1(storeRef.current, recoilState, newValue);
1437 };
1438 }
1439
1440 function useResetRecoilState(recoilState) {
1441 return () => setRecoilValue$1(storeRef.current, recoilState, DEFAULT_VALUE$2);
1442 }
1443
1444 function useRecoilValueLoadable(recoilValue) {
1445 if (!recoilValuesUsed.current.has(recoilValue.key)) {
1446 recoilValuesUsed.current = setByAddingToSet$3(recoilValuesUsed.current, recoilValue.key);
1447 } // TODO Restore optimization to memoize lookup
1448
1449
1450 return getRecoilValueAsLoadable$1(storeRef.current, recoilValue);
1451 }
1452
1453 function useRecoilValue(recoilValue) {
1454 const loadable = useRecoilValueLoadable(recoilValue);
1455 return handleLoadable(loadable, recoilValue, storeRef);
1456 }
1457
1458 function useRecoilState(recoilState) {
1459 return [useRecoilValue(recoilState), useSetRecoilState(recoilState)];
1460 }
1461
1462 function useRecoilStateLoadable(recoilState) {
1463 return [useRecoilValueLoadable(recoilState), useSetRecoilState(recoilState)];
1464 }
1465
1466 return {
1467 getRecoilValue: useRecoilValue,
1468 getRecoilValueLoadable: useRecoilValueLoadable,
1469 getRecoilState: useRecoilState,
1470 getRecoilStateLoadable: useRecoilStateLoadable,
1471 getSetRecoilState: useSetRecoilState,
1472 getResetRecoilState: useResetRecoilState
1473 };
1474 }, [recoilValuesUsed, storeRef]);
1475}
1476/**
1477 Returns the value represented by the RecoilValue.
1478 If the value is pending, it will throw a Promise to suspend the component,
1479 if the value is an error it will throw it for the nearest React error boundary.
1480 This will also subscribe the component for any updates in the value.
1481 */
1482
1483
1484function useRecoilValue(recoilValue) {
1485 return useInterface().getRecoilValue(recoilValue);
1486}
1487/**
1488 Like useRecoilValue(), but either returns the value if available or
1489 just undefined if not available for any reason, such as pending or error.
1490*/
1491
1492
1493function useRecoilValueLoadable(recoilValue) {
1494 return useInterface().getRecoilValueLoadable(recoilValue);
1495}
1496/**
1497 Returns a function that allows the value of a RecoilState to be updated, but does
1498 not subscribe the compoment to changes to that RecoilState.
1499*/
1500
1501
1502function useSetRecoilState(recoilState) {
1503 return useCallback(useInterface().getSetRecoilState(recoilState), [recoilState]);
1504}
1505/**
1506 Returns a function that will reset the value of a RecoilState to its default
1507*/
1508
1509
1510function useResetRecoilState(recoilState) {
1511 return useCallback(useInterface().getResetRecoilState(recoilState), [recoilState]);
1512}
1513/**
1514 Equivalent to useState(). Allows the value of the RecoilState to be read and written.
1515 Subsequent updates to the RecoilState will cause the component to re-render. If the
1516 RecoilState is pending, this will suspend the compoment and initiate the
1517 retrieval of the value. If evaluating the RecoilState resulted in an error, this will
1518 throw the error so that the nearest React error boundary can catch it.
1519*/
1520
1521
1522function useRecoilState(recoilState) {
1523 const recoilInterface = useInterface();
1524 const [value] = recoilInterface.getRecoilState(recoilState);
1525 const setValue = useCallback(recoilInterface.getSetRecoilState(recoilState), [recoilState]);
1526 return [value, setValue];
1527}
1528/**
1529 Like useRecoilState(), but does not cause Suspense or React error handling. Returns
1530 an object that indicates whether the RecoilState is available, pending, or
1531 unavailable due to an error.
1532*/
1533
1534
1535function useRecoilStateLoadable(recoilState) {
1536 const recoilInterface = useInterface();
1537 const [value] = recoilInterface.getRecoilStateLoadable(recoilState);
1538 const setValue = useCallback(recoilInterface.getSetRecoilState(recoilState), [recoilState]);
1539 return [value, setValue];
1540}
1541
1542function useTransactionSubscription(callback) {
1543 const storeRef = useStoreRef$1();
1544 useEffect$1(() => {
1545 const sub = storeRef.current.subscribeToTransactions(callback);
1546 return sub.release;
1547 }, [callback, storeRef]);
1548} // TODO instead of force update can put snapshot into local state
1549
1550
1551function useTreeStateClone() {
1552 const [_, setState] = useState$1(0);
1553 const forceUpdate = useCallback(() => setState(x => x + 1), []);
1554 useTransactionSubscription(forceUpdate);
1555 const storeRef = useStoreRef$1();
1556 return cloneState(storeRef.current.getState().currentTree, {
1557 isSnapshot: true
1558 });
1559}
1560
1561function useSnapshotWithStateChange(transaction) {
1562 const storeRef = useStoreRef$1();
1563 let snapshot = useTreeStateClone();
1564
1565 const update = ({
1566 key
1567 }, updater) => {
1568 [snapshot] = setNodeValue$3(storeRef.current, snapshot, key, peekNodeLoadable$2(storeRef.current, snapshot, key).map(updater));
1569 };
1570
1571 transaction(update);
1572 const atomValues = Recoil_mapMap(snapshot.atomValues, v => v.contents); // Only report atoms, not selectors
1573
1574 const updatedAtoms = Recoil_intersectSets(snapshot.dirtyAtoms, new Set(atomValues.keys()));
1575 return {
1576 atomValues,
1577 updatedAtoms
1578 };
1579}
1580
1581function externallyVisibleAtomValuesInState(state) {
1582 const atomValues = state.atomValues;
1583 const persistedAtomContentsValues = Recoil_mapMap(Recoil_filterMap(atomValues, (v, k) => {
1584 var _node$options;
1585
1586 const node = getNode$2(k);
1587 const persistence = (_node$options = node.options) === null || _node$options === void 0 ? void 0 : _node$options.persistence_UNSTABLE;
1588 return persistence != null && persistence.type !== 'none' && v.state === 'hasValue';
1589 }), v => v.contents); // Merge in nonvalidated atoms; we may not have defs for them but they will
1590 // all have persistence on or they wouldn't be there in the first place.
1591
1592 return Recoil_mergeMaps(state.nonvalidatedAtoms, persistedAtomContentsValues);
1593}
1594
1595/**
1596 Calls the given callback after any atoms have been modified and the consequent
1597 component re-renders have been committed. This is intended for persisting
1598 the values of the atoms to storage. The stored values can then be restored
1599 using the useSetUnvalidatedAtomValues hook.
1600
1601 The callback receives the following info:
1602
1603 atomValues: The current value of every atom that is both persistable (persistence
1604 type not set to 'none') and whose value is available (not in an
1605 error or loading state).
1606
1607 previousAtomValues: The value of every persistable and available atom before
1608 the transaction began.
1609
1610 atomInfo: A map containing the persistence settings for each atom. Every key
1611 that exists in atomValues will also exist in atomInfo.
1612
1613 modifiedAtoms: The set of atoms that were written to during the transaction.
1614
1615 transactionMetadata: Arbitrary information that was added via the
1616 useSetUnvalidatedAtomValues hook. Useful for ignoring the useSetUnvalidatedAtomValues
1617 transaction, to avoid loops.
1618*/
1619function useTransactionObservation(callback) {
1620 useTransactionSubscription(useCallback((store, previousState) => {
1621 let nextTree = store.getState().nextTree;
1622
1623 if (!nextTree) {
1624 Recoil_recoverableViolation('Transaction subscribers notified without a next tree being present -- this is a bug in Recoil');
1625 nextTree = store.getState().currentTree; // attempt to trundle on
1626 }
1627
1628 const atomValues = externallyVisibleAtomValuesInState(nextTree);
1629 const previousAtomValues = externallyVisibleAtomValuesInState(previousState);
1630 const atomInfo = Recoil_mapMap(nodes$1, node => {
1631 var _node$options$persist, _node$options2, _node$options2$persis, _node$options$persist2, _node$options3, _node$options3$persis;
1632
1633 return {
1634 persistence_UNSTABLE: {
1635 type: (_node$options$persist = (_node$options2 = node.options) === null || _node$options2 === void 0 ? void 0 : (_node$options2$persis = _node$options2.persistence_UNSTABLE) === null || _node$options2$persis === void 0 ? void 0 : _node$options2$persis.type) !== null && _node$options$persist !== void 0 ? _node$options$persist : 'none',
1636 backButton: (_node$options$persist2 = (_node$options3 = node.options) === null || _node$options3 === void 0 ? void 0 : (_node$options3$persis = _node$options3.persistence_UNSTABLE) === null || _node$options3$persis === void 0 ? void 0 : _node$options3$persis.backButton) !== null && _node$options$persist2 !== void 0 ? _node$options$persist2 : false
1637 }
1638 };
1639 });
1640 const modifiedAtoms = new Set(nextTree.dirtyAtoms);
1641 callback({
1642 atomValues,
1643 previousAtomValues,
1644 atomInfo,
1645 modifiedAtoms,
1646 transactionMetadata: { ...nextTree.transactionMetadata
1647 }
1648 });
1649 }, [callback]));
1650}
1651
1652function useGoToSnapshot() {
1653 const storeRef = useStoreRef$1();
1654 return snapshot => {
1655 reactDom.unstable_batchedUpdates(() => {
1656 snapshot.updatedAtoms.forEach(key => {
1657 setRecoilValue$1(storeRef.current, new AbstractRecoilValue$2(key), snapshot.atomValues.get(key));
1658 });
1659 });
1660 };
1661}
1662
1663function useSetUnvalidatedAtomValues() {
1664 const storeRef = useStoreRef$1();
1665 return (values, transactionMetadata = {}) => {
1666 reactDom.unstable_batchedUpdates(() => {
1667 storeRef.current.addTransactionMetadata(transactionMetadata);
1668 values.forEach((value, key) => setUnvalidatedRecoilValue$1(storeRef.current, new AbstractRecoilValue$2(key), value));
1669 });
1670 };
1671}
1672
1673class Sentinel {}
1674
1675const SENTINEL = new Sentinel();
1676
1677function useRecoilCallback(fn, deps) {
1678 const storeRef = useStoreRef$1();
1679 return useCallback((...args) => {
1680 let snapshot = cloneState(storeRef.current.getState().currentTree, {
1681 isSnapshot: true
1682 });
1683
1684 function getLoadable(recoilValue) {
1685 let result;
1686 [snapshot, result] = getNodeLoadable$2(storeRef.current, snapshot, recoilValue.key);
1687 return result;
1688 }
1689
1690 function getPromise(recoilValue) {
1691 {
1692 return getLoadable(recoilValue).toPromise();
1693 }
1694 }
1695
1696 function set(recoilState, newValueOrUpdater) {
1697 const newValue = valueFromValueOrUpdater(storeRef.current, snapshot, recoilState, newValueOrUpdater);
1698 setRecoilValue$1(storeRef.current, recoilState, newValue);
1699 }
1700
1701 function reset(recoilState) {
1702 setRecoilValue$1(storeRef.current, recoilState, DEFAULT_VALUE$2);
1703 }
1704
1705 let ret = SENTINEL;
1706 reactDom.unstable_batchedUpdates(() => {
1707 // flowlint-next-line unclear-type:off
1708 ret = fn({
1709 getPromise,
1710 getLoadable,
1711 set,
1712 reset
1713 }, ...args);
1714 });
1715 Recoil_invariant(!(ret instanceof Sentinel), 'unstable_batchedUpdates should return immediately');
1716 return ret;
1717 }, deps != null ? [...deps, storeRef] : undefined // eslint-disable-line fb-www/react-hooks-deps
1718 );
1719}
1720
1721var Recoil_Hooks = {
1722 useRecoilCallback,
1723 useRecoilValue,
1724 useRecoilValueLoadable,
1725 useRecoilState,
1726 useRecoilStateLoadable,
1727 useSetRecoilState,
1728 useResetRecoilState,
1729 useRecoilInterface: useInterface,
1730 useTransactionSubscription,
1731 useSnapshotWithStateChange,
1732 useTransactionObservation,
1733 useGoToSnapshot,
1734 useSetUnvalidatedAtomValues
1735};
1736
1737/**
1738 * Copyright 2004-present Facebook. All Rights Reserved.
1739 *
1740 * Implements (a subset of) the interface of built-in Map but supports arrays as
1741 * keys. Two keys are equal if corresponding elements are equal according to the
1742 * equality semantics of built-in Map. Operations are at worst O(n*b) where n is
1743 * the array length and b is the complexity of the built-in operation.
1744 *
1745 * @emails oncall+perf_viz
1746 *
1747 * @format
1748 */
1749
1750var Recoil_ArrayKeyedMap = /*#__PURE__*/Object.freeze({
1751 __proto__: null
1752});
1753
1754function cacheWithReferenceEquality() {
1755 return new Recoil_ArrayKeyedMap();
1756}
1757
1758var Recoil_cacheWithReferenceEquality = cacheWithReferenceEquality;
1759
1760/**
1761 * Copyright 2004-present Facebook. All Rights Reserved.
1762 *
1763 * This is a stub for some integration into FB internal stuff
1764 */
1765function startPerfBlock(id) {
1766 return () => {};
1767}
1768
1769var Recoil_PerformanceTimings = {
1770 startPerfBlock
1771};
1772
1773/**
1774 * (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
1775 *
1776 * @emails oncall+perf_viz
1777 *
1778 * @format
1779 */
1780/**
1781 * The everySet() method tests whether all elements in the given Set pass the
1782 * test implemented by the provided function.
1783 */
1784
1785function everySet(set, callback, context) {
1786 const iterator = set.entries();
1787 let current = iterator.next();
1788
1789 while (!current.done) {
1790 const entry = current.value;
1791
1792 if (!callback.call(context, entry[1], entry[0], set)) {
1793 return false;
1794 }
1795
1796 current = iterator.next();
1797 }
1798
1799 return true;
1800}
1801
1802var Recoil_everySet = everySet;
1803
1804/**
1805 * Checks if two sets are equal
1806 */
1807
1808
1809function equalsSet(one, two) {
1810 if (one.size !== two.size) {
1811 return false;
1812 }
1813
1814 return Recoil_everySet(one, value => two.has(value));
1815}
1816
1817var Recoil_equalsSet = equalsSet;
1818
1819const emptySet$1 = Object.freeze(new Set());
1820
1821const {
1822 mapBySettingInMap: mapBySettingInMap$3,
1823 mapByUpdatingInMap: mapByUpdatingInMap$2,
1824 setByAddingToSet: setByAddingToSet$4,
1825 setByDeletingFromSet: setByDeletingFromSet$1
1826} = Recoil_CopyOnWrite;
1827
1828
1829
1830const {
1831 detectCircularDependencies: detectCircularDependencies$1,
1832 getNodeLoadable: getNodeLoadable$3,
1833 setNodeValue: setNodeValue$4
1834} = Recoil_FunctionalCore;
1835
1836const {
1837 loadableWithError: loadableWithError$1,
1838 loadableWithPromise: loadableWithPromise$1,
1839 loadableWithValue: loadableWithValue$2
1840} = Recoil_Loadable;
1841
1842const {
1843 DEFAULT_VALUE: DEFAULT_VALUE$3,
1844 RecoilValueNotReady: RecoilValueNotReady$2,
1845 registerNode: registerNode$2
1846} = Recoil_Node;
1847
1848const {
1849 startPerfBlock: startPerfBlock$1
1850} = Recoil_PerformanceTimings;
1851
1852const {
1853 isRecoilValue: isRecoilValue$2
1854} = Recoil_RecoilValue;
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864// flowlint-next-line unclear-type:off
1865const emptySet$2 = Object.freeze(new Set());
1866
1867function cacheKeyFromDepValues(depValues) {
1868 const answer = [];
1869
1870 for (const key of Array.from(depValues.keys()).sort()) {
1871 const loadable = Recoil_nullthrows(depValues.get(key));
1872 answer.push(key);
1873 answer.push(loadable.contents);
1874 }
1875
1876 return answer;
1877}
1878/* eslint-disable no-redeclare */
1879
1880
1881function selector$1(options) {
1882 const {
1883 key,
1884 get,
1885 cacheImplementation_UNSTABLE: cacheImplementation
1886 } = options;
1887 const set = options.set != null ? options.set : undefined; // flow
1888
1889 let cache = cacheImplementation !== null && cacheImplementation !== void 0 ? cacheImplementation : Recoil_cacheWithReferenceEquality();
1890
1891 function putIntoCache(store, cacheKey, loadable) {
1892 if (loadable.state !== 'loading') {
1893 // Synchronous result
1894 if (!options.dangerouslyAllowMutability === true) {
1895 Recoil_deepFreezeValue(loadable.contents);
1896 }
1897 } else {
1898 // Asynchronous result
1899 // When the promise resolves, we need to replace the loading state in the
1900 // cache and fire any external subscriptions to re-render with the new value.
1901 loadable.contents.then(result => {
1902 // If the value is now resolved, then update the cache with the new value
1903 if (!options.dangerouslyAllowMutability === true) {
1904 Recoil_deepFreezeValue(result);
1905 }
1906
1907 cache = cache.set(cacheKey, loadableWithValue$2(result)); // TODO Potential optimization: I think this is updating the cache
1908 // with a cacheKey of the dep when it wasn't ready yet. We could also
1909 // theoretically put the result in the cache for a cacheKey with the
1910 // dep resolved. If we had some way of figuring out what that cacheKey was..
1911 // Note that this optimization would change the user visible behavior slightly,
1912 // see the unit test "useRecoilState - selector catching promise 2".
1913 // If the user catches and handles pending async dependencies, then returns
1914 // a promise that resolves when they are available there is a question if
1915 // the result of that promise should be the value of the selector, or if
1916 // the selector should re-evaluate when the dependency is available.
1917 // If the promise returned and the pending dependency resolve at different
1918 // times, then the behaviour is better defined, as in the unit test,
1919 // "useRecoilState - selector catching promise and resolving asynchronously"
1920 // Fire subscriptions to re-render any subscribed components with the new value.
1921 // The store uses the CURRENT state, not the old state from which
1922 // this was called. That state likely doesn't have the subscriptions saved yet.
1923
1924 store.fireNodeSubscriptions(new Set([key]), 'now');
1925 return result;
1926 }).catch(error => {
1927 // TODO Figure out why we are catching promises here versus evaluateSelectorFunction
1928 // OH, I see why. Ok, work on this.
1929 if (Recoil_isPromise(error)) {
1930 return error;
1931 } // The async value was rejected with an error. Update the cache with
1932 // the error and fire subscriptions to re-render.
1933
1934
1935 if (!options.dangerouslyAllowMutability === true) {
1936 Recoil_deepFreezeValue(error);
1937 }
1938
1939 cache = cache.set(cacheKey, loadableWithError$1(error));
1940 store.fireNodeSubscriptions(new Set([key]), 'now');
1941 return error;
1942 });
1943 }
1944
1945 cache = cache.set(cacheKey, loadable);
1946 }
1947
1948 function getFromCache(store, state) {
1949 var _state$nodeDeps$get;
1950
1951 let newState = state; // First, get the current deps for this selector
1952
1953 const currentDeps = (_state$nodeDeps$get = state.nodeDeps.get(key)) !== null && _state$nodeDeps$get !== void 0 ? _state$nodeDeps$get : emptySet$2;
1954 const depValues = new Map(Array.from(currentDeps).sort().map(depKey => {
1955 const [nextState, loadable] = getNodeLoadable$3(store, newState, depKey);
1956 newState = nextState;
1957 return [depKey, loadable];
1958 })); // Always cache and evaluate a selector
1959 // It may provide a result even when not all deps are available.
1960
1961 const cacheKey = cacheKeyFromDepValues(depValues);
1962 const cached = cache.get(cacheKey);
1963
1964 if (cached != null) {
1965 return [newState, cached];
1966 } // Cache miss, compute the value
1967
1968
1969 const [nextState, loadable, newDepValues] = computeAndSubscribeSelector(store, newState);
1970 newState = nextState; // Save result in cache
1971
1972 const newCacheKey = cacheKeyFromDepValues(newDepValues);
1973 putIntoCache(store, newCacheKey, loadable);
1974 return [newState, loadable];
1975 }
1976
1977 function evaluateSelectorFunction(store, state) {
1978 const endPerfBlock = startPerfBlock$1(key);
1979 let newState = state;
1980 const depValues = new Map();
1981
1982 function getRecoilValue({
1983 key
1984 }) {
1985 let loadable;
1986 [newState, loadable] = getNodeLoadable$3(store, state, key);
1987 depValues.set(key, loadable);
1988
1989 if (loadable.state === 'hasValue') {
1990 return loadable.contents;
1991 } else {
1992 throw loadable.contents; // Promise or error
1993 }
1994 }
1995
1996 try {
1997 // The big moment!
1998 const output = get({
1999 get: getRecoilValue
2000 });
2001 const result = isRecoilValue$2(output) ? getRecoilValue(output) : output; // TODO Allow user to also return Loadables for improved composability
2002
2003 const loadable = !Recoil_isPromise(result) ? ( // The selector returned a simple synchronous value, so let's use it!
2004 endPerfBlock(), loadableWithValue$2(result)) : // The user returned a promise for an asynchronous selector. This will
2005 // resolve to the proper value of the selector when available.
2006 loadableWithPromise$1(result.finally(endPerfBlock));
2007 return [newState, loadable, depValues];
2008 } catch (errorOrDepPromise) {
2009 const loadable = !Recoil_isPromise(errorOrDepPromise) ? ( // There was a synchronous error in the evaluation
2010 endPerfBlock(), loadableWithError$1(errorOrDepPromise)) : // If an asynchronous dependency was not ready, then return a promise that
2011 // will resolve when we finally do have a real value or error for the selector.
2012 loadableWithPromise$1(errorOrDepPromise.then(() => {
2013 // The dependency we were waiting on is now available.
2014 // So, let's try to evaluate the selector again and return that value.
2015 let loadable = loadableWithError$1(new Error('Internal Recoil Selector Error') // To make Flow happy
2016 ); // This is done asynchronously, so we need to make sure to save the state
2017
2018 store.replaceState(asyncState => {
2019 let newAsyncState;
2020 [newAsyncState, loadable] = getFromCache(store, asyncState);
2021 return newAsyncState;
2022 });
2023
2024 if (loadable.state === 'hasError') {
2025 throw loadable.contents;
2026 } // Either the re-try provided a value, which we will use, or it
2027 // got blocked again. In that case this is a promise and we'll try again.
2028
2029
2030 return loadable.contents;
2031 }).finally(endPerfBlock));
2032 return [newState, loadable, depValues];
2033 }
2034 }
2035
2036 function computeAndSubscribeSelector(store, state) {
2037 var _state$nodeDeps$get2;
2038
2039 // Call the selector get evaluation function to get the new value
2040 const [newStateFromEvaluate, loadable, newDepValues] = evaluateSelectorFunction(store, state);
2041 let newState = newStateFromEvaluate; // Update state with new upsteram dependencies
2042
2043 const oldDeps = (_state$nodeDeps$get2 = state.nodeDeps.get(key)) !== null && _state$nodeDeps$get2 !== void 0 ? _state$nodeDeps$get2 : emptySet$2;
2044 const newDeps = new Set(newDepValues.keys());
2045 newState = Recoil_equalsSet(oldDeps, newDeps) ? newState : { ...newState,
2046 nodeDeps: mapBySettingInMap$3(newState.nodeDeps, key, newDeps)
2047 }; // Update state with new downstream subscriptions
2048
2049 const addedDeps = Recoil_differenceSets(newDeps, oldDeps);
2050 const removedDeps = Recoil_differenceSets(oldDeps, newDeps);
2051
2052 for (const upstreamNode of addedDeps) {
2053 newState = { ...newState,
2054 nodeToNodeSubscriptions: mapByUpdatingInMap$2(newState.nodeToNodeSubscriptions, upstreamNode, subs => setByAddingToSet$4(subs !== null && subs !== void 0 ? subs : emptySet$2, key))
2055 };
2056 }
2057
2058 for (const upstreamNode of removedDeps) {
2059 newState = { ...newState,
2060 nodeToNodeSubscriptions: mapByUpdatingInMap$2(newState.nodeToNodeSubscriptions, upstreamNode, subs => setByDeletingFromSet$1(subs !== null && subs !== void 0 ? subs : emptySet$2, key))
2061 };
2062 }
2063
2064 if (__DEV__) {
2065 detectCircularDependencies$1(newState, [key]);
2066 }
2067
2068 return [newState, loadable, newDepValues];
2069 }
2070
2071 function myGet(store, state) {
2072 // TODO memoize a value if no deps have changed to avoid a cache lookup
2073 // Lookup the node value in the cache. If not there, then compute
2074 // the value and update the state with any changed node subscriptions.
2075 return getFromCache(store, state);
2076 }
2077
2078 if (set != null) {
2079 function mySet(store, state, newValue) {
2080 let newState = state;
2081 const writtenNodes = new Set();
2082
2083 function getRecoilValue({
2084 key
2085 }) {
2086 const [nextState, loadable] = getNodeLoadable$3(store, newState, key);
2087 newState = nextState;
2088
2089 if (loadable.state === 'hasValue') {
2090 return loadable.contents;
2091 } else if (loadable.state === 'loading') {
2092 throw new RecoilValueNotReady$2(key);
2093 } else {
2094 throw loadable.contents;
2095 }
2096 }
2097
2098 function setRecoilState(recoilState, valueOrUpdater) {
2099 const newValue = typeof valueOrUpdater === 'function' ? // cast to any because we can't restrict type S from being a function itself without losing support for opaque types
2100 // flowlint-next-line unclear-type:off
2101 valueOrUpdater(getRecoilValue(recoilState)) : valueOrUpdater;
2102 let written;
2103 [newState, written] = setNodeValue$4(store, newState, recoilState.key, newValue);
2104 written.forEach(atom => writtenNodes.add(atom));
2105 }
2106
2107 function resetRecoilState(recoilState) {
2108 setRecoilState(recoilState, DEFAULT_VALUE$3);
2109 }
2110
2111 set({
2112 set: setRecoilState,
2113 get: getRecoilValue,
2114 reset: resetRecoilState
2115 }, newValue);
2116 return [newState, writtenNodes];
2117 }
2118
2119 return registerNode$2({
2120 key,
2121 options,
2122 get: myGet,
2123 set: mySet
2124 });
2125 } else {
2126 return registerNode$2({
2127 key,
2128 options,
2129 get: myGet
2130 });
2131 }
2132}
2133/* eslint-enable no-redeclare */
2134
2135
2136var Recoil_selector_OLD = selector$1;
2137
2138const selector$2 = Recoil_selector_OLD;
2139var Recoil_selector = selector$2;
2140
2141const {
2142 useRecoilCallback: useRecoilCallback$1,
2143 useRecoilState: useRecoilState$1,
2144 useRecoilStateLoadable: useRecoilStateLoadable$1,
2145 useRecoilValue: useRecoilValue$1,
2146 useRecoilValueLoadable: useRecoilValueLoadable$1,
2147 useResetRecoilState: useResetRecoilState$1,
2148 useSetRecoilState: useSetRecoilState$1,
2149 useSetUnvalidatedAtomValues: useSetUnvalidatedAtomValues$1,
2150 useTransactionObservation: useTransactionObservation$1,
2151 useTransactionSubscription: useTransactionSubscription$1
2152} = Recoil_Hooks;
2153
2154const {
2155 DefaultValue: DefaultValue$2
2156} = Recoil_Node;
2157
2158const {
2159 RecoilRoot: RecoilRoot$1
2160} = Recoil_RecoilRoot_react;
2161
2162const {
2163 isRecoilValue: isRecoilValue$3
2164} = Recoil_RecoilValue;
2165
2166
2167
2168var Recoil = {
2169 // Types
2170 DefaultValue: DefaultValue$2,
2171 // Components
2172 RecoilRoot: RecoilRoot$1,
2173 // RecoilValues
2174 atom: Recoil_atom,
2175 selector: Recoil_selector,
2176 // Hooks that accept RecoilValues
2177 useRecoilValue: useRecoilValue$1,
2178 useRecoilValueLoadable: useRecoilValueLoadable$1,
2179 useRecoilState: useRecoilState$1,
2180 useRecoilStateLoadable: useRecoilStateLoadable$1,
2181 useSetRecoilState: useSetRecoilState$1,
2182 useResetRecoilState: useResetRecoilState$1,
2183 // Hooks for asynchronous Recoil
2184 useRecoilCallback: useRecoilCallback$1,
2185 // Hooks for Persistence/Debugging
2186 useTransactionObservation_UNSTABLE: useTransactionObservation$1,
2187 useTransactionSubscription_UNSTABLE: useTransactionSubscription$1,
2188 useSetUnvalidatedAtomValues_UNSTABLE: useSetUnvalidatedAtomValues$1,
2189 // Other functions
2190 isRecoilValue: isRecoilValue$3
2191};
2192var Recoil_1 = Recoil.DefaultValue;
2193var Recoil_2 = Recoil.RecoilRoot;
2194var Recoil_3 = Recoil.atom;
2195var Recoil_4 = Recoil.selector;
2196var Recoil_5 = Recoil.useRecoilValue;
2197var Recoil_6 = Recoil.useRecoilValueLoadable;
2198var Recoil_7 = Recoil.useRecoilState;
2199var Recoil_8 = Recoil.useRecoilStateLoadable;
2200var Recoil_9 = Recoil.useSetRecoilState;
2201var Recoil_10 = Recoil.useResetRecoilState;
2202var Recoil_11 = Recoil.useRecoilCallback;
2203var Recoil_12 = Recoil.useTransactionObservation_UNSTABLE;
2204var Recoil_13 = Recoil.useTransactionSubscription_UNSTABLE;
2205var Recoil_14 = Recoil.useSetUnvalidatedAtomValues_UNSTABLE;
2206var Recoil_15 = Recoil.isRecoilValue;
2207
2208exports.DefaultValue = Recoil_1;
2209exports.RecoilRoot = Recoil_2;
2210exports.atom = Recoil_3;
2211exports.default = Recoil;
2212exports.isRecoilValue = Recoil_15;
2213exports.selector = Recoil_4;
2214exports.useRecoilCallback = Recoil_11;
2215exports.useRecoilState = Recoil_7;
2216exports.useRecoilStateLoadable = Recoil_8;
2217exports.useRecoilValue = Recoil_5;
2218exports.useRecoilValueLoadable = Recoil_6;
2219exports.useResetRecoilState = Recoil_10;
2220exports.useSetRecoilState = Recoil_9;
2221exports.useSetUnvalidatedAtomValues_UNSTABLE = Recoil_14;
2222exports.useTransactionObservation_UNSTABLE = Recoil_12;
2223exports.useTransactionSubscription_UNSTABLE = Recoil_13;