UNPKG

quad-tap

Version:

A pure JavaScript implementation of the Quad-Tap overlay interaction for videos with advanced video player API integration

1,183 lines (1,163 loc) 182 kB
var t; t = () => ( () => { var t = { d: (e, o) => { for (var n in o) t.o(o, n) && !t.o(e, n) && Object.defineProperty(e, n, { enumerable: !0, get: o[n] }) } , o: (t, e) => Object.prototype.hasOwnProperty.call(t, e) } , e = {}; function o(t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {} , o = document.createElement(t); if (e.className && (o.className = e.className), e.id && (o.id = e.id), e.text && (o.textContent = e.text), e.html && (o.innerHTML = e.html), e.attributes) for (var n in e.attributes) o.setAttribute(n, e.attributes[n]); if (e.styles) for (var i in e.styles) o.style[i] = e.styles[i]; if (e.events) for (var a in e.events) o.addEventListener(a, e.events[a]); return e.children && e.children.forEach((function(t) { o.appendChild(t) } )), o } function n(t, e, o) { if (arguments.length > 3 && void 0 !== arguments[3] && arguments[3]) { var n = t.parentElement; if (n) { var i = n.getBoundingClientRect(); e = i.width * e, o = i.height * o } } t.style.left = e + "px", t.style.top = o + "px", t.style.transform = "translate(-50%, -50%)" } function i(t) { return i = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) { return typeof t } : function(t) { return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t } , i(t) } t.d(e, { default: () => M }); var a = "quadTap_"; function r(t, e) { try { var o = a + t; return "object" === i(e) ? localStorage.setItem(o, JSON.stringify(e)) : localStorage.setItem(o, e), !0 } catch (t) { return console.error("[QuadTap] Error saving to localStorage:", t), !1 } } function s(t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : null; try { var o = a + t , n = localStorage.getItem(o); if (null === n) return e; try { return JSON.parse(n) } catch (t) { return n } } catch (t) { return console.error("[QuadTap] Error retrieving from localStorage:", t), e } } function l(t) { return l = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) { return typeof t } : function(t) { return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t } , l(t) } function d() { d = function() { return e } ; var t, e = {}, o = Object.prototype, n = o.hasOwnProperty, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", r = i.asyncIterator || "@@asyncIterator", s = i.toStringTag || "@@toStringTag"; function c(t, e, o, n) { return Object.defineProperty(t, e, { value: o, enumerable: !n, configurable: !n, writable: !n }) } try { c({}, "") } catch (t) { c = function(t, e, o) { return t[e] = o } } function u(e, o, n, i) { var a = o && o.prototype instanceof g ? o : g , r = Object.create(a.prototype); return c(r, "_invoke", function(e, o, n) { var i = 1; return function(a, r) { if (3 === i) throw Error("Generator is already running"); if (4 === i) { if ("throw" === a) throw r; return { value: t, done: !0 } } for (n.method = a, n.arg = r; ; ) { var s = n.delegate; if (s) { var l = j(s, n); if (l) { if (l === p) continue; return l } } if ("next" === n.method) n.sent = n._sent = n.arg; else if ("throw" === n.method) { if (1 === i) throw i = 4, n.arg; n.dispatchException(n.arg) } else "return" === n.method && n.abrupt("return", n.arg); i = 3; var d = h(e, o, n); if ("normal" === d.type) { if (i = n.done ? 4 : 2, d.arg === p) continue; return { value: d.arg, done: n.done } } "throw" === d.type && (i = 4, n.method = "throw", n.arg = d.arg) } } }(e, n, new T(i || [])), !0), r } function h(t, e, o) { try { return { type: "normal", arg: t.call(e, o) } } catch (t) { return { type: "throw", arg: t } } } e.wrap = u; var p = {}; function g() {} function m() {} function f() {} var b = {}; c(b, a, (function() { return this } )); var v = Object.getPrototypeOf , y = v && v(v(B([]))); y && y !== o && n.call(y, a) && (b = y); var w = f.prototype = g.prototype = Object.create(b); function x(t) { ["next", "throw", "return"].forEach((function(e) { c(t, e, (function(t) { return this._invoke(e, t) } )) } )) } function C(t, e, o) { var n = document.createElement("button"); w(n, b); // Detect if we're on mobile or small screen var isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); var isSmallScreen = window.innerWidth < 768; // Apply responsive styles for buttons on mobile/small screens if (isMobile || isSmallScreen) { n.style.width = "26px"; n.style.height = "26px"; n.style.margin = "0 2px"; n.style.fontSize = "13px"; } // Fix alignment issues - using a single block of style definitions n.style.display = "flex"; n.style.alignItems = "center"; n.style.justifyContent = "center"; n.style.lineHeight = "1"; n.style.padding = "0"; // Remove any default padding n.style.verticalAlign = "middle"; n.textContent = t; n.setAttribute("aria-label", e); n.addEventListener("mouseenter", (function() { w(n, v) })), n.addEventListener("mouseleave", (function() { n.style.backgroundColor = "" })), n.addEventListener("click", function(e) { e.preventDefault(); o(e); }), // Add touch events for mobile n.addEventListener("touchstart", function(e) { e.preventDefault(); // Prevent default touch behavior w(n, v); // Apply hover style on touch }), n.addEventListener("touchend", function(e) { e.preventDefault(); // Prevent default touch behavior n.style.backgroundColor = ""; // Reset style o(e); // Call the original handler }), n.addEventListener("touchcancel", function(e) { n.style.backgroundColor = ""; // Reset style on touch cancel }); return n; } function j(t) { var n = o.method , i = e.i[n]; if (i === t) return o.delegate = null, "throw" === n && e.i.return && (o.method = "return", o.arg = t, j(e, o), "throw" === o.method) || "return" !== n && (o.method = "throw", o.arg = new TypeError("The iterator does not provide a '" + n + "' method")), p; var a = h(i, e.i, o.arg); if ("throw" === a.type) return o.method = "throw", o.arg = a.arg, o.delegate = null, p; var r = a.arg; return r ? r.done ? (o[e.r] = r.value, o.next = e.n, "return" !== o.method && (o.method = "next", o.arg = t), o.delegate = null, p) : r : (o.method = "throw", o.arg = new TypeError("iterator result is not an object"), o.delegate = null, p) } function k(t) { this.tryEntries.push(t) } function S(e) { var o = e[4] || {}; o.type = "normal", o.arg = t, e[4] = o } function T(t) { this.tryEntries = [[-1]], t.forEach(k, this), this.reset(!0) } function B(e) { if (null != e) { var o = e[a]; if (o) return o.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var i = -1 , r = function o() { for (; ++i < e.length; ) if (n.call(e, i)) return o.value = e[i], o.done = !1, o; return o.value = t, o.done = !0, o }; return r.next = r } } throw new TypeError(l(e) + " is not iterable") } return m.prototype = f, c(w, "constructor", f), c(f, "constructor", m), m.displayName = c(f, s, "GeneratorFunction"), e.isGeneratorFunction = function(t) { var e = "function" == typeof t && t.constructor; return !!e && (e === m || "GeneratorFunction" === (e.displayName || e.name)) } , e.mark = function(t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, f) : (t.__proto__ = f, c(t, s, "GeneratorFunction")), t.prototype = Object.create(w), t } , e.awrap = function(t) { return { __await: t } } , x(C.prototype), c(C.prototype, r, (function() { return this } )), e.AsyncIterator = C, e.async = function(t, o, n, i, a) { void 0 === a && (a = Promise); var r = new C(u(t, o, n, i),a); return e.isGeneratorFunction(o) ? r : r.next().then((function(t) { return t.done ? t.value : r.next() } )) } , x(w), c(w, s, "Generator"), c(w, a, (function() { return this } )), c(w, "toString", (function() { return "[object Generator]" } )), e.keys = function(t) { var e = Object(t) , o = []; for (var n in e) o.unshift(n); return function t() { for (; o.length; ) if ((n = o.pop())in e) return t.value = n, t.done = !1, t; return t.done = !0, t } } , e.values = B, T.prototype = { constructor: T, reset: function(e) { if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(S), !e) for (var o in this) "t" === o.charAt(0) && n.call(this, o) && !isNaN(+o.slice(1)) && (this[o] = t) }, stop: function() { this.done = !0; var t = this.tryEntries[0][4]; if ("throw" === t.type) throw t.arg; return this.rval }, dispatchException: function(e) { if (this.done) throw e; var o = this; function n(t) { r.type = "throw", r.arg = e, o.next = t } for (var i = o.tryEntries.length - 1; i >= 0; --i) { var a = this.tryEntries[i] , r = a[4] , s = this.prev , l = a[1] , d = a[2]; if (-1 === a[0]) return n("end"), !1; if (!l && !d) throw Error("try statement without catch or finally"); if (null != a[0] && a[0] <= s) { if (s < l) return this.method = "next", this.arg = t, n(l), !0; if (s < d) return n(d), !1 } } }, abrupt: function(t, e) { for (var o = this.tryEntries.length - 1; o >= 0; --o) { var n = this.tryEntries[o]; if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) { var i = n; break } } i && ("break" === t || "continue" === t) && i[0] <= e && e <= i[2] && (i = null); var a = i ? i[4] : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i[2], p) : this.complete(a) }, complete: function(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), p }, finish: function(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var o = this.tryEntries[e]; if (o[2] === t) return this.complete(o[4], o[3]), S(o), p } }, catch: function(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var o = this.tryEntries[e]; if (o[0] === t) { var n = o[4]; if ("throw" === n.type) { var i = n.arg; S(o) } return i } } throw Error("illegal catch attempt") }, delegateYield: function(e, o, n) { return this.delegate = { i: B(e), r: o, n }, "next" === this.method && (this.arg = t), p } }, e } function c(t, e, o, n, i, a, r) { try { var s = t[a](r) , l = s.value } catch (t) { return void o(t) } s.done ? e(l) : Promise.resolve(l).then(n, i) } function u(t) { return function() { var e = this , o = arguments; return new Promise((function(n, i) { var a = t.apply(e, o); function r(t) { c(a, n, i, r, s, "next", t) } function s(t) { c(a, n, i, r, s, "throw", t) } r(void 0) } )) } } function h() { return (h = u(d().mark((function t(e) { var o, n, i; return d().wrap((function(t) { for (; ; ) switch (t.prev = t.next) { case 0: if (n = e.elements.video, !(i = (null === (o = e.config.videoPlayerApi) || void 0 === o ? void 0 : o.enabled) && e.config.videoPlayerApi.adapter)) { t.next = 7; break } return t.next = 5, i.play(); case 5: t.next = 16; break; case 7: if (!n) { t.next = 16; break } return t.prev = 8, t.next = 11, n.play(); case 11: t.next = 16; break; case 13: t.prev = 13, t.t0 = t.catch(8), console.error("Error resuming video playback:", t.t0); case 16: case "end": return t.stop() } } ), t, null, [[8, 13]]) } )))).apply(this, arguments) } function p() { return (p = u(d().mark((function t(e) { var o, n, i; return d().wrap((function(t) { for (; ; ) switch (t.prev = t.next) { case 0: if (n = e.elements.video, !(i = (null === (o = e.config.videoPlayerApi) || void 0 === o ? void 0 : o.enabled) && e.config.videoPlayerApi.adapter)) { t.next = 11; break } // QuadTap MOD: Unconditionally pause if adapter exists return t.next = 5, i.pause(); case 5: // e.state.wasPlayingBefore = t.sent; // QuadTap MOD: Removed wasPlayingBefore logic // if (!e.state.wasPlayingBefore) { // t.next = 9; // break // } // return t.next = 9, // i.pause(); // case 9: t.next = 12; // QuadTap MOD: Skip to end after pause break; case 11: // QuadTap MOD: Unconditionally pause if native video element exists n && n.pause(); // e.state.wasPlayingBefore = !1; // QuadTap MOD: Removed wasPlayingBefore logic case 12: case "end": return t.stop() } } ), t) } )))).apply(this, arguments) } var g = { width: "60%", // Adjusted from 70% maxWidth: "350px", // Adjusted from 420px height: "auto", padding: "6px 10px", // Slightly reduced padding borderRadius: "24px", backgroundColor: "rgba(0, 0, 0, 0.7)", display: "flex", justifyContent: "space-around", // Restored original space-around alignItems: "center", boxShadow: "0 2px 8px rgba(0, 0, 0, 0.3)", transition: "opacity 0.3s ease, width 0.3s ease, padding 0.3s ease" } , m = { position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)" } , f = { position: "static", top: "", left: "", transform: "", margin: "20px auto" } , b = { width: "30px", // Adjusted from 32px height: "30px", // Adjusted from 32px margin: "0 3px", // Adjusted from 4px borderRadius: "50%", border: "none", backgroundColor: "rgba(255, 255, 255, 0.2)", color: "white", fontSize: "14px", // Adjusted from 15px cursor: "pointer", outline: "none", display: "flex", justifyContent: "center", alignItems: "center", transition: "background-color 0.2s ease" } , v = { backgroundColor: "rgba(255, 255, 255, 0.2)" } , y = { position: "absolute", backgroundColor: "rgba(0, 0, 0, 0.8)", color: "white", padding: "5px 10px", borderRadius: "4px", fontSize: "14px", zIndex: "2000", pointerEvents: "none", opacity: "0", transition: "opacity 0.3s ease" }; function w(t, e) { Object.assign(t.style, e) } function x(t) { var e = t.overlay , o = t.onPlay , n = t.onPause , i = t.onRewind , a = t.onForward , r = t.onShare , s = t.onCopyUrl , l = t.rewindTime , d = void 0 === l ? 30 : l , c = t.forwardTime , u = void 0 === c ? 30 : c , h = t.debug , p = void 0 !== h && h , b = t.showAllButtons , v = void 0 !== b && b , y = t.isLightbox , x = void 0 !== y && y , j = document.createElement("div"); // Apply base styles w(j, g); w(j, x ? f : m); // Detect if we're on mobile or small screen var isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); var isSmallScreen = window.innerWidth < 768; // Apply responsive styles for mobile/small screens if (isMobile || isSmallScreen) { // Narrower on mobile but not too narrow j.style.width = "65%"; j.style.maxWidth = "280px"; j.style.padding = "5px 8px"; } if (!x) { var T = parseInt(getComputedStyle(e).zIndex) || 1e3; j.style.zIndex = (T + 10).toString() } var B = C("⟲" + d, "Rewind " + d + " seconds", i) , E = C("▶", "Play/Pause", (function(t) { var e = "▶" === E.textContent; E.textContent = e ? "❚❚" : "▶", e ? o(t) : n(t) } )) , q = C("⟳" + u, "Forward " + u + " seconds", a) , P = C("⤴", "Share", (function(t) { if (t.stopPropagation(), r) r(t); else { var e = window.location.href; navigator.share ? navigator.share({ title: "Check out this video moment", url: e }).catch((function(t) { console.error("Error sharing:", t) } )) : (k(e), S(P, "Link copied!")) } } )) , O = C("⧉", "Copy URL", (function(t) { t.stopPropagation(), s ? s(t) : (k(window.location.href), S(O, "Link copied!")) } )); if (j.appendChild(B), j.appendChild(E), j.appendChild(q), (v || x) && (j.appendChild(P), j.appendChild(O)), // Add click event handler to stop propagation j.addEventListener("click", (function(t) { t.stopPropagation(), p && console.log("[QuadTap] Control strip clicked, propagation stopped") })), // Add touch event handlers for mobile j.addEventListener("touchstart", function(t) { t.stopPropagation(); j.style.opacity = "1"; p && console.log("[QuadTap] Control strip touch started, propagation stopped"); }), j.addEventListener("touchend", function(t) { t.stopPropagation(); p && console.log("[QuadTap] Control strip touch ended, propagation stopped"); }), j.addEventListener("touchmove", function(t) { t.stopPropagation(); }), e.appendChild(j), !x) { var z, L = function() { j.style.opacity = "0.5" }; j.addEventListener("mouseenter", (function() { clearTimeout(z), j.style.opacity = "1" } )), j.addEventListener("mouseleave", (function() { clearTimeout(z), z = setTimeout(L, 2e3) } )), j.style.opacity = "1", z = setTimeout(L, 2e3) } return p && (console.log("[QuadTap] Control strip created with positioning:", { isLightbox: x, className: j.className, zIndex: j.style.zIndex }), x || new ResizeObserver((function() { var t = j.getBoundingClientRect() , o = e.getBoundingClientRect() , n = (t.top - o.top + t.height / 2) / o.height * 100 , i = (t.left - o.left + t.width / 2) / o.width * 100; console.log("[QuadTap] Control strip position after resize:", { topPercent: n.toFixed(2) + "%", leftPercent: i.toFixed(2) + "%", width: t.width, height: t.height }) } )).observe(e)), j } function C(t, e, o) { var n = document.createElement("button"); w(n, b); // Detect if we're on mobile or small screen var isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); var isSmallScreen = window.innerWidth < 768; // Apply responsive styles for buttons on mobile/small screens if (isMobile || isSmallScreen) { n.style.width = "26px"; n.style.height = "26px"; n.style.margin = "0 2px"; n.style.fontSize = "13px"; } // Fix alignment issues - using a single block of style definitions n.style.display = "flex"; n.style.alignItems = "center"; n.style.justifyContent = "center"; n.style.lineHeight = "1"; n.style.padding = "0"; // Remove any default padding n.style.verticalAlign = "middle"; n.textContent = t; n.setAttribute("aria-label", e); n.addEventListener("mouseenter", (function() { w(n, v) })), n.addEventListener("mouseleave", (function() { n.style.backgroundColor = "" })), n.addEventListener("click", function(e) { e.preventDefault(); o(e); }), // Add touch events for mobile n.addEventListener("touchstart", function(e) { e.preventDefault(); // Prevent default touch behavior w(n, v); // Apply hover style on touch }), n.addEventListener("touchend", function(e) { e.preventDefault(); // Prevent default touch behavior n.style.backgroundColor = ""; // Reset style o(e); // Call the original handler }), n.addEventListener("touchcancel", function(e) { n.style.backgroundColor = ""; // Reset style on touch cancel }); return n; } function j(t, e) { var o = t.querySelector("button:nth-child(2)"); o && (o.textContent = e ? "❚❚" : "▶") } function k(t) { if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(t).catch((function(t) { console.error("Failed to copy text: ", t) } )); else { var e = document.createElement("textarea"); e.value = t, e.style.position = "fixed", document.body.appendChild(e), e.select(); try { document.execCommand("copy") } catch (t) { console.error("Failed to copy text: ", t) } document.body.removeChild(e) } } function S(t, e) { var o = document.createElement("div"); w(o, y), o.textContent = e; var n = t.getBoundingClientRect(); o.style.top = "".concat(n.top - 30, "px"), o.style.left = "".concat(n.left + n.width / 2, "px"), o.style.transform = "translateX(-50%)", document.body.appendChild(o), setTimeout((function() { o.style.opacity = "1" } ), 10), setTimeout((function() { o.style.opacity = "0", setTimeout((function() { document.body.removeChild(o) } ), 300) } ), 1500) } function T(t) { return T = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) { return typeof t } : function(t) { return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t } , T(t) } function B(t, e) { for (var o = 0; o < e.length; o++) { var n = e[o]; n.enumerable = n.enumerable || !1, n.configurable = !0, "value"in n && (n.writable = !0), Object.defineProperty(t, E(n.key), n) } } function E(t) { var e = function(t) { if ("object" != T(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var o = e.call(t, "string"); if ("object" != T(o)) return o; throw new TypeError("@@toPrimitive must return a primitive value.") } return String(t) }(t); return "symbol" == T(e) ? e : e + "" } var q = { containerId: "main-video-droppable", videoSelector: "#main-video", autoCancelTimeout: 5e3, debug: !0, emojis: { quadrants: { topLeft: "🕊️", topRight: "🌟", bottomLeft: "🌧️", bottomRight: "💥" }, directional: { up: "🚀", right: "👑", down: "⬇️", left: "🤫" }, thoughts: { topLeft: ["🌸", "🎈", "🌦️", "🛤️"], topRight: ["🌈", "✨", "🌤️", "🎆"], bottomLeft: ["🍂", "🌙", "☔", "🗿"], bottomRight: ["⚖️", "🏆", "⛈️", "💣"] } }, videoControls: { enabled: !0, rewindTime: 30, forwardTime: 30 }, callbacks: { onOverlayActivate: null, onThrowDownInitiate: null, onThrowDownConfirm: null, onThrowDownCancel: null, onVideoControl: null } }; const P = function() { return t = function t() { var e, o, n = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}; !function(t, e) { if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function") }(this, t), this.config = Object.assign({}, q, n), n.emojis && (this.config.emojis = Object.assign({}, q.emojis, n.emojis), n.emojis.quadrants && (this.config.emojis.quadrants = Object.assign({}, q.emojis.quadrants, n.emojis.quadrants)), n.emojis.directional && (this.config.emojis.directional = Object.assign({}, q.emojis.directional, n.emojis.directional)), n.emojis.thoughts && (this.config.emojis.thoughts = Object.assign({}, q.emojis.thoughts, n.emojis.thoughts))), n.videoControls && (this.config.videoControls = Object.assign({}, q.videoControls, n.videoControls)), n.profileBubble ? this.config.profileBubble = Object.assign({}, { imageUrl: null, fallbackEmoji: "👤", size: "60px", borderColor: "white", borderWidth: "2px", backgroundColor: "rgba(0, 0, 0, 0.7)" }, n.profileBubble) : this.config.profileBubble = { imageUrl: null, fallbackEmoji: "👤", size: "60px", borderColor: "white", borderWidth: "2px", backgroundColor: "rgba(0, 0, 0, 0.7)" }, n.colors ? (this.config.colors = { overlay: { background: "rgba(240, 240, 245, 0.5)", quadrantGradients: { topLeft: "rgba(0, 255, 255, 0.8)", topRight: "rgba(255, 255, 0, 0.8)", bottomLeft: "rgba(0, 255, 0, 0.8)", bottomRight: "rgba(255, 0, 255, 0.8)" } }, lightbox: { background: "rgba(20, 30, 40, 0.95)", text: "white", headerBackground: "rgba(30, 40, 60, 0.8)", buttonPrimary: "#4CAF50", buttonSecondary: "#f44336" } }, n.colors.overlay && (this.config.colors.overlay = Object.assign({}, this.config.colors.overlay, n.colors.overlay), n.colors.overlay.quadrantGradients && (this.config.colors.overlay.quadrantGradients = Object.assign({}, this.config.colors.overlay.quadrantGradients, n.colors.overlay.quadrantGradients))), n.colors.lightbox && (this.config.colors.lightbox = Object.assign({}, this.config.colors.lightbox, n.colors.lightbox))) : this.config.colors = { overlay: { background: "rgba(240, 240, 245, 0.5)", quadrantGradients: { topLeft: "rgba(0, 255, 255, 0.8)", topRight: "rgba(255, 255, 0, 0.8)", bottomLeft: "rgba(0, 255, 0, 0.8)", bottomRight: "rgba(255, 0, 255, 0.8)" } }, lightbox: { background: "rgba(20, 30, 40, 0.95)", text: "white", headerBackground: "rgba(30, 40, 60, 0.8)", buttonPrimary: "#4CAF50", buttonSecondary: "#f44336" } }, this.state = { active: !1, profileBubblePosition: { x: 0, y: 0 }, currentQuadrant: null, autoCancelTimer: null, containerDimensions: { width: 0, height: 0 }, videoPlaying: !1, wasPlayingBefore: !1, recording: !1, mediaStream: null, mediaRecorder: null, recordingStartTime: 0, recordingIndicator: null, swipeDebounceTimer: null, // For debounce timing swipeProcessing: !1 // Add this to track active swipe processing }, this.elements = { container: null, video: null, overlay: null, profileBubble: null, directionalEmojis: {}, quadrantEmojis: {}, videoControls: null, tooltip: null, lightBox: null, lightBoxContent: null, emojiGrid: null, commentBox: null }, this.throttledResize = (e = this.handleResize.bind(this), function() { o || (e.apply(void 0, arguments), o = !0, setTimeout((function() { o = !1 } ), 100)) } ), this.init() } , e = [{ key: "log", value: function(t, e) { this.config.debug && console.log("[QuadTap] ".concat(t), e || "") } }, { key: "init", value: function() { this.log("Initializing QuadTap"); var t = document.getElementById(this.config.containerId); t ? (this.elements.container = t, function() { if (!document.getElementById("quad-tap-styles")) { var t = document.createElement("style"); t.id = "quad-tap-styles", t.textContent = "\n /* Overlay Container */\n .overlay-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.3s ease;\n z-index: 1000;\n background-color: rgba(240, 240, 245, 0.5);\n }\n \n .overlay-container.active {\n opacity: 1;\n pointer-events: auto;\n }\n \n /* Block pointer events on video when overlay is active */\n .overlay-container.active + video,\n .quad-tap-overlay.active + video {\n pointer-events: none;\n }\n \n /* Quadrants */\n .quadrant {\n position: absolute;\n width: 50%;\n height: 50%;\n opacity: 0.8;\n transition: opacity 0.3s ease;\n }\n \n .quadrant.top-left {\n top: 0;\n left: 0;\n background: linear-gradient(135deg, rgba(0, 255, 255, 0.8), rgba(0, 255, 255, 0));\n }\n \n .quadrant.top-right {\n top: 0;\n right: 0;\n background: linear-gradient(225deg, rgba(255, 255, 0, 0.8), rgba(255, 255, 0, 0));\n }\n \n .quadrant.bottom-left {\n bottom: 0;\n left: 0;\n background: linear-gradient(45deg, rgba(0, 255, 0, 0.8), rgba(0, 255, 0, 0));\n }\n \n .quadrant.bottom-right {\n bottom: 0;\n right: 0;\n background: linear-gradient(315deg, rgba(255, 0, 255, 0.8), rgba(255, 0, 255, 0));\n }\n \n /* Profile Bubble */\n .profile-bubble {\n position: absolute;\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background-color: rgba(128, 128, 128, 0.8);\n border: 2px solid white;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);\n display: flex;\n justify-content: center;\n align-items: center;\n cursor: pointer;\n z-index: 1001;\n transform: translate(-50%, -50%);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n }\n \n .profile-bubble:hover {\n transform: translate(-50%, -50%) scale(1.1);\n box-shadow: 0 0 15px rgba(0, 0, 0, 0.7);\n }\n \n /* Light-Box Modal */\n .td-modal {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(23, 32, 42, 0.7);\n z-index: 2000;\n justify-content: center;\n align-items: center;\n opacity: 0;\n transition: opacity 0.3s ease;\n }\n \n .td-modal.active {\n display: flex;\n opacity: 1;\n }\n \n .td-modal-content {\n background-color: white;\n padding: 20px;\n border-radius: 10px;\n width: 95%;\n max-width: 800px;\n max-height: 80vh;\n overflow-y: auto;\n position: relative;\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n \n .td-modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n }\n \n .td-modal-header h4 {\n margin: 0;\n font-size: 1.5rem;\n color: #333;\n }\n \n .td-close-btn, .td-pause-play-btn {\n background: none;\n border: none;\n font-size: 1.5rem;\n cursor: pointer;\n color: #999;\n transition: color 0.2s ease;\n }\n \n .td-close-btn {\n margin-left: 10px;\n }\n \n .td-pause-play-btn {\n margin-left: auto;\n }\n \n .td-close-btn:hover, .td-pause-play-btn:hover {\n color: #333;\n }\n \n /* Emoji Grid */\n .emoji-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n grid-template-rows: 1fr 1fr;\n gap: 10px;\n width: 100%;\n }\n \n .emoji-quadrant {\n padding: 10px;\n border-radius: 8px;\n }\n \n .emoji-quadrant.top-left {\n background-color: rgba(0, 255, 255, 0.2);\n }\n \n .emoji-quadrant.top-right {\n background-color: rgba(255, 255, 0, 0.2);\n }\n \n .emoji-quadrant.bottom-left {\n background-color: rgba(0, 255, 0, 0.2);\n }\n \n .emoji-quadrant.bottom-right {\n background-color: rgba(255, 0, 255, 0.2);\n }\n \n .emoji-row {\n display: flex;\n justify-content: space-around;\n margin-bottom: 10px;\n background-color: transparent;\n }\n \n .emoji-cell {\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: transparent;\n }\n \n .thought-emoji {\n font-size: 2rem;\n cursor: pointer;\n padding: 5px;\n border-radius: 5px;\n transition: transform 0.2s ease, background-color 0.2s ease;\n }\n \n .thought-emoji:hover {\n transform: scale(1.2);\n background-color: rgba(255, 255, 255, 0.5);\n }\n \n .thought-emoji.selected {\n background-color: rgba(255, 255, 255, 0.8);\n box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);\n }\n \n /* Tooltip */\n .tooltip {\n position: absolute;\n background-color: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 5px 10px;\n border-radius: 5px;\n font-size: 0.8rem;\n pointer-events: none;\n z-index: 1002;\n transition: opacity 0.3s ease;\n }\n \n /* Comment Box */\n .comment-box {\n margin-top: 20px;\n width: 100%;\n }\n \n .comment-box textarea {\n width: 100%;\n padding: 10px;\n border: 1px solid #ddd;\n border-radius: 5px;\n resize: vertical;\n min-height: 80px;\n font-family: inherit;\n }\n \n /* Media Buttons */\n .media-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n margin-top: 10px;\n margin-bottom: 10px;\n }\n \n .media-button {\n padding: 8px 12px;\n border: none;\n border-radius: 5px;\n cursor: pointer;\n font-weight: bold;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n .upload-button {\n background-color: #3498db;\n color: white;\n }\n \n .upload-button:hover {\n background-color: #2980b9;\n }\n \n .capture-button {\n background-color: #e74c3c;\n color: white;\n }\n \n .capture-button:hover {\n background-color: #c0392b;\n }\n \n .uploaded-file-name {\n margin-top: 5px;\n padding: 5px;\n background-color: #f1f1f1;\n border-radius: 3px;\n font-size: 0.9rem;\n width: 100%;\n }\n \n .recording-message {\n margin-top: 5px;\n padding: 5px;\n background-color: #f8d7da;\n color: #721c24;\n border-radius: 3px;\n font-size: 0.9rem;\n width: 100%;\n }\n \n .recording-indicator {\n animation: pulse 1.5s infinite;\n }\n \n @keyframes pulse {\n 0% { opacity: 1; }\n 50% { opacity: 0.5; }\n 100% { opacity: 1; }\n }\n \n /* Action Buttons */\n .action-buttons {\n display: flex;\n justify-content: flex-end;\n margin-top: 20px;\n gap: 10px;\n }\n \n .action-button {\n padding: 8px 16px;\n border: none;\n border-radius: 5px;\n cursor: pointer;\n font-weight: bold;\n transition: background-color 0.2s ease;\n }\n \n .save-button {\n background-color: #4CAF50;\n color: white;\n }\n \n .save-button:hover {\n background-color: #45a049;\n }\n \n .cancel-button {\n background-color: #f44336;\n color: white;\n }\n \n .cancel-button:hover {\n background-color: #d32f2f;\n }\n ", document.head.appendChild(t) } }(), this.createOverlayElements(), this.createLightBoxElements(), this.bindEventHandlers(), this.log("QuadTap initialized successfully")) : this.log("Container not found", this.config.containerId) } }, { key: "createOverlayElements", value: function() { var t = this , e = o("div", { className: "quad-tap-overlay", styles: { display: "none", backgroundColor: this.config.colors.overlay.background } }) , n = o("div", { className: "overlay-close-btn", html: "&times;", styles: { position: "absolute", top: "10px", right: "10px", width: "30px", height: "30px", borderRadius: "50%", backgroundColor: "rgba(0, 0, 0, 0.5)", color: "white", display: "flex", justifyContent: "center", alignItems: "center", fontSize: "20px", cursor: "pointer", zIndex: "1002" }, events: { click: function(e) { t.deactivateOverlay(), e.stopPropagation() } } }) , i = o("div", { className: "quadrant top-left", styles: { background: "radial-gradient(circle at 0% 0%, ".concat(this.config.colors.overlay.quadrantGradients.topLeft, ", transparent 70%)") } }) , a = o("div", { className: "quadrant top-right", styles: { background: "radial-gradient(circle at 100% 0%, ".concat(this.config.colors.overlay.quadrantGradients.topRight, ", transparent 70%)") } }) , r = o("div", { className: "quadrant bottom-left", styles: { background: "radial-gradient(circle at 0% 100%, ".concat(this.config.colors.overlay.quadrantGradients.bottomLeft, ", transparent 70%)") } }) , s = o("div", { className: "quadrant bottom-right", styles: { background: "radial-gradient(circle at 100% 100%, ".concat(this.config.colors.overlay.quadrantGradients.bottomRight, ", transparent 70%)") } }) , l = { display: "none", width: this.c