@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.js CHANGED
@@ -104,8 +104,8 @@ var HostedFrameModal = class {
104
104
  __publicField(this, "messageHandler", null);
105
105
  }
106
106
  openHostedFrame(url, options) {
107
- if (typeof document === "undefined") return;
108
- if (this.modal) return;
107
+ if (typeof document === "undefined") return null;
108
+ if (this.modal) return null;
109
109
  this.modal = document.createElement("div");
110
110
  Object.assign(this.modal.style, {
111
111
  position: "fixed",
@@ -182,9 +182,13 @@ var HostedFrameModal = class {
182
182
  if (!data || typeof data !== "object" || !data.type) {
183
183
  return;
184
184
  }
185
- options.onMessage(data, container);
185
+ options.onMessage(data, container, event);
186
186
  };
187
187
  window.addEventListener("message", this.messageHandler);
188
+ return {
189
+ container,
190
+ iframe: this.iframe
191
+ };
188
192
  }
189
193
  close() {
190
194
  if (typeof window === "undefined") return;
@@ -350,6 +354,7 @@ var LOGIN_CALLBACK_RESULT_PARAM = "yd_login_result";
350
354
  var LOGIN_CALLBACK_RETURN_HASH_PARAM = "yd_login_return_hash";
351
355
  var LOGIN_CALLBACK_STATE_PARAM = "yd_login_state";
352
356
  var LOGIN_CALLBACK_STORAGE_PREFIX = "yd-login-callback:";
357
+ var DEFAULT_IFRAME_LOAD_TIMEOUT_MS = 1500;
353
358
  function decodeCallbackPayload(value) {
354
359
  try {
355
360
  const padded = value.padEnd(
@@ -477,6 +482,138 @@ function logLoginWarn(message, details) {
477
482
  if (typeof console === "undefined") return;
478
483
  console.warn(LOGIN_UI_LOG_PREFIX, message, details || {});
479
484
  }
485
+ function getIframeLoadTimeoutMs(options) {
486
+ const timeout = options?.iframeLoadTimeoutMs;
487
+ if (typeof timeout !== "number" || !Number.isFinite(timeout)) {
488
+ return DEFAULT_IFRAME_LOAD_TIMEOUT_MS;
489
+ }
490
+ return Math.max(0, timeout);
491
+ }
492
+ function applyLoginPanelStyle(panel) {
493
+ Object.assign(panel.style, {
494
+ position: "absolute",
495
+ inset: "0",
496
+ display: "flex",
497
+ alignItems: "center",
498
+ justifyContent: "center",
499
+ border: "1px solid rgba(229,229,229,0.92)",
500
+ borderRadius: "28px",
501
+ background: "rgba(255,255,255,0.94)",
502
+ color: "#0f172a",
503
+ padding: "24px",
504
+ textAlign: "center",
505
+ zIndex: "1",
506
+ boxShadow: "0 18px 50px rgba(15,15,15,0.06)",
507
+ backdropFilter: "blur(16px)"
508
+ });
509
+ }
510
+ function createLoginPanelContent() {
511
+ const content = document.createElement("div");
512
+ Object.assign(content.style, {
513
+ maxWidth: "360px"
514
+ });
515
+ const badge = document.createElement("div");
516
+ badge.textContent = "YOUiDIAN";
517
+ Object.assign(badge.style, {
518
+ display: "inline-flex",
519
+ alignItems: "center",
520
+ border: "1px solid rgba(229,229,229,0.92)",
521
+ borderRadius: "9999px",
522
+ background: "#fafafa",
523
+ color: "#171717",
524
+ fontSize: "11px",
525
+ fontWeight: "700",
526
+ letterSpacing: "0.22em",
527
+ lineHeight: "1",
528
+ marginBottom: "18px",
529
+ padding: "8px 12px"
530
+ });
531
+ content.appendChild(badge);
532
+ return content;
533
+ }
534
+ function createLoginPanelTitle(value) {
535
+ const title = document.createElement("div");
536
+ title.textContent = value;
537
+ Object.assign(title.style, {
538
+ color: "#171717",
539
+ fontSize: "18px",
540
+ fontWeight: "700",
541
+ lineHeight: "1.35",
542
+ marginBottom: "10px"
543
+ });
544
+ return title;
545
+ }
546
+ function createLoginPanelDescription(value) {
547
+ const description = document.createElement("div");
548
+ description.textContent = value;
549
+ Object.assign(description.style, {
550
+ color: "#525252",
551
+ fontSize: "14px",
552
+ lineHeight: "1.6",
553
+ marginBottom: "20px"
554
+ });
555
+ return description;
556
+ }
557
+ function ensureLoginLoadingStyles() {
558
+ if (document.getElementById("youidian-login-loading-style")) {
559
+ return;
560
+ }
561
+ const style = document.createElement("style");
562
+ style.id = "youidian-login-loading-style";
563
+ style.textContent = "@keyframes youidian-login-spin{to{transform:rotate(360deg)}}";
564
+ document.head.appendChild(style);
565
+ }
566
+ function createLoginLoadingPanel(options) {
567
+ ensureLoginLoadingStyles();
568
+ const panel = document.createElement("div");
569
+ applyLoginPanelStyle(panel);
570
+ const content = createLoginPanelContent();
571
+ const spinner = document.createElement("div");
572
+ Object.assign(spinner.style, {
573
+ width: "22px",
574
+ height: "22px",
575
+ borderRadius: "9999px",
576
+ border: "2px solid rgba(23,23,23,0.16)",
577
+ borderTopColor: "#171717",
578
+ margin: "0 auto 18px",
579
+ animation: "youidian-login-spin 780ms linear infinite"
580
+ });
581
+ content.appendChild(spinner);
582
+ content.appendChild(createLoginPanelTitle(options.title));
583
+ content.appendChild(createLoginPanelDescription(options.description));
584
+ panel.appendChild(content);
585
+ return panel;
586
+ }
587
+ function createLoginRedirectingPanel(options) {
588
+ return createLoginLoadingPanel(options);
589
+ }
590
+ function createLoginFallbackPanel(options) {
591
+ const panel = document.createElement("div");
592
+ applyLoginPanelStyle(panel);
593
+ const content = createLoginPanelContent();
594
+ const button = document.createElement("button");
595
+ button.type = "button";
596
+ button.textContent = options.buttonText;
597
+ Object.assign(button.style, {
598
+ width: "100%",
599
+ border: "0",
600
+ borderRadius: "12px",
601
+ background: "#0a0a0a",
602
+ color: "#ffffff",
603
+ cursor: "pointer",
604
+ fontSize: "14px",
605
+ fontWeight: "700",
606
+ minHeight: "44px",
607
+ padding: "12px 16px",
608
+ boxShadow: "0 12px 28px rgba(17,17,17,0.14)"
609
+ });
610
+ button.onclick = options.onRedirect;
611
+ content.appendChild(createLoginPanelTitle(options.title));
612
+ content.appendChild(createLoginPanelDescription(options.description));
613
+ content.appendChild(button);
614
+ panel.appendChild(content);
615
+ return panel;
616
+ }
480
617
  var LoginUI = class extends HostedFrameModal {
481
618
  constructor() {
482
619
  super(...arguments);
@@ -485,6 +622,11 @@ var LoginUI = class extends HostedFrameModal {
485
622
  __publicField(this, "callbackStorageHandler", null);
486
623
  __publicField(this, "popupMessageHandler", null);
487
624
  __publicField(this, "closeMonitor", null);
625
+ __publicField(this, "iframeFallbackPanel", null);
626
+ __publicField(this, "iframeLoadingPanel", null);
627
+ __publicField(this, "iframeLoadTimer", null);
628
+ __publicField(this, "iframeRedirectTimer", null);
629
+ __publicField(this, "iframeReady", false);
488
630
  __publicField(this, "completed", false);
489
631
  }
490
632
  cleanup() {
@@ -502,11 +644,114 @@ var LoginUI = class extends HostedFrameModal {
502
644
  if (typeof window !== "undefined" && this.closeMonitor) {
503
645
  window.clearInterval(this.closeMonitor);
504
646
  }
647
+ if (typeof window !== "undefined" && this.iframeLoadTimer) {
648
+ window.clearTimeout(this.iframeLoadTimer);
649
+ }
650
+ if (typeof window !== "undefined" && this.iframeRedirectTimer) {
651
+ window.clearTimeout(this.iframeRedirectTimer);
652
+ }
653
+ if (this.iframeFallbackPanel?.parentNode) {
654
+ this.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel);
655
+ }
656
+ if (this.iframeLoadingPanel?.parentNode) {
657
+ this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
658
+ }
505
659
  this.popupMessageHandler = null;
506
660
  this.closeMonitor = null;
661
+ this.iframeFallbackPanel = null;
662
+ this.iframeLoadingPanel = null;
663
+ this.iframeLoadTimer = null;
664
+ this.iframeRedirectTimer = null;
665
+ this.iframeReady = false;
507
666
  this.popup = null;
508
667
  this.completed = false;
509
668
  }
669
+ markIframeReady() {
670
+ this.iframeReady = true;
671
+ if (typeof window !== "undefined" && this.iframeLoadTimer) {
672
+ window.clearTimeout(this.iframeLoadTimer);
673
+ this.iframeLoadTimer = null;
674
+ }
675
+ if (typeof window !== "undefined" && this.iframeRedirectTimer) {
676
+ window.clearTimeout(this.iframeRedirectTimer);
677
+ this.iframeRedirectTimer = null;
678
+ }
679
+ if (this.iframeFallbackPanel?.parentNode) {
680
+ this.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel);
681
+ }
682
+ if (this.iframeLoadingPanel?.parentNode) {
683
+ this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
684
+ }
685
+ this.iframeFallbackPanel = null;
686
+ this.iframeLoadingPanel = null;
687
+ }
688
+ showIframeLoading(container, options) {
689
+ if (this.iframeLoadingPanel || this.iframeReady) {
690
+ return;
691
+ }
692
+ const panel = createLoginLoadingPanel({
693
+ description: options?.loadingDescription || "Please wait while the secure login page opens.",
694
+ title: options?.loadingTitle || "Opening login page"
695
+ });
696
+ this.iframeLoadingPanel = panel;
697
+ container.appendChild(panel);
698
+ }
699
+ showIframeFallback(options) {
700
+ if (this.iframeReady || this.iframeFallbackPanel) {
701
+ return;
702
+ }
703
+ const { container, finalUrl, loginOptions } = options;
704
+ logLoginWarn("Hosted login iframe did not report ready in time", {
705
+ loginUrl: finalUrl
706
+ });
707
+ if (this.iframeLoadingPanel?.parentNode) {
708
+ this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
709
+ }
710
+ this.iframeLoadingPanel = null;
711
+ if (loginOptions?.fallbackRedirectMode !== "manual") {
712
+ const panel2 = createLoginRedirectingPanel({
713
+ description: loginOptions?.fallbackDescription || "The embedded login page is taking longer than expected. Redirecting you to the login page now.",
714
+ title: loginOptions?.fallbackTitle || "Redirecting to login page"
715
+ });
716
+ this.iframeFallbackPanel = panel2;
717
+ container.appendChild(panel2);
718
+ loginOptions?.onFallbackVisible?.();
719
+ this.iframeRedirectTimer = window.setTimeout(() => {
720
+ this.iframeRedirectTimer = null;
721
+ logLoginInfo("Redirecting to hosted login fallback page", {
722
+ loginUrl: finalUrl
723
+ });
724
+ window.location.assign(finalUrl);
725
+ }, 350);
726
+ return;
727
+ }
728
+ const panel = createLoginFallbackPanel({
729
+ buttonText: loginOptions?.fallbackButtonText || "Continue to login",
730
+ description: loginOptions?.fallbackDescription || "The embedded login page is taking longer than expected. Continue on the login page to finish signing in.",
731
+ title: loginOptions?.fallbackTitle || "Login page is still loading",
732
+ onRedirect: () => {
733
+ logLoginInfo("Redirecting to hosted login fallback page", {
734
+ loginUrl: finalUrl
735
+ });
736
+ window.location.assign(finalUrl);
737
+ }
738
+ });
739
+ this.iframeFallbackPanel = panel;
740
+ container.appendChild(panel);
741
+ loginOptions?.onFallbackVisible?.();
742
+ }
743
+ startIframeWatchdog(options) {
744
+ if (typeof window === "undefined") return;
745
+ const timeoutMs = getIframeLoadTimeoutMs(options.loginOptions);
746
+ if (timeoutMs === 0) {
747
+ this.showIframeFallback(options);
748
+ return;
749
+ }
750
+ this.iframeLoadTimer = window.setTimeout(() => {
751
+ this.iframeLoadTimer = null;
752
+ this.showIframeFallback(options);
753
+ }, timeoutMs);
754
+ }
510
755
  handleLoginEvent(data, options) {
511
756
  if (!data || typeof data !== "object" || !data.type) {
512
757
  logLoginDebug("Ignored non-login event payload");
@@ -516,6 +761,8 @@ var LoginUI = class extends HostedFrameModal {
516
761
  type: data.type
517
762
  });
518
763
  switch (data.type) {
764
+ case "LOGIN_READY":
765
+ break;
519
766
  case "LOGIN_SUCCESS":
520
767
  if (this.completed) {
521
768
  break;
@@ -623,15 +870,20 @@ var LoginUI = class extends HostedFrameModal {
623
870
  parentOrigin: launchPayload.origin || null
624
871
  });
625
872
  this.completed = false;
873
+ this.iframeReady = false;
626
874
  this.listenForLoginCallback(callbackState, options);
627
- this.openHostedFrame(finalUrl, {
875
+ const hostedFrame = this.openHostedFrame(finalUrl, {
628
876
  allowedOrigin: options?.allowedOrigin || loginOrigin || void 0,
629
877
  height: "min(760px, 94vh)",
630
878
  onCloseButton: () => {
631
879
  options?.onCancel?.();
632
880
  options?.onClose?.();
633
881
  },
634
- onMessage: (data, container) => {
882
+ onMessage: (data, container, event) => {
883
+ const isIframeEvent = event.source === this.iframe?.contentWindow;
884
+ if (isIframeEvent && (data.type === "LOGIN_READY" || data.type === "LOGIN_RESIZE") || data.type === "LOGIN_SUCCESS" || data.type === "LOGIN_ERROR") {
885
+ this.markIframeReady();
886
+ }
635
887
  if (data.type === "LOGIN_RESIZE" && data.height) {
636
888
  const maxHeight = window.innerHeight * 0.94;
637
889
  container.style.height = `${Math.min(data.height, maxHeight)}px`;
@@ -640,6 +892,15 @@ var LoginUI = class extends HostedFrameModal {
640
892
  },
641
893
  width: "min(520px, 100%)"
642
894
  });
895
+ if (hostedFrame) {
896
+ this.showIframeLoading(hostedFrame.container, options);
897
+ this.startIframeWatchdog({
898
+ container: hostedFrame.container,
899
+ finalUrl,
900
+ launchPayload,
901
+ loginOptions: options
902
+ });
903
+ }
643
904
  }
644
905
  openLoginPopup(params, options) {
645
906
  if (typeof window === "undefined") return;