wavesurfer.js 7.9.6 → 7.9.8
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/dist/__tests__/draggable.test.js +2 -2
- package/dist/__tests__/renderer.test.d.ts +6 -0
- package/dist/__tests__/renderer.test.js +180 -0
- package/dist/__tests__/timer.test.js +0 -10
- package/dist/__tests__/wavesurfer.test.d.ts +1 -0
- package/dist/__tests__/wavesurfer.test.js +227 -0
- package/dist/player.js +1 -1
- package/dist/plugins/hover.cjs +1 -1
- package/dist/plugins/hover.d.ts +19 -0
- 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.d.ts +2 -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/spectrogram.cjs +1 -1
- package/dist/plugins/spectrogram.d.ts +2 -0
- package/dist/plugins/spectrogram.esm.js +1 -1
- package/dist/plugins/spectrogram.js +1 -1
- package/dist/plugins/spectrogram.min.js +1 -1
- package/dist/renderer.js +7 -2
- package/dist/timer.js +0 -1
- package/dist/types.d.ts +1 -1
- package/dist/wavesurfer.cjs +1 -1
- package/dist/wavesurfer.d.ts +1 -1
- package/dist/wavesurfer.esm.js +1 -1
- package/dist/wavesurfer.js +4 -2
- package/dist/wavesurfer.min.js +1 -1
- package/dist/webaudio.js +4 -2
- package/package.json +3 -3
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import Renderer from '../renderer.js';
|
|
11
|
+
const createAudioBuffer = (channels, duration = 1) => {
|
|
12
|
+
return {
|
|
13
|
+
duration,
|
|
14
|
+
length: channels[0].length,
|
|
15
|
+
sampleRate: channels[0].length / duration,
|
|
16
|
+
numberOfChannels: channels.length,
|
|
17
|
+
getChannelData: (i) => Float32Array.from(channels[i]),
|
|
18
|
+
copyFromChannel: jest.fn(),
|
|
19
|
+
copyToChannel: jest.fn(),
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
describe('Renderer', () => {
|
|
23
|
+
let container;
|
|
24
|
+
let renderer;
|
|
25
|
+
const originalGetContext = window.HTMLCanvasElement.prototype.getContext;
|
|
26
|
+
const originalToDataURL = window.HTMLCanvasElement.prototype.toDataURL;
|
|
27
|
+
const originalToBlob = window.HTMLCanvasElement.prototype.toBlob;
|
|
28
|
+
beforeAll(() => {
|
|
29
|
+
Object.defineProperty(window, 'devicePixelRatio', { value: 1, writable: true });
|
|
30
|
+
window.HTMLCanvasElement.prototype.getContext = jest.fn(() => ({
|
|
31
|
+
beginPath: jest.fn(),
|
|
32
|
+
rect: jest.fn(),
|
|
33
|
+
roundRect: jest.fn(),
|
|
34
|
+
moveTo: jest.fn(),
|
|
35
|
+
lineTo: jest.fn(),
|
|
36
|
+
closePath: jest.fn(),
|
|
37
|
+
fill: jest.fn(),
|
|
38
|
+
drawImage: jest.fn(),
|
|
39
|
+
fillRect: jest.fn(),
|
|
40
|
+
createLinearGradient: jest.fn(() => ({ addColorStop: jest.fn() })),
|
|
41
|
+
globalCompositeOperation: '',
|
|
42
|
+
canvas: { width: 100, height: 100 },
|
|
43
|
+
}));
|
|
44
|
+
window.HTMLCanvasElement.prototype.toDataURL = jest.fn(() => 'data:mock');
|
|
45
|
+
window.HTMLCanvasElement.prototype.toBlob = jest.fn((cb) => cb(new Blob([''])));
|
|
46
|
+
});
|
|
47
|
+
afterAll(() => {
|
|
48
|
+
window.HTMLCanvasElement.prototype.getContext = originalGetContext;
|
|
49
|
+
window.HTMLCanvasElement.prototype.toDataURL = originalToDataURL;
|
|
50
|
+
window.HTMLCanvasElement.prototype.toBlob = originalToBlob;
|
|
51
|
+
});
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
container = document.createElement('div');
|
|
54
|
+
container.id = 'root';
|
|
55
|
+
document.body.appendChild(container);
|
|
56
|
+
renderer = new Renderer({ container });
|
|
57
|
+
});
|
|
58
|
+
afterEach(() => {
|
|
59
|
+
renderer.destroy();
|
|
60
|
+
container.remove();
|
|
61
|
+
jest.clearAllMocks();
|
|
62
|
+
});
|
|
63
|
+
test('parentFromOptionsContainer returns element and throws', () => {
|
|
64
|
+
expect(renderer.parentFromOptionsContainer(container)).toBe(container);
|
|
65
|
+
expect(renderer.parentFromOptionsContainer('#root')).toBe(container);
|
|
66
|
+
expect(() => renderer.parentFromOptionsContainer('#missing')).toThrow();
|
|
67
|
+
});
|
|
68
|
+
test('initHtml creates shadow root', () => {
|
|
69
|
+
const [el, shadow] = renderer.initHtml();
|
|
70
|
+
expect(el.shadowRoot).toBe(shadow);
|
|
71
|
+
expect(shadow.querySelector('.scroll')).not.toBeNull();
|
|
72
|
+
});
|
|
73
|
+
test('getHeight calculates values', () => {
|
|
74
|
+
;
|
|
75
|
+
renderer.audioData = { numberOfChannels: 2 };
|
|
76
|
+
expect(renderer.getHeight(undefined, undefined)).toBe(128);
|
|
77
|
+
expect(renderer.getHeight(50, undefined)).toBe(50);
|
|
78
|
+
container.style.height = '200px';
|
|
79
|
+
expect(renderer.getHeight('auto', [{ overlay: false }])).toBe(64);
|
|
80
|
+
});
|
|
81
|
+
test('createDelay resolves after time', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
82
|
+
jest.useFakeTimers();
|
|
83
|
+
const delay = renderer.createDelay(10);
|
|
84
|
+
const spy = jest.fn();
|
|
85
|
+
const p = delay().then(spy);
|
|
86
|
+
jest.advanceTimersByTime(10);
|
|
87
|
+
yield p;
|
|
88
|
+
expect(spy).toHaveBeenCalled();
|
|
89
|
+
jest.useRealTimers();
|
|
90
|
+
}));
|
|
91
|
+
test('convertColorValues supports gradients', () => {
|
|
92
|
+
const result = renderer.convertColorValues(['red', 'blue']);
|
|
93
|
+
expect(typeof result).toBe('object');
|
|
94
|
+
expect(renderer.convertColorValues('red')).toBe('red');
|
|
95
|
+
});
|
|
96
|
+
test('getPixelRatio returns positive', () => {
|
|
97
|
+
window.devicePixelRatio = 2;
|
|
98
|
+
expect(renderer.getPixelRatio()).toBe(2);
|
|
99
|
+
});
|
|
100
|
+
test('renderBarWaveform and renderLineWaveform draw on context', () => {
|
|
101
|
+
const ctx = renderer.canvasWrapper.ownerDocument.createElement('canvas').getContext('2d');
|
|
102
|
+
const data = [new Float32Array([0, 0.5, -0.5]), new Float32Array([0, -0.5, 0.5])];
|
|
103
|
+
renderer.renderBarWaveform(data, {}, ctx, 1);
|
|
104
|
+
expect(ctx.beginPath).toHaveBeenCalled();
|
|
105
|
+
renderer.renderLineWaveform(data, {}, ctx, 1);
|
|
106
|
+
expect(ctx.lineTo).toHaveBeenCalled();
|
|
107
|
+
});
|
|
108
|
+
test('renderWaveform chooses rendering path', () => {
|
|
109
|
+
const ctx = document.createElement('canvas').getContext('2d');
|
|
110
|
+
const data = [new Float32Array([0, 1])];
|
|
111
|
+
const spyBar = jest.spyOn(renderer, 'renderBarWaveform');
|
|
112
|
+
const spyLine = jest.spyOn(renderer, 'renderLineWaveform');
|
|
113
|
+
renderer.renderWaveform(data, { barWidth: 1 }, ctx);
|
|
114
|
+
expect(spyBar).toHaveBeenCalled();
|
|
115
|
+
renderer.renderWaveform(data, {}, ctx);
|
|
116
|
+
expect(spyLine).toHaveBeenCalled();
|
|
117
|
+
});
|
|
118
|
+
test('renderSingleCanvas appends canvases', () => {
|
|
119
|
+
const canvasContainer = document.createElement('div');
|
|
120
|
+
const progressContainer = document.createElement('div');
|
|
121
|
+
const data = [new Float32Array([0, 1])];
|
|
122
|
+
renderer.renderSingleCanvas(data, {}, 10, 10, 0, canvasContainer, progressContainer);
|
|
123
|
+
expect(canvasContainer.querySelector('canvas')).not.toBeNull();
|
|
124
|
+
expect(progressContainer.querySelector('canvas')).not.toBeNull();
|
|
125
|
+
});
|
|
126
|
+
test('renderMultiCanvas draws and subscribes', () => {
|
|
127
|
+
const canvasContainer = document.createElement('div');
|
|
128
|
+
const progressContainer = document.createElement('div');
|
|
129
|
+
const data = [new Float32Array([0, 1])];
|
|
130
|
+
Object.defineProperty(renderer.scrollContainer, 'clientWidth', { configurable: true, value: 200 });
|
|
131
|
+
renderer.renderMultiCanvas(data, { barWidth: 1 }, 200, 10, canvasContainer, progressContainer);
|
|
132
|
+
expect(canvasContainer.querySelector('canvas')).not.toBeNull();
|
|
133
|
+
});
|
|
134
|
+
test('renderChannel creates containers', () => {
|
|
135
|
+
const data = [new Float32Array([0, 1])];
|
|
136
|
+
renderer.renderChannel(data, {}, 10, 0);
|
|
137
|
+
expect(renderer.canvasWrapper.children.length).toBeGreaterThan(0);
|
|
138
|
+
});
|
|
139
|
+
test('render processes audio buffer', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
140
|
+
const buffer = createAudioBuffer([[0, 0.5, -0.5]]);
|
|
141
|
+
const spy = jest.fn();
|
|
142
|
+
renderer.on('render', spy);
|
|
143
|
+
yield renderer.render(buffer);
|
|
144
|
+
expect(spy).toHaveBeenCalled();
|
|
145
|
+
}));
|
|
146
|
+
test('reRender keeps scroll position', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
147
|
+
const buffer = createAudioBuffer([[0, 0.5, -0.5]]);
|
|
148
|
+
yield renderer.render(buffer);
|
|
149
|
+
renderer.setScroll(10);
|
|
150
|
+
renderer.reRender();
|
|
151
|
+
expect(renderer.getScroll()).toBe(10);
|
|
152
|
+
}));
|
|
153
|
+
test('zoom updates option', () => {
|
|
154
|
+
renderer.zoom(20);
|
|
155
|
+
expect(renderer.options.minPxPerSec).toBe(20);
|
|
156
|
+
});
|
|
157
|
+
test('scrollIntoView updates scroll', () => {
|
|
158
|
+
Object.defineProperty(renderer.scrollContainer, 'scrollWidth', { configurable: true, value: 100 });
|
|
159
|
+
Object.defineProperty(renderer.scrollContainer, 'clientWidth', { configurable: true, value: 50 });
|
|
160
|
+
renderer.renderProgress(0);
|
|
161
|
+
renderer.scrollIntoView(0.8);
|
|
162
|
+
expect(renderer.getScroll()).toBeGreaterThanOrEqual(0);
|
|
163
|
+
});
|
|
164
|
+
test('renderProgress updates styles', () => {
|
|
165
|
+
renderer.renderProgress(0.5);
|
|
166
|
+
expect(renderer.progressWrapper.style.width).toBe('50%');
|
|
167
|
+
});
|
|
168
|
+
test('exportImage returns data', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
169
|
+
const canvas = document.createElement('canvas');
|
|
170
|
+
renderer.canvasWrapper.appendChild(canvas);
|
|
171
|
+
const urls = yield renderer.exportImage('image/png', 1, 'dataURL');
|
|
172
|
+
expect(urls).toHaveLength(1);
|
|
173
|
+
const blobs = yield renderer.exportImage('image/png', 1, 'blob');
|
|
174
|
+
expect(blobs).toHaveLength(1);
|
|
175
|
+
}));
|
|
176
|
+
test('destroy cleans up', () => {
|
|
177
|
+
renderer.destroy();
|
|
178
|
+
expect(container.contains(renderer.getWrapper())).toBe(false);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
@@ -15,14 +15,4 @@ describe('Timer', () => {
|
|
|
15
15
|
timer.start();
|
|
16
16
|
expect(tick).toHaveBeenCalledTimes(2);
|
|
17
17
|
});
|
|
18
|
-
test('stop unsubscribes', () => {
|
|
19
|
-
const timer = new Timer();
|
|
20
|
-
const tick = jest.fn();
|
|
21
|
-
timer.on('tick', tick);
|
|
22
|
-
timer.start();
|
|
23
|
-
timer.stop();
|
|
24
|
-
tick.mockClear();
|
|
25
|
-
timer.emit('tick');
|
|
26
|
-
expect(tick).not.toHaveBeenCalled();
|
|
27
|
-
});
|
|
28
18
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
jest.mock('../renderer.js', () => {
|
|
11
|
+
let lastInstance;
|
|
12
|
+
class Renderer {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.wrapper = document.createElement('div');
|
|
15
|
+
this.renderProgress = jest.fn();
|
|
16
|
+
this.on = jest.fn(() => () => undefined);
|
|
17
|
+
this.setOptions = jest.fn();
|
|
18
|
+
this.getWrapper = jest.fn(() => this.wrapper);
|
|
19
|
+
this.getWidth = jest.fn(() => 100);
|
|
20
|
+
this.getScroll = jest.fn(() => 0);
|
|
21
|
+
this.setScroll = jest.fn();
|
|
22
|
+
this.setScrollPercentage = jest.fn();
|
|
23
|
+
this.render = jest.fn();
|
|
24
|
+
this.zoom = jest.fn();
|
|
25
|
+
this.exportImage = jest.fn(() => []);
|
|
26
|
+
this.destroy = jest.fn();
|
|
27
|
+
this.options = options;
|
|
28
|
+
lastInstance = this;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { __esModule: true, default: Renderer, getLastInstance: () => lastInstance };
|
|
32
|
+
});
|
|
33
|
+
jest.mock('../timer.js', () => {
|
|
34
|
+
let lastInstance;
|
|
35
|
+
class Timer {
|
|
36
|
+
constructor() {
|
|
37
|
+
this.on = jest.fn(() => () => undefined);
|
|
38
|
+
this.start = jest.fn();
|
|
39
|
+
this.stop = jest.fn();
|
|
40
|
+
this.destroy = jest.fn();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const ctor = jest.fn(() => {
|
|
44
|
+
lastInstance = new Timer();
|
|
45
|
+
return lastInstance;
|
|
46
|
+
});
|
|
47
|
+
return { __esModule: true, default: ctor, getLastInstance: () => lastInstance };
|
|
48
|
+
});
|
|
49
|
+
jest.mock('../decoder.js', () => {
|
|
50
|
+
const createBuffer = jest.fn((data, duration) => ({
|
|
51
|
+
duration,
|
|
52
|
+
numberOfChannels: data.length,
|
|
53
|
+
getChannelData: (i) => Float32Array.from(data[i]),
|
|
54
|
+
}));
|
|
55
|
+
return { __esModule: true, default: { decode: jest.fn(), createBuffer } };
|
|
56
|
+
});
|
|
57
|
+
import WaveSurfer from '../wavesurfer.js';
|
|
58
|
+
import { BasePlugin } from '../base-plugin.js';
|
|
59
|
+
import * as RendererModule from '../renderer.js';
|
|
60
|
+
import * as TimerModule from '../timer.js';
|
|
61
|
+
const getRenderer = RendererModule.getLastInstance;
|
|
62
|
+
const getTimer = TimerModule.getLastInstance;
|
|
63
|
+
const createMedia = () => {
|
|
64
|
+
const media = document.createElement('audio');
|
|
65
|
+
media.play = jest.fn().mockResolvedValue(undefined);
|
|
66
|
+
media.pause = jest.fn();
|
|
67
|
+
Object.defineProperty(media, 'duration', { configurable: true, value: 100, writable: true });
|
|
68
|
+
return media;
|
|
69
|
+
};
|
|
70
|
+
const createWs = (opts = {}) => {
|
|
71
|
+
const container = document.createElement('div');
|
|
72
|
+
return WaveSurfer.create(Object.assign({ container, media: createMedia() }, opts));
|
|
73
|
+
};
|
|
74
|
+
afterEach(() => {
|
|
75
|
+
jest.clearAllMocks();
|
|
76
|
+
});
|
|
77
|
+
describe('WaveSurfer public methods', () => {
|
|
78
|
+
test('create returns instance', () => {
|
|
79
|
+
const ws = createWs();
|
|
80
|
+
expect(ws).toBeInstanceOf(WaveSurfer);
|
|
81
|
+
});
|
|
82
|
+
test('setOptions merges options and updates renderer', () => {
|
|
83
|
+
const ws = createWs();
|
|
84
|
+
ws.setOptions({ height: 200, audioRate: 2, mediaControls: true });
|
|
85
|
+
const renderer = getRenderer();
|
|
86
|
+
expect(ws.options.height).toBe(200);
|
|
87
|
+
expect(renderer.setOptions).toHaveBeenCalledWith(ws.options);
|
|
88
|
+
expect(ws.getPlaybackRate()).toBe(2);
|
|
89
|
+
expect(ws.getMediaElement().controls).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
test('registerPlugin adds and removes plugin', () => {
|
|
92
|
+
const ws = createWs();
|
|
93
|
+
class TestPlugin extends BasePlugin {
|
|
94
|
+
}
|
|
95
|
+
const plugin = new TestPlugin({});
|
|
96
|
+
ws.registerPlugin(plugin);
|
|
97
|
+
expect(ws.getActivePlugins()).toContain(plugin);
|
|
98
|
+
plugin.destroy();
|
|
99
|
+
expect(ws.getActivePlugins()).not.toContain(plugin);
|
|
100
|
+
});
|
|
101
|
+
test('wrapper and scroll helpers call renderer', () => {
|
|
102
|
+
const ws = createWs();
|
|
103
|
+
const renderer = getRenderer();
|
|
104
|
+
ws.getWrapper();
|
|
105
|
+
expect(renderer.getWrapper).toHaveBeenCalled();
|
|
106
|
+
ws.getWidth();
|
|
107
|
+
expect(renderer.getWidth).toHaveBeenCalled();
|
|
108
|
+
ws.getScroll();
|
|
109
|
+
expect(renderer.getScroll).toHaveBeenCalled();
|
|
110
|
+
ws.setScroll(42);
|
|
111
|
+
expect(renderer.setScroll).toHaveBeenCalledWith(42);
|
|
112
|
+
jest.spyOn(ws, 'getDuration').mockReturnValue(10);
|
|
113
|
+
ws.setScrollTime(5);
|
|
114
|
+
expect(renderer.setScrollPercentage).toHaveBeenCalledWith(0.5);
|
|
115
|
+
});
|
|
116
|
+
test('load and loadBlob call loadAudio', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
117
|
+
const ws = createWs();
|
|
118
|
+
const spy = jest.spyOn(ws, 'loadAudio').mockResolvedValue(undefined);
|
|
119
|
+
yield ws.load('url');
|
|
120
|
+
expect(spy).toHaveBeenCalledWith('url', undefined, undefined, undefined);
|
|
121
|
+
const blob = new Blob([]);
|
|
122
|
+
yield ws.loadBlob(blob);
|
|
123
|
+
expect(spy).toHaveBeenCalledWith('', blob, undefined, undefined);
|
|
124
|
+
}));
|
|
125
|
+
test('zoom requires decoded data', () => {
|
|
126
|
+
const ws = createWs();
|
|
127
|
+
expect(() => ws.zoom(10)).toThrow();
|
|
128
|
+
ws.decodedData = { duration: 1 };
|
|
129
|
+
ws.zoom(10);
|
|
130
|
+
expect(getRenderer().zoom).toHaveBeenCalledWith(10);
|
|
131
|
+
});
|
|
132
|
+
test('getDecodedData returns buffer', () => {
|
|
133
|
+
const ws = createWs();
|
|
134
|
+
ws.decodedData = 123;
|
|
135
|
+
expect(ws.getDecodedData()).toBe(123);
|
|
136
|
+
});
|
|
137
|
+
test('exportPeaks reads data from buffer', () => {
|
|
138
|
+
const ws = createWs();
|
|
139
|
+
ws.decodedData = {
|
|
140
|
+
numberOfChannels: 1,
|
|
141
|
+
getChannelData: () => new Float32Array([0, 1, -1]),
|
|
142
|
+
duration: 3,
|
|
143
|
+
};
|
|
144
|
+
const peaks = ws.exportPeaks({ maxLength: 3, precision: 100 });
|
|
145
|
+
expect(peaks[0]).toEqual([0, 1, -1]);
|
|
146
|
+
});
|
|
147
|
+
test('getDuration falls back to decoded data', () => {
|
|
148
|
+
const ws = createWs();
|
|
149
|
+
const media = ws.getMediaElement();
|
|
150
|
+
Object.defineProperty(media, 'duration', { configurable: true, value: Infinity });
|
|
151
|
+
ws.decodedData = { duration: 2 };
|
|
152
|
+
expect(ws.getDuration()).toBe(2);
|
|
153
|
+
});
|
|
154
|
+
test('toggleInteraction sets option', () => {
|
|
155
|
+
const ws = createWs();
|
|
156
|
+
ws.toggleInteraction(false);
|
|
157
|
+
expect(ws.options.interact).toBe(false);
|
|
158
|
+
});
|
|
159
|
+
test('setTime updates progress and emits event', () => {
|
|
160
|
+
const ws = createWs();
|
|
161
|
+
const spy = jest.fn();
|
|
162
|
+
ws.on('timeupdate', spy);
|
|
163
|
+
ws.setTime(1);
|
|
164
|
+
expect(spy).toHaveBeenCalledWith(1);
|
|
165
|
+
expect(getRenderer().renderProgress).toHaveBeenCalled();
|
|
166
|
+
});
|
|
167
|
+
test('seekTo calculates correct time', () => {
|
|
168
|
+
const ws = createWs();
|
|
169
|
+
jest.spyOn(ws, 'getDuration').mockReturnValue(10);
|
|
170
|
+
const setTimeSpy = jest.spyOn(ws, 'setTime');
|
|
171
|
+
ws.seekTo(0.5);
|
|
172
|
+
expect(setTimeSpy).toHaveBeenCalledWith(5);
|
|
173
|
+
});
|
|
174
|
+
test('play sets start and end', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
175
|
+
const ws = createWs();
|
|
176
|
+
const spy = jest.spyOn(ws, 'setTime');
|
|
177
|
+
yield ws.play(2, 4);
|
|
178
|
+
expect(spy).toHaveBeenCalledWith(2);
|
|
179
|
+
expect(ws.stopAtPosition).toBe(4);
|
|
180
|
+
}));
|
|
181
|
+
test('playPause toggles play and pause', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
182
|
+
const ws = createWs();
|
|
183
|
+
const media = ws.getMediaElement();
|
|
184
|
+
yield ws.playPause();
|
|
185
|
+
expect(media.play).toHaveBeenCalled();
|
|
186
|
+
Object.defineProperty(media, 'paused', { configurable: true, value: false });
|
|
187
|
+
yield ws.playPause();
|
|
188
|
+
expect(media.pause).toHaveBeenCalled();
|
|
189
|
+
}));
|
|
190
|
+
test('stop resets time', () => {
|
|
191
|
+
const ws = createWs();
|
|
192
|
+
ws.setTime(5);
|
|
193
|
+
ws.stop();
|
|
194
|
+
expect(ws.getCurrentTime()).toBe(0);
|
|
195
|
+
});
|
|
196
|
+
test('skip and empty', () => {
|
|
197
|
+
const ws = createWs();
|
|
198
|
+
ws.getMediaElement().currentTime = 1;
|
|
199
|
+
const spy = jest.spyOn(ws, 'setTime');
|
|
200
|
+
ws.skip(2);
|
|
201
|
+
expect(spy).toHaveBeenCalledWith(3);
|
|
202
|
+
const loadSpy = jest.spyOn(ws, 'load').mockResolvedValue(undefined);
|
|
203
|
+
ws.empty();
|
|
204
|
+
expect(loadSpy).toHaveBeenCalledWith('', [[0]], 0.001);
|
|
205
|
+
});
|
|
206
|
+
test('setMediaElement reinitializes events', () => {
|
|
207
|
+
const ws = createWs();
|
|
208
|
+
const unsub = jest.spyOn(ws, 'unsubscribePlayerEvents');
|
|
209
|
+
const init = jest.spyOn(ws, 'initPlayerEvents');
|
|
210
|
+
const el = createMedia();
|
|
211
|
+
ws.setMediaElement(el);
|
|
212
|
+
expect(unsub).toHaveBeenCalled();
|
|
213
|
+
expect(init).toHaveBeenCalled();
|
|
214
|
+
expect(ws.getMediaElement()).toBe(el);
|
|
215
|
+
});
|
|
216
|
+
test('exportImage uses renderer', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
217
|
+
const ws = createWs();
|
|
218
|
+
yield ws.exportImage('image/png', 1, 'dataURL');
|
|
219
|
+
expect(getRenderer().exportImage).toHaveBeenCalled();
|
|
220
|
+
}));
|
|
221
|
+
test('destroy cleans up renderer and timer', () => {
|
|
222
|
+
const ws = createWs();
|
|
223
|
+
ws.destroy();
|
|
224
|
+
expect(getRenderer().destroy).toHaveBeenCalled();
|
|
225
|
+
expect(getTimer().destroy).toHaveBeenCalled();
|
|
226
|
+
});
|
|
227
|
+
});
|
package/dist/player.js
CHANGED
package/dist/plugins/hover.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";class t{constructor(){this.listeners={}}on(t,e,s){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),null==s?void 0:s.once){const s=()=>{this.un(t,s),this.un(t,e)};return this.on(t,s),s}return()=>this.un(t,e)}un(t,e){var s;null===(s=this.listeners[t])||void 0===s||s.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}class e extends t{constructor(t){super(),this.subscriptions=[],this.options=t}onInit(){}_init(t){this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t()))}}function s(t,e){const i=e.xmlns?document.createElementNS(e.xmlns,t):document.createElement(t);for(const[t,n]of Object.entries(e))if("children"===t&&n)for(const[t,e]of Object.entries(n))e instanceof Node?i.appendChild(e):"string"==typeof e?i.appendChild(document.createTextNode(e)):i.appendChild(s(t,e));else"style"===t?Object.assign(i.style,n):"textContent"===t?i.textContent=n:i.setAttribute(t,n.toString());return i}function i(t,e,i){const n=s(t,e||{});return null==i||i.appendChild(n),n}const n={lineWidth:1,labelSize:11,formatTimeCallback:t=>`${Math.floor(t/60)}:${`0${Math.floor(t)%60}`.slice(-2)}`};class o extends e{constructor(t){super(t||{}),this.unsubscribe=()=>{},this.onPointerMove=t=>{if(!this.wavesurfer)return;const e=this.wavesurfer.getWrapper().getBoundingClientRect(),{width:s}=e,i=t.clientX-e.left,n=Math.min(1,Math.max(0,i/s)),o=Math.min(s-this.options.lineWidth-1,i);this.wrapper.style.transform=`translateX(${o}px)`,this.wrapper.style.opacity="1";const r=this.wavesurfer.getDuration()||0;this.label.textContent=this.options.formatTimeCallback(r*n);const a=this.label.offsetWidth;this.label.style.transform=
|
|
1
|
+
"use strict";class t{constructor(){this.listeners={}}on(t,e,s){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),null==s?void 0:s.once){const s=()=>{this.un(t,s),this.un(t,e)};return this.on(t,s),s}return()=>this.un(t,e)}un(t,e){var s;null===(s=this.listeners[t])||void 0===s||s.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}class e extends t{constructor(t){super(),this.subscriptions=[],this.options=t}onInit(){}_init(t){this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t()))}}function s(t,e){const i=e.xmlns?document.createElementNS(e.xmlns,t):document.createElement(t);for(const[t,n]of Object.entries(e))if("children"===t&&n)for(const[t,e]of Object.entries(n))e instanceof Node?i.appendChild(e):"string"==typeof e?i.appendChild(document.createTextNode(e)):i.appendChild(s(t,e));else"style"===t?Object.assign(i.style,n):"textContent"===t?i.textContent=n:i.setAttribute(t,n.toString());return i}function i(t,e,i){const n=s(t,e||{});return null==i||i.appendChild(n),n}const n={lineWidth:1,labelSize:11,labelPreferLeft:!1,formatTimeCallback:t=>`${Math.floor(t/60)}:${`0${Math.floor(t)%60}`.slice(-2)}`};class o extends e{constructor(t){super(t||{}),this.unsubscribe=()=>{},this.onPointerMove=t=>{if(!this.wavesurfer)return;const e=this.wavesurfer.getWrapper().getBoundingClientRect(),{width:s}=e,i=t.clientX-e.left,n=Math.min(1,Math.max(0,i/s)),o=Math.min(s-this.options.lineWidth-1,i);this.wrapper.style.transform=`translateX(${o}px)`,this.wrapper.style.opacity="1";const r=this.wavesurfer.getDuration()||0;this.label.textContent=this.options.formatTimeCallback(r*n);const a=this.label.offsetWidth,l=this.options.labelPreferLeft?o-a>0:o+a>s;this.label.style.transform=l?`translateX(-${a+this.options.lineWidth}px)`:"",this.emit("hover",n)},this.onPointerLeave=()=>{this.wrapper.style.opacity="0"},this.options=Object.assign({},n,t),this.wrapper=i("div",{part:"hover"}),this.label=i("span",{part:"hover-label"},this.wrapper)}static create(t){return new o(t)}addUnits(t){return`${t}${"number"==typeof t?"px":""}`}onInit(){if(!this.wavesurfer)throw Error("WaveSurfer is not initialized");const t=this.wavesurfer.options,e=this.options.lineColor||t.cursorColor||t.progressColor;Object.assign(this.wrapper.style,{position:"absolute",zIndex:10,left:0,top:0,height:"100%",pointerEvents:"none",borderLeft:`${this.addUnits(this.options.lineWidth)} solid ${e}`,opacity:"0",transition:"opacity .1s ease-in"}),Object.assign(this.label.style,{display:"block",backgroundColor:this.options.labelBackground,color:this.options.labelColor,fontSize:`${this.addUnits(this.options.labelSize)}`,transition:"transform .1s ease-in",padding:"2px 3px"});const s=this.wavesurfer.getWrapper();s.appendChild(this.wrapper),s.addEventListener("pointermove",this.onPointerMove),s.addEventListener("pointerleave",this.onPointerLeave),s.addEventListener("wheel",this.onPointerMove),this.unsubscribe=()=>{s.removeEventListener("pointermove",this.onPointerMove),s.removeEventListener("pointerleave",this.onPointerLeave),s.removeEventListener("wheel",this.onPointerMove)}}destroy(){super.destroy(),this.unsubscribe(),this.wrapper.remove()}}module.exports=o;
|
package/dist/plugins/hover.d.ts
CHANGED
|
@@ -3,16 +3,35 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import BasePlugin, { type BasePluginEvents } from '../base-plugin.js';
|
|
5
5
|
export type HoverPluginOptions = {
|
|
6
|
+
/** The hover cursor color (playback cursor and progress mask colors used as falllback in this order)
|
|
7
|
+
*/
|
|
6
8
|
lineColor?: string;
|
|
9
|
+
/**
|
|
10
|
+
* The hover cursor width (pixels used if no units specified)
|
|
11
|
+
* @default 1
|
|
12
|
+
*/
|
|
7
13
|
lineWidth?: string | number;
|
|
14
|
+
/** The color of the label text */
|
|
8
15
|
labelColor?: string;
|
|
16
|
+
/**
|
|
17
|
+
* The font size of the label text (pixels used if no units specified)
|
|
18
|
+
* @default 11
|
|
19
|
+
*/
|
|
9
20
|
labelSize?: string | number;
|
|
21
|
+
/** The background color of the label */
|
|
10
22
|
labelBackground?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Whether to display the label to the left of the cursor if possible
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
labelPreferLeft?: boolean;
|
|
28
|
+
/** Custom function to customize the displayed label text (m:ss used if not specified) */
|
|
11
29
|
formatTimeCallback?: (seconds: number) => string;
|
|
12
30
|
};
|
|
13
31
|
declare const defaultOptions: {
|
|
14
32
|
lineWidth: number;
|
|
15
33
|
labelSize: number;
|
|
34
|
+
labelPreferLeft: boolean;
|
|
16
35
|
formatTimeCallback(seconds: number): string;
|
|
17
36
|
};
|
|
18
37
|
export type HoverPluginEvents = BasePluginEvents & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class t{constructor(){this.listeners={}}on(t,e,s){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),null==s?void 0:s.once){const s=()=>{this.un(t,s),this.un(t,e)};return this.on(t,s),s}return()=>this.un(t,e)}un(t,e){var s;null===(s=this.listeners[t])||void 0===s||s.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}class e extends t{constructor(t){super(),this.subscriptions=[],this.options=t}onInit(){}_init(t){this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t()))}}function s(t,e){const i=e.xmlns?document.createElementNS(e.xmlns,t):document.createElement(t);for(const[t,n]of Object.entries(e))if("children"===t&&n)for(const[t,e]of Object.entries(n))e instanceof Node?i.appendChild(e):"string"==typeof e?i.appendChild(document.createTextNode(e)):i.appendChild(s(t,e));else"style"===t?Object.assign(i.style,n):"textContent"===t?i.textContent=n:i.setAttribute(t,n.toString());return i}function i(t,e,i){const n=s(t,e||{});return null==i||i.appendChild(n),n}const n={lineWidth:1,labelSize:11,formatTimeCallback:t=>`${Math.floor(t/60)}:${`0${Math.floor(t)%60}`.slice(-2)}`};class o extends e{constructor(t){super(t||{}),this.unsubscribe=()=>{},this.onPointerMove=t=>{if(!this.wavesurfer)return;const e=this.wavesurfer.getWrapper().getBoundingClientRect(),{width:s}=e,i=t.clientX-e.left,n=Math.min(1,Math.max(0,i/s)),o=Math.min(s-this.options.lineWidth-1,i);this.wrapper.style.transform=`translateX(${o}px)`,this.wrapper.style.opacity="1";const r=this.wavesurfer.getDuration()||0;this.label.textContent=this.options.formatTimeCallback(r*n);const a=this.label.offsetWidth;this.label.style.transform=
|
|
1
|
+
class t{constructor(){this.listeners={}}on(t,e,s){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),null==s?void 0:s.once){const s=()=>{this.un(t,s),this.un(t,e)};return this.on(t,s),s}return()=>this.un(t,e)}un(t,e){var s;null===(s=this.listeners[t])||void 0===s||s.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}class e extends t{constructor(t){super(),this.subscriptions=[],this.options=t}onInit(){}_init(t){this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t()))}}function s(t,e){const i=e.xmlns?document.createElementNS(e.xmlns,t):document.createElement(t);for(const[t,n]of Object.entries(e))if("children"===t&&n)for(const[t,e]of Object.entries(n))e instanceof Node?i.appendChild(e):"string"==typeof e?i.appendChild(document.createTextNode(e)):i.appendChild(s(t,e));else"style"===t?Object.assign(i.style,n):"textContent"===t?i.textContent=n:i.setAttribute(t,n.toString());return i}function i(t,e,i){const n=s(t,e||{});return null==i||i.appendChild(n),n}const n={lineWidth:1,labelSize:11,labelPreferLeft:!1,formatTimeCallback:t=>`${Math.floor(t/60)}:${`0${Math.floor(t)%60}`.slice(-2)}`};class o extends e{constructor(t){super(t||{}),this.unsubscribe=()=>{},this.onPointerMove=t=>{if(!this.wavesurfer)return;const e=this.wavesurfer.getWrapper().getBoundingClientRect(),{width:s}=e,i=t.clientX-e.left,n=Math.min(1,Math.max(0,i/s)),o=Math.min(s-this.options.lineWidth-1,i);this.wrapper.style.transform=`translateX(${o}px)`,this.wrapper.style.opacity="1";const r=this.wavesurfer.getDuration()||0;this.label.textContent=this.options.formatTimeCallback(r*n);const a=this.label.offsetWidth,l=this.options.labelPreferLeft?o-a>0:o+a>s;this.label.style.transform=l?`translateX(-${a+this.options.lineWidth}px)`:"",this.emit("hover",n)},this.onPointerLeave=()=>{this.wrapper.style.opacity="0"},this.options=Object.assign({},n,t),this.wrapper=i("div",{part:"hover"}),this.label=i("span",{part:"hover-label"},this.wrapper)}static create(t){return new o(t)}addUnits(t){return`${t}${"number"==typeof t?"px":""}`}onInit(){if(!this.wavesurfer)throw Error("WaveSurfer is not initialized");const t=this.wavesurfer.options,e=this.options.lineColor||t.cursorColor||t.progressColor;Object.assign(this.wrapper.style,{position:"absolute",zIndex:10,left:0,top:0,height:"100%",pointerEvents:"none",borderLeft:`${this.addUnits(this.options.lineWidth)} solid ${e}`,opacity:"0",transition:"opacity .1s ease-in"}),Object.assign(this.label.style,{display:"block",backgroundColor:this.options.labelBackground,color:this.options.labelColor,fontSize:`${this.addUnits(this.options.labelSize)}`,transition:"transform .1s ease-in",padding:"2px 3px"});const s=this.wavesurfer.getWrapper();s.appendChild(this.wrapper),s.addEventListener("pointermove",this.onPointerMove),s.addEventListener("pointerleave",this.onPointerLeave),s.addEventListener("wheel",this.onPointerMove),this.unsubscribe=()=>{s.removeEventListener("pointermove",this.onPointerMove),s.removeEventListener("pointerleave",this.onPointerLeave),s.removeEventListener("wheel",this.onPointerMove)}}destroy(){super.destroy(),this.unsubscribe(),this.wrapper.remove()}}export{o as default};
|
package/dist/plugins/hover.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class t{constructor(){this.listeners={}}on(t,e,s){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),null==s?void 0:s.once){const s=()=>{this.un(t,s),this.un(t,e)};return this.on(t,s),s}return()=>this.un(t,e)}un(t,e){var s;null===(s=this.listeners[t])||void 0===s||s.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}class e extends t{constructor(t){super(),this.subscriptions=[],this.options=t}onInit(){}_init(t){this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t()))}}function s(t,e){const i=e.xmlns?document.createElementNS(e.xmlns,t):document.createElement(t);for(const[t,n]of Object.entries(e))if("children"===t&&n)for(const[t,e]of Object.entries(n))e instanceof Node?i.appendChild(e):"string"==typeof e?i.appendChild(document.createTextNode(e)):i.appendChild(s(t,e));else"style"===t?Object.assign(i.style,n):"textContent"===t?i.textContent=n:i.setAttribute(t,n.toString());return i}function i(t,e,i){const n=s(t,e||{});return null==i||i.appendChild(n),n}const n={lineWidth:1,labelSize:11,formatTimeCallback:t=>`${Math.floor(t/60)}:${`0${Math.floor(t)%60}`.slice(-2)}`};class o extends e{constructor(t){super(t||{}),this.unsubscribe=()=>{},this.onPointerMove=t=>{if(!this.wavesurfer)return;const e=this.wavesurfer.getWrapper().getBoundingClientRect(),{width:s}=e,i=t.clientX-e.left,n=Math.min(1,Math.max(0,i/s)),o=Math.min(s-this.options.lineWidth-1,i);this.wrapper.style.transform=`translateX(${o}px)`,this.wrapper.style.opacity="1";const r=this.wavesurfer.getDuration()||0;this.label.textContent=this.options.formatTimeCallback(r*n);const a=this.label.offsetWidth;this.label.style.transform=
|
|
1
|
+
class t{constructor(){this.listeners={}}on(t,e,s){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),null==s?void 0:s.once){const s=()=>{this.un(t,s),this.un(t,e)};return this.on(t,s),s}return()=>this.un(t,e)}un(t,e){var s;null===(s=this.listeners[t])||void 0===s||s.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}class e extends t{constructor(t){super(),this.subscriptions=[],this.options=t}onInit(){}_init(t){this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t()))}}function s(t,e){const i=e.xmlns?document.createElementNS(e.xmlns,t):document.createElement(t);for(const[t,n]of Object.entries(e))if("children"===t&&n)for(const[t,e]of Object.entries(n))e instanceof Node?i.appendChild(e):"string"==typeof e?i.appendChild(document.createTextNode(e)):i.appendChild(s(t,e));else"style"===t?Object.assign(i.style,n):"textContent"===t?i.textContent=n:i.setAttribute(t,n.toString());return i}function i(t,e,i){const n=s(t,e||{});return null==i||i.appendChild(n),n}const n={lineWidth:1,labelSize:11,labelPreferLeft:!1,formatTimeCallback:t=>`${Math.floor(t/60)}:${`0${Math.floor(t)%60}`.slice(-2)}`};class o extends e{constructor(t){super(t||{}),this.unsubscribe=()=>{},this.onPointerMove=t=>{if(!this.wavesurfer)return;const e=this.wavesurfer.getWrapper().getBoundingClientRect(),{width:s}=e,i=t.clientX-e.left,n=Math.min(1,Math.max(0,i/s)),o=Math.min(s-this.options.lineWidth-1,i);this.wrapper.style.transform=`translateX(${o}px)`,this.wrapper.style.opacity="1";const r=this.wavesurfer.getDuration()||0;this.label.textContent=this.options.formatTimeCallback(r*n);const a=this.label.offsetWidth,l=this.options.labelPreferLeft?o-a>0:o+a>s;this.label.style.transform=l?`translateX(-${a+this.options.lineWidth}px)`:"",this.emit("hover",n)},this.onPointerLeave=()=>{this.wrapper.style.opacity="0"},this.options=Object.assign({},n,t),this.wrapper=i("div",{part:"hover"}),this.label=i("span",{part:"hover-label"},this.wrapper)}static create(t){return new o(t)}addUnits(t){return`${t}${"number"==typeof t?"px":""}`}onInit(){if(!this.wavesurfer)throw Error("WaveSurfer is not initialized");const t=this.wavesurfer.options,e=this.options.lineColor||t.cursorColor||t.progressColor;Object.assign(this.wrapper.style,{position:"absolute",zIndex:10,left:0,top:0,height:"100%",pointerEvents:"none",borderLeft:`${this.addUnits(this.options.lineWidth)} solid ${e}`,opacity:"0",transition:"opacity .1s ease-in"}),Object.assign(this.label.style,{display:"block",backgroundColor:this.options.labelBackground,color:this.options.labelColor,fontSize:`${this.addUnits(this.options.labelSize)}`,transition:"transform .1s ease-in",padding:"2px 3px"});const s=this.wavesurfer.getWrapper();s.appendChild(this.wrapper),s.addEventListener("pointermove",this.onPointerMove),s.addEventListener("pointerleave",this.onPointerLeave),s.addEventListener("wheel",this.onPointerMove),this.unsubscribe=()=>{s.removeEventListener("pointermove",this.onPointerMove),s.removeEventListener("pointerleave",this.onPointerLeave),s.removeEventListener("wheel",this.onPointerMove)}}destroy(){super.destroy(),this.unsubscribe(),this.wrapper.remove()}}export{o as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):((e="undefined"!=typeof globalThis?globalThis:e||self).WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.Hover=t())}(this,(function(){"use strict";class e{constructor(){this.listeners={}}on(e,t,s){if(this.listeners[e]||(this.listeners[e]=new Set),this.listeners[e].add(t),null==s?void 0:s.once){const s=()=>{this.un(e,s),this.un(e,t)};return this.on(e,s),s}return()=>this.un(e,t)}un(e,t){var s;null===(s=this.listeners[e])||void 0===s||s.delete(t)}once(e,t){return this.on(e,t,{once:!0})}unAll(){this.listeners={}}emit(e,...t){this.listeners[e]&&this.listeners[e].forEach((e=>e(...t)))}}class t extends e{constructor(e){super(),this.subscriptions=[],this.options=e}onInit(){}_init(e){this.wavesurfer=e,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((e=>e()))}}function s(e,t){const i=t.xmlns?document.createElementNS(t.xmlns,e):document.createElement(e);for(const[e,n]of Object.entries(t))if("children"===e&&n)for(const[e,t]of Object.entries(n))t instanceof Node?i.appendChild(t):"string"==typeof t?i.appendChild(document.createTextNode(t)):i.appendChild(s(e,t));else"style"===e?Object.assign(i.style,n):"textContent"===e?i.textContent=n:i.setAttribute(e,n.toString());return i}function i(e,t,i){const n=s(e,t||{});return null==i||i.appendChild(n),n}const n={lineWidth:1,labelSize:11,formatTimeCallback:e=>`${Math.floor(e/60)}:${`0${Math.floor(e)%60}`.slice(-2)}`};class o extends t{constructor(e){super(e||{}),this.unsubscribe=()=>{},this.onPointerMove=e=>{if(!this.wavesurfer)return;const t=this.wavesurfer.getWrapper().getBoundingClientRect(),{width:s}=t,i=e.clientX-t.left,n=Math.min(1,Math.max(0,i/s)),o=Math.min(s-this.options.lineWidth-1,i);this.wrapper.style.transform=`translateX(${o}px)`,this.wrapper.style.opacity="1";const r=this.wavesurfer.getDuration()||0;this.label.textContent=this.options.formatTimeCallback(r*n);const a=this.label.offsetWidth;this.label.style.transform=
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):((e="undefined"!=typeof globalThis?globalThis:e||self).WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.Hover=t())}(this,(function(){"use strict";class e{constructor(){this.listeners={}}on(e,t,s){if(this.listeners[e]||(this.listeners[e]=new Set),this.listeners[e].add(t),null==s?void 0:s.once){const s=()=>{this.un(e,s),this.un(e,t)};return this.on(e,s),s}return()=>this.un(e,t)}un(e,t){var s;null===(s=this.listeners[e])||void 0===s||s.delete(t)}once(e,t){return this.on(e,t,{once:!0})}unAll(){this.listeners={}}emit(e,...t){this.listeners[e]&&this.listeners[e].forEach((e=>e(...t)))}}class t extends e{constructor(e){super(),this.subscriptions=[],this.options=e}onInit(){}_init(e){this.wavesurfer=e,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((e=>e()))}}function s(e,t){const i=t.xmlns?document.createElementNS(t.xmlns,e):document.createElement(e);for(const[e,n]of Object.entries(t))if("children"===e&&n)for(const[e,t]of Object.entries(n))t instanceof Node?i.appendChild(t):"string"==typeof t?i.appendChild(document.createTextNode(t)):i.appendChild(s(e,t));else"style"===e?Object.assign(i.style,n):"textContent"===e?i.textContent=n:i.setAttribute(e,n.toString());return i}function i(e,t,i){const n=s(e,t||{});return null==i||i.appendChild(n),n}const n={lineWidth:1,labelSize:11,labelPreferLeft:!1,formatTimeCallback:e=>`${Math.floor(e/60)}:${`0${Math.floor(e)%60}`.slice(-2)}`};class o extends t{constructor(e){super(e||{}),this.unsubscribe=()=>{},this.onPointerMove=e=>{if(!this.wavesurfer)return;const t=this.wavesurfer.getWrapper().getBoundingClientRect(),{width:s}=t,i=e.clientX-t.left,n=Math.min(1,Math.max(0,i/s)),o=Math.min(s-this.options.lineWidth-1,i);this.wrapper.style.transform=`translateX(${o}px)`,this.wrapper.style.opacity="1";const r=this.wavesurfer.getDuration()||0;this.label.textContent=this.options.formatTimeCallback(r*n);const a=this.label.offsetWidth,l=this.options.labelPreferLeft?o-a>0:o+a>s;this.label.style.transform=l?`translateX(-${a+this.options.lineWidth}px)`:"",this.emit("hover",n)},this.onPointerLeave=()=>{this.wrapper.style.opacity="0"},this.options=Object.assign({},n,e),this.wrapper=i("div",{part:"hover"}),this.label=i("span",{part:"hover-label"},this.wrapper)}static create(e){return new o(e)}addUnits(e){return`${e}${"number"==typeof e?"px":""}`}onInit(){if(!this.wavesurfer)throw Error("WaveSurfer is not initialized");const e=this.wavesurfer.options,t=this.options.lineColor||e.cursorColor||e.progressColor;Object.assign(this.wrapper.style,{position:"absolute",zIndex:10,left:0,top:0,height:"100%",pointerEvents:"none",borderLeft:`${this.addUnits(this.options.lineWidth)} solid ${t}`,opacity:"0",transition:"opacity .1s ease-in"}),Object.assign(this.label.style,{display:"block",backgroundColor:this.options.labelBackground,color:this.options.labelColor,fontSize:`${this.addUnits(this.options.labelSize)}`,transition:"transform .1s ease-in",padding:"2px 3px"});const s=this.wavesurfer.getWrapper();s.appendChild(this.wrapper),s.addEventListener("pointermove",this.onPointerMove),s.addEventListener("pointerleave",this.onPointerLeave),s.addEventListener("wheel",this.onPointerMove),this.unsubscribe=()=>{s.removeEventListener("pointermove",this.onPointerMove),s.removeEventListener("pointerleave",this.onPointerLeave),s.removeEventListener("wheel",this.onPointerMove)}}destroy(){super.destroy(),this.unsubscribe(),this.wrapper.remove()}}return o}));
|