@lumiapassport/ui-kit 1.15.10 → 1.15.11

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.js CHANGED
@@ -101,7 +101,7 @@ function getServiceUrls() {
101
101
  }
102
102
  function getIframeUrl() {
103
103
  const config = DEFAULT_LUMIA_PASSPORT_CONFIG;
104
- const buildIframeUrl = "https://auth.lumiapassport.com";
104
+ const buildIframeUrl = "http://localhost:5173/iframe/index.html";
105
105
  const iframeUrl = buildIframeUrl || config.services.iframeUrl || "https://auth.lumiapassport.com";
106
106
  return iframeUrl;
107
107
  }
@@ -541,6 +541,15 @@ var init_site = __esm({
541
541
  });
542
542
 
543
543
  // src/internal/auth/passkey.ts
544
+ var passkey_exports = {};
545
+ __export(passkey_exports, {
546
+ authenticateWithPasskey: () => authenticateWithPasskey,
547
+ createPasskeyHelpers: () => createPasskeyHelpers,
548
+ hasAvailablePasskeys: () => hasAvailablePasskeys,
549
+ isWebAuthnSupported: () => isWebAuthnSupported,
550
+ registerPasskey: () => registerPasskey,
551
+ resetWebAuthnFlags: () => resetWebAuthnFlags
552
+ });
544
553
  function setGlobalConditionalUI(active) {
545
554
  if (typeof window !== "undefined") window.__LUMIA_CONDITIONAL_UI_ACTIVE__ = active;
546
555
  }
@@ -2233,6 +2242,12 @@ var init_email = __esm({
2233
2242
  });
2234
2243
 
2235
2244
  // src/internal/auth/providers/passkey.ts
2245
+ var passkey_exports2 = {};
2246
+ __export(passkey_exports2, {
2247
+ beginPasskeyLinking: () => beginPasskeyLinking,
2248
+ completePasskeyLinking: () => completePasskeyLinking,
2249
+ linkPasskeyWithWebAuthn: () => linkPasskeyWithWebAuthn
2250
+ });
2236
2251
  async function completePasskeyLinking(payload) {
2237
2252
  const hasValidToken = await ensureValidToken();
2238
2253
  if (!hasValidToken) throw new Error("No authentication token available");
@@ -2311,8 +2326,8 @@ async function linkPasskeyWithWebAuthn(optionsOverride) {
2311
2326
  }
2312
2327
  try {
2313
2328
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2314
- const friendlyDisplay = `Lumia User (${ts})`;
2315
- const friendlyName = `lumia-link.${ts}`;
2329
+ const friendlyDisplay = `Lumia Passport (${ts})`;
2330
+ const friendlyName = `lumia-passport.${ts}`;
2316
2331
  const originalUser = publicKeyOptions.user;
2317
2332
  publicKeyOptions = {
2318
2333
  ...publicKeyOptions,
@@ -2347,6 +2362,8 @@ async function linkPasskeyWithWebAuthn(optionsOverride) {
2347
2362
  const attestationPayload = credentialToAttestationPayload(credential);
2348
2363
  const cid = challengeId || "local-" + Date.now();
2349
2364
  await completePasskeyLinking({ challengeId: cid, credential: attestationPayload });
2365
+ const rawIdB64 = btoa(String.fromCharCode(...new Uint8Array(credential.rawId)));
2366
+ return { credentialId: credential.id, rawId: rawIdB64 };
2350
2367
  }
2351
2368
  var init_passkey2 = __esm({
2352
2369
  "src/internal/auth/providers/passkey.ts"() {
@@ -5501,7 +5518,7 @@ function Header() {
5501
5518
  // package.json
5502
5519
  var package_default = {
5503
5520
  name: "@lumiapassport/ui-kit",
5504
- version: "1.15.10",
5521
+ version: "1.15.11",
5505
5522
  description: "React UI components and hooks for Lumia Passport authentication and Account Abstraction",
5506
5523
  type: "module",
5507
5524
  main: "./dist/index.cjs",
@@ -8407,6 +8424,7 @@ var useRestoreStore = create4((set) => ({
8407
8424
  restoreFile: null,
8408
8425
  checkingBackup: false,
8409
8426
  hasServerBackup: false,
8427
+ isCreatingPasskey: false,
8410
8428
  selectedCloudProvider: null,
8411
8429
  error: null,
8412
8430
  success: null,
@@ -8418,6 +8436,7 @@ var useRestoreStore = create4((set) => ({
8418
8436
  setRestoreFile: (restoreFile) => set({ restoreFile }),
8419
8437
  setCheckingBackup: (checkingBackup) => set({ checkingBackup }),
8420
8438
  setHasServerBackup: (hasServerBackup) => set({ hasServerBackup }),
8439
+ setIsCreatingPasskey: (isCreatingPasskey) => set({ isCreatingPasskey }),
8421
8440
  setSelectedCloudProvider: (providerId) => set({ selectedCloudProvider: providerId }),
8422
8441
  setError: (error) => set({ error }),
8423
8442
  setSuccess: (success) => set({ success })
@@ -8542,7 +8561,7 @@ function useCreateBackup() {
8542
8561
  const address = useLumiaPassportSession((st) => st.address);
8543
8562
  const hasServerVault = useLumiaPassportSession((st) => st.hasServerVault);
8544
8563
  const setIsDialogForced = useLayoutStore((st) => st.setIsDialogForced);
8545
- const { usePasskey, restorePassword, selectedCloudProvider, setSuccess, setError, setMethod } = useRestoreStore();
8564
+ const { usePasskey, restorePassword, selectedCloudProvider, setSuccess, setError, setMethod, setIsCreatingPasskey } = useRestoreStore();
8546
8565
  useEffect15(() => {
8547
8566
  if (!hasServerVault) {
8548
8567
  setMethod("server");
@@ -8561,12 +8580,13 @@ function useCreateBackup() {
8561
8580
  if (!usePasskey && !restorePassword) {
8562
8581
  throw new Error("Please provide a password for the backup");
8563
8582
  }
8583
+ const password = !usePasskey ? restorePassword : void 0;
8564
8584
  const navigateToMainMenu = jwt.isNewUser || !hasServerVault;
8565
- console.log("[BACKUP STATUS] is new user:", jwt.isNewUser, !hasServerVault);
8585
+ console.log("[BACKUP STATUS] is new user:", jwt.isNewUser, !hasServerVault, "usePasskey:", usePasskey);
8566
8586
  return {
8567
8587
  response: await iframeManager.createBackup(
8568
8588
  passportUserId,
8569
- { method: "server", password: restorePassword },
8589
+ { method: "server", password },
8570
8590
  jwt.accessToken
8571
8591
  ),
8572
8592
  navigateToMainMenu
@@ -8590,7 +8610,11 @@ function useCreateBackup() {
8590
8610
  setIsDialogForced(false);
8591
8611
  },
8592
8612
  onError: async (error) => {
8593
- setError(error?.message || "Backup creation failed");
8613
+ if (error?.name === "NotAllowedError" || error?.message?.includes("timed out or was not allowed")) {
8614
+ setError("Passkey selection was cancelled. Please try again or create a new passkey.");
8615
+ } else {
8616
+ setError(error?.message || "Backup creation failed");
8617
+ }
8594
8618
  qc.invalidateQueries({ queryKey: [CHECK_BACKUP_QUERY_KEY, address] });
8595
8619
  }
8596
8620
  });
@@ -8628,6 +8652,31 @@ function useCreateBackup() {
8628
8652
  qc.invalidateQueries({ queryKey: [CHECK_BACKUP_QUERY_KEY, address] });
8629
8653
  }
8630
8654
  });
8655
+ const { mutate: createPasskey, isPending: isPasskeyCreating } = useMutation7({
8656
+ mutationFn: async () => {
8657
+ setIsCreatingPasskey(true);
8658
+ const { linkPasskeyWithWebAuthn: linkPasskeyWithWebAuthn2 } = await Promise.resolve().then(() => (init_passkey2(), passkey_exports2));
8659
+ const { createPasskeyHelpers: createPasskeyHelpers2 } = await Promise.resolve().then(() => (init_passkey(), passkey_exports));
8660
+ const { credentialId, rawId } = await linkPasskeyWithWebAuthn2();
8661
+ const helpers = createPasskeyHelpers2(passportUserId);
8662
+ helpers.setCredId(credentialId);
8663
+ helpers.setRawId(rawId);
8664
+ return { credentialId, rawId };
8665
+ },
8666
+ onSuccess: async () => {
8667
+ setIsCreatingPasskey(false);
8668
+ setError(null);
8669
+ setSuccess("Passkey created successfully. You can now create a backup.");
8670
+ },
8671
+ onError: async (error) => {
8672
+ setIsCreatingPasskey(false);
8673
+ if (error.name === "NotAllowedError") {
8674
+ setError("Passkey creation cancelled. Please try again.");
8675
+ } else {
8676
+ setError(error?.message || "Failed to create passkey");
8677
+ }
8678
+ }
8679
+ });
8631
8680
  const { mutate: createCloudBackup, isPending: isCloudBackupCreating } = useMutation7({
8632
8681
  mutationFn: async () => {
8633
8682
  const iframeManager = getIframeManager();
@@ -8674,7 +8723,9 @@ function useCreateBackup() {
8674
8723
  isCloudBackupCreating,
8675
8724
  createCloudBackup,
8676
8725
  isLocalBackupCreating,
8677
- createLocalBackup
8726
+ createLocalBackup,
8727
+ isPasskeyCreating,
8728
+ createPasskey
8678
8729
  };
8679
8730
  }
8680
8731
 
@@ -8891,7 +8942,7 @@ function MethodSelector(props) {
8891
8942
  import { AlertCircle, FileUp as FileUp2, Upload, User } from "lucide-react";
8892
8943
 
8893
8944
  // src/internal/components/KeyshareRestoreMenu/components/PasswordPasskey.tsx
8894
- import { ChevronRight as ChevronRight2, Eye, EyeOff, Info as Info2, Key as Key4, Loader as Loader8 } from "lucide-react";
8945
+ import { ChevronRight as ChevronRight2, Eye, EyeOff, Info as Info2, Key as Key4, Loader as Loader8, Plus } from "lucide-react";
8895
8946
  import { useRef as useRef12 } from "react";
8896
8947
  import { Fragment as Fragment9, jsx as jsx39, jsxs as jsxs32 } from "react/jsx-runtime";
8897
8948
  function PasswordPasskey(props) {
@@ -8902,7 +8953,8 @@ function PasswordPasskey(props) {
8902
8953
  isLoading,
8903
8954
  disabled,
8904
8955
  isEncryptionMethod,
8905
- actionHandler
8956
+ actionHandler,
8957
+ onCreatePasskey
8906
8958
  } = props;
8907
8959
  const hasServerVault = useLumiaPassportSession((st) => st.hasServerVault);
8908
8960
  const actionRef = useRef12(null);
@@ -8911,6 +8963,7 @@ function PasswordPasskey(props) {
8911
8963
  restorePassword,
8912
8964
  usePasskey,
8913
8965
  error,
8966
+ isCreatingPasskey,
8914
8967
  setRestorePassword,
8915
8968
  setShowPassword,
8916
8969
  setUsePasskey,
@@ -9007,22 +9060,41 @@ function PasswordPasskey(props) {
9007
9060
  children: isLoading ? /* @__PURE__ */ jsx39(Loader8, { className: "animate-spin h-4 w-4" }) : /* @__PURE__ */ jsx39(ChevronRight2, { className: "h-4 w-4" })
9008
9061
  }
9009
9062
  )
9010
- ] }) : /* @__PURE__ */ jsxs32(
9011
- Button,
9012
- {
9013
- ref: actionRef,
9014
- size: "large",
9015
- variant: "default",
9016
- title: actionCaption,
9017
- onClick: actionHandler,
9018
- disabled: isLoading || disabled || !!error || !usePasskey && !restorePassword,
9019
- className: "w-full",
9020
- children: [
9021
- isLoading ? /* @__PURE__ */ jsx39(Loader8, { className: "animate-spin h-4 w-4" }) : /* @__PURE__ */ jsx39(ActionIcon, { className: "h-4 w-4" }),
9022
- !isLoading && /* @__PURE__ */ jsx39("span", { children: actionCaption })
9023
- ]
9024
- }
9025
- ),
9063
+ ] }) : /* @__PURE__ */ jsxs32("div", { className: "w-full flex flex-col gap-[var(--l-pass-gap)]", children: [
9064
+ /* @__PURE__ */ jsx39(
9065
+ Button,
9066
+ {
9067
+ ref: actionRef,
9068
+ size: "large",
9069
+ variant: "default",
9070
+ title: actionCaption,
9071
+ onClick: actionHandler,
9072
+ disabled: isLoading || disabled || !usePasskey && !restorePassword,
9073
+ className: "w-full",
9074
+ children: isLoading ? /* @__PURE__ */ jsxs32(Fragment9, { children: [
9075
+ /* @__PURE__ */ jsx39(Loader8, { className: "animate-spin h-4 w-4" }),
9076
+ isCreatingPasskey && /* @__PURE__ */ jsx39("span", { children: "Creating Passkey..." })
9077
+ ] }) : /* @__PURE__ */ jsxs32(Fragment9, { children: [
9078
+ /* @__PURE__ */ jsx39(ActionIcon, { className: "h-4 w-4" }),
9079
+ /* @__PURE__ */ jsx39("span", { children: actionCaption })
9080
+ ] })
9081
+ }
9082
+ ),
9083
+ mode === "backup" && onCreatePasskey && /* @__PURE__ */ jsxs32(
9084
+ Button,
9085
+ {
9086
+ size: "medium",
9087
+ variant: "outline",
9088
+ onClick: onCreatePasskey,
9089
+ disabled: isLoading || disabled,
9090
+ className: "w-full",
9091
+ children: [
9092
+ /* @__PURE__ */ jsx39(Plus, { className: "h-4 w-4" }),
9093
+ /* @__PURE__ */ jsx39("span", { children: "Create new Passkey" })
9094
+ ]
9095
+ }
9096
+ )
9097
+ ] }),
9026
9098
  !isEncryptionMethod && !!usePasskey && /* @__PURE__ */ jsx39(Highlight, { type: "info", className: "w-full flex flex-col gap-[var(--l-pass-gap)] text-[10px]", children: mode === "backup" && /* @__PURE__ */ jsxs32("div", { className: "flex gap-[var(--l-pass-gap)]", children: [
9027
9099
  /* @__PURE__ */ jsx39(Info2, { className: "h-4 w-4 flex-shrink-0" }),
9028
9100
  /* @__PURE__ */ jsxs32("span", { className: "text-[var(--l-pass-fg-muted)] block flex-1", children: [
@@ -9176,7 +9248,7 @@ import { Download, Key as Key5, Upload as Upload2 } from "lucide-react";
9176
9248
  import { useEffect as useEffect17 } from "react";
9177
9249
  import { Fragment as Fragment12, jsx as jsx42, jsxs as jsxs35 } from "react/jsx-runtime";
9178
9250
  function Server(props) {
9179
- const { isLoading, mode = "restore", serverHandler } = props;
9251
+ const { isLoading, mode = "restore", serverHandler, createPasskeyHandler } = props;
9180
9252
  const qc = useQueryClient6();
9181
9253
  const address = useLumiaPassportSession((st) => st.address);
9182
9254
  const setUsePasskey = useRestoreStore((st) => st.setUsePasskey);
@@ -9195,7 +9267,8 @@ function Server(props) {
9195
9267
  isLoading,
9196
9268
  actionCaption: mode === "backup" ? "Create Vault Backup" : "Restore from Vault",
9197
9269
  actionIcon: mode === "backup" ? Upload2 : Download,
9198
- actionHandler: () => serverHandler()
9270
+ actionHandler: () => serverHandler(),
9271
+ onCreatePasskey: createPasskeyHandler
9199
9272
  }
9200
9273
  ),
9201
9274
  !!serverRecoveryStatus?.created?.at && /* @__PURE__ */ jsxs35(Highlight, { type: "success", className: "flex gap-[var(--l-pass-gap)]", children: [
@@ -9657,7 +9730,9 @@ function KeyshareBackupMenu() {
9657
9730
  isCloudBackupCreating,
9658
9731
  createCloudBackup,
9659
9732
  isLocalBackupCreating,
9660
- createLocalBackup
9733
+ createLocalBackup,
9734
+ isPasskeyCreating,
9735
+ createPasskey
9661
9736
  } = useCreateBackup();
9662
9737
  const BackupComponent = !!currentBackupMethod ? COMPONENTS[currentBackupMethod] : null;
9663
9738
  return /* @__PURE__ */ jsx46(
@@ -9719,10 +9794,11 @@ function KeyshareBackupMenu() {
9719
9794
  BackupComponent,
9720
9795
  {
9721
9796
  mode: "backup",
9722
- isLoading: isPasswordBackupCreating || isCloudBackupCreating || isLocalBackupCreating,
9797
+ isLoading: isPasswordBackupCreating || isCloudBackupCreating || isLocalBackupCreating || isPasskeyCreating,
9723
9798
  fileHandler: createLocalBackup,
9724
9799
  serverHandler: createPasswordBackup,
9725
- cloudHandler: createCloudBackup
9800
+ cloudHandler: createCloudBackup,
9801
+ createPasskeyHandler: createPasskey
9726
9802
  }
9727
9803
  ) }),
9728
9804
  !isRecoveryLoading && !currentBackupMethod && !hasRecoveryData && /* @__PURE__ */ jsxs39(Highlight, { type: "warning", className: "flex gap-[var(--l-pass-gap)]", children: [