import { Observable as ObservableT } from './index' import Observable from './observable' /** * Creates an observable that only emits values as long as {@link toggler}'s last output is `true` * * {@link toggle} takes a source `Observable` and a toggler `Observable`. The output `Observable` * will only ever emit `T`s while `Observable`'s last emitted value was `true`. If `Observable` last * emitted `false` then any `T`s up until the next (`Observable`) `true` will be discarded. In other words, toggler * `Observable` controls whether or not output `Observable` emits values or not. If source * `Observable` {@link complete()}s then toggler `Observable` will be {@link unsubscribe()}d, however * {@link complete()} from toggler `Observable` is ignored. Calling {@link unsubscribe()} on output * `Observable` will call {@link unsubscribe()} on both source and toggler. * * @example Marble diagram * * // source s: |--1--2--3--4--5--6--7--8--| * // source t: |-----T-----F-----T--F-----| * // toggle(s, t): |-----2--3--4-----6--7-----| * * @param {ObservableT} source observable that acts as source emits * @param {ObservableT} toggler observable that controls the emits of the returned observable * @returns {ObservableT} the observable that only emits when toggler's last emit is `true` */ export default function toggle( source: ObservableT, toggler: ObservableT ): ObservableT { return new Observable( ({ complete, error, next }): (() => void) => { let doNext = false const togglerSubscription = toggler.subscribe({ next: (bool): boolean => (doNext = bool) }) const sourceSubscription = source.subscribe({ complete, error, next: (value): false | void => doNext && next(value) }) return (): void => { togglerSubscription.unsubscribe() sourceSubscription.unsubscribe() } } ) }