@abstraxn/signer-react 3.3.9 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/dist/src/ConnectButton.css.d.ts +2 -0
- package/dist/src/ConnectButton.css.js +1 -0
- package/dist/src/ConnectButton.d.ts +0 -1
- package/dist/src/ConnectButton.js +7 -6
- package/dist/src/ExternalWalletButtons.css.d.ts +2 -0
- package/dist/src/ExternalWalletButtons.css.js +1 -0
- package/dist/src/ExternalWalletButtons.d.ts +4 -1
- package/dist/src/ExternalWalletButtons.js +6 -1
- package/dist/src/WalletModal.css +2 -0
- package/dist/src/WalletModal.css.d.ts +2 -0
- package/dist/src/WalletModal.css.js +1 -0
- package/dist/src/WalletModal.d.ts +2 -2
- package/dist/src/WalletModal.js +113 -59
- package/dist/src/components/AbstraxnLogo.d.ts +17 -0
- package/dist/src/components/AbstraxnLogo.js +29 -0
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js +406 -338
- package/dist/src/components/AbstraxnProvider/useAbstraxnProviderBase.d.ts +7 -0
- package/dist/src/components/AbstraxnProvider/useAbstraxnProviderBase.js +9 -0
- package/dist/src/components/AbstraxnProvider/useWalletInitialization.js +41 -6
- package/dist/src/components/OnboardingUI/OnboardingUI.css +99 -4
- package/dist/src/components/OnboardingUI/OnboardingUI.css.d.ts +2 -0
- package/dist/src/components/OnboardingUI/OnboardingUI.css.js +1 -0
- package/dist/src/components/OnboardingUI/OnboardingUIReact.d.ts +0 -1
- package/dist/src/components/OnboardingUI/OnboardingUIReact.js +46 -19
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.d.ts +24 -1
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.js +348 -160
- package/dist/src/components/OnboardingUI/components/Divider.d.ts +7 -0
- package/dist/src/components/OnboardingUI/components/Divider.js +9 -0
- package/dist/src/components/OnboardingUI/components/EmailForm.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/EmailForm.js +1 -2
- package/dist/src/components/OnboardingUI/components/MfaForm.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/MfaForm.js +2 -3
- package/dist/src/components/OnboardingUI/components/Modal.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/Modal.js +12 -4
- package/dist/src/components/OnboardingUI/components/OtpForm.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/OtpForm.js +2 -3
- package/dist/src/components/OnboardingUI/components/PasskeyButton.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/PasskeyButton.js +2 -2
- package/dist/src/components/OnboardingUI/components/SocialButtons.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/SocialButtons.js +3 -3
- package/dist/src/components/OnboardingUI/onboardingShadowContainer.d.ts +9 -0
- package/dist/src/components/OnboardingUI/onboardingShadowContainer.js +36 -0
- package/dist/src/components/ShadowHost/ShadowHost.d.ts +18 -0
- package/dist/src/components/ShadowHost/ShadowHost.js +123 -0
- package/dist/src/components/ShadowHost/ShadowHostContext.d.ts +10 -0
- package/dist/src/components/ShadowHost/ShadowHostContext.js +14 -0
- package/dist/src/components/ShadowHost/index.d.ts +2 -0
- package/dist/src/components/ShadowHost/index.js +3 -0
- package/dist/src/components/WalletModal/components/ChainSelector.css +9 -0
- package/dist/src/components/WalletModal/components/ChainSelector.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ChainSelector.css.js +1 -0
- package/dist/src/components/WalletModal/components/ChainSelector.d.ts +0 -1
- package/dist/src/components/WalletModal/components/ChainSelector.js +78 -23
- package/dist/src/components/WalletModal/components/CodeInput.d.ts +12 -0
- package/dist/src/components/WalletModal/components/CodeInput.js +39 -0
- package/dist/src/components/WalletModal/components/ExportKeyModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ExportKeyModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/ExportKeyModal.d.ts +0 -2
- package/dist/src/components/WalletModal/components/ExportKeyModal.js +2 -4
- package/dist/src/components/WalletModal/components/ExportWarningModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ExportWarningModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/ExportWarningModal.d.ts +0 -2
- package/dist/src/components/WalletModal/components/ExportWarningModal.js +2 -4
- package/dist/src/components/WalletModal/components/ManageWalletModal.css +27 -1
- package/dist/src/components/WalletModal/components/ManageWalletModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ManageWalletModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/ManageWalletModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/ManageWalletModal.js +66 -148
- package/dist/src/components/WalletModal/components/MfaVerifyModal.d.ts +15 -0
- package/dist/src/components/WalletModal/components/MfaVerifyModal.js +98 -0
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.css +2 -12
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.js +0 -1
- package/dist/src/components/WalletModal/components/ReceiveModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ReceiveModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/ReceiveModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/ReceiveModal.js +2 -2
- package/dist/src/components/WalletModal/components/SendModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/SendModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/SendModal.d.ts +5 -2
- package/dist/src/components/WalletModal/components/SendModal.js +25 -82
- package/dist/src/components/WalletModal/components/SignMfaModalHost.d.ts +1 -0
- package/dist/src/components/WalletModal/components/SignMfaModalHost.js +50 -0
- package/dist/src/components/WalletModal/components/SuccessModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/SuccessModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/SuccessModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/SuccessModal.js +0 -1
- package/dist/src/components/WalletModal/components/TokenSelectorModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/TokenSelectorModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/TokenSelectorModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/TokenSelectorModal.js +0 -1
- package/dist/src/components/WalletModal/components/UserAvatar.js +2 -1
- package/dist/src/components/WalletModal/components/index.d.ts +3 -0
- package/dist/src/components/WalletModal/components/index.js +2 -0
- package/dist/src/components/WalletModal/hooks/useSendTransaction.js +18 -6
- package/dist/src/components/icons.d.ts +2 -0
- package/dist/src/components/icons.js +4 -0
- package/dist/src/hooks.d.ts +81 -20
- package/dist/src/hooks.js +194 -36
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +2 -2
- package/dist/src/signMfaBridge.d.ts +7 -0
- package/dist/src/signMfaBridge.js +20 -0
- package/dist/src/types.d.ts +4 -0
- package/dist/src/utils/shadowFocus.d.ts +8 -0
- package/dist/src/utils/shadowFocus.js +15 -0
- package/dist/src/utils/shadowRegistry.d.ts +23 -0
- package/dist/src/utils/shadowRegistry.js +36 -0
- package/dist/src/walletConnectMobile.d.ts +9 -5
- package/dist/src/walletConnectMobile.js +152 -51
- package/package.json +9 -4
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { isValidEmail } from "@abstraxn/signer-core";
|
|
2
|
+
import { abstraxnLogoSvgHtml } from "../AbstraxnLogo";
|
|
3
|
+
import { createOnboardingShadowContainer } from "./onboardingShadowContainer";
|
|
4
|
+
import { queryAllAcrossShadowRoots } from "../../utils/shadowRegistry";
|
|
5
|
+
import { getDeepActiveElement } from "../../utils/shadowFocus";
|
|
2
6
|
// CSS styles embedded as string
|
|
3
7
|
const ONBOARDING_UI_STYLES = `
|
|
4
8
|
.onboarding-container {
|
|
@@ -19,6 +23,12 @@ const ONBOARDING_UI_STYLES = `
|
|
|
19
23
|
.onboarding-container.onboarding-inline {
|
|
20
24
|
min-height: auto;
|
|
21
25
|
padding: 0;
|
|
26
|
+
justify-content: flex-start;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.onboarding-container.onboarding-inline .onboarding-card {
|
|
30
|
+
max-height: none;
|
|
31
|
+
overflow-y: visible;
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
/* Modal Styles */
|
|
@@ -108,6 +118,99 @@ const ONBOARDING_UI_STYLES = `
|
|
|
108
118
|
padding: 0;
|
|
109
119
|
}
|
|
110
120
|
|
|
121
|
+
/* Close (X) button — absolutely positioned in the modal's top-right corner.
|
|
122
|
+
Anchored against .onboarding-modal-content, which is already position: relative. */
|
|
123
|
+
.onboarding-modal-close {
|
|
124
|
+
position: absolute;
|
|
125
|
+
top: 16px;
|
|
126
|
+
right: 16px;
|
|
127
|
+
z-index: 10;
|
|
128
|
+
display: flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
justify-content: center;
|
|
131
|
+
width: 32px;
|
|
132
|
+
height: 32px;
|
|
133
|
+
padding: 0;
|
|
134
|
+
border: none;
|
|
135
|
+
border-radius: 50%;
|
|
136
|
+
background: transparent;
|
|
137
|
+
color: #6b7280;
|
|
138
|
+
cursor: pointer;
|
|
139
|
+
transition: background-color 0.15s ease, color 0.15s ease;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.onboarding-modal-close:hover {
|
|
143
|
+
background-color: rgba(0, 0, 0, 0.06);
|
|
144
|
+
color: #111827;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.onboarding-modal-close.onboarding-theme-dark {
|
|
148
|
+
color: #9ca3af;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.onboarding-modal-close.onboarding-theme-dark:hover {
|
|
152
|
+
background-color: rgba(255, 255, 255, 0.08);
|
|
153
|
+
color: #f9fafb;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* Back button — used on the OTP and MFA verification screens */
|
|
157
|
+
.onboarding-otp-back-button {
|
|
158
|
+
align-self: flex-start;
|
|
159
|
+
width: 40px;
|
|
160
|
+
height: 40px;
|
|
161
|
+
min-width: 40px;
|
|
162
|
+
min-height: 40px;
|
|
163
|
+
display: flex !important;
|
|
164
|
+
align-items: center;
|
|
165
|
+
justify-content: center;
|
|
166
|
+
background-color: transparent !important;
|
|
167
|
+
border: none;
|
|
168
|
+
border-radius: 8px;
|
|
169
|
+
cursor: pointer;
|
|
170
|
+
transition: all 0.2s ease;
|
|
171
|
+
color: #6b7280 !important;
|
|
172
|
+
padding: 0;
|
|
173
|
+
margin: 0;
|
|
174
|
+
box-shadow: none !important;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.onboarding-otp-back-button svg {
|
|
178
|
+
width: 20px;
|
|
179
|
+
height: 20px;
|
|
180
|
+
flex-shrink: 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.onboarding-otp-back-button:hover:not(:disabled) {
|
|
184
|
+
background-color: #f3f4f6 !important;
|
|
185
|
+
color: #111827 !important;
|
|
186
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05) !important;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.onboarding-otp-back-button:active:not(:disabled) {
|
|
190
|
+
background-color: #e5e7eb !important;
|
|
191
|
+
transform: scale(0.95);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.onboarding-otp-back-button:disabled {
|
|
195
|
+
opacity: 0.3;
|
|
196
|
+
cursor: not-allowed;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.onboarding-theme-dark .onboarding-otp-back-button {
|
|
200
|
+
background-color: transparent !important;
|
|
201
|
+
color: #9ca3af !important;
|
|
202
|
+
box-shadow: none !important;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.onboarding-theme-dark .onboarding-otp-back-button:hover:not(:disabled) {
|
|
206
|
+
background-color: rgba(255, 255, 255, 0.1) !important;
|
|
207
|
+
color: #ffffff !important;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.onboarding-theme-dark .onboarding-otp-back-button:active:not(:disabled) {
|
|
211
|
+
background-color: rgba(255, 255, 255, 0.15) !important;
|
|
212
|
+
}
|
|
213
|
+
|
|
111
214
|
/* Light Theme */
|
|
112
215
|
.onboarding-theme-light {
|
|
113
216
|
color: #000000;
|
|
@@ -770,7 +873,9 @@ const ONBOARDING_UI_STYLES = `
|
|
|
770
873
|
.onboarding-otp-verification .onboarding-button {
|
|
771
874
|
/* Match OTP inputs width: 6 inputs × 44px + 5 gaps × 10px = 314px */
|
|
772
875
|
width: 314px;
|
|
773
|
-
max-width:
|
|
876
|
+
max-width: 100%;
|
|
877
|
+
margin-left: auto;
|
|
878
|
+
margin-right: auto;
|
|
774
879
|
}
|
|
775
880
|
|
|
776
881
|
.onboarding-otp-icon-container {
|
|
@@ -975,6 +1080,51 @@ const ONBOARDING_UI_STYLES = `
|
|
|
975
1080
|
cursor: not-allowed;
|
|
976
1081
|
}
|
|
977
1082
|
|
|
1083
|
+
.onboarding-mfa-trouble-text {
|
|
1084
|
+
font-size: 14px;
|
|
1085
|
+
margin: -6px 0 16px;
|
|
1086
|
+
color: #6b7280;
|
|
1087
|
+
text-align: center;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
.onboarding-theme-dark .onboarding-mfa-trouble-text {
|
|
1091
|
+
color: #9ca3af;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
.onboarding-mfa-backup-link {
|
|
1095
|
+
border: none !important;
|
|
1096
|
+
background: transparent !important;
|
|
1097
|
+
padding: 0 !important;
|
|
1098
|
+
margin: 0;
|
|
1099
|
+
text-decoration: underline;
|
|
1100
|
+
cursor: pointer;
|
|
1101
|
+
font-weight: 600;
|
|
1102
|
+
font-size: 14px;
|
|
1103
|
+
font-family: inherit;
|
|
1104
|
+
line-height: inherit;
|
|
1105
|
+
box-shadow: none !important;
|
|
1106
|
+
outline: none;
|
|
1107
|
+
appearance: none;
|
|
1108
|
+
-webkit-appearance: none;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
.onboarding-theme-light .onboarding-mfa-backup-link {
|
|
1112
|
+
color: #111827;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
.onboarding-theme-dark .onboarding-mfa-backup-link {
|
|
1116
|
+
color: #e5e7eb;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
.onboarding-mfa-backup-link:hover:not(:disabled) {
|
|
1120
|
+
opacity: 0.8;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
.onboarding-mfa-backup-link:disabled {
|
|
1124
|
+
opacity: 0.6;
|
|
1125
|
+
cursor: not-allowed;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
978
1128
|
.onboarding-otp-resend {
|
|
979
1129
|
text-align: center;
|
|
980
1130
|
margin-top: 20px;
|
|
@@ -1081,7 +1231,15 @@ const ONBOARDING_UI_STYLES = `
|
|
|
1081
1231
|
* Works with vanilla JavaScript - no framework dependencies required.
|
|
1082
1232
|
*/
|
|
1083
1233
|
export class OnboardingUIWeb {
|
|
1084
|
-
static
|
|
1234
|
+
// Instance-level, not class-static: each instance now owns its own shadow
|
|
1235
|
+
// root (see shadowContainer below), so a shared class-static flag would
|
|
1236
|
+
// wrongly make a second instance skip injecting styles into its own new
|
|
1237
|
+
// shadow root, leaving it completely unstyled.
|
|
1238
|
+
stylesInjected = false;
|
|
1239
|
+
shadowContainer = null;
|
|
1240
|
+
shadowTeardown = null;
|
|
1241
|
+
/** Pending OAuth loader timer from checkUrlParams — cleared in destroy() so StrictMode cleanup cannot paint into a torn-down shadow root. */
|
|
1242
|
+
pendingLoadingModalTimer = null;
|
|
1085
1243
|
config;
|
|
1086
1244
|
container = null;
|
|
1087
1245
|
rootElement = null;
|
|
@@ -1150,10 +1308,48 @@ export class OnboardingUIWeb {
|
|
|
1150
1308
|
this.externalWalletDivider.style.display = "";
|
|
1151
1309
|
}
|
|
1152
1310
|
}
|
|
1311
|
+
/** True when this instance still owns an attached shadow container. */
|
|
1312
|
+
hasLiveShadow() {
|
|
1313
|
+
return !!this.shadowContainer?.isConnected;
|
|
1314
|
+
}
|
|
1315
|
+
/**
|
|
1316
|
+
* Rebuild the shadow tree if destroy()/StrictMode tore it down.
|
|
1317
|
+
* Safe to call before showLoadingModal / showOnboarding recovery paths.
|
|
1318
|
+
*/
|
|
1319
|
+
ensureLiveShadow() {
|
|
1320
|
+
if (this.hasLiveShadow())
|
|
1321
|
+
return;
|
|
1322
|
+
this.init();
|
|
1323
|
+
}
|
|
1153
1324
|
/**
|
|
1154
1325
|
* Initialize and render the component
|
|
1155
1326
|
*/
|
|
1156
1327
|
init() {
|
|
1328
|
+
// Re-init after destroy / StrictMode: drop any stale host first so we never
|
|
1329
|
+
// accumulate orphaned shadow roots on document.body.
|
|
1330
|
+
if (this.shadowTeardown) {
|
|
1331
|
+
try {
|
|
1332
|
+
this.shadowTeardown();
|
|
1333
|
+
}
|
|
1334
|
+
catch {
|
|
1335
|
+
// Ignore teardown errors on a partially-detached host.
|
|
1336
|
+
}
|
|
1337
|
+
this.shadowTeardown = null;
|
|
1338
|
+
this.shadowContainer = null;
|
|
1339
|
+
this.stylesInjected = false;
|
|
1340
|
+
this.modalOverlay = null;
|
|
1341
|
+
}
|
|
1342
|
+
const shadow = createOnboardingShadowContainer();
|
|
1343
|
+
this.shadowContainer = shadow.container;
|
|
1344
|
+
this.shadowTeardown = shadow.teardown;
|
|
1345
|
+
// Same inline stacking-context-defense styles as the React ShadowHost —
|
|
1346
|
+
// prevents ordinary host-page global CSS from promoting this host into
|
|
1347
|
+
// its own stacking context and trapping the modal's z-index inside it.
|
|
1348
|
+
shadow.hostElement.style.position = "static";
|
|
1349
|
+
shadow.hostElement.style.zIndex = "auto";
|
|
1350
|
+
shadow.hostElement.style.transform = "none";
|
|
1351
|
+
shadow.hostElement.style.opacity = "1";
|
|
1352
|
+
shadow.hostElement.style.isolation = "auto";
|
|
1157
1353
|
this.injectStyles();
|
|
1158
1354
|
this.setupContainer();
|
|
1159
1355
|
this.render();
|
|
@@ -1187,8 +1383,16 @@ export class OnboardingUIWeb {
|
|
|
1187
1383
|
// Don't show "Verifying login..." - provider will show MFA screen instead; avoid it appearing after MFA modal
|
|
1188
1384
|
return;
|
|
1189
1385
|
}
|
|
1386
|
+
if (this.pendingLoadingModalTimer !== null) {
|
|
1387
|
+
clearTimeout(this.pendingLoadingModalTimer);
|
|
1388
|
+
this.pendingLoadingModalTimer = null;
|
|
1389
|
+
}
|
|
1190
1390
|
requestAnimationFrame(() => {
|
|
1191
|
-
setTimeout(() => {
|
|
1391
|
+
this.pendingLoadingModalTimer = setTimeout(() => {
|
|
1392
|
+
this.pendingLoadingModalTimer = null;
|
|
1393
|
+
// Skip if destroy() already ran (StrictMode cleanup) — remount re-inits and shows the loader.
|
|
1394
|
+
if (!this.hasLiveShadow())
|
|
1395
|
+
return;
|
|
1192
1396
|
this.showLoadingModal();
|
|
1193
1397
|
}, 100);
|
|
1194
1398
|
});
|
|
@@ -1301,6 +1505,7 @@ export class OnboardingUIWeb {
|
|
|
1301
1505
|
// OK Button
|
|
1302
1506
|
const okButton = this.createElement("button", {
|
|
1303
1507
|
className: "onboarding-button onboarding-button-primary",
|
|
1508
|
+
part: "button-primary",
|
|
1304
1509
|
textContent: "OK",
|
|
1305
1510
|
style: "width: 100%; max-width: 200px;",
|
|
1306
1511
|
});
|
|
@@ -1354,15 +1559,24 @@ export class OnboardingUIWeb {
|
|
|
1354
1559
|
* Public method to allow external access
|
|
1355
1560
|
*/
|
|
1356
1561
|
showLoadingModal() {
|
|
1357
|
-
//
|
|
1358
|
-
|
|
1562
|
+
// Shadow DOM: the loader must live inside this instance's shadow container.
|
|
1563
|
+
// After StrictMode destroy() (or any tear-down), that container is gone —
|
|
1564
|
+
// rebuild before painting, otherwise the overlay is created detached and
|
|
1565
|
+
// never appears (pre-shadow appends went to document.body and survived).
|
|
1566
|
+
this.ensureLiveShadow();
|
|
1567
|
+
if (!this.shadowContainer)
|
|
1568
|
+
return;
|
|
1569
|
+
// Hide any other modals that might be showing (wallet selection, etc.) —
|
|
1570
|
+
// now possibly living in a different shadow root, so this must query
|
|
1571
|
+
// across every registered boundary, not just the real document.
|
|
1572
|
+
const otherModals = queryAllAcrossShadowRoots(".onboarding-modal-overlay, .external-wallet-modal, .wallet-modal-overlay");
|
|
1359
1573
|
otherModals.forEach((modal) => {
|
|
1360
1574
|
if (modal.id !== "onboarding-loading-modal-overlay") {
|
|
1361
1575
|
modal.style.display = "none";
|
|
1362
1576
|
}
|
|
1363
1577
|
});
|
|
1364
1578
|
// Create modal overlay if it doesn't exist
|
|
1365
|
-
let loadingModalOverlay =
|
|
1579
|
+
let loadingModalOverlay = this.shadowContainer?.querySelector("#onboarding-loading-modal-overlay");
|
|
1366
1580
|
if (!loadingModalOverlay) {
|
|
1367
1581
|
loadingModalOverlay = this.createElement("div", {
|
|
1368
1582
|
id: "onboarding-loading-modal-overlay",
|
|
@@ -1454,7 +1668,7 @@ export class OnboardingUIWeb {
|
|
|
1454
1668
|
`,
|
|
1455
1669
|
});
|
|
1456
1670
|
// Add keyframes if not exists
|
|
1457
|
-
if (!
|
|
1671
|
+
if (!this.shadowContainer?.querySelector("#onboarding-spin-style")) {
|
|
1458
1672
|
const style = document.createElement("style");
|
|
1459
1673
|
style.id = "onboarding-spin-style";
|
|
1460
1674
|
style.textContent = `
|
|
@@ -1462,7 +1676,7 @@ export class OnboardingUIWeb {
|
|
|
1462
1676
|
to { transform: rotate(360deg); }
|
|
1463
1677
|
}
|
|
1464
1678
|
`;
|
|
1465
|
-
|
|
1679
|
+
this.shadowContainer?.appendChild(style);
|
|
1466
1680
|
}
|
|
1467
1681
|
// Text
|
|
1468
1682
|
const text = this.createElement("p", {
|
|
@@ -1478,10 +1692,7 @@ export class OnboardingUIWeb {
|
|
|
1478
1692
|
loadingCard.appendChild(text);
|
|
1479
1693
|
// Footer "Powered by Abstraxn"
|
|
1480
1694
|
if (this.config.showFooter !== false) {
|
|
1481
|
-
const textColor = this.
|
|
1482
|
-
(this.config.theme === "dark" ? "#9ca3af" : "#6b7280");
|
|
1483
|
-
const brandColor = this.config.colors?.text ||
|
|
1484
|
-
(this.config.theme === "dark" ? "#e5e7eb" : "#374151");
|
|
1695
|
+
const { textColor, brandColor } = this.getFooterTextColors();
|
|
1485
1696
|
const footer = this.createElement("div", {
|
|
1486
1697
|
className: "onboarding-footer",
|
|
1487
1698
|
});
|
|
@@ -1502,24 +1713,7 @@ export class OnboardingUIWeb {
|
|
|
1502
1713
|
"aria-label": "Visit Abstraxn website",
|
|
1503
1714
|
});
|
|
1504
1715
|
const logoSvg = this.createElement("span", {
|
|
1505
|
-
innerHTML:
|
|
1506
|
-
<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;">
|
|
1507
|
-
<path d="M47.9082 37.191L23.9541 23.553L0 9.91504L37.7436 -8.13502e-06L47.9082 37.191Z" fill="url(#paint0_linear_1242_781)"/>
|
|
1508
|
-
<path d="M13.5156 46.3594L10.1846 47.2344L8.99219 42.873L12.4365 42.4111L13.5156 46.3594ZM20.4268 44.5566L17.1152 45.4199L16.125 41.8818L19.5566 41.3721L20.4268 44.5566ZM26.9307 42.834L23.6152 43.6982L22.8438 40.9443L26.2744 40.4326L26.9307 42.834ZM33.5078 41.1074L30.1875 41.9727L29.6328 39.9951L33.0635 39.4844L33.5078 41.1074ZM39.998 39.4014L36.6729 40.2686L36.3359 39.0674L39.7656 38.5508L39.998 39.4014ZM10.1406 33.9434L11.6807 39.5762L8.15918 39.7568L6.46094 33.543L10.1406 33.9434ZM17.6582 34.5996L18.8916 39.1113L15.4199 39.3496L14.0078 34.3076L17.6582 34.5996ZM24.8779 35.332L25.8047 38.7227L22.3252 38.959L21.2266 35.0361L24.8779 35.332ZM32.0918 36.0723L32.7119 38.3398L29.2227 38.5723L28.4375 35.7656L32.0918 36.0723ZM43.2373 38.5488L43.1172 38.1172L47.7939 37.3516L43.2373 38.5488ZM39.3047 36.8096L39.6182 37.9561L36.1221 38.1846L35.6484 36.4961L39.3047 36.8096ZM47.7939 37.3516L43.0107 37.7939L42.8516 37.2236L47.7939 37.3516ZM47.8291 37.2988L42.7227 36.7529L42.5547 36.1523L47.8291 37.2988ZM47.8652 37.2412L42.3711 35.3486L42.2031 34.7471L47.8652 37.2412ZM38.748 34.8604L39.0664 36.0254L35.3369 35.4043L34.8594 33.6982L38.748 34.8604ZM31.0576 32.3994L31.6787 34.6709L27.959 34.0566L27.1719 31.2461L31.0576 32.3994ZM38.0811 32.6318L38.4092 33.8301L34.4893 32.3496L34.1543 31.1523C34.1005 30.9591 34.0322 30.7719 33.9531 30.5918L38.0811 32.6318ZM23.3682 29.9385L24.291 33.3164L20.5801 32.71L19.4844 28.7949L23.3682 29.9385ZM15.6641 27.4805L16.8896 31.9629L13.1875 31.3594L11.7812 26.3379L15.6641 27.4805ZM29.9463 28.4678L30.5693 30.748L26.6201 29.2812L25.8633 26.583C25.8534 26.5431 25.8417 26.5028 25.8281 26.4639L29.9463 28.4678ZM7.6875 25.0938L9.21484 30.6816L5.44727 29.959L3.75781 23.7793L7.6875 25.0938ZM21.5312 23.3623L22.4492 26.7227L18.5059 25.2627L17.4141 21.3643L21.5312 23.3623ZM13.6104 20.1602L14.8242 24.6006L10.8887 23.1387L9.49219 18.1553L13.6104 20.1602ZM5.2168 16.0654L6.72559 21.585L2.70703 19.9473L1.06055 13.8701L5.2168 16.0654Z" fill="url(#paint1_linear_1242_781)"/>
|
|
1509
|
-
<defs>
|
|
1510
|
-
<linearGradient id="paint0_linear_1242_781" x1="7.03362" y1="6.09543" x2="47.2003" y2="57.0656" gradientUnits="userSpaceOnUse">
|
|
1511
|
-
<stop stop-color="#F878D2"/>
|
|
1512
|
-
<stop offset="0.393522" stop-color="#FDCC81"/>
|
|
1513
|
-
<stop offset="1" stop-color="#F9A0D9"/>
|
|
1514
|
-
</linearGradient>
|
|
1515
|
-
<linearGradient id="paint1_linear_1242_781" x1="2.53739" y1="21.5136" x2="48.7969" y2="38.5742" gradientUnits="userSpaceOnUse">
|
|
1516
|
-
<stop stop-color="#F878D2"/>
|
|
1517
|
-
<stop offset="0.393522" stop-color="#FDCC81"/>
|
|
1518
|
-
<stop offset="1" stop-color="#F9A0D9"/>
|
|
1519
|
-
</linearGradient>
|
|
1520
|
-
</defs>
|
|
1521
|
-
</svg>
|
|
1522
|
-
`,
|
|
1716
|
+
innerHTML: abstraxnLogoSvgHtml({ size: 20, gradientId: "abstraxn_logo_web_error" }),
|
|
1523
1717
|
style: "display: inline-flex; align-items: center;",
|
|
1524
1718
|
});
|
|
1525
1719
|
brandContainer.appendChild(logoSvg);
|
|
@@ -1533,7 +1727,7 @@ export class OnboardingUIWeb {
|
|
|
1533
1727
|
loadingCard.appendChild(footer);
|
|
1534
1728
|
}
|
|
1535
1729
|
loadingModalOverlay.appendChild(loadingCard);
|
|
1536
|
-
|
|
1730
|
+
this.shadowContainer?.appendChild(loadingModalOverlay);
|
|
1537
1731
|
}
|
|
1538
1732
|
else {
|
|
1539
1733
|
// Ensure modal is visible
|
|
@@ -1556,7 +1750,7 @@ export class OnboardingUIWeb {
|
|
|
1556
1750
|
* Hide loading modal overlay
|
|
1557
1751
|
*/
|
|
1558
1752
|
hideLoadingModal() {
|
|
1559
|
-
const loadingModalOverlay =
|
|
1753
|
+
const loadingModalOverlay = this.shadowContainer?.querySelector("#onboarding-loading-modal-overlay");
|
|
1560
1754
|
if (loadingModalOverlay) {
|
|
1561
1755
|
loadingModalOverlay.style.display = "none";
|
|
1562
1756
|
loadingModalOverlay.style.visibility = "hidden";
|
|
@@ -1571,7 +1765,7 @@ export class OnboardingUIWeb {
|
|
|
1571
1765
|
const displayMessage = this.normalizeErrorMessage(message);
|
|
1572
1766
|
// Helper function to close error modal
|
|
1573
1767
|
const closeErrorModal = () => {
|
|
1574
|
-
const overlay =
|
|
1768
|
+
const overlay = this.shadowContainer?.querySelector("#onboarding-error-modal-overlay");
|
|
1575
1769
|
if (overlay) {
|
|
1576
1770
|
overlay.style.display = "none";
|
|
1577
1771
|
document.body.style.overflow = "";
|
|
@@ -1582,7 +1776,7 @@ export class OnboardingUIWeb {
|
|
|
1582
1776
|
}
|
|
1583
1777
|
};
|
|
1584
1778
|
// Create modal overlay if it doesn't exist
|
|
1585
|
-
let errorModalOverlay =
|
|
1779
|
+
let errorModalOverlay = this.shadowContainer?.querySelector("#onboarding-error-modal-overlay");
|
|
1586
1780
|
if (!errorModalOverlay) {
|
|
1587
1781
|
errorModalOverlay = this.createElement("div", {
|
|
1588
1782
|
id: "onboarding-error-modal-overlay",
|
|
@@ -1701,6 +1895,7 @@ export class OnboardingUIWeb {
|
|
|
1701
1895
|
// OK Button
|
|
1702
1896
|
const okButton = this.createElement("button", {
|
|
1703
1897
|
className: "onboarding-button onboarding-button-primary",
|
|
1898
|
+
part: "button-primary",
|
|
1704
1899
|
textContent: "OK",
|
|
1705
1900
|
style: "width: 100%; max-width: 200px;",
|
|
1706
1901
|
});
|
|
@@ -1708,10 +1903,7 @@ export class OnboardingUIWeb {
|
|
|
1708
1903
|
errorCard.appendChild(okButton);
|
|
1709
1904
|
// Footer "Powered by Abstraxn"
|
|
1710
1905
|
if (this.config.showFooter !== false) {
|
|
1711
|
-
const textColor = this.
|
|
1712
|
-
(this.config.theme === "dark" ? "#9ca3af" : "#6b7280");
|
|
1713
|
-
const brandColor = this.config.colors?.text ||
|
|
1714
|
-
(this.config.theme === "dark" ? "#e5e7eb" : "#374151");
|
|
1906
|
+
const { textColor, brandColor } = this.getFooterTextColors();
|
|
1715
1907
|
const footer = this.createElement("div", {
|
|
1716
1908
|
className: "onboarding-footer",
|
|
1717
1909
|
});
|
|
@@ -1732,24 +1924,7 @@ export class OnboardingUIWeb {
|
|
|
1732
1924
|
"aria-label": "Visit Abstraxn website",
|
|
1733
1925
|
});
|
|
1734
1926
|
const logoSvg = this.createElement("span", {
|
|
1735
|
-
innerHTML:
|
|
1736
|
-
<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;">
|
|
1737
|
-
<path d="M47.9082 37.191L23.9541 23.553L0 9.91504L37.7436 -8.13502e-06L47.9082 37.191Z" fill="url(#paint0_linear_error_modal)"/>
|
|
1738
|
-
<path d="M13.5156 46.3594L10.1846 47.2344L8.99219 42.873L12.4365 42.4111L13.5156 46.3594ZM20.4268 44.5566L17.1152 45.4199L16.125 41.8818L19.5566 41.3721L20.4268 44.5566ZM26.9307 42.834L23.6152 43.6982L22.8438 40.9443L26.2744 40.4326L26.9307 42.834ZM33.5078 41.1074L30.1875 41.9727L29.6328 39.9951L33.0635 39.4844L33.5078 41.1074ZM39.998 39.4014L36.6729 40.2686L36.3359 39.0674L39.7656 38.5508L39.998 39.4014ZM10.1406 33.9434L11.6807 39.5762L8.15918 39.7568L6.46094 33.543L10.1406 33.9434ZM17.6582 34.5996L18.8916 39.1113L15.4199 39.3496L14.0078 34.3076L17.6582 34.5996ZM24.8779 35.332L25.8047 38.7227L22.3252 38.959L21.2266 35.0361L24.8779 35.332ZM32.0918 36.0723L32.7119 38.3398L29.2227 38.5723L28.4375 35.7656L32.0918 36.0723ZM43.2373 38.5488L43.1172 38.1172L47.7939 37.3516L43.2373 38.5488ZM39.3047 36.8096L39.6182 37.9561L36.1221 38.1846L35.6484 36.4961L39.3047 36.8096ZM47.7939 37.3516L43.0107 37.7939L42.8516 37.2236L47.7939 37.3516ZM47.8291 37.2988L42.7227 36.7529L42.5547 36.1523L47.8291 37.2988ZM47.8652 37.2412L42.3711 35.3486L42.2031 34.7471L47.8652 37.2412ZM38.748 34.8604L39.0664 36.0254L35.3369 35.4043L34.8594 33.6982L38.748 34.8604ZM31.0576 32.3994L31.6787 34.6709L27.959 34.0566L27.1719 31.2461L31.0576 32.3994ZM38.0811 32.6318L38.4092 33.8301L34.4893 32.3496L34.1543 31.1523C34.1005 30.9591 34.0322 30.7719 33.9531 30.5918L38.0811 32.6318ZM23.3682 29.9385L24.291 33.3164L20.5801 32.71L19.4844 28.7949L23.3682 29.9385ZM15.6641 27.4805L16.8896 31.9629L13.1875 31.3594L11.7812 26.3379L15.6641 27.4805ZM29.9463 28.4678L30.5693 30.748L26.6201 29.2812L25.8633 26.583C25.8534 26.5431 25.8417 26.5028 25.8281 26.4639L29.9463 28.4678ZM7.6875 25.0938L9.21484 30.6816L5.44727 29.959L3.75781 23.7793L7.6875 25.0938ZM21.5312 23.3623L22.4492 26.7227L18.5059 25.2627L17.4141 21.3643L21.5312 23.3623ZM13.6104 20.1602L14.8242 24.6006L10.8887 23.1387L9.49219 18.1553L13.6104 20.1602ZM5.2168 16.0654L6.72559 21.585L2.70703 19.9473L1.06055 13.8701L5.2168 16.0654Z" fill="url(#paint1_linear_error_modal)"/>
|
|
1739
|
-
<defs>
|
|
1740
|
-
<linearGradient id="paint0_linear_error_modal" x1="7.03362" y1="6.09543" x2="47.2003" y2="57.0656" gradientUnits="userSpaceOnUse">
|
|
1741
|
-
<stop stop-color="#F878D2"/>
|
|
1742
|
-
<stop offset="0.393522" stop-color="#FDCC81"/>
|
|
1743
|
-
<stop offset="1" stop-color="#F9A0D9"/>
|
|
1744
|
-
</linearGradient>
|
|
1745
|
-
<linearGradient id="paint1_linear_error_modal" x1="2.53739" y1="21.5136" x2="48.7969" y2="38.5742" gradientUnits="userSpaceOnUse">
|
|
1746
|
-
<stop stop-color="#F878D2"/>
|
|
1747
|
-
<stop offset="0.393522" stop-color="#FDCC81"/>
|
|
1748
|
-
<stop offset="1" stop-color="#F9A0D9"/>
|
|
1749
|
-
</linearGradient>
|
|
1750
|
-
</defs>
|
|
1751
|
-
</svg>
|
|
1752
|
-
`,
|
|
1927
|
+
innerHTML: abstraxnLogoSvgHtml({ size: 20, gradientId: "abstraxn_logo_web_error_modal" }),
|
|
1753
1928
|
style: "display: inline-flex; align-items: center;",
|
|
1754
1929
|
});
|
|
1755
1930
|
brandContainer.appendChild(logoSvg);
|
|
@@ -1763,7 +1938,7 @@ export class OnboardingUIWeb {
|
|
|
1763
1938
|
errorCard.appendChild(footer);
|
|
1764
1939
|
}
|
|
1765
1940
|
errorModalOverlay.appendChild(errorCard);
|
|
1766
|
-
|
|
1941
|
+
this.shadowContainer?.appendChild(errorModalOverlay);
|
|
1767
1942
|
}
|
|
1768
1943
|
else {
|
|
1769
1944
|
// Update message if overlay exists
|
|
@@ -1779,32 +1954,26 @@ export class OnboardingUIWeb {
|
|
|
1779
1954
|
* Inject CSS styles into the document head (only once)
|
|
1780
1955
|
*/
|
|
1781
1956
|
injectStyles() {
|
|
1782
|
-
if (
|
|
1957
|
+
if (this.stylesInjected || !this.shadowContainer) {
|
|
1783
1958
|
return;
|
|
1784
1959
|
}
|
|
1785
|
-
//
|
|
1786
|
-
|
|
1960
|
+
// Defensive DOM-existence check (stylesInjected already guards this
|
|
1961
|
+
// per-instance, but this is cheap and matches the idempotency pattern
|
|
1962
|
+
// used elsewhere).
|
|
1963
|
+
const existingStyle = this.shadowContainer.querySelector("#onboarding-ui-styles");
|
|
1787
1964
|
if (existingStyle) {
|
|
1788
|
-
|
|
1965
|
+
this.stylesInjected = true;
|
|
1789
1966
|
return;
|
|
1790
1967
|
}
|
|
1791
1968
|
// Create and inject style element
|
|
1792
1969
|
const styleElement = document.createElement("style");
|
|
1793
1970
|
styleElement.id = "onboarding-ui-styles";
|
|
1794
1971
|
styleElement.textContent = ONBOARDING_UI_STYLES;
|
|
1795
|
-
|
|
1796
|
-
// Inject custom CSS if provided
|
|
1797
|
-
if (this.config.customCSS) {
|
|
1798
|
-
const customStyleElement = document.createElement("style");
|
|
1799
|
-
customStyleElement.id = "onboarding-ui-custom-styles";
|
|
1800
|
-
customStyleElement.textContent = this.config.customCSS;
|
|
1801
|
-
document.head.appendChild(customStyleElement);
|
|
1802
|
-
}
|
|
1972
|
+
this.shadowContainer.appendChild(styleElement);
|
|
1803
1973
|
// Apply custom colors if provided
|
|
1804
1974
|
if (this.config.colors) {
|
|
1805
1975
|
this.applyCustomColors();
|
|
1806
1976
|
}
|
|
1807
|
-
OnboardingUIWeb.stylesInjected = true;
|
|
1808
1977
|
// Inject utility styles for loading/error modes
|
|
1809
1978
|
const utilityStyle = document.createElement("style");
|
|
1810
1979
|
utilityStyle.id = "onboarding-utility-styles";
|
|
@@ -1814,15 +1983,61 @@ export class OnboardingUIWeb {
|
|
|
1814
1983
|
display: none !important;
|
|
1815
1984
|
}
|
|
1816
1985
|
`;
|
|
1817
|
-
|
|
1986
|
+
this.shadowContainer.appendChild(utilityStyle);
|
|
1987
|
+
// Custom CSS is injected strictly last, always — deliberate reorder from
|
|
1988
|
+
// the pre-migration order (base styles -> customCSS -> colors -> utility)
|
|
1989
|
+
// so customCSS always wins over both base styles and colors on
|
|
1990
|
+
// equal-specificity rules. See docs/shadow-dom-migration-plan.md Section 9.
|
|
1991
|
+
if (this.config.customCSS) {
|
|
1992
|
+
const customStyleElement = document.createElement("style");
|
|
1993
|
+
customStyleElement.id = "onboarding-ui-custom-styles";
|
|
1994
|
+
customStyleElement.textContent = this.config.customCSS;
|
|
1995
|
+
this.shadowContainer.appendChild(customStyleElement);
|
|
1996
|
+
}
|
|
1997
|
+
this.stylesInjected = true;
|
|
1998
|
+
}
|
|
1999
|
+
/**
|
|
2000
|
+
* Build a divider element (line + "or" text) matching `.onboarding-divider`
|
|
2001
|
+
*/
|
|
2002
|
+
createDividerElement() {
|
|
2003
|
+
const divider = this.createElement("div", {
|
|
2004
|
+
className: "onboarding-divider",
|
|
2005
|
+
});
|
|
2006
|
+
const dividerText = this.createElement("span", {
|
|
2007
|
+
className: "onboarding-divider-text",
|
|
2008
|
+
textContent: "or",
|
|
2009
|
+
});
|
|
2010
|
+
divider.appendChild(dividerText);
|
|
2011
|
+
return divider;
|
|
2012
|
+
}
|
|
2013
|
+
/**
|
|
2014
|
+
* Footer text/brand colors, derived from config.colors.text with theme-based fallbacks
|
|
2015
|
+
*/
|
|
2016
|
+
getFooterTextColors() {
|
|
2017
|
+
const textColor = this.config.colors?.text ||
|
|
2018
|
+
(this.config.theme === "dark" ? "#9ca3af" : "#6b7280");
|
|
2019
|
+
const brandColor = this.config.colors?.text ||
|
|
2020
|
+
(this.config.theme === "dark" ? "#e5e7eb" : "#374151");
|
|
2021
|
+
return { textColor, brandColor };
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Passkey button colors, derived from config.colors with theme-based fallbacks
|
|
2025
|
+
*/
|
|
2026
|
+
getPasskeyButtonColors() {
|
|
2027
|
+
const passkeyBg = this.config.colors?.primary ||
|
|
2028
|
+
(this.config.theme === "dark" ? "#4b5563" : "#ffffff");
|
|
2029
|
+
const passkeyBorder = this.config.colors?.border ||
|
|
2030
|
+
(this.config.theme === "dark" ? "#6b7280" : "#e5e7eb");
|
|
2031
|
+
const passkeyTextColor = this.config.colors?.text ||
|
|
2032
|
+
(this.config.theme === "dark" ? "#ffffff" : "#1f2937");
|
|
2033
|
+
return { passkeyBg, passkeyBorder, passkeyTextColor };
|
|
1818
2034
|
}
|
|
1819
2035
|
/**
|
|
1820
2036
|
* Apply custom colors from config
|
|
1821
2037
|
*/
|
|
1822
2038
|
applyCustomColors() {
|
|
1823
|
-
if (!this.config.colors)
|
|
2039
|
+
if (!this.config.colors || !this.shadowContainer)
|
|
1824
2040
|
return;
|
|
1825
|
-
const root = this.rootElement || document.documentElement;
|
|
1826
2041
|
const style = document.createElement("style");
|
|
1827
2042
|
style.id = "onboarding-ui-colors";
|
|
1828
2043
|
let css = "";
|
|
@@ -1847,15 +2062,16 @@ export class OnboardingUIWeb {
|
|
|
1847
2062
|
css += `.onboarding-error { color: ${this.config.colors.error} !important; }`;
|
|
1848
2063
|
}
|
|
1849
2064
|
style.textContent = css;
|
|
1850
|
-
|
|
2065
|
+
this.shadowContainer.appendChild(style);
|
|
1851
2066
|
}
|
|
1852
2067
|
/**
|
|
1853
2068
|
* Setup the container element
|
|
1854
2069
|
*/
|
|
1855
2070
|
setupContainer() {
|
|
1856
|
-
// For modal mode, always use
|
|
2071
|
+
// For modal mode, always use the shadow container (the boundary this
|
|
2072
|
+
// instance owns), not document.body directly.
|
|
1857
2073
|
if (this.config.modal) {
|
|
1858
|
-
this.container =
|
|
2074
|
+
this.container = this.shadowContainer;
|
|
1859
2075
|
}
|
|
1860
2076
|
else {
|
|
1861
2077
|
if (this.config.container) {
|
|
@@ -1870,8 +2086,8 @@ export class OnboardingUIWeb {
|
|
|
1870
2086
|
}
|
|
1871
2087
|
}
|
|
1872
2088
|
else {
|
|
1873
|
-
//
|
|
1874
|
-
this.container =
|
|
2089
|
+
// Default container: the shadow container this instance owns.
|
|
2090
|
+
this.container = this.shadowContainer;
|
|
1875
2091
|
}
|
|
1876
2092
|
}
|
|
1877
2093
|
}
|
|
@@ -1908,6 +2124,7 @@ export class OnboardingUIWeb {
|
|
|
1908
2124
|
// Create root element for the form
|
|
1909
2125
|
this.rootElement = this.createElement("div", {
|
|
1910
2126
|
className: `onboarding-container onboarding-theme-${this.config.theme} ${this.config.className}`,
|
|
2127
|
+
part: "container",
|
|
1911
2128
|
style: this.parseStyle(this.config.style),
|
|
1912
2129
|
});
|
|
1913
2130
|
// Build the form content
|
|
@@ -1938,10 +2155,11 @@ export class OnboardingUIWeb {
|
|
|
1938
2155
|
}
|
|
1939
2156
|
});
|
|
1940
2157
|
}
|
|
1941
|
-
// Prevent body scroll when modal is open
|
|
2158
|
+
// Prevent body scroll when modal is open (intentional real document.body
|
|
2159
|
+
// side effect, not a style leak — the host page's own scroll state).
|
|
1942
2160
|
document.body.style.overflow = "hidden";
|
|
1943
|
-
// Append
|
|
1944
|
-
|
|
2161
|
+
// Append inside this instance's own shadow container, not document.body.
|
|
2162
|
+
this.shadowContainer?.appendChild(this.modalOverlay);
|
|
1945
2163
|
// Add animation class
|
|
1946
2164
|
setTimeout(() => {
|
|
1947
2165
|
if (this.modalOverlay) {
|
|
@@ -1969,11 +2187,12 @@ export class OnboardingUIWeb {
|
|
|
1969
2187
|
const focusableElements = this.modalContent.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
|
|
1970
2188
|
const firstElement = focusableElements[0];
|
|
1971
2189
|
const lastElement = focusableElements[focusableElements.length - 1];
|
|
1972
|
-
|
|
2190
|
+
const active = getDeepActiveElement();
|
|
2191
|
+
if (e.shiftKey && active === firstElement) {
|
|
1973
2192
|
e.preventDefault();
|
|
1974
2193
|
lastElement.focus();
|
|
1975
2194
|
}
|
|
1976
|
-
else if (!e.shiftKey &&
|
|
2195
|
+
else if (!e.shiftKey && active === lastElement) {
|
|
1977
2196
|
e.preventDefault();
|
|
1978
2197
|
firstElement.focus();
|
|
1979
2198
|
}
|
|
@@ -1987,12 +2206,13 @@ export class OnboardingUIWeb {
|
|
|
1987
2206
|
// Create root element
|
|
1988
2207
|
this.rootElement = this.createElement("div", {
|
|
1989
2208
|
className: `onboarding-container onboarding-inline onboarding-theme-${this.config.theme} ${this.config.className}`,
|
|
2209
|
+
part: "container",
|
|
1990
2210
|
style: this.parseStyle(this.config.style),
|
|
1991
2211
|
});
|
|
1992
2212
|
// Build the form content
|
|
1993
2213
|
this.buildFormContent();
|
|
1994
2214
|
// Append to container
|
|
1995
|
-
if (this.container ===
|
|
2215
|
+
if (this.container === this.shadowContainer) {
|
|
1996
2216
|
this.container.appendChild(this.rootElement);
|
|
1997
2217
|
}
|
|
1998
2218
|
else {
|
|
@@ -2007,7 +2227,7 @@ export class OnboardingUIWeb {
|
|
|
2007
2227
|
if (!this.rootElement)
|
|
2008
2228
|
return;
|
|
2009
2229
|
// Create card
|
|
2010
|
-
const card = this.createElement("div", { className: "onboarding-card" });
|
|
2230
|
+
const card = this.createElement("div", { className: "onboarding-card", part: "card" });
|
|
2011
2231
|
// Header with logo at top
|
|
2012
2232
|
const header = this.createElement("div", {
|
|
2013
2233
|
className: "onboarding-header",
|
|
@@ -2079,6 +2299,7 @@ export class OnboardingUIWeb {
|
|
|
2079
2299
|
id: "onboarding-email-input",
|
|
2080
2300
|
placeholder: this.config.labels?.emailPlaceholder || "Enter your email",
|
|
2081
2301
|
className: "onboarding-input",
|
|
2302
|
+
part: "input",
|
|
2082
2303
|
required: true,
|
|
2083
2304
|
autocomplete: "email",
|
|
2084
2305
|
"aria-label": this.config.labels?.emailLabel || "Email Address",
|
|
@@ -2139,6 +2360,7 @@ export class OnboardingUIWeb {
|
|
|
2139
2360
|
id: "onboarding-otp-input",
|
|
2140
2361
|
placeholder: this.config.labels?.otpPlaceholder || "Enter 6-digit code",
|
|
2141
2362
|
className: "onboarding-input",
|
|
2363
|
+
part: "input",
|
|
2142
2364
|
required: false, // Don't require initially since it's hidden
|
|
2143
2365
|
maxLength: 6,
|
|
2144
2366
|
inputMode: "numeric",
|
|
@@ -2161,6 +2383,7 @@ export class OnboardingUIWeb {
|
|
|
2161
2383
|
this.continueButton = this.createElement("button", {
|
|
2162
2384
|
type: "submit",
|
|
2163
2385
|
className: "onboarding-button onboarding-button-primary",
|
|
2386
|
+
part: "button-primary",
|
|
2164
2387
|
textContent: this.config.labels?.emailButton || "Continue",
|
|
2165
2388
|
"aria-label": this.config.labels?.emailButton || "Continue with email",
|
|
2166
2389
|
style: allAuthMethodsEnabled ? "display: none;" : "",
|
|
@@ -2180,14 +2403,7 @@ export class OnboardingUIWeb {
|
|
|
2180
2403
|
}
|
|
2181
2404
|
// Divider (show if email plus any social method is enabled)
|
|
2182
2405
|
if (showEmail && socialMethods.length > 0) {
|
|
2183
|
-
this.divider = this.
|
|
2184
|
-
className: "onboarding-divider",
|
|
2185
|
-
});
|
|
2186
|
-
const dividerText = this.createElement("span", {
|
|
2187
|
-
className: "onboarding-divider-text",
|
|
2188
|
-
textContent: "or",
|
|
2189
|
-
});
|
|
2190
|
-
this.divider.appendChild(dividerText);
|
|
2406
|
+
this.divider = this.createDividerElement();
|
|
2191
2407
|
card.appendChild(this.divider);
|
|
2192
2408
|
}
|
|
2193
2409
|
else {
|
|
@@ -2210,6 +2426,7 @@ export class OnboardingUIWeb {
|
|
|
2210
2426
|
className: isGoogle
|
|
2211
2427
|
? "onboarding-button onboarding-button-google"
|
|
2212
2428
|
: "onboarding-button onboarding-button-social",
|
|
2429
|
+
part: isGoogle ? "button-google" : undefined,
|
|
2213
2430
|
"aria-label": this.config.labels?.[`${method}Button`] ||
|
|
2214
2431
|
(method === "google"
|
|
2215
2432
|
? "Continue with Google"
|
|
@@ -2287,14 +2504,7 @@ export class OnboardingUIWeb {
|
|
|
2287
2504
|
}
|
|
2288
2505
|
// Passkey divider (only show if passkey is enabled and there are other auth methods)
|
|
2289
2506
|
if (showPasskey && (showEmail || socialMethods.length > 0)) {
|
|
2290
|
-
this.passkeyDivider = this.
|
|
2291
|
-
className: "onboarding-divider",
|
|
2292
|
-
});
|
|
2293
|
-
const passkeyDividerText = this.createElement("span", {
|
|
2294
|
-
className: "onboarding-divider-text",
|
|
2295
|
-
textContent: "or",
|
|
2296
|
-
});
|
|
2297
|
-
this.passkeyDivider.appendChild(passkeyDividerText);
|
|
2507
|
+
this.passkeyDivider = this.createDividerElement();
|
|
2298
2508
|
card.appendChild(this.passkeyDivider);
|
|
2299
2509
|
}
|
|
2300
2510
|
else {
|
|
@@ -2302,12 +2512,7 @@ export class OnboardingUIWeb {
|
|
|
2302
2512
|
}
|
|
2303
2513
|
// Passkey login button (only show if passkey auth is enabled)
|
|
2304
2514
|
if (showPasskey) {
|
|
2305
|
-
const passkeyBg = this.
|
|
2306
|
-
(this.config.theme === "dark" ? "#4b5563" : "#ffffff");
|
|
2307
|
-
const passkeyBorder = this.config.colors?.border ||
|
|
2308
|
-
(this.config.theme === "dark" ? "#6b7280" : "#e5e7eb");
|
|
2309
|
-
const passkeyTextColor = this.config.colors?.text ||
|
|
2310
|
-
(this.config.theme === "dark" ? "#ffffff" : "#1f2937");
|
|
2515
|
+
const { passkeyBg, passkeyBorder, passkeyTextColor } = this.getPasskeyButtonColors();
|
|
2311
2516
|
this.passkeyLoginButton = this.createElement("button", {
|
|
2312
2517
|
type: "button",
|
|
2313
2518
|
className: "onboarding-button onboarding-button-passkey",
|
|
@@ -2366,15 +2571,10 @@ export class OnboardingUIWeb {
|
|
|
2366
2571
|
card.appendChild(this.passkeyErrorElement);
|
|
2367
2572
|
}
|
|
2368
2573
|
// External wallet divider (shown immediately if external wallets are enabled)
|
|
2369
|
-
this.externalWalletDivider = this.
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
const externalWalletDividerText = this.createElement("span", {
|
|
2374
|
-
className: "onboarding-divider-text",
|
|
2375
|
-
textContent: "or",
|
|
2376
|
-
});
|
|
2377
|
-
this.externalWalletDivider.appendChild(externalWalletDividerText);
|
|
2574
|
+
this.externalWalletDivider = this.createDividerElement();
|
|
2575
|
+
this.externalWalletDivider.style.display = this.externalWalletsEnabled
|
|
2576
|
+
? ""
|
|
2577
|
+
: "none";
|
|
2378
2578
|
card.appendChild(this.externalWalletDivider);
|
|
2379
2579
|
// External wallet container (shown immediately if external wallets are enabled)
|
|
2380
2580
|
this.externalWalletContainer = this.createElement("div", {
|
|
@@ -2384,10 +2584,7 @@ export class OnboardingUIWeb {
|
|
|
2384
2584
|
card.appendChild(this.externalWalletContainer);
|
|
2385
2585
|
// Footer (inside card, so it appears on initial login screen)
|
|
2386
2586
|
if (this.config.showFooter) {
|
|
2387
|
-
const textColor = this.
|
|
2388
|
-
(this.config.theme === "dark" ? "#9ca3af" : "#6b7280");
|
|
2389
|
-
const brandColor = this.config.colors?.text ||
|
|
2390
|
-
(this.config.theme === "dark" ? "#e5e7eb" : "#374151");
|
|
2587
|
+
const { textColor, brandColor } = this.getFooterTextColors();
|
|
2391
2588
|
this.footer = this.createElement("div", {
|
|
2392
2589
|
className: "onboarding-footer",
|
|
2393
2590
|
});
|
|
@@ -2411,24 +2608,7 @@ export class OnboardingUIWeb {
|
|
|
2411
2608
|
});
|
|
2412
2609
|
// Abstraxn logo SVG
|
|
2413
2610
|
const logoSvg = this.createElement("span", {
|
|
2414
|
-
innerHTML:
|
|
2415
|
-
<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;">
|
|
2416
|
-
<path d="M47.9082 37.191L23.9541 23.553L0 9.91504L37.7436 -8.13502e-06L47.9082 37.191Z" fill="url(#paint0_linear_1242_781)"/>
|
|
2417
|
-
<path d="M13.5156 46.3594L10.1846 47.2344L8.99219 42.873L12.4365 42.4111L13.5156 46.3594ZM20.4268 44.5566L17.1152 45.4199L16.125 41.8818L19.5566 41.3721L20.4268 44.5566ZM26.9307 42.834L23.6152 43.6982L22.8438 40.9443L26.2744 40.4326L26.9307 42.834ZM33.5078 41.1074L30.1875 41.9727L29.6328 39.9951L33.0635 39.4844L33.5078 41.1074ZM39.998 39.4014L36.6729 40.2686L36.3359 39.0674L39.7656 38.5508L39.998 39.4014ZM10.1406 33.9434L11.6807 39.5762L8.15918 39.7568L6.46094 33.543L10.1406 33.9434ZM17.6582 34.5996L18.8916 39.1113L15.4199 39.3496L14.0078 34.3076L17.6582 34.5996ZM24.8779 35.332L25.8047 38.7227L22.3252 38.959L21.2266 35.0361L24.8779 35.332ZM32.0918 36.0723L32.7119 38.3398L29.2227 38.5723L28.4375 35.7656L32.0918 36.0723ZM43.2373 38.5488L43.1172 38.1172L47.7939 37.3516L43.2373 38.5488ZM39.3047 36.8096L39.6182 37.9561L36.1221 38.1846L35.6484 36.4961L39.3047 36.8096ZM47.7939 37.3516L43.0107 37.7939L42.8516 37.2236L47.7939 37.3516ZM47.8291 37.2988L42.7227 36.7529L42.5547 36.1523L47.8291 37.2988ZM47.8652 37.2412L42.3711 35.3486L42.2031 34.7471L47.8652 37.2412ZM38.748 34.8604L39.0664 36.0254L35.3369 35.4043L34.8594 33.6982L38.748 34.8604ZM31.0576 32.3994L31.6787 34.6709L27.959 34.0566L27.1719 31.2461L31.0576 32.3994ZM38.0811 32.6318L38.4092 33.8301L34.4893 32.3496L34.1543 31.1523C34.1005 30.9591 34.0322 30.7719 33.9531 30.5918L38.0811 32.6318ZM23.3682 29.9385L24.291 33.3164L20.5801 32.71L19.4844 28.7949L23.3682 29.9385ZM15.6641 27.4805L16.8896 31.9629L13.1875 31.3594L11.7812 26.3379L15.6641 27.4805ZM29.9463 28.4678L30.5693 30.748L26.6201 29.2812L25.8633 26.583C25.8534 26.5431 25.8417 26.5028 25.8281 26.4639L29.9463 28.4678ZM7.6875 25.0938L9.21484 30.6816L5.44727 29.959L3.75781 23.7793L7.6875 25.0938ZM21.5312 23.3623L22.4492 26.7227L18.5059 25.2627L17.4141 21.3643L21.5312 23.3623ZM13.6104 20.1602L14.8242 24.6006L10.8887 23.1387L9.49219 18.1553L13.6104 20.1602ZM5.2168 16.0654L6.72559 21.585L2.70703 19.9473L1.06055 13.8701L5.2168 16.0654Z" fill="url(#paint1_linear_1242_781)"/>
|
|
2418
|
-
<defs>
|
|
2419
|
-
<linearGradient id="paint0_linear_1242_781" x1="7.03362" y1="6.09543" x2="47.2003" y2="57.0656" gradientUnits="userSpaceOnUse">
|
|
2420
|
-
<stop stop-color="#F878D2"/>
|
|
2421
|
-
<stop offset="0.393522" stop-color="#FDCC81"/>
|
|
2422
|
-
<stop offset="1" stop-color="#F9A0D9"/>
|
|
2423
|
-
</linearGradient>
|
|
2424
|
-
<linearGradient id="paint1_linear_1242_781" x1="2.53739" y1="21.5136" x2="48.7969" y2="38.5742" gradientUnits="userSpaceOnUse">
|
|
2425
|
-
<stop stop-color="#F878D2"/>
|
|
2426
|
-
<stop offset="0.393522" stop-color="#FDCC81"/>
|
|
2427
|
-
<stop offset="1" stop-color="#F9A0D9"/>
|
|
2428
|
-
</linearGradient>
|
|
2429
|
-
</defs>
|
|
2430
|
-
</svg>
|
|
2431
|
-
`,
|
|
2611
|
+
innerHTML: abstraxnLogoSvgHtml({ size: 20, gradientId: "abstraxn_logo_web_main" }),
|
|
2432
2612
|
style: "display: inline-flex; align-items: center;",
|
|
2433
2613
|
});
|
|
2434
2614
|
brandContainer.appendChild(logoSvg);
|
|
@@ -2835,6 +3015,7 @@ export class OnboardingUIWeb {
|
|
|
2835
3015
|
this.verifyButton = this.createElement("button", {
|
|
2836
3016
|
type: "button",
|
|
2837
3017
|
className: "onboarding-button onboarding-button-primary",
|
|
3018
|
+
part: "button-primary",
|
|
2838
3019
|
textContent: "Verify",
|
|
2839
3020
|
});
|
|
2840
3021
|
this.verifyButton.disabled = true; // Start disabled; updateVerifyButtonDisabled() keeps it in sync
|
|
@@ -2867,10 +3048,7 @@ export class OnboardingUIWeb {
|
|
|
2867
3048
|
}
|
|
2868
3049
|
// Footer (add to OTP screen as well)
|
|
2869
3050
|
if (this.config.showFooter) {
|
|
2870
|
-
const textColor = this.
|
|
2871
|
-
(this.config.theme === "dark" ? "#9ca3af" : "#6b7280");
|
|
2872
|
-
const brandColor = this.config.colors?.text ||
|
|
2873
|
-
(this.config.theme === "dark" ? "#e5e7eb" : "#374151");
|
|
3051
|
+
const { textColor, brandColor } = this.getFooterTextColors();
|
|
2874
3052
|
const otpFooter = this.createElement("div", {
|
|
2875
3053
|
className: "onboarding-footer",
|
|
2876
3054
|
});
|
|
@@ -2894,24 +3072,7 @@ export class OnboardingUIWeb {
|
|
|
2894
3072
|
});
|
|
2895
3073
|
// Abstraxn logo SVG
|
|
2896
3074
|
const logoSvg = this.createElement("span", {
|
|
2897
|
-
innerHTML:
|
|
2898
|
-
<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;">
|
|
2899
|
-
<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)"/>
|
|
2900
|
-
<path d="M13.5156 46.3594L10.1846 47.2344L8.99219 42.873L12.4365 42.4111L13.5156 46.3594ZM20.4268 44.5566L17.1152 45.4199L16.125 41.8818L19.5566 41.3721L20.4268 44.5566ZM26.9307 42.834L23.6152 43.6982L22.8438 40.9443L26.2744 40.4326L26.9307 42.834ZM33.5078 41.1074L30.1875 41.9727L29.6328 39.9951L33.0635 39.4844L33.5078 41.1074ZM39.998 39.4014L36.6729 40.2686L36.3359 39.0674L39.7656 38.5508L39.998 39.4014ZM10.1406 33.9434L11.6807 39.5762L8.15918 39.7568L6.46094 33.543L10.1406 33.9434ZM17.6582 34.5996L18.8916 39.1113L15.4199 39.3496L14.0078 34.3076L17.6582 34.5996ZM24.8779 35.332L25.8047 38.7227L22.3252 38.959L21.2266 35.0361L24.8779 35.332ZM32.0918 36.0723L32.7119 38.3398L29.2227 38.5723L28.4375 35.7656L32.0918 36.0723ZM43.2373 38.5488L43.1172 38.1172L47.7939 37.3516L43.2373 38.5488ZM39.3047 36.8096L39.6182 37.9561L36.1221 38.1846L35.6484 36.4961L39.3047 36.8096ZM47.7939 37.3516L43.0107 37.7939L42.8516 37.2236L47.7939 37.3516ZM47.8291 37.2988L42.7227 36.7529L42.5547 36.1523L47.8291 37.2988ZM47.8652 37.2412L42.3711 35.3486L42.2031 34.7471L47.8652 37.2412ZM38.748 34.8604L39.0664 36.0254L35.3369 35.4043L34.8594 33.6982L38.748 34.8604ZM31.0576 32.3994L31.6787 34.6709L27.959 34.0566L27.1719 31.2461L31.0576 32.3994ZM38.0811 32.6318L38.4092 33.8301L34.4893 32.3496L34.1543 31.1523C34.1005 30.9591 34.0322 30.7719 33.9531 30.5918L38.0811 32.6318ZM23.3682 29.9385L24.291 33.3164L20.5801 32.71L19.4844 28.7949L23.3682 29.9385ZM15.6641 27.4805L16.8896 31.9629L13.1875 31.3594L11.7812 26.3379L15.6641 27.4805ZM29.9463 28.4678L30.5693 30.748L26.6201 29.2812L25.8633 26.583C25.8534 26.5431 25.8417 26.5028 25.8281 26.4639L29.9463 28.4678ZM7.6875 25.0938L9.21484 30.6816L5.44727 29.959L3.75781 23.7793L7.6875 25.0938ZM21.5312 23.3623L22.4492 26.7227L18.5059 25.2627L17.4141 21.3643L21.5312 23.3623ZM13.6104 20.1602L14.8242 24.6006L10.8887 23.1387L9.49219 18.1553L13.6104 20.1602ZM5.2168 16.0654L6.72559 21.585L2.70703 19.9473L1.06055 13.8701L5.2168 16.0654Z" fill="url(#paint1_linear_1242_781_otp)"/>
|
|
2901
|
-
<defs>
|
|
2902
|
-
<linearGradient id="paint0_linear_1242_781_otp" x1="7.03362" y1="6.09543" x2="47.2003" y2="57.0656" gradientUnits="userSpaceOnUse">
|
|
2903
|
-
<stop stop-color="#F878D2"/>
|
|
2904
|
-
<stop offset="0.393522" stop-color="#FDCC81"/>
|
|
2905
|
-
<stop offset="1" stop-color="#F9A0D9"/>
|
|
2906
|
-
</linearGradient>
|
|
2907
|
-
<linearGradient id="paint1_linear_1242_781_otp" x1="2.53739" y1="21.5136" x2="48.7969" y2="38.5742" gradientUnits="userSpaceOnUse">
|
|
2908
|
-
<stop stop-color="#F878D2"/>
|
|
2909
|
-
<stop offset="0.393522" stop-color="#FDCC81"/>
|
|
2910
|
-
<stop offset="1" stop-color="#F9A0D9"/>
|
|
2911
|
-
</linearGradient>
|
|
2912
|
-
</defs>
|
|
2913
|
-
</svg>
|
|
2914
|
-
`,
|
|
3075
|
+
innerHTML: abstraxnLogoSvgHtml({ size: 20, gradientId: "abstraxn_logo_web_otp" }),
|
|
2915
3076
|
style: "display: inline-flex; align-items: center;",
|
|
2916
3077
|
});
|
|
2917
3078
|
brandContainer.appendChild(logoSvg);
|
|
@@ -3404,6 +3565,7 @@ export class OnboardingUIWeb {
|
|
|
3404
3565
|
this.mfaVerifyButton = this.createElement("button", {
|
|
3405
3566
|
type: "button",
|
|
3406
3567
|
className: "onboarding-button onboarding-button-primary",
|
|
3568
|
+
part: "button-primary",
|
|
3407
3569
|
textContent: "Verify",
|
|
3408
3570
|
});
|
|
3409
3571
|
this.mfaVerifyButton.disabled = true;
|
|
@@ -4056,6 +4218,12 @@ export class OnboardingUIWeb {
|
|
|
4056
4218
|
* Destroy the component
|
|
4057
4219
|
*/
|
|
4058
4220
|
destroy() {
|
|
4221
|
+
// Cancel any delayed OAuth loader so it cannot paint into a torn-down shadow root
|
|
4222
|
+
// (or call ensureLiveShadow and orphan a new host after StrictMode cleanup).
|
|
4223
|
+
if (this.pendingLoadingModalTimer !== null) {
|
|
4224
|
+
clearTimeout(this.pendingLoadingModalTimer);
|
|
4225
|
+
this.pendingLoadingModalTimer = null;
|
|
4226
|
+
}
|
|
4059
4227
|
// Reset to login form before destroying to ensure clean state
|
|
4060
4228
|
this.resetToLoginForm();
|
|
4061
4229
|
// Clean up modal
|
|
@@ -4086,6 +4254,26 @@ export class OnboardingUIWeb {
|
|
|
4086
4254
|
this.mfaUseBackupCode = false;
|
|
4087
4255
|
this.externalWalletContainer = null; // Clear external wallet container reference
|
|
4088
4256
|
this.externalWalletDivider = null; // Clear external wallet divider reference
|
|
4257
|
+
// Remove this instance's own shadow host from document.body and
|
|
4258
|
+
// unregister it from shadowRegistry — entirely self-contained to this
|
|
4259
|
+
// instance, does not affect any other coexisting OnboardingUIWeb instance
|
|
4260
|
+
// (see docs/shadow-dom-migration-plan.md — this was a page-wide singleton
|
|
4261
|
+
// in an earlier draft of the design, corrected to per-instance).
|
|
4262
|
+
this.shadowTeardown?.();
|
|
4263
|
+
this.shadowTeardown = null;
|
|
4264
|
+
this.shadowContainer = null;
|
|
4265
|
+
// MUST reset alongside shadowContainer: a later re-init() creates a
|
|
4266
|
+
// BRAND NEW shadow container with zero styles injected into it yet. If
|
|
4267
|
+
// this stayed true, injectStyles()'s first-line guard
|
|
4268
|
+
// (`if (this.stylesInjected || ...) return;`) would short-circuit before
|
|
4269
|
+
// ever reaching its own DOM-existence check, permanently skipping style
|
|
4270
|
+
// injection for the new container — the modal would render with only
|
|
4271
|
+
// its inline `display` style and none of its own CSS (no position:fixed,
|
|
4272
|
+
// no z-index), landing in normal document flow instead of as an overlay.
|
|
4273
|
+
// This exact sequence happens every time under React 18 StrictMode's
|
|
4274
|
+
// dev-mode mount->cleanup->mount cycle: destroy() runs once via the
|
|
4275
|
+
// simulated cleanup, then a real re-init happens lazily on first click.
|
|
4276
|
+
this.stylesInjected = false;
|
|
4089
4277
|
}
|
|
4090
4278
|
/**
|
|
4091
4279
|
* Create DOM element helper
|