wavesurfer.js 7.11.1 → 7.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/__tests__/memory-leaks.test.d.ts +7 -0
- package/dist/__tests__/memory-leaks.test.js +281 -0
- package/dist/__tests__/player.test.js +107 -0
- package/dist/__tests__/renderer-utils.test.js +55 -2
- package/dist/draggable.d.ts +4 -0
- package/dist/draggable.js +4 -0
- package/dist/player.d.ts +21 -0
- package/dist/player.js +86 -0
- package/dist/plugins/envelope.cjs +1 -1
- package/dist/plugins/envelope.esm.js +1 -1
- package/dist/plugins/envelope.js +1 -1
- package/dist/plugins/envelope.min.js +1 -1
- package/dist/plugins/hover.cjs +1 -1
- package/dist/plugins/hover.d.ts +0 -3
- package/dist/plugins/hover.esm.js +1 -1
- package/dist/plugins/hover.js +1 -1
- package/dist/plugins/hover.min.js +1 -1
- package/dist/plugins/minimap.cjs +1 -1
- package/dist/plugins/minimap.esm.js +1 -1
- package/dist/plugins/minimap.js +1 -1
- package/dist/plugins/minimap.min.js +1 -1
- package/dist/plugins/record.cjs +1 -1
- package/dist/plugins/record.esm.js +1 -1
- package/dist/plugins/record.js +1 -1
- package/dist/plugins/record.min.js +1 -1
- package/dist/plugins/regions.cjs +1 -1
- package/dist/plugins/regions.esm.js +1 -1
- package/dist/plugins/regions.js +1 -1
- package/dist/plugins/regions.min.js +1 -1
- package/dist/plugins/timeline.cjs +1 -1
- package/dist/plugins/timeline.d.ts +1 -1
- package/dist/plugins/timeline.esm.js +1 -1
- package/dist/plugins/timeline.js +1 -1
- package/dist/plugins/timeline.min.js +1 -1
- package/dist/plugins/zoom.cjs +1 -1
- package/dist/plugins/zoom.esm.js +1 -1
- package/dist/plugins/zoom.js +1 -1
- package/dist/plugins/zoom.min.js +1 -1
- package/dist/reactive/__tests__/drag-stream.test.d.ts +1 -0
- package/dist/reactive/__tests__/drag-stream.test.js +199 -0
- package/dist/reactive/__tests__/event-stream-emitter.test.d.ts +1 -0
- package/dist/reactive/__tests__/event-stream-emitter.test.js +230 -0
- package/dist/reactive/__tests__/event-streams.test.d.ts +1 -0
- package/dist/reactive/__tests__/event-streams.test.js +278 -0
- package/dist/reactive/__tests__/media-event-bridge.test.d.ts +1 -0
- package/dist/reactive/__tests__/media-event-bridge.test.js +202 -0
- package/dist/reactive/__tests__/render-scheduler.test.d.ts +1 -0
- package/dist/reactive/__tests__/render-scheduler.test.js +216 -0
- package/dist/reactive/__tests__/scroll-stream.test.d.ts +1 -0
- package/dist/reactive/__tests__/scroll-stream.test.js +191 -0
- package/dist/reactive/__tests__/state-event-emitter.test.d.ts +1 -0
- package/dist/reactive/__tests__/state-event-emitter.test.js +234 -0
- package/dist/reactive/__tests__/store.test.d.ts +1 -0
- package/dist/reactive/__tests__/store.test.js +271 -0
- package/dist/reactive/drag-stream.d.ts +48 -0
- package/dist/reactive/drag-stream.js +146 -0
- package/dist/reactive/event-stream-emitter.d.ts +104 -0
- package/dist/reactive/event-stream-emitter.js +151 -0
- package/dist/reactive/event-streams.d.ts +65 -0
- package/dist/reactive/event-streams.js +146 -0
- package/dist/reactive/media-event-bridge.d.ts +51 -0
- package/dist/reactive/media-event-bridge.js +152 -0
- package/dist/reactive/render-scheduler.d.ts +43 -0
- package/dist/reactive/render-scheduler.js +75 -0
- package/dist/reactive/scroll-stream.d.ts +93 -0
- package/dist/reactive/scroll-stream.js +131 -0
- package/dist/reactive/state-event-emitter.d.ts +105 -0
- package/dist/reactive/state-event-emitter.js +213 -0
- package/dist/reactive/store.d.ts +66 -0
- package/dist/reactive/store.js +115 -0
- package/dist/renderer-utils.d.ts +13 -4
- package/dist/renderer-utils.js +35 -15
- package/dist/renderer.d.ts +2 -1
- package/dist/renderer.js +51 -48
- package/dist/state/__tests__/wavesurfer-state.test.d.ts +1 -0
- package/dist/state/__tests__/wavesurfer-state.test.js +268 -0
- package/dist/state/wavesurfer-state.d.ts +90 -0
- package/dist/state/wavesurfer-state.js +124 -0
- package/dist/types.d.ts +165 -1
- package/dist/wavesurfer.cjs +1 -1
- package/dist/wavesurfer.d.ts +16 -0
- package/dist/wavesurfer.esm.js +1 -1
- package/dist/wavesurfer.js +32 -0
- package/dist/wavesurfer.min.js +1 -1
- package/package.json +2 -3
package/dist/plugins/zoom.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class t{constructor(){this.listeners={}}on(t,i,
|
|
1
|
+
class t{constructor(){this.listeners={}}on(t,i,s){if(this.listeners[t]||(this.listeners[t]=new Set),null==s?void 0:s.once){const s=(...e)=>{this.un(t,s),i(...e)};return this.listeners[t].add(s),()=>this.un(t,s)}return this.listeners[t].add(i),()=>this.un(t,i)}un(t,i){var s;null===(s=this.listeners[t])||void 0===s||s.delete(i)}once(t,i){return this.on(t,i,{once:!0})}unAll(){this.listeners={}}emit(t,...i){this.listeners[t]&&this.listeners[t].forEach((t=>t(...i)))}}class i extends t{constructor(t){super(),this.subscriptions=[],this.isDestroyed=!1,this.options=t}onInit(){}_init(t){this.isDestroyed&&(this.subscriptions=[],this.isDestroyed=!1),this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t())),this.subscriptions=[],this.isDestroyed=!0,this.wavesurfer=void 0}}function s(t,i){let s;const e=()=>{s&&(s(),s=void 0),s=t()},o=i.map((t=>t.subscribe(e)));return e(),()=>{s&&(s(),s=void 0),o.forEach((t=>t()))}}function e(t,i){const s=function(t){let i=t;const s=new Set;return{get value(){return i},set(t){Object.is(i,t)||(i=t,s.forEach((t=>t(i))))},update(t){this.set(t(i))},subscribe:t=>(s.add(t),()=>s.delete(t))}}(null),e=t=>{s.set(t)};return t.addEventListener(i,e),s._cleanup=()=>{t.removeEventListener(i,e)},s}const o={scale:.5,deltaThreshold:5,exponentialZooming:!1,iterations:20};class n extends i{constructor(t){super(t||{}),this.wrapper=void 0,this.container=null,this.accumulatedDelta=0,this.pointerTime=0,this.oldX=0,this.endZoom=0,this.startZoom=0,this.isPinching=!1,this.initialPinchDistance=0,this.initialZoom=0,this.onWheel=t=>{if(this.wavesurfer&&this.container&&!(Math.abs(t.deltaX)>=Math.abs(t.deltaY))&&(t.preventDefault(),this.accumulatedDelta+=-t.deltaY,0===this.startZoom&&this.options.exponentialZooming&&(this.startZoom=this.wavesurfer.getWrapper().clientWidth/this.wavesurfer.getDuration()),0===this.options.deltaThreshold||Math.abs(this.accumulatedDelta)>=this.options.deltaThreshold)){const i=this.wavesurfer.getDuration(),s=0===this.wavesurfer.options.minPxPerSec?this.wavesurfer.getWrapper().scrollWidth/i:this.wavesurfer.options.minPxPerSec,e=t.clientX-this.container.getBoundingClientRect().left,o=this.container.clientWidth,n=this.wavesurfer.getScroll();e===this.oldX&&0!==this.oldX||(this.pointerTime=(n+e)/s),this.oldX=e;const h=this.calculateNewZoom(s,this.accumulatedDelta),r=o/h*(e/o);h*i<o?(this.wavesurfer.zoom(o/i),this.container.scrollLeft=0):(this.wavesurfer.zoom(h),this.container.scrollLeft=(this.pointerTime-r)*h),this.accumulatedDelta=0}},this.calculateNewZoom=(t,i)=>{let s;if(this.options.exponentialZooming){const e=i>0?Math.pow(this.endZoom/this.startZoom,1/(this.options.iterations-1)):Math.pow(this.startZoom/this.endZoom,1/(this.options.iterations-1));s=Math.max(0,t*e)}else s=Math.max(0,t+i*this.options.scale);return Math.min(s,this.options.maxZoom)},this.onTouchStart=t=>{if(this.wavesurfer&&this.container&&2===t.touches.length){t.preventDefault(),this.isPinching=!0,this.initialPinchDistance=this.getTouchDistance(t);const i=this.wavesurfer.getDuration();this.initialZoom=0===this.wavesurfer.options.minPxPerSec?this.wavesurfer.getWrapper().scrollWidth/i:this.wavesurfer.options.minPxPerSec;const s=this.getTouchCenterX(t)-this.container.getBoundingClientRect().left,e=this.wavesurfer.getScroll();this.pointerTime=(e+s)/this.initialZoom,this.oldX=s}},this.onTouchMove=t=>{if(!this.isPinching||2!==t.touches.length||!this.wavesurfer||!this.container)return;t.preventDefault();const i=this.getTouchDistance(t)/this.initialPinchDistance;let s=this.initialZoom*i;s=Math.min(s,this.options.maxZoom);const e=this.wavesurfer.getDuration(),o=this.container.clientWidth,n=o/e;s<n&&(s=n);const h=o/s*(this.oldX/o);s===n?(this.wavesurfer.zoom(n),this.container.scrollLeft=0):(this.wavesurfer.zoom(s),this.container.scrollLeft=(this.pointerTime-h)*s)},this.onTouchEnd=t=>{this.isPinching&&t.touches.length<2&&(this.isPinching=!1,this.initialPinchDistance=0,this.initialZoom=0)},this.options=Object.assign({},o,t)}static create(t){return new n(t)}onInit(){var t,i;if(this.wrapper=null===(t=this.wavesurfer)||void 0===t?void 0:t.getWrapper(),!this.wrapper)return;this.container=this.wrapper.parentElement,void 0===this.options.maxZoom&&(this.options.maxZoom=this.container.clientWidth),this.endZoom=this.options.maxZoom;const o=null===(i=this.wavesurfer)||void 0===i?void 0:i.getState();o&&this.subscriptions.push(s((()=>{if(o.zoom.value>0&&0===this.startZoom&&this.options.exponentialZooming){const t=o.duration.value;t>0&&this.container&&(this.startZoom=this.container.clientWidth/t)}}),[o.zoom,o.duration]));const n=e(this.container,"wheel"),h=e(this.container,"touchstart"),r=e(this.container,"touchmove"),a=e(this.container,"touchend"),c=e(this.container,"touchcancel");this.subscriptions.push(s((()=>{const t=n.value;t&&this.onWheel(t)}),[n])),this.subscriptions.push(s((()=>{const t=h.value;t&&this.onTouchStart(t)}),[h])),this.subscriptions.push(s((()=>{const t=r.value;t&&this.onTouchMove(t)}),[r])),this.subscriptions.push(s((()=>{const t=a.value;t&&this.onTouchEnd(t)}),[a])),this.subscriptions.push(s((()=>{const t=c.value;t&&this.onTouchEnd(t)}),[c]))}getTouchDistance(t){const i=t.touches[0],s=t.touches[1];return Math.sqrt(Math.pow(s.clientX-i.clientX,2)+Math.pow(s.clientY-i.clientY,2))}getTouchCenterX(t){const i=t.touches[0],s=t.touches[1];return(i.clientX+s.clientX)/2}destroy(){super.destroy()}}export{n as default};
|
package/dist/plugins/zoom.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class t{constructor(){this.listeners={}}on(t,i,
|
|
1
|
+
class t{constructor(){this.listeners={}}on(t,i,s){if(this.listeners[t]||(this.listeners[t]=new Set),null==s?void 0:s.once){const s=(...e)=>{this.un(t,s),i(...e)};return this.listeners[t].add(s),()=>this.un(t,s)}return this.listeners[t].add(i),()=>this.un(t,i)}un(t,i){var s;null===(s=this.listeners[t])||void 0===s||s.delete(i)}once(t,i){return this.on(t,i,{once:!0})}unAll(){this.listeners={}}emit(t,...i){this.listeners[t]&&this.listeners[t].forEach((t=>t(...i)))}}class i extends t{constructor(t){super(),this.subscriptions=[],this.isDestroyed=!1,this.options=t}onInit(){}_init(t){this.isDestroyed&&(this.subscriptions=[],this.isDestroyed=!1),this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t())),this.subscriptions=[],this.isDestroyed=!0,this.wavesurfer=void 0}}function s(t,i){let s;const e=()=>{s&&(s(),s=void 0),s=t()},o=i.map((t=>t.subscribe(e)));return e(),()=>{s&&(s(),s=void 0),o.forEach((t=>t()))}}function e(t,i){const s=function(t){let i=t;const s=new Set;return{get value(){return i},set(t){Object.is(i,t)||(i=t,s.forEach((t=>t(i))))},update(t){this.set(t(i))},subscribe:t=>(s.add(t),()=>s.delete(t))}}(null),e=t=>{s.set(t)};return t.addEventListener(i,e),s._cleanup=()=>{t.removeEventListener(i,e)},s}const o={scale:.5,deltaThreshold:5,exponentialZooming:!1,iterations:20};class n extends i{constructor(t){super(t||{}),this.wrapper=void 0,this.container=null,this.accumulatedDelta=0,this.pointerTime=0,this.oldX=0,this.endZoom=0,this.startZoom=0,this.isPinching=!1,this.initialPinchDistance=0,this.initialZoom=0,this.onWheel=t=>{if(this.wavesurfer&&this.container&&!(Math.abs(t.deltaX)>=Math.abs(t.deltaY))&&(t.preventDefault(),this.accumulatedDelta+=-t.deltaY,0===this.startZoom&&this.options.exponentialZooming&&(this.startZoom=this.wavesurfer.getWrapper().clientWidth/this.wavesurfer.getDuration()),0===this.options.deltaThreshold||Math.abs(this.accumulatedDelta)>=this.options.deltaThreshold)){const i=this.wavesurfer.getDuration(),s=0===this.wavesurfer.options.minPxPerSec?this.wavesurfer.getWrapper().scrollWidth/i:this.wavesurfer.options.minPxPerSec,e=t.clientX-this.container.getBoundingClientRect().left,o=this.container.clientWidth,n=this.wavesurfer.getScroll();e===this.oldX&&0!==this.oldX||(this.pointerTime=(n+e)/s),this.oldX=e;const h=this.calculateNewZoom(s,this.accumulatedDelta),r=o/h*(e/o);h*i<o?(this.wavesurfer.zoom(o/i),this.container.scrollLeft=0):(this.wavesurfer.zoom(h),this.container.scrollLeft=(this.pointerTime-r)*h),this.accumulatedDelta=0}},this.calculateNewZoom=(t,i)=>{let s;if(this.options.exponentialZooming){const e=i>0?Math.pow(this.endZoom/this.startZoom,1/(this.options.iterations-1)):Math.pow(this.startZoom/this.endZoom,1/(this.options.iterations-1));s=Math.max(0,t*e)}else s=Math.max(0,t+i*this.options.scale);return Math.min(s,this.options.maxZoom)},this.onTouchStart=t=>{if(this.wavesurfer&&this.container&&2===t.touches.length){t.preventDefault(),this.isPinching=!0,this.initialPinchDistance=this.getTouchDistance(t);const i=this.wavesurfer.getDuration();this.initialZoom=0===this.wavesurfer.options.minPxPerSec?this.wavesurfer.getWrapper().scrollWidth/i:this.wavesurfer.options.minPxPerSec;const s=this.getTouchCenterX(t)-this.container.getBoundingClientRect().left,e=this.wavesurfer.getScroll();this.pointerTime=(e+s)/this.initialZoom,this.oldX=s}},this.onTouchMove=t=>{if(!this.isPinching||2!==t.touches.length||!this.wavesurfer||!this.container)return;t.preventDefault();const i=this.getTouchDistance(t)/this.initialPinchDistance;let s=this.initialZoom*i;s=Math.min(s,this.options.maxZoom);const e=this.wavesurfer.getDuration(),o=this.container.clientWidth,n=o/e;s<n&&(s=n);const h=o/s*(this.oldX/o);s===n?(this.wavesurfer.zoom(n),this.container.scrollLeft=0):(this.wavesurfer.zoom(s),this.container.scrollLeft=(this.pointerTime-h)*s)},this.onTouchEnd=t=>{this.isPinching&&t.touches.length<2&&(this.isPinching=!1,this.initialPinchDistance=0,this.initialZoom=0)},this.options=Object.assign({},o,t)}static create(t){return new n(t)}onInit(){var t,i;if(this.wrapper=null===(t=this.wavesurfer)||void 0===t?void 0:t.getWrapper(),!this.wrapper)return;this.container=this.wrapper.parentElement,void 0===this.options.maxZoom&&(this.options.maxZoom=this.container.clientWidth),this.endZoom=this.options.maxZoom;const o=null===(i=this.wavesurfer)||void 0===i?void 0:i.getState();o&&this.subscriptions.push(s((()=>{if(o.zoom.value>0&&0===this.startZoom&&this.options.exponentialZooming){const t=o.duration.value;t>0&&this.container&&(this.startZoom=this.container.clientWidth/t)}}),[o.zoom,o.duration]));const n=e(this.container,"wheel"),h=e(this.container,"touchstart"),r=e(this.container,"touchmove"),a=e(this.container,"touchend"),c=e(this.container,"touchcancel");this.subscriptions.push(s((()=>{const t=n.value;t&&this.onWheel(t)}),[n])),this.subscriptions.push(s((()=>{const t=h.value;t&&this.onTouchStart(t)}),[h])),this.subscriptions.push(s((()=>{const t=r.value;t&&this.onTouchMove(t)}),[r])),this.subscriptions.push(s((()=>{const t=a.value;t&&this.onTouchEnd(t)}),[a])),this.subscriptions.push(s((()=>{const t=c.value;t&&this.onTouchEnd(t)}),[c]))}getTouchDistance(t){const i=t.touches[0],s=t.touches[1];return Math.sqrt(Math.pow(s.clientX-i.clientX,2)+Math.pow(s.clientY-i.clientY,2))}getTouchCenterX(t){const i=t.touches[0],s=t.touches[1];return(i.clientX+s.clientX)/2}destroy(){super.destroy()}}export{n as default};
|
package/dist/plugins/zoom.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,
|
|
1
|
+
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?module.exports=i():"function"==typeof define&&define.amd?define(i):((t="undefined"!=typeof globalThis?globalThis:t||self).WaveSurfer=t.WaveSurfer||{},t.WaveSurfer.Zoom=i())}(this,(function(){"use strict";class t{constructor(){this.listeners={}}on(t,i,s){if(this.listeners[t]||(this.listeners[t]=new Set),null==s?void 0:s.once){const s=(...e)=>{this.un(t,s),i(...e)};return this.listeners[t].add(s),()=>this.un(t,s)}return this.listeners[t].add(i),()=>this.un(t,i)}un(t,i){var s;null===(s=this.listeners[t])||void 0===s||s.delete(i)}once(t,i){return this.on(t,i,{once:!0})}unAll(){this.listeners={}}emit(t,...i){this.listeners[t]&&this.listeners[t].forEach((t=>t(...i)))}}class i extends t{constructor(t){super(),this.subscriptions=[],this.isDestroyed=!1,this.options=t}onInit(){}_init(t){this.isDestroyed&&(this.subscriptions=[],this.isDestroyed=!1),this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t())),this.subscriptions=[],this.isDestroyed=!0,this.wavesurfer=void 0}}function s(t,i){let s;const e=()=>{s&&(s(),s=void 0),s=t()},o=i.map((t=>t.subscribe(e)));return e(),()=>{s&&(s(),s=void 0),o.forEach((t=>t()))}}function e(t,i){const s=function(t){let i=t;const s=new Set;return{get value(){return i},set(t){Object.is(i,t)||(i=t,s.forEach((t=>t(i))))},update(t){this.set(t(i))},subscribe:t=>(s.add(t),()=>s.delete(t))}}(null),e=t=>{s.set(t)};return t.addEventListener(i,e),s._cleanup=()=>{t.removeEventListener(i,e)},s}const o={scale:.5,deltaThreshold:5,exponentialZooming:!1,iterations:20};class n extends i{constructor(t){super(t||{}),this.wrapper=void 0,this.container=null,this.accumulatedDelta=0,this.pointerTime=0,this.oldX=0,this.endZoom=0,this.startZoom=0,this.isPinching=!1,this.initialPinchDistance=0,this.initialZoom=0,this.onWheel=t=>{if(this.wavesurfer&&this.container&&!(Math.abs(t.deltaX)>=Math.abs(t.deltaY))&&(t.preventDefault(),this.accumulatedDelta+=-t.deltaY,0===this.startZoom&&this.options.exponentialZooming&&(this.startZoom=this.wavesurfer.getWrapper().clientWidth/this.wavesurfer.getDuration()),0===this.options.deltaThreshold||Math.abs(this.accumulatedDelta)>=this.options.deltaThreshold)){const i=this.wavesurfer.getDuration(),s=0===this.wavesurfer.options.minPxPerSec?this.wavesurfer.getWrapper().scrollWidth/i:this.wavesurfer.options.minPxPerSec,e=t.clientX-this.container.getBoundingClientRect().left,o=this.container.clientWidth,n=this.wavesurfer.getScroll();e===this.oldX&&0!==this.oldX||(this.pointerTime=(n+e)/s),this.oldX=e;const h=this.calculateNewZoom(s,this.accumulatedDelta),r=o/h*(e/o);h*i<o?(this.wavesurfer.zoom(o/i),this.container.scrollLeft=0):(this.wavesurfer.zoom(h),this.container.scrollLeft=(this.pointerTime-r)*h),this.accumulatedDelta=0}},this.calculateNewZoom=(t,i)=>{let s;if(this.options.exponentialZooming){const e=i>0?Math.pow(this.endZoom/this.startZoom,1/(this.options.iterations-1)):Math.pow(this.startZoom/this.endZoom,1/(this.options.iterations-1));s=Math.max(0,t*e)}else s=Math.max(0,t+i*this.options.scale);return Math.min(s,this.options.maxZoom)},this.onTouchStart=t=>{if(this.wavesurfer&&this.container&&2===t.touches.length){t.preventDefault(),this.isPinching=!0,this.initialPinchDistance=this.getTouchDistance(t);const i=this.wavesurfer.getDuration();this.initialZoom=0===this.wavesurfer.options.minPxPerSec?this.wavesurfer.getWrapper().scrollWidth/i:this.wavesurfer.options.minPxPerSec;const s=this.getTouchCenterX(t)-this.container.getBoundingClientRect().left,e=this.wavesurfer.getScroll();this.pointerTime=(e+s)/this.initialZoom,this.oldX=s}},this.onTouchMove=t=>{if(!this.isPinching||2!==t.touches.length||!this.wavesurfer||!this.container)return;t.preventDefault();const i=this.getTouchDistance(t)/this.initialPinchDistance;let s=this.initialZoom*i;s=Math.min(s,this.options.maxZoom);const e=this.wavesurfer.getDuration(),o=this.container.clientWidth,n=o/e;s<n&&(s=n);const h=o/s*(this.oldX/o);s===n?(this.wavesurfer.zoom(n),this.container.scrollLeft=0):(this.wavesurfer.zoom(s),this.container.scrollLeft=(this.pointerTime-h)*s)},this.onTouchEnd=t=>{this.isPinching&&t.touches.length<2&&(this.isPinching=!1,this.initialPinchDistance=0,this.initialZoom=0)},this.options=Object.assign({},o,t)}static create(t){return new n(t)}onInit(){var t,i;if(this.wrapper=null===(t=this.wavesurfer)||void 0===t?void 0:t.getWrapper(),!this.wrapper)return;this.container=this.wrapper.parentElement,void 0===this.options.maxZoom&&(this.options.maxZoom=this.container.clientWidth),this.endZoom=this.options.maxZoom;const o=null===(i=this.wavesurfer)||void 0===i?void 0:i.getState();o&&this.subscriptions.push(s((()=>{if(o.zoom.value>0&&0===this.startZoom&&this.options.exponentialZooming){const t=o.duration.value;t>0&&this.container&&(this.startZoom=this.container.clientWidth/t)}}),[o.zoom,o.duration]));const n=e(this.container,"wheel"),h=e(this.container,"touchstart"),r=e(this.container,"touchmove"),a=e(this.container,"touchend"),c=e(this.container,"touchcancel");this.subscriptions.push(s((()=>{const t=n.value;t&&this.onWheel(t)}),[n])),this.subscriptions.push(s((()=>{const t=h.value;t&&this.onTouchStart(t)}),[h])),this.subscriptions.push(s((()=>{const t=r.value;t&&this.onTouchMove(t)}),[r])),this.subscriptions.push(s((()=>{const t=a.value;t&&this.onTouchEnd(t)}),[a])),this.subscriptions.push(s((()=>{const t=c.value;t&&this.onTouchEnd(t)}),[c]))}getTouchDistance(t){const i=t.touches[0],s=t.touches[1];return Math.sqrt(Math.pow(s.clientX-i.clientX,2)+Math.pow(s.clientY-i.clientY,2))}getTouchCenterX(t){const i=t.touches[0],s=t.touches[1];return(i.clientX+s.clientX)/2}destroy(){super.destroy()}}return n}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { createDragStream } from '../drag-stream';
|
|
2
|
+
describe('createDragStream', () => {
|
|
3
|
+
beforeAll(() => {
|
|
4
|
+
// Mock matchMedia
|
|
5
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
6
|
+
writable: true,
|
|
7
|
+
value: jest.fn().mockReturnValue({
|
|
8
|
+
matches: false,
|
|
9
|
+
addListener: jest.fn(),
|
|
10
|
+
removeListener: jest.fn(),
|
|
11
|
+
}),
|
|
12
|
+
});
|
|
13
|
+
// Polyfill PointerEvent for jsdom
|
|
14
|
+
if (typeof window.PointerEvent === 'undefined') {
|
|
15
|
+
class FakePointerEvent extends MouseEvent {
|
|
16
|
+
constructor(type, props) {
|
|
17
|
+
super(type, props);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// @ts-expect-error - Polyfill PointerEvent for jsdom test environment
|
|
21
|
+
window.PointerEvent = FakePointerEvent;
|
|
22
|
+
// @ts-expect-error - Polyfill PointerEvent for jsdom test environment
|
|
23
|
+
global.PointerEvent = FakePointerEvent;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
let element;
|
|
27
|
+
let events;
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
element = document.createElement('div');
|
|
30
|
+
document.body.appendChild(element);
|
|
31
|
+
element.getBoundingClientRect = jest.fn(() => ({
|
|
32
|
+
left: 0,
|
|
33
|
+
top: 0,
|
|
34
|
+
right: 100,
|
|
35
|
+
bottom: 100,
|
|
36
|
+
width: 100,
|
|
37
|
+
height: 100,
|
|
38
|
+
x: 0,
|
|
39
|
+
y: 0,
|
|
40
|
+
toJSON: () => ({}),
|
|
41
|
+
}));
|
|
42
|
+
events = [];
|
|
43
|
+
});
|
|
44
|
+
afterEach(() => {
|
|
45
|
+
document.body.removeChild(element);
|
|
46
|
+
});
|
|
47
|
+
it('should create a drag signal', () => {
|
|
48
|
+
const { signal, cleanup } = createDragStream(element);
|
|
49
|
+
expect(signal).toBeDefined();
|
|
50
|
+
expect(signal.value).toBeNull();
|
|
51
|
+
cleanup();
|
|
52
|
+
});
|
|
53
|
+
it('should emit start event on drag', () => {
|
|
54
|
+
var _a;
|
|
55
|
+
const { signal, cleanup } = createDragStream(element, { threshold: 0 });
|
|
56
|
+
signal.subscribe((event) => {
|
|
57
|
+
if (event)
|
|
58
|
+
events.push(event);
|
|
59
|
+
});
|
|
60
|
+
// Simulate drag
|
|
61
|
+
const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 });
|
|
62
|
+
element.dispatchEvent(pointerDown);
|
|
63
|
+
const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20 });
|
|
64
|
+
document.dispatchEvent(pointerMove);
|
|
65
|
+
expect(events.length).toBeGreaterThan(0);
|
|
66
|
+
expect((_a = events[0]) === null || _a === void 0 ? void 0 : _a.type).toBe('start');
|
|
67
|
+
cleanup();
|
|
68
|
+
});
|
|
69
|
+
it('should emit move events with deltas', () => {
|
|
70
|
+
const { signal, cleanup } = createDragStream(element, { threshold: 0 });
|
|
71
|
+
signal.subscribe((event) => {
|
|
72
|
+
if (event)
|
|
73
|
+
events.push(event);
|
|
74
|
+
});
|
|
75
|
+
// Simulate drag
|
|
76
|
+
const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 });
|
|
77
|
+
element.dispatchEvent(pointerDown);
|
|
78
|
+
const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 30 });
|
|
79
|
+
document.dispatchEvent(pointerMove);
|
|
80
|
+
const moveEvent = events.find((e) => e.type === 'move');
|
|
81
|
+
expect(moveEvent).toBeDefined();
|
|
82
|
+
expect(moveEvent === null || moveEvent === void 0 ? void 0 : moveEvent.deltaX).toBe(10);
|
|
83
|
+
expect(moveEvent === null || moveEvent === void 0 ? void 0 : moveEvent.deltaY).toBe(20);
|
|
84
|
+
cleanup();
|
|
85
|
+
});
|
|
86
|
+
it('should emit end event on pointer up', () => {
|
|
87
|
+
const { signal, cleanup } = createDragStream(element, { threshold: 0 });
|
|
88
|
+
signal.subscribe((event) => {
|
|
89
|
+
if (event)
|
|
90
|
+
events.push(event);
|
|
91
|
+
});
|
|
92
|
+
// Simulate drag
|
|
93
|
+
const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 });
|
|
94
|
+
element.dispatchEvent(pointerDown);
|
|
95
|
+
const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20 });
|
|
96
|
+
document.dispatchEvent(pointerMove);
|
|
97
|
+
const pointerUp = new PointerEvent('pointerup', { clientX: 20, clientY: 20 });
|
|
98
|
+
document.dispatchEvent(pointerUp);
|
|
99
|
+
expect(events.some((e) => e.type === 'end')).toBe(true);
|
|
100
|
+
cleanup();
|
|
101
|
+
});
|
|
102
|
+
it('should respect threshold', () => {
|
|
103
|
+
const { signal, cleanup } = createDragStream(element, { threshold: 10 });
|
|
104
|
+
signal.subscribe((event) => {
|
|
105
|
+
if (event)
|
|
106
|
+
events.push(event);
|
|
107
|
+
});
|
|
108
|
+
// Simulate small drag (below threshold)
|
|
109
|
+
const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 });
|
|
110
|
+
element.dispatchEvent(pointerDown);
|
|
111
|
+
const pointerMove = new PointerEvent('pointermove', { clientX: 15, clientY: 15 });
|
|
112
|
+
document.dispatchEvent(pointerMove);
|
|
113
|
+
// Should not emit events yet
|
|
114
|
+
expect(events.length).toBe(0);
|
|
115
|
+
// Simulate larger drag (above threshold)
|
|
116
|
+
const pointerMove2 = new PointerEvent('pointermove', { clientX: 25, clientY: 25 });
|
|
117
|
+
document.dispatchEvent(pointerMove2);
|
|
118
|
+
// Should now emit events
|
|
119
|
+
expect(events.length).toBeGreaterThan(0);
|
|
120
|
+
cleanup();
|
|
121
|
+
});
|
|
122
|
+
it('should cleanup event listeners', () => {
|
|
123
|
+
const { cleanup } = createDragStream(element);
|
|
124
|
+
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
|
|
125
|
+
const removeEventListenerSpy = jest.spyOn(document, 'removeEventListener');
|
|
126
|
+
// Trigger drag to attach document listeners
|
|
127
|
+
const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 });
|
|
128
|
+
element.dispatchEvent(pointerDown);
|
|
129
|
+
expect(addEventListenerSpy).toHaveBeenCalled();
|
|
130
|
+
cleanup();
|
|
131
|
+
expect(removeEventListenerSpy).toHaveBeenCalled();
|
|
132
|
+
addEventListenerSpy.mockRestore();
|
|
133
|
+
removeEventListenerSpy.mockRestore();
|
|
134
|
+
});
|
|
135
|
+
it('should ignore non-primary mouse buttons', () => {
|
|
136
|
+
const { signal, cleanup } = createDragStream(element);
|
|
137
|
+
signal.subscribe((event) => {
|
|
138
|
+
if (event)
|
|
139
|
+
events.push(event);
|
|
140
|
+
});
|
|
141
|
+
// Simulate right-click drag
|
|
142
|
+
const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 2 });
|
|
143
|
+
element.dispatchEvent(pointerDown);
|
|
144
|
+
const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20 });
|
|
145
|
+
document.dispatchEvent(pointerMove);
|
|
146
|
+
// Should not emit any events
|
|
147
|
+
expect(events.length).toBe(0);
|
|
148
|
+
cleanup();
|
|
149
|
+
});
|
|
150
|
+
it('should stop propagation during drag', () => {
|
|
151
|
+
const { signal, cleanup } = createDragStream(element, { threshold: 0 });
|
|
152
|
+
signal.subscribe((event) => {
|
|
153
|
+
if (event)
|
|
154
|
+
events.push(event);
|
|
155
|
+
});
|
|
156
|
+
// Start drag
|
|
157
|
+
const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 });
|
|
158
|
+
element.dispatchEvent(pointerDown);
|
|
159
|
+
// Move - should prevent click
|
|
160
|
+
const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20 });
|
|
161
|
+
document.dispatchEvent(pointerMove);
|
|
162
|
+
// End drag
|
|
163
|
+
const pointerUp = new PointerEvent('pointerup', { clientX: 20, clientY: 20 });
|
|
164
|
+
document.dispatchEvent(pointerUp);
|
|
165
|
+
// Simulate click after drag
|
|
166
|
+
const clickHandler = jest.fn();
|
|
167
|
+
document.addEventListener('click', clickHandler, { capture: true });
|
|
168
|
+
const click = new MouseEvent('click', { bubbles: true });
|
|
169
|
+
Object.defineProperty(click, 'stopPropagation', { value: jest.fn() });
|
|
170
|
+
Object.defineProperty(click, 'preventDefault', { value: jest.fn() });
|
|
171
|
+
document.dispatchEvent(click);
|
|
172
|
+
document.removeEventListener('click', clickHandler, { capture: true });
|
|
173
|
+
cleanup();
|
|
174
|
+
});
|
|
175
|
+
it('should handle pointer leave events', () => {
|
|
176
|
+
const { signal, cleanup } = createDragStream(element, { threshold: 0 });
|
|
177
|
+
signal.subscribe((event) => {
|
|
178
|
+
if (event)
|
|
179
|
+
events.push(event);
|
|
180
|
+
});
|
|
181
|
+
// Start drag
|
|
182
|
+
const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0, pointerId: 1 });
|
|
183
|
+
element.dispatchEvent(pointerDown);
|
|
184
|
+
// Move to start dragging
|
|
185
|
+
const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20, pointerId: 1 });
|
|
186
|
+
document.dispatchEvent(pointerMove);
|
|
187
|
+
// Pointer leaves document
|
|
188
|
+
const pointerOut = new PointerEvent('pointerout', {
|
|
189
|
+
clientX: 20,
|
|
190
|
+
clientY: 20,
|
|
191
|
+
pointerId: 1,
|
|
192
|
+
relatedTarget: document.documentElement,
|
|
193
|
+
});
|
|
194
|
+
document.dispatchEvent(pointerOut);
|
|
195
|
+
// Should emit end event
|
|
196
|
+
expect(events.some((e) => e.type === 'end')).toBe(true);
|
|
197
|
+
cleanup();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { toStream, toStreams, mergeStreams, mapStream, filterStream } from '../event-stream-emitter';
|
|
2
|
+
import EventEmitter from '../../event-emitter';
|
|
3
|
+
// Test class that exposes emit for testing
|
|
4
|
+
class TestEmitter extends EventEmitter {
|
|
5
|
+
emit(event, ...args) {
|
|
6
|
+
super.emit(event, ...args);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
describe('event-stream-emitter', () => {
|
|
10
|
+
let emitter;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
emitter = new TestEmitter();
|
|
13
|
+
});
|
|
14
|
+
describe('toStream', () => {
|
|
15
|
+
it('should create a stream from event', () => {
|
|
16
|
+
const { stream, cleanup } = toStream(emitter, 'play');
|
|
17
|
+
expect(stream.value).toBeNull();
|
|
18
|
+
const values = [];
|
|
19
|
+
stream.subscribe((value) => values.push(value));
|
|
20
|
+
emitter.emit('play');
|
|
21
|
+
expect(stream.value).toEqual([]);
|
|
22
|
+
// Values includes initial null and then the event
|
|
23
|
+
expect(values.length).toBeGreaterThanOrEqual(1);
|
|
24
|
+
expect(values[values.length - 1]).toEqual([]);
|
|
25
|
+
cleanup();
|
|
26
|
+
});
|
|
27
|
+
it('should update stream with event arguments', () => {
|
|
28
|
+
const { stream, cleanup } = toStream(emitter, 'timeupdate');
|
|
29
|
+
emitter.emit('timeupdate', 42);
|
|
30
|
+
expect(stream.value).toEqual([42]);
|
|
31
|
+
emitter.emit('timeupdate', 100);
|
|
32
|
+
expect(stream.value).toEqual([100]);
|
|
33
|
+
cleanup();
|
|
34
|
+
});
|
|
35
|
+
it('should handle multiple arguments', () => {
|
|
36
|
+
const { stream, cleanup } = toStream(emitter, 'customEvent');
|
|
37
|
+
emitter.emit('customEvent', 'hello', 5);
|
|
38
|
+
expect(stream.value).toEqual(['hello', 5]);
|
|
39
|
+
cleanup();
|
|
40
|
+
});
|
|
41
|
+
it('should cleanup event listener', () => {
|
|
42
|
+
const { stream, cleanup } = toStream(emitter, 'play');
|
|
43
|
+
emitter.emit('play');
|
|
44
|
+
expect(stream.value).toEqual([]);
|
|
45
|
+
cleanup();
|
|
46
|
+
// After cleanup, event should not update stream
|
|
47
|
+
const oldValue = stream.value;
|
|
48
|
+
emitter.emit('play');
|
|
49
|
+
expect(stream.value).toBe(oldValue); // Value should not change after cleanup
|
|
50
|
+
});
|
|
51
|
+
it('should allow multiple subscriptions to stream', () => {
|
|
52
|
+
const { stream, cleanup } = toStream(emitter, 'timeupdate');
|
|
53
|
+
const values1 = [];
|
|
54
|
+
const values2 = [];
|
|
55
|
+
stream.subscribe((value) => values1.push(value));
|
|
56
|
+
stream.subscribe((value) => values2.push(value));
|
|
57
|
+
emitter.emit('timeupdate', 10);
|
|
58
|
+
emitter.emit('timeupdate', 20);
|
|
59
|
+
expect(values1).toContainEqual([10]);
|
|
60
|
+
expect(values1).toContainEqual([20]);
|
|
61
|
+
expect(values2).toContainEqual([10]);
|
|
62
|
+
expect(values2).toContainEqual([20]);
|
|
63
|
+
cleanup();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('toStreams', () => {
|
|
67
|
+
it('should create multiple streams', () => {
|
|
68
|
+
const streams = toStreams(emitter, ['play', 'pause', 'timeupdate']);
|
|
69
|
+
expect(streams.play).toBeDefined();
|
|
70
|
+
expect(streams.pause).toBeDefined();
|
|
71
|
+
expect(streams.timeupdate).toBeDefined();
|
|
72
|
+
emitter.emit('play');
|
|
73
|
+
expect(streams.play.value).toEqual([]);
|
|
74
|
+
emitter.emit('pause');
|
|
75
|
+
expect(streams.pause.value).toEqual([]);
|
|
76
|
+
emitter.emit('timeupdate', 50);
|
|
77
|
+
expect(streams.timeupdate.value).toEqual([50]);
|
|
78
|
+
streams.cleanup();
|
|
79
|
+
});
|
|
80
|
+
it('should cleanup all streams', () => {
|
|
81
|
+
const streams = toStreams(emitter, ['play', 'pause']);
|
|
82
|
+
streams.cleanup();
|
|
83
|
+
emitter.emit('play');
|
|
84
|
+
emitter.emit('pause');
|
|
85
|
+
// Streams should not update after cleanup
|
|
86
|
+
expect(streams.play.value).toBeNull();
|
|
87
|
+
expect(streams.pause.value).toBeNull();
|
|
88
|
+
});
|
|
89
|
+
it('should handle empty event list', () => {
|
|
90
|
+
const streams = toStreams(emitter, []);
|
|
91
|
+
expect(streams.cleanup).toBeDefined();
|
|
92
|
+
expect(typeof streams.cleanup).toBe('function');
|
|
93
|
+
streams.cleanup(); // Should not throw
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
describe('mergeStreams', () => {
|
|
97
|
+
it('should merge multiple events into one stream', () => {
|
|
98
|
+
const { stream, cleanup } = mergeStreams(emitter, ['play', 'pause']);
|
|
99
|
+
expect(stream.value).toBeNull();
|
|
100
|
+
const values = [];
|
|
101
|
+
stream.subscribe((value) => values.push(value));
|
|
102
|
+
emitter.emit('play');
|
|
103
|
+
expect(stream.value).toEqual({ event: 'play', args: [] });
|
|
104
|
+
emitter.emit('pause');
|
|
105
|
+
expect(stream.value).toEqual({ event: 'pause', args: [] });
|
|
106
|
+
expect(values).toContainEqual({ event: 'play', args: [] });
|
|
107
|
+
expect(values).toContainEqual({ event: 'pause', args: [] });
|
|
108
|
+
cleanup();
|
|
109
|
+
});
|
|
110
|
+
it('should include event arguments in merged stream', () => {
|
|
111
|
+
const { stream, cleanup } = mergeStreams(emitter, ['timeupdate', 'error']);
|
|
112
|
+
emitter.emit('timeupdate', 42);
|
|
113
|
+
expect(stream.value).toEqual({ event: 'timeupdate', args: [42] });
|
|
114
|
+
const error = new Error('Test error');
|
|
115
|
+
emitter.emit('error', error);
|
|
116
|
+
expect(stream.value).toEqual({ event: 'error', args: [error] });
|
|
117
|
+
cleanup();
|
|
118
|
+
});
|
|
119
|
+
it('should cleanup all merged event listeners', () => {
|
|
120
|
+
const { stream, cleanup } = mergeStreams(emitter, ['play', 'pause']);
|
|
121
|
+
cleanup();
|
|
122
|
+
emitter.emit('play');
|
|
123
|
+
emitter.emit('pause');
|
|
124
|
+
// Stream should not update after cleanup
|
|
125
|
+
expect(stream.value).toBeNull();
|
|
126
|
+
});
|
|
127
|
+
it('should handle single event', () => {
|
|
128
|
+
const { stream, cleanup } = mergeStreams(emitter, ['play']);
|
|
129
|
+
emitter.emit('play');
|
|
130
|
+
expect(stream.value).toEqual({ event: 'play', args: [] });
|
|
131
|
+
cleanup();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe('mapStream', () => {
|
|
135
|
+
it('should transform stream values', () => {
|
|
136
|
+
const { stream: timeStream, cleanup } = toStream(emitter, 'timeupdate');
|
|
137
|
+
const seconds = mapStream(timeStream, (value) => (value ? Math.floor(value[0]) : 0));
|
|
138
|
+
expect(seconds.value).toBe(0);
|
|
139
|
+
emitter.emit('timeupdate', 42.7);
|
|
140
|
+
expect(seconds.value).toBe(42);
|
|
141
|
+
emitter.emit('timeupdate', 99.9);
|
|
142
|
+
expect(seconds.value).toBe(99);
|
|
143
|
+
cleanup();
|
|
144
|
+
});
|
|
145
|
+
it('should work with multiple subscriptions', () => {
|
|
146
|
+
const { stream: timeStream, cleanup } = toStream(emitter, 'timeupdate');
|
|
147
|
+
const doubled = mapStream(timeStream, (value) => (value ? value[0] * 2 : 0));
|
|
148
|
+
const values = [];
|
|
149
|
+
doubled.subscribe((value) => values.push(value));
|
|
150
|
+
emitter.emit('timeupdate', 5);
|
|
151
|
+
emitter.emit('timeupdate', 10);
|
|
152
|
+
expect(values).toContain(10);
|
|
153
|
+
expect(values).toContain(20);
|
|
154
|
+
cleanup();
|
|
155
|
+
});
|
|
156
|
+
it('should handle null values', () => {
|
|
157
|
+
const { stream, cleanup } = toStream(emitter, 'play');
|
|
158
|
+
const mapped = mapStream(stream, (value) => (value ? 'playing' : 'not playing'));
|
|
159
|
+
expect(mapped.value).toBe('not playing');
|
|
160
|
+
emitter.emit('play');
|
|
161
|
+
expect(mapped.value).toBe('playing');
|
|
162
|
+
cleanup();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe('filterStream', () => {
|
|
166
|
+
it('should filter stream values', () => {
|
|
167
|
+
const { stream: timeStream, cleanup } = toStream(emitter, 'timeupdate');
|
|
168
|
+
const afterTen = filterStream(timeStream, (value) => (value ? value[0] > 10 : false));
|
|
169
|
+
expect(afterTen.value).toBeNull();
|
|
170
|
+
emitter.emit('timeupdate', 5);
|
|
171
|
+
expect(afterTen.value).toBeNull();
|
|
172
|
+
emitter.emit('timeupdate', 15);
|
|
173
|
+
expect(afterTen.value).toEqual([15]);
|
|
174
|
+
emitter.emit('timeupdate', 7);
|
|
175
|
+
expect(afterTen.value).toBeNull();
|
|
176
|
+
cleanup();
|
|
177
|
+
});
|
|
178
|
+
it('should work with subscriptions', () => {
|
|
179
|
+
const { stream: timeStream, cleanup } = toStream(emitter, 'timeupdate');
|
|
180
|
+
const evenSeconds = filterStream(timeStream, (value) => value !== null && Math.floor(value[0]) % 2 === 0);
|
|
181
|
+
const values = [];
|
|
182
|
+
evenSeconds.subscribe((value) => values.push(value));
|
|
183
|
+
emitter.emit('timeupdate', 1);
|
|
184
|
+
emitter.emit('timeupdate', 2);
|
|
185
|
+
emitter.emit('timeupdate', 3);
|
|
186
|
+
emitter.emit('timeupdate', 4);
|
|
187
|
+
expect(values.filter((v) => v !== null)).toEqual([[2], [4]]);
|
|
188
|
+
cleanup();
|
|
189
|
+
});
|
|
190
|
+
it('should pass through values that match predicate', () => {
|
|
191
|
+
const { stream, cleanup } = toStream(emitter, 'customEvent');
|
|
192
|
+
const onlyHello = filterStream(stream, (value) => value !== null && value[0] === 'hello');
|
|
193
|
+
emitter.emit('customEvent', 'hello', 1);
|
|
194
|
+
expect(onlyHello.value).toEqual(['hello', 1]);
|
|
195
|
+
emitter.emit('customEvent', 'world', 2);
|
|
196
|
+
expect(onlyHello.value).toBeNull();
|
|
197
|
+
cleanup();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
describe('integration', () => {
|
|
201
|
+
it('should allow chaining stream operations', () => {
|
|
202
|
+
const { stream: timeStream, cleanup } = toStream(emitter, 'timeupdate');
|
|
203
|
+
// Filter for times > 10, then map to seconds
|
|
204
|
+
const filtered = filterStream(timeStream, (value) => (value ? value[0] > 10 : false));
|
|
205
|
+
const seconds = mapStream(filtered, (value) => (value ? Math.floor(value[0]) : 0));
|
|
206
|
+
const values = [];
|
|
207
|
+
seconds.subscribe((value) => values.push(value));
|
|
208
|
+
emitter.emit('timeupdate', 5);
|
|
209
|
+
emitter.emit('timeupdate', 15.7);
|
|
210
|
+
emitter.emit('timeupdate', 20.3);
|
|
211
|
+
expect(values).toContain(15);
|
|
212
|
+
expect(values).toContain(20);
|
|
213
|
+
expect(values).not.toContain(5);
|
|
214
|
+
cleanup();
|
|
215
|
+
});
|
|
216
|
+
it('should work with merged streams', () => {
|
|
217
|
+
const { stream: mergedStream, cleanup } = mergeStreams(emitter, ['play', 'pause']);
|
|
218
|
+
const eventNames = mapStream(mergedStream, (value) => (value ? value.event : null));
|
|
219
|
+
const names = [];
|
|
220
|
+
eventNames.subscribe((name) => names.push(name));
|
|
221
|
+
emitter.emit('play');
|
|
222
|
+
emitter.emit('pause');
|
|
223
|
+
emitter.emit('play');
|
|
224
|
+
expect(names).toContain('play');
|
|
225
|
+
expect(names).toContain('pause');
|
|
226
|
+
expect(names.filter((n) => n === 'play')).toHaveLength(2);
|
|
227
|
+
cleanup();
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|