@youidian/sdk 3.3.10 → 3.4.2
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/client.cjs +1123 -41
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +74 -4
- package/dist/client.d.ts +74 -4
- package/dist/client.js +1120 -41
- package/dist/client.js.map +1 -1
- package/dist/feedback.cjs +682 -0
- package/dist/feedback.cjs.map +1 -0
- package/dist/feedback.d.cts +38 -0
- package/dist/feedback.d.ts +38 -0
- package/dist/feedback.js +656 -0
- package/dist/feedback.js.map +1 -0
- package/dist/index.cjs +1866 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1861 -41
- package/dist/index.js.map +1 -1
- package/dist/{login-DerOcXcH.d.cts → login-Dqemys65.d.cts} +8 -4
- package/dist/{login-DerOcXcH.d.ts → login-Dqemys65.d.ts} +8 -4
- package/dist/login.cjs +334 -33
- package/dist/login.cjs.map +1 -1
- package/dist/login.d.cts +1 -1
- package/dist/login.d.ts +1 -1
- package/dist/login.js +334 -33
- package/dist/login.js.map +1 -1
- package/dist/server.cjs +87 -0
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +146 -1
- package/dist/server.d.ts +146 -1
- package/dist/server.js +87 -0
- package/dist/server.js.map +1 -1
- package/package.json +6 -1
|
@@ -21,8 +21,8 @@ declare class HostedFrameModal<TData extends HostedFrameMessage> {
|
|
|
21
21
|
close(): void;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
type LoginEventType = "LOGIN_READY" | "LOGIN_SUCCESS" | "LOGIN_CANCELLED" | "LOGIN_CLOSE" | "LOGIN_RESIZE" | "LOGIN_ERROR";
|
|
25
|
-
type LoginDisplayMode = "modal" | "popup";
|
|
24
|
+
type LoginEventType = "LOGIN_READY" | "LOGIN_SUCCESS" | "LOGIN_CANCELLED" | "LOGIN_CLOSE" | "LOGIN_RESIZE" | "LOGIN_REDIRECT_REQUIRED" | "LOGIN_ERROR";
|
|
25
|
+
type LoginDisplayMode = "auto" | "modal" | "popup" | "redirect";
|
|
26
26
|
type LoginFallbackRedirectMode = "auto" | "manual";
|
|
27
27
|
interface LoginResult {
|
|
28
28
|
avatar?: string | null;
|
|
@@ -43,6 +43,9 @@ interface LoginResult {
|
|
|
43
43
|
}
|
|
44
44
|
interface LoginEventData extends HostedFrameMessage, LoginResult {
|
|
45
45
|
type: LoginEventType;
|
|
46
|
+
attemptId?: string;
|
|
47
|
+
authUrl?: string;
|
|
48
|
+
channel?: string;
|
|
46
49
|
error?: string;
|
|
47
50
|
message?: string;
|
|
48
51
|
}
|
|
@@ -54,8 +57,8 @@ interface LoginUIOptions {
|
|
|
54
57
|
/** Optional same-origin URL used as the no-API OAuth callback landing page. */
|
|
55
58
|
callbackUrl?: string;
|
|
56
59
|
/**
|
|
57
|
-
* How to open the hosted login page. Defaults to "
|
|
58
|
-
*
|
|
60
|
+
* How to open the hosted login page. Defaults to "auto", which uses an
|
|
61
|
+
* iframe modal on desktop and redirects on mobile/embedded browsers.
|
|
59
62
|
*/
|
|
60
63
|
displayMode?: LoginDisplayMode;
|
|
61
64
|
/** Text for the fallback button shown when the iframe does not report readiness. */
|
|
@@ -142,6 +145,7 @@ declare class LoginUI extends HostedFrameModal<LoginEventData> {
|
|
|
142
145
|
private showIframeFallback;
|
|
143
146
|
private startIframeWatchdog;
|
|
144
147
|
private handleLoginEvent;
|
|
148
|
+
private openLoginRedirect;
|
|
145
149
|
private listenForLoginCallback;
|
|
146
150
|
close(): void;
|
|
147
151
|
private buildOpenContext;
|
|
@@ -21,8 +21,8 @@ declare class HostedFrameModal<TData extends HostedFrameMessage> {
|
|
|
21
21
|
close(): void;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
type LoginEventType = "LOGIN_READY" | "LOGIN_SUCCESS" | "LOGIN_CANCELLED" | "LOGIN_CLOSE" | "LOGIN_RESIZE" | "LOGIN_ERROR";
|
|
25
|
-
type LoginDisplayMode = "modal" | "popup";
|
|
24
|
+
type LoginEventType = "LOGIN_READY" | "LOGIN_SUCCESS" | "LOGIN_CANCELLED" | "LOGIN_CLOSE" | "LOGIN_RESIZE" | "LOGIN_REDIRECT_REQUIRED" | "LOGIN_ERROR";
|
|
25
|
+
type LoginDisplayMode = "auto" | "modal" | "popup" | "redirect";
|
|
26
26
|
type LoginFallbackRedirectMode = "auto" | "manual";
|
|
27
27
|
interface LoginResult {
|
|
28
28
|
avatar?: string | null;
|
|
@@ -43,6 +43,9 @@ interface LoginResult {
|
|
|
43
43
|
}
|
|
44
44
|
interface LoginEventData extends HostedFrameMessage, LoginResult {
|
|
45
45
|
type: LoginEventType;
|
|
46
|
+
attemptId?: string;
|
|
47
|
+
authUrl?: string;
|
|
48
|
+
channel?: string;
|
|
46
49
|
error?: string;
|
|
47
50
|
message?: string;
|
|
48
51
|
}
|
|
@@ -54,8 +57,8 @@ interface LoginUIOptions {
|
|
|
54
57
|
/** Optional same-origin URL used as the no-API OAuth callback landing page. */
|
|
55
58
|
callbackUrl?: string;
|
|
56
59
|
/**
|
|
57
|
-
* How to open the hosted login page. Defaults to "
|
|
58
|
-
*
|
|
60
|
+
* How to open the hosted login page. Defaults to "auto", which uses an
|
|
61
|
+
* iframe modal on desktop and redirects on mobile/embedded browsers.
|
|
59
62
|
*/
|
|
60
63
|
displayMode?: LoginDisplayMode;
|
|
61
64
|
/** Text for the fallback button shown when the iframe does not report readiness. */
|
|
@@ -142,6 +145,7 @@ declare class LoginUI extends HostedFrameModal<LoginEventData> {
|
|
|
142
145
|
private showIframeFallback;
|
|
143
146
|
private startIframeWatchdog;
|
|
144
147
|
private handleLoginEvent;
|
|
148
|
+
private openLoginRedirect;
|
|
145
149
|
private listenForLoginCallback;
|
|
146
150
|
close(): void;
|
|
147
151
|
private buildOpenContext;
|
package/dist/login.cjs
CHANGED
|
@@ -28,6 +28,91 @@ __export(login_exports, {
|
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(login_exports);
|
|
30
30
|
|
|
31
|
+
// src/environment.ts
|
|
32
|
+
function normalizeText(value) {
|
|
33
|
+
return value || "";
|
|
34
|
+
}
|
|
35
|
+
function getRuntimeInput() {
|
|
36
|
+
if (typeof navigator === "undefined") {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
const nav = navigator;
|
|
40
|
+
const coarsePointer = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(pointer: coarse)").matches : void 0;
|
|
41
|
+
return {
|
|
42
|
+
coarsePointer,
|
|
43
|
+
maxTouchPoints: nav.maxTouchPoints || 0,
|
|
44
|
+
platform: nav.platform || "",
|
|
45
|
+
standalone: nav.standalone,
|
|
46
|
+
userAgent: nav.userAgent || "",
|
|
47
|
+
userAgentDataMobile: nav.userAgentData?.mobile
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function includesAny(value, patterns) {
|
|
51
|
+
return patterns.some((pattern) => pattern.test(value));
|
|
52
|
+
}
|
|
53
|
+
function detectLoginEnvironment(input = getRuntimeInput()) {
|
|
54
|
+
const userAgent = normalizeText(input.userAgent);
|
|
55
|
+
const platform = normalizeText(input.platform);
|
|
56
|
+
const rawMaxTouchPoints = input.maxTouchPoints ?? 0;
|
|
57
|
+
const maxTouchPoints = Number.isFinite(rawMaxTouchPoints) ? Math.max(0, rawMaxTouchPoints) : 0;
|
|
58
|
+
const isCoarsePointer = input.coarsePointer === true;
|
|
59
|
+
const isTouch = maxTouchPoints > 0 || isCoarsePointer;
|
|
60
|
+
const isWeChat = /micromessenger/i.test(userAgent);
|
|
61
|
+
const isAndroid = /\bandroid\b/i.test(userAgent);
|
|
62
|
+
const hasExplicitIOSDevice = /\b(iPad|iPhone|iPod)\b/i.test(userAgent);
|
|
63
|
+
const hasMacintoshUserAgent = /\bMacintosh\b/i.test(userAgent);
|
|
64
|
+
const hasMacPlatform = /^Mac/i.test(platform);
|
|
65
|
+
const isIPadOS = !hasExplicitIOSDevice && hasMacintoshUserAgent && hasMacPlatform && typeof input.standalone !== "undefined" && maxTouchPoints > 2;
|
|
66
|
+
const isIOS = hasExplicitIOSDevice || isIPadOS;
|
|
67
|
+
const isTabletByUa = includesAny(userAgent, [
|
|
68
|
+
/\biPad\b/i,
|
|
69
|
+
/\btablet\b/i,
|
|
70
|
+
/\bplaybook\b/i,
|
|
71
|
+
/\bsilk\b(?!.*\bmobile\b)/i,
|
|
72
|
+
/\bkindle\b/i,
|
|
73
|
+
/\bnexus 7\b/i,
|
|
74
|
+
/\bnexus 9\b/i,
|
|
75
|
+
/\bxoom\b/i,
|
|
76
|
+
/\bsm-t\d+/i,
|
|
77
|
+
/\bgt-p\d+/i,
|
|
78
|
+
/\bmi pad\b/i
|
|
79
|
+
]);
|
|
80
|
+
const isMobileByUa = includesAny(userAgent, [
|
|
81
|
+
/\bMobile\b/i,
|
|
82
|
+
/\biPhone\b/i,
|
|
83
|
+
/\biPod\b/i,
|
|
84
|
+
/\bWindows Phone\b/i,
|
|
85
|
+
/\bIEMobile\b/i,
|
|
86
|
+
/\bBlackBerry\b/i,
|
|
87
|
+
/\bBB10\b/i,
|
|
88
|
+
/\bOpera Mini\b/i,
|
|
89
|
+
/\bOpera Mobi\b/i,
|
|
90
|
+
/\bwebOS\b/i
|
|
91
|
+
]);
|
|
92
|
+
const isAndroidTablet = isAndroid && !/\bMobile\b/i.test(userAgent);
|
|
93
|
+
const isTablet = isIPadOS || isTabletByUa || isAndroidTablet;
|
|
94
|
+
const isMobile = input.userAgentDataMobile === true || isMobileByUa || isAndroid && !isTablet || isIOS && !isTablet;
|
|
95
|
+
const deviceType = isTablet ? "tablet" : isMobile ? "mobile" : userAgent || platform || isTouch ? "desktop" : "unknown";
|
|
96
|
+
const shouldUseRedirectLogin = deviceType === "mobile" || deviceType === "tablet" || isWeChat;
|
|
97
|
+
return {
|
|
98
|
+
deviceType,
|
|
99
|
+
isAndroid,
|
|
100
|
+
isCoarsePointer,
|
|
101
|
+
isDesktop: deviceType === "desktop",
|
|
102
|
+
isIOS,
|
|
103
|
+
isIPadOS,
|
|
104
|
+
isMobile,
|
|
105
|
+
isStandalone: input.standalone === true,
|
|
106
|
+
isTablet,
|
|
107
|
+
isTouch,
|
|
108
|
+
isWeChat,
|
|
109
|
+
maxTouchPoints,
|
|
110
|
+
platform,
|
|
111
|
+
shouldUseRedirectLogin,
|
|
112
|
+
userAgent
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
31
116
|
// src/hosted-modal.ts
|
|
32
117
|
var SDK_SUPPORTED_LOCALES = [
|
|
33
118
|
"en",
|
|
@@ -151,7 +236,7 @@ var HostedFrameModal = class {
|
|
|
151
236
|
const container = document.createElement("div");
|
|
152
237
|
Object.assign(container.style, {
|
|
153
238
|
width: options.width || "450px",
|
|
154
|
-
height: options.height || "min(
|
|
239
|
+
height: options.height || "min(760px, calc(100vh - 32px))",
|
|
155
240
|
backgroundColor: "transparent",
|
|
156
241
|
borderRadius: "28px",
|
|
157
242
|
overflow: "visible",
|
|
@@ -159,8 +244,7 @@ var HostedFrameModal = class {
|
|
|
159
244
|
boxShadow: "none",
|
|
160
245
|
maxWidth: "calc(100vw - 32px)",
|
|
161
246
|
maxHeight: "calc(100vh - 32px)",
|
|
162
|
-
transition: "
|
|
163
|
-
willChange: "height"
|
|
247
|
+
transition: "none"
|
|
164
248
|
});
|
|
165
249
|
const closeBtn = document.createElement("button");
|
|
166
250
|
closeBtn.innerHTML = "\xD7";
|
|
@@ -239,6 +323,15 @@ function getOrigin(value) {
|
|
|
239
323
|
return null;
|
|
240
324
|
}
|
|
241
325
|
}
|
|
326
|
+
function isValidLoginRedirectUrl(value) {
|
|
327
|
+
if (!value) return false;
|
|
328
|
+
try {
|
|
329
|
+
const url = new URL(value);
|
|
330
|
+
return url.protocol === "https:" || url.protocol === "http:";
|
|
331
|
+
} catch {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
242
335
|
function createLoginCallbackState() {
|
|
243
336
|
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
244
337
|
return crypto.randomUUID().replace(/-/g, "");
|
|
@@ -585,6 +678,24 @@ function applyLoginPanelStyle(panel) {
|
|
|
585
678
|
backdropFilter: "blur(16px)"
|
|
586
679
|
});
|
|
587
680
|
}
|
|
681
|
+
function applyLoginLoadingPanelStyle(panel) {
|
|
682
|
+
Object.assign(panel.style, {
|
|
683
|
+
position: "absolute",
|
|
684
|
+
inset: "0",
|
|
685
|
+
display: "flex",
|
|
686
|
+
alignItems: "center",
|
|
687
|
+
justifyContent: "center",
|
|
688
|
+
border: "0",
|
|
689
|
+
borderRadius: "28px",
|
|
690
|
+
background: "rgba(255,255,255,0.94)",
|
|
691
|
+
color: "#0f172a",
|
|
692
|
+
padding: "24px",
|
|
693
|
+
textAlign: "center",
|
|
694
|
+
zIndex: "1",
|
|
695
|
+
boxShadow: "none",
|
|
696
|
+
backdropFilter: "blur(16px)"
|
|
697
|
+
});
|
|
698
|
+
}
|
|
588
699
|
function createLoginPanelContent() {
|
|
589
700
|
const content = document.createElement("div");
|
|
590
701
|
Object.assign(content.style, {
|
|
@@ -609,6 +720,71 @@ function createLoginPanelContent() {
|
|
|
609
720
|
content.appendChild(badge);
|
|
610
721
|
return content;
|
|
611
722
|
}
|
|
723
|
+
function createBrandLoadingMark() {
|
|
724
|
+
const logo = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
725
|
+
logo.setAttribute("viewBox", "0 0 1024 1024");
|
|
726
|
+
logo.setAttribute("fill", "none");
|
|
727
|
+
logo.setAttribute("aria-hidden", "true");
|
|
728
|
+
Object.assign(logo.style, {
|
|
729
|
+
width: "112px",
|
|
730
|
+
height: "112px",
|
|
731
|
+
color: "#22c55e",
|
|
732
|
+
display: "block",
|
|
733
|
+
overflow: "visible"
|
|
734
|
+
});
|
|
735
|
+
const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
736
|
+
group.setAttribute("fill", "currentColor");
|
|
737
|
+
const ring = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
738
|
+
ring.setAttribute(
|
|
739
|
+
"d",
|
|
740
|
+
"M704.298 679.54A264 264 0 1 1 704.298 309.46A49 49 0 0 1 634.4 378.149A166 166 0 1 0 634.4 610.851A49 49 0 0 1 704.298 679.54Z"
|
|
741
|
+
);
|
|
742
|
+
ring.setAttribute("class", "youidian-sdk-brand-loading__ring");
|
|
743
|
+
const dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
744
|
+
dot.setAttribute("class", "youidian-sdk-brand-loading__dot");
|
|
745
|
+
dot.setAttribute("cx", "714.5");
|
|
746
|
+
dot.setAttribute("cy", "490.5");
|
|
747
|
+
dot.setAttribute("r", "68");
|
|
748
|
+
group.appendChild(ring);
|
|
749
|
+
group.appendChild(dot);
|
|
750
|
+
logo.appendChild(group);
|
|
751
|
+
return logo;
|
|
752
|
+
}
|
|
753
|
+
function createBrandLoadingCopy() {
|
|
754
|
+
const brand = document.createElement("div");
|
|
755
|
+
brand.className = "youidian-sdk-brand-loading__copy";
|
|
756
|
+
Object.assign(brand.style, {
|
|
757
|
+
display: "flex",
|
|
758
|
+
flexDirection: "column",
|
|
759
|
+
alignItems: "flex-start",
|
|
760
|
+
justifyContent: "center",
|
|
761
|
+
lineHeight: "1"
|
|
762
|
+
});
|
|
763
|
+
const name = document.createElement("div");
|
|
764
|
+
name.className = "youidian-sdk-brand-loading__name";
|
|
765
|
+
name.textContent = "\u4F18\u6613\u70B9";
|
|
766
|
+
Object.assign(name.style, {
|
|
767
|
+
color: "#0f172a",
|
|
768
|
+
fontSize: "34px",
|
|
769
|
+
fontWeight: "900",
|
|
770
|
+
letterSpacing: "0",
|
|
771
|
+
lineHeight: "1"
|
|
772
|
+
});
|
|
773
|
+
const tagline = document.createElement("div");
|
|
774
|
+
tagline.className = "youidian-sdk-brand-loading__tagline";
|
|
775
|
+
tagline.textContent = "\u5F00\u53D1\u8005\u670D\u52A1\u4E2D\u53F0";
|
|
776
|
+
Object.assign(tagline.style, {
|
|
777
|
+
color: "#64748b",
|
|
778
|
+
fontSize: "16px",
|
|
779
|
+
fontWeight: "700",
|
|
780
|
+
letterSpacing: "0.24em",
|
|
781
|
+
lineHeight: "1",
|
|
782
|
+
marginTop: "6px"
|
|
783
|
+
});
|
|
784
|
+
brand.appendChild(name);
|
|
785
|
+
brand.appendChild(tagline);
|
|
786
|
+
return brand;
|
|
787
|
+
}
|
|
612
788
|
function createLoginPanelTitle(value) {
|
|
613
789
|
const title = document.createElement("div");
|
|
614
790
|
title.textContent = value;
|
|
@@ -638,32 +814,111 @@ function ensureLoginLoadingStyles() {
|
|
|
638
814
|
}
|
|
639
815
|
const style = document.createElement("style");
|
|
640
816
|
style.id = "youidian-login-loading-style";
|
|
641
|
-
style.textContent =
|
|
817
|
+
style.textContent = `
|
|
818
|
+
.youidian-sdk-brand-loading__ring,
|
|
819
|
+
.youidian-sdk-brand-loading__dot {
|
|
820
|
+
transform-box: fill-box;
|
|
821
|
+
transform-origin: center;
|
|
822
|
+
will-change: opacity, transform;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
.youidian-sdk-brand-loading__ring {
|
|
826
|
+
animation: youidian-sdk-brand-loading-ring 1400ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
.youidian-sdk-brand-loading__dot {
|
|
830
|
+
animation: youidian-sdk-brand-loading-dot 1400ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
.youidian-sdk-brand-loading__copy {
|
|
834
|
+
will-change: opacity, transform;
|
|
835
|
+
animation: youidian-sdk-brand-loading-copy 1600ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
.youidian-sdk-brand-loading__tagline {
|
|
839
|
+
will-change: opacity;
|
|
840
|
+
animation: youidian-sdk-brand-loading-tagline 1600ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
@keyframes youidian-sdk-brand-loading-ring {
|
|
844
|
+
0%,
|
|
845
|
+
100% {
|
|
846
|
+
opacity: 0.72;
|
|
847
|
+
transform: rotate(0deg) scale(0.98);
|
|
848
|
+
}
|
|
849
|
+
50% {
|
|
850
|
+
opacity: 1;
|
|
851
|
+
transform: rotate(8deg) scale(1.02);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
@keyframes youidian-sdk-brand-loading-dot {
|
|
856
|
+
0%,
|
|
857
|
+
100% {
|
|
858
|
+
opacity: 0.55;
|
|
859
|
+
transform: scale(0.9);
|
|
860
|
+
}
|
|
861
|
+
50% {
|
|
862
|
+
opacity: 1;
|
|
863
|
+
transform: scale(1.08);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
@keyframes youidian-sdk-brand-loading-copy {
|
|
868
|
+
0%,
|
|
869
|
+
100% {
|
|
870
|
+
opacity: 0.86;
|
|
871
|
+
transform: translateY(0);
|
|
872
|
+
}
|
|
873
|
+
50% {
|
|
874
|
+
opacity: 1;
|
|
875
|
+
transform: translateY(-1px);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
@keyframes youidian-sdk-brand-loading-tagline {
|
|
880
|
+
0%,
|
|
881
|
+
100% {
|
|
882
|
+
opacity: 0.64;
|
|
883
|
+
}
|
|
884
|
+
50% {
|
|
885
|
+
opacity: 0.92;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
@media (prefers-reduced-motion: reduce) {
|
|
890
|
+
.youidian-sdk-brand-loading__ring,
|
|
891
|
+
.youidian-sdk-brand-loading__dot,
|
|
892
|
+
.youidian-sdk-brand-loading__copy,
|
|
893
|
+
.youidian-sdk-brand-loading__tagline {
|
|
894
|
+
animation: none;
|
|
895
|
+
opacity: 1;
|
|
896
|
+
transform: none;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
`;
|
|
642
900
|
document.head.appendChild(style);
|
|
643
901
|
}
|
|
644
|
-
function createLoginLoadingPanel(
|
|
902
|
+
function createLoginLoadingPanel() {
|
|
645
903
|
ensureLoginLoadingStyles();
|
|
646
904
|
const panel = document.createElement("div");
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
margin: "0 auto 18px",
|
|
657
|
-
animation: "youidian-login-spin 780ms linear infinite"
|
|
905
|
+
applyLoginLoadingPanelStyle(panel);
|
|
906
|
+
panel.setAttribute("role", "status");
|
|
907
|
+
panel.setAttribute("aria-label", "\u4F18\u6613\u70B9\u5F00\u53D1\u8005\u670D\u52A1\u4E2D\u53F0");
|
|
908
|
+
const content = document.createElement("div");
|
|
909
|
+
Object.assign(content.style, {
|
|
910
|
+
display: "flex",
|
|
911
|
+
alignItems: "center",
|
|
912
|
+
justifyContent: "center",
|
|
913
|
+
gap: "12px"
|
|
658
914
|
});
|
|
659
|
-
content.appendChild(
|
|
660
|
-
content.appendChild(
|
|
661
|
-
content.appendChild(createLoginPanelDescription(options.description));
|
|
915
|
+
content.appendChild(createBrandLoadingMark());
|
|
916
|
+
content.appendChild(createBrandLoadingCopy());
|
|
662
917
|
panel.appendChild(content);
|
|
663
918
|
return panel;
|
|
664
919
|
}
|
|
665
|
-
function createLoginRedirectingPanel(
|
|
666
|
-
return createLoginLoadingPanel(
|
|
920
|
+
function createLoginRedirectingPanel(_options) {
|
|
921
|
+
return createLoginLoadingPanel();
|
|
667
922
|
}
|
|
668
923
|
function createLoginFallbackPanel(options) {
|
|
669
924
|
const panel = document.createElement("div");
|
|
@@ -745,6 +1000,7 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
745
1000
|
this.completed = false;
|
|
746
1001
|
}
|
|
747
1002
|
markIframeReady() {
|
|
1003
|
+
if (this.iframeReady) return;
|
|
748
1004
|
this.iframeReady = true;
|
|
749
1005
|
if (typeof window !== "undefined" && this.iframeLoadTimer) {
|
|
750
1006
|
window.clearTimeout(this.iframeLoadTimer);
|
|
@@ -763,14 +1019,11 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
763
1019
|
this.iframeFallbackPanel = null;
|
|
764
1020
|
this.iframeLoadingPanel = null;
|
|
765
1021
|
}
|
|
766
|
-
showIframeLoading(container
|
|
1022
|
+
showIframeLoading(container) {
|
|
767
1023
|
if (this.iframeLoadingPanel || this.iframeReady) {
|
|
768
1024
|
return;
|
|
769
1025
|
}
|
|
770
|
-
const panel = createLoginLoadingPanel(
|
|
771
|
-
description: options?.loadingDescription || "Please wait while the secure login page opens.",
|
|
772
|
-
title: options?.loadingTitle || "Opening login page"
|
|
773
|
-
});
|
|
1026
|
+
const panel = createLoginLoadingPanel();
|
|
774
1027
|
this.iframeLoadingPanel = panel;
|
|
775
1028
|
container.appendChild(panel);
|
|
776
1029
|
}
|
|
@@ -858,6 +1111,20 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
858
1111
|
break;
|
|
859
1112
|
case "LOGIN_RESIZE":
|
|
860
1113
|
break;
|
|
1114
|
+
case "LOGIN_REDIRECT_REQUIRED":
|
|
1115
|
+
if (!isValidLoginRedirectUrl(data.authUrl)) {
|
|
1116
|
+
logLoginWarn("Login redirect requested with invalid authUrl");
|
|
1117
|
+
options?.onError?.("Login redirect URL is invalid", data);
|
|
1118
|
+
break;
|
|
1119
|
+
}
|
|
1120
|
+
logLoginInfo("Login redirect requested by hosted page", {
|
|
1121
|
+
attemptId: data.attemptId || null,
|
|
1122
|
+
channel: data.channel || null,
|
|
1123
|
+
authUrl: data.authUrl
|
|
1124
|
+
});
|
|
1125
|
+
this.close();
|
|
1126
|
+
window.location.assign(data.authUrl);
|
|
1127
|
+
break;
|
|
861
1128
|
case "LOGIN_ERROR":
|
|
862
1129
|
if (this.completed) {
|
|
863
1130
|
break;
|
|
@@ -881,6 +1148,25 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
881
1148
|
break;
|
|
882
1149
|
}
|
|
883
1150
|
}
|
|
1151
|
+
openLoginRedirect(params, options) {
|
|
1152
|
+
if (typeof window === "undefined") return;
|
|
1153
|
+
const { callbackState, finalUrl, launchPayload } = this.buildOpenContext(
|
|
1154
|
+
params,
|
|
1155
|
+
options
|
|
1156
|
+
);
|
|
1157
|
+
logLoginInfo("Redirecting to hosted login page", {
|
|
1158
|
+
appId: params.appId,
|
|
1159
|
+
callbackState,
|
|
1160
|
+
callbackUrl: launchPayload.callbackUrl || null,
|
|
1161
|
+
hasCallbackUrl: Boolean(launchPayload.callbackUrl),
|
|
1162
|
+
loginUrl: finalUrl,
|
|
1163
|
+
autoClose: options?.autoClose ?? true,
|
|
1164
|
+
displayMode: "redirect",
|
|
1165
|
+
pageUrl: window.location.href,
|
|
1166
|
+
parentOrigin: launchPayload.origin || null
|
|
1167
|
+
});
|
|
1168
|
+
window.location.assign(finalUrl);
|
|
1169
|
+
}
|
|
884
1170
|
listenForLoginCallback(callbackState, options) {
|
|
885
1171
|
try {
|
|
886
1172
|
this.callbackChannel = new BroadcastChannel(
|
|
@@ -957,21 +1243,28 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
957
1243
|
options?.onCancel?.();
|
|
958
1244
|
options?.onClose?.();
|
|
959
1245
|
},
|
|
960
|
-
onMessage: (data,
|
|
1246
|
+
onMessage: (data, _container, event) => {
|
|
961
1247
|
const isIframeEvent = event.source === this.iframe?.contentWindow;
|
|
1248
|
+
if (!isIframeEvent && (data.type === "LOGIN_READY" || data.type === "LOGIN_RESIZE")) {
|
|
1249
|
+
logLoginWarn(
|
|
1250
|
+
"Login lifecycle event ignored: event.source does not match iframe contentWindow",
|
|
1251
|
+
{
|
|
1252
|
+
type: data.type,
|
|
1253
|
+
eventOrigin: event.origin,
|
|
1254
|
+
hasIframe: Boolean(this.iframe),
|
|
1255
|
+
hasIframeContentWindow: Boolean(this.iframe?.contentWindow)
|
|
1256
|
+
}
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
962
1259
|
if (isIframeEvent && (data.type === "LOGIN_READY" || data.type === "LOGIN_RESIZE") || data.type === "LOGIN_SUCCESS" || data.type === "LOGIN_ERROR") {
|
|
963
1260
|
this.markIframeReady();
|
|
964
1261
|
}
|
|
965
|
-
if (data.type === "LOGIN_RESIZE" && data.height) {
|
|
966
|
-
const maxHeight = window.innerHeight * 0.94;
|
|
967
|
-
container.style.height = `${Math.min(data.height, maxHeight)}px`;
|
|
968
|
-
}
|
|
969
1262
|
this.handleLoginEvent(data, options);
|
|
970
1263
|
},
|
|
971
1264
|
width: "min(520px, 100%)"
|
|
972
1265
|
});
|
|
973
1266
|
if (hostedFrame) {
|
|
974
|
-
this.showIframeLoading(hostedFrame.container
|
|
1267
|
+
this.showIframeLoading(hostedFrame.container);
|
|
975
1268
|
this.startIframeWatchdog({
|
|
976
1269
|
container: hostedFrame.container,
|
|
977
1270
|
finalUrl,
|
|
@@ -1075,11 +1368,19 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
1075
1368
|
}
|
|
1076
1369
|
openLogin(params, options) {
|
|
1077
1370
|
if (typeof window === "undefined") return;
|
|
1078
|
-
const displayMode = options?.displayMode ?? "
|
|
1371
|
+
const displayMode = options?.displayMode ?? "auto";
|
|
1372
|
+
if (displayMode === "redirect") {
|
|
1373
|
+
this.openLoginRedirect(params, options);
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1079
1376
|
if (displayMode === "popup") {
|
|
1080
1377
|
this.openLoginPopup(params, options);
|
|
1081
1378
|
return;
|
|
1082
1379
|
}
|
|
1380
|
+
if (displayMode === "auto" && detectLoginEnvironment().shouldUseRedirectLogin) {
|
|
1381
|
+
this.openLoginRedirect(params, options);
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1083
1384
|
this.openLoginModal(params, options);
|
|
1084
1385
|
}
|
|
1085
1386
|
};
|