@nymphjs/tilmeld-components 1.0.0-beta.13 → 1.0.0-beta.130
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/CHANGELOG.md +490 -0
- package/README.md +6 -4
- package/dist/Account.svelte +516 -0
- package/dist/ChangePassword.svelte +309 -0
- package/dist/Login.svelte +603 -0
- package/dist/Recover.svelte +463 -0
- package/dist/RevokeTokens.svelte +236 -0
- package/dist/TwoFactor.svelte +544 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/{lib → dist}/index.js.map +1 -1
- package/jest.config.js +32 -0
- package/package.json +54 -43
- package/src/Account.svelte +280 -113
- package/src/ChangePassword.svelte +147 -51
- package/src/Login.svelte +328 -115
- package/src/Recover.svelte +180 -78
- package/src/RevokeTokens.svelte +236 -0
- package/src/TwoFactor.svelte +544 -0
- package/src/index.d.ts +3 -1
- package/src/index.ts +3 -1
- package/tsconfig.json +8 -4
- package/typedoc.json +4 -0
- package/dist/index.cjs +0 -3
- package/dist/index.cjs.LICENSE.txt +0 -45
- package/dist/index.cjs.map +0 -1
- package/jest.config.cjs +0 -6
- package/lib/Account.svelte +0 -333
- package/lib/Account.svelte.map +0 -1
- package/lib/ChangePassword.svelte +0 -188
- package/lib/ChangePassword.svelte.map +0 -1
- package/lib/Login.svelte +0 -353
- package/lib/Login.svelte.map +0 -1
- package/lib/Recover.svelte +0 -339
- package/lib/Recover.svelte.map +0 -1
- package/lib/index.d.ts +0 -5
- package/lib/index.js +0 -6
- package/webpack.config.cjs +0 -35
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
{#if $user != null}
|
|
2
4
|
<Dialog
|
|
3
|
-
use
|
|
5
|
+
{use}
|
|
4
6
|
bind:open
|
|
5
7
|
aria-labelledby="tilmeld-password-title"
|
|
6
8
|
aria-describedby="tilmeld-password-content"
|
|
7
9
|
surface$class="tilmeld-password-dialog-surface"
|
|
8
|
-
{...exclude(
|
|
10
|
+
{...exclude(restProps, [
|
|
9
11
|
'password$',
|
|
10
12
|
'newPassword$',
|
|
11
13
|
'newPassword2$',
|
|
14
|
+
'revokeTokens$',
|
|
12
15
|
'closeButton$',
|
|
13
16
|
'saveButton$',
|
|
14
17
|
'progress$',
|
|
@@ -24,7 +27,7 @@
|
|
|
24
27
|
type="password"
|
|
25
28
|
style="width: 100%;"
|
|
26
29
|
input$autocomplete="current-password"
|
|
27
|
-
{...prefixFilter(
|
|
30
|
+
{...prefixFilter(restProps, 'password$')}
|
|
28
31
|
/>
|
|
29
32
|
</div>
|
|
30
33
|
|
|
@@ -35,7 +38,7 @@
|
|
|
35
38
|
type="password"
|
|
36
39
|
style="width: 100%;"
|
|
37
40
|
input$autocomplete="new-password"
|
|
38
|
-
{...prefixFilter(
|
|
41
|
+
{...prefixFilter(restProps, 'newPassword$')}
|
|
39
42
|
/>
|
|
40
43
|
</div>
|
|
41
44
|
|
|
@@ -46,11 +49,28 @@
|
|
|
46
49
|
type="password"
|
|
47
50
|
style="width: 100%;"
|
|
48
51
|
input$autocomplete="new-password"
|
|
49
|
-
{...prefixFilter(
|
|
52
|
+
{...prefixFilter(restProps, 'newPassword2$')}
|
|
50
53
|
/>
|
|
51
54
|
</div>
|
|
52
55
|
|
|
53
|
-
<
|
|
56
|
+
<div style="margin: 1em 0;">
|
|
57
|
+
<FormField>
|
|
58
|
+
<Checkbox
|
|
59
|
+
bind:checked={revokeCurrentTokens}
|
|
60
|
+
{...prefixFilter(restProps, 'revokeTokens$')}
|
|
61
|
+
/>
|
|
62
|
+
{#snippet label()}
|
|
63
|
+
Log out of all other sessions.
|
|
64
|
+
<span
|
|
65
|
+
style="display: block; font-size: 0.7em; height: 0; overflow: visible;"
|
|
66
|
+
>
|
|
67
|
+
Use this if you think you've been hacked.
|
|
68
|
+
</span>
|
|
69
|
+
{/snippet}
|
|
70
|
+
</FormField>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
{@render additional?.()}
|
|
54
74
|
|
|
55
75
|
{#if failureMessage}
|
|
56
76
|
<div class="tilmeld-password-failure">
|
|
@@ -58,27 +78,24 @@
|
|
|
58
78
|
</div>
|
|
59
79
|
{/if}
|
|
60
80
|
|
|
61
|
-
{#if
|
|
81
|
+
{#if loading}
|
|
62
82
|
<div class="tilmeld-password-loading">
|
|
63
83
|
<CircularProgress
|
|
64
84
|
style="height: 24px; width: 24px;"
|
|
65
85
|
indeterminate
|
|
66
|
-
{...prefixFilter(
|
|
86
|
+
{...prefixFilter(restProps, 'progress$')}
|
|
67
87
|
/>
|
|
68
88
|
</div>
|
|
69
89
|
{/if}
|
|
70
90
|
</Content>
|
|
71
91
|
<Actions>
|
|
72
|
-
<Button
|
|
73
|
-
disabled={changing}
|
|
74
|
-
{...prefixFilter($$restProps, 'closeButton$')}
|
|
75
|
-
>
|
|
92
|
+
<Button disabled={loading} {...prefixFilter(restProps, 'closeButton$')}>
|
|
76
93
|
<Label>Close</Label>
|
|
77
94
|
</Button>
|
|
78
95
|
<Button
|
|
79
|
-
|
|
80
|
-
disabled={
|
|
81
|
-
{...prefixFilter(
|
|
96
|
+
onclick={preventDefault(stopPropagation(changePassword))}
|
|
97
|
+
disabled={loading}
|
|
98
|
+
{...prefixFilter(restProps, 'saveButton$')}
|
|
82
99
|
>
|
|
83
100
|
<Label>Change Password</Label>
|
|
84
101
|
</Button>
|
|
@@ -87,62 +104,140 @@
|
|
|
87
104
|
{/if}
|
|
88
105
|
|
|
89
106
|
<script lang="ts">
|
|
107
|
+
import type { ComponentProps, Snippet } from 'svelte';
|
|
90
108
|
import { onMount, onDestroy } from 'svelte';
|
|
91
|
-
import {
|
|
109
|
+
import type { Writable } from 'svelte/store';
|
|
110
|
+
import { writable } from 'svelte/store';
|
|
92
111
|
import CircularProgress from '@smui/circular-progress';
|
|
93
112
|
import Dialog, { Title, Content, Actions } from '@smui/dialog';
|
|
94
113
|
import Textfield from '@smui/textfield';
|
|
114
|
+
import Checkbox from '@smui/checkbox';
|
|
115
|
+
import FormField from '@smui/form-field';
|
|
95
116
|
import Button, { Label } from '@smui/button';
|
|
96
117
|
import type { ActionArray } from '@smui/common/internal';
|
|
97
|
-
import {
|
|
98
|
-
|
|
99
|
-
exclude,
|
|
100
|
-
prefixFilter,
|
|
101
|
-
} from '@smui/common/internal';
|
|
118
|
+
import { exclude, prefixFilter } from '@smui/common/internal';
|
|
119
|
+
import { preventDefault, stopPropagation } from '@smui/common/events';
|
|
102
120
|
import type { CurrentUserData } from '@nymphjs/tilmeld-client';
|
|
103
121
|
import type { User as UserClass } from '@nymphjs/tilmeld-client';
|
|
104
122
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
123
|
+
type OwnProps = {
|
|
124
|
+
/**
|
|
125
|
+
* An array of Action or [Action, ActionProps] to be applied to the element.
|
|
126
|
+
*/
|
|
127
|
+
use?: ActionArray;
|
|
128
|
+
/**
|
|
129
|
+
* Whether the dialog is open.
|
|
130
|
+
*/
|
|
131
|
+
open?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* The title of the dialog.
|
|
134
|
+
*/
|
|
135
|
+
title?: string;
|
|
136
|
+
/**
|
|
137
|
+
* The User class from Nymph.
|
|
138
|
+
*/
|
|
139
|
+
User: typeof UserClass;
|
|
140
|
+
/**
|
|
141
|
+
* A writable store of the current user.
|
|
142
|
+
*
|
|
143
|
+
* It will be retrieved from the server if not provided.
|
|
144
|
+
*/
|
|
145
|
+
user?: Writable<(UserClass & CurrentUserData) | null | undefined>;
|
|
146
|
+
/**
|
|
147
|
+
* User provided. You can bind to it if you need to.
|
|
148
|
+
*/
|
|
149
|
+
currentPassword?: string;
|
|
150
|
+
/**
|
|
151
|
+
* User provided. You can bind to it if you need to.
|
|
152
|
+
*/
|
|
153
|
+
newPassword?: string;
|
|
154
|
+
/**
|
|
155
|
+
* User provided. You can bind to it if you need to.
|
|
156
|
+
*/
|
|
157
|
+
newPassword2?: string;
|
|
158
|
+
/**
|
|
159
|
+
* User provided. You can bind to it if you need to.
|
|
160
|
+
*/
|
|
161
|
+
revokeCurrentTokens?: boolean;
|
|
113
162
|
|
|
114
|
-
|
|
115
|
-
|
|
163
|
+
/**
|
|
164
|
+
* A spot for additional content.
|
|
165
|
+
*/
|
|
166
|
+
additional?: Snippet;
|
|
167
|
+
};
|
|
168
|
+
let {
|
|
169
|
+
use = [],
|
|
170
|
+
open = $bindable(false),
|
|
171
|
+
title = 'Change Your Password',
|
|
172
|
+
User,
|
|
173
|
+
user = $bindable(writable(false as unknown as undefined)),
|
|
174
|
+
currentPassword = $bindable(''),
|
|
175
|
+
newPassword = $bindable(''),
|
|
176
|
+
newPassword2 = $bindable(''),
|
|
177
|
+
revokeCurrentTokens = $bindable(false),
|
|
178
|
+
additional,
|
|
179
|
+
...restProps
|
|
180
|
+
}: OwnProps & {
|
|
181
|
+
[
|
|
182
|
+
k in keyof ComponentProps<typeof Textfield> as `password\$${k}`
|
|
183
|
+
]?: ComponentProps<typeof Textfield>[k];
|
|
184
|
+
} & {
|
|
185
|
+
[
|
|
186
|
+
k in keyof ComponentProps<typeof Textfield> as `newPassword\$${k}`
|
|
187
|
+
]?: ComponentProps<typeof Textfield>[k];
|
|
188
|
+
} & {
|
|
189
|
+
[
|
|
190
|
+
k in keyof ComponentProps<typeof Textfield> as `newPassword2\$${k}`
|
|
191
|
+
]?: ComponentProps<typeof Textfield>[k];
|
|
192
|
+
} & {
|
|
193
|
+
[
|
|
194
|
+
k in keyof ComponentProps<typeof Checkbox> as `revokeTokens\$${k}`
|
|
195
|
+
]?: ComponentProps<typeof Checkbox>[k];
|
|
196
|
+
} & {
|
|
197
|
+
[
|
|
198
|
+
k in keyof ComponentProps<typeof CircularProgress> as `progress\$${k}`
|
|
199
|
+
]?: ComponentProps<typeof CircularProgress>[k];
|
|
200
|
+
} & {
|
|
201
|
+
[
|
|
202
|
+
k in keyof ComponentProps<
|
|
203
|
+
typeof Button<undefined, 'button'>
|
|
204
|
+
> as `closeButton\$${k}`
|
|
205
|
+
]?: ComponentProps<typeof Button<undefined, 'button'>>[k];
|
|
206
|
+
} & {
|
|
207
|
+
[
|
|
208
|
+
k in keyof ComponentProps<
|
|
209
|
+
typeof Button<undefined, 'button'>
|
|
210
|
+
> as `saveButton\$${k}`
|
|
211
|
+
]?: ComponentProps<typeof Button<undefined, 'button'>>[k];
|
|
212
|
+
} = $props();
|
|
116
213
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
/** User provided. You can bind to it if you need to. */
|
|
120
|
-
export let newPassword = '';
|
|
121
|
-
/** User provided. You can bind to it if you need to. */
|
|
122
|
-
export let newPassword2 = '';
|
|
214
|
+
let loading = $state(false);
|
|
215
|
+
let failureMessage: string | undefined = $state();
|
|
123
216
|
|
|
124
|
-
|
|
217
|
+
$effect(() => {
|
|
125
218
|
if (!open) {
|
|
126
|
-
|
|
219
|
+
loading = false;
|
|
127
220
|
failureMessage = undefined;
|
|
128
221
|
currentPassword = '';
|
|
129
222
|
newPassword = '';
|
|
130
223
|
newPassword2 = '';
|
|
224
|
+
revokeCurrentTokens = false;
|
|
131
225
|
}
|
|
132
|
-
}
|
|
226
|
+
});
|
|
133
227
|
|
|
134
228
|
const onLogin = (currentUser: UserClass & CurrentUserData) => {
|
|
135
|
-
user = currentUser;
|
|
229
|
+
$user = currentUser;
|
|
136
230
|
};
|
|
137
231
|
const onLogout = () => {
|
|
138
|
-
user =
|
|
232
|
+
$user = null;
|
|
139
233
|
};
|
|
140
234
|
|
|
141
235
|
onMount(async () => {
|
|
142
236
|
User.on('login', onLogin);
|
|
143
237
|
User.on('logout', onLogout);
|
|
144
|
-
if (user === undefined) {
|
|
145
|
-
user =
|
|
238
|
+
if ($user === (false as unknown as undefined)) {
|
|
239
|
+
$user = undefined;
|
|
240
|
+
$user = await User.current();
|
|
146
241
|
}
|
|
147
242
|
});
|
|
148
243
|
|
|
@@ -166,22 +261,23 @@
|
|
|
166
261
|
}
|
|
167
262
|
|
|
168
263
|
failureMessage = undefined;
|
|
169
|
-
|
|
264
|
+
loading = true;
|
|
170
265
|
|
|
171
266
|
// Get the current user again, in case their data has changed.
|
|
172
|
-
user =
|
|
267
|
+
$user = await User.current();
|
|
173
268
|
|
|
174
|
-
if (user == null) {
|
|
269
|
+
if ($user == null) {
|
|
175
270
|
failureMessage = 'You must be logged in.';
|
|
176
|
-
|
|
271
|
+
loading = false;
|
|
177
272
|
return;
|
|
178
273
|
}
|
|
179
274
|
|
|
180
275
|
try {
|
|
181
276
|
// Change the user's password.
|
|
182
|
-
const data = await user.$changePassword({
|
|
277
|
+
const data = await $user.$changePassword({
|
|
183
278
|
currentPassword,
|
|
184
279
|
newPassword,
|
|
280
|
+
revokeCurrentTokens,
|
|
185
281
|
});
|
|
186
282
|
|
|
187
283
|
if (!data.result) {
|
|
@@ -192,7 +288,7 @@
|
|
|
192
288
|
} catch (e: any) {
|
|
193
289
|
failureMessage = e?.message;
|
|
194
290
|
}
|
|
195
|
-
|
|
291
|
+
loading = false;
|
|
196
292
|
}
|
|
197
293
|
</script>
|
|
198
294
|
|