@livepeer-frameworks/player-wc 0.1.9 → 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 (140) 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 +18 -13
  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 +13 -3
  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 +707 -488
  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 +2 -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/controllers/player-controller-host.d.ts +7 -1
  60. package/dist/types/index.d.ts +1 -0
  61. package/package.json +10 -13
  62. package/src/components/controls/fw-fullscreen-button.ts +75 -0
  63. package/src/components/controls/fw-live-badge.ts +109 -0
  64. package/src/components/controls/fw-play-button.ts +75 -0
  65. package/src/components/controls/fw-skip-button.ts +59 -0
  66. package/src/components/controls/fw-time-display.ts +74 -0
  67. package/src/components/controls/fw-volume-control.ts +75 -0
  68. package/src/components/controls/index.ts +6 -0
  69. package/src/components/fw-dev-mode-panel.ts +10 -17
  70. package/src/components/fw-error-overlay.ts +13 -5
  71. package/src/components/fw-idle-screen.ts +10 -2
  72. package/src/components/fw-loading-screen.ts +90 -46
  73. package/src/components/fw-loading-spinner.ts +18 -9
  74. package/src/components/fw-player-controls.ts +17 -13
  75. package/src/components/fw-player.ts +166 -64
  76. package/src/components/fw-settings-menu.ts +49 -9
  77. package/src/components/fw-stream-state-overlay.ts +13 -5
  78. package/src/components/fw-toast.ts +11 -1
  79. package/src/components/fw-volume-control.ts +14 -3
  80. package/src/controllers/player-controller-host.ts +18 -0
  81. package/src/index.ts +10 -0
  82. package/src/styles/shared-styles.ts +401 -304
  83. package/dist/cjs/components/fw-context-menu.js +0 -17
  84. package/dist/cjs/components/fw-context-menu.js.map +0 -1
  85. package/dist/cjs/components/fw-dev-mode-panel.js +0 -907
  86. package/dist/cjs/components/fw-dev-mode-panel.js.map +0 -1
  87. package/dist/cjs/components/fw-dvd-logo.js +0 -211
  88. package/dist/cjs/components/fw-dvd-logo.js.map +0 -1
  89. package/dist/cjs/components/fw-error-overlay.js +0 -101
  90. package/dist/cjs/components/fw-error-overlay.js.map +0 -1
  91. package/dist/cjs/components/fw-idle-screen.js +0 -726
  92. package/dist/cjs/components/fw-idle-screen.js.map +0 -1
  93. package/dist/cjs/components/fw-loading-screen.js +0 -513
  94. package/dist/cjs/components/fw-loading-screen.js.map +0 -1
  95. package/dist/cjs/components/fw-loading-spinner.js +0 -62
  96. package/dist/cjs/components/fw-loading-spinner.js.map +0 -1
  97. package/dist/cjs/components/fw-player-controls.js +0 -451
  98. package/dist/cjs/components/fw-player-controls.js.map +0 -1
  99. package/dist/cjs/components/fw-player.js +0 -832
  100. package/dist/cjs/components/fw-player.js.map +0 -1
  101. package/dist/cjs/components/fw-seek-bar.js +0 -383
  102. package/dist/cjs/components/fw-seek-bar.js.map +0 -1
  103. package/dist/cjs/components/fw-settings-menu.js +0 -253
  104. package/dist/cjs/components/fw-settings-menu.js.map +0 -1
  105. package/dist/cjs/components/fw-skip-indicator.js +0 -143
  106. package/dist/cjs/components/fw-skip-indicator.js.map +0 -1
  107. package/dist/cjs/components/fw-speed-indicator.js +0 -61
  108. package/dist/cjs/components/fw-speed-indicator.js.map +0 -1
  109. package/dist/cjs/components/fw-stats-panel.js +0 -205
  110. package/dist/cjs/components/fw-stats-panel.js.map +0 -1
  111. package/dist/cjs/components/fw-stream-state-overlay.js +0 -338
  112. package/dist/cjs/components/fw-stream-state-overlay.js.map +0 -1
  113. package/dist/cjs/components/fw-subtitle-renderer.js +0 -217
  114. package/dist/cjs/components/fw-subtitle-renderer.js.map +0 -1
  115. package/dist/cjs/components/fw-thumbnail-overlay.js +0 -161
  116. package/dist/cjs/components/fw-thumbnail-overlay.js.map +0 -1
  117. package/dist/cjs/components/fw-title-overlay.js +0 -72
  118. package/dist/cjs/components/fw-title-overlay.js.map +0 -1
  119. package/dist/cjs/components/fw-toast.js +0 -74
  120. package/dist/cjs/components/fw-toast.js.map +0 -1
  121. package/dist/cjs/components/fw-volume-control.js +0 -276
  122. package/dist/cjs/components/fw-volume-control.js.map +0 -1
  123. package/dist/cjs/components/shared/hitmarker-audio.js +0 -76
  124. package/dist/cjs/components/shared/hitmarker-audio.js.map +0 -1
  125. package/dist/cjs/constants/media-assets.js +0 -11
  126. package/dist/cjs/constants/media-assets.js.map +0 -1
  127. package/dist/cjs/controllers/player-controller-host.js +0 -364
  128. package/dist/cjs/controllers/player-controller-host.js.map +0 -1
  129. package/dist/cjs/define.js +0 -53
  130. package/dist/cjs/define.js.map +0 -1
  131. package/dist/cjs/icons/index.js +0 -180
  132. package/dist/cjs/icons/index.js.map +0 -1
  133. package/dist/cjs/index.js +0 -108
  134. package/dist/cjs/index.js.map +0 -1
  135. 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
  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.map +0 -1
  137. package/dist/cjs/styles/shared-styles.js +0 -1985
  138. package/dist/cjs/styles/shared-styles.js.map +0 -1
  139. package/dist/cjs/styles/utility-styles.js +0 -725
  140. package/dist/cjs/styles/utility-styles.js.map +0 -1
@@ -0,0 +1,59 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+ import { createTranslator, type TranslateFn } from "@livepeer-frameworks/player-core";
4
+
5
+ @customElement("fw-skip-button")
6
+ export class FwSkipButton extends LitElement {
7
+ @property({ type: String }) direction: "back" | "forward" = "forward";
8
+ @property({ type: Number }) seconds = 10;
9
+ private _player: any = null;
10
+
11
+ private get _t(): TranslateFn {
12
+ return this._player?.pc?.t ?? createTranslator({ locale: "en" });
13
+ }
14
+
15
+ static styles = css`
16
+ :host {
17
+ display: inline-flex;
18
+ align-items: center;
19
+ }
20
+ `;
21
+
22
+ private _resolvePlayer(): HTMLElement | null {
23
+ const forId = this.getAttribute("for");
24
+ if (forId) return document.getElementById(forId);
25
+ return this.closest("fw-player");
26
+ }
27
+
28
+ connectedCallback() {
29
+ super.connectedCallback();
30
+ this._player = this._resolvePlayer();
31
+ }
32
+
33
+ private handleClick() {
34
+ const delta = this.direction === "back" ? -this.seconds : this.seconds;
35
+ this._player?.pc?.seekBy(delta);
36
+ }
37
+
38
+ render() {
39
+ const label = this.direction === "back" ? this._t("skipBackward") : this._t("skipForward");
40
+ const icon = this.direction === "back" ? "\u23EA" : "\u23E9";
41
+ const shortcut = this.direction === "back" ? "j" : "l";
42
+
43
+ return html`<button
44
+ type="button"
45
+ class="fw-btn-flush"
46
+ aria-label=${label}
47
+ title="${label} (${shortcut})"
48
+ @click=${this.handleClick}
49
+ >
50
+ ${icon} ${this.seconds}s
51
+ </button>`;
52
+ }
53
+ }
54
+
55
+ declare global {
56
+ interface HTMLElementTagNameMap {
57
+ "fw-skip-button": FwSkipButton;
58
+ }
59
+ }
@@ -0,0 +1,74 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, state } from "lit/decorators.js";
3
+ import { formatTimeDisplay } from "@livepeer-frameworks/player-core";
4
+
5
+ @customElement("fw-time-display")
6
+ export class FwTimeDisplay extends LitElement {
7
+ @state() private display = "";
8
+ private _player: any = null;
9
+ private _cleanup: (() => void) | null = null;
10
+
11
+ static styles = css`
12
+ :host {
13
+ display: inline-flex;
14
+ align-items: center;
15
+ font-variant-numeric: tabular-nums;
16
+ }
17
+ span {
18
+ white-space: nowrap;
19
+ font-size: 0.75rem;
20
+ }
21
+ `;
22
+
23
+ private _resolvePlayer(): HTMLElement | null {
24
+ const forId = this.getAttribute("for");
25
+ if (forId) return document.getElementById(forId);
26
+ return this.closest("fw-player");
27
+ }
28
+
29
+ connectedCallback() {
30
+ super.connectedCallback();
31
+ this._player = this._resolvePlayer();
32
+ if (!this._player) return;
33
+ const pc = this._player.pc;
34
+ if (!pc) return;
35
+
36
+ this.updateDisplay();
37
+ const handler = () => this.updateDisplay();
38
+ this._player.addEventListener("fw-time-update", handler);
39
+ this._player.addEventListener("fw-ready", handler);
40
+ this._cleanup = () => {
41
+ this._player?.removeEventListener("fw-time-update", handler);
42
+ this._player?.removeEventListener("fw-ready", handler);
43
+ };
44
+ }
45
+
46
+ disconnectedCallback() {
47
+ super.disconnectedCallback();
48
+ this._cleanup?.();
49
+ this._cleanup = null;
50
+ }
51
+
52
+ private updateDisplay() {
53
+ const pc = this._player?.pc;
54
+ if (!pc) return;
55
+ const s = pc.s;
56
+ this.display = formatTimeDisplay({
57
+ isLive: s.isEffectivelyLive,
58
+ currentTime: s.currentTime,
59
+ duration: s.duration,
60
+ liveEdge: pc.getLiveEdge?.() ?? s.duration,
61
+ seekableStart: pc.getSeekableStart?.() ?? 0,
62
+ });
63
+ }
64
+
65
+ render() {
66
+ return html`<span>${this.display}</span>`;
67
+ }
68
+ }
69
+
70
+ declare global {
71
+ interface HTMLElementTagNameMap {
72
+ "fw-time-display": FwTimeDisplay;
73
+ }
74
+ }
@@ -0,0 +1,75 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, state } from "lit/decorators.js";
3
+ import { createTranslator, type TranslateFn } from "@livepeer-frameworks/player-core";
4
+
5
+ @customElement("fw-volume-button")
6
+ export class FwVolumeControl extends LitElement {
7
+ @state() private isMuted = false;
8
+ private _player: any = null;
9
+ private _cleanup: (() => void) | null = null;
10
+
11
+ private get _t(): TranslateFn {
12
+ return this._player?.pc?.t ?? createTranslator({ locale: "en" });
13
+ }
14
+
15
+ static styles = css`
16
+ :host {
17
+ display: inline-flex;
18
+ align-items: center;
19
+ }
20
+ `;
21
+
22
+ private _resolvePlayer(): HTMLElement | null {
23
+ const forId = this.getAttribute("for");
24
+ if (forId) return document.getElementById(forId);
25
+ return this.closest("fw-player");
26
+ }
27
+
28
+ connectedCallback() {
29
+ super.connectedCallback();
30
+ this._player = this._resolvePlayer();
31
+ if (!this._player) return;
32
+ const pc = this._player.pc;
33
+ if (!pc) return;
34
+
35
+ this.isMuted = pc.s.isMuted;
36
+ const handler = () => {
37
+ this.isMuted = this._player.pc.s.isMuted;
38
+ };
39
+ this._player.addEventListener("fw-volume-change", handler);
40
+ this._player.addEventListener("fw-ready", handler);
41
+ this._cleanup = () => {
42
+ this._player?.removeEventListener("fw-volume-change", handler);
43
+ this._player?.removeEventListener("fw-ready", handler);
44
+ };
45
+ }
46
+
47
+ disconnectedCallback() {
48
+ super.disconnectedCallback();
49
+ this._cleanup?.();
50
+ this._cleanup = null;
51
+ }
52
+
53
+ private handleClick() {
54
+ this._player?.pc?.toggleMute();
55
+ }
56
+
57
+ render() {
58
+ return html`<button
59
+ type="button"
60
+ class="fw-btn-flush"
61
+ aria-label=${this.isMuted ? this._t("unmute") : this._t("mute")}
62
+ aria-pressed=${this.isMuted}
63
+ title=${this.isMuted ? this._t("unmute") : this._t("mute")}
64
+ @click=${this.handleClick}
65
+ >
66
+ ${this.isMuted ? "\uD83D\uDD07" : "\uD83D\uDD0A"}
67
+ </button>`;
68
+ }
69
+ }
70
+
71
+ declare global {
72
+ interface HTMLElementTagNameMap {
73
+ "fw-volume-button": FwVolumeControl;
74
+ }
75
+ }
@@ -0,0 +1,6 @@
1
+ export { FwPlayButton } from "./fw-play-button";
2
+ export { FwSkipButton } from "./fw-skip-button";
3
+ export { FwVolumeControl } from "./fw-volume-control";
4
+ export { FwTimeDisplay } from "./fw-time-display";
5
+ export { FwLiveBadge } from "./fw-live-badge";
6
+ export { FwFullscreenButton } from "./fw-fullscreen-button";
@@ -36,7 +36,7 @@ export class FwDevModePanel extends LitElement {
36
36
 
37
37
  @state() private _activeTab: "config" | "stats" = "config";
38
38
  @state() private _hoveredComboIndex: number | null = null;
39
- @state() private _tooltipAbove = false;
39
+ @state() private _tooltipPos: { top: number; left: number } | null = null;
40
40
  @state() private _showDisabledPlayers = false;
41
41
 
42
42
  @state() private _playbackScore = 1;
@@ -219,18 +219,12 @@ export class FwDevModePanel extends LitElement {
219
219
 
220
220
  private _handleComboMouseEnter(index: number, event: MouseEvent): void {
221
221
  this._hoveredComboIndex = index;
222
-
223
- const container = this.renderRoot.querySelector(".fw-dev-body") as HTMLElement | null;
224
- if (!container) {
225
- return;
226
- }
227
-
228
222
  const row = event.currentTarget as HTMLElement;
229
- const containerRect = container.getBoundingClientRect();
230
223
  const rowRect = row.getBoundingClientRect();
231
- const relativePosition = (rowRect.top - containerRect.top) / containerRect.height;
232
-
233
- this._tooltipAbove = relativePosition > 0.6;
224
+ this._tooltipPos = {
225
+ top: Math.max(8, Math.min(rowRect.top, window.innerHeight - 200)),
226
+ left: Math.max(8, rowRect.left - 228),
227
+ };
234
228
  }
235
229
 
236
230
  private _handleModeChange(mode: "auto" | "low-latency" | "quality"): void {
@@ -764,6 +758,7 @@ export class FwDevModePanel extends LitElement {
764
758
  this._handleComboMouseEnter(index, event)}
765
759
  @mouseleave=${() => {
766
760
  this._hoveredComboIndex = null;
761
+ this._tooltipPos = null;
767
762
  }}
768
763
  >
769
764
  <button
@@ -804,14 +799,12 @@ export class FwDevModePanel extends LitElement {
804
799
  >
805
800
  </button>
806
801
 
807
- ${this._hoveredComboIndex === index
802
+ ${this._hoveredComboIndex === index && this._tooltipPos
808
803
  ? html`
809
804
  <div
810
- class=${classMap({
811
- "fw-dev-tooltip": true,
812
- "fw-dev-tooltip--above": this._tooltipAbove,
813
- "fw-dev-tooltip--below": !this._tooltipAbove,
814
- })}
805
+ class="fw-dev-tooltip"
806
+ style="top: ${this._tooltipPos.top}px; left: ${this._tooltipPos
807
+ .left}px;"
815
808
  >
816
809
  <div class="fw-dev-tooltip-header">
817
810
  <div class="fw-dev-tooltip-title">${combo.playerName}</div>
@@ -4,11 +4,19 @@ import { classMap } from "lit/directives/class-map.js";
4
4
  import { sharedStyles } from "../styles/shared-styles.js";
5
5
  import { utilityStyles } from "../styles/utility-styles.js";
6
6
  import { closeIcon } from "../icons/index.js";
7
+ import { createTranslator, type TranslateFn } from "@livepeer-frameworks/player-core";
7
8
 
8
9
  @customElement("fw-error-overlay")
9
10
  export class FwErrorOverlay extends LitElement {
10
11
  @property({ type: String }) error: string | null = null;
11
12
  @property({ type: Boolean, attribute: "is-passive" }) isPassive = false;
13
+ @property({ attribute: false }) translator?: TranslateFn;
14
+
15
+ private _defaultTranslator: TranslateFn = createTranslator({ locale: "en" });
16
+
17
+ private get _t(): TranslateFn {
18
+ return this.translator ?? this._defaultTranslator;
19
+ }
12
20
 
13
21
  static styles = [
14
22
  sharedStyles,
@@ -51,28 +59,28 @@ export class FwErrorOverlay extends LitElement {
51
59
  "fw-error-title--warning": this.isPassive,
52
60
  "fw-error-title--error": !this.isPassive,
53
61
  })}
54
- >${this.isPassive ? "Warning" : "Error"}</span
62
+ >${this.isPassive ? this._t("warning") : this._t("error")}</span
55
63
  >
56
64
  <button
57
65
  type="button"
58
66
  class="fw-error-close"
59
67
  @click=${this._clearError}
60
- aria-label="Dismiss"
68
+ aria-label=${this._t("dismiss")}
61
69
  >
62
70
  ${closeIcon()}
63
71
  </button>
64
72
  </div>
65
73
  <div class="fw-error-body">
66
- <p class="fw-error-message">Playback issue</p>
74
+ <p class="fw-error-message">${this.error || this._t("playbackIssue")}</p>
67
75
  </div>
68
76
  <div class="fw-error-actions">
69
77
  <button
70
78
  type="button"
71
79
  class="fw-error-btn"
72
- aria-label="Retry playback"
80
+ aria-label=${this._t("retry")}
73
81
  @click=${this._retry}
74
82
  >
75
- Retry
83
+ ${this._t("retry")}
76
84
  </button>
77
85
  </div>
78
86
  </div>
@@ -4,6 +4,7 @@ import { sharedStyles } from "../styles/shared-styles.js";
4
4
  import { utilityStyles } from "../styles/utility-styles.js";
5
5
  import { LOGOMARK_DATA_URL } from "../constants/media-assets.js";
6
6
  import { playHitmarkerSound } from "./shared/hitmarker-audio.js";
7
+ import { createTranslator, type TranslateFn } from "@livepeer-frameworks/player-core";
7
8
  import "./fw-dvd-logo.js";
8
9
 
9
10
  interface ParticleState {
@@ -59,6 +60,13 @@ export class FwIdleScreen extends LitElement {
59
60
  @property({ type: String, attribute: "logo-src" }) logoSrc?: string;
60
61
  @property({ type: Boolean, attribute: "retry-enabled" }) retryEnabled = false;
61
62
  @property({ attribute: false }) onRetry?: () => void;
63
+ @property({ attribute: false }) translator?: TranslateFn;
64
+
65
+ private _defaultTranslator: TranslateFn = createTranslator({ locale: "en" });
66
+
67
+ private get _t(): TranslateFn {
68
+ return this.translator ?? this._defaultTranslator;
69
+ }
62
70
  @query(".idle-container") private _containerEl?: HTMLDivElement;
63
71
 
64
72
  @state() private _logoSize = 100;
@@ -552,7 +560,7 @@ export class FwIdleScreen extends LitElement {
552
560
  }
553
561
 
554
562
  private get _displayMessage() {
555
- return this.error || this.message || "Waiting for stream...";
563
+ return this.error || this.message || this._t("waitingForStream");
556
564
  }
557
565
 
558
566
  private _renderStatusIcon() {
@@ -744,7 +752,7 @@ export class FwIdleScreen extends LitElement {
744
752
  : nothing}
745
753
  ${this._showRetry
746
754
  ? html`<button type="button" class="retry-btn" @click=${this._handleRetry}>
747
- Retry
755
+ ${this._t("retry")}
748
756
  </button>`
749
757
  : nothing}
750
758
  </div>
@@ -4,12 +4,12 @@ import { sharedStyles } from "../styles/shared-styles.js";
4
4
  import { utilityStyles } from "../styles/utility-styles.js";
5
5
  import { LOGOMARK_DATA_URL } from "../constants/media-assets.js";
6
6
  import { playHitmarkerSound } from "./shared/hitmarker-audio.js";
7
+ import { createTranslator, type TranslateFn } from "@livepeer-frameworks/player-core";
7
8
  import "./fw-dvd-logo.js";
8
9
 
9
10
  interface ParticleState {
10
11
  left: number;
11
12
  size: number;
12
- color: string;
13
13
  duration: number;
14
14
  delay: number;
15
15
  }
@@ -19,7 +19,6 @@ interface BubbleState {
19
19
  left: number;
20
20
  size: number;
21
21
  opacity: number;
22
- color: string;
23
22
  }
24
23
 
25
24
  interface Hitmarker {
@@ -28,32 +27,13 @@ interface Hitmarker {
28
27
  y: number;
29
28
  }
30
29
 
31
- const BUBBLE_COLORS = [
32
- "rgba(122, 162, 247, 0.2)",
33
- "rgba(187, 154, 247, 0.2)",
34
- "rgba(158, 206, 106, 0.2)",
35
- "rgba(115, 218, 202, 0.2)",
36
- "rgba(125, 207, 255, 0.2)",
37
- "rgba(247, 118, 142, 0.2)",
38
- "rgba(224, 175, 104, 0.2)",
39
- "rgba(42, 195, 222, 0.2)",
40
- ];
41
-
42
- const PARTICLE_COLORS = [
43
- "#7aa2f7",
44
- "#bb9af7",
45
- "#9ece6a",
46
- "#73daca",
47
- "#7dcfff",
48
- "#f7768e",
49
- "#e0af68",
50
- "#2ac3de",
51
- ];
52
-
53
30
  @customElement("fw-loading-screen")
54
31
  export class FwLoadingScreen extends LitElement {
55
- @property({ type: String }) message = "Waiting for source...";
32
+ @property({ type: String }) message?: string;
56
33
  @property({ type: String, attribute: "logo-src" }) logoSrc?: string;
34
+ @property({ attribute: false }) translator?: TranslateFn;
35
+
36
+ private _defaultTranslator: TranslateFn = createTranslator({ locale: "en" });
57
37
  @query(".loading-container") private _containerEl?: HTMLDivElement;
58
38
 
59
39
  @state() private _logoSize = 100;
@@ -85,11 +65,11 @@ export class FwLoadingScreen extends LitElement {
85
65
  user-select: none;
86
66
  background: linear-gradient(
87
67
  135deg,
88
- hsl(var(--tn-bg-dark, 235 21% 11%)) 0%,
89
- hsl(var(--tn-bg, 233 23% 17%)) 25%,
90
- hsl(var(--tn-bg-dark, 235 21% 11%)) 50%,
91
- hsl(var(--tn-bg, 233 23% 17%)) 75%,
92
- hsl(var(--tn-bg-dark, 235 21% 11%)) 100%
68
+ hsl(var(--fw-surface-deep, 235 21% 11%)) 0%,
69
+ hsl(var(--fw-surface, 233 23% 17%)) 25%,
70
+ hsl(var(--fw-surface-deep, 235 21% 11%)) 50%,
71
+ hsl(var(--fw-surface, 233 23% 17%)) 75%,
72
+ hsl(var(--fw-surface-deep, 235 21% 11%)) 100%
93
73
  );
94
74
  background-size: 400% 400%;
95
75
  animation: _fw-gradient-shift 16s ease-in-out infinite;
@@ -115,6 +95,56 @@ export class FwLoadingScreen extends LitElement {
115
95
  transition: opacity 1s ease-in-out;
116
96
  }
117
97
 
98
+ .particle:nth-child(8n + 1) {
99
+ background: hsl(var(--fw-accent, 218 79% 73%));
100
+ }
101
+ .particle:nth-child(8n + 2) {
102
+ background: hsl(var(--fw-accent-secondary, 178 64% 63%));
103
+ }
104
+ .particle:nth-child(8n + 3) {
105
+ background: hsl(var(--fw-success, 95 53% 55%));
106
+ }
107
+ .particle:nth-child(8n + 4) {
108
+ background: hsl(var(--fw-info, 178 64% 63%));
109
+ }
110
+ .particle:nth-child(8n + 5) {
111
+ background: hsl(var(--fw-danger, 348 74% 64%));
112
+ }
113
+ .particle:nth-child(8n + 6) {
114
+ background: hsl(var(--fw-warning, 35 79% 64%));
115
+ }
116
+ .particle:nth-child(8n + 7) {
117
+ background: hsl(var(--fw-accent, 218 79% 73%) / 0.8);
118
+ }
119
+ .particle:nth-child(8n + 8) {
120
+ background: hsl(var(--fw-accent-secondary, 178 64% 63%) / 0.8);
121
+ }
122
+
123
+ .bubble:nth-child(8n + 1) {
124
+ background: hsl(var(--fw-accent, 218 79% 73%) / 0.2);
125
+ }
126
+ .bubble:nth-child(8n + 2) {
127
+ background: hsl(var(--fw-accent-secondary, 178 64% 63%) / 0.2);
128
+ }
129
+ .bubble:nth-child(8n + 3) {
130
+ background: hsl(var(--fw-success, 95 53% 55%) / 0.2);
131
+ }
132
+ .bubble:nth-child(8n + 4) {
133
+ background: hsl(var(--fw-info, 178 64% 63%) / 0.2);
134
+ }
135
+ .bubble:nth-child(8n + 5) {
136
+ background: hsl(var(--fw-danger, 348 74% 64%) / 0.2);
137
+ }
138
+ .bubble:nth-child(8n + 6) {
139
+ background: hsl(var(--fw-warning, 35 79% 64%) / 0.2);
140
+ }
141
+ .bubble:nth-child(8n + 7) {
142
+ background: hsl(var(--fw-accent, 218 79% 73%) / 0.15);
143
+ }
144
+ .bubble:nth-child(8n + 8) {
145
+ background: hsl(var(--fw-accent-secondary, 178 64% 63%) / 0.15);
146
+ }
147
+
118
148
  .center-logo {
119
149
  position: absolute;
120
150
  top: 50%;
@@ -127,7 +157,7 @@ export class FwLoadingScreen extends LitElement {
127
157
  .logo-pulse {
128
158
  position: absolute;
129
159
  border-radius: 50%;
130
- background: rgba(122, 162, 247, 0.15);
160
+ background: hsl(var(--fw-accent, 218 79% 73%) / 0.15);
131
161
  animation: _fw-logo-pulse 3s ease-in-out infinite;
132
162
  pointer-events: none;
133
163
  }
@@ -156,7 +186,8 @@ export class FwLoadingScreen extends LitElement {
156
186
 
157
187
  .logo-mark.hovered {
158
188
  transform: scale(1.1);
159
- filter: drop-shadow(0 6px 12px rgba(36, 40, 59, 0.4)) brightness(1.1);
189
+ filter: drop-shadow(0 6px 12px hsl(var(--fw-surface-deep, 235 21% 11%) / 0.4))
190
+ brightness(1.1);
160
191
  }
161
192
 
162
193
  .message {
@@ -165,11 +196,11 @@ export class FwLoadingScreen extends LitElement {
165
196
  left: 50%;
166
197
  transform: translateX(-50%);
167
198
  z-index: 8;
168
- color: #a9b1d6;
199
+ color: hsl(var(--fw-text-muted, 224 16% 53%));
169
200
  font-size: 16px;
170
201
  font-weight: 500;
171
202
  text-align: center;
172
- text-shadow: 0 2px 4px rgba(36, 40, 59, 0.5);
203
+ text-shadow: 0 2px 4px hsl(var(--fw-surface-deep, 235 21% 11%) / 0.5);
173
204
  animation: _fw-fade-in-out 2s ease-in-out infinite;
174
205
  pointer-events: none;
175
206
  }
@@ -179,9 +210,21 @@ export class FwLoadingScreen extends LitElement {
179
210
  inset: 0;
180
211
  pointer-events: none;
181
212
  background:
182
- radial-gradient(circle at 20% 80%, rgba(122, 162, 247, 0.03) 0%, transparent 50%),
183
- radial-gradient(circle at 80% 20%, rgba(187, 154, 247, 0.03) 0%, transparent 50%),
184
- radial-gradient(circle at 40% 40%, rgba(158, 206, 106, 0.02) 0%, transparent 50%);
213
+ radial-gradient(
214
+ circle at 20% 80%,
215
+ hsl(var(--fw-accent, 218 79% 73%) / 0.03) 0%,
216
+ transparent 50%
217
+ ),
218
+ radial-gradient(
219
+ circle at 80% 20%,
220
+ hsl(var(--fw-accent-secondary, 178 64% 63%) / 0.03) 0%,
221
+ transparent 50%
222
+ ),
223
+ radial-gradient(
224
+ circle at 40% 40%,
225
+ hsl(var(--fw-success, 95 53% 55%) / 0.02) 0%,
226
+ transparent 50%
227
+ );
185
228
  }
186
229
 
187
230
  .hitmarker {
@@ -197,8 +240,8 @@ export class FwLoadingScreen extends LitElement {
197
240
  position: absolute;
198
241
  width: 12px;
199
242
  height: 3px;
200
- background-color: #fff;
201
- box-shadow: 0 0 8px rgba(255, 255, 255, 0.8);
243
+ background-color: hsl(var(--fw-text-bright, 0 0% 100%));
244
+ box-shadow: 0 0 8px hsl(var(--fw-text-bright, 0 0% 100%) / 0.8);
202
245
  border-radius: 1px;
203
246
  }
204
247
 
@@ -331,22 +374,20 @@ export class FwLoadingScreen extends LitElement {
331
374
  }
332
375
 
333
376
  private _createParticles(): ParticleState[] {
334
- return Array.from({ length: 12 }, (_, index) => ({
377
+ return Array.from({ length: 12 }, () => ({
335
378
  left: Math.random() * 100,
336
379
  size: Math.random() * 4 + 2,
337
- color: PARTICLE_COLORS[index % PARTICLE_COLORS.length],
338
380
  duration: 8 + Math.random() * 4,
339
381
  delay: Math.random() * 8,
340
382
  }));
341
383
  }
342
384
 
343
385
  private _createBubbles(): BubbleState[] {
344
- return Array.from({ length: 8 }, (_, index) => ({
386
+ return Array.from({ length: 8 }, () => ({
345
387
  top: Math.random() * 80 + 10,
346
388
  left: Math.random() * 80 + 10,
347
389
  size: Math.random() * 60 + 30,
348
390
  opacity: 0,
349
- color: BUBBLE_COLORS[index % BUBBLE_COLORS.length],
350
391
  }));
351
392
  }
352
393
 
@@ -449,8 +490,13 @@ export class FwLoadingScreen extends LitElement {
449
490
  }, 600);
450
491
  };
451
492
 
493
+ private get _t(): TranslateFn {
494
+ return this.translator ?? this._defaultTranslator;
495
+ }
496
+
452
497
  protected render() {
453
498
  const logoSrc = this.logoSrc || LOGOMARK_DATA_URL;
499
+ const displayMessage = this.message ?? this._t("waitingForSource");
454
500
  return html`
455
501
  <div
456
502
  class="loading-container fw-player-root"
@@ -477,7 +523,6 @@ export class FwLoadingScreen extends LitElement {
477
523
  left:${particle.left}%;
478
524
  width:${particle.size}px;
479
525
  height:${particle.size}px;
480
- background:${particle.color};
481
526
  animation-duration:${particle.duration}s;
482
527
  animation-delay:${particle.delay}s;
483
528
  "
@@ -496,7 +541,6 @@ export class FwLoadingScreen extends LitElement {
496
541
  left:${bubble.left}%;
497
542
  width:${bubble.size}px;
498
543
  height:${bubble.size}px;
499
- background:${bubble.color};
500
544
  opacity:${bubble.opacity};
501
545
  "
502
546
  ></div>
@@ -526,7 +570,7 @@ export class FwLoadingScreen extends LitElement {
526
570
 
527
571
  <fw-dvd-logo .parentRef=${this._containerEl ?? null} .scale=${0.08}></fw-dvd-logo>
528
572
 
529
- <div class="message">${this.message}</div>
573
+ <div class="message">${displayMessage}</div>
530
574
  <div class="overlay-texture"></div>
531
575
  </div>
532
576
  `;