@vonage/vivid 3.57.0 → 3.58.0

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.
@@ -9,7 +9,6 @@ require('./index2.cjs');
9
9
  const localized = require('./localized.cjs');
10
10
  const applyMixins = require('./apply-mixins.cjs');
11
11
  const when = require('./when.cjs');
12
- const ref = require('./ref.cjs');
13
12
  const classNames = require('./class-names.cjs');
14
13
 
15
14
  const styles = ":host{display:block;max-inline-size:350px}.wrapper{container-type:inline-size}.base{display:inline-flex;box-sizing:border-box;align-items:center;padding:8px;color:var(--vvd-color-canvas-text);gap:16px;inline-size:100%;user-select:none}.base .slider{flex:1;grid-area:slider;min-inline-size:var(--audio-player-min-inline-size, 200px)}.base .controls{display:flex;align-items:center;justify-content:center;gap:8px;grid-area:controls}.base .time-stamp{display:inline-flex}.base .time-stamp .current-time,.base .time-stamp .total-time{margin-inline:6px;min-inline-size:32px}.base .playback{grid-area:playback}@container (max-width: 500px){.base.two-lines{display:inline-grid;grid-template:auto auto/1fr;grid-template-areas:\"slider\" \"controls\";inline-size:100%;row-gap:4px}.base.two-lines .time-stamp{margin-inline:auto 2px}.base.two-lines.playback{grid-template-areas:\"slider slider\" \"controls playback\";grid-template-columns:1fr auto}.base.two-lines.playback .time-stamp{margin-inline:auto}.base .slider{box-sizing:border-box;min-inline-size:auto;padding-inline:2px}}";
@@ -24,6 +23,20 @@ var __decorateClass = (decorators, target, key, kind) => {
24
23
  __defProp(target, key, result);
25
24
  return result;
26
25
  };
26
+ const SKIP_DIRECTIONS = {
27
+ FORWARD: 1,
28
+ BACKWARD: -1
29
+ };
30
+ function formatTime(time) {
31
+ if (!time || Number.isNaN(time)) {
32
+ return "0:00";
33
+ }
34
+ const min = Math.floor(time / 60);
35
+ const sec = Math.floor(time % 60);
36
+ return min + ":" + (sec < 10 ? "0" + sec : sec);
37
+ }
38
+ const PAUSE = true;
39
+ const PLAY = false;
27
40
  const validSkipByConverter = {
28
41
  toView(value) {
29
42
  return value;
@@ -34,7 +47,7 @@ const validSkipByConverter = {
34
47
  };
35
48
  class AudioPlayer extends index.FoundationElement {
36
49
  constructor() {
37
- super(...arguments);
50
+ super();
38
51
  this.playButtonAriaLabel = null;
39
52
  this.pauseButtonAriaLabel = null;
40
53
  this.sliderAriaLabel = null;
@@ -42,106 +55,109 @@ class AudioPlayer extends index.FoundationElement {
42
55
  this.skipBackwardButtonAriaLabel = null;
43
56
  this.disabled = false;
44
57
  this.notime = false;
45
- this.paused = true;
46
- /**
47
- * @internal
48
- */
49
- this._rewind = () => {
50
- if (this._playerEl) {
51
- this._playerEl.currentTime = this._playerEl.duration * (Number(this._sliderEl.value) / 100);
58
+ this.#playerEl = new Audio();
59
+ this.#pausedChanged = (pausing) => {
60
+ if (pausing === this.paused) {
61
+ return;
62
+ }
63
+ if (!this.paused) {
64
+ this.#playerEl.pause();
65
+ } else {
66
+ this.#updateProgress();
67
+ this.#playerEl.play();
68
+ }
69
+ this.#setPausedState();
70
+ };
71
+ this.#updateProgress = () => {
72
+ index.Observable.notify(this, "currentTime");
73
+ const percent = this.currentTime / this.duration * 100;
74
+ if (percent === 100) {
75
+ this.pause();
76
+ }
77
+ };
78
+ this.#updateTotalTime = () => {
79
+ index.Observable.notify(this, "duration");
80
+ };
81
+ this.#rewind = () => {
82
+ if (this.#playerEl) {
83
+ this.currentTime = this.duration * Number(this.#sliderEl.value) / 100;
84
+ }
85
+ };
86
+ this.#handleSliderEvent = (event) => {
87
+ if (event.target === this.#sliderEl) {
88
+ this.pause();
89
+ this.#rewind();
52
90
  }
91
+ return true;
53
92
  };
93
+ this.#setPausedState = () => {
94
+ index.Observable.notify(this, "paused");
95
+ };
96
+ this.#playerEl.addEventListener("timeupdate", this.#updateProgress);
97
+ this.#playerEl.addEventListener("loadedmetadata", this.#updateTotalTime);
98
+ }
99
+ srcChanged() {
100
+ if (this.src === void 0) {
101
+ this.#playerEl.removeAttribute("src");
102
+ } else {
103
+ this.#playerEl.src = this.src;
104
+ }
105
+ }
106
+ get paused() {
107
+ index.Observable.track(this, "paused");
108
+ return this.#playerEl.paused;
109
+ }
110
+ set paused(_) {
111
+ }
112
+ get duration() {
113
+ index.Observable.track(this, "duration");
114
+ return this.#playerEl.duration;
115
+ }
116
+ set duration(_) {
117
+ }
118
+ get currentTime() {
119
+ index.Observable.track(this, "currentTime");
120
+ return this.#playerEl.currentTime;
121
+ }
122
+ set currentTime(value) {
123
+ this.#playerEl.currentTime = value;
124
+ }
125
+ get #sliderEl() {
126
+ return this.shadowRoot.querySelector(".slider");
127
+ }
128
+ #playerEl;
129
+ get #baseElement() {
130
+ return this.shadowRoot.querySelector(".base");
54
131
  }
55
132
  connectedCallback() {
56
133
  super.connectedCallback();
57
- document.addEventListener("mouseup", this._rewind);
134
+ document.addEventListener("mouseup", this.#rewind);
135
+ this.#setInteractionListeners();
136
+ this.#setPausedState();
58
137
  }
59
138
  disconnectedCallback() {
60
139
  super.disconnectedCallback();
61
- document.addEventListener("mouseup", this._rewind);
140
+ document.addEventListener("mouseup", this.#rewind);
141
+ this.#setInteractionListeners(false);
62
142
  }
63
- /**
64
- * @internal
65
- */
66
- _togglePlay() {
67
- if (this.paused) {
68
- this._updateProgress();
69
- this._playerEl.play();
70
- } else {
71
- this._playerEl.pause();
72
- }
73
- this.paused = !this.paused;
143
+ play() {
144
+ this.#pausedChanged(PLAY);
74
145
  }
75
- /**
76
- * @internal
77
- */
78
- _onSkipButtonClick(isForward) {
79
- if (this._playerEl) {
80
- const currentTime = this._playerEl.currentTime;
81
- const skipDirection = isForward ? 1 : -1;
82
- const skipValue = parseInt(this.skipBy) * skipDirection;
83
- const newTime = currentTime + skipValue;
84
- this._playerEl.currentTime = Math.max(
85
- 0,
86
- Math.min(this._playerEl.duration, newTime)
87
- );
88
- this._updateProgress();
89
- }
146
+ pause() {
147
+ this.#pausedChanged(PAUSE);
90
148
  }
91
- /**
92
- * @internal
93
- */
94
- _updateProgress() {
95
- let currentTime;
96
- const current = this._playerEl.currentTime;
97
- const percent = current / this._playerEl.duration * 100;
98
- if (this._sliderEl) {
99
- this._sliderEl.value = percent.toString();
100
- this._sliderEl.ariaValuetext = this._formatTime(current);
101
- }
102
- if (percent === 100) {
103
- this.paused = true;
104
- }
105
- if (this._timeStampEl) {
106
- currentTime = this._timeStampEl.querySelector(".current-time");
107
- if (currentTime)
108
- currentTime.textContent = this._formatTime(current);
109
- }
110
- }
111
- /**
112
- * @internal
113
- */
114
- _updateTotalTime() {
115
- let totalTime;
116
- if (this._playerEl)
117
- this.duration = this._playerEl.duration;
118
- if (this._timeStampEl) {
119
- totalTime = this._timeStampEl.querySelector(".total-time");
120
- if (totalTime)
121
- totalTime.textContent = this._formatTime(this._playerEl.duration);
122
- }
123
- }
124
- /**
125
- * @internal
126
- */
127
- _handleSliderEvent(event) {
128
- if (event.target === this._sliderEl) {
129
- this.paused = true;
130
- if (this._playerEl) {
131
- this._playerEl.pause();
132
- }
133
- this._rewind();
134
- }
135
- return true;
136
- }
137
- /**
138
- * @internal
139
- */
140
- _formatTime(time) {
141
- const min = Math.floor(time / 60);
142
- const sec = Math.floor(time % 60);
143
- return min + ":" + (sec < 10 ? "0" + sec : sec);
149
+ #setInteractionListeners(add = true) {
150
+ const action = add ? "addEventListener" : "removeEventListener";
151
+ this.#baseElement[action]("keyup", this.#handleSliderEvent);
152
+ this.#baseElement[action]("keydown", this.#handleSliderEvent);
153
+ this.#baseElement[action]("mousedown", this.#handleSliderEvent);
144
154
  }
155
+ #pausedChanged;
156
+ #updateProgress;
157
+ #updateTotalTime;
158
+ #rewind;
159
+ #handleSliderEvent;
160
+ #setPausedState;
145
161
  }
146
162
  __decorateClass([
147
163
  index.attr({ attribute: "play-button-aria-label" })
@@ -176,18 +192,27 @@ __decorateClass([
176
192
  converter: validSkipByConverter
177
193
  })
178
194
  ], AudioPlayer.prototype, "skipBy");
179
- __decorateClass([
180
- index.observable
181
- ], AudioPlayer.prototype, "paused");
182
- __decorateClass([
183
- index.observable
184
- ], AudioPlayer.prototype, "duration");
185
195
  applyMixins.applyMixins(AudioPlayer, localized.Localized);
186
196
 
197
+ function getCurrentTimePercentage(x) {
198
+ if (Number.isNaN(x.currentTime) || Number.isNaN(x.duration)) {
199
+ return 0;
200
+ }
201
+ return x.currentTime / x.duration * 100;
202
+ }
203
+ function skip(audioElement, skipDirection) {
204
+ const currentTime = audioElement.currentTime;
205
+ const skipValue = parseInt(audioElement.skipBy) * skipDirection;
206
+ const newTime = currentTime + skipValue;
207
+ audioElement.currentTime = Math.max(
208
+ 0,
209
+ Math.min(audioElement.duration, newTime)
210
+ );
211
+ }
187
212
  const getClasses = ({ disabled, duration }) => classNames.classNames(["disabled", Boolean(disabled) || !duration]);
188
213
  function renderButton(context) {
189
214
  const buttonTag = context.tagFor(definition.Button);
190
- return index.html`<${buttonTag} class="pause" @click="${(x) => x._togglePlay()}"
215
+ return index.html`<${buttonTag} class="pause" @click="${(x) => x.paused ? x.play() : x.pause()}"
191
216
  icon="${(x) => x.paused ? "play-solid" : "pause-solid"}"
192
217
  aria-label="${(x) => x.paused ? x.playButtonAriaLabel || x.locale.audioPlayer.playButtonLabel : x.pauseButtonAriaLabel || x.locale.audioPlayer.pauseButtonLabel}"
193
218
  size='condensed'
@@ -198,7 +223,8 @@ function renderButton(context) {
198
223
  function renderBackwardSkipButtons(context) {
199
224
  const buttonTag = context.tagFor(definition.Button);
200
225
  return index.html`
201
- <${buttonTag} class="skip backward" @click="${(x) => x._onSkipButtonClick(false)}"
226
+ <${buttonTag} class="skip backward"
227
+ @click="${(element) => skip(element, SKIP_DIRECTIONS.BACKWARD)}"
202
228
  icon="${(x) => x.skipBy == enums.MediaSkipBy.Five ? "5-sec-backward-line" : x.skipBy == enums.MediaSkipBy.Thirty ? "30-sec-backward-line" : "10-sec-backward-line"}"
203
229
  size='condensed'
204
230
  aria-label="${(x) => x.skipBackwardButtonAriaLabel || x.locale.audioPlayer.skipBackwardButton}"
@@ -210,7 +236,8 @@ function renderBackwardSkipButtons(context) {
210
236
  function renderForwardSkipButtons(context) {
211
237
  const buttonTag = context.tagFor(definition.Button);
212
238
  return index.html`
213
- <${buttonTag} class="skip forward" @click="${(x) => x._onSkipButtonClick(true)}"
239
+ <${buttonTag} class="skip forward"
240
+ @click="${(element) => skip(element, SKIP_DIRECTIONS.FORWARD)}"
214
241
  icon="${(x) => x.skipBy == enums.MediaSkipBy.Five ? "5-sec-forward-line" : x.skipBy == enums.MediaSkipBy.Thirty ? "30-sec-forward-line" : "10-sec-forward-line"}"
215
242
  size='condensed'
216
243
  aria-label="${(x) => x.skipForwardButtonAriaLabel || x.locale.audioPlayer.skipForwardButton}"
@@ -221,29 +248,26 @@ function renderForwardSkipButtons(context) {
221
248
  }
222
249
  function renderSlider(context) {
223
250
  const sliderTag = context.tagFor(definition$1.Slider);
224
- return index.html`<${sliderTag}
225
- ${ref.ref("_sliderEl")} class="slider"
226
- aria-label="${(x) => x.sliderAriaLabel || x.locale.audioPlayer.sliderLabel}"
227
- value="0" max="100"
228
- connotation="${(x) => x.connotation}"
229
- ?disabled="${(x) => x.disabled || !x.duration}">
251
+ return index.html`
252
+ <${sliderTag}
253
+ class="slider"
254
+ aria-label="${(x) => x.sliderAriaLabel || x.locale.audioPlayer.sliderLabel}"
255
+ value="${getCurrentTimePercentage}" max="100"
256
+ ariaValuetext="${(x) => formatTime(x.currentTime)}"
257
+ connotation="${(x) => x.connotation}"
258
+ ?disabled="${(x) => x.disabled || !x.duration}">
230
259
  </${sliderTag}>`;
231
260
  }
232
261
  function renderTimestamp() {
233
- return index.html` <div class="time-stamp" ${ref.ref("_timeStampEl")}>
234
- <span class="current-time">0:00</span>
262
+ return index.html` <div class="time-stamp">
263
+ <span class="current-time">${(x) => formatTime(x.currentTime)}</span>
235
264
  <span>/</span>
236
- <span class="total-time">0:00</span>
265
+ <span class="total-time">${(x) => formatTime(x.duration)}</span>
237
266
  </div>`;
238
267
  }
239
268
  const AudioPlayerTemplate = (context) => {
240
269
  return index.html` <div class="wrapper">
241
- <div
242
- class="base ${getClasses}"
243
- @keyup="${(x, c) => x._handleSliderEvent(c.event)}"
244
- @keydown="${(x, c) => x._handleSliderEvent(c.event)}"
245
- @mousedown="${(x, c) => x._handleSliderEvent(c.event)}"
246
- >
270
+ <div class="base ${getClasses}">
247
271
  <div class="controls">
248
272
  ${when.when(
249
273
  (x) => x.skipBy && x.skipBy != enums.MediaSkipBy.Zero,
@@ -257,12 +281,6 @@ const AudioPlayerTemplate = (context) => {
257
281
  ${when.when((x) => !x.notime, renderTimestamp())}
258
282
  </div>
259
283
  ${renderSlider(context)}
260
- <audio
261
- ${ref.ref("_playerEl")}
262
- src="${(x) => x.src}"
263
- @timeupdate="${(x) => x._updateProgress()}"
264
- @loadedmetadata="${(x) => x._updateTotalTime()}"
265
- ></audio>
266
284
  </div>
267
285
  </div>`;
268
286
  };
@@ -1,4 +1,4 @@
1
- import { a as attr, F as FoundationElement, o as observable, h as html, r as registerFactory } from './index.js';
1
+ import { a as attr, F as FoundationElement, O as Observable, h as html, r as registerFactory } from './index.js';
2
2
  import { B as Button, a as buttonRegistries } from './definition11.js';
3
3
  import { S as Slider, a as sliderRegistries } from './definition46.js';
4
4
  import { M as MediaSkipBy } from './enums.js';
@@ -7,7 +7,6 @@ import './index2.js';
7
7
  import { L as Localized } from './localized.js';
8
8
  import { a as applyMixins } from './apply-mixins.js';
9
9
  import { w as when } from './when.js';
10
- import { r as ref } from './ref.js';
11
10
  import { c as classNames } from './class-names.js';
12
11
 
13
12
  const styles = ":host{display:block;max-inline-size:350px}.wrapper{container-type:inline-size}.base{display:inline-flex;box-sizing:border-box;align-items:center;padding:8px;color:var(--vvd-color-canvas-text);gap:16px;inline-size:100%;user-select:none}.base .slider{flex:1;grid-area:slider;min-inline-size:var(--audio-player-min-inline-size, 200px)}.base .controls{display:flex;align-items:center;justify-content:center;gap:8px;grid-area:controls}.base .time-stamp{display:inline-flex}.base .time-stamp .current-time,.base .time-stamp .total-time{margin-inline:6px;min-inline-size:32px}.base .playback{grid-area:playback}@container (max-width: 500px){.base.two-lines{display:inline-grid;grid-template:auto auto/1fr;grid-template-areas:\"slider\" \"controls\";inline-size:100%;row-gap:4px}.base.two-lines .time-stamp{margin-inline:auto 2px}.base.two-lines.playback{grid-template-areas:\"slider slider\" \"controls playback\";grid-template-columns:1fr auto}.base.two-lines.playback .time-stamp{margin-inline:auto}.base .slider{box-sizing:border-box;min-inline-size:auto;padding-inline:2px}}";
@@ -22,6 +21,20 @@ var __decorateClass = (decorators, target, key, kind) => {
22
21
  __defProp(target, key, result);
23
22
  return result;
24
23
  };
24
+ const SKIP_DIRECTIONS = {
25
+ FORWARD: 1,
26
+ BACKWARD: -1
27
+ };
28
+ function formatTime(time) {
29
+ if (!time || Number.isNaN(time)) {
30
+ return "0:00";
31
+ }
32
+ const min = Math.floor(time / 60);
33
+ const sec = Math.floor(time % 60);
34
+ return min + ":" + (sec < 10 ? "0" + sec : sec);
35
+ }
36
+ const PAUSE = true;
37
+ const PLAY = false;
25
38
  const validSkipByConverter = {
26
39
  toView(value) {
27
40
  return value;
@@ -32,7 +45,7 @@ const validSkipByConverter = {
32
45
  };
33
46
  class AudioPlayer extends FoundationElement {
34
47
  constructor() {
35
- super(...arguments);
48
+ super();
36
49
  this.playButtonAriaLabel = null;
37
50
  this.pauseButtonAriaLabel = null;
38
51
  this.sliderAriaLabel = null;
@@ -40,106 +53,109 @@ class AudioPlayer extends FoundationElement {
40
53
  this.skipBackwardButtonAriaLabel = null;
41
54
  this.disabled = false;
42
55
  this.notime = false;
43
- this.paused = true;
44
- /**
45
- * @internal
46
- */
47
- this._rewind = () => {
48
- if (this._playerEl) {
49
- this._playerEl.currentTime = this._playerEl.duration * (Number(this._sliderEl.value) / 100);
56
+ this.#playerEl = new Audio();
57
+ this.#pausedChanged = (pausing) => {
58
+ if (pausing === this.paused) {
59
+ return;
60
+ }
61
+ if (!this.paused) {
62
+ this.#playerEl.pause();
63
+ } else {
64
+ this.#updateProgress();
65
+ this.#playerEl.play();
66
+ }
67
+ this.#setPausedState();
68
+ };
69
+ this.#updateProgress = () => {
70
+ Observable.notify(this, "currentTime");
71
+ const percent = this.currentTime / this.duration * 100;
72
+ if (percent === 100) {
73
+ this.pause();
74
+ }
75
+ };
76
+ this.#updateTotalTime = () => {
77
+ Observable.notify(this, "duration");
78
+ };
79
+ this.#rewind = () => {
80
+ if (this.#playerEl) {
81
+ this.currentTime = this.duration * Number(this.#sliderEl.value) / 100;
82
+ }
83
+ };
84
+ this.#handleSliderEvent = (event) => {
85
+ if (event.target === this.#sliderEl) {
86
+ this.pause();
87
+ this.#rewind();
50
88
  }
89
+ return true;
51
90
  };
91
+ this.#setPausedState = () => {
92
+ Observable.notify(this, "paused");
93
+ };
94
+ this.#playerEl.addEventListener("timeupdate", this.#updateProgress);
95
+ this.#playerEl.addEventListener("loadedmetadata", this.#updateTotalTime);
96
+ }
97
+ srcChanged() {
98
+ if (this.src === void 0) {
99
+ this.#playerEl.removeAttribute("src");
100
+ } else {
101
+ this.#playerEl.src = this.src;
102
+ }
103
+ }
104
+ get paused() {
105
+ Observable.track(this, "paused");
106
+ return this.#playerEl.paused;
107
+ }
108
+ set paused(_) {
109
+ }
110
+ get duration() {
111
+ Observable.track(this, "duration");
112
+ return this.#playerEl.duration;
113
+ }
114
+ set duration(_) {
115
+ }
116
+ get currentTime() {
117
+ Observable.track(this, "currentTime");
118
+ return this.#playerEl.currentTime;
119
+ }
120
+ set currentTime(value) {
121
+ this.#playerEl.currentTime = value;
122
+ }
123
+ get #sliderEl() {
124
+ return this.shadowRoot.querySelector(".slider");
125
+ }
126
+ #playerEl;
127
+ get #baseElement() {
128
+ return this.shadowRoot.querySelector(".base");
52
129
  }
53
130
  connectedCallback() {
54
131
  super.connectedCallback();
55
- document.addEventListener("mouseup", this._rewind);
132
+ document.addEventListener("mouseup", this.#rewind);
133
+ this.#setInteractionListeners();
134
+ this.#setPausedState();
56
135
  }
57
136
  disconnectedCallback() {
58
137
  super.disconnectedCallback();
59
- document.addEventListener("mouseup", this._rewind);
138
+ document.addEventListener("mouseup", this.#rewind);
139
+ this.#setInteractionListeners(false);
60
140
  }
61
- /**
62
- * @internal
63
- */
64
- _togglePlay() {
65
- if (this.paused) {
66
- this._updateProgress();
67
- this._playerEl.play();
68
- } else {
69
- this._playerEl.pause();
70
- }
71
- this.paused = !this.paused;
141
+ play() {
142
+ this.#pausedChanged(PLAY);
72
143
  }
73
- /**
74
- * @internal
75
- */
76
- _onSkipButtonClick(isForward) {
77
- if (this._playerEl) {
78
- const currentTime = this._playerEl.currentTime;
79
- const skipDirection = isForward ? 1 : -1;
80
- const skipValue = parseInt(this.skipBy) * skipDirection;
81
- const newTime = currentTime + skipValue;
82
- this._playerEl.currentTime = Math.max(
83
- 0,
84
- Math.min(this._playerEl.duration, newTime)
85
- );
86
- this._updateProgress();
87
- }
144
+ pause() {
145
+ this.#pausedChanged(PAUSE);
88
146
  }
89
- /**
90
- * @internal
91
- */
92
- _updateProgress() {
93
- let currentTime;
94
- const current = this._playerEl.currentTime;
95
- const percent = current / this._playerEl.duration * 100;
96
- if (this._sliderEl) {
97
- this._sliderEl.value = percent.toString();
98
- this._sliderEl.ariaValuetext = this._formatTime(current);
99
- }
100
- if (percent === 100) {
101
- this.paused = true;
102
- }
103
- if (this._timeStampEl) {
104
- currentTime = this._timeStampEl.querySelector(".current-time");
105
- if (currentTime)
106
- currentTime.textContent = this._formatTime(current);
107
- }
108
- }
109
- /**
110
- * @internal
111
- */
112
- _updateTotalTime() {
113
- let totalTime;
114
- if (this._playerEl)
115
- this.duration = this._playerEl.duration;
116
- if (this._timeStampEl) {
117
- totalTime = this._timeStampEl.querySelector(".total-time");
118
- if (totalTime)
119
- totalTime.textContent = this._formatTime(this._playerEl.duration);
120
- }
121
- }
122
- /**
123
- * @internal
124
- */
125
- _handleSliderEvent(event) {
126
- if (event.target === this._sliderEl) {
127
- this.paused = true;
128
- if (this._playerEl) {
129
- this._playerEl.pause();
130
- }
131
- this._rewind();
132
- }
133
- return true;
134
- }
135
- /**
136
- * @internal
137
- */
138
- _formatTime(time) {
139
- const min = Math.floor(time / 60);
140
- const sec = Math.floor(time % 60);
141
- return min + ":" + (sec < 10 ? "0" + sec : sec);
147
+ #setInteractionListeners(add = true) {
148
+ const action = add ? "addEventListener" : "removeEventListener";
149
+ this.#baseElement[action]("keyup", this.#handleSliderEvent);
150
+ this.#baseElement[action]("keydown", this.#handleSliderEvent);
151
+ this.#baseElement[action]("mousedown", this.#handleSliderEvent);
142
152
  }
153
+ #pausedChanged;
154
+ #updateProgress;
155
+ #updateTotalTime;
156
+ #rewind;
157
+ #handleSliderEvent;
158
+ #setPausedState;
143
159
  }
144
160
  __decorateClass([
145
161
  attr({ attribute: "play-button-aria-label" })
@@ -174,18 +190,27 @@ __decorateClass([
174
190
  converter: validSkipByConverter
175
191
  })
176
192
  ], AudioPlayer.prototype, "skipBy");
177
- __decorateClass([
178
- observable
179
- ], AudioPlayer.prototype, "paused");
180
- __decorateClass([
181
- observable
182
- ], AudioPlayer.prototype, "duration");
183
193
  applyMixins(AudioPlayer, Localized);
184
194
 
195
+ function getCurrentTimePercentage(x) {
196
+ if (Number.isNaN(x.currentTime) || Number.isNaN(x.duration)) {
197
+ return 0;
198
+ }
199
+ return x.currentTime / x.duration * 100;
200
+ }
201
+ function skip(audioElement, skipDirection) {
202
+ const currentTime = audioElement.currentTime;
203
+ const skipValue = parseInt(audioElement.skipBy) * skipDirection;
204
+ const newTime = currentTime + skipValue;
205
+ audioElement.currentTime = Math.max(
206
+ 0,
207
+ Math.min(audioElement.duration, newTime)
208
+ );
209
+ }
185
210
  const getClasses = ({ disabled, duration }) => classNames(["disabled", Boolean(disabled) || !duration]);
186
211
  function renderButton(context) {
187
212
  const buttonTag = context.tagFor(Button);
188
- return html`<${buttonTag} class="pause" @click="${(x) => x._togglePlay()}"
213
+ return html`<${buttonTag} class="pause" @click="${(x) => x.paused ? x.play() : x.pause()}"
189
214
  icon="${(x) => x.paused ? "play-solid" : "pause-solid"}"
190
215
  aria-label="${(x) => x.paused ? x.playButtonAriaLabel || x.locale.audioPlayer.playButtonLabel : x.pauseButtonAriaLabel || x.locale.audioPlayer.pauseButtonLabel}"
191
216
  size='condensed'
@@ -196,7 +221,8 @@ function renderButton(context) {
196
221
  function renderBackwardSkipButtons(context) {
197
222
  const buttonTag = context.tagFor(Button);
198
223
  return html`
199
- <${buttonTag} class="skip backward" @click="${(x) => x._onSkipButtonClick(false)}"
224
+ <${buttonTag} class="skip backward"
225
+ @click="${(element) => skip(element, SKIP_DIRECTIONS.BACKWARD)}"
200
226
  icon="${(x) => x.skipBy == MediaSkipBy.Five ? "5-sec-backward-line" : x.skipBy == MediaSkipBy.Thirty ? "30-sec-backward-line" : "10-sec-backward-line"}"
201
227
  size='condensed'
202
228
  aria-label="${(x) => x.skipBackwardButtonAriaLabel || x.locale.audioPlayer.skipBackwardButton}"
@@ -208,7 +234,8 @@ function renderBackwardSkipButtons(context) {
208
234
  function renderForwardSkipButtons(context) {
209
235
  const buttonTag = context.tagFor(Button);
210
236
  return html`
211
- <${buttonTag} class="skip forward" @click="${(x) => x._onSkipButtonClick(true)}"
237
+ <${buttonTag} class="skip forward"
238
+ @click="${(element) => skip(element, SKIP_DIRECTIONS.FORWARD)}"
212
239
  icon="${(x) => x.skipBy == MediaSkipBy.Five ? "5-sec-forward-line" : x.skipBy == MediaSkipBy.Thirty ? "30-sec-forward-line" : "10-sec-forward-line"}"
213
240
  size='condensed'
214
241
  aria-label="${(x) => x.skipForwardButtonAriaLabel || x.locale.audioPlayer.skipForwardButton}"
@@ -219,29 +246,26 @@ function renderForwardSkipButtons(context) {
219
246
  }
220
247
  function renderSlider(context) {
221
248
  const sliderTag = context.tagFor(Slider);
222
- return html`<${sliderTag}
223
- ${ref("_sliderEl")} class="slider"
224
- aria-label="${(x) => x.sliderAriaLabel || x.locale.audioPlayer.sliderLabel}"
225
- value="0" max="100"
226
- connotation="${(x) => x.connotation}"
227
- ?disabled="${(x) => x.disabled || !x.duration}">
249
+ return html`
250
+ <${sliderTag}
251
+ class="slider"
252
+ aria-label="${(x) => x.sliderAriaLabel || x.locale.audioPlayer.sliderLabel}"
253
+ value="${getCurrentTimePercentage}" max="100"
254
+ ariaValuetext="${(x) => formatTime(x.currentTime)}"
255
+ connotation="${(x) => x.connotation}"
256
+ ?disabled="${(x) => x.disabled || !x.duration}">
228
257
  </${sliderTag}>`;
229
258
  }
230
259
  function renderTimestamp() {
231
- return html` <div class="time-stamp" ${ref("_timeStampEl")}>
232
- <span class="current-time">0:00</span>
260
+ return html` <div class="time-stamp">
261
+ <span class="current-time">${(x) => formatTime(x.currentTime)}</span>
233
262
  <span>/</span>
234
- <span class="total-time">0:00</span>
263
+ <span class="total-time">${(x) => formatTime(x.duration)}</span>
235
264
  </div>`;
236
265
  }
237
266
  const AudioPlayerTemplate = (context) => {
238
267
  return html` <div class="wrapper">
239
- <div
240
- class="base ${getClasses}"
241
- @keyup="${(x, c) => x._handleSliderEvent(c.event)}"
242
- @keydown="${(x, c) => x._handleSliderEvent(c.event)}"
243
- @mousedown="${(x, c) => x._handleSliderEvent(c.event)}"
244
- >
268
+ <div class="base ${getClasses}">
245
269
  <div class="controls">
246
270
  ${when(
247
271
  (x) => x.skipBy && x.skipBy != MediaSkipBy.Zero,
@@ -255,12 +279,6 @@ const AudioPlayerTemplate = (context) => {
255
279
  ${when((x) => !x.notime, renderTimestamp())}
256
280
  </div>
257
281
  ${renderSlider(context)}
258
- <audio
259
- ${ref("_playerEl")}
260
- src="${(x) => x.src}"
261
- @timeupdate="${(x) => x._updateProgress()}"
262
- @loadedmetadata="${(x) => x._updateTotalTime()}"
263
- ></audio>
264
282
  </div>
265
283
  </div>`;
266
284
  };