@volr/react-ui 0.1.120 → 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 CHANGED
@@ -575,6 +575,19 @@ var en = {
575
575
  windows: "Please use your phone via QR code. (Windows Hello is not supported)",
576
576
  default: "Please use this device's biometric.",
577
577
  note: "Using other devices or apps may not work."
578
+ },
579
+ migration: {
580
+ title: "Set up passkey for this site",
581
+ description: "Your wallet was created on {{sourceDomain}}. To use it here, you need to set up a new passkey for this site.",
582
+ descriptionGeneric: "Your wallet was created on a different site. To use it here, you need to set up a new passkey for this site.",
583
+ currentDomain: "Current site",
584
+ sourceDomain: "Original site",
585
+ benefits: "Your wallet address and balance will remain the same.",
586
+ cta: "Set up passkey",
587
+ later: "Do it later",
588
+ inProgress: "Setting up...",
589
+ success: "Passkey set up successfully!",
590
+ error: "Failed to set up passkey. Please try again."
578
591
  }
579
592
  },
580
593
  success: {
@@ -804,6 +817,19 @@ var ko = {
804
817
  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)",
805
818
  default: "\uC774 \uAE30\uAE30\uC758 \uC0DD\uCCB4 \uC778\uC99D\uC744 \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694.",
806
819
  note: "\uB2E4\uB978 \uAE30\uAE30\uB098 \uC571 \uC0AC\uC6A9 \uC2DC \uB3D9\uC791\uD558\uC9C0 \uC54A\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
820
+ },
821
+ migration: {
822
+ title: "\uC774 \uC0AC\uC774\uD2B8\uC6A9 \uD328\uC2A4\uD0A4 \uC124\uC815",
823
+ 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.",
824
+ 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.",
825
+ currentDomain: "\uD604\uC7AC \uC0AC\uC774\uD2B8",
826
+ sourceDomain: "\uC6D0\uBCF8 \uC0AC\uC774\uD2B8",
827
+ benefits: "\uC9C0\uAC11 \uC8FC\uC18C\uC640 \uC794\uC561\uC740 \uADF8\uB300\uB85C \uC720\uC9C0\uB429\uB2C8\uB2E4.",
828
+ cta: "\uD328\uC2A4\uD0A4 \uC124\uC815\uD558\uAE30",
829
+ later: "\uB098\uC911\uC5D0 \uD558\uAE30",
830
+ inProgress: "\uC124\uC815 \uC911...",
831
+ success: "\uD328\uC2A4\uD0A4 \uC124\uC815\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4!",
832
+ error: "\uD328\uC2A4\uD0A4 \uC124\uC815\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694."
807
833
  }
808
834
  },
809
835
  success: {
@@ -1863,6 +1889,84 @@ function PasskeyCompatibilityScreen({
1863
1889
  ] })
1864
1890
  ] });
1865
1891
  }
1892
+ function PasskeyMigrationView({
1893
+ sourcePasskey,
1894
+ currentDomain,
1895
+ onMigrate,
1896
+ onSkip,
1897
+ onError,
1898
+ isOpen = true,
1899
+ wrapInModal = true
1900
+ }) {
1901
+ const { t } = useI18n();
1902
+ const [isMigrating, setIsMigrating] = React13.useState(false);
1903
+ const [error, setError] = React13.useState(null);
1904
+ const biometricType = getBiometricType();
1905
+ const handleMigrate = async () => {
1906
+ try {
1907
+ setIsMigrating(true);
1908
+ setError(null);
1909
+ await onMigrate();
1910
+ } catch (err) {
1911
+ const errorMessage = err instanceof Error ? err.message : String(err);
1912
+ setError(t("passkey.migration.error"));
1913
+ if (onError) {
1914
+ onError(err instanceof Error ? err : new Error(errorMessage));
1915
+ }
1916
+ } finally {
1917
+ setIsMigrating(false);
1918
+ }
1919
+ };
1920
+ const content = /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1921
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-xl volr:font-semibold volr:mb-4", children: t("passkey.migration.title") }),
1922
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:my-6 volr:flex volr:justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(BiometricIcon, { type: biometricType, size: 48 }) }),
1923
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "volr:text-sm volr:mb-4 volr:text-center volr-text-secondary", children: sourcePasskey.rpId ? t("passkey.migration.description").replace(
1924
+ "{{sourceDomain}}",
1925
+ sourcePasskey.rpId
1926
+ ) : t("passkey.migration.descriptionGeneric") }),
1927
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:mb-4 volr:p-3 volr:rounded-lg volr:border volr:border-slate-200 volr:bg-slate-50", children: [
1928
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:justify-between volr:items-center volr:text-sm volr:mb-2", children: [
1929
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr-text-secondary", children: t("passkey.migration.sourceDomain") }),
1930
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:font-mono volr:text-xs", children: sourcePasskey.rpId })
1931
+ ] }),
1932
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:justify-between volr:items-center volr:text-sm", children: [
1933
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr-text-secondary", children: t("passkey.migration.currentDomain") }),
1934
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:font-mono volr:text-xs", children: currentDomain })
1935
+ ] })
1936
+ ] }),
1937
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:mb-6 volr:p-3 volr:rounded-lg volr-hint", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "volr:text-sm volr:flex volr:items-start volr:gap-2", children: [
1938
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "volr:text-base", children: "\u2713" }),
1939
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("passkey.migration.benefits") })
1940
+ ] }) }),
1941
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "volr:mb-4 volr:p-3 volr:rounded-lg volr:border volr:text-sm volr:text-left volr-error", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: error }) }),
1942
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "volr:flex volr:flex-col volr:gap-3", children: [
1943
+ /* @__PURE__ */ jsxRuntime.jsx(
1944
+ Button,
1945
+ {
1946
+ variant: "primary",
1947
+ fullWidth: true,
1948
+ onClick: handleMigrate,
1949
+ disabled: isMigrating,
1950
+ children: isMigrating ? t("passkey.migration.inProgress") : t("passkey.migration.cta")
1951
+ }
1952
+ ),
1953
+ onSkip && /* @__PURE__ */ jsxRuntime.jsx(
1954
+ Button,
1955
+ {
1956
+ variant: "ghost",
1957
+ fullWidth: true,
1958
+ onClick: onSkip,
1959
+ disabled: isMigrating,
1960
+ children: t("passkey.migration.later")
1961
+ }
1962
+ )
1963
+ ] })
1964
+ ] });
1965
+ if (!wrapInModal) {
1966
+ return content;
1967
+ }
1968
+ return /* @__PURE__ */ jsxRuntime.jsx(Modal, { open: isOpen, onOpenChange: (open) => !open && onSkip?.(), children: content });
1969
+ }
1866
1970
  function PasskeyEnrollView({
1867
1971
  onComplete,
1868
1972
  onError,
@@ -1891,14 +1995,34 @@ function PasskeyEnrollView({
1891
1995
  [compatibility.platform]
1892
1996
  );
1893
1997
  const hasPasskey = user?.keyStorageType === "passkey";
1998
+ const currentDomain = React13.useMemo(() => {
1999
+ if (typeof window === "undefined") return "localhost";
2000
+ return window.location.hostname;
2001
+ }, []);
2002
+ const migrationInfo = React13.useMemo(() => {
2003
+ if (!user?.registeredPasskeys || user.registeredPasskeys.length === 0) {
2004
+ return { needsMigration: false, sourcePasskey: null };
2005
+ }
2006
+ const hasPasskeyOnCurrentDomain = user.registeredPasskeys.some(
2007
+ (pk) => pk.rpId === currentDomain
2008
+ );
2009
+ if (hasPasskeyOnCurrentDomain) {
2010
+ return { needsMigration: false, sourcePasskey: null };
2011
+ }
2012
+ const sourcePasskey = user.registeredPasskeys[0];
2013
+ return { needsMigration: true, sourcePasskey };
2014
+ }, [user?.registeredPasskeys, currentDomain]);
1894
2015
  React13.useEffect(() => {
1895
2016
  console.log("[PasskeyEnrollView] User state:", {
1896
2017
  user,
1897
2018
  keyStorageType: user?.keyStorageType,
1898
2019
  evmAddress: user?.evmAddress,
1899
- hasPasskey
2020
+ hasPasskey,
2021
+ registeredPasskeys: user?.registeredPasskeys,
2022
+ currentDomain,
2023
+ migrationInfo
1900
2024
  });
1901
- }, [user, hasPasskey]);
2025
+ }, [user, hasPasskey, currentDomain, migrationInfo]);
1902
2026
  React13.useEffect(() => {
1903
2027
  if (hasPasskey && !user?.evmAddress && !isRefreshing) {
1904
2028
  const refreshUserData = async () => {
@@ -2036,6 +2160,23 @@ function PasskeyEnrollView({
2036
2160
  }
2037
2161
  return /* @__PURE__ */ jsxRuntime.jsx(Modal, { open: isOpen, onOpenChange: (open) => !open && onLogout?.(), children: compatibilityContent });
2038
2162
  }
2163
+ if (migrationInfo.needsMigration && migrationInfo.sourcePasskey) {
2164
+ const handleMigration = async () => {
2165
+ await handleEnroll();
2166
+ };
2167
+ return /* @__PURE__ */ jsxRuntime.jsx(
2168
+ PasskeyMigrationView,
2169
+ {
2170
+ sourcePasskey: migrationInfo.sourcePasskey,
2171
+ currentDomain,
2172
+ onMigrate: handleMigration,
2173
+ onSkip: handleLogout,
2174
+ onError,
2175
+ isOpen,
2176
+ wrapInModal
2177
+ }
2178
+ );
2179
+ }
2039
2180
  if (hasPasskey) {
2040
2181
  const handleClose = () => {
2041
2182
  if (onClose) {