diff --git a/packages/dataverse/src/derivations/IDerivation.ts b/packages/dataverse/src/derivations/IDerivation.ts index fc03d3f..a89d75f 100644 --- a/packages/dataverse/src/derivations/IDerivation.ts +++ b/packages/dataverse/src/derivations/IDerivation.ts @@ -18,9 +18,13 @@ export interface IDerivation { isHot: boolean /** - * Returns a `Tappable` of the changes of this derivation. + * Calls `listener` with a fresh value every time the prism _has_ a new value, throttled by Ticker. */ - onChange(ticker: Ticker, listener: (v: V) => void): VoidFn + onChange( + ticker: Ticker, + listener: (v: V) => void, + immediate?: boolean, + ): VoidFn onStale(cb: () => void): VoidFn @@ -29,17 +33,6 @@ export interface IDerivation { */ keepHot(): VoidFn - /** - * Convenience method that taps (subscribes to) the derivation using `this.changes(ticker).tap(fn)` and immediately calls - * the callback with the current value. - * - * @param ticker - The ticker to use for batching. - * @param fn - The callback to call on update. - * - * @see onChange - */ - tapImmediate(ticker: Ticker, fn: (cb: V) => void): VoidFn - /** * Add a derivation as a dependent of this derivation. * diff --git a/packages/dataverse/src/derivations/prism/prism.ts b/packages/dataverse/src/derivations/prism/prism.ts index 5e7d80e..39a0323 100644 --- a/packages/dataverse/src/derivations/prism/prism.ts +++ b/packages/dataverse/src/derivations/prism/prism.ts @@ -222,8 +222,18 @@ class PrismDerivation implements IDerivation { return this._state.hot } - onChange(ticker: Ticker, listener: (v: V) => void): VoidFn { - return new DerivationEmitter(this, ticker).tappable().tap(listener) + onChange( + ticker: Ticker, + listener: (v: V) => void, + immediate: boolean = false, + ): VoidFn { + const unsubscribe = new DerivationEmitter(this, ticker) + .tappable() + .tap(listener) + if (immediate) { + listener(this.getValue()) + } + return unsubscribe } /** @@ -245,21 +255,6 @@ class PrismDerivation implements IDerivation { return this.onStale(() => {}) } - /** - * Convenience method that taps (subscribes to) the derivation using `this.changes(ticker).tap(fn)` and immediately calls - * the callback with the current value. - * - * @param ticker - The ticker to use for batching. - * @param fn - The callback to call on update. - * - * @see onChange - */ - tapImmediate(ticker: Ticker, fn: (cb: V) => void): VoidFn { - const untap = this.onChange(ticker, fn) - fn(this.getValue()) - return untap - } - /** * Add a derivation as a dependent of this derivation. * diff --git a/packages/dataverse/src/utils/Tappable.ts b/packages/dataverse/src/utils/Tappable.ts index 05db260..560b9db 100644 --- a/packages/dataverse/src/utils/Tappable.ts +++ b/packages/dataverse/src/utils/Tappable.ts @@ -72,13 +72,6 @@ export default class Tappable { } } - /* - * tapImmediate(cb: Listener): Untap { - * const ret = this.tap(cb) - * return ret - * } - */ - private _removeTapperById(id: number) { this._tappers.delete(id) this._check() diff --git a/packages/playground/src/shared/hello-world-extension-dataverse/index.tsx b/packages/playground/src/shared/hello-world-extension-dataverse/index.tsx index 2ee1c43..9d8d513 100644 --- a/packages/playground/src/shared/hello-world-extension-dataverse/index.tsx +++ b/packages/playground/src/shared/hello-world-extension-dataverse/index.tsx @@ -13,9 +13,9 @@ import {Box, prism, Ticker, val} from '@theatre/dataverse' * * Without going into the details of `prism`, `Ticker`, and `val`, note that by wrapping our `ToolsetConfig` in a prism, our * ```ts - * ... .tapImmediate(Ticker.raf, (toolset) => { + * ... .onChange(Ticker.raf, (toolset) => { * set(toolset) - * }) + * }, true) * ``` * code will be called whenever `val(obj.props.exampleProp)` changes (whenever the user clicks the switch and the `onChange` callback is called). * This will ensure that our switch's value matches its state and is reflected in the UI via `set(toolset)`. @@ -56,9 +56,13 @@ studio.extend({ }, ]) // listen to changes to this derivation using the requestAnimationFrame shared ticker - .tapImmediate(Ticker.raf, (value) => { - set(value) - }) + .onChange( + Ticker.raf, + (value) => { + set(value) + }, + true, + ) return untapFn }, diff --git a/packages/r3f/src/extension/index.ts b/packages/r3f/src/extension/index.ts index 1f26dc1..ce33bae 100644 --- a/packages/r3f/src/extension/index.ts +++ b/packages/r3f/src/extension/index.ts @@ -35,9 +35,13 @@ const r3fExtension: IExtension = { }, ] }) - return calc.tapImmediate(Ticker.raf, () => { - set(calc.getValue()) - }) + return calc.onChange( + Ticker.raf, + () => { + set(calc.getValue()) + }, + true, + ) }, 'snapshot-editor': (set, studio) => { const {createSnapshot} = useExtensionStore.getState() @@ -136,9 +140,13 @@ const r3fExtension: IExtension = { }, ] }) - return calc.tapImmediate(Ticker.raf, () => { - set(calc.getValue()) - }) + return calc.onChange( + Ticker.raf, + () => { + set(calc.getValue()) + }, + true, + ) }, }, panes: [ diff --git a/theatre/core/src/coreExports.ts b/theatre/core/src/coreExports.ts index 2e067f6..8210e36 100644 --- a/theatre/core/src/coreExports.ts +++ b/theatre/core/src/coreExports.ts @@ -156,9 +156,13 @@ export function onChange

>( ): VoidFn { if (isPointer(pointer)) { const derivation = valueDerivation(pointer) - return derivation.tapImmediate(getCoreTicker(), callback as $IntentionalAny) + return derivation.onChange( + getCoreTicker(), + callback as $IntentionalAny, + true, + ) } else if (isDerivation(pointer)) { - return pointer.tapImmediate(getCoreTicker(), callback as $IntentionalAny) + return pointer.onChange(getCoreTicker(), callback as $IntentionalAny, true) } else { throw new Error( `Called onChange(p) where p is neither a pointer nor a derivation.`, diff --git a/theatre/core/src/sheetObjects/TheatreSheetObject.ts b/theatre/core/src/sheetObjects/TheatreSheetObject.ts index a227c38..39ff343 100644 --- a/theatre/core/src/sheetObjects/TheatreSheetObject.ts +++ b/theatre/core/src/sheetObjects/TheatreSheetObject.ts @@ -158,7 +158,7 @@ export default class TheatreSheetObject< } onValuesChange(fn: (values: this['value']) => void): VoidFn { - return this._valuesDerivation().tapImmediate(getCoreTicker(), fn) + return this._valuesDerivation().onChange(getCoreTicker(), fn, true) } // internal: Make the deviration keepHot if directly read diff --git a/theatre/studio/src/TheatreStudio.ts b/theatre/studio/src/TheatreStudio.ts index 6c412b5..63ce576 100644 --- a/theatre/studio/src/TheatreStudio.ts +++ b/theatre/studio/src/TheatreStudio.ts @@ -440,7 +440,7 @@ export default class TheatreStudio implements IStudio { } onSelectionChange(fn: (s: (ISheetObject | ISheet)[]) => void): VoidFn { - return this._getSelectionDerivation().tapImmediate(studioTicker, fn) + return this._getSelectionDerivation().onChange(studioTicker, fn, true) } get selection(): Array { diff --git a/theatre/studio/src/panels/SequenceEditorPanel/FrameGrid/FrameGrid.tsx b/theatre/studio/src/panels/SequenceEditorPanel/FrameGrid/FrameGrid.tsx index 2579c1e..6ae424f 100644 --- a/theatre/studio/src/panels/SequenceEditorPanel/FrameGrid/FrameGrid.tsx +++ b/theatre/studio/src/panels/SequenceEditorPanel/FrameGrid/FrameGrid.tsx @@ -75,12 +75,16 @@ const FrameGrid: React.FC<{ fps: sequence.subUnitsPerUnit, snapToGrid: (n: number) => sequence.closestGridPosition(n), } - }).tapImmediate(studioTicker, (p) => { - ctx.save() - ctx.scale(ratio!, ratio!) - drawGrid(p) - ctx.restore() - }) + }).onChange( + studioTicker, + (p) => { + ctx.save() + ctx.scale(ratio!, ratio!) + drawGrid(p) + ctx.restore() + }, + true, + ) return () => { untap() diff --git a/theatre/studio/src/panels/SequenceEditorPanel/FrameGrid/StampsGrid.tsx b/theatre/studio/src/panels/SequenceEditorPanel/FrameGrid/StampsGrid.tsx index 1458a6c..0446484 100644 --- a/theatre/studio/src/panels/SequenceEditorPanel/FrameGrid/StampsGrid.tsx +++ b/theatre/studio/src/panels/SequenceEditorPanel/FrameGrid/StampsGrid.tsx @@ -86,7 +86,7 @@ const StampsGrid: React.FC<{ sequencePositionFormatter: sequence.positionFormatter, snapToGrid: (n: number) => sequence.closestGridPosition(n), } - }).tapImmediate(studioTicker, drawStamps) + }).onChange(studioTicker, drawStamps, true) }, [fullSecondStampsContainer, width, layoutP]) return (