@legendapp/state 2.1.0 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.mjs CHANGED
@@ -192,6 +192,228 @@ function extractFunction(node, key, fnOrComputed, computedChildNode) {
192
192
  }
193
193
  }
194
194
 
195
+ function isObservable(obs) {
196
+ return obs && !!obs[symbolGetNode];
197
+ }
198
+ function isEvent(obs) {
199
+ var _a;
200
+ return obs && ((_a = obs[symbolGetNode]) === null || _a === void 0 ? void 0 : _a.isEvent);
201
+ }
202
+ function computeSelector(selector, e, retainObservable) {
203
+ let c = selector;
204
+ if (isFunction(c)) {
205
+ c = e ? c(e) : c();
206
+ }
207
+ return isObservable(c) && !retainObservable ? c.get() : c;
208
+ }
209
+ function getObservableIndex(obs) {
210
+ const node = getNode(obs);
211
+ const n = +node.key;
212
+ return n - n < 1 ? +n : -1;
213
+ }
214
+ function opaqueObject(value) {
215
+ if (value) {
216
+ value[symbolOpaque] = true;
217
+ }
218
+ return value;
219
+ }
220
+ function lockObservable(obs, value) {
221
+ var _a;
222
+ const root = (_a = getNode(obs)) === null || _a === void 0 ? void 0 : _a.root;
223
+ if (root) {
224
+ root.locked = value;
225
+ }
226
+ }
227
+ function setAtPath(obj, path, pathTypes, value, fullObj, restore) {
228
+ let o = obj;
229
+ let oFull = fullObj;
230
+ if (path.length > 0) {
231
+ for (let i = 0; i < path.length; i++) {
232
+ const p = path[i];
233
+ if (i === path.length - 1) {
234
+ // Don't set if the value is the same. This prevents creating a new key
235
+ // when setting undefined on an object without this key
236
+ if (o[p] !== value) {
237
+ o[p] = value;
238
+ }
239
+ }
240
+ else if (o[p] === symbolDelete) {
241
+ // If this was previously deleted, restore it
242
+ if (oFull) {
243
+ o[p] = oFull[p];
244
+ restore === null || restore === void 0 ? void 0 : restore(path.slice(0, i + 1), o[p]);
245
+ }
246
+ break;
247
+ }
248
+ else if (o[p] === undefined || o[p] === null) {
249
+ o[p] = initializePathType(pathTypes[i]);
250
+ }
251
+ o = o[p];
252
+ if (oFull) {
253
+ oFull = oFull[p];
254
+ }
255
+ }
256
+ }
257
+ else {
258
+ obj = value;
259
+ }
260
+ return obj;
261
+ }
262
+ function setInObservableAtPath(obs, path, pathTypes, value, mode) {
263
+ let o = obs;
264
+ let v = value;
265
+ for (let i = 0; i < path.length; i++) {
266
+ const p = path[i];
267
+ if (!o.peek()[p]) {
268
+ o[p].set(initializePathType(pathTypes[i]));
269
+ }
270
+ o = o[p];
271
+ v = v[p];
272
+ }
273
+ if (v === symbolDelete) {
274
+ o.delete();
275
+ }
276
+ // Assign if possible, or set otherwise
277
+ else if (mode === 'assign' && o.assign && isObject(o.peek())) {
278
+ o.assign(v);
279
+ }
280
+ else {
281
+ o.set(v);
282
+ }
283
+ }
284
+ function mergeIntoObservable(target, ...sources) {
285
+ beginBatch();
286
+ globalState.isMerging = true;
287
+ for (let i = 0; i < sources.length; i++) {
288
+ target = _mergeIntoObservable(target, sources[i]);
289
+ }
290
+ globalState.isMerging = false;
291
+ endBatch();
292
+ return target;
293
+ }
294
+ function _mergeIntoObservable(target, source) {
295
+ var _a;
296
+ const needsSet = isObservable(target);
297
+ const targetValue = needsSet ? target.peek() : target;
298
+ const isTargetArr = isArray(targetValue);
299
+ const isTargetObj = !isTargetArr && isObject(targetValue);
300
+ if ((isTargetObj && isObject(source) && !isEmpty(targetValue)) ||
301
+ (isTargetArr && isArray(source) && targetValue.length > 0)) {
302
+ const keys = Object.keys(source);
303
+ for (let i = 0; i < keys.length; i++) {
304
+ const key = keys[i];
305
+ const sourceValue = source[key];
306
+ if (sourceValue === symbolDelete) {
307
+ needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete) ? target[key].delete() : delete target[key];
308
+ }
309
+ else {
310
+ const isObj = isObject(sourceValue);
311
+ const isArr = !isObj && isArray(sourceValue);
312
+ const targetChild = target[key];
313
+ if ((isObj || isArr) && targetChild && (needsSet || !isEmpty(targetChild))) {
314
+ if (!needsSet && (!targetChild || (isObj ? !isObject(targetChild) : !isArray(targetChild)))) {
315
+ target[key] = sourceValue;
316
+ }
317
+ else {
318
+ _mergeIntoObservable(targetChild, sourceValue);
319
+ }
320
+ }
321
+ else {
322
+ needsSet
323
+ ? targetChild.set(sourceValue)
324
+ : (target[key] = sourceValue);
325
+ }
326
+ }
327
+ }
328
+ }
329
+ else if (source !== undefined) {
330
+ needsSet ? target.set(source) : (target = source);
331
+ }
332
+ return target;
333
+ }
334
+ function constructObjectWithPath(path, pathTypes, value) {
335
+ let out;
336
+ if (path.length > 0) {
337
+ let o = (out = {});
338
+ for (let i = 0; i < path.length; i++) {
339
+ const p = path[i];
340
+ o[p] = i === path.length - 1 ? value : initializePathType(pathTypes[i]);
341
+ o = o[p];
342
+ }
343
+ }
344
+ else {
345
+ out = value;
346
+ }
347
+ return out;
348
+ }
349
+ function deconstructObjectWithPath(path, pathTypes, value) {
350
+ let o = value;
351
+ for (let i = 0; i < path.length; i++) {
352
+ const p = path[i];
353
+ o = o ? o[p] : initializePathType(pathTypes[i]);
354
+ }
355
+ return o;
356
+ }
357
+ function isObservableValueReady(value) {
358
+ return !!value && ((!isObject(value) && !isArray(value)) || !isEmpty(value));
359
+ }
360
+ function setSilently(obs, newValue) {
361
+ const node = getNode(obs);
362
+ return setNodeValue(node, newValue).newValue;
363
+ }
364
+ function getPathType(value) {
365
+ return isArray(value) ? 'array' : value instanceof Map ? 'map' : value instanceof Set ? 'set' : 'object';
366
+ }
367
+ function initializePathType(pathType) {
368
+ switch (pathType) {
369
+ case 'array':
370
+ return [];
371
+ case 'object':
372
+ return {};
373
+ case 'map':
374
+ return new Map();
375
+ case 'set':
376
+ return new Set();
377
+ }
378
+ }
379
+ function replacer(_, value) {
380
+ if (value instanceof Map) {
381
+ return {
382
+ __LSType: 'Map',
383
+ value: Array.from(value.entries()), // or with spread: value: [...value]
384
+ };
385
+ }
386
+ else if (value instanceof Set) {
387
+ return {
388
+ __LSType: 'Set',
389
+ value: Array.from(value), // or with spread: value: [...value]
390
+ };
391
+ }
392
+ else {
393
+ return value;
394
+ }
395
+ }
396
+ function reviver(_, value) {
397
+ if (typeof value === 'object' && value) {
398
+ if (value.__LSType === 'Map') {
399
+ return new Map(value.value);
400
+ }
401
+ else if (value.__LSType === 'Set') {
402
+ return new Set(value.value);
403
+ }
404
+ }
405
+ return value;
406
+ }
407
+ function safeStringify(value) {
408
+ return JSON.stringify(value, replacer);
409
+ }
410
+ function safeParse(value) {
411
+ return JSON.parse(value, reviver);
412
+ }
413
+ function clone(value) {
414
+ return safeParse(safeStringify(value));
415
+ }
416
+
195
417
  let timeout;
196
418
  let numInBatch = 0;
197
419
  let isRunningBatch = false;
@@ -217,22 +439,28 @@ function isArraySubset(mainArr, subsetArr) {
217
439
  }
218
440
  function createPreviousHandlerInner(value, changes) {
219
441
  // Clones the current state and inject the previous data at the changed path
220
- let clone = value ? JSON.parse(JSON.stringify(value)) : {};
442
+ let cloned = value ? clone(value) : {};
221
443
  for (let i = 0; i < changes.length; i++) {
222
444
  const { path, prevAtPath } = changes[i];
223
- let o = clone;
445
+ let o = cloned;
224
446
  if (path.length > 0) {
225
447
  let i;
226
448
  for (i = 0; i < path.length - 1; i++) {
227
449
  o = o[path[i]];
228
450
  }
229
- o[path[i]] = prevAtPath;
451
+ const key = path[i];
452
+ if (o instanceof Map) {
453
+ o.set(key, prevAtPath);
454
+ }
455
+ else {
456
+ o[key] = prevAtPath;
457
+ }
230
458
  }
231
459
  else {
232
- clone = prevAtPath;
460
+ cloned = prevAtPath;
233
461
  }
234
462
  }
235
- return clone;
463
+ return cloned;
236
464
  }
237
465
  function createPreviousHandler(value, changes) {
238
466
  // Create a function that generates the previous state
@@ -302,7 +530,7 @@ function computeChangesRecursive(changesInBatch, node, value, path, pathTypes, v
302
530
  const parent = node.parent;
303
531
  if (parent) {
304
532
  const parentValue = getNodeValue(parent);
305
- computeChangesRecursive(changesInBatch, parent, parentValue, [node.key].concat(path), [(isArray(value) ? 'array' : 'object')].concat(pathTypes), valueAtPath, prevAtPath, immediate, level + 1, whenOptimizedOnlyIf);
533
+ computeChangesRecursive(changesInBatch, parent, parentValue, [node.key].concat(path), [getPathType(value)].concat(pathTypes), valueAtPath, prevAtPath, immediate, level + 1, whenOptimizedOnlyIf);
306
534
  }
307
535
  }
308
536
  }
@@ -1119,6 +1347,9 @@ function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRo
1119
1347
  childNode = node;
1120
1348
  // Make sure we don't call too many listeners for ever property set
1121
1349
  beginBatch();
1350
+ if (isPrim === undefined) {
1351
+ isPrim = isPrimitive(newValue);
1352
+ }
1122
1353
  let hasADiff = isPrim;
1123
1354
  let whenOptimizedOnlyIf = false;
1124
1355
  // If new value is an object or array update notify down the tree
@@ -1193,176 +1424,6 @@ function peek(node) {
1193
1424
  return value;
1194
1425
  }
1195
1426
 
1196
- function isObservable(obs) {
1197
- return obs && !!obs[symbolGetNode];
1198
- }
1199
- function isEvent(obs) {
1200
- var _a;
1201
- return obs && ((_a = obs[symbolGetNode]) === null || _a === void 0 ? void 0 : _a.isEvent);
1202
- }
1203
- function computeSelector(selector, e, retainObservable) {
1204
- let c = selector;
1205
- if (isFunction(c)) {
1206
- c = e ? c(e) : c();
1207
- }
1208
- return isObservable(c) && !retainObservable ? c.get() : c;
1209
- }
1210
- function getObservableIndex(obs) {
1211
- const node = getNode(obs);
1212
- const n = +node.key;
1213
- return n - n < 1 ? +n : -1;
1214
- }
1215
- function opaqueObject(value) {
1216
- if (value) {
1217
- value[symbolOpaque] = true;
1218
- }
1219
- return value;
1220
- }
1221
- function lockObservable(obs, value) {
1222
- var _a;
1223
- const root = (_a = getNode(obs)) === null || _a === void 0 ? void 0 : _a.root;
1224
- if (root) {
1225
- root.locked = value;
1226
- }
1227
- }
1228
- function setAtPath(obj, path, pathTypes, value, fullObj, restore) {
1229
- let o = obj;
1230
- let oFull = fullObj;
1231
- if (path.length > 0) {
1232
- for (let i = 0; i < path.length; i++) {
1233
- const p = path[i];
1234
- if (i === path.length - 1) {
1235
- // Don't set if the value is the same. This prevents creating a new key
1236
- // when setting undefined on an object without this key
1237
- if (o[p] !== value) {
1238
- o[p] = value;
1239
- }
1240
- }
1241
- else if (o[p] === symbolDelete) {
1242
- // If this was previously deleted, restore it
1243
- if (oFull) {
1244
- o[p] = oFull[p];
1245
- restore === null || restore === void 0 ? void 0 : restore(path.slice(0, i + 1), o[p]);
1246
- }
1247
- break;
1248
- }
1249
- else if (o[p] === undefined || o[p] === null) {
1250
- o[p] = pathTypes[i] === 'array' ? [] : {};
1251
- }
1252
- o = o[p];
1253
- if (oFull) {
1254
- oFull = oFull[p];
1255
- }
1256
- }
1257
- }
1258
- else {
1259
- obj = value;
1260
- }
1261
- return obj;
1262
- }
1263
- function setInObservableAtPath(obs, path, pathTypes, value, mode) {
1264
- let o = obs;
1265
- let v = value;
1266
- for (let i = 0; i < path.length; i++) {
1267
- const p = path[i];
1268
- if (!o.peek()[p] && pathTypes[i] === 'array') {
1269
- o[p].set([]);
1270
- }
1271
- o = o[p];
1272
- v = v[p];
1273
- }
1274
- if (v === symbolDelete) {
1275
- o.delete();
1276
- }
1277
- // Assign if possible, or set otherwise
1278
- else if (mode === 'assign' && o.assign && isObject(o.peek())) {
1279
- o.assign(v);
1280
- }
1281
- else {
1282
- o.set(v);
1283
- }
1284
- }
1285
- function mergeIntoObservable(target, ...sources) {
1286
- beginBatch();
1287
- globalState.isMerging = true;
1288
- for (let i = 0; i < sources.length; i++) {
1289
- target = _mergeIntoObservable(target, sources[i]);
1290
- }
1291
- globalState.isMerging = false;
1292
- endBatch();
1293
- return target;
1294
- }
1295
- function _mergeIntoObservable(target, source) {
1296
- var _a;
1297
- const needsSet = isObservable(target);
1298
- const targetValue = needsSet ? target.peek() : target;
1299
- const isTargetArr = isArray(targetValue);
1300
- const isTargetObj = !isTargetArr && isObject(targetValue);
1301
- if ((isTargetObj && isObject(source) && !isEmpty(targetValue)) ||
1302
- (isTargetArr && isArray(source) && targetValue.length > 0)) {
1303
- const keys = Object.keys(source);
1304
- for (let i = 0; i < keys.length; i++) {
1305
- const key = keys[i];
1306
- const sourceValue = source[key];
1307
- if (sourceValue === symbolDelete) {
1308
- needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete) ? target[key].delete() : delete target[key];
1309
- }
1310
- else {
1311
- const isObj = isObject(sourceValue);
1312
- const isArr = !isObj && isArray(sourceValue);
1313
- const targetChild = target[key];
1314
- if ((isObj || isArr) && targetChild && (needsSet || !isEmpty(targetChild))) {
1315
- if (!needsSet && (!targetChild || (isObj ? !isObject(targetChild) : !isArray(targetChild)))) {
1316
- target[key] = sourceValue;
1317
- }
1318
- else {
1319
- _mergeIntoObservable(targetChild, sourceValue);
1320
- }
1321
- }
1322
- else {
1323
- needsSet
1324
- ? targetChild.set(sourceValue)
1325
- : (target[key] = sourceValue);
1326
- }
1327
- }
1328
- }
1329
- }
1330
- else if (source !== undefined) {
1331
- needsSet ? target.set(source) : (target = source);
1332
- }
1333
- return target;
1334
- }
1335
- function constructObjectWithPath(path, pathTypes, value) {
1336
- let out;
1337
- if (path.length > 0) {
1338
- let o = (out = {});
1339
- for (let i = 0; i < path.length; i++) {
1340
- const p = path[i];
1341
- o[p] = i === path.length - 1 ? value : pathTypes[i] === 'array' ? [] : {};
1342
- o = o[p];
1343
- }
1344
- }
1345
- else {
1346
- out = value;
1347
- }
1348
- return out;
1349
- }
1350
- function deconstructObjectWithPath(path, pathTypes, value) {
1351
- let o = value;
1352
- for (let i = 0; i < path.length; i++) {
1353
- const p = path[i];
1354
- o = o ? o[p] : pathTypes[i] === 'array' ? [] : {};
1355
- }
1356
- return o;
1357
- }
1358
- function isObservableValueReady(value) {
1359
- return !!value && ((!isObject(value) && !isArray(value)) || !isEmpty(value));
1360
- }
1361
- function setSilently(obs, newValue) {
1362
- const node = getNode(obs);
1363
- return setNodeValue(node, newValue).newValue;
1364
- }
1365
-
1366
1427
  const fns = ['get', 'set', 'peek', 'onChange', 'toggle'];
1367
1428
  function ObservablePrimitiveClass(node) {
1368
1429
  this._node = node;
@@ -1738,15 +1799,20 @@ function whenReady(predicate, effect) {
1738
1799
  }
1739
1800
 
1740
1801
  const internal = {
1802
+ clone,
1741
1803
  ensureNodeValue,
1742
1804
  findIDKey,
1743
1805
  get,
1744
1806
  getNode,
1807
+ getPathType,
1745
1808
  getProxy,
1746
1809
  globalState,
1810
+ initializePathType,
1747
1811
  observableFns,
1748
1812
  optimized,
1749
1813
  peek,
1814
+ safeParse,
1815
+ safeStringify,
1750
1816
  set,
1751
1817
  setAtPath,
1752
1818
  setNodeValue,