@volr/react-ui 0.1.119 → 0.1.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +197 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +197 -9
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -61,6 +61,7 @@ declare const VolrUIProvider: React$1.FC<VolrUIProviderProps>;
|
|
|
61
61
|
/**
|
|
62
62
|
* Passkey Enrollment View Component
|
|
63
63
|
* Modern passkey setup with device-specific biometric icons
|
|
64
|
+
* Includes cross-domain migration detection and guidance
|
|
64
65
|
*/
|
|
65
66
|
interface PasskeyEnrollViewProps {
|
|
66
67
|
onComplete: () => void;
|
|
@@ -151,6 +152,7 @@ declare const en: {
|
|
|
151
152
|
readonly titleTouchId: "Set up Touch ID login";
|
|
152
153
|
readonly titleFaceId: "Set up Face ID login";
|
|
153
154
|
readonly titleFingerprint: "Set up fingerprint login";
|
|
155
|
+
readonly titleQrCode: "Set up mobile login";
|
|
154
156
|
readonly description: "Sign in instantly, every time.";
|
|
155
157
|
readonly touchId: "Use Touch ID to create your passkey";
|
|
156
158
|
readonly faceId: "Use Face ID to create your passkey";
|
|
@@ -178,6 +180,7 @@ declare const en: {
|
|
|
178
180
|
readonly outdatedSamsung: "Please update Samsung Internet to the latest version.";
|
|
179
181
|
readonly outdatedIOS: "iOS 17.4 or later is required. Please check for software updates in Settings.";
|
|
180
182
|
readonly firefoxNotSupported: "Secure login is not available in Firefox. Please use Chrome or Safari.";
|
|
183
|
+
readonly whaleNotSupported: "Secure login is not available in Whale browser. Please use Chrome.";
|
|
181
184
|
readonly unknownBrowser: "Secure login may not work properly in this browser.";
|
|
182
185
|
readonly openInExternalBrowser: "Open in external browser";
|
|
183
186
|
readonly updateBrowser: "Update browser";
|
|
@@ -192,6 +195,19 @@ declare const en: {
|
|
|
192
195
|
readonly default: "Please use this device's biometric.";
|
|
193
196
|
readonly note: "Using other devices or apps may not work.";
|
|
194
197
|
};
|
|
198
|
+
readonly migration: {
|
|
199
|
+
readonly title: "Set up passkey for this site";
|
|
200
|
+
readonly description: "Your wallet was created on {{sourceDomain}}. To use it here, you need to set up a new passkey for this site.";
|
|
201
|
+
readonly descriptionGeneric: "Your wallet was created on a different site. To use it here, you need to set up a new passkey for this site.";
|
|
202
|
+
readonly currentDomain: "Current site";
|
|
203
|
+
readonly sourceDomain: "Original site";
|
|
204
|
+
readonly benefits: "Your wallet address and balance will remain the same.";
|
|
205
|
+
readonly cta: "Set up passkey";
|
|
206
|
+
readonly later: "Do it later";
|
|
207
|
+
readonly inProgress: "Setting up...";
|
|
208
|
+
readonly success: "Passkey set up successfully!";
|
|
209
|
+
readonly error: "Failed to set up passkey. Please try again.";
|
|
210
|
+
};
|
|
195
211
|
};
|
|
196
212
|
readonly success: {
|
|
197
213
|
readonly title: "Success!";
|
package/dist/index.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ declare const VolrUIProvider: React$1.FC<VolrUIProviderProps>;
|
|
|
61
61
|
/**
|
|
62
62
|
* Passkey Enrollment View Component
|
|
63
63
|
* Modern passkey setup with device-specific biometric icons
|
|
64
|
+
* Includes cross-domain migration detection and guidance
|
|
64
65
|
*/
|
|
65
66
|
interface PasskeyEnrollViewProps {
|
|
66
67
|
onComplete: () => void;
|
|
@@ -151,6 +152,7 @@ declare const en: {
|
|
|
151
152
|
readonly titleTouchId: "Set up Touch ID login";
|
|
152
153
|
readonly titleFaceId: "Set up Face ID login";
|
|
153
154
|
readonly titleFingerprint: "Set up fingerprint login";
|
|
155
|
+
readonly titleQrCode: "Set up mobile login";
|
|
154
156
|
readonly description: "Sign in instantly, every time.";
|
|
155
157
|
readonly touchId: "Use Touch ID to create your passkey";
|
|
156
158
|
readonly faceId: "Use Face ID to create your passkey";
|
|
@@ -178,6 +180,7 @@ declare const en: {
|
|
|
178
180
|
readonly outdatedSamsung: "Please update Samsung Internet to the latest version.";
|
|
179
181
|
readonly outdatedIOS: "iOS 17.4 or later is required. Please check for software updates in Settings.";
|
|
180
182
|
readonly firefoxNotSupported: "Secure login is not available in Firefox. Please use Chrome or Safari.";
|
|
183
|
+
readonly whaleNotSupported: "Secure login is not available in Whale browser. Please use Chrome.";
|
|
181
184
|
readonly unknownBrowser: "Secure login may not work properly in this browser.";
|
|
182
185
|
readonly openInExternalBrowser: "Open in external browser";
|
|
183
186
|
readonly updateBrowser: "Update browser";
|
|
@@ -192,6 +195,19 @@ declare const en: {
|
|
|
192
195
|
readonly default: "Please use this device's biometric.";
|
|
193
196
|
readonly note: "Using other devices or apps may not work.";
|
|
194
197
|
};
|
|
198
|
+
readonly migration: {
|
|
199
|
+
readonly title: "Set up passkey for this site";
|
|
200
|
+
readonly description: "Your wallet was created on {{sourceDomain}}. To use it here, you need to set up a new passkey for this site.";
|
|
201
|
+
readonly descriptionGeneric: "Your wallet was created on a different site. To use it here, you need to set up a new passkey for this site.";
|
|
202
|
+
readonly currentDomain: "Current site";
|
|
203
|
+
readonly sourceDomain: "Original site";
|
|
204
|
+
readonly benefits: "Your wallet address and balance will remain the same.";
|
|
205
|
+
readonly cta: "Set up passkey";
|
|
206
|
+
readonly later: "Do it later";
|
|
207
|
+
readonly inProgress: "Setting up...";
|
|
208
|
+
readonly success: "Passkey set up successfully!";
|
|
209
|
+
readonly error: "Failed to set up passkey. Please try again.";
|
|
210
|
+
};
|
|
195
211
|
};
|
|
196
212
|
readonly success: {
|
|
197
213
|
readonly title: "Success!";
|
package/dist/index.js
CHANGED
|
@@ -526,6 +526,7 @@ var en = {
|
|
|
526
526
|
titleTouchId: "Set up Touch ID login",
|
|
527
527
|
titleFaceId: "Set up Face ID login",
|
|
528
528
|
titleFingerprint: "Set up fingerprint login",
|
|
529
|
+
titleQrCode: "Set up mobile login",
|
|
529
530
|
// Short description
|
|
530
531
|
description: "Sign in instantly, every time.",
|
|
531
532
|
// Legacy keys for backward compatibility
|
|
@@ -555,6 +556,7 @@ var en = {
|
|
|
555
556
|
outdatedSamsung: "Please update Samsung Internet to the latest version.",
|
|
556
557
|
outdatedIOS: "iOS 17.4 or later is required. Please check for software updates in Settings.",
|
|
557
558
|
firefoxNotSupported: "Secure login is not available in Firefox. Please use Chrome or Safari.",
|
|
559
|
+
whaleNotSupported: "Secure login is not available in Whale browser. Please use Chrome.",
|
|
558
560
|
unknownBrowser: "Secure login may not work properly in this browser.",
|
|
559
561
|
openInExternalBrowser: "Open in external browser",
|
|
560
562
|
updateBrowser: "Update browser",
|
|
@@ -568,6 +570,19 @@ var en = {
|
|
|
568
570
|
windows: "Please use your phone via QR code. (Windows Hello is not supported)",
|
|
569
571
|
default: "Please use this device's biometric.",
|
|
570
572
|
note: "Using other devices or apps may not work."
|
|
573
|
+
},
|
|
574
|
+
migration: {
|
|
575
|
+
title: "Set up passkey for this site",
|
|
576
|
+
description: "Your wallet was created on {{sourceDomain}}. To use it here, you need to set up a new passkey for this site.",
|
|
577
|
+
descriptionGeneric: "Your wallet was created on a different site. To use it here, you need to set up a new passkey for this site.",
|
|
578
|
+
currentDomain: "Current site",
|
|
579
|
+
sourceDomain: "Original site",
|
|
580
|
+
benefits: "Your wallet address and balance will remain the same.",
|
|
581
|
+
cta: "Set up passkey",
|
|
582
|
+
later: "Do it later",
|
|
583
|
+
inProgress: "Setting up...",
|
|
584
|
+
success: "Passkey set up successfully!",
|
|
585
|
+
error: "Failed to set up passkey. Please try again."
|
|
571
586
|
}
|
|
572
587
|
},
|
|
573
588
|
success: {
|
|
@@ -753,6 +768,7 @@ var ko = {
|
|
|
753
768
|
titleTouchId: "Touch ID \uB85C\uADF8\uC778 \uC124\uC815",
|
|
754
769
|
titleFaceId: "Face ID \uB85C\uADF8\uC778 \uC124\uC815",
|
|
755
770
|
titleFingerprint: "\uC9C0\uBB38 \uB85C\uADF8\uC778 \uC124\uC815",
|
|
771
|
+
titleQrCode: "\uD734\uB300\uD3F0\uC73C\uB85C \uB85C\uADF8\uC778 \uC124\uC815",
|
|
756
772
|
// Short description
|
|
757
773
|
description: "\uD55C \uBC88 \uB4F1\uB85D\uD558\uBA74, \uB2E4\uC74C\uBD80\uD130 \uBC14\uB85C \uB85C\uADF8\uC778",
|
|
758
774
|
// Legacy keys for backward compatibility
|
|
@@ -782,6 +798,7 @@ var ko = {
|
|
|
782
798
|
outdatedSamsung: "Samsung Internet\uC744 \uCD5C\uC2E0 \uBC84\uC804\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD574\uC8FC\uC138\uC694.",
|
|
783
799
|
outdatedIOS: "iOS 17.4 \uC774\uC0C1 \uBC84\uC804\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC124\uC815\uC5D0\uC11C \uC18C\uD504\uD2B8\uC6E8\uC5B4 \uC5C5\uB370\uC774\uD2B8\uB97C \uD655\uC778\uD574\uC8FC\uC138\uC694.",
|
|
784
800
|
firefoxNotSupported: "Firefox\uC5D0\uC11C\uB294 \uBCF4\uC548 \uB85C\uADF8\uC778\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. Chrome \uB610\uB294 Safari\uB97C \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694.",
|
|
801
|
+
whaleNotSupported: "\uC6E8\uC77C \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C\uB294 \uBCF4\uC548 \uB85C\uADF8\uC778\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. Chrome\uC744 \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694.",
|
|
785
802
|
unknownBrowser: "\uC774 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C\uB294 \uBCF4\uC548 \uB85C\uADF8\uC778\uC774 \uC81C\uB300\uB85C \uC791\uB3D9\uD558\uC9C0 \uC54A\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
786
803
|
openInExternalBrowser: "\uC678\uBD80 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uAE30",
|
|
787
804
|
updateBrowser: "\uBE0C\uB77C\uC6B0\uC800 \uC5C5\uB370\uC774\uD2B8",
|
|
@@ -795,6 +812,19 @@ var ko = {
|
|
|
795
812
|
windows: "QR \uCF54\uB4DC\uB85C \uD734\uB300\uD3F0\uC744 \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694. (Windows Hello\uB294 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4)",
|
|
796
813
|
default: "\uC774 \uAE30\uAE30\uC758 \uC0DD\uCCB4 \uC778\uC99D\uC744 \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694.",
|
|
797
814
|
note: "\uB2E4\uB978 \uAE30\uAE30\uB098 \uC571 \uC0AC\uC6A9 \uC2DC \uB3D9\uC791\uD558\uC9C0 \uC54A\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
|
|
815
|
+
},
|
|
816
|
+
migration: {
|
|
817
|
+
title: "\uC774 \uC0AC\uC774\uD2B8\uC6A9 \uD328\uC2A4\uD0A4 \uC124\uC815",
|
|
818
|
+
description: "\uC9C0\uAC11\uC774 {{sourceDomain}}\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC774 \uC0AC\uC774\uD2B8\uC5D0\uC11C \uC0AC\uC6A9\uD558\uB824\uBA74 \uC0C8 \uD328\uC2A4\uD0A4\uB97C \uC124\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.",
|
|
819
|
+
descriptionGeneric: "\uC9C0\uAC11\uC774 \uB2E4\uB978 \uC0AC\uC774\uD2B8\uC5D0\uC11C \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC774 \uC0AC\uC774\uD2B8\uC5D0\uC11C \uC0AC\uC6A9\uD558\uB824\uBA74 \uC0C8 \uD328\uC2A4\uD0A4\uB97C \uC124\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.",
|
|
820
|
+
currentDomain: "\uD604\uC7AC \uC0AC\uC774\uD2B8",
|
|
821
|
+
sourceDomain: "\uC6D0\uBCF8 \uC0AC\uC774\uD2B8",
|
|
822
|
+
benefits: "\uC9C0\uAC11 \uC8FC\uC18C\uC640 \uC794\uC561\uC740 \uADF8\uB300\uB85C \uC720\uC9C0\uB429\uB2C8\uB2E4.",
|
|
823
|
+
cta: "\uD328\uC2A4\uD0A4 \uC124\uC815\uD558\uAE30",
|
|
824
|
+
later: "\uB098\uC911\uC5D0 \uD558\uAE30",
|
|
825
|
+
inProgress: "\uC124\uC815 \uC911...",
|
|
826
|
+
success: "\uD328\uC2A4\uD0A4 \uC124\uC815\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4!",
|
|
827
|
+
error: "\uD328\uC2A4\uD0A4 \uC124\uC815\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694."
|
|
798
828
|
}
|
|
799
829
|
},
|
|
800
830
|
success: {
|
|
@@ -1366,13 +1396,21 @@ var ModalHeader = ({
|
|
|
1366
1396
|
|
|
1367
1397
|
// src/components/features/passkey/utils/biometric.ts
|
|
1368
1398
|
function getBiometricType() {
|
|
1399
|
+
if (typeof navigator === "undefined") return "fingerprint";
|
|
1369
1400
|
const ua = navigator.userAgent;
|
|
1401
|
+
const platform = navigator.platform || "";
|
|
1370
1402
|
if (/iPhone|iPad|iPod/.test(ua)) {
|
|
1371
1403
|
return "faceId";
|
|
1372
1404
|
}
|
|
1373
1405
|
if (/Macintosh|MacIntel/.test(ua)) {
|
|
1406
|
+
if (navigator.maxTouchPoints > 1) {
|
|
1407
|
+
return "faceId";
|
|
1408
|
+
}
|
|
1374
1409
|
return "touchId";
|
|
1375
1410
|
}
|
|
1411
|
+
if (/Win/.test(platform)) {
|
|
1412
|
+
return "qrCode";
|
|
1413
|
+
}
|
|
1376
1414
|
return "fingerprint";
|
|
1377
1415
|
}
|
|
1378
1416
|
function getUserFriendlyError(error, t) {
|
|
@@ -1620,12 +1658,44 @@ function FingerprintIcon({ size }) {
|
|
|
1620
1658
|
}
|
|
1621
1659
|
);
|
|
1622
1660
|
}
|
|
1661
|
+
function QrCodeIcon({ size }) {
|
|
1662
|
+
const fill = "#f87171";
|
|
1663
|
+
return /* @__PURE__ */ jsxs(
|
|
1664
|
+
"svg",
|
|
1665
|
+
{
|
|
1666
|
+
width: size,
|
|
1667
|
+
height: size,
|
|
1668
|
+
viewBox: "0 0 24 24",
|
|
1669
|
+
fill: "none",
|
|
1670
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1671
|
+
children: [
|
|
1672
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1", fill }),
|
|
1673
|
+
/* @__PURE__ */ jsx("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1", fill }),
|
|
1674
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1", fill }),
|
|
1675
|
+
/* @__PURE__ */ jsx("rect", { x: "5", y: "5", width: "3", height: "3", fill: "white" }),
|
|
1676
|
+
/* @__PURE__ */ jsx("rect", { x: "16", y: "5", width: "3", height: "3", fill: "white" }),
|
|
1677
|
+
/* @__PURE__ */ jsx("rect", { x: "5", y: "16", width: "3", height: "3", fill: "white" }),
|
|
1678
|
+
/* @__PURE__ */ jsx("rect", { x: "14", y: "14", width: "2", height: "2", fill }),
|
|
1679
|
+
/* @__PURE__ */ jsx("rect", { x: "17", y: "14", width: "2", height: "2", fill }),
|
|
1680
|
+
/* @__PURE__ */ jsx("rect", { x: "14", y: "17", width: "2", height: "2", fill }),
|
|
1681
|
+
/* @__PURE__ */ jsx("rect", { x: "19", y: "17", width: "2", height: "2", fill }),
|
|
1682
|
+
/* @__PURE__ */ jsx("rect", { x: "17", y: "19", width: "2", height: "2", fill }),
|
|
1683
|
+
/* @__PURE__ */ jsx("rect", { x: "11", y: "3", width: "2", height: "2", fill }),
|
|
1684
|
+
/* @__PURE__ */ jsx("rect", { x: "11", y: "6", width: "2", height: "2", fill }),
|
|
1685
|
+
/* @__PURE__ */ jsx("rect", { x: "11", y: "11", width: "2", height: "2", fill }),
|
|
1686
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "11", width: "2", height: "2", fill }),
|
|
1687
|
+
/* @__PURE__ */ jsx("rect", { x: "6", y: "11", width: "2", height: "2", fill })
|
|
1688
|
+
]
|
|
1689
|
+
}
|
|
1690
|
+
);
|
|
1691
|
+
}
|
|
1623
1692
|
function BiometricIcon({ type, size = 80, animate = false }) {
|
|
1624
1693
|
const className = animate ? "volr:animate-pulse" : "";
|
|
1625
1694
|
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
1626
1695
|
type === "faceId" && /* @__PURE__ */ jsx(FaceIdIcon, { size }),
|
|
1627
1696
|
type === "touchId" && /* @__PURE__ */ jsx(TouchIdIcon, { size }),
|
|
1628
|
-
type === "fingerprint" && /* @__PURE__ */ jsx(FingerprintIcon, { size })
|
|
1697
|
+
type === "fingerprint" && /* @__PURE__ */ jsx(FingerprintIcon, { size }),
|
|
1698
|
+
type === "qrCode" && /* @__PURE__ */ jsx(QrCodeIcon, { size })
|
|
1629
1699
|
] });
|
|
1630
1700
|
}
|
|
1631
1701
|
var sizeMap = {
|
|
@@ -1814,6 +1884,84 @@ function PasskeyCompatibilityScreen({
|
|
|
1814
1884
|
] })
|
|
1815
1885
|
] });
|
|
1816
1886
|
}
|
|
1887
|
+
function PasskeyMigrationView({
|
|
1888
|
+
sourcePasskey,
|
|
1889
|
+
currentDomain,
|
|
1890
|
+
onMigrate,
|
|
1891
|
+
onSkip,
|
|
1892
|
+
onError,
|
|
1893
|
+
isOpen = true,
|
|
1894
|
+
wrapInModal = true
|
|
1895
|
+
}) {
|
|
1896
|
+
const { t } = useI18n();
|
|
1897
|
+
const [isMigrating, setIsMigrating] = useState(false);
|
|
1898
|
+
const [error, setError] = useState(null);
|
|
1899
|
+
const biometricType = getBiometricType();
|
|
1900
|
+
const handleMigrate = async () => {
|
|
1901
|
+
try {
|
|
1902
|
+
setIsMigrating(true);
|
|
1903
|
+
setError(null);
|
|
1904
|
+
await onMigrate();
|
|
1905
|
+
} catch (err) {
|
|
1906
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1907
|
+
setError(t("passkey.migration.error"));
|
|
1908
|
+
if (onError) {
|
|
1909
|
+
onError(err instanceof Error ? err : new Error(errorMessage));
|
|
1910
|
+
}
|
|
1911
|
+
} finally {
|
|
1912
|
+
setIsMigrating(false);
|
|
1913
|
+
}
|
|
1914
|
+
};
|
|
1915
|
+
const content = /* @__PURE__ */ jsxs("div", { children: [
|
|
1916
|
+
/* @__PURE__ */ jsx("p", { className: "volr:text-xl volr:font-semibold volr:mb-4", children: t("passkey.migration.title") }),
|
|
1917
|
+
/* @__PURE__ */ jsx("div", { className: "volr:my-6 volr:flex volr:justify-center", children: /* @__PURE__ */ jsx(BiometricIcon, { type: biometricType, size: 48 }) }),
|
|
1918
|
+
/* @__PURE__ */ jsx("p", { className: "volr:text-sm volr:mb-4 volr:text-center volr-text-secondary", children: sourcePasskey.rpId ? t("passkey.migration.description").replace(
|
|
1919
|
+
"{{sourceDomain}}",
|
|
1920
|
+
sourcePasskey.rpId
|
|
1921
|
+
) : t("passkey.migration.descriptionGeneric") }),
|
|
1922
|
+
/* @__PURE__ */ jsxs("div", { className: "volr:mb-4 volr:p-3 volr:rounded-lg volr:border volr:border-slate-200 volr:bg-slate-50", children: [
|
|
1923
|
+
/* @__PURE__ */ jsxs("div", { className: "volr:flex volr:justify-between volr:items-center volr:text-sm volr:mb-2", children: [
|
|
1924
|
+
/* @__PURE__ */ jsx("span", { className: "volr-text-secondary", children: t("passkey.migration.sourceDomain") }),
|
|
1925
|
+
/* @__PURE__ */ jsx("span", { className: "volr:font-mono volr:text-xs", children: sourcePasskey.rpId })
|
|
1926
|
+
] }),
|
|
1927
|
+
/* @__PURE__ */ jsxs("div", { className: "volr:flex volr:justify-between volr:items-center volr:text-sm", children: [
|
|
1928
|
+
/* @__PURE__ */ jsx("span", { className: "volr-text-secondary", children: t("passkey.migration.currentDomain") }),
|
|
1929
|
+
/* @__PURE__ */ jsx("span", { className: "volr:font-mono volr:text-xs", children: currentDomain })
|
|
1930
|
+
] })
|
|
1931
|
+
] }),
|
|
1932
|
+
/* @__PURE__ */ jsx("div", { className: "volr:mb-6 volr:p-3 volr:rounded-lg volr-hint", children: /* @__PURE__ */ jsxs("p", { className: "volr:text-sm volr:flex volr:items-start volr:gap-2", children: [
|
|
1933
|
+
/* @__PURE__ */ jsx("span", { className: "volr:text-base", children: "\u2713" }),
|
|
1934
|
+
/* @__PURE__ */ jsx("span", { children: t("passkey.migration.benefits") })
|
|
1935
|
+
] }) }),
|
|
1936
|
+
error && /* @__PURE__ */ jsx("div", { className: "volr:mb-4 volr:p-3 volr:rounded-lg volr:border volr:text-sm volr:text-left volr-error", children: /* @__PURE__ */ jsx("span", { children: error }) }),
|
|
1937
|
+
/* @__PURE__ */ jsxs("div", { className: "volr:flex volr:flex-col volr:gap-3", children: [
|
|
1938
|
+
/* @__PURE__ */ jsx(
|
|
1939
|
+
Button,
|
|
1940
|
+
{
|
|
1941
|
+
variant: "primary",
|
|
1942
|
+
fullWidth: true,
|
|
1943
|
+
onClick: handleMigrate,
|
|
1944
|
+
disabled: isMigrating,
|
|
1945
|
+
children: isMigrating ? t("passkey.migration.inProgress") : t("passkey.migration.cta")
|
|
1946
|
+
}
|
|
1947
|
+
),
|
|
1948
|
+
onSkip && /* @__PURE__ */ jsx(
|
|
1949
|
+
Button,
|
|
1950
|
+
{
|
|
1951
|
+
variant: "ghost",
|
|
1952
|
+
fullWidth: true,
|
|
1953
|
+
onClick: onSkip,
|
|
1954
|
+
disabled: isMigrating,
|
|
1955
|
+
children: t("passkey.migration.later")
|
|
1956
|
+
}
|
|
1957
|
+
)
|
|
1958
|
+
] })
|
|
1959
|
+
] });
|
|
1960
|
+
if (!wrapInModal) {
|
|
1961
|
+
return content;
|
|
1962
|
+
}
|
|
1963
|
+
return /* @__PURE__ */ jsx(Modal, { open: isOpen, onOpenChange: (open) => !open && onSkip?.(), children: content });
|
|
1964
|
+
}
|
|
1817
1965
|
function PasskeyEnrollView({
|
|
1818
1966
|
onComplete,
|
|
1819
1967
|
onError,
|
|
@@ -1842,14 +1990,34 @@ function PasskeyEnrollView({
|
|
|
1842
1990
|
[compatibility.platform]
|
|
1843
1991
|
);
|
|
1844
1992
|
const hasPasskey = user?.keyStorageType === "passkey";
|
|
1993
|
+
const currentDomain = useMemo(() => {
|
|
1994
|
+
if (typeof window === "undefined") return "localhost";
|
|
1995
|
+
return window.location.hostname;
|
|
1996
|
+
}, []);
|
|
1997
|
+
const migrationInfo = useMemo(() => {
|
|
1998
|
+
if (!user?.registeredPasskeys || user.registeredPasskeys.length === 0) {
|
|
1999
|
+
return { needsMigration: false, sourcePasskey: null };
|
|
2000
|
+
}
|
|
2001
|
+
const hasPasskeyOnCurrentDomain = user.registeredPasskeys.some(
|
|
2002
|
+
(pk) => pk.rpId === currentDomain
|
|
2003
|
+
);
|
|
2004
|
+
if (hasPasskeyOnCurrentDomain) {
|
|
2005
|
+
return { needsMigration: false, sourcePasskey: null };
|
|
2006
|
+
}
|
|
2007
|
+
const sourcePasskey = user.registeredPasskeys[0];
|
|
2008
|
+
return { needsMigration: true, sourcePasskey };
|
|
2009
|
+
}, [user?.registeredPasskeys, currentDomain]);
|
|
1845
2010
|
useEffect(() => {
|
|
1846
2011
|
console.log("[PasskeyEnrollView] User state:", {
|
|
1847
2012
|
user,
|
|
1848
2013
|
keyStorageType: user?.keyStorageType,
|
|
1849
2014
|
evmAddress: user?.evmAddress,
|
|
1850
|
-
hasPasskey
|
|
2015
|
+
hasPasskey,
|
|
2016
|
+
registeredPasskeys: user?.registeredPasskeys,
|
|
2017
|
+
currentDomain,
|
|
2018
|
+
migrationInfo
|
|
1851
2019
|
});
|
|
1852
|
-
}, [user, hasPasskey]);
|
|
2020
|
+
}, [user, hasPasskey, currentDomain, migrationInfo]);
|
|
1853
2021
|
useEffect(() => {
|
|
1854
2022
|
if (hasPasskey && !user?.evmAddress && !isRefreshing) {
|
|
1855
2023
|
const refreshUserData = async () => {
|
|
@@ -1960,13 +2128,16 @@ function PasskeyEnrollView({
|
|
|
1960
2128
|
}
|
|
1961
2129
|
};
|
|
1962
2130
|
const getBiometricTitle = () => {
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
2131
|
+
switch (biometricType) {
|
|
2132
|
+
case "faceId":
|
|
2133
|
+
return t("passkey.titleFaceId");
|
|
2134
|
+
case "touchId":
|
|
2135
|
+
return t("passkey.titleTouchId");
|
|
2136
|
+
case "qrCode":
|
|
2137
|
+
return t("passkey.titleQrCode");
|
|
2138
|
+
default:
|
|
2139
|
+
return t("passkey.titleFingerprint");
|
|
1968
2140
|
}
|
|
1969
|
-
return t("passkey.titleFingerprint");
|
|
1970
2141
|
};
|
|
1971
2142
|
const getBiometricDescription = () => {
|
|
1972
2143
|
return t("passkey.description");
|
|
@@ -1984,6 +2155,23 @@ function PasskeyEnrollView({
|
|
|
1984
2155
|
}
|
|
1985
2156
|
return /* @__PURE__ */ jsx(Modal, { open: isOpen, onOpenChange: (open) => !open && onLogout?.(), children: compatibilityContent });
|
|
1986
2157
|
}
|
|
2158
|
+
if (migrationInfo.needsMigration && migrationInfo.sourcePasskey) {
|
|
2159
|
+
const handleMigration = async () => {
|
|
2160
|
+
await handleEnroll();
|
|
2161
|
+
};
|
|
2162
|
+
return /* @__PURE__ */ jsx(
|
|
2163
|
+
PasskeyMigrationView,
|
|
2164
|
+
{
|
|
2165
|
+
sourcePasskey: migrationInfo.sourcePasskey,
|
|
2166
|
+
currentDomain,
|
|
2167
|
+
onMigrate: handleMigration,
|
|
2168
|
+
onSkip: handleLogout,
|
|
2169
|
+
onError,
|
|
2170
|
+
isOpen,
|
|
2171
|
+
wrapInModal
|
|
2172
|
+
}
|
|
2173
|
+
);
|
|
2174
|
+
}
|
|
1987
2175
|
if (hasPasskey) {
|
|
1988
2176
|
const handleClose = () => {
|
|
1989
2177
|
if (onClose) {
|