@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,224 +1,224 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
EmailCodeForm Component
|
|
3
|
-
Two-step email + code verification form
|
|
4
|
-
-->
|
|
5
|
-
<script lang="ts">
|
|
6
|
-
import { createEventDispatcher } from 'svelte';
|
|
7
|
-
import type { EmailCodeStep } from '../types.js';
|
|
8
|
-
import Button from '../shared/Button.svelte';
|
|
9
|
-
import Input from '../shared/Input.svelte';
|
|
10
|
-
import AuthError from '../helpers/AuthError.svelte';
|
|
11
|
-
import OTPInput from '../helpers/OTPInput.svelte';
|
|
12
|
-
import ResendCodeButton from '../helpers/ResendCodeButton.svelte';
|
|
13
|
-
|
|
14
|
-
export let step: EmailCodeStep = 'email';
|
|
15
|
-
export let email = '';
|
|
16
|
-
export let maskedEmail = '';
|
|
17
|
-
export let loading = false;
|
|
18
|
-
export let error = '';
|
|
19
|
-
export let resendRemainingTime = 0;
|
|
20
|
-
let className = '';
|
|
21
|
-
export { className as class };
|
|
22
|
-
|
|
23
|
-
const dispatch = createEventDispatcher<{
|
|
24
|
-
'submit-email': { email: string };
|
|
25
|
-
'submit-code': { code: string };
|
|
26
|
-
'dismiss-error': void;
|
|
27
|
-
back: void;
|
|
28
|
-
resend: void;
|
|
29
|
-
}>();
|
|
30
|
-
|
|
31
|
-
let code = '';
|
|
32
|
-
let emailInput = '';
|
|
33
|
-
|
|
34
|
-
$: emailInput = email;
|
|
35
|
-
|
|
36
|
-
function handleEmailSubmit() {
|
|
37
|
-
if (emailInput.trim() && !loading) {
|
|
38
|
-
dispatch('submit-email', { email: emailInput.trim() });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function handleCodeComplete(e: CustomEvent<{ value: string }>) {
|
|
43
|
-
code = e.detail.value;
|
|
44
|
-
if (!loading) {
|
|
45
|
-
dispatch('submit-code', { code });
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function handleBack() {
|
|
50
|
-
code = '';
|
|
51
|
-
dispatch('back');
|
|
52
|
-
}
|
|
53
|
-
</script>
|
|
54
|
-
|
|
55
|
-
<div class="authrim-email-form {className}" {...$$restProps}>
|
|
56
|
-
{#if step === 'email'}
|
|
57
|
-
<form on:submit|preventDefault={handleEmailSubmit} class="authrim-email-form__form">
|
|
58
|
-
<div class="authrim-email-form__header">
|
|
59
|
-
<h2 class="authrim-email-form__title">Sign in with email</h2>
|
|
60
|
-
<p class="authrim-email-form__desc">
|
|
61
|
-
Enter your email and we'll send you a verification code
|
|
62
|
-
</p>
|
|
63
|
-
</div>
|
|
64
|
-
|
|
65
|
-
{#if error}
|
|
66
|
-
<AuthError message={error} on:dismiss={() => dispatch('dismiss-error')} />
|
|
67
|
-
{/if}
|
|
68
|
-
|
|
69
|
-
<Input
|
|
70
|
-
type="email"
|
|
71
|
-
label="Email address"
|
|
72
|
-
placeholder="you@example.com"
|
|
73
|
-
bind:value={emailInput}
|
|
74
|
-
disabled={loading}
|
|
75
|
-
required
|
|
76
|
-
fullWidth
|
|
77
|
-
size="lg"
|
|
78
|
-
error={!!error}
|
|
79
|
-
/>
|
|
80
|
-
|
|
81
|
-
<Button type="submit" {loading} fullWidth size="lg">
|
|
82
|
-
Continue
|
|
83
|
-
</Button>
|
|
84
|
-
</form>
|
|
85
|
-
{:else}
|
|
86
|
-
<div class="authrim-email-form__code">
|
|
87
|
-
<button
|
|
88
|
-
type="button"
|
|
89
|
-
class="authrim-email-form__back"
|
|
90
|
-
on:click={handleBack}
|
|
91
|
-
disabled={loading}
|
|
92
|
-
>
|
|
93
|
-
<svg viewBox="0 0 20 20" fill="currentColor" class="authrim-email-form__back-icon">
|
|
94
|
-
<path fill-rule="evenodd" d="M17 10a.75.75 0 01-.75.75H5.612l4.158 3.96a.75.75 0 11-1.04 1.08l-5.5-5.25a.75.75 0 010-1.08l5.5-5.25a.75.75 0 111.04 1.08L5.612 9.25H16.25A.75.75 0 0117 10z" clip-rule="evenodd"/>
|
|
95
|
-
</svg>
|
|
96
|
-
Back
|
|
97
|
-
</button>
|
|
98
|
-
|
|
99
|
-
<div class="authrim-email-form__header">
|
|
100
|
-
<h2 class="authrim-email-form__title">Check your email</h2>
|
|
101
|
-
<p class="authrim-email-form__desc">
|
|
102
|
-
We sent a code to <strong>{maskedEmail || email}</strong>
|
|
103
|
-
</p>
|
|
104
|
-
</div>
|
|
105
|
-
|
|
106
|
-
{#if error}
|
|
107
|
-
<AuthError message={error} on:dismiss={() => dispatch('dismiss-error')} />
|
|
108
|
-
{/if}
|
|
109
|
-
|
|
110
|
-
<div class="authrim-email-form__otp-wrap">
|
|
111
|
-
<OTPInput
|
|
112
|
-
bind:value={code}
|
|
113
|
-
disabled={loading}
|
|
114
|
-
error={!!error}
|
|
115
|
-
on:complete={handleCodeComplete}
|
|
116
|
-
/>
|
|
117
|
-
</div>
|
|
118
|
-
|
|
119
|
-
<div class="authrim-email-form__resend">
|
|
120
|
-
<span class="authrim-email-form__resend-text">Didn't receive the code?</span>
|
|
121
|
-
<ResendCodeButton
|
|
122
|
-
remainingTime={resendRemainingTime}
|
|
123
|
-
{loading}
|
|
124
|
-
on:click={() => dispatch('resend')}
|
|
125
|
-
/>
|
|
126
|
-
</div>
|
|
127
|
-
|
|
128
|
-
<Button
|
|
129
|
-
type="button"
|
|
130
|
-
{loading}
|
|
131
|
-
fullWidth
|
|
132
|
-
size="lg"
|
|
133
|
-
disabled={code.length < 6}
|
|
134
|
-
on:click={() => dispatch('submit-code', { code })}
|
|
135
|
-
>
|
|
136
|
-
Verify
|
|
137
|
-
</Button>
|
|
138
|
-
</div>
|
|
139
|
-
{/if}
|
|
140
|
-
</div>
|
|
141
|
-
|
|
142
|
-
<style>
|
|
143
|
-
.authrim-email-form__form,
|
|
144
|
-
.authrim-email-form__code {
|
|
145
|
-
display: flex;
|
|
146
|
-
flex-direction: column;
|
|
147
|
-
gap: var(--authrim-space-5);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.authrim-email-form__header {
|
|
151
|
-
text-align: center;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
.authrim-email-form__title {
|
|
155
|
-
margin: 0 0 var(--authrim-space-2);
|
|
156
|
-
font-size: var(--authrim-text-xl);
|
|
157
|
-
font-weight: 700;
|
|
158
|
-
color: var(--authrim-color-text);
|
|
159
|
-
letter-spacing: var(--authrim-tracking-tight);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
.authrim-email-form__desc {
|
|
163
|
-
margin: 0;
|
|
164
|
-
font-size: var(--authrim-text-sm);
|
|
165
|
-
color: var(--authrim-color-text-secondary);
|
|
166
|
-
line-height: var(--authrim-leading-relaxed);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
.authrim-email-form__desc strong {
|
|
170
|
-
color: var(--authrim-color-text);
|
|
171
|
-
font-weight: 600;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
.authrim-email-form__back {
|
|
175
|
-
display: inline-flex;
|
|
176
|
-
align-items: center;
|
|
177
|
-
gap: var(--authrim-space-1);
|
|
178
|
-
padding: var(--authrim-space-1) var(--authrim-space-2);
|
|
179
|
-
margin: 0 0 var(--authrim-space-2) calc(-1 * var(--authrim-space-2));
|
|
180
|
-
font-family: var(--authrim-font-sans);
|
|
181
|
-
font-size: var(--authrim-text-sm);
|
|
182
|
-
font-weight: 500;
|
|
183
|
-
color: var(--authrim-color-text-secondary);
|
|
184
|
-
background: transparent;
|
|
185
|
-
border: none;
|
|
186
|
-
border-radius: var(--authrim-radius-sm);
|
|
187
|
-
cursor: pointer;
|
|
188
|
-
transition:
|
|
189
|
-
color var(--authrim-duration-fast) var(--authrim-ease-default),
|
|
190
|
-
background-color var(--authrim-duration-fast) var(--authrim-ease-default);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.authrim-email-form__back:hover:not(:disabled) {
|
|
194
|
-
color: var(--authrim-color-text);
|
|
195
|
-
background: var(--authrim-color-bg-subtle);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.authrim-email-form__back:disabled {
|
|
199
|
-
opacity: 0.5;
|
|
200
|
-
cursor: not-allowed;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
.authrim-email-form__back-icon {
|
|
204
|
-
width: 18px;
|
|
205
|
-
height: 18px;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.authrim-email-form__otp-wrap {
|
|
209
|
-
padding: var(--authrim-space-4) 0;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
.authrim-email-form__resend {
|
|
213
|
-
display: flex;
|
|
214
|
-
align-items: center;
|
|
215
|
-
justify-content: center;
|
|
216
|
-
gap: var(--authrim-space-1);
|
|
217
|
-
flex-wrap: wrap;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
.authrim-email-form__resend-text {
|
|
221
|
-
font-size: var(--authrim-text-sm);
|
|
222
|
-
color: var(--authrim-color-text-muted);
|
|
223
|
-
}
|
|
224
|
-
</style>
|
|
1
|
+
<!--
|
|
2
|
+
EmailCodeForm Component
|
|
3
|
+
Two-step email + code verification form
|
|
4
|
+
-->
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { createEventDispatcher } from 'svelte';
|
|
7
|
+
import type { EmailCodeStep } from '../types.js';
|
|
8
|
+
import Button from '../shared/Button.svelte';
|
|
9
|
+
import Input from '../shared/Input.svelte';
|
|
10
|
+
import AuthError from '../helpers/AuthError.svelte';
|
|
11
|
+
import OTPInput from '../helpers/OTPInput.svelte';
|
|
12
|
+
import ResendCodeButton from '../helpers/ResendCodeButton.svelte';
|
|
13
|
+
|
|
14
|
+
export let step: EmailCodeStep = 'email';
|
|
15
|
+
export let email = '';
|
|
16
|
+
export let maskedEmail = '';
|
|
17
|
+
export let loading = false;
|
|
18
|
+
export let error = '';
|
|
19
|
+
export let resendRemainingTime = 0;
|
|
20
|
+
let className = '';
|
|
21
|
+
export { className as class };
|
|
22
|
+
|
|
23
|
+
const dispatch = createEventDispatcher<{
|
|
24
|
+
'submit-email': { email: string };
|
|
25
|
+
'submit-code': { code: string };
|
|
26
|
+
'dismiss-error': void;
|
|
27
|
+
back: void;
|
|
28
|
+
resend: void;
|
|
29
|
+
}>();
|
|
30
|
+
|
|
31
|
+
let code = '';
|
|
32
|
+
let emailInput = '';
|
|
33
|
+
|
|
34
|
+
$: emailInput = email;
|
|
35
|
+
|
|
36
|
+
function handleEmailSubmit() {
|
|
37
|
+
if (emailInput.trim() && !loading) {
|
|
38
|
+
dispatch('submit-email', { email: emailInput.trim() });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function handleCodeComplete(e: CustomEvent<{ value: string }>) {
|
|
43
|
+
code = e.detail.value;
|
|
44
|
+
if (!loading) {
|
|
45
|
+
dispatch('submit-code', { code });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function handleBack() {
|
|
50
|
+
code = '';
|
|
51
|
+
dispatch('back');
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<div class="authrim-email-form {className}" {...$$restProps}>
|
|
56
|
+
{#if step === 'email'}
|
|
57
|
+
<form on:submit|preventDefault={handleEmailSubmit} class="authrim-email-form__form">
|
|
58
|
+
<div class="authrim-email-form__header">
|
|
59
|
+
<h2 class="authrim-email-form__title">Sign in with email</h2>
|
|
60
|
+
<p class="authrim-email-form__desc">
|
|
61
|
+
Enter your email and we'll send you a verification code
|
|
62
|
+
</p>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
{#if error}
|
|
66
|
+
<AuthError message={error} on:dismiss={() => dispatch('dismiss-error')} />
|
|
67
|
+
{/if}
|
|
68
|
+
|
|
69
|
+
<Input
|
|
70
|
+
type="email"
|
|
71
|
+
label="Email address"
|
|
72
|
+
placeholder="you@example.com"
|
|
73
|
+
bind:value={emailInput}
|
|
74
|
+
disabled={loading}
|
|
75
|
+
required
|
|
76
|
+
fullWidth
|
|
77
|
+
size="lg"
|
|
78
|
+
error={!!error}
|
|
79
|
+
/>
|
|
80
|
+
|
|
81
|
+
<Button type="submit" {loading} fullWidth size="lg">
|
|
82
|
+
Continue
|
|
83
|
+
</Button>
|
|
84
|
+
</form>
|
|
85
|
+
{:else}
|
|
86
|
+
<div class="authrim-email-form__code">
|
|
87
|
+
<button
|
|
88
|
+
type="button"
|
|
89
|
+
class="authrim-email-form__back"
|
|
90
|
+
on:click={handleBack}
|
|
91
|
+
disabled={loading}
|
|
92
|
+
>
|
|
93
|
+
<svg viewBox="0 0 20 20" fill="currentColor" class="authrim-email-form__back-icon">
|
|
94
|
+
<path fill-rule="evenodd" d="M17 10a.75.75 0 01-.75.75H5.612l4.158 3.96a.75.75 0 11-1.04 1.08l-5.5-5.25a.75.75 0 010-1.08l5.5-5.25a.75.75 0 111.04 1.08L5.612 9.25H16.25A.75.75 0 0117 10z" clip-rule="evenodd"/>
|
|
95
|
+
</svg>
|
|
96
|
+
Back
|
|
97
|
+
</button>
|
|
98
|
+
|
|
99
|
+
<div class="authrim-email-form__header">
|
|
100
|
+
<h2 class="authrim-email-form__title">Check your email</h2>
|
|
101
|
+
<p class="authrim-email-form__desc">
|
|
102
|
+
We sent a code to <strong>{maskedEmail || email}</strong>
|
|
103
|
+
</p>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
{#if error}
|
|
107
|
+
<AuthError message={error} on:dismiss={() => dispatch('dismiss-error')} />
|
|
108
|
+
{/if}
|
|
109
|
+
|
|
110
|
+
<div class="authrim-email-form__otp-wrap">
|
|
111
|
+
<OTPInput
|
|
112
|
+
bind:value={code}
|
|
113
|
+
disabled={loading}
|
|
114
|
+
error={!!error}
|
|
115
|
+
on:complete={handleCodeComplete}
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<div class="authrim-email-form__resend">
|
|
120
|
+
<span class="authrim-email-form__resend-text">Didn't receive the code?</span>
|
|
121
|
+
<ResendCodeButton
|
|
122
|
+
remainingTime={resendRemainingTime}
|
|
123
|
+
{loading}
|
|
124
|
+
on:click={() => dispatch('resend')}
|
|
125
|
+
/>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<Button
|
|
129
|
+
type="button"
|
|
130
|
+
{loading}
|
|
131
|
+
fullWidth
|
|
132
|
+
size="lg"
|
|
133
|
+
disabled={code.length < 6}
|
|
134
|
+
on:click={() => dispatch('submit-code', { code })}
|
|
135
|
+
>
|
|
136
|
+
Verify
|
|
137
|
+
</Button>
|
|
138
|
+
</div>
|
|
139
|
+
{/if}
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<style>
|
|
143
|
+
.authrim-email-form__form,
|
|
144
|
+
.authrim-email-form__code {
|
|
145
|
+
display: flex;
|
|
146
|
+
flex-direction: column;
|
|
147
|
+
gap: var(--authrim-space-5);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.authrim-email-form__header {
|
|
151
|
+
text-align: center;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.authrim-email-form__title {
|
|
155
|
+
margin: 0 0 var(--authrim-space-2);
|
|
156
|
+
font-size: var(--authrim-text-xl);
|
|
157
|
+
font-weight: 700;
|
|
158
|
+
color: var(--authrim-color-text);
|
|
159
|
+
letter-spacing: var(--authrim-tracking-tight);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.authrim-email-form__desc {
|
|
163
|
+
margin: 0;
|
|
164
|
+
font-size: var(--authrim-text-sm);
|
|
165
|
+
color: var(--authrim-color-text-secondary);
|
|
166
|
+
line-height: var(--authrim-leading-relaxed);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.authrim-email-form__desc strong {
|
|
170
|
+
color: var(--authrim-color-text);
|
|
171
|
+
font-weight: 600;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.authrim-email-form__back {
|
|
175
|
+
display: inline-flex;
|
|
176
|
+
align-items: center;
|
|
177
|
+
gap: var(--authrim-space-1);
|
|
178
|
+
padding: var(--authrim-space-1) var(--authrim-space-2);
|
|
179
|
+
margin: 0 0 var(--authrim-space-2) calc(-1 * var(--authrim-space-2));
|
|
180
|
+
font-family: var(--authrim-font-sans);
|
|
181
|
+
font-size: var(--authrim-text-sm);
|
|
182
|
+
font-weight: 500;
|
|
183
|
+
color: var(--authrim-color-text-secondary);
|
|
184
|
+
background: transparent;
|
|
185
|
+
border: none;
|
|
186
|
+
border-radius: var(--authrim-radius-sm);
|
|
187
|
+
cursor: pointer;
|
|
188
|
+
transition:
|
|
189
|
+
color var(--authrim-duration-fast) var(--authrim-ease-default),
|
|
190
|
+
background-color var(--authrim-duration-fast) var(--authrim-ease-default);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.authrim-email-form__back:hover:not(:disabled) {
|
|
194
|
+
color: var(--authrim-color-text);
|
|
195
|
+
background: var(--authrim-color-bg-subtle);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.authrim-email-form__back:disabled {
|
|
199
|
+
opacity: 0.5;
|
|
200
|
+
cursor: not-allowed;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.authrim-email-form__back-icon {
|
|
204
|
+
width: 18px;
|
|
205
|
+
height: 18px;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.authrim-email-form__otp-wrap {
|
|
209
|
+
padding: var(--authrim-space-4) 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.authrim-email-form__resend {
|
|
213
|
+
display: flex;
|
|
214
|
+
align-items: center;
|
|
215
|
+
justify-content: center;
|
|
216
|
+
gap: var(--authrim-space-1);
|
|
217
|
+
flex-wrap: wrap;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.authrim-email-form__resend-text {
|
|
221
|
+
font-size: var(--authrim-text-sm);
|
|
222
|
+
color: var(--authrim-color-text-muted);
|
|
223
|
+
}
|
|
224
|
+
</style>
|