@yiin/reactive-proxy-state 1.0.16 → 1.0.17

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.
@@ -1,13 +1,16 @@
1
+ import { WatchEffectStopHandle } from './watch-effect';
1
2
  import { Ref, isRefSymbol } from './ref';
2
3
  declare const isComputedSymbol: unique symbol;
3
4
  export interface ComputedRef<T = any> extends Omit<Ref<T>, 'value'> {
4
5
  readonly value: T;
5
6
  readonly [isComputedSymbol]: true;
6
7
  readonly [isRefSymbol]: true;
8
+ readonly effect: WatchEffectStopHandle<T>;
7
9
  }
8
10
  export interface WritableComputedRef<T> extends Ref<T> {
9
11
  readonly [isComputedSymbol]: true;
10
12
  readonly [isRefSymbol]: true;
13
+ readonly effect: WatchEffectStopHandle<T>;
11
14
  }
12
15
  type ComputedGetter<T> = () => T;
13
16
  type ComputedSetter<T> = (v: T) => void;
package/dist/index.js CHANGED
@@ -58,6 +58,26 @@ function deepEqual(a, b, seen = globalSeen) {
58
58
  let result;
59
59
  if (Array.isArray(a)) {
60
60
  result = a.length === b.length && a.every((val, idx) => deepEqual(val, b[idx], seen));
61
+ } else if (a instanceof Map && b instanceof Map) {
62
+ result = a.size === b.size;
63
+ if (result) {
64
+ for (const [key, value] of a) {
65
+ if (!b.has(key) || !deepEqual(value, b.get(key), seen)) {
66
+ result = false;
67
+ break;
68
+ }
69
+ }
70
+ }
71
+ } else if (a instanceof Set && b instanceof Set) {
72
+ result = a.size === b.size;
73
+ if (result) {
74
+ for (const value of a) {
75
+ if (!b.has(value)) {
76
+ result = false;
77
+ break;
78
+ }
79
+ }
80
+ }
61
81
  } else {
62
82
  const keysA = Object.keys(a);
63
83
  const keysB = Object.keys(b);
@@ -120,7 +140,8 @@ function traverse(value, seen = new Set) {
120
140
  traverse(value[i], seen);
121
141
  }
122
142
  } else if (value instanceof Set || value instanceof Map) {
123
- for (const v of value) {
143
+ const rawValue = value.__v_raw || value;
144
+ for (const v of rawValue) {
124
145
  if (Array.isArray(v)) {
125
146
  traverse(v[0], seen);
126
147
  traverse(v[1], seen);
@@ -465,12 +486,17 @@ function flushEffects() {
465
486
  }
466
487
  }
467
488
  for (const effect of effectsToRun) {
468
- if (effect.active) {
469
- if (effect.options?.scheduler) {
470
- effect.options.scheduler(effect.run);
471
- } else {
472
- effect.run();
473
- }
489
+ if (!effect.active)
490
+ continue;
491
+ if (effect.options?.scheduler) {
492
+ effect.options.scheduler(effect.run);
493
+ }
494
+ }
495
+ for (const effect of effectsToRun) {
496
+ if (!effect.active)
497
+ continue;
498
+ if (!effect.options?.scheduler) {
499
+ effect.run();
474
500
  }
475
501
  }
476
502
  } finally {
@@ -714,6 +740,9 @@ function wrapSet(set, emit, path = []) {
714
740
  track(target, "size");
715
741
  return target.size;
716
742
  }
743
+ if (prop === "constructor") {
744
+ return Set;
745
+ }
717
746
  const value = Reflect.get(target, prop, receiver);
718
747
  if (typeof value === "function") {
719
748
  return value.bind(target);
@@ -952,6 +981,9 @@ function wrapMap(map, emit, path = []) {
952
981
  track(target, "size");
953
982
  return target.size;
954
983
  }
984
+ if (prop === "constructor") {
985
+ return Map;
986
+ }
955
987
  const value = Reflect.get(target, prop, receiver);
956
988
  if (typeof value === "function") {
957
989
  return value.bind(target);
@@ -1320,35 +1352,6 @@ function reactive(obj, emit, path = []) {
1320
1352
  globalSeen.set(obj, proxy);
1321
1353
  return proxy;
1322
1354
  }
1323
- // src/watch.ts
1324
- function watch(sourceInput, callback, options = {}) {
1325
- const { immediate = false, deep = true } = options;
1326
- const source = typeof sourceInput === "function" ? sourceInput : () => sourceInput;
1327
- let oldValue;
1328
- let initialized = false;
1329
- const stopEffect = watchEffect(() => {
1330
- const currentValue = source();
1331
- if (deep) {
1332
- traverse(currentValue);
1333
- }
1334
- if (initialized) {
1335
- let hasChanged = false;
1336
- hasChanged = deep || currentValue !== oldValue;
1337
- if (hasChanged) {
1338
- const prevOldValue = oldValue;
1339
- oldValue = deep ? deepClone(currentValue) : currentValue;
1340
- callback(currentValue, prevOldValue);
1341
- }
1342
- } else {
1343
- oldValue = deep ? deepClone(currentValue) : currentValue;
1344
- initialized = true;
1345
- if (immediate) {
1346
- callback(currentValue, undefined);
1347
- }
1348
- }
1349
- }, { lazy: false });
1350
- return stopEffect;
1351
- }
1352
1355
  // src/ref.ts
1353
1356
  var isRefSymbol = Symbol("isRef");
1354
1357
  function ref(value) {
@@ -1402,6 +1405,7 @@ function toRef(object, key) {
1402
1405
  function triggerRef(ref2) {
1403
1406
  trigger(ref2, "value");
1404
1407
  }
1408
+
1405
1409
  // src/computed.ts
1406
1410
  var isComputedSymbol = Symbol("isComputed");
1407
1411
  function computed(getterOrOptions) {
@@ -1444,13 +1448,82 @@ function computed(getterOrOptions) {
1444
1448
  } else {
1445
1449
  console.warn("computed value is read-only");
1446
1450
  }
1447
- }
1451
+ },
1452
+ effect: stopHandle
1448
1453
  };
1449
1454
  return computedRef;
1450
1455
  }
1451
1456
  function isComputed(c) {
1452
1457
  return !!(c && c[isComputedSymbol]);
1453
1458
  }
1459
+
1460
+ // src/watch.ts
1461
+ function watch(source, callback, options = {}) {
1462
+ const { immediate = false, deep = true } = options;
1463
+ const isMultiSource = Array.isArray(source);
1464
+ const getter = () => {
1465
+ if (isMultiSource) {
1466
+ return source.map((s) => {
1467
+ if (isRef(s))
1468
+ return s.value;
1469
+ if (isComputed(s))
1470
+ return s.value;
1471
+ if (typeof s === "function")
1472
+ return s();
1473
+ return s;
1474
+ });
1475
+ }
1476
+ if (isRef(source))
1477
+ return source.value;
1478
+ if (isComputed(source))
1479
+ return source.value;
1480
+ if (typeof source === "function")
1481
+ return source();
1482
+ return source;
1483
+ };
1484
+ let oldValue;
1485
+ let initialized = false;
1486
+ const stopEffect = watchEffect(() => {
1487
+ let currentValue = getter();
1488
+ if (deep) {
1489
+ traverse(currentValue);
1490
+ }
1491
+ const job = () => {
1492
+ if (initialized) {
1493
+ let hasChanged = false;
1494
+ if (isMultiSource) {
1495
+ if (!Array.isArray(oldValue) || currentValue.length !== oldValue.length) {
1496
+ hasChanged = true;
1497
+ } else {
1498
+ hasChanged = currentValue.some((val, i) => {
1499
+ return deep ? !deepEqual(val, oldValue[i]) : val !== oldValue[i];
1500
+ });
1501
+ }
1502
+ } else {
1503
+ hasChanged = deep ? !deepEqual(currentValue, oldValue) : currentValue !== oldValue;
1504
+ }
1505
+ if (hasChanged) {
1506
+ const prevOldValue = oldValue;
1507
+ if (isMultiSource) {
1508
+ currentValue = getter();
1509
+ }
1510
+ const valueToClone = currentValue && typeof currentValue === "object" && currentValue.__v_raw ? currentValue.__v_raw : currentValue;
1511
+ oldValue = deep ? deepClone(valueToClone) : currentValue;
1512
+ callback(currentValue, prevOldValue);
1513
+ }
1514
+ } else {
1515
+ const valueToClone = currentValue && typeof currentValue === "object" && currentValue.__v_raw ? currentValue.__v_raw : currentValue;
1516
+ oldValue = deep ? deepClone(valueToClone) : currentValue;
1517
+ initialized = true;
1518
+ if (immediate) {
1519
+ callback(currentValue, undefined);
1520
+ }
1521
+ }
1522
+ };
1523
+ job();
1524
+ });
1525
+ return stopEffect;
1526
+ }
1454
1527
  export {
1455
1528
  wrapperCache,
1456
1529
  wrapSet,
package/dist/types.d.ts CHANGED
@@ -12,3 +12,11 @@ export interface StateEvent {
12
12
  oldValues?: any[];
13
13
  }
14
14
  export type EmitFunction = (event: StateEvent) => void;
15
+ import { Ref } from './ref';
16
+ import { ComputedRef } from './computed';
17
+ export type BaseWatchSource<T = any> = Ref<T> | ComputedRef<T> | (() => T);
18
+ export type WatchSource<T = any> = BaseWatchSource<T> | T;
19
+ export type UnwrapWatchSource<T> = T extends BaseWatchSource<infer V> ? V : T extends object ? T : T;
20
+ export type UnwrapWatchSources<T> = {
21
+ -readonly [K in keyof T]: UnwrapWatchSource<T[K]>;
22
+ };
package/dist/watch.d.ts CHANGED
@@ -1,14 +1,11 @@
1
- type WatchCallback<T = any> = (newValue: T, oldValue: T | undefined) => void;
2
- type WatchSource<T = any> = () => T;
3
- type WatchSourceInput<T = any> = WatchSource<T> | T;
1
+ import { WatchSource, UnwrapWatchSource, UnwrapWatchSources } from './types';
2
+ type WatchCallback<T, O> = (newValue: T, oldValue: O) => void;
4
3
  type WatchStopHandle = () => void;
5
4
  export interface WatchOptions {
6
5
  immediate?: boolean;
7
6
  deep?: boolean;
8
7
  }
9
- /**
10
- * watches a reactive source (getter function or reactive object/ref)
11
- * and runs a callback when the source's value changes.
12
- */
13
- export declare function watch<T = any>(sourceInput: WatchSourceInput<T>, callback: WatchCallback<T>, options?: WatchOptions): WatchStopHandle;
8
+ export declare function watch<T extends readonly WatchSource<unknown>[], Immediate extends Readonly<boolean> = false>(sources: [...T], callback: WatchCallback<UnwrapWatchSources<T>, Immediate extends true ? (UnwrapWatchSources<T> | undefined) : UnwrapWatchSources<T>>, options?: WatchOptions): WatchStopHandle;
9
+ export declare function watch<T, Immediate extends Readonly<boolean> = false>(source: () => T, callback: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: WatchOptions): WatchStopHandle;
10
+ export declare function watch<T, Immediate extends Readonly<boolean> = false>(source: WatchSource<T>, callback: WatchCallback<UnwrapWatchSource<T>, Immediate extends true ? (UnwrapWatchSource<T> | undefined) : UnwrapWatchSource<T>>, options?: WatchOptions): WatchStopHandle;
14
11
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yiin/reactive-proxy-state",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "author": "Yiin <stanislovas@yiin.lt>",
5
5
  "repository": {
6
6
  "type": "git",