@authrim/sveltekit 0.1.0 → 0.1.2
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/LICENSE +191 -191
- package/README.md +527 -531
- package/dist/components/AuthProvider.svelte +56 -56
- package/dist/components/ProtectedRoute.svelte +71 -71
- package/dist/components/SignInButton.svelte +93 -93
- package/dist/components/SignOutButton.svelte +72 -72
- package/dist/components/UserProfile.svelte +71 -71
- package/dist/ui/account/LinkAccountButton.svelte +133 -133
- package/dist/ui/account/LinkedAccountsList.svelte +233 -233
- package/dist/ui/account/UnlinkAccountButton.svelte +179 -179
- package/dist/ui/forms/EmailCodeForm.svelte +224 -224
- package/dist/ui/forms/PasskeyConditionalInput.svelte +173 -173
- package/dist/ui/forms/SocialLoginButtons.svelte +209 -209
- package/dist/ui/helpers/AuthError.svelte +124 -124
- package/dist/ui/helpers/AuthLoading.svelte +83 -83
- package/dist/ui/helpers/OTPInput.svelte +214 -214
- package/dist/ui/helpers/ResendCodeButton.svelte +140 -140
- package/dist/ui/passkey/PasskeyDeleteButton.svelte +177 -177
- package/dist/ui/passkey/PasskeyList.svelte +225 -225
- package/dist/ui/passkey/PasskeyRegisterButton.svelte +52 -52
- package/dist/ui/session/SessionExpiryIndicator.svelte +109 -109
- package/dist/ui/session/SessionList.svelte +231 -231
- package/dist/ui/session/SessionRevokeButton.svelte +72 -72
- package/dist/ui/shared/Badge.svelte +100 -100
- package/dist/ui/shared/Button.svelte +213 -213
- package/dist/ui/shared/Card.svelte +85 -85
- package/dist/ui/shared/Input.svelte +192 -192
- package/dist/ui/shared/Spinner.svelte +75 -75
- package/dist/ui/styles/base.css +168 -168
- package/dist/ui/styles/theme.css +279 -279
- package/dist/ui/templates/AccountSettingsTemplate.svelte +205 -205
- package/dist/ui/templates/LoginTemplate.svelte +234 -234
- package/dist/ui/templates/SignUpTemplate.svelte +345 -345
- package/package.json +112 -111
|
@@ -1,225 +1,225 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
PasskeyList Component
|
|
3
|
-
Display and manage registered passkeys
|
|
4
|
-
-->
|
|
5
|
-
<script lang="ts">
|
|
6
|
-
import { createEventDispatcher } from 'svelte';
|
|
7
|
-
import type { PasskeyItemDisplay } from '../types.js';
|
|
8
|
-
import Badge from '../shared/Badge.svelte';
|
|
9
|
-
import Spinner from '../shared/Spinner.svelte';
|
|
10
|
-
import PasskeyDeleteButton from './PasskeyDeleteButton.svelte';
|
|
11
|
-
|
|
12
|
-
export let passkeys: PasskeyItemDisplay[] = [];
|
|
13
|
-
export let loading = false;
|
|
14
|
-
export let deletingId: string | undefined = undefined;
|
|
15
|
-
let className = '';
|
|
16
|
-
export { className as class };
|
|
17
|
-
|
|
18
|
-
const dispatch = createEventDispatcher<{
|
|
19
|
-
delete: { credentialId: string };
|
|
20
|
-
}>();
|
|
21
|
-
|
|
22
|
-
function formatDate(date: Date | undefined): string {
|
|
23
|
-
if (!date) return 'Unknown';
|
|
24
|
-
return new Intl.DateTimeFormat('en-US', {
|
|
25
|
-
month: 'short',
|
|
26
|
-
day: 'numeric',
|
|
27
|
-
year: 'numeric',
|
|
28
|
-
}).format(date);
|
|
29
|
-
}
|
|
30
|
-
</script>
|
|
31
|
-
|
|
32
|
-
<div class="authrim-passkey-list {className}" {...$$restProps}>
|
|
33
|
-
{#if loading && passkeys.length === 0}
|
|
34
|
-
<div class="authrim-passkey-list__loading">
|
|
35
|
-
<Spinner size="md" />
|
|
36
|
-
<span>Loading passkeys...</span>
|
|
37
|
-
</div>
|
|
38
|
-
{:else if passkeys.length === 0}
|
|
39
|
-
<div class="authrim-passkey-list__empty">
|
|
40
|
-
<div class="authrim-passkey-list__empty-icon">
|
|
41
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
42
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"/>
|
|
43
|
-
</svg>
|
|
44
|
-
</div>
|
|
45
|
-
<p class="authrim-passkey-list__empty-title">No passkeys yet</p>
|
|
46
|
-
<p class="authrim-passkey-list__empty-desc">
|
|
47
|
-
Add a passkey to sign in quickly and securely
|
|
48
|
-
</p>
|
|
49
|
-
</div>
|
|
50
|
-
{:else}
|
|
51
|
-
<ul class="authrim-passkey-list__items">
|
|
52
|
-
{#each passkeys as passkey, index (passkey.credentialId)}
|
|
53
|
-
<li
|
|
54
|
-
class="authrim-passkey-list__item"
|
|
55
|
-
style="animation-delay: {index * 50}ms"
|
|
56
|
-
>
|
|
57
|
-
<div class="authrim-passkey-list__icon">
|
|
58
|
-
{#if passkey.deviceType === 'platform'}
|
|
59
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
60
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 1.5H8.25A2.25 2.25 0 006 3.75v16.5a2.25 2.25 0 002.25 2.25h7.5A2.25 2.25 0 0018 20.25V3.75a2.25 2.25 0 00-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3"/>
|
|
61
|
-
</svg>
|
|
62
|
-
{:else}
|
|
63
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
64
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"/>
|
|
65
|
-
</svg>
|
|
66
|
-
{/if}
|
|
67
|
-
</div>
|
|
68
|
-
|
|
69
|
-
<div class="authrim-passkey-list__info">
|
|
70
|
-
<div class="authrim-passkey-list__name-row">
|
|
71
|
-
<span class="authrim-passkey-list__name">
|
|
72
|
-
{passkey.name || 'Passkey'}
|
|
73
|
-
</span>
|
|
74
|
-
{#if passkey.deviceType}
|
|
75
|
-
<Badge size="sm" variant={passkey.deviceType === 'platform' ? 'accent' : 'default'}>
|
|
76
|
-
{passkey.deviceType === 'platform' ? 'This device' : 'Security key'}
|
|
77
|
-
</Badge>
|
|
78
|
-
{/if}
|
|
79
|
-
</div>
|
|
80
|
-
<div class="authrim-passkey-list__meta">
|
|
81
|
-
{#if passkey.createdAt}
|
|
82
|
-
<span>Added {formatDate(passkey.createdAt)}</span>
|
|
83
|
-
{/if}
|
|
84
|
-
{#if passkey.lastUsedAt}
|
|
85
|
-
<span class="authrim-passkey-list__sep">·</span>
|
|
86
|
-
<span>Last used {formatDate(passkey.lastUsedAt)}</span>
|
|
87
|
-
{/if}
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<PasskeyDeleteButton
|
|
92
|
-
credentialId={passkey.credentialId}
|
|
93
|
-
loading={deletingId === passkey.credentialId}
|
|
94
|
-
on:confirm={() => dispatch('delete', { credentialId: passkey.credentialId })}
|
|
95
|
-
/>
|
|
96
|
-
</li>
|
|
97
|
-
{/each}
|
|
98
|
-
</ul>
|
|
99
|
-
{/if}
|
|
100
|
-
</div>
|
|
101
|
-
|
|
102
|
-
<style>
|
|
103
|
-
.authrim-passkey-list__loading {
|
|
104
|
-
display: flex;
|
|
105
|
-
flex-direction: column;
|
|
106
|
-
align-items: center;
|
|
107
|
-
gap: var(--authrim-space-3);
|
|
108
|
-
padding: var(--authrim-space-8);
|
|
109
|
-
color: var(--authrim-color-text-secondary);
|
|
110
|
-
font-size: var(--authrim-text-sm);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.authrim-passkey-list__empty {
|
|
114
|
-
display: flex;
|
|
115
|
-
flex-direction: column;
|
|
116
|
-
align-items: center;
|
|
117
|
-
padding: var(--authrim-space-8);
|
|
118
|
-
text-align: center;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.authrim-passkey-list__empty-icon {
|
|
122
|
-
width: 48px;
|
|
123
|
-
height: 48px;
|
|
124
|
-
margin-bottom: var(--authrim-space-4);
|
|
125
|
-
color: var(--authrim-color-text-muted);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
.authrim-passkey-list__empty-icon svg {
|
|
129
|
-
width: 100%;
|
|
130
|
-
height: 100%;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.authrim-passkey-list__empty-title {
|
|
134
|
-
margin: 0 0 var(--authrim-space-2);
|
|
135
|
-
font-size: var(--authrim-text-base);
|
|
136
|
-
font-weight: 600;
|
|
137
|
-
color: var(--authrim-color-text);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.authrim-passkey-list__empty-desc {
|
|
141
|
-
margin: 0;
|
|
142
|
-
font-size: var(--authrim-text-sm);
|
|
143
|
-
color: var(--authrim-color-text-secondary);
|
|
144
|
-
max-width: 280px;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.authrim-passkey-list__items {
|
|
148
|
-
list-style: none;
|
|
149
|
-
margin: 0;
|
|
150
|
-
padding: 0;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.authrim-passkey-list__item {
|
|
154
|
-
display: flex;
|
|
155
|
-
align-items: center;
|
|
156
|
-
gap: var(--authrim-space-4);
|
|
157
|
-
padding: var(--authrim-space-4);
|
|
158
|
-
border-bottom: 1px solid var(--authrim-color-border-subtle);
|
|
159
|
-
animation: slide-in var(--authrim-duration-normal) var(--authrim-ease-out) both;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
@keyframes slide-in {
|
|
163
|
-
from {
|
|
164
|
-
opacity: 0;
|
|
165
|
-
transform: translateX(8px);
|
|
166
|
-
}
|
|
167
|
-
to {
|
|
168
|
-
opacity: 1;
|
|
169
|
-
transform: translateX(0);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.authrim-passkey-list__item:last-child {
|
|
174
|
-
border-bottom: none;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
.authrim-passkey-list__icon {
|
|
178
|
-
flex-shrink: 0;
|
|
179
|
-
display: flex;
|
|
180
|
-
align-items: center;
|
|
181
|
-
justify-content: center;
|
|
182
|
-
width: 40px;
|
|
183
|
-
height: 40px;
|
|
184
|
-
background: var(--authrim-color-bg-subtle);
|
|
185
|
-
border-radius: var(--authrim-radius-md);
|
|
186
|
-
color: var(--authrim-color-text-secondary);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
.authrim-passkey-list__icon svg {
|
|
190
|
-
width: 20px;
|
|
191
|
-
height: 20px;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
.authrim-passkey-list__info {
|
|
195
|
-
flex: 1;
|
|
196
|
-
min-width: 0;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
.authrim-passkey-list__name-row {
|
|
200
|
-
display: flex;
|
|
201
|
-
align-items: center;
|
|
202
|
-
gap: var(--authrim-space-2);
|
|
203
|
-
flex-wrap: wrap;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
.authrim-passkey-list__name {
|
|
207
|
-
font-size: var(--authrim-text-sm);
|
|
208
|
-
font-weight: 500;
|
|
209
|
-
color: var(--authrim-color-text);
|
|
210
|
-
letter-spacing: var(--authrim-tracking-tight);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
.authrim-passkey-list__meta {
|
|
214
|
-
display: flex;
|
|
215
|
-
align-items: center;
|
|
216
|
-
gap: var(--authrim-space-1);
|
|
217
|
-
margin-top: var(--authrim-space-1);
|
|
218
|
-
font-size: var(--authrim-text-xs);
|
|
219
|
-
color: var(--authrim-color-text-muted);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
.authrim-passkey-list__sep {
|
|
223
|
-
color: var(--authrim-color-border-strong);
|
|
224
|
-
}
|
|
225
|
-
</style>
|
|
1
|
+
<!--
|
|
2
|
+
PasskeyList Component
|
|
3
|
+
Display and manage registered passkeys
|
|
4
|
+
-->
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { createEventDispatcher } from 'svelte';
|
|
7
|
+
import type { PasskeyItemDisplay } from '../types.js';
|
|
8
|
+
import Badge from '../shared/Badge.svelte';
|
|
9
|
+
import Spinner from '../shared/Spinner.svelte';
|
|
10
|
+
import PasskeyDeleteButton from './PasskeyDeleteButton.svelte';
|
|
11
|
+
|
|
12
|
+
export let passkeys: PasskeyItemDisplay[] = [];
|
|
13
|
+
export let loading = false;
|
|
14
|
+
export let deletingId: string | undefined = undefined;
|
|
15
|
+
let className = '';
|
|
16
|
+
export { className as class };
|
|
17
|
+
|
|
18
|
+
const dispatch = createEventDispatcher<{
|
|
19
|
+
delete: { credentialId: string };
|
|
20
|
+
}>();
|
|
21
|
+
|
|
22
|
+
function formatDate(date: Date | undefined): string {
|
|
23
|
+
if (!date) return 'Unknown';
|
|
24
|
+
return new Intl.DateTimeFormat('en-US', {
|
|
25
|
+
month: 'short',
|
|
26
|
+
day: 'numeric',
|
|
27
|
+
year: 'numeric',
|
|
28
|
+
}).format(date);
|
|
29
|
+
}
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<div class="authrim-passkey-list {className}" {...$$restProps}>
|
|
33
|
+
{#if loading && passkeys.length === 0}
|
|
34
|
+
<div class="authrim-passkey-list__loading">
|
|
35
|
+
<Spinner size="md" />
|
|
36
|
+
<span>Loading passkeys...</span>
|
|
37
|
+
</div>
|
|
38
|
+
{:else if passkeys.length === 0}
|
|
39
|
+
<div class="authrim-passkey-list__empty">
|
|
40
|
+
<div class="authrim-passkey-list__empty-icon">
|
|
41
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
42
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"/>
|
|
43
|
+
</svg>
|
|
44
|
+
</div>
|
|
45
|
+
<p class="authrim-passkey-list__empty-title">No passkeys yet</p>
|
|
46
|
+
<p class="authrim-passkey-list__empty-desc">
|
|
47
|
+
Add a passkey to sign in quickly and securely
|
|
48
|
+
</p>
|
|
49
|
+
</div>
|
|
50
|
+
{:else}
|
|
51
|
+
<ul class="authrim-passkey-list__items">
|
|
52
|
+
{#each passkeys as passkey, index (passkey.credentialId)}
|
|
53
|
+
<li
|
|
54
|
+
class="authrim-passkey-list__item"
|
|
55
|
+
style="animation-delay: {index * 50}ms"
|
|
56
|
+
>
|
|
57
|
+
<div class="authrim-passkey-list__icon">
|
|
58
|
+
{#if passkey.deviceType === 'platform'}
|
|
59
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
60
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 1.5H8.25A2.25 2.25 0 006 3.75v16.5a2.25 2.25 0 002.25 2.25h7.5A2.25 2.25 0 0018 20.25V3.75a2.25 2.25 0 00-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3"/>
|
|
61
|
+
</svg>
|
|
62
|
+
{:else}
|
|
63
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
64
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"/>
|
|
65
|
+
</svg>
|
|
66
|
+
{/if}
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<div class="authrim-passkey-list__info">
|
|
70
|
+
<div class="authrim-passkey-list__name-row">
|
|
71
|
+
<span class="authrim-passkey-list__name">
|
|
72
|
+
{passkey.name || 'Passkey'}
|
|
73
|
+
</span>
|
|
74
|
+
{#if passkey.deviceType}
|
|
75
|
+
<Badge size="sm" variant={passkey.deviceType === 'platform' ? 'accent' : 'default'}>
|
|
76
|
+
{passkey.deviceType === 'platform' ? 'This device' : 'Security key'}
|
|
77
|
+
</Badge>
|
|
78
|
+
{/if}
|
|
79
|
+
</div>
|
|
80
|
+
<div class="authrim-passkey-list__meta">
|
|
81
|
+
{#if passkey.createdAt}
|
|
82
|
+
<span>Added {formatDate(passkey.createdAt)}</span>
|
|
83
|
+
{/if}
|
|
84
|
+
{#if passkey.lastUsedAt}
|
|
85
|
+
<span class="authrim-passkey-list__sep">·</span>
|
|
86
|
+
<span>Last used {formatDate(passkey.lastUsedAt)}</span>
|
|
87
|
+
{/if}
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<PasskeyDeleteButton
|
|
92
|
+
credentialId={passkey.credentialId}
|
|
93
|
+
loading={deletingId === passkey.credentialId}
|
|
94
|
+
on:confirm={() => dispatch('delete', { credentialId: passkey.credentialId })}
|
|
95
|
+
/>
|
|
96
|
+
</li>
|
|
97
|
+
{/each}
|
|
98
|
+
</ul>
|
|
99
|
+
{/if}
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<style>
|
|
103
|
+
.authrim-passkey-list__loading {
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
106
|
+
align-items: center;
|
|
107
|
+
gap: var(--authrim-space-3);
|
|
108
|
+
padding: var(--authrim-space-8);
|
|
109
|
+
color: var(--authrim-color-text-secondary);
|
|
110
|
+
font-size: var(--authrim-text-sm);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.authrim-passkey-list__empty {
|
|
114
|
+
display: flex;
|
|
115
|
+
flex-direction: column;
|
|
116
|
+
align-items: center;
|
|
117
|
+
padding: var(--authrim-space-8);
|
|
118
|
+
text-align: center;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.authrim-passkey-list__empty-icon {
|
|
122
|
+
width: 48px;
|
|
123
|
+
height: 48px;
|
|
124
|
+
margin-bottom: var(--authrim-space-4);
|
|
125
|
+
color: var(--authrim-color-text-muted);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.authrim-passkey-list__empty-icon svg {
|
|
129
|
+
width: 100%;
|
|
130
|
+
height: 100%;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.authrim-passkey-list__empty-title {
|
|
134
|
+
margin: 0 0 var(--authrim-space-2);
|
|
135
|
+
font-size: var(--authrim-text-base);
|
|
136
|
+
font-weight: 600;
|
|
137
|
+
color: var(--authrim-color-text);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.authrim-passkey-list__empty-desc {
|
|
141
|
+
margin: 0;
|
|
142
|
+
font-size: var(--authrim-text-sm);
|
|
143
|
+
color: var(--authrim-color-text-secondary);
|
|
144
|
+
max-width: 280px;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.authrim-passkey-list__items {
|
|
148
|
+
list-style: none;
|
|
149
|
+
margin: 0;
|
|
150
|
+
padding: 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.authrim-passkey-list__item {
|
|
154
|
+
display: flex;
|
|
155
|
+
align-items: center;
|
|
156
|
+
gap: var(--authrim-space-4);
|
|
157
|
+
padding: var(--authrim-space-4);
|
|
158
|
+
border-bottom: 1px solid var(--authrim-color-border-subtle);
|
|
159
|
+
animation: slide-in var(--authrim-duration-normal) var(--authrim-ease-out) both;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@keyframes slide-in {
|
|
163
|
+
from {
|
|
164
|
+
opacity: 0;
|
|
165
|
+
transform: translateX(8px);
|
|
166
|
+
}
|
|
167
|
+
to {
|
|
168
|
+
opacity: 1;
|
|
169
|
+
transform: translateX(0);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.authrim-passkey-list__item:last-child {
|
|
174
|
+
border-bottom: none;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.authrim-passkey-list__icon {
|
|
178
|
+
flex-shrink: 0;
|
|
179
|
+
display: flex;
|
|
180
|
+
align-items: center;
|
|
181
|
+
justify-content: center;
|
|
182
|
+
width: 40px;
|
|
183
|
+
height: 40px;
|
|
184
|
+
background: var(--authrim-color-bg-subtle);
|
|
185
|
+
border-radius: var(--authrim-radius-md);
|
|
186
|
+
color: var(--authrim-color-text-secondary);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.authrim-passkey-list__icon svg {
|
|
190
|
+
width: 20px;
|
|
191
|
+
height: 20px;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.authrim-passkey-list__info {
|
|
195
|
+
flex: 1;
|
|
196
|
+
min-width: 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.authrim-passkey-list__name-row {
|
|
200
|
+
display: flex;
|
|
201
|
+
align-items: center;
|
|
202
|
+
gap: var(--authrim-space-2);
|
|
203
|
+
flex-wrap: wrap;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.authrim-passkey-list__name {
|
|
207
|
+
font-size: var(--authrim-text-sm);
|
|
208
|
+
font-weight: 500;
|
|
209
|
+
color: var(--authrim-color-text);
|
|
210
|
+
letter-spacing: var(--authrim-tracking-tight);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.authrim-passkey-list__meta {
|
|
214
|
+
display: flex;
|
|
215
|
+
align-items: center;
|
|
216
|
+
gap: var(--authrim-space-1);
|
|
217
|
+
margin-top: var(--authrim-space-1);
|
|
218
|
+
font-size: var(--authrim-text-xs);
|
|
219
|
+
color: var(--authrim-color-text-muted);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.authrim-passkey-list__sep {
|
|
223
|
+
color: var(--authrim-color-border-strong);
|
|
224
|
+
}
|
|
225
|
+
</style>
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
PasskeyRegisterButton Component
|
|
3
|
-
Button to register a new passkey
|
|
4
|
-
-->
|
|
5
|
-
<script lang="ts">
|
|
6
|
-
import { createEventDispatcher } from 'svelte';
|
|
7
|
-
import Button from '../shared/Button.svelte';
|
|
8
|
-
|
|
9
|
-
export let loading = false;
|
|
10
|
-
export let disabled = false;
|
|
11
|
-
export let variant: 'primary' | 'secondary' | 'outline' = 'primary';
|
|
12
|
-
export let size: 'sm' | 'md' | 'lg' = 'md';
|
|
13
|
-
export let fullWidth = false;
|
|
14
|
-
let className = '';
|
|
15
|
-
export { className as class };
|
|
16
|
-
|
|
17
|
-
const dispatch = createEventDispatcher<{ click: void }>();
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<Button
|
|
21
|
-
{variant}
|
|
22
|
-
{size}
|
|
23
|
-
{loading}
|
|
24
|
-
{disabled}
|
|
25
|
-
{fullWidth}
|
|
26
|
-
class="authrim-passkey-register {className}"
|
|
27
|
-
on:click={() => dispatch('click')}
|
|
28
|
-
{...$$restProps}
|
|
29
|
-
>
|
|
30
|
-
<svg
|
|
31
|
-
class="authrim-passkey-register__icon"
|
|
32
|
-
viewBox="0 0 20 20"
|
|
33
|
-
fill="none"
|
|
34
|
-
stroke="currentColor"
|
|
35
|
-
stroke-width="1.5"
|
|
36
|
-
>
|
|
37
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M13.125 4.375a2.5 2.5 0 012.5 2.5m2.5 0a5 5 0 01-5.858 4.927c-.469-.081-.966.021-1.302.358L8.75 14.375H6.875v1.875H5v1.875H2.188v-2.348c0-.498.197-.976.549-1.327l5.416-5.416c.337-.336.44-.833.358-1.302A5 5 0 1118.125 6.875z"/>
|
|
38
|
-
</svg>
|
|
39
|
-
<slot>Add passkey</slot>
|
|
40
|
-
</Button>
|
|
41
|
-
|
|
42
|
-
<style>
|
|
43
|
-
:global(.authrim-passkey-register) {
|
|
44
|
-
gap: var(--authrim-space-2);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.authrim-passkey-register__icon {
|
|
48
|
-
width: 18px;
|
|
49
|
-
height: 18px;
|
|
50
|
-
flex-shrink: 0;
|
|
51
|
-
}
|
|
52
|
-
</style>
|
|
1
|
+
<!--
|
|
2
|
+
PasskeyRegisterButton Component
|
|
3
|
+
Button to register a new passkey
|
|
4
|
+
-->
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { createEventDispatcher } from 'svelte';
|
|
7
|
+
import Button from '../shared/Button.svelte';
|
|
8
|
+
|
|
9
|
+
export let loading = false;
|
|
10
|
+
export let disabled = false;
|
|
11
|
+
export let variant: 'primary' | 'secondary' | 'outline' = 'primary';
|
|
12
|
+
export let size: 'sm' | 'md' | 'lg' = 'md';
|
|
13
|
+
export let fullWidth = false;
|
|
14
|
+
let className = '';
|
|
15
|
+
export { className as class };
|
|
16
|
+
|
|
17
|
+
const dispatch = createEventDispatcher<{ click: void }>();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<Button
|
|
21
|
+
{variant}
|
|
22
|
+
{size}
|
|
23
|
+
{loading}
|
|
24
|
+
{disabled}
|
|
25
|
+
{fullWidth}
|
|
26
|
+
class="authrim-passkey-register {className}"
|
|
27
|
+
on:click={() => dispatch('click')}
|
|
28
|
+
{...$$restProps}
|
|
29
|
+
>
|
|
30
|
+
<svg
|
|
31
|
+
class="authrim-passkey-register__icon"
|
|
32
|
+
viewBox="0 0 20 20"
|
|
33
|
+
fill="none"
|
|
34
|
+
stroke="currentColor"
|
|
35
|
+
stroke-width="1.5"
|
|
36
|
+
>
|
|
37
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M13.125 4.375a2.5 2.5 0 012.5 2.5m2.5 0a5 5 0 01-5.858 4.927c-.469-.081-.966.021-1.302.358L8.75 14.375H6.875v1.875H5v1.875H2.188v-2.348c0-.498.197-.976.549-1.327l5.416-5.416c.337-.336.44-.833.358-1.302A5 5 0 1118.125 6.875z"/>
|
|
38
|
+
</svg>
|
|
39
|
+
<slot>Add passkey</slot>
|
|
40
|
+
</Button>
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
:global(.authrim-passkey-register) {
|
|
44
|
+
gap: var(--authrim-space-2);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.authrim-passkey-register__icon {
|
|
48
|
+
width: 18px;
|
|
49
|
+
height: 18px;
|
|
50
|
+
flex-shrink: 0;
|
|
51
|
+
}
|
|
52
|
+
</style>
|