@genex-ai/embed-sdk 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-BWJ2FVCH.js → chunk-EEOKYBXG.js} +143 -25
- package/dist/index.js +1 -1
- package/dist/sentry.js +1 -1
- package/package.json +1 -1
|
@@ -25,6 +25,7 @@ var authWaiters = [];
|
|
|
25
25
|
var playerWaiters = [];
|
|
26
26
|
var overlayEl = null;
|
|
27
27
|
var popoverEl = null;
|
|
28
|
+
var popoverMinimizeTimer;
|
|
28
29
|
var pendingPlayerSave;
|
|
29
30
|
var hasPendingPlayerSave = false;
|
|
30
31
|
var pendingScores = /* @__PURE__ */ new Map();
|
|
@@ -621,19 +622,91 @@ function enterBlocked() {
|
|
|
621
622
|
}
|
|
622
623
|
var OVERLAY_TEXT = {
|
|
623
624
|
// Delayed (text grace period): most connects finish before the text ever
|
|
624
|
-
// shows — a sub-second text flash reads as a glitch.
|
|
625
|
-
|
|
626
|
-
|
|
625
|
+
// shows — a sub-second text flash reads as a glitch. `wordmark` states show
|
|
626
|
+
// GENEX in the breathing decrypt loop instead of an instruction.
|
|
627
|
+
connecting: { title: "GENEX", wordmark: true },
|
|
628
|
+
// Same treatment as `connecting` so the whole standalone bounce (gate ->
|
|
627
629
|
// /play/authorize -> gate) reads as ONE continuous screen. Still neutral:
|
|
628
630
|
// the automatic bounce precedes GUEST play as often as sign-in.
|
|
629
|
-
redirecting: { title: "
|
|
631
|
+
redirecting: { title: "GENEX", wordmark: true },
|
|
630
632
|
// Terminal states need the visitor to act — text shows immediately.
|
|
631
633
|
"blocked-standalone": { title: "Sign in to play", button: "Sign in", instant: true },
|
|
632
634
|
"blocked-embedded": { title: "Sign in on the Genex dashboard to continue", instant: true }
|
|
633
635
|
};
|
|
634
|
-
var OVERLAY_FONT_URL = "https://cdn.genex.technology/fonts/
|
|
635
|
-
var OVERLAY_FONT_STACK = "'Geist',
|
|
636
|
+
var OVERLAY_FONT_URL = "https://cdn.genex.technology/fonts/GeistMono-variable.woff2";
|
|
637
|
+
var OVERLAY_FONT_STACK = "'Geist Mono',ui-monospace,SFMono-Regular,Menlo,monospace";
|
|
636
638
|
var overlayFontRequested = false;
|
|
639
|
+
var SCRAMBLE_NOISE = "!<>-_/[]{}=+*^?#$%&@";
|
|
640
|
+
var SCRAMBLE_TICK_MS = 50;
|
|
641
|
+
var SCRAMBLE_SETTLE_TICKS = 10;
|
|
642
|
+
var WORDMARK_LOOP_PHASES = [
|
|
643
|
+
{ name: "churn", ticks: 5 },
|
|
644
|
+
{ name: "settle", ticks: 10 },
|
|
645
|
+
{ name: "hold", ticks: 12 },
|
|
646
|
+
{ name: "dissolve", ticks: 8 }
|
|
647
|
+
];
|
|
648
|
+
function scrambleNoise(length) {
|
|
649
|
+
let out = "";
|
|
650
|
+
for (let i = 0; i < length; i++) {
|
|
651
|
+
out += SCRAMBLE_NOISE[Math.floor(Math.random() * SCRAMBLE_NOISE.length)];
|
|
652
|
+
}
|
|
653
|
+
return out;
|
|
654
|
+
}
|
|
655
|
+
function scrambleStatic() {
|
|
656
|
+
try {
|
|
657
|
+
const w = win();
|
|
658
|
+
if (!w || typeof w.matchMedia !== "function") return true;
|
|
659
|
+
return w.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
660
|
+
} catch {
|
|
661
|
+
return true;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
function scrambleIn(el, text) {
|
|
665
|
+
if (scrambleStatic()) {
|
|
666
|
+
el.textContent = text;
|
|
667
|
+
return () => {
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
let i = 0;
|
|
671
|
+
el.textContent = scrambleNoise(text.length);
|
|
672
|
+
const id = setInterval(() => {
|
|
673
|
+
i++;
|
|
674
|
+
if (i >= SCRAMBLE_SETTLE_TICKS) {
|
|
675
|
+
el.textContent = text;
|
|
676
|
+
clearInterval(id);
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
const lock = Math.floor(i / SCRAMBLE_SETTLE_TICKS * text.length);
|
|
680
|
+
el.textContent = text.slice(0, lock) + scrambleNoise(text.length - lock);
|
|
681
|
+
}, SCRAMBLE_TICK_MS);
|
|
682
|
+
return () => clearInterval(id);
|
|
683
|
+
}
|
|
684
|
+
function wordmarkLoop(el, text) {
|
|
685
|
+
if (scrambleStatic()) {
|
|
686
|
+
el.textContent = text;
|
|
687
|
+
return () => {
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
let phase = 0;
|
|
691
|
+
let i = 0;
|
|
692
|
+
const frame = () => {
|
|
693
|
+
const p = WORDMARK_LOOP_PHASES[phase];
|
|
694
|
+
let kept;
|
|
695
|
+
if (p.name === "churn") kept = 0;
|
|
696
|
+
else if (p.name === "settle") kept = Math.floor(i / p.ticks * text.length);
|
|
697
|
+
else if (p.name === "hold") kept = text.length;
|
|
698
|
+
else kept = text.length - Math.floor(i / p.ticks * text.length);
|
|
699
|
+
el.textContent = text.slice(0, kept) + scrambleNoise(text.length - kept);
|
|
700
|
+
i++;
|
|
701
|
+
if (i >= p.ticks) {
|
|
702
|
+
i = 0;
|
|
703
|
+
phase = (phase + 1) % WORDMARK_LOOP_PHASES.length;
|
|
704
|
+
}
|
|
705
|
+
};
|
|
706
|
+
frame();
|
|
707
|
+
const id = setInterval(frame, SCRAMBLE_TICK_MS);
|
|
708
|
+
return () => clearInterval(id);
|
|
709
|
+
}
|
|
637
710
|
function ensureOverlayFont(d) {
|
|
638
711
|
if (overlayFontRequested) return;
|
|
639
712
|
overlayFontRequested = true;
|
|
@@ -641,7 +714,7 @@ function ensureOverlayFont(d) {
|
|
|
641
714
|
const FF = win()?.FontFace;
|
|
642
715
|
const fonts = d.fonts;
|
|
643
716
|
if (!FF || !fonts?.add) return;
|
|
644
|
-
const face = new FF("Geist", `url(${OVERLAY_FONT_URL}) format('woff2')`, {
|
|
717
|
+
const face = new FF("Geist Mono", `url(${OVERLAY_FONT_URL}) format('woff2')`, {
|
|
645
718
|
weight: "100 900",
|
|
646
719
|
display: "swap"
|
|
647
720
|
});
|
|
@@ -664,7 +737,7 @@ function removeOverlay(instant = false) {
|
|
|
664
737
|
const el = overlayEl;
|
|
665
738
|
overlayEl = null;
|
|
666
739
|
if (!el) return;
|
|
667
|
-
el.
|
|
740
|
+
el.stopText();
|
|
668
741
|
const root = el.root;
|
|
669
742
|
if (instant || !root.style) {
|
|
670
743
|
root.remove?.();
|
|
@@ -686,12 +759,12 @@ function buildOverlay(d) {
|
|
|
686
759
|
ensureOverlayFont(d);
|
|
687
760
|
const root = d.createElement("div");
|
|
688
761
|
root.setAttribute("data-genex-embed-overlay", "");
|
|
689
|
-
root.style.cssText = `position:fixed;inset:0;z-index:2147483647;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:
|
|
762
|
+
root.style.cssText = `position:fixed;inset:0;z-index:2147483647;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:14px;background:#000;color:#fff;font-family:${OVERLAY_FONT_STACK};text-align:center;pointer-events:auto;user-select:none`;
|
|
690
763
|
const title = d.createElement("div");
|
|
691
|
-
title.style.cssText = "font-size:
|
|
764
|
+
title.style.cssText = "font-size:13px;font-weight:400;line-height:1.3;padding:0 24px;opacity:0;min-height:1.3em;font-variant-ligatures:none";
|
|
692
765
|
root.appendChild(title);
|
|
693
766
|
const button = d.createElement("button");
|
|
694
|
-
button.style.cssText = "font-size:
|
|
767
|
+
button.style.cssText = "font-family:inherit;font-size:13px;font-weight:500;line-height:1.3;padding:8px 22px;border-radius:9px;border:none;cursor:pointer;background:#4b60bf;color:#fff;display:none";
|
|
695
768
|
button.addEventListener("mouseenter", () => {
|
|
696
769
|
button.style.background = "#3f51a8";
|
|
697
770
|
});
|
|
@@ -712,29 +785,37 @@ function buildOverlay(d) {
|
|
|
712
785
|
if (d.body) mount();
|
|
713
786
|
else d.addEventListener?.("DOMContentLoaded", mount);
|
|
714
787
|
let textTimer;
|
|
715
|
-
|
|
788
|
+
let cancelScramble;
|
|
789
|
+
const stopText = () => {
|
|
716
790
|
if (textTimer !== void 0) {
|
|
717
791
|
clearTimeout(textTimer);
|
|
718
792
|
textTimer = void 0;
|
|
719
793
|
}
|
|
794
|
+
if (cancelScramble) {
|
|
795
|
+
cancelScramble();
|
|
796
|
+
cancelScramble = void 0;
|
|
797
|
+
}
|
|
720
798
|
};
|
|
721
799
|
return {
|
|
722
800
|
root,
|
|
723
|
-
|
|
801
|
+
stopText,
|
|
724
802
|
setContent(kind) {
|
|
725
803
|
const text = OVERLAY_TEXT[kind];
|
|
726
|
-
|
|
804
|
+
stopText();
|
|
727
805
|
title.textContent = text.title;
|
|
728
|
-
|
|
729
|
-
|
|
806
|
+
title.style.letterSpacing = text.wordmark ? "0.22em" : "";
|
|
807
|
+
title.style.marginRight = text.wordmark ? "-0.22em" : "";
|
|
808
|
+
const reveal = () => {
|
|
730
809
|
title.style.opacity = "1";
|
|
810
|
+
cancelScramble = text.wordmark ? wordmarkLoop(title, text.title) : scrambleIn(title, text.title);
|
|
811
|
+
};
|
|
812
|
+
if (text.instant || overlayTextDelayMs <= 0) {
|
|
813
|
+
reveal();
|
|
731
814
|
} else {
|
|
732
|
-
title.style.transition = "";
|
|
733
815
|
title.style.opacity = "0";
|
|
734
816
|
textTimer = setTimeout(() => {
|
|
735
817
|
textTimer = void 0;
|
|
736
|
-
|
|
737
|
-
title.style.opacity = "1";
|
|
818
|
+
reveal();
|
|
738
819
|
}, overlayTextDelayMs);
|
|
739
820
|
}
|
|
740
821
|
button.style.display = text.button ? "inline-block" : "none";
|
|
@@ -752,6 +833,10 @@ function showGuestPopover() {
|
|
|
752
833
|
}
|
|
753
834
|
}
|
|
754
835
|
function removeGuestPopover() {
|
|
836
|
+
if (popoverMinimizeTimer !== void 0) {
|
|
837
|
+
clearTimeout(popoverMinimizeTimer);
|
|
838
|
+
popoverMinimizeTimer = void 0;
|
|
839
|
+
}
|
|
755
840
|
try {
|
|
756
841
|
const root = popoverEl?.root;
|
|
757
842
|
root?.remove?.();
|
|
@@ -761,15 +846,31 @@ function removeGuestPopover() {
|
|
|
761
846
|
}
|
|
762
847
|
function buildGuestPopover(d) {
|
|
763
848
|
ensureOverlayFont(d);
|
|
849
|
+
let mobile = false;
|
|
850
|
+
try {
|
|
851
|
+
const w = win();
|
|
852
|
+
const nav = w?.navigator;
|
|
853
|
+
if (w && nav) {
|
|
854
|
+
const coarse = w.matchMedia?.("(pointer: coarse)").matches ?? false;
|
|
855
|
+
const touch = (nav.maxTouchPoints ?? 0) > 1;
|
|
856
|
+
const mobileUA = nav.userAgentData ? nav.userAgentData.mobile : /Mobi|Android/i.test(nav.userAgent ?? "");
|
|
857
|
+
mobile = touch && coarse || mobileUA;
|
|
858
|
+
}
|
|
859
|
+
} catch {
|
|
860
|
+
}
|
|
764
861
|
const root = d.createElement("div");
|
|
765
862
|
root.setAttribute("data-genex-guest-popover", "");
|
|
766
|
-
root.style.cssText =
|
|
863
|
+
root.style.cssText = "position:fixed;top:calc(12px + env(safe-area-inset-top));right:calc(12px + env(safe-area-inset-right));z-index:2147483646;display:flex;justify-content:flex-end;pointer-events:none";
|
|
864
|
+
const card = d.createElement("div");
|
|
865
|
+
card.style.cssText = `display:flex;align-items:center;border-radius:12px;background:rgba(0,0,0,0.85);color:#fff;font-family:${OVERLAY_FONT_STACK};box-shadow:0 4px 24px rgba(0,0,0,0.4);pointer-events:auto;user-select:none;` + (mobile ? "gap:8px;padding:8px 8px 8px 12px;font-size:12px;max-width:calc(100vw - 88px)" : "gap:12px;padding:10px 12px 10px 16px;font-size:13px");
|
|
866
|
+
root.appendChild(card);
|
|
767
867
|
const text = d.createElement("span");
|
|
768
|
-
text.textContent = user?.name ? `Playing as ${user.name} \u2014 sign in to save progress` : "Sign in to save progress";
|
|
769
|
-
|
|
868
|
+
text.textContent = !mobile && user?.name ? `Playing as ${user.name} \u2014 sign in to save progress` : "Sign in to save progress";
|
|
869
|
+
if (mobile) text.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap";
|
|
870
|
+
card.appendChild(text);
|
|
770
871
|
const signIn = d.createElement("button");
|
|
771
872
|
signIn.textContent = "Sign in";
|
|
772
|
-
signIn.style.cssText = "font-
|
|
873
|
+
signIn.style.cssText = "font-family:inherit;font-weight:500;border-radius:9px;border:none;cursor:pointer;background:#4b60bf;color:#fff;" + (mobile ? "font-size:12px;padding:5px 12px" : "font-size:13px;padding:6px 16px");
|
|
773
874
|
signIn.addEventListener("mouseenter", () => {
|
|
774
875
|
signIn.style.background = "#3f51a8";
|
|
775
876
|
});
|
|
@@ -783,7 +884,7 @@ function buildGuestPopover(d) {
|
|
|
783
884
|
clearRetryFlag();
|
|
784
885
|
void redirectToAuthorize(w);
|
|
785
886
|
});
|
|
786
|
-
|
|
887
|
+
card.appendChild(signIn);
|
|
787
888
|
const dismiss = d.createElement("button");
|
|
788
889
|
dismiss.textContent = "\xD7";
|
|
789
890
|
dismiss.setAttribute("aria-label", "Dismiss");
|
|
@@ -792,7 +893,24 @@ function buildGuestPopover(d) {
|
|
|
792
893
|
writePopoverDismissed();
|
|
793
894
|
removeGuestPopover();
|
|
794
895
|
});
|
|
795
|
-
|
|
896
|
+
card.appendChild(dismiss);
|
|
897
|
+
if (mobile) {
|
|
898
|
+
const chip = d.createElement("button");
|
|
899
|
+
chip.setAttribute("aria-label", "Sign in to save progress");
|
|
900
|
+
chip.style.cssText = "display:none;width:44px;height:44px;border-radius:50%;border:none;cursor:pointer;background:rgba(0,0,0,0.55);color:#fff;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);pointer-events:auto";
|
|
901
|
+
chip.innerHTML = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></svg>';
|
|
902
|
+
root.appendChild(chip);
|
|
903
|
+
const setMinimized = (v) => {
|
|
904
|
+
card.style.display = v ? "none" : "flex";
|
|
905
|
+
chip.style.display = v ? "flex" : "none";
|
|
906
|
+
};
|
|
907
|
+
popoverMinimizeTimer = setTimeout(() => setMinimized(true), 5e3);
|
|
908
|
+
card.addEventListener("pointerdown", () => {
|
|
909
|
+
if (popoverMinimizeTimer !== void 0) clearTimeout(popoverMinimizeTimer);
|
|
910
|
+
popoverMinimizeTimer = void 0;
|
|
911
|
+
});
|
|
912
|
+
chip.addEventListener("click", () => setMinimized(false));
|
|
913
|
+
}
|
|
796
914
|
const mount = () => {
|
|
797
915
|
if (d.body && !root.isConnected) d.body.appendChild(root);
|
|
798
916
|
};
|
package/dist/index.js
CHANGED
package/dist/sentry.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/embed-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Player identity + durable game state for genex games \u2014 signed-in or guest play, per-player save slots, shared world state, and soft-trust leaderboards.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|