@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.
Files changed (41) hide show
  1. package/cli.js +16 -19
  2. package/dist/_astro/app.f7d04798.js +39 -0
  3. package/dist/_astro/client.a5ffbec0.js +24 -0
  4. package/dist/_astro/index.03be2d59.js +9 -0
  5. package/dist/_astro/index.2dd0ad08.css +1 -0
  6. package/dist/_astro/index.cc62d81f.css +1 -0
  7. package/dist/index.html +7 -0
  8. package/package.json +9 -1
  9. package/.turbo/turbo-build.log +0 -32
  10. package/.vscode/extensions.json +0 -4
  11. package/.vscode/launch.json +0 -11
  12. package/CHANGELOG.md +0 -37
  13. package/src/components/README.md +0 -3
  14. package/src/components/app/app.component.tsx +0 -83
  15. package/src/components/app/app.context.tsx +0 -41
  16. package/src/components/app/app.css.ts +0 -15
  17. package/src/components/app/index.ts +0 -1
  18. package/src/components/card/card.component.tsx +0 -42
  19. package/src/components/card/card.css.ts +0 -40
  20. package/src/components/card/index.ts +0 -1
  21. package/src/components/flow/flow.component.tsx +0 -99
  22. package/src/components/flow/flow.css.ts +0 -20
  23. package/src/components/flow/flow.domain.ts +0 -18
  24. package/src/components/flow/flow.error.tsx +0 -32
  25. package/src/components/flow/flow.initial.tsx +0 -14
  26. package/src/components/flow/flow.loader.tsx +0 -9
  27. package/src/components/flow/flow.progress.tsx +0 -119
  28. package/src/components/flow/flow.recover.tsx +0 -121
  29. package/src/components/flow/flow.success.tsx +0 -40
  30. package/src/components/flow/flow.types.ts +0 -48
  31. package/src/components/flow/index.ts +0 -3
  32. package/src/components/text/index.ts +0 -1
  33. package/src/components/text/text.component.tsx +0 -8
  34. package/src/components/text/use-i18n.ts +0 -13
  35. package/src/config.ts +0 -13
  36. package/src/domain/i18n.ts +0 -115
  37. package/src/env.d.ts +0 -1
  38. package/src/layouts/README.md +0 -3
  39. package/src/layouts/page.astro +0 -33
  40. package/src/pages/index.astro +0 -8
  41. /package/{public → dist}/favicon.png +0 -0
@@ -1,32 +0,0 @@
1
-
2
- > @slashid/jump-page@0.0.6 build /Users/ivankovic/projects/slashid/javascript/apps/jump-page
3
- > astro build
4
-
5
- 05:00:06 PM [content] No content directory found. Skipping type generation.
6
- 05:00:06 PM [build] output target: static
7
- 05:00:06 PM [build] Collecting build info...
8
- 05:00:06 PM [build] Completed in 111ms.
9
- 05:00:06 PM [build] Building static entrypoints...
10
- 05:00:07 PM [build] Completed in 1.68s.
11
-
12
- building client
13
- vite v4.5.0 building for production...
14
- transforming...
15
- ✓ 384 modules transformed.
16
- rendering chunks...
17
- computing gzip size...
18
- dist/_astro/index.cc62d81f.css 31.75 kB │ gzip: 5.49 kB
19
- dist/_astro/index.03be2d59.js 6.83 kB │ gzip: 2.72 kB
20
- dist/_astro/client.a5ffbec0.js 135.34 kB │ gzip: 43.73 kB
21
- dist/_astro/app.51fc6a0f.js 203.42 kB │ gzip: 56.61 kB
22
- ✓ built in 1.94s
23
- Completed in 1.95s.
24
-
25
-
26
- generating static routes
27
- ▶ src/pages/index.astro
28
- └─ /index.html (+122ms)
29
- Completed in 132ms.
30
-
31
- 05:00:09 PM [build] 1 page(s) built in 3.88s
32
- 05:00:09 PM [build] Complete!
@@ -1,4 +0,0 @@
1
- {
2
- "recommendations": ["astro-build.astro-vscode"],
3
- "unwantedRecommendations": []
4
- }
@@ -1,11 +0,0 @@
1
- {
2
- "version": "0.2.0",
3
- "configurations": [
4
- {
5
- "command": "./node_modules/.bin/astro dev",
6
- "name": "Development server",
7
- "request": "launch",
8
- "type": "node-terminal"
9
- }
10
- ]
11
- }
package/CHANGELOG.md DELETED
@@ -1,37 +0,0 @@
1
- # @slashid/jump-page
2
-
3
- ## 0.0.6
4
-
5
- ### Patch Changes
6
-
7
- - Updated dependencies [64212fd]
8
- - @slashid/react-primitives@0.1.4
9
-
10
- ## 0.0.5
11
-
12
- ### Patch Changes
13
-
14
- - Updated dependencies [21c2948]
15
- - @slashid/react-primitives@0.1.3
16
-
17
- ## 0.0.4
18
-
19
- ### Patch Changes
20
-
21
- - Updated dependencies [0e2fb6b]
22
- - @slashid/react-primitives@0.1.2
23
-
24
- ## 0.0.3
25
-
26
- ### Patch Changes
27
-
28
- - Updated dependencies [0e4746c]
29
- - @slashid/react-primitives@0.1.1
30
-
31
- ## 0.0.2
32
-
33
- ### Patch Changes
34
-
35
- - c1cf068: Update dependencies
36
- - Updated dependencies [c1cf068]
37
- - @slashid/react-primitives@0.1.0
@@ -1,3 +0,0 @@
1
- # Components
2
-
3
- This folder should only contain components meant to render server side and then hydrate on the client side.
@@ -1,83 +0,0 @@
1
- import { SlashID } from "@slashid/slashid";
2
- import * as Sentry from "@sentry/react";
3
- import {
4
- Logo,
5
- TextProvider,
6
- ThemeRoot,
7
- isBrowser,
8
- } from "@slashid/react-primitives";
9
-
10
- import {
11
- AppContext,
12
- initialAppContextState,
13
- type AppState,
14
- type AppContextState,
15
- type AppReadyState,
16
- } from "./app.context";
17
- import { useEffect, useMemo, useRef, useState } from "react";
18
- import { I18N, detectLanguage } from "../../domain/i18n";
19
- import { Flow, Error } from "../flow";
20
- import { Card } from "../card";
21
-
22
- import * as styles from "./app.css";
23
- import { config } from "../../config";
24
-
25
- export function App() {
26
- const isClientSide = isBrowser();
27
- const [appState, setAppState] = useState<AppState>("initial");
28
- const sidRef = useRef<SlashID | undefined>(undefined);
29
-
30
- useEffect(() => {
31
- if (appState === "initial") {
32
- Sentry.init({
33
- dsn: "https://6435e8a20ba8b61404fb4621d2aedd4a@o4505317722619904.ingest.sentry.io/4506275681075200",
34
- });
35
-
36
- sidRef.current = new SlashID({
37
- analyticsEnabled: false,
38
- sdkURL: config.sdkURL,
39
- baseURL: config.baseURL,
40
- });
41
-
42
- setAppState("ready");
43
- }
44
- }, [appState]);
45
-
46
- const state: AppContextState = useMemo(() => {
47
- // checking for hydration makes the first client side render the same as the one on the server side
48
- // language check and URL params can only be done on the client side so we need to wait for the first render
49
- if (!isClientSide || appState == "initial") {
50
- return initialAppContextState;
51
- }
52
-
53
- const appReadyState: AppReadyState = {
54
- // TODO read customisation props from the URL
55
- logo: <Logo />,
56
- language: detectLanguage(),
57
- state: appState,
58
- sdk: sidRef.current as SlashID,
59
- };
60
-
61
- return appReadyState;
62
- }, [appState, isClientSide]);
63
-
64
- return (
65
- <ThemeRoot theme="light">
66
- <Sentry.ErrorBoundary
67
- fallback={
68
- <Card>
69
- <Error type="error" />
70
- </Card>
71
- }
72
- >
73
- <AppContext.Provider value={state}>
74
- <TextProvider text={I18N[state.language]}>
75
- <main className={styles.app}>
76
- <Flow />
77
- </main>
78
- </TextProvider>
79
- </AppContext.Provider>
80
- </Sentry.ErrorBoundary>
81
- </ThemeRoot>
82
- );
83
- }
@@ -1,41 +0,0 @@
1
- import { createContext, useContext } from "react";
2
- import { Logo } from "@slashid/react-primitives";
3
- import type { SlashID } from "@slashid/slashid";
4
-
5
- import { type Language } from "../../domain/i18n";
6
-
7
- export type AppState = "initial" | "ready";
8
-
9
- type AppConfig = {
10
- logo: string | React.ReactNode;
11
- language: Language;
12
- };
13
-
14
- export type AppInitialState = AppConfig & {
15
- state: "initial";
16
- sdk: undefined;
17
- };
18
-
19
- export type AppReadyState = AppConfig & {
20
- state: "ready";
21
- sdk: SlashID;
22
- };
23
-
24
- export type AppContextState = AppInitialState | AppReadyState;
25
-
26
- export const initialAppContextState: AppContextState = {
27
- logo: <Logo />,
28
- language: "en",
29
- state: "initial",
30
- sdk: undefined,
31
- };
32
-
33
- export const AppContext = createContext<AppContextState>(
34
- initialAppContextState
35
- );
36
-
37
- export const useAppContext = () => {
38
- const appContext = useContext(AppContext);
39
-
40
- return appContext;
41
- };
@@ -1,15 +0,0 @@
1
- import { publicVariables } from "@slashid/react-primitives";
2
- import { style } from "@vanilla-extract/css";
3
-
4
- export const app = style({
5
- fontFamily: publicVariables.font.fontFamily,
6
- backgroundColor: publicVariables.color.background,
7
- boxSizing: "border-box",
8
- display: "flex",
9
- justifyContent: "center",
10
- alignItems: "center",
11
- width: "100%",
12
- height: "100vh",
13
- padding: 0,
14
- margin: 0,
15
- });
@@ -1 +0,0 @@
1
- export * from "./app.component";
@@ -1,42 +0,0 @@
1
- import { useAppContext } from "../app/app.context";
2
- import { Text } from "../text";
3
- import * as styles from "./card.css";
4
-
5
- export type Props = {
6
- children: React.ReactNode;
7
- footer?: React.ReactNode;
8
- header?: React.ReactNode;
9
- };
10
-
11
- function DefaultHeader() {
12
- const { logo } = useAppContext();
13
-
14
- return <div className={styles.logo}>{logo}</div>;
15
- }
16
-
17
- function DefaultFooter() {
18
- return (
19
- <Text
20
- t="footer.text"
21
- variant={{
22
- size: "xs",
23
- weight: "semibold",
24
- color: "placeholder",
25
- }}
26
- />
27
- );
28
- }
29
-
30
- export function Card({
31
- children,
32
- header = <DefaultHeader />,
33
- footer = <DefaultFooter />,
34
- }: Props) {
35
- return (
36
- <article className={styles.card}>
37
- {header && <header className={styles.header}>{header}</header>}
38
- <div>{children}</div>
39
- {footer && <footer className={styles.footer}>{footer}</footer>}
40
- </article>
41
- );
42
- }
@@ -1,40 +0,0 @@
1
- import { publicVariables, theme } from "@slashid/react-primitives";
2
- import { globalStyle, style } from "@vanilla-extract/css";
3
-
4
- export const card = style({
5
- display: "grid",
6
- gridTemplateRows: "auto 1fr auto",
7
- backgroundColor: publicVariables.color.panel,
8
- width: "100%",
9
- minHeight: "100vh",
10
- padding: "32px 32px 16px 32px",
11
- boxSizing: "border-box",
12
-
13
- "@media": {
14
- "screen and (min-width: 768px)": {
15
- borderRadius: `calc(2 * ${publicVariables.border.radius})`,
16
- width: "465px",
17
- minHeight: "330px",
18
- },
19
- },
20
- });
21
-
22
- export const header = style({
23
- marginBottom: theme.space[1],
24
- });
25
-
26
- export const footer = style({
27
- width: "100%",
28
- textAlign: "center",
29
- marginTop: theme.space[8],
30
- });
31
-
32
- export const logo = style({
33
- width: 32,
34
- height: 32,
35
- });
36
-
37
- globalStyle(`${logo} > svg`, {
38
- height: 32,
39
- width: 32,
40
- });
@@ -1 +0,0 @@
1
- export * from "./card.component";
@@ -1,99 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import * as Sentry from "@sentry/react";
3
- import { Card } from "../card";
4
- import { Initial } from "./flow.initial";
5
- import { Error } from "./flow.error";
6
- import type { Challenges, State, FlowType } from "./flow.types";
7
- import { useAppContext } from "../app/app.context";
8
- import { Progress } from "./flow.progress";
9
- import type { ChallengeListInner } from "@slashid/slashid";
10
- import { Success } from "./flow.success";
11
- import { ensureError } from "./flow.domain";
12
-
13
- function isPasswordRecoveryFlow(challenges: Challenges): boolean {
14
- return challenges.some((challenge) => challenge.type === "password_reset");
15
- }
16
-
17
- function getFlowTypeFromChallenges(challenges: Challenges): FlowType {
18
- if (isPasswordRecoveryFlow(challenges)) {
19
- return "password-recovery";
20
- }
21
-
22
- return "catch-all";
23
- }
24
-
25
- export function Flow() {
26
- const [flowState, setFlowState] = useState<State>({ state: "initial" });
27
- const { sdk, state: appState } = useAppContext();
28
-
29
- useEffect(() => {
30
- if (flowState.state !== "initial") return;
31
-
32
- async function processChallenges() {
33
- if (!sdk) return;
34
- setFlowState({ state: "parsing-url" });
35
-
36
- let challenges: ChallengeListInner[] | null = [];
37
-
38
- try {
39
- challenges = await sdk.getChallengesFromURL();
40
- } catch (e: unknown) {
41
- Sentry.captureException(ensureError(e));
42
- }
43
-
44
- if (!challenges) {
45
- setFlowState({ state: "no-challenges", challenges: null });
46
- return;
47
- }
48
-
49
- const flowType = getFlowTypeFromChallenges(challenges);
50
-
51
- setFlowState({ state: "progress", challenges, flowType });
52
- }
53
-
54
- processChallenges();
55
- }, [appState, flowState.state, sdk]);
56
-
57
- const handleSuccess = () => {
58
- if (flowState.state !== "progress") return;
59
-
60
- setFlowState({
61
- state: "success",
62
- challenges: flowState.challenges,
63
- flowType: flowState.flowType,
64
- });
65
- };
66
-
67
- const handleError = ({ error }: { error: Error }) => {
68
- if (flowState.state !== "progress") return;
69
-
70
- setFlowState({
71
- state: "error",
72
- challenges: flowState.challenges,
73
- flowType: flowState.flowType,
74
- error,
75
- });
76
- };
77
-
78
- return (
79
- <Card>
80
- {(appState !== "ready" || flowState.state === "parsing-url") && (
81
- <Initial />
82
- )}
83
- {appState === "ready" && (
84
- <>
85
- {flowState.state === "progress" && (
86
- <Progress
87
- onSuccess={handleSuccess}
88
- onError={handleError}
89
- flowType={flowState.flowType}
90
- />
91
- )}
92
- {flowState.state === "no-challenges" && <Error type="warning" />}
93
- {flowState.state === "success" && <Success />}
94
- {flowState.state === "error" && <Error type="error" />}
95
- </>
96
- )}
97
- </Card>
98
- );
99
- }
@@ -1,20 +0,0 @@
1
- import { publicVariables, theme } from "@slashid/react-primitives";
2
- import { style } from "@vanilla-extract/css";
3
-
4
- export const formInputs = style({
5
- margin: "24px 0",
6
- });
7
-
8
- export const passwordRecoveryPrompt = style({
9
- display: "flex",
10
- alignItems: "baseline",
11
- marginTop: "8px",
12
- });
13
-
14
- export const errorMessage = style({
15
- display: "block",
16
- marginTop: theme.space[2],
17
- color: publicVariables.color.error,
18
- fontWeight: "600",
19
- lineHeight: "122%",
20
- });
@@ -1,18 +0,0 @@
1
- /**
2
- * Ensure that a valid Error instance is returned, since in JS you can throw anything.
3
- */
4
- export function ensureError(value: unknown): Error {
5
- if (value instanceof Error) return value;
6
-
7
- let stringified = "[Unable to stringify the thrown value]";
8
- try {
9
- stringified = JSON.stringify(value);
10
- } catch {
11
- // ignore
12
- }
13
-
14
- const error = new Error(
15
- `This value was thrown as is, not through an Error: ${stringified}`
16
- );
17
- return error;
18
- }
@@ -1,32 +0,0 @@
1
- import { Circle, Exclamation, Stack } from "@slashid/react-primitives";
2
- import { Text } from "../text";
3
-
4
- export type ErrorType = "warning" | "error";
5
-
6
- function ErrorIcon({ type }: { type: ErrorType }) {
7
- return (
8
- <Circle variant={type === "warning" ? "blue" : "red"} shouldAnimate={false}>
9
- <Exclamation />
10
- </Circle>
11
- );
12
- }
13
-
14
- export function Error({ type }: { type: ErrorType }) {
15
- return (
16
- <>
17
- <Stack space="0.25">
18
- <Text
19
- as="h1"
20
- variant={{ size: "2xl-title", weight: "bold" }}
21
- t="error.title"
22
- />
23
- <Text
24
- as="h2"
25
- t="error.detail"
26
- variant={{ color: "contrast", weight: "semibold" }}
27
- />
28
- </Stack>
29
- <ErrorIcon type={type} />
30
- </>
31
- );
32
- }
@@ -1,14 +0,0 @@
1
- import { Skeleton, Stack } from "@slashid/react-primitives";
2
- import { Loader } from "./flow.loader";
3
-
4
- export function Initial() {
5
- return (
6
- <>
7
- <Stack space="2">
8
- <Skeleton width={"75%"} height={24} />
9
- <Skeleton width={"50%"} height={16} />
10
- </Stack>
11
- <Loader />
12
- </>
13
- );
14
- }
@@ -1,9 +0,0 @@
1
- import { Circle, Spinner } from "@slashid/react-primitives";
2
-
3
- export function Loader() {
4
- return (
5
- <Circle>
6
- <Spinner />
7
- </Circle>
8
- );
9
- }
@@ -1,119 +0,0 @@
1
- import { useEffect } from "react";
2
- import * as Sentry from "@sentry/react";
3
- import { Stack } from "@slashid/react-primitives";
4
-
5
- import { Loader } from "./flow.loader";
6
- import type { FlowType } from "./flow.types";
7
- import { Text } from "../text";
8
- import { useAppContext } from "../app/app.context";
9
- import { Recover } from "./flow.recover";
10
-
11
- type SlashIDErrorMessage = { message: string };
12
- class SlashIDError extends Error {
13
- errors: SlashIDErrorMessage[];
14
-
15
- constructor(errors: SlashIDErrorMessage[]) {
16
- super(errors.length > 0 ? errors[0].message : "Unknown SlashID error");
17
- this.errors = errors;
18
- }
19
- }
20
-
21
- function isSlashIDError(e: unknown): e is SlashIDError {
22
- if (
23
- typeof e === "object" &&
24
- e !== null &&
25
- "errors" in e &&
26
- Array.isArray(e.errors)
27
- ) {
28
- return true;
29
- }
30
-
31
- return false;
32
- }
33
-
34
- function ensureError(value: unknown): Error {
35
- if (value instanceof Error) return value;
36
-
37
- // special case - sometimes the core SDK throws a non-error object
38
- if (isSlashIDError(value)) {
39
- const error = new SlashIDError(value.errors);
40
- return error;
41
- }
42
-
43
- let stringified = "[Unable to stringify the thrown value]";
44
- try {
45
- stringified = JSON.stringify(value);
46
- } catch {
47
- // ignore
48
- }
49
-
50
- const error = new Error(
51
- `This value was thrown as is, not through an Error: ${stringified}`
52
- );
53
- return error;
54
- }
55
-
56
- export type Props = {
57
- flowType: FlowType;
58
- onSuccess: () => void;
59
- onError: ({ error }: { error: Error }) => void;
60
- };
61
-
62
- export function Progress({ onSuccess, onError, flowType }: Props) {
63
- const { sdk } = useAppContext();
64
-
65
- useEffect(() => {
66
- if (!sdk) return;
67
-
68
- async function authenticate() {
69
- try {
70
- await sdk?.getUserFromURL();
71
- onSuccess();
72
- } catch (e: unknown) {
73
- const safeError = ensureError(e);
74
- Sentry.captureException(safeError);
75
- onError({ error: safeError });
76
- }
77
- }
78
-
79
- function handlePasswordResetEvent() {
80
- console.log("Password reset - input ready");
81
- }
82
-
83
- if (flowType === "password-recovery") {
84
- console.log("Subscribed");
85
- sdk.subscribe("passwordResetReady", handlePasswordResetEvent);
86
- }
87
-
88
- authenticate();
89
-
90
- return () => {
91
- if (flowType === "password-recovery") {
92
- console.log("Cleaned up");
93
- sdk.unsubscribe("passwordResetReady", handlePasswordResetEvent);
94
- }
95
- };
96
- }, [flowType, onError, onSuccess, sdk]);
97
-
98
- if (flowType === "password-recovery") {
99
- return <Recover />;
100
- }
101
-
102
- return (
103
- <>
104
- <Stack space="0.25">
105
- <Text
106
- as="h1"
107
- variant={{ size: "2xl-title", weight: "bold" }}
108
- t="initial.title"
109
- />
110
- <Text
111
- variant={{ color: "contrast", weight: "semibold" }}
112
- as="h2"
113
- t="initial.details"
114
- />
115
- </Stack>
116
- <Loader />
117
- </>
118
- );
119
- }