@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,345 +1,345 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SignUpTemplate Component
|
|
3
|
-
|
|
4
|
-
Reference implementation for sign-up screens.
|
|
5
|
-
Copy and customize for production use.
|
|
6
|
-
|
|
7
|
-
@example
|
|
8
|
-
<SignUpTemplate
|
|
9
|
-
availableProviders={['google', 'github']}
|
|
10
|
-
enablePasskey={true}
|
|
11
|
-
on:passkey-signup={handlePasskeySignup}
|
|
12
|
-
on:social-signup={handleSocialSignup}
|
|
13
|
-
on:email-submit={handleEmailSubmit}
|
|
14
|
-
/>
|
|
15
|
-
-->
|
|
16
|
-
<script lang="ts">
|
|
17
|
-
import { createEventDispatcher } from 'svelte';
|
|
18
|
-
import type { SocialProvider } from '../../types.js';
|
|
19
|
-
import Card from '../shared/Card.svelte';
|
|
20
|
-
import Button from '../shared/Button.svelte';
|
|
21
|
-
import Input from '../shared/Input.svelte';
|
|
22
|
-
import AuthError from '../helpers/AuthError.svelte';
|
|
23
|
-
import SocialLoginButtons from '../forms/SocialLoginButtons.svelte';
|
|
24
|
-
import OTPInput from '../helpers/OTPInput.svelte';
|
|
25
|
-
import ResendCodeButton from '../helpers/ResendCodeButton.svelte';
|
|
26
|
-
|
|
27
|
-
export let availableProviders: SocialProvider[] = [];
|
|
28
|
-
export let enablePasskey = true;
|
|
29
|
-
export let enableEmailCode = true;
|
|
30
|
-
export let loading = false;
|
|
31
|
-
export let loadingProvider: SocialProvider | undefined = undefined;
|
|
32
|
-
export let error = '';
|
|
33
|
-
export let title = 'Create account';
|
|
34
|
-
export let subtitle = 'Get started with your free account';
|
|
35
|
-
let className = '';
|
|
36
|
-
export { className as class };
|
|
37
|
-
|
|
38
|
-
const dispatch = createEventDispatcher<{
|
|
39
|
-
'passkey-signup': { name: string };
|
|
40
|
-
'social-signup': { provider: SocialProvider };
|
|
41
|
-
'email-submit': { email: string; name: string };
|
|
42
|
-
'code-submit': { code: string };
|
|
43
|
-
'code-resend': void;
|
|
44
|
-
'dismiss-error': void;
|
|
45
|
-
}>();
|
|
46
|
-
|
|
47
|
-
let step: 'form' | 'code' = 'form';
|
|
48
|
-
let name = '';
|
|
49
|
-
let email = '';
|
|
50
|
-
let code = '';
|
|
51
|
-
let resendTime = 0;
|
|
52
|
-
|
|
53
|
-
function handlePasskeySignup() {
|
|
54
|
-
if (name.trim()) {
|
|
55
|
-
dispatch('passkey-signup', { name: name.trim() });
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function handleSocialClick(e: CustomEvent<{ provider: SocialProvider }>) {
|
|
60
|
-
dispatch('social-signup', e.detail);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function handleEmailSubmit() {
|
|
64
|
-
if (email.trim() && name.trim()) {
|
|
65
|
-
dispatch('email-submit', { email: email.trim(), name: name.trim() });
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function handleCodeComplete(e: CustomEvent<{ value: string }>) {
|
|
70
|
-
code = e.detail.value;
|
|
71
|
-
dispatch('code-submit', { code });
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function handleBack() {
|
|
75
|
-
step = 'form';
|
|
76
|
-
code = '';
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function setStep(newStep: 'form' | 'code') {
|
|
80
|
-
step = newStep;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function setResendTime(time: number) {
|
|
84
|
-
resendTime = time;
|
|
85
|
-
}
|
|
86
|
-
</script>
|
|
87
|
-
|
|
88
|
-
<div class="authrim-signup-template {className}">
|
|
89
|
-
<Card padding="lg" shadow="lg" class="authrim-signup-template__card">
|
|
90
|
-
{#if step === 'form'}
|
|
91
|
-
<div class="authrim-signup-template__header">
|
|
92
|
-
<h1 class="authrim-signup-template__title">{title}</h1>
|
|
93
|
-
<p class="authrim-signup-template__subtitle">{subtitle}</p>
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
{#if error}
|
|
97
|
-
<AuthError message={error} on:dismiss={() => dispatch('dismiss-error')} />
|
|
98
|
-
{/if}
|
|
99
|
-
|
|
100
|
-
<div class="authrim-signup-template__content">
|
|
101
|
-
<form on:submit|preventDefault={enablePasskey ? handlePasskeySignup : handleEmailSubmit} class="authrim-signup-template__form">
|
|
102
|
-
<Input
|
|
103
|
-
label="Name"
|
|
104
|
-
placeholder="Your name"
|
|
105
|
-
bind:value={name}
|
|
106
|
-
disabled={loading}
|
|
107
|
-
required
|
|
108
|
-
fullWidth
|
|
109
|
-
size="lg"
|
|
110
|
-
/>
|
|
111
|
-
|
|
112
|
-
{#if enableEmailCode && !enablePasskey}
|
|
113
|
-
<Input
|
|
114
|
-
type="email"
|
|
115
|
-
label="Email"
|
|
116
|
-
placeholder="you@example.com"
|
|
117
|
-
bind:value={email}
|
|
118
|
-
disabled={loading}
|
|
119
|
-
required
|
|
120
|
-
fullWidth
|
|
121
|
-
size="lg"
|
|
122
|
-
/>
|
|
123
|
-
{/if}
|
|
124
|
-
|
|
125
|
-
{#if enablePasskey}
|
|
126
|
-
<Button type="submit" fullWidth size="lg" {loading} disabled={!name.trim()}>
|
|
127
|
-
Create account with Passkey
|
|
128
|
-
</Button>
|
|
129
|
-
{:else if enableEmailCode}
|
|
130
|
-
<Button type="submit" fullWidth size="lg" {loading} disabled={!name.trim() || !email.trim()}>
|
|
131
|
-
Continue
|
|
132
|
-
</Button>
|
|
133
|
-
{/if}
|
|
134
|
-
</form>
|
|
135
|
-
|
|
136
|
-
{#if availableProviders.length > 0}
|
|
137
|
-
<div class="authrim-signup-template__divider">
|
|
138
|
-
<span>or sign up with</span>
|
|
139
|
-
</div>
|
|
140
|
-
|
|
141
|
-
<SocialLoginButtons
|
|
142
|
-
providers={availableProviders}
|
|
143
|
-
{loading}
|
|
144
|
-
{loadingProvider}
|
|
145
|
-
on:click={handleSocialClick}
|
|
146
|
-
/>
|
|
147
|
-
{/if}
|
|
148
|
-
</div>
|
|
149
|
-
|
|
150
|
-
{:else}
|
|
151
|
-
<button type="button" class="authrim-signup-template__back" on:click={handleBack}>
|
|
152
|
-
<svg viewBox="0 0 20 20" fill="currentColor">
|
|
153
|
-
<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"/>
|
|
154
|
-
</svg>
|
|
155
|
-
Back
|
|
156
|
-
</button>
|
|
157
|
-
|
|
158
|
-
<div class="authrim-signup-template__header">
|
|
159
|
-
<h1 class="authrim-signup-template__title">Verify your email</h1>
|
|
160
|
-
<p class="authrim-signup-template__subtitle">
|
|
161
|
-
We sent a code to <strong>{email}</strong>
|
|
162
|
-
</p>
|
|
163
|
-
</div>
|
|
164
|
-
|
|
165
|
-
{#if error}
|
|
166
|
-
<AuthError message={error} on:dismiss={() => dispatch('dismiss-error')} />
|
|
167
|
-
{/if}
|
|
168
|
-
|
|
169
|
-
<div class="authrim-signup-template__code">
|
|
170
|
-
<OTPInput
|
|
171
|
-
bind:value={code}
|
|
172
|
-
disabled={loading}
|
|
173
|
-
on:complete={handleCodeComplete}
|
|
174
|
-
/>
|
|
175
|
-
|
|
176
|
-
<div class="authrim-signup-template__resend">
|
|
177
|
-
<span>Didn't receive the code?</span>
|
|
178
|
-
<ResendCodeButton
|
|
179
|
-
remainingTime={resendTime}
|
|
180
|
-
{loading}
|
|
181
|
-
on:click={() => dispatch('code-resend')}
|
|
182
|
-
/>
|
|
183
|
-
</div>
|
|
184
|
-
|
|
185
|
-
<Button
|
|
186
|
-
fullWidth
|
|
187
|
-
size="lg"
|
|
188
|
-
{loading}
|
|
189
|
-
disabled={code.length < 6}
|
|
190
|
-
on:click={() => dispatch('code-submit', { code })}
|
|
191
|
-
>
|
|
192
|
-
Verify
|
|
193
|
-
</Button>
|
|
194
|
-
</div>
|
|
195
|
-
{/if}
|
|
196
|
-
</Card>
|
|
197
|
-
|
|
198
|
-
{#if step === 'form'}
|
|
199
|
-
<div class="authrim-signup-template__footer">
|
|
200
|
-
<slot name="footer">
|
|
201
|
-
<p>
|
|
202
|
-
Already have an account?
|
|
203
|
-
<a href="/login" class="authrim-signup-template__link">Sign in</a>
|
|
204
|
-
</p>
|
|
205
|
-
</slot>
|
|
206
|
-
</div>
|
|
207
|
-
{/if}
|
|
208
|
-
</div>
|
|
209
|
-
|
|
210
|
-
<style>
|
|
211
|
-
.authrim-signup-template {
|
|
212
|
-
display: flex;
|
|
213
|
-
justify-content: center;
|
|
214
|
-
align-items: center;
|
|
215
|
-
min-height: 100vh;
|
|
216
|
-
padding: var(--authrim-space-4);
|
|
217
|
-
background:
|
|
218
|
-
linear-gradient(135deg, var(--authrim-color-bg-subtle) 0%, var(--authrim-color-bg) 100%);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
:global(.authrim-signup-template__card) {
|
|
222
|
-
width: 100%;
|
|
223
|
-
max-width: 420px;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
.authrim-signup-template__header {
|
|
227
|
-
text-align: center;
|
|
228
|
-
margin-bottom: var(--authrim-space-6);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
.authrim-signup-template__title {
|
|
232
|
-
margin: 0 0 var(--authrim-space-2);
|
|
233
|
-
font-size: var(--authrim-text-2xl);
|
|
234
|
-
font-weight: 700;
|
|
235
|
-
color: var(--authrim-color-text);
|
|
236
|
-
letter-spacing: var(--authrim-tracking-tight);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
.authrim-signup-template__subtitle {
|
|
240
|
-
margin: 0;
|
|
241
|
-
font-size: var(--authrim-text-sm);
|
|
242
|
-
color: var(--authrim-color-text-secondary);
|
|
243
|
-
line-height: var(--authrim-leading-relaxed);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
.authrim-signup-template__subtitle strong {
|
|
247
|
-
color: var(--authrim-color-text);
|
|
248
|
-
font-weight: 600;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.authrim-signup-template__content {
|
|
252
|
-
display: flex;
|
|
253
|
-
flex-direction: column;
|
|
254
|
-
gap: var(--authrim-space-5);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
.authrim-signup-template__form {
|
|
258
|
-
display: flex;
|
|
259
|
-
flex-direction: column;
|
|
260
|
-
gap: var(--authrim-space-4);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
.authrim-signup-template__divider {
|
|
264
|
-
display: flex;
|
|
265
|
-
align-items: center;
|
|
266
|
-
gap: var(--authrim-space-3);
|
|
267
|
-
color: var(--authrim-color-text-muted);
|
|
268
|
-
font-size: var(--authrim-text-sm);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
.authrim-signup-template__divider::before,
|
|
272
|
-
.authrim-signup-template__divider::after {
|
|
273
|
-
content: '';
|
|
274
|
-
flex: 1;
|
|
275
|
-
height: 1px;
|
|
276
|
-
background: var(--authrim-color-border);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.authrim-signup-template__back {
|
|
280
|
-
display: inline-flex;
|
|
281
|
-
align-items: center;
|
|
282
|
-
gap: var(--authrim-space-1);
|
|
283
|
-
padding: var(--authrim-space-1) var(--authrim-space-2);
|
|
284
|
-
margin: 0 0 var(--authrim-space-4) calc(-1 * var(--authrim-space-2));
|
|
285
|
-
font-family: var(--authrim-font-sans);
|
|
286
|
-
font-size: var(--authrim-text-sm);
|
|
287
|
-
font-weight: 500;
|
|
288
|
-
color: var(--authrim-color-text-secondary);
|
|
289
|
-
background: transparent;
|
|
290
|
-
border: none;
|
|
291
|
-
border-radius: var(--authrim-radius-sm);
|
|
292
|
-
cursor: pointer;
|
|
293
|
-
transition:
|
|
294
|
-
color var(--authrim-duration-fast) var(--authrim-ease-default),
|
|
295
|
-
background-color var(--authrim-duration-fast) var(--authrim-ease-default);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
.authrim-signup-template__back:hover {
|
|
299
|
-
color: var(--authrim-color-text);
|
|
300
|
-
background: var(--authrim-color-bg-subtle);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
.authrim-signup-template__back svg {
|
|
304
|
-
width: 18px;
|
|
305
|
-
height: 18px;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
.authrim-signup-template__code {
|
|
309
|
-
display: flex;
|
|
310
|
-
flex-direction: column;
|
|
311
|
-
gap: var(--authrim-space-5);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
.authrim-signup-template__resend {
|
|
315
|
-
display: flex;
|
|
316
|
-
align-items: center;
|
|
317
|
-
justify-content: center;
|
|
318
|
-
gap: var(--authrim-space-1);
|
|
319
|
-
flex-wrap: wrap;
|
|
320
|
-
font-size: var(--authrim-text-sm);
|
|
321
|
-
color: var(--authrim-color-text-muted);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
.authrim-signup-template__footer {
|
|
325
|
-
text-align: center;
|
|
326
|
-
font-size: var(--authrim-text-sm);
|
|
327
|
-
color: var(--authrim-color-text-secondary);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
.authrim-signup-template__footer p {
|
|
331
|
-
margin: 0;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
.authrim-signup-template__link {
|
|
335
|
-
color: var(--authrim-color-primary);
|
|
336
|
-
font-weight: 500;
|
|
337
|
-
text-decoration: none;
|
|
338
|
-
transition: color var(--authrim-duration-fast) var(--authrim-ease-default);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
.authrim-signup-template__link:hover {
|
|
342
|
-
color: var(--authrim-color-primary-hover);
|
|
343
|
-
text-decoration: underline;
|
|
344
|
-
}
|
|
345
|
-
</style>
|
|
1
|
+
<!--
|
|
2
|
+
SignUpTemplate Component
|
|
3
|
+
|
|
4
|
+
Reference implementation for sign-up screens.
|
|
5
|
+
Copy and customize for production use.
|
|
6
|
+
|
|
7
|
+
@example
|
|
8
|
+
<SignUpTemplate
|
|
9
|
+
availableProviders={['google', 'github']}
|
|
10
|
+
enablePasskey={true}
|
|
11
|
+
on:passkey-signup={handlePasskeySignup}
|
|
12
|
+
on:social-signup={handleSocialSignup}
|
|
13
|
+
on:email-submit={handleEmailSubmit}
|
|
14
|
+
/>
|
|
15
|
+
-->
|
|
16
|
+
<script lang="ts">
|
|
17
|
+
import { createEventDispatcher } from 'svelte';
|
|
18
|
+
import type { SocialProvider } from '../../types.js';
|
|
19
|
+
import Card from '../shared/Card.svelte';
|
|
20
|
+
import Button from '../shared/Button.svelte';
|
|
21
|
+
import Input from '../shared/Input.svelte';
|
|
22
|
+
import AuthError from '../helpers/AuthError.svelte';
|
|
23
|
+
import SocialLoginButtons from '../forms/SocialLoginButtons.svelte';
|
|
24
|
+
import OTPInput from '../helpers/OTPInput.svelte';
|
|
25
|
+
import ResendCodeButton from '../helpers/ResendCodeButton.svelte';
|
|
26
|
+
|
|
27
|
+
export let availableProviders: SocialProvider[] = [];
|
|
28
|
+
export let enablePasskey = true;
|
|
29
|
+
export let enableEmailCode = true;
|
|
30
|
+
export let loading = false;
|
|
31
|
+
export let loadingProvider: SocialProvider | undefined = undefined;
|
|
32
|
+
export let error = '';
|
|
33
|
+
export let title = 'Create account';
|
|
34
|
+
export let subtitle = 'Get started with your free account';
|
|
35
|
+
let className = '';
|
|
36
|
+
export { className as class };
|
|
37
|
+
|
|
38
|
+
const dispatch = createEventDispatcher<{
|
|
39
|
+
'passkey-signup': { name: string };
|
|
40
|
+
'social-signup': { provider: SocialProvider };
|
|
41
|
+
'email-submit': { email: string; name: string };
|
|
42
|
+
'code-submit': { code: string };
|
|
43
|
+
'code-resend': void;
|
|
44
|
+
'dismiss-error': void;
|
|
45
|
+
}>();
|
|
46
|
+
|
|
47
|
+
let step: 'form' | 'code' = 'form';
|
|
48
|
+
let name = '';
|
|
49
|
+
let email = '';
|
|
50
|
+
let code = '';
|
|
51
|
+
let resendTime = 0;
|
|
52
|
+
|
|
53
|
+
function handlePasskeySignup() {
|
|
54
|
+
if (name.trim()) {
|
|
55
|
+
dispatch('passkey-signup', { name: name.trim() });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function handleSocialClick(e: CustomEvent<{ provider: SocialProvider }>) {
|
|
60
|
+
dispatch('social-signup', e.detail);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function handleEmailSubmit() {
|
|
64
|
+
if (email.trim() && name.trim()) {
|
|
65
|
+
dispatch('email-submit', { email: email.trim(), name: name.trim() });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function handleCodeComplete(e: CustomEvent<{ value: string }>) {
|
|
70
|
+
code = e.detail.value;
|
|
71
|
+
dispatch('code-submit', { code });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function handleBack() {
|
|
75
|
+
step = 'form';
|
|
76
|
+
code = '';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function setStep(newStep: 'form' | 'code') {
|
|
80
|
+
step = newStep;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function setResendTime(time: number) {
|
|
84
|
+
resendTime = time;
|
|
85
|
+
}
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<div class="authrim-signup-template {className}">
|
|
89
|
+
<Card padding="lg" shadow="lg" class="authrim-signup-template__card">
|
|
90
|
+
{#if step === 'form'}
|
|
91
|
+
<div class="authrim-signup-template__header">
|
|
92
|
+
<h1 class="authrim-signup-template__title">{title}</h1>
|
|
93
|
+
<p class="authrim-signup-template__subtitle">{subtitle}</p>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
{#if error}
|
|
97
|
+
<AuthError message={error} on:dismiss={() => dispatch('dismiss-error')} />
|
|
98
|
+
{/if}
|
|
99
|
+
|
|
100
|
+
<div class="authrim-signup-template__content">
|
|
101
|
+
<form on:submit|preventDefault={enablePasskey ? handlePasskeySignup : handleEmailSubmit} class="authrim-signup-template__form">
|
|
102
|
+
<Input
|
|
103
|
+
label="Name"
|
|
104
|
+
placeholder="Your name"
|
|
105
|
+
bind:value={name}
|
|
106
|
+
disabled={loading}
|
|
107
|
+
required
|
|
108
|
+
fullWidth
|
|
109
|
+
size="lg"
|
|
110
|
+
/>
|
|
111
|
+
|
|
112
|
+
{#if enableEmailCode && !enablePasskey}
|
|
113
|
+
<Input
|
|
114
|
+
type="email"
|
|
115
|
+
label="Email"
|
|
116
|
+
placeholder="you@example.com"
|
|
117
|
+
bind:value={email}
|
|
118
|
+
disabled={loading}
|
|
119
|
+
required
|
|
120
|
+
fullWidth
|
|
121
|
+
size="lg"
|
|
122
|
+
/>
|
|
123
|
+
{/if}
|
|
124
|
+
|
|
125
|
+
{#if enablePasskey}
|
|
126
|
+
<Button type="submit" fullWidth size="lg" {loading} disabled={!name.trim()}>
|
|
127
|
+
Create account with Passkey
|
|
128
|
+
</Button>
|
|
129
|
+
{:else if enableEmailCode}
|
|
130
|
+
<Button type="submit" fullWidth size="lg" {loading} disabled={!name.trim() || !email.trim()}>
|
|
131
|
+
Continue
|
|
132
|
+
</Button>
|
|
133
|
+
{/if}
|
|
134
|
+
</form>
|
|
135
|
+
|
|
136
|
+
{#if availableProviders.length > 0}
|
|
137
|
+
<div class="authrim-signup-template__divider">
|
|
138
|
+
<span>or sign up with</span>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<SocialLoginButtons
|
|
142
|
+
providers={availableProviders}
|
|
143
|
+
{loading}
|
|
144
|
+
{loadingProvider}
|
|
145
|
+
on:click={handleSocialClick}
|
|
146
|
+
/>
|
|
147
|
+
{/if}
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
{:else}
|
|
151
|
+
<button type="button" class="authrim-signup-template__back" on:click={handleBack}>
|
|
152
|
+
<svg viewBox="0 0 20 20" fill="currentColor">
|
|
153
|
+
<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"/>
|
|
154
|
+
</svg>
|
|
155
|
+
Back
|
|
156
|
+
</button>
|
|
157
|
+
|
|
158
|
+
<div class="authrim-signup-template__header">
|
|
159
|
+
<h1 class="authrim-signup-template__title">Verify your email</h1>
|
|
160
|
+
<p class="authrim-signup-template__subtitle">
|
|
161
|
+
We sent a code to <strong>{email}</strong>
|
|
162
|
+
</p>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
{#if error}
|
|
166
|
+
<AuthError message={error} on:dismiss={() => dispatch('dismiss-error')} />
|
|
167
|
+
{/if}
|
|
168
|
+
|
|
169
|
+
<div class="authrim-signup-template__code">
|
|
170
|
+
<OTPInput
|
|
171
|
+
bind:value={code}
|
|
172
|
+
disabled={loading}
|
|
173
|
+
on:complete={handleCodeComplete}
|
|
174
|
+
/>
|
|
175
|
+
|
|
176
|
+
<div class="authrim-signup-template__resend">
|
|
177
|
+
<span>Didn't receive the code?</span>
|
|
178
|
+
<ResendCodeButton
|
|
179
|
+
remainingTime={resendTime}
|
|
180
|
+
{loading}
|
|
181
|
+
on:click={() => dispatch('code-resend')}
|
|
182
|
+
/>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
<Button
|
|
186
|
+
fullWidth
|
|
187
|
+
size="lg"
|
|
188
|
+
{loading}
|
|
189
|
+
disabled={code.length < 6}
|
|
190
|
+
on:click={() => dispatch('code-submit', { code })}
|
|
191
|
+
>
|
|
192
|
+
Verify
|
|
193
|
+
</Button>
|
|
194
|
+
</div>
|
|
195
|
+
{/if}
|
|
196
|
+
</Card>
|
|
197
|
+
|
|
198
|
+
{#if step === 'form'}
|
|
199
|
+
<div class="authrim-signup-template__footer">
|
|
200
|
+
<slot name="footer">
|
|
201
|
+
<p>
|
|
202
|
+
Already have an account?
|
|
203
|
+
<a href="/login" class="authrim-signup-template__link">Sign in</a>
|
|
204
|
+
</p>
|
|
205
|
+
</slot>
|
|
206
|
+
</div>
|
|
207
|
+
{/if}
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<style>
|
|
211
|
+
.authrim-signup-template {
|
|
212
|
+
display: flex;
|
|
213
|
+
justify-content: center;
|
|
214
|
+
align-items: center;
|
|
215
|
+
min-height: 100vh;
|
|
216
|
+
padding: var(--authrim-space-4);
|
|
217
|
+
background:
|
|
218
|
+
linear-gradient(135deg, var(--authrim-color-bg-subtle) 0%, var(--authrim-color-bg) 100%);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
:global(.authrim-signup-template__card) {
|
|
222
|
+
width: 100%;
|
|
223
|
+
max-width: 420px;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.authrim-signup-template__header {
|
|
227
|
+
text-align: center;
|
|
228
|
+
margin-bottom: var(--authrim-space-6);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.authrim-signup-template__title {
|
|
232
|
+
margin: 0 0 var(--authrim-space-2);
|
|
233
|
+
font-size: var(--authrim-text-2xl);
|
|
234
|
+
font-weight: 700;
|
|
235
|
+
color: var(--authrim-color-text);
|
|
236
|
+
letter-spacing: var(--authrim-tracking-tight);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.authrim-signup-template__subtitle {
|
|
240
|
+
margin: 0;
|
|
241
|
+
font-size: var(--authrim-text-sm);
|
|
242
|
+
color: var(--authrim-color-text-secondary);
|
|
243
|
+
line-height: var(--authrim-leading-relaxed);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.authrim-signup-template__subtitle strong {
|
|
247
|
+
color: var(--authrim-color-text);
|
|
248
|
+
font-weight: 600;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.authrim-signup-template__content {
|
|
252
|
+
display: flex;
|
|
253
|
+
flex-direction: column;
|
|
254
|
+
gap: var(--authrim-space-5);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.authrim-signup-template__form {
|
|
258
|
+
display: flex;
|
|
259
|
+
flex-direction: column;
|
|
260
|
+
gap: var(--authrim-space-4);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.authrim-signup-template__divider {
|
|
264
|
+
display: flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
gap: var(--authrim-space-3);
|
|
267
|
+
color: var(--authrim-color-text-muted);
|
|
268
|
+
font-size: var(--authrim-text-sm);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.authrim-signup-template__divider::before,
|
|
272
|
+
.authrim-signup-template__divider::after {
|
|
273
|
+
content: '';
|
|
274
|
+
flex: 1;
|
|
275
|
+
height: 1px;
|
|
276
|
+
background: var(--authrim-color-border);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.authrim-signup-template__back {
|
|
280
|
+
display: inline-flex;
|
|
281
|
+
align-items: center;
|
|
282
|
+
gap: var(--authrim-space-1);
|
|
283
|
+
padding: var(--authrim-space-1) var(--authrim-space-2);
|
|
284
|
+
margin: 0 0 var(--authrim-space-4) calc(-1 * var(--authrim-space-2));
|
|
285
|
+
font-family: var(--authrim-font-sans);
|
|
286
|
+
font-size: var(--authrim-text-sm);
|
|
287
|
+
font-weight: 500;
|
|
288
|
+
color: var(--authrim-color-text-secondary);
|
|
289
|
+
background: transparent;
|
|
290
|
+
border: none;
|
|
291
|
+
border-radius: var(--authrim-radius-sm);
|
|
292
|
+
cursor: pointer;
|
|
293
|
+
transition:
|
|
294
|
+
color var(--authrim-duration-fast) var(--authrim-ease-default),
|
|
295
|
+
background-color var(--authrim-duration-fast) var(--authrim-ease-default);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.authrim-signup-template__back:hover {
|
|
299
|
+
color: var(--authrim-color-text);
|
|
300
|
+
background: var(--authrim-color-bg-subtle);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.authrim-signup-template__back svg {
|
|
304
|
+
width: 18px;
|
|
305
|
+
height: 18px;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.authrim-signup-template__code {
|
|
309
|
+
display: flex;
|
|
310
|
+
flex-direction: column;
|
|
311
|
+
gap: var(--authrim-space-5);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.authrim-signup-template__resend {
|
|
315
|
+
display: flex;
|
|
316
|
+
align-items: center;
|
|
317
|
+
justify-content: center;
|
|
318
|
+
gap: var(--authrim-space-1);
|
|
319
|
+
flex-wrap: wrap;
|
|
320
|
+
font-size: var(--authrim-text-sm);
|
|
321
|
+
color: var(--authrim-color-text-muted);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.authrim-signup-template__footer {
|
|
325
|
+
text-align: center;
|
|
326
|
+
font-size: var(--authrim-text-sm);
|
|
327
|
+
color: var(--authrim-color-text-secondary);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.authrim-signup-template__footer p {
|
|
331
|
+
margin: 0;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.authrim-signup-template__link {
|
|
335
|
+
color: var(--authrim-color-primary);
|
|
336
|
+
font-weight: 500;
|
|
337
|
+
text-decoration: none;
|
|
338
|
+
transition: color var(--authrim-duration-fast) var(--authrim-ease-default);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.authrim-signup-template__link:hover {
|
|
342
|
+
color: var(--authrim-color-primary-hover);
|
|
343
|
+
text-decoration: underline;
|
|
344
|
+
}
|
|
345
|
+
</style>
|