@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,205 +1,205 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
AccountSettingsTemplate Component
|
|
3
|
-
|
|
4
|
-
Reference implementation for account settings screens.
|
|
5
|
-
Copy and customize for production use.
|
|
6
|
-
|
|
7
|
-
@example
|
|
8
|
-
<AccountSettingsTemplate
|
|
9
|
-
{passkeys}
|
|
10
|
-
{sessions}
|
|
11
|
-
{linkedAccounts}
|
|
12
|
-
currentSessionId={session.id}
|
|
13
|
-
on:passkey-register={handlePasskeyRegister}
|
|
14
|
-
on:passkey-delete={handlePasskeyDelete}
|
|
15
|
-
on:session-revoke={handleSessionRevoke}
|
|
16
|
-
on:account-link={handleAccountLink}
|
|
17
|
-
on:account-unlink={handleAccountUnlink}
|
|
18
|
-
/>
|
|
19
|
-
-->
|
|
20
|
-
<script lang="ts">
|
|
21
|
-
import { createEventDispatcher } from 'svelte';
|
|
22
|
-
import type { SocialProvider } from '../../types.js';
|
|
23
|
-
import type { PasskeyItemDisplay, SessionItemDisplay, LinkedAccountDisplay } from '../types.js';
|
|
24
|
-
import Card from '../shared/Card.svelte';
|
|
25
|
-
import PasskeyList from '../passkey/PasskeyList.svelte';
|
|
26
|
-
import PasskeyRegisterButton from '../passkey/PasskeyRegisterButton.svelte';
|
|
27
|
-
import SessionList from '../session/SessionList.svelte';
|
|
28
|
-
import LinkedAccountsList from '../account/LinkedAccountsList.svelte';
|
|
29
|
-
import LinkAccountButton from '../account/LinkAccountButton.svelte';
|
|
30
|
-
|
|
31
|
-
export let passkeys: PasskeyItemDisplay[] = [];
|
|
32
|
-
export let sessions: SessionItemDisplay[] = [];
|
|
33
|
-
export let linkedAccounts: LinkedAccountDisplay[] = [];
|
|
34
|
-
export let currentSessionId: string | undefined = undefined;
|
|
35
|
-
export let loading = false;
|
|
36
|
-
export let passkeyLoading = false;
|
|
37
|
-
export let deletingPasskeyId: string | undefined = undefined;
|
|
38
|
-
export let revokingSessionId: string | undefined = undefined;
|
|
39
|
-
export let unlinkingAccountId: string | undefined = undefined;
|
|
40
|
-
export let linkableProviders: SocialProvider[] = ['google', 'github', 'apple'];
|
|
41
|
-
export let linkingProvider: SocialProvider | undefined = undefined;
|
|
42
|
-
let className = '';
|
|
43
|
-
export { className as class };
|
|
44
|
-
|
|
45
|
-
const dispatch = createEventDispatcher<{
|
|
46
|
-
'passkey-register': void;
|
|
47
|
-
'passkey-delete': { credentialId: string };
|
|
48
|
-
'session-revoke': { sessionId: string };
|
|
49
|
-
'account-link': { provider: SocialProvider };
|
|
50
|
-
'account-unlink': { accountId: string; provider: SocialProvider };
|
|
51
|
-
}>();
|
|
52
|
-
|
|
53
|
-
$: linkedProviders = new Set(linkedAccounts.map((a) => a.provider));
|
|
54
|
-
$: availableToLink = linkableProviders.filter((p) => !linkedProviders.has(p));
|
|
55
|
-
</script>
|
|
56
|
-
|
|
57
|
-
<div class="authrim-account-settings {className}">
|
|
58
|
-
<h1 class="authrim-account-settings__title">Account Settings</h1>
|
|
59
|
-
|
|
60
|
-
<div class="authrim-account-settings__grid">
|
|
61
|
-
<!-- Passkeys Section -->
|
|
62
|
-
<Card class="authrim-account-settings__section">
|
|
63
|
-
<div slot="header" class="authrim-account-settings__section-header">
|
|
64
|
-
<div>
|
|
65
|
-
<h2 class="authrim-account-settings__section-title">Passkeys</h2>
|
|
66
|
-
<p class="authrim-account-settings__section-desc">
|
|
67
|
-
Passkeys let you sign in securely without a password
|
|
68
|
-
</p>
|
|
69
|
-
</div>
|
|
70
|
-
<PasskeyRegisterButton
|
|
71
|
-
variant="outline"
|
|
72
|
-
size="sm"
|
|
73
|
-
loading={passkeyLoading}
|
|
74
|
-
on:click={() => dispatch('passkey-register')}
|
|
75
|
-
/>
|
|
76
|
-
</div>
|
|
77
|
-
|
|
78
|
-
<PasskeyList
|
|
79
|
-
{passkeys}
|
|
80
|
-
{loading}
|
|
81
|
-
deletingId={deletingPasskeyId}
|
|
82
|
-
on:delete={(e) => dispatch('passkey-delete', e.detail)}
|
|
83
|
-
/>
|
|
84
|
-
</Card>
|
|
85
|
-
|
|
86
|
-
<!-- Sessions Section -->
|
|
87
|
-
<Card class="authrim-account-settings__section">
|
|
88
|
-
<div slot="header" class="authrim-account-settings__section-header">
|
|
89
|
-
<div>
|
|
90
|
-
<h2 class="authrim-account-settings__section-title">Active Sessions</h2>
|
|
91
|
-
<p class="authrim-account-settings__section-desc">
|
|
92
|
-
Manage your active sign-in sessions
|
|
93
|
-
</p>
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
|
|
97
|
-
<SessionList
|
|
98
|
-
{sessions}
|
|
99
|
-
{currentSessionId}
|
|
100
|
-
{loading}
|
|
101
|
-
revokingId={revokingSessionId}
|
|
102
|
-
on:revoke={(e) => dispatch('session-revoke', e.detail)}
|
|
103
|
-
/>
|
|
104
|
-
</Card>
|
|
105
|
-
|
|
106
|
-
<!-- Linked Accounts Section -->
|
|
107
|
-
<Card class="authrim-account-settings__section">
|
|
108
|
-
<div slot="header" class="authrim-account-settings__section-header">
|
|
109
|
-
<div>
|
|
110
|
-
<h2 class="authrim-account-settings__section-title">Linked Accounts</h2>
|
|
111
|
-
<p class="authrim-account-settings__section-desc">
|
|
112
|
-
Connect accounts for easier sign-in
|
|
113
|
-
</p>
|
|
114
|
-
</div>
|
|
115
|
-
</div>
|
|
116
|
-
|
|
117
|
-
<LinkedAccountsList
|
|
118
|
-
accounts={linkedAccounts}
|
|
119
|
-
{loading}
|
|
120
|
-
unlinkingId={unlinkingAccountId}
|
|
121
|
-
on:unlink={(e) => dispatch('account-unlink', e.detail)}
|
|
122
|
-
/>
|
|
123
|
-
|
|
124
|
-
{#if availableToLink.length > 0}
|
|
125
|
-
<div class="authrim-account-settings__link-buttons">
|
|
126
|
-
{#each availableToLink as provider}
|
|
127
|
-
<LinkAccountButton
|
|
128
|
-
{provider}
|
|
129
|
-
loading={linkingProvider === provider}
|
|
130
|
-
disabled={loading || !!linkingProvider}
|
|
131
|
-
on:click={() => dispatch('account-link', { provider })}
|
|
132
|
-
/>
|
|
133
|
-
{/each}
|
|
134
|
-
</div>
|
|
135
|
-
{/if}
|
|
136
|
-
</Card>
|
|
137
|
-
</div>
|
|
138
|
-
</div>
|
|
139
|
-
|
|
140
|
-
<style>
|
|
141
|
-
.authrim-account-settings {
|
|
142
|
-
max-width: 800px;
|
|
143
|
-
margin: 0 auto;
|
|
144
|
-
padding: var(--authrim-space-6);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.authrim-account-settings__title {
|
|
148
|
-
margin: 0 0 var(--authrim-space-6);
|
|
149
|
-
font-size: var(--authrim-text-2xl);
|
|
150
|
-
font-weight: 700;
|
|
151
|
-
color: var(--authrim-color-text);
|
|
152
|
-
letter-spacing: var(--authrim-tracking-tight);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
.authrim-account-settings__grid {
|
|
156
|
-
display: flex;
|
|
157
|
-
flex-direction: column;
|
|
158
|
-
gap: var(--authrim-space-6);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
:global(.authrim-account-settings__section) {
|
|
162
|
-
overflow: hidden;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
.authrim-account-settings__section-header {
|
|
166
|
-
display: flex;
|
|
167
|
-
align-items: flex-start;
|
|
168
|
-
justify-content: space-between;
|
|
169
|
-
gap: var(--authrim-space-4);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.authrim-account-settings__section-title {
|
|
173
|
-
margin: 0 0 var(--authrim-space-1);
|
|
174
|
-
font-size: var(--authrim-text-base);
|
|
175
|
-
font-weight: 600;
|
|
176
|
-
color: var(--authrim-color-text);
|
|
177
|
-
letter-spacing: var(--authrim-tracking-tight);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.authrim-account-settings__section-desc {
|
|
181
|
-
margin: 0;
|
|
182
|
-
font-size: var(--authrim-text-sm);
|
|
183
|
-
color: var(--authrim-color-text-secondary);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
.authrim-account-settings__link-buttons {
|
|
187
|
-
display: flex;
|
|
188
|
-
flex-wrap: wrap;
|
|
189
|
-
gap: var(--authrim-space-2);
|
|
190
|
-
padding: var(--authrim-space-4);
|
|
191
|
-
border-top: 1px solid var(--authrim-color-border-subtle);
|
|
192
|
-
background: var(--authrim-color-bg-subtle);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
@media (max-width: 640px) {
|
|
196
|
-
.authrim-account-settings {
|
|
197
|
-
padding: var(--authrim-space-4);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
.authrim-account-settings__section-header {
|
|
201
|
-
flex-direction: column;
|
|
202
|
-
gap: var(--authrim-space-3);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
</style>
|
|
1
|
+
<!--
|
|
2
|
+
AccountSettingsTemplate Component
|
|
3
|
+
|
|
4
|
+
Reference implementation for account settings screens.
|
|
5
|
+
Copy and customize for production use.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
<AccountSettingsTemplate
|
|
9
|
+
{passkeys}
|
|
10
|
+
{sessions}
|
|
11
|
+
{linkedAccounts}
|
|
12
|
+
currentSessionId={session.id}
|
|
13
|
+
on:passkey-register={handlePasskeyRegister}
|
|
14
|
+
on:passkey-delete={handlePasskeyDelete}
|
|
15
|
+
on:session-revoke={handleSessionRevoke}
|
|
16
|
+
on:account-link={handleAccountLink}
|
|
17
|
+
on:account-unlink={handleAccountUnlink}
|
|
18
|
+
/>
|
|
19
|
+
-->
|
|
20
|
+
<script lang="ts">
|
|
21
|
+
import { createEventDispatcher } from 'svelte';
|
|
22
|
+
import type { SocialProvider } from '../../types.js';
|
|
23
|
+
import type { PasskeyItemDisplay, SessionItemDisplay, LinkedAccountDisplay } from '../types.js';
|
|
24
|
+
import Card from '../shared/Card.svelte';
|
|
25
|
+
import PasskeyList from '../passkey/PasskeyList.svelte';
|
|
26
|
+
import PasskeyRegisterButton from '../passkey/PasskeyRegisterButton.svelte';
|
|
27
|
+
import SessionList from '../session/SessionList.svelte';
|
|
28
|
+
import LinkedAccountsList from '../account/LinkedAccountsList.svelte';
|
|
29
|
+
import LinkAccountButton from '../account/LinkAccountButton.svelte';
|
|
30
|
+
|
|
31
|
+
export let passkeys: PasskeyItemDisplay[] = [];
|
|
32
|
+
export let sessions: SessionItemDisplay[] = [];
|
|
33
|
+
export let linkedAccounts: LinkedAccountDisplay[] = [];
|
|
34
|
+
export let currentSessionId: string | undefined = undefined;
|
|
35
|
+
export let loading = false;
|
|
36
|
+
export let passkeyLoading = false;
|
|
37
|
+
export let deletingPasskeyId: string | undefined = undefined;
|
|
38
|
+
export let revokingSessionId: string | undefined = undefined;
|
|
39
|
+
export let unlinkingAccountId: string | undefined = undefined;
|
|
40
|
+
export let linkableProviders: SocialProvider[] = ['google', 'github', 'apple'];
|
|
41
|
+
export let linkingProvider: SocialProvider | undefined = undefined;
|
|
42
|
+
let className = '';
|
|
43
|
+
export { className as class };
|
|
44
|
+
|
|
45
|
+
const dispatch = createEventDispatcher<{
|
|
46
|
+
'passkey-register': void;
|
|
47
|
+
'passkey-delete': { credentialId: string };
|
|
48
|
+
'session-revoke': { sessionId: string };
|
|
49
|
+
'account-link': { provider: SocialProvider };
|
|
50
|
+
'account-unlink': { accountId: string; provider: SocialProvider };
|
|
51
|
+
}>();
|
|
52
|
+
|
|
53
|
+
$: linkedProviders = new Set(linkedAccounts.map((a) => a.provider));
|
|
54
|
+
$: availableToLink = linkableProviders.filter((p) => !linkedProviders.has(p));
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<div class="authrim-account-settings {className}">
|
|
58
|
+
<h1 class="authrim-account-settings__title">Account Settings</h1>
|
|
59
|
+
|
|
60
|
+
<div class="authrim-account-settings__grid">
|
|
61
|
+
<!-- Passkeys Section -->
|
|
62
|
+
<Card class="authrim-account-settings__section">
|
|
63
|
+
<div slot="header" class="authrim-account-settings__section-header">
|
|
64
|
+
<div>
|
|
65
|
+
<h2 class="authrim-account-settings__section-title">Passkeys</h2>
|
|
66
|
+
<p class="authrim-account-settings__section-desc">
|
|
67
|
+
Passkeys let you sign in securely without a password
|
|
68
|
+
</p>
|
|
69
|
+
</div>
|
|
70
|
+
<PasskeyRegisterButton
|
|
71
|
+
variant="outline"
|
|
72
|
+
size="sm"
|
|
73
|
+
loading={passkeyLoading}
|
|
74
|
+
on:click={() => dispatch('passkey-register')}
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<PasskeyList
|
|
79
|
+
{passkeys}
|
|
80
|
+
{loading}
|
|
81
|
+
deletingId={deletingPasskeyId}
|
|
82
|
+
on:delete={(e) => dispatch('passkey-delete', e.detail)}
|
|
83
|
+
/>
|
|
84
|
+
</Card>
|
|
85
|
+
|
|
86
|
+
<!-- Sessions Section -->
|
|
87
|
+
<Card class="authrim-account-settings__section">
|
|
88
|
+
<div slot="header" class="authrim-account-settings__section-header">
|
|
89
|
+
<div>
|
|
90
|
+
<h2 class="authrim-account-settings__section-title">Active Sessions</h2>
|
|
91
|
+
<p class="authrim-account-settings__section-desc">
|
|
92
|
+
Manage your active sign-in sessions
|
|
93
|
+
</p>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<SessionList
|
|
98
|
+
{sessions}
|
|
99
|
+
{currentSessionId}
|
|
100
|
+
{loading}
|
|
101
|
+
revokingId={revokingSessionId}
|
|
102
|
+
on:revoke={(e) => dispatch('session-revoke', e.detail)}
|
|
103
|
+
/>
|
|
104
|
+
</Card>
|
|
105
|
+
|
|
106
|
+
<!-- Linked Accounts Section -->
|
|
107
|
+
<Card class="authrim-account-settings__section">
|
|
108
|
+
<div slot="header" class="authrim-account-settings__section-header">
|
|
109
|
+
<div>
|
|
110
|
+
<h2 class="authrim-account-settings__section-title">Linked Accounts</h2>
|
|
111
|
+
<p class="authrim-account-settings__section-desc">
|
|
112
|
+
Connect accounts for easier sign-in
|
|
113
|
+
</p>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<LinkedAccountsList
|
|
118
|
+
accounts={linkedAccounts}
|
|
119
|
+
{loading}
|
|
120
|
+
unlinkingId={unlinkingAccountId}
|
|
121
|
+
on:unlink={(e) => dispatch('account-unlink', e.detail)}
|
|
122
|
+
/>
|
|
123
|
+
|
|
124
|
+
{#if availableToLink.length > 0}
|
|
125
|
+
<div class="authrim-account-settings__link-buttons">
|
|
126
|
+
{#each availableToLink as provider}
|
|
127
|
+
<LinkAccountButton
|
|
128
|
+
{provider}
|
|
129
|
+
loading={linkingProvider === provider}
|
|
130
|
+
disabled={loading || !!linkingProvider}
|
|
131
|
+
on:click={() => dispatch('account-link', { provider })}
|
|
132
|
+
/>
|
|
133
|
+
{/each}
|
|
134
|
+
</div>
|
|
135
|
+
{/if}
|
|
136
|
+
</Card>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<style>
|
|
141
|
+
.authrim-account-settings {
|
|
142
|
+
max-width: 800px;
|
|
143
|
+
margin: 0 auto;
|
|
144
|
+
padding: var(--authrim-space-6);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.authrim-account-settings__title {
|
|
148
|
+
margin: 0 0 var(--authrim-space-6);
|
|
149
|
+
font-size: var(--authrim-text-2xl);
|
|
150
|
+
font-weight: 700;
|
|
151
|
+
color: var(--authrim-color-text);
|
|
152
|
+
letter-spacing: var(--authrim-tracking-tight);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.authrim-account-settings__grid {
|
|
156
|
+
display: flex;
|
|
157
|
+
flex-direction: column;
|
|
158
|
+
gap: var(--authrim-space-6);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
:global(.authrim-account-settings__section) {
|
|
162
|
+
overflow: hidden;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.authrim-account-settings__section-header {
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: flex-start;
|
|
168
|
+
justify-content: space-between;
|
|
169
|
+
gap: var(--authrim-space-4);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.authrim-account-settings__section-title {
|
|
173
|
+
margin: 0 0 var(--authrim-space-1);
|
|
174
|
+
font-size: var(--authrim-text-base);
|
|
175
|
+
font-weight: 600;
|
|
176
|
+
color: var(--authrim-color-text);
|
|
177
|
+
letter-spacing: var(--authrim-tracking-tight);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.authrim-account-settings__section-desc {
|
|
181
|
+
margin: 0;
|
|
182
|
+
font-size: var(--authrim-text-sm);
|
|
183
|
+
color: var(--authrim-color-text-secondary);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.authrim-account-settings__link-buttons {
|
|
187
|
+
display: flex;
|
|
188
|
+
flex-wrap: wrap;
|
|
189
|
+
gap: var(--authrim-space-2);
|
|
190
|
+
padding: var(--authrim-space-4);
|
|
191
|
+
border-top: 1px solid var(--authrim-color-border-subtle);
|
|
192
|
+
background: var(--authrim-color-bg-subtle);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@media (max-width: 640px) {
|
|
196
|
+
.authrim-account-settings {
|
|
197
|
+
padding: var(--authrim-space-4);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.authrim-account-settings__section-header {
|
|
201
|
+
flex-direction: column;
|
|
202
|
+
gap: var(--authrim-space-3);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
</style>
|