@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.
Files changed (269) hide show
  1. package/dist/AppConfig/AppConfig.d.ts +29 -0
  2. package/dist/AuthCard/AuthCard.d.ts +10 -0
  3. package/dist/AuthCard/AuthCard.stories.d.ts +34 -0
  4. package/dist/AuthCard/style.css.d.ts +23 -0
  5. package/dist/DialogTrigger/index.d.ts +13 -0
  6. package/dist/DocumentTitle/DocumentTitle.d.ts +3 -0
  7. package/dist/EnumMapper.d.ts +25 -0
  8. package/dist/ExternalLink.d.ts +3 -0
  9. package/dist/FullscreenDismissBlocker.d.ts +5 -0
  10. package/{lib/HistoryState.ts → dist/HistoryState.d.ts} +2 -5
  11. package/dist/IndieTabletopClubLogo.d.ts +7 -0
  12. package/dist/IndieTabletopClubSymbol.d.ts +7 -0
  13. package/dist/InfoPage/index.d.ts +8 -0
  14. package/dist/InfoPage/pages.d.ts +2 -0
  15. package/dist/InfoPage/style.css.d.ts +5 -0
  16. package/dist/Letterhead/index.d.ts +19 -0
  17. package/dist/Letterhead/stories.d.ts +13 -0
  18. package/dist/Letterhead/style.css.d.ts +46 -0
  19. package/dist/LetterheadForm/LetterheadReadonlyTextField.stories.d.ts +17 -0
  20. package/dist/LetterheadForm/LetterheadSubmitError.stories.d.ts +11 -0
  21. package/dist/LetterheadForm/LetterheadTextField.stories.d.ts +336 -0
  22. package/dist/LetterheadForm/index.d.ts +44 -0
  23. package/dist/LetterheadForm/style.css.d.ts +8 -0
  24. package/dist/LoadingIndicator.d.ts +3 -0
  25. package/dist/MiddotSeparated/MiddotSeparated.d.ts +8 -0
  26. package/dist/MiddotSeparated/MiddotSeparated.stories.d.ts +586 -0
  27. package/dist/MiddotSeparated/style.css.d.ts +1 -0
  28. package/dist/ModalDialog/index.d.ts +12 -0
  29. package/dist/ModalDialog/style.css.d.ts +58 -0
  30. package/dist/ModernIDB/Cursor.d.ts +56 -0
  31. package/dist/ModernIDB/ModernIDB.d.ts +66 -0
  32. package/dist/ModernIDB/ModernIDBError.d.ts +3 -0
  33. package/dist/ModernIDB/ObjectStore.d.ts +112 -0
  34. package/dist/ModernIDB/ObjectStoreIndex.d.ts +53 -0
  35. package/dist/ModernIDB/Transaction.d.ts +16 -0
  36. package/dist/ModernIDB/VersionChangeManager.d.ts +30 -0
  37. package/dist/ModernIDB/bindings/factory.d.ts +12 -0
  38. package/dist/ModernIDB/bindings/index.d.ts +2 -0
  39. package/{lib/ModernIDB/bindings/types.ts → dist/ModernIDB/bindings/types.d.ts} +13 -32
  40. package/dist/ModernIDB/bindings/utils.d.ts +2 -0
  41. package/dist/ModernIDB/index.d.ts +10 -0
  42. package/dist/ModernIDB/types.d.ts +88 -0
  43. package/dist/ModernIDB/utils.d.ts +4 -0
  44. package/dist/QRCode/QRCode.d.ts +7 -0
  45. package/dist/QRCode/QRCode.stories.d.ts +33 -0
  46. package/dist/QRCode/style.css.d.ts +4 -0
  47. package/dist/ReleaseInfo/index.d.ts +5 -0
  48. package/dist/RulesetResolver.d.ts +87 -0
  49. package/dist/SafariCheck/SafariCheck.d.ts +23 -0
  50. package/dist/SafariCheck/SafariCheck.stories.d.ts +73 -0
  51. package/dist/SafariCheck/style.css.d.ts +17 -0
  52. package/dist/ServiceWorkerHandler.d.ts +11 -0
  53. package/dist/ShareButton/ShareButton.d.ts +57 -0
  54. package/dist/ShareButton/ShareButton.stories.d.ts +1577 -0
  55. package/dist/ShareButton/test.css.d.ts +1 -0
  56. package/dist/SubscribeCard/LetterheadInfoCard.d.ts +2 -0
  57. package/dist/SubscribeCard/SubscribeByEmailCard.d.ts +24 -0
  58. package/dist/SubscribeCard/SubscribeByEmailCard.stories.d.ts +10 -0
  59. package/dist/SubscribeCard/SubscribeByPledgeCard.d.ts +36 -0
  60. package/dist/SubscribeCard/SubscribeByPledgeCard.stories.d.ts +65 -0
  61. package/dist/SubscribeCard/style.css.d.ts +4 -0
  62. package/dist/account/AccountIssueView.d.ts +3 -0
  63. package/dist/account/AlreadyLoggedInView.d.ts +5 -0
  64. package/dist/account/CurrentUserFetcher.d.ts +20 -0
  65. package/dist/account/CurrentUserFetcher.stories.d.ts +136 -0
  66. package/dist/account/FailureFallbackView.d.ts +1 -0
  67. package/dist/account/JoinCard.d.ts +14 -0
  68. package/dist/account/JoinCard.stories.d.ts +143 -0
  69. package/dist/account/LoadingView.d.ts +1 -0
  70. package/dist/account/LoginCard.d.ts +39 -0
  71. package/dist/account/LoginCard.stories.d.ts +217 -0
  72. package/dist/account/LoginView.d.ts +10 -0
  73. package/dist/account/NoConnectionView.d.ts +4 -0
  74. package/dist/account/PasswordResetCard.d.ts +15 -0
  75. package/dist/account/PasswordResetCard.stories.d.ts +128 -0
  76. package/dist/account/UserMismatchView.d.ts +6 -0
  77. package/dist/account/VerifyPage.d.ts +13 -0
  78. package/dist/account/style.css.d.ts +10 -0
  79. package/{lib/account/types.ts → dist/account/types.d.ts} +3 -6
  80. package/dist/account/useFetchCurrentUser.d.ts +28 -0
  81. package/dist/account/useRedirectPath.d.ts +6 -0
  82. package/dist/animations.css.d.ts +3 -0
  83. package/dist/append-copy-to-text.d.ts +10 -0
  84. package/dist/append-copy-to-text.test.d.ts +1 -0
  85. package/dist/appkit.css +1 -0
  86. package/dist/appkit.js +10692 -0
  87. package/dist/async-op.d.ts +101 -0
  88. package/dist/atomic.css.d.ts +6 -0
  89. package/{lib/caught-value.ts → dist/caught-value.d.ts} +1 -11
  90. package/{lib/class-names.ts → dist/class-names.d.ts} +6 -17
  91. package/dist/client.d.ts +424 -0
  92. package/dist/common.css.d.ts +5 -0
  93. package/dist/copyrightRange.d.ts +1 -0
  94. package/dist/copyrightRange.test.d.ts +1 -0
  95. package/dist/createSafeStorage.d.ts +34 -0
  96. package/dist/failureMessages.d.ts +20 -0
  97. package/dist/failureMessages.test.d.ts +1 -0
  98. package/dist/form/FormSubmitButton.d.ts +17 -0
  99. package/dist/form/SubmitErrorAlert.d.ts +5 -0
  100. package/dist/form/style.css.d.ts +3 -0
  101. package/dist/globals.css.d.ts +0 -0
  102. package/dist/groupBy.d.ts +1 -0
  103. package/dist/groupBy.test.d.ts +1 -0
  104. package/dist/hrefs.d.ts +32 -0
  105. package/dist/hrefs.test.d.ts +1 -0
  106. package/dist/idToDate.d.ts +5 -0
  107. package/dist/idToDate.test.d.ts +1 -0
  108. package/dist/ids.d.ts +1 -0
  109. package/dist/ids.test.d.ts +1 -0
  110. package/dist/index.d.ts +64 -0
  111. package/dist/internal.css.d.ts +2 -0
  112. package/dist/mailto.d.ts +8 -0
  113. package/dist/mailto.test.d.ts +1 -0
  114. package/dist/media.d.ts +39 -0
  115. package/dist/random.d.ts +3 -0
  116. package/dist/result/swr.d.ts +4 -0
  117. package/{lib/sleep.ts → dist/sleep.d.ts} +1 -3
  118. package/dist/store/index.d.ts +237 -0
  119. package/dist/store/store.d.ts +144 -0
  120. package/dist/store/types.d.ts +49 -0
  121. package/dist/store/utils.d.ts +10 -0
  122. package/dist/storybook/decorators.d.ts +3 -0
  123. package/dist/structs.d.ts +1 -0
  124. package/{lib/typeguards.ts → dist/typeguards.d.ts} +1 -3
  125. package/dist/typeguards.test.d.ts +1 -0
  126. package/{lib/types.ts → dist/types.d.ts} +12 -23
  127. package/dist/unique.d.ts +10 -0
  128. package/dist/unique.test.d.ts +1 -0
  129. package/dist/use-async-op.d.ts +6 -0
  130. package/dist/use-document-background-color.d.ts +4 -0
  131. package/dist/use-form.d.ts +29 -0
  132. package/dist/use-is-installed.d.ts +8 -0
  133. package/dist/use-media-query.d.ts +1 -0
  134. package/dist/use-reverting-state.d.ts +5 -0
  135. package/dist/use-scroll-restoration.d.ts +25 -0
  136. package/dist/useEnsureValue.d.ts +6 -0
  137. package/dist/useInvokeClient.d.ts +25 -0
  138. package/dist/useIsVisible.d.ts +4 -0
  139. package/dist/utm.d.ts +58 -0
  140. package/dist/utm.test.d.ts +1 -0
  141. package/dist/validations.d.ts +3 -0
  142. package/dist/vars.css.d.ts +10 -0
  143. package/package.json +12 -5
  144. package/lib/AppConfig/AppConfig.tsx +0 -61
  145. package/lib/AuthCard/AuthCard.stories.ts +0 -34
  146. package/lib/AuthCard/AuthCard.tsx +0 -64
  147. package/lib/AuthCard/style.css.ts +0 -49
  148. package/lib/DialogTrigger/index.tsx +0 -36
  149. package/lib/DocumentTitle/DocumentTitle.tsx +0 -10
  150. package/lib/EnumMapper.ts +0 -50
  151. package/lib/ExternalLink.tsx +0 -10
  152. package/lib/FullscreenDismissBlocker.tsx +0 -23
  153. package/lib/IndieTabletopClubLogo.tsx +0 -44
  154. package/lib/IndieTabletopClubSymbol.tsx +0 -37
  155. package/lib/InfoPage/index.tsx +0 -46
  156. package/lib/InfoPage/pages.tsx +0 -36
  157. package/lib/InfoPage/style.css.ts +0 -36
  158. package/lib/Letterhead/index.tsx +0 -85
  159. package/lib/Letterhead/stories.tsx +0 -41
  160. package/lib/Letterhead/style.css.ts +0 -152
  161. package/lib/LetterheadForm/LetterheadReadonlyTextField.stories.tsx +0 -17
  162. package/lib/LetterheadForm/LetterheadSubmitError.stories.tsx +0 -19
  163. package/lib/LetterheadForm/LetterheadTextField.stories.tsx +0 -19
  164. package/lib/LetterheadForm/index.tsx +0 -137
  165. package/lib/LetterheadForm/style.css.ts +0 -89
  166. package/lib/LoadingIndicator.tsx +0 -40
  167. package/lib/MiddotSeparated/MiddotSeparated.stories.ts +0 -26
  168. package/lib/MiddotSeparated/MiddotSeparated.tsx +0 -26
  169. package/lib/MiddotSeparated/style.css.ts +0 -10
  170. package/lib/ModalDialog/index.tsx +0 -28
  171. package/lib/ModalDialog/style.css.ts +0 -88
  172. package/lib/ModernIDB/Cursor.ts +0 -91
  173. package/lib/ModernIDB/ModernIDB.ts +0 -337
  174. package/lib/ModernIDB/ModernIDBError.ts +0 -9
  175. package/lib/ModernIDB/ObjectStore.ts +0 -195
  176. package/lib/ModernIDB/ObjectStoreIndex.ts +0 -102
  177. package/lib/ModernIDB/README.md +0 -9
  178. package/lib/ModernIDB/Transaction.ts +0 -40
  179. package/lib/ModernIDB/VersionChangeManager.ts +0 -57
  180. package/lib/ModernIDB/bindings/factory.tsx +0 -165
  181. package/lib/ModernIDB/bindings/index.ts +0 -2
  182. package/lib/ModernIDB/bindings/utils.tsx +0 -32
  183. package/lib/ModernIDB/index.ts +0 -10
  184. package/lib/ModernIDB/types.ts +0 -120
  185. package/lib/ModernIDB/utils.ts +0 -51
  186. package/lib/QRCode/QRCode.stories.tsx +0 -41
  187. package/lib/QRCode/QRCode.tsx +0 -54
  188. package/lib/QRCode/style.css.ts +0 -23
  189. package/lib/ReleaseInfo/index.tsx +0 -29
  190. package/lib/RulesetResolver.ts +0 -214
  191. package/lib/SafariCheck/SafariCheck.stories.tsx +0 -99
  192. package/lib/SafariCheck/SafariCheck.tsx +0 -273
  193. package/lib/SafariCheck/addToDock.svg +0 -13
  194. package/lib/SafariCheck/addToHomeScreen.svg +0 -12
  195. package/lib/SafariCheck/safari.svg +0 -32
  196. package/lib/SafariCheck/shareIcon.svg +0 -11
  197. package/lib/SafariCheck/style.css.ts +0 -106
  198. package/lib/ServiceWorkerHandler.tsx +0 -53
  199. package/lib/ShareButton/ShareButton.stories.tsx +0 -58
  200. package/lib/ShareButton/ShareButton.tsx +0 -153
  201. package/lib/ShareButton/test.css.ts +0 -3
  202. package/lib/SubscribeCard/LetterheadInfoCard.tsx +0 -23
  203. package/lib/SubscribeCard/SubscribeByEmailCard.stories.tsx +0 -69
  204. package/lib/SubscribeCard/SubscribeByEmailCard.tsx +0 -183
  205. package/lib/SubscribeCard/SubscribeByPledgeCard.stories.tsx +0 -133
  206. package/lib/SubscribeCard/SubscribeByPledgeCard.tsx +0 -127
  207. package/lib/SubscribeCard/style.css.ts +0 -14
  208. package/lib/account/AccountIssueView.tsx +0 -44
  209. package/lib/account/AlreadyLoggedInView.tsx +0 -47
  210. package/lib/account/CurrentUserFetcher.stories.tsx +0 -292
  211. package/lib/account/CurrentUserFetcher.tsx +0 -118
  212. package/lib/account/FailureFallbackView.tsx +0 -36
  213. package/lib/account/JoinCard.stories.tsx +0 -257
  214. package/lib/account/JoinCard.tsx +0 -301
  215. package/lib/account/LoadingView.tsx +0 -14
  216. package/lib/account/LoginCard.stories.tsx +0 -288
  217. package/lib/account/LoginCard.tsx +0 -100
  218. package/lib/account/LoginView.tsx +0 -151
  219. package/lib/account/NoConnectionView.tsx +0 -34
  220. package/lib/account/PasswordResetCard.stories.tsx +0 -242
  221. package/lib/account/PasswordResetCard.tsx +0 -296
  222. package/lib/account/UserMismatchView.tsx +0 -62
  223. package/lib/account/VerifyPage.tsx +0 -195
  224. package/lib/account/style.css.ts +0 -57
  225. package/lib/account/useFetchCurrentUser.tsx +0 -63
  226. package/lib/account/useRedirectPath.ts +0 -21
  227. package/lib/animations.css.ts +0 -17
  228. package/lib/append-copy-to-text.ts +0 -35
  229. package/lib/async-op.ts +0 -286
  230. package/lib/atomic.css.ts +0 -11
  231. package/lib/client.ts +0 -662
  232. package/lib/common.css.ts +0 -48
  233. package/lib/copyrightRange.ts +0 -10
  234. package/lib/createSafeStorage.ts +0 -91
  235. package/lib/failureMessages.ts +0 -108
  236. package/lib/form/FormSubmitButton.tsx +0 -58
  237. package/lib/form/SubmitErrorAlert.tsx +0 -21
  238. package/lib/form/style.css.ts +0 -9
  239. package/lib/globals.css.ts +0 -62
  240. package/lib/groupBy.ts +0 -25
  241. package/lib/hrefs.ts +0 -48
  242. package/lib/idToDate.ts +0 -8
  243. package/lib/ids.ts +0 -6
  244. package/lib/index.ts +0 -71
  245. package/lib/internal.css.ts +0 -10
  246. package/lib/mailto.ts +0 -40
  247. package/lib/media.ts +0 -50
  248. package/lib/random.ts +0 -19
  249. package/lib/result/swr.ts +0 -18
  250. package/lib/store/index.tsx +0 -241
  251. package/lib/store/store.ts +0 -479
  252. package/lib/store/types.ts +0 -45
  253. package/lib/store/utils.ts +0 -54
  254. package/lib/storybook/decorators.tsx +0 -10
  255. package/lib/structs.ts +0 -3
  256. package/lib/unique.ts +0 -24
  257. package/lib/use-async-op.ts +0 -16
  258. package/lib/use-document-background-color.ts +0 -16
  259. package/lib/use-form.ts +0 -78
  260. package/lib/use-is-installed.ts +0 -17
  261. package/lib/use-media-query.ts +0 -21
  262. package/lib/use-reverting-state.ts +0 -32
  263. package/lib/use-scroll-restoration.ts +0 -99
  264. package/lib/useEnsureValue.ts +0 -31
  265. package/lib/useInvokeClient.ts +0 -54
  266. package/lib/useIsVisible.ts +0 -27
  267. package/lib/utm.ts +0 -92
  268. package/lib/validations.ts +0 -25
  269. package/lib/vars.css.ts +0 -13
@@ -1,45 +0,0 @@
1
- import type { Failure, Success } from "../async-op.ts";
2
- import type { CurrentUser, FailurePayload, SessionInfo } from "../types.ts";
3
-
4
- export type EmitterActor<Outgoing> = {
5
- sendBack: (event: Outgoing) => void;
6
- };
7
-
8
- export type PullResult =
9
- | Success<{ pulled: SyncedItem[] }>
10
- | Failure<FailurePayload>;
11
-
12
- export type PushResult =
13
- | Success<{ pushed: SyncedItem[]; pulled: SyncedItem[] }>
14
- | Failure<FailurePayload>;
15
-
16
- export type SyncedItem = {
17
- id: string;
18
- name: string;
19
- updatedTs: number;
20
- deleted: boolean;
21
- };
22
-
23
- export type SyncAttempt = {
24
- startedTs: number;
25
- pull: PullResult | null;
26
- push: PushResult | null;
27
- };
28
-
29
- export type MachineContext = {
30
- currentSync: SyncAttempt | null;
31
- lastSuccessfulSyncTs: number | null;
32
- currentUser: CurrentUser | null;
33
- sessionInfo: SessionInfo | null;
34
- pushOnceIdle: boolean;
35
- syncLog: SyncAttempt[];
36
- };
37
-
38
- export type MachineEvent =
39
- | { type: "push" }
40
- | { type: "pull" }
41
- | { type: "currentUser"; currentUser: CurrentUser }
42
- | { type: "serverUser"; serverUser: CurrentUser }
43
- | { type: "sessionInfo"; sessionInfo: SessionInfo }
44
- | { type: "sessionExpired" }
45
- | { type: "reset" };
@@ -1,54 +0,0 @@
1
- import type { UserGameData } from "@indietabletop/types";
2
- import { Failure } from "../async-op.js";
3
- import type { FailurePayload } from "../types.ts";
4
- import type { SyncedItem } from "./types.ts";
5
-
6
- /**
7
- * Flattens the UserGameData structure to a flat SyncedItem[].
8
- */
9
- export function toSyncedItems(data: UserGameData) {
10
- return Object.values(data).flatMap((groups) => {
11
- return Object.values(groups).flatMap((items) => {
12
- return items.map((item): SyncedItem => {
13
- if (!("deleted" in item)) {
14
- return {
15
- id: item.id,
16
- name: item.id,
17
- deleted: false,
18
- updatedTs: item.updatedTs,
19
- };
20
- }
21
-
22
- return {
23
- id: item.id,
24
- name: item.name,
25
- deleted: item.deleted,
26
- updatedTs: item.updatedTs,
27
- };
28
- });
29
- });
30
- });
31
- }
32
-
33
- export function assertNonNullish<T>(
34
- value: T,
35
- message: string,
36
- ): asserts value is NonNullable<T> {
37
- if (value == null) {
38
- throw new Error(message);
39
- }
40
- }
41
-
42
- function isFailurePayload(
43
- error: unknown,
44
- ): error is { cause: Failure<FailurePayload> } {
45
- return error instanceof Error && error.cause instanceof Failure;
46
- }
47
-
48
- export function caughtToResult(error: unknown): Failure<FailurePayload> {
49
- if (isFailurePayload(error)) {
50
- return error.cause;
51
- }
52
-
53
- return new Failure<FailurePayload>({ type: "UNKNOWN_ERROR" });
54
- }
@@ -1,10 +0,0 @@
1
- import { FormProvider, type FormProviderProps } from "@ariakit/react";
2
- import { type Decorator } from "@storybook/react-vite";
3
-
4
- export function form(props?: FormProviderProps): Decorator {
5
- return (Story) => (
6
- <FormProvider {...props}>
7
- <Story />
8
- </FormProvider>
9
- );
10
- }
package/lib/structs.ts DELETED
@@ -1,3 +0,0 @@
1
- // Structs are exported from here for backwards compat. Generally, types
2
- // should be used directly from the types package.
3
- export { currentUser, redeemedPledge, sessionInfo } from "@indietabletop/types";
package/lib/unique.ts DELETED
@@ -1,24 +0,0 @@
1
- type UniqueKey = string | number;
2
-
3
- /**
4
- * Returns an array of unique items, determining uniqueness via the getKey
5
- * function.
6
- *
7
- * Note that the first unique item is returned, all others are omitted
8
- * (assuming that they are unique, so it shouldn't matter).
9
- */
10
- export function uniqueBy<T>(items: T[], getKey: (item: T) => UniqueKey): T[] {
11
- const seen = new Set<UniqueKey>();
12
- const returnItems: T[] = [];
13
-
14
- for (const item of items) {
15
- const uniqueKey = getKey(item);
16
-
17
- if (!seen.has(uniqueKey)) {
18
- returnItems.push(item);
19
- seen.add(uniqueKey);
20
- }
21
- }
22
-
23
- return returnItems;
24
- }
@@ -1,16 +0,0 @@
1
- import { useCallback, useState } from "react";
2
- import { type AsyncOp, Failure, Pending, Success } from "./async-op.js";
3
-
4
- export function useAsyncOp<T, E>() {
5
- const [op, setOp] = useState<AsyncOp<T, E>>(new Pending());
6
-
7
- const setSuccess = useCallback((value: T) => {
8
- setOp(new Success(value));
9
- }, []);
10
-
11
- const setFailure = useCallback((failure: E) => {
12
- setOp(new Failure(failure));
13
- }, []);
14
-
15
- return { op, setSuccess, setFailure };
16
- }
@@ -1,16 +0,0 @@
1
- import { useEffect } from "react";
2
-
3
- /**
4
- * Sets document background color, reverting it to previous color on unmount.
5
- */
6
- export function useDocumentBackgroundColor(bodyColor: string) {
7
- useEffect(() => {
8
- const style = window.document.documentElement.style;
9
- const originalColor = style.backgroundColor;
10
- style.backgroundColor = bodyColor;
11
-
12
- return () => {
13
- style.backgroundColor = originalColor;
14
- };
15
- });
16
- }
package/lib/use-form.ts DELETED
@@ -1,78 +0,0 @@
1
- import { type FormStoreState, useFormStore } from "@ariakit/react";
2
- import { useState } from "react";
3
- import { Failure, Success } from "./async-op.ts";
4
- import { caughtValueToString } from "./caught-value.ts";
5
-
6
- type Validator<T> = (value: T) => string | null;
7
-
8
- type MaybePromise<T> = T | Promise<T>;
9
-
10
- export function useForm<T extends object, R>(props: {
11
- defaultValues: T;
12
- validate?: { [K in keyof T]?: Validator<T[K]> };
13
-
14
- /**
15
- * Handles form submission login.
16
- *
17
- * This function should return a Success or Failure. Failures should always contain a string
18
- * which will be used as the form error message.
19
- */
20
- onSubmit: (
21
- state: FormStoreState<T>,
22
- ) => MaybePromise<Success<R> | Failure<string>>;
23
-
24
- /**
25
- * If submission was successful (i.e. onSubmit returned a Success), will be run to perform any
26
- * side-effect necessary.
27
- *
28
- * Typically this is used for navigation on mutating some local state.
29
- */
30
- onSuccess?: (value: R, state: FormStoreState<T>) => MaybePromise<void>;
31
- }) {
32
- const submitName = "submit";
33
-
34
- const [op, setOp] = useState<Awaited<
35
- ReturnType<typeof props.onSubmit>
36
- > | null>(null);
37
-
38
- const form = useFormStore({
39
- defaultValues: props.defaultValues,
40
- });
41
-
42
- form.useSubmit(async (state) => {
43
- try {
44
- const submitOp = await props.onSubmit(state);
45
-
46
- if (submitOp.isFailure) {
47
- form.setError(submitName, submitOp.failure);
48
- }
49
-
50
- if (submitOp.isSuccess) {
51
- await props.onSuccess?.(submitOp.value, state);
52
- }
53
-
54
- setOp(submitOp);
55
- } catch (error) {
56
- form.setError(submitName, caughtValueToString(error));
57
- }
58
- });
59
-
60
- form.useValidate((state) => {
61
- if (props.validate) {
62
- const entries = Object.entries(props.validate) as Array<
63
- [keyof T & string, Validator<T[keyof T]>]
64
- >;
65
-
66
- for (const [key, validate] of entries) {
67
- const value = state.values[key];
68
- const message = validate(value);
69
-
70
- if (message) {
71
- form.setError(key, message);
72
- }
73
- }
74
- }
75
- });
76
-
77
- return { form, submitName, op };
78
- }
@@ -1,17 +0,0 @@
1
- import { useMemo } from "react";
2
-
3
- /**
4
- * Checks whether the app is installed.
5
- *
6
- * Note that this doesn't check whether the app is installed on the device at
7
- * all, only whether the currently running process is within an installed window
8
- * or running within a browser.
9
- */
10
- export function useIsInstalled() {
11
- // The only way to get into the Standalone display mode is to install
12
- // the app, so this is a good way to check installation status.
13
- return useMemo(
14
- () => window.matchMedia("(display-mode: standalone)").matches,
15
- [],
16
- );
17
- }
@@ -1,21 +0,0 @@
1
- import { useState, useEffect } from "react";
2
-
3
- export function useMediaQuery(query: string) {
4
- const [isMatch, setMatch] = useState(window.matchMedia(query).matches);
5
-
6
- useEffect(() => {
7
- const mql = window.matchMedia(query);
8
-
9
- const handleChange = ({ matches }: MediaQueryListEvent): void => {
10
- setMatch(matches);
11
- };
12
-
13
- mql.addEventListener("change", handleChange);
14
-
15
- return () => {
16
- mql.removeEventListener("change", handleChange);
17
- };
18
- }, [query]);
19
-
20
- return isMatch;
21
- }
@@ -1,32 +0,0 @@
1
- import { useEffect, useRef, useState } from "react";
2
-
3
- /**
4
- * Sets a state that will automatically revert to null after specified number
5
- * of milliseconds.
6
- */
7
- export function useRevertingState<T>(initialState: T, revertAfterMs: number) {
8
- const [state, setState] = useState<T | null>(initialState);
9
- const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
10
-
11
- useEffect(() => {
12
- const timeoutId = timeoutRef.current;
13
-
14
- if (timeoutId) {
15
- clearInterval(timeoutId);
16
- }
17
-
18
- if (state) {
19
- timeoutRef.current = setTimeout(() => {
20
- setState(null);
21
- }, revertAfterMs);
22
- }
23
-
24
- return () => {
25
- if (timeoutId) {
26
- clearTimeout(timeoutId);
27
- }
28
- };
29
- }, [revertAfterMs, state]);
30
-
31
- return [state, setState] as const;
32
- }
@@ -1,99 +0,0 @@
1
- import { useEffect, useLayoutEffect, useMemo } from "react";
2
-
3
- type TimestampedCoordniates = [ts: number, x: number, y: number];
4
-
5
- const scrollPositions = new Map<string, TimestampedCoordniates>();
6
-
7
- /**
8
- * Handles scroll restoration on window.
9
- *
10
- * This hook behaves a little differently than the default browser scroll
11
- * restoration. This is due to limitations of Wouter (our router of choice)
12
- * as well the need to make the app feel more app-like.
13
- *
14
- * Every scroll position is remembered however the user has got to it (we
15
- * don't differentiate between new entries in browser history and back
16
- * navigation), but they are only restored if the user last visited the
17
- * location less than 60 minutes ago.
18
- */
19
- export function useScrollRestoration(
20
- /**
21
- * The current path, provided by your router of choice.
22
- */
23
- pathname: string,
24
-
25
- options?: {
26
- /**
27
- * A list of paths where scroll restoration should never be performed.
28
- *
29
- * This list should have stable identity for optimal performance. Make
30
- * sure to use `useMemo` or define the list in module scope.
31
- */
32
- neverRestore?: string[];
33
- }
34
- ) {
35
- // Standardise pathname, making sure that paths ending with and without
36
- // a slash are treated equally
37
- const normalizedPathname = pathname.replace(/\/$/, "") || "/";
38
-
39
- const neverRestore = useMemo(
40
- () => new Set(options?.neverRestore),
41
- [options?.neverRestore]
42
- );
43
-
44
- // Record scroll position for given pathname on pushState/replaceState.
45
- useEffect(() => {
46
- const handleEvent = () => {
47
- const x = window.scrollX;
48
- const y = window.scrollY;
49
- scrollPositions.set(normalizedPathname, [Date.now(), x, y]);
50
- console.info(
51
- `Set scroll position for '${normalizedPathname}' (x: ${x}, y: ${y}).`
52
- );
53
- };
54
-
55
- // These events are provided by Wouter. They are not native browser events!
56
- window.addEventListener("pushState", handleEvent);
57
- window.addEventListener("replaceState", handleEvent);
58
-
59
- return () => {
60
- window.removeEventListener("pushState", handleEvent);
61
- window.removeEventListener("replaceState", handleEvent);
62
- };
63
- }, [normalizedPathname]);
64
-
65
- // Restore scroll position if last visit was less than 60 minutes ago.
66
- useLayoutEffect(() => {
67
- const maxDiff = 60_000 * 60; // 60 minutes
68
- const coordinates = scrollPositions.get(normalizedPathname);
69
-
70
- if (coordinates) {
71
- if (!neverRestore.has(normalizedPathname)) {
72
- const now = Date.now();
73
- const [ts, x, y] = coordinates;
74
-
75
- if (now - ts < maxDiff) {
76
- window.scrollTo(x, y);
77
- console.info(
78
- `Restoring scroll position for '${normalizedPathname}' (x: ${x}, y: ${y}).`
79
- );
80
- } else {
81
- window.scrollTo(0, 0);
82
- console.info(
83
- `Not restoring scroll position for '${normalizedPathname}'. Last visit >60 min ago.`
84
- );
85
- }
86
- } else {
87
- window.scrollTo(0, 0);
88
- console.info(
89
- `Not restoring scroll position for '${normalizedPathname}'. Page is set never to restore.`
90
- );
91
- }
92
- } else {
93
- window.scrollTo(0, 0);
94
- console.info(
95
- `Not restoring scroll position for '${normalizedPathname}'. Page not visited yet.`
96
- );
97
- }
98
- }, [normalizedPathname]);
99
- }
@@ -1,31 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import { Failure, Pending, Success, type AsyncOp } from "./async-op.ts";
3
- import { caughtValueToString } from "./caught-value.ts";
4
-
5
- /**
6
- * Checks if the provided value is non-nullish, otherwise calls provided
7
- * getValue function to obtain the value (presumably from some remote location).
8
- */
9
- export function useEnsureValue<T>(
10
- value: T | null | undefined,
11
- getValue: () => Promise<Success<T> | Failure<string>>,
12
- ) {
13
- const [result, setShareLink] = useState<AsyncOp<T, string>>(
14
- value != null ? new Success(value) : new Pending(),
15
- );
16
-
17
- useEffect(() => {
18
- if (value == null) {
19
- getValue().then(
20
- (success) => {
21
- setShareLink(success);
22
- },
23
- (error: unknown) => {
24
- setShareLink(new Failure(caughtValueToString(error)));
25
- },
26
- );
27
- }
28
- }, [value, getValue]);
29
-
30
- return result;
31
- }
@@ -1,54 +0,0 @@
1
- import { useCallback } from "react";
2
- import type { SWRConfiguration, SWRResponse } from "swr";
3
- import useSWR from "swr";
4
- import type { Pending } from "./async-op.ts";
5
- import type { IndieTabletopClient } from "./client.ts";
6
- import { swrResponseToResult } from "./result/swr.ts";
7
-
8
- /**
9
- * Creates a `useInvokeClient` hook that makes it ergonomic to invoke
10
- * client methods.
11
- *
12
- * Note that only methods starting with `get` are picked up. This hook is
13
- * intended for making easy fetches, not for form submissions.
14
- */
15
- export function createUseInvokeClient<C extends IndieTabletopClient>(c: C) {
16
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
- type Fn = (...args: any) => any;
18
-
19
- return function useInvokeClient<K extends keyof C & `get${string}`>(
20
- /**
21
- * ITC Client's method name.
22
- */
23
- method: K,
24
-
25
- /**
26
- * Method's arguments.
27
- *
28
- * **IMPORTANT**: Must be an array or primitive values as it is directly
29
- * used as a `useCallback` dependecy array.
30
- */
31
- args: C[K] extends Fn ? Parameters<C[K]> : never,
32
-
33
- options?: {
34
- performFetch?: boolean;
35
- swr?: SWRConfiguration;
36
- },
37
- ): C[K] extends Fn
38
- ? [Awaited<ReturnType<C[K]>> | Pending, SWRResponse<unknown, unknown>]
39
- : never {
40
- const { performFetch = true } = options ?? {};
41
-
42
- const callback = useCallback(() => {
43
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
44
- return (c[method] as Fn)(...args);
45
-
46
- // eslint-disable-next-line react-hooks/exhaustive-deps
47
- }, [method, ...args]);
48
-
49
- const cacheKey = [method, ...args].join(":");
50
- const swr = useSWR(performFetch ? cacheKey : null, callback, options?.swr);
51
-
52
- return [swrResponseToResult(swr), swr] as never;
53
- };
54
- }
@@ -1,27 +0,0 @@
1
- import { useEffect, useRef, useState } from "react";
2
-
3
- export function useIsVisible<T extends HTMLElement>(
4
- initialState = false,
5
- options?: IntersectionObserverInit,
6
- ) {
7
- const ref = useRef<T | null>(null);
8
- const [isVisible, setVisible] = useState(initialState);
9
-
10
- useEffect(() => {
11
- if (ref.current) {
12
- const observer = new IntersectionObserver(([entry]) => {
13
- if (entry) {
14
- setVisible(entry.isIntersecting);
15
- }
16
- }, options);
17
-
18
- observer.observe(ref.current);
19
-
20
- return () => {
21
- observer.disconnect();
22
- };
23
- }
24
- });
25
-
26
- return { ref, isVisible };
27
- }
package/lib/utm.ts DELETED
@@ -1,92 +0,0 @@
1
- /**
2
- * Given an object with keys that might contain undefined values, returns a new
3
- * object only with keys that are not undefined.
4
- */
5
- function omitUndefinedKeys<T>(record: Record<string, T | undefined>) {
6
- return Object.fromEntries(
7
- Object.entries(record).filter(([_, v]) => v !== undefined),
8
- ) as Record<string, T>;
9
- }
10
-
11
- /**
12
- * Full UTM configuration object.
13
- */
14
- export type UtmParams = {
15
- /**
16
- * The website/platform the visitor is coming from.
17
- */
18
- source: string;
19
-
20
- /**
21
- * The type of marketing channel (e.g. cpc, email, affiliate, social,
22
- * or similar).
23
- */
24
- medium: string;
25
-
26
- /**
27
- * The name of the campaign or product description. In our case, this is
28
- * usually the name of the app.
29
- */
30
- campaign: string;
31
-
32
- /**
33
- * Optionally, provide an identifier for the place from which the link was
34
- * clicked. E.g. footer, join, etc.
35
- */
36
- content?: string;
37
-
38
- /**
39
- * Optionally, identify paid keywords. We usually do not use this.
40
- */
41
- term?: string;
42
- };
43
-
44
- /**
45
- * UTM Params configuration that is appropriate to set at the link level,
46
- * if app-level defaults have been set.
47
- */
48
- export type LinkUtmParams = Pick<UtmParams, "content" | "term">;
49
-
50
- /**
51
- * Returns URL Search params with provided UTM configuration.
52
- *
53
- * Most of the time, you probably want to set up some defaults using
54
- * {@link createUtm}. This function is intended for special cases.
55
- */
56
- export function utm(params: UtmParams) {
57
- return new URLSearchParams(
58
- omitUndefinedKeys({
59
- utm_source: params.source,
60
- utm_medium: params.medium,
61
- utm_campaign: params.campaign,
62
- utm_content: params.content,
63
- utm_term: params.term,
64
- }),
65
- );
66
- }
67
-
68
- /**
69
- * A factory for the {@link utm} function. Use it to set sensible defaults for
70
- * further use of the returned function.
71
- *
72
- * @example
73
- * ```ts
74
- * const utm = createUtm({
75
- * source: "indietabletopclub",
76
- * medium: "referral",
77
- * campaign: "spacegitsapp",
78
- * });
79
- *
80
- * utm() // => URLSearchParams that inlude the above config
81
- *
82
- * utm({ campaign: "foo", content: "bar" }) // Sets optional fiels and overrides
83
- * ```
84
- */
85
- export function createUtm(defaults: UtmParams) {
86
- return function (params?: Partial<UtmParams>) {
87
- return utm({
88
- ...defaults,
89
- ...(params && omitUndefinedKeys(params)),
90
- });
91
- };
92
- }
@@ -1,25 +0,0 @@
1
- export const EMAIL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i;
2
-
3
- export const validEmail = (value: string) => {
4
- if (value && !EMAIL_REGEX.test(value)) {
5
- return "This doesn't look like a valid email.";
6
- }
7
-
8
- return null;
9
- };
10
-
11
- export const validPassword = (value: string) => {
12
- if (value) {
13
- if (value.length < 8) {
14
- return "A password has to be at least 8 characters long.";
15
- }
16
-
17
- if (value.length > 256) {
18
- return "A password cannot be longer than 256 characters.";
19
- }
20
-
21
- return null;
22
- }
23
-
24
- return null;
25
- };
package/lib/vars.css.ts DELETED
@@ -1,13 +0,0 @@
1
- import { createGlobalTheme } from "@vanilla-extract/css";
2
-
3
- export const Color = createGlobalTheme(":root", {
4
- GRAY: "#ececec",
5
- MID_GRAY: "hsl(0 0% 50%)",
6
- LIGHT_GRAY: "#e7e8e8",
7
- PALE_GRAY: "#f6f7f7",
8
- PURPLE: "#d6446e",
9
- });
10
-
11
- export const ZIndex = createGlobalTheme(":root", {
12
- DIALOG: "100",
13
- });