@gramercytech/gx-componentkit
Version:
Vue 3 component library for building kiosk-style applications on the Eventfinity platform
1,098 lines (1,095 loc) • 105 kB
JavaScript
const O = { class: "gx-modal-wrapper" }, H = { class: "gx-modal-container" }, W = {
key: 0,
class: "gx-modal-title"
}, j = ["innerHTML"], Y = { class: "gx-modal-buttons" }, Q = /* @__PURE__ */ Vue.defineComponent({
__name: "GxModal",
props: {
pluginVars: {},
theme: {},
errorMessages: { default: () => [] }
},
emits: ["close-modal"],
setup(d, { emit: c }) {
const r = d, l = c, e = Vue.computed(
() => r.errorMessages.length ? r.errorMessages : r.pluginVars.messages || []
), o = () => {
l("close-modal");
}, u = (t) => {
const n = r.pluginVars[t];
typeof n == "function" && n(), o();
};
return Vue.watch(
() => r.theme,
(t) => {
var _, a, s, m, p, V;
const n = "gx-modal-theme-override", g = document.getElementById(n);
if (g && g.remove(), t != null && t.colors_override_theme) {
const x = document.createElement("style");
x.id = n, x.innerHTML = `
.gx-modal-container {
--gx-modal-bg-color: ${t.modal_background_color};
--gx-modal-text-color: ${t.modal_text_color};
--gx-modal-primary-button-bg: ${(_ = t.primaryButtons) == null ? void 0 : _.backgroundColor};
--gx-modal-primary-button-color: ${(a = t.primaryButtons) == null ? void 0 : a.color};
--gx-modal-primary-button-border: ${(s = t.primaryButtons) == null ? void 0 : s.borderColor};
--gx-modal-secondary-button-bg: ${(m = t.secondaryButtons) == null ? void 0 : m.backgroundColor};
--gx-modal-secondary-button-color: ${(p = t.secondaryButtons) == null ? void 0 : p.color};
--gx-modal-secondary-button-border: ${(V = t.secondaryButtons) == null ? void 0 : V.borderColor};
}
`, document.head.appendChild(x);
}
},
{ immediate: !0 }
), (t, n) => (Vue.openBlock(), Vue.createElementBlock("div", O, [
Vue.createElementVNode("div", H, [
t.pluginVars.title ? (Vue.openBlock(), Vue.createElementBlock("h2", W, Vue.toDisplayString(t.pluginVars.title), 1)) : Vue.createCommentVNode("", !0),
(Vue.openBlock(!0), Vue.createElementBlock(Vue.Fragment, null, Vue.renderList(e.value, (g, _) => (Vue.openBlock(), Vue.createElementBlock("p", {
key: _,
class: "gx-modal-message",
innerHTML: g
}, null, 8, j))), 128)),
Vue.createElementVNode("div", Y, [
t.pluginVars.left_button_text ? (Vue.openBlock(), Vue.createElementBlock("button", {
key: 0,
class: "gx-modal-button gx-modal-button--secondary",
onClick: n[0] || (n[0] = (g) => u("left_button_action"))
}, Vue.toDisplayString(t.pluginVars.left_button_text), 1)) : Vue.createCommentVNode("", !0),
t.pluginVars.right_button_text ? (Vue.openBlock(), Vue.createElementBlock("button", {
key: 1,
class: "gx-modal-button gx-modal-button--primary",
onClick: n[1] || (n[1] = (g) => u("right_button_action"))
}, Vue.toDisplayString(t.pluginVars.right_button_text), 1)) : Vue.createCommentVNode("", !0)
])
])
]));
}
}), z = (d, c) => {
const r = d.__vccOpts || d;
for (const [l, e] of c)
r[l] = e;
return r;
}, X = /* @__PURE__ */ z(Q, [["__scopeId", "data-v-8eb120a8"]]), K = { class: "gx-camera" }, J = { class: "gx-camera__container" }, Z = {
key: 0,
class: "gx-camera__overlay"
}, ee = {
key: 0,
class: "gx-camera__grid"
}, te = {
key: 1,
class: "gx-camera__border"
}, oe = {
key: 2,
class: "gx-camera__circle"
}, ne = {
key: 1,
class: "gx-camera__countdown"
}, ae = {
key: 2,
class: "gx-camera__status"
}, se = {
key: 3,
class: "gx-camera__error"
}, le = {
key: 0,
class: "gx-camera__controls"
}, re = ["value"], ue = ["disabled"], ie = { class: "gx-camera__action-buttons" }, ce = ["disabled"], de = ["disabled"], me = {
key: 0,
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24",
class: "gx-camera__icon"
}, ge = {
key: 1,
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24",
class: "gx-camera__icon"
}, pe = { class: "gx-camera__mode-toggle" }, Ve = /* @__PURE__ */ Vue.defineComponent({
__name: "GxCamera",
props: {
facingMode: { default: "environment" },
width: { default: 640 },
height: { default: 480 },
showControls: { type: Boolean, default: !0 },
showOverlay: { type: Boolean, default: !0 },
overlayType: { default: "border" },
mode: { default: "photo" },
autoStart: { type: Boolean, default: !0 },
countdown: { default: 0 },
quality: { default: 0.8 }
},
emits: ["photo-captured", "video-recorded", "stream-started", "stream-stopped", "error", "device-changed"],
setup(d, { expose: c, emit: r }) {
const l = d, e = r, o = Vue.ref(), u = Vue.ref(), t = Vue.ref(!1), n = Vue.ref(!1), g = Vue.ref(!1), _ = Vue.ref(0), a = Vue.ref(null), s = Vue.ref(null), m = Vue.ref([]), p = Vue.ref(""), V = Vue.ref(l.mode), x = Vue.ref(l.facingMode);
let C = null, T = [], y = null;
const b = Vue.computed({
get: () => V.value,
set: (h) => V.value = h
}), I = Vue.computed({
get: () => x.value,
set: (h) => x.value = h
}), E = async () => {
try {
const h = await navigator.mediaDevices.enumerateDevices();
m.value = h.filter((f) => f.kind === "videoinput").map((f) => ({
deviceId: f.deviceId,
label: f.label,
kind: f.kind
}));
} catch (h) {
console.error("Failed to enumerate devices:", h), s.value = "Failed to get camera devices";
}
}, w = () => {
const h = {
video: {
width: { ideal: l.width },
height: { ideal: l.height }
}
};
return p.value ? h.video.deviceId = { exact: p.value } : h.video.facingMode = I.value, h;
}, D = async () => {
try {
s.value = null, a.value = "Starting camera...";
const h = w(), f = await navigator.mediaDevices.getUserMedia(h);
if (!o.value)
throw new Error("Video element not found");
o.value.srcObject = f, y = f, t.value = !0, a.value = null, e("stream-started", f);
} catch (h) {
console.error("Failed to start camera:", h), s.value = "Failed to access camera. Please check permissions.", a.value = null, e("error", "Failed to access camera");
}
}, P = () => {
y && (y.getTracks().forEach((h) => h.stop()), y = null), o.value && (o.value.srcObject = null), t.value = !1, e("stream-stopped");
}, S = async () => {
t.value && (P(), await D(), e("device-changed", p.value));
}, F = async () => {
I.value = I.value === "user" ? "environment" : "user", t.value && (P(), await D());
}, q = () => new Promise((h) => {
if (l.countdown <= 0) {
h();
return;
}
g.value = !0, _.value = l.countdown;
const f = setInterval(() => {
_.value--, _.value <= 0 && (clearInterval(f), g.value = !1, h());
}, 1e3);
}), k = async () => {
if (!(!o.value || !u.value || !t.value))
try {
await q();
const h = o.value, f = u.value, M = f.getContext("2d");
if (!M)
throw new Error("Failed to get canvas context");
f.width = h.videoWidth, f.height = h.videoHeight, M.drawImage(h, 0, 0, f.width, f.height), f.toBlob((L) => {
if (L) {
const G = f.toDataURL("image/jpeg", l.quality);
e("photo-captured", L, G);
}
}, "image/jpeg", l.quality);
} catch (h) {
console.error("Failed to capture photo:", h), s.value = "Failed to capture photo", e("error", "Failed to capture photo");
}
}, i = () => {
if (y)
try {
T = [], C = new MediaRecorder(y), C.ondataavailable = (h) => {
h.data.size > 0 && T.push(h.data);
}, C.onstop = () => {
const h = new Blob(T, { type: "video/webm" }), f = URL.createObjectURL(h);
e("video-recorded", h, f);
}, C.start(), n.value = !0;
} catch (h) {
console.error("Failed to start recording:", h), s.value = "Failed to start recording", e("error", "Failed to start recording");
}
}, v = () => {
C && n.value && (C.stop(), n.value = !1);
}, B = () => {
n.value ? v() : i();
}, N = (h) => {
n.value && v(), b.value = h;
}, $ = () => {
a.value = null;
};
return Vue.watch(() => l.facingMode, (h) => {
I.value = h, t.value && !p.value && S();
}), Vue.watch(() => l.mode, (h) => {
N(h);
}), Vue.onMounted(async () => {
await E(), l.autoStart && await D();
}), Vue.onBeforeUnmount(() => {
P(), n.value && v();
}), c({
startStream: D,
stopStream: P,
capturePhoto: k,
startRecording: i,
stopRecording: v,
toggleRecording: B,
switchCamera: S,
getAvailableDevices: E,
isStreaming: () => t.value,
isRecording: () => n.value
}), (h, f) => (Vue.openBlock(), Vue.createElementBlock("div", K, [
Vue.createElementVNode("div", J, [
Vue.createElementVNode("video", {
ref_key: "videoElement",
ref: o,
class: Vue.normalizeClass(["gx-camera__video", { "gx-camera__video--mirrored": I.value === "user" }]),
autoplay: "",
muted: "",
playsinline: "",
onLoadedmetadata: $
}, null, 34),
h.showOverlay ? (Vue.openBlock(), Vue.createElementBlock("div", Z, [
h.overlayType === "grid" ? (Vue.openBlock(), Vue.createElementBlock("div", ee, f[3] || (f[3] = [
Vue.createElementVNode("div", { class: "gx-camera__grid-line gx-camera__grid-line--vertical" }, null, -1),
Vue.createElementVNode("div", { class: "gx-camera__grid-line gx-camera__grid-line--vertical" }, null, -1),
Vue.createElementVNode("div", { class: "gx-camera__grid-line gx-camera__grid-line--horizontal" }, null, -1),
Vue.createElementVNode("div", { class: "gx-camera__grid-line gx-camera__grid-line--horizontal" }, null, -1)
]))) : Vue.createCommentVNode("", !0),
h.overlayType === "border" ? (Vue.openBlock(), Vue.createElementBlock("div", te)) : Vue.createCommentVNode("", !0),
h.overlayType === "circle" ? (Vue.openBlock(), Vue.createElementBlock("div", oe)) : Vue.createCommentVNode("", !0)
])) : Vue.createCommentVNode("", !0),
g.value ? (Vue.openBlock(), Vue.createElementBlock("div", ne, Vue.toDisplayString(_.value), 1)) : Vue.createCommentVNode("", !0),
a.value ? (Vue.openBlock(), Vue.createElementBlock("div", ae, Vue.toDisplayString(a.value), 1)) : Vue.createCommentVNode("", !0),
s.value ? (Vue.openBlock(), Vue.createElementBlock("div", se, Vue.toDisplayString(s.value), 1)) : Vue.createCommentVNode("", !0)
]),
h.showControls ? (Vue.openBlock(), Vue.createElementBlock("div", le, [
m.value.length > 1 ? Vue.withDirectives((Vue.openBlock(), Vue.createElementBlock("select", {
key: 0,
"onUpdate:modelValue": f[0] || (f[0] = (M) => p.value = M),
onChange: S,
class: "gx-camera__device-select"
}, [
(Vue.openBlock(!0), Vue.createElementBlock(Vue.Fragment, null, Vue.renderList(m.value, (M) => (Vue.openBlock(), Vue.createElementBlock("option", {
key: M.deviceId,
value: M.deviceId
}, Vue.toDisplayString(M.label || `Camera ${M.deviceId.substring(0, 8)}`), 9, re))), 128))
], 544)), [
[Vue.vModelSelect, p.value]
]) : Vue.createCommentVNode("", !0),
p.value ? Vue.createCommentVNode("", !0) : (Vue.openBlock(), Vue.createElementBlock("button", {
key: 1,
onClick: F,
class: "gx-camera__control-button gx-camera__flip-button",
disabled: !t.value
}, f[4] || (f[4] = [
Vue.createElementVNode("svg", {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24",
class: "gx-camera__icon"
}, [
Vue.createElementVNode("path", { d: "M15.7 16.5c0 .8-.7 1.5-1.5 1.5s-1.5-.7-1.5-1.5.7-1.5 1.5-1.5 1.5.7 1.5 1.5zm-8.7 0c0 .8-.7 1.5-1.5 1.5S4 17.3 4 16.5 4.7 15 5.5 15s1.5.7 1.5 1.5zm11-9.2c0-.6-.4-1-1-1h-13c-.6 0-1 .4-1 1v8.4c0 .6.4 1 1 1h13c.6 0 1-.4 1-1V7.3z" })
], -1),
Vue.createTextVNode(" Flip ")
]), 8, ue)),
Vue.createElementVNode("div", ie, [
b.value === "photo" ? (Vue.openBlock(), Vue.createElementBlock("button", {
key: 0,
onClick: k,
disabled: !t.value || g.value,
class: "gx-camera__control-button gx-camera__capture-button"
}, [
f[5] || (f[5] = Vue.createElementVNode("svg", {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24",
class: "gx-camera__icon"
}, [
Vue.createElementVNode("circle", {
cx: "12",
cy: "12",
r: "3.2"
}),
Vue.createElementVNode("path", { d: "M9 2 7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" })
], -1)),
Vue.createTextVNode(" " + Vue.toDisplayString(g.value ? _.value : "Capture"), 1)
], 8, ce)) : Vue.createCommentVNode("", !0),
b.value === "video" ? (Vue.openBlock(), Vue.createElementBlock("button", {
key: 1,
onClick: B,
disabled: !t.value,
class: Vue.normalizeClass(["gx-camera__control-button", { "gx-camera__recording-button--active": n.value }])
}, [
n.value ? (Vue.openBlock(), Vue.createElementBlock("svg", ge, f[7] || (f[7] = [
Vue.createElementVNode("rect", {
x: "6",
y: "6",
width: "12",
height: "12"
}, null, -1)
]))) : (Vue.openBlock(), Vue.createElementBlock("svg", me, f[6] || (f[6] = [
Vue.createElementVNode("circle", {
cx: "12",
cy: "12",
r: "10"
}, null, -1)
]))),
Vue.createTextVNode(" " + Vue.toDisplayString(n.value ? "Stop" : "Record"), 1)
], 10, de)) : Vue.createCommentVNode("", !0)
]),
Vue.createElementVNode("div", pe, [
Vue.createElementVNode("button", {
onClick: f[1] || (f[1] = (M) => N("photo")),
class: Vue.normalizeClass(["gx-camera__mode-button", { "gx-camera__mode-button--active": b.value === "photo" }])
}, " Photo ", 2),
Vue.createElementVNode("button", {
onClick: f[2] || (f[2] = (M) => N("video")),
class: Vue.normalizeClass(["gx-camera__mode-button", { "gx-camera__mode-button--active": b.value === "video" }])
}, " Video ", 2)
])
])) : Vue.createCommentVNode("", !0),
Vue.createElementVNode("canvas", {
ref_key: "canvasElement",
ref: u,
class: "gx-camera__canvas",
style: { display: "none" }
}, null, 512)
]));
}
}), _e = /* @__PURE__ */ z(Ve, [["__scopeId", "data-v-20f2d1f0"]]), ve = ["src", "poster", "autoplay", "loop", "muted", "controls", "playsinline"], he = {
key: 0,
class: "gx-video-player__custom-controls"
}, fe = { key: 0 }, ke = { key: 1 }, ye = { class: "gx-video-player__progress" }, be = { class: "gx-video-player__time" }, xe = /* @__PURE__ */ Vue.defineComponent({
__name: "GxVideoPlayer",
props: {
src: {},
poster: {},
autoplay: { type: Boolean, default: !1 },
loop: { type: Boolean, default: !1 },
muted: { type: Boolean, default: !1 },
showControls: { type: Boolean, default: !0 },
playsinline: { type: Boolean, default: !0 }
},
emits: ["play", "pause", "ended", "timeupdate", "loadedmetadata", "error"],
setup(d, { expose: c, emit: r }) {
const l = r, e = Vue.ref(), o = Vue.ref(!1), u = Vue.ref(0), t = Vue.ref(0), n = Vue.ref(!1), g = Vue.computed(() => t.value > 0 ? u.value / t.value * 100 : 0), _ = () => {
e.value && (o.value ? e.value.pause() : e.value.play());
}, a = () => {
e.value && (n.value ? document.exitFullscreen && document.exitFullscreen() : e.value.requestFullscreen && e.value.requestFullscreen());
}, s = (b) => {
const I = Math.floor(b / 60), E = Math.floor(b % 60);
return `${I}:${E.toString().padStart(2, "0")}`;
}, m = () => {
o.value = !0, l("play");
}, p = () => {
o.value = !1, l("pause");
}, V = () => {
o.value = !1, l("ended");
}, x = () => {
e.value && (u.value = e.value.currentTime, l("timeupdate", u.value));
}, C = () => {
e.value && (t.value = e.value.duration, l("loadedmetadata", t.value));
}, T = (b) => {
l("error", b);
}, y = () => {
n.value = !!document.fullscreenElement;
};
return Vue.onMounted(() => {
document.addEventListener("fullscreenchange", y);
}), Vue.onBeforeUnmount(() => {
document.removeEventListener("fullscreenchange", y);
}), c({
play: () => {
var b;
return (b = e.value) == null ? void 0 : b.play();
},
pause: () => {
var b;
return (b = e.value) == null ? void 0 : b.pause();
},
seek: (b) => {
e.value && (e.value.currentTime = b);
},
togglePlay: _,
toggleFullscreen: a,
videoElement: e
}), (b, I) => (Vue.openBlock(), Vue.createElementBlock("div", {
class: Vue.normalizeClass(["gx-video-player", { "gx-video-player--fullscreen": n.value }])
}, [
Vue.createElementVNode("video", {
ref_key: "videoElement",
ref: e,
src: b.src,
poster: b.poster,
autoplay: b.autoplay,
loop: b.loop,
muted: b.muted,
controls: b.showControls,
playsinline: b.playsinline,
onLoadedmetadata: C,
onTimeupdate: x,
onEnded: V,
onPlay: m,
onPause: p,
onError: T,
class: "gx-video-player__video"
}, null, 40, ve),
b.showControls ? Vue.createCommentVNode("", !0) : (Vue.openBlock(), Vue.createElementBlock("div", he, [
Vue.createElementVNode("button", {
onClick: _,
class: Vue.normalizeClass(["gx-video-player__play-button", { "gx-video-player__play-button--playing": o.value }])
}, [
o.value ? (Vue.openBlock(), Vue.createElementBlock("span", ke, "⏸")) : (Vue.openBlock(), Vue.createElementBlock("span", fe, "▶"))
], 2),
Vue.createElementVNode("div", ye, [
Vue.createElementVNode("div", {
class: "gx-video-player__progress-bar",
style: Vue.normalizeStyle({ width: `${g.value}%` })
}, null, 4)
]),
Vue.createElementVNode("div", be, Vue.toDisplayString(s(u.value)) + " / " + Vue.toDisplayString(s(t.value)), 1),
Vue.createElementVNode("button", {
onClick: a,
class: "gx-video-player__fullscreen-button"
}, " ⛶ ")
]))
], 2));
}
}), Ee = /* @__PURE__ */ z(xe, [["__scopeId", "data-v-0c29ddc6"]]), Be = { class: "gx-audio-visualizer" }, $e = ["width", "height"], Ce = {
key: 0,
class: "gx-audio-visualizer__controls"
}, we = ["disabled"], Ne = {
key: 1,
class: "gx-audio-visualizer__error"
}, Se = /* @__PURE__ */ Vue.defineComponent({
__name: "GxAudioVisualizer",
props: {
audioSource: {},
width: { default: 800 },
height: { default: 200 },
color: { default: "#007bff" },
backgroundColor: { default: "transparent" },
sensitivity: { default: 1 },
showControls: { type: Boolean, default: !0 },
autoStart: { type: Boolean, default: !1 },
type: { default: "bars" }
},
emits: ["visualization-start", "visualization-stop", "error"],
setup(d, { expose: c, emit: r }) {
const l = d, e = r, o = Vue.ref(), u = Vue.ref(!1), t = Vue.ref(null), n = Vue.ref(l.type), g = Vue.ref(l.width), _ = Vue.ref(l.height);
let a = null, s = null, m = null, p = null, V = null, x = null;
const C = async () => {
try {
a = new (window.AudioContext || window.webkitAudioContext)(), a.state === "suspended" && await a.resume(), s = a.createAnalyser(), s.fftSize = 256, s.smoothingTimeConstant = 0.8;
const i = s.frequencyBinCount;
return V = new Uint8Array(i), x = new Uint8Array(i), !0;
} catch (i) {
return console.error("Failed to initialize audio context:", i), t.value = "Failed to initialize audio context", e("error", "Failed to initialize audio context"), !1;
}
}, T = () => {
if (!a || !s || !l.audioSource) return !1;
try {
if (l.audioSource instanceof MediaStream)
m = a.createMediaStreamSource(l.audioSource);
else if (l.audioSource instanceof HTMLAudioElement)
m = a.createMediaElementSource(l.audioSource);
else if (l.audioSource instanceof AudioNode)
m = l.audioSource;
else
throw new Error("Unsupported audio source type");
return m.connect(s), !0;
} catch (i) {
return console.error("Failed to connect audio source:", i), t.value = "Failed to connect audio source", e("error", "Failed to connect audio source"), !1;
}
}, y = async () => {
u.value || !await C() || l.audioSource && !T() || (u.value = !0, t.value = null, D(), e("visualization-start"));
}, b = () => {
u.value && (u.value = !1, p && (cancelAnimationFrame(p), p = null), m && s && m.disconnect(s), a && a.state !== "closed" && a.close(), w(), e("visualization-stop"));
}, I = () => {
u.value ? b() : y();
}, E = () => {
u.value && (b(), Vue.nextTick(() => y()));
}, w = () => {
const i = o.value;
if (!i) return;
const v = i.getContext("2d");
v && (v.clearRect(0, 0, i.width, i.height), l.backgroundColor !== "transparent" && (v.fillStyle = l.backgroundColor, v.fillRect(0, 0, i.width, i.height)));
}, D = () => {
!u.value || !s || !V || !x || (s.getByteFrequencyData(V), s.getByteTimeDomainData(x), P(), p = requestAnimationFrame(D));
}, P = () => {
const i = o.value;
if (!i || !V) return;
const v = i.getContext("2d");
if (v)
switch (w(), n.value) {
case "bars":
S(v, i);
break;
case "wave":
F(v, i);
break;
case "circle":
q(v, i);
break;
case "frequency":
k(v, i);
break;
}
}, S = (i, v) => {
if (!V) return;
const B = v.width / V.length * 2.5;
let N, $ = 0;
i.fillStyle = l.color;
for (let h = 0; h < V.length; h++)
N = V[h] / 255 * v.height * l.sensitivity, i.fillRect($, v.height - N, B, N), $ += B + 1;
}, F = (i, v) => {
if (!x) return;
i.lineWidth = 2, i.strokeStyle = l.color, i.beginPath();
const B = v.width / x.length;
let N = 0;
for (let $ = 0; $ < x.length; $++) {
const f = x[$] / 128 * l.sensitivity * v.height / 2;
$ === 0 ? i.moveTo(N, f) : i.lineTo(N, f), N += B;
}
i.stroke();
}, q = (i, v) => {
if (!V) return;
const B = v.width / 2, N = v.height / 2, $ = Math.min(B, N) * 0.7;
i.strokeStyle = l.color, i.lineWidth = 2;
for (let h = 0; h < V.length; h++) {
const f = h / V.length * Math.PI * 2, M = V[h] / 255 * $ * l.sensitivity, L = B + Math.cos(f) * $, G = N + Math.sin(f) * $, U = B + Math.cos(f) * ($ + M), A = N + Math.sin(f) * ($ + M);
i.beginPath(), i.moveTo(L, G), i.lineTo(U, A), i.stroke();
}
}, k = (i, v) => {
if (!V) return;
const B = i.createLinearGradient(0, 0, 0, v.height);
B.addColorStop(0, l.color), B.addColorStop(1, "transparent"), i.fillStyle = B, i.beginPath(), i.moveTo(0, v.height);
const N = v.width / V.length;
for (let $ = 0; $ < V.length; $++) {
const h = v.height - V[$] / 255 * v.height * l.sensitivity;
i.lineTo($ * N, h);
}
i.lineTo(v.width, v.height), i.closePath(), i.fill();
};
return Vue.watch(() => l.audioSource, (i) => {
u.value && (b(), i && Vue.nextTick(() => y()));
}), Vue.watch(() => l.width, (i) => {
g.value = i;
}), Vue.watch(() => l.height, (i) => {
_.value = i;
}), Vue.onMounted(() => {
l.autoStart && l.audioSource && y();
}), Vue.onBeforeUnmount(() => {
b();
}), c({
start: y,
stop: b,
toggle: I,
isActive: () => u.value
}), (i, v) => (Vue.openBlock(), Vue.createElementBlock("div", Be, [
Vue.createElementVNode("canvas", {
ref_key: "canvasElement",
ref: o,
class: "gx-audio-visualizer__canvas",
width: g.value,
height: _.value
}, null, 8, $e),
i.showControls ? (Vue.openBlock(), Vue.createElementBlock("div", Ce, [
Vue.createElementVNode("button", {
onClick: I,
class: "gx-audio-visualizer__control-button",
disabled: !i.audioSource
}, Vue.toDisplayString(u.value ? "Stop" : "Start"), 9, we),
Vue.withDirectives(Vue.createElementVNode("select", {
"onUpdate:modelValue": v[0] || (v[0] = (B) => n.value = B),
class: "gx-audio-visualizer__type-select",
onChange: E
}, v[1] || (v[1] = [
Vue.createElementVNode("option", { value: "bars" }, "Bars", -1),
Vue.createElementVNode("option", { value: "wave" }, "Waveform", -1),
Vue.createElementVNode("option", { value: "circle" }, "Circular", -1),
Vue.createElementVNode("option", { value: "frequency" }, "Frequency", -1)
]), 544), [
[Vue.vModelSelect, n.value]
])
])) : Vue.createCommentVNode("", !0),
t.value ? (Vue.openBlock(), Vue.createElementBlock("div", Ne, Vue.toDisplayString(t.value), 1)) : Vue.createCommentVNode("", !0)
]));
}
}), De = /* @__PURE__ */ z(Se, [["__scopeId", "data-v-ba308843"]]), Ie = { class: "gx-barcode-scanner" }, Me = {
key: 0,
class: "gx-barcode-scanner__instructions"
}, ze = { class: "gx-barcode-scanner__options" }, Te = {
key: 0,
class: "gx-barcode-scanner__manual-input"
}, Pe = { class: "gx-barcode-scanner__input-wrapper" }, Fe = ["placeholder"], qe = ["disabled"], Le = {
key: 1,
class: "gx-barcode-scanner__error"
}, Ge = /* @__PURE__ */ Vue.defineComponent({
__name: "GxBarcodeScanner",
props: {
pluginVars: {},
directScan: { type: Boolean, default: !1 },
autoInit: { type: Boolean, default: !0 },
showManualInput: { type: Boolean, default: !1 }
},
emits: ["user-scan", "stage-change", "scan-error"],
setup(d, { emit: c }) {
const r = d, l = c, e = Vue.ref(!1);
Vue.ref(!1);
const o = Vue.ref(r.pluginVars.default_option || "scan_code"), u = Vue.ref(""), t = Vue.ref(null), n = Vue.ref(), g = Vue.ref(), _ = Vue.computed(() => r.showManualInput || r.pluginVars.show_manual_input), a = () => {
e.value = !0, t.value = null, C();
}, s = () => {
r.autoInit ? l("stage-change", -1) : e.value = !1, T();
}, m = (y) => {
o.value !== y && (s(), o.value = y, t.value = null);
}, p = (y) => {
(y.code === "Enter" || y.code === "NumpadEnter") && (y.preventDefault(), V());
}, V = () => {
if (!u.value.trim()) return;
const y = u.value.trim();
l("user-scan", y), u.value = "";
};
let x = !1;
const C = async () => {
if (n.value)
try {
const y = document.createElement("video");
y.autoplay = !0, y.muted = !0, y.playsInline = !0;
const b = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: r.pluginVars.facing_mode || "environment"
}
});
y.srcObject = b, n.value.appendChild(y), x = !0;
} catch (y) {
console.error("Camera access denied:", y), t.value = "Camera access is required for scanning";
}
}, T = () => {
if (!n.value) return;
const y = n.value.querySelector("video");
y != null && y.srcObject && (y.srcObject.getTracks().forEach((I) => I.stop()), y.srcObject = null), n.value.innerHTML = "", x = !1;
};
return Vue.onMounted(() => {
r.autoInit && a();
}), Vue.onBeforeUnmount(() => {
T();
}), (y, b) => (Vue.openBlock(), Vue.createElementBlock("div", Ie, [
e.value && y.pluginVars.instructions ? (Vue.openBlock(), Vue.createElementBlock("h6", Me, Vue.toDisplayString(y.pluginVars.instructions), 1)) : Vue.createCommentVNode("", !0),
Vue.withDirectives(Vue.createElementVNode("div", {
ref_key: "interactiveElement",
ref: n,
class: "gx-barcode-scanner__video"
}, null, 512), [
[Vue.vShow, e.value]
]),
e.value ? (Vue.openBlock(), Vue.createElementBlock("button", {
key: 1,
onClick: s,
class: "gx-barcode-scanner__back-button"
}, Vue.toDisplayString(y.pluginVars.back_text || "Back"), 1)) : (Vue.openBlock(), Vue.createElementBlock(Vue.Fragment, { key: 2 }, [
Vue.createElementVNode("div", ze, [
Vue.createElementVNode("button", {
class: Vue.normalizeClass(["gx-barcode-scanner__option gx-barcode-scanner__option--qr", {
"gx-barcode-scanner__option--active": o.value === "scan_code",
"gx-barcode-scanner__option--inactive": o.value !== "scan_code"
}]),
onClick: a
}, [
b[2] || (b[2] = Vue.createElementVNode("svg", {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 448 512",
class: "gx-barcode-scanner__icon"
}, [
Vue.createElementVNode("path", { d: "M0 80C0 53.5 21.5 32 48 32h96c26.5 0 48 21.5 48 48v96c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80zM64 96v64h64V96H64zM0 336c0-26.5 21.5-48 48-48h96c26.5 0 48 21.5 48 48v96c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V336zm64 16v64h64V352H64zM304 32h96c26.5 0 48 21.5 48 48v96c0 26.5-21.5 48-48 48H304c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48zm80 64H320v64h64V96zM256 304c0-8.8 7.2-16 16-16h64c8.8 0 16 7.2 16 16s7.2 16 16 16h32c8.8 0 16-7.2 16-16s7.2-16 16-16s16 7.2 16 16v96c0 8.8-7.2 16-16 16H368c-8.8 0-16-7.2-16-16s-7.2-16-16-16s-16 7.2-16 16v64c0 8.8-7.2 16-16 16H272c-8.8 0-16-7.2-16-16V304zM368 480a16 16 0 1 1 0-32 16 16 0 1 1 0 32zm64 0a16 16 0 1 1 0-32 16 16 0 1 1 0 32z" })
], -1)),
Vue.createElementVNode("span", null, Vue.toDisplayString(y.pluginVars.scan_code_text || "Scan Code"), 1)
], 2),
_.value ? (Vue.openBlock(), Vue.createElementBlock("button", {
key: 0,
class: Vue.normalizeClass(["gx-barcode-scanner__option gx-barcode-scanner__option--manual", {
"gx-barcode-scanner__option--active": o.value === "sign_in",
"gx-barcode-scanner__option--inactive": o.value !== "sign_in"
}]),
onClick: b[0] || (b[0] = (I) => m("sign_in"))
}, [
Vue.createElementVNode("span", null, Vue.toDisplayString(y.pluginVars.manual_input_text || "Manual Input"), 1)
], 2)) : Vue.createCommentVNode("", !0)
]),
o.value === "sign_in" ? (Vue.openBlock(), Vue.createElementBlock("div", Te, [
Vue.createElementVNode("div", Pe, [
Vue.withDirectives(Vue.createElementVNode("input", {
ref_key: "manualInput",
ref: g,
"onUpdate:modelValue": b[1] || (b[1] = (I) => u.value = I),
type: "text",
class: "gx-barcode-scanner__input",
placeholder: y.pluginVars.input_placeholder || "Enter code manually",
onKeydown: p
}, null, 40, Fe), [
[Vue.vModelText, u.value]
])
]),
Vue.createElementVNode("button", {
onClick: V,
disabled: !u.value.trim(),
class: "gx-barcode-scanner__submit-button"
}, Vue.toDisplayString(y.pluginVars.submit_text || "Submit"), 9, qe)
])) : Vue.createCommentVNode("", !0),
t.value ? (Vue.openBlock(), Vue.createElementBlock("div", Le, Vue.toDisplayString(t.value), 1)) : Vue.createCommentVNode("", !0)
], 64))
]));
}
}), Re = /* @__PURE__ */ z(Ge, [["__scopeId", "data-v-4109ef44"]]), Ue = { class: "gx-countdown__display" }, Ae = {
key: 0,
class: "gx-countdown__progress"
}, Oe = /* @__PURE__ */ Vue.defineComponent({
__name: "GxCountdown",
props: {
duration: {},
autoStart: { type: Boolean, default: !0 },
showProgress: { type: Boolean, default: !0 },
format: { default: "mm:ss" }
},
emits: ["finished", "tick", "started", "stopped"],
setup(d, { expose: c, emit: r }) {
const l = d, e = r, o = Vue.ref(l.duration), u = Vue.ref(!1), t = Vue.ref(!1);
let n = null;
const g = Vue.computed(() => {
const V = Math.max(0, o.value);
switch (l.format) {
case "ss":
return V.toString().padStart(2, "0");
case "hh:mm:ss":
const x = Math.floor(V / 3600), C = Math.floor(V % 3600 / 60), T = V % 60;
return `${x.toString().padStart(2, "0")}:${C.toString().padStart(2, "0")}:${T.toString().padStart(2, "0")}`;
case "mm:ss":
default:
const y = Math.floor(V / 60), b = V % 60;
return `${y.toString().padStart(2, "0")}:${b.toString().padStart(2, "0")}`;
}
}), _ = Vue.computed(() => (l.duration - o.value) / l.duration * 100), a = () => {
u.value || t.value || (u.value = !0, e("started"), n = setInterval(() => {
o.value--, e("tick", o.value), o.value <= 0 && p();
}, 1e3));
}, s = () => {
u.value && (u.value = !1, n && (clearInterval(n), n = null), e("stopped"));
}, m = () => {
s(), o.value = l.duration, t.value = !1;
}, p = () => {
s(), t.value = !0, o.value = 0, e("finished");
};
return Vue.onMounted(() => {
l.autoStart && a();
}), Vue.onBeforeUnmount(() => {
s();
}), c({
start: a,
stop: s,
reset: m,
finish: p,
isRunning: u,
isFinished: t,
timeRemaining: o
}), (V, x) => (Vue.openBlock(), Vue.createElementBlock("div", {
class: Vue.normalizeClass(["gx-countdown", { "gx-countdown--finished": t.value }])
}, [
Vue.createElementVNode("div", Ue, Vue.toDisplayString(g.value), 1),
V.showProgress ? (Vue.openBlock(), Vue.createElementBlock("div", Ae, [
Vue.createElementVNode("div", {
class: "gx-countdown__progress-bar",
style: Vue.normalizeStyle({ width: `${_.value}%` })
}, null, 4)
])) : Vue.createCommentVNode("", !0)
], 2));
}
}), He = /* @__PURE__ */ z(Oe, [["__scopeId", "data-v-16c319f6"]]), We = /* @__PURE__ */ Vue.defineComponent({
__name: "GxThemeWrapper",
props: {
theme: {},
applyGlobalStyles: { type: Boolean, default: !0 }
},
setup(d) {
const c = d, r = Vue.computed(() => {
var o, u, t, n;
if (!c.theme) return {};
const e = {};
return (o = c.theme) != null && o.background_color && (e.backgroundColor = (u = c.theme) == null ? void 0 : u.background_color), (t = c.theme) != null && t.text_color && (e.color = (n = c.theme) == null ? void 0 : n.text_color), Object.keys(c.theme).forEach((g) => {
typeof c.theme[g] == "string" && g.includes("color") && (e[`--gx-${g.replace(/_/g, "-")}`] = c.theme[g]);
}), e;
}), l = Vue.computed(() => {
var o, u;
const e = [];
return (o = c.theme) != null && o.dark_mode ? e.push("gx-theme--dark") : e.push("gx-theme--light"), (u = c.theme) != null && u.high_contrast && e.push("gx-theme--high-contrast"), e;
});
return Vue.watch(
() => c.theme,
(e) => {
if (!c.applyGlobalStyles || !e) return;
const o = "gx-global-theme-styles";
let u = document.getElementById(o);
u || (u = document.createElement("style"), u.id = o, document.head.appendChild(u));
const t = Object.keys(e).filter((n) => typeof e[n] == "string" && n.includes("color")).map((n) => `--gx-${n.replace(/_/g, "-")}: ${e[n]};`).join(`
`);
u.textContent = `
:root {
${t}
}
.gx-theme--dark {
color-scheme: dark;
}
.gx-theme--light {
color-scheme: light;
}
.gx-theme--high-contrast {
filter: contrast(1.5);
}
`;
},
{ immediate: !0 }
), (e, o) => (Vue.openBlock(), Vue.createElementBlock("div", {
class: Vue.normalizeClass(["gx-theme-wrapper", l.value]),
style: Vue.normalizeStyle(r.value)
}, [
Vue.renderSlot(e.$slots, "default", {}, void 0, !0)
], 6));
}
}), je = /* @__PURE__ */ z(We, [["__scopeId", "data-v-65b7330e"]]), Ye = { class: "gx-page-start__inner" }, Qe = { class: "gx-page-start__header" }, Xe = ["src"], Ke = { class: "gx-page-start__title" }, Je = { class: "gx-page-start__subtitle" }, Ze = { class: "gx-page-start__description" }, et = /* @__PURE__ */ Vue.defineComponent({
__name: "GxPageStart",
props: {
stringsList: {},
pluginVars: {},
theme: {}
},
emits: ["stage-change"],
setup(d) {
return (c, r) => (Vue.openBlock(), Vue.createElementBlock("div", {
class: "gx-page-start",
onClick: r[0] || (r[0] = (l) => c.$emit("stage-change", 1))
}, [
Vue.createElementVNode("div", Ye, [
Vue.createElementVNode("div", Qe, [
c.theme.logo_image ? (Vue.openBlock(), Vue.createElementBlock("img", {
key: 0,
src: c.theme.logo_image,
class: "gx-page-start__logo",
alt: "Logo"
}, null, 8, Xe)) : Vue.createCommentVNode("", !0),
Vue.createElementVNode("h1", Ke, Vue.toDisplayString(c.stringsList.line_1), 1),
Vue.createElementVNode("h2", Je, Vue.toDisplayString(c.stringsList.line_2), 1)
]),
Vue.createElementVNode("h4", Ze, Vue.toDisplayString(c.stringsList.line_3), 1)
])
]));
}
}), tt = /* @__PURE__ */ z(et, [["__scopeId", "data-v-ddba0c24"]]), ot = { class: "gx-page-instructions" }, nt = { class: "gx-page-instructions__inner" }, at = { class: "gx-page-instructions__header" }, st = ["src"], lt = { class: "gx-page-instructions__title" }, rt = { class: "gx-page-instructions__subtitle" }, ut = {
key: 0,
class: "gx-page-instructions__registration"
}, it = { class: "gx-page-instructions__registration-instructions" }, ct = {
key: 0,
class: "gx-page-instructions__input-field"
}, dt = {
key: 0,
class: "gx-page-instructions__error"
}, mt = ["disabled"], gt = /* @__PURE__ */ Vue.defineComponent({
__name: "GxPageInstructions",
props: {
pluginVars: {},
theme: {}
},
emits: ["stage-change", "user-found"],
setup(d, { emit: c }) {
const r = d, l = c, e = Vue.ref({
name: "",
email: ""
}), o = Vue.ref(!1), u = Vue.ref(null), t = Vue.computed(
() => r.pluginVars.attendee_options === "registration" && (o.value || e.value.email === "" && r.pluginVars.registrationFields !== "name" || e.value.name === "" && r.pluginVars.registrationFields !== "email")
), n = (s) => {
const p = s.target.previousElementSibling;
p == null || p.focus();
}, g = async () => {
o.value = !0;
try {
r.pluginVars.attendee_options !== "registration" ? l("stage-change", 1) : r.pluginVars.registrationFields === "name" ? l("user-found", {
first_name: e.value.name
}) : await _({
first_name: e.value.name,
last_name: "",
contact_email: e.value.email.toLowerCase()
});
} catch (s) {
console.error(s), o.value = !1;
}
}, _ = async (s = {}) => {
try {
console.log("Register user:", s), l("user-found", s);
} catch (m) {
console.error(m), u.value = m == null ? void 0 : m.message, o.value = !1;
}
}, a = (s) => {
!t.value && (s.code === "Enter" || s.code === "NumpadEnter") && g();
};
return Vue.onMounted(() => {
r.pluginVars.attendee_options !== "scanning" && document.body.addEventListener("keydown", a);
}), Vue.onBeforeUnmount(() => {
r.pluginVars.attendee_options !== "scanning" && document.body.removeEventListener("keydown", a);
}), (s, m) => {
var V, x;
const p = Vue.resolveComponent("GxBarcodeScanner");
return Vue.openBlock(), Vue.createElementBlock("div", ot, [
Vue.createElementVNode("div", nt, [
Vue.createElementVNode("div", at, [
s.theme.logo_image ? (Vue.openBlock(), Vue.createElementBlock("img", {
key: 0,
src: s.theme.logo_image,
class: "gx-page-instructions__logo",
alt: "Logo"
}, null, 8, st)) : Vue.createCommentVNode("", !0),
Vue.createElementVNode("h1", lt, Vue.toDisplayString(s.pluginVars.line_1), 1),
Vue.createElementVNode("h2", rt, Vue.toDisplayString(s.pluginVars.line_2), 1)
]),
s.pluginVars.attendee_options === "registration" ? (Vue.openBlock(), Vue.createElementBlock("div", ut, [
Vue.createElementVNode("h4", it, Vue.toDisplayString(s.pluginVars.registration_instructions), 1),
s.pluginVars.registrationFields !== "email" ? (Vue.openBlock(), Vue.createElementBlock("div", ct, [
Vue.withDirectives(Vue.createElementVNode("input", {
"onUpdate:modelValue": m[0] || (m[0] = (C) => e.value.name = C),
name: "name",
id: "name",
type: "text",
class: Vue.normalizeClass([{ "has-text": e.value.name.length }, "gx-page-instructions__input"])
}, null, 2), [
[Vue.vModelText, e.value.name]
]),
e.value.name === "" ? (Vue.openBlock(), Vue.createElementBlock("div", {
key: 0,
onClick: n,
class: "gx-page-instructions__placeholder"
}, " Name ")) : Vue.createCommentVNode("", !0)
])) : Vue.createCommentVNode("", !0),
s.pluginVars.registrationFields !== "name" ? (Vue.openBlock(), Vue.createElementBlock(Vue.Fragment, { key: 1 }, [
(V = u.value) != null && V.includes("field must be a valid") ? (Vue.openBlock(), Vue.createElementBlock("div", dt, [
m[4] || (m[4] = Vue.createElementVNode("svg", {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 512 512",
class: "gx-page-instructions__error-icon"
}, [
Vue.createElementVNode("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336l24 0 0-64-24 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l48 0c13.3 0 24 10.7 24 24l0 88 8 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z" })
], -1)),
Vue.createTextVNode(" " + Vue.toDisplayString(s.pluginVars.invalid_email_warning), 1)
])) : Vue.createCommentVNode("", !0),
Vue.createElementVNode("div", {
class: Vue.normalizeClass(["gx-page-instructions__input-field", {
"gx-page-instructions__input-field--error": (x = u.value) == null ? void 0 : x.includes("field must be a valid")
}])
}, [
Vue.withDirectives(Vue.createElementVNode("input", {
"onUpdate:modelValue": m[1] || (m[1] = (C) => e.value.email = C),
name: "email",
id: "email",
type: "email",
class: Vue.normalizeClass([{ "has-text": e.value.email.length }, "gx-page-instructions__input"])
}, null, 2), [
[Vue.vModelText, e.value.email]
]),
e.value.email === "" ? (Vue.openBlock(), Vue.createElementBlock("div", {
key: 0,
onClick: n,
class: "gx-page-instructions__placeholder"
}, " Email ")) : Vue.createCommentVNode("", !0)
], 2)
], 64)) : Vue.createCommentVNode("", !0)
])) : s.pluginVars.attendee_options === "scanning" || s.pluginVars.attendee_options === "scan" ? (Vue.openBlock(), Vue.createBlock(p, {
key: 1,
onUserScan: m[2] || (m[2] = (C) => s.$emit("user-found", C)),
onStageChange: m[3] || (m[3] = (C) => s.$emit("stage-change", -1)),
"plugin-vars": s.pluginVars.barcodeVars,
"register-function": _,
"auto-init": s.pluginVars.attendee_options === "scan"
}, null, 8, ["plugin-vars", "auto-init"])) : Vue.createCommentVNode("", !0),
s.pluginVars.attendee_options !== "scanning" && s.pluginVars.attendee_options !== "scan" ? (Vue.openBlock(), Vue.createElementBlock("button", {
key: 2,
class: "gx-page-instructions__button",
onClick: g,
disabled: t.value
}, Vue.toDisplayString(s.pluginVars.button_text), 9, mt)) : Vue.createCommentVNode("", !0)
])
]);
};
}
}), pt = /* @__PURE__ */ z(gt, [["__scopeId", "data-v-aea16ed5"]]), Vt = { class: "gx-page-prompt" }, _t = { class: "gx-page-prompt__inner" }, vt = { class: "gx-page-prompt__header" }, ht = ["src"], ft = { class: "gx-page-prompt__title" }, kt = {
key: 1,
class: "gx-page-prompt__subtitle"
}, yt = { class: "gx-page-prompt__content" }, bt = ["innerHTML"], xt = {
key: 0,
class: "gx-page-prompt__timer"
}, Et = { class: "gx-page-prompt__timer-value" }, Bt = {
key: 1,
class: "gx-page-prompt__input-section"
}, $t = {
key: 0,
class: "gx-page-prompt__input-label"
}, Ct = ["placeholder", "maxlength"], wt = ["placeholder", "maxlength"], Nt = {
key: 3,
class: "gx-page-prompt__char-count"
}, St = { class: "gx-page-prompt__actions" }, Dt = ["disabled"], It = /* @__PURE__ */ Vue.defineComponent({
__name: "GxPagePrompt",
props: {
pluginVars: {},
theme: {},
promptText: {},
inputType: { default: null },
inputLabel: {},
inputPlaceholder: { default: "Enter your response..." },
inputRequired: { type: Boolean, default: !1 },
maxInputLength: { default: 500 },
showTimer: { type: Boolean, default: !1 },
timerDuration: { default: 60 },
showBackButton: { type: Boolean, default: !1 },
showSkipButton: { type: Boolean, default: !1 }
},
emits: ["continue", "back", "skip", "timer-expired"],
setup(d, { emit: c }) {
const r = d, l = c, e = Vue.ref(""), o = Vue.ref(r.timerDuration);
let u = null;
const t = Vue.computed(() => r.promptText || r.pluginVars.prompt_content || r.pluginVars.line_3 || "Please follow the instructions below."), n = Vue.computed(() => {
const a = Math.floor(o.value / 60), s = o.value % 60;
return `${a}:${s.toString().padStart(2, "0")}`;
}), g = () => {
l("continue", e.value);
}, _ = () => {
r.showTimer && (u = setInterval(() => {
o.value--, o.value <= 0 && (clearInterval(u), l("timer-expired"));
}, 1e3));
};
return Vue.onMounted(() => {
r.showTimer && _();
}), Vue.onUnmounted(() => {
u && clearInterval(u);
}), (a, s) => (Vue.openBlock(), Vue.createElementBlock("div", Vt, [
Vue.createElementVNode("div", _t, [
Vue.createElementVNode("div", vt, [
a.theme.logo_image ? (Vue.openBlock(), Vue.createElementBlock("img", {
key: 0,
src: a.theme.logo_image,
class: "gx-page-prompt__logo",
alt: "Logo"
}, null, 8, ht)) : Vue.createCommentVNode("", !0),
Vue.createElementVNode("h1", ft, Vue.toDisplayString(a.pluginVars.line_1 || "Prompt"), 1),
a.pluginVars.line_2 ? (Vue.openBlock(), Vue.createElementBlock("h2", kt, Vue.toDisplayString(a.pluginVars.line_2), 1)) : Vue.createCommentVNode("", !0)
]),
Vue.createElementVNode("div", yt, [
Vue.createElementVNode("div", {
class: "gx-page-prompt__prompt-text",
innerHTML: t.value
}, null, 8, bt),
a.showTimer && o.value ? (Vue.openBlock(), Vue.createElementBlock("div", xt, [
s[4] || (s[4] = Vue.createElementVNode("div", { class: "gx-page-prompt__timer-label" }, "Time remaining:", -1)),
Vue.createElementVNode("div", Et, Vue.toDisplayString(n.value), 1)
])) : Vue.createCommentVNode("", !0),
a.inputType ? (Vue.openBlock(), Vue.createElementBlock("div", Bt, [
a.inputLabel ? (Vue.openBlock(), Vue.createElementBlock("label", $t, Vue.toDisplayString(a.inputLabel), 1)) : Vue.createCommentVNode("", !0),
a.inputType === "textarea" ? Vue.withDirectives((Vue.openBlock(), Vue.createElementBlock("textarea", {
key: 1,
"onUpdate:modelValue": s[0] || (s[0] = (m) => e.value = m),
placeholder: a.inputPlaceholder,
class: "gx-page-prompt__textarea",
maxlength: a.maxInputLength
}, null, 8, Ct)), [
[Vue.vModelText, e.value]
]) : a.inputType === "text" ? Vue.withDirectives((Vue.openBlock(), Vue.createElementBlock("input", {
key: 2,
"onUpdate:modelValue": s[1] || (s[1] = (m) => e.value = m),
placeholder: a.inputPlaceholder,
class: "gx-page-prompt__text-input",
maxlength: a.maxInputLength
}, null, 8, wt)), [
[Vue.vModelText, e.value]
]) : Vue.createCommentVNode("", !0),
e.value.length > 0 && a.ma