signer-test-sdk-react 0.0.14 → 0.0.15

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.
@@ -1,3 +1,4 @@
1
+ import { isValidEmail } from "signer-test-sdk-core";
1
2
  // CSS styles embedded as string
2
3
  const ONBOARDING_UI_STYLES = `
3
4
  .onboarding-container {
@@ -101,44 +102,6 @@ const ONBOARDING_UI_STYLES = `
101
102
  transform: scale(0.95);
102
103
  }
103
104
 
104
- .onboarding-modal-close {
105
- position: absolute;
106
- top: 24px;
107
- right: 24px;
108
- width: 32px;
109
- height: 32px;
110
- border: none;
111
- background-color: #f3f4f6;
112
- border-radius: 8px;
113
- cursor: pointer;
114
- display: flex;
115
- align-items: center;
116
- justify-content: center;
117
- font-size: 18px;
118
- line-height: 1;
119
- color: #6b7280;
120
- transition: all 0.2s ease;
121
- z-index: 10;
122
- padding: 0;
123
- font-weight: 400;
124
- }
125
-
126
- .onboarding-modal-close:hover {
127
- background-color: #e5e7eb;
128
- color: #374151;
129
- transform: scale(1.05);
130
- }
131
-
132
- .onboarding-theme-dark .onboarding-modal-close {
133
- background-color: #374151;
134
- color: #9ca3af;
135
- }
136
-
137
- .onboarding-theme-dark .onboarding-modal-close:hover {
138
- background-color: #4b5563;
139
- color: #ffffff;
140
- }
141
-
142
105
  /* Modal container adjustments */
143
106
  .onboarding-modal-content .onboarding-container {
144
107
  min-height: auto;
@@ -159,7 +122,7 @@ const ONBOARDING_UI_STYLES = `
159
122
  width: 420px;
160
123
  max-width: 420px;
161
124
  min-width: 420px;
162
- padding: 40px;
125
+ padding: 20px;
163
126
  border-radius: 16px;
164
127
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08);
165
128
  background-color: inherit;
@@ -191,7 +154,7 @@ const ONBOARDING_UI_STYLES = `
191
154
 
192
155
  @media (max-width: 480px) {
193
156
  .onboarding-card {
194
- padding: 32px 24px;
157
+ padding: 24px 20px;
195
158
  border-radius: 0;
196
159
  max-height: 100vh;
197
160
  }
@@ -211,14 +174,14 @@ const ONBOARDING_UI_STYLES = `
211
174
 
212
175
  .onboarding-header {
213
176
  text-align: center;
214
- margin-bottom: 32px;
177
+ margin-bottom: 20px;
215
178
  }
216
179
 
217
180
  .onboarding-logo-section {
218
181
  display: flex;
219
182
  flex-direction: column;
220
183
  align-items: center;
221
- margin-bottom: 24px;
184
+ margin-bottom: 12px;
222
185
  }
223
186
 
224
187
  .onboarding-logo-container {
@@ -241,9 +204,9 @@ const ONBOARDING_UI_STYLES = `
241
204
  margin: 0;
242
205
  color: inherit;
243
206
  text-align: center;
244
- margin-bottom: 28px;
207
+ margin-bottom: 4px;
245
208
  letter-spacing: -0.01em;
246
- line-height: 1.4;
209
+ line-height: 1.2;
247
210
  }
248
211
 
249
212
  @media (max-width: 480px) {
@@ -266,7 +229,7 @@ const ONBOARDING_UI_STYLES = `
266
229
  }
267
230
 
268
231
  .onboarding-input-group {
269
- margin-bottom: 20px;
232
+ margin-bottom: 8px;
270
233
  }
271
234
 
272
235
  .onboarding-input-label {
@@ -274,7 +237,7 @@ const ONBOARDING_UI_STYLES = `
274
237
  font-size: 14px;
275
238
  font-weight: 500;
276
239
  color: #374151;
277
- margin-bottom: 8px;
240
+ margin-bottom: 4px;
278
241
  letter-spacing: -0.01em;
279
242
  line-height: 1.5;
280
243
  text-align: left;
@@ -325,11 +288,30 @@ const ONBOARDING_UI_STYLES = `
325
288
  color: #000000;
326
289
  }
327
290
 
291
+ .onboarding-theme-light .onboarding-input:-webkit-autofill,
292
+ .onboarding-theme-light .onboarding-input:-webkit-autofill:hover,
293
+ .onboarding-theme-light .onboarding-input:-webkit-autofill:focus,
294
+ .onboarding-theme-light .onboarding-input:-webkit-autofill:active {
295
+ -webkit-box-shadow: 0 0 0 30px #ffffff inset !important;
296
+ -webkit-text-fill-color: #111827 !important;
297
+ transition: background-color 5000s ease-in-out 0s;
298
+ }
299
+
328
300
  .onboarding-theme-dark .onboarding-input {
329
301
  background-color: #374151;
330
302
  color: #ffffff;
331
303
  }
332
304
 
305
+ .onboarding-theme-dark .onboarding-input:-webkit-autofill,
306
+ .onboarding-theme-dark .onboarding-input:-webkit-autofill:hover,
307
+ .onboarding-theme-dark .onboarding-input:-webkit-autofill:focus,
308
+ .onboarding-theme-dark .onboarding-input:-webkit-autofill:active {
309
+ -webkit-box-shadow: 0 0 0 30px #374151 inset !important;
310
+ -webkit-text-fill-color: #ffffff !important;
311
+ color: #ffffff !important;
312
+ transition: background-color 5000s ease-in-out 0s;
313
+ }
314
+
333
315
  .onboarding-input:focus {
334
316
  outline: none;
335
317
  }
@@ -349,7 +331,7 @@ const ONBOARDING_UI_STYLES = `
349
331
  .onboarding-theme-dark .onboarding-input:focus {
350
332
  border-color: #9ca3af;
351
333
  box-shadow: 0 0 0 3px rgba(156, 163, 175, 0.2);
352
- background-color: #4b5563;
334
+ background-color: #374151;
353
335
  color: #ffffff;
354
336
  }
355
337
 
@@ -441,7 +423,7 @@ const ONBOARDING_UI_STYLES = `
441
423
  align-items: center;
442
424
  justify-content: center;
443
425
  gap: 8px;
444
- margin-bottom: 12px;
426
+ margin-bottom: 6px;
445
427
  letter-spacing: -0.01em;
446
428
  line-height: 1.5;
447
429
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
@@ -643,7 +625,7 @@ const ONBOARDING_UI_STYLES = `
643
625
  .onboarding-divider {
644
626
  display: flex;
645
627
  align-items: center;
646
- margin: 20px 0;
628
+ margin: 10px 0;
647
629
  position: relative;
648
630
  }
649
631
 
@@ -734,38 +716,54 @@ const ONBOARDING_UI_STYLES = `
734
716
  }
735
717
 
736
718
  .onboarding-otp-icon-container {
737
- width: 72px;
738
- height: 72px;
719
+ width: 64px;
720
+ height: 64px;
739
721
  border-radius: 50%;
740
722
  display: flex;
741
723
  align-items: center;
742
724
  justify-content: center;
743
- margin-bottom: 20px;
725
+ margin-bottom: 24px;
744
726
  position: relative;
727
+ background: transparent;
728
+ border: 3px solid #eef2ff;
745
729
  }
746
730
 
747
- .onboarding-theme-light .onboarding-otp-icon-container {
748
- background: linear-gradient(135deg, rgba(17, 24, 39, 0.1) 0%, rgba(17, 24, 39, 0.05) 100%);
731
+ .onboarding-otp-icon-container::after {
732
+ content: '';
733
+ position: absolute;
734
+ top: -3px;
735
+ left: -3px;
736
+ right: -3px;
737
+ bottom: -3px;
738
+ border-radius: 50%;
739
+ border: 3px solid transparent;
740
+ border-top-color: #363ff9;
741
+ animation: onboarding-spin 2s linear infinite;
742
+ }
743
+
744
+ @keyframes onboarding-spin {
745
+ 0% { transform: rotate(0deg); }
746
+ 100% { transform: rotate(360deg); }
749
747
  }
750
748
 
751
749
  .onboarding-theme-dark .onboarding-otp-icon-container {
752
- background: linear-gradient(135deg, rgba(156, 163, 175, 0.2) 0%, rgba(156, 163, 175, 0.1) 100%);
750
+ border-color: rgba(156, 163, 175, 0.2);
753
751
  }
754
752
 
755
753
  .onboarding-otp-icon-inner {
756
- width: 48px;
757
- height: 48px;
758
- background-color: #dc2626;
759
- border-radius: 10px;
754
+ width: 100%;
755
+ height: 100%;
756
+ background-color: transparent;
760
757
  display: flex;
761
758
  align-items: center;
762
759
  justify-content: center;
760
+ z-index: 1;
763
761
  }
764
762
 
765
763
  .onboarding-otp-icon {
766
- width: 24px;
767
- height: 24px;
768
- color: #ffffff;
764
+ width: 28px;
765
+ height: 28px;
766
+ color: #363ff9;
769
767
  }
770
768
 
771
769
  .onboarding-otp-title {
@@ -944,7 +942,7 @@ const ONBOARDING_UI_STYLES = `
944
942
  }
945
943
 
946
944
  .onboarding-passkey-signup-link {
947
- text-decoration: none;
945
+ text-decoration: underline;
948
946
  cursor: pointer;
949
947
  font-size: 14px;
950
948
  font-weight: 500;
@@ -955,22 +953,14 @@ const ONBOARDING_UI_STYLES = `
955
953
  }
956
954
 
957
955
  .onboarding-theme-light .onboarding-passkey-signup-link {
958
- color: #111827;
959
- }
956
+ color: #2170f5;
957
+ }
960
958
 
961
- .onboarding-theme-light .onboarding-passkey-signup-link:hover {
962
- color: #1f2937;
963
- text-decoration: underline;
964
- }
965
959
 
966
960
  .onboarding-theme-dark .onboarding-passkey-signup-link {
967
- color: #9ca3af;
968
- }
961
+ color: #2170f5;
962
+ }
969
963
 
970
- .onboarding-theme-dark .onboarding-passkey-signup-link:hover {
971
- color: #d1d5db;
972
- text-decoration: underline;
973
- }
974
964
  `;
975
965
  /**
976
966
  * OnboardingUI Class
@@ -1002,7 +992,6 @@ export class OnboardingUIWeb {
1002
992
  errorElement = null;
1003
993
  otpGroup = null;
1004
994
  otpVerificationScreen = null;
1005
- closeButton = null;
1006
995
  resendButton = null;
1007
996
  socialGrid = null;
1008
997
  externalWalletContainer = null;
@@ -1010,8 +999,8 @@ export class OnboardingUIWeb {
1010
999
  divider = null;
1011
1000
  footer = null;
1012
1001
  verifyButton = null;
1013
- email = '';
1014
- otp = '';
1002
+ email = "";
1003
+ otp = "";
1015
1004
  otpSent = false;
1016
1005
  loading = false;
1017
1006
  activeButton = null;
@@ -1020,15 +1009,14 @@ export class OnboardingUIWeb {
1020
1009
  externalWalletsEnabled = false;
1021
1010
  constructor(config, externalWalletsEnabled = false) {
1022
1011
  this.externalWalletsEnabled = externalWalletsEnabled;
1023
- const defaultTheme = config.theme || 'light';
1012
+ const defaultTheme = config.theme || "light";
1024
1013
  this.config = {
1025
1014
  theme: defaultTheme,
1026
1015
  showFooter: config.showFooter !== false,
1027
- className: config.className || '',
1016
+ className: config.className || "",
1028
1017
  modal: config.modal !== false,
1029
1018
  closeOnBackdropClick: config.closeOnBackdropClick !== false,
1030
- showCloseButton: config.showCloseButton !== false,
1031
- onboardTitle: config.onboardTitle || 'Sign in',
1019
+ onboardTitle: config.onboardTitle || "Sign In",
1032
1020
  handleUrlParams: config.handleUrlParams !== false,
1033
1021
  ...config,
1034
1022
  };
@@ -1039,10 +1027,10 @@ export class OnboardingUIWeb {
1039
1027
  */
1040
1028
  showExternalWallets() {
1041
1029
  if (this.externalWalletContainer) {
1042
- this.externalWalletContainer.style.display = '';
1030
+ this.externalWalletContainer.style.display = "";
1043
1031
  }
1044
1032
  if (this.externalWalletDivider) {
1045
- this.externalWalletDivider.style.display = '';
1033
+ this.externalWalletDivider.style.display = "";
1046
1034
  }
1047
1035
  }
1048
1036
  /**
@@ -1059,25 +1047,29 @@ export class OnboardingUIWeb {
1059
1047
  * Check URL parameters for social login callbacks
1060
1048
  */
1061
1049
  checkUrlParams() {
1062
- if (typeof window === 'undefined')
1050
+ if (typeof window === "undefined")
1063
1051
  return;
1064
1052
  if (!this.config.handleUrlParams)
1065
1053
  return;
1066
1054
  const params = new URLSearchParams(window.location.search);
1067
- const success = params.get('success');
1068
- const error = params.get('error');
1069
- const accessToken = params.get('accessToken');
1070
- const provider = params.get('provider') || params.get('authProvider');
1055
+ const success = params.get("success");
1056
+ const error = params.get("error");
1057
+ const accessToken = params.get("accessToken");
1058
+ const provider = params.get("provider") || params.get("authProvider");
1071
1059
  // Helper to extract provider from accessToken JWT
1072
1060
  const getAuthProviderFromToken = (token) => {
1073
1061
  try {
1074
- const base64Url = token.split('.')[1];
1075
- const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
1076
- const jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function (c) {
1077
- return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
1078
- }).join(''));
1062
+ const base64Url = token.split(".")[1];
1063
+ const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
1064
+ const jsonPayload = decodeURIComponent(window
1065
+ .atob(base64)
1066
+ .split("")
1067
+ .map(function (c) {
1068
+ return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
1069
+ })
1070
+ .join(""));
1079
1071
  const payload = JSON.parse(jsonPayload);
1080
- return (payload.authProvider || payload.provider || '').toLowerCase();
1072
+ return (payload.authProvider || payload.provider || "").toLowerCase();
1081
1073
  }
1082
1074
  catch (e) {
1083
1075
  return null;
@@ -1088,10 +1080,14 @@ export class OnboardingUIWeb {
1088
1080
  if (!detectedProvider && accessToken) {
1089
1081
  detectedProvider = getAuthProviderFromToken(accessToken);
1090
1082
  }
1091
- const isOAuthCallback = detectedProvider && (detectedProvider === 'google' || detectedProvider === 'discord' || detectedProvider === 'twitter' || detectedProvider === 'x');
1092
- const hasOAuthParams = isOAuthCallback || (success === 'true' && !!accessToken);
1083
+ const isOAuthCallback = detectedProvider &&
1084
+ (detectedProvider === "google" ||
1085
+ detectedProvider === "discord" ||
1086
+ detectedProvider === "twitter" ||
1087
+ detectedProvider === "x");
1088
+ const hasOAuthParams = isOAuthCallback || (success === "true" && !!accessToken);
1093
1089
  // If success=true and it's an OAuth callback (Google, Discord, Twitter), show loading modal with header and footer
1094
- if (success === 'true' && hasOAuthParams) {
1090
+ if (success === "true" && hasOAuthParams) {
1095
1091
  // Show loading modal immediately - it creates its own overlay
1096
1092
  // Use requestAnimationFrame + setTimeout to ensure DOM is ready
1097
1093
  requestAnimationFrame(() => {
@@ -1103,12 +1099,12 @@ export class OnboardingUIWeb {
1103
1099
  return;
1104
1100
  }
1105
1101
  // Check login source to decide if we should handle this (for errors)
1106
- const source = localStorage.getItem('abstraxn_login_source');
1102
+ const source = localStorage.getItem("abstraxn_login_source");
1107
1103
  const isModal = this.config.modal;
1108
1104
  if (source) {
1109
- if (source === 'modal' && !isModal)
1105
+ if (source === "modal" && !isModal)
1110
1106
  return; // Modal initiated, I am Inline -> Ignore
1111
- if (source === 'inline' && isModal)
1107
+ if (source === "inline" && isModal)
1112
1108
  return; // Inline initiated, I am Modal -> Ignore
1113
1109
  }
1114
1110
  else {
@@ -1141,77 +1137,77 @@ export class OnboardingUIWeb {
1141
1137
  return;
1142
1138
  // Hide loading modal if it exists (for inline components)
1143
1139
  this.hideLoadingModal();
1144
- const card = this.rootElement.querySelector('.onboarding-card');
1140
+ const card = this.rootElement.querySelector(".onboarding-card");
1145
1141
  if (!card)
1146
1142
  return;
1147
1143
  // Add error mode class to card
1148
- card.classList.add('onboarding-mode-error');
1149
- card.classList.remove('onboarding-mode-loading');
1144
+ card.classList.add("onboarding-mode-error");
1145
+ card.classList.remove("onboarding-mode-loading");
1150
1146
  // Create or show error container
1151
- let errorContainer = this.rootElement.querySelector('.onboarding-error-container');
1147
+ let errorContainer = this.rootElement.querySelector(".onboarding-error-container");
1152
1148
  if (!errorContainer) {
1153
- errorContainer = this.createElement('div', {
1154
- className: 'onboarding-error-container',
1155
- style: 'display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px 0; text-align: center;',
1149
+ errorContainer = this.createElement("div", {
1150
+ className: "onboarding-error-container",
1151
+ style: "display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px 0; text-align: center;",
1156
1152
  });
1157
1153
  // Error Icon
1158
- const iconContainer = this.createElement('div', {
1159
- style: 'width: 64px; height: 64px; background-color: #fee2e2; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-bottom: 20px;',
1154
+ const iconContainer = this.createElement("div", {
1155
+ style: "width: 64px; height: 64px; background-color: #fee2e2; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-bottom: 20px;",
1160
1156
  });
1161
1157
  // Dark mode adjustment for icon container
1162
- if (this.config.theme === 'dark') {
1163
- iconContainer.style.backgroundColor = 'rgba(220, 38, 38, 0.2)';
1164
- }
1165
- const iconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
1166
- iconSvg.setAttribute('width', '32');
1167
- iconSvg.setAttribute('height', '32');
1168
- iconSvg.setAttribute('viewBox', '0 0 24 24');
1169
- iconSvg.setAttribute('fill', 'none');
1170
- iconSvg.setAttribute('stroke', '#dc2626');
1171
- iconSvg.setAttribute('stroke-width', '2');
1172
- iconSvg.setAttribute('stroke-linecap', 'round');
1173
- iconSvg.setAttribute('stroke-linejoin', 'round');
1174
- const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
1175
- circle.setAttribute('cx', '12');
1176
- circle.setAttribute('cy', '12');
1177
- circle.setAttribute('r', '10');
1158
+ if (this.config.theme === "dark") {
1159
+ iconContainer.style.backgroundColor = "rgba(220, 38, 38, 0.2)";
1160
+ }
1161
+ const iconSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
1162
+ iconSvg.setAttribute("width", "32");
1163
+ iconSvg.setAttribute("height", "32");
1164
+ iconSvg.setAttribute("viewBox", "0 0 24 24");
1165
+ iconSvg.setAttribute("fill", "none");
1166
+ iconSvg.setAttribute("stroke", "#dc2626");
1167
+ iconSvg.setAttribute("stroke-width", "2");
1168
+ iconSvg.setAttribute("stroke-linecap", "round");
1169
+ iconSvg.setAttribute("stroke-linejoin", "round");
1170
+ const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
1171
+ circle.setAttribute("cx", "12");
1172
+ circle.setAttribute("cy", "12");
1173
+ circle.setAttribute("r", "10");
1178
1174
  iconSvg.appendChild(circle);
1179
- const line1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
1180
- line1.setAttribute('x1', '12');
1181
- line1.setAttribute('y1', '8');
1182
- line1.setAttribute('x2', '12');
1183
- line1.setAttribute('y2', '12');
1175
+ const line1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
1176
+ line1.setAttribute("x1", "12");
1177
+ line1.setAttribute("y1", "8");
1178
+ line1.setAttribute("x2", "12");
1179
+ line1.setAttribute("y2", "12");
1184
1180
  iconSvg.appendChild(line1);
1185
- const line2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
1186
- line2.setAttribute('x1', '12');
1187
- line2.setAttribute('y1', '16');
1188
- line2.setAttribute('x2', '12.01');
1189
- line2.setAttribute('y2', '16');
1181
+ const line2 = document.createElementNS("http://www.w3.org/2000/svg", "line");
1182
+ line2.setAttribute("x1", "12");
1183
+ line2.setAttribute("y1", "16");
1184
+ line2.setAttribute("x2", "12.01");
1185
+ line2.setAttribute("y2", "16");
1190
1186
  iconSvg.appendChild(line2);
1191
1187
  iconContainer.appendChild(iconSvg);
1192
1188
  errorContainer.appendChild(iconContainer);
1193
1189
  // Title
1194
- const title = this.createElement('h3', {
1195
- textContent: 'Authentication Failed',
1196
- style: 'font-size: 20px; font-weight: 600; margin: 0 0 12px 0; color: inherit;',
1190
+ const title = this.createElement("h3", {
1191
+ textContent: "Authentication Failed",
1192
+ style: "font-size: 20px; font-weight: 600; margin: 0 0 12px 0; color: inherit;",
1197
1193
  });
1198
1194
  errorContainer.appendChild(title);
1199
1195
  // Message
1200
- const msg = this.createElement('p', {
1196
+ const msg = this.createElement("p", {
1201
1197
  textContent: message,
1202
- style: 'font-size: 14px; color: #6b7280; margin: 0 0 24px 0; line-height: 1.5; max-width: 100%; word-break: break-word;',
1198
+ style: "font-size: 14px; color: #6b7280; margin: 0 0 24px 0; line-height: 1.5; max-width: 100%; word-break: break-word;",
1203
1199
  });
1204
- if (this.config.theme === 'dark') {
1205
- msg.style.color = '#9ca3af';
1200
+ if (this.config.theme === "dark") {
1201
+ msg.style.color = "#9ca3af";
1206
1202
  }
1207
1203
  errorContainer.appendChild(msg);
1208
1204
  // OK Button
1209
- const okButton = this.createElement('button', {
1210
- className: 'onboarding-button onboarding-button-primary',
1211
- textContent: 'OK',
1212
- style: 'width: 100%; max-width: 200px;',
1205
+ const okButton = this.createElement("button", {
1206
+ className: "onboarding-button onboarding-button-primary",
1207
+ textContent: "OK",
1208
+ style: "width: 100%; max-width: 200px;",
1213
1209
  });
1214
- okButton.addEventListener('click', () => {
1210
+ okButton.addEventListener("click", () => {
1215
1211
  if (this.config.modal) {
1216
1212
  this.close();
1217
1213
  }
@@ -1220,7 +1216,7 @@ export class OnboardingUIWeb {
1220
1216
  }
1221
1217
  // Also clear URL params to prevent showing error again on refresh
1222
1218
  const url = new URL(window.location.href);
1223
- url.searchParams.delete('error');
1219
+ url.searchParams.delete("error");
1224
1220
  window.history.replaceState({}, document.title, url.toString());
1225
1221
  });
1226
1222
  errorContainer.appendChild(okButton);
@@ -1228,10 +1224,10 @@ export class OnboardingUIWeb {
1228
1224
  }
1229
1225
  else {
1230
1226
  // Update message if container exists
1231
- const msgEl = errorContainer.querySelector('p');
1227
+ const msgEl = errorContainer.querySelector("p");
1232
1228
  if (msgEl)
1233
1229
  msgEl.textContent = message;
1234
- errorContainer.style.display = 'flex';
1230
+ errorContainer.style.display = "flex";
1235
1231
  }
1236
1232
  // Move footer to the bottom
1237
1233
  if (this.footer) {
@@ -1251,7 +1247,7 @@ export class OnboardingUIWeb {
1251
1247
  }
1252
1248
  // Hide the main modal overlay to prevent showing wallet options below loading screen
1253
1249
  if (this.modalOverlay) {
1254
- this.modalOverlay.style.display = 'none';
1250
+ this.modalOverlay.style.display = "none";
1255
1251
  }
1256
1252
  // Show loading modal overlay instead (with higher z-index)
1257
1253
  this.showLoadingModal();
@@ -1262,17 +1258,17 @@ export class OnboardingUIWeb {
1262
1258
  */
1263
1259
  showLoadingModal() {
1264
1260
  // Hide any other modals that might be showing (wallet selection, etc.)
1265
- const otherModals = document.querySelectorAll('.onboarding-modal-overlay, .external-wallet-modal, .wallet-modal-overlay');
1261
+ const otherModals = document.querySelectorAll(".onboarding-modal-overlay, .external-wallet-modal, .wallet-modal-overlay");
1266
1262
  otherModals.forEach((modal) => {
1267
- if (modal.id !== 'onboarding-loading-modal-overlay') {
1268
- modal.style.display = 'none';
1263
+ if (modal.id !== "onboarding-loading-modal-overlay") {
1264
+ modal.style.display = "none";
1269
1265
  }
1270
1266
  });
1271
1267
  // Create modal overlay if it doesn't exist
1272
- let loadingModalOverlay = document.getElementById('onboarding-loading-modal-overlay');
1268
+ let loadingModalOverlay = document.getElementById("onboarding-loading-modal-overlay");
1273
1269
  if (!loadingModalOverlay) {
1274
- loadingModalOverlay = this.createElement('div', {
1275
- id: 'onboarding-loading-modal-overlay',
1270
+ loadingModalOverlay = this.createElement("div", {
1271
+ id: "onboarding-loading-modal-overlay",
1276
1272
  style: `
1277
1273
  position: fixed;
1278
1274
  top: 0;
@@ -1287,10 +1283,10 @@ export class OnboardingUIWeb {
1287
1283
  backdrop-filter: blur(4px);
1288
1284
  `,
1289
1285
  });
1290
- const loadingCard = this.createElement('div', {
1286
+ const loadingCard = this.createElement("div", {
1291
1287
  className: `onboarding-card onboarding-theme-${this.config.theme}`,
1292
1288
  style: `
1293
- background: ${this.config.theme === 'dark' ? '#1f2937' : 'white'};
1289
+ background: ${this.config.theme === "dark" ? "#1f2937" : "white"};
1294
1290
  border-radius: 16px;
1295
1291
  padding: 32px 32px 28px;
1296
1292
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
@@ -1306,31 +1302,35 @@ export class OnboardingUIWeb {
1306
1302
  `,
1307
1303
  });
1308
1304
  // Header with logo and title
1309
- const header = this.createElement('div', {
1310
- className: 'onboarding-header',
1311
- style: 'display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; margin-bottom: 32px;',
1305
+ const header = this.createElement("div", {
1306
+ className: "onboarding-header",
1307
+ style: "display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; margin-bottom: 32px;",
1308
+ });
1309
+ const logoSection = this.createElement("div", {
1310
+ className: "onboarding-logo-section",
1312
1311
  });
1313
- const logoSection = this.createElement('div', { className: 'onboarding-logo-section' });
1314
1312
  if (this.config.logo) {
1315
- const logoContainer = this.createElement('div', { className: 'onboarding-logo-container' });
1316
- const logoImg = this.createElement('img', {
1313
+ const logoContainer = this.createElement("div", {
1314
+ className: "onboarding-logo-container",
1315
+ });
1316
+ const logoImg = this.createElement("img", {
1317
1317
  src: this.config.logo,
1318
- alt: 'Abstraxn',
1319
- className: 'onboarding-logo-img',
1318
+ alt: "Abstraxn",
1319
+ className: "onboarding-logo-img",
1320
1320
  });
1321
1321
  logoContainer.appendChild(logoImg);
1322
1322
  logoSection.appendChild(logoContainer);
1323
1323
  }
1324
1324
  header.appendChild(logoSection);
1325
1325
  // Add title
1326
- const title = this.createElement('h1', {
1327
- className: 'onboarding-title',
1328
- textContent: this.config.onboardTitle || 'Sign in',
1326
+ const title = this.createElement("h1", {
1327
+ className: "onboarding-title",
1328
+ textContent: this.config.onboardTitle || "Sign In",
1329
1329
  style: `
1330
1330
  font-size: 24px;
1331
1331
  font-weight: 600;
1332
1332
  margin: 0;
1333
- color: ${this.config.theme === 'dark' ? '#ffffff' : '#111827'};
1333
+ color: ${this.config.theme === "dark" ? "#ffffff" : "#111827"};
1334
1334
  text-align: center;
1335
1335
  margin-bottom: 0;
1336
1336
  letter-spacing: -0.01em;
@@ -1340,10 +1340,12 @@ export class OnboardingUIWeb {
1340
1340
  header.appendChild(title);
1341
1341
  loadingCard.appendChild(header);
1342
1342
  // Spinner
1343
- const spinnerColor = this.config.theme === 'dark' ? '#9ca3af' : '#111827';
1344
- const spinnerBorderColor = this.config.theme === 'dark' ? 'rgba(156, 163, 175, 0.2)' : 'rgba(17, 24, 39, 0.1)';
1345
- const spinner = this.createElement('div', {
1346
- className: 'onboarding-loading-spinner',
1343
+ const spinnerColor = this.config.theme === "dark" ? "#9ca3af" : "#111827";
1344
+ const spinnerBorderColor = this.config.theme === "dark"
1345
+ ? "rgba(156, 163, 175, 0.2)"
1346
+ : "rgba(17, 24, 39, 0.1)";
1347
+ const spinner = this.createElement("div", {
1348
+ className: "onboarding-loading-spinner",
1347
1349
  style: `
1348
1350
  width: 40px;
1349
1351
  height: 40px;
@@ -1355,9 +1357,9 @@ export class OnboardingUIWeb {
1355
1357
  `,
1356
1358
  });
1357
1359
  // Add keyframes if not exists
1358
- if (!document.getElementById('onboarding-spin-style')) {
1359
- const style = document.createElement('style');
1360
- style.id = 'onboarding-spin-style';
1360
+ if (!document.getElementById("onboarding-spin-style")) {
1361
+ const style = document.createElement("style");
1362
+ style.id = "onboarding-spin-style";
1361
1363
  style.textContent = `
1362
1364
  @keyframes onboarding-spin {
1363
1365
  to { transform: rotate(360deg); }
@@ -1366,11 +1368,11 @@ export class OnboardingUIWeb {
1366
1368
  document.head.appendChild(style);
1367
1369
  }
1368
1370
  // Text
1369
- const text = this.createElement('p', {
1370
- textContent: 'Verifying login...',
1371
+ const text = this.createElement("p", {
1372
+ textContent: "Verifying login...",
1371
1373
  style: `
1372
1374
  font-size: 16px;
1373
- color: ${this.config.theme === 'dark' ? '#e5e7eb' : '#374151'};
1375
+ color: ${this.config.theme === "dark" ? "#e5e7eb" : "#374151"};
1374
1376
  margin: 0;
1375
1377
  font-weight: 500;
1376
1378
  `,
@@ -1379,23 +1381,30 @@ export class OnboardingUIWeb {
1379
1381
  loadingCard.appendChild(text);
1380
1382
  // Footer "Powered by Abstraxn"
1381
1383
  if (this.config.showFooter !== false) {
1382
- const textColor = this.config.colors?.text || (this.config.theme === 'dark' ? '#9ca3af' : '#6b7280');
1383
- const brandColor = this.config.colors?.text || (this.config.theme === 'dark' ? '#e5e7eb' : '#374151');
1384
- const footer = this.createElement('div', { className: 'onboarding-footer' });
1385
- const footerText = this.createElement('p', {
1386
- className: 'onboarding-footer-text',
1384
+ const textColor = this.config.colors?.text ||
1385
+ (this.config.theme === "dark" ? "#9ca3af" : "#6b7280");
1386
+ const brandColor = this.config.colors?.text ||
1387
+ (this.config.theme === "dark" ? "#e5e7eb" : "#374151");
1388
+ const footer = this.createElement("div", {
1389
+ className: "onboarding-footer",
1390
+ });
1391
+ const footerText = this.createElement("p", {
1392
+ className: "onboarding-footer-text",
1387
1393
  style: `color: ${textColor}; display: flex; align-items: center; gap: 6px; justify-content: center; font-size: 11px; margin: 0;`,
1388
1394
  });
1389
- const poweredBySpan = this.createElement('span', { textContent: 'Powered by', style: `color: ${textColor};` });
1395
+ const poweredBySpan = this.createElement("span", {
1396
+ textContent: "Powered by",
1397
+ style: `color: ${textColor};`,
1398
+ });
1390
1399
  footerText.appendChild(poweredBySpan);
1391
- const brandContainer = this.createElement('a', {
1392
- href: 'https://www.abstraxn.com/',
1393
- target: '_blank',
1394
- rel: 'noopener noreferrer',
1395
- style: 'display: inline-flex; align-items: center; gap: 6px; text-decoration: none; cursor: pointer;',
1396
- 'aria-label': 'Visit Abstraxn website',
1400
+ const brandContainer = this.createElement("a", {
1401
+ href: "https://www.abstraxn.com/",
1402
+ target: "_blank",
1403
+ rel: "noopener noreferrer",
1404
+ style: "display: inline-flex; align-items: center; gap: 6px; text-decoration: none; cursor: pointer;",
1405
+ "aria-label": "Visit Abstraxn website",
1397
1406
  });
1398
- const logoSvg = this.createElement('span', {
1407
+ const logoSvg = this.createElement("span", {
1399
1408
  innerHTML: `
1400
1409
  <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none" style="width: 20px; height: 20px; display: inline-block; vertical-align: middle;">
1401
1410
  <path d="M47.9082 37.191L23.9541 23.553L0 9.91504L37.7436 -8.13502e-06L47.9082 37.191Z" fill="url(#paint0_linear_1242_781)"/>
@@ -1414,11 +1423,11 @@ export class OnboardingUIWeb {
1414
1423
  </defs>
1415
1424
  </svg>
1416
1425
  `,
1417
- style: 'display: inline-flex; align-items: center;',
1426
+ style: "display: inline-flex; align-items: center;",
1418
1427
  });
1419
1428
  brandContainer.appendChild(logoSvg);
1420
- const brandText = this.createElement('span', {
1421
- textContent: 'abstraxn',
1429
+ const brandText = this.createElement("span", {
1430
+ textContent: "abstraxn",
1422
1431
  style: `color: ${brandColor}; font-weight: 700; letter-spacing: 0.2px;`,
1423
1432
  });
1424
1433
  brandContainer.appendChild(brandText);
@@ -1431,31 +1440,31 @@ export class OnboardingUIWeb {
1431
1440
  }
1432
1441
  else {
1433
1442
  // Ensure modal is visible
1434
- loadingModalOverlay.style.display = 'flex';
1435
- loadingModalOverlay.style.visibility = 'visible';
1436
- loadingModalOverlay.style.opacity = '1';
1437
- loadingModalOverlay.style.zIndex = '9999999';
1443
+ loadingModalOverlay.style.display = "flex";
1444
+ loadingModalOverlay.style.visibility = "visible";
1445
+ loadingModalOverlay.style.opacity = "1";
1446
+ loadingModalOverlay.style.zIndex = "9999999";
1438
1447
  }
1439
1448
  // Prevent body scroll
1440
- document.body.style.overflow = 'hidden';
1449
+ document.body.style.overflow = "hidden";
1441
1450
  // Force visibility (defensive check)
1442
1451
  if (loadingModalOverlay) {
1443
- loadingModalOverlay.style.display = 'flex';
1444
- loadingModalOverlay.style.visibility = 'visible';
1445
- loadingModalOverlay.style.opacity = '1';
1446
- loadingModalOverlay.style.zIndex = '9999999';
1452
+ loadingModalOverlay.style.display = "flex";
1453
+ loadingModalOverlay.style.visibility = "visible";
1454
+ loadingModalOverlay.style.opacity = "1";
1455
+ loadingModalOverlay.style.zIndex = "9999999";
1447
1456
  }
1448
1457
  }
1449
1458
  /**
1450
1459
  * Hide loading modal overlay
1451
1460
  */
1452
1461
  hideLoadingModal() {
1453
- const loadingModalOverlay = document.getElementById('onboarding-loading-modal-overlay');
1462
+ const loadingModalOverlay = document.getElementById("onboarding-loading-modal-overlay");
1454
1463
  if (loadingModalOverlay) {
1455
- loadingModalOverlay.style.display = 'none';
1456
- loadingModalOverlay.style.visibility = 'hidden';
1457
- loadingModalOverlay.style.opacity = '0';
1458
- document.body.style.overflow = '';
1464
+ loadingModalOverlay.style.display = "none";
1465
+ loadingModalOverlay.style.visibility = "hidden";
1466
+ loadingModalOverlay.style.opacity = "0";
1467
+ document.body.style.overflow = "";
1459
1468
  }
1460
1469
  }
1461
1470
  /**
@@ -1464,21 +1473,21 @@ export class OnboardingUIWeb {
1464
1473
  showErrorModal(message) {
1465
1474
  // Helper function to close error modal
1466
1475
  const closeErrorModal = () => {
1467
- const overlay = document.getElementById('onboarding-error-modal-overlay');
1476
+ const overlay = document.getElementById("onboarding-error-modal-overlay");
1468
1477
  if (overlay) {
1469
- overlay.style.display = 'none';
1470
- document.body.style.overflow = '';
1478
+ overlay.style.display = "none";
1479
+ document.body.style.overflow = "";
1471
1480
  // Clear URL params
1472
1481
  const url = new URL(window.location.href);
1473
- url.searchParams.delete('error');
1482
+ url.searchParams.delete("error");
1474
1483
  window.history.replaceState({}, document.title, url.toString());
1475
1484
  }
1476
1485
  };
1477
1486
  // Create modal overlay if it doesn't exist
1478
- let errorModalOverlay = document.getElementById('onboarding-error-modal-overlay');
1487
+ let errorModalOverlay = document.getElementById("onboarding-error-modal-overlay");
1479
1488
  if (!errorModalOverlay) {
1480
- errorModalOverlay = this.createElement('div', {
1481
- id: 'onboarding-error-modal-overlay',
1489
+ errorModalOverlay = this.createElement("div", {
1490
+ id: "onboarding-error-modal-overlay",
1482
1491
  style: `
1483
1492
  position: fixed;
1484
1493
  top: 0;
@@ -1494,15 +1503,15 @@ export class OnboardingUIWeb {
1494
1503
  `,
1495
1504
  });
1496
1505
  // Add backdrop click handler to close modal
1497
- errorModalOverlay.addEventListener('click', (e) => {
1506
+ errorModalOverlay.addEventListener("click", (e) => {
1498
1507
  if (e.target === errorModalOverlay) {
1499
1508
  closeErrorModal();
1500
1509
  }
1501
1510
  });
1502
- const errorCard = this.createElement('div', {
1511
+ const errorCard = this.createElement("div", {
1503
1512
  className: `onboarding-card onboarding-theme-${this.config.theme}`,
1504
1513
  style: `
1505
- background: ${this.config.theme === 'dark' ? '#1f2937' : 'white'};
1514
+ background: ${this.config.theme === "dark" ? "#1f2937" : "white"};
1506
1515
  border-radius: 16px;
1507
1516
  padding: 40px;
1508
1517
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
@@ -1519,21 +1528,25 @@ export class OnboardingUIWeb {
1519
1528
  `,
1520
1529
  });
1521
1530
  // Prevent clicks on card from closing modal
1522
- errorCard.addEventListener('click', (e) => {
1531
+ errorCard.addEventListener("click", (e) => {
1523
1532
  e.stopPropagation();
1524
1533
  });
1525
1534
  // Header with logo
1526
- const header = this.createElement('div', {
1527
- className: 'onboarding-header',
1528
- style: 'display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; margin-bottom: 24px;',
1535
+ const header = this.createElement("div", {
1536
+ className: "onboarding-header",
1537
+ style: "display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; margin-bottom: 24px;",
1538
+ });
1539
+ const logoSection = this.createElement("div", {
1540
+ className: "onboarding-logo-section",
1529
1541
  });
1530
- const logoSection = this.createElement('div', { className: 'onboarding-logo-section' });
1531
1542
  if (this.config.logo) {
1532
- const logoContainer = this.createElement('div', { className: 'onboarding-logo-container' });
1533
- const logoImg = this.createElement('img', {
1543
+ const logoContainer = this.createElement("div", {
1544
+ className: "onboarding-logo-container",
1545
+ });
1546
+ const logoImg = this.createElement("img", {
1534
1547
  src: this.config.logo,
1535
- alt: 'Abstraxn',
1536
- className: 'onboarding-logo-img',
1548
+ alt: "Abstraxn",
1549
+ className: "onboarding-logo-img",
1537
1550
  });
1538
1551
  logoContainer.appendChild(logoImg);
1539
1552
  logoSection.appendChild(logoContainer);
@@ -1541,79 +1554,86 @@ export class OnboardingUIWeb {
1541
1554
  header.appendChild(logoSection);
1542
1555
  errorCard.appendChild(header);
1543
1556
  // Error Icon
1544
- const iconContainer = this.createElement('div', {
1545
- style: 'width: 64px; height: 64px; background-color: #fee2e2; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-bottom: 20px;',
1546
- });
1547
- if (this.config.theme === 'dark') {
1548
- iconContainer.style.backgroundColor = 'rgba(220, 38, 38, 0.2)';
1549
- }
1550
- const iconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
1551
- iconSvg.setAttribute('width', '32');
1552
- iconSvg.setAttribute('height', '32');
1553
- iconSvg.setAttribute('viewBox', '0 0 24 24');
1554
- iconSvg.setAttribute('fill', 'none');
1555
- iconSvg.setAttribute('stroke', '#dc2626');
1556
- iconSvg.setAttribute('stroke-width', '2');
1557
- iconSvg.setAttribute('stroke-linecap', 'round');
1558
- iconSvg.setAttribute('stroke-linejoin', 'round');
1559
- const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
1560
- circle.setAttribute('cx', '12');
1561
- circle.setAttribute('cy', '12');
1562
- circle.setAttribute('r', '10');
1557
+ const iconContainer = this.createElement("div", {
1558
+ style: "width: 64px; height: 64px; background-color: #fee2e2; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-bottom: 20px;",
1559
+ });
1560
+ if (this.config.theme === "dark") {
1561
+ iconContainer.style.backgroundColor = "rgba(220, 38, 38, 0.2)";
1562
+ }
1563
+ const iconSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
1564
+ iconSvg.setAttribute("width", "32");
1565
+ iconSvg.setAttribute("height", "32");
1566
+ iconSvg.setAttribute("viewBox", "0 0 24 24");
1567
+ iconSvg.setAttribute("fill", "none");
1568
+ iconSvg.setAttribute("stroke", "#dc2626");
1569
+ iconSvg.setAttribute("stroke-width", "2");
1570
+ iconSvg.setAttribute("stroke-linecap", "round");
1571
+ iconSvg.setAttribute("stroke-linejoin", "round");
1572
+ const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
1573
+ circle.setAttribute("cx", "12");
1574
+ circle.setAttribute("cy", "12");
1575
+ circle.setAttribute("r", "10");
1563
1576
  iconSvg.appendChild(circle);
1564
- const line1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
1565
- line1.setAttribute('x1', '12');
1566
- line1.setAttribute('y1', '8');
1567
- line1.setAttribute('x2', '12');
1568
- line1.setAttribute('y2', '12');
1577
+ const line1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
1578
+ line1.setAttribute("x1", "12");
1579
+ line1.setAttribute("y1", "8");
1580
+ line1.setAttribute("x2", "12");
1581
+ line1.setAttribute("y2", "12");
1569
1582
  iconSvg.appendChild(line1);
1570
- const line2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
1571
- line2.setAttribute('x1', '12');
1572
- line2.setAttribute('y1', '16');
1573
- line2.setAttribute('x2', '12.01');
1574
- line2.setAttribute('y2', '16');
1583
+ const line2 = document.createElementNS("http://www.w3.org/2000/svg", "line");
1584
+ line2.setAttribute("x1", "12");
1585
+ line2.setAttribute("y1", "16");
1586
+ line2.setAttribute("x2", "12.01");
1587
+ line2.setAttribute("y2", "16");
1575
1588
  iconSvg.appendChild(line2);
1576
1589
  iconContainer.appendChild(iconSvg);
1577
1590
  errorCard.appendChild(iconContainer);
1578
1591
  // Title
1579
- const title = this.createElement('h3', {
1580
- textContent: 'Authentication Failed',
1581
- style: `font-size: 20px; font-weight: 600; margin: 0 0 12px 0; color: ${this.config.theme === 'dark' ? '#ffffff' : '#111827'};`,
1592
+ const title = this.createElement("h3", {
1593
+ textContent: "Authentication Failed",
1594
+ style: `font-size: 20px; font-weight: 600; margin: 0 0 12px 0; color: ${this.config.theme === "dark" ? "#ffffff" : "#111827"};`,
1582
1595
  });
1583
1596
  errorCard.appendChild(title);
1584
1597
  // Message
1585
- const msg = this.createElement('p', {
1598
+ const msg = this.createElement("p", {
1586
1599
  textContent: message,
1587
- style: `font-size: 14px; color: ${this.config.theme === 'dark' ? '#e5e7eb' : '#374151'}; margin: 0 0 24px 0; line-height: 1.5; max-width: 100%; word-break: break-word;`,
1600
+ style: `font-size: 14px; color: ${this.config.theme === "dark" ? "#e5e7eb" : "#374151"}; margin: 0 0 24px 0; line-height: 1.5; max-width: 100%; word-break: break-word;`,
1588
1601
  });
1589
1602
  errorCard.appendChild(msg);
1590
1603
  // OK Button
1591
- const okButton = this.createElement('button', {
1592
- className: 'onboarding-button onboarding-button-primary',
1593
- textContent: 'OK',
1594
- style: 'width: 100%; max-width: 200px;',
1604
+ const okButton = this.createElement("button", {
1605
+ className: "onboarding-button onboarding-button-primary",
1606
+ textContent: "OK",
1607
+ style: "width: 100%; max-width: 200px;",
1595
1608
  });
1596
- okButton.addEventListener('click', closeErrorModal);
1609
+ okButton.addEventListener("click", closeErrorModal);
1597
1610
  errorCard.appendChild(okButton);
1598
1611
  // Footer "Powered by Abstraxn"
1599
1612
  if (this.config.showFooter !== false) {
1600
- const textColor = this.config.colors?.text || (this.config.theme === 'dark' ? '#9ca3af' : '#6b7280');
1601
- const brandColor = this.config.colors?.text || (this.config.theme === 'dark' ? '#e5e7eb' : '#374151');
1602
- const footer = this.createElement('div', { className: 'onboarding-footer' });
1603
- const footerText = this.createElement('p', {
1604
- className: 'onboarding-footer-text',
1613
+ const textColor = this.config.colors?.text ||
1614
+ (this.config.theme === "dark" ? "#9ca3af" : "#6b7280");
1615
+ const brandColor = this.config.colors?.text ||
1616
+ (this.config.theme === "dark" ? "#e5e7eb" : "#374151");
1617
+ const footer = this.createElement("div", {
1618
+ className: "onboarding-footer",
1619
+ });
1620
+ const footerText = this.createElement("p", {
1621
+ className: "onboarding-footer-text",
1605
1622
  style: `color: ${textColor}; display: flex; align-items: center; gap: 6px; justify-content: center; font-size: 11px; margin: 0; margin-top: 24px;`,
1606
1623
  });
1607
- const poweredBySpan = this.createElement('span', { textContent: 'Powered by', style: `color: ${textColor};` });
1624
+ const poweredBySpan = this.createElement("span", {
1625
+ textContent: "Powered by",
1626
+ style: `color: ${textColor};`,
1627
+ });
1608
1628
  footerText.appendChild(poweredBySpan);
1609
- const brandContainer = this.createElement('a', {
1610
- href: 'https://www.abstraxn.com/',
1611
- target: '_blank',
1612
- rel: 'noopener noreferrer',
1613
- style: 'display: inline-flex; align-items: center; gap: 6px; text-decoration: none; cursor: pointer;',
1614
- 'aria-label': 'Visit Abstraxn website',
1629
+ const brandContainer = this.createElement("a", {
1630
+ href: "https://www.abstraxn.com/",
1631
+ target: "_blank",
1632
+ rel: "noopener noreferrer",
1633
+ style: "display: inline-flex; align-items: center; gap: 6px; text-decoration: none; cursor: pointer;",
1634
+ "aria-label": "Visit Abstraxn website",
1615
1635
  });
1616
- const logoSvg = this.createElement('span', {
1636
+ const logoSvg = this.createElement("span", {
1617
1637
  innerHTML: `
1618
1638
  <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none" style="width: 20px; height: 20px; display: inline-block; vertical-align: middle;">
1619
1639
  <path d="M47.9082 37.191L23.9541 23.553L0 9.91504L37.7436 -8.13502e-06L47.9082 37.191Z" fill="url(#paint0_linear_error_modal)"/>
@@ -1632,11 +1652,11 @@ export class OnboardingUIWeb {
1632
1652
  </defs>
1633
1653
  </svg>
1634
1654
  `,
1635
- style: 'display: inline-flex; align-items: center;',
1655
+ style: "display: inline-flex; align-items: center;",
1636
1656
  });
1637
1657
  brandContainer.appendChild(logoSvg);
1638
- const brandText = this.createElement('span', {
1639
- textContent: 'abstraxn',
1658
+ const brandText = this.createElement("span", {
1659
+ textContent: "abstraxn",
1640
1660
  style: `color: ${brandColor}; font-weight: 700; letter-spacing: 0.2px;`,
1641
1661
  });
1642
1662
  brandContainer.appendChild(brandText);
@@ -1649,13 +1669,13 @@ export class OnboardingUIWeb {
1649
1669
  }
1650
1670
  else {
1651
1671
  // Update message if overlay exists
1652
- const msgEl = errorModalOverlay.querySelector('p');
1672
+ const msgEl = errorModalOverlay.querySelector("p");
1653
1673
  if (msgEl)
1654
1674
  msgEl.textContent = message;
1655
- errorModalOverlay.style.display = 'flex';
1675
+ errorModalOverlay.style.display = "flex";
1656
1676
  }
1657
1677
  // Prevent body scroll
1658
- document.body.style.overflow = 'hidden';
1678
+ document.body.style.overflow = "hidden";
1659
1679
  }
1660
1680
  /**
1661
1681
  * Inject CSS styles into the document head (only once)
@@ -1665,20 +1685,20 @@ export class OnboardingUIWeb {
1665
1685
  return;
1666
1686
  }
1667
1687
  // Check if styles are already injected
1668
- const existingStyle = document.getElementById('onboarding-ui-styles');
1688
+ const existingStyle = document.getElementById("onboarding-ui-styles");
1669
1689
  if (existingStyle) {
1670
1690
  OnboardingUIWeb.stylesInjected = true;
1671
1691
  return;
1672
1692
  }
1673
1693
  // Create and inject style element
1674
- const styleElement = document.createElement('style');
1675
- styleElement.id = 'onboarding-ui-styles';
1694
+ const styleElement = document.createElement("style");
1695
+ styleElement.id = "onboarding-ui-styles";
1676
1696
  styleElement.textContent = ONBOARDING_UI_STYLES;
1677
1697
  document.head.appendChild(styleElement);
1678
1698
  // Inject custom CSS if provided
1679
1699
  if (this.config.customCSS) {
1680
- const customStyleElement = document.createElement('style');
1681
- customStyleElement.id = 'onboarding-ui-custom-styles';
1700
+ const customStyleElement = document.createElement("style");
1701
+ customStyleElement.id = "onboarding-ui-custom-styles";
1682
1702
  customStyleElement.textContent = this.config.customCSS;
1683
1703
  document.head.appendChild(customStyleElement);
1684
1704
  }
@@ -1688,8 +1708,8 @@ export class OnboardingUIWeb {
1688
1708
  }
1689
1709
  OnboardingUIWeb.stylesInjected = true;
1690
1710
  // Inject utility styles for loading/error modes
1691
- const utilityStyle = document.createElement('style');
1692
- utilityStyle.id = 'onboarding-utility-styles';
1711
+ const utilityStyle = document.createElement("style");
1712
+ utilityStyle.id = "onboarding-utility-styles";
1693
1713
  utilityStyle.textContent = `
1694
1714
  .onboarding-card.onboarding-mode-loading > *:not(.onboarding-loading-container):not(.onboarding-header):not(.onboarding-footer),
1695
1715
  .onboarding-card.onboarding-mode-error > *:not(.onboarding-error-container):not(.onboarding-header):not(.onboarding-footer) {
@@ -1705,9 +1725,9 @@ export class OnboardingUIWeb {
1705
1725
  if (!this.config.colors)
1706
1726
  return;
1707
1727
  const root = this.rootElement || document.documentElement;
1708
- const style = document.createElement('style');
1709
- style.id = 'onboarding-ui-colors';
1710
- let css = '';
1728
+ const style = document.createElement("style");
1729
+ style.id = "onboarding-ui-colors";
1730
+ let css = "";
1711
1731
  if (this.config.colors.primary) {
1712
1732
  css += `.onboarding-button-primary { background-color: ${this.config.colors.primary} !important; background: ${this.config.colors.primary} !important; }`;
1713
1733
  css += `.onboarding-footer-brand { color: ${this.config.colors.primary} !important; }`;
@@ -1726,7 +1746,7 @@ export class OnboardingUIWeb {
1726
1746
  css += `.onboarding-input { border-color: ${this.config.colors.border} !important; }`;
1727
1747
  }
1728
1748
  if (this.config.colors.error) {
1729
- css += `.onboarding-error { background-color: ${this.config.colors.error} !important; }`;
1749
+ css += `.onboarding-error { color: ${this.config.colors.error} !important; }`;
1730
1750
  }
1731
1751
  style.textContent = css;
1732
1752
  document.head.appendChild(style);
@@ -1741,7 +1761,7 @@ export class OnboardingUIWeb {
1741
1761
  }
1742
1762
  else {
1743
1763
  if (this.config.container) {
1744
- if (typeof this.config.container === 'string') {
1764
+ if (typeof this.config.container === "string") {
1745
1765
  this.container = document.querySelector(this.config.container);
1746
1766
  if (!this.container) {
1747
1767
  throw new Error(`Container element not found: ${this.config.container}`);
@@ -1775,41 +1795,23 @@ export class OnboardingUIWeb {
1775
1795
  */
1776
1796
  renderAsModal() {
1777
1797
  // Create modal overlay (backdrop) - start hidden to prevent flicker
1778
- this.modalOverlay = this.createElement('div', {
1779
- className: 'onboarding-modal-overlay',
1780
- style: 'display: none;', // Start hidden by default
1798
+ this.modalOverlay = this.createElement("div", {
1799
+ className: "onboarding-modal-overlay",
1800
+ style: "display: none;", // Start hidden by default
1781
1801
  });
1782
1802
  // Create modal content wrapper
1783
- this.modalContent = this.createElement('div', {
1803
+ this.modalContent = this.createElement("div", {
1784
1804
  className: `onboarding-modal-content onboarding-theme-${this.config.theme}`,
1785
- role: 'dialog',
1786
- 'aria-modal': 'true',
1787
- 'aria-labelledby': 'onboarding-title',
1805
+ role: "dialog",
1806
+ "aria-modal": "true",
1807
+ "aria-labelledby": "onboarding-title",
1788
1808
  tabIndex: -1,
1789
1809
  });
1790
1810
  // Create root element for the form
1791
- this.rootElement = this.createElement('div', {
1811
+ this.rootElement = this.createElement("div", {
1792
1812
  className: `onboarding-container onboarding-theme-${this.config.theme} ${this.config.className}`,
1793
1813
  style: this.parseStyle(this.config.style),
1794
1814
  });
1795
- // Close button
1796
- if (this.config.showCloseButton) {
1797
- this.closeButton = this.createElement('button', {
1798
- className: 'onboarding-modal-close',
1799
- type: 'button',
1800
- innerHTML: '×',
1801
- 'aria-label': 'Close modal',
1802
- 'aria-describedby': 'close-button-description',
1803
- });
1804
- this.closeButton.addEventListener('click', () => this.close());
1805
- this.closeButton.addEventListener('keydown', (e) => {
1806
- if (e.key === 'Enter' || e.key === ' ') {
1807
- e.preventDefault();
1808
- this.close();
1809
- }
1810
- });
1811
- this.modalContent.appendChild(this.closeButton);
1812
- }
1813
1815
  // Build the form content
1814
1816
  this.buildFormContent();
1815
1817
  // Append form to root, root to modal content, modal content to overlay
@@ -1817,33 +1819,30 @@ export class OnboardingUIWeb {
1817
1819
  this.modalOverlay.appendChild(this.modalContent);
1818
1820
  // Add click handler for backdrop
1819
1821
  if (this.config.closeOnBackdropClick) {
1820
- this.modalOverlay.addEventListener('click', (e) => {
1822
+ this.modalOverlay.addEventListener("click", (e) => {
1821
1823
  if (e.target === this.modalOverlay) {
1822
1824
  this.close();
1823
1825
  }
1824
1826
  });
1825
1827
  }
1826
1828
  // Prevent body scroll when modal is open
1827
- document.body.style.overflow = 'hidden';
1829
+ document.body.style.overflow = "hidden";
1828
1830
  // Append to body
1829
1831
  document.body.appendChild(this.modalOverlay);
1830
1832
  // Add animation class
1831
1833
  setTimeout(() => {
1832
1834
  if (this.modalOverlay) {
1833
- this.modalOverlay.classList.add('onboarding-modal-open');
1835
+ this.modalOverlay.classList.add("onboarding-modal-open");
1834
1836
  // Focus management for accessibility
1835
1837
  if (this.emailInput) {
1836
1838
  this.emailInput.focus();
1837
1839
  }
1838
1840
  }
1839
1841
  }, 10);
1840
- // Add keyboard navigation (ESC to close)
1841
- this.modalOverlay.addEventListener('keydown', (e) => {
1842
- if (e.key === 'Escape' && this.config.showCloseButton) {
1843
- this.close();
1844
- }
1842
+ // Add keyboard navigation
1843
+ this.modalOverlay.addEventListener("keydown", (e) => {
1845
1844
  // Trap focus within modal
1846
- if (e.key === 'Tab') {
1845
+ if (e.key === "Tab") {
1847
1846
  this.trapFocus(e);
1848
1847
  }
1849
1848
  });
@@ -1873,7 +1872,7 @@ export class OnboardingUIWeb {
1873
1872
  if (!this.container)
1874
1873
  return;
1875
1874
  // Create root element
1876
- this.rootElement = this.createElement('div', {
1875
+ this.rootElement = this.createElement("div", {
1877
1876
  className: `onboarding-container onboarding-inline onboarding-theme-${this.config.theme} ${this.config.className}`,
1878
1877
  style: this.parseStyle(this.config.style),
1879
1878
  });
@@ -1884,7 +1883,7 @@ export class OnboardingUIWeb {
1884
1883
  this.container.appendChild(this.rootElement);
1885
1884
  }
1886
1885
  else {
1887
- this.container.innerHTML = '';
1886
+ this.container.innerHTML = "";
1888
1887
  this.container.appendChild(this.rootElement);
1889
1888
  }
1890
1889
  }
@@ -1895,95 +1894,110 @@ export class OnboardingUIWeb {
1895
1894
  if (!this.rootElement)
1896
1895
  return;
1897
1896
  // Create card
1898
- const card = this.createElement('div', { className: 'onboarding-card' });
1897
+ const card = this.createElement("div", { className: "onboarding-card" });
1899
1898
  // Header with logo at top
1900
- const header = this.createElement('div', { className: 'onboarding-header' });
1899
+ const header = this.createElement("div", {
1900
+ className: "onboarding-header",
1901
+ });
1901
1902
  // Logo section (centered at top)
1902
- const logoSection = this.createElement('div', { className: 'onboarding-logo-section' });
1903
1903
  if (this.config.logo) {
1904
- const logoContainer = this.createElement('div', { className: 'onboarding-logo-container' });
1905
- const logoImg = this.createElement('img', {
1904
+ const logoSection = this.createElement("div", {
1905
+ className: "onboarding-logo-section",
1906
+ });
1907
+ const logoContainer = this.createElement("div", {
1908
+ className: "onboarding-logo-container",
1909
+ });
1910
+ const logoImg = this.createElement("img", {
1906
1911
  src: this.config.logo,
1907
- alt: 'Logo',
1908
- className: 'onboarding-logo-img',
1912
+ alt: "Logo",
1913
+ className: "onboarding-logo-img",
1909
1914
  });
1910
1915
  logoContainer.appendChild(logoImg);
1911
1916
  logoSection.appendChild(logoContainer);
1917
+ header.appendChild(logoSection);
1912
1918
  }
1913
- header.appendChild(logoSection);
1914
- // Onboarding title (always shown, default: "Sign in")
1915
- const title = this.createElement('h1', {
1916
- className: 'onboarding-title',
1917
- textContent: this.config.onboardTitle || 'Sign in',
1918
- id: 'onboarding-title',
1919
+ // Onboarding title (always shown, default: "Sign In")
1920
+ const title = this.createElement("h1", {
1921
+ className: "onboarding-title",
1922
+ textContent: this.config.onboardTitle || "Sign In",
1923
+ id: "onboarding-title",
1919
1924
  });
1920
1925
  header.appendChild(title);
1921
1926
  // Form
1922
- this.emailForm = this.createElement('form', {
1923
- className: 'onboarding-form',
1924
- 'aria-label': 'Sign in form',
1927
+ this.emailForm = this.createElement("form", {
1928
+ className: "onboarding-form",
1929
+ "aria-label": "Sign In form",
1925
1930
  noValidate: true,
1926
1931
  });
1927
1932
  // Email input group
1928
- const emailGroup = this.createElement('div', { className: 'onboarding-input-group' });
1933
+ const emailGroup = this.createElement("div", {
1934
+ className: "onboarding-input-group",
1935
+ });
1929
1936
  // Email label
1930
- const emailLabel = this.createElement('label', {
1931
- className: 'onboarding-input-label',
1932
- textContent: this.config.labels?.emailLabel || 'Email Address',
1933
- htmlFor: 'onboarding-email-input',
1937
+ const emailLabel = this.createElement("label", {
1938
+ className: "onboarding-input-label",
1939
+ textContent: this.config.labels?.emailLabel || "Email Address",
1940
+ htmlFor: "onboarding-email-input",
1934
1941
  });
1935
1942
  emailGroup.appendChild(emailLabel);
1936
- const emailWrapper = this.createElement('div', { className: 'onboarding-input-wrapper' });
1943
+ const emailWrapper = this.createElement("div", {
1944
+ className: "onboarding-input-wrapper",
1945
+ });
1937
1946
  // Email icon SVG
1938
1947
  const emailIcon = this.createEmailIcon();
1939
1948
  emailWrapper.appendChild(emailIcon);
1940
1949
  // Get auth methods to check if all are enabled
1941
- const authMethods = this.config.authMethods || ['otp', 'google'];
1942
- const showEmail = authMethods.includes('otp');
1943
- const showGoogle = authMethods.includes('google');
1944
- const showTwitter = authMethods.includes('twitter');
1945
- const showDiscord = authMethods.includes('discord');
1946
- const showPasskey = authMethods.includes('passkey');
1950
+ const authMethods = this.config.authMethods || ["otp", "google"];
1951
+ const showEmail = authMethods.includes("otp");
1952
+ const showGoogle = authMethods.includes("google");
1953
+ const showTwitter = authMethods.includes("twitter");
1954
+ const showDiscord = authMethods.includes("discord");
1955
+ const showPasskey = authMethods.includes("passkey");
1947
1956
  const socialMethods = [
1948
- { key: 'google', show: showGoogle },
1949
- { key: 'twitter', show: showTwitter },
1950
- { key: 'discord', show: showDiscord },
1957
+ { key: "google", show: showGoogle },
1958
+ { key: "twitter", show: showTwitter },
1959
+ { key: "discord", show: showDiscord },
1951
1960
  ].filter((m) => m.show);
1952
1961
  // Treat “all configs” as email + passkey + all socials present
1953
1962
  const allAuthMethodsEnabled = showEmail && showPasskey && showGoogle && showTwitter && showDiscord;
1954
1963
  // Email input
1955
- this.emailInput = this.createElement('input', {
1956
- type: 'email',
1957
- id: 'onboarding-email-input',
1958
- placeholder: this.config.labels?.emailPlaceholder || 'Enter your email',
1959
- className: 'onboarding-input',
1964
+ this.emailInput = this.createElement("input", {
1965
+ type: "email",
1966
+ id: "onboarding-email-input",
1967
+ placeholder: this.config.labels?.emailPlaceholder || "Enter your email",
1968
+ className: "onboarding-input",
1960
1969
  required: true,
1961
- autocomplete: 'email',
1962
- 'aria-label': this.config.labels?.emailLabel || 'Email Address',
1963
- 'aria-required': 'true',
1964
- style: allAuthMethodsEnabled ? 'padding-right: 48px;' : '',
1970
+ autocomplete: "email",
1971
+ "aria-label": this.config.labels?.emailLabel || "Email Address",
1972
+ "aria-required": "true",
1973
+ style: allAuthMethodsEnabled ? "padding-right: 48px;" : "",
1965
1974
  });
1966
1975
  emailWrapper.appendChild(this.emailInput);
1967
1976
  // Add right arrow button inside input when all auth methods are enabled
1968
1977
  if (allAuthMethodsEnabled) {
1969
- this.emailArrowButton = this.createElement('button', {
1970
- type: 'button',
1971
- className: 'onboarding-input-arrow-button',
1972
- 'aria-label': this.config.labels?.emailButton || 'Continue with email',
1978
+ this.emailArrowButton = this.createElement("button", {
1979
+ type: "button",
1980
+ className: "onboarding-input-arrow-button",
1981
+ "aria-label": this.config.labels?.emailButton || "Continue with email",
1982
+ disabled: true,
1973
1983
  });
1974
1984
  const arrowIcon = this.createArrowIcon();
1975
- arrowIcon.setAttribute('aria-hidden', 'true');
1985
+ arrowIcon.setAttribute("aria-hidden", "true");
1976
1986
  this.emailArrowButton.appendChild(arrowIcon);
1977
1987
  // Add click handler to submit form
1978
- this.emailArrowButton.addEventListener('click', (e) => {
1988
+ this.emailArrowButton.addEventListener("click", (e) => {
1979
1989
  e.preventDefault();
1980
- if (this.emailInput && this.emailInput.value.trim()) {
1990
+ if (this.emailInput &&
1991
+ this.emailInput.value.trim() &&
1992
+ isValidEmail(this.emailInput.value.trim())) {
1981
1993
  this.emailForm?.requestSubmit();
1982
1994
  }
1983
1995
  });
1984
1996
  // Also submit on Enter key
1985
- this.emailInput.addEventListener('keydown', (e) => {
1986
- if (e.key === 'Enter' && this.emailInput?.value.trim()) {
1997
+ this.emailInput.addEventListener("keydown", (e) => {
1998
+ if (e.key === "Enter" &&
1999
+ this.emailInput?.value.trim() &&
2000
+ isValidEmail(this.emailInput.value.trim())) {
1987
2001
  e.preventDefault();
1988
2002
  this.emailForm?.requestSubmit();
1989
2003
  }
@@ -1993,48 +2007,51 @@ export class OnboardingUIWeb {
1993
2007
  emailGroup.appendChild(emailWrapper);
1994
2008
  this.emailForm.appendChild(emailGroup);
1995
2009
  // OTP input group (initially hidden)
1996
- this.otpGroup = this.createElement('div', {
1997
- className: 'onboarding-input-group',
1998
- style: 'display: none;',
2010
+ this.otpGroup = this.createElement("div", {
2011
+ className: "onboarding-input-group",
2012
+ style: "display: none;",
1999
2013
  });
2000
2014
  // OTP label
2001
- const otpLabel = this.createElement('label', {
2002
- className: 'onboarding-input-label',
2003
- textContent: this.config.labels?.otpLabel || 'Verification code',
2004
- htmlFor: 'onboarding-otp-input',
2015
+ const otpLabel = this.createElement("label", {
2016
+ className: "onboarding-input-label",
2017
+ textContent: this.config.labels?.otpLabel || "Verification code",
2018
+ htmlFor: "onboarding-otp-input",
2005
2019
  });
2006
2020
  this.otpGroup.appendChild(otpLabel);
2007
- const otpWrapper = this.createElement('div', { className: 'onboarding-input-wrapper' });
2008
- this.otpInput = this.createElement('input', {
2009
- type: 'text',
2010
- id: 'onboarding-otp-input',
2011
- placeholder: this.config.labels?.otpPlaceholder || 'Enter 6-digit code',
2012
- className: 'onboarding-input',
2021
+ const otpWrapper = this.createElement("div", {
2022
+ className: "onboarding-input-wrapper",
2023
+ });
2024
+ this.otpInput = this.createElement("input", {
2025
+ type: "text",
2026
+ id: "onboarding-otp-input",
2027
+ placeholder: this.config.labels?.otpPlaceholder || "Enter 6-digit code",
2028
+ className: "onboarding-input",
2013
2029
  required: false, // Don't require initially since it's hidden
2014
2030
  maxLength: 6,
2015
- inputMode: 'numeric',
2016
- pattern: '[0-9]*',
2017
- autocomplete: 'one-time-code',
2018
- 'aria-label': this.config.labels?.otpLabel || 'Verification code',
2031
+ inputMode: "numeric",
2032
+ pattern: "[0-9]*",
2033
+ autocomplete: "one-time-code",
2034
+ "aria-label": this.config.labels?.otpLabel || "Verification code",
2019
2035
  });
2020
2036
  otpWrapper.appendChild(this.otpInput);
2021
2037
  this.otpGroup.appendChild(otpWrapper);
2022
2038
  this.emailForm.appendChild(this.otpGroup);
2023
2039
  // Error element
2024
- this.errorElement = this.createElement('div', {
2025
- className: 'onboarding-error',
2026
- style: 'display: none;',
2027
- role: 'alert',
2028
- 'aria-live': 'polite',
2040
+ this.errorElement = this.createElement("div", {
2041
+ className: "onboarding-error",
2042
+ style: "display: none;",
2043
+ role: "alert",
2044
+ "aria-live": "polite",
2029
2045
  });
2030
2046
  this.emailForm.appendChild(this.errorElement);
2031
2047
  // Continue button (hide if all auth methods are enabled)
2032
- this.continueButton = this.createElement('button', {
2033
- type: 'submit',
2034
- className: 'onboarding-button onboarding-button-primary',
2035
- textContent: this.config.labels?.emailButton || 'Continue',
2036
- 'aria-label': this.config.labels?.emailButton || 'Continue with email',
2037
- style: allAuthMethodsEnabled ? 'display: none;' : '',
2048
+ this.continueButton = this.createElement("button", {
2049
+ type: "submit",
2050
+ className: "onboarding-button onboarding-button-primary",
2051
+ textContent: this.config.labels?.emailButton || "Continue",
2052
+ "aria-label": this.config.labels?.emailButton || "Continue with email",
2053
+ style: allAuthMethodsEnabled ? "display: none;" : "",
2054
+ disabled: true,
2038
2055
  });
2039
2056
  this.emailForm.appendChild(this.continueButton);
2040
2057
  card.appendChild(header);
@@ -2045,24 +2062,26 @@ export class OnboardingUIWeb {
2045
2062
  }
2046
2063
  else {
2047
2064
  // Still create the form but hide it (needed for OTP flow)
2048
- this.emailForm.style.display = 'none';
2065
+ this.emailForm.style.display = "none";
2049
2066
  card.appendChild(this.emailForm);
2050
2067
  }
2051
2068
  // Divider (show if email plus any social method is enabled)
2052
2069
  if (showEmail && socialMethods.length > 0) {
2053
- this.divider = this.createElement('div', { className: 'onboarding-divider' });
2054
- const dividerText = this.createElement('span', {
2055
- className: 'onboarding-divider-text',
2056
- textContent: 'or',
2070
+ this.divider = this.createElement("div", {
2071
+ className: "onboarding-divider",
2072
+ });
2073
+ const dividerText = this.createElement("span", {
2074
+ className: "onboarding-divider-text",
2075
+ textContent: "or",
2057
2076
  });
2058
2077
  this.divider.appendChild(dividerText);
2059
2078
  card.appendChild(this.divider);
2060
2079
  }
2061
2080
  else {
2062
2081
  // Create divider element but hide it
2063
- this.divider = this.createElement('div', {
2064
- className: 'onboarding-divider',
2065
- style: 'display: none;',
2082
+ this.divider = this.createElement("div", {
2083
+ className: "onboarding-divider",
2084
+ style: "display: none;",
2066
2085
  });
2067
2086
  card.appendChild(this.divider);
2068
2087
  }
@@ -2070,17 +2089,19 @@ export class OnboardingUIWeb {
2070
2089
  if (socialMethods.length > 0) {
2071
2090
  if (socialMethods.length === 1) {
2072
2091
  const method = socialMethods[0].key;
2073
- const isGoogle = method === 'google';
2074
- const isTwitter = method === 'twitter';
2075
- const isDiscord = method === 'discord';
2076
- const button = this.createElement('button', {
2077
- type: 'button',
2078
- className: isGoogle ? 'onboarding-button onboarding-button-google' : 'onboarding-button onboarding-button-social',
2079
- 'aria-label': this.config.labels?.[`${method}Button`] ||
2080
- (method === 'google'
2081
- ? 'Continue with Google'
2082
- : method === 'twitter'
2083
- ? 'Continue with X'
2092
+ const isGoogle = method === "google";
2093
+ const isTwitter = method === "twitter";
2094
+ const isDiscord = method === "discord";
2095
+ const button = this.createElement("button", {
2096
+ type: "button",
2097
+ className: isGoogle
2098
+ ? "onboarding-button onboarding-button-google"
2099
+ : "onboarding-button onboarding-button-social",
2100
+ "aria-label": this.config.labels?.[`${method}Button`] ||
2101
+ (method === "google"
2102
+ ? "Continue with Google"
2103
+ : method === "twitter"
2104
+ ? "Continue with X"
2084
2105
  : `Continue with ${method.charAt(0).toUpperCase() + method.slice(1)}`),
2085
2106
  });
2086
2107
  const icon = isGoogle
@@ -2088,13 +2109,13 @@ export class OnboardingUIWeb {
2088
2109
  : isTwitter
2089
2110
  ? this.createTwitterIcon()
2090
2111
  : this.createDiscordIcon();
2091
- icon.setAttribute('aria-hidden', 'true');
2112
+ icon.setAttribute("aria-hidden", "true");
2092
2113
  button.appendChild(icon);
2093
2114
  const label = this.config.labels?.[`${method}Button`] ||
2094
- (method === 'google'
2095
- ? 'Continue with Google'
2096
- : method === 'twitter'
2097
- ? 'Continue with X'
2115
+ (method === "google"
2116
+ ? "Continue with Google"
2117
+ : method === "twitter"
2118
+ ? "Continue with X"
2098
2119
  : `Continue with ${method.charAt(0).toUpperCase() + method.slice(1)}`);
2099
2120
  button.appendChild(document.createTextNode(` ${label}`));
2100
2121
  if (isGoogle) {
@@ -2109,19 +2130,21 @@ export class OnboardingUIWeb {
2109
2130
  card.appendChild(button);
2110
2131
  }
2111
2132
  else {
2112
- this.socialGrid = this.createElement('div', { className: 'onboarding-social-grid' });
2133
+ this.socialGrid = this.createElement("div", {
2134
+ className: "onboarding-social-grid",
2135
+ });
2113
2136
  socialMethods.forEach(({ key: method }) => {
2114
- const isGoogle = method === 'google';
2115
- const isTwitter = method === 'twitter';
2116
- const isDiscord = method === 'discord';
2117
- const button = this.createElement('button', {
2118
- type: 'button',
2119
- className: 'onboarding-button-social-icon',
2120
- 'aria-label': this.config.labels?.[`${method}Button`] ||
2121
- (method === 'google'
2122
- ? 'Google'
2123
- : method === 'twitter'
2124
- ? 'X'
2137
+ const isGoogle = method === "google";
2138
+ const isTwitter = method === "twitter";
2139
+ const isDiscord = method === "discord";
2140
+ const button = this.createElement("button", {
2141
+ type: "button",
2142
+ className: "onboarding-button-social-icon",
2143
+ "aria-label": this.config.labels?.[`${method}Button`] ||
2144
+ (method === "google"
2145
+ ? "Google"
2146
+ : method === "twitter"
2147
+ ? "X"
2125
2148
  : method.charAt(0).toUpperCase() + method.slice(1)),
2126
2149
  });
2127
2150
  const icon = isGoogle
@@ -2129,7 +2152,7 @@ export class OnboardingUIWeb {
2129
2152
  : isTwitter
2130
2153
  ? this.createTwitterIcon()
2131
2154
  : this.createDiscordIcon();
2132
- icon.setAttribute('aria-hidden', 'true');
2155
+ icon.setAttribute("aria-hidden", "true");
2133
2156
  button.appendChild(icon);
2134
2157
  if (isGoogle) {
2135
2158
  this.googleButton = button;
@@ -2151,10 +2174,12 @@ export class OnboardingUIWeb {
2151
2174
  }
2152
2175
  // Passkey divider (only show if passkey is enabled and there are other auth methods)
2153
2176
  if (showPasskey && (showEmail || socialMethods.length > 0)) {
2154
- this.passkeyDivider = this.createElement('div', { className: 'onboarding-divider' });
2155
- const passkeyDividerText = this.createElement('span', {
2156
- className: 'onboarding-divider-text',
2157
- textContent: 'or',
2177
+ this.passkeyDivider = this.createElement("div", {
2178
+ className: "onboarding-divider",
2179
+ });
2180
+ const passkeyDividerText = this.createElement("span", {
2181
+ className: "onboarding-divider-text",
2182
+ textContent: "or",
2158
2183
  });
2159
2184
  this.passkeyDivider.appendChild(passkeyDividerText);
2160
2185
  card.appendChild(this.passkeyDivider);
@@ -2165,17 +2190,15 @@ export class OnboardingUIWeb {
2165
2190
  // Passkey login button (only show if passkey auth is enabled)
2166
2191
  if (showPasskey) {
2167
2192
  const passkeyBg = this.config.colors?.primary ||
2168
- (this.config.theme === 'dark' ? '#4b5563' : '#ffffff');
2193
+ (this.config.theme === "dark" ? "#4b5563" : "#ffffff");
2169
2194
  const passkeyBorder = this.config.colors?.border ||
2170
- (this.config.theme === 'dark' ? '#6b7280' : '#e5e7eb');
2195
+ (this.config.theme === "dark" ? "#6b7280" : "#e5e7eb");
2171
2196
  const passkeyTextColor = this.config.colors?.text ||
2172
- (this.config.theme === 'dark' ? '#ffffff' : '#1f2937');
2173
- // Set passkey link color based on theme: white for dark theme, black for light theme
2174
- const passkeyLinkColor = this.config.theme === 'dark' ? '#ffffff' : '#1f2937';
2175
- this.passkeyLoginButton = this.createElement('button', {
2176
- type: 'button',
2177
- className: 'onboarding-button onboarding-button-passkey',
2178
- 'aria-label': this.config.labels?.passkeyLoginButton || 'Log in with passkey',
2197
+ (this.config.theme === "dark" ? "#ffffff" : "#1f2937");
2198
+ this.passkeyLoginButton = this.createElement("button", {
2199
+ type: "button",
2200
+ className: "onboarding-button onboarding-button-passkey",
2201
+ "aria-label": this.config.labels?.passkeyLoginButton || "Log in with passkey",
2179
2202
  style: `
2180
2203
  background-color: ${passkeyBg};
2181
2204
  color: ${passkeyTextColor};
@@ -2183,94 +2206,98 @@ export class OnboardingUIWeb {
2183
2206
  `,
2184
2207
  });
2185
2208
  const passkeyIcon = this.createPasskeyIcon();
2186
- passkeyIcon.setAttribute('aria-hidden', 'true');
2209
+ passkeyIcon.setAttribute("aria-hidden", "true");
2187
2210
  this.passkeyLoginButton.appendChild(passkeyIcon);
2188
- const passkeyText = this.config.labels?.passkeyLoginButton || 'Log in with passkey';
2211
+ const passkeyText = this.config.labels?.passkeyLoginButton || "Log in with passkey";
2189
2212
  this.passkeyLoginButton.appendChild(document.createTextNode(` ${passkeyText}`));
2190
2213
  card.appendChild(this.passkeyLoginButton);
2191
2214
  // Passkey signup link
2192
- const passkeySignupContainer = this.createElement('div', {
2193
- style: 'text-align: center; margin-top: 12px;',
2215
+ const passkeySignupContainer = this.createElement("div", {
2216
+ style: "text-align: center; margin-top: 12px;",
2194
2217
  });
2195
- this.passkeySignupLink = this.createElement('a', {
2196
- className: 'onboarding-passkey-signup-link',
2197
- href: '#',
2198
- textContent: this.config.labels?.passkeySignupButton || 'Sign up with passkey',
2199
- 'aria-label': this.config.labels?.passkeySignupButton || 'Sign up with passkey',
2200
- style: `color: ${passkeyLinkColor};`,
2218
+ this.passkeySignupLink = this.createElement("a", {
2219
+ className: "onboarding-passkey-signup-link",
2220
+ href: "#",
2221
+ textContent: this.config.labels?.passkeySignupButton || "Sign up with passkey",
2222
+ "aria-label": this.config.labels?.passkeySignupButton || "Sign up with passkey",
2201
2223
  });
2202
2224
  passkeySignupContainer.appendChild(this.passkeySignupLink);
2203
2225
  card.appendChild(passkeySignupContainer);
2204
2226
  // Passkey error element (local to passkey section)
2205
- this.passkeyErrorElement = this.createElement('div', {
2206
- className: 'onboarding-error',
2207
- style: 'display: none; margin-top: 12px;',
2208
- role: 'alert',
2209
- 'aria-live': 'polite',
2227
+ this.passkeyErrorElement = this.createElement("div", {
2228
+ className: "onboarding-error",
2229
+ style: "display: none; margin-top: 12px;",
2230
+ role: "alert",
2231
+ "aria-live": "polite",
2210
2232
  });
2211
2233
  card.appendChild(this.passkeyErrorElement);
2212
2234
  }
2213
2235
  else {
2214
2236
  // Create passkey elements but hide them
2215
- this.passkeyLoginButton = this.createElement('button', {
2216
- type: 'button',
2217
- className: 'onboarding-button onboarding-button-passkey',
2218
- style: 'display: none;',
2237
+ this.passkeyLoginButton = this.createElement("button", {
2238
+ type: "button",
2239
+ className: "onboarding-button onboarding-button-passkey",
2240
+ style: "display: none;",
2219
2241
  });
2220
2242
  card.appendChild(this.passkeyLoginButton);
2221
- this.passkeySignupLink = this.createElement('a', {
2222
- className: 'onboarding-passkey-signup-link',
2223
- href: '#',
2224
- style: 'display: none;',
2243
+ this.passkeySignupLink = this.createElement("a", {
2244
+ className: "onboarding-passkey-signup-link",
2245
+ href: "#",
2246
+ style: "display: none;",
2225
2247
  });
2226
2248
  card.appendChild(this.passkeySignupLink);
2227
- this.passkeyErrorElement = this.createElement('div', {
2228
- className: 'onboarding-error',
2229
- style: 'display: none;',
2249
+ this.passkeyErrorElement = this.createElement("div", {
2250
+ className: "onboarding-error",
2251
+ style: "display: none;",
2230
2252
  });
2231
2253
  card.appendChild(this.passkeyErrorElement);
2232
2254
  }
2233
2255
  // External wallet divider (shown immediately if external wallets are enabled)
2234
- this.externalWalletDivider = this.createElement('div', {
2235
- className: 'onboarding-divider',
2236
- style: this.externalWalletsEnabled ? '' : 'display: none;',
2256
+ this.externalWalletDivider = this.createElement("div", {
2257
+ className: "onboarding-divider",
2258
+ style: this.externalWalletsEnabled ? "" : "display: none;",
2237
2259
  });
2238
- const externalWalletDividerText = this.createElement('span', {
2239
- className: 'onboarding-divider-text',
2240
- textContent: 'or',
2260
+ const externalWalletDividerText = this.createElement("span", {
2261
+ className: "onboarding-divider-text",
2262
+ textContent: "or",
2241
2263
  });
2242
2264
  this.externalWalletDivider.appendChild(externalWalletDividerText);
2243
2265
  card.appendChild(this.externalWalletDivider);
2244
2266
  // External wallet container (shown immediately if external wallets are enabled)
2245
- this.externalWalletContainer = this.createElement('div', {
2246
- id: 'onboarding-external-wallet-container',
2247
- style: this.externalWalletsEnabled ? '' : 'display: none;',
2267
+ this.externalWalletContainer = this.createElement("div", {
2268
+ id: "onboarding-external-wallet-container",
2269
+ style: this.externalWalletsEnabled ? "" : "display: none;",
2248
2270
  });
2249
2271
  card.appendChild(this.externalWalletContainer);
2250
2272
  // Footer (inside card, so it appears on initial login screen)
2251
2273
  if (this.config.showFooter) {
2252
2274
  const textColor = this.config.colors?.text ||
2253
- (this.config.theme === 'dark' ? '#9ca3af' : '#6b7280');
2275
+ (this.config.theme === "dark" ? "#9ca3af" : "#6b7280");
2254
2276
  const brandColor = this.config.colors?.text ||
2255
- (this.config.theme === 'dark' ? '#e5e7eb' : '#374151');
2256
- this.footer = this.createElement('div', { className: 'onboarding-footer' });
2257
- const footerText = this.createElement('p', {
2258
- className: 'onboarding-footer-text',
2277
+ (this.config.theme === "dark" ? "#e5e7eb" : "#374151");
2278
+ this.footer = this.createElement("div", {
2279
+ className: "onboarding-footer",
2280
+ });
2281
+ const footerText = this.createElement("p", {
2282
+ className: "onboarding-footer-text",
2259
2283
  style: `color: ${textColor}; display: flex; align-items: center; gap: 6px; justify-content: center;`,
2260
2284
  });
2261
2285
  // "Powered by" text
2262
- const poweredBySpan = this.createElement('span', { textContent: 'Powered by', style: `color: ${textColor};` });
2286
+ const poweredBySpan = this.createElement("span", {
2287
+ textContent: "Powered by",
2288
+ style: `color: ${textColor};`,
2289
+ });
2263
2290
  footerText.appendChild(poweredBySpan);
2264
2291
  // Inline brand with logo (clickable link)
2265
- const brandContainer = this.createElement('a', {
2266
- href: 'https://www.abstraxn.com/',
2267
- target: '_blank',
2268
- rel: 'noopener noreferrer',
2269
- style: 'display: inline-flex; align-items: center; gap: 6px; text-decoration: none; cursor: pointer;',
2270
- 'aria-label': 'Visit Abstraxn website',
2292
+ const brandContainer = this.createElement("a", {
2293
+ href: "https://www.abstraxn.com/",
2294
+ target: "_blank",
2295
+ rel: "noopener noreferrer",
2296
+ style: "display: inline-flex; align-items: center; gap: 6px; text-decoration: none; cursor: pointer;",
2297
+ "aria-label": "Visit Abstraxn website",
2271
2298
  });
2272
2299
  // Abstraxn logo SVG
2273
- const logoSvg = this.createElement('span', {
2300
+ const logoSvg = this.createElement("span", {
2274
2301
  innerHTML: `
2275
2302
  <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none" style="width: 20px; height: 20px; display: inline-block; vertical-align: middle;">
2276
2303
  <path d="M47.9082 37.191L23.9541 23.553L0 9.91504L37.7436 -8.13502e-06L47.9082 37.191Z" fill="url(#paint0_linear_1242_781)"/>
@@ -2289,11 +2316,11 @@ export class OnboardingUIWeb {
2289
2316
  </defs>
2290
2317
  </svg>
2291
2318
  `,
2292
- style: 'display: inline-flex; align-items: center;',
2319
+ style: "display: inline-flex; align-items: center;",
2293
2320
  });
2294
2321
  brandContainer.appendChild(logoSvg);
2295
- const brandText = this.createElement('span', {
2296
- textContent: 'abstraxn',
2322
+ const brandText = this.createElement("span", {
2323
+ textContent: "abstraxn",
2297
2324
  style: `color: ${brandColor}; font-weight: 700; letter-spacing: 0.2px;`,
2298
2325
  });
2299
2326
  brandContainer.appendChild(brandText);
@@ -2307,54 +2334,57 @@ export class OnboardingUIWeb {
2307
2334
  * Attach event listeners
2308
2335
  */
2309
2336
  attachEventListeners() {
2310
- if (!this.emailForm || !this.emailInput || !this.otpInput || !this.continueButton) {
2337
+ if (!this.emailForm ||
2338
+ !this.emailInput ||
2339
+ !this.otpInput ||
2340
+ !this.continueButton) {
2311
2341
  return;
2312
2342
  }
2313
2343
  // Email input change
2314
- this.emailInput.addEventListener('input', (e) => {
2344
+ this.emailInput.addEventListener("input", (e) => {
2315
2345
  this.email = e.target.value;
2316
2346
  this.updateButtonState();
2317
2347
  });
2318
2348
  // OTP input change
2319
- this.otpInput.addEventListener('input', (e) => {
2349
+ this.otpInput.addEventListener("input", (e) => {
2320
2350
  this.otp = e.target.value;
2321
2351
  });
2322
2352
  // Form submit
2323
- this.emailForm.addEventListener('submit', (e) => {
2353
+ this.emailForm.addEventListener("submit", (e) => {
2324
2354
  e.preventDefault();
2325
2355
  this.handleEmailSubmit();
2326
2356
  });
2327
2357
  // Google button click
2328
2358
  if (this.googleButton) {
2329
- this.googleButton.addEventListener('click', (e) => {
2359
+ this.googleButton.addEventListener("click", (e) => {
2330
2360
  e.preventDefault();
2331
2361
  this.handleGoogleLogin();
2332
2362
  });
2333
2363
  }
2334
2364
  // Twitter button click
2335
2365
  if (this.twitterButton) {
2336
- this.twitterButton.addEventListener('click', (e) => {
2366
+ this.twitterButton.addEventListener("click", (e) => {
2337
2367
  e.preventDefault();
2338
2368
  this.handleTwitterLogin();
2339
2369
  });
2340
2370
  }
2341
2371
  // Discord button click
2342
2372
  if (this.discordButton) {
2343
- this.discordButton.addEventListener('click', (e) => {
2373
+ this.discordButton.addEventListener("click", (e) => {
2344
2374
  e.preventDefault();
2345
2375
  this.handleDiscordLogin();
2346
2376
  });
2347
2377
  }
2348
2378
  // Passkey login button click
2349
2379
  if (this.passkeyLoginButton) {
2350
- this.passkeyLoginButton.addEventListener('click', (e) => {
2380
+ this.passkeyLoginButton.addEventListener("click", (e) => {
2351
2381
  e.preventDefault();
2352
2382
  this.handlePasskeyLogin();
2353
2383
  });
2354
2384
  }
2355
2385
  // Passkey signup link click
2356
2386
  if (this.passkeySignupLink) {
2357
- this.passkeySignupLink.addEventListener('click', (e) => {
2387
+ this.passkeySignupLink.addEventListener("click", (e) => {
2358
2388
  e.preventDefault();
2359
2389
  this.handlePasskeySignup();
2360
2390
  });
@@ -2368,12 +2398,12 @@ export class OnboardingUIWeb {
2368
2398
  return;
2369
2399
  // Ensure email is captured from input field
2370
2400
  this.email = this.emailInput.value.trim();
2371
- if (!this.email || !this.email.includes('@')) {
2372
- this.setError('Please enter a valid email address');
2401
+ if (!this.email || !this.email.includes("@")) {
2402
+ this.setError("Please enter a valid email address");
2373
2403
  return;
2374
2404
  }
2375
2405
  this.setError(null);
2376
- this.setLoading(true, 'email');
2406
+ this.setLoading(true, "email");
2377
2407
  try {
2378
2408
  if (!this.otpSent) {
2379
2409
  // Initiate OTP
@@ -2382,20 +2412,20 @@ export class OnboardingUIWeb {
2382
2412
  }
2383
2413
  else if (this.config.emailOtpEndpoint) {
2384
2414
  const response = await fetch(this.config.emailOtpEndpoint, {
2385
- method: 'POST',
2415
+ method: "POST",
2386
2416
  headers: {
2387
- 'Content-Type': 'application/json',
2417
+ "Content-Type": "application/json",
2388
2418
  },
2389
2419
  body: JSON.stringify({ email: this.email }),
2390
2420
  });
2391
2421
  if (!response.ok) {
2392
- throw new Error('Failed to send OTP');
2422
+ throw new Error("Failed to send OTP");
2393
2423
  }
2394
2424
  }
2395
2425
  this.otpSent = true;
2396
2426
  this.showOtpInput();
2397
2427
  if (this.continueButton) {
2398
- this.continueButton.textContent = 'Verify OTP';
2428
+ this.continueButton.textContent = "Verify OTP";
2399
2429
  }
2400
2430
  }
2401
2431
  else {
@@ -2406,14 +2436,14 @@ export class OnboardingUIWeb {
2406
2436
  this.config.onLoginSuccess?.({ token: result.token });
2407
2437
  }
2408
2438
  else {
2409
- throw new Error('Invalid OTP');
2439
+ throw new Error("Invalid OTP");
2410
2440
  }
2411
2441
  }
2412
2442
  else if (this.config.emailOtpEndpoint) {
2413
2443
  const response = await fetch(`${this.config.emailOtpEndpoint}/verify`, {
2414
- method: 'POST',
2444
+ method: "POST",
2415
2445
  headers: {
2416
- 'Content-Type': 'application/json',
2446
+ "Content-Type": "application/json",
2417
2447
  },
2418
2448
  body: JSON.stringify({ email: this.email, otp: this.otp }),
2419
2449
  });
@@ -2422,13 +2452,13 @@ export class OnboardingUIWeb {
2422
2452
  this.config.onLoginSuccess?.({ token: data.token });
2423
2453
  }
2424
2454
  else {
2425
- throw new Error(data.message || 'Invalid OTP');
2455
+ throw new Error(data.message || "Invalid OTP");
2426
2456
  }
2427
2457
  }
2428
2458
  }
2429
2459
  }
2430
2460
  catch (err) {
2431
- const errorMessage = err instanceof Error ? err.message : 'An error occurred';
2461
+ const errorMessage = err instanceof Error ? err.message : "An error occurred";
2432
2462
  this.setError(errorMessage);
2433
2463
  this.config.onLoginError?.(err instanceof Error ? err : new Error(errorMessage));
2434
2464
  }
@@ -2441,14 +2471,14 @@ export class OnboardingUIWeb {
2441
2471
  */
2442
2472
  async handleGoogleLogin() {
2443
2473
  // console.log('🔵 Google login button clicked');
2444
- // console.log('🔵 Config:', {
2445
- // hasOnGoogleLogin: !!this.config.onGoogleLogin,
2446
- // googleAuthEndpoint: this.config.googleAuthEndpoint
2474
+ // console.log('🔵 Config:', {
2475
+ // hasOnGoogleLogin: !!this.config.onGoogleLogin,
2476
+ // googleAuthEndpoint: this.config.googleAuthEndpoint
2447
2477
  // });
2448
2478
  this.setError(null);
2449
- this.setLoading(true, 'google');
2479
+ this.setLoading(true, "google");
2450
2480
  try {
2451
- localStorage.setItem('abstraxn_login_source', this.config.modal ? 'modal' : 'inline');
2481
+ localStorage.setItem("abstraxn_login_source", this.config.modal ? "modal" : "inline");
2452
2482
  if (this.config.onGoogleLogin) {
2453
2483
  // console.log('🔄 Calling onGoogleLogin callback');
2454
2484
  await this.config.onGoogleLogin();
@@ -2458,11 +2488,11 @@ export class OnboardingUIWeb {
2458
2488
  window.location.href = this.config.googleAuthEndpoint;
2459
2489
  }
2460
2490
  else {
2461
- throw new Error('Google login endpoint not configured');
2491
+ throw new Error("Google login endpoint not configured");
2462
2492
  }
2463
2493
  }
2464
2494
  catch (err) {
2465
- const errorMessage = err instanceof Error ? err.message : 'An error occurred';
2495
+ const errorMessage = err instanceof Error ? err.message : "An error occurred";
2466
2496
  this.setError(errorMessage);
2467
2497
  this.config.onLoginError?.(err instanceof Error ? err : new Error(errorMessage));
2468
2498
  }
@@ -2475,7 +2505,7 @@ export class OnboardingUIWeb {
2475
2505
  */
2476
2506
  async handleTwitterLogin() {
2477
2507
  this.setError(null);
2478
- this.setLoading(true, 'twitter');
2508
+ this.setLoading(true, "twitter");
2479
2509
  try {
2480
2510
  if (this.config.onTwitterLogin) {
2481
2511
  await this.config.onTwitterLogin();
@@ -2484,11 +2514,11 @@ export class OnboardingUIWeb {
2484
2514
  window.location.href = this.config.twitterAuthEndpoint;
2485
2515
  }
2486
2516
  else {
2487
- throw new Error('X (Twitter) login not configured');
2517
+ throw new Error("X (Twitter) login not configured");
2488
2518
  }
2489
2519
  }
2490
2520
  catch (err) {
2491
- const errorMessage = err instanceof Error ? err.message : 'An error occurred';
2521
+ const errorMessage = err instanceof Error ? err.message : "An error occurred";
2492
2522
  this.setError(errorMessage);
2493
2523
  this.config.onLoginError?.(err instanceof Error ? err : new Error(errorMessage));
2494
2524
  }
@@ -2501,7 +2531,7 @@ export class OnboardingUIWeb {
2501
2531
  */
2502
2532
  async handleDiscordLogin() {
2503
2533
  this.setError(null);
2504
- this.setLoading(true, 'discord');
2534
+ this.setLoading(true, "discord");
2505
2535
  try {
2506
2536
  if (this.config.onDiscordLogin) {
2507
2537
  await this.config.onDiscordLogin();
@@ -2510,11 +2540,11 @@ export class OnboardingUIWeb {
2510
2540
  window.location.href = this.config.discordAuthEndpoint;
2511
2541
  }
2512
2542
  else {
2513
- throw new Error('Discord login not configured');
2543
+ throw new Error("Discord login not configured");
2514
2544
  }
2515
2545
  }
2516
2546
  catch (err) {
2517
- const errorMessage = err instanceof Error ? err.message : 'An error occurred';
2547
+ const errorMessage = err instanceof Error ? err.message : "An error occurred";
2518
2548
  this.setError(errorMessage);
2519
2549
  this.config.onLoginError?.(err instanceof Error ? err : new Error(errorMessage));
2520
2550
  }
@@ -2529,46 +2559,51 @@ export class OnboardingUIWeb {
2529
2559
  */
2530
2560
  hideLoginElements() {
2531
2561
  if (this.emailForm) {
2532
- this.emailForm.style.display = 'none';
2562
+ this.emailForm.style.display = "none";
2563
+ }
2564
+ // Hide the header when showing OTP screen
2565
+ const header = this.rootElement?.querySelector(".onboarding-header");
2566
+ if (header) {
2567
+ header.style.display = "none";
2533
2568
  }
2534
2569
  if (this.divider) {
2535
- this.divider.style.display = 'none';
2570
+ this.divider.style.display = "none";
2536
2571
  }
2537
2572
  if (this.googleButton) {
2538
- this.googleButton.style.display = 'none';
2573
+ this.googleButton.style.display = "none";
2539
2574
  }
2540
2575
  if (this.twitterButton) {
2541
- this.twitterButton.style.display = 'none';
2576
+ this.twitterButton.style.display = "none";
2542
2577
  }
2543
2578
  if (this.discordButton) {
2544
- this.discordButton.style.display = 'none';
2579
+ this.discordButton.style.display = "none";
2545
2580
  }
2546
2581
  if (this.socialGrid) {
2547
- this.socialGrid.style.display = 'none';
2582
+ this.socialGrid.style.display = "none";
2548
2583
  }
2549
2584
  if (this.passkeyDivider) {
2550
- this.passkeyDivider.style.display = 'none';
2585
+ this.passkeyDivider.style.display = "none";
2551
2586
  }
2552
2587
  // Hide passkey buttons on OTP screen
2553
2588
  if (this.passkeyLoginButton) {
2554
- this.passkeyLoginButton.style.display = 'none';
2589
+ this.passkeyLoginButton.style.display = "none";
2555
2590
  }
2556
2591
  if (this.passkeySignupLink) {
2557
- this.passkeySignupLink.style.display = 'none';
2592
+ this.passkeySignupLink.style.display = "none";
2558
2593
  }
2559
2594
  if (this.passkeyErrorElement) {
2560
- this.passkeyErrorElement.style.display = 'none';
2595
+ this.passkeyErrorElement.style.display = "none";
2561
2596
  }
2562
2597
  // Hide external wallets on OTP screen
2563
2598
  if (this.externalWalletContainer) {
2564
- this.externalWalletContainer.style.display = 'none';
2599
+ this.externalWalletContainer.style.display = "none";
2565
2600
  }
2566
2601
  if (this.externalWalletDivider) {
2567
- this.externalWalletDivider.style.display = 'none';
2602
+ this.externalWalletDivider.style.display = "none";
2568
2603
  }
2569
2604
  // Hide footer on login card (OTP screen has its own footer)
2570
2605
  if (this.footer) {
2571
- this.footer.style.display = 'none';
2606
+ this.footer.style.display = "none";
2572
2607
  }
2573
2608
  }
2574
2609
  /**
@@ -2594,97 +2629,115 @@ export class OnboardingUIWeb {
2594
2629
  this.verifyButton = null;
2595
2630
  }
2596
2631
  // Get the card element
2597
- const card = this.rootElement.querySelector('.onboarding-card');
2632
+ const card = this.rootElement.querySelector(".onboarding-card");
2598
2633
  if (!card)
2599
2634
  return;
2600
2635
  // Add class to card to indicate OTP screen is active (for CSS targeting)
2601
- card.classList.add('onboarding-otp-active');
2636
+ card.classList.add("onboarding-otp-active");
2602
2637
  // Create OTP verification container
2603
- this.otpVerificationScreen = this.createElement('div', {
2604
- className: 'onboarding-otp-verification',
2638
+ this.otpVerificationScreen = this.createElement("div", {
2639
+ className: "onboarding-otp-verification",
2640
+ });
2641
+ // Add Back Button
2642
+ const backButton = this.createElement("button", {
2643
+ type: "button",
2644
+ className: "onboarding-otp-back-button",
2645
+ "aria-label": "Go back to email input",
2605
2646
  });
2647
+ backButton.innerHTML = `
2648
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2649
+ <path d="M19 12H5M12 19l-7-7 7-7" />
2650
+ </svg>
2651
+ `;
2652
+ backButton.addEventListener("click", () => {
2653
+ if (!this.loading) {
2654
+ this.resetToLoginForm();
2655
+ }
2656
+ });
2657
+ this.otpVerificationScreen.appendChild(backButton);
2606
2658
  // Email icon container
2607
- const iconContainer = this.createElement('div', {
2608
- className: 'onboarding-otp-icon-container',
2659
+ const iconContainer = this.createElement("div", {
2660
+ className: "onboarding-otp-icon-container",
2609
2661
  });
2610
- const iconInner = this.createElement('div', {
2611
- className: 'onboarding-otp-icon-inner',
2662
+ const iconInner = this.createElement("div", {
2663
+ className: "onboarding-otp-icon-inner",
2612
2664
  });
2613
2665
  const emailIcon = this.createEmailIconSVG();
2614
2666
  iconInner.appendChild(emailIcon);
2615
2667
  iconContainer.appendChild(iconInner);
2616
2668
  this.otpVerificationScreen.appendChild(iconContainer);
2617
2669
  // Title
2618
- const title = this.createElement('h1', {
2619
- className: 'onboarding-otp-title',
2620
- textContent: 'Enter verification code',
2670
+ const title = this.createElement("h1", {
2671
+ className: "onboarding-otp-title",
2672
+ textContent: "Enter verification code",
2621
2673
  });
2622
2674
  this.otpVerificationScreen.appendChild(title);
2623
2675
  // Instruction text
2624
- const instruction = this.createElement('p', {
2625
- className: 'onboarding-otp-instruction',
2626
- textContent: 'We sent a verification code to',
2676
+ const instruction = this.createElement("p", {
2677
+ className: "onboarding-otp-instruction",
2678
+ textContent: "We sent a verification code to",
2627
2679
  });
2628
2680
  this.otpVerificationScreen.appendChild(instruction);
2629
2681
  // Email address
2630
- const emailDisplay = this.createElement('p', {
2631
- className: 'onboarding-otp-email',
2682
+ const emailDisplay = this.createElement("p", {
2683
+ className: "onboarding-otp-email",
2632
2684
  textContent: this.email,
2633
2685
  });
2634
2686
  this.otpVerificationScreen.appendChild(emailDisplay);
2635
2687
  // OTP inputs container
2636
- const inputsContainer = this.createElement('div', {
2637
- className: 'onboarding-otp-inputs-container',
2688
+ const inputsContainer = this.createElement("div", {
2689
+ className: "onboarding-otp-inputs-container",
2638
2690
  });
2639
2691
  // Create 6 input fields
2640
2692
  this.otpInputs = [];
2641
2693
  for (let i = 0; i < 6; i++) {
2642
- const input = this.createElement('input', {
2643
- type: 'text',
2644
- className: 'onboarding-otp-input',
2694
+ const input = this.createElement("input", {
2695
+ type: "text",
2696
+ className: "onboarding-otp-input",
2645
2697
  maxLength: 1,
2646
- inputMode: 'numeric',
2647
- pattern: '[0-9]*',
2698
+ inputMode: "numeric",
2699
+ pattern: "[0-9]*",
2648
2700
  });
2649
2701
  // Add event listeners for auto-advance
2650
- input.addEventListener('input', (e) => this.handleOtpInput(e, i));
2651
- input.addEventListener('keydown', (e) => this.handleOtpKeydown(e, i));
2652
- input.addEventListener('paste', (e) => this.handleOtpPaste(e));
2702
+ input.addEventListener("input", (e) => this.handleOtpInput(e, i));
2703
+ input.addEventListener("keydown", (e) => this.handleOtpKeydown(e, i));
2704
+ input.addEventListener("paste", (e) => this.handleOtpPaste(e));
2653
2705
  this.otpInputs.push(input);
2654
2706
  inputsContainer.appendChild(input);
2655
2707
  }
2656
2708
  this.otpVerificationScreen.appendChild(inputsContainer);
2657
2709
  // Error element (for OTP screen)
2658
- const otpErrorElement = this.createElement('div', {
2659
- className: 'onboarding-error',
2660
- style: 'display: none;',
2710
+ const otpErrorElement = this.createElement("div", {
2711
+ className: "onboarding-error",
2712
+ style: "display: none;",
2661
2713
  });
2662
2714
  this.otpVerificationScreen.appendChild(otpErrorElement);
2663
2715
  // Store reference for OTP screen errors
2664
2716
  this.otpVerificationScreen.errorElement = otpErrorElement;
2665
2717
  // Verify button
2666
- this.verifyButton = this.createElement('button', {
2667
- type: 'button',
2668
- className: 'onboarding-button onboarding-button-primary',
2669
- textContent: 'Verify',
2718
+ this.verifyButton = this.createElement("button", {
2719
+ type: "button",
2720
+ className: "onboarding-button onboarding-button-primary",
2721
+ textContent: "Verify",
2670
2722
  });
2671
- this.verifyButton.addEventListener('click', () => this.handleOtpVerify());
2723
+ this.verifyButton.addEventListener("click", () => this.handleOtpVerify());
2672
2724
  this.otpVerificationScreen.appendChild(this.verifyButton);
2673
2725
  // Resend section
2674
- const resendSection = this.createElement('div', {
2675
- className: 'onboarding-otp-resend',
2726
+ const resendSection = this.createElement("div", {
2727
+ className: "onboarding-otp-resend",
2676
2728
  });
2677
- const resendText = this.createElement('p', {
2678
- className: 'onboarding-otp-resend-text',
2729
+ const resendText = this.createElement("p", {
2730
+ className: "onboarding-otp-resend-text",
2679
2731
  });
2680
- resendText.innerHTML = 'Didn\'t receive the email? <span class="onboarding-otp-resend-link" id="otp-resend-link">Resend</span>';
2732
+ resendText.innerHTML =
2733
+ 'Didn\'t receive the email? <span class="onboarding-otp-resend-link" id="otp-resend-link">Resend</span>';
2681
2734
  resendSection.appendChild(resendText);
2682
2735
  this.otpVerificationScreen.appendChild(resendSection);
2683
2736
  // Add resend click handler
2684
- const resendLink = resendSection.querySelector('#otp-resend-link');
2737
+ const resendLink = resendSection.querySelector("#otp-resend-link");
2685
2738
  if (resendLink) {
2686
2739
  this.resendButton = resendLink;
2687
- resendLink.addEventListener('click', (e) => {
2740
+ resendLink.addEventListener("click", (e) => {
2688
2741
  e.preventDefault();
2689
2742
  e.stopPropagation();
2690
2743
  // Prevent click if cooldown is active
@@ -2697,27 +2750,32 @@ export class OnboardingUIWeb {
2697
2750
  // Footer (add to OTP screen as well)
2698
2751
  if (this.config.showFooter) {
2699
2752
  const textColor = this.config.colors?.text ||
2700
- (this.config.theme === 'dark' ? '#9ca3af' : '#6b7280');
2753
+ (this.config.theme === "dark" ? "#9ca3af" : "#6b7280");
2701
2754
  const brandColor = this.config.colors?.text ||
2702
- (this.config.theme === 'dark' ? '#e5e7eb' : '#374151');
2703
- const otpFooter = this.createElement('div', { className: 'onboarding-footer' });
2704
- const otpFooterText = this.createElement('p', {
2705
- className: 'onboarding-footer-text',
2755
+ (this.config.theme === "dark" ? "#e5e7eb" : "#374151");
2756
+ const otpFooter = this.createElement("div", {
2757
+ className: "onboarding-footer",
2758
+ });
2759
+ const otpFooterText = this.createElement("p", {
2760
+ className: "onboarding-footer-text",
2706
2761
  style: `color: ${textColor}; display: flex; align-items: center; gap: 6px; justify-content: center;`,
2707
2762
  });
2708
2763
  // "Powered by" text
2709
- const poweredBySpan = this.createElement('span', { textContent: 'Powered by', style: `color: ${textColor};` });
2764
+ const poweredBySpan = this.createElement("span", {
2765
+ textContent: "Powered by",
2766
+ style: `color: ${textColor};`,
2767
+ });
2710
2768
  otpFooterText.appendChild(poweredBySpan);
2711
2769
  // Inline brand with logo (clickable link)
2712
- const brandContainer = this.createElement('a', {
2713
- href: 'https://www.abstraxn.com/',
2714
- target: '_blank',
2715
- rel: 'noopener noreferrer',
2716
- style: 'display: inline-flex; align-items: center; gap: 6px; text-decoration: none; cursor: pointer;',
2717
- 'aria-label': 'Visit Abstraxn website',
2770
+ const brandContainer = this.createElement("a", {
2771
+ href: "https://www.abstraxn.com/",
2772
+ target: "_blank",
2773
+ rel: "noopener noreferrer",
2774
+ style: "display: inline-flex; align-items: center; gap: 6px; text-decoration: none; cursor: pointer;",
2775
+ "aria-label": "Visit Abstraxn website",
2718
2776
  });
2719
2777
  // Abstraxn logo SVG
2720
- const logoSvg = this.createElement('span', {
2778
+ const logoSvg = this.createElement("span", {
2721
2779
  innerHTML: `
2722
2780
  <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none" style="width: 20px; height: 20px; display: inline-block; vertical-align: middle;">
2723
2781
  <path d="M47.9082 37.191L23.9541 23.553L0 9.91504L37.7436 -8.13502e-06L47.9082 37.191Z" fill="url(#paint0_linear_1242_781_otp)"/>
@@ -2736,11 +2794,11 @@ export class OnboardingUIWeb {
2736
2794
  </defs>
2737
2795
  </svg>
2738
2796
  `,
2739
- style: 'display: inline-flex; align-items: center;',
2797
+ style: "display: inline-flex; align-items: center;",
2740
2798
  });
2741
2799
  brandContainer.appendChild(logoSvg);
2742
- const brandText = this.createElement('span', {
2743
- textContent: 'abstraxn',
2800
+ const brandText = this.createElement("span", {
2801
+ textContent: "abstraxn",
2744
2802
  style: `color: ${brandColor}; font-weight: 700; letter-spacing: 0.2px;`,
2745
2803
  });
2746
2804
  brandContainer.appendChild(brandText);
@@ -2755,7 +2813,8 @@ export class OnboardingUIWeb {
2755
2813
  this.hideLoginElements();
2756
2814
  // Also ensure they stay hidden after DOM updates
2757
2815
  setTimeout(() => {
2758
- if (this.otpVerificationScreen && this.otpVerificationScreen.parentElement) {
2816
+ if (this.otpVerificationScreen &&
2817
+ this.otpVerificationScreen.parentElement) {
2759
2818
  this.hideLoginElements();
2760
2819
  }
2761
2820
  }, 0);
@@ -2765,7 +2824,8 @@ export class OnboardingUIWeb {
2765
2824
  this.otpInputs[0].focus();
2766
2825
  }
2767
2826
  // Final check to ensure social buttons are hidden
2768
- if (this.otpVerificationScreen && this.otpVerificationScreen.parentElement) {
2827
+ if (this.otpVerificationScreen &&
2828
+ this.otpVerificationScreen.parentElement) {
2769
2829
  this.hideLoginElements();
2770
2830
  }
2771
2831
  }, 100);
@@ -2776,20 +2836,15 @@ export class OnboardingUIWeb {
2776
2836
  * Create email icon SVG
2777
2837
  */
2778
2838
  createEmailIconSVG() {
2779
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
2780
- svg.setAttribute('class', 'onboarding-otp-icon');
2781
- svg.setAttribute('viewBox', '0 0 24 24');
2782
- svg.setAttribute('fill', 'none');
2783
- svg.setAttribute('stroke', 'currentColor');
2784
- svg.setAttribute('stroke-width', '2');
2785
- svg.setAttribute('stroke-linecap', 'round');
2786
- svg.setAttribute('stroke-linejoin', 'round');
2787
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
2788
- path.setAttribute('d', 'M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z');
2839
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
2840
+ svg.setAttribute("class", "onboarding-otp-icon");
2841
+ svg.setAttribute("viewBox", "0 0 17 17");
2842
+ svg.setAttribute("fill", "currentColor");
2843
+ svg.setAttribute("width", "28");
2844
+ svg.setAttribute("height", "28");
2845
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
2846
+ path.setAttribute("d", "M0 2v13h17v-13h-17zM8.494 9.817l-6.896-6.817h13.82l-6.924 6.817zM5.755 8.516l-4.755 4.682v-9.383l4.755 4.701zM6.466 9.219l2.026 2.003 1.996-1.966 4.8 4.744h-13.677l4.855-4.781zM11.201 8.555l4.799-4.725v9.467l-4.799-4.742z");
2789
2847
  svg.appendChild(path);
2790
- const polyline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
2791
- polyline.setAttribute('points', '22,6 12,13 2,6');
2792
- svg.appendChild(polyline);
2793
2848
  return svg;
2794
2849
  }
2795
2850
  /**
@@ -2797,7 +2852,7 @@ export class OnboardingUIWeb {
2797
2852
  */
2798
2853
  handleOtpInput(e, index) {
2799
2854
  const input = e.target;
2800
- const value = input.value.replace(/[^0-9]/g, '');
2855
+ const value = input.value.replace(/[^0-9]/g, "");
2801
2856
  if (value) {
2802
2857
  input.value = value;
2803
2858
  // Move to next input if available
@@ -2811,7 +2866,7 @@ export class OnboardingUIWeb {
2811
2866
  }
2812
2867
  }
2813
2868
  else {
2814
- input.value = '';
2869
+ input.value = "";
2815
2870
  }
2816
2871
  this.updateOtpValue();
2817
2872
  // Auto-submit when 6 digits are entered (only if auto-submit is enabled)
@@ -2827,7 +2882,7 @@ export class OnboardingUIWeb {
2827
2882
  */
2828
2883
  handleOtpKeydown(e, index) {
2829
2884
  const input = e.target;
2830
- if (e.key === 'Backspace' && !input.value && index > 0) {
2885
+ if (e.key === "Backspace" && !input.value && index > 0) {
2831
2886
  this.otpInputs[index - 1].focus();
2832
2887
  }
2833
2888
  }
@@ -2836,11 +2891,11 @@ export class OnboardingUIWeb {
2836
2891
  */
2837
2892
  handleOtpPaste(e) {
2838
2893
  e.preventDefault();
2839
- const pastedData = e.clipboardData?.getData('text') || '';
2840
- const digits = pastedData.replace(/[^0-9]/g, '').slice(0, 6);
2894
+ const pastedData = e.clipboardData?.getData("text") || "";
2895
+ const digits = pastedData.replace(/[^0-9]/g, "").slice(0, 6);
2841
2896
  for (let i = 0; i < 6; i++) {
2842
2897
  if (this.otpInputs[i]) {
2843
- this.otpInputs[i].value = digits[i] || '';
2898
+ this.otpInputs[i].value = digits[i] || "";
2844
2899
  }
2845
2900
  }
2846
2901
  // Focus the last filled input or the last input
@@ -2861,7 +2916,7 @@ export class OnboardingUIWeb {
2861
2916
  * Update OTP value from input fields
2862
2917
  */
2863
2918
  updateOtpValue() {
2864
- this.otp = this.otpInputs.map(input => input.value).join('');
2919
+ this.otp = this.otpInputs.map((input) => input.value).join("");
2865
2920
  }
2866
2921
  /**
2867
2922
  * Handle OTP verification
@@ -2869,14 +2924,14 @@ export class OnboardingUIWeb {
2869
2924
  async handleOtpVerify() {
2870
2925
  this.updateOtpValue();
2871
2926
  if (this.otp.length !== 6) {
2872
- this.setError('Please enter the complete 6-digit code');
2927
+ this.setError("Please enter the complete 6-digit code");
2873
2928
  return;
2874
2929
  }
2875
2930
  // Disable inputs during verification
2876
- this.otpInputs.forEach(input => {
2931
+ this.otpInputs.forEach((input) => {
2877
2932
  input.disabled = true;
2878
2933
  });
2879
- this.setLoading(true, 'email');
2934
+ this.setLoading(true, "email");
2880
2935
  this.setError(null);
2881
2936
  try {
2882
2937
  if (this.config.onEmailOtpVerify) {
@@ -2886,15 +2941,15 @@ export class OnboardingUIWeb {
2886
2941
  }
2887
2942
  else {
2888
2943
  // Use the error message from the API response, fallback to generic message only if not provided
2889
- const errorMessage = result.error || 'Invalid verification code';
2944
+ const errorMessage = result.error || "Invalid verification code";
2890
2945
  throw new Error(errorMessage);
2891
2946
  }
2892
2947
  }
2893
2948
  else if (this.config.emailOtpEndpoint) {
2894
2949
  const response = await fetch(`${this.config.emailOtpEndpoint}/verify`, {
2895
- method: 'POST',
2950
+ method: "POST",
2896
2951
  headers: {
2897
- 'Content-Type': 'application/json',
2952
+ "Content-Type": "application/json",
2898
2953
  },
2899
2954
  body: JSON.stringify({ email: this.email, otp: this.otp }),
2900
2955
  });
@@ -2904,13 +2959,13 @@ export class OnboardingUIWeb {
2904
2959
  }
2905
2960
  else {
2906
2961
  // Use the error message from the API response, fallback to generic message only if not provided
2907
- const errorMessage = data.message || data.error || 'Invalid verification code';
2962
+ const errorMessage = data.message || data.error || "Invalid verification code";
2908
2963
  throw new Error(errorMessage);
2909
2964
  }
2910
2965
  }
2911
2966
  }
2912
2967
  catch (err) {
2913
- const errorMessage = err instanceof Error ? err.message : 'An error occurred';
2968
+ const errorMessage = err instanceof Error ? err.message : "An error occurred";
2914
2969
  this.setError(errorMessage);
2915
2970
  this.config.onLoginError?.(err instanceof Error ? err : new Error(errorMessage));
2916
2971
  // Disable auto-submit after failed attempt
@@ -2922,23 +2977,25 @@ export class OnboardingUIWeb {
2922
2977
  this.hideLoginElements();
2923
2978
  // Also use setTimeout to ensure they stay hidden after any potential re-renders
2924
2979
  setTimeout(() => {
2925
- if (this.otpVerificationScreen && this.otpVerificationScreen.parentElement) {
2980
+ if (this.otpVerificationScreen &&
2981
+ this.otpVerificationScreen.parentElement) {
2926
2982
  this.hideLoginElements();
2927
2983
  }
2928
2984
  }, 0);
2929
2985
  // Additional check after a short delay to catch any late re-renders
2930
2986
  setTimeout(() => {
2931
- if (this.otpVerificationScreen && this.otpVerificationScreen.parentElement) {
2987
+ if (this.otpVerificationScreen &&
2988
+ this.otpVerificationScreen.parentElement) {
2932
2989
  this.hideLoginElements();
2933
2990
  }
2934
2991
  }, 100);
2935
2992
  }
2936
2993
  // Clear OTP inputs on error
2937
- this.otpInputs.forEach(input => {
2938
- input.value = '';
2994
+ this.otpInputs.forEach((input) => {
2995
+ input.value = "";
2939
2996
  input.disabled = false;
2940
2997
  });
2941
- this.otp = '';
2998
+ this.otp = "";
2942
2999
  if (this.otpInputs[0]) {
2943
3000
  this.otpInputs[0].focus();
2944
3001
  }
@@ -2957,29 +3014,29 @@ export class OnboardingUIWeb {
2957
3014
  // Re-enable auto-submit when resending OTP
2958
3015
  this.autoSubmitEnabled = true;
2959
3016
  this.setError(null);
2960
- this.setLoading(true, 'email');
3017
+ this.setLoading(true, "email");
2961
3018
  try {
2962
3019
  if (this.config.onEmailOtpInitiate) {
2963
3020
  await this.config.onEmailOtpInitiate(this.email);
2964
3021
  }
2965
3022
  else if (this.config.emailOtpEndpoint) {
2966
3023
  const response = await fetch(this.config.emailOtpEndpoint, {
2967
- method: 'POST',
3024
+ method: "POST",
2968
3025
  headers: {
2969
- 'Content-Type': 'application/json',
3026
+ "Content-Type": "application/json",
2970
3027
  },
2971
3028
  body: JSON.stringify({ email: this.email }),
2972
3029
  });
2973
3030
  if (!response.ok) {
2974
- throw new Error('Failed to resend OTP');
3031
+ throw new Error("Failed to resend OTP");
2975
3032
  }
2976
3033
  }
2977
3034
  // Clear OTP inputs
2978
- this.otpInputs.forEach(input => {
2979
- input.value = '';
3035
+ this.otpInputs.forEach((input) => {
3036
+ input.value = "";
2980
3037
  input.disabled = false;
2981
3038
  });
2982
- this.otp = '';
3039
+ this.otp = "";
2983
3040
  if (this.otpInputs[0]) {
2984
3041
  this.otpInputs[0].focus();
2985
3042
  }
@@ -2987,7 +3044,7 @@ export class OnboardingUIWeb {
2987
3044
  this.startResendCooldown();
2988
3045
  }
2989
3046
  catch (err) {
2990
- const errorMessage = err instanceof Error ? err.message : 'Failed to resend OTP';
3047
+ const errorMessage = err instanceof Error ? err.message : "Failed to resend OTP";
2991
3048
  this.setError(errorMessage);
2992
3049
  this.config.onLoginError?.(err instanceof Error ? err : new Error(errorMessage));
2993
3050
  }
@@ -3007,10 +3064,10 @@ export class OnboardingUIWeb {
3007
3064
  // Update UI immediately
3008
3065
  if (this.resendButton) {
3009
3066
  this.resendButton.textContent = `Resend (${this.resendCooldown}s)`;
3010
- this.resendButton.classList.add('onboarding-otp-resend-link-disabled');
3011
- this.resendButton.style.pointerEvents = 'none';
3012
- this.resendButton.style.cursor = 'not-allowed';
3013
- this.resendButton.style.opacity = '0.6';
3067
+ this.resendButton.classList.add("onboarding-otp-resend-link-disabled");
3068
+ this.resendButton.style.pointerEvents = "none";
3069
+ this.resendButton.style.cursor = "not-allowed";
3070
+ this.resendButton.style.opacity = "0.6";
3014
3071
  }
3015
3072
  // Start countdown timer
3016
3073
  this.resendCooldownTimer = setInterval(() => {
@@ -3027,11 +3084,11 @@ export class OnboardingUIWeb {
3027
3084
  this.resendCooldownTimer = null;
3028
3085
  }
3029
3086
  if (this.resendButton) {
3030
- this.resendButton.textContent = 'Resend';
3031
- this.resendButton.classList.remove('onboarding-otp-resend-link-disabled');
3032
- this.resendButton.style.pointerEvents = 'auto';
3033
- this.resendButton.style.cursor = 'pointer';
3034
- this.resendButton.style.opacity = '1';
3087
+ this.resendButton.textContent = "Resend";
3088
+ this.resendButton.classList.remove("onboarding-otp-resend-link-disabled");
3089
+ this.resendButton.style.pointerEvents = "auto";
3090
+ this.resendButton.style.cursor = "pointer";
3091
+ this.resendButton.style.opacity = "1";
3035
3092
  }
3036
3093
  }
3037
3094
  }, 1000);
@@ -3040,32 +3097,42 @@ export class OnboardingUIWeb {
3040
3097
  * Set error message
3041
3098
  */
3042
3099
  setError(message) {
3100
+ const formatMessage = (msg) => {
3101
+ if (msg.startsWith("{") && msg.endsWith("}")) {
3102
+ return msg;
3103
+ }
3104
+ return `{ ${msg} }`;
3105
+ };
3043
3106
  // Show error in OTP screen if it exists
3044
3107
  if (this.otpVerificationScreen) {
3045
- const otpErrorElement = this.otpVerificationScreen.errorElement;
3108
+ const otpErrorElement = this.otpVerificationScreen
3109
+ .errorElement;
3046
3110
  if (otpErrorElement) {
3047
3111
  if (message) {
3048
- otpErrorElement.textContent = message;
3049
- otpErrorElement.style.display = 'block';
3112
+ otpErrorElement.textContent = formatMessage(message);
3113
+ otpErrorElement.style.display = "block";
3050
3114
  }
3051
3115
  else {
3052
- otpErrorElement.style.display = 'none';
3116
+ otpErrorElement.style.display = "none";
3053
3117
  }
3054
3118
  // Ensure social buttons remain hidden when showing error on OTP screen
3055
3119
  // Call immediately and also with delays to catch any re-renders
3056
3120
  this.hideLoginElements();
3057
3121
  setTimeout(() => {
3058
- if (this.otpVerificationScreen && this.otpVerificationScreen.parentElement) {
3122
+ if (this.otpVerificationScreen &&
3123
+ this.otpVerificationScreen.parentElement) {
3059
3124
  this.hideLoginElements();
3060
3125
  }
3061
3126
  }, 0);
3062
3127
  setTimeout(() => {
3063
- if (this.otpVerificationScreen && this.otpVerificationScreen.parentElement) {
3128
+ if (this.otpVerificationScreen &&
3129
+ this.otpVerificationScreen.parentElement) {
3064
3130
  this.hideLoginElements();
3065
3131
  }
3066
3132
  }, 50);
3067
3133
  setTimeout(() => {
3068
- if (this.otpVerificationScreen && this.otpVerificationScreen.parentElement) {
3134
+ if (this.otpVerificationScreen &&
3135
+ this.otpVerificationScreen.parentElement) {
3069
3136
  this.hideLoginElements();
3070
3137
  }
3071
3138
  }, 150);
@@ -3076,11 +3143,11 @@ export class OnboardingUIWeb {
3076
3143
  if (!this.errorElement)
3077
3144
  return;
3078
3145
  if (message) {
3079
- this.errorElement.textContent = message;
3080
- this.errorElement.style.display = 'block';
3146
+ this.errorElement.textContent = formatMessage(message);
3147
+ this.errorElement.style.display = "block";
3081
3148
  }
3082
3149
  else {
3083
- this.errorElement.style.display = 'none';
3150
+ this.errorElement.style.display = "none";
3084
3151
  }
3085
3152
  }
3086
3153
  /**
@@ -3099,11 +3166,15 @@ export class OnboardingUIWeb {
3099
3166
  if (this.continueButton) {
3100
3167
  this.continueButton.disabled = loading || !this.email;
3101
3168
  // Show loading text only if this is the active button
3102
- if (loading && this.activeButton === 'email') {
3103
- this.continueButton.textContent = this.otpSent ? 'Verifying...' : 'Loading...';
3169
+ if (loading && this.activeButton === "email") {
3170
+ this.continueButton.textContent = this.otpSent
3171
+ ? "Verifying..."
3172
+ : "Loading...";
3104
3173
  }
3105
3174
  else if (!loading) {
3106
- this.continueButton.textContent = this.otpSent ? 'Verify OTP' : 'Continue';
3175
+ this.continueButton.textContent = this.otpSent
3176
+ ? "Verify OTP"
3177
+ : "Continue";
3107
3178
  }
3108
3179
  }
3109
3180
  // Email arrow button (when all auth methods are enabled)
@@ -3127,23 +3198,23 @@ export class OnboardingUIWeb {
3127
3198
  if (this.passkeyLoginButton) {
3128
3199
  this.passkeyLoginButton.disabled = loading;
3129
3200
  // Show loading text only if this is the active button
3130
- if (loading && this.activeButton === 'passkey') {
3201
+ if (loading && this.activeButton === "passkey") {
3131
3202
  // Update only the text node, preserve the icon
3132
- const textNodes = Array.from(this.passkeyLoginButton.childNodes).filter(node => node.nodeType === Node.TEXT_NODE);
3203
+ const textNodes = Array.from(this.passkeyLoginButton.childNodes).filter((node) => node.nodeType === Node.TEXT_NODE);
3133
3204
  if (textNodes.length > 0) {
3134
- textNodes[0].textContent = ' Authenticating...';
3205
+ textNodes[0].textContent = " Authenticating...";
3135
3206
  }
3136
3207
  else {
3137
3208
  // If no text node exists, append one (icon should already be there)
3138
- this.passkeyLoginButton.appendChild(document.createTextNode(' Authenticating...'));
3209
+ this.passkeyLoginButton.appendChild(document.createTextNode(" Authenticating..."));
3139
3210
  }
3140
- this.passkeyLoginButton.style.opacity = '0.7';
3141
- this.passkeyLoginButton.style.cursor = 'not-allowed';
3211
+ this.passkeyLoginButton.style.opacity = "0.7";
3212
+ this.passkeyLoginButton.style.cursor = "not-allowed";
3142
3213
  }
3143
3214
  else if (!loading) {
3144
3215
  // Update only the text node, preserve the icon
3145
- const textNodes = Array.from(this.passkeyLoginButton.childNodes).filter(node => node.nodeType === Node.TEXT_NODE);
3146
- const passkeyText = ` ${this.config.labels?.passkeyLoginButton || 'Log in with passkey'}`;
3216
+ const textNodes = Array.from(this.passkeyLoginButton.childNodes).filter((node) => node.nodeType === Node.TEXT_NODE);
3217
+ const passkeyText = ` ${this.config.labels?.passkeyLoginButton || "Log in with passkey"}`;
3147
3218
  if (textNodes.length > 0) {
3148
3219
  textNodes[0].textContent = passkeyText;
3149
3220
  }
@@ -3151,21 +3222,21 @@ export class OnboardingUIWeb {
3151
3222
  // If no text node exists, append one (icon should already be there)
3152
3223
  this.passkeyLoginButton.appendChild(document.createTextNode(passkeyText));
3153
3224
  }
3154
- this.passkeyLoginButton.style.opacity = '1';
3155
- this.passkeyLoginButton.style.cursor = 'pointer';
3225
+ this.passkeyLoginButton.style.opacity = "1";
3226
+ this.passkeyLoginButton.style.cursor = "pointer";
3156
3227
  }
3157
3228
  }
3158
3229
  // Passkey signup link
3159
3230
  if (this.passkeySignupLink) {
3160
3231
  if (loading) {
3161
- this.passkeySignupLink.style.opacity = '0.5';
3162
- this.passkeySignupLink.style.pointerEvents = 'none';
3163
- this.passkeySignupLink.style.cursor = 'not-allowed';
3232
+ this.passkeySignupLink.style.opacity = "0.5";
3233
+ this.passkeySignupLink.style.pointerEvents = "none";
3234
+ this.passkeySignupLink.style.cursor = "not-allowed";
3164
3235
  }
3165
3236
  else {
3166
- this.passkeySignupLink.style.opacity = '1';
3167
- this.passkeySignupLink.style.pointerEvents = 'auto';
3168
- this.passkeySignupLink.style.cursor = 'pointer';
3237
+ this.passkeySignupLink.style.opacity = "1";
3238
+ this.passkeySignupLink.style.pointerEvents = "auto";
3239
+ this.passkeySignupLink.style.cursor = "pointer";
3169
3240
  }
3170
3241
  }
3171
3242
  // Email input
@@ -3180,14 +3251,14 @@ export class OnboardingUIWeb {
3180
3251
  if (this.verifyButton) {
3181
3252
  this.verifyButton.disabled = loading;
3182
3253
  if (loading) {
3183
- this.verifyButton.textContent = 'Verifying...';
3184
- this.verifyButton.style.opacity = '0.7';
3185
- this.verifyButton.style.cursor = 'not-allowed';
3254
+ this.verifyButton.textContent = "Verifying...";
3255
+ this.verifyButton.style.opacity = "0.7";
3256
+ this.verifyButton.style.cursor = "not-allowed";
3186
3257
  }
3187
3258
  else {
3188
- this.verifyButton.textContent = 'Verify';
3189
- this.verifyButton.style.opacity = '1';
3190
- this.verifyButton.style.cursor = 'pointer';
3259
+ this.verifyButton.textContent = "Verify";
3260
+ this.verifyButton.style.opacity = "1";
3261
+ this.verifyButton.style.cursor = "pointer";
3191
3262
  }
3192
3263
  }
3193
3264
  }
@@ -3195,12 +3266,13 @@ export class OnboardingUIWeb {
3195
3266
  * Update button state
3196
3267
  */
3197
3268
  updateButtonState() {
3269
+ const isValid = isValidEmail(this.email.trim());
3198
3270
  if (this.continueButton) {
3199
- this.continueButton.disabled = this.loading || !this.email;
3271
+ this.continueButton.disabled = this.loading || !isValid;
3200
3272
  }
3201
3273
  // Update arrow button state (when all auth methods are enabled)
3202
3274
  if (this.emailArrowButton) {
3203
- this.emailArrowButton.disabled = this.loading || !this.email;
3275
+ this.emailArrowButton.disabled = this.loading || !isValid;
3204
3276
  }
3205
3277
  }
3206
3278
  /**
@@ -3217,7 +3289,7 @@ export class OnboardingUIWeb {
3217
3289
  */
3218
3290
  setVisible(visible) {
3219
3291
  if (this.rootElement) {
3220
- this.rootElement.style.display = visible ? '' : 'none';
3292
+ this.rootElement.style.display = visible ? "" : "none";
3221
3293
  }
3222
3294
  }
3223
3295
  /**
@@ -3236,26 +3308,26 @@ export class OnboardingUIWeb {
3236
3308
  this.otpVerificationScreen = null;
3237
3309
  }
3238
3310
  // Remove loading/error mode classes and OTP active class
3239
- const card = this.rootElement?.querySelector('.onboarding-card');
3311
+ const card = this.rootElement?.querySelector(".onboarding-card");
3240
3312
  if (card) {
3241
- card.classList.remove('onboarding-mode-loading');
3242
- card.classList.remove('onboarding-mode-error');
3243
- card.classList.remove('onboarding-otp-active');
3313
+ card.classList.remove("onboarding-mode-loading");
3314
+ card.classList.remove("onboarding-mode-error");
3315
+ card.classList.remove("onboarding-otp-active");
3244
3316
  }
3245
3317
  // Hide loading modal if exists (for inline components)
3246
3318
  this.hideLoadingModal();
3247
3319
  // Remove error container if exists
3248
- const errorContainer = this.rootElement?.querySelector('.onboarding-error-container');
3320
+ const errorContainer = this.rootElement?.querySelector(".onboarding-error-container");
3249
3321
  if (errorContainer) {
3250
3322
  errorContainer.remove();
3251
3323
  }
3252
3324
  // Clear OTP inputs
3253
- this.otpInputs.forEach(input => {
3254
- input.value = '';
3325
+ this.otpInputs.forEach((input) => {
3326
+ input.value = "";
3255
3327
  input.disabled = false;
3256
3328
  });
3257
3329
  this.otpInputs = [];
3258
- this.otp = '';
3330
+ this.otp = "";
3259
3331
  this.otpSent = false;
3260
3332
  this.loading = false;
3261
3333
  // Clear timer
@@ -3266,88 +3338,105 @@ export class OnboardingUIWeb {
3266
3338
  }
3267
3339
  this.resendCooldown = 0;
3268
3340
  if (this.resendButton) {
3269
- this.resendButton.textContent = 'Resend';
3270
- this.resendButton.classList.remove('onboarding-otp-resend-link-disabled');
3271
- this.resendButton.style.pointerEvents = 'auto';
3272
- this.resendButton.style.cursor = 'pointer';
3273
- this.resendButton.style.opacity = '1';
3341
+ this.resendButton.textContent = "Resend";
3342
+ this.resendButton.classList.remove("onboarding-otp-resend-link-disabled");
3343
+ this.resendButton.style.pointerEvents = "auto";
3344
+ this.resendButton.style.cursor = "pointer";
3345
+ this.resendButton.style.opacity = "1";
3274
3346
  }
3275
3347
  // Get auth methods
3276
- const authMethods = this.config.authMethods || ['otp', 'google'];
3277
- const showEmail = authMethods.includes('otp');
3278
- const showGoogle = authMethods.includes('google');
3279
- const showTwitter = authMethods.includes('twitter');
3280
- const showDiscord = authMethods.includes('discord');
3281
- const showPasskey = authMethods.includes('passkey');
3348
+ const authMethods = this.config.authMethods || ["otp", "google"];
3349
+ const showEmail = authMethods.includes("otp");
3350
+ const showGoogle = authMethods.includes("google");
3351
+ const showTwitter = authMethods.includes("twitter");
3352
+ const showDiscord = authMethods.includes("discord");
3353
+ const showPasskey = authMethods.includes("passkey");
3282
3354
  const socialMethods = [
3283
- { key: 'google', show: showGoogle },
3284
- { key: 'twitter', show: showTwitter },
3285
- { key: 'discord', show: showDiscord },
3355
+ { key: "google", show: showGoogle },
3356
+ { key: "twitter", show: showTwitter },
3357
+ { key: "discord", show: showDiscord },
3286
3358
  ].filter((m) => m.show);
3287
3359
  // Show the email form and all login-related elements
3288
3360
  if (this.emailForm) {
3289
- this.emailForm.style.display = showEmail ? '' : 'none';
3361
+ this.emailForm.style.display = showEmail ? "" : "none";
3362
+ }
3363
+ // Show the header again when returning to login form
3364
+ const header = this.rootElement?.querySelector(".onboarding-header");
3365
+ if (header) {
3366
+ header.style.display = "";
3290
3367
  }
3291
3368
  if (this.divider) {
3292
- this.divider.style.display = (showEmail && socialMethods.length > 0) ? '' : 'none';
3369
+ this.divider.style.display =
3370
+ showEmail && socialMethods.length > 0 ? "" : "none";
3293
3371
  }
3294
3372
  if (this.passkeyDivider) {
3295
- this.passkeyDivider.style.display = (showPasskey && (showEmail || socialMethods.length > 0)) ? '' : 'none';
3373
+ this.passkeyDivider.style.display =
3374
+ showPasskey && (showEmail || socialMethods.length > 0) ? "" : "none";
3296
3375
  }
3297
3376
  if (this.googleButton) {
3298
- this.googleButton.style.display = showGoogle ? '' : 'none';
3377
+ this.googleButton.style.display = showGoogle ? "" : "none";
3299
3378
  this.googleButton.disabled = false;
3300
3379
  }
3301
3380
  if (this.twitterButton) {
3302
- this.twitterButton.style.display = showTwitter ? '' : 'none';
3381
+ this.twitterButton.style.display = showTwitter ? "" : "none";
3303
3382
  this.twitterButton.disabled = false;
3304
3383
  }
3305
3384
  if (this.discordButton) {
3306
- this.discordButton.style.display = showDiscord ? '' : 'none';
3385
+ this.discordButton.style.display = showDiscord ? "" : "none";
3307
3386
  this.discordButton.disabled = false;
3308
3387
  }
3309
3388
  if (this.socialGrid) {
3310
- this.socialGrid.style.display = socialMethods.length > 1 ? '' : 'none';
3389
+ this.socialGrid.style.display = socialMethods.length > 1 ? "" : "none";
3311
3390
  }
3312
3391
  // Show passkey buttons again when returning to login form
3313
3392
  if (this.passkeyLoginButton) {
3314
- this.passkeyLoginButton.style.display = showPasskey ? '' : 'none';
3393
+ this.passkeyLoginButton.style.display = showPasskey ? "" : "none";
3315
3394
  }
3316
3395
  if (this.passkeySignupLink) {
3317
- this.passkeySignupLink.style.display = showPasskey ? '' : 'none';
3396
+ this.passkeySignupLink.style.display = showPasskey ? "" : "none";
3318
3397
  }
3319
3398
  if (this.passkeyErrorElement) {
3320
- this.passkeyErrorElement.style.display = 'none'; // Hide error when resetting
3399
+ this.passkeyErrorElement.style.display = "none"; // Hide error when resetting
3321
3400
  }
3322
3401
  // Show external wallets again when returning to login form
3323
- // Note: The visibility will be managed by AbstraxnProvider, but we ensure they're available
3324
- // AbstraxnProvider will handle showing them if external wallets are enabled
3402
+ if (this.externalWalletsEnabled) {
3403
+ if (this.externalWalletContainer) {
3404
+ this.externalWalletContainer.style.display = "";
3405
+ }
3406
+ if (this.externalWalletDivider) {
3407
+ // Show divider only if we have email or social methods
3408
+ const hasEmailOrSocial = showEmail || socialMethods.length > 0;
3409
+ this.externalWalletDivider.style.display = hasEmailOrSocial
3410
+ ? ""
3411
+ : "none";
3412
+ }
3413
+ }
3325
3414
  if (this.footer) {
3326
- this.footer.style.display = '';
3415
+ this.footer.style.display = "";
3327
3416
  }
3328
3417
  // Clear error messages
3329
3418
  this.setError(null);
3330
3419
  if (this.errorElement) {
3331
- this.errorElement.style.display = 'none';
3420
+ this.errorElement.style.display = "none";
3332
3421
  }
3333
3422
  // Reset email input - enable it and clear value
3334
3423
  if (this.emailInput) {
3335
- this.emailInput.value = '';
3424
+ this.emailInput.value = "";
3336
3425
  this.emailInput.disabled = false;
3337
- this.email = '';
3426
+ this.email = "";
3338
3427
  }
3339
3428
  // Reset OTP group (hidden input)
3340
3429
  if (this.otpGroup) {
3341
- this.otpGroup.style.display = 'none';
3430
+ this.otpGroup.style.display = "none";
3342
3431
  if (this.otpInput) {
3343
- this.otpInput.value = '';
3432
+ this.otpInput.value = "";
3344
3433
  this.otpInput.disabled = false;
3345
3434
  }
3346
3435
  }
3347
3436
  // Reset button state - ensure it shows "Continue" and is properly enabled/disabled
3348
3437
  if (this.continueButton) {
3349
- this.continueButton.disabled = !this.email; // Disabled only if no email
3350
- this.continueButton.textContent = this.config.labels?.emailButton || 'Continue';
3438
+ this.continueButton.textContent =
3439
+ this.config.labels?.emailButton || "Continue";
3351
3440
  }
3352
3441
  // Update button state to ensure everything is in sync
3353
3442
  this.updateButtonState();
@@ -3358,13 +3447,13 @@ export class OnboardingUIWeb {
3358
3447
  close() {
3359
3448
  // Clear URL params to prevent showing error again on refresh
3360
3449
  const url = new URL(window.location.href);
3361
- url.searchParams.delete('error');
3362
- url.searchParams.delete('success');
3450
+ url.searchParams.delete("error");
3451
+ url.searchParams.delete("success");
3363
3452
  window.history.replaceState({}, document.title, url.toString());
3364
3453
  if (this.modalOverlay) {
3365
3454
  // Add closing animation
3366
- this.modalOverlay.classList.remove('onboarding-modal-open');
3367
- this.modalOverlay.classList.add('onboarding-modal-closing');
3455
+ this.modalOverlay.classList.remove("onboarding-modal-open");
3456
+ this.modalOverlay.classList.add("onboarding-modal-closing");
3368
3457
  // Remove after animation
3369
3458
  setTimeout(() => {
3370
3459
  this.destroy();
@@ -3374,7 +3463,7 @@ export class OnboardingUIWeb {
3374
3463
  this.destroy();
3375
3464
  }
3376
3465
  // Restore body scroll
3377
- document.body.style.overflow = '';
3466
+ document.body.style.overflow = "";
3378
3467
  // Call onClose callback
3379
3468
  if (this.config.onClose) {
3380
3469
  this.config.onClose();
@@ -3395,7 +3484,7 @@ export class OnboardingUIWeb {
3395
3484
  this.rootElement.parentNode.removeChild(this.rootElement);
3396
3485
  }
3397
3486
  // Restore body scroll
3398
- document.body.style.overflow = '';
3487
+ document.body.style.overflow = "";
3399
3488
  // Clear references
3400
3489
  this.rootElement = null;
3401
3490
  this.modalOverlay = null;
@@ -3407,7 +3496,6 @@ export class OnboardingUIWeb {
3407
3496
  this.googleButton = null;
3408
3497
  this.errorElement = null;
3409
3498
  this.otpGroup = null;
3410
- this.closeButton = null;
3411
3499
  this.otpVerificationScreen = null; // Clear OTP screen reference
3412
3500
  this.externalWalletContainer = null; // Clear external wallet container reference
3413
3501
  this.externalWalletDivider = null; // Clear external wallet divider reference
@@ -3419,35 +3507,40 @@ export class OnboardingUIWeb {
3419
3507
  const element = document.createElement(tag);
3420
3508
  Object.keys(options).forEach((key) => {
3421
3509
  const value = options[key];
3422
- if (key === 'className' && typeof value === 'string') {
3510
+ if (key === "className" && typeof value === "string") {
3423
3511
  element.className = value;
3424
3512
  }
3425
- else if (key === 'textContent' && (typeof value === 'string' || value === null)) {
3513
+ else if (key === "textContent" &&
3514
+ (typeof value === "string" || value === null)) {
3426
3515
  element.textContent = value;
3427
3516
  }
3428
- else if (key === 'innerHTML' && typeof value === 'string') {
3517
+ else if (key === "innerHTML" && typeof value === "string") {
3429
3518
  element.innerHTML = value;
3430
3519
  }
3431
- else if (key === 'style' && typeof value === 'string') {
3432
- element.setAttribute('style', value);
3520
+ else if (key === "style" && typeof value === "string") {
3521
+ element.setAttribute("style", value);
3433
3522
  }
3434
- else if (key === 'htmlFor' && typeof value === 'string') {
3523
+ else if (key === "htmlFor" && typeof value === "string") {
3435
3524
  // Use setAttribute for htmlFor to ensure it works correctly
3436
- element.setAttribute('for', value);
3525
+ element.setAttribute("for", value);
3437
3526
  }
3438
- else if (key.startsWith('aria-') || key === 'role' || key === 'tabIndex' || key === 'autocomplete' || key === 'noValidate') {
3527
+ else if (key.startsWith("aria-") ||
3528
+ key === "role" ||
3529
+ key === "tabIndex" ||
3530
+ key === "autocomplete" ||
3531
+ key === "noValidate") {
3439
3532
  // Handle ARIA attributes and other special attributes
3440
- if (key === 'tabIndex') {
3533
+ if (key === "tabIndex") {
3441
3534
  element.tabIndex = value;
3442
3535
  }
3443
- else if (key === 'noValidate') {
3536
+ else if (key === "noValidate") {
3444
3537
  element.noValidate = value;
3445
3538
  }
3446
3539
  else {
3447
3540
  element.setAttribute(key, String(value));
3448
3541
  }
3449
3542
  }
3450
- else if (key !== 'style' && value !== undefined) {
3543
+ else if (key !== "style" && value !== undefined) {
3451
3544
  element[key] = value;
3452
3545
  }
3453
3546
  });
@@ -3458,34 +3551,29 @@ export class OnboardingUIWeb {
3458
3551
  */
3459
3552
  parseStyle(style) {
3460
3553
  if (!style)
3461
- return '';
3462
- if (typeof style === 'string')
3554
+ return "";
3555
+ if (typeof style === "string")
3463
3556
  return style;
3464
3557
  return Object.entries(style)
3465
3558
  .filter(([_, value]) => value !== undefined && value !== null)
3466
3559
  .map(([key, value]) => {
3467
- const cssKey = key.replace(/([A-Z])/g, '-$1').toLowerCase();
3560
+ const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
3468
3561
  return `${cssKey}: ${value}`;
3469
3562
  })
3470
- .join('; ');
3563
+ .join("; ");
3471
3564
  }
3472
3565
  /**
3473
3566
  * Create email icon SVG
3474
3567
  */
3475
3568
  createEmailIcon() {
3476
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
3477
- svg.setAttribute('class', 'onboarding-input-icon');
3478
- svg.setAttribute('width', '20');
3479
- svg.setAttribute('height', '20');
3480
- svg.setAttribute('viewBox', '0 0 20 20');
3481
- svg.setAttribute('fill', 'none');
3482
- svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
3483
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
3484
- path.setAttribute('d', 'M2.5 6.66667L10 11.6667L17.5 6.66667M3.33333 15H16.6667C17.5871 15 18.3333 14.2538 18.3333 13.3333V6.66667C18.3333 5.74619 17.5871 5 16.6667 5H3.33333C2.41286 5 1.66667 5.74619 1.66667 6.66667V13.3333C1.66667 14.2538 2.41286 15 3.33333 15Z');
3485
- path.setAttribute('stroke', 'currentColor');
3486
- path.setAttribute('stroke-width', '1.5');
3487
- path.setAttribute('stroke-linecap', 'round');
3488
- path.setAttribute('stroke-linejoin', 'round');
3569
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
3570
+ svg.setAttribute("class", "onboarding-input-icon");
3571
+ svg.setAttribute("width", "18");
3572
+ svg.setAttribute("height", "18");
3573
+ svg.setAttribute("viewBox", "0 0 17 17");
3574
+ svg.setAttribute("fill", "currentColor");
3575
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
3576
+ path.setAttribute("d", "M0 2v13h17v-13h-17zM8.494 9.817l-6.896-6.817h13.82l-6.924 6.817zM5.755 8.516l-4.755 4.682v-9.383l4.755 4.701zM6.466 9.219l2.026 2.003 1.996-1.966 4.8 4.744h-13.677l4.855-4.781zM11.201 8.555l4.799-4.725v9.467l-4.799-4.742z");
3489
3577
  svg.appendChild(path);
3490
3578
  return svg;
3491
3579
  }
@@ -3493,35 +3581,35 @@ export class OnboardingUIWeb {
3493
3581
  * Create Google icon SVG
3494
3582
  */
3495
3583
  createGoogleIcon() {
3496
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
3497
- svg.setAttribute('class', 'onboarding-google-icon');
3498
- svg.setAttribute('width', '20');
3499
- svg.setAttribute('height', '20');
3500
- svg.setAttribute('viewBox', '0 0 20 20');
3501
- svg.setAttribute('fill', 'none');
3502
- svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
3584
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
3585
+ svg.setAttribute("class", "onboarding-google-icon");
3586
+ svg.setAttribute("width", "20");
3587
+ svg.setAttribute("height", "20");
3588
+ svg.setAttribute("viewBox", "0 0 20 20");
3589
+ svg.setAttribute("fill", "none");
3590
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
3503
3591
  const paths = [
3504
3592
  {
3505
- d: 'M18.1712 8.36792H17.5V8.33333H10V11.6667H14.7096C14.2225 13.1071 13.2408 14.2854 12.0125 15.0125L14.9696 17.3458C16.7792 15.6958 17.9167 13.3958 17.9167 10.8333C17.9167 10.275 17.8708 9.72917 17.7833 9.20417L18.1712 8.36792Z',
3506
- fill: '#4285F4',
3593
+ d: "M18.1712 8.36792H17.5V8.33333H10V11.6667H14.7096C14.2225 13.1071 13.2408 14.2854 12.0125 15.0125L14.9696 17.3458C16.7792 15.6958 17.9167 13.3958 17.9167 10.8333C17.9167 10.275 17.8708 9.72917 17.7833 9.20417L18.1712 8.36792Z",
3594
+ fill: "#4285F4",
3507
3595
  },
3508
3596
  {
3509
- d: 'M10 18.3333C12.5542 18.3333 14.7208 17.4708 16.3042 16.0125L13.3471 13.6792C12.5042 14.2542 11.4042 14.5833 10 14.5833C7.52083 14.5833 5.39583 12.9042 4.61667 10.6917L1.57083 13.0292C3.13333 16.1 6.32083 18.3333 10 18.3333Z',
3510
- fill: '#34A853',
3597
+ d: "M10 18.3333C12.5542 18.3333 14.7208 17.4708 16.3042 16.0125L13.3471 13.6792C12.5042 14.2542 11.4042 14.5833 10 14.5833C7.52083 14.5833 5.39583 12.9042 4.61667 10.6917L1.57083 13.0292C3.13333 16.1 6.32083 18.3333 10 18.3333Z",
3598
+ fill: "#34A853",
3511
3599
  },
3512
3600
  {
3513
- d: 'M4.61667 10.6917C4.39583 10.0708 4.27083 9.40417 4.27083 8.70833C4.27083 8.0125 4.39583 7.34583 4.61667 6.72417L1.57083 4.3875C0.9375 5.66667 0.583336 7.10833 0.583336 8.70833C0.583336 10.3083 0.9375 11.75 1.57083 13.0292L4.61667 10.6917Z',
3514
- fill: '#FBBC05',
3601
+ d: "M4.61667 10.6917C4.39583 10.0708 4.27083 9.40417 4.27083 8.70833C4.27083 8.0125 4.39583 7.34583 4.61667 6.72417L1.57083 4.3875C0.9375 5.66667 0.583336 7.10833 0.583336 8.70833C0.583336 10.3083 0.9375 11.75 1.57083 13.0292L4.61667 10.6917Z",
3602
+ fill: "#FBBC05",
3515
3603
  },
3516
3604
  {
3517
- d: 'M10 2.91667C11.5125 2.91667 12.8708 3.47083 13.9292 4.42917L16.375 2C14.7208 0.483333 12.5542 -0.000165871 10 -0.000165871C6.32083 -0.000165871 3.13333 2.23333 1.57083 5.30417L4.61667 7.64167C5.39583 5.42917 7.52083 3.75 10 3.75V2.91667Z',
3518
- fill: '#EA4335',
3605
+ d: "M10 2.91667C11.5125 2.91667 12.8708 3.47083 13.9292 4.42917L16.375 2C14.7208 0.483333 12.5542 -0.000165871 10 -0.000165871C6.32083 -0.000165871 3.13333 2.23333 1.57083 5.30417L4.61667 7.64167C5.39583 5.42917 7.52083 3.75 10 3.75V2.91667Z",
3606
+ fill: "#EA4335",
3519
3607
  },
3520
3608
  ];
3521
3609
  paths.forEach((pathData) => {
3522
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
3523
- path.setAttribute('d', pathData.d);
3524
- path.setAttribute('fill', pathData.fill);
3610
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
3611
+ path.setAttribute("d", pathData.d);
3612
+ path.setAttribute("fill", pathData.fill);
3525
3613
  svg.appendChild(path);
3526
3614
  });
3527
3615
  return svg;
@@ -3530,19 +3618,19 @@ export class OnboardingUIWeb {
3530
3618
  * Create right arrow icon SVG
3531
3619
  */
3532
3620
  createArrowIcon() {
3533
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
3534
- svg.setAttribute('class', 'onboarding-input-arrow-icon');
3535
- svg.setAttribute('width', '20');
3536
- svg.setAttribute('height', '20');
3537
- svg.setAttribute('viewBox', '0 0 20 20');
3538
- svg.setAttribute('fill', 'none');
3539
- svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
3540
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
3541
- path.setAttribute('d', 'M7.5 15L12.5 10L7.5 5');
3542
- path.setAttribute('stroke', 'currentColor');
3543
- path.setAttribute('stroke-width', '2');
3544
- path.setAttribute('stroke-linecap', 'round');
3545
- path.setAttribute('stroke-linejoin', 'round');
3621
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
3622
+ svg.setAttribute("class", "onboarding-input-arrow-icon");
3623
+ svg.setAttribute("width", "20");
3624
+ svg.setAttribute("height", "20");
3625
+ svg.setAttribute("viewBox", "0 0 20 20");
3626
+ svg.setAttribute("fill", "none");
3627
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
3628
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
3629
+ path.setAttribute("d", "M7.5 15L12.5 10L7.5 5");
3630
+ path.setAttribute("stroke", "currentColor");
3631
+ path.setAttribute("stroke-width", "2");
3632
+ path.setAttribute("stroke-linecap", "round");
3633
+ path.setAttribute("stroke-linejoin", "round");
3546
3634
  svg.appendChild(path);
3547
3635
  return svg;
3548
3636
  }
@@ -3550,20 +3638,20 @@ export class OnboardingUIWeb {
3550
3638
  * Create passkey icon SVG
3551
3639
  */
3552
3640
  createPasskeyIcon() {
3553
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
3554
- svg.setAttribute('class', 'onboarding-passkey-icon');
3555
- svg.setAttribute('width', '20');
3556
- svg.setAttribute('height', '20');
3557
- svg.setAttribute('viewBox', '0 0 24 24');
3558
- svg.setAttribute('fill', 'none');
3559
- svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
3560
- svg.setAttribute('aria-hidden', 'true');
3641
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
3642
+ svg.setAttribute("class", "onboarding-passkey-icon");
3643
+ svg.setAttribute("width", "20");
3644
+ svg.setAttribute("height", "20");
3645
+ svg.setAttribute("viewBox", "0 0 24 24");
3646
+ svg.setAttribute("fill", "none");
3647
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
3648
+ svg.setAttribute("aria-hidden", "true");
3561
3649
  // Passkey icon (user with key)
3562
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
3563
- path.setAttribute('d', 'M3.682 19.338v-2.102c0-.476.127-.915.382-1.315.255-.4.603-.708 1.042-.926a14.89 14.89 0 0 1 2.939-1.067c.982-.24 1.966-.36 2.953-.36.352 0 .708.018 1.066.054.358.035.712.084 1.062.147-.015.831.164 1.613.537 2.347a4.882 4.882 0 0 0 1.595 1.822v1.4H3.682Zm15.003 2.713-1.303-1.303v-4.029a2.976 2.976 0 0 1-1.564-1.08 2.944 2.944 0 0 1-.608-1.832c0-.841.297-1.557.891-2.147a2.944 2.944 0 0 1 2.154-.886c.837 0 1.552.295 2.145.886.594.59.89 1.306.89 2.148 0 .656-.182 1.238-.546 1.743a3.018 3.018 0 0 1-1.404 1.084l1.073 1.072-1.294 1.31 1.294 1.301-1.728 1.733ZM11 12.006c-.94 0-1.742-.333-2.405-.999a3.28 3.28 0 0 1-.994-2.4c0-.94.331-1.743.994-2.405A3.276 3.276 0 0 1 11 5.208c.94 0 1.742.331 2.405.994.663.662.994 1.463.994 2.4 0 .939-.331 1.74-.994 2.406a3.27 3.27 0 0 1-2.405.998Zm7.252 2.235a.833.833 0 0 0 .612-.255.842.842 0 0 0 .255-.617.834.834 0 0 0-.253-.614.835.835 0 0 0-.612-.252.85.85 0 0 0-.616.251.823.823 0 0 0-.257.612c0 .24.085.447.257.618a.838.838 0 0 0 .614.257Z');
3650
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
3651
+ path.setAttribute("d", "M3.682 19.338v-2.102c0-.476.127-.915.382-1.315.255-.4.603-.708 1.042-.926a14.89 14.89 0 0 1 2.939-1.067c.982-.24 1.966-.36 2.953-.36.352 0 .708.018 1.066.054.358.035.712.084 1.062.147-.015.831.164 1.613.537 2.347a4.882 4.882 0 0 0 1.595 1.822v1.4H3.682Zm15.003 2.713-1.303-1.303v-4.029a2.976 2.976 0 0 1-1.564-1.08 2.944 2.944 0 0 1-.608-1.832c0-.841.297-1.557.891-2.147a2.944 2.944 0 0 1 2.154-.886c.837 0 1.552.295 2.145.886.594.59.89 1.306.89 2.148 0 .656-.182 1.238-.546 1.743a3.018 3.018 0 0 1-1.404 1.084l1.073 1.072-1.294 1.31 1.294 1.301-1.728 1.733ZM11 12.006c-.94 0-1.742-.333-2.405-.999a3.28 3.28 0 0 1-.994-2.4c0-.94.331-1.743.994-2.405A3.276 3.276 0 0 1 11 5.208c.94 0 1.742.331 2.405.994.663.662.994 1.463.994 2.4 0 .939-.331 1.74-.994 2.406a3.27 3.27 0 0 1-2.405.998Zm7.252 2.235a.833.833 0 0 0 .612-.255.842.842 0 0 0 .255-.617.834.834 0 0 0-.253-.614.835.835 0 0 0-.612-.252.85.85 0 0 0-.616.251.823.823 0 0 0-.257.612c0 .24.085.447.257.618a.838.838 0 0 0 .614.257Z");
3564
3652
  // Set icon color based on theme: white for dark theme, black for light theme
3565
- const iconColor = this.config.theme === 'dark' ? '#ffffff' : '#000000';
3566
- path.setAttribute('fill', iconColor);
3653
+ const iconColor = this.config.theme === "dark" ? "#ffffff" : "#000000";
3654
+ path.setAttribute("fill", iconColor);
3567
3655
  svg.appendChild(path);
3568
3656
  return svg;
3569
3657
  }
@@ -3571,16 +3659,16 @@ export class OnboardingUIWeb {
3571
3659
  * Create X (Twitter) icon SVG
3572
3660
  */
3573
3661
  createTwitterIcon() {
3574
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
3575
- svg.setAttribute('class', 'onboarding-social-icon');
3576
- svg.setAttribute('width', '20');
3577
- svg.setAttribute('height', '20');
3578
- svg.setAttribute('viewBox', '0 0 24 24');
3579
- svg.setAttribute('fill', 'none');
3580
- svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
3581
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
3582
- path.setAttribute('d', 'M4 3h4.6l3.09 4.1L14.5 3H20l-5.63 7.08L20.4 21H15.8l-3.5-4.65L8.3 21H2.8l6-7.67L4 3Zm2.04 1.2L9.7 9l.1.12L4.97 19h1.79l4.04-5.39L14.78 19h1.8l-5.02-6.55-.05-.06L17.97 4.2h-1.8l-3.52 4.62L9 4.2H6.04Z');
3583
- path.setAttribute('fill', 'currentColor');
3662
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
3663
+ svg.setAttribute("class", "onboarding-social-icon");
3664
+ svg.setAttribute("width", "20");
3665
+ svg.setAttribute("height", "20");
3666
+ svg.setAttribute("viewBox", "0 0 24 24");
3667
+ svg.setAttribute("fill", "none");
3668
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
3669
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
3670
+ path.setAttribute("d", "M4 3h4.6l3.09 4.1L14.5 3H20l-5.63 7.08L20.4 21H15.8l-3.5-4.65L8.3 21H2.8l6-7.67L4 3Zm2.04 1.2L9.7 9l.1.12L4.97 19h1.79l4.04-5.39L14.78 19h1.8l-5.02-6.55-.05-.06L17.97 4.2h-1.8l-3.52 4.62L9 4.2H6.04Z");
3671
+ path.setAttribute("fill", "currentColor");
3584
3672
  svg.appendChild(path);
3585
3673
  return svg;
3586
3674
  }
@@ -3588,16 +3676,16 @@ export class OnboardingUIWeb {
3588
3676
  * Create Discord icon SVG
3589
3677
  */
3590
3678
  createDiscordIcon() {
3591
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
3592
- svg.setAttribute('class', 'onboarding-social-icon');
3593
- svg.setAttribute('width', '20');
3594
- svg.setAttribute('height', '20');
3595
- svg.setAttribute('viewBox', '0 0 24 24');
3596
- svg.setAttribute('fill', 'none');
3597
- svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
3598
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
3599
- path.setAttribute('d', 'M20.317 4.37a16.75 16.75 0 0 0-4.091-1.272.06.06 0 0 0-.063.03 11.651 11.651 0 0 0-.512 1.054 15.93 15.93 0 0 0-4.813 0 10.69 10.69 0 0 0-.522-1.054.06.06 0 0 0-.063-.03 16.742 16.742 0 0 0-4.092 1.272.055.055 0 0 0-.025.021C2.84 8.167 2.18 11.875 2.46 15.547a.066.066 0 0 0 .025.045 16.86 16.86 0 0 0 4.98 2.52.06.06 0 0 0 .066-.02c.384-.525.726-1.08 1.02-1.66a.06.06 0 0 0-.033-.083 11.117 11.117 0 0 1-1.593-.765.06.06 0 0 1-.006-.1c.107-.08.214-.162.316-.245a.06.06 0 0 1 .061-.008 11.65 11.65 0 0 0 10.104 0 .06.06 0 0 1 .062.007c.103.083.21.166.316.246a.06.06 0 0 1-.005.1 10.859 10.859 0 0 1-1.594.764.06.06 0 0 0-.033.084 9.255 9.255 0 0 0 1.02 1.659.06.06 0 0 0 .065.02 16.824 16.824 0 0 0 4.982-2.52.06.06 0 0 0 .024-.044c.416-5.09-.698-8.76-2.89-11.156a.048.048 0 0 0-.024-.02ZM9.68 13.348c-.996 0-1.812-.91-1.812-2.03 0-1.12.805-2.031 1.812-2.031 1.016 0 1.822.922 1.812 2.031 0 1.12-.805 2.03-1.812 2.03Zm4.64 0c-.996 0-1.812-.91-1.812-2.03 0-1.12.805-2.031 1.812-2.031 1.016 0 1.822.922 1.812 2.031 0 1.12-.796 2.03-1.812 2.03Z');
3600
- path.setAttribute('fill', 'currentColor');
3679
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
3680
+ svg.setAttribute("class", "onboarding-social-icon");
3681
+ svg.setAttribute("width", "20");
3682
+ svg.setAttribute("height", "20");
3683
+ svg.setAttribute("viewBox", "0 0 24 24");
3684
+ svg.setAttribute("fill", "none");
3685
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
3686
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
3687
+ path.setAttribute("d", "M20.317 4.37a16.75 16.75 0 0 0-4.091-1.272.06.06 0 0 0-.063.03 11.651 11.651 0 0 0-.512 1.054 15.93 15.93 0 0 0-4.813 0 10.69 10.69 0 0 0-.522-1.054.06.06 0 0 0-.063-.03 16.742 16.742 0 0 0-4.092 1.272.055.055 0 0 0-.025.021C2.84 8.167 2.18 11.875 2.46 15.547a.066.066 0 0 0 .025.045 16.86 16.86 0 0 0 4.98 2.52.06.06 0 0 0 .066-.02c.384-.525.726-1.08 1.02-1.66a.06.06 0 0 0-.033-.083 11.117 11.117 0 0 1-1.593-.765.06.06 0 0 1-.006-.1c.107-.08.214-.162.316-.245a.06.06 0 0 1 .061-.008 11.65 11.65 0 0 0 10.104 0 .06.06 0 0 1 .062.007c.103.083.21.166.316.246a.06.06 0 0 1-.005.1 10.859 10.859 0 0 1-1.594.764.06.06 0 0 0-.033.084 9.255 9.255 0 0 0 1.02 1.659.06.06 0 0 0 .065.02 16.824 16.824 0 0 0 4.982-2.52.06.06 0 0 0 .024-.044c.416-5.09-.698-8.76-2.89-11.156a.048.048 0 0 0-.024-.02ZM9.68 13.348c-.996 0-1.812-.91-1.812-2.03 0-1.12.805-2.031 1.812-2.031 1.016 0 1.822.922 1.812 2.031 0 1.12-.805 2.03-1.812 2.03Zm4.64 0c-.996 0-1.812-.91-1.812-2.03 0-1.12.805-2.031 1.812-2.031 1.016 0 1.822.922 1.812 2.031 0 1.12-.796 2.03-1.812 2.03Z");
3688
+ path.setAttribute("fill", "currentColor");
3601
3689
  svg.appendChild(path);
3602
3690
  return svg;
3603
3691
  }
@@ -3608,7 +3696,7 @@ export class OnboardingUIWeb {
3608
3696
  if (this.loading)
3609
3697
  return;
3610
3698
  try {
3611
- this.setLoading(true, 'passkey');
3699
+ this.setLoading(true, "passkey");
3612
3700
  this.hidePasskeyError();
3613
3701
  if (this.config.onPasskeyLogin) {
3614
3702
  await this.config.onPasskeyLogin();
@@ -3618,13 +3706,15 @@ export class OnboardingUIWeb {
3618
3706
  }
3619
3707
  }
3620
3708
  else {
3621
- throw new Error('Passkey login handler not configured');
3709
+ throw new Error("Passkey login handler not configured");
3622
3710
  }
3623
3711
  }
3624
3712
  catch (error) {
3625
- this.showPasskeyError(error instanceof Error ? error.message : 'Failed to login with passkey');
3713
+ this.showPasskeyError(error instanceof Error ? error.message : "Failed to login with passkey");
3626
3714
  if (this.config.onLoginError) {
3627
- this.config.onLoginError(error instanceof Error ? error : new Error('Failed to login with passkey'));
3715
+ this.config.onLoginError(error instanceof Error
3716
+ ? error
3717
+ : new Error("Failed to login with passkey"));
3628
3718
  }
3629
3719
  }
3630
3720
  finally {
@@ -3638,7 +3728,7 @@ export class OnboardingUIWeb {
3638
3728
  if (this.loading)
3639
3729
  return;
3640
3730
  try {
3641
- this.setLoading(true, 'passkey');
3731
+ this.setLoading(true, "passkey");
3642
3732
  this.hidePasskeyError();
3643
3733
  if (this.config.onPasskeySignup) {
3644
3734
  await this.config.onPasskeySignup();
@@ -3648,13 +3738,15 @@ export class OnboardingUIWeb {
3648
3738
  }
3649
3739
  }
3650
3740
  else {
3651
- throw new Error('Passkey signup handler not configured');
3741
+ throw new Error("Passkey signup handler not configured");
3652
3742
  }
3653
3743
  }
3654
3744
  catch (error) {
3655
- this.showPasskeyError(error instanceof Error ? error.message : 'Failed to signup with passkey');
3745
+ this.showPasskeyError(error instanceof Error ? error.message : "Failed to signup with passkey");
3656
3746
  if (this.config.onLoginError) {
3657
- this.config.onLoginError(error instanceof Error ? error : new Error('Failed to signup with passkey'));
3747
+ this.config.onLoginError(error instanceof Error
3748
+ ? error
3749
+ : new Error("Failed to signup with passkey"));
3658
3750
  }
3659
3751
  }
3660
3752
  finally {
@@ -3668,7 +3760,7 @@ export class OnboardingUIWeb {
3668
3760
  if (!this.passkeyErrorElement)
3669
3761
  return;
3670
3762
  this.passkeyErrorElement.textContent = message;
3671
- this.passkeyErrorElement.style.display = 'block';
3763
+ this.passkeyErrorElement.style.display = "block";
3672
3764
  }
3673
3765
  /**
3674
3766
  * Hide passkey-specific error
@@ -3676,8 +3768,8 @@ export class OnboardingUIWeb {
3676
3768
  hidePasskeyError() {
3677
3769
  if (!this.passkeyErrorElement)
3678
3770
  return;
3679
- this.passkeyErrorElement.textContent = '';
3680
- this.passkeyErrorElement.style.display = 'none';
3771
+ this.passkeyErrorElement.textContent = "";
3772
+ this.passkeyErrorElement.style.display = "none";
3681
3773
  }
3682
3774
  }
3683
3775
  export default OnboardingUIWeb;