theatre/packages/dataverse/src/Box.ts

90 lines
2.1 KiB
TypeScript
Raw Normal View History

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.
*
2022-02-15 22:59:34 +01:00
* @see Box.derivation
2022-01-19 13:06:13 +01:00
*/
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
}
}