@livepeer-frameworks/player-wc 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/fw-player-controls.js +22 -12
- package/dist/cjs/components/fw-player-controls.js.map +1 -1
- package/dist/cjs/components/fw-volume-control.js +91 -36
- package/dist/cjs/components/fw-volume-control.js.map +1 -1
- package/dist/esm/components/fw-player-controls.js +23 -13
- package/dist/esm/components/fw-player-controls.js.map +1 -1
- package/dist/esm/components/fw-volume-control.js +91 -36
- package/dist/esm/components/fw-volume-control.js.map +1 -1
- package/dist/fw-player.iife.js +19 -15
- package/dist/types/components/fw-player-controls.d.ts +1 -0
- package/dist/types/components/fw-volume-control.d.ts +11 -0
- package/package.json +1 -1
- package/src/components/fw-player-controls.ts +22 -15
- package/src/components/fw-volume-control.ts +98 -40
|
@@ -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";
|
|
@@ -55,6 +55,7 @@ export class FwPlayerControls extends LitElement {
|
|
|
55
55
|
@state() private _settingsOpen = false;
|
|
56
56
|
@state() private _isNearLiveState = true;
|
|
57
57
|
@state() private _buffered: TimeRanges | null = null;
|
|
58
|
+
@query(".fw-settings-anchor") private _settingsAnchorEl!: HTMLElement | null;
|
|
58
59
|
|
|
59
60
|
private _boundVideo: HTMLVideoElement | null = null;
|
|
60
61
|
private _onBufferedUpdate: (() => void) | null = null;
|
|
@@ -150,15 +151,15 @@ export class FwPlayerControls extends LitElement {
|
|
|
150
151
|
|
|
151
152
|
private _onWindowClick = (event: MouseEvent): void => {
|
|
152
153
|
const path = event.composedPath();
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
154
|
+
const anchor = this._settingsAnchorEl;
|
|
155
|
+
const insideControls =
|
|
156
|
+
anchor !== null &&
|
|
157
|
+
path.some((entry) => {
|
|
158
|
+
if (!(entry instanceof Node)) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
return anchor.contains(entry);
|
|
162
|
+
});
|
|
162
163
|
|
|
163
164
|
if (!insideControls) {
|
|
164
165
|
this._settingsOpen = false;
|
|
@@ -331,6 +332,7 @@ export class FwPlayerControls extends LitElement {
|
|
|
331
332
|
seekableStart: context.seekableStart,
|
|
332
333
|
unixoffset: context.mistStreamInfo?.unixoffset,
|
|
333
334
|
});
|
|
335
|
+
const showTimeDisplay = !(context.isLive && timeDisplay === "LIVE");
|
|
334
336
|
|
|
335
337
|
const liveButtonDisabled = !context.hasDvrWindow || this._isNearLiveState;
|
|
336
338
|
|
|
@@ -404,10 +406,13 @@ export class FwPlayerControls extends LitElement {
|
|
|
404
406
|
<fw-volume-control .pc=${this.pc}></fw-volume-control>
|
|
405
407
|
</div>
|
|
406
408
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
409
|
+
${showTimeDisplay
|
|
410
|
+
? html`
|
|
411
|
+
<div class="fw-control-group">
|
|
412
|
+
<span class="fw-time-display">${timeDisplay}</span>
|
|
413
|
+
</div>
|
|
414
|
+
`
|
|
415
|
+
: nothing}
|
|
411
416
|
${context.isLive
|
|
412
417
|
? html`
|
|
413
418
|
<div class="fw-control-group">
|
|
@@ -472,7 +477,8 @@ export class FwPlayerControls extends LitElement {
|
|
|
472
477
|
aria-label="Settings"
|
|
473
478
|
title="Settings"
|
|
474
479
|
?disabled=${disabled}
|
|
475
|
-
@click=${() => {
|
|
480
|
+
@click=${(event: MouseEvent) => {
|
|
481
|
+
event.stopPropagation();
|
|
476
482
|
if (disabled) {
|
|
477
483
|
return;
|
|
478
484
|
}
|
|
@@ -489,6 +495,7 @@ export class FwPlayerControls extends LitElement {
|
|
|
489
495
|
.open=${this._settingsOpen}
|
|
490
496
|
.playbackMode=${this.playbackMode}
|
|
491
497
|
.isContentLive=${this.isContentLive}
|
|
498
|
+
@click=${(event: MouseEvent) => event.stopPropagation()}
|
|
492
499
|
@fw-close=${() => {
|
|
493
500
|
this._settingsOpen = false;
|
|
494
501
|
}}
|
|
@@ -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 {
|
|
@@ -106,6 +115,89 @@ export class FwVolumeControl extends LitElement {
|
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
117
|
|
|
118
|
+
private _beginDragInteraction(target: HTMLElement, pointerId: number): void {
|
|
119
|
+
this._activePointerId = pointerId;
|
|
120
|
+
this._activeSliderTarget = target;
|
|
121
|
+
this._dragging = true;
|
|
122
|
+
this._hovered = true;
|
|
123
|
+
this._focused = true;
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
target.setPointerCapture(pointerId);
|
|
127
|
+
} catch {
|
|
128
|
+
// Non-fatal: we still listen on window as a fallback.
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
window.addEventListener("pointermove", this._onGlobalPointerMove);
|
|
132
|
+
window.addEventListener("pointerup", this._onGlobalPointerUp);
|
|
133
|
+
window.addEventListener("pointercancel", this._onGlobalPointerUp);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private _endDragInteraction(): void {
|
|
137
|
+
const pointerId = this._activePointerId;
|
|
138
|
+
const target = this._activeSliderTarget;
|
|
139
|
+
if (pointerId != null && target) {
|
|
140
|
+
try {
|
|
141
|
+
if (target.hasPointerCapture(pointerId)) {
|
|
142
|
+
target.releasePointerCapture(pointerId);
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
// Ignore pointer-capture release errors.
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this._activePointerId = null;
|
|
150
|
+
this._activeSliderTarget = null;
|
|
151
|
+
this._dragging = false;
|
|
152
|
+
window.removeEventListener("pointermove", this._onGlobalPointerMove);
|
|
153
|
+
window.removeEventListener("pointerup", this._onGlobalPointerUp);
|
|
154
|
+
window.removeEventListener("pointercancel", this._onGlobalPointerUp);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private _onGlobalPointerMove = (event: PointerEvent): void => {
|
|
158
|
+
if (!this._dragging || this._activePointerId !== event.pointerId) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const target = this._activeSliderTarget;
|
|
162
|
+
if (!target) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
this._setVolumeFromClientX(event.clientX, target);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
private _onGlobalPointerUp = (event: PointerEvent): void => {
|
|
169
|
+
if (!this._dragging || this._activePointerId !== event.pointerId) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this._endDragInteraction();
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
private _handleMouseEnter = (): void => {
|
|
176
|
+
this._hovered = true;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
private _handleMouseLeave = (): void => {
|
|
180
|
+
if (this._dragging) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
this._hovered = false;
|
|
184
|
+
this._focused = false;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
private _handleFocusIn = (): void => {
|
|
188
|
+
this._focused = true;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
private _handleFocusOut = (event: FocusEvent): void => {
|
|
192
|
+
if (this._dragging) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const related = event.relatedTarget as Node | null;
|
|
196
|
+
if (!related || !this.renderRoot.contains(related)) {
|
|
197
|
+
this._focused = false;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
109
201
|
private _onSliderPointerDown = (event: PointerEvent) => {
|
|
110
202
|
if (!this._hasAudio) {
|
|
111
203
|
return;
|
|
@@ -113,30 +205,8 @@ export class FwVolumeControl extends LitElement {
|
|
|
113
205
|
|
|
114
206
|
event.preventDefault();
|
|
115
207
|
const target = event.currentTarget as HTMLElement;
|
|
116
|
-
this.
|
|
208
|
+
this._beginDragInteraction(target, event.pointerId);
|
|
117
209
|
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
210
|
};
|
|
141
211
|
|
|
142
212
|
private _onWheel = (event: WheelEvent) => {
|
|
@@ -170,22 +240,10 @@ export class FwVolumeControl extends LitElement {
|
|
|
170
240
|
})}
|
|
171
241
|
role="group"
|
|
172
242
|
aria-label="Volume controls"
|
|
173
|
-
@mouseenter=${
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
@
|
|
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
|
-
}}
|
|
243
|
+
@mouseenter=${this._handleMouseEnter}
|
|
244
|
+
@mouseleave=${this._handleMouseLeave}
|
|
245
|
+
@focusin=${this._handleFocusIn}
|
|
246
|
+
@focusout=${this._handleFocusOut}
|
|
189
247
|
@click=${(event: MouseEvent) => {
|
|
190
248
|
if (this._hasAudio && event.target === event.currentTarget) {
|
|
191
249
|
this.pc.toggleMute();
|