New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

value-enhancer

Package Overview
Dependencies
Maintainers
1
Versions
87
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

value-enhancer - npm Package Compare versions

Comparing version 3.1.5 to 4.0.0

dist/typings-8a4e5768.d.ts

154

dist/collections.d.ts

@@ -1,56 +0,24 @@

import { R as ReadonlyVal, F as FlattenVal } from './typings-4a9c4c94.js';
import { R as ReadonlyVal } from './typings-8a4e5768.js';
interface ReactiveCollection<TKey = any, TValue = any> {
/**
* Watch collection value changes.
* @param watcher Watcher to add.
* The Watcher will receive an optional key whose value may have changed.
* If the key is not provided, the collection do not know which values have changed.
* @returns Disposer to remove the watcher.
*/
watch(watcher: (key?: TKey) => void): () => void;
/**
* Remove a watcher.
* @param watcher Watcher to remove. If not provided, all watchers are removed.
*/
unwatch(watcher?: (...args: any[]) => any): void;
/**
* Notify watchers that some values may have changed.
* @param key Optional key whose value may have changed.
* If not provided, the collection do not know which values have changed.
*/
notify(key?: TKey): void;
/**
* Get the value associated with the given key.
* @param key Key to get the value for.
* @returns The value associated with the given key, or undefined if the key is not in the collection.
*/
get(key: TKey): TValue | undefined;
}
/**
* A reactive list. Similar to an Array except bracket-notation(e.g. `arr[0]`) is not allowed to get/set elements.
* Changes to the map will be notified to subscribers of `watch`.
* Changes to the map will be notified to subscribers of `$`.
*
* @example
* ```ts
* import { ReactiveList, fromCollection } from "value-enhancer/collections"
* import { derive } from "value-enhancer";
* import { ReactiveList } from "value-enhancer/collections";
*
* const list = new ReactiveList(["a", "b", "c"]);
* const item$ = derive(list.$, list => list.get(2)); // watch the item at index 2
*
* const item$ = fromCollection(list, 2); // watch the item at index 2
*
* console.log(item$.value); // "c"
*
* list.set(2, "d");
*
* console.log(item$.value); // "d"
* ```
*/
declare class ReactiveList<TValue> implements ReactiveCollection<number, TValue> {
declare class ReactiveList<TValue> {
#private;
constructor(arrayLike?: ArrayLike<TValue>);
watch(watcher: (key?: number) => void): () => void;
unwatch(watcher: (...args: any[]) => any): void;
notify(key?: number): void;
$: ReadonlyVal<this>;
/**

@@ -180,33 +148,34 @@ * Get the internal array. Use it as a read-only array.

toJSON(): unknown;
dispose(): void;
}
declare const SET$: unique symbol;
/**
* A reactive map inherited from `Map`.
* Changes to the map will be notified to subscribers of `watch`.
* Changes to the map will be notified to subscribers of `$`.
*
* @example
* ```ts
* import { ReactiveMap, fromCollection } from "value-enhancer/collections"
* import { val, flatten } from "value-enhancer";
* import { ReactiveMap } from "value-enhancer/collections";
*
* const map = new ReactiveMap();
* const v = val("someValue");
* const item$ = flatten(map.$, map => map.get("someKey")); // watch the item at "someKey"
*
* const item$ = fromCollection(map, "someKey"); // watch the item at "someKey"
*
* console.log(item$.value); // undefined
*
* map.set("someKey", "someValue");
*
* map.set("someKey", v);
* console.log(item$.value); // "someValue"
* v.set("someValue2");
* console.log(item$.value); // "someValue2"
* ```
*/
declare class ReactiveMap<TKey, TValue> extends Map<TKey, TValue> implements ReactiveCollection<TKey, TValue> {
declare class ReactiveMap<TKey, TValue> extends Map<TKey, TValue> {
constructor(entries?: readonly (readonly [TKey, TValue])[] | null);
private _watchers_;
watch(watcher: (key?: TKey) => void): () => void;
unwatch(watcher: (...args: any[]) => any): void;
notify(key?: TKey): void;
readonly $: ReadonlyVal<this>;
private [SET$]?;
delete(key: TKey): boolean;
clear(): void;
set(key: TKey, value: TValue): this;
dispose(): void;
/**

@@ -218,2 +187,3 @@ * Replace all entries in the Map.

replace(entries: Iterable<readonly [TKey, TValue]>): Map<TKey, TValue>;
dispose(): void;
}

@@ -223,29 +193,21 @@

* A reactive set inherited from `Set`.
* Changes to the set will be notified to subscribers of `watch`.
* Changes to the set will be notified to subscribers of `$`.
*
* @example
* ```ts
* import { ReactiveSet, fromCollection } from "value-enhancer/collections"
* import { derive } from "value-enhancer";
* import { ReactiveSet } from "value-enhancer/collections"
*
* const set = new ReactiveSet();
* const item$ = derive(set.$, set => set.has("someValue")); // watch the existence of "someValue"
*
* const item$ = fromCollection(map, "someValue"); // watch the existence of "someValue"
*
* console.log(item$.value); // false
*
* map.add("someValue");
*
* set.add("someValue");
* console.log(item$.value); // true
* ```
*/
declare class ReactiveSet<TValue> extends Set<TValue> implements ReactiveCollection<TValue, boolean> {
declare class ReactiveSet<TValue> extends Set<TValue> {
constructor(entries?: readonly TValue[] | null);
private _watchers_;
watch(watcher: (value?: TValue) => void): () => void;
unwatch(watcher: (...args: any[]) => any): void;
notify(value?: TValue): void;
/**
* @alias Set#has
*/
get: (value: TValue) => boolean;
readonly $: ReadonlyVal<this>;
private [SET$]?;
delete(key: TValue): boolean;

@@ -263,56 +225,2 @@ clear(): void;

/**
* Create a readonly val from a reactive collection watching a specific key.
*
* @param collection The reactive collection
* @param key The key to watch
* @returns A readonly val watching the item at the specified key
*
* @example
* ```ts
* import { ReactiveMap, fromCollection } from "value-enhancer/collections"
*
* const map = new ReactiveMap();
*
* const item$ = fromCollection(map, "someKey"); // watch the item at "someKey"
*
* console.log(item$.value); // undefined
*
* map.set("someKey", "someValue");
*
* console.log(item$.value); // "someValue"
* ```
*/
declare const fromCollection: <TKey = any, TValue = any>(collection: ReactiveCollection<TKey, TValue>, key: TKey) => ReadonlyVal<TValue | undefined>;
/**
* Create a readonly val from a reactive collection watching a specific key.
* Auto-flatten the value of the item if it is a Val.
*
* @param collection The reactive collection
* @param key The key to watch
* @returns A readonly val watching the item at the specified key
*
* @example
* ```ts
* import { ReactiveMap, flattenFromCollection } from "value-enhancer/collections"
* import { val } from "value-enhancer";
*
* const map = new ReactiveMap();
* const v = val("someValue")
*
* const item$ = flattenFromCollection(map, "someKey"); // watch the item at "someKey"
*
* console.log(item$.value); // undefined
*
* map.set("someKey", v);
*
* console.log(item$.value); // "someValue"
*
* v.set("someValue2");
*
* console.log(item$.value); // "someValue2"
* ```
*/
declare const flattenFromCollection: <TKey = any, TValue = any>(collection: ReactiveCollection<TKey, TValue>, key: TKey) => ReadonlyVal<FlattenVal<TValue> | undefined>;
export { ReactiveCollection, ReactiveList, ReactiveMap, ReactiveSet, flattenFromCollection, fromCollection };
export { ReactiveList, ReactiveMap, ReactiveSet };
'use strict';
// src/scheduler.ts
var nextTick = /* @__PURE__ */ Promise.resolve();
var pendingSubs1 = /* @__PURE__ */ new Set();
var pendingSubs2 = /* @__PURE__ */ new Set();
var pendingSubs = pendingSubs1;
var pending;
var flush = () => {
const curPendingSubs = pendingSubs;
pendingSubs = pendingSubs === pendingSubs1 ? pendingSubs2 : pendingSubs1;
pending = false;
for (const subs of curPendingSubs) {
subs.exec(1 /* Async */);
}
curPendingSubs.clear();
};
var schedule = (subs) => {
pendingSubs.add(subs);
pending = pending || nextTick.then(flush);
};
var cancelTask = (subs) => pendingSubs.delete(subs);
// src/utils.ts

@@ -12,5 +33,189 @@ var defaultEqual = Object.is;

};
var INIT_VALUE = {};
var isVal = (val) => !!val?.$valCompute;
// src/subscribers.ts
var Subscribers = class {
constructor(getValue, start) {
this.#getValue = getValue;
this.#start = start;
}
dirty = false;
notify() {
this.#notReadySubscribers.clear();
if (this.subs.size > 0) {
this.exec(3 /* Computed */);
this.exec(2 /* Eager */);
if (this[1 /* Async */] > 0) {
schedule(this);
}
} else {
this.dirty = false;
}
}
add(subscriber, mode) {
if (this.#start && this.subs.size <= 0) {
this.#startDisposer = this.#start(this);
}
const currentMode = this.subs.get(subscriber);
if (currentMode) {
this[currentMode]--;
}
this.#notReadySubscribers.add(subscriber);
this.subs.set(subscriber, mode);
this[mode]++;
return () => this.remove(subscriber);
}
remove(subscriber) {
this.#notReadySubscribers.delete(subscriber);
const mode = this.subs.get(subscriber);
if (mode) {
this.subs.delete(subscriber);
this[mode]--;
if (this.subs.size <= 0) {
this.#stop();
}
}
}
clear() {
this.subs.clear();
this.#notReadySubscribers.clear();
this[1 /* Async */] = this[2 /* Eager */] = this[3 /* Computed */] = 0;
cancelTask(this);
this.#stop();
}
exec(mode) {
if (this[mode] > 0) {
let value;
if (mode === 3 /* Computed */) {
if (this[1 /* Async */] + this[2 /* Eager */] <= 0) {
this.dirty = false;
}
} else {
value = this.#getValue();
if (!this.dirty) {
return;
}
if (mode === 1 /* Async */ || /* mode === SubscriberMode.Eager && */
this[1 /* Async */] <= 0) {
this.dirty = false;
}
}
for (const [sub, subMode] of this.subs) {
if (subMode === mode && !this.#notReadySubscribers.has(sub)) {
invoke(sub, value);
}
}
}
}
subs = /* @__PURE__ */ new Map();
#stop() {
this.#startDisposer && (this.#startDisposer = this.#startDisposer());
}
#getValue;
[1 /* Async */] = 0;
[2 /* Eager */] = 0;
[3 /* Computed */] = 0;
#notReadySubscribers = /* @__PURE__ */ new Set();
#start;
#startDisposer;
};
// src/readonly-val.ts
var ReadonlyValImpl = class {
/**
* Manage subscribers for a val.
*/
_subs;
#eager;
/**
* @param get A pure function that returns the current value of the val.
* @param config Custom config for the val.
* @param start A function that is called when a val get its first subscriber.
* The returned disposer will be called when the last subscriber unsubscribed from the val.
*/
constructor(get, { equal = defaultEqual, eager } = {}, start) {
this.get = get;
if (equal) {
this.$equal = equal;
}
this.#eager = eager;
this._subs = new Subscribers(get, start);
}
get value() {
return this.get();
}
get;
$equal;
reaction(subscriber, eager = this.#eager) {
return this._subs.add(
subscriber,
eager ? 2 /* Eager */ : 1 /* Async */
);
}
subscribe(subscriber, eager = this.#eager) {
const disposer = this.reaction(subscriber, eager);
invoke(subscriber, this.value);
this._subs.dirty = false;
return disposer;
}
$valCompute(subscriber) {
return this._subs.add(subscriber, 3 /* Computed */);
}
unsubscribe(subscriber) {
if (subscriber) {
this._subs.remove(subscriber);
} else {
this._subs.clear();
}
}
dispose() {
this._subs.clear();
}
/**
* @returns the string representation of `this.value`.
*
* @example
* ```js
* const v$ = val(val(val(1)));
* console.log(`${v$}`); // "1"
* ```
*/
toString() {
return String(this.value);
}
/**
* @returns the JSON representation of `this.value`.
*
* @example
* ```js
* const v$ = val(val(val({ a: 1 })));
* JSON.stringify(v$); // '{"a":1}'
* ```
*/
toJSON(key) {
const value = this.value;
return value && value.toJSON ? value.toJSON(key) : value;
}
};
function readonlyVal(value, config) {
let currentValue = value;
let subs;
const set = (value2) => {
if (!val.$equal?.(value2, currentValue)) {
currentValue = value2;
if (subs) {
subs.dirty = true;
subs.notify();
}
}
};
const val = new ReadonlyValImpl(
() => currentValue,
config,
(s) => {
subs = s;
}
);
return [val, set];
}
// src/collections/list.ts

@@ -21,16 +226,8 @@ var ReactiveList = class {

this.#data = arrayLike ? Array.from(arrayLike) : [];
const [val, setVal] = readonlyVal(this, { equal: false });
this.$ = val;
this.#set$ = setVal;
}
#watchers = /* @__PURE__ */ new Set();
watch(watcher) {
this.#watchers.add(watcher);
return () => this.unwatch(watcher);
}
unwatch(watcher) {
this.#watchers.delete(watcher);
}
notify(key) {
for (const sub of this.#watchers) {
invoke(sub, key);
}
}
$;
#set$;
/**

@@ -91,3 +288,3 @@ * Get the internal array. Use it as a read-only array.

first() {
if (this.#data.length) {
if (this.#data.length > 0) {
return this.#data[0];

@@ -100,3 +297,3 @@ }

last() {
if (this.#data.length) {
if (this.#data.length > 0) {
return this.#data[this.length - 1];

@@ -111,7 +308,5 @@ }

push(...items) {
this.#data.push(...items);
if (items.length == 1) {
this.notify(this.#data.length - 1);
} else if (items.length > 1) {
this.notify();
if (items.length > 0) {
this.#data.push(...items);
this.#set$(this);
}

@@ -127,3 +322,3 @@ }

const result = this.#data.pop();
this.notify(this.#data.length);
this.#set$(this);
return result;

@@ -138,5 +333,5 @@ }

pushHead(...items) {
this.#data.unshift(...items);
if (items.length > 0) {
this.notify();
this.#data.unshift(...items);
this.#set$(this);
}

@@ -152,3 +347,3 @@ }

const result = this.#data.shift();
this.notify();
this.#set$(this);
return result;

@@ -166,3 +361,3 @@ }

this.#data[index] = item;
this.notify(index);
this.#set$(this);
}

@@ -179,3 +374,3 @@ }

this.#data.splice(index, 0, ...items);
this.notify();
this.#set$(this);
}

@@ -193,6 +388,4 @@ }

const result = this.#data.splice(index, count);
if (result.length === 1) {
this.notify(index);
} else if (result.length > 1) {
this.notify();
if (result.length > 0) {
this.#set$(this);
}

@@ -205,5 +398,5 @@ }

clear() {
if (this.length) {
if (this.length > 0) {
this.#data.length = 0;
this.notify();
this.#set$(this);
}

@@ -226,3 +419,3 @@ return this;

if (isDirty || cached.size > 0) {
this.notify();
this.#set$(this);
}

@@ -238,3 +431,3 @@ return [...cached];

this.#data.reverse();
this.notify();
this.#set$(this);
}

@@ -256,3 +449,3 @@ return this;

this.#data.sort(compareFn);
this.notify();
this.#set$(this);
}

@@ -278,4 +471,10 @@ return this;

}
dispose() {
this.$.dispose();
}
};
// src/collections/utils.ts
var SET$ = Symbol("set");
// src/collections/map.ts

@@ -285,22 +484,12 @@ var ReactiveMap = class extends Map {

super(entries);
const [val, setVal] = readonlyVal(this, { equal: false });
this.$ = val;
this[SET$] = setVal;
}
_ws = /* @__PURE__ */ new Set();
watch(watcher) {
this._ws.add(watcher);
return () => this.unwatch(watcher);
}
unwatch(watcher) {
this._ws.delete(watcher);
}
notify(key) {
if (this._ws) {
for (const sub of this._ws) {
invoke(sub, key);
}
}
}
$;
[SET$];
delete(key) {
const deleted = super.delete(key);
if (deleted) {
this.notify(key);
this[SET$]?.(this);
}

@@ -312,3 +501,3 @@ return deleted;

super.clear();
this.notify();
this[SET$]?.(this);
}

@@ -320,9 +509,6 @@ }

if (isDirty) {
this.notify(key);
this[SET$]?.(this);
}
return this;
}
dispose() {
this._ws.clear();
}
/**

@@ -343,6 +529,9 @@ * Replace all entries in the Map.

if (isDirty || cached.size > 0) {
this.notify();
this[SET$]?.(this);
}
return cached;
}
dispose() {
this.$.dispose();
}
};

@@ -354,27 +543,12 @@

super(entries);
this.get = this.has;
const [val, setVal] = readonlyVal(this, { equal: false });
this.$ = val;
this[SET$] = setVal;
}
_ws = /* @__PURE__ */ new Set();
watch(watcher) {
this._ws.add(watcher);
return () => this.unwatch(watcher);
}
unwatch(watcher) {
this._ws.delete(watcher);
}
notify(value) {
if (this._ws) {
for (const sub of this._ws) {
invoke(sub, value);
}
}
}
/**
* @alias Set#has
*/
get;
$;
[SET$];
delete(key) {
const deleted = super.delete(key);
if (deleted) {
this.notify(key);
this[SET$]?.(this);
}

@@ -386,3 +560,3 @@ return deleted;

super.clear();
this.notify();
this[SET$]?.(this);
}

@@ -394,3 +568,3 @@ }

if (isDirty) {
this.notify(value);
this[SET$]?.(this);
}

@@ -400,3 +574,3 @@ return this;

dispose() {
this._ws.clear();
this.$.dispose();
}

@@ -417,3 +591,3 @@ /**

if (isDirty || cached.size > 0) {
this.notify();
this[SET$]?.(this);
}

@@ -424,314 +598,4 @@ return cached;

// src/scheduler.ts
var nextTick = /* @__PURE__ */ Promise.resolve();
var pendingSubs1 = /* @__PURE__ */ new Set();
var pendingSubs2 = /* @__PURE__ */ new Set();
var pendingSubs = pendingSubs1;
var pending;
var flush = () => {
const curPendingSubs = pendingSubs;
pendingSubs = pendingSubs === pendingSubs1 ? pendingSubs2 : pendingSubs1;
pending = false;
for (const subs of curPendingSubs) {
subs.exec(1 /* Async */);
}
curPendingSubs.clear();
};
var schedule = (subs) => {
pendingSubs.add(subs);
pending = pending || nextTick.then(flush);
};
var cancelTask = (subs) => pendingSubs.delete(subs);
// src/subscribers.ts
var Subscribers = class {
constructor(getValue, start) {
this.#getValue = getValue;
this.#start = start;
}
dirty = false;
notify() {
this.#notReadySubscribers.clear();
if (this.subs.size > 0) {
this.exec(3 /* Computed */);
this.exec(2 /* Eager */);
if (this[1 /* Async */] > 0) {
schedule(this);
}
} else {
this.dirty = false;
}
}
add(subscriber, mode) {
if (this.#start && this.subs.size <= 0) {
this.#startDisposer = this.#start(this);
}
const currentMode = this.subs.get(subscriber);
if (currentMode) {
this[currentMode]--;
}
this.#notReadySubscribers.add(subscriber);
this.subs.set(subscriber, mode);
this[mode]++;
return () => this.remove(subscriber);
}
remove(subscriber) {
this.#notReadySubscribers.delete(subscriber);
const mode = this.subs.get(subscriber);
if (mode) {
this.subs.delete(subscriber);
this[mode]--;
if (this.subs.size <= 0) {
this.#stop();
}
}
}
clear() {
this.subs.clear();
this.#notReadySubscribers.clear();
this[1 /* Async */] = this[2 /* Eager */] = this[3 /* Computed */] = 0;
cancelTask(this);
this.#stop();
}
exec(mode) {
if (this[mode] > 0) {
let value;
if (mode === 3 /* Computed */) {
if (this[1 /* Async */] + this[2 /* Eager */] <= 0) {
this.dirty = false;
}
} else {
value = this.#getValue();
if (!this.dirty) {
return;
}
if (mode === 1 /* Async */ || /* mode === SubscriberMode.Eager && */
this[1 /* Async */] <= 0) {
this.dirty = false;
}
}
for (const [sub, subMode] of this.subs) {
if (subMode === mode && !this.#notReadySubscribers.has(sub)) {
invoke(sub, value);
}
}
}
}
subs = /* @__PURE__ */ new Map();
#stop() {
this.#startDisposer && (this.#startDisposer = this.#startDisposer());
}
#getValue;
[1 /* Async */] = 0;
[2 /* Eager */] = 0;
[3 /* Computed */] = 0;
#notReadySubscribers = /* @__PURE__ */ new Set();
#start;
#startDisposer;
};
// src/readonly-val.ts
var ReadonlyValImpl = class {
/**
* Manage subscribers for a val.
*/
_subs;
#eager;
/**
* @param get A pure function that returns the current value of the val.
* @param config Custom config for the val.
* @param start A function that is called when a val get its first subscriber.
* The returned disposer will be called when the last subscriber unsubscribed from the val.
*/
constructor(get, { equal, compare, eager } = {}, start) {
this.get = get;
this.compare = this.equal = equal || compare || defaultEqual;
this.#eager = eager;
this._subs = new Subscribers(get, start);
}
get value() {
return this.get();
}
get;
equal;
/**
* @ignore
* @deprecated Use `equal` instead.
*/
compare;
reaction(subscriber, eager = this.#eager) {
return this._subs.add(
subscriber,
eager ? 2 /* Eager */ : 1 /* Async */
);
}
subscribe(subscriber, eager = this.#eager) {
const disposer = this.reaction(subscriber, eager);
invoke(subscriber, this.value);
this._subs.dirty = false;
return disposer;
}
$valCompute(subscriber) {
return this._subs.add(subscriber, 3 /* Computed */);
}
unsubscribe(subscriber) {
if (subscriber) {
this._subs.remove(subscriber);
} else {
this._subs.clear();
}
}
dispose() {
this._subs.clear();
}
/**
* @returns the string representation of `this.value`.
*
* @example
* ```js
* const v$ = val(val(val(1)));
* console.log(`${v$}`); // "1"
* ```
*/
toString() {
return String(this.value);
}
/**
* @returns the JSON representation of `this.value`.
*
* @example
* ```js
* const v$ = val(val(val({ a: 1 })));
* JSON.stringify(v$); // '{"a":1}'
* ```
*/
toJSON(key) {
const value = this.value;
return value && value.toJSON ? value.toJSON(key) : value;
}
};
// src/flatten-from.ts
var FlattenFromImpl = class extends ReadonlyValImpl {
constructor(getValue, listen, config) {
const initialEqual = config && (config.equal || config.compare);
let currentValue = INIT_VALUE;
let dirty = false;
let notified = false;
let innerMaybeVal;
let innerVal;
let innerDisposer;
const computeValue = () => {
if (this._subs.subs.size <= 0) {
updateInnerVal();
}
return innerVal ? innerVal.value : innerMaybeVal;
};
const get = () => {
if (currentValue === INIT_VALUE || this._subs.subs.size <= 0) {
currentValue = computeValue();
} else if (dirty) {
const value = computeValue();
if (!this.equal(value, currentValue)) {
this._subs.dirty = true;
currentValue = value;
}
}
dirty = notified = false;
return currentValue;
};
const updateInnerVal = () => {
const maybeVal = getValue();
if (maybeVal !== innerMaybeVal) {
innerMaybeVal = maybeVal;
innerVal = isVal(maybeVal) ? maybeVal : null;
innerDisposer?.();
innerDisposer = innerVal && innerVal.$valCompute(notify);
currentEqual = initialEqual || (innerVal ? innerVal.equal : defaultEqual);
}
};
const notify = () => {
dirty = true;
if (!notified) {
notified = true;
this._subs.notify();
}
};
super(get, config, () => {
const outerDisposer = listen(() => {
updateInnerVal();
notify();
});
updateInnerVal();
currentValue = innerVal ? innerVal.value : innerMaybeVal;
dirty = notified = false;
return () => {
innerDisposer?.();
outerDisposer?.();
};
});
let currentEqual = this.equal;
this.equal = (newValue, oldValue) => currentEqual(newValue, oldValue);
}
};
var flattenFrom = (getValue, listen, config) => new FlattenFromImpl(getValue, listen, config);
// src/from.ts
var FromImpl = class extends ReadonlyValImpl {
constructor(getValue, listen, config) {
let currentValue = INIT_VALUE;
let dirty = false;
let notified = false;
const get = () => {
if (currentValue === INIT_VALUE || this._subs.subs.size <= 0) {
currentValue = getValue();
} else if (dirty) {
const value = getValue();
if (!this.equal(value, currentValue)) {
this._subs.dirty = true;
currentValue = value;
}
}
dirty = notified = false;
return currentValue;
};
const notify = () => {
dirty = true;
if (!notified) {
notified = true;
this._subs.notify();
}
};
super(get, config, () => {
const disposer = listen(notify);
currentValue = getValue();
dirty = notified = false;
return disposer;
});
}
};
var from = (getValue, listen, config) => new FromImpl(getValue, listen, config);
// src/collections/utils.ts
var fromCollection = (collection, key) => from(
() => collection.get(key),
(notify) => collection.watch((k) => {
if (k === key || k == null) {
notify();
}
})
);
var flattenFromCollection = (collection, key) => flattenFrom(
() => collection.get(key),
(notify) => collection.watch((k) => {
if (k === key || k == null) {
notify();
}
})
);
exports.ReactiveList = ReactiveList;
exports.ReactiveMap = ReactiveMap;
exports.ReactiveSet = ReactiveSet;
exports.flattenFromCollection = flattenFromCollection;
exports.fromCollection = fromCollection;

@@ -1,3 +0,3 @@

import { R as ReadonlyVal, V as ValInputsValueTuple, a as ValConfig, F as FlattenVal, b as ValDisposer, c as ValSetValue, d as Val, e as ValSubscriber } from './typings-4a9c4c94.js';
export { f as ValCompare, g as ValEqual } from './typings-4a9c4c94.js';
import { R as ReadonlyVal, V as ValInputsValueTuple, a as ValConfig, F as FlattenVal, b as ValDisposer, c as ValSetValue, d as Val, e as ValSubscriber } from './typings-8a4e5768.js';
export { f as ValEqual } from './typings-8a4e5768.js';

@@ -12,7 +12,2 @@ /** Returns the value passed in. */

declare const isVal: <T>(val: T) => val is T extends ReadonlyVal<any> ? T : never;
/**
* @ignore
* @deprecated No longer needed. `isVal` works without `markVal` now.
*/
declare const markVal: <T extends ReadonlyVal>(val: T) => T;

@@ -88,8 +83,2 @@ type CombineValTransform<TCombinedValue = any, TValues extends readonly any[] = any[]> = (newValues: TValues) => TCombinedValue;

declare function flatten<TSrcValue = any, TValOrValue = any>(val: ReadonlyVal<TSrcValue>, get: (value: TSrcValue) => TValOrValue, config?: ValConfig<FlattenVal<TValOrValue>>): ReadonlyVal<FlattenVal<TValOrValue>>;
/**
* @ignore
* @deprecated
* Renamed to `flatten`.
*/
declare const unwrap: typeof flatten;

@@ -108,8 +97,2 @@ /**

declare const flattenFrom: <TValOrValue = any>(getValue: () => TValOrValue, listen: (notify: () => void) => ValDisposer | void | undefined, config?: ValConfig<FlattenVal<TValOrValue>> | undefined) => ReadonlyVal<FlattenVal<TValOrValue>>;
/**
* @ignore
* @deprecated
* Renamed to `flattenFrom`.
*/
declare const unwrapFrom: <TValOrValue = any>(getValue: () => TValOrValue, listen: (notify: () => void) => ValDisposer | void | undefined, config?: ValConfig<FlattenVal<TValOrValue>> | undefined) => ReadonlyVal<FlattenVal<TValOrValue>>;

@@ -251,2 +234,2 @@ /**

export { CombineValTransform, DerivedValTransform, FlattenVal, ReadonlyVal, Val, ValConfig, ValDisposer, ValSetValue, ValSubscriber, combine, derive, flatten, flattenFrom, from, groupVals, identity, isVal, markVal, reaction, readonlyVal, setValue, subscribe, unsubscribe, unwrap, unwrapFrom, val };
export { CombineValTransform, DerivedValTransform, FlattenVal, ReadonlyVal, Val, ValConfig, ValDisposer, ValSetValue, ValSubscriber, combine, derive, flatten, flattenFrom, from, groupVals, identity, isVal, reaction, readonlyVal, setValue, subscribe, unsubscribe, val };

@@ -11,3 +11,3 @@ 'use strict';

for (let i = valInputs.length - 1; i >= 0; i--) {
if (!valInputs[i].equal(valInputs[i].value, cachedSrcValues[i])) {
if (!valInputs[i].$equal?.(valInputs[i].value, cachedSrcValues[i])) {
return false;

@@ -29,3 +29,2 @@ }

var isVal = (val2) => !!val2?.$valCompute;
var markVal = identity;

@@ -153,5 +152,7 @@ // src/scheduler.ts

*/
constructor(get, { equal, compare, eager } = {}, start) {
constructor(get, { equal = defaultEqual, eager } = {}, start) {
this.get = get;
this.compare = this.equal = equal || compare || defaultEqual;
if (equal) {
this.$equal = equal;
}
this.#eager = eager;

@@ -164,8 +165,3 @@ this._subs = new Subscribers(get, start);

get;
equal;
/**
* @ignore
* @deprecated Use `equal` instead.
*/
compare;
$equal;
reaction(subscriber, eager = this.#eager) {

@@ -226,3 +222,3 @@ return this._subs.add(

const set = (value2) => {
if (!val2.equal(value2, currentValue)) {
if (!val2.$equal?.(value2, currentValue)) {
currentValue = value2;

@@ -266,3 +262,3 @@ if (subs) {

const value = getValue2();
if (!this.equal(value, currentValue)) {
if (!this.$equal?.(value, currentValue)) {
this._subs.dirty = true;

@@ -311,3 +307,3 @@ currentValue = value;

return from(
() => cachedSrcValue !== INIT_VALUE && val2.equal(val2.value, cachedSrcValue) ? cachedValue : cachedValue = transform(cachedSrcValue = val2.value),
() => cachedSrcValue === INIT_VALUE || !val2.$equal?.(val2.value, cachedSrcValue) ? cachedValue = transform(cachedSrcValue = val2.value) : cachedValue,
(notify) => val2.$valCompute(notify),

@@ -321,3 +317,3 @@ config

constructor(getValue2, listen, config) {
const initialEqual = config && (config.equal || config.compare);
const initialEqual = config?.equal;
let currentValue = INIT_VALUE;

@@ -340,3 +336,3 @@ let dirty = false;

const value = computeValue();
if (!this.equal(value, currentValue)) {
if (!this.$equal?.(value, currentValue)) {
this._subs.dirty = true;

@@ -356,3 +352,3 @@ currentValue = value;

innerDisposer = innerVal && innerVal.$valCompute(notify);
currentEqual = initialEqual || (innerVal ? innerVal.equal : defaultEqual);
this.$equal = initialEqual || (initialEqual === false ? void 0 : innerVal ? innerVal.$equal : defaultEqual);
}

@@ -380,8 +376,5 @@ };

});
let currentEqual = this.equal;
this.equal = (newValue, oldValue) => currentEqual(newValue, oldValue);
}
};
var flattenFrom = (getValue2, listen, config) => new FlattenFromImpl(getValue2, listen, config);
var unwrapFrom = flattenFrom;

@@ -396,3 +389,2 @@ // src/flatten.ts

}
var unwrap = flatten;

@@ -405,3 +397,3 @@ // src/val.ts

this.set = (value) => {
if (!this.equal(value, currentValue)) {
if (!this.$equal?.(value, currentValue)) {
this._subs.dirty = true;

@@ -439,3 +431,2 @@ currentValue = value;

exports.isVal = isVal;
exports.markVal = markVal;
exports.reaction = reaction;

@@ -446,4 +437,2 @@ exports.readonlyVal = readonlyVal;

exports.unsubscribe = unsubscribe;
exports.unwrap = unwrap;
exports.unwrapFrom = unwrapFrom;
exports.val = val;
{
"name": "value-enhancer",
"version": "3.1.5",
"version": "4.0.0",
"private": false,

@@ -5,0 +5,0 @@ "description": "A tiny library to enhance value with reactive wrapper.",

@@ -428,7 +428,8 @@ # [value-enhancer](https://github.com/crimx/value-enhancer)

```ts
import { ReactiveList, fromCollection } from "value-enhancer/collections";
import { derive } from "value-enhancer";
import { ReactiveList } from "value-enhancer/collections";
const list = new ReactiveList(["a", "b", "c"]);
const item$ = fromCollection(list, 2); // watch the item at index 2
const item$ = derive(list.$, list => list.get(2)); // watch the item at index 2

@@ -443,4 +444,4 @@ console.log(item$.value); // "c"

```ts
import { ReactiveMap, flattenFromCollection } from "value-enhancer/collections";
import { val } from "value-enhancer";
import { val, flatten } from "value-enhancer";
import { ReactiveMap } from "value-enhancer/collections";

@@ -450,3 +451,3 @@ const map = new ReactiveMap();

const item$ = flattenFromCollection(map, "someKey"); // watch the item at "someKey"
const item$ = flatten(map.$, map => map.get("someKey")); // watch the item at "someKey"

@@ -453,0 +454,0 @@ console.log(item$.value); // undefined

@@ -1,6 +0,3 @@

export type { ReactiveCollection } from "./typings";
export { ReactiveList } from "./list";
export { ReactiveMap } from "./map";
export { ReactiveSet } from "./set";
export { flattenFromCollection, fromCollection } from "./utils";

@@ -1,26 +0,22 @@

import { invoke } from "../utils";
import type { ReactiveCollection } from "./typings";
import { readonlyVal } from "../readonly-val";
import type { ReadonlyVal, ValSetValue } from "../typings";
/**
* A reactive list. Similar to an Array except bracket-notation(e.g. `arr[0]`) is not allowed to get/set elements.
* Changes to the map will be notified to subscribers of `watch`.
* Changes to the map will be notified to subscribers of `$`.
*
* @example
* ```ts
* import { ReactiveList, fromCollection } from "value-enhancer/collections"
* import { derive } from "value-enhancer";
* import { ReactiveList } from "value-enhancer/collections";
*
* const list = new ReactiveList(["a", "b", "c"]);
* const item$ = derive(list.$, list => list.get(2)); // watch the item at index 2
*
* const item$ = fromCollection(list, 2); // watch the item at index 2
*
* console.log(item$.value); // "c"
*
* list.set(2, "d");
*
* console.log(item$.value); // "d"
* ```
*/
export class ReactiveList<TValue>
implements ReactiveCollection<number, TValue>
{
export class ReactiveList<TValue> {
#data: TValue[];

@@ -30,21 +26,11 @@

this.#data = arrayLike ? Array.from(arrayLike) : [];
const [val, setVal] = readonlyVal(this, { equal: false });
this.$ = val;
this.#set$ = setVal;
}
#watchers = new Set<(key?: number) => void>();
public $: ReadonlyVal<this>;
public watch(watcher: (key?: number) => void): () => void {
this.#watchers.add(watcher);
return () => this.unwatch(watcher);
}
#set$: ValSetValue<this>;
public unwatch(watcher: (...args: any[]) => any): void {
this.#watchers.delete(watcher);
}
public notify(key?: number): void {
for (const sub of this.#watchers) {
invoke(sub, key);
}
}
/**

@@ -113,3 +99,3 @@ * Get the internal array. Use it as a read-only array.

public first(): TValue | undefined {
if (this.#data.length) {
if (this.#data.length > 0) {
return this.#data[0];

@@ -123,3 +109,3 @@ }

public last(): TValue | undefined {
if (this.#data.length) {
if (this.#data.length > 0) {
return this.#data[this.length - 1];

@@ -135,7 +121,5 @@ }

public push(...items: TValue[]): void {
this.#data.push(...items);
if (items.length == 1) {
this.notify(this.#data.length - 1);
} else if (items.length > 1) {
this.notify();
if (items.length > 0) {
this.#data.push(...items);
this.#set$(this);
}

@@ -152,3 +136,3 @@ }

const result = this.#data.pop();
this.notify(this.#data.length);
this.#set$(this);
return result;

@@ -164,5 +148,5 @@ }

public pushHead(...items: TValue[]): void {
this.#data.unshift(...items);
if (items.length > 0) {
this.notify();
this.#data.unshift(...items);
this.#set$(this);
}

@@ -179,3 +163,3 @@ }

const result = this.#data.shift();
this.notify();
this.#set$(this);
return result;

@@ -194,3 +178,3 @@ }

this.#data[index] = item;
this.notify(index);
this.#set$(this);
}

@@ -208,3 +192,3 @@ }

this.#data.splice(index, 0, ...items);
this.notify();
this.#set$(this);
}

@@ -223,6 +207,4 @@ }

const result = this.#data.splice(index, count);
if (result.length === 1) {
this.notify(index);
} else if (result.length > 1) {
this.notify();
if (result.length > 0) {
this.#set$(this);
}

@@ -236,5 +218,5 @@ }

public clear(): this {
if (this.length) {
if (this.length > 0) {
this.#data.length = 0;
this.notify();
this.#set$(this);
}

@@ -258,3 +240,3 @@ return this;

if (isDirty || cached.size > 0) {
this.notify();
this.#set$(this);
}

@@ -271,3 +253,3 @@ return [...cached];

this.#data.reverse();
this.notify();
this.#set$(this);
}

@@ -290,3 +272,3 @@ return this;

this.#data.sort(compareFn);
this.notify();
this.#set$(this);
}

@@ -315,2 +297,6 @@ return this;

}
public dispose(): void {
this.$.dispose();
}
}

@@ -1,56 +0,41 @@

import type { ReactiveCollection } from "./typings";
import { readonlyVal } from "../readonly-val";
import type { ReadonlyVal, ValSetValue } from "../typings";
import { SET$ } from "./utils";
import { invoke } from "../utils";
/**
* A reactive map inherited from `Map`.
* Changes to the map will be notified to subscribers of `watch`.
* Changes to the map will be notified to subscribers of `$`.
*
* @example
* ```ts
* import { ReactiveMap, fromCollection } from "value-enhancer/collections"
* import { val, flatten } from "value-enhancer";
* import { ReactiveMap } from "value-enhancer/collections";
*
* const map = new ReactiveMap();
* const v = val("someValue");
* const item$ = flatten(map.$, map => map.get("someKey")); // watch the item at "someKey"
*
* const item$ = fromCollection(map, "someKey"); // watch the item at "someKey"
*
* console.log(item$.value); // undefined
*
* map.set("someKey", "someValue");
*
* map.set("someKey", v);
* console.log(item$.value); // "someValue"
* v.set("someValue2");
* console.log(item$.value); // "someValue2"
* ```
*/
export class ReactiveMap<TKey, TValue>
extends Map<TKey, TValue>
implements ReactiveCollection<TKey, TValue>
{
export class ReactiveMap<TKey, TValue> extends Map<TKey, TValue> {
public constructor(entries?: readonly (readonly [TKey, TValue])[] | null) {
super(entries);
const [val, setVal] = readonlyVal(this, { equal: false });
this.$ = val;
this[SET$] = setVal;
}
private _watchers_ = new Set<(key?: TKey) => void>();
public readonly $: ReadonlyVal<this>;
public watch(watcher: (key?: TKey) => void): () => void {
this._watchers_.add(watcher);
return () => this.unwatch(watcher);
}
private [SET$]?: ValSetValue<this>;
public unwatch(watcher: (...args: any[]) => any): void {
this._watchers_.delete(watcher);
}
public notify(key?: TKey): void {
// watchers may not exist during super constructor call
if (this._watchers_) {
for (const sub of this._watchers_) {
invoke(sub, key);
}
}
}
public override delete(key: TKey): boolean {
const deleted = super.delete(key);
if (deleted) {
this.notify(key);
this[SET$]?.(this);
}

@@ -63,3 +48,3 @@ return deleted;

super.clear();
this.notify();
this[SET$]?.(this);
}

@@ -72,3 +57,3 @@ }

if (isDirty) {
this.notify(key);
this[SET$]?.(this);
}

@@ -78,6 +63,2 @@ return this;

public dispose(): void {
this._watchers_.clear();
}
/**

@@ -100,6 +81,10 @@ * Replace all entries in the Map.

if (isDirty || cached.size > 0) {
this.notify();
this[SET$]?.(this);
}
return cached;
}
public dispose(): void {
this.$.dispose();
}
}

@@ -10,5 +10,3 @@ # Reactive Collections

ReactiveList,
fromCollection,
flattenFromCollection,
} from "value-enhancer/collections";
```

@@ -1,63 +0,39 @@

import type { ReactiveCollection } from "./typings";
import { readonlyVal } from "../readonly-val";
import type { ReadonlyVal, ValSetValue } from "../typings";
import { SET$ } from "./utils";
import { invoke } from "../utils";
/**
* A reactive set inherited from `Set`.
* Changes to the set will be notified to subscribers of `watch`.
* Changes to the set will be notified to subscribers of `$`.
*
* @example
* ```ts
* import { ReactiveSet, fromCollection } from "value-enhancer/collections"
* import { derive } from "value-enhancer";
* import { ReactiveSet } from "value-enhancer/collections"
*
* const set = new ReactiveSet();
* const item$ = derive(set.$, set => set.has("someValue")); // watch the existence of "someValue"
*
* const item$ = fromCollection(map, "someValue"); // watch the existence of "someValue"
*
* console.log(item$.value); // false
*
* map.add("someValue");
*
* set.add("someValue");
* console.log(item$.value); // true
* ```
*/
export class ReactiveSet<TValue>
extends Set<TValue>
implements ReactiveCollection<TValue, boolean>
{
export class ReactiveSet<TValue> extends Set<TValue> {
public constructor(entries?: readonly TValue[] | null) {
super(entries);
this.get = this.has;
const [val, setVal] = readonlyVal(this, { equal: false });
this.$ = val;
this[SET$] = setVal;
}
private _watchers_ = new Set<(value?: TValue) => void>();
public readonly $: ReadonlyVal<this>;
public watch(watcher: (value?: TValue) => void): () => void {
this._watchers_.add(watcher);
return () => this.unwatch(watcher);
}
private [SET$]?: ValSetValue<this>;
public unwatch(watcher: (...args: any[]) => any): void {
this._watchers_.delete(watcher);
}
public notify(value?: TValue): void {
// watchers may not exist during super constructor call
if (this._watchers_) {
for (const sub of this._watchers_) {
invoke(sub, value);
}
}
}
/**
* @alias Set#has
*/
public get: (value: TValue) => boolean;
public override delete(key: TValue): boolean {
const deleted = super.delete(key);
if (deleted) {
this.notify(key);
this[SET$]?.(this);
}

@@ -70,3 +46,3 @@ return deleted;

super.clear();
this.notify();
this[SET$]?.(this);
}

@@ -79,3 +55,3 @@ }

if (isDirty) {
this.notify(value);
this[SET$]?.(this);
}

@@ -86,3 +62,3 @@ return this;

public dispose(): void {
this._watchers_.clear();
this.$.dispose();
}

@@ -104,3 +80,3 @@

if (isDirty || cached.size > 0) {
this.notify();
this[SET$]?.(this);
}

@@ -107,0 +83,0 @@ return cached;

@@ -1,84 +0,1 @@

import type { FlattenVal, ReadonlyVal } from "../typings";
import type { ReactiveCollection } from "./typings";
import { flattenFrom } from "../flatten-from";
import { from } from "../from";
/**
* Create a readonly val from a reactive collection watching a specific key.
*
* @param collection The reactive collection
* @param key The key to watch
* @returns A readonly val watching the item at the specified key
*
* @example
* ```ts
* import { ReactiveMap, fromCollection } from "value-enhancer/collections"
*
* const map = new ReactiveMap();
*
* const item$ = fromCollection(map, "someKey"); // watch the item at "someKey"
*
* console.log(item$.value); // undefined
*
* map.set("someKey", "someValue");
*
* console.log(item$.value); // "someValue"
* ```
*/
export const fromCollection = <TKey = any, TValue = any>(
collection: ReactiveCollection<TKey, TValue>,
key: TKey
): ReadonlyVal<TValue | undefined> =>
from(
() => collection.get(key),
notify =>
collection.watch(k => {
if (k === key || k == null) {
notify();
}
})
);
/**
* Create a readonly val from a reactive collection watching a specific key.
* Auto-flatten the value of the item if it is a Val.
*
* @param collection The reactive collection
* @param key The key to watch
* @returns A readonly val watching the item at the specified key
*
* @example
* ```ts
* import { ReactiveMap, flattenFromCollection } from "value-enhancer/collections"
* import { val } from "value-enhancer";
*
* const map = new ReactiveMap();
* const v = val("someValue")
*
* const item$ = flattenFromCollection(map, "someKey"); // watch the item at "someKey"
*
* console.log(item$.value); // undefined
*
* map.set("someKey", v);
*
* console.log(item$.value); // "someValue"
*
* v.set("someValue2");
*
* console.log(item$.value); // "someValue2"
* ```
*/
export const flattenFromCollection = <TKey = any, TValue = any>(
collection: ReactiveCollection<TKey, TValue>,
key: TKey
): ReadonlyVal<FlattenVal<TValue> | undefined> =>
flattenFrom(
() => collection.get(key),
notify =>
collection.watch(k => {
if (k === key || k == null) {
notify();
}
})
);
export const SET$ = Symbol("set");

@@ -43,5 +43,5 @@ import type { ReadonlyVal, ValConfig } from "./typings";

() =>
cachedSrcValue !== INIT_VALUE && val.equal(val.value, cachedSrcValue)
? cachedValue
: (cachedValue = transform((cachedSrcValue = val.value))),
cachedSrcValue === INIT_VALUE || !val.$equal?.(val.value, cachedSrcValue)
? (cachedValue = transform((cachedSrcValue = val.value)))
: cachedValue,
notify => val.$valCompute(notify),

@@ -48,0 +48,0 @@ config

@@ -20,3 +20,3 @@ import type {

) {
const initialEqual = config && (config.equal || config.compare);
const initialEqual = config?.equal;

@@ -43,3 +43,3 @@ let currentValue = INIT_VALUE as TValue;

const value = computeValue();
if (!this.equal(value, currentValue)) {
if (!this.$equal?.(value, currentValue)) {
this._subs.dirty = true;

@@ -60,4 +60,9 @@ currentValue = value;

innerDisposer = innerVal && innerVal.$valCompute(notify);
currentEqual =
initialEqual || (innerVal ? innerVal.equal : defaultEqual);
this.$equal =
initialEqual ||
(initialEqual === false
? void 0
: innerVal
? innerVal.$equal
: defaultEqual);
}

@@ -90,6 +95,2 @@ };

});
let currentEqual = this.equal;
this.equal = (newValue: TValue, oldValue: TValue) =>
currentEqual(newValue, oldValue);
}

@@ -115,8 +116,1 @@ }

new FlattenFromImpl(getValue, listen, config);
/**
* @ignore
* @deprecated
* Renamed to `flattenFrom`.
*/
export const unwrapFrom = flattenFrom;

@@ -60,8 +60,1 @@ import type { FlattenVal, ReadonlyVal, ValConfig } from "./typings";

}
/**
* @ignore
* @deprecated
* Renamed to `flatten`.
*/
export const unwrap = flatten;

@@ -20,3 +20,3 @@ import { ReadonlyValImpl } from "./readonly-val";

const value = getValue();
if (!this.equal(value, currentValue)) {
if (!this.$equal?.(value, currentValue)) {
this._subs.dirty = true;

@@ -23,0 +23,0 @@ currentValue = value;

@@ -5,3 +5,2 @@ export type {

Val,
ValCompare,
ValConfig,

@@ -14,8 +13,8 @@ ValDisposer,

export { identity, isVal, markVal } from "./utils";
export { identity, isVal } from "./utils";
export { combine, type CombineValTransform } from "./combine";
export { derive, type DerivedValTransform } from "./derive";
export { flatten, unwrap } from "./flatten";
export { flattenFrom, unwrapFrom } from "./flatten-from";
export { flatten } from "./flatten";
export { flattenFrom } from "./flatten-from";
export { from } from "./from";

@@ -22,0 +21,0 @@ export { groupVals, readonlyVal } from "./readonly-val";

@@ -32,7 +32,9 @@ import type { ValOnStart } from "./subscribers";

get: () => TValue,
{ equal, compare, eager }: ValConfig<TValue> = {},
{ equal = defaultEqual, eager }: ValConfig<TValue> = {},
start?: ValOnStart
) {
this.get = get;
this.compare = this.equal = equal || compare || defaultEqual;
if (equal) {
this.$equal = equal;
}
this.#eager = eager;

@@ -48,10 +50,4 @@ this._subs = new Subscribers<TValue>(get, start);

public equal: (this: void, newValue: TValue, oldValue: TValue) => boolean;
public $equal?: (this: void, newValue: TValue, oldValue: TValue) => boolean;
/**
* @ignore
* @deprecated Use `equal` instead.
*/
public compare: (this: void, newValue: TValue, oldValue: TValue) => boolean;
public reaction(

@@ -153,3 +149,3 @@ subscriber: ValSubscriber<TValue>,

const set = (value: TValue | undefined): void => {
if (!val.equal(value, currentValue)) {
if (!val.$equal?.(value, currentValue)) {
currentValue = value;

@@ -156,0 +152,0 @@ if (subs) {

@@ -7,9 +7,4 @@ export interface ReadonlyVal<TValue = any> {

/** Compare two values. Default `Object.is`. */
equal(this: void, newValue: TValue, oldValue: TValue): boolean;
$equal?: (this: void, newValue: TValue, oldValue: TValue) => boolean;
/**
* @ignore
* @deprecated Use `equal` instead.
*/
compare(this: void, newValue: TValue, oldValue: TValue): boolean;
/**
* Subscribe to value changes without immediate emission.

@@ -60,11 +55,2 @@ * @param subscriber

/**
* @ignore
* @deprecated Use Equal instead.
*/
export type ValCompare<TValue = any> = (
newValue: TValue,
oldValue: TValue
) => boolean;
export type ValSubscriber<TValue = any> = (newValue: TValue) => void;

@@ -80,10 +66,6 @@

* Compare two values. Default `Object.is`.
* `false` to disable equality check.
*/
equal?: ValEqual<TValue>;
equal?: ValEqual<TValue> | false;
/**
* @ignore
* @deprecated Use `equal` instead.
*/
compare?: ValEqual<TValue>;
/**
* Set the default behavior of subscription and reaction.

@@ -90,0 +72,0 @@ * Emission triggers synchronously if `true`. Default `false`.

@@ -19,3 +19,3 @@ import type { ReadonlyVal, ValInputsValueTuple } from "./typings";

for (let i = valInputs.length - 1; i >= 0; i--) {
if (!valInputs[i].equal(valInputs[i].value, cachedSrcValues[i])) {
if (!valInputs[i].$equal?.(valInputs[i].value, cachedSrcValues[i])) {
return false;

@@ -54,7 +54,1 @@ }

!!(val as ReadonlyVal | undefined)?.$valCompute;
/**
* @ignore
* @deprecated No longer needed. `isVal` works without `markVal` now.
*/
export const markVal: <T extends ReadonlyVal>(val: T) => T = identity;

@@ -12,3 +12,3 @@ import type { Val, ValConfig } from "./typings";

this.set = (value: TValue) => {
if (!this.equal(value, currentValue)) {
if (!this.$equal?.(value, currentValue)) {
this._subs.dirty = true;

@@ -15,0 +15,0 @@ currentValue = value;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc