@mrgnw/anahtar 0.0.19 → 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() {
|
|
@@ -385,9 +404,15 @@ async function removePasskey(id: string) {
|
|
|
385
404
|
autocomplete="username webauthn"
|
|
386
405
|
disabled={loading}
|
|
387
406
|
/>
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
407
|
+
<button type="submit" class="anahtar-pill-go" disabled={loading || !email.includes('@')}>
|
|
408
|
+
{#if loading}
|
|
409
|
+
...
|
|
410
|
+
{:else}
|
|
411
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
|
412
|
+
<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>
|
|
413
|
+
</svg>
|
|
414
|
+
{/if}
|
|
415
|
+
</button>
|
|
391
416
|
</form>
|
|
392
417
|
{/if}
|
|
393
418
|
</div>
|
|
@@ -396,7 +421,7 @@ async function removePasskey(id: string) {
|
|
|
396
421
|
<div class="anahtar-pill-otp-help" transition:slide={{ duration: 150 }}>
|
|
397
422
|
<span class="anahtar-pill-otp-help-text">{m.codeSentTo}</span>
|
|
398
423
|
<span class="anahtar-pill-otp-help-sep">·</span>
|
|
399
|
-
<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>
|
|
400
425
|
<span class="anahtar-pill-otp-help-sep">·</span>
|
|
401
426
|
<button class="anahtar-pill-otp-help-link" onclick={resend} disabled={loading}>{m.resend}</button>
|
|
402
427
|
</div>
|
|
@@ -406,7 +431,7 @@ async function removePasskey(id: string) {
|
|
|
406
431
|
<p class="anahtar-pill-error" transition:slide={{ duration: 150 }}>{error}</p>
|
|
407
432
|
{/if}
|
|
408
433
|
|
|
409
|
-
{#if passkeyOnboarding
|
|
434
|
+
{#if passkeyOnboarding}
|
|
410
435
|
<div class="anahtar-pill-onboarding" transition:slide={{ duration: 200 }}>
|
|
411
436
|
<PasskeyPrompt {m} onRegister={handlePasskeyRegister} onSkip={handlePasskeySkip} />
|
|
412
437
|
</div>
|
|
@@ -475,6 +500,7 @@ async function removePasskey(id: string) {
|
|
|
475
500
|
white-space: nowrap;
|
|
476
501
|
height: 2.25rem;
|
|
477
502
|
box-sizing: border-box;
|
|
503
|
+
overflow: hidden;
|
|
478
504
|
}
|
|
479
505
|
|
|
480
506
|
.anahtar-pill-sep {
|
|
@@ -515,6 +541,9 @@ async function removePasskey(id: string) {
|
|
|
515
541
|
display: flex;
|
|
516
542
|
align-items: center;
|
|
517
543
|
gap: 0.375rem;
|
|
544
|
+
flex: 1;
|
|
545
|
+
min-width: 0;
|
|
546
|
+
overflow: hidden;
|
|
518
547
|
}
|
|
519
548
|
|
|
520
549
|
.anahtar-pill-email-input {
|
|
@@ -523,7 +552,8 @@ async function removePasskey(id: string) {
|
|
|
523
552
|
outline: none;
|
|
524
553
|
font-size: 0.875rem;
|
|
525
554
|
color: var(--anahtar-pill-fg, #111827);
|
|
526
|
-
|
|
555
|
+
flex: 1;
|
|
556
|
+
min-width: 0;
|
|
527
557
|
padding: 0.125rem 0;
|
|
528
558
|
}
|
|
529
559
|
.anahtar-pill-email-input::placeholder { color: var(--anahtar-pill-placeholder, #9ca3af); }
|
|
@@ -533,12 +563,14 @@ async function removePasskey(id: string) {
|
|
|
533
563
|
color: var(--anahtar-primary-fg, #fff);
|
|
534
564
|
border: none;
|
|
535
565
|
border-radius: 9999px;
|
|
536
|
-
padding: 0.
|
|
537
|
-
|
|
538
|
-
|
|
566
|
+
padding: 0.3rem;
|
|
567
|
+
display: flex;
|
|
568
|
+
align-items: center;
|
|
569
|
+
justify-content: center;
|
|
570
|
+
flex-shrink: 0;
|
|
539
571
|
cursor: pointer;
|
|
540
572
|
transition: opacity 0.15s;
|
|
541
|
-
|
|
573
|
+
line-height: 1;
|
|
542
574
|
}
|
|
543
575
|
.anahtar-pill-go:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
544
576
|
.anahtar-pill-go:hover:not(:disabled) { opacity: 0.85; }
|
|
@@ -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>;
|