@embarkai/ui-kit 0.4.11 → 0.4.13

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.
@@ -15,7 +15,7 @@
15
15
  <meta http-equiv="X-Content-Type-Options" content="nosniff" />
16
16
  <meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin" />
17
17
 
18
- <title>EmbarkAI Secure Wallet - iframe version 0.4.11</title>
18
+ <title>EmbarkAI Secure Wallet - iframe version 0.4.13</title>
19
19
 
20
20
  <!-- Styles will be injected by build process -->
21
21
  <style>
@@ -6262,7 +6262,7 @@ var SigningManager = class extends TokenRefreshApiClient {
6262
6262
  };
6263
6263
 
6264
6264
  // src/iframe/main.ts
6265
- var IFRAME_VERSION = "0.4.11";
6265
+ var IFRAME_VERSION = "0.4.13";
6266
6266
  var IframeWallet = class {
6267
6267
  constructor() {
6268
6268
  console.log("=".repeat(60));
package/dist/index.cjs CHANGED
@@ -5281,7 +5281,7 @@ var init_OtpIcon = __esm({
5281
5281
  });
5282
5282
 
5283
5283
  // src/internal/components/AuthMenu/VerifyStep/VerificationCodeInput.tsx
5284
- var import_react16, import_jsx_runtime15, VerificationCodeInput;
5284
+ var import_react16, import_jsx_runtime15, getRemainingSeconds, VerificationCodeInput;
5285
5285
  var init_VerificationCodeInput = __esm({
5286
5286
  "src/internal/components/AuthMenu/VerifyStep/VerificationCodeInput.tsx"() {
5287
5287
  init_i18n();
@@ -5290,16 +5290,39 @@ var init_VerificationCodeInput = __esm({
5290
5290
  init_button();
5291
5291
  init_useAuthStore();
5292
5292
  import_jsx_runtime15 = require("react/jsx-runtime");
5293
+ getRemainingSeconds = (expiresAt) => Math.max(0, Math.ceil((expiresAt - Date.now()) / 1e3));
5293
5294
  VerificationCodeInput = (props) => {
5294
5295
  const { onVerifyCode, onResendCode, isLoading, expiresIn } = props;
5295
5296
  const { t } = useT();
5296
5297
  const setAlert = useAuthStore((st) => st.setAlert);
5297
- const [timeLeft, setTimeLeft] = (0, import_react16.useState)(expiresIn);
5298
+ const [expiresAt, setExpiresAt] = (0, import_react16.useState)(() => Date.now() + Math.max(0, expiresIn) * 1e3);
5299
+ const [timeLeft, setTimeLeft] = (0, import_react16.useState)(() => getRemainingSeconds(expiresAt));
5298
5300
  (0, import_react16.useEffect)(() => {
5299
- if (timeLeft <= 0) return;
5300
- const t2 = setTimeout(() => setTimeLeft((s) => s - 1), 1e3);
5301
- return () => clearTimeout(t2);
5302
- }, [timeLeft]);
5301
+ const nextExpiresAt = Date.now() + Math.max(0, expiresIn) * 1e3;
5302
+ setExpiresAt(nextExpiresAt);
5303
+ setTimeLeft(getRemainingSeconds(nextExpiresAt));
5304
+ }, [expiresIn]);
5305
+ (0, import_react16.useEffect)(() => {
5306
+ let intervalId;
5307
+ const syncTimeLeft = () => {
5308
+ const remaining = getRemainingSeconds(expiresAt);
5309
+ setTimeLeft(remaining);
5310
+ if (remaining <= 0 && intervalId) {
5311
+ window.clearInterval(intervalId);
5312
+ intervalId = void 0;
5313
+ }
5314
+ };
5315
+ syncTimeLeft();
5316
+ if (getRemainingSeconds(expiresAt) <= 0) return;
5317
+ intervalId = window.setInterval(syncTimeLeft, 1e3);
5318
+ window.addEventListener("focus", syncTimeLeft);
5319
+ document.addEventListener("visibilitychange", syncTimeLeft);
5320
+ return () => {
5321
+ if (intervalId) window.clearInterval(intervalId);
5322
+ window.removeEventListener("focus", syncTimeLeft);
5323
+ document.removeEventListener("visibilitychange", syncTimeLeft);
5324
+ };
5325
+ }, [expiresAt]);
5303
5326
  const lastSubmittedRef = (0, import_react16.useRef)(null);
5304
5327
  const inputsRef = (0, import_react16.useRef)([]);
5305
5328
  const [digits, setDigits] = (0, import_react16.useState)(["", "", "", "", "", ""]);
@@ -5480,14 +5503,17 @@ function VerifyStep(props) {
5480
5503
  },
5481
5504
  onError: (error) => {
5482
5505
  let errorMessage = "";
5483
- if (error.message?.includes("Invalid") || error.message?.includes("invalid")) {
5506
+ const rawErrorMessage = error.message || "";
5507
+ const normalizedErrorMessage = rawErrorMessage.toLowerCase();
5508
+ if (normalizedErrorMessage.includes("invalid")) {
5484
5509
  errorMessage = "Invalid verification code. Please try again.";
5485
- } else if (error.message?.includes("expired")) {
5510
+ } else if (normalizedErrorMessage.includes("expired")) {
5486
5511
  errorMessage = "Verification code expired. Please request a new one.";
5487
- } else if (error.message?.includes("429") || error.message?.includes("Too many")) {
5512
+ setExpiresIn(0);
5513
+ } else if (normalizedErrorMessage.includes("429") || normalizedErrorMessage.includes("too many")) {
5488
5514
  errorMessage = "Too many attempts. Please try again later.";
5489
5515
  } else {
5490
- errorMessage = error.message || "Verification failed. Please try again.";
5516
+ errorMessage = rawErrorMessage || "Verification failed. Please try again.";
5491
5517
  }
5492
5518
  setAlert({
5493
5519
  title: "Verification failed",
@@ -13716,7 +13742,17 @@ function useVerifyCode() {
13716
13742
  const qc = (0, import_react_query30.useQueryClient)();
13717
13743
  const address = useSession((st) => st.address);
13718
13744
  const setIsLoading = useSession((st) => st.setIsLoading);
13719
- const { email, emailCode, setEmail, setEmailStep, setEmailCode, setProviderType, setLinkIsLoading, setAlert } = useManageWalletStore();
13745
+ const {
13746
+ email,
13747
+ emailCode,
13748
+ setEmail,
13749
+ setEmailStep,
13750
+ setEmailCode,
13751
+ setEmailCodeExpiresIn,
13752
+ setProviderType,
13753
+ setLinkIsLoading,
13754
+ setAlert
13755
+ } = useManageWalletStore();
13720
13756
  return (0, import_react_query30.useMutation)({
13721
13757
  mutationFn: async (codeToVerify) => {
13722
13758
  const code = codeToVerify ?? emailCode;
@@ -13745,7 +13781,11 @@ function useVerifyCode() {
13745
13781
  setLinkIsLoading(false);
13746
13782
  },
13747
13783
  onError: (error) => {
13748
- setAlert({ title: "Error", message: error?.message || "Failed to verify and link email" });
13784
+ const message = error?.message || "Failed to verify and link email";
13785
+ if (message.toLowerCase().includes("expired")) {
13786
+ setEmailCodeExpiresIn(0);
13787
+ }
13788
+ setAlert({ title: "Error", message });
13749
13789
  setIsLoading(false);
13750
13790
  setLinkIsLoading(false);
13751
13791
  }
@@ -15822,11 +15862,20 @@ function useConnectedApps() {
15822
15862
  enabled: !!userId,
15823
15863
  queryKey: [CONNECTED_TRUSTED_APPS_QUERY, userId],
15824
15864
  queryFn: async () => {
15865
+ const response = await tssClient.get("/api/auth/connected-apps", true);
15866
+ if (!response.success || !response.data) {
15867
+ const error = response.error || "Failed to fetch connected apps";
15868
+ throw new Error(error);
15869
+ }
15825
15870
  const iframeManager = getIframeManager();
15826
- return await iframeManager.getTrustedApps(userId).catch(() => {
15827
- console.error("[ConnectedApps] Failed to load connected apps from iframe");
15871
+ const trustedApps = await iframeManager.getTrustedApps(userId).catch(() => {
15872
+ console.error("[ConnectedApps] Failed to load trusted apps from iframe");
15828
15873
  return [];
15829
15874
  });
15875
+ return response.data.apps.map((app) => ({
15876
+ ...app,
15877
+ trustedMeta: trustedApps.find((ta) => ta.projectId === app.projectId) || null
15878
+ }));
15830
15879
  }
15831
15880
  });
15832
15881
  }
@@ -15856,6 +15905,7 @@ var init_hooks2 = __esm({
15856
15905
  init_SessionContext();
15857
15906
  import_react_query42 = require("@tanstack/react-query");
15858
15907
  init_keyshare();
15908
+ init_httpClient();
15859
15909
  init_iframe_manager();
15860
15910
  init_vaultClient();
15861
15911
  init_constants6();
@@ -15864,9 +15914,16 @@ var init_hooks2 = __esm({
15864
15914
 
15865
15915
  // src/internal/components/SecurityMenu/ConnectedApps.tsx
15866
15916
  function Application(props) {
15867
- const { appLogo, appName, origin, trustedAt, untrustApp } = props;
15917
+ const {
15918
+ logo,
15919
+ name,
15920
+ // domains,
15921
+ firstConnectedAt,
15922
+ trustedMeta,
15923
+ untrustApp
15924
+ } = props;
15868
15925
  const { t } = useT();
15869
- const isAppTrusted = trustedAt && (0, import_dayjs5.default)(trustedAt).isValid() && (0, import_dayjs5.default)(trustedAt).isBefore((0, import_dayjs5.default)());
15926
+ const resolvedLogo = logo || trustedMeta?.appLogo || null;
15870
15927
  return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
15871
15928
  "div",
15872
15929
  {
@@ -15885,8 +15942,8 @@ function Application(props) {
15885
15942
  "rounded-[var(--ui-kit-el-bdrs)] bg-[var(--ui-kit-bg)]"
15886
15943
  ),
15887
15944
  children: [
15888
- appLogo ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "w-full h-full p-1", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("img", { src: appLogo, alt: appName, className: "w-full h-full object-contain" }) }) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react52.AppWindowMac, { className: "w-6 h-6 text-[var(--ui-kit-fg)]" }),
15889
- isAppTrusted && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
15945
+ resolvedLogo ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "w-full h-full p-1", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("img", { src: resolvedLogo, alt: name, className: "w-full h-full object-contain" }) }) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react52.AppWindowMac, { className: "w-6 h-6 text-[var(--ui-kit-fg)]" }),
15946
+ !!trustedMeta && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
15890
15947
  "div",
15891
15948
  {
15892
15949
  className: cn(
@@ -15900,21 +15957,26 @@ function Application(props) {
15900
15957
  }
15901
15958
  ),
15902
15959
  /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex-1 min-w-0", children: [
15903
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "font-semibold truncate", children: appName || new URL(origin).hostname }),
15904
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-[var(--ui-kit-fg-muted)] truncate", children: new URL(origin).hostname }),
15905
- isAppTrusted ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-[var(--ui-kit-fg)] truncate", children: t("passport:securityMenu.connectedApps.trustedAt", {
15906
- time: (0, import_dayjs5.default)(trustedAt).format("MMM D, YYYY HH:mm")
15960
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "font-semibold truncate", children: name }),
15961
+ trustedMeta?.origin && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-[var(--ui-kit-fg-muted)] truncate", children: new URL(trustedMeta.origin).hostname }),
15962
+ !!trustedMeta ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-[var(--ui-kit-fg)] truncate", children: t("passport:securityMenu.connectedApps.trustedAt", {
15963
+ time: (0, import_dayjs5.default)(trustedMeta.trustedAt).format("MMM D, YYYY HH:mm")
15907
15964
  }) }) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-[var(--ui-kit-fg-muted)] truncate", children: t("passport:securityMenu.connectedApps.connectedAt", {
15908
- time: (0, import_dayjs5.default)(trustedAt).format("MMM D, YYYY HH:mm")
15965
+ time: (0, import_dayjs5.default)(firstConnectedAt).format("MMM D, YYYY HH:mm")
15909
15966
  }) })
15910
15967
  ] }),
15911
- isAppTrusted && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
15968
+ !!trustedMeta && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
15912
15969
  Button,
15913
15970
  {
15914
15971
  variant: "outline",
15915
15972
  size: "icon",
15916
15973
  className: "text-[var(--ui-kit-bg-error)] flex-none rounded-[var(--ui-kit-el-bdrs)]",
15917
- onClick: () => untrustApp({ ...(0, import_lodash_es7.omit)(props, "untrustApp"), hostname: new URL(origin).hostname }),
15974
+ onClick: () => {
15975
+ untrustApp({
15976
+ ...(0, import_lodash_es7.omit)(props, "untrustApp"),
15977
+ hostname: new URL(trustedMeta.origin).hostname
15978
+ });
15979
+ },
15918
15980
  children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react52.ShieldBanIcon, { className: "h-4 w-4" })
15919
15981
  }
15920
15982
  )
@@ -15934,13 +15996,7 @@ function ConnectedApps(props) {
15934
15996
  /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { children: t("passport:securityMenu.connectedApps.noConnectedApps") })
15935
15997
  ] });
15936
15998
  return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
15937
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "font-medium text-xs text-[var(--ui-kit-fg)]", children: [
15938
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { children: t("passport:securityMenu.connectedApps.connectedApps") }),
15939
- connectedApps.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { children: [
15940
- " ",
15941
- connectedApps.length
15942
- ] })
15943
- ] }),
15999
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "font-medium text-xs text-[var(--ui-kit-fg)]", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { children: t("passport:securityMenu.connectedApps.connectedApps") }) }),
15944
16000
  /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "w-full flex flex-col gap-[var(--ui-kit-gap)]", children: connectedApps.map((app, index) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Application, { ...app, untrustApp }, index)) })
15945
16001
  ] });
15946
16002
  }
@@ -19240,7 +19296,7 @@ var init_package = __esm({
19240
19296
  "package.json"() {
19241
19297
  package_default = {
19242
19298
  name: "@embarkai/ui-kit",
19243
- version: "0.4.11",
19299
+ version: "0.4.13",
19244
19300
  description: "React UI components and hooks for EmbarkAI authentication and Account Abstraction",
19245
19301
  type: "module",
19246
19302
  main: "./dist/index.cjs",
package/dist/index.d.cts CHANGED
@@ -1802,13 +1802,16 @@ declare function getUserProfile(): Promise<UserProfile>;
1802
1802
  */
1803
1803
  declare function updateUserProfile(updates: UpdateProfileRequest): Promise<UserProfile>;
1804
1804
 
1805
- declare function useConnectedApps(): _tanstack_react_query.UseQueryResult<any[] | {
1806
- userId: string;
1805
+ declare function useConnectedApps(): _tanstack_react_query.UseQueryResult<{
1806
+ trustedMeta: any;
1807
1807
  projectId: string;
1808
- origin: string;
1809
- trustedAt: number;
1810
- appName?: string;
1811
- appLogo?: string;
1808
+ name: string;
1809
+ logo: string;
1810
+ domains: unknown;
1811
+ providers: unknown;
1812
+ smartWalletAddress: string;
1813
+ firstConnectedAt: string;
1814
+ lastActiveAt: string;
1812
1815
  }[], Error>;
1813
1816
  declare function useKeyshareRecoveryStats(): _tanstack_react_query.UseQueryResult<{
1814
1817
  keyshareInfo: {
package/dist/index.d.ts CHANGED
@@ -1802,13 +1802,16 @@ declare function getUserProfile(): Promise<UserProfile>;
1802
1802
  */
1803
1803
  declare function updateUserProfile(updates: UpdateProfileRequest): Promise<UserProfile>;
1804
1804
 
1805
- declare function useConnectedApps(): _tanstack_react_query.UseQueryResult<any[] | {
1806
- userId: string;
1805
+ declare function useConnectedApps(): _tanstack_react_query.UseQueryResult<{
1806
+ trustedMeta: any;
1807
1807
  projectId: string;
1808
- origin: string;
1809
- trustedAt: number;
1810
- appName?: string;
1811
- appLogo?: string;
1808
+ name: string;
1809
+ logo: string;
1810
+ domains: unknown;
1811
+ providers: unknown;
1812
+ smartWalletAddress: string;
1813
+ firstConnectedAt: string;
1814
+ lastActiveAt: string;
1812
1815
  }[], Error>;
1813
1816
  declare function useKeyshareRecoveryStats(): _tanstack_react_query.UseQueryResult<{
1814
1817
  keyshareInfo: {
package/dist/index.js CHANGED
@@ -5262,23 +5262,46 @@ var init_OtpIcon = __esm({
5262
5262
  // src/internal/components/AuthMenu/VerifyStep/VerificationCodeInput.tsx
5263
5263
  import { useEffect as useEffect9, useRef as useRef7, useState as useState3 } from "react";
5264
5264
  import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
5265
- var VerificationCodeInput;
5265
+ var getRemainingSeconds, VerificationCodeInput;
5266
5266
  var init_VerificationCodeInput = __esm({
5267
5267
  "src/internal/components/AuthMenu/VerifyStep/VerificationCodeInput.tsx"() {
5268
5268
  init_i18n();
5269
5269
  init_utils2();
5270
5270
  init_button();
5271
5271
  init_useAuthStore();
5272
+ getRemainingSeconds = (expiresAt) => Math.max(0, Math.ceil((expiresAt - Date.now()) / 1e3));
5272
5273
  VerificationCodeInput = (props) => {
5273
5274
  const { onVerifyCode, onResendCode, isLoading, expiresIn } = props;
5274
5275
  const { t } = useT();
5275
5276
  const setAlert = useAuthStore((st) => st.setAlert);
5276
- const [timeLeft, setTimeLeft] = useState3(expiresIn);
5277
+ const [expiresAt, setExpiresAt] = useState3(() => Date.now() + Math.max(0, expiresIn) * 1e3);
5278
+ const [timeLeft, setTimeLeft] = useState3(() => getRemainingSeconds(expiresAt));
5277
5279
  useEffect9(() => {
5278
- if (timeLeft <= 0) return;
5279
- const t2 = setTimeout(() => setTimeLeft((s) => s - 1), 1e3);
5280
- return () => clearTimeout(t2);
5281
- }, [timeLeft]);
5280
+ const nextExpiresAt = Date.now() + Math.max(0, expiresIn) * 1e3;
5281
+ setExpiresAt(nextExpiresAt);
5282
+ setTimeLeft(getRemainingSeconds(nextExpiresAt));
5283
+ }, [expiresIn]);
5284
+ useEffect9(() => {
5285
+ let intervalId;
5286
+ const syncTimeLeft = () => {
5287
+ const remaining = getRemainingSeconds(expiresAt);
5288
+ setTimeLeft(remaining);
5289
+ if (remaining <= 0 && intervalId) {
5290
+ window.clearInterval(intervalId);
5291
+ intervalId = void 0;
5292
+ }
5293
+ };
5294
+ syncTimeLeft();
5295
+ if (getRemainingSeconds(expiresAt) <= 0) return;
5296
+ intervalId = window.setInterval(syncTimeLeft, 1e3);
5297
+ window.addEventListener("focus", syncTimeLeft);
5298
+ document.addEventListener("visibilitychange", syncTimeLeft);
5299
+ return () => {
5300
+ if (intervalId) window.clearInterval(intervalId);
5301
+ window.removeEventListener("focus", syncTimeLeft);
5302
+ document.removeEventListener("visibilitychange", syncTimeLeft);
5303
+ };
5304
+ }, [expiresAt]);
5282
5305
  const lastSubmittedRef = useRef7(null);
5283
5306
  const inputsRef = useRef7([]);
5284
5307
  const [digits, setDigits] = useState3(["", "", "", "", "", ""]);
@@ -5463,14 +5486,17 @@ function VerifyStep(props) {
5463
5486
  },
5464
5487
  onError: (error) => {
5465
5488
  let errorMessage = "";
5466
- if (error.message?.includes("Invalid") || error.message?.includes("invalid")) {
5489
+ const rawErrorMessage = error.message || "";
5490
+ const normalizedErrorMessage = rawErrorMessage.toLowerCase();
5491
+ if (normalizedErrorMessage.includes("invalid")) {
5467
5492
  errorMessage = "Invalid verification code. Please try again.";
5468
- } else if (error.message?.includes("expired")) {
5493
+ } else if (normalizedErrorMessage.includes("expired")) {
5469
5494
  errorMessage = "Verification code expired. Please request a new one.";
5470
- } else if (error.message?.includes("429") || error.message?.includes("Too many")) {
5495
+ setExpiresIn(0);
5496
+ } else if (normalizedErrorMessage.includes("429") || normalizedErrorMessage.includes("too many")) {
5471
5497
  errorMessage = "Too many attempts. Please try again later.";
5472
5498
  } else {
5473
- errorMessage = error.message || "Verification failed. Please try again.";
5499
+ errorMessage = rawErrorMessage || "Verification failed. Please try again.";
5474
5500
  }
5475
5501
  setAlert({
5476
5502
  title: "Verification failed",
@@ -13660,7 +13686,17 @@ function useVerifyCode() {
13660
13686
  const qc = useQueryClient14();
13661
13687
  const address = useSession((st) => st.address);
13662
13688
  const setIsLoading = useSession((st) => st.setIsLoading);
13663
- const { email, emailCode, setEmail, setEmailStep, setEmailCode, setProviderType, setLinkIsLoading, setAlert } = useManageWalletStore();
13689
+ const {
13690
+ email,
13691
+ emailCode,
13692
+ setEmail,
13693
+ setEmailStep,
13694
+ setEmailCode,
13695
+ setEmailCodeExpiresIn,
13696
+ setProviderType,
13697
+ setLinkIsLoading,
13698
+ setAlert
13699
+ } = useManageWalletStore();
13664
13700
  return useMutation14({
13665
13701
  mutationFn: async (codeToVerify) => {
13666
13702
  const code = codeToVerify ?? emailCode;
@@ -13689,7 +13725,11 @@ function useVerifyCode() {
13689
13725
  setLinkIsLoading(false);
13690
13726
  },
13691
13727
  onError: (error) => {
13692
- setAlert({ title: "Error", message: error?.message || "Failed to verify and link email" });
13728
+ const message = error?.message || "Failed to verify and link email";
13729
+ if (message.toLowerCase().includes("expired")) {
13730
+ setEmailCodeExpiresIn(0);
13731
+ }
13732
+ setAlert({ title: "Error", message });
13693
13733
  setIsLoading(false);
13694
13734
  setLinkIsLoading(false);
13695
13735
  }
@@ -15755,11 +15795,20 @@ function useConnectedApps() {
15755
15795
  enabled: !!userId,
15756
15796
  queryKey: [CONNECTED_TRUSTED_APPS_QUERY, userId],
15757
15797
  queryFn: async () => {
15798
+ const response = await tssClient.get("/api/auth/connected-apps", true);
15799
+ if (!response.success || !response.data) {
15800
+ const error = response.error || "Failed to fetch connected apps";
15801
+ throw new Error(error);
15802
+ }
15758
15803
  const iframeManager = getIframeManager();
15759
- return await iframeManager.getTrustedApps(userId).catch(() => {
15760
- console.error("[ConnectedApps] Failed to load connected apps from iframe");
15804
+ const trustedApps = await iframeManager.getTrustedApps(userId).catch(() => {
15805
+ console.error("[ConnectedApps] Failed to load trusted apps from iframe");
15761
15806
  return [];
15762
15807
  });
15808
+ return response.data.apps.map((app) => ({
15809
+ ...app,
15810
+ trustedMeta: trustedApps.find((ta) => ta.projectId === app.projectId) || null
15811
+ }));
15763
15812
  }
15764
15813
  });
15765
15814
  }
@@ -15787,6 +15836,7 @@ var init_hooks2 = __esm({
15787
15836
  "src/internal/components/SecurityMenu/hooks.ts"() {
15788
15837
  init_SessionContext();
15789
15838
  init_keyshare();
15839
+ init_httpClient();
15790
15840
  init_iframe_manager();
15791
15841
  init_vaultClient();
15792
15842
  init_constants6();
@@ -15799,9 +15849,16 @@ import { omit } from "lodash-es";
15799
15849
  import { AppWindowMac, Info as Info5, ShieldBanIcon, ShieldCheckIcon } from "lucide-react";
15800
15850
  import { Fragment as Fragment32, jsx as jsx82, jsxs as jsxs75 } from "react/jsx-runtime";
15801
15851
  function Application(props) {
15802
- const { appLogo, appName, origin, trustedAt, untrustApp } = props;
15852
+ const {
15853
+ logo,
15854
+ name,
15855
+ // domains,
15856
+ firstConnectedAt,
15857
+ trustedMeta,
15858
+ untrustApp
15859
+ } = props;
15803
15860
  const { t } = useT();
15804
- const isAppTrusted = trustedAt && dayjs5(trustedAt).isValid() && dayjs5(trustedAt).isBefore(dayjs5());
15861
+ const resolvedLogo = logo || trustedMeta?.appLogo || null;
15805
15862
  return /* @__PURE__ */ jsxs75(
15806
15863
  "div",
15807
15864
  {
@@ -15820,8 +15877,8 @@ function Application(props) {
15820
15877
  "rounded-[var(--ui-kit-el-bdrs)] bg-[var(--ui-kit-bg)]"
15821
15878
  ),
15822
15879
  children: [
15823
- appLogo ? /* @__PURE__ */ jsx82("div", { className: "w-full h-full p-1", children: /* @__PURE__ */ jsx82("img", { src: appLogo, alt: appName, className: "w-full h-full object-contain" }) }) : /* @__PURE__ */ jsx82(AppWindowMac, { className: "w-6 h-6 text-[var(--ui-kit-fg)]" }),
15824
- isAppTrusted && /* @__PURE__ */ jsx82(
15880
+ resolvedLogo ? /* @__PURE__ */ jsx82("div", { className: "w-full h-full p-1", children: /* @__PURE__ */ jsx82("img", { src: resolvedLogo, alt: name, className: "w-full h-full object-contain" }) }) : /* @__PURE__ */ jsx82(AppWindowMac, { className: "w-6 h-6 text-[var(--ui-kit-fg)]" }),
15881
+ !!trustedMeta && /* @__PURE__ */ jsx82(
15825
15882
  "div",
15826
15883
  {
15827
15884
  className: cn(
@@ -15835,21 +15892,26 @@ function Application(props) {
15835
15892
  }
15836
15893
  ),
15837
15894
  /* @__PURE__ */ jsxs75("div", { className: "flex-1 min-w-0", children: [
15838
- /* @__PURE__ */ jsx82("div", { className: "font-semibold truncate", children: appName || new URL(origin).hostname }),
15839
- /* @__PURE__ */ jsx82("div", { className: "text-[var(--ui-kit-fg-muted)] truncate", children: new URL(origin).hostname }),
15840
- isAppTrusted ? /* @__PURE__ */ jsx82("div", { className: "text-[var(--ui-kit-fg)] truncate", children: t("passport:securityMenu.connectedApps.trustedAt", {
15841
- time: dayjs5(trustedAt).format("MMM D, YYYY HH:mm")
15895
+ /* @__PURE__ */ jsx82("div", { className: "font-semibold truncate", children: name }),
15896
+ trustedMeta?.origin && /* @__PURE__ */ jsx82("div", { className: "text-[var(--ui-kit-fg-muted)] truncate", children: new URL(trustedMeta.origin).hostname }),
15897
+ !!trustedMeta ? /* @__PURE__ */ jsx82("div", { className: "text-[var(--ui-kit-fg)] truncate", children: t("passport:securityMenu.connectedApps.trustedAt", {
15898
+ time: dayjs5(trustedMeta.trustedAt).format("MMM D, YYYY HH:mm")
15842
15899
  }) }) : /* @__PURE__ */ jsx82("div", { className: "text-[var(--ui-kit-fg-muted)] truncate", children: t("passport:securityMenu.connectedApps.connectedAt", {
15843
- time: dayjs5(trustedAt).format("MMM D, YYYY HH:mm")
15900
+ time: dayjs5(firstConnectedAt).format("MMM D, YYYY HH:mm")
15844
15901
  }) })
15845
15902
  ] }),
15846
- isAppTrusted && /* @__PURE__ */ jsx82(
15903
+ !!trustedMeta && /* @__PURE__ */ jsx82(
15847
15904
  Button,
15848
15905
  {
15849
15906
  variant: "outline",
15850
15907
  size: "icon",
15851
15908
  className: "text-[var(--ui-kit-bg-error)] flex-none rounded-[var(--ui-kit-el-bdrs)]",
15852
- onClick: () => untrustApp({ ...omit(props, "untrustApp"), hostname: new URL(origin).hostname }),
15909
+ onClick: () => {
15910
+ untrustApp({
15911
+ ...omit(props, "untrustApp"),
15912
+ hostname: new URL(trustedMeta.origin).hostname
15913
+ });
15914
+ },
15853
15915
  children: /* @__PURE__ */ jsx82(ShieldBanIcon, { className: "h-4 w-4" })
15854
15916
  }
15855
15917
  )
@@ -15869,13 +15931,7 @@ function ConnectedApps(props) {
15869
15931
  /* @__PURE__ */ jsx82("span", { children: t("passport:securityMenu.connectedApps.noConnectedApps") })
15870
15932
  ] });
15871
15933
  return /* @__PURE__ */ jsxs75(Fragment32, { children: [
15872
- /* @__PURE__ */ jsxs75("span", { className: "font-medium text-xs text-[var(--ui-kit-fg)]", children: [
15873
- /* @__PURE__ */ jsx82("span", { children: t("passport:securityMenu.connectedApps.connectedApps") }),
15874
- connectedApps.length > 0 && /* @__PURE__ */ jsxs75("span", { children: [
15875
- " ",
15876
- connectedApps.length
15877
- ] })
15878
- ] }),
15934
+ /* @__PURE__ */ jsx82("span", { className: "font-medium text-xs text-[var(--ui-kit-fg)]", children: /* @__PURE__ */ jsx82("span", { children: t("passport:securityMenu.connectedApps.connectedApps") }) }),
15879
15935
  /* @__PURE__ */ jsx82("div", { className: "w-full flex flex-col gap-[var(--ui-kit-gap)]", children: connectedApps.map((app, index) => /* @__PURE__ */ jsx82(Application, { ...app, untrustApp }, index)) })
15880
15936
  ] });
15881
15937
  }
@@ -19158,7 +19214,7 @@ var init_package = __esm({
19158
19214
  "package.json"() {
19159
19215
  package_default = {
19160
19216
  name: "@embarkai/ui-kit",
19161
- version: "0.4.11",
19217
+ version: "0.4.13",
19162
19218
  description: "React UI components and hooks for EmbarkAI authentication and Account Abstraction",
19163
19219
  type: "module",
19164
19220
  main: "./dist/index.cjs",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embarkai/ui-kit",
3
- "version": "0.4.11",
3
+ "version": "0.4.13",
4
4
  "description": "React UI components and hooks for EmbarkAI authentication and Account Abstraction",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",