@oddin-gg/havik-player 1.0.3 → 1.0.5

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/index.js CHANGED
@@ -518,9 +518,13 @@ function me(e) {
518
518
  }
519
519
  e.liveSyncDuration ??= fe;
520
520
  let t = Math.max(12, e.liveSyncDuration + pe);
521
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t);
521
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), he(e, e.liveSyncDuration);
522
522
  }
523
- var he = class {
523
+ function he(e, t) {
524
+ let n = (e, t, n) => Math.min(n, Math.max(t, e));
525
+ e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
526
+ }
527
+ var ge = class {
524
528
  name = "hls";
525
529
  hls = null;
526
530
  deps;
@@ -709,7 +713,7 @@ var he = class {
709
713
  resumeChasing() {
710
714
  this.chaseSuspended = !1;
711
715
  let e = this.hls;
712
- e && (this.savedLiveMaxLatency !== void 0 && (e.config.liveMaxLatencyDuration = this.savedLiveMaxLatency), this.savedMaxSyncRate !== void 0 && (e.config.maxLiveSyncPlaybackRate = this.savedMaxSyncRate));
716
+ e && (e.config.liveMaxLatencyDuration = this.savedLiveMaxLatency, e.config.maxLiveSyncPlaybackRate = this.savedMaxSyncRate);
713
717
  }
714
718
  emitEnded(e) {
715
719
  this.endedEmitted || (this.endedEmitted = !0, this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.deps.emit({
@@ -811,7 +815,7 @@ var he = class {
811
815
  };
812
816
  //#endregion
813
817
  //#region src/core/engine/native.ts
814
- function ge(e) {
818
+ function _e(e) {
815
819
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
816
820
  }
817
821
  var W = class {
@@ -942,15 +946,15 @@ function q(e, t) {
942
946
  }
943
947
  //#endregion
944
948
  //#region src/ui/styles.ts
945
- var J = "havik-player-styles", _e = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:rgba(255,255,255,.3);border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:70px;opacity:1}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:50%;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
946
- function ve(e = document) {
949
+ var J = "havik-player-styles", ve = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:rgba(255,255,255,.3);border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:70px;opacity:1}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:50%;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
950
+ function ye(e = document) {
947
951
  if (e.getElementById(J)) return;
948
952
  let t = e.createElement("style");
949
- t.id = J, t.textContent = _e, e.head.appendChild(t);
953
+ t.id = J, t.textContent = ve, e.head.appendChild(t);
950
954
  }
951
955
  //#endregion
952
956
  //#region src/ui/icons.ts
953
- var ye = {
957
+ var be = {
954
958
  play: "<path d=\"M8 5v14l11-7z\"/>",
955
959
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
956
960
  volumeHigh: "<path d=\"M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4zm-2.5-9v2.06A7 7 0 0 1 14 19v2a9 9 0 0 0 0-18z\"/>",
@@ -964,20 +968,20 @@ var ye = {
964
968
  retry: "<path d=\"M17.65 6.35A8 8 0 1 0 19.73 13h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>"
965
969
  };
966
970
  function Y(e) {
967
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${ye[e]}</svg>`;
971
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${be[e]}</svg>`;
968
972
  }
969
973
  //#endregion
970
974
  //#region src/ui/controls.ts
971
- var be = 3e3, xe = /* @__PURE__ */ new Set([
975
+ var xe = 3e3, Se = /* @__PURE__ */ new Set([
972
976
  "GONE",
973
977
  "NOT_FOUND",
974
978
  "INVALID_URN",
975
979
  "UNAUTHORIZED"
976
980
  ]);
977
- function Se(e) {
978
- return new Ce(e);
981
+ function Ce(e) {
982
+ return new we(e);
979
983
  }
980
- var Ce = class {
984
+ var we = class {
981
985
  root;
982
986
  video;
983
987
  player;
@@ -1017,7 +1021,7 @@ var Ce = class {
1017
1021
  scrubbing = !1;
1018
1022
  offFns = [];
1019
1023
  constructor(e) {
1020
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? be, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.errorMessage = e.errorMessage, ve(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
1024
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? xe, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.errorMessage = e.errorMessage, ye(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
1021
1025
  let t = (e, t, n) => {
1022
1026
  let r = this.doc.createElement(e);
1023
1027
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -1104,7 +1108,7 @@ var Ce = class {
1104
1108
  e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Y("play"), e.addEventListener("click", () => void this.player.play()), t.append(e);
1105
1109
  } else {
1106
1110
  let n = this.doc.createElement("div");
1107
- if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !xe.has(this.lastError.code)) {
1111
+ if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !Se.has(this.lastError.code)) {
1108
1112
  let e = this.doc.createElement("button");
1109
1113
  e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Y("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), t.append(e);
1110
1114
  }
@@ -1193,17 +1197,17 @@ var Ce = class {
1193
1197
  renderQualityMenu() {
1194
1198
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
1195
1199
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
1196
- for (let n of e) this.menu.append(this.menuItem(we(n), t === n.index, () => this.player.setQuality(n.index)));
1200
+ for (let n of e) this.menu.append(this.menuItem(Te(n), t === n.index, () => this.player.setQuality(n.index)));
1197
1201
  }
1198
1202
  renderAudioMenu() {
1199
1203
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
1200
1204
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
1201
- for (let t of e) this.menu.append(this.menuItem(Te(t), t.default, () => this.player.setAudioTrack(t.id)));
1205
+ for (let t of e) this.menu.append(this.menuItem(Ee(t), t.default, () => this.player.setAudioTrack(t.id)));
1202
1206
  }
1203
1207
  renderCcMenu() {
1204
1208
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
1205
1209
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
1206
- for (let t of e) this.menu.append(this.menuItem(Ee(t), !1, () => this.player.setTextTrack(t.id)));
1210
+ for (let t of e) this.menu.append(this.menuItem(De(t), !1, () => this.player.setTextTrack(t.id)));
1207
1211
  }
1208
1212
  onTracksChanged() {
1209
1213
  this.openMenu && this.renderMenu(this.openMenu);
@@ -1309,27 +1313,27 @@ function X(e) {
1309
1313
  let t = Math.floor(e % 60), n = Math.floor(e / 60 % 60), r = Math.floor(e / 3600), i = r > 0 ? String(n).padStart(2, "0") : String(n), a = String(t).padStart(2, "0");
1310
1314
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
1311
1315
  }
1312
- function we(e) {
1316
+ function Te(e) {
1313
1317
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
1314
1318
  }
1315
- function Te(e) {
1319
+ function Ee(e) {
1316
1320
  return e.name || e.lang || `Track ${e.id}`;
1317
1321
  }
1318
- function Ee(e) {
1322
+ function De(e) {
1319
1323
  return e.name || e.lang || `Track ${e.id}`;
1320
1324
  }
1321
1325
  //#endregion
1322
1326
  //#region src/managed/index.ts
1323
- var De = 6e3, Oe = 45e3, ke = 2e3, Z = 3, Ae = 2e3, je = 480 * 1e3;
1327
+ var Oe = 6e3, ke = 45e3, Z = 2e3, Ae = 3, je = 2e3, Me = 480 * 1e3;
1324
1328
  async function Q(e) {
1325
1329
  if (!e.video || typeof e.video.play != "function") throw new t("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
1326
1330
  if (!e.baseUrl) throw new t("INTERNAL", 0, "createPlayer: baseUrl is required");
1327
1331
  if (!e.matchUrn) throw new t("INVALID_URN", 0, "createPlayer: matchUrn is required");
1328
1332
  if (!e.credential) throw new t("INTERNAL", 0, "createPlayer: credential is required");
1329
- let n = new Me(e);
1333
+ let n = new Ne(e);
1330
1334
  return await n.start(), n;
1331
1335
  }
1332
- var Me = class {
1336
+ var Ne = class {
1333
1337
  opts;
1334
1338
  abort = new AbortController();
1335
1339
  listeners = {};
@@ -1408,13 +1412,13 @@ var Me = class {
1408
1412
  !r && !s() && l();
1409
1413
  }, e);
1410
1414
  };
1411
- d(De), this.armingSub = w({
1415
+ d(Oe), this.armingSub = w({
1412
1416
  eventsBaseUrl: n,
1413
1417
  matchUrn: this.opts.matchUrn,
1414
1418
  credential: this.opts.credential,
1415
- onAlive: () => d(Oe),
1419
+ onAlive: () => d(ke),
1416
1420
  onState: (e) => {
1417
- r || s() || (e.state === "live" || e.state === "gone") && setTimeout(u, Math.random() * ke);
1421
+ r || s() || (e.state === "live" || e.state === "gone") && setTimeout(u, Math.random() * Z);
1418
1422
  },
1419
1423
  onError: () => l()
1420
1424
  });
@@ -1459,8 +1463,8 @@ var Me = class {
1459
1463
  emit: (e) => this.onEngineEvent(e)
1460
1464
  }, a = this.opts.engine ?? "auto";
1461
1465
  if (a === "native") return new W(i);
1462
- if (a === "hls" || L()) return new he(i);
1463
- if (ge(this.opts.video)) return new W(i);
1466
+ if (a === "hls" || L()) return new ge(i);
1467
+ if (_e(this.opts.video)) return new W(i);
1464
1468
  throw new t("INTERNAL", 0, "no supported HLS playback engine in this browser");
1465
1469
  }
1466
1470
  onEngineEvent(e) {
@@ -1505,7 +1509,7 @@ var Me = class {
1505
1509
  r = 0, i = !1;
1506
1510
  },
1507
1511
  onError: () => {
1508
- this.destroyed || e !== this.loadGen || i || (r += 1, r >= Z && (i = !0, this.emit("warning", new t("NETWORK", 0, `live-state events unreachable at ${n} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
1512
+ this.destroyed || e !== this.loadGen || i || (r += 1, r >= Ae && (i = !0, this.emit("warning", new t("NETWORK", 0, `live-state events unreachable at ${n} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
1509
1513
  }
1510
1514
  });
1511
1515
  }
@@ -1527,7 +1531,7 @@ var Me = class {
1527
1531
  }
1528
1532
  t.controls = !1;
1529
1533
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
1530
- r && r.insertBefore(n, t), n.appendChild(t), q(n, this.opts.theme), this.container = n, this.controlBar = Se({
1534
+ r && r.insertBefore(n, t), n.appendChild(t), q(n, this.opts.theme), this.container = n, this.controlBar = Ce({
1531
1535
  root: n,
1532
1536
  video: t,
1533
1537
  player: this,
@@ -1550,7 +1554,7 @@ var Me = class {
1550
1554
  }
1551
1555
  startStats() {
1552
1556
  this.stopStats();
1553
- let e = Math.max(500, this.opts.statsIntervalMs ?? Ae);
1557
+ let e = Math.max(500, this.opts.statsIntervalMs ?? je);
1554
1558
  this.statsTimer = setInterval(() => {
1555
1559
  this.engine && this.emit("stats", this.engine.getStats());
1556
1560
  }, e);
@@ -1560,7 +1564,7 @@ var Me = class {
1560
1564
  }
1561
1565
  scheduleLicenseRefresh() {
1562
1566
  this.stopRefresh();
1563
- let e = this.opts.licenseRefreshMs ?? je;
1567
+ let e = this.opts.licenseRefreshMs ?? Me;
1564
1568
  !e || !this._descriptor?.drmEnabled || (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
1565
1569
  }
1566
1570
  stopRefresh() {
@@ -1695,7 +1699,7 @@ function $(e) {
1695
1699
  }
1696
1700
  //#endregion
1697
1701
  //#region src/embed/host.ts
1698
- function Ne(e) {
1702
+ function Pe(e) {
1699
1703
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
1700
1704
  if (!e.src) throw Error("mountEmbed: opts.src is required");
1701
1705
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -1754,8 +1758,8 @@ function Ne(e) {
1754
1758
  }
1755
1759
  //#endregion
1756
1760
  //#region src/embed/page.ts
1757
- var Pe = /^[A-Za-z0-9:_.-]{1,128}$/;
1758
- function Fe() {
1761
+ var Fe = /^[A-Za-z0-9:_.-]{1,128}$/;
1762
+ function Ie() {
1759
1763
  let e = window.HAVIK_EMBED_CONFIG;
1760
1764
  if (e) return {
1761
1765
  baseUrl: e.baseUrl ?? "",
@@ -1777,9 +1781,9 @@ function Fe() {
1777
1781
  waitForLive: !0
1778
1782
  };
1779
1783
  }
1780
- async function Ie() {
1781
- let e = Fe();
1782
- Re();
1784
+ async function Le() {
1785
+ let e = Ie();
1786
+ ze();
1783
1787
  let n = document.createElement("video");
1784
1788
  n.setAttribute("playsinline", ""), n.muted = e.muted ?? !0, n.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(n);
1785
1789
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -1834,7 +1838,7 @@ async function Ie() {
1834
1838
  code: e.code,
1835
1839
  message: e.message
1836
1840
  })), e.on("autoplayblocked", () => {
1837
- i({ type: "oddin:autoplayblocked" }), Le(n, e);
1841
+ i({ type: "oddin:autoplayblocked" }), Re(n, e);
1838
1842
  });
1839
1843
  }, s = async (r) => {
1840
1844
  a?.destroy(), a = null;
@@ -1900,7 +1904,7 @@ async function Ie() {
1900
1904
  a?.retry();
1901
1905
  break;
1902
1906
  case "oddin:load":
1903
- typeof e.matchUrn == "string" && Pe.test(e.matchUrn) && s(e.matchUrn);
1907
+ typeof e.matchUrn == "string" && Fe.test(e.matchUrn) && s(e.matchUrn);
1904
1908
  break;
1905
1909
  case "oddin:destroy":
1906
1910
  c();
@@ -1914,18 +1918,18 @@ async function Ie() {
1914
1918
  protocol: 1
1915
1919
  });
1916
1920
  }
1917
- function Le(e, t) {
1921
+ function Re(e, t) {
1918
1922
  if (document.getElementById("havik-tap")) return;
1919
1923
  let n = document.createElement("button");
1920
1924
  n.id = "havik-tap", n.textContent = "▶ Tap to play", n.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:0;background:rgba(0,0,0,.55);color:#fff;font:600 18px system-ui,sans-serif;cursor:pointer;z-index:9", n.addEventListener("click", () => {
1921
1925
  n.remove(), t.play();
1922
1926
  }), document.body.appendChild(n);
1923
1927
  }
1924
- function Re() {
1928
+ function ze() {
1925
1929
  let e = document.createElement("style");
1926
1930
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
1927
1931
  }
1928
1932
  //#endregion
1929
- export { G as ODDIN_THEME, t as PlaybackError, q as applyTheme, Ie as bootEmbed, k as clearDeviceId, Q as createPlayer, T as deriveEventsBaseUrl, oe as fetchCatalog, ce as fetchTournament, ue as flattenMatches, O as getDeviceId, N as isLowLatencyManifest, $ as isOddinMessage, j as licenseRequestHeaders, Ne as mountEmbed, y as pollToLive, x as resolveStream, w as subscribeLiveState, C as watchStatus };
1933
+ export { G as ODDIN_THEME, t as PlaybackError, q as applyTheme, Le as bootEmbed, k as clearDeviceId, Q as createPlayer, T as deriveEventsBaseUrl, oe as fetchCatalog, ce as fetchTournament, ue as flattenMatches, O as getDeviceId, N as isLowLatencyManifest, $ as isOddinMessage, j as licenseRequestHeaders, Pe as mountEmbed, y as pollToLive, x as resolveStream, w as subscribeLiveState, C as watchStatus };
1930
1934
 
1931
1935
  //# sourceMappingURL=index.js.map