@micromag/element-audio 0.3.307 → 0.3.311

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