@micromag/element-audio 0.3.307 → 0.3.310

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/lib/index.js CHANGED
@@ -5,15 +5,17 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var _defineProperty = require('@babel/runtime/helpers/defineProperty');
6
6
  var classNames = require('classnames');
7
7
  var isFunction = require('lodash/isFunction');
8
+ var isNumber = require('lodash/isNumber');
8
9
  var PropTypes = require('prop-types');
9
10
  var React = require('react');
10
11
  var core = require('@micromag/core');
11
12
  var hooks = require('@micromag/core/hooks');
12
13
  var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
13
14
  var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
15
+ var react = require('@use-gesture/react');
16
+ var reactIntl = require('react-intl');
14
17
  var core$1 = require('@react-spring/core');
15
18
  var web = require('@react-spring/web');
16
- var react = require('@use-gesture/react');
17
19
  require('whatwg-fetch');
18
20
  var utils = require('@micromag/core/utils');
19
21
 
@@ -22,205 +24,107 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
22
24
  var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
23
25
  var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
24
26
  var isFunction__default = /*#__PURE__*/_interopDefaultLegacy(isFunction);
27
+ var isNumber__default = /*#__PURE__*/_interopDefaultLegacy(isNumber);
25
28
  var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
26
29
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
27
30
  var _toConsumableArray__default = /*#__PURE__*/_interopDefaultLegacy(_toConsumableArray);
28
31
  var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray);
29
32
 
30
- var styles$1 = {"container":"micromag-element-audio-audio-wave-container","button":"micromag-element-audio-audio-wave-button","canvasBackground":"micromag-element-audio-audio-wave-canvasBackground","canvasProgress":"micromag-element-audio-audio-wave-canvasProgress"};
33
+ var styles$2 = {"container":"micromag-element-audio-audio-bars-container","seekButton":"micromag-element-audio-audio-bars-seekButton"};
31
34
 
32
- var propTypes$1 = {
33
- currentTime: PropTypes__default["default"].number,
35
+ var propTypes$2 = {
36
+ progress: PropTypes__default["default"].number,
34
37
  duration: PropTypes__default["default"].number,
35
38
  playing: PropTypes__default["default"].bool,
36
- sampleWidth: PropTypes__default["default"].number,
37
- sampleMargin: PropTypes__default["default"].number,
38
- minSampleHeight: PropTypes__default["default"].number,
39
- backgroundColor: core.PropTypes.color,
40
- progressColor: core.PropTypes.color,
41
- audioLevels: PropTypes__default["default"].arrayOf(PropTypes__default["default"].number),
42
- className: PropTypes__default["default"].string,
43
- onSeek: PropTypes__default["default"].func,
44
- onResume: PropTypes__default["default"].func,
45
- onReady: PropTypes__default["default"].func
39
+ seek: PropTypes__default["default"].func,
40
+ play: PropTypes__default["default"].func,
41
+ // onReady: PropTypes.func,
42
+ className: PropTypes__default["default"].string
46
43
  };
47
- var defaultProps$1 = {
48
- currentTime: null,
49
- duration: null,
44
+ var defaultProps$2 = {
45
+ progress: 0,
46
+ duration: 0,
50
47
  playing: false,
51
- sampleWidth: 3,
52
- sampleMargin: 1,
53
- minSampleHeight: 2,
54
- backgroundColor: 'white',
55
- progressColor: null,
56
- audioLevels: null,
57
- className: null,
58
- onSeek: null,
59
- onResume: null,
60
- onReady: null
48
+ seek: null,
49
+ play: null,
50
+ // onReady: null,
51
+ className: null
61
52
  };
62
53
 
63
- function AudioWave(_ref) {
64
- var currentTime = _ref.currentTime,
65
- duration = _ref.duration,
54
+ function AudioBars(_ref) {
55
+ var progress = _ref.progress,
66
56
  playing = _ref.playing,
67
- sampleWidth = _ref.sampleWidth,
68
- sampleMargin = _ref.sampleMargin,
69
- minSampleHeight = _ref.minSampleHeight,
70
- backgroundColor = _ref.backgroundColor,
71
- progressColor = _ref.progressColor,
72
- audioLevels = _ref.audioLevels,
73
- className = _ref.className,
74
- onSeek = _ref.onSeek,
75
- onResume = _ref.onResume,
76
- onReady = _ref.onReady;
77
- var canvasBackgroundRef = React.useRef(null);
78
- var canvasProgressRef = React.useRef(null);
79
- var mainColor = React.useMemo(function () {
80
- var _ref2 = backgroundColor || {},
81
- _ref2$color = _ref2.color,
82
- color = _ref2$color === void 0 ? 'white' : _ref2$color;
83
-
84
- return color;
85
- }, [backgroundColor]);
86
- var alternateColor = React.useMemo(function () {
87
- return utils.getContrastingColor(backgroundColor, progressColor);
88
- }, [progressColor, backgroundColor]);
57
+ duration = _ref.duration,
58
+ seek = _ref.seek,
59
+ play = _ref.play,
60
+ className = _ref.className;
61
+ var intl = reactIntl.useIntl();
89
62
 
90
63
  var _useDimensionObserver = hooks.useDimensionObserver(),
91
64
  elRef = _useDimensionObserver.ref,
92
65
  _useDimensionObserver2 = _useDimensionObserver.width,
93
66
  elWidth = _useDimensionObserver2 === void 0 ? null : _useDimensionObserver2,
94
- elHeight = _useDimensionObserver.height; // Linear animation for progress bar
95
-
96
-
97
- var _useSpring = core$1.useSpring(function () {
98
- return {
99
- x: 0,
100
- config: {
101
- duration: 0
102
- }
103
- };
104
- }),
105
- _useSpring2 = _slicedToArray__default["default"](_useSpring, 2),
106
- springProps = _useSpring2[0],
107
- setSpringProps = _useSpring2[1];
108
-
109
- React.useEffect(function () {
110
- if (currentTime === null || duration === null) {
111
- return;
112
- }
113
-
114
- var progress = currentTime / duration;
115
- setSpringProps.start({
116
- reset: true,
117
- immediate: !playing,
118
- from: {
119
- x: progress
120
- },
121
- to: {
122
- x: playing ? 1 : progress
123
- },
124
- config: {
125
- duration: (duration - currentTime) * 1000
126
- }
67
+ elHeight = _useDimensionObserver.height;
68
+
69
+ var barWidth = 1;
70
+ var barGap = 1;
71
+ var barSize = barWidth + barGap;
72
+ var current = progress * elWidth;
73
+
74
+ var _useState = React.useState(null),
75
+ _useState2 = _slicedToArray__default["default"](_useState, 2),
76
+ currentSeek = _useState2[0],
77
+ setCurrentSeek = _useState2[1];
78
+
79
+ var items = React.useMemo(function () {
80
+ var count = Math.floor(elWidth / barSize);
81
+ return _toConsumableArray__default["default"](Array(count).keys()).map(function () {
82
+ return Math.floor(Math.random() * 100);
127
83
  });
128
- }, [playing, duration, currentTime, setSpringProps]); // draw canvas
84
+ }, [elWidth, barSize]);
85
+ var seekFromX = React.useCallback(function () {
86
+ var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
129
87
 
130
- React.useEffect(function () {
131
- if (audioLevels === null || audioLevels.length === 0 || elRef.current === null) {
88
+ if (x === null) {
132
89
  return;
133
90
  }
134
91
 
135
- var sampleOuterWidth = sampleWidth + sampleMargin * 2;
136
- var samplesCount = Math.floor(elWidth / sampleOuterWidth); // const amplitudes = [];
137
- // get samples
138
-
139
- var levelsBySamples = audioLevels.length / samplesCount;
140
-
141
- var amplitudes = _toConsumableArray__default["default"](Array(samplesCount).keys()).reduce(function (newAmplitudes, index) {
142
- var levelStartIndex = index * levelsBySamples;
143
- var levelEndIndex = levelStartIndex + levelsBySamples;
144
- var newValues = [];
145
-
146
- for (var i = Math.floor(levelStartIndex); i < Math.round(levelEndIndex); i += 1) {
147
- newValues.push(audioLevels[i]);
148
- }
149
-
150
- return levelsBySamples >= 1 ? [].concat(_toConsumableArray__default["default"](newAmplitudes), [newValues.reduce(function (total, value) {
151
- return total + value;
152
- }, 0) / newValues.length]) : [].concat(_toConsumableArray__default["default"](newAmplitudes), newValues);
153
- }, []); // for (let sampleI = 0; sampleI < samplesCount; sampleI += levelsBySamples) {
154
- // // if (levelsBySamples >= 1) {
155
- // // const sampleSize = Math.floor(levelsBySamples);
156
- // // const sampleStart = sampleSize * sampleI;
157
- // // let sum = 0;
158
- // // for (let sampleSizeI = 0; sampleSizeI < sampleSize; sampleSizeI += 1) {
159
- // // sum += Math.abs(audioLevels[sampleStart + sampleSizeI]);
160
- // // }
161
- // // amplitudes.push(sum / sampleSize);
162
- // // } else {
163
- // console.log(sampleI);
164
- // amplitudes.push(Math.abs(audioLevels[Math.floor(sampleI)]));
165
- // // for (let sampleSizeI = 0; sampleSizeI < sampleSize; sampleSizeI += 1) {
166
- // // console.log(sampleI, sampleSize);
167
- // // amplitudes.push(Math.abs(audioLevels[sampleI % sampleSize]));
168
- // // }
169
- // // }
170
- // }
171
-
172
-
173
- var minAmplitude = Math.min.apply(Math, _toConsumableArray__default["default"](amplitudes));
174
- var maxAmplitude = Math.max.apply(Math, _toConsumableArray__default["default"](amplitudes));
175
- var delta = maxAmplitude - minAmplitude;
176
- var normalizedAmplitudes = amplitudes.map(function (n) {
177
- return (n - minAmplitude) / delta;
178
- }); // draw samples
179
-
180
- var canvasBg = canvasBackgroundRef.current;
181
- var canvasProgress = canvasProgressRef.current;
182
- var scale = typeof window !== 'undefined' ? window.devicePixelRatio : 1;
183
- canvasBg.width = canvasProgress.width = Math.floor(elWidth * scale);
184
- canvasBg.height = canvasProgress.height = Math.floor(elHeight * scale);
185
- var ctxBG = canvasBg.getContext('2d');
186
- var ctxProgress = canvasProgress.getContext('2d');
187
- ctxBG.scale(scale, scale);
188
- ctxProgress.scale(scale, scale);
189
- ctxBG.clearRect(0, 0, elWidth, elHeight);
190
- ctxProgress.clearRect(0, 0, elWidth, elHeight);
191
- ctxBG.fillStyle = mainColor;
192
- ctxProgress.fillStyle = alternateColor;
193
- var offsetLeft = (elWidth - samplesCount * sampleOuterWidth) / 2;
194
- normalizedAmplitudes.forEach(function (amplitude, amplitudeI) {
195
- var sampleHeight = Math.max(minSampleHeight, amplitude * elHeight);
196
- var sampleX = sampleOuterWidth * amplitudeI + offsetLeft + sampleMargin;
197
- var sampleY = elHeight / 2 - sampleHeight / 2;
198
- ctxBG.fillRect(Math.round(sampleX), Math.round(sampleY), sampleWidth, Math.round(sampleHeight));
199
- ctxProgress.fillRect(Math.round(sampleX), Math.round(sampleY), sampleWidth, Math.round(sampleHeight));
200
- });
201
-
202
- if (onReady !== null) {
203
- onReady();
204
- }
205
- }, [audioLevels, sampleWidth, sampleMargin, minSampleHeight, elWidth, elHeight, mainColor, alternateColor, onReady]); // User events
206
-
207
- var seekFromX = React.useCallback(function (x) {
208
92
  var _elRef$current$getBou = elRef.current.getBoundingClientRect(),
209
93
  elX = _elRef$current$getBou.left,
210
94
  width = _elRef$current$getBou.width;
211
95
 
212
- var progress = Math.max(0, Math.min(1, (x - elX) / width));
96
+ var distance = Math.max(0, Math.min(1, (x - elX) / width));
213
97
 
214
- if (onSeek !== null && duration !== null) {
215
- onSeek(progress * duration);
98
+ if (seek !== null && duration !== null) {
99
+ seek(parseFloat(distance * duration, 10));
216
100
  }
217
101
 
218
- if (!playing) {
219
- onResume();
102
+ if (!playing && play != null) {
103
+ play();
220
104
  }
221
- }, [duration, playing, onSeek, onResume]);
105
+ }, [elRef.current, elWidth, duration, playing, seek, play]);
106
+ var seekTemporary = React.useCallback(function (x) {
107
+ var _elRef$current$getBou2 = elRef.current.getBoundingClientRect(),
108
+ elX = _elRef$current$getBou2.left,
109
+ width = _elRef$current$getBou2.width;
110
+
111
+ var distance = Math.max(0, Math.min(1, (x - elX) / width));
112
+ setCurrentSeek(distance * elWidth);
113
+ }, [elRef.current, elWidth, setCurrentSeek]);
222
114
  var bind = react.useGesture({
223
- onDrag: function onDrag(_ref3) {
115
+ onDrag: function onDrag(_ref2) {
116
+ var _ref2$xy = _slicedToArray__default["default"](_ref2.xy, 1),
117
+ x = _ref2$xy[0],
118
+ elapsedTime = _ref2.elapsedTime,
119
+ active = _ref2.active;
120
+
121
+ if (!active && elapsedTime > 300) {
122
+ return;
123
+ }
124
+
125
+ seekTemporary(x);
126
+ },
127
+ onDragStart: function onDragStart(_ref3) {
224
128
  var _ref3$xy = _slicedToArray__default["default"](_ref3.xy, 1),
225
129
  x = _ref3$xy[0],
226
130
  elapsedTime = _ref3.elapsedTime,
@@ -230,7 +134,16 @@ function AudioWave(_ref) {
230
134
  return;
231
135
  }
232
136
 
137
+ seekTemporary(x);
138
+ },
139
+ onDragEnd: function onDragEnd(_ref4) {
140
+ var _ref4$xy = _slicedToArray__default["default"](_ref4.xy, 1),
141
+ x = _ref4$xy[0];
142
+
233
143
  seekFromX(x);
144
+ setTimeout(function () {
145
+ setCurrentSeek(null);
146
+ }, 1000);
234
147
  }
235
148
  }, {
236
149
  drag: {
@@ -238,29 +151,62 @@ function AudioWave(_ref) {
238
151
  filterTaps: true
239
152
  }
240
153
  });
241
- return /*#__PURE__*/React__default["default"].createElement("div", Object.assign({
242
- className: classNames__default["default"]([styles$1.container, _defineProperty__default["default"]({}, className, className !== null)]),
154
+ return /*#__PURE__*/React__default["default"].createElement("div", {
155
+ className: classNames__default["default"]([styles$2.container, _defineProperty__default["default"]({}, className, className !== null)]),
243
156
  ref: elRef
244
- }, bind()), /*#__PURE__*/React__default["default"].createElement("canvas", {
245
- ref: canvasBackgroundRef,
246
- className: styles$1.canvasBackground
247
- }), /*#__PURE__*/React__default["default"].createElement(web.animated.canvas, {
248
- ref: canvasProgressRef,
249
- className: styles$1.canvasProgress,
250
- style: {
251
- clipPath: springProps.x.to(function (x) {
252
- return "polygon(0 0, ".concat(x * 100, "% 0, ").concat(x * 100, "% 100%, 0 100%)");
253
- })
254
- }
255
- }));
157
+ }, /*#__PURE__*/React__default["default"].createElement("svg", {
158
+ version: "1.1",
159
+ xmlns: "http://www.w3.org/2000/svg",
160
+ xmlnsXlink: "http://www.w3.org/1999/xlink",
161
+ x: "0",
162
+ y: "0",
163
+ width: "".concat(elWidth, "px"),
164
+ height: "".concat(elHeight, "px"),
165
+ viewBox: "0 0 ".concat(elWidth, " ").concat(elHeight),
166
+ className: className,
167
+ xmlSpace: "preserve"
168
+ }, items.map(function (size, i) {
169
+ return /*#__PURE__*/React__default["default"].createElement("rect", {
170
+ key: "bar-".concat(i + 1),
171
+ width: barWidth,
172
+ height: size,
173
+ x: i * barSize,
174
+ y: elHeight / 2 - size / 2,
175
+ fill: (currentSeek || current) > i * barSize ? 'white' : 'gray',
176
+ stroke: "black",
177
+ strokeWidth: "0px",
178
+ strokeLinejoin: "round",
179
+ strokeLinecap: "round"
180
+ });
181
+ })), /*#__PURE__*/React__default["default"].createElement("button", Object.assign({}, bind(), {
182
+ onClick: function onClick(e) {
183
+ return e.target !== null ? seekFromX(e.target.clientX) : null;
184
+ },
185
+ type: "button",
186
+ className: styles$2.seekButton,
187
+ title: intl.formatMessage({
188
+ id: "G1Gyjn",
189
+ defaultMessage: [{
190
+ "type": 0,
191
+ "value": "Seek"
192
+ }]
193
+ }),
194
+ "aria-label": intl.formatMessage({
195
+ id: "G1Gyjn",
196
+ defaultMessage: [{
197
+ "type": 0,
198
+ "value": "Seek"
199
+ }]
200
+ })
201
+ })));
256
202
  }
257
203
 
258
- AudioWave.propTypes = propTypes$1;
259
- AudioWave.defaultProps = defaultProps$1;
204
+ AudioBars.propTypes = propTypes$2;
205
+ AudioBars.defaultProps = defaultProps$2;
260
206
 
261
- var styles = {"container":"micromag-element-audio-container","wave":"micromag-element-audio-wave"};
207
+ var styles$1 = {"container":"micromag-element-audio-container","wave":"micromag-element-audio-wave"};
262
208
 
263
- var propTypes = {
209
+ var propTypes$1 = {
264
210
  media: core.PropTypes.audioMedia,
265
211
  mediaRef: PropTypes__default["default"].oneOfType([PropTypes__default["default"].func, PropTypes__default["default"].shape({
266
212
  current: PropTypes__default["default"].any
@@ -272,13 +218,13 @@ var propTypes = {
272
218
  preload: PropTypes__default["default"].oneOf(['auto', 'none', 'metadata']),
273
219
  shouldLoad: PropTypes__default["default"].bool,
274
220
  waveFake: PropTypes__default["default"].bool,
275
- waveProps: PropTypes__default["default"].shape({
276
- sampleWidth: PropTypes__default["default"].number,
277
- sampleMargin: PropTypes__default["default"].number,
278
- minSampleHeight: PropTypes__default["default"].number
279
- }),
221
+ // waveProps: PropTypes.shape({
222
+ // sampleWidth: PropTypes.number,
223
+ // sampleMargin: PropTypes.number,
224
+ // minSampleHeight: PropTypes.number,
225
+ // }),
280
226
  withWave: PropTypes__default["default"].bool,
281
- reduceBufferFactor: PropTypes__default["default"].number,
227
+ // reduceBufferFactor: PropTypes.number,
282
228
  className: PropTypes__default["default"].string,
283
229
  onReady: PropTypes__default["default"].func,
284
230
  onPlay: PropTypes__default["default"].func,
@@ -290,7 +236,7 @@ var propTypes = {
290
236
  onDurationChange: PropTypes__default["default"].func,
291
237
  onVolumeChange: PropTypes__default["default"].func
292
238
  };
293
- var defaultProps = {
239
+ var defaultProps$1 = {
294
240
  media: null,
295
241
  mediaRef: null,
296
242
  muted: false,
@@ -300,9 +246,9 @@ var defaultProps = {
300
246
  preload: 'auto',
301
247
  shouldLoad: true,
302
248
  waveFake: false,
303
- waveProps: null,
249
+ // waveProps: null,
304
250
  withWave: false,
305
- reduceBufferFactor: 100,
251
+ // reduceBufferFactor: 100,
306
252
  className: null,
307
253
  onReady: null,
308
254
  onPlay: null,
@@ -325,9 +271,7 @@ var Audio = function Audio(_ref) {
325
271
  preload = _ref.preload,
326
272
  shouldLoad = _ref.shouldLoad,
327
273
  waveFake = _ref.waveFake,
328
- waveProps = _ref.waveProps,
329
274
  withWave = _ref.withWave,
330
- reduceBufferFactor = _ref.reduceBufferFactor,
331
275
  className = _ref.className,
332
276
  onReady = _ref.onReady,
333
277
  onPlay = _ref.onPlay,
@@ -354,11 +298,11 @@ var Audio = function Audio(_ref) {
354
298
  });
355
299
  var duration = hooks.useMediaDuration(_ref4.current, {
356
300
  id: url
357
- });
358
- var audioLevels = hooks.useMediaWaveform(media, {
359
- fake: waveFake,
360
- reduceBufferFactor: reduceBufferFactor
361
- });
301
+ }); // const audioLevels = useMediaWaveform(media, {
302
+ // fake: waveFake,
303
+ // reduceBufferFactor,
304
+ // });
305
+
362
306
  hooks.useMediaLoad(_ref4.current, {
363
307
  preload: preload,
364
308
  shouldLoad: shouldLoad
@@ -380,7 +324,7 @@ var Audio = function Audio(_ref) {
380
324
  if (customOnVolumeChange !== null) {
381
325
  customOnVolumeChange(element.volume);
382
326
  }
383
- }, [customOnVolumeChange]);
327
+ }, [_ref4.current, customOnVolumeChange]);
384
328
  var onWavePlay = React.useCallback(function () {
385
329
  var _ref$current2 = _ref4.current,
386
330
  element = _ref$current2 === void 0 ? null : _ref$current2;
@@ -390,7 +334,7 @@ var Audio = function Audio(_ref) {
390
334
  }
391
335
 
392
336
  element.play();
393
- }, []);
337
+ }, [_ref4.current]);
394
338
  var onWaveSeek = React.useCallback(function (newTime) {
395
339
  var _ref$current3 = _ref4.current,
396
340
  element = _ref$current3 === void 0 ? null : _ref$current3;
@@ -399,8 +343,12 @@ var Audio = function Audio(_ref) {
399
343
  return;
400
344
  }
401
345
 
402
- element.currentTime = newTime;
403
- }, []);
346
+ console.log('fuck off', newTime);
347
+
348
+ if (isNumber__default["default"](newTime)) {
349
+ element.currentTime = newTime;
350
+ }
351
+ }, [_ref4.current]);
404
352
  React.useEffect(function () {
405
353
  if (waveReady && onReady !== null) {
406
354
  onReady();
@@ -428,8 +376,9 @@ var Audio = function Audio(_ref) {
428
376
  disabled: paused,
429
377
  onStep: onProgressStep
430
378
  });
379
+ var progress = currentTime !== null && duration > 0 ? currentTime / duration : 0;
431
380
  return /*#__PURE__*/React__default["default"].createElement("div", {
432
- className: classNames__default["default"]([styles.container, _defineProperty__default["default"]({}, className, className !== null)])
381
+ className: classNames__default["default"]([styles$1.container, _defineProperty__default["default"]({}, className, className !== null)])
433
382
  }, /*#__PURE__*/React__default["default"].createElement("audio", {
434
383
  key: url,
435
384
  ref: function ref(newRef) {
@@ -453,26 +402,255 @@ var Audio = function Audio(_ref) {
453
402
  onSeeked: onSeeked,
454
403
  onTimeUpdate: onTimeUpdate,
455
404
  onVolumeChange: onVolumeChange
456
- }), withWave ? /*#__PURE__*/React__default["default"].createElement(AudioWave, Object.assign({
457
- className: styles.wave,
458
- media: media,
459
- currentTime: currentTime
460
- }, waveProps, {
405
+ }), withWave ? /*#__PURE__*/React__default["default"].createElement(AudioBars, {
406
+ className: styles$1.wave,
407
+ progress: progress // {...waveProps}
408
+ ,
461
409
  duration: duration,
462
410
  playing: !paused,
463
- onSeek: onWaveSeek,
464
- onResume: onWavePlay,
465
- audioLevels: audioLevels
466
- })) : null);
411
+ seek: onWaveSeek,
412
+ play: onWavePlay
413
+ }) : null);
467
414
  };
468
415
 
469
- Audio.propTypes = propTypes;
470
- Audio.defaultProps = defaultProps;
416
+ Audio.propTypes = propTypes$1;
417
+ Audio.defaultProps = defaultProps$1;
471
418
  var Audio$1 = /*#__PURE__*/React__default["default"].forwardRef(function (props, ref) {
472
419
  return /*#__PURE__*/React__default["default"].createElement(Audio, Object.assign({
473
420
  mediaRef: ref
474
421
  }, props));
475
422
  });
476
423
 
424
+ var styles = {"container":"micromag-element-audio-audio-wave-container","button":"micromag-element-audio-audio-wave-button","canvasBackground":"micromag-element-audio-audio-wave-canvasBackground","canvasProgress":"micromag-element-audio-audio-wave-canvasProgress"};
425
+
426
+ var propTypes = {
427
+ currentTime: PropTypes__default["default"].number,
428
+ duration: PropTypes__default["default"].number,
429
+ playing: PropTypes__default["default"].bool,
430
+ sampleWidth: PropTypes__default["default"].number,
431
+ sampleMargin: PropTypes__default["default"].number,
432
+ minSampleHeight: PropTypes__default["default"].number,
433
+ backgroundColor: core.PropTypes.color,
434
+ progressColor: core.PropTypes.color,
435
+ audioLevels: PropTypes__default["default"].arrayOf(PropTypes__default["default"].number),
436
+ className: PropTypes__default["default"].string,
437
+ onSeek: PropTypes__default["default"].func,
438
+ onResume: PropTypes__default["default"].func,
439
+ onReady: PropTypes__default["default"].func
440
+ };
441
+ var defaultProps = {
442
+ currentTime: null,
443
+ duration: null,
444
+ playing: false,
445
+ sampleWidth: 3,
446
+ sampleMargin: 1,
447
+ minSampleHeight: 2,
448
+ backgroundColor: 'white',
449
+ progressColor: null,
450
+ audioLevels: null,
451
+ className: null,
452
+ onSeek: null,
453
+ onResume: null,
454
+ onReady: null
455
+ };
456
+
457
+ function AudioWave(_ref) {
458
+ var currentTime = _ref.currentTime,
459
+ duration = _ref.duration,
460
+ playing = _ref.playing,
461
+ sampleWidth = _ref.sampleWidth,
462
+ sampleMargin = _ref.sampleMargin,
463
+ minSampleHeight = _ref.minSampleHeight,
464
+ backgroundColor = _ref.backgroundColor,
465
+ progressColor = _ref.progressColor,
466
+ audioLevels = _ref.audioLevels,
467
+ className = _ref.className,
468
+ onSeek = _ref.onSeek,
469
+ onResume = _ref.onResume,
470
+ onReady = _ref.onReady;
471
+ var canvasBackgroundRef = React.useRef(null);
472
+ var canvasProgressRef = React.useRef(null);
473
+ var mainColor = React.useMemo(function () {
474
+ var _ref2 = backgroundColor || {},
475
+ _ref2$color = _ref2.color,
476
+ color = _ref2$color === void 0 ? 'white' : _ref2$color;
477
+
478
+ return color;
479
+ }, [backgroundColor]);
480
+ var alternateColor = React.useMemo(function () {
481
+ return utils.getContrastingColor(backgroundColor, progressColor);
482
+ }, [progressColor, backgroundColor]);
483
+
484
+ var _useDimensionObserver = hooks.useDimensionObserver(),
485
+ elRef = _useDimensionObserver.ref,
486
+ _useDimensionObserver2 = _useDimensionObserver.width,
487
+ elWidth = _useDimensionObserver2 === void 0 ? null : _useDimensionObserver2,
488
+ elHeight = _useDimensionObserver.height; // Linear animation for progress bar
489
+
490
+
491
+ var _useSpring = core$1.useSpring(function () {
492
+ return {
493
+ x: 0,
494
+ config: {
495
+ duration: 0
496
+ }
497
+ };
498
+ }),
499
+ _useSpring2 = _slicedToArray__default["default"](_useSpring, 2),
500
+ springProps = _useSpring2[0],
501
+ setSpringProps = _useSpring2[1];
502
+
503
+ React.useEffect(function () {
504
+ if (currentTime === null || duration === null) {
505
+ return;
506
+ }
507
+
508
+ var progress = currentTime / duration;
509
+ setSpringProps.start({
510
+ reset: true,
511
+ immediate: !playing,
512
+ from: {
513
+ x: progress
514
+ },
515
+ to: {
516
+ x: playing ? 1 : progress
517
+ },
518
+ config: {
519
+ duration: (duration - currentTime) * 1000
520
+ }
521
+ });
522
+ }, [playing, duration, currentTime, setSpringProps]); // draw canvas
523
+
524
+ React.useEffect(function () {
525
+ if (audioLevels === null || audioLevels.length === 0 || elRef.current === null) {
526
+ return;
527
+ }
528
+
529
+ var sampleOuterWidth = sampleWidth + sampleMargin * 2;
530
+ var samplesCount = Math.floor(elWidth / sampleOuterWidth); // const amplitudes = [];
531
+ // get samples
532
+
533
+ var levelsBySamples = audioLevels.length / samplesCount;
534
+
535
+ var amplitudes = _toConsumableArray__default["default"](Array(samplesCount).keys()).reduce(function (newAmplitudes, index) {
536
+ var levelStartIndex = index * levelsBySamples;
537
+ var levelEndIndex = levelStartIndex + levelsBySamples;
538
+ var newValues = [];
539
+
540
+ for (var i = Math.floor(levelStartIndex); i < Math.round(levelEndIndex); i += 1) {
541
+ newValues.push(audioLevels[i]);
542
+ }
543
+
544
+ return levelsBySamples >= 1 ? [].concat(_toConsumableArray__default["default"](newAmplitudes), [newValues.reduce(function (total, value) {
545
+ return total + value;
546
+ }, 0) / newValues.length]) : [].concat(_toConsumableArray__default["default"](newAmplitudes), newValues);
547
+ }, []); // for (let sampleI = 0; sampleI < samplesCount; sampleI += levelsBySamples) {
548
+ // // if (levelsBySamples >= 1) {
549
+ // // const sampleSize = Math.floor(levelsBySamples);
550
+ // // const sampleStart = sampleSize * sampleI;
551
+ // // let sum = 0;
552
+ // // for (let sampleSizeI = 0; sampleSizeI < sampleSize; sampleSizeI += 1) {
553
+ // // sum += Math.abs(audioLevels[sampleStart + sampleSizeI]);
554
+ // // }
555
+ // // amplitudes.push(sum / sampleSize);
556
+ // // } else {
557
+ // console.log(sampleI);
558
+ // amplitudes.push(Math.abs(audioLevels[Math.floor(sampleI)]));
559
+ // // for (let sampleSizeI = 0; sampleSizeI < sampleSize; sampleSizeI += 1) {
560
+ // // console.log(sampleI, sampleSize);
561
+ // // amplitudes.push(Math.abs(audioLevels[sampleI % sampleSize]));
562
+ // // }
563
+ // // }
564
+ // }
565
+
566
+
567
+ var minAmplitude = Math.min.apply(Math, _toConsumableArray__default["default"](amplitudes));
568
+ var maxAmplitude = Math.max.apply(Math, _toConsumableArray__default["default"](amplitudes));
569
+ var delta = maxAmplitude - minAmplitude;
570
+ var normalizedAmplitudes = amplitudes.map(function (n) {
571
+ return (n - minAmplitude) / delta;
572
+ }); // draw samples
573
+
574
+ var canvasBg = canvasBackgroundRef.current;
575
+ var canvasProgress = canvasProgressRef.current;
576
+ var scale = typeof window !== 'undefined' ? window.devicePixelRatio : 1;
577
+ canvasBg.width = canvasProgress.width = Math.floor(elWidth * scale);
578
+ canvasBg.height = canvasProgress.height = Math.floor(elHeight * scale);
579
+ var ctxBG = canvasBg.getContext('2d');
580
+ var ctxProgress = canvasProgress.getContext('2d');
581
+ ctxBG.scale(scale, scale);
582
+ ctxProgress.scale(scale, scale);
583
+ ctxBG.clearRect(0, 0, elWidth, elHeight);
584
+ ctxProgress.clearRect(0, 0, elWidth, elHeight);
585
+ ctxBG.fillStyle = mainColor;
586
+ ctxProgress.fillStyle = alternateColor;
587
+ var offsetLeft = (elWidth - samplesCount * sampleOuterWidth) / 2;
588
+ normalizedAmplitudes.forEach(function (amplitude, amplitudeI) {
589
+ var sampleHeight = Math.max(minSampleHeight, amplitude * elHeight);
590
+ var sampleX = sampleOuterWidth * amplitudeI + offsetLeft + sampleMargin;
591
+ var sampleY = elHeight / 2 - sampleHeight / 2;
592
+ ctxBG.fillRect(Math.round(sampleX), Math.round(sampleY), sampleWidth, Math.round(sampleHeight));
593
+ ctxProgress.fillRect(Math.round(sampleX), Math.round(sampleY), sampleWidth, Math.round(sampleHeight));
594
+ });
595
+
596
+ if (onReady !== null) {
597
+ onReady();
598
+ }
599
+ }, [audioLevels, sampleWidth, sampleMargin, minSampleHeight, elWidth, elHeight, mainColor, alternateColor, onReady]); // User events
600
+
601
+ var seekFromX = React.useCallback(function (x) {
602
+ var _elRef$current$getBou = elRef.current.getBoundingClientRect(),
603
+ elX = _elRef$current$getBou.left,
604
+ width = _elRef$current$getBou.width;
605
+
606
+ var progress = Math.max(0, Math.min(1, (x - elX) / width));
607
+
608
+ if (onSeek !== null && duration !== null) {
609
+ onSeek(progress * duration);
610
+ }
611
+
612
+ if (!playing) {
613
+ onResume();
614
+ }
615
+ }, [duration, playing, onSeek, onResume]);
616
+ var bind = react.useGesture({
617
+ onDrag: function onDrag(_ref3) {
618
+ var _ref3$xy = _slicedToArray__default["default"](_ref3.xy, 1),
619
+ x = _ref3$xy[0],
620
+ elapsedTime = _ref3.elapsedTime,
621
+ active = _ref3.active;
622
+
623
+ if (!active && elapsedTime > 300) {
624
+ return;
625
+ }
626
+
627
+ seekFromX(x);
628
+ }
629
+ }, {
630
+ drag: {
631
+ axis: 'x',
632
+ filterTaps: true
633
+ }
634
+ });
635
+ return /*#__PURE__*/React__default["default"].createElement("div", Object.assign({
636
+ className: classNames__default["default"]([styles.container, _defineProperty__default["default"]({}, className, className !== null)]),
637
+ ref: elRef
638
+ }, bind()), /*#__PURE__*/React__default["default"].createElement("canvas", {
639
+ ref: canvasBackgroundRef,
640
+ className: styles.canvasBackground
641
+ }), /*#__PURE__*/React__default["default"].createElement(web.animated.canvas, {
642
+ ref: canvasProgressRef,
643
+ className: styles.canvasProgress,
644
+ style: {
645
+ clipPath: springProps.x.to(function (x) {
646
+ return "polygon(0 0, ".concat(x * 100, "% 0, ").concat(x * 100, "% 100%, 0 100%)");
647
+ })
648
+ }
649
+ }));
650
+ }
651
+
652
+ AudioWave.propTypes = propTypes;
653
+ AudioWave.defaultProps = defaultProps;
654
+
477
655
  exports.AudioWave = AudioWave;
478
656
  exports["default"] = Audio$1;