@livepeer-frameworks/player-wc 0.1.8 → 0.2.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 (141) hide show
  1. package/dist/esm/components/controls/fw-fullscreen-button.js +76 -0
  2. package/dist/esm/components/controls/fw-fullscreen-button.js.map +1 -0
  3. package/dist/esm/components/controls/fw-live-badge.js +109 -0
  4. package/dist/esm/components/controls/fw-live-badge.js.map +1 -0
  5. package/dist/esm/components/controls/fw-play-button.js +76 -0
  6. package/dist/esm/components/controls/fw-play-button.js.map +1 -0
  7. package/dist/esm/components/controls/fw-skip-button.js +62 -0
  8. package/dist/esm/components/controls/fw-skip-button.js.map +1 -0
  9. package/dist/esm/components/controls/fw-time-display.js +77 -0
  10. package/dist/esm/components/controls/fw-time-display.js.map +1 -0
  11. package/dist/esm/components/controls/fw-volume-control.js +76 -0
  12. package/dist/esm/components/controls/fw-volume-control.js.map +1 -0
  13. package/dist/esm/components/fw-dev-mode-panel.js +11 -15
  14. package/dist/esm/components/fw-dev-mode-panel.js.map +1 -1
  15. package/dist/esm/components/fw-error-overlay.js +13 -5
  16. package/dist/esm/components/fw-error-overlay.js.map +1 -1
  17. package/dist/esm/components/fw-idle-screen.js +10 -2
  18. package/dist/esm/components/fw-idle-screen.js.map +1 -1
  19. package/dist/esm/components/fw-loading-screen.js +89 -42
  20. package/dist/esm/components/fw-loading-screen.js.map +1 -1
  21. package/dist/esm/components/fw-loading-spinner.js +20 -9
  22. package/dist/esm/components/fw-loading-spinner.js.map +1 -1
  23. package/dist/esm/components/fw-player-controls.js +41 -26
  24. package/dist/esm/components/fw-player-controls.js.map +1 -1
  25. package/dist/esm/components/fw-player.js +165 -59
  26. package/dist/esm/components/fw-player.js.map +1 -1
  27. package/dist/esm/components/fw-settings-menu.js +44 -9
  28. package/dist/esm/components/fw-settings-menu.js.map +1 -1
  29. package/dist/esm/components/fw-stream-state-overlay.js +13 -5
  30. package/dist/esm/components/fw-stream-state-overlay.js.map +1 -1
  31. package/dist/esm/components/fw-toast.js +11 -1
  32. package/dist/esm/components/fw-toast.js.map +1 -1
  33. package/dist/esm/components/fw-volume-control.js +104 -39
  34. package/dist/esm/components/fw-volume-control.js.map +1 -1
  35. package/dist/esm/controllers/player-controller-host.js +14 -1
  36. package/dist/esm/controllers/player-controller-host.js.map +1 -1
  37. package/dist/esm/index.js +6 -0
  38. package/dist/esm/index.js.map +1 -1
  39. package/dist/esm/styles/shared-styles.js +401 -304
  40. package/dist/esm/styles/shared-styles.js.map +1 -1
  41. package/dist/fw-player.iife.js +722 -499
  42. package/dist/types/components/controls/fw-fullscreen-button.d.ts +18 -0
  43. package/dist/types/components/controls/fw-live-badge.d.ts +19 -0
  44. package/dist/types/components/controls/fw-play-button.d.ts +18 -0
  45. package/dist/types/components/controls/fw-skip-button.d.ts +17 -0
  46. package/dist/types/components/controls/fw-time-display.d.ts +17 -0
  47. package/dist/types/components/controls/fw-volume-control.d.ts +18 -0
  48. package/dist/types/components/controls/index.d.ts +6 -0
  49. package/dist/types/components/fw-dev-mode-panel.d.ts +1 -1
  50. package/dist/types/components/fw-error-overlay.d.ts +4 -0
  51. package/dist/types/components/fw-idle-screen.d.ts +4 -0
  52. package/dist/types/components/fw-loading-screen.d.ts +5 -1
  53. package/dist/types/components/fw-loading-spinner.d.ts +4 -0
  54. package/dist/types/components/fw-player-controls.d.ts +3 -1
  55. package/dist/types/components/fw-player.d.ts +10 -1
  56. package/dist/types/components/fw-settings-menu.d.ts +3 -1
  57. package/dist/types/components/fw-stream-state-overlay.d.ts +4 -0
  58. package/dist/types/components/fw-toast.d.ts +4 -0
  59. package/dist/types/components/fw-volume-control.d.ts +11 -0
  60. package/dist/types/controllers/player-controller-host.d.ts +7 -1
  61. package/dist/types/index.d.ts +1 -0
  62. package/package.json +10 -13
  63. package/src/components/controls/fw-fullscreen-button.ts +75 -0
  64. package/src/components/controls/fw-live-badge.ts +109 -0
  65. package/src/components/controls/fw-play-button.ts +75 -0
  66. package/src/components/controls/fw-skip-button.ts +59 -0
  67. package/src/components/controls/fw-time-display.ts +74 -0
  68. package/src/components/controls/fw-volume-control.ts +75 -0
  69. package/src/components/controls/index.ts +6 -0
  70. package/src/components/fw-dev-mode-panel.ts +10 -17
  71. package/src/components/fw-error-overlay.ts +13 -5
  72. package/src/components/fw-idle-screen.ts +10 -2
  73. package/src/components/fw-loading-screen.ts +90 -46
  74. package/src/components/fw-loading-spinner.ts +18 -9
  75. package/src/components/fw-player-controls.ts +39 -28
  76. package/src/components/fw-player.ts +166 -64
  77. package/src/components/fw-settings-menu.ts +49 -9
  78. package/src/components/fw-stream-state-overlay.ts +13 -5
  79. package/src/components/fw-toast.ts +11 -1
  80. package/src/components/fw-volume-control.ts +112 -43
  81. package/src/controllers/player-controller-host.ts +18 -0
  82. package/src/index.ts +10 -0
  83. package/src/styles/shared-styles.ts +401 -304
  84. package/dist/cjs/components/fw-context-menu.js +0 -17
  85. package/dist/cjs/components/fw-context-menu.js.map +0 -1
  86. package/dist/cjs/components/fw-dev-mode-panel.js +0 -907
  87. package/dist/cjs/components/fw-dev-mode-panel.js.map +0 -1
  88. package/dist/cjs/components/fw-dvd-logo.js +0 -211
  89. package/dist/cjs/components/fw-dvd-logo.js.map +0 -1
  90. package/dist/cjs/components/fw-error-overlay.js +0 -101
  91. package/dist/cjs/components/fw-error-overlay.js.map +0 -1
  92. package/dist/cjs/components/fw-idle-screen.js +0 -726
  93. package/dist/cjs/components/fw-idle-screen.js.map +0 -1
  94. package/dist/cjs/components/fw-loading-screen.js +0 -513
  95. package/dist/cjs/components/fw-loading-screen.js.map +0 -1
  96. package/dist/cjs/components/fw-loading-spinner.js +0 -62
  97. package/dist/cjs/components/fw-loading-spinner.js.map +0 -1
  98. package/dist/cjs/components/fw-player-controls.js +0 -441
  99. package/dist/cjs/components/fw-player-controls.js.map +0 -1
  100. package/dist/cjs/components/fw-player.js +0 -832
  101. package/dist/cjs/components/fw-player.js.map +0 -1
  102. package/dist/cjs/components/fw-seek-bar.js +0 -383
  103. package/dist/cjs/components/fw-seek-bar.js.map +0 -1
  104. package/dist/cjs/components/fw-settings-menu.js +0 -253
  105. package/dist/cjs/components/fw-settings-menu.js.map +0 -1
  106. package/dist/cjs/components/fw-skip-indicator.js +0 -143
  107. package/dist/cjs/components/fw-skip-indicator.js.map +0 -1
  108. package/dist/cjs/components/fw-speed-indicator.js +0 -61
  109. package/dist/cjs/components/fw-speed-indicator.js.map +0 -1
  110. package/dist/cjs/components/fw-stats-panel.js +0 -205
  111. package/dist/cjs/components/fw-stats-panel.js.map +0 -1
  112. package/dist/cjs/components/fw-stream-state-overlay.js +0 -338
  113. package/dist/cjs/components/fw-stream-state-overlay.js.map +0 -1
  114. package/dist/cjs/components/fw-subtitle-renderer.js +0 -217
  115. package/dist/cjs/components/fw-subtitle-renderer.js.map +0 -1
  116. package/dist/cjs/components/fw-thumbnail-overlay.js +0 -161
  117. package/dist/cjs/components/fw-thumbnail-overlay.js.map +0 -1
  118. package/dist/cjs/components/fw-title-overlay.js +0 -72
  119. package/dist/cjs/components/fw-title-overlay.js.map +0 -1
  120. package/dist/cjs/components/fw-toast.js +0 -74
  121. package/dist/cjs/components/fw-toast.js.map +0 -1
  122. package/dist/cjs/components/fw-volume-control.js +0 -221
  123. package/dist/cjs/components/fw-volume-control.js.map +0 -1
  124. package/dist/cjs/components/shared/hitmarker-audio.js +0 -76
  125. package/dist/cjs/components/shared/hitmarker-audio.js.map +0 -1
  126. package/dist/cjs/constants/media-assets.js +0 -11
  127. package/dist/cjs/constants/media-assets.js.map +0 -1
  128. package/dist/cjs/controllers/player-controller-host.js +0 -364
  129. package/dist/cjs/controllers/player-controller-host.js.map +0 -1
  130. package/dist/cjs/define.js +0 -53
  131. package/dist/cjs/define.js.map +0 -1
  132. package/dist/cjs/icons/index.js +0 -180
  133. package/dist/cjs/icons/index.js.map +0 -1
  134. package/dist/cjs/index.js +0 -108
  135. package/dist/cjs/index.js.map +0 -1
  136. package/dist/cjs/node_modules/.pnpm/@rollup_plugin-typescript@12.3.0_rollup@4.57.1_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.js +0 -33
  137. package/dist/cjs/node_modules/.pnpm/@rollup_plugin-typescript@12.3.0_rollup@4.57.1_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.js.map +0 -1
  138. package/dist/cjs/styles/shared-styles.js +0 -1985
  139. package/dist/cjs/styles/shared-styles.js.map +0 -1
  140. package/dist/cjs/styles/utility-styles.js +0 -725
  141. package/dist/cjs/styles/utility-styles.js.map +0 -1
@@ -15,9 +15,11 @@ export class FwVolumeControl extends LitElement {
15
15
 
16
16
  @state() private _hovered = false;
17
17
  @state() private _focused = false;
18
+ @state() private _dragging = false;
18
19
  @state() private _hasAudio = true;
19
20
 
20
21
  private _activePointerId: number | null = null;
22
+ private _activeSliderTarget: HTMLElement | null = null;
21
23
 
22
24
  static styles = [
23
25
  sharedStyles,
@@ -34,6 +36,8 @@ export class FwVolumeControl extends LitElement {
34
36
  background: rgb(255 255 255 / 0.2);
35
37
  border-radius: 9999px;
36
38
  cursor: pointer;
39
+ touch-action: none;
40
+ user-select: none;
37
41
  }
38
42
 
39
43
  .slider-fill {
@@ -59,7 +63,12 @@ export class FwVolumeControl extends LitElement {
59
63
  ];
60
64
 
61
65
  private get _expanded(): boolean {
62
- return this._hovered || this._focused;
66
+ return this._hovered || this._focused || this._dragging;
67
+ }
68
+
69
+ disconnectedCallback(): void {
70
+ super.disconnectedCallback();
71
+ this._endDragInteraction();
63
72
  }
64
73
 
65
74
  protected updated(): void {
@@ -67,6 +76,13 @@ export class FwVolumeControl extends LitElement {
67
76
  }
68
77
 
69
78
  private _updateHasAudio(): void {
79
+ // Primary: trust MistServer stream metadata (matches ddvtech embed approach)
80
+ const mistHasAudio = this.pc?.s.streamState?.streamInfo?.hasAudio;
81
+ if (mistHasAudio !== undefined) {
82
+ this._hasAudio = mistHasAudio;
83
+ return;
84
+ }
85
+
70
86
  const video = this.pc?.s.videoElement;
71
87
  if (!video) {
72
88
  this._hasAudio = true;
@@ -106,6 +122,89 @@ export class FwVolumeControl extends LitElement {
106
122
  }
107
123
  }
108
124
 
125
+ private _beginDragInteraction(target: HTMLElement, pointerId: number): void {
126
+ this._activePointerId = pointerId;
127
+ this._activeSliderTarget = target;
128
+ this._dragging = true;
129
+ this._hovered = true;
130
+ this._focused = true;
131
+
132
+ try {
133
+ target.setPointerCapture(pointerId);
134
+ } catch {
135
+ // Non-fatal: we still listen on window as a fallback.
136
+ }
137
+
138
+ window.addEventListener("pointermove", this._onGlobalPointerMove);
139
+ window.addEventListener("pointerup", this._onGlobalPointerUp);
140
+ window.addEventListener("pointercancel", this._onGlobalPointerUp);
141
+ }
142
+
143
+ private _endDragInteraction(): void {
144
+ const pointerId = this._activePointerId;
145
+ const target = this._activeSliderTarget;
146
+ if (pointerId != null && target) {
147
+ try {
148
+ if (target.hasPointerCapture(pointerId)) {
149
+ target.releasePointerCapture(pointerId);
150
+ }
151
+ } catch {
152
+ // Ignore pointer-capture release errors.
153
+ }
154
+ }
155
+
156
+ this._activePointerId = null;
157
+ this._activeSliderTarget = null;
158
+ this._dragging = false;
159
+ window.removeEventListener("pointermove", this._onGlobalPointerMove);
160
+ window.removeEventListener("pointerup", this._onGlobalPointerUp);
161
+ window.removeEventListener("pointercancel", this._onGlobalPointerUp);
162
+ }
163
+
164
+ private _onGlobalPointerMove = (event: PointerEvent): void => {
165
+ if (!this._dragging || this._activePointerId !== event.pointerId) {
166
+ return;
167
+ }
168
+ const target = this._activeSliderTarget;
169
+ if (!target) {
170
+ return;
171
+ }
172
+ this._setVolumeFromClientX(event.clientX, target);
173
+ };
174
+
175
+ private _onGlobalPointerUp = (event: PointerEvent): void => {
176
+ if (!this._dragging || this._activePointerId !== event.pointerId) {
177
+ return;
178
+ }
179
+ this._endDragInteraction();
180
+ };
181
+
182
+ private _handleMouseEnter = (): void => {
183
+ this._hovered = true;
184
+ };
185
+
186
+ private _handleMouseLeave = (): void => {
187
+ if (this._dragging) {
188
+ return;
189
+ }
190
+ this._hovered = false;
191
+ this._focused = false;
192
+ };
193
+
194
+ private _handleFocusIn = (): void => {
195
+ this._focused = true;
196
+ };
197
+
198
+ private _handleFocusOut = (event: FocusEvent): void => {
199
+ if (this._dragging) {
200
+ return;
201
+ }
202
+ const related = event.relatedTarget as Node | null;
203
+ if (!related || !this.renderRoot.contains(related)) {
204
+ this._focused = false;
205
+ }
206
+ };
207
+
109
208
  private _onSliderPointerDown = (event: PointerEvent) => {
110
209
  if (!this._hasAudio) {
111
210
  return;
@@ -113,30 +212,8 @@ export class FwVolumeControl extends LitElement {
113
212
 
114
213
  event.preventDefault();
115
214
  const target = event.currentTarget as HTMLElement;
116
- this._activePointerId = event.pointerId;
215
+ this._beginDragInteraction(target, event.pointerId);
117
216
  this._setVolumeFromClientX(event.clientX, target);
118
-
119
- const onMove = (moveEvent: PointerEvent) => {
120
- if (this._activePointerId !== moveEvent.pointerId) {
121
- return;
122
- }
123
- this._setVolumeFromClientX(moveEvent.clientX, target);
124
- };
125
-
126
- const onUp = (upEvent: PointerEvent) => {
127
- if (this._activePointerId !== upEvent.pointerId) {
128
- return;
129
- }
130
-
131
- this._activePointerId = null;
132
- window.removeEventListener("pointermove", onMove);
133
- window.removeEventListener("pointerup", onUp);
134
- window.removeEventListener("pointercancel", onUp);
135
- };
136
-
137
- window.addEventListener("pointermove", onMove);
138
- window.addEventListener("pointerup", onUp);
139
- window.addEventListener("pointercancel", onUp);
140
217
  };
141
218
 
142
219
  private _onWheel = (event: WheelEvent) => {
@@ -170,22 +247,10 @@ export class FwVolumeControl extends LitElement {
170
247
  })}
171
248
  role="group"
172
249
  aria-label="Volume controls"
173
- @mouseenter=${() => {
174
- this._hovered = true;
175
- }}
176
- @mouseleave=${() => {
177
- this._hovered = false;
178
- this._focused = false;
179
- }}
180
- @focusin=${() => {
181
- this._focused = true;
182
- }}
183
- @focusout=${(event: FocusEvent) => {
184
- const related = event.relatedTarget as Node | null;
185
- if (!related || !this.renderRoot.contains(related)) {
186
- this._focused = false;
187
- }
188
- }}
250
+ @mouseenter=${this._handleMouseEnter}
251
+ @mouseleave=${this._handleMouseLeave}
252
+ @focusin=${this._handleFocusIn}
253
+ @focusout=${this._handleFocusOut}
189
254
  @click=${(event: MouseEvent) => {
190
255
  if (this._hasAudio && event.target === event.currentTarget) {
191
256
  this.pc.toggleMute();
@@ -202,8 +267,12 @@ export class FwVolumeControl extends LitElement {
202
267
  }
203
268
  }}
204
269
  ?disabled=${!this._hasAudio}
205
- aria-label=${!this._hasAudio ? "No audio" : isMuted ? "Unmute" : "Mute"}
206
- title=${!this._hasAudio ? "No audio" : isMuted ? "Unmute" : "Mute"}
270
+ aria-label=${!this._hasAudio
271
+ ? "No audio"
272
+ : isMuted
273
+ ? this.pc.t("unmute")
274
+ : this.pc.t("mute")}
275
+ title=${!this._hasAudio ? "No audio" : isMuted ? this.pc.t("unmute") : this.pc.t("mute")}
207
276
  >
208
277
  ${isMuted || !this._hasAudio ? volumeOffIcon(16) : volumeUpIcon(16)}
209
278
  </button>
@@ -218,7 +287,7 @@ export class FwVolumeControl extends LitElement {
218
287
  <div
219
288
  class="slider"
220
289
  role="slider"
221
- aria-label="Volume"
290
+ aria-label=${this.pc.t("volume")}
222
291
  aria-valuemin="0"
223
292
  aria-valuemax="100"
224
293
  aria-valuenow=${Math.round(displayVolume * 100)}
@@ -5,6 +5,7 @@
5
5
  import type { ReactiveController, ReactiveControllerHost } from "lit";
6
6
  import {
7
7
  PlayerController,
8
+ createTranslator,
8
9
  type PlayerControllerConfig,
9
10
  type PlayerState,
10
11
  type StreamState,
@@ -13,6 +14,8 @@ import {
13
14
  type ContentEndpoints,
14
15
  type ContentMetadata,
15
16
  type ClassifiedError,
17
+ type TranslateFn,
18
+ type I18nConfig,
16
19
  } from "@livepeer-frameworks/player-core";
17
20
 
18
21
  export interface PlayerControllerHostState {
@@ -105,11 +108,20 @@ export class PlayerControllerHost implements ReactiveController {
105
108
 
106
109
  s: PlayerControllerHostState = { ...initialState };
107
110
 
111
+ /** Translation function, updated when locale changes. */
112
+ t: TranslateFn = createTranslator({ locale: "en" });
113
+
108
114
  constructor(host: HostElement) {
109
115
  this.host = host;
110
116
  host.addController(this);
111
117
  }
112
118
 
119
+ /** Rebuild the translator when locale or custom translations change. */
120
+ updateTranslator(config: I18nConfig) {
121
+ this.t = createTranslator(config);
122
+ this.host.requestUpdate();
123
+ }
124
+
113
125
  // ---- Configuration & Lifecycle ----
114
126
 
115
127
  configure(config: PlayerControllerConfig) {
@@ -434,6 +446,12 @@ export class PlayerControllerHost implements ReactiveController {
434
446
  async retry() {
435
447
  await this.controller?.retry();
436
448
  }
449
+ async tryNextSource() {
450
+ await this.controller?.retryWithFallback();
451
+ }
452
+ canAttemptFallback(): boolean {
453
+ return this.controller?.canAttemptFallback() ?? false;
454
+ }
437
455
  async reload() {
438
456
  await this.controller?.reload();
439
457
  }
package/src/index.ts CHANGED
@@ -30,6 +30,16 @@ export { FwSkipIndicator } from "./components/fw-skip-indicator.js";
30
30
  export { FwSpeedIndicator } from "./components/fw-speed-indicator.js";
31
31
  export { FwContextMenu } from "./components/fw-context-menu.js";
32
32
 
33
+ // Composable control elements
34
+ export {
35
+ FwPlayButton,
36
+ FwSkipButton,
37
+ FwVolumeControl as FwVolumeButton,
38
+ FwTimeDisplay,
39
+ FwLiveBadge,
40
+ FwFullscreenButton,
41
+ } from "./components/controls/index.js";
42
+
33
43
  // Controller
34
44
  export { PlayerControllerHost } from "./controllers/player-controller-host.js";
35
45
  export type { PlayerControllerHostState } from "./controllers/player-controller-host.js";