@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
@@ -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
  `;
@@ -1,8 +1,17 @@
1
1
  import { LitElement, html, css } from "lit";
2
- import { customElement } from "lit/decorators.js";
2
+ import { customElement, property } from "lit/decorators.js";
3
+ import { createTranslator, type TranslateFn } from "@livepeer-frameworks/player-core";
3
4
 
4
5
  @customElement("fw-loading-spinner")
5
6
  export class FwLoadingSpinner extends LitElement {
7
+ @property({ attribute: false }) translator?: TranslateFn;
8
+
9
+ private _defaultTranslator: TranslateFn = createTranslator({ locale: "en" });
10
+
11
+ private get _t(): TranslateFn {
12
+ return this.translator ?? this._defaultTranslator;
13
+ }
14
+
6
15
  static styles = css`
7
16
  :host {
8
17
  display: contents;
@@ -13,7 +22,7 @@ export class FwLoadingSpinner extends LitElement {
13
22
  display: flex;
14
23
  align-items: center;
15
24
  justify-content: center;
16
- background: rgb(0 0 0 / 0.4);
25
+ background: hsl(var(--fw-surface-deep, 235 21% 11%) / 0.85);
17
26
  backdrop-filter: blur(4px);
18
27
  z-index: 20;
19
28
  }
@@ -22,18 +31,18 @@ export class FwLoadingSpinner extends LitElement {
22
31
  align-items: center;
23
32
  gap: 0.75rem;
24
33
  border-radius: 0.5rem;
25
- border: 1px solid rgb(255 255 255 / 0.1);
26
- background: rgb(0 0 0 / 0.7);
34
+ border: 1px solid hsl(var(--fw-text, 229 73% 86%) / 0.1);
35
+ background: hsl(var(--fw-surface-deep, 235 21% 11%) / 0.9);
27
36
  padding: 0.75rem 1rem;
28
37
  font-size: 0.875rem;
29
- color: white;
30
- box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
38
+ color: hsl(var(--fw-text, 229 73% 86%));
39
+ box-shadow: 0 10px 15px -3px hsl(var(--fw-shadow-color, 0 0% 0%) / 0.1);
31
40
  }
32
41
  .spinner {
33
42
  width: 1rem;
34
43
  height: 1rem;
35
- border: 2px solid rgb(255 255 255 / 0.3);
36
- border-top-color: white;
44
+ border: 2px solid hsl(var(--fw-text-faint, 228 15% 45%) / 0.3);
45
+ border-top-color: hsl(var(--fw-accent, 218 79% 73%));
37
46
  border-radius: 50%;
38
47
  animation: _fw-spin 1s linear infinite;
39
48
  }
@@ -49,7 +58,7 @@ export class FwLoadingSpinner extends LitElement {
49
58
  <div class="overlay" role="status" aria-live="polite">
50
59
  <div class="pill">
51
60
  <div class="spinner"></div>
52
- <span>Buffering...</span>
61
+ <span>${this._t("buffering")}</span>
53
62
  </div>
54
63
  </div>
55
64
  `;
@@ -3,7 +3,7 @@
3
3
  * Parity port of React/Svelte control behavior.
4
4
  */
5
5
  import { LitElement, html, css, nothing, type PropertyValues } from "lit";
6
- import { customElement, property, state } from "lit/decorators.js";
6
+ import { customElement, property, query, state } from "lit/decorators.js";
7
7
  import { classMap } from "lit/directives/class-map.js";
8
8
  import { sharedStyles } from "../styles/shared-styles.js";
9
9
  import { utilityStyles } from "../styles/utility-styles.js";
@@ -28,6 +28,7 @@ import {
28
28
  isMediaStreamSource,
29
29
  type MistStreamInfo,
30
30
  type PlaybackMode,
31
+ type FwLocale,
31
32
  } from "@livepeer-frameworks/player-core";
32
33
  import type { PlayerControllerHost } from "../controllers/player-controller-host.js";
33
34
 
@@ -51,10 +52,12 @@ export class FwPlayerControls extends LitElement {
51
52
  @property({ type: Boolean, attribute: "dev-mode" }) devMode = false;
52
53
  @property({ type: Boolean, attribute: "show-stats-button" }) showStatsButton = false;
53
54
  @property({ type: Boolean, attribute: "is-stats-open" }) isStatsOpen = false;
55
+ @property({ attribute: "active-locale" }) activeLocale?: FwLocale;
54
56
 
55
57
  @state() private _settingsOpen = false;
56
58
  @state() private _isNearLiveState = true;
57
59
  @state() private _buffered: TimeRanges | null = null;
60
+ @query(".fw-settings-anchor") private _settingsAnchorEl!: HTMLElement | null;
58
61
 
59
62
  private _boundVideo: HTMLVideoElement | null = null;
60
63
  private _onBufferedUpdate: (() => void) | null = null;
@@ -150,15 +153,15 @@ export class FwPlayerControls extends LitElement {
150
153
 
151
154
  private _onWindowClick = (event: MouseEvent): void => {
152
155
  const path = event.composedPath();
153
- const insideControls = path.some((entry) => {
154
- if (!(entry instanceof HTMLElement)) {
155
- return false;
156
- }
157
- return (
158
- entry.classList.contains("fw-settings-anchor") ||
159
- entry.classList.contains("fw-settings-menu")
160
- );
161
- });
156
+ const anchor = this._settingsAnchorEl;
157
+ const insideControls =
158
+ anchor !== null &&
159
+ path.some((entry) => {
160
+ if (!(entry instanceof Node)) {
161
+ return false;
162
+ }
163
+ return anchor.contains(entry);
164
+ });
162
165
 
163
166
  if (!insideControls) {
164
167
  this._settingsOpen = false;
@@ -331,13 +334,13 @@ export class FwPlayerControls extends LitElement {
331
334
  seekableStart: context.seekableStart,
332
335
  unixoffset: context.mistStreamInfo?.unixoffset,
333
336
  });
337
+ const showTimeDisplay = !(context.isLive && timeDisplay === "LIVE");
334
338
 
335
339
  const liveButtonDisabled = !context.hasDvrWindow || this._isNearLiveState;
336
340
 
337
341
  return html`
338
342
  <div
339
343
  class=${classMap({
340
- "fw-player-surface": true,
341
344
  "fw-controls-wrapper": true,
342
345
  "fw-controls-wrapper--visible": shouldShowControls,
343
346
  "fw-controls-wrapper--hidden": !shouldShowControls,
@@ -370,7 +373,7 @@ export class FwPlayerControls extends LitElement {
370
373
  type="button"
371
374
  class="fw-btn-flush"
372
375
  ?disabled=${disabled}
373
- aria-label=${state.isPlaying ? "Pause" : "Play"}
376
+ aria-label=${state.isPlaying ? this.pc.t("pause") : this.pc.t("play")}
374
377
  @click=${() => this.pc.togglePlay()}
375
378
  >
376
379
  ${state.isPlaying ? pauseIcon(18) : playIcon(18)}
@@ -382,7 +385,7 @@ export class FwPlayerControls extends LitElement {
382
385
  type="button"
383
386
  class="fw-btn-flush hidden sm:flex"
384
387
  ?disabled=${disabled}
385
- aria-label="Skip back 10 seconds"
388
+ aria-label=${this.pc.t("skipBackward")}
386
389
  @click=${() => this.pc.seekBy(-10)}
387
390
  >
388
391
  ${skipBackIcon(16)}
@@ -391,7 +394,7 @@ export class FwPlayerControls extends LitElement {
391
394
  type="button"
392
395
  class="fw-btn-flush hidden sm:flex"
393
396
  ?disabled=${disabled}
394
- aria-label="Skip forward 10 seconds"
397
+ aria-label=${this.pc.t("skipForward")}
395
398
  @click=${() => this.pc.seekBy(10)}
396
399
  >
397
400
  ${skipForwardIcon(16)}
@@ -404,10 +407,13 @@ export class FwPlayerControls extends LitElement {
404
407
  <fw-volume-control .pc=${this.pc}></fw-volume-control>
405
408
  </div>
406
409
 
407
- <div class="fw-control-group">
408
- <span class="fw-time-display">${timeDisplay}</span>
409
- </div>
410
-
410
+ ${showTimeDisplay
411
+ ? html`
412
+ <div class="fw-control-group">
413
+ <span class="fw-time-display">${timeDisplay}</span>
414
+ </div>
415
+ `
416
+ : nothing}
411
417
  ${context.isLive
412
418
  ? html`
413
419
  <div class="fw-control-group">
@@ -421,12 +427,12 @@ export class FwPlayerControls extends LitElement {
421
427
  "fw-live-badge--behind": !liveButtonDisabled,
422
428
  })}
423
429
  title=${!context.hasDvrWindow
424
- ? "Live only"
430
+ ? this.pc.t("live")
425
431
  : this._isNearLiveState
426
- ? "At live edge"
427
- : "Jump to live"}
432
+ ? this.pc.t("live")
433
+ : this.pc.t("live")}
428
434
  >
429
- LIVE
435
+ ${this.pc.t("live").toUpperCase()}
430
436
  ${!this._isNearLiveState && context.hasDvrWindow
431
437
  ? seekToLiveIcon(10)
432
438
  : nothing}
@@ -446,8 +452,8 @@ export class FwPlayerControls extends LitElement {
446
452
  "fw-btn-flush": true,
447
453
  "fw-btn-flush--active": this.isStatsOpen,
448
454
  })}
449
- aria-label="Toggle stats"
450
- title="Stats"
455
+ aria-label=${this.pc.t("showStats")}
456
+ title=${this.pc.t("showStats")}
451
457
  @click=${() =>
452
458
  this.dispatchEvent(
453
459
  new CustomEvent("fw-stats-toggle", {
@@ -469,10 +475,11 @@ export class FwPlayerControls extends LitElement {
469
475
  group: true,
470
476
  "fw-btn-flush--active": this._settingsOpen,
471
477
  })}
472
- aria-label="Settings"
473
- title="Settings"
478
+ aria-label=${this.pc.t("settings")}
479
+ title=${this.pc.t("settings")}
474
480
  ?disabled=${disabled}
475
- @click=${() => {
481
+ @click=${(event: MouseEvent) => {
482
+ event.stopPropagation();
476
483
  if (disabled) {
477
484
  return;
478
485
  }
@@ -489,6 +496,8 @@ export class FwPlayerControls extends LitElement {
489
496
  .open=${this._settingsOpen}
490
497
  .playbackMode=${this.playbackMode}
491
498
  .isContentLive=${this.isContentLive}
499
+ .activeLocale=${this.activeLocale}
500
+ @click=${(event: MouseEvent) => event.stopPropagation()}
492
501
  @fw-close=${() => {
493
502
  this._settingsOpen = false;
494
503
  }}
@@ -501,7 +510,9 @@ export class FwPlayerControls extends LitElement {
501
510
  type="button"
502
511
  class="fw-btn-flush"
503
512
  ?disabled=${disabled}
504
- aria-label=${state.isFullscreen ? "Exit fullscreen" : "Fullscreen"}
513
+ aria-label=${state.isFullscreen
514
+ ? this.pc.t("exitFullscreen")
515
+ : this.pc.t("fullscreen")}
505
516
  @click=${() => this.pc.toggleFullscreen()}
506
517
  >
507
518
  ${state.isFullscreen ? fullscreenExitIcon(16) : fullscreenIcon(16)}