@indietabletop/appkit 6.1.6 → 7.0.0-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/dist/AppConfig/AppConfig.d.ts +29 -0
- package/dist/AuthCard/AuthCard.d.ts +10 -0
- package/dist/AuthCard/AuthCard.stories.d.ts +34 -0
- package/dist/AuthCard/style.css.d.ts +23 -0
- package/dist/DialogTrigger/index.d.ts +13 -0
- package/dist/DocumentTitle/DocumentTitle.d.ts +3 -0
- package/dist/EnumMapper.d.ts +25 -0
- package/dist/ExternalLink.d.ts +3 -0
- package/dist/FullscreenDismissBlocker.d.ts +5 -0
- package/{lib/HistoryState.ts → dist/HistoryState.d.ts} +2 -5
- package/dist/IndieTabletopClubLogo.d.ts +7 -0
- package/dist/IndieTabletopClubSymbol.d.ts +7 -0
- package/dist/InfoPage/index.d.ts +8 -0
- package/dist/InfoPage/pages.d.ts +2 -0
- package/dist/InfoPage/style.css.d.ts +5 -0
- package/dist/Letterhead/index.d.ts +19 -0
- package/dist/Letterhead/stories.d.ts +13 -0
- package/dist/Letterhead/style.css.d.ts +46 -0
- package/dist/LetterheadForm/LetterheadReadonlyTextField.stories.d.ts +17 -0
- package/dist/LetterheadForm/LetterheadSubmitError.stories.d.ts +11 -0
- package/dist/LetterheadForm/LetterheadTextField.stories.d.ts +336 -0
- package/dist/LetterheadForm/index.d.ts +44 -0
- package/dist/LetterheadForm/style.css.d.ts +8 -0
- package/dist/LoadingIndicator.d.ts +3 -0
- package/dist/MiddotSeparated/MiddotSeparated.d.ts +8 -0
- package/dist/MiddotSeparated/MiddotSeparated.stories.d.ts +586 -0
- package/dist/MiddotSeparated/style.css.d.ts +1 -0
- package/dist/ModalDialog/index.d.ts +12 -0
- package/dist/ModalDialog/style.css.d.ts +58 -0
- package/dist/ModernIDB/Cursor.d.ts +56 -0
- package/dist/ModernIDB/ModernIDB.d.ts +66 -0
- package/dist/ModernIDB/ModernIDBError.d.ts +3 -0
- package/dist/ModernIDB/ObjectStore.d.ts +112 -0
- package/dist/ModernIDB/ObjectStoreIndex.d.ts +53 -0
- package/dist/ModernIDB/Transaction.d.ts +16 -0
- package/dist/ModernIDB/VersionChangeManager.d.ts +30 -0
- package/dist/ModernIDB/bindings/factory.d.ts +12 -0
- package/dist/ModernIDB/bindings/index.d.ts +2 -0
- package/{lib/ModernIDB/bindings/types.ts → dist/ModernIDB/bindings/types.d.ts} +13 -32
- package/dist/ModernIDB/bindings/utils.d.ts +2 -0
- package/dist/ModernIDB/index.d.ts +10 -0
- package/dist/ModernIDB/types.d.ts +88 -0
- package/dist/ModernIDB/utils.d.ts +4 -0
- package/dist/QRCode/QRCode.d.ts +7 -0
- package/dist/QRCode/QRCode.stories.d.ts +33 -0
- package/dist/QRCode/style.css.d.ts +4 -0
- package/dist/ReleaseInfo/index.d.ts +5 -0
- package/dist/RulesetResolver.d.ts +87 -0
- package/dist/SafariCheck/SafariCheck.d.ts +23 -0
- package/dist/SafariCheck/SafariCheck.stories.d.ts +73 -0
- package/dist/SafariCheck/style.css.d.ts +17 -0
- package/dist/ServiceWorkerHandler.d.ts +11 -0
- package/dist/ShareButton/ShareButton.d.ts +57 -0
- package/dist/ShareButton/ShareButton.stories.d.ts +1577 -0
- package/dist/ShareButton/test.css.d.ts +1 -0
- package/dist/SubscribeCard/LetterheadInfoCard.d.ts +2 -0
- package/dist/SubscribeCard/SubscribeByEmailCard.d.ts +24 -0
- package/dist/SubscribeCard/SubscribeByEmailCard.stories.d.ts +10 -0
- package/dist/SubscribeCard/SubscribeByPledgeCard.d.ts +36 -0
- package/dist/SubscribeCard/SubscribeByPledgeCard.stories.d.ts +65 -0
- package/dist/SubscribeCard/style.css.d.ts +4 -0
- package/dist/account/AccountIssueView.d.ts +3 -0
- package/dist/account/AlreadyLoggedInView.d.ts +5 -0
- package/dist/account/CurrentUserFetcher.d.ts +20 -0
- package/dist/account/CurrentUserFetcher.stories.d.ts +136 -0
- package/dist/account/FailureFallbackView.d.ts +1 -0
- package/dist/account/JoinCard.d.ts +14 -0
- package/dist/account/JoinCard.stories.d.ts +143 -0
- package/dist/account/LoadingView.d.ts +1 -0
- package/dist/account/LoginCard.d.ts +39 -0
- package/dist/account/LoginCard.stories.d.ts +217 -0
- package/dist/account/LoginView.d.ts +10 -0
- package/dist/account/NoConnectionView.d.ts +4 -0
- package/dist/account/PasswordResetCard.d.ts +15 -0
- package/dist/account/PasswordResetCard.stories.d.ts +128 -0
- package/dist/account/UserMismatchView.d.ts +6 -0
- package/dist/account/VerifyPage.d.ts +13 -0
- package/dist/account/style.css.d.ts +10 -0
- package/{lib/account/types.ts → dist/account/types.d.ts} +3 -6
- package/dist/account/useFetchCurrentUser.d.ts +28 -0
- package/dist/account/useRedirectPath.d.ts +6 -0
- package/dist/animations.css.d.ts +3 -0
- package/dist/append-copy-to-text.d.ts +10 -0
- package/dist/append-copy-to-text.test.d.ts +1 -0
- package/dist/appkit.css +1 -0
- package/dist/appkit.js +10692 -0
- package/dist/async-op.d.ts +101 -0
- package/dist/atomic.css.d.ts +6 -0
- package/{lib/caught-value.ts → dist/caught-value.d.ts} +1 -11
- package/{lib/class-names.ts → dist/class-names.d.ts} +6 -17
- package/dist/client.d.ts +424 -0
- package/dist/common.css.d.ts +5 -0
- package/dist/copyrightRange.d.ts +1 -0
- package/dist/copyrightRange.test.d.ts +1 -0
- package/dist/createSafeStorage.d.ts +34 -0
- package/dist/failureMessages.d.ts +20 -0
- package/dist/failureMessages.test.d.ts +1 -0
- package/dist/form/FormSubmitButton.d.ts +17 -0
- package/dist/form/SubmitErrorAlert.d.ts +5 -0
- package/dist/form/style.css.d.ts +3 -0
- package/dist/globals.css.d.ts +0 -0
- package/dist/groupBy.d.ts +1 -0
- package/dist/groupBy.test.d.ts +1 -0
- package/dist/hrefs.d.ts +32 -0
- package/dist/hrefs.test.d.ts +1 -0
- package/dist/idToDate.d.ts +5 -0
- package/dist/idToDate.test.d.ts +1 -0
- package/dist/ids.d.ts +1 -0
- package/dist/ids.test.d.ts +1 -0
- package/dist/index.d.ts +64 -0
- package/dist/internal.css.d.ts +2 -0
- package/dist/mailto.d.ts +8 -0
- package/dist/mailto.test.d.ts +1 -0
- package/dist/media.d.ts +39 -0
- package/dist/random.d.ts +3 -0
- package/dist/result/swr.d.ts +4 -0
- package/{lib/sleep.ts → dist/sleep.d.ts} +1 -3
- package/dist/store/index.d.ts +237 -0
- package/dist/store/store.d.ts +144 -0
- package/dist/store/types.d.ts +49 -0
- package/dist/store/utils.d.ts +10 -0
- package/dist/storybook/decorators.d.ts +3 -0
- package/dist/structs.d.ts +1 -0
- package/{lib/typeguards.ts → dist/typeguards.d.ts} +1 -3
- package/dist/typeguards.test.d.ts +1 -0
- package/{lib/types.ts → dist/types.d.ts} +12 -23
- package/dist/unique.d.ts +10 -0
- package/dist/unique.test.d.ts +1 -0
- package/dist/use-async-op.d.ts +6 -0
- package/dist/use-document-background-color.d.ts +4 -0
- package/dist/use-form.d.ts +29 -0
- package/dist/use-is-installed.d.ts +8 -0
- package/dist/use-media-query.d.ts +1 -0
- package/dist/use-reverting-state.d.ts +5 -0
- package/dist/use-scroll-restoration.d.ts +25 -0
- package/dist/useEnsureValue.d.ts +6 -0
- package/dist/useInvokeClient.d.ts +25 -0
- package/dist/useIsVisible.d.ts +4 -0
- package/dist/utm.d.ts +58 -0
- package/dist/utm.test.d.ts +1 -0
- package/dist/validations.d.ts +3 -0
- package/dist/vars.css.d.ts +10 -0
- package/package.json +12 -5
- package/lib/AppConfig/AppConfig.tsx +0 -61
- package/lib/AuthCard/AuthCard.stories.ts +0 -34
- package/lib/AuthCard/AuthCard.tsx +0 -64
- package/lib/AuthCard/style.css.ts +0 -49
- package/lib/DialogTrigger/index.tsx +0 -36
- package/lib/DocumentTitle/DocumentTitle.tsx +0 -10
- package/lib/EnumMapper.ts +0 -50
- package/lib/ExternalLink.tsx +0 -10
- package/lib/FullscreenDismissBlocker.tsx +0 -23
- package/lib/IndieTabletopClubLogo.tsx +0 -44
- package/lib/IndieTabletopClubSymbol.tsx +0 -37
- package/lib/InfoPage/index.tsx +0 -46
- package/lib/InfoPage/pages.tsx +0 -36
- package/lib/InfoPage/style.css.ts +0 -36
- package/lib/Letterhead/index.tsx +0 -85
- package/lib/Letterhead/stories.tsx +0 -41
- package/lib/Letterhead/style.css.ts +0 -152
- package/lib/LetterheadForm/LetterheadReadonlyTextField.stories.tsx +0 -17
- package/lib/LetterheadForm/LetterheadSubmitError.stories.tsx +0 -19
- package/lib/LetterheadForm/LetterheadTextField.stories.tsx +0 -19
- package/lib/LetterheadForm/index.tsx +0 -137
- package/lib/LetterheadForm/style.css.ts +0 -89
- package/lib/LoadingIndicator.tsx +0 -40
- package/lib/MiddotSeparated/MiddotSeparated.stories.ts +0 -26
- package/lib/MiddotSeparated/MiddotSeparated.tsx +0 -26
- package/lib/MiddotSeparated/style.css.ts +0 -10
- package/lib/ModalDialog/index.tsx +0 -28
- package/lib/ModalDialog/style.css.ts +0 -88
- package/lib/ModernIDB/Cursor.ts +0 -91
- package/lib/ModernIDB/ModernIDB.ts +0 -337
- package/lib/ModernIDB/ModernIDBError.ts +0 -9
- package/lib/ModernIDB/ObjectStore.ts +0 -195
- package/lib/ModernIDB/ObjectStoreIndex.ts +0 -102
- package/lib/ModernIDB/README.md +0 -9
- package/lib/ModernIDB/Transaction.ts +0 -40
- package/lib/ModernIDB/VersionChangeManager.ts +0 -57
- package/lib/ModernIDB/bindings/factory.tsx +0 -165
- package/lib/ModernIDB/bindings/index.ts +0 -2
- package/lib/ModernIDB/bindings/utils.tsx +0 -32
- package/lib/ModernIDB/index.ts +0 -10
- package/lib/ModernIDB/types.ts +0 -120
- package/lib/ModernIDB/utils.ts +0 -51
- package/lib/QRCode/QRCode.stories.tsx +0 -41
- package/lib/QRCode/QRCode.tsx +0 -54
- package/lib/QRCode/style.css.ts +0 -23
- package/lib/ReleaseInfo/index.tsx +0 -29
- package/lib/RulesetResolver.ts +0 -214
- package/lib/SafariCheck/SafariCheck.stories.tsx +0 -99
- package/lib/SafariCheck/SafariCheck.tsx +0 -273
- package/lib/SafariCheck/addToDock.svg +0 -13
- package/lib/SafariCheck/addToHomeScreen.svg +0 -12
- package/lib/SafariCheck/safari.svg +0 -32
- package/lib/SafariCheck/shareIcon.svg +0 -11
- package/lib/SafariCheck/style.css.ts +0 -106
- package/lib/ServiceWorkerHandler.tsx +0 -53
- package/lib/ShareButton/ShareButton.stories.tsx +0 -58
- package/lib/ShareButton/ShareButton.tsx +0 -153
- package/lib/ShareButton/test.css.ts +0 -3
- package/lib/SubscribeCard/LetterheadInfoCard.tsx +0 -23
- package/lib/SubscribeCard/SubscribeByEmailCard.stories.tsx +0 -69
- package/lib/SubscribeCard/SubscribeByEmailCard.tsx +0 -183
- package/lib/SubscribeCard/SubscribeByPledgeCard.stories.tsx +0 -133
- package/lib/SubscribeCard/SubscribeByPledgeCard.tsx +0 -127
- package/lib/SubscribeCard/style.css.ts +0 -14
- package/lib/account/AccountIssueView.tsx +0 -44
- package/lib/account/AlreadyLoggedInView.tsx +0 -47
- package/lib/account/CurrentUserFetcher.stories.tsx +0 -292
- package/lib/account/CurrentUserFetcher.tsx +0 -118
- package/lib/account/FailureFallbackView.tsx +0 -36
- package/lib/account/JoinCard.stories.tsx +0 -257
- package/lib/account/JoinCard.tsx +0 -301
- package/lib/account/LoadingView.tsx +0 -14
- package/lib/account/LoginCard.stories.tsx +0 -288
- package/lib/account/LoginCard.tsx +0 -100
- package/lib/account/LoginView.tsx +0 -151
- package/lib/account/NoConnectionView.tsx +0 -34
- package/lib/account/PasswordResetCard.stories.tsx +0 -242
- package/lib/account/PasswordResetCard.tsx +0 -296
- package/lib/account/UserMismatchView.tsx +0 -62
- package/lib/account/VerifyPage.tsx +0 -195
- package/lib/account/style.css.ts +0 -57
- package/lib/account/useFetchCurrentUser.tsx +0 -63
- package/lib/account/useRedirectPath.ts +0 -21
- package/lib/animations.css.ts +0 -17
- package/lib/append-copy-to-text.ts +0 -35
- package/lib/async-op.ts +0 -286
- package/lib/atomic.css.ts +0 -11
- package/lib/client.ts +0 -662
- package/lib/common.css.ts +0 -48
- package/lib/copyrightRange.ts +0 -10
- package/lib/createSafeStorage.ts +0 -91
- package/lib/failureMessages.ts +0 -108
- package/lib/form/FormSubmitButton.tsx +0 -58
- package/lib/form/SubmitErrorAlert.tsx +0 -21
- package/lib/form/style.css.ts +0 -9
- package/lib/globals.css.ts +0 -62
- package/lib/groupBy.ts +0 -25
- package/lib/hrefs.ts +0 -48
- package/lib/idToDate.ts +0 -8
- package/lib/ids.ts +0 -6
- package/lib/index.ts +0 -71
- package/lib/internal.css.ts +0 -10
- package/lib/mailto.ts +0 -40
- package/lib/media.ts +0 -50
- package/lib/random.ts +0 -19
- package/lib/result/swr.ts +0 -18
- package/lib/store/index.tsx +0 -241
- package/lib/store/store.ts +0 -479
- package/lib/store/types.ts +0 -45
- package/lib/store/utils.ts +0 -54
- package/lib/storybook/decorators.tsx +0 -10
- package/lib/structs.ts +0 -3
- package/lib/unique.ts +0 -24
- package/lib/use-async-op.ts +0 -16
- package/lib/use-document-background-color.ts +0 -16
- package/lib/use-form.ts +0 -78
- package/lib/use-is-installed.ts +0 -17
- package/lib/use-media-query.ts +0 -21
- package/lib/use-reverting-state.ts +0 -32
- package/lib/use-scroll-restoration.ts +0 -99
- package/lib/useEnsureValue.ts +0 -31
- package/lib/useInvokeClient.ts +0 -54
- package/lib/useIsVisible.ts +0 -27
- package/lib/utm.ts +0 -92
- package/lib/validations.ts +0 -25
- package/lib/vars.css.ts +0 -13
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { cx } from "../class-names.ts";
|
|
2
|
-
import { Letterhead } from "../Letterhead/index.tsx";
|
|
3
|
-
import { LoadingIndicator } from "../LoadingIndicator.tsx";
|
|
4
|
-
import { loadingView } from "./style.css.ts";
|
|
5
|
-
|
|
6
|
-
export function LoadingView() {
|
|
7
|
-
return (
|
|
8
|
-
<Letterhead>
|
|
9
|
-
<div {...cx(loadingView.container)}>
|
|
10
|
-
<LoadingIndicator />
|
|
11
|
-
</div>
|
|
12
|
-
</Letterhead>
|
|
13
|
-
);
|
|
14
|
-
}
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import { http, HttpResponse } from "msw";
|
|
2
|
-
import { fn } from "storybook/test";
|
|
3
|
-
import preview from "../../.storybook/preview.tsx";
|
|
4
|
-
import { sleep } from "../sleep.ts";
|
|
5
|
-
import type { CurrentUser, SessionInfo } from "../types.ts";
|
|
6
|
-
import { LoginCard } from "./LoginCard.tsx";
|
|
7
|
-
|
|
8
|
-
function createMocks(options?: { responseSpeed?: number }) {
|
|
9
|
-
const simulateNetwork = () => sleep(options?.responseSpeed ?? 2000);
|
|
10
|
-
|
|
11
|
-
const john: CurrentUser = {
|
|
12
|
-
id: "john",
|
|
13
|
-
email: "john@example.com",
|
|
14
|
-
isVerified: true,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const mary: CurrentUser = {
|
|
18
|
-
id: "mary",
|
|
19
|
-
email: "mary@example.com",
|
|
20
|
-
isVerified: true,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const sessionInfo: SessionInfo = {
|
|
24
|
-
createdTs: 123,
|
|
25
|
-
expiresTs: 123,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
data: { john, mary },
|
|
30
|
-
handlers: {
|
|
31
|
-
refreshTokens: {
|
|
32
|
-
failed: () => {
|
|
33
|
-
return http.post(
|
|
34
|
-
"http://mock.api/v1/sessions/access-tokens",
|
|
35
|
-
async () => {
|
|
36
|
-
await simulateNetwork();
|
|
37
|
-
return HttpResponse.text("Refresh token expired or missing", {
|
|
38
|
-
status: 401,
|
|
39
|
-
});
|
|
40
|
-
},
|
|
41
|
-
);
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
getCurrentUser: {
|
|
46
|
-
success: (currentUser: CurrentUser) => {
|
|
47
|
-
return http.get("http://mock.api/v1/users/me", async () => {
|
|
48
|
-
await simulateNetwork();
|
|
49
|
-
return HttpResponse.json(currentUser);
|
|
50
|
-
});
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Cookie is valid, but user doesn't exist any more. This can happen
|
|
55
|
-
* after user deletion.
|
|
56
|
-
*/
|
|
57
|
-
notFound: () => {
|
|
58
|
-
return http.get("http://mock.api/v1/users/me", async () => {
|
|
59
|
-
await simulateNetwork();
|
|
60
|
-
return HttpResponse.text("User not found", { status: 404 });
|
|
61
|
-
});
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
noConnection: () => {
|
|
65
|
-
return http.get("http://mock.api/v1/users/me", async () => {
|
|
66
|
-
return HttpResponse.error();
|
|
67
|
-
});
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
unknownFailure: () => {
|
|
71
|
-
return http.get("http://mock.api/v1/users/me", async () => {
|
|
72
|
-
await simulateNetwork();
|
|
73
|
-
return HttpResponse.text("Internal server error", { status: 500 });
|
|
74
|
-
});
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Auth cookies no longer valid to make this request.
|
|
79
|
-
*/
|
|
80
|
-
notAuthenticated: () => {
|
|
81
|
-
return http.get("http://mock.api/v1/users/me", async () => {
|
|
82
|
-
await simulateNetwork();
|
|
83
|
-
return HttpResponse.text("Not authenticated", { status: 401 });
|
|
84
|
-
});
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
createNewSession: {
|
|
89
|
-
success: (currentUser: CurrentUser) => {
|
|
90
|
-
return http.post("http://mock.api/v1/sessions", async () => {
|
|
91
|
-
await simulateNetwork();
|
|
92
|
-
return HttpResponse.json({ currentUser, sessionInfo });
|
|
93
|
-
});
|
|
94
|
-
},
|
|
95
|
-
|
|
96
|
-
invalidCredentials: () => {
|
|
97
|
-
return http.post("http://mock.api/v1/sessions", async () => {
|
|
98
|
-
await simulateNetwork();
|
|
99
|
-
return HttpResponse.text("Credentials do not match", {
|
|
100
|
-
status: 401,
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
userNotFound: () => {
|
|
106
|
-
return http.post("http://mock.api/v1/sessions", async () => {
|
|
107
|
-
await simulateNetwork();
|
|
108
|
-
return HttpResponse.text("User not found", { status: 404 });
|
|
109
|
-
});
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
unknownFailure: () => {
|
|
113
|
-
return http.post("http://mock.api/v1/sessions", async () => {
|
|
114
|
-
await simulateNetwork();
|
|
115
|
-
return HttpResponse.text("Internal server error", { status: 500 });
|
|
116
|
-
});
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const { data, handlers } = createMocks({ responseSpeed: 700 });
|
|
124
|
-
|
|
125
|
-
const meta = preview.meta({
|
|
126
|
-
title: "Account/Login Card",
|
|
127
|
-
component: LoginCard,
|
|
128
|
-
tags: ["autodocs"],
|
|
129
|
-
args: {
|
|
130
|
-
description: "Log in to Indie Tabletop Club to enable backup & sync.",
|
|
131
|
-
defaultValues: {},
|
|
132
|
-
onLogin: fn(),
|
|
133
|
-
},
|
|
134
|
-
parameters: {
|
|
135
|
-
msw: {
|
|
136
|
-
handlers: {
|
|
137
|
-
refreshTokens: handlers.refreshTokens.failed(),
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* The majority case where no user is stored locally, proactive user session
|
|
145
|
-
* check returns 401, and subsequently correct credentials are provided.
|
|
146
|
-
*/
|
|
147
|
-
export const Default = meta.story({
|
|
148
|
-
parameters: {
|
|
149
|
-
msw: {
|
|
150
|
-
handlers: {
|
|
151
|
-
getCurrentUser: handlers.getCurrentUser.notAuthenticated(),
|
|
152
|
-
createNewSession: handlers.createNewSession.success(data.john),
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Similar to the default case, but invalid credentials are provided to when
|
|
160
|
-
* attempting to create a new session.
|
|
161
|
-
*/
|
|
162
|
-
export const InvalidCredentialsOnSubmit = meta.story({
|
|
163
|
-
parameters: {
|
|
164
|
-
msw: {
|
|
165
|
-
handlers: {
|
|
166
|
-
getCurrentUser: handlers.getCurrentUser.notAuthenticated(),
|
|
167
|
-
createNewSession: handlers.createNewSession.invalidCredentials(),
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Similar to the default case, but when credentials are provided, an account
|
|
175
|
-
* email is used that is not currently in the database.
|
|
176
|
-
*/
|
|
177
|
-
export const UserNotFoundOnSubmit = meta.story({
|
|
178
|
-
parameters: {
|
|
179
|
-
msw: {
|
|
180
|
-
handlers: {
|
|
181
|
-
getCurrentUser: handlers.getCurrentUser.notAuthenticated(),
|
|
182
|
-
createNewSession: handlers.createNewSession.userNotFound(),
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Similar to the default case, but the session creation call returns an error
|
|
190
|
-
* that doesn't have a specific meaning in the context of the login page.
|
|
191
|
-
*/
|
|
192
|
-
export const UnknownFailureOnSubmit = meta.story({
|
|
193
|
-
parameters: {
|
|
194
|
-
msw: {
|
|
195
|
-
handlers: {
|
|
196
|
-
getCurrentUser: handlers.getCurrentUser.notAuthenticated(),
|
|
197
|
-
createNewSession: handlers.createNewSession.unknownFailure(),
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* A case when user is stored locally, but their server session has expired.
|
|
205
|
-
*/
|
|
206
|
-
export const ReauthenticateSession = meta.story({
|
|
207
|
-
parameters: {
|
|
208
|
-
msw: {
|
|
209
|
-
handlers: {
|
|
210
|
-
getCurrentUser: handlers.getCurrentUser.notAuthenticated(),
|
|
211
|
-
createNewSession: handlers.createNewSession.success(data.john),
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* The user is already stored in the app, and proactive user-session check
|
|
219
|
-
* returns the same user (based on ID).
|
|
220
|
-
*
|
|
221
|
-
* The user is directed to app without any further steps.
|
|
222
|
-
*/
|
|
223
|
-
export const AlreadyLoggedIn = meta.story({
|
|
224
|
-
parameters: {
|
|
225
|
-
msw: {
|
|
226
|
-
handlers: {
|
|
227
|
-
getCurrentUser: handlers.getCurrentUser.success(data.john),
|
|
228
|
-
},
|
|
229
|
-
},
|
|
230
|
-
},
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* A user is provided, and proactive user session check returns a different
|
|
235
|
-
* user. This can happen when different users log into separate apps with
|
|
236
|
-
* different credentials.
|
|
237
|
-
*/
|
|
238
|
-
export const UserMismatch = meta.story({
|
|
239
|
-
parameters: {
|
|
240
|
-
msw: {
|
|
241
|
-
handlers: {
|
|
242
|
-
getCurrentUser: handlers.getCurrentUser.success(data.mary),
|
|
243
|
-
},
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* During the proactive user session check, the user is reportd as not found.
|
|
250
|
-
* This means that the tokens are still valid, but the user DB entity is gone.
|
|
251
|
-
* This can happen if a user closed their account.
|
|
252
|
-
*/
|
|
253
|
-
export const UserNotFound = meta.story({
|
|
254
|
-
parameters: {
|
|
255
|
-
msw: {
|
|
256
|
-
handlers: {
|
|
257
|
-
getCurrentUser: handlers.getCurrentUser.notFound(),
|
|
258
|
-
},
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* The proactive user session check has failed due to connection issues.
|
|
265
|
-
*/
|
|
266
|
-
export const NoConnection = meta.story({
|
|
267
|
-
parameters: {
|
|
268
|
-
msw: {
|
|
269
|
-
handlers: {
|
|
270
|
-
getCurrentUser: handlers.getCurrentUser.noConnection(),
|
|
271
|
-
},
|
|
272
|
-
},
|
|
273
|
-
},
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* The proactive user session check has failed due to an error that doesn't
|
|
278
|
-
* carry any special meaning.
|
|
279
|
-
*/
|
|
280
|
-
export const UnknownFailure = meta.story({
|
|
281
|
-
parameters: {
|
|
282
|
-
msw: {
|
|
283
|
-
handlers: {
|
|
284
|
-
getCurrentUser: handlers.getCurrentUser.unknownFailure(),
|
|
285
|
-
},
|
|
286
|
-
},
|
|
287
|
-
},
|
|
288
|
-
});
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { type ReactNode } from "react";
|
|
2
|
-
import { useCurrentUser } from "../store/index.tsx";
|
|
3
|
-
import { AccountIssueView } from "./AccountIssueView.tsx";
|
|
4
|
-
import { AlreadyLoggedInView } from "./AlreadyLoggedInView.tsx";
|
|
5
|
-
import { FailureFallbackView } from "./FailureFallbackView.tsx";
|
|
6
|
-
import { LoadingView } from "./LoadingView.tsx";
|
|
7
|
-
import { LoginView } from "./LoginView.tsx";
|
|
8
|
-
import { NoConnectionView } from "./NoConnectionView.tsx";
|
|
9
|
-
import type { AuthEventHandler, DefaultFormValues } from "./types.ts";
|
|
10
|
-
import { useFetchCurrentUser } from "./useFetchCurrentUser.tsx";
|
|
11
|
-
import { UserMismatchView } from "./UserMismatchView.tsx";
|
|
12
|
-
|
|
13
|
-
export type LoginCardProps = {
|
|
14
|
-
/**
|
|
15
|
-
* A description that will appear in the default login case (i.e. when an
|
|
16
|
-
* unauthenticated user is prompted to log in).
|
|
17
|
-
*
|
|
18
|
-
* This should reinforce to the user the benefits that they are going to
|
|
19
|
-
* get by signing in. Every app has slightly different capabilities, so this
|
|
20
|
-
* should be tailored for each individual app.
|
|
21
|
-
*/
|
|
22
|
-
description: ReactNode;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Default values for the login form.
|
|
26
|
-
*
|
|
27
|
-
* You might want to provide a value from history state or query param, so
|
|
28
|
-
* that if a user jumps between multiple pages with email field, the email
|
|
29
|
-
* address is maintained across these locations.
|
|
30
|
-
*/
|
|
31
|
-
defaultValues?: DefaultFormValues;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Called when the login action succeeds.
|
|
35
|
-
*
|
|
36
|
-
* If no handler is provided, the component will will navigate to the
|
|
37
|
-
* dashboard (as determined by `appConfig.hrefs.dashboard()` return value),
|
|
38
|
-
* or a location provided in `redirectTo` query param if it is a valid
|
|
39
|
-
* local path.
|
|
40
|
-
*/
|
|
41
|
-
onLogin?: AuthEventHandler;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Allows the user to log into Indie Tabletop Club.
|
|
46
|
-
*
|
|
47
|
-
* Will automatically use the `redirectTo` query param value as the redirect
|
|
48
|
-
* location after successful login.
|
|
49
|
-
*
|
|
50
|
-
* Otherwise, the user will be redirected to the app's dashboard.
|
|
51
|
-
*/
|
|
52
|
-
export function LoginCard(props: LoginCardProps) {
|
|
53
|
-
const currentUser = useCurrentUser();
|
|
54
|
-
const { result, latestAttemptTs, reload } = useFetchCurrentUser();
|
|
55
|
-
|
|
56
|
-
return result.unpack(
|
|
57
|
-
(serverUser) => {
|
|
58
|
-
if (currentUser && currentUser.id !== serverUser.id) {
|
|
59
|
-
return (
|
|
60
|
-
<UserMismatchView
|
|
61
|
-
serverUser={serverUser}
|
|
62
|
-
localUser={currentUser}
|
|
63
|
-
reload={reload}
|
|
64
|
-
/>
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return <AlreadyLoggedInView currentUser={serverUser} reload={reload} />;
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
(failure) => {
|
|
72
|
-
if (failure.type === "API_ERROR") {
|
|
73
|
-
if (failure.code === 401) {
|
|
74
|
-
return (
|
|
75
|
-
<LoginView {...props} currentUser={currentUser} reload={reload} />
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (failure.code === 404) {
|
|
80
|
-
return <AccountIssueView reload={reload} />;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (failure.type === "NETWORK_ERROR") {
|
|
85
|
-
return (
|
|
86
|
-
<NoConnectionView
|
|
87
|
-
latestAttemptTs={latestAttemptTs}
|
|
88
|
-
onRetry={() => reload()}
|
|
89
|
-
/>
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return <FailureFallbackView />;
|
|
94
|
-
},
|
|
95
|
-
|
|
96
|
-
() => {
|
|
97
|
-
return <LoadingView />;
|
|
98
|
-
},
|
|
99
|
-
);
|
|
100
|
-
}
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { Button, Form, useStoreState } from "@ariakit/react";
|
|
2
|
-
import type { ReactNode } from "react";
|
|
3
|
-
import { Link, useLocation } from "wouter";
|
|
4
|
-
import { useAppConfig } from "../AppConfig/AppConfig.tsx";
|
|
5
|
-
import { interactiveText } from "../common.css.ts";
|
|
6
|
-
import { getSubmitFailureMessage } from "../failureMessages.ts";
|
|
7
|
-
import {
|
|
8
|
-
Letterhead,
|
|
9
|
-
LetterheadHeading,
|
|
10
|
-
LetterheadParagraph,
|
|
11
|
-
LetterheadSubmitButton,
|
|
12
|
-
} from "../Letterhead/index.tsx";
|
|
13
|
-
import {
|
|
14
|
-
InputsStack,
|
|
15
|
-
LetterheadFormActions,
|
|
16
|
-
LetterheadHeader,
|
|
17
|
-
LetterheadSubmitError,
|
|
18
|
-
LetterheadTextField,
|
|
19
|
-
} from "../LetterheadForm/index.tsx";
|
|
20
|
-
import { useAppActions } from "../store/index.tsx";
|
|
21
|
-
import type { CurrentUser } from "../types.ts";
|
|
22
|
-
import { useForm } from "../use-form.ts";
|
|
23
|
-
import { validEmail } from "../validations.ts";
|
|
24
|
-
import type { AuthEventHandler, DefaultFormValues } from "./types.ts";
|
|
25
|
-
import { useRedirectPath } from "./useRedirectPath.ts";
|
|
26
|
-
|
|
27
|
-
export function LoginView(props: {
|
|
28
|
-
defaultValues?: DefaultFormValues;
|
|
29
|
-
onLogin?: AuthEventHandler;
|
|
30
|
-
currentUser: CurrentUser | null;
|
|
31
|
-
description: ReactNode;
|
|
32
|
-
reload: () => void;
|
|
33
|
-
}) {
|
|
34
|
-
const { currentUser, defaultValues, description, onLogin, reload } = props;
|
|
35
|
-
const { placeholders, client, hrefs } = useAppConfig();
|
|
36
|
-
const { logout } = useAppActions();
|
|
37
|
-
|
|
38
|
-
const localUserPresent = !!currentUser?.email;
|
|
39
|
-
const defaultEmailValue = currentUser?.email ?? defaultValues?.email ?? "";
|
|
40
|
-
const redirectPath = useRedirectPath() ?? hrefs.dashboard();
|
|
41
|
-
const [_, navigate] = useLocation();
|
|
42
|
-
|
|
43
|
-
const { form, submitName } = useForm({
|
|
44
|
-
defaultValues: { email: defaultEmailValue, password: "" },
|
|
45
|
-
validate: { email: validEmail },
|
|
46
|
-
async onSubmit({ values }) {
|
|
47
|
-
const result = await client.login(values);
|
|
48
|
-
|
|
49
|
-
return result.mapFailure((failure) => {
|
|
50
|
-
return getSubmitFailureMessage(failure, {
|
|
51
|
-
401: "🔐 Username and password do not match.",
|
|
52
|
-
404: "🤔 Couldn't find a user with this email address.",
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
},
|
|
56
|
-
onSuccess() {
|
|
57
|
-
if (onLogin) {
|
|
58
|
-
onLogin();
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// If a custom onLogin handler is not provided, will automatically
|
|
62
|
-
// navigate to the appropriate redirect path.
|
|
63
|
-
else {
|
|
64
|
-
navigate(redirectPath);
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const emailValue = useStoreState(form, (state) => state.values.email);
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<Letterhead>
|
|
73
|
-
<LetterheadHeader>
|
|
74
|
-
<LetterheadHeading>Log in</LetterheadHeading>
|
|
75
|
-
|
|
76
|
-
{localUserPresent ? (
|
|
77
|
-
<>
|
|
78
|
-
<LetterheadParagraph>
|
|
79
|
-
Your session has expired. Please log into Indie Tabletop Club
|
|
80
|
-
again.
|
|
81
|
-
</LetterheadParagraph>
|
|
82
|
-
|
|
83
|
-
<LetterheadParagraph>
|
|
84
|
-
{"To use a different account, please "}
|
|
85
|
-
<Button
|
|
86
|
-
className={interactiveText}
|
|
87
|
-
onClick={async () => {
|
|
88
|
-
await logout();
|
|
89
|
-
reload();
|
|
90
|
-
}}
|
|
91
|
-
>
|
|
92
|
-
log out
|
|
93
|
-
</Button>
|
|
94
|
-
{" first."}
|
|
95
|
-
</LetterheadParagraph>
|
|
96
|
-
</>
|
|
97
|
-
) : (
|
|
98
|
-
<LetterheadParagraph>
|
|
99
|
-
{description}
|
|
100
|
-
{" Do not have an account? "}
|
|
101
|
-
<Link
|
|
102
|
-
href={hrefs.join()}
|
|
103
|
-
className={interactiveText}
|
|
104
|
-
state={{ emailValue }}
|
|
105
|
-
>
|
|
106
|
-
Join now
|
|
107
|
-
</Link>
|
|
108
|
-
{"."}
|
|
109
|
-
</LetterheadParagraph>
|
|
110
|
-
)}
|
|
111
|
-
</LetterheadHeader>
|
|
112
|
-
|
|
113
|
-
<Form store={form} resetOnSubmit={false}>
|
|
114
|
-
<InputsStack>
|
|
115
|
-
<LetterheadTextField
|
|
116
|
-
name={form.names.email}
|
|
117
|
-
placeholder={placeholders.email}
|
|
118
|
-
label="Email"
|
|
119
|
-
type="email"
|
|
120
|
-
readOnly={localUserPresent}
|
|
121
|
-
required
|
|
122
|
-
/>
|
|
123
|
-
<LetterheadTextField
|
|
124
|
-
name={form.names.password}
|
|
125
|
-
label="Password"
|
|
126
|
-
placeholder="Your password"
|
|
127
|
-
type="password"
|
|
128
|
-
required
|
|
129
|
-
/>
|
|
130
|
-
</InputsStack>
|
|
131
|
-
|
|
132
|
-
<LetterheadFormActions>
|
|
133
|
-
<LetterheadSubmitError name={submitName} />
|
|
134
|
-
<LetterheadSubmitButton>Log in</LetterheadSubmitButton>
|
|
135
|
-
|
|
136
|
-
<LetterheadParagraph align="start">
|
|
137
|
-
Forgot password?{" "}
|
|
138
|
-
<Link
|
|
139
|
-
href="/password"
|
|
140
|
-
className={interactiveText}
|
|
141
|
-
state={{ emailValue }}
|
|
142
|
-
>
|
|
143
|
-
Reset it
|
|
144
|
-
</Link>
|
|
145
|
-
{"."}
|
|
146
|
-
</LetterheadParagraph>
|
|
147
|
-
</LetterheadFormActions>
|
|
148
|
-
</Form>
|
|
149
|
-
</Letterhead>
|
|
150
|
-
);
|
|
151
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Button } from "@ariakit/react";
|
|
2
|
-
import { cx } from "../class-names.ts";
|
|
3
|
-
import { interactiveText } from "../common.css.ts";
|
|
4
|
-
import {
|
|
5
|
-
Letterhead,
|
|
6
|
-
LetterheadHeading,
|
|
7
|
-
LetterheadParagraph,
|
|
8
|
-
} from "../Letterhead/index.tsx";
|
|
9
|
-
|
|
10
|
-
export function NoConnectionView(props: {
|
|
11
|
-
latestAttemptTs: number;
|
|
12
|
-
onRetry: () => void;
|
|
13
|
-
}) {
|
|
14
|
-
const { latestAttemptTs, onRetry } = props;
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<Letterhead>
|
|
18
|
-
<LetterheadHeading>No connection</LetterheadHeading>
|
|
19
|
-
|
|
20
|
-
<LetterheadParagraph>
|
|
21
|
-
{"There seems to be an issue reaching to our servers. "}
|
|
22
|
-
{"Are you connected to the internet? Last attempt at "}
|
|
23
|
-
{new Date(latestAttemptTs).toLocaleTimeString()}
|
|
24
|
-
{"."}
|
|
25
|
-
</LetterheadParagraph>
|
|
26
|
-
|
|
27
|
-
<LetterheadParagraph>
|
|
28
|
-
<Button {...cx(interactiveText)} onClick={() => onRetry()}>
|
|
29
|
-
Try again
|
|
30
|
-
</Button>
|
|
31
|
-
</LetterheadParagraph>
|
|
32
|
-
</Letterhead>
|
|
33
|
-
);
|
|
34
|
-
}
|