@checksub_team/peaks_timeline 2.2.0-alpha.0 → 2.2.0-alpha.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checksub_team/peaks_timeline",
3
- "version": "2.2.0-alpha.0",
3
+ "version": "2.2.0-alpha.2",
4
4
  "description": "JavaScript UI component for displaying audio waveforms",
5
5
  "main": "./peaks.js",
6
6
  "types": "./peaks.js.d.ts",
package/peaks.js CHANGED
@@ -16326,6 +16326,9 @@ module.exports = function (SourceGroup, Source, Utils, Konva) {
16326
16326
  }
16327
16327
  };
16328
16328
  ModeLayer.prototype._onKeyboardDelete = function () {
16329
+ if (!this._view.isFocusedByClick()) {
16330
+ return;
16331
+ }
16329
16332
  const selectedElements = Object.values(this._selectedElements);
16330
16333
  if (selectedElements.length === 1) {
16331
16334
  var selectedElement = selectedElements[0];
@@ -19828,21 +19831,16 @@ module.exports = function (Utils, Konva) {
19828
19831
  WaveformShape.prototype._sceneFunc = function (context) {
19829
19832
  var width = this._view.getWidth();
19830
19833
  var waveformData = this._layer.getLoadedData(this._url).data;
19831
- var targetSpeed = this._source.targetSpeed || 1;
19832
- var startPixel = 0, startOffset = 0;
19834
+ var startPixel = 0, startOffset = 0, endPixel = width, targetSpeed = 1;
19833
19835
  if (this._source) {
19834
- startPixel = this._view.timeToPixels(this._source.mediaStartTime) + Math.max(this._view.getFrameOffset() - this._view.timeToPixels(this._source.startTime), 0);
19836
+ targetSpeed = this._source.targetSpeed || 1;
19837
+ startPixel = Math.floor((this._view.timeToPixels(this._source.mediaStartTime) + Math.max(this._view.getFrameOffset() - this._view.timeToPixels(this._source.startTime), 0)) * targetSpeed);
19835
19838
  startOffset = this._view.timeToPixels(this._source.mediaStartTime);
19839
+ endPixel = Math.min(Math.ceil((this._view.timeToPixels(this._source.mediaEndTime) - Math.max(this._view.timeToPixels(this._source.endTime) - this._view.getFrameOffset() - this._view.getWidth(), 0)) * targetSpeed), waveformData.length);
19836
19840
  }
19837
- var endPixel = width;
19838
- if (this._source) {
19839
- var effectiveMediaDuration = (this._source.endTime - this._source.startTime) * targetSpeed;
19840
- var effectiveMediaEndTime = Math.min(this._source.mediaStartTime + effectiveMediaDuration, this._source.duration || Infinity);
19841
- endPixel = Math.min(this._view.timeToPixels(effectiveMediaEndTime) - Math.max(this._view.timeToPixels(this._source.endTime) - this._view.getFrameOffset() - this._view.getWidth(), 0), waveformData.length);
19842
- }
19843
- this._drawWaveform(context, waveformData, startPixel, startOffset, endPixel, this._height);
19841
+ this._drawWaveform(context, waveformData, startPixel, startOffset, endPixel, targetSpeed, this._height);
19844
19842
  };
19845
- WaveformShape.prototype._drawWaveform = function (context, waveformData, startPixel, startOffset, endPixel, height) {
19843
+ WaveformShape.prototype._drawWaveform = function (context, waveformData, startPixel, startOffset, endPixel, targetSpeed, height) {
19846
19844
  var channels = waveformData.channels;
19847
19845
  var waveformTop = 0;
19848
19846
  var waveformHeight = Math.floor(height / channels);
@@ -19850,24 +19848,21 @@ module.exports = function (Utils, Konva) {
19850
19848
  if (i === channels - 1) {
19851
19849
  waveformHeight = height - (channels - 1) * waveformHeight;
19852
19850
  }
19853
- this._drawChannel(context, waveformData.channel(i), startPixel, startOffset, endPixel, waveformTop, waveformHeight);
19851
+ this._drawChannel(context, waveformData.channel(i), startPixel, startOffset, endPixel, waveformTop, waveformHeight, targetSpeed);
19854
19852
  waveformTop += waveformHeight;
19855
19853
  }
19856
19854
  };
19857
- WaveformShape.prototype._drawChannel = function (context, channel, startPixel, startOffset, endPixel, top, height) {
19858
- var x, val, displayX;
19855
+ WaveformShape.prototype._drawChannel = function (context, channel, startPixel, startOffset, endPixel, top, height, targetSpeed) {
19856
+ var x, val;
19859
19857
  var amplitudeScale = this._view.getAmplitudeScale();
19860
- var targetSpeed = this._source && this._source.targetSpeed ? this._source.targetSpeed : 1;
19861
19858
  context.beginPath();
19862
- for (x = Math.floor(startPixel); x < Math.ceil(endPixel); x++) {
19859
+ for (x = startPixel; x < endPixel; x++) {
19863
19860
  val = channel.min_sample(x);
19864
- displayX = (x - startPixel) / targetSpeed + startPixel;
19865
- context.lineTo(displayX - startOffset + 0.5, top + scaleY(val, height, amplitudeScale) + 0.5);
19861
+ context.lineTo(x / targetSpeed - startOffset + 0.5, top + scaleY(val, height, amplitudeScale) + 0.5);
19866
19862
  }
19867
- for (x = Math.ceil(endPixel) - 1; x >= Math.floor(startPixel); x--) {
19863
+ for (x = endPixel - 1; x >= startPixel; x--) {
19868
19864
  val = channel.max_sample(x);
19869
- displayX = (x - startPixel) / targetSpeed + startPixel;
19870
- context.lineTo(displayX - startOffset + 0.5, top + scaleY(val, height, amplitudeScale) + 0.5);
19865
+ context.lineTo(x / targetSpeed - startOffset + 0.5, top + scaleY(val, height, amplitudeScale) + 0.5);
19871
19866
  }
19872
19867
  context.closePath();
19873
19868
  context.fillShape(this);
@@ -22401,7 +22396,8 @@ module.exports = function (MouseDragHandler, PlayheadLayer, SourcesLayer, ModeLa
22401
22396
  self._timelineLength = 0;
22402
22397
  self._timeToPixelsScale = self._options.initialZoomLevel;
22403
22398
  self._timeToPixelsMinScale = self._options.minScale;
22404
- self._isFocused = false;
22399
+ self._focusedByHover = false;
22400
+ self._focusedByClick = false;
22405
22401
  self._isClickable = true;
22406
22402
  self._width = container.clientWidth;
22407
22403
  self._height = container.clientHeight || self._options.height;
@@ -22477,13 +22473,13 @@ module.exports = function (MouseDragHandler, PlayheadLayer, SourcesLayer, ModeLa
22477
22473
  }
22478
22474
  });
22479
22475
  this._stage.on('mouseover', function () {
22480
- self._isFocused = true;
22476
+ self._focusedByHover = true;
22481
22477
  });
22482
22478
  this._stage.on('mouseout', function () {
22483
- self._isFocused = false;
22479
+ self._focusedByHover = false;
22484
22480
  });
22485
22481
  this._stage.on('click', function (event) {
22486
- self._isFocused = true;
22482
+ self._focusedByClick = true;
22487
22483
  if (!self._isClickable) {
22488
22484
  return;
22489
22485
  }
@@ -22539,11 +22535,18 @@ module.exports = function (MouseDragHandler, PlayheadLayer, SourcesLayer, ModeLa
22539
22535
  window.addEventListener('mouseup', this._mouseUp.bind(this), false);
22540
22536
  window.addEventListener('touchend', this._mouseUp.bind(this), false);
22541
22537
  window.addEventListener('blur', this._mouseUp.bind(this), false);
22538
+ this._onWindowClick = this._onWindowClick.bind(this);
22539
+ window.addEventListener('click', this._onWindowClick, false);
22542
22540
  }
22543
22541
  View.prototype._mouseUp = function () {
22544
22542
  this.clearScrollingInterval();
22545
22543
  this._peaks.emit('handler.view.mouseup');
22546
22544
  };
22545
+ View.prototype._onWindowClick = function (event) {
22546
+ if (!this._container.contains(event.target)) {
22547
+ this._focusedByClick = false;
22548
+ }
22549
+ };
22547
22550
  View.prototype.setClickable = function (clickable) {
22548
22551
  this._isClickable = clickable;
22549
22552
  };
@@ -22628,8 +22631,14 @@ module.exports = function (MouseDragHandler, PlayheadLayer, SourcesLayer, ModeLa
22628
22631
  View.prototype.isListening = function () {
22629
22632
  return this._stage.listening();
22630
22633
  };
22634
+ View.prototype.isFocusedByHover = function () {
22635
+ return this._focusedByHover;
22636
+ };
22637
+ View.prototype.isFocusedByClick = function () {
22638
+ return this._focusedByClick;
22639
+ };
22631
22640
  View.prototype.isFocused = function () {
22632
- return this._isFocused;
22641
+ return this._focusedByHover || this._focusedByClick;
22633
22642
  };
22634
22643
  View.prototype.batchDrawSourcesLayer = function () {
22635
22644
  this._sourcesLayer.batchDraw();
@@ -22929,6 +22938,7 @@ module.exports = function (MouseDragHandler, PlayheadLayer, SourcesLayer, ModeLa
22929
22938
  this._peaks.off('handler.keyboard.shiftright', this._onKeyboardShiftRight);
22930
22939
  this._peaks.off('handler.view.defaultmode', this._onDefaultMode);
22931
22940
  this._peaks.off('handler.view.cutmode', this._onCutMode);
22941
+ window.removeEventListener('click', this._onWindowClick, false);
22932
22942
  if (this._stage) {
22933
22943
  this._stage.destroy();
22934
22944
  this._stage = null;
@@ -234,6 +234,10 @@ define([
234
234
  };
235
235
 
236
236
  ModeLayer.prototype._onKeyboardDelete = function() {
237
+ if (!this._view.isFocusedByClick()) {
238
+ return;
239
+ }
240
+
237
241
  const selectedElements = Object.values(this._selectedElements);
238
242
 
239
243
  // We allow deletion if there is ONLY 1 element selected
@@ -72,36 +72,29 @@ define(['../utils', 'konva'], function(Utils, Konva) {
72
72
  WaveformShape.prototype._sceneFunc = function(context) {
73
73
  var width = this._view.getWidth();
74
74
  var waveformData = this._layer.getLoadedData(this._url).data;
75
- var targetSpeed = this._source.targetSpeed || 1.0;
76
75
 
77
- var startPixel = 0, startOffset = 0;
76
+ var startPixel = 0, startOffset = 0, endPixel = width, targetSpeed = 1.0;
78
77
 
79
78
  if (this._source) {
80
- startPixel = this._view.timeToPixels(this._source.mediaStartTime) + Math.max(
81
- this._view.getFrameOffset() - this._view.timeToPixels(this._source.startTime),
82
- 0
79
+ targetSpeed = this._source.targetSpeed || 1.0;
80
+
81
+ startPixel = Math.floor(
82
+ (this._view.timeToPixels(this._source.mediaStartTime) + Math.max(
83
+ this._view.getFrameOffset() - this._view.timeToPixels(this._source.startTime),
84
+ 0
85
+ )) * targetSpeed
83
86
  );
84
87
 
85
88
  startOffset = this._view.timeToPixels(this._source.mediaStartTime);
86
- }
87
-
88
- var endPixel = width;
89
-
90
- if (this._source) {
91
- // Calculate the effective media end time based on targetSpeed
92
- // If speed is 2.0, we can fit 2x more audio in the same visual space
93
- var effectiveMediaDuration = (this._source.endTime - this._source.startTime) * targetSpeed;
94
- var effectiveMediaEndTime = Math.min(
95
- this._source.mediaStartTime + effectiveMediaDuration,
96
- this._source.duration || Infinity
97
- );
98
89
 
99
90
  endPixel = Math.min(
100
- this._view.timeToPixels(effectiveMediaEndTime) - Math.max(
101
- this._view.timeToPixels(this._source.endTime)
102
- - this._view.getFrameOffset()
103
- - this._view.getWidth(),
104
- 0
91
+ Math.ceil(
92
+ (this._view.timeToPixels(this._source.mediaEndTime) - Math.max(
93
+ this._view.timeToPixels(this._source.endTime)
94
+ - this._view.getFrameOffset()
95
+ - this._view.getWidth(),
96
+ 0
97
+ )) * targetSpeed
105
98
  ),
106
99
  waveformData.length
107
100
  );
@@ -113,6 +106,7 @@ define(['../utils', 'konva'], function(Utils, Konva) {
113
106
  startPixel,
114
107
  startOffset,
115
108
  endPixel,
109
+ targetSpeed,
116
110
  this._height
117
111
  );
118
112
  };
@@ -133,7 +127,7 @@ define(['../utils', 'konva'], function(Utils, Konva) {
133
127
  */
134
128
 
135
129
  WaveformShape.prototype._drawWaveform = function(context, waveformData,
136
- startPixel, startOffset, endPixel, height) {
130
+ startPixel, startOffset, endPixel, targetSpeed, height) {
137
131
  var channels = waveformData.channels;
138
132
 
139
133
  var waveformTop = 0;
@@ -151,7 +145,8 @@ define(['../utils', 'konva'], function(Utils, Konva) {
151
145
  startOffset,
152
146
  endPixel,
153
147
  waveformTop,
154
- waveformHeight
148
+ waveformHeight,
149
+ targetSpeed
155
150
  );
156
151
 
157
152
  waveformTop += waveformHeight;
@@ -159,31 +154,23 @@ define(['../utils', 'konva'], function(Utils, Konva) {
159
154
  };
160
155
 
161
156
  WaveformShape.prototype._drawChannel = function(context, channel,
162
- startPixel, startOffset, endPixel, top, height) {
163
- var x, val, displayX;
157
+ startPixel, startOffset, endPixel, top, height, targetSpeed) {
158
+ var x, val;
164
159
 
165
160
  var amplitudeScale = this._view.getAmplitudeScale();
166
- var targetSpeed = this._source && this._source.targetSpeed ? this._source.targetSpeed : 1.0;
167
161
 
168
162
  context.beginPath();
169
163
 
170
- for (x = Math.floor(startPixel); x < Math.ceil(endPixel); x++) {
164
+ for (x = startPixel; x < endPixel; x++) {
171
165
  val = channel.min_sample(x);
172
166
 
173
- // Scale the x position by dividing by targetSpeed to compress/expand the waveform
174
- // targetSpeed = 2.0 means the waveform is drawn at half width (compressed)
175
- // targetSpeed = 0.5 means the waveform is drawn at double width (expanded)
176
- displayX = (x - startPixel) / targetSpeed + startPixel;
177
-
178
- context.lineTo(displayX - startOffset + 0.5, top + scaleY(val, height, amplitudeScale) + 0.5);
167
+ context.lineTo(x / targetSpeed - startOffset + 0.5, top + scaleY(val, height, amplitudeScale) + 0.5);
179
168
  }
180
169
 
181
- for (x = Math.ceil(endPixel) - 1; x >= Math.floor(startPixel); x--) {
170
+ for (x = endPixel - 1; x >= startPixel; x--) {
182
171
  val = channel.max_sample(x);
183
172
 
184
- displayX = (x - startPixel) / targetSpeed + startPixel;
185
-
186
- context.lineTo(displayX - startOffset + 0.5, top + scaleY(val, height, amplitudeScale) + 0.5);
173
+ context.lineTo(x / targetSpeed - startOffset + 0.5, top + scaleY(val, height, amplitudeScale) + 0.5);
187
174
  }
188
175
 
189
176
  context.closePath();
package/src/view.js CHANGED
@@ -79,7 +79,8 @@ define([
79
79
  self._timeToPixelsScale = self._options.initialZoomLevel;
80
80
  self._timeToPixelsMinScale = self._options.minScale;
81
81
 
82
- self._isFocused = false;
82
+ self._focusedByHover = false;
83
+ self._focusedByClick = false; // Track if focus was set by click
83
84
  self._isClickable = true;
84
85
 
85
86
  self._width = container.clientWidth;
@@ -205,15 +206,15 @@ define([
205
206
  });
206
207
 
207
208
  this._stage.on('mouseover', function() {
208
- self._isFocused = true;
209
+ self._focusedByHover = true;
209
210
  });
210
211
 
211
212
  this._stage.on('mouseout', function() {
212
- self._isFocused = false;
213
+ self._focusedByHover = false;
213
214
  });
214
215
 
215
216
  this._stage.on('click', function(event) {
216
- self._isFocused = true;
217
+ self._focusedByClick = true;
217
218
 
218
219
  if (!self._isClickable) {
219
220
  return;
@@ -307,6 +308,10 @@ define([
307
308
  window.addEventListener('mouseup', this._mouseUp.bind(this), false);
308
309
  window.addEventListener('touchend', this._mouseUp.bind(this), false);
309
310
  window.addEventListener('blur', this._mouseUp.bind(this), false);
311
+
312
+ // Handle clicks outside the timeline to remove focus
313
+ this._onWindowClick = this._onWindowClick.bind(this);
314
+ window.addEventListener('click', this._onWindowClick, false);
310
315
  }
311
316
 
312
317
  View.prototype._mouseUp = function() {
@@ -314,6 +319,12 @@ define([
314
319
  this._peaks.emit('handler.view.mouseup');
315
320
  };
316
321
 
322
+ View.prototype._onWindowClick = function(event) {
323
+ if (!this._container.contains(event.target)) {
324
+ this._focusedByClick = false;
325
+ }
326
+ };
327
+
317
328
  View.prototype.setClickable = function(clickable) {
318
329
  this._isClickable = clickable;
319
330
  };
@@ -430,8 +441,16 @@ define([
430
441
  return this._stage.listening();
431
442
  };
432
443
 
444
+ View.prototype.isFocusedByHover = function() {
445
+ return this._focusedByHover;
446
+ };
447
+
448
+ View.prototype.isFocusedByClick = function() {
449
+ return this._focusedByClick;
450
+ };
451
+
433
452
  View.prototype.isFocused = function() {
434
- return this._isFocused;
453
+ return this._focusedByHover || this._focusedByClick;
435
454
  };
436
455
 
437
456
  View.prototype.batchDrawSourcesLayer = function() {
@@ -900,6 +919,9 @@ define([
900
919
  this._peaks.off('handler.view.defaultmode', this._onDefaultMode);
901
920
  this._peaks.off('handler.view.cutmode', this._onCutMode);
902
921
 
922
+ // Remove window click listener
923
+ window.removeEventListener('click', this._onWindowClick, false);
924
+
903
925
  if (this._stage) {
904
926
  this._stage.destroy();
905
927
  this._stage = null;