three-vr-player 0.3.0 → 0.4.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.
@@ -1,92 +1,109 @@
1
- import { P as V, V as D, S as J, L as W, a as q, b as Y } from "./VideoSource-CJGIX8gL.js";
2
- import { M as tt, c as et, d as st, i as it } from "./VideoSource-CJGIX8gL.js";
3
- function L(l) {
1
+ import { P as Y, V as _, S as H, L as K, a as G, b as Q } from "./VideoSource-CJGIX8gL.js";
2
+ import { M as nt, c as rt, d as at, i as pt } from "./VideoSource-CJGIX8gL.js";
3
+ function R(l) {
4
4
  if (!Number.isFinite(l) || l < 0) return "0:00";
5
- const t = Math.floor(l % 60), s = Math.floor(l / 60 % 60), e = Math.floor(l / 3600), a = String(t).padStart(2, "0");
6
- return e > 0 ? `${e}:${String(s).padStart(2, "0")}:${a}` : `${s}:${a}`;
5
+ const t = Math.floor(l % 60), e = Math.floor(l / 60 % 60), s = Math.floor(l / 3600), p = String(t).padStart(2, "0");
6
+ return s > 0 ? `${s}:${String(e).padStart(2, "0")}:${p}` : `${e}:${p}`;
7
7
  }
8
- function o(l, t = {}, s = []) {
9
- const e = document.createElement(l), { class: a, ...c } = t;
10
- a && (e.className = a), Object.assign(e, c);
11
- for (const d of s) e.append(d);
12
- return e;
8
+ function o(l, t = {}, e = []) {
9
+ const s = document.createElement(l), { class: p, ...c } = t;
10
+ p && (s.className = p), Object.assign(s, c);
11
+ for (const u of e) s.append(u);
12
+ return s;
13
13
  }
14
- class _ {
15
- constructor(t, s) {
14
+ class X {
15
+ constructor(t, e) {
16
16
  this.nodes = [], this.disposers = [];
17
- const e = s.video, a = o("button", { class: "tvp-btn tvp-play", title: "Play/Pause", textContent: "▶" }), c = o("input", { class: "tvp-seek", type: "range", min: "0", max: "1000", value: "0" }), d = o("span", { class: "tvp-time", textContent: "0:00 / 0:00" }), n = o("button", { class: "tvp-btn tvp-mute", title: "Volume", textContent: "🔊" }), h = o("input", { class: "tvp-volume", type: "range", min: "0", max: "1", step: "0.01", value: "1" }), m = o("div", { class: "tvp-volpopup", hidden: !0 }, [h]), R = o("span", { class: "tvp-volwrap" }, [n, m]), j = o("span", { class: "tvp-vrslot" }), x = o("button", { class: "tvp-btn tvp-projbtn", title: "Projection", textContent: "🌐" }), u = o("div", { class: "tvp-projmenu", hidden: !0 });
18
- for (const i of V) {
19
- const r = o("button", { textContent: i.label });
20
- r.dataset.mode = i.value, u.append(r);
17
+ const s = e.video, p = o("button", { class: "tvp-btn tvp-play", title: "Play/Pause", textContent: "▶" }), c = o("input", { class: "tvp-seek", type: "range", min: "0", max: "1000", value: "0" }), u = o("span", { class: "tvp-time", textContent: "0:00 / 0:00" }), r = o("button", { class: "tvp-btn tvp-mute", title: "Volume", textContent: "🔊" }), v = o("input", { class: "tvp-volume", type: "range", min: "0", max: "1", step: "0.01", value: "1" }), f = o("div", { class: "tvp-volpopup", hidden: !0 }, [v]), D = o("span", { class: "tvp-volwrap" }, [r, f]), N = o("span", { class: "tvp-vrslot" }), b = o("button", { class: "tvp-btn tvp-projbtn", title: "Projection", textContent: "🌐" }), h = o("div", { class: "tvp-projmenu", hidden: !0 });
18
+ for (const i of Y) {
19
+ const n = o("button", { textContent: i.label });
20
+ n.dataset.mode = i.value, h.append(n);
21
21
  }
22
- const B = o("span", { class: "tvp-projwrap" }, [x, u]), C = o("button", { class: "tvp-btn tvp-settingsbtn", title: "Settings", textContent: "⚙" }), F = o("button", { class: "tvp-btn tvp-fullscreen", title: "Fullscreen", textContent: "⛶" }), $ = o("footer", { class: "tvp-controls" }, [a, c, d, R, j, B, C, F]), b = o("input", { type: "checkbox", checked: s.initial.swapEyes }), f = o("input", { type: "range", min: "30", max: "100", step: "1", value: String(s.initial.fov) }), y = o("span", { textContent: String(s.initial.fov) }), w = o("input", { type: "range", min: "1", max: "2", step: "0.25", value: String(s.initial.supersampling) }), z = o("span", { textContent: String(s.initial.supersampling) }), k = o("input", { type: "checkbox", checked: s.proxy.enabled }), S = o("input", { type: "text", value: s.proxy.url, placeholder: "http://localhost:8888", spellcheck: !1 }), P = o("input", { type: "password", value: s.proxy.apiPassword, placeholder: "API password" }), N = o("section", { class: "tvp-settings" }, [
23
- o("label", { class: "row" }, [b, "Swap eyes (if depth looks wrong)"]),
24
- o("label", {}, [T("Field of view (zoom): ", y, "°"), f]),
25
- o("label", {}, [T("Supersampling: ", z, "× (sharpness)"), w]),
22
+ const J = o("span", { class: "tvp-projwrap" }, [b, h]), k = o("button", { class: "tvp-btn tvp-settingsbtn", title: "Settings", textContent: "⚙" }), O = o("button", { class: "tvp-btn tvp-fullscreen", title: "Fullscreen", textContent: "⛶" }), S = o("footer", { class: "tvp-controls" }, [p, c, u, D, N, J, k, O]), P = o("input", { type: "checkbox", checked: e.initial.swapEyes }), x = o("input", { type: "range", min: "30", max: "100", step: "1", value: String(e.initial.fov) }), E = o("span", { textContent: String(e.initial.fov) }), j = o("input", { type: "range", min: "1", max: "2", step: "0.25", value: String(e.initial.supersampling) }), A = o("span", { textContent: String(e.initial.supersampling) }), C = o("input", { type: "checkbox", checked: e.proxy.enabled }), F = o("input", { type: "text", value: e.proxy.url, placeholder: "http://localhost:8888", spellcheck: !1 }), T = o("input", { type: "password", value: e.proxy.apiPassword, placeholder: "API password" }), g = o("section", { class: "tvp-settings" }, [
23
+ o("label", { class: "row" }, [P, "Swap eyes (if depth looks wrong)"]),
24
+ o("label", {}, [$("Field of view (zoom): ", E, "°"), x]),
25
+ o("label", {}, [$("Supersampling: ", A, "× (sharpness)"), j]),
26
26
  o("hr", { class: "tvp-sep" }),
27
- o("label", { class: "row" }, [k, "Use CORS proxy"]),
28
- o("label", {}, ["Proxy URL", S]),
29
- o("label", {}, ["API password", P])
30
- ]), U = o("div", { class: "tvp-toast" });
31
- this.nodes.push($, N, U);
27
+ o("label", { class: "row" }, [C, "Use CORS proxy"]),
28
+ o("label", {}, ["Proxy URL", F]),
29
+ o("label", {}, ["API password", T])
30
+ ]), W = o("div", { class: "tvp-toast" });
31
+ this.nodes.push(S, g, W);
32
32
  for (const i of this.nodes) t.append(i);
33
- const p = (i, r, v, g) => {
34
- i.addEventListener(r, v, g), this.disposers.push(() => i.removeEventListener(r, v, g));
35
- }, O = (i) => c.style.setProperty("--seek", `${i}%`);
36
- p(a, "click", () => {
37
- e.paused ? e.play() : e.pause();
38
- }), p(e, "play", () => {
39
- a.textContent = "⏸";
40
- }), p(e, "pause", () => {
41
- a.textContent = "";
42
- }), p(e, "timeupdate", () => {
43
- if (e.duration) {
44
- const i = e.currentTime / e.duration * 100;
45
- c.value = String(i * 10), O(i), d.textContent = `${L(e.currentTime)} / ${L(e.duration)}`;
33
+ const a = (i, n, d, m) => {
34
+ i.addEventListener(n, d, m), this.disposers.push(() => i.removeEventListener(n, d, m));
35
+ }, I = (i) => c.style.setProperty("--seek", `${i}%`), y = () => {
36
+ f.hidden = !0, h.hidden = !0, g.classList.remove("open");
37
+ };
38
+ a(p, "click", () => {
39
+ s.paused ? s.play() : s.pause();
40
+ }), a(s, "play", () => {
41
+ p.textContent = "";
42
+ }), a(s, "pause", () => {
43
+ p.textContent = "▶";
44
+ }), a(s, "timeupdate", () => {
45
+ if (s.duration) {
46
+ const i = s.currentTime / s.duration * 100;
47
+ c.value = String(i * 10), I(i), u.textContent = `${R(s.currentTime)} / ${R(s.duration)}`;
46
48
  }
47
- }), p(c, "input", () => {
48
- O(Number(c.value) / 10), e.duration && (e.currentTime = Number(c.value) / 1e3 * e.duration);
49
- }), p(n, "click", (i) => {
50
- i.stopPropagation(), m.hidden = !m.hidden;
51
- }), p(h, "input", () => {
52
- e.volume = Number(h.value), e.muted = e.volume === 0, n.textContent = e.muted ? "🔇" : "🔊";
49
+ }), a(c, "input", () => {
50
+ I(Number(c.value) / 10), s.duration && (s.currentTime = Number(c.value) / 1e3 * s.duration);
51
+ }), a(r, "click", (i) => {
52
+ i.stopPropagation();
53
+ const n = f.hidden;
54
+ y(), f.hidden = !n;
55
+ }), a(v, "input", () => {
56
+ s.volume = Number(v.value), s.muted = s.volume === 0, r.textContent = s.muted ? "🔇" : "🔊";
53
57
  });
54
- const A = () => {
55
- const i = s.getProjection();
56
- let r = "Projection";
57
- u.querySelectorAll("button").forEach((v) => {
58
- const g = v.dataset.mode === i;
59
- v.classList.toggle("active", g), g && (r = `Projection: ${v.textContent}`);
60
- }), x.title = r;
58
+ const M = () => {
59
+ const i = e.getProjection();
60
+ let n = "Projection";
61
+ h.querySelectorAll("button").forEach((d) => {
62
+ const m = d.dataset.mode === i;
63
+ d.classList.toggle("active", m), m && (n = `Projection: ${d.textContent}`);
64
+ }), b.title = n;
61
65
  };
62
- p(x, "click", (i) => {
63
- i.stopPropagation(), u.hidden = !u.hidden;
64
- }), p(u, "click", (i) => {
65
- const r = i.target.closest("button[data-mode]");
66
- r && (s.setProjection(r.dataset.mode), A(), u.hidden = !0);
67
- }), A(), p(C, "click", (i) => {
68
- i.stopPropagation(), N.classList.toggle("open");
69
- }), p(b, "change", () => s.setSwapEyes(b.checked)), p(f, "input", () => {
70
- const i = Number(f.value);
71
- y.textContent = String(i), s.setFov(i);
72
- }), p(w, "input", () => {
73
- const i = Number(w.value);
74
- z.textContent = String(i), s.setSupersampling(i);
66
+ a(b, "click", (i) => {
67
+ i.stopPropagation();
68
+ const n = h.hidden;
69
+ y(), h.hidden = !n;
70
+ }), a(h, "click", (i) => {
71
+ const n = i.target.closest("button[data-mode]");
72
+ n && (e.setProjection(n.dataset.mode), M(), h.hidden = !0);
73
+ }), M(), a(k, "click", (i) => {
74
+ i.stopPropagation();
75
+ const n = !g.classList.contains("open");
76
+ y(), g.classList.toggle("open", n);
77
+ }), a(P, "change", () => e.setSwapEyes(P.checked)), a(x, "input", () => {
78
+ const i = Number(x.value);
79
+ E.textContent = String(i), e.setFov(i);
80
+ }), a(j, "input", () => {
81
+ const i = Number(j.value);
82
+ A.textContent = String(i), e.setSupersampling(i);
75
83
  });
76
- const E = () => s.setProxy({ url: S.value.trim(), apiPassword: P.value, enabled: k.checked });
77
- p(k, "change", E), p(S, "change", E), p(P, "change", E), p(s.surface, "wheel", (i) => {
84
+ const L = () => e.setProxy({ url: F.value.trim(), apiPassword: T.value, enabled: C.checked });
85
+ a(C, "change", L), a(F, "change", L), a(T, "change", L), a(e.surface, "wheel", (i) => {
78
86
  i.preventDefault();
79
- const r = Math.max(30, Math.min(100, Number(f.value) + Math.sign(i.deltaY) * 3));
80
- f.value = String(r), y.textContent = String(r), s.setFov(r);
81
- }, { passive: !1 }), p(F, "click", () => {
82
- var r, v;
83
- const i = s.fullscreenTarget;
84
- document.fullscreenElement ? (v = document.exitFullscreen) == null || v.call(document) : (r = i.requestFullscreen) == null || r.call(i);
85
- }), p(document, "click", (i) => {
86
- const r = i.composedPath();
87
- !m.hidden && !r.includes(m) && !r.includes(n) && (m.hidden = !0), !u.hidden && !r.includes(u) && !r.includes(x) && (u.hidden = !0);
88
- }), s.vrSupported().then((i) => {
89
- i && (Object.assign(s.vrButton.style, { position: "static", left: "auto", bottom: "auto", transform: "none", margin: "0" }), j.append(s.vrButton));
87
+ const n = Math.max(30, Math.min(100, Number(x.value) + Math.sign(i.deltaY) * 3));
88
+ x.value = String(n), E.textContent = String(n), e.setFov(n);
89
+ }, { passive: !1 }), a(O, "click", () => {
90
+ var n, d;
91
+ const i = e.fullscreenTarget;
92
+ document.fullscreenElement ? (d = document.exitFullscreen) == null || d.call(document) : (n = i.requestFullscreen) == null || n.call(i);
93
+ }), a(document, "click", (i) => {
94
+ const n = i.composedPath(), d = (m) => n.includes(m);
95
+ [f, r, h, b, g, k].some(d) || y();
96
+ });
97
+ let w = 0;
98
+ const q = () => !f.hidden || !h.hidden || g.classList.contains("open"), B = () => {
99
+ q() || S.classList.add("tvp-hidden");
100
+ }, z = () => {
101
+ S.classList.remove("tvp-hidden"), clearTimeout(w), w = window.setTimeout(B, 5e3);
102
+ };
103
+ a(e.fullscreenTarget, "pointermove", z), a(e.fullscreenTarget, "pointerdown", z), a(e.fullscreenTarget, "pointerleave", () => {
104
+ clearTimeout(w), B();
105
+ }), this.disposers.push(() => clearTimeout(w)), z(), e.vrSupported().then((i) => {
106
+ i && (Object.assign(e.vrButton.style, { position: "static", left: "auto", bottom: "auto", transform: "none", margin: "0" }), N.append(e.vrButton));
90
107
  });
91
108
  }
92
109
  dispose() {
@@ -94,82 +111,82 @@ class _ {
94
111
  for (const t of this.nodes) t.remove();
95
112
  }
96
113
  }
97
- function T(l, t, s) {
98
- const e = document.createDocumentFragment();
99
- return e.append(l, t, s), e;
114
+ function $(l, t, e) {
115
+ const s = document.createDocumentFragment();
116
+ return s.append(l, t, e), s;
100
117
  }
101
- const I = ":host,:host *,.tvp,.tvp *{box-sizing:border-box}.tvp-canvas{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;display:block;touch-action:none;cursor:grab}.tvp-canvas:active{cursor:grabbing}.tvp-video{display:none}.tvp-controls{position:absolute;left:0;right:0;bottom:0;display:flex;align-items:center;gap:10px;padding:12px;background:linear-gradient(transparent,#000c);z-index:5;font:14px system-ui,Segoe UI,Roboto,sans-serif;color:#e8eaed}.tvp-btn{padding:4px;border:0;background:none;color:#e8eaed;cursor:pointer;font-size:22px;line-height:1}.tvp-btn:hover{opacity:.7}.tvp-seek{flex:1;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:14px;background:transparent;cursor:pointer;margin:0}.tvp-seek::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:linear-gradient(to right,#4f8cff var(--seek,0%),#3a4150 var(--seek,0%))}.tvp-seek::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-top:-4px;width:12px;height:12px;border-radius:50%;background:#fff;cursor:pointer}.tvp-seek::-moz-range-track{height:4px;border-radius:2px;background:#3a4150}.tvp-seek::-moz-range-progress{height:4px;border-radius:2px;background:#4f8cff}.tvp-seek::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:#fff;cursor:pointer}.tvp-time{font-variant-numeric:tabular-nums;min-width:96px;text-align:center;color:#cfd6e2}.tvp-volwrap,.tvp-projwrap{position:relative;display:inline-flex}.tvp-volpopup{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);width:40px;height:132px;background:#121418eb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid #2a2f3a;border-radius:10px;z-index:8;box-shadow:0 8px 24px #0009}.tvp-volpopup[hidden]{display:none}.tvp-volume{position:absolute;top:50%;left:50%;width:104px;height:14px;margin:0;transform:translate(-50%,-50%) rotate(-90deg);-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;cursor:pointer}.tvp-volume::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:#3a4150}.tvp-volume::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-top:-4px;width:12px;height:12px;border-radius:50%;background:#fff;cursor:pointer}.tvp-volume::-moz-range-track{height:4px;border-radius:2px;background:#3a4150}.tvp-volume::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:#fff;cursor:pointer}.tvp-projmenu{position:absolute;bottom:calc(100% + 8px);right:0;min-width:210px;background:#121418eb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid #2a2f3a;border-radius:10px;padding:6px;display:flex;flex-direction:column;gap:2px;z-index:8;box-shadow:0 8px 24px #0009}.tvp-projmenu[hidden]{display:none}.tvp-projmenu button{text-align:left;background:transparent;border:0;color:#e8eaed;padding:8px 10px;border-radius:7px;cursor:pointer;font:inherit;white-space:nowrap}.tvp-projmenu button:hover{background:#252b39}.tvp-projmenu button.active{background:#4f8cff;color:#fff}.tvp-vrslot button{position:static!important}.tvp-settings{position:absolute;bottom:62px;right:10px;width:300px;max-width:calc(100% - 20px);max-height:70%;overflow-y:auto;background:#121418eb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid #2a2f3a;border-radius:12px;padding:14px;display:none;flex-direction:column;gap:12px;z-index:6;font:14px system-ui,Segoe UI,Roboto,sans-serif;color:#e8eaed}.tvp-settings.open{display:flex}.tvp-settings label{display:flex;flex-direction:column;gap:4px;font-size:12px;color:#aab2c0}.tvp-settings label.row{flex-direction:row;align-items:center;gap:8px;color:#e8eaed;font-size:13px}.tvp-settings input[type=range]{width:100%;accent-color:#4f8cff}.tvp-settings input[type=text],.tvp-settings input[type=password]{width:100%;padding:7px 9px;border-radius:7px;border:1px solid #333;background:#151821;color:#e8eaed;font:inherit}.tvp-sep{width:100%;border:0;border-top:1px solid #2a2f3a;margin:2px 0}.tvp-toast{position:absolute;left:50%;bottom:74px;transform:translate(-50%);max-width:80%;padding:10px 16px;border-radius:10px;background:#1b1f2aed;border:1px solid #2a2f3a;color:#e8eaed;opacity:0;pointer-events:none;transition:opacity .2s;z-index:7;font:13px system-ui}.tvp-toast.show{opacity:1}", M = "three-vr-player:settings";
102
- class H {
103
- constructor(t, s = {}) {
104
- var c, d;
105
- this.source = new D(), this.listeners = /* @__PURE__ */ new Map(), this.readyEmitted = !1, this.native = !1, this.loading = !1, this.useProxy = !1, this.opts = s, this.proxyConfig = s.proxy, this.useProxy = !!s.proxy;
106
- const e = s.persistSettings ? this.loadSettings() : null;
118
+ const U = ":host,:host *,.tvp,.tvp *{box-sizing:border-box}.tvp-canvas{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;display:block;touch-action:none;cursor:grab}.tvp-canvas:active{cursor:grabbing}.tvp-video{display:none}.tvp-controls{position:absolute;left:0;right:0;bottom:0;display:flex;align-items:center;gap:10px;padding:12px;background:linear-gradient(transparent,#000c);z-index:5;font:14px system-ui,Segoe UI,Roboto,sans-serif;color:#e8eaed;transition:opacity .3s}.tvp-controls.tvp-hidden{opacity:0;pointer-events:none}.tvp-btn{padding:4px;border:0;background:none;color:#e8eaed;cursor:pointer;font-size:22px;line-height:1}.tvp-btn:hover{opacity:.7}.tvp-seek{flex:1;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:14px;background:transparent;cursor:pointer;margin:0}.tvp-seek::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:linear-gradient(to right,#4f8cff var(--seek,0%),#3a4150 var(--seek,0%))}.tvp-seek::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-top:-4px;width:12px;height:12px;border-radius:50%;background:#fff;cursor:pointer}.tvp-seek::-moz-range-track{height:4px;border-radius:2px;background:#3a4150}.tvp-seek::-moz-range-progress{height:4px;border-radius:2px;background:#4f8cff}.tvp-seek::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:#fff;cursor:pointer}.tvp-time{font-variant-numeric:tabular-nums;min-width:96px;text-align:center;color:#cfd6e2}.tvp-volwrap,.tvp-projwrap{position:relative;display:inline-flex}.tvp-volpopup{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);width:40px;height:132px;background:#121418eb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid #2a2f3a;border-radius:10px;z-index:8;box-shadow:0 8px 24px #0009}.tvp-volpopup[hidden]{display:none}.tvp-volume{position:absolute;top:50%;left:50%;width:104px;height:14px;margin:0;transform:translate(-50%,-50%) rotate(-90deg);-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;cursor:pointer}.tvp-volume::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:#3a4150}.tvp-volume::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-top:-4px;width:12px;height:12px;border-radius:50%;background:#fff;cursor:pointer}.tvp-volume::-moz-range-track{height:4px;border-radius:2px;background:#3a4150}.tvp-volume::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:#fff;cursor:pointer}.tvp-projmenu{position:absolute;bottom:calc(100% + 8px);right:0;min-width:210px;background:#121418eb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid #2a2f3a;border-radius:10px;padding:6px;display:flex;flex-direction:column;gap:2px;z-index:8;box-shadow:0 8px 24px #0009}.tvp-projmenu[hidden]{display:none}.tvp-projmenu button{text-align:left;background:transparent;border:0;color:#e8eaed;padding:8px 10px;border-radius:7px;cursor:pointer;font:inherit;white-space:nowrap}.tvp-projmenu button:hover{background:#252b39}.tvp-projmenu button.active{background:#4f8cff;color:#fff}.tvp-vrslot button{position:static!important}.tvp-settings{position:absolute;bottom:62px;right:10px;width:300px;max-width:calc(100% - 20px);max-height:70%;overflow-y:auto;background:#121418eb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid #2a2f3a;border-radius:12px;padding:14px;display:none;flex-direction:column;gap:12px;z-index:6;font:14px system-ui,Segoe UI,Roboto,sans-serif;color:#e8eaed}.tvp-settings.open{display:flex}.tvp-settings label{display:flex;flex-direction:column;gap:4px;font-size:12px;color:#aab2c0}.tvp-settings label.row{flex-direction:row;align-items:center;gap:8px;color:#e8eaed;font-size:13px}.tvp-settings input[type=range]{width:100%;accent-color:#4f8cff}.tvp-settings input[type=text],.tvp-settings input[type=password]{width:100%;padding:7px 9px;border-radius:7px;border:1px solid #333;background:#151821;color:#e8eaed;font:inherit}.tvp-sep{width:100%;border:0;border-top:1px solid #2a2f3a;margin:2px 0}.tvp-toast{position:absolute;left:50%;bottom:74px;transform:translate(-50%);max-width:80%;padding:10px 16px;border-radius:10px;background:#1b1f2aed;border:1px solid #2a2f3a;color:#e8eaed;opacity:0;pointer-events:none;transition:opacity .2s;z-index:7;font:13px system-ui}.tvp-toast.show{opacity:1}", V = "three-vr-player:settings";
119
+ class Z {
120
+ constructor(t, e = {}) {
121
+ var c, u;
122
+ this.source = new _(), this.listeners = /* @__PURE__ */ new Map(), this.readyEmitted = !1, this.native = !1, this.loading = !1, this.useProxy = !1, this.opts = e, this.proxyConfig = e.proxy, this.useProxy = !!e.proxy;
123
+ const s = e.persistSettings ? this.loadSettings() : null;
107
124
  this.view = {
108
- projection: s.projection ?? (e == null ? void 0 : e.projection) ?? "180-sbs",
109
- swapEyes: s.swapEyes ?? (e == null ? void 0 : e.swapEyes) ?? !1,
110
- fov: s.fov ?? (e == null ? void 0 : e.fov) ?? 70,
111
- supersampling: s.supersampling ?? (e == null ? void 0 : e.supersampling) ?? 1.5
125
+ projection: e.projection ?? (s == null ? void 0 : s.projection) ?? "180-sbs",
126
+ swapEyes: e.swapEyes ?? (s == null ? void 0 : s.swapEyes) ?? !1,
127
+ fov: e.fov ?? (s == null ? void 0 : s.fov) ?? 70,
128
+ supersampling: e.supersampling ?? (s == null ? void 0 : s.supersampling) ?? 1.5
112
129
  }, this.wrap = document.createElement("div"), this.wrap.className = "tvp", this.wrap.style.cssText = "position:relative;width:100%;height:100%;overflow:hidden;", t.appendChild(this.wrap);
113
- let a;
114
- if (s.shadowDom !== !1) {
115
- const n = this.wrap.attachShadow({ mode: "open" }), h = document.createElement("style");
116
- h.textContent = I, n.appendChild(h), a = n;
130
+ let p;
131
+ if (e.shadowDom !== !1) {
132
+ const r = this.wrap.attachShadow({ mode: "open" }), v = document.createElement("style");
133
+ v.textContent = U, r.appendChild(v), p = r;
117
134
  } else {
118
135
  if (!document.getElementById("tvp-styles")) {
119
- const n = document.createElement("style");
120
- n.id = "tvp-styles", n.textContent = I, document.head.appendChild(n);
136
+ const r = document.createElement("style");
137
+ r.id = "tvp-styles", r.textContent = U, document.head.appendChild(r);
121
138
  }
122
- a = this.wrap;
139
+ p = this.wrap;
123
140
  }
124
- this.canvas = document.createElement("canvas"), this.canvas.className = "tvp-canvas", this.video = document.createElement("video"), this.video.className = "tvp-video", this.video.playsInline = !0, s.crossOrigin !== null && (this.video.crossOrigin = s.crossOrigin ?? "anonymous"), a.append(this.canvas, this.video), this.scene = new J({
141
+ this.canvas = document.createElement("canvas"), this.canvas.className = "tvp-canvas", this.video = document.createElement("video"), this.video.className = "tvp-video", this.video.playsInline = !0, e.crossOrigin !== null && (this.video.crossOrigin = e.crossOrigin ?? "anonymous"), p.append(this.canvas, this.video), this.scene = new H({
125
142
  canvas: this.canvas,
126
143
  video: this.video,
127
144
  projection: this.view.projection,
128
145
  swapEyes: this.view.swapEyes,
129
146
  fov: this.view.fov,
130
147
  supersampling: this.view.supersampling
131
- }), this.look = new W(this.scene.camera, this.canvas, { isPresenting: () => this.scene.renderer.xr.isPresenting }), this.scene.onFrame(() => this.look.update()), this.look.setEnabled(!this.scene.isFlat()), s.controls !== !1 && (this.ui = new _(a, {
148
+ }), this.look = new K(this.scene.camera, this.canvas, { isPresenting: () => this.scene.renderer.xr.isPresenting }), this.scene.onFrame(() => this.look.update()), this.look.setEnabled(!this.scene.isFlat()), e.controls !== !1 && (this.ui = new X(p, {
132
149
  video: this.video,
133
150
  surface: this.canvas,
134
151
  fullscreenTarget: this.wrap,
135
152
  vrButton: this.scene.vrButton,
136
153
  vrSupported: () => this.vrSupported(),
137
154
  getProjection: () => this.scene.getProjection(),
138
- setProjection: (n) => this.setProjection(n),
139
- setSwapEyes: (n) => this.setSwapEyes(n),
140
- setFov: (n) => this.setFov(n),
141
- setSupersampling: (n) => this.setSupersampling(n),
155
+ setProjection: (r) => this.setProjection(r),
156
+ setSwapEyes: (r) => this.setSwapEyes(r),
157
+ setFov: (r) => this.setFov(r),
158
+ setSupersampling: (r) => this.setSupersampling(r),
142
159
  initial: { swapEyes: this.view.swapEyes, fov: this.view.fov, supersampling: this.view.supersampling },
143
- proxy: { url: ((c = this.proxyConfig) == null ? void 0 : c.url) ?? "", apiPassword: ((d = this.proxyConfig) == null ? void 0 : d.apiPassword) ?? "", enabled: this.useProxy },
144
- setProxy: (n) => this.setProxy(n)
160
+ proxy: { url: ((c = this.proxyConfig) == null ? void 0 : c.url) ?? "", apiPassword: ((u = this.proxyConfig) == null ? void 0 : u.apiPassword) ?? "", enabled: this.useProxy },
161
+ setProxy: (r) => this.setProxy(r)
145
162
  })), this.video.addEventListener("play", () => this.emit("play")), this.video.addEventListener("pause", () => this.emit("pause")), this.video.addEventListener("ended", () => this.emit("ended")), this.video.addEventListener("timeupdate", () => this.emit("timeupdate", this.video.currentTime)), this.video.addEventListener("error", () => {
146
163
  this.loading || this.emit("error", this.video.error);
147
164
  }), this.video.addEventListener("loadedmetadata", () => {
148
165
  this.readyEmitted || (this.readyEmitted = !0, this.emit("ready"));
149
- }), this.scene.renderer.xr.addEventListener("sessionstart", () => this.emit("enterxr")), this.scene.renderer.xr.addEventListener("sessionend", () => this.emit("exitxr")), s.src && this.load(s.src, { projection: s.projection });
166
+ }), this.scene.renderer.xr.addEventListener("sessionstart", () => this.emit("enterxr")), this.scene.renderer.xr.addEventListener("sessionend", () => this.emit("exitxr")), e.src && this.load(e.src, { projection: e.projection });
150
167
  }
151
168
  vrSupported() {
152
169
  return this.opts.vrButton === !1 || !navigator.xr ? Promise.resolve(!1) : navigator.xr.isSessionSupported("immersive-vr").catch(() => !1);
153
170
  }
154
- async load(t, s = {}) {
171
+ async load(t, e = {}) {
155
172
  this.currentSrc = t;
156
- const e = s.projection ?? (this.opts.autoDetect !== !1 ? q(t) : null);
157
- e && this.setProjection(e);
158
- const { url: a, format: c } = Y(t, this.useProxy ? this.proxyConfig : void 0), d = this.opts.crossOrigin === void 0 ? "anonymous" : this.opts.crossOrigin;
173
+ const s = e.projection ?? (this.opts.autoDetect !== !1 ? G(t) : null);
174
+ s && this.setProjection(s);
175
+ const { url: p, format: c } = Q(t, this.useProxy ? this.proxyConfig : void 0), u = this.opts.crossOrigin === void 0 ? "anonymous" : this.opts.crossOrigin;
159
176
  this.loading = !0;
160
177
  try {
161
- await this.source.attach(this.video, { url: a, format: c }, { crossOrigin: d }), this.setNativeFallback(!1), await this.video.play().catch(() => {
178
+ await this.source.attach(this.video, { url: p, format: c }, { crossOrigin: u }), this.setNativeFallback(!1), await this.video.play().catch(() => {
162
179
  });
163
- } catch (n) {
164
- if (this.opts.nativeFallback !== !1 && c === "progressive" && d !== null)
180
+ } catch (r) {
181
+ if (this.opts.nativeFallback !== !1 && c === "progressive" && u !== null)
165
182
  try {
166
- this.setNativeFallback(!0), await this.source.attach(this.video, { url: a, format: c }, { crossOrigin: null }), await this.video.play().catch(() => {
183
+ this.setNativeFallback(!0), await this.source.attach(this.video, { url: p, format: c }, { crossOrigin: null }), await this.video.play().catch(() => {
167
184
  }), this.emit("fallback");
168
185
  return;
169
- } catch (h) {
170
- throw this.setNativeFallback(!1), this.emit("error", h), h;
186
+ } catch (v) {
187
+ throw this.setNativeFallback(!1), this.emit("error", v), v;
171
188
  }
172
- throw this.setNativeFallback(!1), this.emit("error", n), n;
189
+ throw this.setNativeFallback(!1), this.emit("error", r), r;
173
190
  } finally {
174
191
  this.loading = !1;
175
192
  }
@@ -210,35 +227,35 @@ class H {
210
227
  this.proxyConfig = t.url ? { url: t.url, apiPassword: t.apiPassword || void 0 } : void 0, this.useProxy = t.enabled, this.currentSrc && this.load(this.currentSrc);
211
228
  }
212
229
  async enterVR() {
213
- var s;
230
+ var e;
214
231
  const t = this.scene.vrButton;
215
- (s = t == null ? void 0 : t.click) == null || s.call(t);
232
+ (e = t == null ? void 0 : t.click) == null || e.call(t);
216
233
  }
217
234
  get three() {
218
235
  return { renderer: this.scene.renderer, scene: this.scene.scene, camera: this.scene.camera };
219
236
  }
220
- on(t, s) {
221
- let e = this.listeners.get(t);
222
- return e || (e = /* @__PURE__ */ new Set(), this.listeners.set(t, e)), e.add(s), this;
237
+ on(t, e) {
238
+ let s = this.listeners.get(t);
239
+ return s || (s = /* @__PURE__ */ new Set(), this.listeners.set(t, s)), s.add(e), this;
223
240
  }
224
- off(t, s) {
225
- var e;
226
- return (e = this.listeners.get(t)) == null || e.delete(s), this;
241
+ off(t, e) {
242
+ var s;
243
+ return (s = this.listeners.get(t)) == null || s.delete(e), this;
227
244
  }
228
- emit(t, s) {
229
- var e;
230
- (e = this.listeners.get(t)) == null || e.forEach((a) => a(s));
245
+ emit(t, e) {
246
+ var s;
247
+ (s = this.listeners.get(t)) == null || s.forEach((p) => p(e));
231
248
  }
232
249
  persist() {
233
250
  if (this.opts.persistSettings)
234
251
  try {
235
- localStorage.setItem(M, JSON.stringify(this.view));
252
+ localStorage.setItem(V, JSON.stringify(this.view));
236
253
  } catch {
237
254
  }
238
255
  }
239
256
  loadSettings() {
240
257
  try {
241
- const t = localStorage.getItem(M);
258
+ const t = localStorage.getItem(V);
242
259
  return t ? JSON.parse(t) : null;
243
260
  } catch {
244
261
  return null;
@@ -249,12 +266,12 @@ class H {
249
266
  (t = this.ui) == null || t.dispose(), this.look.dispose(), this.source.dispose(), this.scene.dispose(), this.video.remove(), this.canvas.remove(), this.wrap.remove(), this.listeners.clear();
250
267
  }
251
268
  }
252
- class K extends HTMLElement {
269
+ class tt extends HTMLElement {
253
270
  static get observedAttributes() {
254
271
  return ["src", "projection"];
255
272
  }
256
273
  connectedCallback() {
257
- this.player || (this.style.display || (this.style.display = "block"), this.player = new H(this, {
274
+ this.player || (this.style.display || (this.style.display = "block"), this.player = new Z(this, {
258
275
  src: this.getAttribute("src") ?? void 0,
259
276
  projection: this.getAttribute("projection") ?? void 0,
260
277
  controls: this.hasAttribute("controls"),
@@ -265,39 +282,39 @@ class K extends HTMLElement {
265
282
  proxy: this.getAttribute("proxy-url") ? { url: this.getAttribute("proxy-url"), apiPassword: this.getAttribute("proxy-password") ?? void 0 } : void 0
266
283
  }));
267
284
  }
268
- attributeChangedCallback(t, s, e) {
269
- !this.player || e == null || (t === "src" && this.player.load(e), t === "projection" && this.player.setProjection(e));
285
+ attributeChangedCallback(t, e, s) {
286
+ !this.player || s == null || (t === "src" && this.player.load(s), t === "projection" && this.player.setProjection(s));
270
287
  }
271
288
  disconnectedCallback() {
272
289
  var t;
273
290
  (t = this.player) == null || t.dispose(), this.player = void 0;
274
291
  }
275
292
  numAttr(t) {
276
- const s = this.getAttribute(t);
277
- return s == null ? void 0 : Number(s);
293
+ const e = this.getAttribute(t);
294
+ return e == null ? void 0 : Number(e);
278
295
  }
279
296
  /** The underlying Player instance (for programmatic control). */
280
297
  get api() {
281
298
  return this.player;
282
299
  }
283
300
  }
284
- function G(l = "three-video") {
285
- typeof customElements < "u" && !customElements.get(l) && customElements.define(l, K);
301
+ function et(l = "three-video") {
302
+ typeof customElements < "u" && !customElements.get(l) && customElements.define(l, tt);
286
303
  }
287
- G();
304
+ et();
288
305
  export {
289
- W as LookControls,
290
- tt as MODES,
291
- V as PROJECTIONS,
292
- H as Player,
293
- J as StereoScene,
294
- K as ThreeVideoElement,
295
- D as VideoSource,
296
- Y as buildProxyUrl,
297
- et as clampAngles,
298
- st as detectFormat,
299
- q as detectProjection,
300
- it as isFlatMode,
301
- G as registerWebComponent
306
+ K as LookControls,
307
+ nt as MODES,
308
+ Y as PROJECTIONS,
309
+ Z as Player,
310
+ H as StereoScene,
311
+ tt as ThreeVideoElement,
312
+ _ as VideoSource,
313
+ Q as buildProxyUrl,
314
+ rt as clampAngles,
315
+ at as detectFormat,
316
+ G as detectProjection,
317
+ pt as isFlatMode,
318
+ et as registerWebComponent
302
319
  };
303
320
  //# sourceMappingURL=three-vr-player.js.map