@youidian/sdk 3.3.3 → 3.3.5

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/index.cjs CHANGED
@@ -145,8 +145,8 @@ var HostedFrameModal = class {
145
145
  __publicField(this, "messageHandler", null);
146
146
  }
147
147
  openHostedFrame(url, options) {
148
- if (typeof document === "undefined") return;
149
- if (this.modal) return;
148
+ if (typeof document === "undefined") return null;
149
+ if (this.modal) return null;
150
150
  this.modal = document.createElement("div");
151
151
  Object.assign(this.modal.style, {
152
152
  position: "fixed",
@@ -223,9 +223,13 @@ var HostedFrameModal = class {
223
223
  if (!data || typeof data !== "object" || !data.type) {
224
224
  return;
225
225
  }
226
- options.onMessage(data, container);
226
+ options.onMessage(data, container, event);
227
227
  };
228
228
  window.addEventListener("message", this.messageHandler);
229
+ return {
230
+ container,
231
+ iframe: this.iframe
232
+ };
229
233
  }
230
234
  close() {
231
235
  if (typeof window === "undefined") return;
@@ -391,6 +395,7 @@ var LOGIN_CALLBACK_RESULT_PARAM = "yd_login_result";
391
395
  var LOGIN_CALLBACK_RETURN_HASH_PARAM = "yd_login_return_hash";
392
396
  var LOGIN_CALLBACK_STATE_PARAM = "yd_login_state";
393
397
  var LOGIN_CALLBACK_STORAGE_PREFIX = "yd-login-callback:";
398
+ var DEFAULT_IFRAME_LOAD_TIMEOUT_MS = 1500;
394
399
  function decodeCallbackPayload(value) {
395
400
  try {
396
401
  const padded = value.padEnd(
@@ -518,6 +523,138 @@ function logLoginWarn(message, details) {
518
523
  if (typeof console === "undefined") return;
519
524
  console.warn(LOGIN_UI_LOG_PREFIX, message, details || {});
520
525
  }
526
+ function getIframeLoadTimeoutMs(options) {
527
+ const timeout = options?.iframeLoadTimeoutMs;
528
+ if (typeof timeout !== "number" || !Number.isFinite(timeout)) {
529
+ return DEFAULT_IFRAME_LOAD_TIMEOUT_MS;
530
+ }
531
+ return Math.max(0, timeout);
532
+ }
533
+ function applyLoginPanelStyle(panel) {
534
+ Object.assign(panel.style, {
535
+ position: "absolute",
536
+ inset: "0",
537
+ display: "flex",
538
+ alignItems: "center",
539
+ justifyContent: "center",
540
+ border: "1px solid rgba(229,229,229,0.92)",
541
+ borderRadius: "28px",
542
+ background: "rgba(255,255,255,0.94)",
543
+ color: "#0f172a",
544
+ padding: "24px",
545
+ textAlign: "center",
546
+ zIndex: "1",
547
+ boxShadow: "0 18px 50px rgba(15,15,15,0.06)",
548
+ backdropFilter: "blur(16px)"
549
+ });
550
+ }
551
+ function createLoginPanelContent() {
552
+ const content = document.createElement("div");
553
+ Object.assign(content.style, {
554
+ maxWidth: "360px"
555
+ });
556
+ const badge = document.createElement("div");
557
+ badge.textContent = "YOUiDIAN";
558
+ Object.assign(badge.style, {
559
+ display: "inline-flex",
560
+ alignItems: "center",
561
+ border: "1px solid rgba(229,229,229,0.92)",
562
+ borderRadius: "9999px",
563
+ background: "#fafafa",
564
+ color: "#171717",
565
+ fontSize: "11px",
566
+ fontWeight: "700",
567
+ letterSpacing: "0.22em",
568
+ lineHeight: "1",
569
+ marginBottom: "18px",
570
+ padding: "8px 12px"
571
+ });
572
+ content.appendChild(badge);
573
+ return content;
574
+ }
575
+ function createLoginPanelTitle(value) {
576
+ const title = document.createElement("div");
577
+ title.textContent = value;
578
+ Object.assign(title.style, {
579
+ color: "#171717",
580
+ fontSize: "18px",
581
+ fontWeight: "700",
582
+ lineHeight: "1.35",
583
+ marginBottom: "10px"
584
+ });
585
+ return title;
586
+ }
587
+ function createLoginPanelDescription(value) {
588
+ const description = document.createElement("div");
589
+ description.textContent = value;
590
+ Object.assign(description.style, {
591
+ color: "#525252",
592
+ fontSize: "14px",
593
+ lineHeight: "1.6",
594
+ marginBottom: "20px"
595
+ });
596
+ return description;
597
+ }
598
+ function ensureLoginLoadingStyles() {
599
+ if (document.getElementById("youidian-login-loading-style")) {
600
+ return;
601
+ }
602
+ const style = document.createElement("style");
603
+ style.id = "youidian-login-loading-style";
604
+ style.textContent = "@keyframes youidian-login-spin{to{transform:rotate(360deg)}}";
605
+ document.head.appendChild(style);
606
+ }
607
+ function createLoginLoadingPanel(options) {
608
+ ensureLoginLoadingStyles();
609
+ const panel = document.createElement("div");
610
+ applyLoginPanelStyle(panel);
611
+ const content = createLoginPanelContent();
612
+ const spinner = document.createElement("div");
613
+ Object.assign(spinner.style, {
614
+ width: "22px",
615
+ height: "22px",
616
+ borderRadius: "9999px",
617
+ border: "2px solid rgba(23,23,23,0.16)",
618
+ borderTopColor: "#171717",
619
+ margin: "0 auto 18px",
620
+ animation: "youidian-login-spin 780ms linear infinite"
621
+ });
622
+ content.appendChild(spinner);
623
+ content.appendChild(createLoginPanelTitle(options.title));
624
+ content.appendChild(createLoginPanelDescription(options.description));
625
+ panel.appendChild(content);
626
+ return panel;
627
+ }
628
+ function createLoginRedirectingPanel(options) {
629
+ return createLoginLoadingPanel(options);
630
+ }
631
+ function createLoginFallbackPanel(options) {
632
+ const panel = document.createElement("div");
633
+ applyLoginPanelStyle(panel);
634
+ const content = createLoginPanelContent();
635
+ const button = document.createElement("button");
636
+ button.type = "button";
637
+ button.textContent = options.buttonText;
638
+ Object.assign(button.style, {
639
+ width: "100%",
640
+ border: "0",
641
+ borderRadius: "12px",
642
+ background: "#0a0a0a",
643
+ color: "#ffffff",
644
+ cursor: "pointer",
645
+ fontSize: "14px",
646
+ fontWeight: "700",
647
+ minHeight: "44px",
648
+ padding: "12px 16px",
649
+ boxShadow: "0 12px 28px rgba(17,17,17,0.14)"
650
+ });
651
+ button.onclick = options.onRedirect;
652
+ content.appendChild(createLoginPanelTitle(options.title));
653
+ content.appendChild(createLoginPanelDescription(options.description));
654
+ content.appendChild(button);
655
+ panel.appendChild(content);
656
+ return panel;
657
+ }
521
658
  var LoginUI = class extends HostedFrameModal {
522
659
  constructor() {
523
660
  super(...arguments);
@@ -526,6 +663,11 @@ var LoginUI = class extends HostedFrameModal {
526
663
  __publicField(this, "callbackStorageHandler", null);
527
664
  __publicField(this, "popupMessageHandler", null);
528
665
  __publicField(this, "closeMonitor", null);
666
+ __publicField(this, "iframeFallbackPanel", null);
667
+ __publicField(this, "iframeLoadingPanel", null);
668
+ __publicField(this, "iframeLoadTimer", null);
669
+ __publicField(this, "iframeRedirectTimer", null);
670
+ __publicField(this, "iframeReady", false);
529
671
  __publicField(this, "completed", false);
530
672
  }
531
673
  cleanup() {
@@ -543,11 +685,114 @@ var LoginUI = class extends HostedFrameModal {
543
685
  if (typeof window !== "undefined" && this.closeMonitor) {
544
686
  window.clearInterval(this.closeMonitor);
545
687
  }
688
+ if (typeof window !== "undefined" && this.iframeLoadTimer) {
689
+ window.clearTimeout(this.iframeLoadTimer);
690
+ }
691
+ if (typeof window !== "undefined" && this.iframeRedirectTimer) {
692
+ window.clearTimeout(this.iframeRedirectTimer);
693
+ }
694
+ if (this.iframeFallbackPanel?.parentNode) {
695
+ this.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel);
696
+ }
697
+ if (this.iframeLoadingPanel?.parentNode) {
698
+ this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
699
+ }
546
700
  this.popupMessageHandler = null;
547
701
  this.closeMonitor = null;
702
+ this.iframeFallbackPanel = null;
703
+ this.iframeLoadingPanel = null;
704
+ this.iframeLoadTimer = null;
705
+ this.iframeRedirectTimer = null;
706
+ this.iframeReady = false;
548
707
  this.popup = null;
549
708
  this.completed = false;
550
709
  }
710
+ markIframeReady() {
711
+ this.iframeReady = true;
712
+ if (typeof window !== "undefined" && this.iframeLoadTimer) {
713
+ window.clearTimeout(this.iframeLoadTimer);
714
+ this.iframeLoadTimer = null;
715
+ }
716
+ if (typeof window !== "undefined" && this.iframeRedirectTimer) {
717
+ window.clearTimeout(this.iframeRedirectTimer);
718
+ this.iframeRedirectTimer = null;
719
+ }
720
+ if (this.iframeFallbackPanel?.parentNode) {
721
+ this.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel);
722
+ }
723
+ if (this.iframeLoadingPanel?.parentNode) {
724
+ this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
725
+ }
726
+ this.iframeFallbackPanel = null;
727
+ this.iframeLoadingPanel = null;
728
+ }
729
+ showIframeLoading(container, options) {
730
+ if (this.iframeLoadingPanel || this.iframeReady) {
731
+ return;
732
+ }
733
+ const panel = createLoginLoadingPanel({
734
+ description: options?.loadingDescription || "Please wait while the secure login page opens.",
735
+ title: options?.loadingTitle || "Opening login page"
736
+ });
737
+ this.iframeLoadingPanel = panel;
738
+ container.appendChild(panel);
739
+ }
740
+ showIframeFallback(options) {
741
+ if (this.iframeReady || this.iframeFallbackPanel) {
742
+ return;
743
+ }
744
+ const { container, finalUrl, loginOptions } = options;
745
+ logLoginWarn("Hosted login iframe did not report ready in time", {
746
+ loginUrl: finalUrl
747
+ });
748
+ if (this.iframeLoadingPanel?.parentNode) {
749
+ this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
750
+ }
751
+ this.iframeLoadingPanel = null;
752
+ if (loginOptions?.fallbackRedirectMode !== "manual") {
753
+ const panel2 = createLoginRedirectingPanel({
754
+ description: loginOptions?.fallbackDescription || "The embedded login page is taking longer than expected. Redirecting you to the login page now.",
755
+ title: loginOptions?.fallbackTitle || "Redirecting to login page"
756
+ });
757
+ this.iframeFallbackPanel = panel2;
758
+ container.appendChild(panel2);
759
+ loginOptions?.onFallbackVisible?.();
760
+ this.iframeRedirectTimer = window.setTimeout(() => {
761
+ this.iframeRedirectTimer = null;
762
+ logLoginInfo("Redirecting to hosted login fallback page", {
763
+ loginUrl: finalUrl
764
+ });
765
+ window.location.assign(finalUrl);
766
+ }, 350);
767
+ return;
768
+ }
769
+ const panel = createLoginFallbackPanel({
770
+ buttonText: loginOptions?.fallbackButtonText || "Continue to login",
771
+ description: loginOptions?.fallbackDescription || "The embedded login page is taking longer than expected. Continue on the login page to finish signing in.",
772
+ title: loginOptions?.fallbackTitle || "Login page is still loading",
773
+ onRedirect: () => {
774
+ logLoginInfo("Redirecting to hosted login fallback page", {
775
+ loginUrl: finalUrl
776
+ });
777
+ window.location.assign(finalUrl);
778
+ }
779
+ });
780
+ this.iframeFallbackPanel = panel;
781
+ container.appendChild(panel);
782
+ loginOptions?.onFallbackVisible?.();
783
+ }
784
+ startIframeWatchdog(options) {
785
+ if (typeof window === "undefined") return;
786
+ const timeoutMs = getIframeLoadTimeoutMs(options.loginOptions);
787
+ if (timeoutMs === 0) {
788
+ this.showIframeFallback(options);
789
+ return;
790
+ }
791
+ this.iframeLoadTimer = window.setTimeout(() => {
792
+ this.iframeLoadTimer = null;
793
+ this.showIframeFallback(options);
794
+ }, timeoutMs);
795
+ }
551
796
  handleLoginEvent(data, options) {
552
797
  if (!data || typeof data !== "object" || !data.type) {
553
798
  logLoginDebug("Ignored non-login event payload");
@@ -557,6 +802,8 @@ var LoginUI = class extends HostedFrameModal {
557
802
  type: data.type
558
803
  });
559
804
  switch (data.type) {
805
+ case "LOGIN_READY":
806
+ break;
560
807
  case "LOGIN_SUCCESS":
561
808
  if (this.completed) {
562
809
  break;
@@ -664,15 +911,20 @@ var LoginUI = class extends HostedFrameModal {
664
911
  parentOrigin: launchPayload.origin || null
665
912
  });
666
913
  this.completed = false;
914
+ this.iframeReady = false;
667
915
  this.listenForLoginCallback(callbackState, options);
668
- this.openHostedFrame(finalUrl, {
916
+ const hostedFrame = this.openHostedFrame(finalUrl, {
669
917
  allowedOrigin: options?.allowedOrigin || loginOrigin || void 0,
670
918
  height: "min(760px, 94vh)",
671
919
  onCloseButton: () => {
672
920
  options?.onCancel?.();
673
921
  options?.onClose?.();
674
922
  },
675
- onMessage: (data, container) => {
923
+ onMessage: (data, container, event) => {
924
+ const isIframeEvent = event.source === this.iframe?.contentWindow;
925
+ if (isIframeEvent && (data.type === "LOGIN_READY" || data.type === "LOGIN_RESIZE") || data.type === "LOGIN_SUCCESS" || data.type === "LOGIN_ERROR") {
926
+ this.markIframeReady();
927
+ }
676
928
  if (data.type === "LOGIN_RESIZE" && data.height) {
677
929
  const maxHeight = window.innerHeight * 0.94;
678
930
  container.style.height = `${Math.min(data.height, maxHeight)}px`;
@@ -681,6 +933,15 @@ var LoginUI = class extends HostedFrameModal {
681
933
  },
682
934
  width: "min(520px, 100%)"
683
935
  });
936
+ if (hostedFrame) {
937
+ this.showIframeLoading(hostedFrame.container, options);
938
+ this.startIframeWatchdog({
939
+ container: hostedFrame.container,
940
+ finalUrl,
941
+ launchPayload,
942
+ loginOptions: options
943
+ });
944
+ }
684
945
  }
685
946
  openLoginPopup(params, options) {
686
947
  if (typeof window === "undefined") return;