@yieldfabric/wallet 0.2.2 → 0.2.3

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
@@ -5370,7 +5370,7 @@ var init_SignupFlow = __esm({
5370
5370
  navigate("/onboarding/choose");
5371
5371
  },
5372
5372
  className: "text-[12px] text-text-muted hover:text-text-primary transition-colors text-left",
5373
- children: "\u2190 Try a different method"
5373
+ children: "\u2039 Try a different method"
5374
5374
  }
5375
5375
  ) })
5376
5376
  ] });
@@ -5786,6 +5786,7 @@ async function fetchSnapshot() {
5786
5786
  return {
5787
5787
  profileCompleted: !!profile && !!profile.profile_completed,
5788
5788
  keyCount: keys.length,
5789
+ keyDeferred: me?.id ? keyStepDeferred(me.id) : false,
5789
5790
  emailVerified: email.verified,
5790
5791
  emailSynthetic: email.is_synthetic,
5791
5792
  identityStatus: identity && identity.status !== "unverified" ? identity : null,
@@ -5818,6 +5819,24 @@ async function getSnapshot() {
5818
5819
  cache = { kind: "inflight", promise };
5819
5820
  return promise;
5820
5821
  }
5822
+ var keyDeferredKey = (userId) => `yf.onboarding.keyDeferred.${userId}`;
5823
+ var keyDeferredHere = /* @__PURE__ */ new Set();
5824
+ function keyStepDeferred(userId) {
5825
+ if (keyDeferredHere.has(userId)) return true;
5826
+ try {
5827
+ return window.localStorage.getItem(keyDeferredKey(userId)) === "1";
5828
+ } catch {
5829
+ return false;
5830
+ }
5831
+ }
5832
+ function deferKeyStep(userId) {
5833
+ keyDeferredHere.add(userId);
5834
+ try {
5835
+ window.localStorage.setItem(keyDeferredKey(userId), "1");
5836
+ } catch {
5837
+ }
5838
+ invalidateOnboardingState();
5839
+ }
5821
5840
  function invalidateOnboardingState() {
5822
5841
  cache = { kind: "empty" };
5823
5842
  scopedIdentity = null;
@@ -5844,10 +5863,10 @@ function decide(snapshot, ctx) {
5844
5863
  if (ctx.kycVerifiesEmail) {
5845
5864
  if (identityStep) return identityStep;
5846
5865
  if (!emailOk) return "email-required";
5847
- if (snapshot.keyCount < MIN_USER_KEYS) return "wallets-required";
5866
+ if (snapshot.keyCount < MIN_USER_KEYS && !snapshot.keyDeferred) return "wallets-required";
5848
5867
  } else {
5849
5868
  if (!emailOk) return "email-required";
5850
- if (snapshot.keyCount < MIN_USER_KEYS) return "wallets-required";
5869
+ if (snapshot.keyCount < MIN_USER_KEYS && !snapshot.keyDeferred) return "wallets-required";
5851
5870
  if (identityStep) return identityStep;
5852
5871
  }
5853
5872
  if (!snapshot.profileCompleted) return "profile-required";
@@ -10267,7 +10286,7 @@ var DEFAULT_MESSAGES = {
10267
10286
  },
10268
10287
  email: {
10269
10288
  title: "Continue with email",
10270
- description: "Email + password. Pick your signing wallets (passkey / MetaMask) in the next step."
10289
+ description: "An email and a password. You can add a passkey later."
10271
10290
  },
10272
10291
  haveAccountPrompt: "Already have an account?",
10273
10292
  signInLinkText: "Sign in"
@@ -10278,7 +10297,7 @@ var DEFAULT_MESSAGES = {
10278
10297
  },
10279
10298
  emailSignup: {
10280
10299
  header: "Create your account",
10281
- subheader: "Your details now \u2014 signing wallets next.",
10300
+ subheader: "An email and a password is all it takes.",
10282
10301
  submitButtonText: "Continue",
10283
10302
  submittingButtonText: "Creating account\u2026",
10284
10303
  backButtonText: "\u2039 Back",
@@ -10626,7 +10645,7 @@ function PlanOfferCard({
10626
10645
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-[8px] font-medium uppercase tracking-[0.1em] text-text-muted", children: "Pay monthly" }),
10627
10646
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 block text-[16px] font-semibold leading-none tracking-tight text-text-primary tabular-nums", children: price })
10628
10647
  ] }),
10629
- /* @__PURE__ */ jsxRuntime.jsx(outline.ArrowRightIcon, { className: "h-3.5 w-3.5 shrink-0 text-text-muted", strokeWidth: 1.7 }),
10648
+ /* @__PURE__ */ jsxRuntime.jsx(outline.ChevronRightIcon, { className: "h-3.5 w-3.5 shrink-0 text-text-muted", strokeWidth: 1.7 }),
10630
10649
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
10631
10650
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-[8px] font-medium uppercase tracking-[0.1em] text-text-muted", children: "Cycle credit" }),
10632
10651
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 block text-[16px] font-semibold leading-none tracking-tight text-text-primary tabular-nums", children: allowance })
@@ -10796,7 +10815,7 @@ function OnboardingMethodCard({
10796
10815
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-text-primary", children: label }),
10797
10816
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] text-text-secondary", children: sublabel })
10798
10817
  ] }),
10799
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-text-secondary", children: "\u2192" })
10818
+ /* @__PURE__ */ jsxRuntime.jsx(outline.ChevronRightIcon, { "aria-hidden": "true", className: "h-4 w-4 text-text-secondary" })
10800
10819
  ]
10801
10820
  }
10802
10821
  );
@@ -14933,35 +14952,6 @@ function providerLabel(p) {
14933
14952
  function ProviderIcon({ provider }) {
14934
14953
  return /* @__PURE__ */ jsxRuntime.jsx(outline.KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 });
14935
14954
  }
14936
- function setupCopy(args) {
14937
- const { keyCount, busy } = args;
14938
- if (keyCount >= MIN_KEYS) {
14939
- return {
14940
- title: "Ready to sign",
14941
- body: keyCount >= RECOMMENDED_KEYS ? "Your signing keys are ready, including a backup recovery path." : "Your signing key is ready. Adding a second key gives you a recovery path, but you can continue now.",
14942
- tone: "done"
14943
- };
14944
- }
14945
- if (busy === "passkey" || busy === "metamask") {
14946
- return {
14947
- title: "Saving your signing key",
14948
- body: "Complete the passkey or wallet prompt. Your smart account will be activated later, only when an on-chain action requires it.",
14949
- tone: "active"
14950
- };
14951
- }
14952
- return {
14953
- title: "Choose a signing key",
14954
- body: "Use a passkey for quick device-native signing, or connect MetaMask if you prefer an external wallet.",
14955
- tone: "waiting"
14956
- };
14957
- }
14958
- function StepDot({
14959
- state,
14960
- icon
14961
- }) {
14962
- const className = state === "done" ? "bg-status-success-bg text-status-success-text border-status-success-text/30" : state === "active" ? "bg-status-warning-bg text-status-warning-text border-status-warning-text/30" : "bg-chip text-text-secondary border-border-default";
14963
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-8 w-8 rounded-full border flex items-center justify-center ${className}`, children: state === "done" ? /* @__PURE__ */ jsxRuntime.jsx(outline.CheckCircleIcon, { className: "h-4 w-4", strokeWidth: 1.8 }) : state === "active" ? /* @__PURE__ */ jsxRuntime.jsx(outline.ArrowPathIcon, { className: "h-4 w-4 animate-spin", strokeWidth: 1.8 }) : icon });
14964
- }
14965
14955
  function SuccessMoment({ visible }) {
14966
14956
  if (!visible) return null;
14967
14957
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -15032,65 +15022,6 @@ function RecoveryPanel({
15032
15022
  }
15033
15023
  );
15034
15024
  }
15035
- function SetupStep({
15036
- label,
15037
- detail,
15038
- state,
15039
- icon
15040
- }) {
15041
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 min-w-0", children: [
15042
- /* @__PURE__ */ jsxRuntime.jsx(StepDot, { state, icon }),
15043
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
15044
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[12px] text-text-primary truncate", children: label }),
15045
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-text-secondary truncate", children: detail })
15046
- ] })
15047
- ] });
15048
- }
15049
- function SetupStatusPanel({
15050
- keyCount,
15051
- busy
15052
- }) {
15053
- const copy = setupCopy({ keyCount, busy });
15054
- const keyState = keyCount >= MIN_KEYS ? "done" : busy === "passkey" || busy === "metamask" ? "active" : "waiting";
15055
- const readyState = keyCount >= MIN_KEYS ? "done" : "waiting";
15056
- return /* @__PURE__ */ jsxRuntime.jsxs(
15057
- "section",
15058
- {
15059
- className: "rounded-lg border border-border-default bg-input-bg px-4 py-4 space-y-4",
15060
- role: "status",
15061
- "aria-live": "polite",
15062
- children: [
15063
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
15064
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 min-w-0", children: [
15065
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[18px] text-text-primary font-medium tracking-normal", children: copy.title }),
15066
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[12px] text-text-secondary leading-relaxed", children: copy.body })
15067
- ] }),
15068
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `shrink-0 h-9 w-9 rounded-full flex items-center justify-center ${copy.tone === "done" ? "bg-status-success-bg text-status-success-text" : copy.tone === "active" ? "bg-status-warning-bg text-status-warning-text" : "bg-chip text-text-secondary"}`, children: copy.tone === "done" ? /* @__PURE__ */ jsxRuntime.jsx(outline.CheckCircleIcon, { className: "h-5 w-5", strokeWidth: 1.8 }) : copy.tone === "active" ? /* @__PURE__ */ jsxRuntime.jsx(outline.ArrowPathIcon, { className: "h-5 w-5 animate-spin", strokeWidth: 1.8 }) : /* @__PURE__ */ jsxRuntime.jsx(outline.ShieldCheckIcon, { className: "h-5 w-5", strokeWidth: 1.8 }) })
15069
- ] }),
15070
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2.5", children: [
15071
- /* @__PURE__ */ jsxRuntime.jsx(
15072
- SetupStep,
15073
- {
15074
- label: "Signing key",
15075
- detail: keyCount >= MIN_KEYS ? "Ready to authorize" : "Choose one below",
15076
- state: keyState,
15077
- icon: /* @__PURE__ */ jsxRuntime.jsx(outline.KeyIcon, { className: "h-4 w-4", strokeWidth: 1.7 })
15078
- }
15079
- ),
15080
- /* @__PURE__ */ jsxRuntime.jsx(
15081
- SetupStep,
15082
- {
15083
- label: "Continue",
15084
- detail: readyState === "done" ? "Unlocked" : "Unlocks automatically",
15085
- state: readyState,
15086
- icon: /* @__PURE__ */ jsxRuntime.jsx(outline.ClockIcon, { className: "h-4 w-4", strokeWidth: 1.7 })
15087
- }
15088
- )
15089
- ] })
15090
- ]
15091
- }
15092
- );
15093
- }
15094
15025
  function AddWalletsStep({ chrome } = {}) {
15095
15026
  const navigate = useWizardNavigate();
15096
15027
  const { bootstrapSession, user } = useAuth();
@@ -15104,6 +15035,7 @@ function AddWalletsStep({ chrome } = {}) {
15104
15035
  const [autoAdvanceArmed, setAutoAdvanceArmed] = React54.useState(false);
15105
15036
  const [emailDraft, setEmailDraft] = React54.useState("");
15106
15037
  const [showDynamic, setShowDynamic] = React54.useState(false);
15038
+ const [walletsOpen, setWalletsOpen] = React54.useState(false);
15107
15039
  const hasSyntheticEmail = !!user?.email && user.email.toLowerCase().endsWith("@external.yieldfabric.local");
15108
15040
  const { snapshot: gateSnapshot } = useOnboardingState();
15109
15041
  const emailOk = !!gateSnapshot && snapshotEmailOk(gateSnapshot);
@@ -15130,7 +15062,7 @@ function AddWalletsStep({ chrome } = {}) {
15130
15062
  }, [refresh]);
15131
15063
  const keyCount = keys.length;
15132
15064
  const canContinue = keyCount >= MIN_KEYS;
15133
- const continueLabel = canContinue ? autoAdvanceArmed ? "Ready - continuing..." : "Continue" : "Add a key to continue";
15065
+ const continueLabel = canContinue ? autoAdvanceArmed ? "Ready - continuing..." : "Continue" : "Add a passkey to continue";
15134
15066
  async function addMetaMask() {
15135
15067
  setError(null);
15136
15068
  setLastFailedAction(null);
@@ -15149,7 +15081,7 @@ function AddWalletsStep({ chrome } = {}) {
15149
15081
  await impl.directLink({
15150
15082
  onComplete: async () => {
15151
15083
  setBusy(null);
15152
- setStatus("Signing key saved. Refreshing\u2026");
15084
+ setStatus("Saved. One moment\u2026");
15153
15085
  await refresh({ invalidate: true });
15154
15086
  },
15155
15087
  onError: (msg) => {
@@ -15205,7 +15137,7 @@ function AddWalletsStep({ chrome } = {}) {
15205
15137
  credential_id: created.credentialId
15206
15138
  }
15207
15139
  }, { purpose: "user" });
15208
- setStatus("Signing key saved. Refreshing\u2026");
15140
+ setStatus("Saved. One moment\u2026");
15209
15141
  await refresh({ invalidate: true });
15210
15142
  const after = await listMyLoginKeys();
15211
15143
  const found = after.some(
@@ -15260,8 +15192,7 @@ function AddWalletsStep({ chrome } = {}) {
15260
15192
  setBusy(null);
15261
15193
  }
15262
15194
  }
15263
- const onContinue = React54.useCallback(async () => {
15264
- if (!canContinue) return;
15195
+ const goOn = React54.useCallback(async () => {
15265
15196
  setBusy("continue");
15266
15197
  setLastFailedAction(null);
15267
15198
  try {
@@ -15288,7 +15219,16 @@ function AddWalletsStep({ chrome } = {}) {
15288
15219
  setError(friendlyActionError(e, "refresh"));
15289
15220
  setBusy(null);
15290
15221
  }
15291
- }, [bootstrapSession, canContinue, config, navigate]);
15222
+ }, [bootstrapSession, config, navigate, user?.role]);
15223
+ const onContinue = React54.useCallback(async () => {
15224
+ if (!canContinue) return;
15225
+ await goOn();
15226
+ }, [canContinue, goOn]);
15227
+ const onSkip = React54.useCallback(async () => {
15228
+ if (!user?.id) return;
15229
+ deferKeyStep(user.id);
15230
+ await goOn();
15231
+ }, [goOn, user?.id]);
15292
15232
  React54.useEffect(() => {
15293
15233
  if (!autoAdvanceArmed || !canContinue || busy) return;
15294
15234
  const timeout = window.setTimeout(() => {
@@ -15314,9 +15254,8 @@ function AddWalletsStep({ chrome } = {}) {
15314
15254
  }
15315
15255
  return /* @__PURE__ */ jsxRuntime.jsx(StepShell, { chrome, wide: true, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 sm:space-y-5 max-w-[420px] mx-auto", children: [
15316
15256
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center space-y-2", children: [
15317
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] uppercase tracking-[0.14em] text-text-secondary", children: "Secure setup" }),
15318
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[21px] text-text-primary font-medium leading-tight", children: "Your account is almost ready" }),
15319
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[12px] leading-relaxed text-text-secondary max-w-[330px] mx-auto", children: "Add a signing key now. Your smart account is activated later, only when an on-chain action needs it." })
15257
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[21px] text-text-primary font-medium leading-tight", children: "Secure your account" }),
15258
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[13px] leading-relaxed text-text-secondary max-w-[340px] mx-auto", children: "A passkey means only you can approve what is done in your name \u2014 one tap with Face ID, a fingerprint or your PIN. You can also do this later." })
15320
15259
  ] }),
15321
15260
  hasSyntheticEmail && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-status-warning-bg border border-status-warning-text/20 p-3 space-y-2", children: [
15322
15261
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] text-status-warning-text", children: "Your account email is a temporary placeholder. Set a real one so you can recover access and (if you ever want it) link Averer KYC." }),
@@ -15343,20 +15282,10 @@ function AddWalletsStep({ chrome } = {}) {
15343
15282
  )
15344
15283
  ] })
15345
15284
  ] }),
15346
- !loading && /* @__PURE__ */ jsxRuntime.jsx(
15347
- SetupStatusPanel,
15348
- {
15349
- keyCount,
15350
- busy
15351
- }
15352
- ),
15353
15285
  /* @__PURE__ */ jsxRuntime.jsx(SuccessMoment, { visible: canContinue && autoAdvanceArmed && !error }),
15354
- loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-border-default bg-input-bg px-4 py-8 text-center text-[11px] text-text-secondary", children: "Loading\u2026" }) : keys.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-border-default bg-input-bg px-4 py-7 flex flex-col items-center gap-2.5", children: [
15355
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-11 h-11 rounded-full bg-chip flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(outline.KeyIcon, { className: "h-5 w-5 text-text-secondary", strokeWidth: 1.5 }) }),
15356
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] text-text-secondary", children: "No signing keys yet" })
15357
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-input-bg rounded-lg px-4 py-3.5 space-y-3", children: [
15286
+ loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-border-default bg-input-bg px-4 py-8 text-center text-[11px] text-text-secondary", children: "Loading\u2026" }) : keys.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-input-bg rounded-lg px-4 py-3.5 space-y-3", children: [
15358
15287
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-[11px]", children: [
15359
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-text-secondary", children: "Signing keys" }),
15288
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-text-secondary", children: "Your keys" }),
15360
15289
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: keyCount < RECOMMENDED_KEYS ? "text-status-warning-text" : "text-status-success-text", children: [
15361
15290
  keyCount === 1 && "1 key \xB7 add a backup",
15362
15291
  keyCount >= RECOMMENDED_KEYS && `${keyCount} keys`
@@ -15383,7 +15312,7 @@ function AddWalletsStep({ chrome } = {}) {
15383
15312
  }) })
15384
15313
  ] }),
15385
15314
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
15386
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-text-secondary text-center", children: !emailOk ? "Verify your email to unlock signing keys" : "Add a key" }),
15315
+ !emailOk ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-text-secondary text-center", children: "Confirm your email first" }) : null,
15387
15316
  !emailOk && /* @__PURE__ */ jsxRuntime.jsxs(
15388
15317
  "button",
15389
15318
  {
@@ -15403,37 +15332,48 @@ function AddWalletsStep({ chrome } = {}) {
15403
15332
  type: "button",
15404
15333
  onClick: addPasskey,
15405
15334
  disabled: busy !== null || !emailOk,
15406
- className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15407
- children: [
15408
- busy === "passkey" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-text-secondary", children: "\u2026" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15409
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Add Passkey" })
15410
- ]
15411
- }
15412
- ),
15413
- /* @__PURE__ */ jsxRuntime.jsxs(
15414
- "button",
15415
- {
15416
- type: "button",
15417
- onClick: addMetaMask,
15418
- disabled: busy !== null || !emailOk,
15419
- className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15335
+ className: `w-full min-h-[46px] flex items-center justify-center gap-2 py-2.5 rounded-lg text-[13px] font-medium transition-colors active:scale-[0.99] disabled:opacity-40 disabled:cursor-not-allowed ${canContinue ? "bg-chip hover:bg-chip-hover text-text-primary" : "bg-cta hover:bg-cta-hover text-on-cta"}`,
15420
15336
  children: [
15421
- busy === "metamask" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-text-secondary", children: "\u2026" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15422
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Add MetaMask" })
15337
+ busy === "passkey" ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u2026" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.KeyIcon, { className: "h-4 w-4", strokeWidth: 1.5 }),
15338
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: canContinue ? "Add another passkey" : "Add a passkey" })
15423
15339
  ]
15424
15340
  }
15425
15341
  ),
15426
- !!config?.auth.enabled.includes("dynamic") && !!config?.auth.settings.dynamic?.environment_id && /* @__PURE__ */ jsxRuntime.jsxs(
15342
+ walletsOpen ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15343
+ /* @__PURE__ */ jsxRuntime.jsxs(
15344
+ "button",
15345
+ {
15346
+ type: "button",
15347
+ onClick: addMetaMask,
15348
+ disabled: busy !== null || !emailOk,
15349
+ className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15350
+ children: [
15351
+ busy === "metamask" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-text-secondary", children: "\u2026" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15352
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Add MetaMask" })
15353
+ ]
15354
+ }
15355
+ ),
15356
+ !!config?.auth.enabled.includes("dynamic") && !!config?.auth.settings.dynamic?.environment_id && /* @__PURE__ */ jsxRuntime.jsxs(
15357
+ "button",
15358
+ {
15359
+ type: "button",
15360
+ onClick: () => setShowDynamic(true),
15361
+ disabled: busy !== null || !emailOk,
15362
+ className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15363
+ children: [
15364
+ /* @__PURE__ */ jsxRuntime.jsx(outline.KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15365
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Add Dynamic" })
15366
+ ]
15367
+ }
15368
+ )
15369
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
15427
15370
  "button",
15428
15371
  {
15429
15372
  type: "button",
15430
- onClick: () => setShowDynamic(true),
15431
- disabled: busy !== null || !emailOk,
15432
- className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15433
- children: [
15434
- /* @__PURE__ */ jsxRuntime.jsx(outline.KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15435
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Add Dynamic" })
15436
- ]
15373
+ onClick: () => setWalletsOpen(true),
15374
+ disabled: busy !== null,
15375
+ className: "w-full py-1.5 text-[11px] text-text-secondary hover:text-text-primary transition-colors disabled:opacity-40",
15376
+ children: "Use a crypto wallet instead"
15437
15377
  }
15438
15378
  )
15439
15379
  ] }),
@@ -15450,7 +15390,7 @@ function AddWalletsStep({ chrome } = {}) {
15450
15390
  registerOnChain: false,
15451
15391
  onComplete: async () => {
15452
15392
  setShowDynamic(false);
15453
- setStatus("Signing key saved. Refreshing\u2026");
15393
+ setStatus("Saved. One moment\u2026");
15454
15394
  await refresh({ invalidate: true });
15455
15395
  },
15456
15396
  onError: (m) => {
@@ -15482,15 +15422,24 @@ function AddWalletsStep({ chrome } = {}) {
15482
15422
  onRetry: retryLastFailure
15483
15423
  }
15484
15424
  ),
15485
- /* @__PURE__ */ jsxRuntime.jsx(
15425
+ canContinue ? /* @__PURE__ */ jsxRuntime.jsx(
15486
15426
  "button",
15487
15427
  {
15488
15428
  type: "button",
15489
15429
  onClick: onContinue,
15490
- disabled: !canContinue || busy === "continue",
15491
- className: "\n w-full min-h-[46px] py-3 rounded-lg\n bg-status-success-bg hover:opacity-80 text-status-success-text\n text-[13px] font-medium\n transition-all duration-200 active:scale-[0.99]\n disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:bg-status-success-bg\n ",
15430
+ disabled: busy === "continue",
15431
+ className: "w-full min-h-[46px] py-3 rounded-lg bg-cta hover:bg-cta-hover text-on-cta text-[13px] font-medium transition-colors active:scale-[0.99] disabled:opacity-40 disabled:cursor-not-allowed",
15492
15432
  children: continueLabel
15493
15433
  }
15434
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
15435
+ "button",
15436
+ {
15437
+ type: "button",
15438
+ onClick: () => void onSkip(),
15439
+ disabled: busy !== null || !user?.id,
15440
+ className: "w-full py-2 text-[13px] text-text-secondary hover:text-text-primary transition-colors disabled:opacity-40",
15441
+ children: "Not now"
15442
+ }
15494
15443
  ),
15495
15444
  keyCount === 1 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-text-secondary text-center pt-1", children: "Tip: a second key is your recovery path. If you lose your only key, the account is locked out." })
15496
15445
  ] }) });
@@ -23074,7 +23023,7 @@ function SecurityPage() {
23074
23023
  rotateStep === "added" || rotateStep === "removing" || rotateStep === "remove-pending" || rotateStep === "done" ? "\u2713 " : "1. ",
23075
23024
  "Add new key"
23076
23025
  ] }),
23077
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u2192" }),
23026
+ /* @__PURE__ */ jsxRuntime.jsx(outline.ChevronRightIcon, { "aria-hidden": "true", className: "h-3 w-3" }),
23078
23027
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: rotateStep === "added" || rotateStep === "removing" || rotateStep === "remove-pending" ? "text-text-primary font-medium" : "", children: [
23079
23028
  rotateStep === "done" ? "\u2713 " : "2. ",
23080
23029
  "Remove old key"
@@ -24004,9 +23953,9 @@ var GroupsView = ({
24004
23953
  "aria-label": `${sourceGroup?.name ?? "Owning group"} is operating ${activeOwnedGroup?.name ?? "owned group"}`,
24005
23954
  children: [
24006
23955
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate rounded-lg border border-border-default dark:border-white/[0.08] bg-chip dark:bg-white/[0.035] px-2.5 py-1.5 text-[11px] font-semibold text-text-secondary", children: "You" }),
24007
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "shrink-0 text-[12px] text-azure dark:text-cyan-300/70", children: "\u2192" }),
23956
+ /* @__PURE__ */ jsxRuntime.jsx(outline.ChevronRightIcon, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0 text-azure dark:text-cyan-300/70" }),
24008
23957
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate rounded-lg border border-border-default dark:border-white/[0.08] bg-chip dark:bg-white/[0.035] px-2.5 py-1.5 text-[11px] font-semibold text-text-secondary", children: sourceGroup?.name ?? compactGroupId(delegationSession.parentGroupId) }),
24009
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "shrink-0 text-[12px] text-azure dark:text-cyan-300/70", children: "\u2192" }),
23958
+ /* @__PURE__ */ jsxRuntime.jsx(outline.ChevronRightIcon, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0 text-azure dark:text-cyan-300/70" }),
24010
23959
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate rounded-lg border border-azure-line dark:border-cyan-300/[0.18] bg-azure-tint dark:bg-cyan-300/[0.08] px-2.5 py-1.5 text-[11px] font-semibold text-azure dark:text-cyan-200", children: activeOwnedGroup?.name ?? compactGroupId(delegationSession.currentGroupId) })
24011
23960
  ]
24012
23961
  }
@@ -24370,7 +24319,7 @@ function OwnedGroupRow({
24370
24319
  return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "px-3.5 py-3", children: [
24371
24320
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
24372
24321
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-[11px] font-semibold text-text-secondary", children: sourceName }),
24373
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "shrink-0 text-[12px] text-azure dark:text-cyan-300/70", children: "\u2192" }),
24322
+ /* @__PURE__ */ jsxRuntime.jsx(outline.ChevronRightIcon, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0 text-azure dark:text-cyan-300/70" }),
24374
24323
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-[12px] font-semibold text-text-primary", children: projection.group.name })
24375
24324
  ] }),
24376
24325
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex items-center justify-between gap-3", children: [
@@ -29714,7 +29663,7 @@ var VerificationDialog = ({
29714
29663
  type: "button",
29715
29664
  onClick: () => setActiveProvider(null),
29716
29665
  className: "mb-3 text-[12px] text-text-secondary hover:text-text-primary",
29717
- children: "\u2190 Choose a different provider"
29666
+ children: "\u2039 Choose a different provider"
29718
29667
  }
29719
29668
  ),
29720
29669
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -29877,7 +29826,7 @@ function BusinessVerificationSection({
29877
29826
  type: "button",
29878
29827
  onClick: () => setFlowInstance(null),
29879
29828
  className: "mb-3 text-[12px] text-text-secondary hover:text-text-primary",
29880
- children: "\u2190 Back"
29829
+ children: "\u2039 Back"
29881
29830
  }
29882
29831
  ),
29883
29832
  /* @__PURE__ */ jsxRuntime.jsx(
package/dist/index.d.cts CHANGED
@@ -3473,7 +3473,8 @@ groupId?: string): Promise<string>;
3473
3473
  *
3474
3474
  * 1. Email not confirmed → 'email-required'
3475
3475
  * (Averer signups skip this; Averer is already an identity gate)
3476
- * 2. < 1 off-chain signing key → 'wallets-required'
3476
+ * 2. < 1 off-chain signing key, not deferred → 'wallets-required'
3477
+ * ("Skip for now" defers it on this device: `deferKeyStep`)
3477
3478
  * 3. Identity verification required but not done → 'identity-required'
3478
3479
  * 4. Profile (display_name + avatar) not completed → 'profile-required'
3479
3480
  * 5. Billing unavailable in a direct plan context → 'service-unavailable'
@@ -3497,11 +3498,13 @@ groupId?: string): Promise<string>;
3497
3498
  * already a verified-identity ceremony, so we do not add a second
3498
3499
  * email-code gate on top of it.
3499
3500
  *
3500
- * - **Signing key before identity.** A user without a signing key has no way to act on
3501
- * the platform anyway, and capturing the key first means the identity
3502
- * step (Stripe KYC) can stamp itself against an established signer
3503
- * rather than a "naked" account. Also gives the user something
3504
- * tangible before being asked for government-issued ID.
3501
+ * - **Signing key before identity, and optional.** Offering the key first
3502
+ * gives the user something tangible before being asked for
3503
+ * government-issued ID. It can be skipped: an email user acts through
3504
+ * their platform-managed key, signing permission follows verification
3505
+ * (auth's capability gate), and auth stores a FIRST key for an
3506
+ * email-confirmed person without signing permission, so a key added
3507
+ * later needs no carve-out either.
3505
3508
  *
3506
3509
  * - **Identity second.** Stripe Identity returns first_name, last_name,
3507
3510
  * dob, and address as `verified_outputs`, which the auth side projects
@@ -3543,6 +3546,11 @@ groupId?: string): Promise<string>;
3543
3546
  interface OnboardingSnapshot {
3544
3547
  profileCompleted: boolean;
3545
3548
  keyCount: number;
3549
+ /** The person chose to add a key later (the key step's "Skip for now").
3550
+ * A key is optional: storing one is not an on-chain act, and signing
3551
+ * permission follows verification (auth's capability gate), never keys.
3552
+ * Absent reads as not deferred. */
3553
+ keyDeferred?: boolean;
3546
3554
  /** Current auth email ownership state. Synthetic wallet-only emails
3547
3555
  * must be replaced before they can be confirmed. */
3548
3556
  emailVerified: boolean;
@@ -3579,14 +3587,6 @@ interface OnboardingSnapshot {
3579
3587
  * fetch failed (treated as NOT exempt — fail-safe). */
3580
3588
  role: string | null;
3581
3589
  }
3582
- /** Drop the cache and notify every mounted hook instance to re-fetch.
3583
- * Call after any mutation that could change the user's onboarding
3584
- * state — wallet add/remove, profile patch, lockdown finalize,
3585
- * identity-verification submission, etc.
3586
- *
3587
- * The subscriber fan-out is critical: without it, sibling consumers
3588
- * of `useOnboardingState` keep their stale React state and continue
3589
- * rendering against an out-of-date decision. */
3590
3590
  declare function invalidateOnboardingState(): void;
3591
3591
  /** Backwards-compatible alias for the now-removed wallet-only API.
3592
3592
  * Callers don't need to know the cache covers both signals now. */
package/dist/index.d.ts CHANGED
@@ -3473,7 +3473,8 @@ groupId?: string): Promise<string>;
3473
3473
  *
3474
3474
  * 1. Email not confirmed → 'email-required'
3475
3475
  * (Averer signups skip this; Averer is already an identity gate)
3476
- * 2. < 1 off-chain signing key → 'wallets-required'
3476
+ * 2. < 1 off-chain signing key, not deferred → 'wallets-required'
3477
+ * ("Skip for now" defers it on this device: `deferKeyStep`)
3477
3478
  * 3. Identity verification required but not done → 'identity-required'
3478
3479
  * 4. Profile (display_name + avatar) not completed → 'profile-required'
3479
3480
  * 5. Billing unavailable in a direct plan context → 'service-unavailable'
@@ -3497,11 +3498,13 @@ groupId?: string): Promise<string>;
3497
3498
  * already a verified-identity ceremony, so we do not add a second
3498
3499
  * email-code gate on top of it.
3499
3500
  *
3500
- * - **Signing key before identity.** A user without a signing key has no way to act on
3501
- * the platform anyway, and capturing the key first means the identity
3502
- * step (Stripe KYC) can stamp itself against an established signer
3503
- * rather than a "naked" account. Also gives the user something
3504
- * tangible before being asked for government-issued ID.
3501
+ * - **Signing key before identity, and optional.** Offering the key first
3502
+ * gives the user something tangible before being asked for
3503
+ * government-issued ID. It can be skipped: an email user acts through
3504
+ * their platform-managed key, signing permission follows verification
3505
+ * (auth's capability gate), and auth stores a FIRST key for an
3506
+ * email-confirmed person without signing permission, so a key added
3507
+ * later needs no carve-out either.
3505
3508
  *
3506
3509
  * - **Identity second.** Stripe Identity returns first_name, last_name,
3507
3510
  * dob, and address as `verified_outputs`, which the auth side projects
@@ -3543,6 +3546,11 @@ groupId?: string): Promise<string>;
3543
3546
  interface OnboardingSnapshot {
3544
3547
  profileCompleted: boolean;
3545
3548
  keyCount: number;
3549
+ /** The person chose to add a key later (the key step's "Skip for now").
3550
+ * A key is optional: storing one is not an on-chain act, and signing
3551
+ * permission follows verification (auth's capability gate), never keys.
3552
+ * Absent reads as not deferred. */
3553
+ keyDeferred?: boolean;
3546
3554
  /** Current auth email ownership state. Synthetic wallet-only emails
3547
3555
  * must be replaced before they can be confirmed. */
3548
3556
  emailVerified: boolean;
@@ -3579,14 +3587,6 @@ interface OnboardingSnapshot {
3579
3587
  * fetch failed (treated as NOT exempt — fail-safe). */
3580
3588
  role: string | null;
3581
3589
  }
3582
- /** Drop the cache and notify every mounted hook instance to re-fetch.
3583
- * Call after any mutation that could change the user's onboarding
3584
- * state — wallet add/remove, profile patch, lockdown finalize,
3585
- * identity-verification submission, etc.
3586
- *
3587
- * The subscriber fan-out is critical: without it, sibling consumers
3588
- * of `useOnboardingState` keep their stale React state and continue
3589
- * rendering against an out-of-date decision. */
3590
3590
  declare function invalidateOnboardingState(): void;
3591
3591
  /** Backwards-compatible alias for the now-removed wallet-only API.
3592
3592
  * Callers don't need to know the cache covers both signals now. */
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import React54, { createContext, lazy, useContext, useState, useEffect, useRef,
9
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
10
  import { AvererSdkProvider, useAvererWallet, AvererWebSdk } from '@averer/averer-websdk';
11
11
  import sha3, { keccak256 } from 'js-sha3';
12
- import { XMarkIcon, IdentificationIcon, CheckCircleIcon, ExclamationTriangleIcon, SparklesIcon, EnvelopeIcon, ArrowPathIcon, KeyIcon, ShieldCheckIcon, CreditCardIcon, ArrowRightIcon, UserIcon, UserGroupIcon, ClockIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
12
+ import { ChevronRightIcon, XMarkIcon, IdentificationIcon, CheckCircleIcon, ExclamationTriangleIcon, SparklesIcon, EnvelopeIcon, ArrowPathIcon, ShieldCheckIcon, KeyIcon, CreditCardIcon, UserIcon, UserGroupIcon } from '@heroicons/react/24/outline';
13
13
  import { Avatar } from '@avatune/react';
14
14
  import theme from '@avatune/kyute-theme/react';
15
15
  import { AnimatePresence, motion } from 'framer-motion';
@@ -5362,7 +5362,7 @@ var init_SignupFlow = __esm({
5362
5362
  navigate("/onboarding/choose");
5363
5363
  },
5364
5364
  className: "text-[12px] text-text-muted hover:text-text-primary transition-colors text-left",
5365
- children: "\u2190 Try a different method"
5365
+ children: "\u2039 Try a different method"
5366
5366
  }
5367
5367
  ) })
5368
5368
  ] });
@@ -5778,6 +5778,7 @@ async function fetchSnapshot() {
5778
5778
  return {
5779
5779
  profileCompleted: !!profile && !!profile.profile_completed,
5780
5780
  keyCount: keys.length,
5781
+ keyDeferred: me?.id ? keyStepDeferred(me.id) : false,
5781
5782
  emailVerified: email.verified,
5782
5783
  emailSynthetic: email.is_synthetic,
5783
5784
  identityStatus: identity && identity.status !== "unverified" ? identity : null,
@@ -5810,6 +5811,24 @@ async function getSnapshot() {
5810
5811
  cache = { kind: "inflight", promise };
5811
5812
  return promise;
5812
5813
  }
5814
+ var keyDeferredKey = (userId) => `yf.onboarding.keyDeferred.${userId}`;
5815
+ var keyDeferredHere = /* @__PURE__ */ new Set();
5816
+ function keyStepDeferred(userId) {
5817
+ if (keyDeferredHere.has(userId)) return true;
5818
+ try {
5819
+ return window.localStorage.getItem(keyDeferredKey(userId)) === "1";
5820
+ } catch {
5821
+ return false;
5822
+ }
5823
+ }
5824
+ function deferKeyStep(userId) {
5825
+ keyDeferredHere.add(userId);
5826
+ try {
5827
+ window.localStorage.setItem(keyDeferredKey(userId), "1");
5828
+ } catch {
5829
+ }
5830
+ invalidateOnboardingState();
5831
+ }
5813
5832
  function invalidateOnboardingState() {
5814
5833
  cache = { kind: "empty" };
5815
5834
  scopedIdentity = null;
@@ -5836,10 +5855,10 @@ function decide(snapshot, ctx) {
5836
5855
  if (ctx.kycVerifiesEmail) {
5837
5856
  if (identityStep) return identityStep;
5838
5857
  if (!emailOk) return "email-required";
5839
- if (snapshot.keyCount < MIN_USER_KEYS) return "wallets-required";
5858
+ if (snapshot.keyCount < MIN_USER_KEYS && !snapshot.keyDeferred) return "wallets-required";
5840
5859
  } else {
5841
5860
  if (!emailOk) return "email-required";
5842
- if (snapshot.keyCount < MIN_USER_KEYS) return "wallets-required";
5861
+ if (snapshot.keyCount < MIN_USER_KEYS && !snapshot.keyDeferred) return "wallets-required";
5843
5862
  if (identityStep) return identityStep;
5844
5863
  }
5845
5864
  if (!snapshot.profileCompleted) return "profile-required";
@@ -10259,7 +10278,7 @@ var DEFAULT_MESSAGES = {
10259
10278
  },
10260
10279
  email: {
10261
10280
  title: "Continue with email",
10262
- description: "Email + password. Pick your signing wallets (passkey / MetaMask) in the next step."
10281
+ description: "An email and a password. You can add a passkey later."
10263
10282
  },
10264
10283
  haveAccountPrompt: "Already have an account?",
10265
10284
  signInLinkText: "Sign in"
@@ -10270,7 +10289,7 @@ var DEFAULT_MESSAGES = {
10270
10289
  },
10271
10290
  emailSignup: {
10272
10291
  header: "Create your account",
10273
- subheader: "Your details now \u2014 signing wallets next.",
10292
+ subheader: "An email and a password is all it takes.",
10274
10293
  submitButtonText: "Continue",
10275
10294
  submittingButtonText: "Creating account\u2026",
10276
10295
  backButtonText: "\u2039 Back",
@@ -10618,7 +10637,7 @@ function PlanOfferCard({
10618
10637
  /* @__PURE__ */ jsx("span", { className: "block text-[8px] font-medium uppercase tracking-[0.1em] text-text-muted", children: "Pay monthly" }),
10619
10638
  /* @__PURE__ */ jsx("span", { className: "mt-1 block text-[16px] font-semibold leading-none tracking-tight text-text-primary tabular-nums", children: price })
10620
10639
  ] }),
10621
- /* @__PURE__ */ jsx(ArrowRightIcon, { className: "h-3.5 w-3.5 shrink-0 text-text-muted", strokeWidth: 1.7 }),
10640
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3.5 w-3.5 shrink-0 text-text-muted", strokeWidth: 1.7 }),
10622
10641
  /* @__PURE__ */ jsxs("span", { children: [
10623
10642
  /* @__PURE__ */ jsx("span", { className: "block text-[8px] font-medium uppercase tracking-[0.1em] text-text-muted", children: "Cycle credit" }),
10624
10643
  /* @__PURE__ */ jsx("span", { className: "mt-1 block text-[16px] font-semibold leading-none tracking-tight text-text-primary tabular-nums", children: allowance })
@@ -10788,7 +10807,7 @@ function OnboardingMethodCard({
10788
10807
  /* @__PURE__ */ jsx("div", { className: "text-sm text-text-primary", children: label }),
10789
10808
  /* @__PURE__ */ jsx("div", { className: "text-[11px] text-text-secondary", children: sublabel })
10790
10809
  ] }),
10791
- /* @__PURE__ */ jsx("div", { className: "text-text-secondary", children: "\u2192" })
10810
+ /* @__PURE__ */ jsx(ChevronRightIcon, { "aria-hidden": "true", className: "h-4 w-4 text-text-secondary" })
10792
10811
  ]
10793
10812
  }
10794
10813
  );
@@ -14925,35 +14944,6 @@ function providerLabel(p) {
14925
14944
  function ProviderIcon({ provider }) {
14926
14945
  return /* @__PURE__ */ jsx(KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 });
14927
14946
  }
14928
- function setupCopy(args) {
14929
- const { keyCount, busy } = args;
14930
- if (keyCount >= MIN_KEYS) {
14931
- return {
14932
- title: "Ready to sign",
14933
- body: keyCount >= RECOMMENDED_KEYS ? "Your signing keys are ready, including a backup recovery path." : "Your signing key is ready. Adding a second key gives you a recovery path, but you can continue now.",
14934
- tone: "done"
14935
- };
14936
- }
14937
- if (busy === "passkey" || busy === "metamask") {
14938
- return {
14939
- title: "Saving your signing key",
14940
- body: "Complete the passkey or wallet prompt. Your smart account will be activated later, only when an on-chain action requires it.",
14941
- tone: "active"
14942
- };
14943
- }
14944
- return {
14945
- title: "Choose a signing key",
14946
- body: "Use a passkey for quick device-native signing, or connect MetaMask if you prefer an external wallet.",
14947
- tone: "waiting"
14948
- };
14949
- }
14950
- function StepDot({
14951
- state,
14952
- icon
14953
- }) {
14954
- const className = state === "done" ? "bg-status-success-bg text-status-success-text border-status-success-text/30" : state === "active" ? "bg-status-warning-bg text-status-warning-text border-status-warning-text/30" : "bg-chip text-text-secondary border-border-default";
14955
- return /* @__PURE__ */ jsx("div", { className: `h-8 w-8 rounded-full border flex items-center justify-center ${className}`, children: state === "done" ? /* @__PURE__ */ jsx(CheckCircleIcon, { className: "h-4 w-4", strokeWidth: 1.8 }) : state === "active" ? /* @__PURE__ */ jsx(ArrowPathIcon, { className: "h-4 w-4 animate-spin", strokeWidth: 1.8 }) : icon });
14956
- }
14957
14947
  function SuccessMoment({ visible }) {
14958
14948
  if (!visible) return null;
14959
14949
  return /* @__PURE__ */ jsx(
@@ -15024,65 +15014,6 @@ function RecoveryPanel({
15024
15014
  }
15025
15015
  );
15026
15016
  }
15027
- function SetupStep({
15028
- label,
15029
- detail,
15030
- state,
15031
- icon
15032
- }) {
15033
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0", children: [
15034
- /* @__PURE__ */ jsx(StepDot, { state, icon }),
15035
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
15036
- /* @__PURE__ */ jsx("div", { className: "text-[12px] text-text-primary truncate", children: label }),
15037
- /* @__PURE__ */ jsx("div", { className: "text-[10px] text-text-secondary truncate", children: detail })
15038
- ] })
15039
- ] });
15040
- }
15041
- function SetupStatusPanel({
15042
- keyCount,
15043
- busy
15044
- }) {
15045
- const copy = setupCopy({ keyCount, busy });
15046
- const keyState = keyCount >= MIN_KEYS ? "done" : busy === "passkey" || busy === "metamask" ? "active" : "waiting";
15047
- const readyState = keyCount >= MIN_KEYS ? "done" : "waiting";
15048
- return /* @__PURE__ */ jsxs(
15049
- "section",
15050
- {
15051
- className: "rounded-lg border border-border-default bg-input-bg px-4 py-4 space-y-4",
15052
- role: "status",
15053
- "aria-live": "polite",
15054
- children: [
15055
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
15056
- /* @__PURE__ */ jsxs("div", { className: "space-y-1 min-w-0", children: [
15057
- /* @__PURE__ */ jsx("h2", { className: "text-[18px] text-text-primary font-medium tracking-normal", children: copy.title }),
15058
- /* @__PURE__ */ jsx("p", { className: "text-[12px] text-text-secondary leading-relaxed", children: copy.body })
15059
- ] }),
15060
- /* @__PURE__ */ jsx("div", { className: `shrink-0 h-9 w-9 rounded-full flex items-center justify-center ${copy.tone === "done" ? "bg-status-success-bg text-status-success-text" : copy.tone === "active" ? "bg-status-warning-bg text-status-warning-text" : "bg-chip text-text-secondary"}`, children: copy.tone === "done" ? /* @__PURE__ */ jsx(CheckCircleIcon, { className: "h-5 w-5", strokeWidth: 1.8 }) : copy.tone === "active" ? /* @__PURE__ */ jsx(ArrowPathIcon, { className: "h-5 w-5 animate-spin", strokeWidth: 1.8 }) : /* @__PURE__ */ jsx(ShieldCheckIcon, { className: "h-5 w-5", strokeWidth: 1.8 }) })
15061
- ] }),
15062
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-2.5", children: [
15063
- /* @__PURE__ */ jsx(
15064
- SetupStep,
15065
- {
15066
- label: "Signing key",
15067
- detail: keyCount >= MIN_KEYS ? "Ready to authorize" : "Choose one below",
15068
- state: keyState,
15069
- icon: /* @__PURE__ */ jsx(KeyIcon, { className: "h-4 w-4", strokeWidth: 1.7 })
15070
- }
15071
- ),
15072
- /* @__PURE__ */ jsx(
15073
- SetupStep,
15074
- {
15075
- label: "Continue",
15076
- detail: readyState === "done" ? "Unlocked" : "Unlocks automatically",
15077
- state: readyState,
15078
- icon: /* @__PURE__ */ jsx(ClockIcon, { className: "h-4 w-4", strokeWidth: 1.7 })
15079
- }
15080
- )
15081
- ] })
15082
- ]
15083
- }
15084
- );
15085
- }
15086
15017
  function AddWalletsStep({ chrome } = {}) {
15087
15018
  const navigate = useWizardNavigate();
15088
15019
  const { bootstrapSession, user } = useAuth();
@@ -15096,6 +15027,7 @@ function AddWalletsStep({ chrome } = {}) {
15096
15027
  const [autoAdvanceArmed, setAutoAdvanceArmed] = useState(false);
15097
15028
  const [emailDraft, setEmailDraft] = useState("");
15098
15029
  const [showDynamic, setShowDynamic] = useState(false);
15030
+ const [walletsOpen, setWalletsOpen] = useState(false);
15099
15031
  const hasSyntheticEmail = !!user?.email && user.email.toLowerCase().endsWith("@external.yieldfabric.local");
15100
15032
  const { snapshot: gateSnapshot } = useOnboardingState();
15101
15033
  const emailOk = !!gateSnapshot && snapshotEmailOk(gateSnapshot);
@@ -15122,7 +15054,7 @@ function AddWalletsStep({ chrome } = {}) {
15122
15054
  }, [refresh]);
15123
15055
  const keyCount = keys.length;
15124
15056
  const canContinue = keyCount >= MIN_KEYS;
15125
- const continueLabel = canContinue ? autoAdvanceArmed ? "Ready - continuing..." : "Continue" : "Add a key to continue";
15057
+ const continueLabel = canContinue ? autoAdvanceArmed ? "Ready - continuing..." : "Continue" : "Add a passkey to continue";
15126
15058
  async function addMetaMask() {
15127
15059
  setError(null);
15128
15060
  setLastFailedAction(null);
@@ -15141,7 +15073,7 @@ function AddWalletsStep({ chrome } = {}) {
15141
15073
  await impl.directLink({
15142
15074
  onComplete: async () => {
15143
15075
  setBusy(null);
15144
- setStatus("Signing key saved. Refreshing\u2026");
15076
+ setStatus("Saved. One moment\u2026");
15145
15077
  await refresh({ invalidate: true });
15146
15078
  },
15147
15079
  onError: (msg) => {
@@ -15197,7 +15129,7 @@ function AddWalletsStep({ chrome } = {}) {
15197
15129
  credential_id: created.credentialId
15198
15130
  }
15199
15131
  }, { purpose: "user" });
15200
- setStatus("Signing key saved. Refreshing\u2026");
15132
+ setStatus("Saved. One moment\u2026");
15201
15133
  await refresh({ invalidate: true });
15202
15134
  const after = await listMyLoginKeys();
15203
15135
  const found = after.some(
@@ -15252,8 +15184,7 @@ function AddWalletsStep({ chrome } = {}) {
15252
15184
  setBusy(null);
15253
15185
  }
15254
15186
  }
15255
- const onContinue = useCallback(async () => {
15256
- if (!canContinue) return;
15187
+ const goOn = useCallback(async () => {
15257
15188
  setBusy("continue");
15258
15189
  setLastFailedAction(null);
15259
15190
  try {
@@ -15280,7 +15211,16 @@ function AddWalletsStep({ chrome } = {}) {
15280
15211
  setError(friendlyActionError(e, "refresh"));
15281
15212
  setBusy(null);
15282
15213
  }
15283
- }, [bootstrapSession, canContinue, config, navigate]);
15214
+ }, [bootstrapSession, config, navigate, user?.role]);
15215
+ const onContinue = useCallback(async () => {
15216
+ if (!canContinue) return;
15217
+ await goOn();
15218
+ }, [canContinue, goOn]);
15219
+ const onSkip = useCallback(async () => {
15220
+ if (!user?.id) return;
15221
+ deferKeyStep(user.id);
15222
+ await goOn();
15223
+ }, [goOn, user?.id]);
15284
15224
  useEffect(() => {
15285
15225
  if (!autoAdvanceArmed || !canContinue || busy) return;
15286
15226
  const timeout = window.setTimeout(() => {
@@ -15306,9 +15246,8 @@ function AddWalletsStep({ chrome } = {}) {
15306
15246
  }
15307
15247
  return /* @__PURE__ */ jsx(StepShell, { chrome, wide: true, children: /* @__PURE__ */ jsxs("div", { className: "space-y-4 sm:space-y-5 max-w-[420px] mx-auto", children: [
15308
15248
  /* @__PURE__ */ jsxs("div", { className: "text-center space-y-2", children: [
15309
- /* @__PURE__ */ jsx("p", { className: "text-[10px] uppercase tracking-[0.14em] text-text-secondary", children: "Secure setup" }),
15310
- /* @__PURE__ */ jsx("h2", { className: "text-[21px] text-text-primary font-medium leading-tight", children: "Your account is almost ready" }),
15311
- /* @__PURE__ */ jsx("p", { className: "text-[12px] leading-relaxed text-text-secondary max-w-[330px] mx-auto", children: "Add a signing key now. Your smart account is activated later, only when an on-chain action needs it." })
15249
+ /* @__PURE__ */ jsx("h2", { className: "text-[21px] text-text-primary font-medium leading-tight", children: "Secure your account" }),
15250
+ /* @__PURE__ */ jsx("p", { className: "text-[13px] leading-relaxed text-text-secondary max-w-[340px] mx-auto", children: "A passkey means only you can approve what is done in your name \u2014 one tap with Face ID, a fingerprint or your PIN. You can also do this later." })
15312
15251
  ] }),
15313
15252
  hasSyntheticEmail && /* @__PURE__ */ jsxs("div", { className: "rounded-lg bg-status-warning-bg border border-status-warning-text/20 p-3 space-y-2", children: [
15314
15253
  /* @__PURE__ */ jsx("div", { className: "text-[11px] text-status-warning-text", children: "Your account email is a temporary placeholder. Set a real one so you can recover access and (if you ever want it) link Averer KYC." }),
@@ -15335,20 +15274,10 @@ function AddWalletsStep({ chrome } = {}) {
15335
15274
  )
15336
15275
  ] })
15337
15276
  ] }),
15338
- !loading && /* @__PURE__ */ jsx(
15339
- SetupStatusPanel,
15340
- {
15341
- keyCount,
15342
- busy
15343
- }
15344
- ),
15345
15277
  /* @__PURE__ */ jsx(SuccessMoment, { visible: canContinue && autoAdvanceArmed && !error }),
15346
- loading ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-dashed border-border-default bg-input-bg px-4 py-8 text-center text-[11px] text-text-secondary", children: "Loading\u2026" }) : keys.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-border-default bg-input-bg px-4 py-7 flex flex-col items-center gap-2.5", children: [
15347
- /* @__PURE__ */ jsx("div", { className: "w-11 h-11 rounded-full bg-chip flex items-center justify-center", children: /* @__PURE__ */ jsx(KeyIcon, { className: "h-5 w-5 text-text-secondary", strokeWidth: 1.5 }) }),
15348
- /* @__PURE__ */ jsx("div", { className: "text-[11px] text-text-secondary", children: "No signing keys yet" })
15349
- ] }) : /* @__PURE__ */ jsxs("div", { className: "bg-input-bg rounded-lg px-4 py-3.5 space-y-3", children: [
15278
+ loading ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-dashed border-border-default bg-input-bg px-4 py-8 text-center text-[11px] text-text-secondary", children: "Loading\u2026" }) : keys.length === 0 ? null : /* @__PURE__ */ jsxs("div", { className: "bg-input-bg rounded-lg px-4 py-3.5 space-y-3", children: [
15350
15279
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-[11px]", children: [
15351
- /* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "Signing keys" }),
15280
+ /* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "Your keys" }),
15352
15281
  /* @__PURE__ */ jsxs("span", { className: keyCount < RECOMMENDED_KEYS ? "text-status-warning-text" : "text-status-success-text", children: [
15353
15282
  keyCount === 1 && "1 key \xB7 add a backup",
15354
15283
  keyCount >= RECOMMENDED_KEYS && `${keyCount} keys`
@@ -15375,7 +15304,7 @@ function AddWalletsStep({ chrome } = {}) {
15375
15304
  }) })
15376
15305
  ] }),
15377
15306
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
15378
- /* @__PURE__ */ jsx("p", { className: "text-[11px] text-text-secondary text-center", children: !emailOk ? "Verify your email to unlock signing keys" : "Add a key" }),
15307
+ !emailOk ? /* @__PURE__ */ jsx("p", { className: "text-[11px] text-text-secondary text-center", children: "Confirm your email first" }) : null,
15379
15308
  !emailOk && /* @__PURE__ */ jsxs(
15380
15309
  "button",
15381
15310
  {
@@ -15395,37 +15324,48 @@ function AddWalletsStep({ chrome } = {}) {
15395
15324
  type: "button",
15396
15325
  onClick: addPasskey,
15397
15326
  disabled: busy !== null || !emailOk,
15398
- className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15399
- children: [
15400
- busy === "passkey" ? /* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "\u2026" }) : /* @__PURE__ */ jsx(KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15401
- /* @__PURE__ */ jsx("span", { children: "Add Passkey" })
15402
- ]
15403
- }
15404
- ),
15405
- /* @__PURE__ */ jsxs(
15406
- "button",
15407
- {
15408
- type: "button",
15409
- onClick: addMetaMask,
15410
- disabled: busy !== null || !emailOk,
15411
- className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15327
+ className: `w-full min-h-[46px] flex items-center justify-center gap-2 py-2.5 rounded-lg text-[13px] font-medium transition-colors active:scale-[0.99] disabled:opacity-40 disabled:cursor-not-allowed ${canContinue ? "bg-chip hover:bg-chip-hover text-text-primary" : "bg-cta hover:bg-cta-hover text-on-cta"}`,
15412
15328
  children: [
15413
- busy === "metamask" ? /* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "\u2026" }) : /* @__PURE__ */ jsx(KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15414
- /* @__PURE__ */ jsx("span", { children: "Add MetaMask" })
15329
+ busy === "passkey" ? /* @__PURE__ */ jsx("span", { children: "\u2026" }) : /* @__PURE__ */ jsx(KeyIcon, { className: "h-4 w-4", strokeWidth: 1.5 }),
15330
+ /* @__PURE__ */ jsx("span", { children: canContinue ? "Add another passkey" : "Add a passkey" })
15415
15331
  ]
15416
15332
  }
15417
15333
  ),
15418
- !!config?.auth.enabled.includes("dynamic") && !!config?.auth.settings.dynamic?.environment_id && /* @__PURE__ */ jsxs(
15334
+ walletsOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
15335
+ /* @__PURE__ */ jsxs(
15336
+ "button",
15337
+ {
15338
+ type: "button",
15339
+ onClick: addMetaMask,
15340
+ disabled: busy !== null || !emailOk,
15341
+ className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15342
+ children: [
15343
+ busy === "metamask" ? /* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "\u2026" }) : /* @__PURE__ */ jsx(KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15344
+ /* @__PURE__ */ jsx("span", { children: "Add MetaMask" })
15345
+ ]
15346
+ }
15347
+ ),
15348
+ !!config?.auth.enabled.includes("dynamic") && !!config?.auth.settings.dynamic?.environment_id && /* @__PURE__ */ jsxs(
15349
+ "button",
15350
+ {
15351
+ type: "button",
15352
+ onClick: () => setShowDynamic(true),
15353
+ disabled: busy !== null || !emailOk,
15354
+ className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15355
+ children: [
15356
+ /* @__PURE__ */ jsx(KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15357
+ /* @__PURE__ */ jsx("span", { children: "Add Dynamic" })
15358
+ ]
15359
+ }
15360
+ )
15361
+ ] }) : /* @__PURE__ */ jsx(
15419
15362
  "button",
15420
15363
  {
15421
15364
  type: "button",
15422
- onClick: () => setShowDynamic(true),
15423
- disabled: busy !== null || !emailOk,
15424
- className: "\n w-full min-h-[44px] flex items-center justify-center gap-2 py-2.5 rounded-lg\n bg-chip hover:bg-chip-hover\n text-[12px] text-text-primary\n transition-all duration-200\n active:scale-[0.98]\n disabled:opacity-40 disabled:cursor-not-allowed\n ",
15425
- children: [
15426
- /* @__PURE__ */ jsx(KeyIcon, { className: "h-4 w-4 text-text-secondary", strokeWidth: 1.5 }),
15427
- /* @__PURE__ */ jsx("span", { children: "Add Dynamic" })
15428
- ]
15365
+ onClick: () => setWalletsOpen(true),
15366
+ disabled: busy !== null,
15367
+ className: "w-full py-1.5 text-[11px] text-text-secondary hover:text-text-primary transition-colors disabled:opacity-40",
15368
+ children: "Use a crypto wallet instead"
15429
15369
  }
15430
15370
  )
15431
15371
  ] }),
@@ -15442,7 +15382,7 @@ function AddWalletsStep({ chrome } = {}) {
15442
15382
  registerOnChain: false,
15443
15383
  onComplete: async () => {
15444
15384
  setShowDynamic(false);
15445
- setStatus("Signing key saved. Refreshing\u2026");
15385
+ setStatus("Saved. One moment\u2026");
15446
15386
  await refresh({ invalidate: true });
15447
15387
  },
15448
15388
  onError: (m) => {
@@ -15474,15 +15414,24 @@ function AddWalletsStep({ chrome } = {}) {
15474
15414
  onRetry: retryLastFailure
15475
15415
  }
15476
15416
  ),
15477
- /* @__PURE__ */ jsx(
15417
+ canContinue ? /* @__PURE__ */ jsx(
15478
15418
  "button",
15479
15419
  {
15480
15420
  type: "button",
15481
15421
  onClick: onContinue,
15482
- disabled: !canContinue || busy === "continue",
15483
- className: "\n w-full min-h-[46px] py-3 rounded-lg\n bg-status-success-bg hover:opacity-80 text-status-success-text\n text-[13px] font-medium\n transition-all duration-200 active:scale-[0.99]\n disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:bg-status-success-bg\n ",
15422
+ disabled: busy === "continue",
15423
+ className: "w-full min-h-[46px] py-3 rounded-lg bg-cta hover:bg-cta-hover text-on-cta text-[13px] font-medium transition-colors active:scale-[0.99] disabled:opacity-40 disabled:cursor-not-allowed",
15484
15424
  children: continueLabel
15485
15425
  }
15426
+ ) : /* @__PURE__ */ jsx(
15427
+ "button",
15428
+ {
15429
+ type: "button",
15430
+ onClick: () => void onSkip(),
15431
+ disabled: busy !== null || !user?.id,
15432
+ className: "w-full py-2 text-[13px] text-text-secondary hover:text-text-primary transition-colors disabled:opacity-40",
15433
+ children: "Not now"
15434
+ }
15486
15435
  ),
15487
15436
  keyCount === 1 && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-text-secondary text-center pt-1", children: "Tip: a second key is your recovery path. If you lose your only key, the account is locked out." })
15488
15437
  ] }) });
@@ -23066,7 +23015,7 @@ function SecurityPage() {
23066
23015
  rotateStep === "added" || rotateStep === "removing" || rotateStep === "remove-pending" || rotateStep === "done" ? "\u2713 " : "1. ",
23067
23016
  "Add new key"
23068
23017
  ] }),
23069
- /* @__PURE__ */ jsx("span", { children: "\u2192" }),
23018
+ /* @__PURE__ */ jsx(ChevronRightIcon, { "aria-hidden": "true", className: "h-3 w-3" }),
23070
23019
  /* @__PURE__ */ jsxs("span", { className: rotateStep === "added" || rotateStep === "removing" || rotateStep === "remove-pending" ? "text-text-primary font-medium" : "", children: [
23071
23020
  rotateStep === "done" ? "\u2713 " : "2. ",
23072
23021
  "Remove old key"
@@ -23996,9 +23945,9 @@ var GroupsView = ({
23996
23945
  "aria-label": `${sourceGroup?.name ?? "Owning group"} is operating ${activeOwnedGroup?.name ?? "owned group"}`,
23997
23946
  children: [
23998
23947
  /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate rounded-lg border border-border-default dark:border-white/[0.08] bg-chip dark:bg-white/[0.035] px-2.5 py-1.5 text-[11px] font-semibold text-text-secondary", children: "You" }),
23999
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "shrink-0 text-[12px] text-azure dark:text-cyan-300/70", children: "\u2192" }),
23948
+ /* @__PURE__ */ jsx(ChevronRightIcon, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0 text-azure dark:text-cyan-300/70" }),
24000
23949
  /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate rounded-lg border border-border-default dark:border-white/[0.08] bg-chip dark:bg-white/[0.035] px-2.5 py-1.5 text-[11px] font-semibold text-text-secondary", children: sourceGroup?.name ?? compactGroupId(delegationSession.parentGroupId) }),
24001
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "shrink-0 text-[12px] text-azure dark:text-cyan-300/70", children: "\u2192" }),
23950
+ /* @__PURE__ */ jsx(ChevronRightIcon, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0 text-azure dark:text-cyan-300/70" }),
24002
23951
  /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate rounded-lg border border-azure-line dark:border-cyan-300/[0.18] bg-azure-tint dark:bg-cyan-300/[0.08] px-2.5 py-1.5 text-[11px] font-semibold text-azure dark:text-cyan-200", children: activeOwnedGroup?.name ?? compactGroupId(delegationSession.currentGroupId) })
24003
23952
  ]
24004
23953
  }
@@ -24362,7 +24311,7 @@ function OwnedGroupRow({
24362
24311
  return /* @__PURE__ */ jsxs("li", { className: "px-3.5 py-3", children: [
24363
24312
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
24364
24313
  /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-[11px] font-semibold text-text-secondary", children: sourceName }),
24365
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "shrink-0 text-[12px] text-azure dark:text-cyan-300/70", children: "\u2192" }),
24314
+ /* @__PURE__ */ jsx(ChevronRightIcon, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0 text-azure dark:text-cyan-300/70" }),
24366
24315
  /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-[12px] font-semibold text-text-primary", children: projection.group.name })
24367
24316
  ] }),
24368
24317
  /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center justify-between gap-3", children: [
@@ -29706,7 +29655,7 @@ var VerificationDialog = ({
29706
29655
  type: "button",
29707
29656
  onClick: () => setActiveProvider(null),
29708
29657
  className: "mb-3 text-[12px] text-text-secondary hover:text-text-primary",
29709
- children: "\u2190 Choose a different provider"
29658
+ children: "\u2039 Choose a different provider"
29710
29659
  }
29711
29660
  ),
29712
29661
  /* @__PURE__ */ jsx(
@@ -29869,7 +29818,7 @@ function BusinessVerificationSection({
29869
29818
  type: "button",
29870
29819
  onClick: () => setFlowInstance(null),
29871
29820
  className: "mb-3 text-[12px] text-text-secondary hover:text-text-primary",
29872
- children: "\u2190 Back"
29821
+ children: "\u2039 Back"
29873
29822
  }
29874
29823
  ),
29875
29824
  /* @__PURE__ */ jsx(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yieldfabric/wallet",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Reusable YieldFabric wallet — login, signing, profile, and key management",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "YieldFabric Technologies Ltd",