@oddin-gg/havik-player 2.13.1 → 2.15.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.
package/docs/API.md CHANGED
@@ -231,6 +231,7 @@ player.on('error', (e) => console.error(e.code, e.httpStatus, e.message));
231
231
  | `controls` | `'custom' \| 'native' \| 'none'` | `'custom'` | Which controls to render. See [Controls & theming](#controls--theming). |
232
232
  | `theme` | [`Partial<HavikTheme>`](#haviktheme) | Oddin brand | Re-skin the custom control bar (ignored unless `controls: 'custom'`). See [Controls & theming](#controls--theming). |
233
233
  | `statusOverlays` | `boolean` | `true` | Branded full-bleed cards for the stopped/pre-play states (ended, fatal error, pre-play, armed-waiting) instead of a frozen frame + a dead play button. Themed via the control-bar tokens + `theme.logoUrl`. Set `false` to render your own UI from the `ended`/`error` events. Ignored unless `controls: 'custom'`. |
234
+ | `cspNonce` | `string` | — | Your page's CSP nonce, stamped on the `<style>` tag the custom control bar injects. Needed only when `style-src` has no `'unsafe-inline'`: without it the browser blocks the tag and the controls render unstyled. See [Content-Security-Policy](#content-security-policy). Ignored unless `controls: 'custom'`. |
234
235
  | `endedMessage` | `string` | "This stream has ended" | Message on the end-of-stream card. |
235
236
  | `interruptedMessage` | `string` | "Reconnecting — please stand by" | Message shown **instead of** `endedMessage` when the server reports the stream stopped but the match is still running (`endedReason: 'interrupted'`, an ingest outage that outlived the bridge's hold). The player rejoins automatically when the stream returns **while `rejoinOnLive` is on** (the default); override this wording if you disable auto-rejoin, since nothing will re-attach on its own. |
236
237
  | `errorMessage` | `string` | the error's message | Message on the fatal-error card (otherwise the error's own message). |
@@ -408,7 +409,10 @@ the theme colors; customise the copy with `endedMessage`/`interruptedMessage`/`e
408
409
  `statusOverlays: false` to drive your own end/error UI from the player events.
409
410
  It auto-hides during playback, supports keyboard shortcuts (space/`k` play-pause,
410
411
  `m` mute, `f` fullscreen, `c` captions, `l` go-live, arrows seek/volume), and is
411
- fully keyboard- and screen-reader-accessible.
412
+ fully keyboard- and screen-reader-accessible. On a mouse, one click on the
413
+ picture plays/pauses. On touch, a single tap shows or hides the bar and a double
414
+ tap plays/pauses, so bringing the controls back on a phone never pauses the
415
+ stream.
412
416
 
413
417
  > **Fullscreen on iPhone:** iPhone Safari has no element Fullscreen API, so the
414
418
  > fullscreen button there enters the **video-native** fullscreen
@@ -430,6 +434,27 @@ type Controls = 'custom' | 'native' | 'none';
430
434
  | `'native'` | The browser's built-in `<video controls>` UI. No wrapper element is added. |
431
435
  | `'none'` | No controls. Drive the player entirely through its [API](#player) (build your own). |
432
436
 
437
+ #### Content-Security-Policy
438
+
439
+ The custom control bar injects one `<style>` tag into the page `<head>`. A page
440
+ whose `style-src` has no `'unsafe-inline'` blocks that tag, and the controls
441
+ render unstyled. Pass the page's nonce as `cspNonce`, and the tag carries it:
442
+
443
+ ```ts
444
+ await createPlayer({
445
+ video,
446
+ env: 'integration',
447
+ matchUrn: 'od:match:1234',
448
+ credential: { apiKey: 'pk_test_…' },
449
+ cspNonce: 'r4nd0mN0nce',
450
+ });
451
+ // with Content-Security-Policy: style-src 'nonce-r4nd0mN0nce'
452
+ ```
453
+
454
+ The rest of the SDK needs no inline style: the theme is applied through CSS
455
+ variables set from JavaScript, which `style-src` allows. With `controls:
456
+ 'native'` or `'none'`, nothing is injected and no nonce is needed.
457
+
433
458
  Re-skin the custom bar in one of two ways; both set the same CSS variables, so
434
459
  they're interchangeable:
435
460
 
package/embed/index.html CHANGED
@@ -28,7 +28,7 @@
28
28
  beacons endpoint can be derived and QoE analytics is silently off.
29
29
  `analytics` is honoured from the injected config only, never the query.
30
30
  -->
31
- <script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.13.1/dist/havik-player.global.js" integrity="sha384-Ct4ZlpTNiWMbtKCo8d52uoSElmYIBpTVj5AgN8kj8KxV6jU7Ok9dDqSg8Id2k5Kd" crossorigin="anonymous"></script>
31
+ <script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.15.0/dist/havik-player.global.js" integrity="sha384-rjpWbfgvCFYqBjKvo1svn8xWY0IWY1Go5D76lXwkSIPGJl1mFeAr/8FAYV76b/v2" crossorigin="anonymous"></script>
32
32
  <script>
33
33
  HavikPlayer.bootEmbed();
34
34
  </script>
@@ -12,7 +12,7 @@
12
12
  shipped in each npm release is pinned to that release with Subresource
13
13
  Integrity, injected at publish time (scripts/inject-sri.mjs). In
14
14
  production, always use a pinned + SRI'd tag like the released copy. -->
15
- <script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.13.1/dist/havik-player.global.js" integrity="sha384-Ct4ZlpTNiWMbtKCo8d52uoSElmYIBpTVj5AgN8kj8KxV6jU7Ok9dDqSg8Id2k5Kd" crossorigin="anonymous"></script>
15
+ <script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.15.0/dist/havik-player.global.js" integrity="sha384-rjpWbfgvCFYqBjKvo1svn8xWY0IWY1Go5D76lXwkSIPGJl1mFeAr/8FAYV76b/v2" crossorigin="anonymous"></script>
16
16
  <script>
17
17
  (async () => {
18
18
  const player = await HavikPlayer.createPlayer({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oddin-gg/havik-player",
3
- "version": "2.13.1",
3
+ "version": "2.15.0",
4
4
  "description": "Havik HTML5 player SDK — LL-HLS + DRM playback for Oddin live streams (managed, bring-your-own-player, and iframe-embed modes).",
5
5
  "type": "module",
6
6
  "sideEffects": false,