@volr/react-ui 0.1.124 → 0.1.126
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 +192 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +193 -5
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -2162,7 +2162,12 @@ function PasskeyEnrollView({
|
|
|
2162
2162
|
}
|
|
2163
2163
|
if (migrationInfo.needsMigration && migrationInfo.sourcePasskey) {
|
|
2164
2164
|
const handleMigration = async () => {
|
|
2165
|
-
|
|
2165
|
+
const targetOrigin = typeof window !== "undefined" ? window.location.origin : "";
|
|
2166
|
+
const sourceRpId = migrationInfo.sourcePasskey.rpId;
|
|
2167
|
+
const sourceOrigin = sourceRpId === "localhost" ? "http://localhost" : `https://${sourceRpId}`;
|
|
2168
|
+
const url = new URL(sourceOrigin);
|
|
2169
|
+
url.searchParams.set("volr_migrate_to", targetOrigin);
|
|
2170
|
+
window.open(url.toString(), "_blank", "noopener,noreferrer");
|
|
2166
2171
|
};
|
|
2167
2172
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2168
2173
|
PasskeyMigrationView,
|
|
@@ -5130,6 +5135,8 @@ function AccountModal({ isOpen, onClose, onError }) {
|
|
|
5130
5135
|
const [currentView, setCurrentView] = React13.useState("main");
|
|
5131
5136
|
const [selectedPayment, setSelectedPayment] = React13.useState(null);
|
|
5132
5137
|
const [isLoggingOut, setIsLoggingOut] = React13.useState(false);
|
|
5138
|
+
const prevUserRef = React13.useRef(user ?? null);
|
|
5139
|
+
const [closingAfterLogin, setClosingAfterLogin] = React13.useState(false);
|
|
5133
5140
|
const [depositAssets, setDepositAssets] = React13.useState([]);
|
|
5134
5141
|
const [depositLoading, setDepositLoading] = React13.useState(false);
|
|
5135
5142
|
const [depositError, setDepositError] = React13.useState(null);
|
|
@@ -5160,6 +5167,29 @@ function AccountModal({ isOpen, onClose, onError }) {
|
|
|
5160
5167
|
}, 200);
|
|
5161
5168
|
}
|
|
5162
5169
|
}, [onClose]);
|
|
5170
|
+
React13.useEffect(() => {
|
|
5171
|
+
if (!isOpen) {
|
|
5172
|
+
setClosingAfterLogin(false);
|
|
5173
|
+
prevUserRef.current = user ?? null;
|
|
5174
|
+
return;
|
|
5175
|
+
}
|
|
5176
|
+
const wasLoggedOut = prevUserRef.current == null;
|
|
5177
|
+
const isNowLoggedIn = user != null;
|
|
5178
|
+
if (wasLoggedOut && isNowLoggedIn) {
|
|
5179
|
+
setClosingAfterLogin(true);
|
|
5180
|
+
setTimeout(() => {
|
|
5181
|
+
onClose();
|
|
5182
|
+
}, 0);
|
|
5183
|
+
}
|
|
5184
|
+
prevUserRef.current = user ?? null;
|
|
5185
|
+
}, [isOpen, user, onClose]);
|
|
5186
|
+
if (closingAfterLogin && isOpen) {
|
|
5187
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { open: isOpen, onOpenChange: handleOpenChange, children: [
|
|
5188
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalHeader, { onClose: () => {
|
|
5189
|
+
} }),
|
|
5190
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:text-center volr:py-8", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-sm volr-text-secondary", children: "Completing login..." }) })
|
|
5191
|
+
] });
|
|
5192
|
+
}
|
|
5163
5193
|
if (!user) {
|
|
5164
5194
|
return /* @__PURE__ */ jsxRuntime.jsx(SigninModal, { isOpen, onClose, onError });
|
|
5165
5195
|
}
|
|
@@ -6637,6 +6667,17 @@ function SignRequestModal({ open, onOpenChange }) {
|
|
|
6637
6667
|
);
|
|
6638
6668
|
}
|
|
6639
6669
|
var VolrUIContext = React13__default.default.createContext(null);
|
|
6670
|
+
function getCurrentRpId() {
|
|
6671
|
+
if (typeof window === "undefined") return "localhost";
|
|
6672
|
+
return window.location.hostname;
|
|
6673
|
+
}
|
|
6674
|
+
function isPasskeyDomainMismatch(user) {
|
|
6675
|
+
const currentRpId = getCurrentRpId();
|
|
6676
|
+
const registered = user?.registeredPasskeys;
|
|
6677
|
+
if (user?.keyStorageType !== "passkey") return false;
|
|
6678
|
+
if (!Array.isArray(registered) || registered.length === 0) return false;
|
|
6679
|
+
return !registered.some((p) => p?.rpId === currentRpId);
|
|
6680
|
+
}
|
|
6640
6681
|
var useVolrUI = () => {
|
|
6641
6682
|
const context = React13.useContext(VolrUIContext);
|
|
6642
6683
|
if (!context) {
|
|
@@ -6767,6 +6808,13 @@ function VolrUIProviderInner({
|
|
|
6767
6808
|
keyStorageType
|
|
6768
6809
|
},
|
|
6769
6810
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VolrModalProvider, { children: [
|
|
6811
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6812
|
+
MigrationCoordinator,
|
|
6813
|
+
{
|
|
6814
|
+
onShowOnboarding: () => setShowOnboarding(true),
|
|
6815
|
+
onHideOnboarding: () => setShowOnboarding(false)
|
|
6816
|
+
}
|
|
6817
|
+
),
|
|
6770
6818
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6771
6819
|
OAuthCallbackHandler,
|
|
6772
6820
|
{
|
|
@@ -6809,6 +6857,130 @@ function VolrUIProviderInner({
|
|
|
6809
6857
|
}
|
|
6810
6858
|
) }) });
|
|
6811
6859
|
}
|
|
6860
|
+
function normalizeOrigin(input) {
|
|
6861
|
+
try {
|
|
6862
|
+
const u = new URL(input);
|
|
6863
|
+
return `${u.protocol}//${u.host}`;
|
|
6864
|
+
} catch {
|
|
6865
|
+
return input;
|
|
6866
|
+
}
|
|
6867
|
+
}
|
|
6868
|
+
function MigrationCoordinator({
|
|
6869
|
+
onShowOnboarding,
|
|
6870
|
+
onHideOnboarding
|
|
6871
|
+
}) {
|
|
6872
|
+
const { user, setUser } = react.useVolrContext();
|
|
6873
|
+
const { client } = react.useInternalAuth();
|
|
6874
|
+
const [running, setRunning] = React13.useState(false);
|
|
6875
|
+
React13.useEffect(() => {
|
|
6876
|
+
if (typeof window === "undefined") return;
|
|
6877
|
+
const handler = (event) => {
|
|
6878
|
+
const data = event.data;
|
|
6879
|
+
if (data?.type === "VOLR_MIGRATION_DONE") {
|
|
6880
|
+
client.refreshSession().then((u) => u && setUser(u)).catch(() => void 0);
|
|
6881
|
+
onHideOnboarding();
|
|
6882
|
+
}
|
|
6883
|
+
};
|
|
6884
|
+
window.addEventListener("message", handler);
|
|
6885
|
+
return () => window.removeEventListener("message", handler);
|
|
6886
|
+
}, [client, setUser, onHideOnboarding]);
|
|
6887
|
+
React13.useEffect(() => {
|
|
6888
|
+
if (typeof window === "undefined") return;
|
|
6889
|
+
if (running) return;
|
|
6890
|
+
const params = new URLSearchParams(window.location.search);
|
|
6891
|
+
const migrationToken = params.get("migration_token");
|
|
6892
|
+
const sourceOriginParam = params.get("source_origin");
|
|
6893
|
+
const isTargetPopup = Boolean(migrationToken && sourceOriginParam);
|
|
6894
|
+
const migrateTo = params.get("volr_migrate_to");
|
|
6895
|
+
const isSourceFlow = Boolean(migrateTo);
|
|
6896
|
+
if (!isTargetPopup && !isSourceFlow) {
|
|
6897
|
+
return;
|
|
6898
|
+
}
|
|
6899
|
+
const run = async () => {
|
|
6900
|
+
setRunning(true);
|
|
6901
|
+
try {
|
|
6902
|
+
if (isTargetPopup) {
|
|
6903
|
+
const sourceOrigin2 = normalizeOrigin(sourceOriginParam);
|
|
6904
|
+
const token2 = migrationToken;
|
|
6905
|
+
const refreshedUser2 = await client.refreshSession();
|
|
6906
|
+
const effectiveUser2 = refreshedUser2 ?? user;
|
|
6907
|
+
if (refreshedUser2) setUser(refreshedUser2);
|
|
6908
|
+
if (!effectiveUser2?.id || !effectiveUser2?.projectId) {
|
|
6909
|
+
throw new Error(
|
|
6910
|
+
"Migration requires an active session on the target site. Please log in first."
|
|
6911
|
+
);
|
|
6912
|
+
}
|
|
6913
|
+
const { requestSeedFromOpener } = await import('@volr/react');
|
|
6914
|
+
const seed = await requestSeedFromOpener(sourceOrigin2, token2);
|
|
6915
|
+
await react.completeMigration({
|
|
6916
|
+
client,
|
|
6917
|
+
userId: seed.userId,
|
|
6918
|
+
projectId: seed.projectId,
|
|
6919
|
+
migrationToken: token2,
|
|
6920
|
+
masterSeed: seed.masterSeed,
|
|
6921
|
+
rpName: effectiveUser2.projectName ?? "Volr",
|
|
6922
|
+
userEmail: effectiveUser2.email ?? null
|
|
6923
|
+
});
|
|
6924
|
+
try {
|
|
6925
|
+
window.opener?.postMessage({ type: "VOLR_MIGRATION_DONE" }, "*");
|
|
6926
|
+
} catch {
|
|
6927
|
+
}
|
|
6928
|
+
window.close();
|
|
6929
|
+
return;
|
|
6930
|
+
}
|
|
6931
|
+
const targetOrigin = normalizeOrigin(migrateTo);
|
|
6932
|
+
const sourceOrigin = window.location.origin;
|
|
6933
|
+
const refreshedUser = await client.refreshSession();
|
|
6934
|
+
const effectiveUser = refreshedUser ?? user;
|
|
6935
|
+
if (refreshedUser) setUser(refreshedUser);
|
|
6936
|
+
if (!effectiveUser?.id || !effectiveUser?.projectId) {
|
|
6937
|
+
throw new Error(
|
|
6938
|
+
"Migration requires an active session on the source site. Please log in first."
|
|
6939
|
+
);
|
|
6940
|
+
}
|
|
6941
|
+
const currentRpId = getCurrentRpId();
|
|
6942
|
+
const sourcePasskey = effectiveUser.registeredPasskeys?.find((p) => p?.rpId === currentRpId) ?? null;
|
|
6943
|
+
if (!sourcePasskey?.credentialId || !sourcePasskey?.blobUrl || !sourcePasskey?.prfInput) {
|
|
6944
|
+
throw new Error(
|
|
6945
|
+
`No passkey registered for source rpId=${currentRpId}. Cannot migrate from this site.`
|
|
6946
|
+
);
|
|
6947
|
+
}
|
|
6948
|
+
const token = await react.requestMigration({ client, targetOrigin });
|
|
6949
|
+
const entropy = await react.decryptEntropyForMigration({
|
|
6950
|
+
client,
|
|
6951
|
+
userId: effectiveUser.id,
|
|
6952
|
+
blobUrl: sourcePasskey.blobUrl,
|
|
6953
|
+
prfInput: sourcePasskey.prfInput,
|
|
6954
|
+
credentialId: sourcePasskey.credentialId,
|
|
6955
|
+
rpName: effectiveUser.projectName ?? "Volr"
|
|
6956
|
+
});
|
|
6957
|
+
const cleanup = react.listenForSeedRequests(
|
|
6958
|
+
[targetOrigin],
|
|
6959
|
+
async () => entropy,
|
|
6960
|
+
() => ({ userId: effectiveUser.id, projectId: effectiveUser.projectId })
|
|
6961
|
+
);
|
|
6962
|
+
const url = new URL(targetOrigin);
|
|
6963
|
+
url.searchParams.set("migration_token", token.migrationToken);
|
|
6964
|
+
url.searchParams.set("source_origin", sourceOrigin);
|
|
6965
|
+
window.open(
|
|
6966
|
+
url.toString(),
|
|
6967
|
+
"volr_migration",
|
|
6968
|
+
"width=500,height=650,left=100,top=100,popup=1"
|
|
6969
|
+
);
|
|
6970
|
+
onShowOnboarding();
|
|
6971
|
+
setTimeout(() => cleanup(), 2 * 60 * 1e3);
|
|
6972
|
+
return;
|
|
6973
|
+
} finally {
|
|
6974
|
+
setRunning(false);
|
|
6975
|
+
}
|
|
6976
|
+
};
|
|
6977
|
+
run().catch((e) => {
|
|
6978
|
+
console.error("[MigrationCoordinator] failed:", e);
|
|
6979
|
+
setRunning(false);
|
|
6980
|
+
});
|
|
6981
|
+
}, [client, user, setUser, running, onShowOnboarding, onHideOnboarding]);
|
|
6982
|
+
return null;
|
|
6983
|
+
}
|
|
6812
6984
|
function AccountModalPortal() {
|
|
6813
6985
|
const { isOpen, mode, close } = useVolrModal();
|
|
6814
6986
|
const [portalRoot, setPortalRoot] = React13.useState(null);
|
|
@@ -7038,6 +7210,7 @@ function OnboardingChecker({
|
|
|
7038
7210
|
const { user, provider, isLoading } = react.useVolrContext();
|
|
7039
7211
|
const { isOpen: isModalOpen } = useVolrModal();
|
|
7040
7212
|
const modalWasOpened = React13__default.default.useRef(false);
|
|
7213
|
+
const pendingMismatchOnboarding = React13__default.default.useRef(false);
|
|
7041
7214
|
React13.useEffect(() => {
|
|
7042
7215
|
if (isModalOpen) {
|
|
7043
7216
|
modalWasOpened.current = true;
|
|
@@ -7047,15 +7220,21 @@ function OnboardingChecker({
|
|
|
7047
7220
|
if (isLoading) {
|
|
7048
7221
|
return;
|
|
7049
7222
|
}
|
|
7223
|
+
const passkeyDomainMismatch = isPasskeyDomainMismatch(user);
|
|
7050
7224
|
if (isModalOpen) {
|
|
7225
|
+
if (passkeyDomainMismatch) {
|
|
7226
|
+
pendingMismatchOnboarding.current = true;
|
|
7227
|
+
}
|
|
7051
7228
|
onHideOnboarding();
|
|
7052
7229
|
return;
|
|
7053
7230
|
}
|
|
7054
7231
|
if (modalWasOpened.current) {
|
|
7055
|
-
|
|
7056
|
-
|
|
7232
|
+
if (!passkeyDomainMismatch && !pendingMismatchOnboarding.current) {
|
|
7233
|
+
onHideOnboarding();
|
|
7234
|
+
return;
|
|
7235
|
+
}
|
|
7057
7236
|
}
|
|
7058
|
-
if (user?.keyStorageType) {
|
|
7237
|
+
if (user?.keyStorageType && !passkeyDomainMismatch && !pendingMismatchOnboarding.current) {
|
|
7059
7238
|
onHideOnboarding();
|
|
7060
7239
|
return;
|
|
7061
7240
|
}
|
|
@@ -7063,6 +7242,15 @@ function OnboardingChecker({
|
|
|
7063
7242
|
onHideOnboarding();
|
|
7064
7243
|
return;
|
|
7065
7244
|
}
|
|
7245
|
+
if (pendingMismatchOnboarding.current) {
|
|
7246
|
+
pendingMismatchOnboarding.current = false;
|
|
7247
|
+
onShowOnboarding();
|
|
7248
|
+
return;
|
|
7249
|
+
}
|
|
7250
|
+
if (passkeyDomainMismatch) {
|
|
7251
|
+
onShowOnboarding();
|
|
7252
|
+
return;
|
|
7253
|
+
}
|
|
7066
7254
|
if (user && enforceSelection) {
|
|
7067
7255
|
if (!keyStorageType) {
|
|
7068
7256
|
console.error(
|