UNPKG

19.1 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var react = require('react');
6var jotai = require('jotai');
7
8function _extends() {
9 _extends = Object.assign ? Object.assign.bind() : function (target) {
10 for (var i = 1; i < arguments.length; i++) {
11 var source = arguments[i];
12
13 for (var key in source) {
14 if (Object.prototype.hasOwnProperty.call(source, key)) {
15 target[key] = source[key];
16 }
17 }
18 }
19
20 return target;
21 };
22 return _extends.apply(this, arguments);
23}
24
25function _unsupportedIterableToArray(o, minLen) {
26 if (!o) return;
27 if (typeof o === "string") return _arrayLikeToArray(o, minLen);
28 var n = Object.prototype.toString.call(o).slice(8, -1);
29 if (n === "Object" && o.constructor) n = o.constructor.name;
30 if (n === "Map" || n === "Set") return Array.from(o);
31 if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
32}
33
34function _arrayLikeToArray(arr, len) {
35 if (len == null || len > arr.length) len = arr.length;
36
37 for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
38
39 return arr2;
40}
41
42function _createForOfIteratorHelperLoose(o, allowArrayLike) {
43 var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
44 if (it) return (it = it.call(o)).next.bind(it);
45
46 if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
47 if (it) o = it;
48 var i = 0;
49 return function () {
50 if (i >= o.length) return {
51 done: true
52 };
53 return {
54 done: false,
55 value: o[i++]
56 };
57 };
58 }
59
60 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
61}
62
63var RESTORE_ATOMS = 'h';
64var DEV_SUBSCRIBE_STATE = 'n';
65var DEV_GET_MOUNTED_ATOMS = 'l';
66var DEV_GET_ATOM_STATE = 'a';
67var DEV_GET_MOUNTED = 'm';
68
69var atomToPrintable$1 = function atomToPrintable(atom) {
70 return atom.debugLabel || atom.toString();
71};
72
73var stateToPrintable = function stateToPrintable(_ref) {
74 var store = _ref[0],
75 atoms = _ref[1];
76 return Object.fromEntries(atoms.flatMap(function (atom) {
77 var _store$DEV_GET_MOUNTE, _store$DEV_GET_ATOM_S;
78
79 var mounted = (_store$DEV_GET_MOUNTE = store[DEV_GET_MOUNTED]) == null ? void 0 : _store$DEV_GET_MOUNTE.call(store, atom);
80
81 if (!mounted) {
82 return [];
83 }
84
85 var dependents = mounted.t;
86 var atomState = ((_store$DEV_GET_ATOM_S = store[DEV_GET_ATOM_STATE]) == null ? void 0 : _store$DEV_GET_ATOM_S.call(store, atom)) || {};
87 return [[atomToPrintable$1(atom), _extends({}, 'e' in atomState && {
88 error: atomState.e
89 }, 'p' in atomState && {
90 promise: atomState.p
91 }, 'v' in atomState && {
92 value: atomState.v
93 }, {
94 dependents: Array.from(dependents).map(atomToPrintable$1)
95 })]];
96 }));
97};
98
99var useAtomsDebugValue = function useAtomsDebugValue(options) {
100 var _options$enabled;
101
102 var enabled = (_options$enabled = options == null ? void 0 : options.enabled) != null ? _options$enabled : process.env.NODE_ENV !== "production";
103 var ScopeContext = jotai.SECRET_INTERNAL_getScopeContext(options == null ? void 0 : options.scope);
104
105 var _useContext = react.useContext(ScopeContext),
106 store = _useContext.s;
107
108 var _useState = react.useState([]),
109 atoms = _useState[0],
110 setAtoms = _useState[1];
111
112 react.useEffect(function () {
113 var _store$DEV_SUBSCRIBE_;
114
115 if (!enabled) {
116 return;
117 }
118
119 var callback = function callback() {
120 var _store$DEV_GET_MOUNTE2;
121
122 setAtoms(Array.from(((_store$DEV_GET_MOUNTE2 = store[DEV_GET_MOUNTED_ATOMS]) == null ? void 0 : _store$DEV_GET_MOUNTE2.call(store)) || []));
123 };
124
125 var unsubscribe = (_store$DEV_SUBSCRIBE_ = store[DEV_SUBSCRIBE_STATE]) == null ? void 0 : _store$DEV_SUBSCRIBE_.call(store, callback);
126 callback();
127 return unsubscribe;
128 }, [enabled, store]);
129 react.useDebugValue([store, atoms], stateToPrintable);
130};
131
132function useAtomDevtools(anAtom, options, deprecatedScope) {
133 if (typeof options === 'string' || typeof deprecatedScope !== 'undefined') {
134 console.warn('DEPRECATED [useAtomDevtools] use DevtoolOptions');
135 options = {
136 name: options,
137 scope: deprecatedScope
138 };
139 }
140
141 var _ref = options || {},
142 enabled = _ref.enabled,
143 name = _ref.name,
144 scope = _ref.scope;
145
146 var extension;
147
148 try {
149 extension = (enabled != null ? enabled : process.env.NODE_ENV !== "production") && window.__REDUX_DEVTOOLS_EXTENSION__;
150 } catch (_unused) {}
151
152 if (!extension) {
153 if (process.env.NODE_ENV !== "production" && enabled) {
154 console.warn('Please install/enable Redux devtools extension');
155 }
156 }
157
158 var _useAtom = jotai.useAtom(anAtom, scope),
159 value = _useAtom[0],
160 setValue = _useAtom[1];
161
162 var lastValue = react.useRef(value);
163 var isTimeTraveling = react.useRef(false);
164 var devtools = react.useRef();
165 var atomName = name || anAtom.debugLabel || anAtom.toString();
166 react.useEffect(function () {
167 if (!extension) {
168 return;
169 }
170
171 var setValueIfWritable = function setValueIfWritable(value) {
172 if (typeof setValue === 'function') {
173 setValue(value);
174 return;
175 }
176
177 console.warn('[Warn] you cannot do write operations (Time-travelling, etc) in read-only atoms\n', anAtom);
178 };
179
180 devtools.current = extension.connect({
181 name: atomName
182 });
183 var unsubscribe = devtools.current.subscribe(function (message) {
184 var _message$payload3, _message$payload4;
185
186 if (message.type === 'ACTION' && message.payload) {
187 try {
188 setValueIfWritable(JSON.parse(message.payload));
189 } catch (e) {
190 console.error('please dispatch a serializable value that JSON.parse() support\n', e);
191 }
192 } else if (message.type === 'DISPATCH' && message.state) {
193 var _message$payload, _message$payload2;
194
195 if (((_message$payload = message.payload) == null ? void 0 : _message$payload.type) === 'JUMP_TO_ACTION' || ((_message$payload2 = message.payload) == null ? void 0 : _message$payload2.type) === 'JUMP_TO_STATE') {
196 isTimeTraveling.current = true;
197 setValueIfWritable(JSON.parse(message.state));
198 }
199 } else if (message.type === 'DISPATCH' && ((_message$payload3 = message.payload) == null ? void 0 : _message$payload3.type) === 'COMMIT') {
200 var _devtools$current;
201
202 (_devtools$current = devtools.current) == null ? void 0 : _devtools$current.init(lastValue.current);
203 } else if (message.type === 'DISPATCH' && ((_message$payload4 = message.payload) == null ? void 0 : _message$payload4.type) === 'IMPORT_STATE') {
204 var _message$payload$next;
205
206 var computedStates = ((_message$payload$next = message.payload.nextLiftedState) == null ? void 0 : _message$payload$next.computedStates) || [];
207 computedStates.forEach(function (_ref2, index) {
208 var state = _ref2.state;
209
210 if (index === 0) {
211 var _devtools$current2;
212
213 (_devtools$current2 = devtools.current) == null ? void 0 : _devtools$current2.init(state);
214 } else {
215 setValueIfWritable(state);
216 }
217 });
218 }
219 });
220 devtools.current.shouldInit = true;
221 return unsubscribe;
222 }, [anAtom, extension, atomName, setValue]);
223 react.useEffect(function () {
224 if (!devtools.current) {
225 return;
226 }
227
228 lastValue.current = value;
229
230 if (devtools.current.shouldInit) {
231 devtools.current.init(value);
232 devtools.current.shouldInit = false;
233 } else if (isTimeTraveling.current) {
234 isTimeTraveling.current = false;
235 } else {
236 devtools.current.send(atomName + " - " + new Date().toLocaleString(), value);
237 }
238 }, [anAtom, extension, atomName, value]);
239}
240
241var isEqualAtomsValues$1 = function isEqualAtomsValues(left, right) {
242 return left.size === right.size && Array.from(left).every(function (_ref) {
243 var left = _ref[0],
244 v = _ref[1];
245 return Object.is(right.get(left), v);
246 });
247};
248
249var isEqualAtomsDependents$1 = function isEqualAtomsDependents(left, right) {
250 return left.size === right.size && Array.from(left).every(function (_ref2) {
251 var a = _ref2[0],
252 dLeft = _ref2[1];
253 var dRight = right.get(a);
254 return dRight && dLeft.size === dRight.size && Array.from(dLeft).every(function (d) {
255 return dRight.has(d);
256 });
257 });
258};
259
260function useAtomsSnapshot(scope) {
261 var ScopeContext = jotai.SECRET_INTERNAL_getScopeContext(scope);
262 var scopeContainer = react.useContext(ScopeContext);
263 var store = scopeContainer.s;
264
265 if (!store[DEV_SUBSCRIBE_STATE]) {
266 throw new Error('useAtomsSnapshot can only be used in dev mode.');
267 }
268
269 var _useState = react.useState(function () {
270 return {
271 values: new Map(),
272 dependents: new Map()
273 };
274 }),
275 atomsSnapshot = _useState[0],
276 setAtomsSnapshot = _useState[1];
277
278 react.useEffect(function () {
279 var _store$DEV_SUBSCRIBE_;
280
281 var prevValues = new Map();
282 var prevDependents = new Map();
283 var invalidatedAtoms = new Set();
284
285 var callback = function callback() {
286 var values = new Map();
287 var dependents = new Map();
288 var hasNewInvalidatedAtoms = false;
289
290 for (var _iterator = _createForOfIteratorHelperLoose(((_store$DEV_GET_MOUNTE = store[DEV_GET_MOUNTED_ATOMS]) == null ? void 0 : _store$DEV_GET_MOUNTE.call(store)) || []), _step; !(_step = _iterator()).done;) {
291 var _store$DEV_GET_MOUNTE, _store$DEV_GET_ATOM_S, _store$DEV_GET_MOUNTE2;
292
293 var atom = _step.value;
294 var atomState = (_store$DEV_GET_ATOM_S = store[DEV_GET_ATOM_STATE]) == null ? void 0 : _store$DEV_GET_ATOM_S.call(store, atom);
295
296 if (atomState) {
297 if (!atomState.y) {
298 if ('p' in atomState) {
299 return;
300 }
301
302 if (!invalidatedAtoms.has(atom)) {
303 invalidatedAtoms.add(atom);
304 hasNewInvalidatedAtoms = true;
305 }
306 }
307
308 if ('v' in atomState) {
309 values.set(atom, atomState.v);
310 }
311 }
312
313 var mounted = (_store$DEV_GET_MOUNTE2 = store[DEV_GET_MOUNTED]) == null ? void 0 : _store$DEV_GET_MOUNTE2.call(store, atom);
314
315 if (mounted) {
316 dependents.set(atom, mounted.t);
317 }
318 }
319
320 if (hasNewInvalidatedAtoms) {
321 return;
322 }
323
324 if (isEqualAtomsValues$1(prevValues, values) && isEqualAtomsDependents$1(prevDependents, dependents)) {
325 return;
326 }
327
328 prevValues = values;
329 prevDependents = dependents;
330 invalidatedAtoms.clear();
331 setAtomsSnapshot({
332 values: values,
333 dependents: dependents
334 });
335 };
336
337 var unsubscribe = (_store$DEV_SUBSCRIBE_ = store[DEV_SUBSCRIBE_STATE]) == null ? void 0 : _store$DEV_SUBSCRIBE_.call(store, callback);
338 callback();
339 return unsubscribe;
340 }, [store]);
341 return atomsSnapshot;
342}
343
344function useGotoAtomsSnapshot(scope) {
345 var ScopeContext = jotai.SECRET_INTERNAL_getScopeContext(scope);
346
347 var _useContext = react.useContext(ScopeContext),
348 store = _useContext.s,
349 versionedWrite = _useContext.w;
350
351 if (!store[DEV_SUBSCRIBE_STATE]) {
352 throw new Error('useGotoAtomsSnapshot can only be used in dev mode.');
353 }
354
355 return react.useCallback(function (snapshot) {
356 var restoreAtoms = function restoreAtoms(values) {
357 if (versionedWrite) {
358 versionedWrite(function (version) {
359 store[RESTORE_ATOMS](values, version);
360 });
361 } else {
362 store[RESTORE_ATOMS](values);
363 }
364 };
365
366 if (isIterable(snapshot)) {
367 if (process.env.NODE_ENV !== "production") {
368 console.warn('snapshot as iterable is deprecated. use an object instead.');
369 }
370
371 restoreAtoms(snapshot);
372 return;
373 }
374
375 restoreAtoms(snapshot.values);
376 }, [store, versionedWrite]);
377}
378
379var isIterable = function isIterable(item) {
380 return typeof item[Symbol.iterator] === 'function';
381};
382
383var isEqualAtomsValues = function isEqualAtomsValues(left, right) {
384 return left.size === right.size && Array.from(left).every(function (_ref) {
385 var left = _ref[0],
386 v = _ref[1];
387 return Object.is(right.get(left), v);
388 });
389};
390
391var isEqualAtomsDependents = function isEqualAtomsDependents(left, right) {
392 return left.size === right.size && Array.from(left).every(function (_ref2) {
393 var a = _ref2[0],
394 dLeft = _ref2[1];
395 var dRight = right.get(a);
396 return dRight && dLeft.size === dRight.size && Array.from(dLeft).every(function (d) {
397 return dRight.has(d);
398 });
399 });
400};
401
402var atomToPrintable = function atomToPrintable(atom) {
403 return atom.debugLabel ? atom + ":" + atom.debugLabel : "" + atom;
404};
405
406var getDevtoolsState = function getDevtoolsState(atomsSnapshot) {
407 var values = {};
408 atomsSnapshot.values.forEach(function (v, atom) {
409 values[atomToPrintable(atom)] = v;
410 });
411 var dependents = {};
412 atomsSnapshot.dependents.forEach(function (d, atom) {
413 dependents[atomToPrintable(atom)] = Array.from(d).map(atomToPrintable);
414 });
415 return {
416 values: values,
417 dependents: dependents
418 };
419};
420
421function useAtomsDevtools(name, options) {
422 if (typeof options !== 'undefined' && typeof options !== 'object') {
423 console.warn('DEPRECATED [useAtomsDevtools] use DevtoolsOptions');
424 options = {
425 scope: options
426 };
427 }
428
429 var _ref3 = options || {},
430 enabled = _ref3.enabled,
431 scope = _ref3.scope;
432
433 var ScopeContext = jotai.SECRET_INTERNAL_getScopeContext(scope);
434
435 var _useContext = react.useContext(ScopeContext),
436 store = _useContext.s,
437 versionedWrite = _useContext.w;
438
439 var extension;
440
441 try {
442 extension = (enabled != null ? enabled : process.env.NODE_ENV !== "production") && window.__REDUX_DEVTOOLS_EXTENSION__;
443 } catch (_unused) {}
444
445 if (!extension) {
446 if (process.env.NODE_ENV !== "production" && enabled) {
447 console.warn('Please install/enable Redux devtools extension');
448 }
449 }
450
451 if (extension && !store[DEV_SUBSCRIBE_STATE]) {
452 throw new Error('useAtomsDevtools can only be used in dev mode.');
453 }
454
455 var _useState = react.useState(function () {
456 return {
457 values: new Map(),
458 dependents: new Map()
459 };
460 }),
461 atomsSnapshot = _useState[0],
462 setAtomsSnapshot = _useState[1];
463
464 react.useEffect(function () {
465 var _store$DEV_SUBSCRIBE_;
466
467 if (!extension) {
468 return;
469 }
470
471 var prevValues = new Map();
472 var prevDependents = new Map();
473 var invalidatedAtoms = new Set();
474
475 var callback = function callback() {
476 var values = new Map();
477 var dependents = new Map();
478 var hasNewInvalidatedAtoms = false;
479
480 for (var _iterator = _createForOfIteratorHelperLoose(((_store$DEV_GET_MOUNTE = store[DEV_GET_MOUNTED_ATOMS]) == null ? void 0 : _store$DEV_GET_MOUNTE.call(store)) || []), _step; !(_step = _iterator()).done;) {
481 var _store$DEV_GET_MOUNTE, _store$DEV_GET_ATOM_S, _store$DEV_GET_MOUNTE2;
482
483 var atom = _step.value;
484 var atomState = (_store$DEV_GET_ATOM_S = store[DEV_GET_ATOM_STATE]) == null ? void 0 : _store$DEV_GET_ATOM_S.call(store, atom);
485
486 if (atomState) {
487 if (!atomState.y) {
488 if ('p' in atomState) {
489 return;
490 }
491
492 if (!invalidatedAtoms.has(atom)) {
493 invalidatedAtoms.add(atom);
494 hasNewInvalidatedAtoms = true;
495 }
496 }
497
498 if ('v' in atomState) {
499 values.set(atom, atomState.v);
500 }
501 }
502
503 var mounted = (_store$DEV_GET_MOUNTE2 = store[DEV_GET_MOUNTED]) == null ? void 0 : _store$DEV_GET_MOUNTE2.call(store, atom);
504
505 if (mounted) {
506 dependents.set(atom, mounted.t);
507 }
508 }
509
510 if (hasNewInvalidatedAtoms) {
511 return;
512 }
513
514 if (isEqualAtomsValues(prevValues, values) && isEqualAtomsDependents(prevDependents, dependents)) {
515 return;
516 }
517
518 prevValues = values;
519 prevDependents = dependents;
520 invalidatedAtoms.clear();
521 setAtomsSnapshot({
522 values: values,
523 dependents: dependents
524 });
525 };
526
527 var unsubscribe = (_store$DEV_SUBSCRIBE_ = store[DEV_SUBSCRIBE_STATE]) == null ? void 0 : _store$DEV_SUBSCRIBE_.call(store, callback);
528 callback();
529 return unsubscribe;
530 }, [extension, store]);
531 var goToSnapshot = react.useCallback(function (snapshot) {
532 var values = snapshot.values;
533
534 if (versionedWrite) {
535 versionedWrite(function (version) {
536 store[RESTORE_ATOMS](values, version);
537 });
538 } else {
539 store[RESTORE_ATOMS](values);
540 }
541 }, [store, versionedWrite]);
542 var isTimeTraveling = react.useRef(false);
543 var isRecording = react.useRef(true);
544 var devtools = react.useRef();
545 var snapshots = react.useRef([]);
546 react.useEffect(function () {
547 if (!extension) {
548 return;
549 }
550
551 var getSnapshotAt = function getSnapshotAt(index) {
552 if (index === void 0) {
553 index = snapshots.current.length - 1;
554 }
555
556 var snapshot = snapshots.current[index >= 0 ? index : 0];
557
558 if (!snapshot) {
559 throw new Error('snaphost index out of bounds');
560 }
561
562 return snapshot;
563 };
564
565 var connection = extension.connect({
566 name: name
567 });
568 var devtoolsUnsubscribe = connection.subscribe(function (message) {
569 var _message$payload;
570
571 switch (message.type) {
572 case 'DISPATCH':
573 switch ((_message$payload = message.payload) == null ? void 0 : _message$payload.type) {
574 case 'RESET':
575 break;
576
577 case 'COMMIT':
578 connection.init(getDevtoolsState(getSnapshotAt()));
579 snapshots.current = [];
580 break;
581
582 case 'JUMP_TO_ACTION':
583 case 'JUMP_TO_STATE':
584 isTimeTraveling.current = true;
585 goToSnapshot(getSnapshotAt(message.payload.actionId - 1));
586 break;
587
588 case 'PAUSE_RECORDING':
589 isRecording.current = !isRecording.current;
590 break;
591 }
592
593 }
594 });
595 devtools.current = connection;
596 devtools.current.shouldInit = true;
597 return devtoolsUnsubscribe;
598 }, [extension, goToSnapshot, name]);
599 react.useEffect(function () {
600 if (!devtools.current) {
601 return;
602 }
603
604 if (devtools.current.shouldInit) {
605 devtools.current.init(undefined);
606 devtools.current.shouldInit = false;
607 return;
608 }
609
610 if (isTimeTraveling.current) {
611 isTimeTraveling.current = false;
612 } else if (isRecording.current) {
613 snapshots.current.push(atomsSnapshot);
614 devtools.current.send({
615 type: "" + snapshots.current.length,
616 updatedAt: new Date().toLocaleString()
617 }, getDevtoolsState(atomsSnapshot));
618 }
619 }, [atomsSnapshot]);
620}
621
622exports.useAtomDevtools = useAtomDevtools;
623exports.useAtomsDebugValue = useAtomsDebugValue;
624exports.useAtomsDevtools = useAtomsDevtools;
625exports.useAtomsSnapshot = useAtomsSnapshot;
626exports.useGotoAtomsSnapshot = useGotoAtomsSnapshot;