2021-06-18 13:05:06 +02:00
|
|
|
import DerivationFromSource from './derivations/DerivationFromSource'
|
|
|
|
import type {IDerivation} from './derivations/IDerivation'
|
|
|
|
import Emitter from './utils/Emitter'
|
2022-01-19 13:06:13 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Common interface for Box types. Boxes wrap a single value.
|
|
|
|
*/
|
2021-06-18 13:05:06 +02:00
|
|
|
export interface IBox<V> {
|
2022-01-19 13:06:13 +01:00
|
|
|
/**
|
|
|
|
* Sets the value of the Box.
|
|
|
|
*
|
|
|
|
* @param v The value to update the Box with.
|
|
|
|
*/
|
|
|
|
|
2021-06-18 13:05:06 +02:00
|
|
|
set(v: V): void
|
2022-01-19 13:06:13 +01:00
|
|
|
/**
|
|
|
|
* Gets the value of the Box.
|
|
|
|
*
|
|
|
|
* @remarks
|
|
|
|
* Usages of `get()` aren't tracked, they are only for retrieving the value. To track changes, you need to
|
|
|
|
* create a derivation.
|
|
|
|
*
|
|
|
|
* @see derivation
|
|
|
|
*/
|
2021-06-18 13:05:06 +02:00
|
|
|
get(): V
|
2022-01-19 13:06:13 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a derivation of the Box that you can use to track changes to it.
|
|
|
|
*/
|
2021-06-18 13:05:06 +02:00
|
|
|
derivation: IDerivation<V>
|
|
|
|
}
|
|
|
|
|
2022-01-19 13:06:13 +01:00
|
|
|
/**
|
|
|
|
* Wraps a single value.
|
|
|
|
*
|
|
|
|
* @remarks
|
|
|
|
* Derivations created with {@link Box.derivation} update based on strict equality (`===`) of the old value and the new one.
|
|
|
|
* This also means that property-changes of objects won't be tracked, and that for objects, updates will trigger on changes of
|
|
|
|
* reference even if the objects are structurally equal.
|
|
|
|
*/
|
2021-06-18 13:05:06 +02:00
|
|
|
export default class Box<V> implements IBox<V> {
|
|
|
|
private _publicDerivation: IDerivation<V>
|
|
|
|
private _emitter = new Emitter<V>()
|
|
|
|
|
2022-01-19 13:06:13 +01:00
|
|
|
/**
|
|
|
|
* @param _value The initial value of the Box.
|
|
|
|
*/
|
|
|
|
constructor(
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
protected _value: V,
|
|
|
|
) {
|
2021-06-18 13:05:06 +02:00
|
|
|
this._publicDerivation = new DerivationFromSource(
|
|
|
|
(listener) => this._emitter.tappable.tap(listener),
|
|
|
|
this.get.bind(this),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-01-19 13:06:13 +01:00
|
|
|
/**
|
|
|
|
* Sets the value of the Box.
|
|
|
|
*
|
|
|
|
* @param v The value to update the Box with.
|
|
|
|
*/
|
2021-06-18 13:05:06 +02:00
|
|
|
set(v: V) {
|
|
|
|
if (v === this._value) return
|
|
|
|
this._value = v
|
|
|
|
this._emitter.emit(v)
|
|
|
|
}
|
|
|
|
|
2022-01-19 13:06:13 +01:00
|
|
|
/**
|
|
|
|
* Gets the value of the Box.
|
|
|
|
*
|
|
|
|
* Note: usages of `get()` aren't tracked, they are only for retrieving the value. To track changes, you need to
|
|
|
|
* create a derivation.
|
|
|
|
*
|
|
|
|
* @see derivation
|
|
|
|
*/
|
2021-06-18 13:05:06 +02:00
|
|
|
get() {
|
|
|
|
return this._value
|
|
|
|
}
|
|
|
|
|
2022-01-19 13:06:13 +01:00
|
|
|
/**
|
|
|
|
* Creates a derivation of the Box that you can use to track changes to it.
|
|
|
|
*/
|
2021-06-18 13:05:06 +02:00
|
|
|
get derivation() {
|
|
|
|
return this._publicDerivation
|
|
|
|
}
|
|
|
|
}
|