@nymphjs/tilmeld-components 1.0.0-beta.13 → 1.0.0-beta.131

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/src/Login.svelte CHANGED
@@ -1,8 +1,9 @@
1
+ <svelte:options runes />
2
+
1
3
  <div
2
4
  style="width: {width}; {style}"
3
5
  use:useActions={use}
4
- use:forwardEvents
5
- {...exclude($$restProps, [
6
+ {...exclude(restProps, [
6
7
  'successRegisteredMessage$',
7
8
  'successLoginMessage$',
8
9
  'username$',
@@ -11,6 +12,8 @@
11
12
  'name$',
12
13
  'email$',
13
14
  'phone$',
15
+ 'code$',
16
+ 'codeMessage$',
14
17
  'loginButton$',
15
18
  'registerButton$',
16
19
  'registerLink$',
@@ -20,46 +23,82 @@
20
23
  'progress$',
21
24
  ])}
22
25
  >
23
- {#if clientConfig == null || registering || loggingIn}
26
+ {#if $clientConfig == null || loading}
24
27
  <div style="display: flex; justify-content: center; align-items: center;">
25
28
  <CircularProgress
26
29
  style="height: 32px; width: 32px;"
27
30
  indeterminate
28
- {...prefixFilter($$restProps, 'progress$')}
31
+ {...prefixFilter(restProps, 'progress$')}
29
32
  />
30
33
  </div>
31
34
  {:else if successRegisteredMessage}
32
- <div {...prefixFilter($$restProps, 'successRegisteredMessage$')}>
35
+ <div {...prefixFilter(restProps, 'successRegisteredMessage$')}>
33
36
  {successRegisteredMessage}
34
37
  </div>
35
38
  {:else if successLoginMessage}
36
- <div {...prefixFilter($$restProps, 'successLoginMessage$')}>
39
+ <div {...prefixFilter(restProps, 'successLoginMessage$')}>
37
40
  {successLoginMessage}
38
41
  </div>
42
+ {:else if totp}
43
+ <form onsubmit={(e) => e.preventDefault()}>
44
+ <div {...prefixFilter(restProps, 'codeMessage$')}>
45
+ Enter the 6-digit 2FA code from your authenticator app.
46
+ </div>
47
+
48
+ <div>
49
+ <Textfield
50
+ bind:value={code}
51
+ label="2FA Code"
52
+ style="width: 100%;"
53
+ input$autocomplete="one-time-code"
54
+ input$name="one-time-code"
55
+ {...prefixFilter(restProps, 'code$')}
56
+ />
57
+ </div>
58
+
59
+ {#if failureMessage}
60
+ <div class="tilmeld-login-failure">
61
+ {failureMessage}
62
+ </div>
63
+ {/if}
64
+
65
+ <div class="tilmeld-login-buttons">
66
+ <Button
67
+ variant="raised"
68
+ type="submit"
69
+ onclick={login}
70
+ {...prefixFilter(restProps, 'loginButton$')}
71
+ >
72
+ <Label>Log In</Label>
73
+ </Button>
74
+ </div>
75
+ </form>
39
76
  {:else}
40
- <form on:submit|preventDefault>
77
+ <form onsubmit={(e) => e.preventDefault()}>
41
78
  <div>
42
79
  <Textfield
43
80
  bind:value={username}
44
81
  bind:this={usernameElem}
45
- label={clientConfig.emailUsernames ? 'Email' : 'Username'}
46
- type={clientConfig.emailUsernames ? 'email' : 'text'}
82
+ label={$clientConfig.emailUsernames ? 'Email' : 'Username'}
83
+ type={$clientConfig.emailUsernames ? 'email' : 'text'}
47
84
  style="width: 100%;"
48
85
  helperLine$style="width: 100%;"
49
86
  invalid={usernameVerified === false}
50
- input$autocomplete={clientConfig.emailUsernames
87
+ input$autocomplete={$clientConfig.emailUsernames
51
88
  ? 'email'
52
89
  : 'username'}
53
- input$name={clientConfig.emailUsernames ? 'email' : 'username'}
90
+ input$name={$clientConfig.emailUsernames ? 'email' : 'username'}
54
91
  input$autocapitalize="off"
55
92
  input$spellcheck="false"
56
- {...prefixFilter($$restProps, 'username$')}
93
+ {...prefixFilter(restProps, 'username$')}
57
94
  >
58
- <HelperText persistent slot="helper">
59
- {#if mode !== 'login'}
60
- {usernameVerifiedMessage || ''}
61
- {/if}
62
- </HelperText>
95
+ {#snippet helper()}
96
+ <HelperText persistent>
97
+ {#if mode !== 'login'}
98
+ {usernameVerifiedMessage || ''}
99
+ {/if}
100
+ </HelperText>
101
+ {/snippet}
63
102
  </Textfield>
64
103
  </div>
65
104
 
@@ -69,16 +108,16 @@
69
108
  label="Password"
70
109
  type="password"
71
110
  style="width: 100%;"
72
- input$autocomplete="{clientConfig.allowRegistration &&
111
+ input$autocomplete="{$clientConfig.allowRegistration &&
73
112
  mode !== 'login'
74
113
  ? 'new'
75
114
  : 'current'}-password"
76
115
  input$name="password"
77
- {...prefixFilter($$restProps, 'password$')}
116
+ {...prefixFilter(restProps, 'password$')}
78
117
  />
79
118
  </div>
80
119
 
81
- {#if clientConfig.allowRegistration && mode !== 'login'}
120
+ {#if $clientConfig.allowRegistration && mode !== 'login'}
82
121
  <div>
83
122
  <Textfield
84
123
  bind:value={password2}
@@ -87,11 +126,11 @@
87
126
  style="width: 100%;"
88
127
  input$autocomplete="new-password"
89
128
  input$name="password2"
90
- {...prefixFilter($$restProps, 'password2$')}
129
+ {...prefixFilter(restProps, 'password2$')}
91
130
  />
92
131
  </div>
93
132
 
94
- {#if clientConfig.regFields.indexOf('name') !== -1}
133
+ {#if $clientConfig.regFields.includes('name')}
95
134
  <div>
96
135
  <Textfield
97
136
  bind:value={name}
@@ -100,12 +139,12 @@
100
139
  style="width: 100%;"
101
140
  input$autocomplete="name"
102
141
  input$name="name"
103
- {...prefixFilter($$restProps, 'name$')}
142
+ {...prefixFilter(restProps, 'name$')}
104
143
  />
105
144
  </div>
106
145
  {/if}
107
146
 
108
- {#if !clientConfig.emailUsernames && clientConfig.regFields.indexOf('email') !== -1}
147
+ {#if !$clientConfig.emailUsernames && $clientConfig.regFields.includes('email')}
109
148
  <div>
110
149
  <Textfield
111
150
  bind:value={email}
@@ -116,12 +155,12 @@
116
155
  input$name="email"
117
156
  input$autocapitalize="off"
118
157
  input$spellcheck="false"
119
- {...prefixFilter($$restProps, 'email$')}
158
+ {...prefixFilter(restProps, 'email$')}
120
159
  />
121
160
  </div>
122
161
  {/if}
123
162
 
124
- {#if clientConfig.regFields.indexOf('phone') !== -1}
163
+ {#if $clientConfig.regFields.includes('phone')}
125
164
  <div>
126
165
  <Textfield
127
166
  bind:value={phone}
@@ -130,13 +169,13 @@
130
169
  style="width: 100%;"
131
170
  input$autocomplete="tel"
132
171
  input$name="phone"
133
- {...prefixFilter($$restProps, 'phone$')}
172
+ {...prefixFilter(restProps, 'phone$')}
134
173
  />
135
174
  </div>
136
175
  {/if}
137
176
  {/if}
138
177
 
139
- <slot name="additional" />
178
+ {@render additional?.()}
140
179
 
141
180
  {#if failureMessage}
142
181
  <div class="tilmeld-login-failure">
@@ -149,8 +188,8 @@
149
188
  <Button
150
189
  variant="raised"
151
190
  type="submit"
152
- on:click={login}
153
- {...prefixFilter($$restProps, 'loginButton$')}
191
+ onclick={login}
192
+ {...prefixFilter(restProps, 'loginButton$')}
154
193
  >
155
194
  <Label>Log In</Label>
156
195
  </Button>
@@ -158,29 +197,29 @@
158
197
  <Button
159
198
  variant="raised"
160
199
  type="submit"
161
- on:click={register}
162
- {...prefixFilter($$restProps, 'registerButton$')}
200
+ onclick={register}
201
+ {...prefixFilter(restProps, 'registerButton$')}
163
202
  >
164
203
  <Label>Create Account</Label>
165
204
  </Button>
166
205
  {/if}
167
206
  </div>
168
207
 
169
- {#if clientConfig.allowRegistration && showExistingUserToggle}
208
+ {#if $clientConfig.allowRegistration && showExistingUserToggle}
170
209
  <div class="tilmeld-login-action">
171
210
  {#if mode === 'login'}
172
211
  <a
173
- href="javascript:void(0);"
174
- on:click={() => (mode = 'register')}
175
- {...prefixFilter($$restProps, 'registerLink$')}
212
+ href={'javascript:void(0);'}
213
+ onclick={() => (mode = 'register')}
214
+ {...prefixFilter(restProps, 'registerLink$')}
176
215
  >
177
216
  Create an account.
178
217
  </a>
179
218
  {:else}
180
219
  <a
181
- href="javascript:void(0);"
182
- on:click={() => (mode = 'login')}
183
- {...prefixFilter($$restProps, 'loginLink$')}
220
+ href={'javascript:void(0);'}
221
+ onclick={() => (mode = 'login')}
222
+ {...prefixFilter(restProps, 'loginLink$')}
184
223
  >
185
224
  Log in to your account.
186
225
  </a>
@@ -188,12 +227,12 @@
188
227
  </div>
189
228
  {/if}
190
229
 
191
- {#if !hideRecovery && clientConfig.pwRecovery && mode === 'login'}
230
+ {#if !hideRecovery && $clientConfig.userFields.includes('email') && $clientConfig.pwRecovery && mode === 'login'}
192
231
  <div class="tilmeld-login-action">
193
232
  <a
194
- href="javascript:void(0);"
195
- on:click={() => (recoverOpen = true)}
196
- {...prefixFilter($$restProps, 'recoverLink$')}
233
+ href={'javascript:void(0);'}
234
+ onclick={() => (recoverOpen = true)}
235
+ {...prefixFilter(restProps, 'recoverLink$')}
197
236
  >
198
237
  I can't access my account.
199
238
  </a>
@@ -202,7 +241,7 @@
202
241
  {User}
203
242
  bind:open={recoverOpen}
204
243
  bind:clientConfig
205
- {...prefixFilter($$restProps, 'recover$')}
244
+ {...prefixFilter(restProps, 'recover$')}
206
245
  />
207
246
  {/if}
208
247
  </form>
@@ -210,95 +249,253 @@
210
249
  </div>
211
250
 
212
251
  <script lang="ts">
213
- import { onMount, createEventDispatcher } from 'svelte';
214
- import { get_current_component } from 'svelte/internal';
252
+ import type { ComponentProps, Snippet } from 'svelte';
253
+ import { onMount } from 'svelte';
254
+ import type { Writable } from 'svelte/store';
255
+ import { writable } from 'svelte/store';
215
256
  import CircularProgress from '@smui/circular-progress';
216
257
  import Button, { Label } from '@smui/button';
217
258
  import Textfield from '@smui/textfield';
218
259
  import HelperText from '@smui/textfield/helper-text';
219
260
  import type { ActionArray } from '@smui/common/internal';
220
- import {
221
- forwardEventsBuilder,
222
- exclude,
223
- prefixFilter,
224
- useActions,
225
- } from '@smui/common/internal';
261
+ import { exclude, prefixFilter, useActions } from '@smui/common/internal';
262
+ import type { SmuiElementPropMap } from '@smui/common';
226
263
  import type {
227
264
  User as UserClass,
228
265
  ClientConfig,
266
+ UserData,
267
+ CurrentUserData,
229
268
  } from '@nymphjs/tilmeld-client';
230
269
  import {
231
270
  login as loginAction,
232
271
  register as registerAction,
233
272
  checkUsername as checkUsernameAction,
273
+ NeedTOTPError,
234
274
  } from '@nymphjs/tilmeld-client';
235
275
  import Recover from './Recover.svelte';
236
276
 
237
- const forwardEvents = forwardEventsBuilder(get_current_component());
238
- const dispatch = createEventDispatcher();
239
-
240
- export let use: ActionArray = [];
241
- export let style = '';
242
- export let clientConfig: ClientConfig | undefined = undefined;
243
- export let User: typeof UserClass;
244
-
245
- /** Hide the recovery link that only appears if password recovery is on. */
246
- export let hideRecovery = false;
247
- /** Give focus to the username box (or email box) when the form is ready. */
248
- export let autofocus = true;
249
- /** This determines whether the 'Log In' or 'Sign Up' button is activated and which corresponding form is shown. */
250
- export let mode: 'login' | 'register' = 'login';
251
- /** Whether to show the 'Log In'/'Sign Up' switcher buttons. */
252
- export let showExistingUserToggle = true;
253
- /** The width of the form. */
254
- export let width = '220px';
277
+ type OwnProps = {
278
+ /**
279
+ * An array of Action or [Action, ActionProps] to be applied to the element.
280
+ */
281
+ use?: ActionArray;
282
+ /**
283
+ * A list of CSS styles.
284
+ */
285
+ style?: string;
286
+ /**
287
+ * A writable store of the Nymph client config.
288
+ *
289
+ * It will be retrieved from the server if not provided.
290
+ */
291
+ clientConfig?: Writable<ClientConfig | undefined>;
292
+ /**
293
+ * The User class from Nymph.
294
+ */
295
+ User: typeof UserClass;
296
+ /**
297
+ * Hide the recovery link that only appears if password recovery is on.
298
+ */
299
+ hideRecovery?: boolean;
300
+ /**
301
+ * Give focus to the username box (or email box) when the form is ready.
302
+ */
303
+ autofocus?: boolean;
304
+ /**
305
+ * This determines whether the 'Log In' or 'Sign Up' button is activated
306
+ * and which corresponding form is shown.
307
+ */
308
+ mode?: 'login' | 'register';
309
+ /**
310
+ * Whether to show the 'Log In'/'Sign Up' switcher buttons.
311
+ */
312
+ showExistingUserToggle?: boolean;
313
+ /**
314
+ * The width of the form.
315
+ */
316
+ width?: string;
317
+ /**
318
+ * User provided. You can bind to it if you need to.
319
+ */
320
+ username?: string;
321
+ /**
322
+ * User provided. You can bind to it if you need to.
323
+ */
324
+ password?: string;
325
+ /**
326
+ * User provided. You can bind to it if you need to.
327
+ */
328
+ password2?: string;
329
+ /**
330
+ * User provided. You can bind to it if you need to.
331
+ */
332
+ name?: string;
333
+ /**
334
+ * User provided. You can bind to it if you need to.
335
+ */
336
+ email?: string;
337
+ /**
338
+ * User provided. You can bind to it if you need to.
339
+ */
340
+ phone?: string;
341
+ /**
342
+ * User provided. You can bind to it if you need to.
343
+ */
344
+ code?: string;
345
+ /**
346
+ * Provide this for anything else that should go up to the server.
347
+ *
348
+ * You can look for it in the User events.
349
+ */
350
+ additionalData?: { [k: string]: any };
255
351
 
256
- /** User provided. You can bind to it if you need to. */
257
- export let username = '';
258
- /** User provided. You can bind to it if you need to. */
259
- export let password = '';
260
- /** User provided. You can bind to it if you need to. */
261
- export let password2 = '';
262
- /** User provided. You can bind to it if you need to. */
263
- export let name = '';
264
- /** User provided. You can bind to it if you need to. */
265
- export let email = '';
266
- /** User provided. You can bind to it if you need to. */
267
- export let phone = '';
352
+ /**
353
+ * A spot for additional content.
354
+ */
355
+ additional?: Snippet;
268
356
 
269
- /** Provide this for anything else that should go up to the server. You can look for it in the User events. */
270
- export let additionalData: { [k: string]: any } | undefined = undefined;
357
+ /**
358
+ * A callback to be called when a user is registered.
359
+ */
360
+ onregister?: (details: {
361
+ user: UserClass & UserData & CurrentUserData;
362
+ }) => void;
363
+ /**
364
+ * A callback to be called when a user is logged in.
365
+ */
366
+ onlogin?: (details: {
367
+ user: UserClass & UserData & CurrentUserData;
368
+ }) => void;
369
+ };
370
+ let {
371
+ use = [],
372
+ style = '',
373
+ clientConfig = $bindable(writable(false as unknown as undefined)),
374
+ User,
375
+ hideRecovery = false,
376
+ autofocus = true,
377
+ mode = $bindable('login'),
378
+ showExistingUserToggle = true,
379
+ width = '220px',
380
+ username = $bindable(''),
381
+ password = $bindable(''),
382
+ password2 = $bindable(''),
383
+ name = $bindable(''),
384
+ email = $bindable(''),
385
+ phone = $bindable(''),
386
+ code = $bindable(''),
387
+ additionalData,
388
+ additional,
389
+ onregister,
390
+ onlogin,
391
+ ...restProps
392
+ }: OwnProps & {
393
+ [
394
+ k in keyof SmuiElementPropMap['div'] as `successRegisteredMessage\$${k}`
395
+ ]?: SmuiElementPropMap['div'][k];
396
+ } & {
397
+ [
398
+ k in keyof SmuiElementPropMap['div'] as `successLoginMessage\$${k}`
399
+ ]?: SmuiElementPropMap['div'][k];
400
+ } & {
401
+ [
402
+ k in keyof ComponentProps<typeof Textfield> as `username\$${k}`
403
+ ]?: ComponentProps<typeof Textfield>[k];
404
+ } & {
405
+ [
406
+ k in keyof ComponentProps<typeof Textfield> as `password\$${k}`
407
+ ]?: ComponentProps<typeof Textfield>[k];
408
+ } & {
409
+ [
410
+ k in keyof ComponentProps<typeof Textfield> as `password2\$${k}`
411
+ ]?: ComponentProps<typeof Textfield>[k];
412
+ } & {
413
+ [
414
+ k in keyof ComponentProps<typeof Textfield> as `name\$${k}`
415
+ ]?: ComponentProps<typeof Textfield>[k];
416
+ } & {
417
+ [
418
+ k in keyof ComponentProps<typeof Textfield> as `email\$${k}`
419
+ ]?: ComponentProps<typeof Textfield>[k];
420
+ } & {
421
+ [
422
+ k in keyof ComponentProps<typeof Textfield> as `phone\$${k}`
423
+ ]?: ComponentProps<typeof Textfield>[k];
424
+ } & {
425
+ [
426
+ k in keyof ComponentProps<typeof Textfield> as `code\$${k}`
427
+ ]?: ComponentProps<typeof Textfield>[k];
428
+ } & {
429
+ [
430
+ k in keyof SmuiElementPropMap['div'] as `codeMessage\$${k}`
431
+ ]?: SmuiElementPropMap['div'][k];
432
+ } & {
433
+ [
434
+ k in keyof ComponentProps<typeof CircularProgress> as `progress\$${k}`
435
+ ]?: ComponentProps<typeof CircularProgress>[k];
436
+ } & {
437
+ [
438
+ k in keyof ComponentProps<
439
+ typeof Button<undefined, 'button'>
440
+ > as `loginButton\$${k}`
441
+ ]?: ComponentProps<typeof Button<undefined, 'button'>>[k];
442
+ } & {
443
+ [
444
+ k in keyof ComponentProps<
445
+ typeof Button<undefined, 'button'>
446
+ > as `registerButton\$${k}`
447
+ ]?: ComponentProps<typeof Button<undefined, 'button'>>[k];
448
+ } & {
449
+ [
450
+ k in keyof SmuiElementPropMap['a'] as `registerLink\$${k}`
451
+ ]?: SmuiElementPropMap['a'][k];
452
+ } & {
453
+ [
454
+ k in keyof SmuiElementPropMap['a'] as `loginLink\$${k}`
455
+ ]?: SmuiElementPropMap['a'][k];
456
+ } & {
457
+ [
458
+ k in keyof SmuiElementPropMap['a'] as `recoverLink\$${k}`
459
+ ]?: SmuiElementPropMap['a'][k];
460
+ } & {
461
+ [
462
+ k in keyof ComponentProps<typeof Recover> as `recover\$${k}`
463
+ ]?: ComponentProps<typeof Recover>[k];
464
+ } = $props();
271
465
 
272
- let usernameElem: Textfield;
273
- let successLoginMessage: string | undefined = undefined;
274
- let successRegisteredMessage: string | undefined = undefined;
275
- let failureMessage: string | undefined = undefined;
276
- let usernameTimer: NodeJS.Timeout | undefined = undefined;
277
- let usernameVerified: boolean | undefined = undefined;
278
- let usernameVerifiedMessage: string | undefined = undefined;
279
- let registering = false;
280
- let loggingIn = false;
281
- let recoverOpen = false;
466
+ let usernameElem: Textfield | undefined = $state();
467
+ let successLoginMessage: string | undefined = $state();
468
+ let successRegisteredMessage: string | undefined = $state();
469
+ let failureMessage: string | undefined = $state();
470
+ let usernameTimer: number | undefined = undefined;
471
+ let usernameVerified: boolean | undefined = $state();
472
+ let usernameVerifiedMessage: string | undefined = $state();
473
+ let totp = $state(false);
474
+ let loading = $state(false);
475
+ let recoverOpen = $state(false);
282
476
 
283
- $: nameFirst = name?.match(/^(.*?)(?: ([^ ]+))?$/)?.[1] ?? '';
284
- $: nameLast = name?.match(/^(.*?)(?: ([^ ]+))?$/)?.[2] ?? '';
477
+ const nameFirst = $derived(name?.match(/^(.*?)(?: ([^ ]+))?$/)?.[1] ?? '');
478
+ const nameLast = $derived(name?.match(/^(.*?)(?: ([^ ]+))?$/)?.[2] ?? '');
285
479
 
286
480
  let _previousMode = mode;
287
- $: if (mode !== _previousMode) {
288
- failureMessage = '';
289
- checkUsername(username);
290
- _previousMode = mode;
291
- }
481
+ $effect(() => {
482
+ if (mode !== _previousMode) {
483
+ failureMessage = '';
484
+ checkUsername(username);
485
+ _previousMode = mode;
486
+ }
487
+ });
292
488
 
293
- $: {
489
+ $effect(() => {
294
490
  checkUsername(username);
295
- }
491
+ });
296
492
 
297
493
  onMount(async () => {
298
- if (clientConfig === undefined) {
299
- clientConfig = await User.getClientConfig();
494
+ if ($clientConfig === (false as unknown as undefined)) {
495
+ $clientConfig = undefined;
496
+ $clientConfig = await User.getClientConfig();
300
497
  }
301
- if (!clientConfig.allowRegistration) {
498
+ if (!$clientConfig.allowRegistration) {
302
499
  mode = 'login';
303
500
  }
304
501
  if (autofocus && usernameElem) {
@@ -309,22 +506,34 @@
309
506
  async function login() {
310
507
  successLoginMessage = undefined;
311
508
  failureMessage = undefined;
312
- loggingIn = true;
509
+ loading = true;
313
510
  try {
314
- const data = await loginAction(User, username, password, additionalData);
511
+ const data = await loginAction(
512
+ User,
513
+ username,
514
+ password,
515
+ code,
516
+ additionalData,
517
+ );
315
518
  successLoginMessage = data.message;
316
- dispatch('login', { user: data.user });
519
+ if (data.user) {
520
+ onlogin?.({ user: data.user });
521
+ }
317
522
  } catch (e: any) {
318
- failureMessage = e?.message;
523
+ if (e instanceof NeedTOTPError) {
524
+ totp = true;
525
+ } else {
526
+ failureMessage = e?.message;
527
+ }
319
528
  }
320
- loggingIn = false;
529
+ loading = false;
321
530
  }
322
531
 
323
532
  async function register() {
324
533
  successRegisteredMessage = undefined;
325
534
  successLoginMessage = undefined;
326
535
  failureMessage = undefined;
327
- registering = true;
536
+ loading = true;
328
537
  try {
329
538
  const data = await registerAction(User, {
330
539
  username,
@@ -338,15 +547,19 @@
338
547
  ...(additionalData ? { additionalData } : {}),
339
548
  });
340
549
  successRegisteredMessage = data.message;
341
- dispatch('register', { user: data.user });
550
+ if (data.user) {
551
+ onregister?.({ user: data.user });
552
+ }
342
553
  if (data.loggedin) {
343
554
  successLoginMessage = data.message;
344
- dispatch('login', { user: data.user });
555
+ if (data.user) {
556
+ onlogin?.({ user: data.user });
557
+ }
345
558
  }
346
559
  } catch (e: any) {
347
560
  failureMessage = e?.message;
348
561
  }
349
- registering = false;
562
+ loading = false;
350
563
  }
351
564
 
352
565
  function checkUsername(newValue: string) {