UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

128 lines (127 loc) 3.61 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OnNewFanOut = exports.MapFanOut = exports.MicrotaskBufferFanOut = exports.MergeFanOut = void 0; const fanout_1 = require("thingies/lib/fanout"); /** * Merges multiple fanouts into a single fanout. The merged fanout emits the * same data as the source fanouts. */ class MergeFanOut extends fanout_1.FanOut { constructor(fanouts) { super(); this.fanouts = fanouts; this.unsubs = []; } listen(listener) { if (!this.listeners.size) this.unsubs = this.fanouts.map((fanout) => fanout.listen((data) => this.emit(data))); const unsub = super.listen(listener); return () => { unsub(); if (!this.listeners.size) { for (const unsub of this.unsubs) unsub(); this.unsubs = []; } }; } } exports.MergeFanOut = MergeFanOut; /** * Buffers data from a fanout and emits the buffered data once per microtask. */ class MicrotaskBufferFanOut extends fanout_1.FanOut { constructor(source) { super(); this.source = source; this.buffer = []; this.unsub = undefined; } listen(listener) { if (!this.unsub) { this.unsub = this.source.listen((data) => { const buffer = this.buffer; if (!buffer.length) { queueMicrotask(() => { this.emit(buffer); this.buffer = []; }); } buffer.push(data); }); } const unsub = super.listen(listener); return () => { unsub(); if (!this.listeners.size) this.clear(); }; } clear() { this.listeners.clear(); this.buffer = []; this.unsub?.(); this.unsub = undefined; } } exports.MicrotaskBufferFanOut = MicrotaskBufferFanOut; /** * Maps the data from a fanout using a mapper function. */ class MapFanOut extends fanout_1.FanOut { constructor(source, mapper) { super(); this.source = source; this.mapper = mapper; this.unsub = undefined; } listen(listener) { if (!this.unsub) this.unsub = this.source.listen((data) => this.emit(this.mapper(data))); const unsub = super.listen(listener); return () => { unsub(); if (!this.listeners.size) this.clear(); }; } clear() { this.listeners.clear(); this.unsub?.(); this.unsub = undefined; } } exports.MapFanOut = MapFanOut; /** * Emits only when the source fanout emits a new value. The first value is * emitted immediately. */ class OnNewFanOut extends fanout_1.FanOut { constructor(source, last = undefined) { super(); this.source = source; this.last = last; this.unsub = undefined; } listen(listener) { if (!this.unsub) { this.unsub = this.source.listen((data) => { if (this.last !== data) this.emit((this.last = data)); }); } const unsub = super.listen(listener); return () => { unsub(); if (!this.listeners.size) this.clear(); }; } clear() { this.listeners.clear(); this.last = undefined; this.unsub?.(); this.unsub = undefined; } } exports.OnNewFanOut = OnNewFanOut;