@mrgnw/anahtar 0.0.20 → 0.0.21

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.
@@ -22,6 +22,7 @@ interface Props {
22
22
  onSignOut?: () => void | Promise<void>;
23
23
  onPasskeysChange?: () => void | Promise<void>;
24
24
  getPasskeys?: () => Promise<PasskeyInfo[]>;
25
+ onStepChange?: (step: 'email' | 'otp' | 'authenticated') => void;
25
26
  }
26
27
 
27
28
  let {
@@ -34,6 +35,7 @@ let {
34
35
  onSignOut,
35
36
  onPasskeysChange,
36
37
  getPasskeys,
38
+ onStepChange,
37
39
  }: Props = $props();
38
40
 
39
41
  let expanded = $state(false);
@@ -47,6 +49,7 @@ let otpStep = $state(false);
47
49
  let otpDigits = $state<string[]>(['', '', '', '', '']);
48
50
  let otpInputs = $state<HTMLInputElement[]>([]);
49
51
  let showPasskeys = $state(false);
52
+ let pendingSuccess = $state(false);
50
53
  let isTouch = $state(false);
51
54
  let hoveredKey = $state<string | null>(null);
52
55
  let passkeyRefresh = $state(0);
@@ -75,9 +78,11 @@ async function handleSignOut() {
75
78
  email = '';
76
79
  otpStep = false;
77
80
  passkeyOnboarding = false;
81
+ pendingSuccess = false;
78
82
  showPasskeys = false;
79
83
  expanded = false;
80
84
  error = '';
85
+ onStepChange?.('email');
81
86
  await onSignOut?.();
82
87
  }
83
88
 
@@ -158,6 +163,7 @@ async function handleEmailSubmit(e: SubmitEvent) {
158
163
  const data = ((await res.json().catch(() => ({}))) as any);
159
164
  otpDigits = ['', '', '', '', ''];
160
165
  otpStep = true;
166
+ onStepChange?.('otp');
161
167
  if (data?.devCode) {
162
168
  const code = String(data.devCode);
163
169
  for (let i = 0; i < 5; i++) otpDigits[i] = code[i] ?? '';
@@ -217,10 +223,13 @@ async function verifyOtp(code: string) {
217
223
  return;
218
224
  }
219
225
  const data = ((await res.json().catch(() => ({}))) as any);
220
- await onSuccess?.();
221
226
  otpStep = false;
222
227
  if (!data.hasPasskey && !data.skipPasskeyPrompt) {
228
+ pendingSuccess = true;
223
229
  passkeyOnboarding = true;
230
+ } else {
231
+ await onSuccess?.();
232
+ onStepChange?.('authenticated');
224
233
  }
225
234
  } catch {
226
235
  error = m.errorGeneric;
@@ -261,11 +270,21 @@ async function handlePasskeyRegister() {
261
270
  passkeyOnboarding = false;
262
271
  passkeyRefresh++;
263
272
  await onPasskeysChange?.();
273
+ if (pendingSuccess) {
274
+ pendingSuccess = false;
275
+ await onSuccess?.();
276
+ onStepChange?.('authenticated');
277
+ }
264
278
  }
265
279
 
266
- function handlePasskeySkip() {
280
+ async function handlePasskeySkip() {
267
281
  fetch(`${apiBase}/skip-passkey`, { method: 'POST' });
268
282
  passkeyOnboarding = false;
283
+ if (pendingSuccess) {
284
+ pendingSuccess = false;
285
+ await onSuccess?.();
286
+ onStepChange?.('authenticated');
287
+ }
269
288
  }
270
289
 
271
290
  async function addPasskey() {
@@ -402,7 +421,7 @@ async function removePasskey(id: string) {
402
421
  <div class="anahtar-pill-otp-help" transition:slide={{ duration: 150 }}>
403
422
  <span class="anahtar-pill-otp-help-text">{m.codeSentTo}</span>
404
423
  <span class="anahtar-pill-otp-help-sep">&middot;</span>
405
- <button class="anahtar-pill-otp-help-link" onclick={() => { otpStep = false; error = ''; }}>{m.differentEmail}</button>
424
+ <button class="anahtar-pill-otp-help-link" onclick={() => { otpStep = false; error = ''; onStepChange?.('email'); }}>{m.differentEmail}</button>
406
425
  <span class="anahtar-pill-otp-help-sep">&middot;</span>
407
426
  <button class="anahtar-pill-otp-help-link" onclick={resend} disabled={loading}>{m.resend}</button>
408
427
  </div>
@@ -412,7 +431,7 @@ async function removePasskey(id: string) {
412
431
  <p class="anahtar-pill-error" transition:slide={{ duration: 150 }}>{error}</p>
413
432
  {/if}
414
433
 
415
- {#if passkeyOnboarding && isAuthenticated}
434
+ {#if passkeyOnboarding}
416
435
  <div class="anahtar-pill-onboarding" transition:slide={{ duration: 200 }}>
417
436
  <PasskeyPrompt {m} onRegister={handlePasskeyRegister} onSkip={handlePasskeySkip} />
418
437
  </div>
@@ -17,6 +17,7 @@ interface Props {
17
17
  onSignOut?: () => void | Promise<void>;
18
18
  onPasskeysChange?: () => void | Promise<void>;
19
19
  getPasskeys?: () => Promise<PasskeyInfo[]>;
20
+ onStepChange?: (step: 'email' | 'otp' | 'authenticated') => void;
20
21
  }
21
22
  declare const AuthPill: import("svelte").Component<Props, {}, "">;
22
23
  type AuthPill = ReturnType<typeof AuthPill>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrgnw/anahtar",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "description": "Opinionated, reusable auth for SvelteKit. Email+OTP + passkeys.",
5
5
  "license": "MIT",
6
6
  "type": "module",