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