@indietabletop/appkit 3.2.0-0 → 3.2.0-10
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/ExternalLink.tsx +10 -0
- package/lib/FormSubmitButton.tsx +58 -0
- package/lib/FullscreenDismissBlocker.tsx +23 -0
- package/lib/IndieTabletopClubLogo.tsx +44 -0
- package/lib/IndieTabletopClubSymbol.tsx +37 -0
- package/lib/Letterhead/index.tsx +85 -0
- package/lib/Letterhead/stories.tsx +45 -0
- package/lib/Letterhead/style.css.ts +141 -0
- package/lib/LetterheadForm/LetterheadReadonlyTextField.stories.tsx +21 -0
- package/lib/LetterheadForm/LetterheadSubmitError.stories.tsx +23 -0
- package/lib/LetterheadForm/LetterheadTextField.stories.tsx +23 -0
- package/lib/LetterheadForm/index.tsx +94 -0
- package/lib/LetterheadForm/style.css.ts +80 -0
- package/lib/LoadingIndicator.tsx +39 -0
- package/lib/ServiceWorkerHandler.tsx +53 -0
- package/lib/animations.css.ts +17 -0
- package/lib/append-copy-to-text.test.ts +29 -0
- package/lib/append-copy-to-text.ts +35 -0
- package/lib/async-op.ts +246 -0
- package/lib/atomic.css.ts +11 -0
- package/{dist/caught-value.js → lib/caught-value.ts} +10 -8
- package/lib/class-names.ts +33 -0
- package/lib/client.ts +288 -0
- package/lib/common.css.ts +48 -0
- package/lib/failureMessages.test.ts +138 -0
- package/lib/failureMessages.ts +76 -0
- package/lib/globals.css.ts +45 -0
- package/{dist/index.d.ts → lib/index.ts} +9 -1
- package/lib/internal.css.ts +10 -0
- package/lib/media.ts +50 -0
- package/lib/storybook/decorators.tsx +10 -0
- package/lib/structs.ts +17 -0
- package/{dist/types.d.ts → lib/types.ts} +11 -6
- package/lib/use-async-op.ts +16 -0
- package/lib/use-document-background-color.ts +16 -0
- package/lib/use-form.ts +73 -0
- package/{dist/use-is-installed.js → lib/use-is-installed.ts} +7 -3
- package/lib/use-media-query.ts +21 -0
- package/lib/use-reverting-state.ts +32 -0
- package/lib/use-scroll-restoration.ts +99 -0
- package/lib/validations.ts +25 -0
- package/lib/vars.css.ts +9 -0
- package/package.json +15 -7
- package/dist/ExternalLink.d.ts +0 -3
- package/dist/ExternalLink.js +0 -4
- package/dist/FormSubmitButton.d.ts +0 -7
- package/dist/FormSubmitButton.js +0 -16
- package/dist/FullscreenDismissBlocker.d.ts +0 -5
- package/dist/FullscreenDismissBlocker.js +0 -19
- package/dist/IndieTabletopClubFooter.d.ts +0 -1
- package/dist/IndieTabletopClubFooter.js +0 -17
- package/dist/IndieTabletopClubLogo.d.ts +0 -7
- package/dist/IndieTabletopClubLogo.js +0 -6
- package/dist/IndieTabletopClubSymbol.d.ts +0 -7
- package/dist/IndieTabletopClubSymbol.js +0 -5
- package/dist/Letterhead.d.ts +0 -6
- package/dist/Letterhead.js +0 -14
- package/dist/LetterheadFooter.d.ts +0 -1
- package/dist/LetterheadFooter.js +0 -17
- package/dist/LoadingIndicator.d.ts +0 -3
- package/dist/LoadingIndicator.js +0 -17
- package/dist/ServiceWorkerHandler.d.ts +0 -11
- package/dist/ServiceWorkerHandler.js +0 -42
- package/dist/animations.css.d.ts +0 -3
- package/dist/animations.css.js +0 -14
- package/dist/append-copy-to-text.d.ts +0 -10
- package/dist/append-copy-to-text.js +0 -29
- package/dist/async-op.d.ts +0 -87
- package/dist/async-op.js +0 -223
- package/dist/caught-value.d.ts +0 -15
- package/dist/class-names.d.ts +0 -4
- package/dist/class-names.js +0 -6
- package/dist/client.d.ts +0 -117
- package/dist/client.js +0 -201
- package/dist/common.css.d.ts +0 -5
- package/dist/common.css.js +0 -38
- package/dist/defineNetlifyConfig.d.ts +0 -34
- package/dist/defineNetlifyConfig.js +0 -35
- package/dist/external-link.d.ts +0 -4
- package/dist/external-link.js +0 -4
- package/dist/form-submit-button.d.ts +0 -7
- package/dist/form-submit-button.js +0 -16
- package/dist/fullscreen-dismiss-blocker.d.ts +0 -5
- package/dist/fullscreen-dismiss-blocker.js +0 -19
- package/dist/globals.css.d.ts +0 -1
- package/dist/globals.css.js +0 -35
- package/dist/index.js +0 -25
- package/dist/internal.css.d.ts +0 -4
- package/dist/internal.css.js +0 -21
- package/dist/media.d.ts +0 -39
- package/dist/media.js +0 -49
- package/dist/service-worker-handler.d.ts +0 -11
- package/dist/service-worker-handler.js +0 -42
- package/dist/structs.d.ts +0 -20
- package/dist/structs.js +0 -15
- package/dist/types.js +0 -1
- package/dist/use-async-op.d.ts +0 -6
- package/dist/use-async-op.js +0 -12
- package/dist/use-document-background-color.d.ts +0 -4
- package/dist/use-document-background-color.js +0 -14
- package/dist/use-form.d.ts +0 -29
- package/dist/use-form.js +0 -33
- package/dist/use-is-installed.d.ts +0 -8
- package/dist/use-media-query.d.ts +0 -1
- package/dist/use-media-query.js +0 -15
- package/dist/use-reverting-state.d.ts +0 -5
- package/dist/use-reverting-state.js +0 -26
- package/dist/use-scroll-restoration.d.ts +0 -25
- package/dist/use-scroll-restoration.js +0 -67
package/dist/client.js
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import { Failure, Success } from "@indietabletop/appkit/async-op";
|
|
2
|
-
import { mask, object, string, Struct } from "superstruct";
|
|
3
|
-
import { currentUser, sessionInfo } from "./structs.js";
|
|
4
|
-
export class IndieTabletopClient {
|
|
5
|
-
constructor(props) {
|
|
6
|
-
Object.defineProperty(this, "origin", {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
configurable: true,
|
|
9
|
-
writable: true,
|
|
10
|
-
value: void 0
|
|
11
|
-
});
|
|
12
|
-
Object.defineProperty(this, "onCurrentUser", {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
configurable: true,
|
|
15
|
-
writable: true,
|
|
16
|
-
value: void 0
|
|
17
|
-
});
|
|
18
|
-
Object.defineProperty(this, "onSessionInfo", {
|
|
19
|
-
enumerable: true,
|
|
20
|
-
configurable: true,
|
|
21
|
-
writable: true,
|
|
22
|
-
value: void 0
|
|
23
|
-
});
|
|
24
|
-
Object.defineProperty(this, "onSessionExpired", {
|
|
25
|
-
enumerable: true,
|
|
26
|
-
configurable: true,
|
|
27
|
-
writable: true,
|
|
28
|
-
value: void 0
|
|
29
|
-
});
|
|
30
|
-
Object.defineProperty(this, "refreshTokenPromise", {
|
|
31
|
-
enumerable: true,
|
|
32
|
-
configurable: true,
|
|
33
|
-
writable: true,
|
|
34
|
-
value: void 0
|
|
35
|
-
});
|
|
36
|
-
this.origin = props.apiOrigin;
|
|
37
|
-
this.onCurrentUser = props.onCurrentUser;
|
|
38
|
-
this.onSessionInfo = props.onSessionInfo;
|
|
39
|
-
this.onSessionExpired = props.onSessionExpired;
|
|
40
|
-
}
|
|
41
|
-
async fetch(path, struct, init) {
|
|
42
|
-
// If json was provided, we stringify it. Otherwise we use body.
|
|
43
|
-
const body = init?.json ? JSON.stringify(init.json) : init?.body;
|
|
44
|
-
// If json was provided, we make sure that content type is correctly set.
|
|
45
|
-
const headers = init?.json
|
|
46
|
-
? { ...init?.headers, "Content-Type": "application/json" }
|
|
47
|
-
: init?.headers;
|
|
48
|
-
try {
|
|
49
|
-
const res = await fetch(`${this.origin}${path}`, {
|
|
50
|
-
// Defaults
|
|
51
|
-
credentials: "include",
|
|
52
|
-
// Overrides
|
|
53
|
-
...init,
|
|
54
|
-
body,
|
|
55
|
-
headers,
|
|
56
|
-
});
|
|
57
|
-
if (!res.ok) {
|
|
58
|
-
console.error(res);
|
|
59
|
-
return new Failure({ type: "API_ERROR", code: res.status });
|
|
60
|
-
}
|
|
61
|
-
try {
|
|
62
|
-
const data = mask(await res.json(), struct);
|
|
63
|
-
return new Success(data);
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
console.error(error);
|
|
67
|
-
return new Failure({ type: "VALIDATION_ERROR" });
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
console.error(error);
|
|
72
|
-
if (error instanceof Error) {
|
|
73
|
-
return new Failure({ type: "NETWORK_ERROR" });
|
|
74
|
-
}
|
|
75
|
-
return new Failure({ type: "UNKNOWN_ERROR" });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Fetches data and retries 401 failures after attempting to refresh tokens.
|
|
80
|
-
*/
|
|
81
|
-
async fetchWithAuth(path, struct, init) {
|
|
82
|
-
const op = await this.fetch(path, struct, init);
|
|
83
|
-
if (op.isSuccess) {
|
|
84
|
-
return op;
|
|
85
|
-
}
|
|
86
|
-
if (op.failure.type === "API_ERROR" && op.failure.code === 401) {
|
|
87
|
-
console.info("API request failed with error 401. Refreshing tokens.");
|
|
88
|
-
const refreshOp = await this.refreshTokens();
|
|
89
|
-
if (refreshOp.isSuccess) {
|
|
90
|
-
console.info("Tokens refreshed. Retrying request.");
|
|
91
|
-
return await this.fetch(path, struct, init);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
console.info("Could not refresh tokens.");
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return op;
|
|
98
|
-
}
|
|
99
|
-
async login(payload) {
|
|
100
|
-
const result = await this.fetch("/v1/sessions", object({
|
|
101
|
-
currentUser: currentUser(),
|
|
102
|
-
sessionInfo: sessionInfo(),
|
|
103
|
-
}), {
|
|
104
|
-
method: "POST",
|
|
105
|
-
json: { email: payload.email, plaintextPassword: payload.password },
|
|
106
|
-
});
|
|
107
|
-
if (result.isSuccess) {
|
|
108
|
-
this.onCurrentUser?.(result.value.currentUser);
|
|
109
|
-
this.onSessionInfo?.(result.value.sessionInfo);
|
|
110
|
-
}
|
|
111
|
-
return result;
|
|
112
|
-
}
|
|
113
|
-
async logout() {
|
|
114
|
-
return await this.fetch("/v1/sessions", object({ message: string() }), {
|
|
115
|
-
method: "DELETE",
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
async join(payload) {
|
|
119
|
-
const res = await this.fetch("/v1/users", object({
|
|
120
|
-
currentUser: currentUser(),
|
|
121
|
-
sessionInfo: sessionInfo(),
|
|
122
|
-
tokenId: string(),
|
|
123
|
-
}), {
|
|
124
|
-
method: "POST",
|
|
125
|
-
json: {
|
|
126
|
-
email: payload.email,
|
|
127
|
-
plaintextPassword: payload.password,
|
|
128
|
-
acceptedTos: payload.acceptedTos,
|
|
129
|
-
subscribedToNewsletter: payload.subscribedToNewsletter,
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
if (res.isSuccess) {
|
|
133
|
-
this.onCurrentUser?.(res.value.currentUser);
|
|
134
|
-
this.onSessionInfo?.(res.value.sessionInfo);
|
|
135
|
-
}
|
|
136
|
-
return res;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Triggers token refresh process.
|
|
140
|
-
*
|
|
141
|
-
* Note that we do not want to perform multiple concurrent token refresh
|
|
142
|
-
* actions, as that will result in unnecessary 401s. For this reason, a
|
|
143
|
-
* reference to t
|
|
144
|
-
*/
|
|
145
|
-
async refreshTokens() {
|
|
146
|
-
// If there is an ongoing token refresh in progress return that. This should
|
|
147
|
-
// only deal the response payload, none of the side-effects and cleanup,
|
|
148
|
-
// which will be handled by the initial invocation.
|
|
149
|
-
const ongoingRequest = this.refreshTokenPromise;
|
|
150
|
-
if (ongoingRequest) {
|
|
151
|
-
console.info("Token refresh ongoing. Reusing existing promise.");
|
|
152
|
-
return await ongoingRequest;
|
|
153
|
-
}
|
|
154
|
-
// Cache the promise on an instance property to share a reference from
|
|
155
|
-
// other potential invocations.
|
|
156
|
-
this.refreshTokenPromise = this.fetch("/v1/sessions/access-tokens", object({ sessionInfo: sessionInfo() }), { method: "POST" });
|
|
157
|
-
const result = await this.refreshTokenPromise;
|
|
158
|
-
if (result.isSuccess) {
|
|
159
|
-
this.onSessionInfo?.(result.value.sessionInfo);
|
|
160
|
-
}
|
|
161
|
-
if (result.isFailure &&
|
|
162
|
-
result.failure.type === "API_ERROR" &&
|
|
163
|
-
result.failure.code === 401) {
|
|
164
|
-
this.onSessionExpired?.();
|
|
165
|
-
}
|
|
166
|
-
// Make sure to reset the shared reference so that subsequent invocations
|
|
167
|
-
// once again initiate token refresh.
|
|
168
|
-
delete this.refreshTokenPromise;
|
|
169
|
-
return result;
|
|
170
|
-
}
|
|
171
|
-
async requestPasswordReset(payload) {
|
|
172
|
-
return await this.fetch(`/v1/password-reset-tokens`, object({ message: string(), tokenId: string() }), { method: "POST", json: payload });
|
|
173
|
-
}
|
|
174
|
-
async checkPasswordResetCode(payload) {
|
|
175
|
-
const queryParams = new URLSearchParams({ plaintextCode: payload.code });
|
|
176
|
-
return await this.fetch(`/v1/password-reset-tokens/${payload.tokenId}?${queryParams}`, object({ message: string() }), { method: "GET" });
|
|
177
|
-
}
|
|
178
|
-
async setNewPassword(payload) {
|
|
179
|
-
const queryParams = new URLSearchParams({ plaintextCode: payload.code });
|
|
180
|
-
return await this.fetch(`/v1/password-reset-tokens/${payload.tokenId}?${queryParams}`, object({ message: string() }), { method: "PUT", json: { plaintextPassword: payload.password } });
|
|
181
|
-
}
|
|
182
|
-
async requestUserVerification() {
|
|
183
|
-
return await this.fetch(`/v1/user-verification-tokens`, object({ message: string(), tokenId: string() }), { method: "POST" });
|
|
184
|
-
}
|
|
185
|
-
async verifyUser(payload) {
|
|
186
|
-
const queryParams = new URLSearchParams({ plaintextCode: payload.code });
|
|
187
|
-
const req = await this.fetch(`/v1/user-verification-tokens/${payload.tokenId}?${queryParams}`, object({ message: string() }), { method: "PUT" });
|
|
188
|
-
if (req.isSuccess) {
|
|
189
|
-
await this.refreshTokens();
|
|
190
|
-
await this.getCurrentUser();
|
|
191
|
-
}
|
|
192
|
-
return req;
|
|
193
|
-
}
|
|
194
|
-
async getCurrentUser() {
|
|
195
|
-
const result = await this.fetchWithAuth(`/v1/users/me`, currentUser());
|
|
196
|
-
if (result.isSuccess) {
|
|
197
|
-
this.onCurrentUser?.(result.value);
|
|
198
|
-
}
|
|
199
|
-
return result;
|
|
200
|
-
}
|
|
201
|
-
}
|
package/dist/common.css.d.ts
DELETED
package/dist/common.css.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { style } from "@vanilla-extract/css";
|
|
2
|
-
import { Hover, MinWidth } from "./media.js";
|
|
3
|
-
export const itcSymbol = style({
|
|
4
|
-
inlineSize: "2.5rem",
|
|
5
|
-
blockSize: "2.5rem",
|
|
6
|
-
margin: "0rem auto 0.75rem",
|
|
7
|
-
"@media": {
|
|
8
|
-
[MinWidth.MEDIUM]: {
|
|
9
|
-
marginBlock: "-1rem 1.5rem",
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
});
|
|
13
|
-
export const manofa = style({
|
|
14
|
-
fontFamily: `"manofa", sans-serif`,
|
|
15
|
-
});
|
|
16
|
-
export const minion = style({
|
|
17
|
-
fontFamily: `"minion-pro", serif`,
|
|
18
|
-
});
|
|
19
|
-
export const itcCard = style([
|
|
20
|
-
minion,
|
|
21
|
-
{
|
|
22
|
-
backgroundColor: "white",
|
|
23
|
-
},
|
|
24
|
-
]);
|
|
25
|
-
export const interactiveText = style({
|
|
26
|
-
display: "inline",
|
|
27
|
-
textDecoration: "underline",
|
|
28
|
-
textDecorationColor: "hsl(from currentcolor h s l / 0.3)",
|
|
29
|
-
textUnderlineOffset: "0.15em",
|
|
30
|
-
"@media": {
|
|
31
|
-
[Hover.HOVER]: {
|
|
32
|
-
transition: "text-decoration-color 200ms",
|
|
33
|
-
":hover": {
|
|
34
|
-
textDecorationColor: "hsl(from currentcolor h s l / 1)",
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { ConfigEnv, PluginOption, UserConfig } from "vite";
|
|
2
|
-
export declare function defineNetlifyConfig(props: {
|
|
3
|
-
/**
|
|
4
|
-
* The server port number.
|
|
5
|
-
*
|
|
6
|
-
* Game apps start from 8000, automation apps from 9000. So far, we got:
|
|
7
|
-
*
|
|
8
|
-
* - API: 8000
|
|
9
|
-
* - Hobgoblin: 8001
|
|
10
|
-
* - Eternol: 8002
|
|
11
|
-
* - Gregbot: 9000
|
|
12
|
-
*/
|
|
13
|
-
port: number;
|
|
14
|
-
/**
|
|
15
|
-
* By default, react and vanilla extract are always configured.
|
|
16
|
-
*/
|
|
17
|
-
additionalPlugins?: PluginOption[];
|
|
18
|
-
/**
|
|
19
|
-
* Can be used to import from `@` at the path specified here. Has to match
|
|
20
|
-
* tsconfig > compilerOptions > paths.
|
|
21
|
-
*
|
|
22
|
-
* Do not use this, just use relative imports.
|
|
23
|
-
*
|
|
24
|
-
* @deprecated
|
|
25
|
-
*/
|
|
26
|
-
resolveAlias?: string;
|
|
27
|
-
/**
|
|
28
|
-
* Determines whether input is "/index.html", or "index.html" or
|
|
29
|
-
* "/src/main.tsx" depnending on command.
|
|
30
|
-
*
|
|
31
|
-
* This is useful when using pre-rendered HTML as input.
|
|
32
|
-
*/
|
|
33
|
-
conditionalInput?: boolean;
|
|
34
|
-
}): ({ command }: ConfigEnv) => UserConfig;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { vanillaExtractPlugin as vanilla } from "@vanilla-extract/vite-plugin";
|
|
2
|
-
import react from "@vitejs/plugin-react";
|
|
3
|
-
export function defineNetlifyConfig(props) {
|
|
4
|
-
const { additionalPlugins = [], conditionalInput = false, resolveAlias, } = props;
|
|
5
|
-
return function configureVite({ command }) {
|
|
6
|
-
return {
|
|
7
|
-
define: {
|
|
8
|
-
// These vars are supplied by Netlify
|
|
9
|
-
BRANCH: JSON.stringify(process.env.BRANCH),
|
|
10
|
-
COMMIT_SHORTCODE: JSON.stringify(process.env.COMMIT_REF?.slice(0, 7)),
|
|
11
|
-
},
|
|
12
|
-
plugins: [react(), vanilla(), ...additionalPlugins],
|
|
13
|
-
esbuild: {
|
|
14
|
-
target: "es2022",
|
|
15
|
-
},
|
|
16
|
-
server: {
|
|
17
|
-
port: props.port,
|
|
18
|
-
},
|
|
19
|
-
resolve: {
|
|
20
|
-
alias: resolveAlias ? { "@": resolveAlias } : undefined,
|
|
21
|
-
},
|
|
22
|
-
build: {
|
|
23
|
-
sourcemap: true,
|
|
24
|
-
manifest: true,
|
|
25
|
-
rollupOptions: {
|
|
26
|
-
// During `build`, we want to only deal with JS files. Production HTML
|
|
27
|
-
// entrypoint is generated via the `build:entrypoint` package script.
|
|
28
|
-
input: conditionalInput && command === "build"
|
|
29
|
-
? "/src/main.tsx"
|
|
30
|
-
: "/index.html",
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
}
|
package/dist/external-link.d.ts
DELETED
package/dist/external-link.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { type FormSubmitProps } from "@ariakit/react";
|
|
2
|
-
import type { ReactNode } from "react";
|
|
3
|
-
export type FormSubmitButtonProps = FormSubmitProps & {
|
|
4
|
-
children: ReactNode;
|
|
5
|
-
loading: ReactNode;
|
|
6
|
-
};
|
|
7
|
-
export declare function FormSubmitButton(props: FormSubmitButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { FormSubmit, useFormContext, useStoreState, } from "@ariakit/react";
|
|
3
|
-
import { fadeIn } from "./animations.css.js";
|
|
4
|
-
export function FormSubmitButton(props) {
|
|
5
|
-
const { children, className, style, loading, ...submitProps } = props;
|
|
6
|
-
const form = useFormContext();
|
|
7
|
-
const isSubmitting = useStoreState(form, (s) => s?.submitting);
|
|
8
|
-
return (_jsxs(FormSubmit, { ...submitProps, className: className, style: { position: "relative", ...style }, children: [_jsx("span", { style: { opacity: isSubmitting ? 0 : 1, transition: "200ms opacity" }, children: children }), isSubmitting && (_jsx("div", { style: {
|
|
9
|
-
display: "flex",
|
|
10
|
-
position: "absolute",
|
|
11
|
-
inset: "0",
|
|
12
|
-
alignItems: "center",
|
|
13
|
-
justifyContent: "center",
|
|
14
|
-
animation: `${fadeIn} 200ms 200ms both`,
|
|
15
|
-
}, children: loading }))] }));
|
|
16
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
2
|
-
function handleKeydown(event) {
|
|
3
|
-
if (event.key === "Escape") {
|
|
4
|
-
event.preventDefault();
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* This component prevents the default MacOS behaviour where a fullscreen window
|
|
9
|
-
* gets minimised by pressing Escape.
|
|
10
|
-
*/
|
|
11
|
-
export function FullscreenDismissBlocker() {
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
window.addEventListener("keydown", handleKeydown);
|
|
14
|
-
return () => {
|
|
15
|
-
window.removeEventListener("keydown", handleKeydown);
|
|
16
|
-
};
|
|
17
|
-
}, []);
|
|
18
|
-
return null;
|
|
19
|
-
}
|
package/dist/globals.css.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/globals.css.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { globalStyle } from "@vanilla-extract/css";
|
|
2
|
-
globalStyle(":root", {
|
|
3
|
-
fontSynthesis: "none",
|
|
4
|
-
textRendering: "optimizeLegibility",
|
|
5
|
-
WebkitFontSmoothing: "antialiased",
|
|
6
|
-
MozOsxFontSmoothing: "grayscale",
|
|
7
|
-
});
|
|
8
|
-
globalStyle("*", {
|
|
9
|
-
boxSizing: "border-box",
|
|
10
|
-
});
|
|
11
|
-
globalStyle("img, picture, svg", {
|
|
12
|
-
display: "block",
|
|
13
|
-
});
|
|
14
|
-
globalStyle("a", {
|
|
15
|
-
display: "block",
|
|
16
|
-
color: "inherit",
|
|
17
|
-
textDecoration: "none",
|
|
18
|
-
});
|
|
19
|
-
globalStyle("input, textarea", {
|
|
20
|
-
fontFamily: "inherit",
|
|
21
|
-
});
|
|
22
|
-
globalStyle("button", {
|
|
23
|
-
display: "block",
|
|
24
|
-
fontSize: "inherit",
|
|
25
|
-
fontFamily: "inherit",
|
|
26
|
-
backgroundColor: "transparent",
|
|
27
|
-
border: "none",
|
|
28
|
-
color: "inherit",
|
|
29
|
-
cursor: "pointer",
|
|
30
|
-
padding: 0,
|
|
31
|
-
});
|
|
32
|
-
globalStyle("body, h1, h2, h3, h4, h5, h6, p, ul, li, ol", {
|
|
33
|
-
margin: 0,
|
|
34
|
-
padding: 0,
|
|
35
|
-
});
|
package/dist/index.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// Components
|
|
2
|
-
export * from "./ExternalLink.js";
|
|
3
|
-
export * from "./FormSubmitButton.js";
|
|
4
|
-
export * from "./FullscreenDismissBlocker.js";
|
|
5
|
-
export * from "./IndieTabletopClubSymbol.js";
|
|
6
|
-
export * from "./LetterheadFooter.js";
|
|
7
|
-
export * from "./LoadingIndicator.js";
|
|
8
|
-
export * from "./ServiceWorkerHandler.js";
|
|
9
|
-
// Hooks
|
|
10
|
-
export * from "./use-async-op.js";
|
|
11
|
-
export * from "./use-document-background-color.js";
|
|
12
|
-
export * from "./use-form.js";
|
|
13
|
-
export * from "./use-is-installed.js";
|
|
14
|
-
export * from "./use-media-query.js";
|
|
15
|
-
export * from "./use-reverting-state.js";
|
|
16
|
-
export * from "./use-scroll-restoration.js";
|
|
17
|
-
// Utils
|
|
18
|
-
export * from "./append-copy-to-text.js";
|
|
19
|
-
export * from "./async-op.js";
|
|
20
|
-
export * from "./caught-value.js";
|
|
21
|
-
export * from "./class-names.js";
|
|
22
|
-
export * from "./client.js";
|
|
23
|
-
export * from "./media.js";
|
|
24
|
-
export * from "./structs.js";
|
|
25
|
-
export * from "./types.js";
|
package/dist/internal.css.d.ts
DELETED
package/dist/internal.css.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { createVar, style } from "@vanilla-extract/css";
|
|
2
|
-
import { bounce } from "./animations.css.js";
|
|
3
|
-
import { minion } from "./common.css.js";
|
|
4
|
-
export const animationDelay = createVar();
|
|
5
|
-
export const dot = style({
|
|
6
|
-
fill: "currentcolor",
|
|
7
|
-
opacity: 0.8,
|
|
8
|
-
animation: `${bounce} 2s ${animationDelay} infinite`,
|
|
9
|
-
});
|
|
10
|
-
export const padding = createVar();
|
|
11
|
-
export const letterhead = style([
|
|
12
|
-
minion,
|
|
13
|
-
{
|
|
14
|
-
vars: { [padding]: "clamp(1rem, 8vw, 4rem)" },
|
|
15
|
-
backgroundColor: "white",
|
|
16
|
-
padding: `max(1rem, calc(${padding} - .5rem)) ${padding} ${padding}`,
|
|
17
|
-
borderRadius: "1rem",
|
|
18
|
-
marginInline: "auto",
|
|
19
|
-
maxInlineSize: "36rem",
|
|
20
|
-
},
|
|
21
|
-
]);
|
package/dist/media.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
|
3
|
-
*/
|
|
4
|
-
export declare enum PrefersColorScheme {
|
|
5
|
-
LIGHT = "(prefers-color-scheme: light)",
|
|
6
|
-
DARK = "(prefers-color-scheme: dark)"
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
|
|
10
|
-
*/
|
|
11
|
-
export declare enum PrefersReducedMotion {
|
|
12
|
-
NO_PREFERENCE = "(prefers-reduced-motion: no-preference)",
|
|
13
|
-
REDUCE = "(prefers-reduced-motion: reduce)"
|
|
14
|
-
}
|
|
15
|
-
export declare enum Hover {
|
|
16
|
-
NONE = "(hover: none)",
|
|
17
|
-
HOVER = "(hover: hover) and (pointer: fine)"
|
|
18
|
-
}
|
|
19
|
-
export declare enum MediaType {
|
|
20
|
-
PRINT = "print",
|
|
21
|
-
SCREEN = "screen"
|
|
22
|
-
}
|
|
23
|
-
export declare enum MinHeight {
|
|
24
|
-
TALL = "(min-height: 40em)"
|
|
25
|
-
}
|
|
26
|
-
export declare enum MinWidth {
|
|
27
|
-
SMALL = "(min-width: 28em)",
|
|
28
|
-
MEDIUM = "(min-width: 50em)",
|
|
29
|
-
WIDE = "(min-width: 66em)",
|
|
30
|
-
X_WIDE = "(min-width: 80em)",
|
|
31
|
-
XX_WIDE = "(min-width: 140em)"
|
|
32
|
-
}
|
|
33
|
-
export declare enum DisplayMode {
|
|
34
|
-
STANDALONE = "(display-mode: standalone)"
|
|
35
|
-
}
|
|
36
|
-
export declare enum Pointer {
|
|
37
|
-
COARSE = "(pointer: coarse)",
|
|
38
|
-
FINE = "(pointer: fine)"
|
|
39
|
-
}
|
package/dist/media.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
|
3
|
-
*/
|
|
4
|
-
export var PrefersColorScheme;
|
|
5
|
-
(function (PrefersColorScheme) {
|
|
6
|
-
PrefersColorScheme["LIGHT"] = "(prefers-color-scheme: light)";
|
|
7
|
-
PrefersColorScheme["DARK"] = "(prefers-color-scheme: dark)";
|
|
8
|
-
})(PrefersColorScheme || (PrefersColorScheme = {}));
|
|
9
|
-
/**
|
|
10
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
|
|
11
|
-
*/
|
|
12
|
-
export var PrefersReducedMotion;
|
|
13
|
-
(function (PrefersReducedMotion) {
|
|
14
|
-
PrefersReducedMotion["NO_PREFERENCE"] = "(prefers-reduced-motion: no-preference)";
|
|
15
|
-
PrefersReducedMotion["REDUCE"] = "(prefers-reduced-motion: reduce)";
|
|
16
|
-
})(PrefersReducedMotion || (PrefersReducedMotion = {}));
|
|
17
|
-
export var Hover;
|
|
18
|
-
(function (Hover) {
|
|
19
|
-
Hover["NONE"] = "(hover: none)";
|
|
20
|
-
// Some Samsung phones incorrectly report that they have "hover" even though they
|
|
21
|
-
// do not. Adding the pointer query correctly filters these phones out.
|
|
22
|
-
Hover["HOVER"] = "(hover: hover) and (pointer: fine)";
|
|
23
|
-
})(Hover || (Hover = {}));
|
|
24
|
-
export var MediaType;
|
|
25
|
-
(function (MediaType) {
|
|
26
|
-
MediaType["PRINT"] = "print";
|
|
27
|
-
MediaType["SCREEN"] = "screen";
|
|
28
|
-
})(MediaType || (MediaType = {}));
|
|
29
|
-
export var MinHeight;
|
|
30
|
-
(function (MinHeight) {
|
|
31
|
-
MinHeight["TALL"] = "(min-height: 40em)";
|
|
32
|
-
})(MinHeight || (MinHeight = {}));
|
|
33
|
-
export var MinWidth;
|
|
34
|
-
(function (MinWidth) {
|
|
35
|
-
MinWidth["SMALL"] = "(min-width: 28em)";
|
|
36
|
-
MinWidth["MEDIUM"] = "(min-width: 50em)";
|
|
37
|
-
MinWidth["WIDE"] = "(min-width: 66em)";
|
|
38
|
-
MinWidth["X_WIDE"] = "(min-width: 80em)";
|
|
39
|
-
MinWidth["XX_WIDE"] = "(min-width: 140em)";
|
|
40
|
-
})(MinWidth || (MinWidth = {}));
|
|
41
|
-
export var DisplayMode;
|
|
42
|
-
(function (DisplayMode) {
|
|
43
|
-
DisplayMode["STANDALONE"] = "(display-mode: standalone)";
|
|
44
|
-
})(DisplayMode || (DisplayMode = {}));
|
|
45
|
-
export var Pointer;
|
|
46
|
-
(function (Pointer) {
|
|
47
|
-
Pointer["COARSE"] = "(pointer: coarse)";
|
|
48
|
-
Pointer["FINE"] = "(pointer: fine)";
|
|
49
|
-
})(Pointer || (Pointer = {}));
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type ReactNode } from "react";
|
|
2
|
-
/**
|
|
3
|
-
* This component handles the installation of a service worker.
|
|
4
|
-
*
|
|
5
|
-
* Currently it doesn't do much, but, eventually, it should provide context
|
|
6
|
-
* to nested components communicating the status of the service worker installation.
|
|
7
|
-
*/
|
|
8
|
-
export declare function ServiceWorkerHandler(props: {
|
|
9
|
-
children: ReactNode;
|
|
10
|
-
path: string;
|
|
11
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect } from "react";
|
|
3
|
-
/**
|
|
4
|
-
* This component handles the installation of a service worker.
|
|
5
|
-
*
|
|
6
|
-
* Currently it doesn't do much, but, eventually, it should provide context
|
|
7
|
-
* to nested components communicating the status of the service worker installation.
|
|
8
|
-
*/
|
|
9
|
-
export function ServiceWorkerHandler(props) {
|
|
10
|
-
useEffect(() => {
|
|
11
|
-
async function registerWorker() {
|
|
12
|
-
// Although modern browsers all support service workers, native app's
|
|
13
|
-
// web views (eg. the Facebook app's embedded browsers) do not.
|
|
14
|
-
if ("serviceWorker" in navigator) {
|
|
15
|
-
try {
|
|
16
|
-
const registration = await navigator.serviceWorker.register(props.path);
|
|
17
|
-
console.info("Service worker registration obtained.");
|
|
18
|
-
registration.addEventListener("updatefound", () => {
|
|
19
|
-
const worker = registration.installing;
|
|
20
|
-
console.info("Installing new service worker.");
|
|
21
|
-
worker?.addEventListener("statechange", ({ target }) => {
|
|
22
|
-
if (target instanceof ServiceWorker) {
|
|
23
|
-
console.info(`Service worker state changed: '${target.state}'.`);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
// In rare cases, service worker installation can fail, e.g. due to network
|
|
30
|
-
// connectivity. There is no need to report the error as there is nothing
|
|
31
|
-
// that can be done to prevent this from occassionally happening.
|
|
32
|
-
console.error(error);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
void registerWorker();
|
|
37
|
-
// Note that it is not necessary to 'cleanup' the registration in
|
|
38
|
-
// the useEffect hook. Calling register() multiple times is a no-op.
|
|
39
|
-
// See https://web.dev/articles/service-workers-registration#subsequent_visits
|
|
40
|
-
}, [props.path]);
|
|
41
|
-
return _jsx(_Fragment, { children: props.children });
|
|
42
|
-
}
|
package/dist/structs.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export declare function currentUser(): import("superstruct").Struct<{
|
|
2
|
-
id: string;
|
|
3
|
-
email: string;
|
|
4
|
-
isVerified: boolean;
|
|
5
|
-
prefersScrollbarVisibility?: "ALWAYS" | undefined;
|
|
6
|
-
}, {
|
|
7
|
-
id: import("superstruct").Struct<string, null>;
|
|
8
|
-
email: import("superstruct").Struct<string, null>;
|
|
9
|
-
isVerified: import("superstruct").Struct<boolean, null>;
|
|
10
|
-
prefersScrollbarVisibility: import("superstruct").Struct<"ALWAYS" | undefined, {
|
|
11
|
-
ALWAYS: "ALWAYS";
|
|
12
|
-
}>;
|
|
13
|
-
}>;
|
|
14
|
-
export declare function sessionInfo(): import("superstruct").Struct<{
|
|
15
|
-
expiresTs: number;
|
|
16
|
-
createdTs: number;
|
|
17
|
-
}, {
|
|
18
|
-
expiresTs: import("superstruct").Struct<number, null>;
|
|
19
|
-
createdTs: import("superstruct").Struct<number, null>;
|
|
20
|
-
}>;
|
package/dist/structs.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { boolean, enums, number, object, optional, string } from "superstruct";
|
|
2
|
-
export function currentUser() {
|
|
3
|
-
return object({
|
|
4
|
-
id: string(),
|
|
5
|
-
email: string(),
|
|
6
|
-
isVerified: boolean(),
|
|
7
|
-
prefersScrollbarVisibility: optional(enums(["ALWAYS"])),
|
|
8
|
-
});
|
|
9
|
-
}
|
|
10
|
-
export function sessionInfo() {
|
|
11
|
-
return object({
|
|
12
|
-
expiresTs: number(),
|
|
13
|
-
createdTs: number(),
|
|
14
|
-
});
|
|
15
|
-
}
|
package/dist/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import { currentUser, sessionInfo } from "./structs.js";
|