@atlasauth/svelte 0.1.0
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 +21 -0
- package/README.md +231 -0
- package/dist/accessors.d.ts +81 -0
- package/dist/accessors.js +126 -0
- package/dist/appearance.d.ts +85 -0
- package/dist/appearance.js +91 -0
- package/dist/components/AtlasLoaded.svelte +7 -0
- package/dist/components/AtlasLoaded.svelte.d.ts +18 -0
- package/dist/components/AtlasLoading.svelte +7 -0
- package/dist/components/AtlasLoading.svelte.d.ts +18 -0
- package/dist/components/AtlasProvider.svelte +23 -0
- package/dist/components/AtlasProvider.svelte.d.ts +33 -0
- package/dist/components/AttemptFlow.svelte +95 -0
- package/dist/components/AttemptFlow.svelte.d.ts +30 -0
- package/dist/components/OrganizationProfile.svelte +22 -0
- package/dist/components/OrganizationProfile.svelte.d.ts +16 -0
- package/dist/components/OrganizationSwitcher.svelte +25 -0
- package/dist/components/OrganizationSwitcher.svelte.d.ts +16 -0
- package/dist/components/Protect.svelte +21 -0
- package/dist/components/Protect.svelte.d.ts +32 -0
- package/dist/components/SignIn.svelte +16 -0
- package/dist/components/SignIn.svelte.d.ts +22 -0
- package/dist/components/SignUp.svelte +16 -0
- package/dist/components/SignUp.svelte.d.ts +21 -0
- package/dist/components/SignedIn.svelte +7 -0
- package/dist/components/SignedIn.svelte.d.ts +18 -0
- package/dist/components/SignedOut.svelte +7 -0
- package/dist/components/SignedOut.svelte.d.ts +18 -0
- package/dist/components/UserButton.svelte +40 -0
- package/dist/components/UserButton.svelte.d.ts +16 -0
- package/dist/components/UserProfile.svelte +35 -0
- package/dist/components/UserProfile.svelte.d.ts +16 -0
- package/dist/context.d.ts +105 -0
- package/dist/context.js +258 -0
- package/dist/fapi.d.ts +11 -0
- package/dist/fapi.js +11 -0
- package/dist/i18n.d.ts +23 -0
- package/dist/i18n.js +77 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +35 -0
- package/dist/protect.d.ts +18 -0
- package/dist/protect.js +18 -0
- package/dist/server.d.ts +101 -0
- package/dist/server.js +87 -0
- package/dist/types.d.ts +42 -0
- package/dist/types.js +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {
|
|
8
|
+
default: {};
|
|
9
|
+
};
|
|
10
|
+
exports?: {} | undefined;
|
|
11
|
+
bindings?: string | undefined;
|
|
12
|
+
};
|
|
13
|
+
export type AtlasLoadingProps = typeof __propDef.props;
|
|
14
|
+
export type AtlasLoadingEvents = typeof __propDef.events;
|
|
15
|
+
export type AtlasLoadingSlots = typeof __propDef.slots;
|
|
16
|
+
export default class AtlasLoading extends SvelteComponent<AtlasLoadingProps, AtlasLoadingEvents, AtlasLoadingSlots> {
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script>import { onDestroy, onMount } from "svelte";
|
|
2
|
+
import { initAtlas } from "../context";
|
|
3
|
+
import { cssVariables, resolveTokens } from "../appearance";
|
|
4
|
+
export let publishableKey;
|
|
5
|
+
export let frontendApi = void 0;
|
|
6
|
+
export let appearance = void 0;
|
|
7
|
+
export let localization = void 0;
|
|
8
|
+
export let fetchImpl = void 0;
|
|
9
|
+
const client = initAtlas({
|
|
10
|
+
publishableKey,
|
|
11
|
+
frontendApi,
|
|
12
|
+
appearance,
|
|
13
|
+
localization,
|
|
14
|
+
fetchImpl
|
|
15
|
+
});
|
|
16
|
+
$: style = Object.entries(cssVariables(resolveTokens(appearance))).map(([name, value]) => `${name}: ${value}`).join("; ");
|
|
17
|
+
onMount(() => void client.boot());
|
|
18
|
+
onDestroy(() => client.destroy());
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<div class="atlas-root" {style}>
|
|
22
|
+
<slot />
|
|
23
|
+
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import { type Appearance } from '../appearance';
|
|
3
|
+
import type { Catalog } from '../i18n';
|
|
4
|
+
declare const __propDef: {
|
|
5
|
+
props: {
|
|
6
|
+
/**
|
|
7
|
+
* §10.1 `<AtlasProvider publishableKey>` — the Svelte peer of React's provider.
|
|
8
|
+
*
|
|
9
|
+
* Calls {@link initAtlas} during component init so the client is in context
|
|
10
|
+
* before any child `<script>` runs, then renders a host-DOM wrapper carrying
|
|
11
|
+
* the appearance tokens as CSS variables. No iframe: components render in the
|
|
12
|
+
* host DOM so Tailwind / plain CSS just work.
|
|
13
|
+
*/ publishableKey: string;
|
|
14
|
+
frontendApi?: string | undefined;
|
|
15
|
+
appearance?: Appearance | undefined;
|
|
16
|
+
localization?: Catalog | undefined;
|
|
17
|
+
fetchImpl?: typeof fetch | undefined;
|
|
18
|
+
};
|
|
19
|
+
events: {
|
|
20
|
+
[evt: string]: CustomEvent<any>;
|
|
21
|
+
};
|
|
22
|
+
slots: {
|
|
23
|
+
default: {};
|
|
24
|
+
};
|
|
25
|
+
exports?: {} | undefined;
|
|
26
|
+
bindings?: string | undefined;
|
|
27
|
+
};
|
|
28
|
+
export type AtlasProviderProps = typeof __propDef.props;
|
|
29
|
+
export type AtlasProviderEvents = typeof __propDef.events;
|
|
30
|
+
export type AtlasProviderSlots = typeof __propDef.slots;
|
|
31
|
+
export default class AtlasProvider extends SvelteComponent<AtlasProviderProps, AtlasProviderEvents, AtlasProviderSlots> {
|
|
32
|
+
}
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script>import { nextStep } from "@atlasauth/js";
|
|
2
|
+
import { useAtlas } from "../context";
|
|
3
|
+
import { classFor } from "../appearance";
|
|
4
|
+
import { translate } from "../i18n";
|
|
5
|
+
export let attempt = null;
|
|
6
|
+
export let busy = false;
|
|
7
|
+
export let errors = [];
|
|
8
|
+
export let titleKey;
|
|
9
|
+
export let onSubmit;
|
|
10
|
+
const atlas = useAtlas();
|
|
11
|
+
const cls = (key, base) => classFor(key, atlas.appearance, base);
|
|
12
|
+
const t = (key, vars) => translate(atlas.catalog, key, vars);
|
|
13
|
+
let values = {};
|
|
14
|
+
$: step = attempt ? nextStep(attempt) : { kind: "collect_identifier" };
|
|
15
|
+
$: fields = (() => {
|
|
16
|
+
switch (step.kind) {
|
|
17
|
+
case "collect_identifier":
|
|
18
|
+
return [{ name: "identifier", labelKey: "signIn.identifierLabel", type: "email" }];
|
|
19
|
+
case "collect_first_factor":
|
|
20
|
+
return [{ name: "password", labelKey: "signIn.passwordLabel", type: "password" }];
|
|
21
|
+
case "collect_second_factor":
|
|
22
|
+
return [{ name: "code", labelKey: "mfa.codeLabel", type: "text" }];
|
|
23
|
+
case "enroll_second_factor":
|
|
24
|
+
return [
|
|
25
|
+
{ name: "code", labelKey: "mfa.enrollFirstCodeLabel", type: "text" },
|
|
26
|
+
{ name: "secondCode", labelKey: "mfa.enrollSecondCodeLabel", type: "text" }
|
|
27
|
+
];
|
|
28
|
+
case "collect_email_code":
|
|
29
|
+
return [{ name: "code", labelKey: "signIn.emailCodeLabel", type: "text" }];
|
|
30
|
+
case "collect_new_password":
|
|
31
|
+
return [{ name: "password", labelKey: "reset.newPasswordLabel", type: "password" }];
|
|
32
|
+
default:
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
})();
|
|
36
|
+
$: message = (() => {
|
|
37
|
+
switch (step.kind) {
|
|
38
|
+
case "await_oauth":
|
|
39
|
+
return t("signIn.magicLinkSent");
|
|
40
|
+
case "done":
|
|
41
|
+
return t("signIn.checkOtherTab");
|
|
42
|
+
case "restart":
|
|
43
|
+
return t("error.generic");
|
|
44
|
+
case "collect_identifier":
|
|
45
|
+
case "collect_first_factor":
|
|
46
|
+
case "collect_second_factor":
|
|
47
|
+
case "enroll_second_factor":
|
|
48
|
+
case "collect_email_code":
|
|
49
|
+
case "collect_new_password":
|
|
50
|
+
return null;
|
|
51
|
+
default:
|
|
52
|
+
return t("error.generic");
|
|
53
|
+
}
|
|
54
|
+
})();
|
|
55
|
+
$: showSubmit = step.kind !== "done" && step.kind !== "await_oauth" && message === null;
|
|
56
|
+
function handleSubmit(event) {
|
|
57
|
+
event.preventDefault();
|
|
58
|
+
onSubmit(values);
|
|
59
|
+
}
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<div class={cls('card', 'atlas-card')}>
|
|
63
|
+
<h1 class={cls('headerTitle', 'atlas-title')}>{t(titleKey)}</h1>
|
|
64
|
+
|
|
65
|
+
{#each errors.filter((e) => !e.param) as error (error.code)}
|
|
66
|
+
<p class={cls('formFieldError', 'atlas-error')} role="alert">{error.message}</p>
|
|
67
|
+
{/each}
|
|
68
|
+
|
|
69
|
+
<form on:submit={handleSubmit}>
|
|
70
|
+
{#if message !== null}
|
|
71
|
+
<p>{message}</p>
|
|
72
|
+
{:else}
|
|
73
|
+
{#each fields as f (f.name)}
|
|
74
|
+
<label class="atlas-field">
|
|
75
|
+
<span>{t(f.labelKey)}</span>
|
|
76
|
+
<input
|
|
77
|
+
class={cls('formFieldInput', 'atlas-input')}
|
|
78
|
+
type={f.type}
|
|
79
|
+
value={values[f.name] ?? ''}
|
|
80
|
+
on:input={(e) => (values[f.name] = e.currentTarget.value)}
|
|
81
|
+
/>
|
|
82
|
+
{#each errors.filter((e) => e.param === f.name) as error (error.code)}
|
|
83
|
+
<span class={cls('formFieldError', 'atlas-error')}>{error.message}</span>
|
|
84
|
+
{/each}
|
|
85
|
+
</label>
|
|
86
|
+
{/each}
|
|
87
|
+
{/if}
|
|
88
|
+
|
|
89
|
+
{#if showSubmit}
|
|
90
|
+
<button class={cls('formButtonPrimary', 'atlas-button')} disabled={busy} type="submit">
|
|
91
|
+
{t('signIn.submit')}
|
|
92
|
+
</button>
|
|
93
|
+
{/if}
|
|
94
|
+
</form>
|
|
95
|
+
</div>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import { type AttemptView, type FieldError } from '@atlasauth/js';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
/**
|
|
6
|
+
* The server-driven flow shell — the Svelte peer of React's `AttemptFlow`.
|
|
7
|
+
*
|
|
8
|
+
* Every branch comes from `nextStep`, which is exhaustive (including the
|
|
9
|
+
* `unknown` case, rendered as an honest message rather than nothing). This
|
|
10
|
+
* component makes no decision about what comes next; it renders whatever
|
|
11
|
+
* `status` the server returned.
|
|
12
|
+
*/ attempt?: AttemptView | null;
|
|
13
|
+
busy?: boolean;
|
|
14
|
+
errors?: FieldError[];
|
|
15
|
+
titleKey: string;
|
|
16
|
+
onSubmit: (values: Record<string, string>) => void;
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
exports?: {} | undefined;
|
|
23
|
+
bindings?: string | undefined;
|
|
24
|
+
};
|
|
25
|
+
export type AttemptFlowProps = typeof __propDef.props;
|
|
26
|
+
export type AttemptFlowEvents = typeof __propDef.events;
|
|
27
|
+
export type AttemptFlowSlots = typeof __propDef.slots;
|
|
28
|
+
export default class AttemptFlow extends SvelteComponent<AttemptFlowProps, AttemptFlowEvents, AttemptFlowSlots> {
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script>import { useAtlas } from "../context";
|
|
2
|
+
import { getOrganization } from "../accessors";
|
|
3
|
+
import { classFor } from "../appearance";
|
|
4
|
+
import { translate } from "../i18n";
|
|
5
|
+
import Protect from "./Protect.svelte";
|
|
6
|
+
const atlas = useAtlas();
|
|
7
|
+
const org = getOrganization();
|
|
8
|
+
const t = (key) => translate(atlas.catalog, key);
|
|
9
|
+
$: cardClass = classFor("card", atlas.appearance, "atlas-card");
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if $org.organization}
|
|
13
|
+
<div class={cardClass}>
|
|
14
|
+
<h1>{$org.organization.name}</h1>
|
|
15
|
+
<p>{t('organization.roleLabel')}: {$org.membership?.role}</p>
|
|
16
|
+
<!-- Management controls are gated on the ACTIVE org role, matching the
|
|
17
|
+
server's §9.2 rule rather than duplicating a looser one. -->
|
|
18
|
+
<Protect permission="org:sys_memberships:manage">
|
|
19
|
+
<button>{t('organization.invite')}</button>
|
|
20
|
+
</Protect>
|
|
21
|
+
</div>
|
|
22
|
+
{/if}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
exports?: {} | undefined;
|
|
9
|
+
bindings?: string | undefined;
|
|
10
|
+
};
|
|
11
|
+
export type OrganizationProfileProps = typeof __propDef.props;
|
|
12
|
+
export type OrganizationProfileEvents = typeof __propDef.events;
|
|
13
|
+
export type OrganizationProfileSlots = typeof __propDef.slots;
|
|
14
|
+
export default class OrganizationProfile extends SvelteComponent<OrganizationProfileProps, OrganizationProfileEvents, OrganizationProfileSlots> {
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script>import { useAtlas } from "../context";
|
|
2
|
+
import { getOrganization } from "../accessors";
|
|
3
|
+
import { classFor } from "../appearance";
|
|
4
|
+
import { translate } from "../i18n";
|
|
5
|
+
const atlas = useAtlas();
|
|
6
|
+
const org = getOrganization();
|
|
7
|
+
const t = (key) => translate(atlas.catalog, key);
|
|
8
|
+
$: menuClass = classFor("menu", atlas.appearance, "atlas-menu");
|
|
9
|
+
$: itemClass = classFor("menuItem", atlas.appearance, "atlas-menu-item");
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<div class={menuClass}>
|
|
13
|
+
<button class={itemClass} on:click={() => void $org.setActive(null)}>
|
|
14
|
+
{t('organization.personal')}
|
|
15
|
+
</button>
|
|
16
|
+
{#each $org.memberships as membership (membership.organization.id)}
|
|
17
|
+
<button
|
|
18
|
+
class={itemClass}
|
|
19
|
+
disabled={membership.organization.id === $org.organization?.id}
|
|
20
|
+
on:click={() => void $org.setActive(membership.organization.id)}
|
|
21
|
+
>
|
|
22
|
+
{membership.organization.name}
|
|
23
|
+
</button>
|
|
24
|
+
{/each}
|
|
25
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
exports?: {} | undefined;
|
|
9
|
+
bindings?: string | undefined;
|
|
10
|
+
};
|
|
11
|
+
export type OrganizationSwitcherProps = typeof __propDef.props;
|
|
12
|
+
export type OrganizationSwitcherEvents = typeof __propDef.events;
|
|
13
|
+
export type OrganizationSwitcherSlots = typeof __propDef.slots;
|
|
14
|
+
export default class OrganizationSwitcher extends SvelteComponent<OrganizationSwitcherProps, OrganizationSwitcherEvents, OrganizationSwitcherSlots> {
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script>import { get } from "svelte/store";
|
|
2
|
+
import { useAtlas } from "../context";
|
|
3
|
+
import { evaluate } from "../protect";
|
|
4
|
+
export let permission = void 0;
|
|
5
|
+
export let role = void 0;
|
|
6
|
+
export let anyPermission = void 0;
|
|
7
|
+
export let allPermissions = void 0;
|
|
8
|
+
const atlas = useAtlas();
|
|
9
|
+
const { status, claims } = atlas;
|
|
10
|
+
$: condition = { permission, role, anyPermission, allPermissions };
|
|
11
|
+
$: allowed = $status !== "loading" && evaluate($claims, condition).allowed;
|
|
12
|
+
$: loading = $status === "loading";
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
{#if loading}
|
|
16
|
+
<!-- nothing while the SDK is still booting -->
|
|
17
|
+
{:else if allowed}
|
|
18
|
+
<slot />
|
|
19
|
+
{:else}
|
|
20
|
+
<slot name="fallback" />
|
|
21
|
+
{/if}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
/**
|
|
5
|
+
* §10.2 `<Protect permission="…">` — conditional rendering.
|
|
6
|
+
*
|
|
7
|
+
* A rendering helper, never an authorization boundary: anyone can flip the
|
|
8
|
+
* condition in devtools. The server checking the same permission is what
|
|
9
|
+
* actually stops them, and this component's job is only to avoid showing a
|
|
10
|
+
* button that would fail. The `default` slot renders when allowed; the
|
|
11
|
+
* `fallback` slot renders otherwise.
|
|
12
|
+
*/ permission?: string | undefined;
|
|
13
|
+
role?: string | undefined;
|
|
14
|
+
anyPermission?: string[] | undefined;
|
|
15
|
+
allPermissions?: string[] | undefined;
|
|
16
|
+
};
|
|
17
|
+
events: {
|
|
18
|
+
[evt: string]: CustomEvent<any>;
|
|
19
|
+
};
|
|
20
|
+
slots: {
|
|
21
|
+
default: {};
|
|
22
|
+
fallback: {};
|
|
23
|
+
};
|
|
24
|
+
exports?: {} | undefined;
|
|
25
|
+
bindings?: string | undefined;
|
|
26
|
+
};
|
|
27
|
+
export type ProtectProps = typeof __propDef.props;
|
|
28
|
+
export type ProtectEvents = typeof __propDef.events;
|
|
29
|
+
export type ProtectSlots = typeof __propDef.slots;
|
|
30
|
+
export default class Protect extends SvelteComponent<ProtectProps, ProtectEvents, ProtectSlots> {
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script>import { onDestroy } from "svelte";
|
|
2
|
+
import { signIn } from "../accessors";
|
|
3
|
+
import AttemptFlow from "./AttemptFlow.svelte";
|
|
4
|
+
export let afterUrl = void 0;
|
|
5
|
+
const flow = signIn();
|
|
6
|
+
const flowState = flow.state;
|
|
7
|
+
onDestroy(() => flow.destroy());
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<AttemptFlow
|
|
11
|
+
attempt={$flowState.attempt}
|
|
12
|
+
busy={$flowState.busy}
|
|
13
|
+
errors={$flowState.errors}
|
|
14
|
+
titleKey="signIn.title"
|
|
15
|
+
onSubmit={flow.submit}
|
|
16
|
+
/>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
/**
|
|
5
|
+
* §10.2 `<SignIn/>` — a full multi-step flow driven entirely by the
|
|
6
|
+
* server-side attempt status. Contains no decision about what comes next; it
|
|
7
|
+
* renders whatever `status` the server returned.
|
|
8
|
+
*/ afterUrl?: string | undefined;
|
|
9
|
+
};
|
|
10
|
+
events: {
|
|
11
|
+
[evt: string]: CustomEvent<any>;
|
|
12
|
+
};
|
|
13
|
+
slots: {};
|
|
14
|
+
exports?: {} | undefined;
|
|
15
|
+
bindings?: string | undefined;
|
|
16
|
+
};
|
|
17
|
+
export type SignInProps = typeof __propDef.props;
|
|
18
|
+
export type SignInEvents = typeof __propDef.events;
|
|
19
|
+
export type SignInSlots = typeof __propDef.slots;
|
|
20
|
+
export default class SignIn extends SvelteComponent<SignInProps, SignInEvents, SignInSlots> {
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script>import { onDestroy } from "svelte";
|
|
2
|
+
import { signUp } from "../accessors";
|
|
3
|
+
import AttemptFlow from "./AttemptFlow.svelte";
|
|
4
|
+
export let afterUrl = void 0;
|
|
5
|
+
const flow = signUp();
|
|
6
|
+
const flowState = flow.state;
|
|
7
|
+
onDestroy(() => flow.destroy());
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<AttemptFlow
|
|
11
|
+
attempt={$flowState.attempt}
|
|
12
|
+
busy={$flowState.busy}
|
|
13
|
+
errors={$flowState.errors}
|
|
14
|
+
titleKey="signUp.title"
|
|
15
|
+
onSubmit={flow.submit}
|
|
16
|
+
/>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
/**
|
|
5
|
+
* §10.2 `<SignUp/>` — the server-driven registration flow. Same shell as
|
|
6
|
+
* `<SignIn/>`, only the title differs; the step sequence comes from the server.
|
|
7
|
+
*/ afterUrl?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
events: {
|
|
10
|
+
[evt: string]: CustomEvent<any>;
|
|
11
|
+
};
|
|
12
|
+
slots: {};
|
|
13
|
+
exports?: {} | undefined;
|
|
14
|
+
bindings?: string | undefined;
|
|
15
|
+
};
|
|
16
|
+
export type SignUpProps = typeof __propDef.props;
|
|
17
|
+
export type SignUpEvents = typeof __propDef.events;
|
|
18
|
+
export type SignUpSlots = typeof __propDef.slots;
|
|
19
|
+
export default class SignUp extends SvelteComponent<SignUpProps, SignUpEvents, SignUpSlots> {
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {
|
|
8
|
+
default: {};
|
|
9
|
+
};
|
|
10
|
+
exports?: {} | undefined;
|
|
11
|
+
bindings?: string | undefined;
|
|
12
|
+
};
|
|
13
|
+
export type SignedInProps = typeof __propDef.props;
|
|
14
|
+
export type SignedInEvents = typeof __propDef.events;
|
|
15
|
+
export type SignedInSlots = typeof __propDef.slots;
|
|
16
|
+
export default class SignedIn extends SvelteComponent<SignedInProps, SignedInEvents, SignedInSlots> {
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {
|
|
8
|
+
default: {};
|
|
9
|
+
};
|
|
10
|
+
exports?: {} | undefined;
|
|
11
|
+
bindings?: string | undefined;
|
|
12
|
+
};
|
|
13
|
+
export type SignedOutProps = typeof __propDef.props;
|
|
14
|
+
export type SignedOutEvents = typeof __propDef.events;
|
|
15
|
+
export type SignedOutSlots = typeof __propDef.slots;
|
|
16
|
+
export default class SignedOut extends SvelteComponent<SignedOutProps, SignedOutEvents, SignedOutSlots> {
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script>import { useAtlas } from "../context";
|
|
2
|
+
import { getUser } from "../accessors";
|
|
3
|
+
import { classFor } from "../appearance";
|
|
4
|
+
import { translate } from "../i18n";
|
|
5
|
+
const atlas = useAtlas();
|
|
6
|
+
const user = getUser();
|
|
7
|
+
const cls = classFor;
|
|
8
|
+
const t = (key) => translate(atlas.catalog, key);
|
|
9
|
+
let open = false;
|
|
10
|
+
$: current = $user.user;
|
|
11
|
+
$: label = current ? [current.first_name, current.last_name].filter(Boolean).join(" ") || current.username || "" : "";
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
{#if current}
|
|
15
|
+
<div class="atlas-user-button">
|
|
16
|
+
<button
|
|
17
|
+
class={cls('avatar', atlas.appearance, 'atlas-avatar')}
|
|
18
|
+
on:click={() => (open = !open)}
|
|
19
|
+
aria-expanded={open}
|
|
20
|
+
>
|
|
21
|
+
{#if current.image_url}
|
|
22
|
+
<img alt="" src={current.image_url} />
|
|
23
|
+
{:else}
|
|
24
|
+
<span>{label.slice(0, 1)}</span>
|
|
25
|
+
{/if}
|
|
26
|
+
</button>
|
|
27
|
+
|
|
28
|
+
{#if open}
|
|
29
|
+
<div class={cls('menu', atlas.appearance, 'atlas-menu')} role="menu">
|
|
30
|
+
<span class={cls('menuItem', atlas.appearance, 'atlas-menu-item')}>{label}</span>
|
|
31
|
+
<button
|
|
32
|
+
class={cls('menuItem', atlas.appearance, 'atlas-menu-item')}
|
|
33
|
+
on:click={() => void atlas.signOut()}
|
|
34
|
+
>
|
|
35
|
+
{t('userButton.signOut')}
|
|
36
|
+
</button>
|
|
37
|
+
</div>
|
|
38
|
+
{/if}
|
|
39
|
+
</div>
|
|
40
|
+
{/if}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
exports?: {} | undefined;
|
|
9
|
+
bindings?: string | undefined;
|
|
10
|
+
};
|
|
11
|
+
export type UserButtonProps = typeof __propDef.props;
|
|
12
|
+
export type UserButtonEvents = typeof __propDef.events;
|
|
13
|
+
export type UserButtonSlots = typeof __propDef.slots;
|
|
14
|
+
export default class UserButton extends SvelteComponent<UserButtonProps, UserButtonEvents, UserButtonSlots> {
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script>import { useAtlas } from "../context";
|
|
2
|
+
import { getUser } from "../accessors";
|
|
3
|
+
import { classFor } from "../appearance";
|
|
4
|
+
import { translate } from "../i18n";
|
|
5
|
+
const atlas = useAtlas();
|
|
6
|
+
const user = getUser();
|
|
7
|
+
const t = (key) => translate(atlas.catalog, key);
|
|
8
|
+
$: current = $user.user;
|
|
9
|
+
$: cardClass = classFor("card", atlas.appearance, "atlas-card");
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if current}
|
|
13
|
+
<div class={cardClass}>
|
|
14
|
+
<h1>{t('userProfile.title')}</h1>
|
|
15
|
+
|
|
16
|
+
<section>
|
|
17
|
+
<h2>{t('userProfile.emailsSection')}</h2>
|
|
18
|
+
<ul>
|
|
19
|
+
{#each current.email_addresses ?? [] as email (email.id)}
|
|
20
|
+
<li>
|
|
21
|
+
{email.email_address}
|
|
22
|
+
{#if !email.verified}
|
|
23
|
+
<em> — {t('userProfile.unverified')}</em>
|
|
24
|
+
{/if}
|
|
25
|
+
</li>
|
|
26
|
+
{/each}
|
|
27
|
+
</ul>
|
|
28
|
+
</section>
|
|
29
|
+
|
|
30
|
+
<section>
|
|
31
|
+
<h2>{t('userProfile.securitySection')}</h2>
|
|
32
|
+
<p>{current.mfa_enabled ? '2FA on' : '2FA off'}</p>
|
|
33
|
+
</section>
|
|
34
|
+
</div>
|
|
35
|
+
{/if}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
exports?: {} | undefined;
|
|
9
|
+
bindings?: string | undefined;
|
|
10
|
+
};
|
|
11
|
+
export type UserProfileProps = typeof __propDef.props;
|
|
12
|
+
export type UserProfileEvents = typeof __propDef.events;
|
|
13
|
+
export type UserProfileSlots = typeof __propDef.slots;
|
|
14
|
+
export default class UserProfile extends SvelteComponent<UserProfileProps, UserProfileEvents, UserProfileSlots> {
|
|
15
|
+
}
|
|
16
|
+
export {};
|