@livepeer-frameworks/player-wc 0.1.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.
Files changed (141) hide show
  1. package/dist/cjs/components/fw-context-menu.js +17 -0
  2. package/dist/cjs/components/fw-context-menu.js.map +1 -0
  3. package/dist/cjs/components/fw-dev-mode-panel.js +273 -0
  4. package/dist/cjs/components/fw-dev-mode-panel.js.map +1 -0
  5. package/dist/cjs/components/fw-error-overlay.js +101 -0
  6. package/dist/cjs/components/fw-error-overlay.js.map +1 -0
  7. package/dist/cjs/components/fw-idle-screen.js +182 -0
  8. package/dist/cjs/components/fw-idle-screen.js.map +1 -0
  9. package/dist/cjs/components/fw-loading-spinner.js +62 -0
  10. package/dist/cjs/components/fw-loading-spinner.js.map +1 -0
  11. package/dist/cjs/components/fw-player-controls.js +258 -0
  12. package/dist/cjs/components/fw-player-controls.js.map +1 -0
  13. package/dist/cjs/components/fw-player.js +570 -0
  14. package/dist/cjs/components/fw-player.js.map +1 -0
  15. package/dist/cjs/components/fw-seek-bar.js +233 -0
  16. package/dist/cjs/components/fw-seek-bar.js.map +1 -0
  17. package/dist/cjs/components/fw-settings-menu.js +126 -0
  18. package/dist/cjs/components/fw-settings-menu.js.map +1 -0
  19. package/dist/cjs/components/fw-skip-indicator.js +143 -0
  20. package/dist/cjs/components/fw-skip-indicator.js.map +1 -0
  21. package/dist/cjs/components/fw-speed-indicator.js +61 -0
  22. package/dist/cjs/components/fw-speed-indicator.js.map +1 -0
  23. package/dist/cjs/components/fw-stats-panel.js +141 -0
  24. package/dist/cjs/components/fw-stats-panel.js.map +1 -0
  25. package/dist/cjs/components/fw-subtitle-renderer.js +70 -0
  26. package/dist/cjs/components/fw-subtitle-renderer.js.map +1 -0
  27. package/dist/cjs/components/fw-title-overlay.js +72 -0
  28. package/dist/cjs/components/fw-title-overlay.js.map +1 -0
  29. package/dist/cjs/components/fw-toast.js +74 -0
  30. package/dist/cjs/components/fw-toast.js.map +1 -0
  31. package/dist/cjs/components/fw-volume-control.js +140 -0
  32. package/dist/cjs/components/fw-volume-control.js.map +1 -0
  33. package/dist/cjs/controllers/player-controller-host.js +315 -0
  34. package/dist/cjs/controllers/player-controller-host.js.map +1 -0
  35. package/dist/cjs/define.js +45 -0
  36. package/dist/cjs/define.js.map +1 -0
  37. package/dist/cjs/icons/index.js +153 -0
  38. package/dist/cjs/icons/index.js.map +1 -0
  39. package/dist/cjs/index.js +88 -0
  40. package/dist/cjs/index.js.map +1 -0
  41. 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 +33 -0
  42. 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 +1 -0
  43. package/dist/cjs/styles/shared-styles.js +1967 -0
  44. package/dist/cjs/styles/shared-styles.js.map +1 -0
  45. package/dist/cjs/styles/utility-styles.js +725 -0
  46. package/dist/cjs/styles/utility-styles.js.map +1 -0
  47. package/dist/esm/components/fw-context-menu.js +17 -0
  48. package/dist/esm/components/fw-context-menu.js.map +1 -0
  49. package/dist/esm/components/fw-dev-mode-panel.js +273 -0
  50. package/dist/esm/components/fw-dev-mode-panel.js.map +1 -0
  51. package/dist/esm/components/fw-error-overlay.js +101 -0
  52. package/dist/esm/components/fw-error-overlay.js.map +1 -0
  53. package/dist/esm/components/fw-idle-screen.js +182 -0
  54. package/dist/esm/components/fw-idle-screen.js.map +1 -0
  55. package/dist/esm/components/fw-loading-spinner.js +62 -0
  56. package/dist/esm/components/fw-loading-spinner.js.map +1 -0
  57. package/dist/esm/components/fw-player-controls.js +258 -0
  58. package/dist/esm/components/fw-player-controls.js.map +1 -0
  59. package/dist/esm/components/fw-player.js +570 -0
  60. package/dist/esm/components/fw-player.js.map +1 -0
  61. package/dist/esm/components/fw-seek-bar.js +233 -0
  62. package/dist/esm/components/fw-seek-bar.js.map +1 -0
  63. package/dist/esm/components/fw-settings-menu.js +126 -0
  64. package/dist/esm/components/fw-settings-menu.js.map +1 -0
  65. package/dist/esm/components/fw-skip-indicator.js +143 -0
  66. package/dist/esm/components/fw-skip-indicator.js.map +1 -0
  67. package/dist/esm/components/fw-speed-indicator.js +61 -0
  68. package/dist/esm/components/fw-speed-indicator.js.map +1 -0
  69. package/dist/esm/components/fw-stats-panel.js +141 -0
  70. package/dist/esm/components/fw-stats-panel.js.map +1 -0
  71. package/dist/esm/components/fw-subtitle-renderer.js +70 -0
  72. package/dist/esm/components/fw-subtitle-renderer.js.map +1 -0
  73. package/dist/esm/components/fw-title-overlay.js +72 -0
  74. package/dist/esm/components/fw-title-overlay.js.map +1 -0
  75. package/dist/esm/components/fw-toast.js +74 -0
  76. package/dist/esm/components/fw-toast.js.map +1 -0
  77. package/dist/esm/components/fw-volume-control.js +140 -0
  78. package/dist/esm/components/fw-volume-control.js.map +1 -0
  79. package/dist/esm/controllers/player-controller-host.js +313 -0
  80. package/dist/esm/controllers/player-controller-host.js.map +1 -0
  81. package/dist/esm/define.js +43 -0
  82. package/dist/esm/define.js.map +1 -0
  83. package/dist/esm/icons/index.js +141 -0
  84. package/dist/esm/icons/index.js.map +1 -0
  85. package/dist/esm/index.js +18 -0
  86. package/dist/esm/index.js.map +1 -0
  87. package/dist/esm/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 +31 -0
  88. package/dist/esm/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 +1 -0
  89. package/dist/esm/styles/shared-styles.js +1965 -0
  90. package/dist/esm/styles/shared-styles.js.map +1 -0
  91. package/dist/esm/styles/utility-styles.js +723 -0
  92. package/dist/esm/styles/utility-styles.js.map +1 -0
  93. package/dist/fw-player.iife.js +4362 -0
  94. package/dist/fw-player.iife.js.map +1 -0
  95. package/dist/types/components/fw-context-menu.d.ts +15 -0
  96. package/dist/types/components/fw-dev-mode-panel.d.ts +24 -0
  97. package/dist/types/components/fw-error-overlay.d.ts +14 -0
  98. package/dist/types/components/fw-idle-screen.d.ts +13 -0
  99. package/dist/types/components/fw-loading-spinner.d.ts +10 -0
  100. package/dist/types/components/fw-player-controls.d.ts +23 -0
  101. package/dist/types/components/fw-player.d.ts +74 -0
  102. package/dist/types/components/fw-seek-bar.d.ts +33 -0
  103. package/dist/types/components/fw-settings-menu.d.ts +16 -0
  104. package/dist/types/components/fw-skip-indicator.d.ts +18 -0
  105. package/dist/types/components/fw-speed-indicator.d.ts +11 -0
  106. package/dist/types/components/fw-stats-panel.d.ts +18 -0
  107. package/dist/types/components/fw-subtitle-renderer.d.ts +21 -0
  108. package/dist/types/components/fw-title-overlay.d.ts +12 -0
  109. package/dist/types/components/fw-toast.d.ts +12 -0
  110. package/dist/types/components/fw-volume-control.d.ts +18 -0
  111. package/dist/types/controllers/player-controller-host.d.ts +119 -0
  112. package/dist/types/define.d.ts +1 -0
  113. package/dist/types/icons/index.d.ts +23 -0
  114. package/dist/types/iife-entry.d.ts +11 -0
  115. package/dist/types/index.d.ts +25 -0
  116. package/dist/types/styles/shared-styles.d.ts +1 -0
  117. package/dist/types/styles/utility-styles.d.ts +1 -0
  118. package/package.json +65 -0
  119. package/src/components/fw-context-menu.ts +23 -0
  120. package/src/components/fw-dev-mode-panel.ts +285 -0
  121. package/src/components/fw-error-overlay.ts +96 -0
  122. package/src/components/fw-idle-screen.ts +182 -0
  123. package/src/components/fw-loading-spinner.ts +63 -0
  124. package/src/components/fw-player-controls.ts +256 -0
  125. package/src/components/fw-player.ts +557 -0
  126. package/src/components/fw-seek-bar.ts +219 -0
  127. package/src/components/fw-settings-menu.ts +128 -0
  128. package/src/components/fw-skip-indicator.ts +139 -0
  129. package/src/components/fw-speed-indicator.ts +57 -0
  130. package/src/components/fw-stats-panel.ts +154 -0
  131. package/src/components/fw-subtitle-renderer.ts +65 -0
  132. package/src/components/fw-title-overlay.ts +64 -0
  133. package/src/components/fw-toast.ts +70 -0
  134. package/src/components/fw-volume-control.ts +140 -0
  135. package/src/controllers/player-controller-host.ts +457 -0
  136. package/src/define.ts +43 -0
  137. package/src/icons/index.ts +209 -0
  138. package/src/iife-entry.ts +11 -0
  139. package/src/index.ts +31 -0
  140. package/src/styles/shared-styles.ts +1962 -0
  141. package/src/styles/utility-styles.ts +720 -0
@@ -0,0 +1,141 @@
1
+ 'use strict';
2
+
3
+ var tslib_es6 = require('../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');
4
+ var lit = require('lit');
5
+ var decorators_js = require('lit/decorators.js');
6
+ var sharedStyles = require('../styles/shared-styles.js');
7
+ var utilityStyles = require('../styles/utility-styles.js');
8
+ var index = require('../icons/index.js');
9
+
10
+ exports.FwStatsPanel = class FwStatsPanel extends lit.LitElement {
11
+ _resolution() {
12
+ const video = this.pc.s.videoElement;
13
+ if (!video || !video.videoWidth || !video.videoHeight)
14
+ return null;
15
+ return `${video.videoWidth}x${video.videoHeight}`;
16
+ }
17
+ _stat(label, value) {
18
+ if (value == null || value === "")
19
+ return lit.nothing;
20
+ return lit.html `<div class="row">
21
+ <span class="label">${label}</span><span class="value">${value}</span>
22
+ </div>`;
23
+ }
24
+ render() {
25
+ const s = this.pc.s;
26
+ const q = s.playbackQuality;
27
+ const meta = s.metadata;
28
+ const ss = s.streamState;
29
+ return lit.html `
30
+ <div class="panel fw-stats-panel">
31
+ <div class="header">
32
+ <span class="title">Stats</span>
33
+ <button
34
+ class="close"
35
+ @click=${() => this.dispatchEvent(new CustomEvent("fw-close", { bubbles: true, composed: true }))}
36
+ aria-label="Close stats"
37
+ >
38
+ ${index.closeIcon()}
39
+ </button>
40
+ </div>
41
+
42
+ ${this._stat("State", s.state)} ${this._stat("Player", s.currentPlayerInfo?.name)}
43
+ ${this._stat("Source", s.currentSourceInfo?.type)}
44
+
45
+ <div class="sep"></div>
46
+
47
+ ${q
48
+ ? lit.html `
49
+ ${this._stat("Resolution", this._resolution())}
50
+ ${this._stat("Bitrate", q.bitrate ? `${Math.round(q.bitrate / 1000)} kbps` : null)}
51
+ ${this._stat("Latency", q.latency != null ? `${q.latency.toFixed(1)}s` : null)}
52
+ ${this._stat("Buffer", q.bufferedAhead != null ? `${q.bufferedAhead.toFixed(1)}s` : null)}
53
+ ${this._stat("Quality", q.score != null ? `${q.score.toFixed(0)}` : null)}
54
+ ${this._stat("Frame drops", q.frameDropRate != null ? `${q.frameDropRate.toFixed(1)}%` : null)}
55
+ ${this._stat("Stalls", q.stallCount ?? null)}
56
+ `
57
+ : lit.nothing}
58
+ ${meta || ss
59
+ ? lit.html `
60
+ <div class="sep"></div>
61
+ ${this._stat("Viewers", meta?.viewers ?? null)}
62
+ ${this._stat("Stream status", ss?.status ?? null)}
63
+ `
64
+ : lit.nothing}
65
+ </div>
66
+ `;
67
+ }
68
+ };
69
+ exports.FwStatsPanel.styles = [
70
+ sharedStyles.sharedStyles,
71
+ utilityStyles.utilityStyles,
72
+ lit.css `
73
+ :host {
74
+ display: contents;
75
+ }
76
+ .panel {
77
+ position: absolute;
78
+ top: 0.75rem;
79
+ left: 0.75rem;
80
+ z-index: 30;
81
+ min-width: 240px;
82
+ max-width: 320px;
83
+ max-height: 80%;
84
+ overflow: auto;
85
+ border-radius: 0.5rem;
86
+ border: 1px solid rgb(255 255 255 / 0.1);
87
+ background: rgb(0 0 0 / 0.85);
88
+ backdrop-filter: blur(8px);
89
+ padding: 0.5rem 0.75rem;
90
+ font-size: 0.6875rem;
91
+ color: rgb(255 255 255 / 0.7);
92
+ }
93
+ .header {
94
+ display: flex;
95
+ align-items: center;
96
+ justify-content: space-between;
97
+ margin-bottom: 0.5rem;
98
+ }
99
+ .title {
100
+ font-size: 0.75rem;
101
+ font-weight: 600;
102
+ color: white;
103
+ }
104
+ .close {
105
+ display: flex;
106
+ background: none;
107
+ border: none;
108
+ color: rgb(255 255 255 / 0.5);
109
+ cursor: pointer;
110
+ padding: 0;
111
+ }
112
+ .close:hover {
113
+ color: white;
114
+ }
115
+ .row {
116
+ display: flex;
117
+ justify-content: space-between;
118
+ padding: 0.125rem 0;
119
+ }
120
+ .label {
121
+ color: rgb(255 255 255 / 0.5);
122
+ }
123
+ .value {
124
+ color: rgb(255 255 255 / 0.9);
125
+ font-variant-numeric: tabular-nums;
126
+ font-family: ui-monospace, monospace;
127
+ }
128
+ .sep {
129
+ height: 1px;
130
+ background: rgb(255 255 255 / 0.08);
131
+ margin: 0.375rem 0;
132
+ }
133
+ `,
134
+ ];
135
+ tslib_es6.__decorate([
136
+ decorators_js.property({ attribute: false })
137
+ ], exports.FwStatsPanel.prototype, "pc", void 0);
138
+ exports.FwStatsPanel = tslib_es6.__decorate([
139
+ decorators_js.customElement("fw-stats-panel")
140
+ ], exports.FwStatsPanel);
141
+ //# sourceMappingURL=fw-stats-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fw-stats-panel.js","sources":["../../../../src/components/fw-stats-panel.ts"],"sourcesContent":["/**\n * <fw-stats-panel> — Stats for nerds overlay.\n * Port of StatsPanel.tsx from player-react.\n */\nimport { LitElement, html, css, nothing } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { sharedStyles } from \"../styles/shared-styles.js\";\nimport { utilityStyles } from \"../styles/utility-styles.js\";\nimport { closeIcon } from \"../icons/index.js\";\nimport type { PlayerControllerHost } from \"../controllers/player-controller-host.js\";\n\n@customElement(\"fw-stats-panel\")\nexport class FwStatsPanel extends LitElement {\n @property({ attribute: false }) pc!: PlayerControllerHost;\n\n static styles = [\n sharedStyles,\n utilityStyles,\n css`\n :host {\n display: contents;\n }\n .panel {\n position: absolute;\n top: 0.75rem;\n left: 0.75rem;\n z-index: 30;\n min-width: 240px;\n max-width: 320px;\n max-height: 80%;\n overflow: auto;\n border-radius: 0.5rem;\n border: 1px solid rgb(255 255 255 / 0.1);\n background: rgb(0 0 0 / 0.85);\n backdrop-filter: blur(8px);\n padding: 0.5rem 0.75rem;\n font-size: 0.6875rem;\n color: rgb(255 255 255 / 0.7);\n }\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 0.5rem;\n }\n .title {\n font-size: 0.75rem;\n font-weight: 600;\n color: white;\n }\n .close {\n display: flex;\n background: none;\n border: none;\n color: rgb(255 255 255 / 0.5);\n cursor: pointer;\n padding: 0;\n }\n .close:hover {\n color: white;\n }\n .row {\n display: flex;\n justify-content: space-between;\n padding: 0.125rem 0;\n }\n .label {\n color: rgb(255 255 255 / 0.5);\n }\n .value {\n color: rgb(255 255 255 / 0.9);\n font-variant-numeric: tabular-nums;\n font-family: ui-monospace, monospace;\n }\n .sep {\n height: 1px;\n background: rgb(255 255 255 / 0.08);\n margin: 0.375rem 0;\n }\n `,\n ];\n\n private _resolution(): string | null {\n const video = this.pc.s.videoElement;\n if (!video || !video.videoWidth || !video.videoHeight) return null;\n return `${video.videoWidth}x${video.videoHeight}`;\n }\n\n private _stat(label: string, value: string | number | null | undefined) {\n if (value == null || value === \"\") return nothing;\n return html`<div class=\"row\">\n <span class=\"label\">${label}</span><span class=\"value\">${value}</span>\n </div>`;\n }\n\n protected render() {\n const s = this.pc.s;\n const q = s.playbackQuality;\n const meta = s.metadata;\n const ss = s.streamState;\n\n return html`\n <div class=\"panel fw-stats-panel\">\n <div class=\"header\">\n <span class=\"title\">Stats</span>\n <button\n class=\"close\"\n @click=${() =>\n this.dispatchEvent(new CustomEvent(\"fw-close\", { bubbles: true, composed: true }))}\n aria-label=\"Close stats\"\n >\n ${closeIcon()}\n </button>\n </div>\n\n ${this._stat(\"State\", s.state)} ${this._stat(\"Player\", s.currentPlayerInfo?.name)}\n ${this._stat(\"Source\", s.currentSourceInfo?.type)}\n\n <div class=\"sep\"></div>\n\n ${q\n ? html`\n ${this._stat(\"Resolution\", this._resolution())}\n ${this._stat(\"Bitrate\", q.bitrate ? `${Math.round(q.bitrate / 1000)} kbps` : null)}\n ${this._stat(\"Latency\", q.latency != null ? `${q.latency.toFixed(1)}s` : null)}\n ${this._stat(\n \"Buffer\",\n q.bufferedAhead != null ? `${q.bufferedAhead.toFixed(1)}s` : null\n )}\n ${this._stat(\"Quality\", q.score != null ? `${q.score.toFixed(0)}` : null)}\n ${this._stat(\n \"Frame drops\",\n q.frameDropRate != null ? `${q.frameDropRate.toFixed(1)}%` : null\n )}\n ${this._stat(\"Stalls\", q.stallCount ?? null)}\n `\n : nothing}\n ${meta || ss\n ? html`\n <div class=\"sep\"></div>\n ${this._stat(\"Viewers\", meta?.viewers ?? null)}\n ${this._stat(\"Stream status\", ss?.status ?? null)}\n `\n : nothing}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"fw-stats-panel\": FwStatsPanel;\n }\n}\n"],"names":["FwStatsPanel","LitElement","nothing","html","closeIcon","sharedStyles","utilityStyles","css","__decorate","property","customElement"],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ var tslib_es6 = require('../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');
4
+ var lit = require('lit');
5
+ var decorators_js = require('lit/decorators.js');
6
+
7
+ exports.FwSubtitleRenderer = class FwSubtitleRenderer extends lit.LitElement {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.currentTime = 0;
11
+ this.enabled = false;
12
+ this.cues = [];
13
+ }
14
+ get _activeCue() {
15
+ if (!this.enabled || !this.cues.length)
16
+ return null;
17
+ const t = this.currentTime * 1000; // Convert to ms
18
+ for (const cue of this.cues) {
19
+ if (t >= cue.startTime && t <= cue.endTime)
20
+ return cue.text;
21
+ }
22
+ return null;
23
+ }
24
+ render() {
25
+ const text = this._activeCue;
26
+ if (!text)
27
+ return lit.nothing;
28
+ return lit.html `<span class="subtitle" aria-live="polite">${text}</span>`;
29
+ }
30
+ };
31
+ exports.FwSubtitleRenderer.styles = lit.css `
32
+ :host {
33
+ display: contents;
34
+ }
35
+ .subtitle {
36
+ position: absolute;
37
+ bottom: 5%;
38
+ left: 50%;
39
+ transform: translateX(-50%);
40
+ display: inline-block;
41
+ max-width: 90%;
42
+ padding: 0.5em 1em;
43
+ border-radius: 4px;
44
+ background: rgb(0 0 0 / 0.75);
45
+ color: white;
46
+ font-size: 1.5rem;
47
+ font-family:
48
+ system-ui,
49
+ -apple-system,
50
+ sans-serif;
51
+ text-shadow: 2px 2px 4px rgb(0 0 0 / 0.5);
52
+ white-space: pre-wrap;
53
+ text-align: center;
54
+ z-index: 15;
55
+ pointer-events: none;
56
+ }
57
+ `;
58
+ tslib_es6.__decorate([
59
+ decorators_js.property({ type: Number })
60
+ ], exports.FwSubtitleRenderer.prototype, "currentTime", void 0);
61
+ tslib_es6.__decorate([
62
+ decorators_js.property({ type: Boolean })
63
+ ], exports.FwSubtitleRenderer.prototype, "enabled", void 0);
64
+ tslib_es6.__decorate([
65
+ decorators_js.property({ attribute: false })
66
+ ], exports.FwSubtitleRenderer.prototype, "cues", void 0);
67
+ exports.FwSubtitleRenderer = tslib_es6.__decorate([
68
+ decorators_js.customElement("fw-subtitle-renderer")
69
+ ], exports.FwSubtitleRenderer);
70
+ //# sourceMappingURL=fw-subtitle-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fw-subtitle-renderer.js","sources":["../../../../src/components/fw-subtitle-renderer.ts"],"sourcesContent":["import { LitElement, html, css, nothing } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\n\ninterface SubtitleCue {\n id?: string;\n startTime: number;\n endTime: number;\n text: string;\n}\n\n@customElement(\"fw-subtitle-renderer\")\nexport class FwSubtitleRenderer extends LitElement {\n @property({ type: Number }) currentTime = 0;\n @property({ type: Boolean }) enabled = false;\n @property({ attribute: false }) cues: SubtitleCue[] = [];\n\n static styles = css`\n :host {\n display: contents;\n }\n .subtitle {\n position: absolute;\n bottom: 5%;\n left: 50%;\n transform: translateX(-50%);\n display: inline-block;\n max-width: 90%;\n padding: 0.5em 1em;\n border-radius: 4px;\n background: rgb(0 0 0 / 0.75);\n color: white;\n font-size: 1.5rem;\n font-family:\n system-ui,\n -apple-system,\n sans-serif;\n text-shadow: 2px 2px 4px rgb(0 0 0 / 0.5);\n white-space: pre-wrap;\n text-align: center;\n z-index: 15;\n pointer-events: none;\n }\n `;\n\n private get _activeCue(): string | null {\n if (!this.enabled || !this.cues.length) return null;\n const t = this.currentTime * 1000; // Convert to ms\n for (const cue of this.cues) {\n if (t >= cue.startTime && t <= cue.endTime) return cue.text;\n }\n return null;\n }\n\n protected render() {\n const text = this._activeCue;\n if (!text) return nothing;\n return html`<span class=\"subtitle\" aria-live=\"polite\">${text}</span>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"fw-subtitle-renderer\": FwSubtitleRenderer;\n }\n}\n"],"names":["FwSubtitleRenderer","LitElement","nothing","html","css","__decorate","property","customElement"],"mappings":";;;;;;AAWaA,0BAAkB,GAAxB,MAAM,kBAAmB,SAAQC,cAAU,CAAA;AAA3C,IAAA,WAAA,GAAA;;QACuB,IAAA,CAAA,WAAW,GAAG,CAAC;QACd,IAAA,CAAA,OAAO,GAAG,KAAK;QACZ,IAAA,CAAA,IAAI,GAAkB,EAAE;IA4C1D;AAdE,IAAA,IAAY,UAAU,GAAA;QACpB,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,IAAI;QACnD,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;AAClC,QAAA,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE;YAC3B,IAAI,CAAC,IAAI,GAAG,CAAC,SAAS,IAAI,CAAC,IAAI,GAAG,CAAC,OAAO;gBAAE,OAAO,GAAG,CAAC,IAAI;QAC7D;AACA,QAAA,OAAO,IAAI;IACb;IAEU,MAAM,GAAA;AACd,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU;AAC5B,QAAA,IAAI,CAAC,IAAI;AAAE,YAAA,OAAOC,WAAO;AACzB,QAAA,OAAOC,QAAI,CAAA,CAAA,0CAAA,EAA6C,IAAI,SAAS;IACvE;;AAzCOH,0BAAA,CAAA,MAAM,GAAGI,OAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BlB,EAAA,CA1BY;AAJeC,oBAAA,CAAA;AAA3B,IAAAC,sBAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;AAAkB,CAAA,EAAAN,0BAAA,CAAA,SAAA,EAAA,aAAA,EAAA,MAAA,CAAA;AACfK,oBAAA,CAAA;AAA5B,IAAAC,sBAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE;AAAkB,CAAA,EAAAN,0BAAA,CAAA,SAAA,EAAA,SAAA,EAAA,MAAA,CAAA;AACbK,oBAAA,CAAA;AAA/B,IAAAC,sBAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE;AAA2B,CAAA,EAAAN,0BAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,CAAA;AAH9CA,0BAAkB,GAAAK,oBAAA,CAAA;IAD9BE,2BAAa,CAAC,sBAAsB;AACxB,CAAA,EAAAP,0BAAkB,CA+C9B;;"}
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ var tslib_es6 = require('../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');
4
+ var lit = require('lit');
5
+ var decorators_js = require('lit/decorators.js');
6
+ var sharedStyles = require('../styles/shared-styles.js');
7
+ var utilityStyles = require('../styles/utility-styles.js');
8
+
9
+ exports.FwTitleOverlay = class FwTitleOverlay extends lit.LitElement {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.title = "";
13
+ this.description = null;
14
+ }
15
+ render() {
16
+ if (this.title === "" && !this.description)
17
+ return lit.nothing;
18
+ return lit.html `
19
+ <div class="overlay fw-title-overlay">
20
+ ${this.title ? lit.html `<div class="title">${this.title}</div>` : lit.nothing}
21
+ ${this.description ? lit.html `<div class="desc">${this.description}</div>` : lit.nothing}
22
+ </div>
23
+ `;
24
+ }
25
+ };
26
+ exports.FwTitleOverlay.styles = [
27
+ sharedStyles.sharedStyles,
28
+ utilityStyles.utilityStyles,
29
+ lit.css `
30
+ :host {
31
+ display: contents;
32
+ }
33
+ .overlay {
34
+ position: absolute;
35
+ inset: 0 0 auto 0;
36
+ padding: 1rem 1.25rem;
37
+ background: linear-gradient(to bottom, rgb(0 0 0 / 0.7), rgb(0 0 0 / 0.4), transparent);
38
+ pointer-events: none;
39
+ transition: opacity 300ms ease;
40
+ z-index: 10;
41
+ }
42
+ .title {
43
+ font-size: 0.875rem;
44
+ font-weight: 500;
45
+ color: white;
46
+ max-width: 80%;
47
+ overflow: hidden;
48
+ text-overflow: ellipsis;
49
+ white-space: nowrap;
50
+ }
51
+ .desc {
52
+ margin-top: 0.25rem;
53
+ font-size: 0.75rem;
54
+ color: rgb(255 255 255 / 0.7);
55
+ max-width: 70%;
56
+ display: -webkit-box;
57
+ -webkit-line-clamp: 2;
58
+ -webkit-box-orient: vertical;
59
+ overflow: hidden;
60
+ }
61
+ `,
62
+ ];
63
+ tslib_es6.__decorate([
64
+ decorators_js.property({ type: String })
65
+ ], exports.FwTitleOverlay.prototype, "title", void 0);
66
+ tslib_es6.__decorate([
67
+ decorators_js.property({ type: String })
68
+ ], exports.FwTitleOverlay.prototype, "description", void 0);
69
+ exports.FwTitleOverlay = tslib_es6.__decorate([
70
+ decorators_js.customElement("fw-title-overlay")
71
+ ], exports.FwTitleOverlay);
72
+ //# sourceMappingURL=fw-title-overlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fw-title-overlay.js","sources":["../../../../src/components/fw-title-overlay.ts"],"sourcesContent":["import { LitElement, html, css, nothing } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { sharedStyles } from \"../styles/shared-styles.js\";\nimport { utilityStyles } from \"../styles/utility-styles.js\";\n\n@customElement(\"fw-title-overlay\")\nexport class FwTitleOverlay extends LitElement {\n @property({ type: String }) override title: string = \"\";\n @property({ type: String }) description: string | null = null;\n\n static styles = [\n sharedStyles,\n utilityStyles,\n css`\n :host {\n display: contents;\n }\n .overlay {\n position: absolute;\n inset: 0 0 auto 0;\n padding: 1rem 1.25rem;\n background: linear-gradient(to bottom, rgb(0 0 0 / 0.7), rgb(0 0 0 / 0.4), transparent);\n pointer-events: none;\n transition: opacity 300ms ease;\n z-index: 10;\n }\n .title {\n font-size: 0.875rem;\n font-weight: 500;\n color: white;\n max-width: 80%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .desc {\n margin-top: 0.25rem;\n font-size: 0.75rem;\n color: rgb(255 255 255 / 0.7);\n max-width: 70%;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n `,\n ];\n\n protected render() {\n if (this.title === \"\" && !this.description) return nothing;\n return html`\n <div class=\"overlay fw-title-overlay\">\n ${this.title ? html`<div class=\"title\">${this.title}</div>` : nothing}\n ${this.description ? html`<div class=\"desc\">${this.description}</div>` : nothing}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"fw-title-overlay\": FwTitleOverlay;\n }\n}\n"],"names":["FwTitleOverlay","LitElement","nothing","html","sharedStyles","utilityStyles","css","__decorate","property","customElement"],"mappings":";;;;;;;;AAMaA,sBAAc,GAApB,MAAM,cAAe,SAAQC,cAAU,CAAA;AAAvC,IAAA,WAAA,GAAA;;QACgC,IAAA,CAAA,KAAK,GAAW,EAAE;QAC3B,IAAA,CAAA,WAAW,GAAkB,IAAI;IAiD/D;IATY,MAAM,GAAA;QACd,IAAI,IAAI,CAAC,KAAK,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;AAAE,YAAA,OAAOC,WAAO;AAC1D,QAAA,OAAOC,QAAI,CAAA;;AAEL,QAAA,EAAA,IAAI,CAAC,KAAK,GAAGA,QAAI,CAAA,CAAA,mBAAA,EAAsB,IAAI,CAAC,KAAK,CAAA,MAAA,CAAQ,GAAGD,WAAO;AACnE,QAAA,EAAA,IAAI,CAAC,WAAW,GAAGC,QAAI,CAAA,CAAA,kBAAA,EAAqB,IAAI,CAAC,WAAW,CAAA,MAAA,CAAQ,GAAGD,WAAO;;KAEnF;IACH;;AA9COF,sBAAA,CAAA,MAAM,GAAG;IACdI,yBAAY;IACZC,2BAAa;AACb,IAAAC,OAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCF,IAAA,CAAA;AACF,CApCY;AAHwBC,oBAAA,CAAA;AAApC,IAAAC,sBAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;AAA8B,CAAA,EAAAR,sBAAA,CAAA,SAAA,EAAA,OAAA,EAAA,MAAA,CAAA;AAC5BO,oBAAA,CAAA;AAA3B,IAAAC,sBAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;AAAoC,CAAA,EAAAR,sBAAA,CAAA,SAAA,EAAA,aAAA,EAAA,MAAA,CAAA;AAFnDA,sBAAc,GAAAO,oBAAA,CAAA;IAD1BE,2BAAa,CAAC,kBAAkB;AACpB,CAAA,EAAAT,sBAAc,CAmD1B;;"}
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ var tslib_es6 = require('../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');
4
+ var lit = require('lit');
5
+ var decorators_js = require('lit/decorators.js');
6
+ var index = require('../icons/index.js');
7
+
8
+ exports.FwToast = class FwToast extends lit.LitElement {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.message = "";
12
+ }
13
+ render() {
14
+ if (!this.message)
15
+ return lit.nothing;
16
+ return lit.html `
17
+ <div class="toast">
18
+ <span>${this.message}</span>
19
+ <button type="button" @click=${this._dismiss} aria-label="Dismiss">${index.closeIcon()}</button>
20
+ </div>
21
+ `;
22
+ }
23
+ _dismiss() {
24
+ this.dispatchEvent(new CustomEvent("fw-dismiss", { bubbles: true, composed: true }));
25
+ }
26
+ };
27
+ exports.FwToast.styles = lit.css `
28
+ :host {
29
+ display: contents;
30
+ }
31
+ .toast {
32
+ display: flex;
33
+ align-items: center;
34
+ gap: 0.5rem;
35
+ border-radius: 0.5rem;
36
+ border: 1px solid rgb(255 255 255 / 0.1);
37
+ background: rgb(0 0 0 / 0.8);
38
+ padding: 0.5rem 1rem;
39
+ font-size: 0.875rem;
40
+ color: white;
41
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
42
+ backdrop-filter: blur(4px);
43
+ animation: _fw-slide-up 200ms ease-out;
44
+ }
45
+ @keyframes _fw-slide-up {
46
+ from {
47
+ opacity: 0;
48
+ transform: translateY(8px);
49
+ }
50
+ to {
51
+ opacity: 1;
52
+ transform: translateY(0);
53
+ }
54
+ }
55
+ button {
56
+ margin-left: 0.125rem;
57
+ color: rgb(255 255 255 / 0.6);
58
+ background: none;
59
+ border: none;
60
+ cursor: pointer;
61
+ padding: 0;
62
+ display: flex;
63
+ }
64
+ button:hover {
65
+ color: white;
66
+ }
67
+ `;
68
+ tslib_es6.__decorate([
69
+ decorators_js.property({ type: String })
70
+ ], exports.FwToast.prototype, "message", void 0);
71
+ exports.FwToast = tslib_es6.__decorate([
72
+ decorators_js.customElement("fw-toast")
73
+ ], exports.FwToast);
74
+ //# sourceMappingURL=fw-toast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fw-toast.js","sources":["../../../../src/components/fw-toast.ts"],"sourcesContent":["import { LitElement, html, css, nothing } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { closeIcon } from \"../icons/index.js\";\n\n@customElement(\"fw-toast\")\nexport class FwToast extends LitElement {\n @property({ type: String }) message = \"\";\n\n static styles = css`\n :host {\n display: contents;\n }\n .toast {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n border-radius: 0.5rem;\n border: 1px solid rgb(255 255 255 / 0.1);\n background: rgb(0 0 0 / 0.8);\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n color: white;\n box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);\n backdrop-filter: blur(4px);\n animation: _fw-slide-up 200ms ease-out;\n }\n @keyframes _fw-slide-up {\n from {\n opacity: 0;\n transform: translateY(8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n button {\n margin-left: 0.125rem;\n color: rgb(255 255 255 / 0.6);\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n display: flex;\n }\n button:hover {\n color: white;\n }\n `;\n\n protected render() {\n if (!this.message) return nothing;\n return html`\n <div class=\"toast\">\n <span>${this.message}</span>\n <button type=\"button\" @click=${this._dismiss} aria-label=\"Dismiss\">${closeIcon()}</button>\n </div>\n `;\n }\n\n private _dismiss() {\n this.dispatchEvent(new CustomEvent(\"fw-dismiss\", { bubbles: true, composed: true }));\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"fw-toast\": FwToast;\n }\n}\n"],"names":["FwToast","LitElement","nothing","html","closeIcon","css","__decorate","property","customElement"],"mappings":";;;;;;;AAKaA,eAAO,GAAb,MAAM,OAAQ,SAAQC,cAAU,CAAA;AAAhC,IAAA,WAAA,GAAA;;QACuB,IAAA,CAAA,OAAO,GAAG,EAAE;IAyD1C;IAbY,MAAM,GAAA;QACd,IAAI,CAAC,IAAI,CAAC,OAAO;AAAE,YAAA,OAAOC,WAAO;AACjC,QAAA,OAAOC,QAAI,CAAA;;AAEC,cAAA,EAAA,IAAI,CAAC,OAAO,CAAA;AACW,qCAAA,EAAA,IAAI,CAAC,QAAQ,CAAA,sBAAA,EAAyBC,eAAS,EAAE,CAAA;;KAEnF;IACH;IAEQ,QAAQ,GAAA;AACd,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACtF;;AAtDOJ,eAAA,CAAA,MAAM,GAAGK,OAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwClB,EAAA,CAxCY;AAFeC,oBAAA,CAAA;AAA3B,IAAAC,sBAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;AAAe,CAAA,EAAAP,eAAA,CAAA,SAAA,EAAA,SAAA,EAAA,MAAA,CAAA;AAD9BA,eAAO,GAAAM,oBAAA,CAAA;IADnBE,2BAAa,CAAC,UAAU;AACZ,CAAA,EAAAR,eAAO,CA0DnB;;"}
@@ -0,0 +1,140 @@
1
+ 'use strict';
2
+
3
+ var tslib_es6 = require('../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');
4
+ var lit = require('lit');
5
+ var decorators_js = require('lit/decorators.js');
6
+ var classMap_js = require('lit/directives/class-map.js');
7
+ var styleMap_js = require('lit/directives/style-map.js');
8
+ var sharedStyles = require('../styles/shared-styles.js');
9
+ var index = require('../icons/index.js');
10
+
11
+ exports.FwVolumeControl = class FwVolumeControl extends lit.LitElement {
12
+ constructor() {
13
+ super(...arguments);
14
+ this._expanded = false;
15
+ this._handleSliderClick = (e) => {
16
+ const target = e.currentTarget;
17
+ const rect = target.getBoundingClientRect();
18
+ const pct = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
19
+ this.pc.setVolume(pct);
20
+ if (this.pc.s.isMuted && pct > 0)
21
+ this.pc.toggleMute();
22
+ };
23
+ this._handleSliderDrag = (e) => {
24
+ const target = e.currentTarget;
25
+ const rect = target.getBoundingClientRect();
26
+ const pct = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
27
+ this.pc.setVolume(pct);
28
+ };
29
+ }
30
+ render() {
31
+ const { isMuted, volume } = this.pc.s;
32
+ const displayVol = isMuted ? 0 : volume;
33
+ return lit.html `
34
+ <div
35
+ class="group fw-volume-group"
36
+ @mouseenter=${() => {
37
+ this._expanded = true;
38
+ }}
39
+ @mouseleave=${() => {
40
+ this._expanded = false;
41
+ }}
42
+ >
43
+ <button
44
+ class="btn fw-btn-flush fw-volume-btn"
45
+ type="button"
46
+ @click=${() => this.pc.toggleMute()}
47
+ aria-label="${isMuted ? "Unmute" : "Mute"}"
48
+ >
49
+ ${isMuted ? index.volumeOffIcon(16) : index.volumeUpIcon(16)}
50
+ </button>
51
+ <div class=${classMap_js.classMap({ "slider-wrap": true, "slider-wrap--expanded": this._expanded })}>
52
+ <div
53
+ class="slider"
54
+ @click=${this._handleSliderClick}
55
+ @pointermove=${this._handleSliderDrag}
56
+ >
57
+ <div class="slider-fill" style=${styleMap_js.styleMap({ width: `${displayVol * 100}%` })}></div>
58
+ <div class="slider-thumb" style=${styleMap_js.styleMap({ left: `${displayVol * 100}%` })}></div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ `;
63
+ }
64
+ };
65
+ exports.FwVolumeControl.styles = [
66
+ sharedStyles.sharedStyles,
67
+ lit.css `
68
+ :host {
69
+ display: flex;
70
+ align-items: center;
71
+ }
72
+ .group {
73
+ display: flex;
74
+ align-items: center;
75
+ gap: 0;
76
+ }
77
+ .btn {
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ width: 2rem;
82
+ height: 2rem;
83
+ background: none;
84
+ border: none;
85
+ color: rgb(255 255 255 / 0.8);
86
+ cursor: pointer;
87
+ padding: 0;
88
+ border-radius: 0.25rem;
89
+ transition: color 150ms;
90
+ }
91
+ .btn:hover {
92
+ color: white;
93
+ }
94
+ .slider-wrap {
95
+ width: 0;
96
+ overflow: hidden;
97
+ transition: width 200ms ease;
98
+ }
99
+ .slider-wrap--expanded {
100
+ width: 72px;
101
+ }
102
+ .slider {
103
+ position: relative;
104
+ width: 72px;
105
+ height: 4px;
106
+ background: rgb(255 255 255 / 0.15);
107
+ border-radius: 2px;
108
+ cursor: pointer;
109
+ }
110
+ .slider-fill {
111
+ position: absolute;
112
+ top: 0;
113
+ left: 0;
114
+ height: 100%;
115
+ background: white;
116
+ border-radius: 2px;
117
+ pointer-events: none;
118
+ }
119
+ .slider-thumb {
120
+ position: absolute;
121
+ top: 50%;
122
+ width: 10px;
123
+ height: 10px;
124
+ border-radius: 50%;
125
+ background: white;
126
+ transform: translate(-50%, -50%);
127
+ pointer-events: none;
128
+ }
129
+ `,
130
+ ];
131
+ tslib_es6.__decorate([
132
+ decorators_js.property({ attribute: false })
133
+ ], exports.FwVolumeControl.prototype, "pc", void 0);
134
+ tslib_es6.__decorate([
135
+ decorators_js.state()
136
+ ], exports.FwVolumeControl.prototype, "_expanded", void 0);
137
+ exports.FwVolumeControl = tslib_es6.__decorate([
138
+ decorators_js.customElement("fw-volume-control")
139
+ ], exports.FwVolumeControl);
140
+ //# sourceMappingURL=fw-volume-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fw-volume-control.js","sources":["../../../../src/components/fw-volume-control.ts"],"sourcesContent":["/**\n * <fw-volume-control> — Mute toggle + volume slider.\n */\nimport { LitElement, html, css } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { classMap } from \"lit/directives/class-map.js\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport { sharedStyles } from \"../styles/shared-styles.js\";\nimport { volumeUpIcon, volumeOffIcon } from \"../icons/index.js\";\nimport type { PlayerControllerHost } from \"../controllers/player-controller-host.js\";\n\n@customElement(\"fw-volume-control\")\nexport class FwVolumeControl extends LitElement {\n @property({ attribute: false }) pc!: PlayerControllerHost;\n @state() private _expanded = false;\n\n static styles = [\n sharedStyles,\n css`\n :host {\n display: flex;\n align-items: center;\n }\n .group {\n display: flex;\n align-items: center;\n gap: 0;\n }\n .btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n background: none;\n border: none;\n color: rgb(255 255 255 / 0.8);\n cursor: pointer;\n padding: 0;\n border-radius: 0.25rem;\n transition: color 150ms;\n }\n .btn:hover {\n color: white;\n }\n .slider-wrap {\n width: 0;\n overflow: hidden;\n transition: width 200ms ease;\n }\n .slider-wrap--expanded {\n width: 72px;\n }\n .slider {\n position: relative;\n width: 72px;\n height: 4px;\n background: rgb(255 255 255 / 0.15);\n border-radius: 2px;\n cursor: pointer;\n }\n .slider-fill {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: white;\n border-radius: 2px;\n pointer-events: none;\n }\n .slider-thumb {\n position: absolute;\n top: 50%;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: white;\n transform: translate(-50%, -50%);\n pointer-events: none;\n }\n `,\n ];\n\n private _handleSliderClick = (e: MouseEvent) => {\n const target = e.currentTarget as HTMLElement;\n const rect = target.getBoundingClientRect();\n const pct = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));\n this.pc.setVolume(pct);\n if (this.pc.s.isMuted && pct > 0) this.pc.toggleMute();\n };\n\n private _handleSliderDrag = (e: PointerEvent) => {\n const target = e.currentTarget as HTMLElement;\n const rect = target.getBoundingClientRect();\n const pct = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));\n this.pc.setVolume(pct);\n };\n\n protected render() {\n const { isMuted, volume } = this.pc.s;\n const displayVol = isMuted ? 0 : volume;\n\n return html`\n <div\n class=\"group fw-volume-group\"\n @mouseenter=${() => {\n this._expanded = true;\n }}\n @mouseleave=${() => {\n this._expanded = false;\n }}\n >\n <button\n class=\"btn fw-btn-flush fw-volume-btn\"\n type=\"button\"\n @click=${() => this.pc.toggleMute()}\n aria-label=\"${isMuted ? \"Unmute\" : \"Mute\"}\"\n >\n ${isMuted ? volumeOffIcon(16) : volumeUpIcon(16)}\n </button>\n <div class=${classMap({ \"slider-wrap\": true, \"slider-wrap--expanded\": this._expanded })}>\n <div\n class=\"slider\"\n @click=${this._handleSliderClick}\n @pointermove=${this._handleSliderDrag}\n >\n <div class=\"slider-fill\" style=${styleMap({ width: `${displayVol * 100}%` })}></div>\n <div class=\"slider-thumb\" style=${styleMap({ left: `${displayVol * 100}%` })}></div>\n </div>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"fw-volume-control\": FwVolumeControl;\n }\n}\n"],"names":["FwVolumeControl","LitElement","html","volumeOffIcon","volumeUpIcon","classMap","styleMap","sharedStyles","css","__decorate","property","state","customElement"],"mappings":"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"}