@vidispine/vdt-videojs 21.3.0 → 22.1.0-pre.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.
Files changed (55) hide show
  1. package/README.md +4 -4
  2. package/deprecated-app/README.md +21 -0
  3. package/{demo.html → deprecated-app/index.html} +1 -1
  4. package/{demo.js → deprecated-app/index.js} +69 -41
  5. package/{samples → deprecated-app/samples}/birds-es.vvt +0 -0
  6. package/{samples → deprecated-app/samples}/birds.vvt +0 -0
  7. package/{tests.js → deprecated-app/tests.js} +87 -54
  8. package/{lib/style.css → dist/index.css} +755 -55
  9. package/dist/index.es.js +2099 -0
  10. package/dist/index.js +2112 -0
  11. package/dist/index.umd.js +2115 -0
  12. package/package.json +29 -85
  13. package/rollup.config.js +54 -0
  14. package/src/constants.js +1 -1
  15. package/src/externalControls.js +14 -18
  16. package/src/helpOverlay.js +12 -16
  17. package/src/helpers.js +3 -3
  18. package/src/index.js +3 -9
  19. package/src/index.stories.mdx +59 -0
  20. package/src/menu.api.stories.mdx +59 -0
  21. package/src/menu.js +23 -19
  22. package/src/{menu.example.md → menu.usage.stories.mdx} +31 -21
  23. package/src/osd.js +24 -18
  24. package/src/player.api.stories.mdx +120 -0
  25. package/src/player.js +157 -108
  26. package/src/player.scss +2 -0
  27. package/src/{player.example.md → player.usage.stories.mdx} +18 -8
  28. package/src/seekBar.js +85 -48
  29. package/src/timeCodeDisplay.js +39 -31
  30. package/src/videoTime.js +4 -4
  31. package/build.js +0 -233
  32. package/lib/index.cjs.js +0 -3240
  33. package/lib/index.esm.js +0 -3227
  34. package/lib/index.umd.js +0 -3243
  35. package/lib/package.json +0 -13
  36. package/lib/src/constants.js +0 -51
  37. package/lib/src/externalControls.js +0 -307
  38. package/lib/src/helpOverlay.js +0 -106
  39. package/lib/src/helpers.js +0 -34
  40. package/lib/src/index.js +0 -13
  41. package/lib/src/menu.js +0 -365
  42. package/lib/src/osd.js +0 -91
  43. package/lib/src/player.js +0 -943
  44. package/lib/src/seekBar.js +0 -833
  45. package/lib/src/timeCodeDisplay.js +0 -253
  46. package/lib/src/videoTime.js +0 -66
  47. package/log.js +0 -24
  48. package/src/_index.stories.js +0 -24
  49. package/src/externalControls.stories.js +0 -6
  50. package/src/helpOverlay.stories.js +0 -6
  51. package/src/menu.classMethods.md +0 -47
  52. package/src/player.classMethods.md +0 -108
  53. package/src/player.stories.js +0 -14
  54. package/src/seekBar.stories.js +0 -8
  55. package/tmp/player.css +0 -1
package/src/seekBar.js CHANGED
@@ -5,8 +5,9 @@
5
5
  /* eslint-disable max-classes-per-file */
6
6
 
7
7
  import mousetrap from 'mousetrap';
8
- import { truncate, sanitize, reactiveSetters } from './helpers';
8
+
9
9
  import { classNames, colors } from './constants';
10
+ import { truncate, sanitize, reactiveSetters } from './helpers';
10
11
 
11
12
  const constants = Object.freeze({
12
13
  className: 'vdt-seekbar',
@@ -249,7 +250,7 @@ export default class SeekBar {
249
250
  this.state = {
250
251
  in: null, // in seconds from 0
251
252
  out: null,
252
- markersEnabled: (this.props.markersEnabled === undefined) ? true : this.props.markersEnabled,
253
+ markersEnabled: this.props.markersEnabled === undefined ? true : this.props.markersEnabled,
253
254
  regions: [], // array with regions providing {in: 0, out: 12} and possibly more
254
255
  dragging: false,
255
256
  };
@@ -264,8 +265,8 @@ export default class SeekBar {
264
265
  this.style.type = 'text/css';
265
266
 
266
267
  // colors from props
267
- const bgColor = (this.props.bgColor) ? this.props.bgColor : constants.defaults.bgColor;
268
- const fillColor = (this.props.fillColor) ? this.props.fillColor : constants.defaults.fillColor;
268
+ const bgColor = this.props.bgColor ? this.props.bgColor : constants.defaults.bgColor;
269
+ const fillColor = this.props.fillColor ? this.props.fillColor : constants.defaults.fillColor;
269
270
 
270
271
  this.style.innerHTML = CSS(sanitize(bgColor), sanitize(fillColor));
271
272
  this.shadow.appendChild(this.style);
@@ -294,7 +295,8 @@ export default class SeekBar {
294
295
  then could use requestAnimationFrame and
295
296
  get a smoother animation at more expense
296
297
  */
297
- bindEvents() { // bind to vdt player instance
298
+ bindEvents() {
299
+ // bind to vdt player instance
298
300
  if (this.props.player) {
299
301
  const { player } = this.props;
300
302
  player.videojs.on('timeupdate', () => {
@@ -370,9 +372,10 @@ export default class SeekBar {
370
372
  }
371
373
 
372
374
  unbindHotKeys() {
373
- this.bindings && this.bindings.forEach((binding) => {
374
- mousetrap.unbind(binding.key);
375
- });
375
+ this.bindings &&
376
+ this.bindings.forEach((binding) => {
377
+ mousetrap.unbind(binding.key);
378
+ });
376
379
  }
377
380
 
378
381
  handleSeek(event) {
@@ -389,7 +392,7 @@ export default class SeekBar {
389
392
  // callback for clicking on a region, if callback returns false, no seek happens
390
393
  // TODO - make a convention of returning true / false to break from seek
391
394
  if (this.props.onRegionClick) {
392
- preventSeek = (this.props.onRegionClick(region));
395
+ preventSeek = this.props.onRegionClick(region);
393
396
  if (!preventSeek) {
394
397
  player.seekTo(region.in);
395
398
  }
@@ -409,7 +412,8 @@ export default class SeekBar {
409
412
  if (clickedOnRegion) return;
410
413
  }
411
414
 
412
- const seekFractionX = (event.clientX - this.bar.getBoundingClientRect().left) / this.bar.offsetWidth;
415
+ const seekFractionX =
416
+ (event.clientX - this.bar.getBoundingClientRect().left) / this.bar.offsetWidth;
413
417
  // -> 0.34732
414
418
 
415
419
  const timeToSeek = seekFractionX * player.videojs.duration();
@@ -428,7 +432,8 @@ export default class SeekBar {
428
432
  left = e.clientX - barOffset;
429
433
  const pxDragged = Math.abs(mouseDownEvent.clientX - e.clientX);
430
434
 
431
- if (left >= 0 && left < barWidth && pxDragged > 1) { // prevent out-of-bounds
435
+ if (left >= 0 && left < barWidth && pxDragged > 1) {
436
+ // prevent out-of-bounds
432
437
  this.dragging = true;
433
438
  const fractionFromStart = parseFloat(left) / barWidth;
434
439
  const seconds = fractionFromStart * duration;
@@ -468,13 +473,18 @@ export default class SeekBar {
468
473
 
469
474
  // handle drag
470
475
 
471
- this.bar.addEventListener('mousedown', (e) => {
472
- e.preventDefault(); // prevents selection cursor
476
+ this.bar.addEventListener(
477
+ 'mousedown',
478
+ (e) => {
479
+ e.preventDefault(); // prevents selection cursor
473
480
 
474
- if (!this.dragging) { // don't attach listeners if something is already dragging
475
- this.handleSeekDrag(e);
476
- }
477
- }, false);
481
+ if (!this.dragging) {
482
+ // don't attach listeners if something is already dragging
483
+ this.handleSeekDrag(e);
484
+ }
485
+ },
486
+ false,
487
+ );
478
488
 
479
489
  this.fill = document.createElement('div');
480
490
  this.fill.className = 'fill';
@@ -493,10 +503,11 @@ export default class SeekBar {
493
503
  this.drawMarkers();
494
504
  }
495
505
 
496
- drawMarkers() { // TODO - add touch events
506
+ drawMarkers() {
507
+ // TODO - add touch events
497
508
  if (this.markersEnabled) {
498
- const markerIn = this.markers[constants.markerTypes.in] = document.createElement('div');
499
- const markerOut = this.markers[constants.markerTypes.out] = document.createElement('div');
509
+ const markerIn = (this.markers[constants.markerTypes.in] = document.createElement('div'));
510
+ const markerOut = (this.markers[constants.markerTypes.out] = document.createElement('div'));
500
511
  markerIn.className = `marker ${constants.markerTypes.in}`;
501
512
  markerOut.className = `marker ${constants.markerTypes.out}`;
502
513
 
@@ -504,19 +515,27 @@ export default class SeekBar {
504
515
  const handleOut = document.createElement('div');
505
516
  handleIn.className = handleOut.className = 'handle';
506
517
 
507
- handleIn.addEventListener('mousedown', (e) => {
508
- e.preventDefault(); // prevents selection cursor
509
- e.stopPropagation(); // prevent triggering seek bar drag
518
+ handleIn.addEventListener(
519
+ 'mousedown',
520
+ (e) => {
521
+ e.preventDefault(); // prevents selection cursor
522
+ e.stopPropagation(); // prevent triggering seek bar drag
510
523
 
511
- this.handleMarkerDrag(markerIn, constants.markerTypes.in, e);
512
- }, false);
524
+ this.handleMarkerDrag(markerIn, constants.markerTypes.in, e);
525
+ },
526
+ false,
527
+ );
513
528
 
514
- handleOut.addEventListener('mousedown', (e) => {
515
- e.preventDefault(); // prevents selection cursor
516
- e.stopPropagation(); // prevent triggering seek bar drag
529
+ handleOut.addEventListener(
530
+ 'mousedown',
531
+ (e) => {
532
+ e.preventDefault(); // prevents selection cursor
533
+ e.stopPropagation(); // prevent triggering seek bar drag
517
534
 
518
- this.handleMarkerDrag(markerOut, constants.markerTypes.out, e);
519
- }, false);
535
+ this.handleMarkerDrag(markerOut, constants.markerTypes.out, e);
536
+ },
537
+ false,
538
+ );
520
539
 
521
540
  markerIn.appendChild(handleIn);
522
541
  markerOut.appendChild(handleOut);
@@ -534,7 +553,7 @@ export default class SeekBar {
534
553
  if (this.state.regions) {
535
554
  // check if any region contains in / out matching value
536
555
  const matchingRegions = [];
537
- const isRegional = (matchingRegions.length > 0);
556
+ const isRegional = matchingRegions.length > 0;
538
557
  if (isRegional) {
539
558
  this.markers[marker.type].classList.add('regional');
540
559
  } else {
@@ -545,10 +564,13 @@ export default class SeekBar {
545
564
  this.drawInAndOutRegion();
546
565
  }
547
566
 
548
- drawInAndOutRegion() { // triggered after drawMarkers if in + out is set
567
+ drawInAndOutRegion() {
568
+ // triggered after drawMarkers if in + out is set
549
569
  if (this.state.in !== null && this.state.out !== null) {
550
570
  this.region.style.left = this.markers[constants.markerTypes.in].style.left;
551
- this.region.style.right = `${100 - parseFloat(this.markers[constants.markerTypes.out].style.left.replace('%', ''))}%`;
571
+ this.region.style.right = `${
572
+ 100 - parseFloat(this.markers[constants.markerTypes.out].style.left.replace('%', ''))
573
+ }%`;
552
574
  } else {
553
575
  // remove region div or hide it
554
576
  }
@@ -559,7 +581,8 @@ export default class SeekBar {
559
581
  but find out if there is a mobile use
560
582
  case before that
561
583
  */
562
- handleMarkerDrag(markerNode, type, mouseDownEvent) { // marker node, marker type (constants.markerTypes)
584
+ handleMarkerDrag(markerNode, type, mouseDownEvent) {
585
+ // marker node, marker type (constants.markerTypes)
563
586
  const barOffset = this.bar.getBoundingClientRect().left; // px from page left side
564
587
  const barWidth = this.bar.getBoundingClientRect().width; // seek bar width
565
588
  const duration = this.props.player.videojs.duration(); // in secondsā
@@ -567,15 +590,20 @@ export default class SeekBar {
567
590
 
568
591
  const drag = (e) => {
569
592
  const pxDragged = Math.abs(mouseDownEvent.clientX - e.clientX);
570
- const markerOffset = (type === constants.markerTypes.in) ? (constants.defaults.markerWidth / 2) : -(constants.defaults.markerWidth / 2);
593
+ const markerOffset =
594
+ type === constants.markerTypes.in
595
+ ? constants.defaults.markerWidth / 2
596
+ : -(constants.defaults.markerWidth / 2);
571
597
  const left = e.clientX - barOffset + markerOffset;
572
598
 
573
- if (left >= 0 && left < barWidth && pxDragged > 1) { // prevent out-of-bounds
599
+ if (left >= 0 && left < barWidth && pxDragged > 1) {
600
+ // prevent out-of-bounds
574
601
  dragHappened = this.dragging = true;
575
602
  markerNode.style.left = `${left}px`;
576
603
  markerNode.classList.add('active');
577
604
 
578
- const fractionFromStart = parseFloat(markerNode.getBoundingClientRect().left - barOffset) / barWidth;
605
+ const fractionFromStart =
606
+ parseFloat(markerNode.getBoundingClientRect().left - barOffset) / barWidth;
579
607
  const seconds = fractionFromStart * duration;
580
608
  this.props.player.videojs.currentTime(seconds);
581
609
  }
@@ -590,7 +618,8 @@ export default class SeekBar {
590
618
  document.removeEventListener('mousemove', drag, false);
591
619
  document.removeEventListener('mouseup', stopDrag, false);
592
620
 
593
- const fractionFromStart = parseFloat(markerNode.getBoundingClientRect().left - barOffset) / barWidth;
621
+ const fractionFromStart =
622
+ parseFloat(markerNode.getBoundingClientRect().left - barOffset) / barWidth;
594
623
  const seconds = fractionFromStart * duration;
595
624
  this[type] = seconds;
596
625
  this.props.player.videojs.currentTime(seconds);
@@ -633,7 +662,8 @@ export default class SeekBar {
633
662
  removedMarker = true;
634
663
  }
635
664
 
636
- if (removedMarker) { // if a marker was removed, region no longer is valid
665
+ if (removedMarker) {
666
+ // if a marker was removed, region no longer is valid
637
667
  this.region.style.left = 'initial';
638
668
  this.region.style.right = 'initial';
639
669
  }
@@ -734,12 +764,16 @@ export default class SeekBar {
734
764
  }
735
765
  }
736
766
 
737
- set regions(regionArray) { // different than i / o markers
738
- if (this.state.regions.length < 1) { // first time add
739
- regionArray && regionArray.forEach((region) => {
740
- this.addRegion(region);
741
- });
742
- } else { // state redraw
767
+ set regions(regionArray) {
768
+ // different than i / o markers
769
+ if (this.state.regions.length < 1) {
770
+ // first time add
771
+ regionArray &&
772
+ regionArray.forEach((region) => {
773
+ this.addRegion(region);
774
+ });
775
+ } else {
776
+ // state redraw
743
777
  this.state.regions.forEach((region, index) => {
744
778
  this.removeRegion(index);
745
779
  });
@@ -772,15 +806,18 @@ export default class SeekBar {
772
806
  if (regionObj.constructor.name === Region.name) {
773
807
  this.state.regions.push(regionObj);
774
808
  this.drawRegion(regionObj);
775
- } else { // try to construct region if has accepted properties
809
+ } else {
810
+ // try to construct region if has accepted properties
776
811
  this.addRegion(new Region(regionObj));
777
812
  }
778
813
  }
779
814
 
780
815
  removeRegion(param) {
781
- if (typeof param === typeof Region) { // TODO - implement this - find by region obj
816
+ if (typeof param === typeof Region) {
817
+ // TODO - implement this - find by region obj
782
818
  // find said matching region
783
- } else { // it's an index
819
+ } else {
820
+ // it's an index
784
821
  this.state.regions[param].el.remove();
785
822
  this.state.regions[param] = null;
786
823
  delete this.state.regions[param];
@@ -3,14 +3,10 @@
3
3
  /* eslint-disable no-plusplus */
4
4
  /* eslint-disable no-unused-expressions */
5
5
 
6
- const timeCodeNodeNames = [
7
- 'hours',
8
- 'minutes',
9
- 'seconds',
10
- 'frame',
11
- ];
12
-
13
- export default class TimeCodeDisplay {// displays and renders smpte timecodes
6
+ const timeCodeNodeNames = ['hours', 'minutes', 'seconds', 'frame'];
7
+
8
+ export default class TimeCodeDisplay {
9
+ // displays and renders smpte timecodes
14
10
  constructor(props) {
15
11
  this.props = props;
16
12
 
@@ -21,7 +17,7 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
21
17
  const classNames = [
22
18
  'vdt-timecode',
23
19
  'vjs-time-control', // will apply default videojs style to the whole container, centers things vertically
24
- (!(this.props.onInput)) ? 'duration' : '', // if no input capability, assume it's a duration timecode
20
+ !this.props.onInput ? 'duration' : '', // if no input capability, assume it's a duration timecode
25
21
  ];
26
22
  this.container = document.createElement('div');
27
23
  this.container.className = classNames.join(' ');
@@ -34,7 +30,8 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
34
30
  node.className = nodeName;
35
31
  node.tabIndex = -1; // prevent default Tab behaviour for cycling inputs
36
32
 
37
- if (this.props.onInput) { // optional input capabilities
33
+ if (this.props.onInput) {
34
+ // optional input capabilities
38
35
  node.maxLength = 2;
39
36
 
40
37
  node.onfocus = (e) => {
@@ -63,17 +60,16 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
63
60
 
64
61
  this.nodes[nodeName] = node;
65
62
 
66
-
67
63
  const colon = document.createElement('span');
68
64
  colon.innerHTML = ':';
69
65
 
70
-
71
66
  this.container.appendChild(node);
72
- (index !== this.nodeNames.length - 1) && this.container.appendChild(colon);
67
+ index !== this.nodeNames.length - 1 && this.container.appendChild(colon);
73
68
  });
74
69
 
75
70
  if (this.props.target) {
76
- if (this.props.appendAfter) { // so it's possible to append after volume control, for example
71
+ if (this.props.appendAfter) {
72
+ // so it's possible to append after volume control, for example
77
73
  this.props.target.parentNode.insertBefore(this.container, this.props.target.nextSibling);
78
74
  } else {
79
75
  this.props.target.appendChild(this.container);
@@ -87,13 +83,20 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
87
83
  }
88
84
  }
89
85
 
90
- update(valuesObj) { // Object.keys and array.forEach are too slow, classic for is faster
86
+ update(valuesObj) {
87
+ // Object.keys and array.forEach are too slow, classic for is faster
91
88
  const startCount = this.nodeNames.length - 1;
92
89
  let i;
93
- for (i = startCount; i > -1; i--) { // updates follow frame -> seconds -> minutes -> hours order
90
+ for (i = startCount; i > -1; i--) {
91
+ // updates follow frame -> seconds -> minutes -> hours order
94
92
  const key = this.nodeNames[i];
95
93
 
96
- if (typeof valuesObj[key] !== 'undefined' && (valuesObj[key] !== parseInt(this.nodes[key].value, 10)) && key !== this.state.selectedNode) { // re-render node if value is defineed and is different from current value
94
+ if (
95
+ typeof valuesObj[key] !== 'undefined' &&
96
+ valuesObj[key] !== parseInt(this.nodes[key].value, 10) &&
97
+ key !== this.state.selectedNode
98
+ ) {
99
+ // re-render node if value is defineed and is different from current value
97
100
  const str = valuesObj[key].toString();
98
101
  this.nodes[key].value = this.toDigitPairStr(str);
99
102
  }
@@ -126,7 +129,7 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
126
129
  }
127
130
 
128
131
  toDigitPairStr(strValue) {
129
- return (strValue.length < 2) ? `0${strValue}` : strValue;
132
+ return strValue.length < 2 ? `0${strValue}` : strValue;
130
133
  }
131
134
 
132
135
  handleTimeCodeInput(e, nodeName) {
@@ -136,12 +139,13 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
136
139
  case 'Enter': // do work before submitting input
137
140
  this.checkAndNormalizeAllInputs();
138
141
 
139
- this.props.onInput && this.props.onInput(e, nodeName, {
140
- hours: this.hours,
141
- minutes: this.minutes,
142
- seconds: this.seconds,
143
- frame: this.frame,
144
- });
142
+ this.props.onInput &&
143
+ this.props.onInput(e, nodeName, {
144
+ hours: this.hours,
145
+ minutes: this.minutes,
146
+ seconds: this.seconds,
147
+ frame: this.frame,
148
+ });
145
149
 
146
150
  this[nodeName] = e.currentTarget.value;
147
151
  e.currentTarget.blur(); // done
@@ -151,12 +155,12 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
151
155
 
152
156
  // tab trough inputs in a loop fashion
153
157
  if (!e.shiftKey) {
154
- if ((nodeIndex + 1) <= (this.nodeNames.length - 1)) {
158
+ if (nodeIndex + 1 <= this.nodeNames.length - 1) {
155
159
  this.nodes[this.nodeNames[nodeIndex + 1]].focus(); // focus next
156
160
  } else {
157
161
  this.nodes[this.nodeNames[0]].focus(); // focus first
158
162
  }
159
- } else if ((nodeIndex - 1) >= 0) {
163
+ } else if (nodeIndex - 1 >= 0) {
160
164
  this.nodes[this.nodeNames[nodeIndex - 1]].focus(); // focus previous
161
165
  } else {
162
166
  this.nodes[this.nodeNames[this.nodeNames.length - 1]].focus(); // focus last
@@ -180,7 +184,8 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
180
184
  if (this.nodes[nodeName].value.length === 2 && !isNaN(e.key)) {
181
185
  const nodeIndex = this.nodeNames.indexOf(nodeName); // determine position in timecode
182
186
 
183
- if ((nodeIndex + 1) <= (this.nodeNames.length - 1)) { // check bounds
187
+ if (nodeIndex + 1 <= this.nodeNames.length - 1) {
188
+ // check bounds
184
189
  this.nodes[this.nodeNames[nodeIndex + 1]].focus(); // focus next
185
190
  }
186
191
  }
@@ -188,7 +193,8 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
188
193
 
189
194
  checkAndNormalizeAllInputs() {
190
195
  this.nodeNames.forEach((nodeName) => {
191
- if (this.nodes[nodeName].value.length < 1) { // somebody left the input blank
196
+ if (this.nodes[nodeName].value.length < 1) {
197
+ // somebody left the input blank
192
198
  this.nodes[nodeName].value = '00';
193
199
  }
194
200
 
@@ -244,12 +250,14 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
244
250
  };
245
251
  }
246
252
 
247
- set spmte(o) {
253
+ set smpte(o) {
248
254
  this.update(o);
249
255
  }
250
256
 
251
257
  get smpteString() {
252
- return `${this.getFormatted('hours')}:${this.getFormatted('minutes')}:${this.getFormatted('seconds')}:${this.getFormatted('frame')}`;
258
+ return `${this.getFormatted('hours')}:${this.getFormatted('minutes')}:${this.getFormatted(
259
+ 'seconds',
260
+ )}:${this.getFormatted('frame')}`;
253
261
  }
254
262
 
255
263
  set external(bool) {
@@ -261,6 +269,6 @@ export default class TimeCodeDisplay {// displays and renders smpte timecodes
261
269
  }
262
270
 
263
271
  get external() {
264
- return (this.container.classList.contains('external'));
272
+ return this.container.classList.contains('external');
265
273
  }
266
274
  }
package/src/videoTime.js CHANGED
@@ -36,10 +36,10 @@ class VideoTime {
36
36
 
37
37
  smpteToCurrentTimeFromStart(values) {
38
38
  return (
39
- values.hours * 3600
40
- + values.minutes * 60
41
- + values.seconds
42
- + values.frame / this.props.frameRate
39
+ values.hours * 3600 +
40
+ values.minutes * 60 +
41
+ values.seconds +
42
+ values.frame / this.props.frameRate
43
43
  );
44
44
  }
45
45