@indietabletop/appkit 5.0.0-0 → 5.0.0-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/lib/AuthCard/AuthCard.stories.ts +7 -11
- package/lib/Letterhead/stories.tsx +6 -10
- package/lib/LetterheadForm/LetterheadReadonlyTextField.stories.tsx +6 -10
- package/lib/LetterheadForm/LetterheadSubmitError.stories.tsx +6 -10
- package/lib/LetterheadForm/LetterheadTextField.stories.tsx +6 -10
- package/lib/MiddotSeparated/MiddotSeparated.stories.ts +7 -13
- package/lib/QRCode/QRCode.stories.tsx +8 -14
- package/lib/SubscribeCard/LetterheadInfoCard.tsx +1 -1
- package/lib/SubscribeCard/SubscribeByEmailCard.stories.tsx +5 -13
- package/lib/SubscribeCard/SubscribeByEmailCard.tsx +6 -0
- package/lib/SubscribeCard/{SubscribeCard.stories.tsx → SubscribeByPledgeCard.stories.tsx} +11 -15
- package/lib/SubscribeCard/{SubscribeCard.tsx → SubscribeByPledgeCard.tsx} +16 -1
- package/lib/account/CurrentUserFetcher.stories.tsx +16 -21
- package/lib/account/CurrentUserFetcher.tsx +4 -0
- package/lib/account/JoinCard.stories.tsx +18 -23
- package/lib/account/LoginCard.stories.tsx +23 -28
- package/lib/account/PasswordResetCard.stories.tsx +16 -21
- package/lib/account/useFetchCurrentUser.tsx +18 -6
- package/lib/client.ts +2 -2
- package/lib/index.ts +1 -1
- package/lib/types/spacegits.ts +6 -2
- package/package.json +10 -7
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
1
|
import { fn } from "storybook/test";
|
|
2
|
+
import preview from "../../.storybook/preview.tsx";
|
|
3
3
|
import { AuthCard } from "./AuthCard.tsx";
|
|
4
4
|
|
|
5
|
-
const meta = {
|
|
5
|
+
const meta = preview.meta({
|
|
6
6
|
title: "Account/Auth Card",
|
|
7
7
|
component: AuthCard,
|
|
8
8
|
tags: ["autodocs"],
|
|
9
9
|
args: {
|
|
10
10
|
onLogout: fn(),
|
|
11
11
|
},
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default meta;
|
|
15
|
-
|
|
16
|
-
type Story = StoryObj<typeof meta>;
|
|
12
|
+
});
|
|
17
13
|
|
|
18
14
|
/**
|
|
19
15
|
* The default case where elements are correctly separated with middots.
|
|
20
16
|
*/
|
|
21
|
-
export const Authenticated
|
|
17
|
+
export const Authenticated = meta.story({
|
|
22
18
|
args: {
|
|
23
19
|
currentUser: {
|
|
24
20
|
id: "martin",
|
|
@@ -26,13 +22,13 @@ export const Authenticated: Story = {
|
|
|
26
22
|
isVerified: true,
|
|
27
23
|
},
|
|
28
24
|
},
|
|
29
|
-
};
|
|
25
|
+
});
|
|
30
26
|
|
|
31
27
|
/**
|
|
32
28
|
* The default case in which all steps of the flow succeed.
|
|
33
29
|
*/
|
|
34
|
-
export const Anonymous
|
|
30
|
+
export const Anonymous = meta.story({
|
|
35
31
|
args: {
|
|
36
32
|
currentUser: null,
|
|
37
33
|
},
|
|
38
|
-
};
|
|
34
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FormProvider } from "@ariakit/react";
|
|
2
|
-
import
|
|
2
|
+
import preview from "../../.storybook/preview.tsx";
|
|
3
3
|
import {
|
|
4
4
|
Letterhead,
|
|
5
5
|
LetterheadHeading,
|
|
@@ -7,20 +7,16 @@ import {
|
|
|
7
7
|
LetterheadSubmitButton,
|
|
8
8
|
} from "./index.tsx";
|
|
9
9
|
|
|
10
|
-
const meta = {
|
|
11
|
-
title: "Letterhead",
|
|
10
|
+
const meta = preview.meta({
|
|
11
|
+
title: "Components/Letterhead",
|
|
12
12
|
component: Letterhead,
|
|
13
13
|
tags: ["autodocs"],
|
|
14
14
|
args: {
|
|
15
15
|
textAlign: "start",
|
|
16
16
|
},
|
|
17
|
-
}
|
|
17
|
+
});
|
|
18
18
|
|
|
19
|
-
export
|
|
20
|
-
|
|
21
|
-
type Story = StoryObj<typeof meta>;
|
|
22
|
-
|
|
23
|
-
export const Default: Story = {
|
|
19
|
+
export const Default = meta.story({
|
|
24
20
|
args: {
|
|
25
21
|
children: (
|
|
26
22
|
<>
|
|
@@ -42,4 +38,4 @@ export const Default: Story = {
|
|
|
42
38
|
</>
|
|
43
39
|
),
|
|
44
40
|
},
|
|
45
|
-
};
|
|
41
|
+
});
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import preview from "../../.storybook/preview.tsx";
|
|
2
2
|
import { LetterheadReadonlyTextField } from "./index.tsx";
|
|
3
3
|
|
|
4
|
-
const meta = {
|
|
5
|
-
title: "ReadonlyTextField",
|
|
4
|
+
const meta = preview.meta({
|
|
5
|
+
title: "Components/ReadonlyTextField",
|
|
6
6
|
component: LetterheadReadonlyTextField,
|
|
7
7
|
tags: ["autodocs"],
|
|
8
8
|
args: {},
|
|
9
|
-
}
|
|
9
|
+
});
|
|
10
10
|
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
type Story = StoryObj<typeof meta>;
|
|
14
|
-
|
|
15
|
-
export const Default: Story = {
|
|
11
|
+
export const Default = meta.story({
|
|
16
12
|
args: {
|
|
17
13
|
label: "Email",
|
|
18
14
|
value: "john@example.com",
|
|
19
15
|
placeholder: "john@example.com",
|
|
20
16
|
},
|
|
21
|
-
};
|
|
17
|
+
});
|
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
import
|
|
1
|
+
import preview from "../../.storybook/preview.tsx";
|
|
2
2
|
import { form } from "../storybook/decorators.tsx";
|
|
3
3
|
import { LetterheadSubmitError } from "./index.tsx";
|
|
4
4
|
|
|
5
|
-
const meta = {
|
|
6
|
-
title: "LetterheadSubmitError",
|
|
5
|
+
const meta = preview.meta({
|
|
6
|
+
title: "Components/LetterheadSubmitError",
|
|
7
7
|
component: LetterheadSubmitError,
|
|
8
8
|
tags: ["autodocs"],
|
|
9
9
|
args: {},
|
|
10
10
|
decorators: [
|
|
11
11
|
form({ defaultErrors: { submit: "This is an error message." } }),
|
|
12
12
|
],
|
|
13
|
-
}
|
|
13
|
+
});
|
|
14
14
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
type Story = StoryObj<typeof meta>;
|
|
18
|
-
|
|
19
|
-
export const Default: Story = {
|
|
15
|
+
export const Default = meta.story({
|
|
20
16
|
args: {
|
|
21
17
|
name: "submit",
|
|
22
18
|
},
|
|
23
|
-
};
|
|
19
|
+
});
|
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
import
|
|
1
|
+
import preview from "../../.storybook/preview.tsx";
|
|
2
2
|
import { form } from "../storybook/decorators.tsx";
|
|
3
3
|
import { LetterheadTextField } from "./index.tsx";
|
|
4
4
|
|
|
5
|
-
const meta = {
|
|
6
|
-
title: "
|
|
5
|
+
const meta = preview.meta({
|
|
6
|
+
title: "Components/LetterheadTextField",
|
|
7
7
|
component: LetterheadTextField,
|
|
8
8
|
tags: ["autodocs"],
|
|
9
9
|
args: {},
|
|
10
10
|
decorators: [form()],
|
|
11
|
-
}
|
|
11
|
+
});
|
|
12
12
|
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
type Story = StoryObj<typeof meta>;
|
|
16
|
-
|
|
17
|
-
export const Default: Story = {
|
|
13
|
+
export const Default = meta.story({
|
|
18
14
|
args: {
|
|
19
15
|
label: "Email",
|
|
20
16
|
placeholder: "john@example.com",
|
|
21
17
|
name: "foo",
|
|
22
18
|
},
|
|
23
|
-
};
|
|
19
|
+
});
|
|
@@ -1,32 +1,26 @@
|
|
|
1
|
-
import
|
|
1
|
+
import preview from "../../.storybook/preview.tsx";
|
|
2
2
|
import { MiddotSeparated } from "./MiddotSeparated.tsx";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type Story = StoryObj<typeof meta>;
|
|
7
|
-
|
|
8
|
-
const meta = {
|
|
4
|
+
const meta = preview.meta({
|
|
9
5
|
title: "Components/Middot Separated",
|
|
10
6
|
component: MiddotSeparated,
|
|
11
7
|
tags: ["autodocs"],
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default meta;
|
|
8
|
+
});
|
|
15
9
|
|
|
16
10
|
/**
|
|
17
11
|
* The default case in which all steps of the flow succeed.
|
|
18
12
|
*/
|
|
19
|
-
export const Default
|
|
13
|
+
export const Default = meta.story({
|
|
20
14
|
args: {
|
|
21
15
|
children: ["Lorem", "Ipsum", " Dolor"],
|
|
22
16
|
},
|
|
23
|
-
};
|
|
17
|
+
});
|
|
24
18
|
|
|
25
19
|
/**
|
|
26
20
|
* Edge case when it comes to handling children in React.
|
|
27
21
|
*/
|
|
28
|
-
export const SingleElement
|
|
22
|
+
export const SingleElement = meta.story({
|
|
29
23
|
args: {
|
|
30
24
|
children: "Lorem",
|
|
31
25
|
},
|
|
32
|
-
};
|
|
26
|
+
});
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
1
|
import { http, HttpResponse } from "msw";
|
|
2
|
+
import preview from "../../.storybook/preview.tsx";
|
|
3
3
|
import { Failure, Pending, Success } from "../async-op.ts";
|
|
4
4
|
import { QRCode } from "./QRCode.tsx";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type Story = StoryObj<typeof meta>;
|
|
9
|
-
|
|
10
|
-
const meta = {
|
|
6
|
+
const meta = preview.meta({
|
|
11
7
|
title: "Components/QR Code",
|
|
12
8
|
component: QRCode,
|
|
13
9
|
tags: ["autodocs"],
|
|
@@ -28,20 +24,18 @@ const meta = {
|
|
|
28
24
|
},
|
|
29
25
|
},
|
|
30
26
|
},
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export default meta;
|
|
27
|
+
});
|
|
34
28
|
|
|
35
|
-
export const SuccessCase
|
|
29
|
+
export const SuccessCase = meta.story({});
|
|
36
30
|
|
|
37
|
-
export const PendingCase
|
|
31
|
+
export const PendingCase = meta.story({
|
|
38
32
|
args: {
|
|
39
33
|
url: new Pending(),
|
|
40
34
|
},
|
|
41
|
-
};
|
|
35
|
+
});
|
|
42
36
|
|
|
43
|
-
export const FailureCase
|
|
37
|
+
export const FailureCase = meta.story({
|
|
44
38
|
args: {
|
|
45
39
|
url: new Failure("Failed"),
|
|
46
40
|
},
|
|
47
|
-
};
|
|
41
|
+
});
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
LetterheadParagraph,
|
|
5
5
|
} from "../Letterhead/index.tsx";
|
|
6
6
|
import * as css from "./style.css.ts";
|
|
7
|
-
import type { ViewContent } from "./
|
|
7
|
+
import type { ViewContent } from "./SubscribeByPledgeCard.tsx";
|
|
8
8
|
|
|
9
9
|
export function LetterheadInfoCard(props: ViewContent) {
|
|
10
10
|
return (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
1
|
import { http, HttpResponse } from "msw";
|
|
2
|
+
import preview from "../../.storybook/preview.tsx";
|
|
3
3
|
import { LetterheadParagraph } from "../Letterhead/index.tsx";
|
|
4
4
|
import { sleep } from "../sleep.ts";
|
|
5
5
|
import { SubscribeByEmailCard } from "./SubscribeByEmailCard.tsx";
|
|
@@ -30,12 +30,8 @@ const handlers = {
|
|
|
30
30
|
},
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* in their pledge.
|
|
36
|
-
*/
|
|
37
|
-
const meta = {
|
|
38
|
-
title: "Pages/Subscribe By Email Card",
|
|
33
|
+
const meta = preview.meta({
|
|
34
|
+
title: "Newsletter/Subscribe By Email Card",
|
|
39
35
|
component: SubscribeByEmailCard,
|
|
40
36
|
tags: ["autodocs"],
|
|
41
37
|
args: {
|
|
@@ -68,10 +64,6 @@ const meta = {
|
|
|
68
64
|
},
|
|
69
65
|
},
|
|
70
66
|
},
|
|
71
|
-
}
|
|
67
|
+
});
|
|
72
68
|
|
|
73
|
-
export
|
|
74
|
-
|
|
75
|
-
type Story = StoryObj<typeof meta>;
|
|
76
|
-
|
|
77
|
-
export const Default: Story = {};
|
|
69
|
+
export const Default = meta.story({});
|
|
@@ -149,6 +149,12 @@ type ViewContent = {
|
|
|
149
149
|
description: ReactNode;
|
|
150
150
|
};
|
|
151
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Allows users to sign up to the newsletter using an arbitrary email.
|
|
154
|
+
*
|
|
155
|
+
* Signups are verified using an one-time code, which is sent to the supplied
|
|
156
|
+
* email address.
|
|
157
|
+
*/
|
|
152
158
|
export function SubscribeByEmailCard(props: {
|
|
153
159
|
content: Record<Exclude<SubscribeStep["type"], "SUBMIT_CODE">, ViewContent>;
|
|
154
160
|
}) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
1
|
import { http, HttpResponse } from "msw";
|
|
2
|
+
import preview from "../../.storybook/preview.tsx";
|
|
3
3
|
import { LetterheadParagraph } from "../Letterhead/index.tsx";
|
|
4
4
|
import { sleep } from "../sleep.ts";
|
|
5
|
-
import {
|
|
5
|
+
import { SubscribeByPledgeCard } from "./SubscribeByPledgeCard.tsx";
|
|
6
6
|
|
|
7
7
|
const pledge = {
|
|
8
8
|
id: "1",
|
|
@@ -48,9 +48,9 @@ const subscribeByPledgeId = {
|
|
|
48
48
|
* Allows users to subscribe to ITC's newsletter using the email provided
|
|
49
49
|
* in their pledge.
|
|
50
50
|
*/
|
|
51
|
-
const meta = {
|
|
52
|
-
title: "
|
|
53
|
-
component:
|
|
51
|
+
const meta = preview.meta({
|
|
52
|
+
title: "Newsletter/Subscribe By Pledge Card",
|
|
53
|
+
component: SubscribeByPledgeCard,
|
|
54
54
|
tags: ["autodocs"],
|
|
55
55
|
args: {
|
|
56
56
|
pledge,
|
|
@@ -101,24 +101,20 @@ const meta = {
|
|
|
101
101
|
},
|
|
102
102
|
},
|
|
103
103
|
},
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export default meta;
|
|
107
|
-
|
|
108
|
-
type Story = StoryObj<typeof meta>;
|
|
104
|
+
});
|
|
109
105
|
|
|
110
106
|
/**
|
|
111
107
|
* The default case, in which the user is not yet subscribed to ITC's newsletter
|
|
112
108
|
* and the submission is successful.
|
|
113
109
|
*/
|
|
114
|
-
export const Default
|
|
110
|
+
export const Default = meta.story({});
|
|
115
111
|
|
|
116
112
|
/**
|
|
117
113
|
* Same like the default case, but the form submission fails. Errors are
|
|
118
114
|
* differentiated using the `getSubmitFailureMessage` helper, so all the basics
|
|
119
115
|
* should be covered, as this page doesn't have special cases.
|
|
120
116
|
*/
|
|
121
|
-
export const FailureOnSubmit
|
|
117
|
+
export const FailureOnSubmit = meta.story({
|
|
122
118
|
parameters: {
|
|
123
119
|
msw: {
|
|
124
120
|
handlers: {
|
|
@@ -126,12 +122,12 @@ export const FailureOnSubmit: Story = {
|
|
|
126
122
|
},
|
|
127
123
|
},
|
|
128
124
|
},
|
|
129
|
-
};
|
|
125
|
+
});
|
|
130
126
|
|
|
131
127
|
/**
|
|
132
128
|
* In this case, the email address associated with this user account is
|
|
133
129
|
* already subscribed to our newsletter.
|
|
134
130
|
*/
|
|
135
|
-
export const AlreadySubscribed
|
|
131
|
+
export const AlreadySubscribed = meta.story({
|
|
136
132
|
args: { pledge: { ...pledge, contactSubscribed: true } },
|
|
137
|
-
};
|
|
133
|
+
});
|
|
@@ -69,7 +69,15 @@ export type ViewContent = {
|
|
|
69
69
|
description: ReactNode;
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Allows users to sign up to the newsletter using the email associated with
|
|
74
|
+
* their pledge ID.
|
|
75
|
+
*
|
|
76
|
+
* Emails are not verified using a one-time code, as the user has just
|
|
77
|
+
* implicitly verified their address by navigating to the page with the unique
|
|
78
|
+
* pledge ID.
|
|
79
|
+
*/
|
|
80
|
+
export function SubscribeByPledgeCard(props: {
|
|
73
81
|
/**
|
|
74
82
|
* The pledge data that will be used to determine whether the user should
|
|
75
83
|
* be prompted for signup.
|
|
@@ -110,3 +118,10 @@ export function SubscribeCard(props: {
|
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
}
|
|
121
|
+
|
|
122
|
+
export {
|
|
123
|
+
/**
|
|
124
|
+
* @deprecated Use {@link SubscribeByPledgeCard}
|
|
125
|
+
*/
|
|
126
|
+
SubscribeByPledgeCard as SubscribeCard,
|
|
127
|
+
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Story } from "@storybook/addon-docs/blocks";
|
|
2
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
1
|
import { http, HttpResponse } from "msw";
|
|
2
|
+
import preview from "../../.storybook/preview.tsx";
|
|
4
3
|
import { sleep } from "../sleep.ts";
|
|
5
4
|
import type { CurrentUser, SessionInfo } from "../types.ts";
|
|
6
5
|
import { CurrentUserFetcher } from "./CurrentUserFetcher.tsx";
|
|
@@ -162,7 +161,7 @@ function createMocks(options?: { responseSpeed?: number }) {
|
|
|
162
161
|
|
|
163
162
|
const { data, handlers } = createMocks({ responseSpeed: 700 });
|
|
164
163
|
|
|
165
|
-
const meta = {
|
|
164
|
+
const meta = preview.meta({
|
|
166
165
|
title: "Account/Current User Fetcher",
|
|
167
166
|
component: CurrentUserFetcher,
|
|
168
167
|
tags: ["autodocs"],
|
|
@@ -189,18 +188,14 @@ const meta = {
|
|
|
189
188
|
},
|
|
190
189
|
},
|
|
191
190
|
},
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export default meta;
|
|
195
|
-
|
|
196
|
-
type Story = StoryObj<typeof meta>;
|
|
191
|
+
});
|
|
197
192
|
|
|
198
193
|
/**
|
|
199
194
|
* The default case, in which a local user is provided (so they have previously
|
|
200
195
|
* logged in), and the current user request returns the same user as is
|
|
201
196
|
* the local user (determined by the user id).
|
|
202
197
|
*/
|
|
203
|
-
export const Default
|
|
198
|
+
export const Default = meta.story({
|
|
204
199
|
parameters: {
|
|
205
200
|
msw: {
|
|
206
201
|
handlers: {
|
|
@@ -208,19 +203,19 @@ export const Default: Story = {
|
|
|
208
203
|
},
|
|
209
204
|
},
|
|
210
205
|
},
|
|
211
|
-
};
|
|
206
|
+
});
|
|
212
207
|
|
|
213
208
|
/**
|
|
214
209
|
* In this case, no local user is provided and the component simply renders
|
|
215
210
|
* its children. There should be no network request in this case.
|
|
216
211
|
*/
|
|
217
|
-
export const NoLocalUser
|
|
212
|
+
export const NoLocalUser = meta.story({});
|
|
218
213
|
|
|
219
214
|
/**
|
|
220
215
|
* In this case, the local user is provided and the current user request returns
|
|
221
216
|
* error 401. The user should supply their credentials again.
|
|
222
217
|
*/
|
|
223
|
-
export const SessionExpired
|
|
218
|
+
export const SessionExpired = meta.story({
|
|
224
219
|
parameters: {
|
|
225
220
|
msw: {
|
|
226
221
|
handlers: {
|
|
@@ -228,7 +223,7 @@ export const SessionExpired: Story = {
|
|
|
228
223
|
},
|
|
229
224
|
},
|
|
230
225
|
},
|
|
231
|
-
};
|
|
226
|
+
});
|
|
232
227
|
|
|
233
228
|
/**
|
|
234
229
|
* In this case, the local user is provided and the current user request returns
|
|
@@ -241,7 +236,7 @@ export const SessionExpired: Story = {
|
|
|
241
236
|
* In practice this should be a rare case, but with unpleasant circumstances
|
|
242
237
|
* if not handled correctly.
|
|
243
238
|
*/
|
|
244
|
-
export const UserMismatch
|
|
239
|
+
export const UserMismatch = meta.story({
|
|
245
240
|
parameters: {
|
|
246
241
|
msw: {
|
|
247
242
|
handlers: {
|
|
@@ -249,11 +244,11 @@ export const UserMismatch: Story = {
|
|
|
249
244
|
},
|
|
250
245
|
},
|
|
251
246
|
},
|
|
252
|
-
};
|
|
247
|
+
});
|
|
253
248
|
|
|
254
249
|
/**
|
|
255
250
|
*/
|
|
256
|
-
export const UserUnverified
|
|
251
|
+
export const UserUnverified = meta.story({
|
|
257
252
|
parameters: {
|
|
258
253
|
msw: {
|
|
259
254
|
handlers: {
|
|
@@ -264,7 +259,7 @@ export const UserUnverified: Story = {
|
|
|
264
259
|
},
|
|
265
260
|
},
|
|
266
261
|
},
|
|
267
|
-
};
|
|
262
|
+
});
|
|
268
263
|
|
|
269
264
|
/**
|
|
270
265
|
* In this case, the local user is provided and the current user request returns
|
|
@@ -272,7 +267,7 @@ export const UserUnverified: Story = {
|
|
|
272
267
|
*
|
|
273
268
|
* This can happen if users delete their accounts but
|
|
274
269
|
*/
|
|
275
|
-
export const UserNotFound
|
|
270
|
+
export const UserNotFound = meta.story({
|
|
276
271
|
parameters: {
|
|
277
272
|
msw: {
|
|
278
273
|
handlers: {
|
|
@@ -280,13 +275,13 @@ export const UserNotFound: Story = {
|
|
|
280
275
|
},
|
|
281
276
|
},
|
|
282
277
|
},
|
|
283
|
-
};
|
|
278
|
+
});
|
|
284
279
|
|
|
285
280
|
/**
|
|
286
281
|
* The proactive user session check has failed due to an error that doesn't
|
|
287
282
|
* carry any special meaning.
|
|
288
283
|
*/
|
|
289
|
-
export const UnknownFailure
|
|
284
|
+
export const UnknownFailure = meta.story({
|
|
290
285
|
parameters: {
|
|
291
286
|
msw: {
|
|
292
287
|
handlers: {
|
|
@@ -294,4 +289,4 @@ export const UnknownFailure: Story = {
|
|
|
294
289
|
},
|
|
295
290
|
},
|
|
296
291
|
},
|
|
297
|
-
};
|
|
292
|
+
});
|
|
@@ -34,6 +34,10 @@ export function CurrentUserFetcher(props: CurrentUserFetcherProps) {
|
|
|
34
34
|
// We only want to fetch the current user if they exist in the store, i.e.
|
|
35
35
|
// they have logged into the app previously.
|
|
36
36
|
performFetch: !!localUser,
|
|
37
|
+
|
|
38
|
+
// If we are performing a fetch, we want to make sure that it is up to date
|
|
39
|
+
// every time the user focuses the window.
|
|
40
|
+
revalidateOnFocus: true,
|
|
37
41
|
});
|
|
38
42
|
|
|
39
43
|
if (result.isFailure && result.failure.type === "API_ERROR") {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Story } from "@storybook/addon-docs/blocks";
|
|
2
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
1
|
import { http, HttpResponse } from "msw";
|
|
2
|
+
import preview from "../../.storybook/preview.tsx";
|
|
4
3
|
import { sleep } from "../sleep.ts";
|
|
5
4
|
import type { CurrentUser, SessionInfo } from "../types.ts";
|
|
6
5
|
import { JoinCard } from "./JoinCard.tsx";
|
|
@@ -135,7 +134,7 @@ function createMocks(options?: { responseSpeed?: number }) {
|
|
|
135
134
|
|
|
136
135
|
const { data, handlers } = createMocks({ responseSpeed: 700 });
|
|
137
136
|
|
|
138
|
-
const meta = {
|
|
137
|
+
const meta = preview.meta({
|
|
139
138
|
title: "Account/Join Card",
|
|
140
139
|
component: JoinCard,
|
|
141
140
|
tags: ["autodocs"],
|
|
@@ -152,22 +151,18 @@ const meta = {
|
|
|
152
151
|
},
|
|
153
152
|
},
|
|
154
153
|
},
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export default meta;
|
|
158
|
-
|
|
159
|
-
type Story = StoryObj<typeof meta>;
|
|
154
|
+
});
|
|
160
155
|
|
|
161
156
|
/**
|
|
162
157
|
* The default case in which all steps of the flow succeed.
|
|
163
158
|
*/
|
|
164
|
-
export const Success
|
|
159
|
+
export const Success = meta.story({});
|
|
165
160
|
|
|
166
161
|
/**
|
|
167
162
|
* In this case, the initial step fails because the email address is associated
|
|
168
163
|
* with an existing user.
|
|
169
164
|
*/
|
|
170
|
-
export const EmailTakenOnJoin
|
|
165
|
+
export const EmailTakenOnJoin = meta.story({
|
|
171
166
|
parameters: {
|
|
172
167
|
msw: {
|
|
173
168
|
handlers: {
|
|
@@ -175,13 +170,13 @@ export const EmailTakenOnJoin: Story = {
|
|
|
175
170
|
},
|
|
176
171
|
},
|
|
177
172
|
},
|
|
178
|
-
};
|
|
173
|
+
});
|
|
179
174
|
|
|
180
175
|
/**
|
|
181
176
|
* In this case, the initial step fails for a reason that doesn't have any
|
|
182
177
|
* special handling in this location. E.g. network error, server error, etc.
|
|
183
178
|
*/
|
|
184
|
-
export const UnknownFailureOnJoin
|
|
179
|
+
export const UnknownFailureOnJoin = meta.story({
|
|
185
180
|
parameters: {
|
|
186
181
|
msw: {
|
|
187
182
|
handlers: {
|
|
@@ -189,13 +184,13 @@ export const UnknownFailureOnJoin: Story = {
|
|
|
189
184
|
},
|
|
190
185
|
},
|
|
191
186
|
},
|
|
192
|
-
};
|
|
187
|
+
});
|
|
193
188
|
|
|
194
189
|
/**
|
|
195
190
|
* In this case, the verify step fails because the token has expired,
|
|
196
191
|
* or is incorrect.
|
|
197
192
|
*/
|
|
198
|
-
export const NotFoundOrExpiredOnVerify
|
|
193
|
+
export const NotFoundOrExpiredOnVerify = meta.story({
|
|
199
194
|
parameters: {
|
|
200
195
|
msw: {
|
|
201
196
|
handlers: {
|
|
@@ -203,13 +198,13 @@ export const NotFoundOrExpiredOnVerify: Story = {
|
|
|
203
198
|
},
|
|
204
199
|
},
|
|
205
200
|
},
|
|
206
|
-
};
|
|
201
|
+
});
|
|
207
202
|
|
|
208
203
|
/**
|
|
209
204
|
* In this case, the verify step fails for a reason that doesn't have any
|
|
210
205
|
* special handling in this location. E.g. network error, server error, etc.
|
|
211
206
|
*/
|
|
212
|
-
export const UnknownFailureOnVerify
|
|
207
|
+
export const UnknownFailureOnVerify = meta.story({
|
|
213
208
|
parameters: {
|
|
214
209
|
msw: {
|
|
215
210
|
handlers: {
|
|
@@ -217,14 +212,14 @@ export const UnknownFailureOnVerify: Story = {
|
|
|
217
212
|
},
|
|
218
213
|
},
|
|
219
214
|
},
|
|
220
|
-
};
|
|
215
|
+
});
|
|
221
216
|
|
|
222
217
|
/**
|
|
223
218
|
* The proactive user-session check returns a user account.
|
|
224
219
|
*
|
|
225
220
|
* The user can continue to use the app, or log out.
|
|
226
221
|
*/
|
|
227
|
-
export const AlreadyLoggedIn
|
|
222
|
+
export const AlreadyLoggedIn = meta.story({
|
|
228
223
|
parameters: {
|
|
229
224
|
msw: {
|
|
230
225
|
handlers: {
|
|
@@ -232,12 +227,12 @@ export const AlreadyLoggedIn: Story = {
|
|
|
232
227
|
},
|
|
233
228
|
},
|
|
234
229
|
},
|
|
235
|
-
};
|
|
230
|
+
});
|
|
236
231
|
|
|
237
232
|
/**
|
|
238
233
|
* The proactive user session check has failed due to connection issues.
|
|
239
234
|
*/
|
|
240
|
-
export const NoConnection
|
|
235
|
+
export const NoConnection = meta.story({
|
|
241
236
|
parameters: {
|
|
242
237
|
msw: {
|
|
243
238
|
handlers: {
|
|
@@ -245,13 +240,13 @@ export const NoConnection: Story = {
|
|
|
245
240
|
},
|
|
246
241
|
},
|
|
247
242
|
},
|
|
248
|
-
};
|
|
243
|
+
});
|
|
249
244
|
|
|
250
245
|
/**
|
|
251
246
|
* The proactive user session check has failed due to an error that doesn't
|
|
252
247
|
* carry any special meaning.
|
|
253
248
|
*/
|
|
254
|
-
export const UnknownFailure
|
|
249
|
+
export const UnknownFailure = meta.story({
|
|
255
250
|
parameters: {
|
|
256
251
|
msw: {
|
|
257
252
|
handlers: {
|
|
@@ -259,4 +254,4 @@ export const UnknownFailure: Story = {
|
|
|
259
254
|
},
|
|
260
255
|
},
|
|
261
256
|
},
|
|
262
|
-
};
|
|
257
|
+
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Story } from "@storybook/addon-docs/blocks";
|
|
2
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
1
|
import { http, HttpResponse } from "msw";
|
|
4
2
|
import { fn } from "storybook/test";
|
|
3
|
+
import preview from "../../.storybook/preview.tsx";
|
|
5
4
|
import { sleep } from "../sleep.ts";
|
|
6
5
|
import type { CurrentUser, SessionInfo } from "../types.ts";
|
|
7
6
|
import { LoginCard } from "./LoginCard.tsx";
|
|
@@ -123,7 +122,7 @@ function createMocks(options?: { responseSpeed?: number }) {
|
|
|
123
122
|
|
|
124
123
|
const { data, handlers } = createMocks({ responseSpeed: 700 });
|
|
125
124
|
|
|
126
|
-
const meta = {
|
|
125
|
+
const meta = preview.meta({
|
|
127
126
|
title: "Account/Login Card",
|
|
128
127
|
component: LoginCard,
|
|
129
128
|
tags: ["autodocs"],
|
|
@@ -139,17 +138,13 @@ const meta = {
|
|
|
139
138
|
},
|
|
140
139
|
},
|
|
141
140
|
},
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export default meta;
|
|
145
|
-
|
|
146
|
-
type Story = StoryObj<typeof meta>;
|
|
141
|
+
});
|
|
147
142
|
|
|
148
143
|
/**
|
|
149
144
|
* The majority case where no user is stored locally, proactive user session
|
|
150
145
|
* check returns 401, and subsequently correct credentials are provided.
|
|
151
146
|
*/
|
|
152
|
-
export const Default
|
|
147
|
+
export const Default = meta.story({
|
|
153
148
|
parameters: {
|
|
154
149
|
msw: {
|
|
155
150
|
handlers: {
|
|
@@ -158,13 +153,13 @@ export const Default: Story = {
|
|
|
158
153
|
},
|
|
159
154
|
},
|
|
160
155
|
},
|
|
161
|
-
};
|
|
156
|
+
});
|
|
162
157
|
|
|
163
158
|
/**
|
|
164
159
|
* Similar to the default case, but invalid credentials are provided to when
|
|
165
160
|
* attempting to create a new session.
|
|
166
161
|
*/
|
|
167
|
-
export const InvalidCredentialsOnSubmit
|
|
162
|
+
export const InvalidCredentialsOnSubmit = meta.story({
|
|
168
163
|
parameters: {
|
|
169
164
|
msw: {
|
|
170
165
|
handlers: {
|
|
@@ -173,13 +168,13 @@ export const InvalidCredentialsOnSubmit: Story = {
|
|
|
173
168
|
},
|
|
174
169
|
},
|
|
175
170
|
},
|
|
176
|
-
};
|
|
171
|
+
});
|
|
177
172
|
|
|
178
173
|
/**
|
|
179
174
|
* Similar to the default case, but when credentials are provided, an account
|
|
180
175
|
* email is used that is not currently in the database.
|
|
181
176
|
*/
|
|
182
|
-
export const UserNotFoundOnSubmit
|
|
177
|
+
export const UserNotFoundOnSubmit = meta.story({
|
|
183
178
|
parameters: {
|
|
184
179
|
msw: {
|
|
185
180
|
handlers: {
|
|
@@ -188,13 +183,13 @@ export const UserNotFoundOnSubmit: Story = {
|
|
|
188
183
|
},
|
|
189
184
|
},
|
|
190
185
|
},
|
|
191
|
-
};
|
|
186
|
+
});
|
|
192
187
|
|
|
193
188
|
/**
|
|
194
189
|
* Similar to the default case, but the session creation call returns an error
|
|
195
190
|
* that doesn't have a specific meaning in the context of the login page.
|
|
196
191
|
*/
|
|
197
|
-
export const UnknownFailureOnSubmit
|
|
192
|
+
export const UnknownFailureOnSubmit = meta.story({
|
|
198
193
|
parameters: {
|
|
199
194
|
msw: {
|
|
200
195
|
handlers: {
|
|
@@ -203,12 +198,12 @@ export const UnknownFailureOnSubmit: Story = {
|
|
|
203
198
|
},
|
|
204
199
|
},
|
|
205
200
|
},
|
|
206
|
-
};
|
|
201
|
+
});
|
|
207
202
|
|
|
208
203
|
/**
|
|
209
204
|
* A case when user is stored locally, but their server session has expired.
|
|
210
205
|
*/
|
|
211
|
-
export const ReauthenticateSession
|
|
206
|
+
export const ReauthenticateSession = meta.story({
|
|
212
207
|
parameters: {
|
|
213
208
|
msw: {
|
|
214
209
|
handlers: {
|
|
@@ -217,7 +212,7 @@ export const ReauthenticateSession: Story = {
|
|
|
217
212
|
},
|
|
218
213
|
},
|
|
219
214
|
},
|
|
220
|
-
};
|
|
215
|
+
});
|
|
221
216
|
|
|
222
217
|
/**
|
|
223
218
|
* The user is already stored in the app, and proactive user-session check
|
|
@@ -225,7 +220,7 @@ export const ReauthenticateSession: Story = {
|
|
|
225
220
|
*
|
|
226
221
|
* The user is directed to app without any further steps.
|
|
227
222
|
*/
|
|
228
|
-
export const AlreadyLoggedIn
|
|
223
|
+
export const AlreadyLoggedIn = meta.story({
|
|
229
224
|
parameters: {
|
|
230
225
|
msw: {
|
|
231
226
|
handlers: {
|
|
@@ -233,14 +228,14 @@ export const AlreadyLoggedIn: Story = {
|
|
|
233
228
|
},
|
|
234
229
|
},
|
|
235
230
|
},
|
|
236
|
-
};
|
|
231
|
+
});
|
|
237
232
|
|
|
238
233
|
/**
|
|
239
234
|
* A user is provided, and proactive user session check returns a different
|
|
240
235
|
* user. This can happen when different users log into separate apps with
|
|
241
236
|
* different credentials.
|
|
242
237
|
*/
|
|
243
|
-
export const UserMismatch
|
|
238
|
+
export const UserMismatch = meta.story({
|
|
244
239
|
parameters: {
|
|
245
240
|
msw: {
|
|
246
241
|
handlers: {
|
|
@@ -248,14 +243,14 @@ export const UserMismatch: Story = {
|
|
|
248
243
|
},
|
|
249
244
|
},
|
|
250
245
|
},
|
|
251
|
-
};
|
|
246
|
+
});
|
|
252
247
|
|
|
253
248
|
/**
|
|
254
249
|
* During the proactive user session check, the user is reportd as not found.
|
|
255
250
|
* This means that the tokens are still valid, but the user DB entity is gone.
|
|
256
251
|
* This can happen if a user closed their account.
|
|
257
252
|
*/
|
|
258
|
-
export const UserNotFound
|
|
253
|
+
export const UserNotFound = meta.story({
|
|
259
254
|
parameters: {
|
|
260
255
|
msw: {
|
|
261
256
|
handlers: {
|
|
@@ -263,12 +258,12 @@ export const UserNotFound: Story = {
|
|
|
263
258
|
},
|
|
264
259
|
},
|
|
265
260
|
},
|
|
266
|
-
};
|
|
261
|
+
});
|
|
267
262
|
|
|
268
263
|
/**
|
|
269
264
|
* The proactive user session check has failed due to connection issues.
|
|
270
265
|
*/
|
|
271
|
-
export const NoConnection
|
|
266
|
+
export const NoConnection = meta.story({
|
|
272
267
|
parameters: {
|
|
273
268
|
msw: {
|
|
274
269
|
handlers: {
|
|
@@ -276,13 +271,13 @@ export const NoConnection: Story = {
|
|
|
276
271
|
},
|
|
277
272
|
},
|
|
278
273
|
},
|
|
279
|
-
};
|
|
274
|
+
});
|
|
280
275
|
|
|
281
276
|
/**
|
|
282
277
|
* The proactive user session check has failed due to an error that doesn't
|
|
283
278
|
* carry any special meaning.
|
|
284
279
|
*/
|
|
285
|
-
export const UnknownFailure
|
|
280
|
+
export const UnknownFailure = meta.story({
|
|
286
281
|
parameters: {
|
|
287
282
|
msw: {
|
|
288
283
|
handlers: {
|
|
@@ -290,4 +285,4 @@ export const UnknownFailure: Story = {
|
|
|
290
285
|
},
|
|
291
286
|
},
|
|
292
287
|
},
|
|
293
|
-
};
|
|
288
|
+
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Story } from "@storybook/addon-docs/blocks";
|
|
2
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
1
|
import { http, HttpResponse } from "msw";
|
|
2
|
+
import preview from "../../.storybook/preview.tsx";
|
|
4
3
|
import { sleep } from "../sleep.ts";
|
|
5
4
|
import type { CurrentUser, SessionInfo } from "../types.ts";
|
|
6
5
|
import { PasswordResetCard } from "./PasswordResetCard.tsx";
|
|
@@ -132,7 +131,7 @@ function createMocks(options?: { responseSpeed?: number }) {
|
|
|
132
131
|
|
|
133
132
|
const { data, handlers } = createMocks({ responseSpeed: 700 });
|
|
134
133
|
|
|
135
|
-
const meta = {
|
|
134
|
+
const meta = preview.meta({
|
|
136
135
|
title: "Account/Password Reset Page",
|
|
137
136
|
component: PasswordResetCard,
|
|
138
137
|
tags: ["autodocs"],
|
|
@@ -147,22 +146,18 @@ const meta = {
|
|
|
147
146
|
},
|
|
148
147
|
},
|
|
149
148
|
},
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export default meta;
|
|
153
|
-
|
|
154
|
-
type Story = StoryObj<typeof meta>;
|
|
149
|
+
});
|
|
155
150
|
|
|
156
151
|
/**
|
|
157
152
|
* The default case in which all steps of the flow succeed.
|
|
158
153
|
*/
|
|
159
|
-
export const Success
|
|
154
|
+
export const Success = meta.story({});
|
|
160
155
|
|
|
161
156
|
/**
|
|
162
157
|
* In this case, the initial step fails because the email address was not
|
|
163
158
|
* found in our database.
|
|
164
159
|
*/
|
|
165
|
-
export const UserNotFoundOnRequestCode
|
|
160
|
+
export const UserNotFoundOnRequestCode = meta.story({
|
|
166
161
|
parameters: {
|
|
167
162
|
msw: {
|
|
168
163
|
handlers: {
|
|
@@ -170,13 +165,13 @@ export const UserNotFoundOnRequestCode: Story = {
|
|
|
170
165
|
},
|
|
171
166
|
},
|
|
172
167
|
},
|
|
173
|
-
};
|
|
168
|
+
});
|
|
174
169
|
|
|
175
170
|
/**
|
|
176
171
|
* In this case, the initial step fails for a reason that doesn't have any
|
|
177
172
|
* special handling in this location. E.g. network error, server error, etc.
|
|
178
173
|
*/
|
|
179
|
-
export const UnknownFailureOnRequestCode
|
|
174
|
+
export const UnknownFailureOnRequestCode = meta.story({
|
|
180
175
|
parameters: {
|
|
181
176
|
msw: {
|
|
182
177
|
handlers: {
|
|
@@ -184,13 +179,13 @@ export const UnknownFailureOnRequestCode: Story = {
|
|
|
184
179
|
},
|
|
185
180
|
},
|
|
186
181
|
},
|
|
187
|
-
};
|
|
182
|
+
});
|
|
188
183
|
|
|
189
184
|
/**
|
|
190
185
|
* In this case, the check code step fails because the token has expired,
|
|
191
186
|
* or is incorrect.
|
|
192
187
|
*/
|
|
193
|
-
export const NotFoundOrExpiredOnCheckCode
|
|
188
|
+
export const NotFoundOrExpiredOnCheckCode = meta.story({
|
|
194
189
|
parameters: {
|
|
195
190
|
msw: {
|
|
196
191
|
handlers: {
|
|
@@ -198,13 +193,13 @@ export const NotFoundOrExpiredOnCheckCode: Story = {
|
|
|
198
193
|
},
|
|
199
194
|
},
|
|
200
195
|
},
|
|
201
|
-
};
|
|
196
|
+
});
|
|
202
197
|
|
|
203
198
|
/**
|
|
204
199
|
* In this case, the check step fails for a reason that doesn't have any
|
|
205
200
|
* special handling in this location. E.g. network error, server error, etc.
|
|
206
201
|
*/
|
|
207
|
-
export const UnknownFailureOnCheckCode
|
|
202
|
+
export const UnknownFailureOnCheckCode = meta.story({
|
|
208
203
|
parameters: {
|
|
209
204
|
msw: {
|
|
210
205
|
handlers: {
|
|
@@ -212,7 +207,7 @@ export const UnknownFailureOnCheckCode: Story = {
|
|
|
212
207
|
},
|
|
213
208
|
},
|
|
214
209
|
},
|
|
215
|
-
};
|
|
210
|
+
});
|
|
216
211
|
|
|
217
212
|
/**
|
|
218
213
|
* In this case, the final set password step fails because the token has
|
|
@@ -222,7 +217,7 @@ export const UnknownFailureOnCheckCode: Story = {
|
|
|
222
217
|
* because the user has gotten through the check step, that would require
|
|
223
218
|
* some very strange set of circumstances.
|
|
224
219
|
*/
|
|
225
|
-
export const NotFoundOrExpiredOnSetPassword
|
|
220
|
+
export const NotFoundOrExpiredOnSetPassword = meta.story({
|
|
226
221
|
parameters: {
|
|
227
222
|
msw: {
|
|
228
223
|
handlers: {
|
|
@@ -230,13 +225,13 @@ export const NotFoundOrExpiredOnSetPassword: Story = {
|
|
|
230
225
|
},
|
|
231
226
|
},
|
|
232
227
|
},
|
|
233
|
-
};
|
|
228
|
+
});
|
|
234
229
|
|
|
235
230
|
/**
|
|
236
231
|
* In this case, the set password step fails for a reason that doesn't have any
|
|
237
232
|
* special handling in this location. E.g. network error, server error, etc.
|
|
238
233
|
*/
|
|
239
|
-
export const UnknownFailureOnSetPassword
|
|
234
|
+
export const UnknownFailureOnSetPassword = meta.story({
|
|
240
235
|
parameters: {
|
|
241
236
|
msw: {
|
|
242
237
|
handlers: {
|
|
@@ -244,4 +239,4 @@ export const UnknownFailureOnSetPassword: Story = {
|
|
|
244
239
|
},
|
|
245
240
|
},
|
|
246
241
|
},
|
|
247
|
-
};
|
|
242
|
+
});
|
|
@@ -10,8 +10,18 @@ export function useFetchCurrentUser(options?: {
|
|
|
10
10
|
* @default true
|
|
11
11
|
*/
|
|
12
12
|
performFetch?: boolean;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Fetch new data every time the window is focused.
|
|
16
|
+
*
|
|
17
|
+
* Note that `performFetch` has to be enabled for this option to have an
|
|
18
|
+
* effect — we are not revalidating when there is no fetch to do!
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
revalidateOnFocus?: boolean;
|
|
13
23
|
}) {
|
|
14
|
-
const { performFetch = true } = options ?? {};
|
|
24
|
+
const { performFetch = true, revalidateOnFocus = false } = options ?? {};
|
|
15
25
|
const client = useClient();
|
|
16
26
|
const [latestAttemptTs, setLatestAttemptTs] = useState(Date.now());
|
|
17
27
|
|
|
@@ -31,12 +41,14 @@ export function useFetchCurrentUser(options?: {
|
|
|
31
41
|
// Invoke the fetch action
|
|
32
42
|
fetchUserAndStoreResult();
|
|
33
43
|
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
if (revalidateOnFocus) {
|
|
45
|
+
const controller = new AbortController();
|
|
46
|
+
window.addEventListener("focus", fetchUserAndStoreResult, controller);
|
|
36
47
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
return () => {
|
|
49
|
+
controller.abort();
|
|
50
|
+
};
|
|
51
|
+
}
|
|
40
52
|
}
|
|
41
53
|
}, [client, latestAttemptTs, performFetch]);
|
|
42
54
|
|
package/lib/client.ts
CHANGED
|
@@ -545,7 +545,7 @@ export class IndieTabletopClient {
|
|
|
545
545
|
});
|
|
546
546
|
|
|
547
547
|
return await this.fetch(
|
|
548
|
-
`/v1/me/data?${params}`,
|
|
548
|
+
`/v1/me/game-data?${params}`,
|
|
549
549
|
unknown() as Struct<UserGameData, null>,
|
|
550
550
|
);
|
|
551
551
|
}
|
|
@@ -557,7 +557,7 @@ export class IndieTabletopClient {
|
|
|
557
557
|
expectCurrentUserId: string | null | undefined;
|
|
558
558
|
}) {
|
|
559
559
|
return await this.fetch(
|
|
560
|
-
`/v1/me/data`,
|
|
560
|
+
`/v1/me/game-data`,
|
|
561
561
|
unknown() as Struct<UserGameData, null>,
|
|
562
562
|
{
|
|
563
563
|
method: "PATCH",
|
package/lib/index.ts
CHANGED
|
@@ -23,7 +23,7 @@ export * from "./ReleaseInfo/index.tsx";
|
|
|
23
23
|
export * from "./ServiceWorkerHandler.tsx";
|
|
24
24
|
export * from "./ShareButton/ShareButton.tsx";
|
|
25
25
|
export * from "./SubscribeCard/SubscribeByEmailCard.tsx";
|
|
26
|
-
export * from "./SubscribeCard/
|
|
26
|
+
export * from "./SubscribeCard/SubscribeByPledgeCard.tsx";
|
|
27
27
|
|
|
28
28
|
// Hooks
|
|
29
29
|
export * from "./RulesetResolver.ts";
|
package/lib/types/spacegits.ts
CHANGED
|
@@ -33,13 +33,17 @@ export function ref() {
|
|
|
33
33
|
return object({ id: string() });
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
export function weaponRef() {
|
|
37
|
+
return assign(ref(), object({ count: number() }));
|
|
38
|
+
}
|
|
39
|
+
|
|
36
40
|
export function treatmentRef() {
|
|
37
41
|
return assign(ref(), object({ locationId: string() }));
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
export function vehicleWeaponRef() {
|
|
41
45
|
return assign(
|
|
42
|
-
|
|
46
|
+
weaponRef(),
|
|
43
47
|
object({ placement: enums(["FIXED", "PINTLE_MOUNTED"]) }),
|
|
44
48
|
);
|
|
45
49
|
}
|
|
@@ -53,7 +57,7 @@ export function gitData() {
|
|
|
53
57
|
id: string(),
|
|
54
58
|
type: ref(),
|
|
55
59
|
name: string(),
|
|
56
|
-
weapons: array(
|
|
60
|
+
weapons: array(weaponRef()),
|
|
57
61
|
gear: array(ref()),
|
|
58
62
|
offenses: array(ref()),
|
|
59
63
|
treatments: array(treatmentRef()),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@indietabletop/appkit",
|
|
3
|
-
"version": "5.0.0-
|
|
3
|
+
"version": "5.0.0-2",
|
|
4
4
|
"description": "A collection of modules used in apps built by Indie Tabletop Club",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -20,20 +20,23 @@
|
|
|
20
20
|
"/lib"
|
|
21
21
|
],
|
|
22
22
|
"author": "Artur Müller",
|
|
23
|
-
"repository":
|
|
24
|
-
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/indietabletop/appkit.git"
|
|
26
|
+
},
|
|
27
|
+
"license": "UNLICENSED",
|
|
25
28
|
"peerDependencies": {
|
|
26
29
|
"react": "^18.0.0 || ^19.0.0"
|
|
27
30
|
},
|
|
28
31
|
"devDependencies": {
|
|
29
|
-
"@storybook/addon-docs": "^
|
|
30
|
-
"@storybook/addon-links": "^
|
|
31
|
-
"@storybook/react-vite": "^
|
|
32
|
+
"@storybook/addon-docs": "^10.0.4",
|
|
33
|
+
"@storybook/addon-links": "^10.0.4",
|
|
34
|
+
"@storybook/react-vite": "^10.0.4",
|
|
32
35
|
"@types/react": "^19.1.8",
|
|
33
36
|
"msw": "^2.11.2",
|
|
34
37
|
"msw-storybook-addon": "^2.0.5",
|
|
35
38
|
"np": "^10.1.0",
|
|
36
|
-
"storybook": "^
|
|
39
|
+
"storybook": "^10.0.4",
|
|
37
40
|
"typescript": "^5.8.2",
|
|
38
41
|
"vite": "^6.3.5",
|
|
39
42
|
"vitest": "^3.2.4"
|