@slashid/jump-page 0.0.7-beta.0 → 0.0.7-beta.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/cli.js +16 -19
- package/dist/_astro/app.f7d04798.js +39 -0
- package/dist/_astro/client.a5ffbec0.js +24 -0
- package/dist/_astro/index.03be2d59.js +9 -0
- package/dist/_astro/index.2dd0ad08.css +1 -0
- package/dist/_astro/index.cc62d81f.css +1 -0
- package/dist/index.html +7 -0
- package/package.json +9 -1
- package/.turbo/turbo-build.log +0 -32
- package/.vscode/extensions.json +0 -4
- package/.vscode/launch.json +0 -11
- package/CHANGELOG.md +0 -37
- package/src/components/README.md +0 -3
- package/src/components/app/app.component.tsx +0 -83
- package/src/components/app/app.context.tsx +0 -41
- package/src/components/app/app.css.ts +0 -15
- package/src/components/app/index.ts +0 -1
- package/src/components/card/card.component.tsx +0 -42
- package/src/components/card/card.css.ts +0 -40
- package/src/components/card/index.ts +0 -1
- package/src/components/flow/flow.component.tsx +0 -99
- package/src/components/flow/flow.css.ts +0 -20
- package/src/components/flow/flow.domain.ts +0 -18
- package/src/components/flow/flow.error.tsx +0 -32
- package/src/components/flow/flow.initial.tsx +0 -14
- package/src/components/flow/flow.loader.tsx +0 -9
- package/src/components/flow/flow.progress.tsx +0 -119
- package/src/components/flow/flow.recover.tsx +0 -121
- package/src/components/flow/flow.success.tsx +0 -40
- package/src/components/flow/flow.types.ts +0 -48
- package/src/components/flow/index.ts +0 -3
- package/src/components/text/index.ts +0 -1
- package/src/components/text/text.component.tsx +0 -8
- package/src/components/text/use-i18n.ts +0 -13
- package/src/config.ts +0 -13
- package/src/domain/i18n.ts +0 -115
- package/src/env.d.ts +0 -1
- package/src/layouts/README.md +0 -3
- package/src/layouts/page.astro +0 -33
- package/src/pages/index.astro +0 -8
- /package/{public → dist}/favicon.png +0 -0
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import type { InvalidPasswordSubmittedEvent } from "@slashid/slashid";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
3
|
-
import {
|
|
4
|
-
Input,
|
|
5
|
-
Stack,
|
|
6
|
-
Text,
|
|
7
|
-
Button,
|
|
8
|
-
sprinkles,
|
|
9
|
-
} from "@slashid/react-primitives";
|
|
10
|
-
|
|
11
|
-
import * as styles from "./flow.css";
|
|
12
|
-
import { useI18n } from "../text/use-i18n";
|
|
13
|
-
import { useAppContext } from "../app/app.context";
|
|
14
|
-
import type { TranslationKeys } from "../../domain/i18n";
|
|
15
|
-
|
|
16
|
-
function getValidationI18nKey(
|
|
17
|
-
errorEvent: InvalidPasswordSubmittedEvent
|
|
18
|
-
): TranslationKeys {
|
|
19
|
-
const textKey = `authenticating.setPassword.validation.${errorEvent.failedRules[0].name}`;
|
|
20
|
-
|
|
21
|
-
// prefer the first error
|
|
22
|
-
return textKey as TranslationKeys;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function ErrorMessage({ message }: { message: string }) {
|
|
26
|
-
return <span className={styles.errorMessage}>{message}</span>;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function Recover() {
|
|
30
|
-
const i18n = useI18n();
|
|
31
|
-
const { sdk } = useAppContext();
|
|
32
|
-
const [password, setPassword] = useState("");
|
|
33
|
-
const [passwordConfirm, setPasswordConfirm] = useState("");
|
|
34
|
-
const [error, setError] = useState<string | null>(null);
|
|
35
|
-
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
const onInvalidPassword = (
|
|
38
|
-
invalidPasswordEvent: InvalidPasswordSubmittedEvent
|
|
39
|
-
) => {
|
|
40
|
-
console.log("onInvalidPassword", invalidPasswordEvent);
|
|
41
|
-
setError(i18n(getValidationI18nKey(invalidPasswordEvent)));
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
sdk?.subscribe("invalidPasswordSubmitted", onInvalidPassword);
|
|
45
|
-
|
|
46
|
-
return () => {
|
|
47
|
-
sdk?.unsubscribe("invalidPasswordSubmitted", onInvalidPassword);
|
|
48
|
-
};
|
|
49
|
-
}, [i18n, sdk, setError]);
|
|
50
|
-
|
|
51
|
-
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
|
52
|
-
event.preventDefault();
|
|
53
|
-
|
|
54
|
-
if (!sdk) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
sdk.publish("passwordSubmitted", password);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const handlePasswordChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
62
|
-
setPassword(event.target.value);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const handleConfirmPasswordChange = (
|
|
66
|
-
event: React.ChangeEvent<HTMLInputElement>
|
|
67
|
-
) => {
|
|
68
|
-
setPasswordConfirm(event.target.value);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<>
|
|
73
|
-
<Stack space="0.25">
|
|
74
|
-
<Text
|
|
75
|
-
as="h1"
|
|
76
|
-
variant={{ size: "2xl-title", weight: "bold" }}
|
|
77
|
-
t="recover.password.title"
|
|
78
|
-
/>
|
|
79
|
-
<Text
|
|
80
|
-
variant={{ color: "contrast", weight: "semibold" }}
|
|
81
|
-
as="h2"
|
|
82
|
-
t="recover.password.details"
|
|
83
|
-
/>
|
|
84
|
-
</Stack>
|
|
85
|
-
<form onSubmit={handleSubmit}>
|
|
86
|
-
<div className={styles.formInputs}>
|
|
87
|
-
{/* TODO add an error state to the input (change border color) */}
|
|
88
|
-
<Input
|
|
89
|
-
id="password-input"
|
|
90
|
-
label={i18n("recover.password.input.password.label")}
|
|
91
|
-
placeholder={i18n("recover.password.input.placeholder")}
|
|
92
|
-
name="password"
|
|
93
|
-
type="password"
|
|
94
|
-
value={password ?? ""}
|
|
95
|
-
onChange={handlePasswordChange}
|
|
96
|
-
/>
|
|
97
|
-
<Input
|
|
98
|
-
id="password-input-confirm"
|
|
99
|
-
label={i18n("recover.password.input.confirmPassword.label")}
|
|
100
|
-
placeholder={i18n("recover.password.input.placeholder")}
|
|
101
|
-
name="passwordConfirm"
|
|
102
|
-
type="password"
|
|
103
|
-
value={passwordConfirm ?? ""}
|
|
104
|
-
onChange={handleConfirmPasswordChange}
|
|
105
|
-
className={sprinkles({ marginTop: "4" })}
|
|
106
|
-
/>
|
|
107
|
-
{error && <ErrorMessage message={error} />}
|
|
108
|
-
</div>
|
|
109
|
-
|
|
110
|
-
<Button
|
|
111
|
-
type="submit"
|
|
112
|
-
variant="primary"
|
|
113
|
-
testId="sid-form-initial-submit-button"
|
|
114
|
-
disabled={!password || password !== passwordConfirm}
|
|
115
|
-
>
|
|
116
|
-
{i18n("recover.password.submit")}
|
|
117
|
-
</Button>
|
|
118
|
-
</form>
|
|
119
|
-
</>
|
|
120
|
-
);
|
|
121
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Circle } from "@slashid/react-primitives";
|
|
2
|
-
import { Text } from "../text";
|
|
3
|
-
|
|
4
|
-
const CheckIcon = () => (
|
|
5
|
-
<Circle>
|
|
6
|
-
<svg
|
|
7
|
-
width="21"
|
|
8
|
-
height="18"
|
|
9
|
-
viewBox="0 0 21 18"
|
|
10
|
-
fill="none"
|
|
11
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
12
|
-
>
|
|
13
|
-
<path
|
|
14
|
-
fillRule="evenodd"
|
|
15
|
-
clipRule="evenodd"
|
|
16
|
-
d="M19.8505 0.705985C20.6342 1.38283 20.7209 2.56684 20.044 3.35055L8.16908 17.1005C7.80192 17.5256 7.2635 17.7637 6.70195 17.7493C6.1404 17.7349 5.61489 17.4695 5.27002 17.0261L0.895049 11.4011C0.259296 10.5837 0.406547 9.4057 1.22394 8.76995C2.04134 8.13419 3.21935 8.28145 3.8551 9.09884L6.82592 12.9185L17.2059 0.89949C17.8828 0.115778 19.0668 0.0291434 19.8505 0.705985Z"
|
|
17
|
-
fill="white"
|
|
18
|
-
/>
|
|
19
|
-
</svg>
|
|
20
|
-
</Circle>
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
// TODO this view always tells you are logged in, even in cases when you just verify the handle and not have a token
|
|
24
|
-
export function Success() {
|
|
25
|
-
return (
|
|
26
|
-
<article data-testid="sid-form-success-state">
|
|
27
|
-
<Text
|
|
28
|
-
as="h1"
|
|
29
|
-
t="success.title"
|
|
30
|
-
variant={{ size: "2xl-title", weight: "bold" }}
|
|
31
|
-
/>
|
|
32
|
-
<Text
|
|
33
|
-
as="h2"
|
|
34
|
-
t="success.details"
|
|
35
|
-
variant={{ color: "contrast", weight: "semibold" }}
|
|
36
|
-
/>
|
|
37
|
-
<CheckIcon />
|
|
38
|
-
</article>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { SlashID } from "@slashid/slashid";
|
|
2
|
-
|
|
3
|
-
export type InitialState = {
|
|
4
|
-
state: "initial";
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export type ParsingURLState = {
|
|
8
|
-
state: "parsing-url";
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export type NoChallengesState = {
|
|
12
|
-
state: "no-challenges";
|
|
13
|
-
challenges: null;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export type ProgressState = {
|
|
17
|
-
state: "progress";
|
|
18
|
-
challenges: Challenges;
|
|
19
|
-
flowType: FlowType;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type SuccessState = {
|
|
23
|
-
state: "success";
|
|
24
|
-
challenges: Challenges;
|
|
25
|
-
flowType: FlowType;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export type ErrorState = {
|
|
29
|
-
state: "error";
|
|
30
|
-
error: Error;
|
|
31
|
-
challenges: Challenges;
|
|
32
|
-
flowType: FlowType;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export type State =
|
|
36
|
-
| InitialState
|
|
37
|
-
| ParsingURLState
|
|
38
|
-
| NoChallengesState
|
|
39
|
-
| ProgressState
|
|
40
|
-
| SuccessState
|
|
41
|
-
| ErrorState;
|
|
42
|
-
|
|
43
|
-
export type FlowType = "catch-all" | "password-recovery";
|
|
44
|
-
|
|
45
|
-
export type ChallengesInURL = Awaited<
|
|
46
|
-
ReturnType<SlashID["getChallengesFromURL"]>
|
|
47
|
-
>;
|
|
48
|
-
export type Challenges = NonNullable<ChallengesInURL>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./text.component";
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Text as BaseText, type TextProps } from "@slashid/react-primitives";
|
|
2
|
-
import type { TranslationKeys } from "../../domain/i18n";
|
|
3
|
-
|
|
4
|
-
type Props = TextProps<Record<TranslationKeys, string>>;
|
|
5
|
-
|
|
6
|
-
export const Text: React.FC<Props> = (props) => {
|
|
7
|
-
return <BaseText {...props} />;
|
|
8
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
2
|
-
import { createI18n } from "../../domain/i18n";
|
|
3
|
-
import { useAppContext } from "../app/app.context";
|
|
4
|
-
|
|
5
|
-
export function useI18n() {
|
|
6
|
-
const { language } = useAppContext();
|
|
7
|
-
|
|
8
|
-
const i18n = useMemo(() => {
|
|
9
|
-
return createI18n(language);
|
|
10
|
-
}, [language]);
|
|
11
|
-
|
|
12
|
-
return i18n;
|
|
13
|
-
}
|
package/src/config.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// TODO this does not work with .env files
|
|
2
|
-
/* export const config = {
|
|
3
|
-
sdkURL:
|
|
4
|
-
import.meta.env.PUBLIC_SID_SDK_URL ||
|
|
5
|
-
"https://cdn.sandbox.slashid.com/sdk.html",
|
|
6
|
-
baseURL:
|
|
7
|
-
import.meta.env.PUBLIC_SID_API_URL || "https://api.sandbox.slashid.com",
|
|
8
|
-
}; */
|
|
9
|
-
|
|
10
|
-
export const config = {
|
|
11
|
-
baseURL: "https://slashid.local",
|
|
12
|
-
sdkURL: "https://jump.slashid.local/sdk.html",
|
|
13
|
-
};
|
package/src/domain/i18n.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
// based on RFC 5646
|
|
2
|
-
export type Language = "en" | "ja";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Check the language based on the browser settings.
|
|
6
|
-
* Default to "en"
|
|
7
|
-
*/
|
|
8
|
-
export function detectLanguage(): Language {
|
|
9
|
-
const language = navigator.language.toLowerCase();
|
|
10
|
-
if (language === "ja" || language.startsWith("ja-")) {
|
|
11
|
-
return "ja";
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return "en";
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const defaultStrings = {
|
|
18
|
-
"footer.text": "Top-tier security by SlashID",
|
|
19
|
-
"initial.title": "Logging you in...",
|
|
20
|
-
"initial.details": "Please follow the on-screen instructions.",
|
|
21
|
-
"recover.password.title": "Reset password",
|
|
22
|
-
"recover.password.details": "Enter your new password.",
|
|
23
|
-
"recover.password.input.password.label": "Password",
|
|
24
|
-
"recover.password.input.confirmPassword.label": "Confirm password",
|
|
25
|
-
"recover.password.input.placeholder": "Type your new password",
|
|
26
|
-
"recover.password.submit": "Reset password",
|
|
27
|
-
"recover.password.validation.length": "Password is too short",
|
|
28
|
-
"recover.password.validation.password_variants": "Contains word 'password'",
|
|
29
|
-
"recover.password.validation.admin_variants": "Contains word 'admin'",
|
|
30
|
-
"recover.password.validation.user_variants": "Contains word 'user'",
|
|
31
|
-
"recover.password.validation.alphanumeric_sequences_1":
|
|
32
|
-
"Sequence of alphanumeric characters",
|
|
33
|
-
"recover.password.validation.alphanumeric_sequences_2":
|
|
34
|
-
"Sequence of alphanumeric characters",
|
|
35
|
-
"recover.password.validation.numeric_sequences_ascending":
|
|
36
|
-
"Sequence of alphanumeric characters",
|
|
37
|
-
"recover.password.validation.numeric_subsequences_ascending":
|
|
38
|
-
"Sequence of alphanumeric characters",
|
|
39
|
-
"recover.password.validation.numeric_sequences_descending":
|
|
40
|
-
"Sequence of alphanumeric characters",
|
|
41
|
-
"recover.password.validation.numeric_subsequences_descending":
|
|
42
|
-
"Sequence of alphanumeric characters",
|
|
43
|
-
"recover.password.validation.common_password_xkcd": "Common password",
|
|
44
|
-
"success.title": "Thank you, you're signed in!",
|
|
45
|
-
"success.details": "You can now close this page.",
|
|
46
|
-
"error.title": "Something went wrong...",
|
|
47
|
-
"error.detail": "Please log in again.",
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export type TranslationKeys = keyof typeof defaultStrings;
|
|
51
|
-
export type Translations = {
|
|
52
|
-
[key in Language]: {
|
|
53
|
-
[key in TranslationKeys]: string;
|
|
54
|
-
};
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// TODO add translations for password validation errors
|
|
58
|
-
export const I18N: Translations = {
|
|
59
|
-
en: defaultStrings,
|
|
60
|
-
ja: {
|
|
61
|
-
"footer.text": defaultStrings["footer.text"],
|
|
62
|
-
"initial.title": "ログイン処理を行っています。",
|
|
63
|
-
"initial.details": "処理完了後、画面は自動で切り替わります。",
|
|
64
|
-
"success.title": "認証が完了しました!",
|
|
65
|
-
"success.details": "このページを閉じて、元のページへ戻ってください。",
|
|
66
|
-
"recover.password.title": defaultStrings["recover.password.title"],
|
|
67
|
-
"recover.password.details": defaultStrings["recover.password.details"],
|
|
68
|
-
"recover.password.input.password.label":
|
|
69
|
-
defaultStrings["recover.password.input.password.label"],
|
|
70
|
-
"recover.password.input.confirmPassword.label":
|
|
71
|
-
defaultStrings["recover.password.input.confirmPassword.label"],
|
|
72
|
-
"recover.password.input.placeholder":
|
|
73
|
-
defaultStrings["recover.password.input.placeholder"],
|
|
74
|
-
"recover.password.submit": defaultStrings["recover.password.submit"],
|
|
75
|
-
"recover.password.validation.length":
|
|
76
|
-
defaultStrings["recover.password.validation.length"],
|
|
77
|
-
"recover.password.validation.password_variants":
|
|
78
|
-
defaultStrings["recover.password.validation.password_variants"],
|
|
79
|
-
"recover.password.validation.admin_variants":
|
|
80
|
-
defaultStrings["recover.password.validation.admin_variants"],
|
|
81
|
-
"recover.password.validation.user_variants":
|
|
82
|
-
defaultStrings["recover.password.validation.user_variants"],
|
|
83
|
-
"recover.password.validation.alphanumeric_sequences_1":
|
|
84
|
-
defaultStrings["recover.password.validation.alphanumeric_sequences_1"],
|
|
85
|
-
"recover.password.validation.alphanumeric_sequences_2":
|
|
86
|
-
defaultStrings["recover.password.validation.alphanumeric_sequences_2"],
|
|
87
|
-
"recover.password.validation.numeric_sequences_ascending":
|
|
88
|
-
defaultStrings["recover.password.validation.numeric_sequences_ascending"],
|
|
89
|
-
"recover.password.validation.numeric_subsequences_ascending":
|
|
90
|
-
defaultStrings[
|
|
91
|
-
"recover.password.validation.numeric_subsequences_ascending"
|
|
92
|
-
],
|
|
93
|
-
"recover.password.validation.numeric_sequences_descending":
|
|
94
|
-
defaultStrings[
|
|
95
|
-
"recover.password.validation.numeric_sequences_descending"
|
|
96
|
-
],
|
|
97
|
-
"recover.password.validation.numeric_subsequences_descending":
|
|
98
|
-
defaultStrings[
|
|
99
|
-
"recover.password.validation.numeric_subsequences_descending"
|
|
100
|
-
],
|
|
101
|
-
"recover.password.validation.common_password_xkcd":
|
|
102
|
-
defaultStrings["recover.password.validation.common_password_xkcd"],
|
|
103
|
-
"error.title": defaultStrings["error.title"],
|
|
104
|
-
"error.detail": "再度ログインをしてください。",
|
|
105
|
-
},
|
|
106
|
-
} as const;
|
|
107
|
-
|
|
108
|
-
export type TranslationKey = keyof Translations[Language];
|
|
109
|
-
|
|
110
|
-
export type Translate = (
|
|
111
|
-
key: TranslationKey
|
|
112
|
-
) => (typeof I18N)[Language][TranslationKey];
|
|
113
|
-
|
|
114
|
-
export const createI18n = (language: Language) => (key: TranslationKey) =>
|
|
115
|
-
I18N[language][key];
|
package/src/env.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="astro/client" />
|
package/src/layouts/README.md
DELETED
package/src/layouts/page.astro
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
interface Props {
|
|
3
|
-
title: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
const { title } = Astro.props;
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
<!DOCTYPE html>
|
|
10
|
-
<html>
|
|
11
|
-
<head>
|
|
12
|
-
<meta charset="utf-8" />
|
|
13
|
-
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
14
|
-
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
15
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
16
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap" rel="stylesheet" />
|
|
17
|
-
<link rel="icon" href="/favicon.png">
|
|
18
|
-
<title>{title}</title>
|
|
19
|
-
</head>
|
|
20
|
-
|
|
21
|
-
<body>
|
|
22
|
-
<slot />
|
|
23
|
-
</body>
|
|
24
|
-
</html>
|
|
25
|
-
|
|
26
|
-
<style>
|
|
27
|
-
body {
|
|
28
|
-
width: 100%;
|
|
29
|
-
height: 100vh;
|
|
30
|
-
margin: 0;
|
|
31
|
-
padding: 0;
|
|
32
|
-
}
|
|
33
|
-
</style>
|
package/src/pages/index.astro
DELETED
|
File without changes
|