@seams/wallet 0.14.0 → 0.15.1

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.
Files changed (87) hide show
  1. package/dist/.build-inputs.sha256 +1 -1
  2. package/dist/esm/SeamsWeb/publicApi/keyExport.js +0 -2
  3. package/dist/esm/SeamsWeb/walletIframe/client/router.js +0 -4
  4. package/dist/esm/SeamsWeb/walletIframe/shared/facadeBoundary.js +0 -4
  5. package/dist/esm/core/signingEngine/routerAb/ecdsaDerivation/presignaturePool.js +24 -27
  6. package/dist/esm/plugins/plugin-utils.js +2 -142
  7. package/dist/esm/react/components/AccountMenuButton/AccountMenuDialog.js +13 -89
  8. package/dist/esm/react/components/AccountMenuButton/AccountsSection.css +7 -1
  9. package/dist/esm/react/components/AccountMenuButton/AuthenticationMethodRow.js +2 -8
  10. package/dist/esm/react/components/AccountMenuButton/AuthenticationMethodsModal.js +4 -17
  11. package/dist/esm/react/components/AccountMenuButton/ExportKeysSection.css +7 -1
  12. package/dist/esm/react/components/AccountMenuButton/LinkedDevicesModal.css +0 -68
  13. package/dist/esm/react/components/AccountMenuButton/LinkedDevicesModal.js +2 -11
  14. package/dist/esm/react/components/AccountMenuButton/Web3AuthProfileButton.css +95 -3
  15. package/dist/esm/react/components/AccountMenuButton/icons/HoverArrowIcon.js +26 -0
  16. package/dist/esm/react/components/AccountMenuButton/index.js +4 -4
  17. package/dist/esm/react/styles/styles.css +102 -4
  18. package/dist/esm/sdk/ecdsaDerivationExport-DOGzq0qC.js +1 -0
  19. package/dist/esm/sdk/exportKeypairOperation-DzbjKbnk.js +1 -0
  20. package/dist/esm/sdk/{host-D3Q_NsmE.js → host-DYuu07E5.js} +1 -1
  21. package/dist/{public/sdk/presignaturePool-DX_hqZ6Z.js → esm/sdk/presignaturePool-V10fZpG3.js} +1 -1
  22. package/dist/esm/sdk/{runtime-auth-DDOPe7LO.js → runtime-auth-BNR1wI8E.js} +1 -1
  23. package/dist/esm/sdk/{runtime-device-link-Bkt5AJAI.js → runtime-device-link-Dq8g_UNb.js} +1 -1
  24. package/dist/{public/sdk/runtime-ecdsa-tempo-DUOkCNFT.js → esm/sdk/runtime-ecdsa-tempo-AGjT7Xpa.js} +1 -1
  25. package/dist/esm/sdk/{runtime-email-otp-Bsv55Gin.js → runtime-email-otp-BpBOuSsT.js} +1 -1
  26. package/dist/esm/sdk/{runtime-export-D7QKXvdg.js → runtime-export-CBsacCPY.js} +1 -1
  27. package/dist/esm/sdk/{runtime-near-Bl7bBU2g.js → runtime-near-J3hKjC7G.js} +1 -1
  28. package/dist/esm/sdk/{runtime-preferences-C2Rqmp7q.js → runtime-preferences-CVt5sLvm.js} +1 -1
  29. package/dist/esm/sdk/{runtime-recovery-BMY7AkJq.js → runtime-recovery-BzewdcoT.js} +1 -1
  30. package/dist/{public/sdk/secp256k1-CL273JMp.js → esm/sdk/secp256k1-CKq7_HD-.js} +1 -1
  31. package/dist/esm/sdk/shared-BywEqTsd.js +6 -0
  32. package/dist/esm/sdk/{signEvmFamily-BE0a14MT.js → signEvmFamily-Cpm3e6Zs.js} +1 -1
  33. package/dist/esm/sdk/wallet-iframe-host-ecdsa.js +1 -1
  34. package/dist/esm/sdk/wallet-iframe-host-full.js +1 -1
  35. package/dist/esm/sdk/wallet-iframe-host-near.js +1 -1
  36. package/dist/esm/sdk/wallet-iframe-host-runtime.js +1 -1
  37. package/dist/public/headers.manifest.json +1 -1
  38. package/dist/public/sdk/ecdsaDerivationExport-DOGzq0qC.js +1 -0
  39. package/dist/public/sdk/exportKeypairOperation-DzbjKbnk.js +1 -0
  40. package/dist/public/sdk/{host-D3Q_NsmE.js → host-DYuu07E5.js} +1 -1
  41. package/dist/{esm/sdk/presignaturePool-DX_hqZ6Z.js → public/sdk/presignaturePool-V10fZpG3.js} +1 -1
  42. package/dist/public/sdk/{runtime-auth-DDOPe7LO.js → runtime-auth-BNR1wI8E.js} +1 -1
  43. package/dist/public/sdk/{runtime-device-link-Bkt5AJAI.js → runtime-device-link-Dq8g_UNb.js} +1 -1
  44. package/dist/{esm/sdk/runtime-ecdsa-tempo-DUOkCNFT.js → public/sdk/runtime-ecdsa-tempo-AGjT7Xpa.js} +1 -1
  45. package/dist/public/sdk/{runtime-email-otp-Bsv55Gin.js → runtime-email-otp-BpBOuSsT.js} +1 -1
  46. package/dist/public/sdk/{runtime-export-D7QKXvdg.js → runtime-export-CBsacCPY.js} +1 -1
  47. package/dist/public/sdk/{runtime-near-Bl7bBU2g.js → runtime-near-J3hKjC7G.js} +1 -1
  48. package/dist/public/sdk/{runtime-preferences-C2Rqmp7q.js → runtime-preferences-CVt5sLvm.js} +1 -1
  49. package/dist/public/sdk/{runtime-recovery-BMY7AkJq.js → runtime-recovery-BzewdcoT.js} +1 -1
  50. package/dist/{esm/sdk/secp256k1-CL273JMp.js → public/sdk/secp256k1-CKq7_HD-.js} +1 -1
  51. package/dist/public/sdk/shared-BywEqTsd.js +6 -0
  52. package/dist/public/sdk/{signEvmFamily-BE0a14MT.js → signEvmFamily-Cpm3e6Zs.js} +1 -1
  53. package/dist/public/sdk/wallet-iframe-host-ecdsa.js +1 -1
  54. package/dist/public/sdk/wallet-iframe-host-full.js +1 -1
  55. package/dist/public/sdk/wallet-iframe-host-near.js +1 -1
  56. package/dist/public/sdk/wallet-iframe-host-runtime.js +1 -1
  57. package/dist/public/wallet-assets.manifest.json +32 -32
  58. package/dist/public/wallet-service/index.html +4 -4
  59. package/dist/types/shared-ts/src/device-linking/contracts.d.ts +0 -9
  60. package/dist/types/shared-ts/src/utils/routerAbEcdsaDerivation.d.ts +0 -1
  61. package/dist/types/wallet/src/SeamsWeb/operations/auth/login.d.ts +1 -2
  62. package/dist/types/wallet/src/SeamsWeb/publicApi/types.d.ts +2 -11
  63. package/dist/types/wallet/src/core/signingEngine/flows/recovery/keyExportFlow.d.ts +0 -3
  64. package/dist/types/wallet/src/core/signingEngine/routerAb/ecdsaDerivation/presignaturePool.d.ts +0 -19
  65. package/dist/types/wallet/src/core/signingEngine/session/identity/ownerLaneScope.d.ts +0 -27
  66. package/dist/types/wallet/src/plugins/plugin-utils.d.ts +0 -30
  67. package/dist/types/wallet/src/react/components/AccountMenuButton/AccountMenuDialog.d.ts +1 -9
  68. package/dist/types/wallet/src/react/components/AccountMenuButton/AuthenticationMethodsModal.d.ts +1 -1
  69. package/dist/types/wallet/src/react/components/AccountMenuButton/LinkedDevicesModal.d.ts +1 -1
  70. package/dist/types/wallet/src/react/components/AccountMenuButton/icons/HoverArrowIcon.d.ts +7 -0
  71. package/package.json +1 -1
  72. package/dist/esm/plugins/headers.js +0 -55
  73. package/dist/esm/plugins/next.js +0 -196
  74. package/dist/esm/plugins/shared-ts/src/utils/normalize.js +0 -31
  75. package/dist/esm/plugins/vite.js +0 -293
  76. package/dist/esm/react/components/AccountMenuButton/icons/LayersIcon.js +0 -8
  77. package/dist/esm/sdk/ecdsaDerivationExport-CuNIssOt.js +0 -1
  78. package/dist/esm/sdk/exportKeypairOperation-Bql0I-8U.js +0 -1
  79. package/dist/esm/sdk/shared-CNT5EU_h.js +0 -6
  80. package/dist/public/sdk/ecdsaDerivationExport-CuNIssOt.js +0 -1
  81. package/dist/public/sdk/exportKeypairOperation-Bql0I-8U.js +0 -1
  82. package/dist/public/sdk/shared-CNT5EU_h.js +0 -6
  83. package/dist/types/wallet/src/plugins/headers.d.ts +0 -25
  84. package/dist/types/wallet/src/plugins/next.d.ts +0 -66
  85. package/dist/types/wallet/src/plugins/vite.d.ts +0 -74
  86. package/dist/types/wallet/src/react/components/AccountMenuButton/icons/LayersIcon.d.ts +0 -2
  87. /package/dist/esm/plugins/{wallet/src/core → core}/browser/walletIframe/hostVariant.js +0 -0
@@ -1 +1 @@
1
- 8d2cd0725d2642fe2d0e9193405bbf21ae5ff7db964113586f3fdbc177f198c8
1
+ 56dfa3066068a5f5ad802cb10bfd073c092a4fde4e47e508b35776539f0bcfd1
@@ -32,7 +32,6 @@ async function exportKey(deps, input) {
32
32
  };
33
33
  requireKeyExportCapability(deps.configs, laneInput);
34
34
  const lane = await deps.domain.resolveExactKeyExportLane(laneInput);
35
- if (lane.kind === "relink_required") return lane;
36
35
  if (lane.kind !== "ed25519") throw new Error(`[key-export] expected an Ed25519 lane, received ${lane.kind}`);
37
36
  await deps.domain.exportKeypairWithUI({
38
37
  ...laneInput,
@@ -49,7 +48,6 @@ async function exportKey(deps, input) {
49
48
  };
50
49
  requireKeyExportCapability(deps.configs, laneInput);
51
50
  const lane = await deps.domain.resolveExactKeyExportLane(laneInput);
52
- if (lane.kind === "relink_required") return lane;
53
51
  if (lane.kind !== "ecdsa") throw new Error(`[key-export] expected an ECDSA lane, received ${lane.kind}`);
54
52
  await deps.domain.exportKeypairWithUI({
55
53
  ...laneInput,
@@ -242,10 +242,6 @@ function walletIframeLoginStatusFromExactSession(state) {
242
242
  }
243
243
  function parseResolveExactKeyExportLaneResult(result) {
244
244
  switch (result.kind) {
245
- case "relink_required": return {
246
- kind: "relink_required",
247
- reason: result.reason
248
- };
249
245
  case "ecdsa": return {
250
246
  kind: "ecdsa",
251
247
  laneIdentity: parseExactEcdsaSigningLaneIdentity(result.laneIdentity)
@@ -19,10 +19,6 @@ function normalizeResolveExactKeyExportLaneInput(input) {
19
19
  }
20
20
  function normalizeResolveExactKeyExportLaneResult(result) {
21
21
  switch (result.kind) {
22
- case "relink_required": return {
23
- kind: "relink_required",
24
- reason: result.reason
25
- };
26
22
  case "ecdsa": return {
27
23
  kind: "ecdsa",
28
24
  laneIdentity: parseExactEcdsaSigningLaneIdentity(result.laneIdentity)
@@ -704,7 +704,7 @@ function resolveSigningRequestExpiresAtMs(input) {
704
704
  const expiresAtMs = Math.min(materialExpiresAtMs, authorizationExpiresAtMs, input.nowMs + ROUTER_AB_ECDSA_DERIVATION_SIGNING_TTL_MS);
705
705
  return Number.isSafeInteger(expiresAtMs) && expiresAtMs > input.nowMs ? expiresAtMs : null;
706
706
  }
707
- async function signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, retryCount, supply) {
707
+ async function signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, retryCount, refillInput) {
708
708
  let poolKey = null;
709
709
  let poolIdentity = null;
710
710
  let presignature = null;
@@ -792,16 +792,16 @@ async function signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, retryCo
792
792
  workerCtx: args.workerCtx
793
793
  });
794
794
  }
795
- if (!presignature && supply.kind === "on_demand") {
795
+ if (!presignature) {
796
796
  const foregroundRefillStartedAt = performance.now();
797
797
  startForegroundRefill(poolKey);
798
798
  try {
799
799
  let refill = await refillRouterAbEcdsaDerivationClientPresignaturePool({
800
- ...supply.refill,
800
+ ...refillInput,
801
801
  trafficClass: "foreground"
802
802
  });
803
803
  if (!refill.ok && refill.code === "invalidated") refill = await refillRouterAbEcdsaDerivationClientPresignaturePool({
804
- ...supply.refill,
804
+ ...refillInput,
805
805
  trafficClass: "foreground"
806
806
  });
807
807
  if (!refill.ok && refill.code !== "pool_full") return refill;
@@ -884,7 +884,7 @@ async function signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, retryCo
884
884
  emitEcdsaSigningTiming(args.operationId, "presignature_reserve", reserveStartedAt);
885
885
  if (reservation.kind === "unavailable") {
886
886
  if (reservation.reason === "claimed_elsewhere") clientPresignatureCleanupState = { kind: "owned_elsewhere" };
887
- if (retryCount < MAX_CLIENT_PRESIGNATURE_CLAIM_RETRIES) return await signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, retryCount + 1, supply);
887
+ if (retryCount < MAX_CLIENT_PRESIGNATURE_CLAIM_RETRIES) return await signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, retryCount + 1, refillInput);
888
888
  return {
889
889
  ok: false,
890
890
  code: reservation.reason === "expired" ? "pool_entry_expired" : "pool_entry_unavailable",
@@ -1066,29 +1066,26 @@ async function signRouterAbEcdsaDerivationDigestWithPool(args) {
1066
1066
  code: "invalid_pool_fill_expiry",
1067
1067
  message: "Router A/B ECDSA derivation pool fill expiry is unavailable or expired"
1068
1068
  };
1069
- const supply = {
1070
- kind: "on_demand",
1071
- refill: {
1072
- relayerUrl: args.relayerUrl,
1073
- keyHandle: args.keyHandle,
1074
- ecdsaThresholdKeyId: signingIdentity.ecdsaThresholdKeyId,
1075
- clientVerifyingShareB64u: signingIdentity.clientVerifyingShareB64u,
1076
- clientSigningMaterial: args.clientSigningMaterial,
1077
- thresholdEcdsaPublicKeyB64u: signingIdentity.thresholdEcdsaPublicKeyB64u,
1078
- credential: args.credential,
1079
- materialActivation: args.materialActivation,
1080
- routerAbEcdsaDerivationPoolFill: {
1081
- kind: "router_ab_ecdsa_derivation_signing_worker_pool",
1082
- scope: args.scope,
1083
- ceremonyExpiresAtMs: Math.min(expiresAtMs, Date.now() + ROUTER_AB_ECDSA_PRESIGN_CEREMONY_MAX_LIFETIME_MS - PRESIGN_CEREMONY_CLOCK_SKEW_MARGIN_MS),
1084
- materialExpiresAtMs: args.authorization.kind === "operation_step_up" ? expiresAtMs : Date.now() + MAX_DURABLE_CLIENT_PRESIGNATURE_LIFETIME_MS
1085
- },
1086
- workerCtx: args.workerCtx,
1087
- ...ecdsaPoolFillAuthorization(args)
1088
- }
1069
+ const refillInput = {
1070
+ relayerUrl: args.relayerUrl,
1071
+ keyHandle: args.keyHandle,
1072
+ ecdsaThresholdKeyId: signingIdentity.ecdsaThresholdKeyId,
1073
+ clientVerifyingShareB64u: signingIdentity.clientVerifyingShareB64u,
1074
+ clientSigningMaterial: args.clientSigningMaterial,
1075
+ thresholdEcdsaPublicKeyB64u: signingIdentity.thresholdEcdsaPublicKeyB64u,
1076
+ credential: args.credential,
1077
+ materialActivation: args.materialActivation,
1078
+ routerAbEcdsaDerivationPoolFill: {
1079
+ kind: "router_ab_ecdsa_derivation_signing_worker_pool",
1080
+ scope: args.scope,
1081
+ ceremonyExpiresAtMs: Math.min(expiresAtMs, Date.now() + ROUTER_AB_ECDSA_PRESIGN_CEREMONY_MAX_LIFETIME_MS - PRESIGN_CEREMONY_CLOCK_SKEW_MARGIN_MS),
1082
+ materialExpiresAtMs: args.authorization.kind === "operation_step_up" ? expiresAtMs : Date.now() + MAX_DURABLE_CLIENT_PRESIGNATURE_LIFETIME_MS
1083
+ },
1084
+ workerCtx: args.workerCtx,
1085
+ ...ecdsaPoolFillAuthorization(args)
1089
1086
  };
1090
- const result = await signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, 0, supply);
1091
- if (!result.ok && (result.code === "pool_entry_expired" || result.code === "pool_entry_unavailable")) return await signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, 0, supply);
1087
+ const result = await signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, 0, refillInput);
1088
+ if (!result.ok && (result.code === "pool_entry_expired" || result.code === "pool_entry_unavailable")) return await signRouterAbEcdsaDerivationDigestWithPoolHitAttempt(args, 0, refillInput);
1092
1089
  return result;
1093
1090
  }
1094
1091
  async function refillRouterAbEcdsaDerivationClientPresignaturePool(args) {
@@ -1,27 +1,5 @@
1
- import "./shared-ts/src/utils/normalize.js";
2
- import { normalizeWalletHostVariant, walletHostScriptFileForVariant } from "./wallet/src/core/browser/walletIframe/hostVariant.js";
3
- import * as fs from "node:fs";
4
- import * as path from "node:path";
5
- import { createRequire } from "node:module";
1
+ import { normalizeWalletHostVariant, walletHostScriptFileForVariant } from "./core/browser/walletIframe/hostVariant.js";
6
2
  //#region src/plugins/plugin-utils.ts
7
- function addPreconnectLink(res, origin) {
8
- if (!origin) return;
9
- try {
10
- const link = `<${origin}>; rel=preconnect; crossorigin`;
11
- const existing = res.getHeader?.("Link");
12
- if (!existing) {
13
- res.setHeader?.("Link", link);
14
- return;
15
- }
16
- if (typeof existing === "string") {
17
- if (!existing.includes(link)) res.setHeader?.("Link", existing + ", " + link);
18
- return;
19
- }
20
- if (Array.isArray(existing)) {
21
- if (!existing.includes(link)) res.setHeader?.("Link", [...existing, link]);
22
- }
23
- } catch {}
24
- }
25
3
  function withAssetVersion(url, assetVersion) {
26
4
  const version = String(assetVersion || "").trim();
27
5
  if (!version) return url;
@@ -50,125 +28,7 @@ function buildWalletServiceHtml(sdkBasePath = "/sdk", assetVersion, walletHostVa
50
28
  </body>
51
29
  </html>`;
52
30
  }
53
- function resolveCoepMode(explicit) {
54
- if (explicit === "strict" || explicit === "off") return explicit;
55
- const raw = String(globalThis?.process?.env?.VITE_COEP_MODE || "").trim().toLowerCase();
56
- if (raw === "strict" || raw === "on" || raw === "1" || raw === "require-corp") return "strict";
57
- if (raw === "off" || raw === "0" || raw === "false") return "off";
58
- return "off";
59
- }
60
- function applyCoepCorp(res) {
61
- res.setHeader?.("Cross-Origin-Embedder-Policy", "require-corp");
62
- res.setHeader?.("Cross-Origin-Resource-Policy", "cross-origin");
63
- }
64
- function applyCoepCorpIfNeeded(res, coepMode) {
65
- if (resolveCoepMode(coepMode) !== "off") applyCoepCorp(res);
66
- }
67
- function echoCorsFromRequest(res, req, opts = {}) {
68
- const honorExisting = opts.honorExistingAcaOrigin === true;
69
- const allowCreds = opts.allowCredentialsWhenExplicit !== false;
70
- const methods = opts.methods || "GET,OPTIONS";
71
- const headers = opts.headers || "Content-Type,Authorization";
72
- const handlePreflight = opts.handlePreflight === true;
73
- const origin = req?.headers && req.headers.origin || "*";
74
- const hasExisting = typeof res.getHeader === "function" && !!res.getHeader("Access-Control-Allow-Origin");
75
- if (!honorExisting || !hasExisting) res.setHeader?.("Access-Control-Allow-Origin", origin);
76
- res.setHeader?.("Vary", "Origin");
77
- res.setHeader?.("Access-Control-Allow-Methods", methods);
78
- res.setHeader?.("Access-Control-Allow-Headers", headers);
79
- if (origin !== "*" && allowCreds) res.setHeader?.("Access-Control-Allow-Credentials", "true");
80
- if (handlePreflight) {
81
- if ((req?.method && String(req.method).toUpperCase()) === "OPTIONS") {
82
- res.statusCode = 204;
83
- res.end?.();
84
- return true;
85
- }
86
- }
87
- return false;
88
- }
89
- /**
90
- * Log and validate Related Origin Requests (ROR) configuration.
91
- * - Prints the well-known endpoint and the configured origins list.
92
- * - Warns if any origins are not absolute (e.g., missing protocol/hostname).
93
- */
94
- function logRorConfig(origins, endpoint = "/.well-known/webauthn") {
95
- if (!Array.isArray(origins) || origins.length === 0) return;
96
- const invalid = [];
97
- for (const o of origins) try {
98
- const u = new URL(o);
99
- if (!u.protocol || !u.hostname) invalid.push(o);
100
- } catch {
101
- invalid.push(o);
102
- }
103
- const msg = `[seams] ROR enabled: GET ${endpoint} -> { origins: [${origins.join(", ")}] }`;
104
- console.log(msg);
105
- if (invalid.length > 0) console.warn(`[seams] ROR warning: invalid origins: ${invalid.join(", ")} (expected absolute origins like https://app.example.com)`);
106
- }
107
- function sanitizeOrigins(values) {
108
- const out = /* @__PURE__ */ new Set();
109
- if (Array.isArray(values)) for (const v of values) {
110
- if (typeof v !== "string") continue;
111
- try {
112
- const u = new URL(v.trim());
113
- const scheme = u.protocol;
114
- const host = u.hostname.toLowerCase();
115
- const port = u.port ? `:${u.port}` : "";
116
- if (!(scheme === "https:") && !(scheme === "http:" && host === "localhost")) continue;
117
- if (u.pathname && u.pathname !== "/" || u.search || u.hash) continue;
118
- out.add(`${scheme}//${host}${port}`);
119
- } catch {}
120
- }
121
- return Array.from(out);
122
- }
123
- function parseConfiguredRorOrigins(value) {
124
- return value.split(",").map((s) => s.trim()).filter(Boolean);
125
- }
126
- function resolveRorOrigins(input) {
127
- return sanitizeOrigins([
128
- ...input.configuredOrigins,
129
- input.docsOrigin.trim(),
130
- input.walletOrigin.trim()
131
- ]);
132
- }
133
- /**
134
- * Infer and set a proper Content-Type header for a given file path.
135
- * Shared by both app and wallet-iframe dev servers.
136
- */
137
- function setContentType(res, filePath) {
138
- switch (path.extname(filePath)) {
139
- case ".js":
140
- res.setHeader("Content-Type", "application/javascript; charset=utf-8");
141
- break;
142
- case ".css":
143
- res.setHeader("Content-Type", "text/css; charset=utf-8");
144
- break;
145
- case ".map":
146
- case ".json":
147
- res.setHeader("Content-Type", "application/json; charset=utf-8");
148
- break;
149
- case ".wasm":
150
- res.setHeader("Content-Type", "application/wasm");
151
- break;
152
- case ".html":
153
- res.setHeader("Content-Type", "text/html; charset=utf-8");
154
- break;
155
- default: res.setHeader("Content-Type", "application/octet-stream");
156
- }
157
- }
158
- const requireCjs = createRequire(import.meta.url);
159
- function resolveSdkDistRoot(explicit) {
160
- if (explicit) return path.resolve(explicit);
161
- const pkgPath = requireCjs.resolve("@seams/wallet/package.json");
162
- const pkgDir = path.dirname(pkgPath);
163
- try {
164
- const esmEntry = JSON.parse(fs.readFileSync(pkgPath, "utf8")).module || "dist/esm/index.js";
165
- const esmAbs = path.resolve(pkgDir, esmEntry);
166
- return path.resolve(path.dirname(esmAbs), "..");
167
- } catch {
168
- return path.join(pkgDir, "dist");
169
- }
170
- }
171
31
  //#endregion
172
- export { addPreconnectLink, applyCoepCorpIfNeeded, buildWalletServiceHtml, echoCorsFromRequest, logRorConfig, parseConfiguredRorOrigins, resolveCoepMode, resolveRorOrigins, resolveSdkDistRoot, setContentType };
32
+ export { buildWalletServiceHtml };
173
33
 
174
34
  //# sourceMappingURL=plugin-utils.js.map
@@ -1,58 +1,9 @@
1
1
  import { Theme, useTheme } from "../theme/ThemeProvider.js";
2
2
  import { AccountMenuScreen } from "./AccountMenuScreen.js";
3
- import { LockKeyholeIcon } from "./icons/LockKeyholeIcon.js";
4
- import { LayersIcon } from "./icons/LayersIcon.js";
5
- import React, { useEffect } from "react";
3
+ import React from "react";
6
4
  import { jsx, jsxs } from "react/jsx-runtime";
7
5
  //#region src/react/components/AccountMenuButton/AccountMenuDialog.tsx
8
- function useAccountMenuDialogKeyboard(input) {
9
- const { isOpen, presentation, onClose, dialogRef, focusableSelector } = input;
10
- const previousFocusRef = React.useRef(null);
11
- const handleDialogKeyDown = React.useCallback((event) => {
12
- if (event.key === "Escape" || event.key === "Esc") {
13
- event.preventDefault();
14
- onClose();
15
- return;
16
- }
17
- if (event.key !== "Tab" || !dialogRef.current) return;
18
- const focusable = Array.from(dialogRef.current.querySelectorAll(focusableSelector));
19
- if (focusable.length === 0) {
20
- event.preventDefault();
21
- dialogRef.current.focus();
22
- return;
23
- }
24
- const first = focusable[0];
25
- const last = focusable[focusable.length - 1];
26
- if (event.shiftKey && document.activeElement === first) {
27
- event.preventDefault();
28
- last.focus();
29
- } else if (!event.shiftKey && document.activeElement === last) {
30
- event.preventDefault();
31
- first.focus();
32
- }
33
- }, [
34
- dialogRef,
35
- focusableSelector,
36
- onClose
37
- ]);
38
- useEffect(() => {
39
- if (!isOpen || presentation !== "modal") return;
40
- previousFocusRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
41
- dialogRef.current?.focus({ preventScroll: true });
42
- window.addEventListener("keydown", handleDialogKeyDown);
43
- return () => {
44
- window.removeEventListener("keydown", handleDialogKeyDown);
45
- previousFocusRef.current?.focus();
46
- previousFocusRef.current = null;
47
- };
48
- }, [
49
- dialogRef,
50
- handleDialogKeyDown,
51
- isOpen,
52
- presentation
53
- ]);
54
- }
55
- const AccountMenuDialogFrame = ({ presentation, onClose, dialogRef, contentClassName, titleId, title, closeLabel, children }) => {
6
+ const AccountMenuDialogFrame = ({ presentation, onClose, dialogRef, contentClassName, titleId, title, children }) => {
56
7
  const { theme, tokens } = useTheme();
57
8
  const scopedTokens = React.useMemo(() => theme === "dark" ? { dark: tokens } : { light: tokens }, [theme, tokens]);
58
9
  if (presentation === "embedded") return /* @__PURE__ */ jsx(AccountMenuScreen, {
@@ -68,52 +19,25 @@ const AccountMenuDialogFrame = ({ presentation, onClose, dialogRef, contentClass
68
19
  className: `seams-linked-devices-modal-backdrop theme-${theme}`,
69
20
  "data-presentation": presentation,
70
21
  role: "presentation",
71
- onMouseDown: (event) => {
72
- if (presentation === "modal" && event.target === event.currentTarget) onClose();
73
- },
74
- children: /* @__PURE__ */ jsxs("div", {
22
+ children: /* @__PURE__ */ jsx("div", {
75
23
  ref: dialogRef,
76
24
  className: `seams-linked-devices-modal-content ${contentClassName}`,
77
- role: presentation === "modal" ? "dialog" : "region",
78
- "aria-modal": presentation === "modal" ? true : void 0,
25
+ role: "region",
79
26
  "aria-labelledby": titleId,
80
27
  tabIndex: -1,
81
- children: [
82
- presentation === "modal" ? /* @__PURE__ */ jsxs("header", {
83
- className: "seams-account-menu-dialog-header",
84
- children: [
85
- /* @__PURE__ */ jsx(LockKeyholeIcon, { size: 13 }),
86
- /* @__PURE__ */ jsx("span", {
87
- className: "seams-account-menu-dialog-host",
88
- children: window.location.host
89
- }),
90
- /* @__PURE__ */ jsx("button", {
91
- type: "button",
92
- className: "seams-linked-devices-modal-close",
93
- onClick: onClose,
94
- "aria-label": closeLabel,
95
- children: "✕"
96
- })
97
- ]
98
- }) : null,
99
- /* @__PURE__ */ jsxs("div", {
100
- className: "seams-account-menu-dialog-main",
101
- children: [/* @__PURE__ */ jsx("h2", {
102
- id: titleId,
103
- className: "seams-linked-devices-modal-title",
104
- children: title
105
- }), children]
106
- }),
107
- presentation === "modal" ? /* @__PURE__ */ jsxs("footer", {
108
- className: "seams-account-menu-dialog-footer",
109
- children: [/* @__PURE__ */ jsx(LayersIcon, { size: 13 }), "Powered by seams"]
110
- }) : null
111
- ]
28
+ children: /* @__PURE__ */ jsxs("div", {
29
+ className: "seams-account-menu-dialog-main",
30
+ children: [/* @__PURE__ */ jsx("h2", {
31
+ id: titleId,
32
+ className: "seams-linked-devices-modal-title",
33
+ children: title
34
+ }), children]
35
+ })
112
36
  })
113
37
  })
114
38
  });
115
39
  };
116
40
  //#endregion
117
- export { AccountMenuDialogFrame, useAccountMenuDialogKeyboard };
41
+ export { AccountMenuDialogFrame };
118
42
 
119
43
  //# sourceMappingURL=AccountMenuDialog.js.map
@@ -49,7 +49,13 @@
49
49
  }
50
50
 
51
51
  .seams-accounts-row:hover {
52
- background: var(--seams-colors-surface2);
52
+ /* a shade off the expander surface behind the rows, which is often surface2;
53
+ mixing follows a theme's surface where a fixed surface step does not */
54
+ background: color-mix(
55
+ in srgb,
56
+ var(--seams-colors-textPrimary) 7%,
57
+ var(--seams-expander-surface, var(--seams-colors-surface))
58
+ );
53
59
  }
54
60
 
55
61
  .seams-accounts-row-chain {
@@ -1,5 +1,6 @@
1
1
  import TouchIcon from "./icons/TouchIcon.js";
2
2
  import { MailIcon } from "./icons/MailIcon.js";
3
+ import { HoverArrowIcon } from "./icons/HoverArrowIcon.js";
3
4
  import "react";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  //#region src/react/components/AccountMenuButton/AuthenticationMethodRow.tsx
@@ -23,14 +24,7 @@ function AuthenticationMethodRow({ kind, title, description, icon, action, onSel
23
24
  }))
24
25
  }),
25
26
  /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("strong", { children: title }), /* @__PURE__ */ jsx("small", { children: description })] }),
26
- /* @__PURE__ */ jsx("svg", {
27
- viewBox: "0 0 24 24",
28
- fill: "none",
29
- stroke: "currentColor",
30
- strokeWidth: "1.5",
31
- "aria-hidden": "true",
32
- children: /* @__PURE__ */ jsx("path", { d: "m9 6 6 6-6 6" })
33
- })
27
+ /* @__PURE__ */ jsx(HoverArrowIcon, {})
34
28
  ]
35
29
  })
36
30
  });
@@ -1,5 +1,5 @@
1
1
  import { useSeams } from "../../context/index.js";
2
- import { AccountMenuDialogFrame, useAccountMenuDialogKeyboard } from "./AccountMenuDialog.js";
2
+ import { AccountMenuDialogFrame } from "./AccountMenuDialog.js";
3
3
  import { AuthenticationMethodRow } from "./AuthenticationMethodRow.js";
4
4
  import { AuthenticationMethodsView } from "./AuthenticationMethodsView.js";
5
5
  import { PlusIcon } from "./icons/PlusIcon.js";
@@ -95,7 +95,6 @@ function currentAuthorityInventory(input) {
95
95
  }
96
96
  throw new Error("The selected authentication method is unavailable on this device authority.");
97
97
  }
98
- const FOCUSABLE_DIALOG_ELEMENTS = "button:not([disabled]), input:not([disabled]), [href], [tabindex]:not([tabindex=\"-1\"])";
99
98
  function methodTitle(method) {
100
99
  return method.kind === "passkey" ? "Passkey" : "Email OTP";
101
100
  }
@@ -113,7 +112,7 @@ function inventoryStatus(state) {
113
112
  case "loaded": return state.inventory.kind === "local_selection" ? "Unlock to manage" : "Active";
114
113
  }
115
114
  }
116
- const AuthenticationMethodsModal = ({ walletId, isOpen, onClose, presentation = "modal" }) => {
115
+ const AuthenticationMethodsModal = ({ walletId, isOpen, onClose, presentation }) => {
117
116
  const { seams, loginState, refreshSession } = useSeams();
118
117
  const [loadState, setLoadState] = React.useState({ kind: "idle" });
119
118
  const [actionState, setActionState] = React.useState({ kind: "idle" });
@@ -184,13 +183,6 @@ const AuthenticationMethodsModal = ({ walletId, isOpen, onClose, presentation =
184
183
  });
185
184
  }
186
185
  }, [selectedWalletAuthMethodId, walletId]);
187
- useAccountMenuDialogKeyboard({
188
- isOpen,
189
- presentation,
190
- onClose,
191
- dialogRef,
192
- focusableSelector: FOCUSABLE_DIALOG_ELEMENTS
193
- });
194
186
  useEffect(() => {
195
187
  if (!isOpen) {
196
188
  loadSequence.current += 1;
@@ -280,10 +272,8 @@ const AuthenticationMethodsModal = ({ walletId, isOpen, onClose, presentation =
280
272
  walletAuthMethodId: method.walletAuthMethodId
281
273
  });
282
274
  await refreshSessionRef.current(walletId);
283
- if (presentation !== "modal") {
284
- setActionState({ kind: "idle" });
285
- await loadInventory();
286
- } else onClose();
275
+ setActionState({ kind: "idle" });
276
+ await loadInventory();
287
277
  } catch (error) {
288
278
  setActionState({
289
279
  kind: "error",
@@ -293,8 +283,6 @@ const AuthenticationMethodsModal = ({ walletId, isOpen, onClose, presentation =
293
283
  }, [
294
284
  actionState,
295
285
  loadInventory,
296
- onClose,
297
- presentation,
298
286
  walletId
299
287
  ]);
300
288
  if (!isOpen) return null;
@@ -311,7 +299,6 @@ const AuthenticationMethodsModal = ({ walletId, isOpen, onClose, presentation =
311
299
  contentClassName: "seams-auth-methods-modal-content",
312
300
  titleId: "seams-auth-methods-modal-title",
313
301
  title: "Authentication methods",
314
- closeLabel: "Close authentication methods",
315
302
  children: /* @__PURE__ */ jsx(AuthenticationMethodsView, {
316
303
  walletLabel: walletId ?? "Wallet",
317
304
  status: inventoryStatus(loadState),
@@ -53,7 +53,13 @@
53
53
  }
54
54
 
55
55
  .seams-export-keys-row:hover:not(:disabled) {
56
- background: var(--seams-colors-surface2);
56
+ /* a shade off the expander surface behind the rows, which is often surface2;
57
+ mixing follows a theme's surface where a fixed surface step does not */
58
+ background: color-mix(
59
+ in srgb,
60
+ var(--seams-colors-textPrimary) 7%,
61
+ var(--seams-expander-surface, var(--seams-colors-surface))
62
+ );
57
63
  }
58
64
 
59
65
  .seams-export-keys-row:disabled {
@@ -50,36 +50,6 @@
50
50
  outline: none;
51
51
  }
52
52
 
53
- /* Modal chrome: the page's host above the content, "Powered by seams" below. */
54
- .seams-account-menu-dialog-header,
55
- .seams-account-menu-dialog-footer {
56
- display: flex;
57
- flex-shrink: 0;
58
- align-items: center;
59
- gap: 0.4375rem;
60
- color: var(--seams-colors-textSecondary);
61
- font-size: 0.75rem;
62
- line-height: 1.5;
63
- }
64
- .seams-account-menu-dialog-header {
65
- padding: 0 0.375rem 0 1.375rem;
66
- border-bottom: 1px solid var(--seams-colors-borderPrimary);
67
- }
68
- .seams-account-menu-dialog-host {
69
- min-width: 0;
70
- overflow: hidden;
71
- text-overflow: ellipsis;
72
- white-space: nowrap;
73
- }
74
- .seams-account-menu-dialog-footer {
75
- padding: 0.875rem 1.375rem;
76
- border-top: 1px solid var(--seams-colors-borderPrimary);
77
- background: var(--seams-colors-surface);
78
- }
79
- .seams-account-menu-dialog-header > svg,
80
- .seams-account-menu-dialog-footer > svg {
81
- flex-shrink: 0;
82
- }
83
53
  .seams-account-menu-dialog-main {
84
54
  display: flex;
85
55
  flex: 1 1 auto;
@@ -119,36 +89,6 @@
119
89
  line-height: 1.5;
120
90
  }
121
91
 
122
- .seams-linked-devices-modal-close {
123
- margin-inline-start: auto;
124
- background: none;
125
- border: none;
126
- font-size: 0.875rem;
127
- font-weight: 600;
128
- color: var(--seams-colors-textMuted);
129
- cursor: pointer;
130
- box-sizing: border-box;
131
- padding: 0;
132
- border-radius: 50%;
133
- width: 44px;
134
- min-width: 44px;
135
- height: 44px;
136
- min-height: 44px;
137
- display: inline-flex;
138
- align-items: center;
139
- justify-content: center;
140
- }
141
-
142
- .seams-linked-devices-modal-close:hover {
143
- color: var(--seams-colors-textPrimary);
144
- background: var(--seams-colors-surface);
145
- }
146
-
147
- .seams-linked-devices-modal-close:focus-visible {
148
- outline: 2px solid currentColor;
149
- outline-offset: 2px;
150
- }
151
-
152
92
  .seams-linked-devices-modal-body {
153
93
  display: grid;
154
94
  min-height: 0;
@@ -551,14 +491,6 @@
551
491
  padding: var(--seams-spacing-md, 1rem);
552
492
  }
553
493
 
554
- .seams-account-menu-dialog-header {
555
- padding-inline-start: var(--seams-spacing-md, 1rem);
556
- }
557
-
558
- .seams-account-menu-dialog-footer {
559
- padding-inline: var(--seams-spacing-md, 1rem);
560
- }
561
-
562
494
  .seams-linked-devices-modal-item-main {
563
495
  align-items: flex-start;
564
496
  flex-direction: column;
@@ -1,6 +1,6 @@
1
1
  import { useSeams } from "../../context/index.js";
2
2
  import { AccountMenuDeviceDetails } from "./AccountMenuDeviceDetails.js";
3
- import { AccountMenuDialogFrame, useAccountMenuDialogKeyboard } from "./AccountMenuDialog.js";
3
+ import { AccountMenuDialogFrame } from "./AccountMenuDialog.js";
4
4
  import { MailIcon } from "./icons/MailIcon.js";
5
5
  import { AuthenticationMethodRow } from "./AuthenticationMethodRow.js";
6
6
  import { LaptopIcon } from "./icons/LaptopIcon.js";
@@ -200,8 +200,7 @@ function withLinkedDevicesLoadTimeout(promise) {
200
200
  });
201
201
  });
202
202
  }
203
- const FOCUSABLE_DIALOG_ELEMENTS = "button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
204
- const LinkedDevicesModal = ({ walletId, isOpen, onClose, presentation = "modal" }) => {
203
+ const LinkedDevicesModal = ({ walletId, isOpen, onClose, presentation }) => {
205
204
  const { seams, loginState } = useSeams();
206
205
  const [loadState, setLoadState] = React.useState({ kind: "idle" });
207
206
  const [revokeState, setRevokeState] = React.useState({ kind: "idle" });
@@ -239,13 +238,6 @@ const LinkedDevicesModal = ({ walletId, isOpen, onClose, presentation = "modal"
239
238
  });
240
239
  }
241
240
  }, [walletId]);
242
- useAccountMenuDialogKeyboard({
243
- isOpen,
244
- presentation,
245
- onClose,
246
- dialogRef,
247
- focusableSelector: FOCUSABLE_DIALOG_ELEMENTS
248
- });
249
241
  useEffect(() => {
250
242
  if (!isOpen) {
251
243
  loadSeq.current += 1;
@@ -301,7 +293,6 @@ const LinkedDevicesModal = ({ walletId, isOpen, onClose, presentation = "modal"
301
293
  contentClassName: "seams-linked-devices-inventory-content",
302
294
  titleId: "seams-linked-devices-modal-title",
303
295
  title: selectedDevice ? "Device details" : "Linked devices",
304
- closeLabel: "Close linked devices",
305
296
  children: [selectedDevice ? /* @__PURE__ */ jsx(AccountMenuDeviceDetails, {
306
297
  title: credentialDescription(viewCredential(selectedDevice.view)),
307
298
  description: deviceMetaLine(selectedDevice.view, selectedDevice.deviceNumber, false, Date.now()),