@indietabletop/appkit 7.0.0-0 → 7.0.0-rc.1

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 (286) hide show
  1. package/lib/AppConfig/AppConfig.tsx +80 -0
  2. package/lib/AppConfig/formatters.tsx +48 -0
  3. package/lib/AuthCard/AuthCard.stories.ts +34 -0
  4. package/lib/AuthCard/AuthCard.tsx +64 -0
  5. package/lib/AuthCard/style.css.ts +49 -0
  6. package/lib/CacheProvider.tsx +20 -0
  7. package/lib/DialogTrigger/index.tsx +36 -0
  8. package/lib/DocumentTitle/DocumentTitle.tsx +10 -0
  9. package/lib/EnumMapper.ts +50 -0
  10. package/lib/ExternalLink.tsx +10 -0
  11. package/lib/FullscreenDismissBlocker.tsx +23 -0
  12. package/{dist/HistoryState.d.ts → lib/HistoryState.ts} +5 -2
  13. package/lib/IndieTabletopClubLogo.tsx +44 -0
  14. package/lib/IndieTabletopClubSymbol.tsx +37 -0
  15. package/lib/InfoPage/index.tsx +46 -0
  16. package/lib/InfoPage/pages.tsx +36 -0
  17. package/lib/InfoPage/style.css.ts +36 -0
  18. package/lib/Letterhead/index.tsx +85 -0
  19. package/lib/Letterhead/stories.tsx +41 -0
  20. package/lib/Letterhead/style.css.ts +152 -0
  21. package/lib/LetterheadForm/LetterheadReadonlyTextField.stories.tsx +17 -0
  22. package/lib/LetterheadForm/LetterheadSubmitError.stories.tsx +19 -0
  23. package/lib/LetterheadForm/LetterheadTextField.stories.tsx +19 -0
  24. package/lib/LetterheadForm/index.tsx +137 -0
  25. package/lib/LetterheadForm/style.css.ts +89 -0
  26. package/lib/ListView/ListView.stories.tsx +36 -0
  27. package/lib/ListView/ListView.tsx +80 -0
  28. package/lib/ListView/style.css.ts +90 -0
  29. package/lib/LoadingIndicator.tsx +40 -0
  30. package/lib/MiddotSeparated/MiddotSeparated.stories.ts +26 -0
  31. package/lib/MiddotSeparated/MiddotSeparated.tsx +26 -0
  32. package/lib/MiddotSeparated/style.css.ts +10 -0
  33. package/lib/ModalDialog/index.tsx +28 -0
  34. package/lib/ModalDialog/style.css.ts +88 -0
  35. package/lib/ModernIDB/Cursor.ts +91 -0
  36. package/lib/ModernIDB/ModernIDB.ts +337 -0
  37. package/lib/ModernIDB/ModernIDBError.ts +9 -0
  38. package/lib/ModernIDB/ObjectStore.ts +195 -0
  39. package/lib/ModernIDB/ObjectStoreIndex.ts +102 -0
  40. package/lib/ModernIDB/README.md +9 -0
  41. package/lib/ModernIDB/Transaction.ts +40 -0
  42. package/lib/ModernIDB/VersionChangeManager.ts +57 -0
  43. package/lib/ModernIDB/bindings/factory.tsx +165 -0
  44. package/lib/ModernIDB/bindings/index.ts +2 -0
  45. package/{dist/ModernIDB/bindings/types.d.ts → lib/ModernIDB/bindings/types.ts} +32 -13
  46. package/lib/ModernIDB/bindings/utils.tsx +32 -0
  47. package/lib/ModernIDB/index.ts +10 -0
  48. package/lib/ModernIDB/types.ts +120 -0
  49. package/lib/ModernIDB/utils.ts +51 -0
  50. package/lib/QRCode/QRCode.stories.tsx +41 -0
  51. package/lib/QRCode/QRCode.tsx +54 -0
  52. package/lib/QRCode/style.css.ts +23 -0
  53. package/lib/ReleaseInfo/index.tsx +29 -0
  54. package/lib/RichText/RichText.tsx +55 -0
  55. package/lib/RichText/style.css.ts +147 -0
  56. package/lib/RulesetResolver.ts +214 -0
  57. package/lib/SafariCheck/SafariCheck.stories.tsx +99 -0
  58. package/lib/SafariCheck/SafariCheck.tsx +273 -0
  59. package/lib/SafariCheck/addToDock.svg +13 -0
  60. package/lib/SafariCheck/addToHomeScreen.svg +12 -0
  61. package/lib/SafariCheck/safari.svg +32 -0
  62. package/lib/SafariCheck/shareIcon.svg +11 -0
  63. package/lib/SafariCheck/style.css.ts +106 -0
  64. package/lib/ServiceWorkerHandler.tsx +53 -0
  65. package/lib/ShareButton/ShareButton.stories.tsx +58 -0
  66. package/lib/ShareButton/ShareButton.tsx +153 -0
  67. package/lib/ShareButton/test.css.ts +3 -0
  68. package/lib/SubscribeCard/LetterheadInfoCard.tsx +23 -0
  69. package/lib/SubscribeCard/SubscribeByEmailCard.stories.tsx +69 -0
  70. package/lib/SubscribeCard/SubscribeByEmailCard.tsx +183 -0
  71. package/lib/SubscribeCard/SubscribeByPledgeCard.stories.tsx +133 -0
  72. package/lib/SubscribeCard/SubscribeByPledgeCard.tsx +127 -0
  73. package/lib/SubscribeCard/style.css.ts +14 -0
  74. package/lib/Sync/SyncIcon.stories.tsx +67 -0
  75. package/lib/Sync/SyncIcon.tsx +102 -0
  76. package/lib/Sync/SyncLog.tsx +222 -0
  77. package/lib/Sync/SyncLogList.stories.tsx +219 -0
  78. package/lib/Sync/style.css.ts +126 -0
  79. package/lib/account/AccountIcon.tsx +15 -0
  80. package/lib/account/AccountIssueView.tsx +44 -0
  81. package/lib/account/AlreadyLoggedInView.tsx +47 -0
  82. package/lib/account/CurrentUserFetcher.stories.tsx +292 -0
  83. package/lib/account/CurrentUserFetcher.tsx +118 -0
  84. package/lib/account/FailureFallbackView.tsx +36 -0
  85. package/lib/account/JoinCard.stories.tsx +257 -0
  86. package/lib/account/JoinCard.tsx +301 -0
  87. package/lib/account/LoadingView.tsx +14 -0
  88. package/lib/account/LoginCard.stories.tsx +288 -0
  89. package/lib/account/LoginCard.tsx +100 -0
  90. package/lib/account/LoginView.tsx +151 -0
  91. package/lib/account/NoConnectionView.tsx +34 -0
  92. package/lib/account/PasswordResetCard.stories.tsx +242 -0
  93. package/lib/account/PasswordResetCard.tsx +296 -0
  94. package/lib/account/UserMismatchView.tsx +62 -0
  95. package/lib/account/VerifyPage.tsx +195 -0
  96. package/lib/account/iconMask.svg +3 -0
  97. package/lib/account/style.css.ts +81 -0
  98. package/{dist/account/types.d.ts → lib/account/types.ts} +6 -3
  99. package/lib/account/useFetchCurrentUser.tsx +63 -0
  100. package/lib/account/useRedirectPath.ts +21 -0
  101. package/lib/animations.css.ts +17 -0
  102. package/lib/append-copy-to-text.ts +35 -0
  103. package/lib/async-op.ts +298 -0
  104. package/lib/atomic.css.ts +11 -0
  105. package/{dist/caught-value.d.ts → lib/caught-value.ts} +11 -1
  106. package/{dist/class-names.d.ts → lib/class-names.ts} +17 -6
  107. package/lib/client.ts +662 -0
  108. package/lib/common.css.ts +48 -0
  109. package/lib/copyrightRange.ts +10 -0
  110. package/lib/createSafeStorage.ts +91 -0
  111. package/lib/createStrictContext.ts +15 -0
  112. package/lib/failureMessages.ts +108 -0
  113. package/lib/form/FormSubmitButton.tsx +58 -0
  114. package/lib/form/SubmitErrorAlert.tsx +21 -0
  115. package/lib/form/style.css.ts +9 -0
  116. package/lib/globals.css.ts +62 -0
  117. package/lib/groupBy.ts +25 -0
  118. package/lib/hrefs.ts +48 -0
  119. package/lib/idToDate.ts +8 -0
  120. package/lib/ids.ts +6 -0
  121. package/lib/index.ts +78 -0
  122. package/lib/internal.css.ts +10 -0
  123. package/lib/layers.css.ts +3 -0
  124. package/lib/mailto.ts +40 -0
  125. package/lib/media.ts +50 -0
  126. package/lib/random.ts +19 -0
  127. package/lib/result/swr.ts +18 -0
  128. package/{dist/sleep.d.ts → lib/sleep.ts} +3 -1
  129. package/lib/store/index.tsx +292 -0
  130. package/lib/store/store.ts +482 -0
  131. package/lib/store/types.ts +45 -0
  132. package/lib/store/utils.ts +54 -0
  133. package/lib/storybook/decorators.tsx +10 -0
  134. package/lib/structs.ts +3 -0
  135. package/{dist/typeguards.d.ts → lib/typeguards.ts} +3 -1
  136. package/{dist/types.d.ts → lib/types.ts} +23 -12
  137. package/lib/unique.ts +24 -0
  138. package/lib/use-async-op.ts +16 -0
  139. package/lib/use-document-background-color.ts +16 -0
  140. package/lib/use-form.ts +78 -0
  141. package/lib/use-is-installed.ts +17 -0
  142. package/lib/use-media-query.ts +21 -0
  143. package/lib/use-reverting-state.ts +32 -0
  144. package/lib/use-scroll-restoration.ts +99 -0
  145. package/lib/useEnsureValue.ts +31 -0
  146. package/lib/useFetchJson.tsx +52 -0
  147. package/lib/useInvokeClient.ts +54 -0
  148. package/lib/useIsVisible.ts +27 -0
  149. package/lib/utm.ts +92 -0
  150. package/lib/validations.ts +25 -0
  151. package/lib/vars.css.ts +13 -0
  152. package/package.json +23 -29
  153. package/dist/AppConfig/AppConfig.d.ts +0 -29
  154. package/dist/AuthCard/AuthCard.d.ts +0 -10
  155. package/dist/AuthCard/AuthCard.stories.d.ts +0 -34
  156. package/dist/AuthCard/style.css.d.ts +0 -23
  157. package/dist/DialogTrigger/index.d.ts +0 -13
  158. package/dist/DocumentTitle/DocumentTitle.d.ts +0 -3
  159. package/dist/EnumMapper.d.ts +0 -25
  160. package/dist/ExternalLink.d.ts +0 -3
  161. package/dist/FullscreenDismissBlocker.d.ts +0 -5
  162. package/dist/IndieTabletopClubLogo.d.ts +0 -7
  163. package/dist/IndieTabletopClubSymbol.d.ts +0 -7
  164. package/dist/InfoPage/index.d.ts +0 -8
  165. package/dist/InfoPage/pages.d.ts +0 -2
  166. package/dist/InfoPage/style.css.d.ts +0 -5
  167. package/dist/Letterhead/index.d.ts +0 -19
  168. package/dist/Letterhead/stories.d.ts +0 -13
  169. package/dist/Letterhead/style.css.d.ts +0 -46
  170. package/dist/LetterheadForm/LetterheadReadonlyTextField.stories.d.ts +0 -17
  171. package/dist/LetterheadForm/LetterheadSubmitError.stories.d.ts +0 -11
  172. package/dist/LetterheadForm/LetterheadTextField.stories.d.ts +0 -336
  173. package/dist/LetterheadForm/index.d.ts +0 -44
  174. package/dist/LetterheadForm/style.css.d.ts +0 -8
  175. package/dist/LoadingIndicator.d.ts +0 -3
  176. package/dist/MiddotSeparated/MiddotSeparated.d.ts +0 -8
  177. package/dist/MiddotSeparated/MiddotSeparated.stories.d.ts +0 -586
  178. package/dist/MiddotSeparated/style.css.d.ts +0 -1
  179. package/dist/ModalDialog/index.d.ts +0 -12
  180. package/dist/ModalDialog/style.css.d.ts +0 -58
  181. package/dist/ModernIDB/Cursor.d.ts +0 -56
  182. package/dist/ModernIDB/ModernIDB.d.ts +0 -66
  183. package/dist/ModernIDB/ModernIDBError.d.ts +0 -3
  184. package/dist/ModernIDB/ObjectStore.d.ts +0 -112
  185. package/dist/ModernIDB/ObjectStoreIndex.d.ts +0 -53
  186. package/dist/ModernIDB/Transaction.d.ts +0 -16
  187. package/dist/ModernIDB/VersionChangeManager.d.ts +0 -30
  188. package/dist/ModernIDB/bindings/factory.d.ts +0 -12
  189. package/dist/ModernIDB/bindings/index.d.ts +0 -2
  190. package/dist/ModernIDB/bindings/utils.d.ts +0 -2
  191. package/dist/ModernIDB/index.d.ts +0 -10
  192. package/dist/ModernIDB/types.d.ts +0 -88
  193. package/dist/ModernIDB/utils.d.ts +0 -4
  194. package/dist/QRCode/QRCode.d.ts +0 -7
  195. package/dist/QRCode/QRCode.stories.d.ts +0 -33
  196. package/dist/QRCode/style.css.d.ts +0 -4
  197. package/dist/ReleaseInfo/index.d.ts +0 -5
  198. package/dist/RulesetResolver.d.ts +0 -87
  199. package/dist/SafariCheck/SafariCheck.d.ts +0 -23
  200. package/dist/SafariCheck/SafariCheck.stories.d.ts +0 -73
  201. package/dist/SafariCheck/style.css.d.ts +0 -17
  202. package/dist/ServiceWorkerHandler.d.ts +0 -11
  203. package/dist/ShareButton/ShareButton.d.ts +0 -57
  204. package/dist/ShareButton/ShareButton.stories.d.ts +0 -1577
  205. package/dist/ShareButton/test.css.d.ts +0 -1
  206. package/dist/SubscribeCard/LetterheadInfoCard.d.ts +0 -2
  207. package/dist/SubscribeCard/SubscribeByEmailCard.d.ts +0 -24
  208. package/dist/SubscribeCard/SubscribeByEmailCard.stories.d.ts +0 -10
  209. package/dist/SubscribeCard/SubscribeByPledgeCard.d.ts +0 -36
  210. package/dist/SubscribeCard/SubscribeByPledgeCard.stories.d.ts +0 -65
  211. package/dist/SubscribeCard/style.css.d.ts +0 -4
  212. package/dist/account/AccountIssueView.d.ts +0 -3
  213. package/dist/account/AlreadyLoggedInView.d.ts +0 -5
  214. package/dist/account/CurrentUserFetcher.d.ts +0 -20
  215. package/dist/account/CurrentUserFetcher.stories.d.ts +0 -136
  216. package/dist/account/FailureFallbackView.d.ts +0 -1
  217. package/dist/account/JoinCard.d.ts +0 -14
  218. package/dist/account/JoinCard.stories.d.ts +0 -143
  219. package/dist/account/LoadingView.d.ts +0 -1
  220. package/dist/account/LoginCard.d.ts +0 -39
  221. package/dist/account/LoginCard.stories.d.ts +0 -217
  222. package/dist/account/LoginView.d.ts +0 -10
  223. package/dist/account/NoConnectionView.d.ts +0 -4
  224. package/dist/account/PasswordResetCard.d.ts +0 -15
  225. package/dist/account/PasswordResetCard.stories.d.ts +0 -128
  226. package/dist/account/UserMismatchView.d.ts +0 -6
  227. package/dist/account/VerifyPage.d.ts +0 -13
  228. package/dist/account/style.css.d.ts +0 -10
  229. package/dist/account/useFetchCurrentUser.d.ts +0 -28
  230. package/dist/account/useRedirectPath.d.ts +0 -6
  231. package/dist/animations.css.d.ts +0 -3
  232. package/dist/append-copy-to-text.d.ts +0 -10
  233. package/dist/append-copy-to-text.test.d.ts +0 -1
  234. package/dist/appkit.css +0 -1
  235. package/dist/appkit.js +0 -10692
  236. package/dist/async-op.d.ts +0 -101
  237. package/dist/atomic.css.d.ts +0 -6
  238. package/dist/client.d.ts +0 -424
  239. package/dist/common.css.d.ts +0 -5
  240. package/dist/copyrightRange.d.ts +0 -1
  241. package/dist/copyrightRange.test.d.ts +0 -1
  242. package/dist/createSafeStorage.d.ts +0 -34
  243. package/dist/failureMessages.d.ts +0 -20
  244. package/dist/failureMessages.test.d.ts +0 -1
  245. package/dist/form/FormSubmitButton.d.ts +0 -17
  246. package/dist/form/SubmitErrorAlert.d.ts +0 -5
  247. package/dist/form/style.css.d.ts +0 -3
  248. package/dist/globals.css.d.ts +0 -0
  249. package/dist/groupBy.d.ts +0 -1
  250. package/dist/groupBy.test.d.ts +0 -1
  251. package/dist/hrefs.d.ts +0 -32
  252. package/dist/hrefs.test.d.ts +0 -1
  253. package/dist/idToDate.d.ts +0 -5
  254. package/dist/idToDate.test.d.ts +0 -1
  255. package/dist/ids.d.ts +0 -1
  256. package/dist/ids.test.d.ts +0 -1
  257. package/dist/index.d.ts +0 -64
  258. package/dist/internal.css.d.ts +0 -2
  259. package/dist/mailto.d.ts +0 -8
  260. package/dist/mailto.test.d.ts +0 -1
  261. package/dist/media.d.ts +0 -39
  262. package/dist/random.d.ts +0 -3
  263. package/dist/result/swr.d.ts +0 -4
  264. package/dist/store/index.d.ts +0 -237
  265. package/dist/store/store.d.ts +0 -144
  266. package/dist/store/types.d.ts +0 -49
  267. package/dist/store/utils.d.ts +0 -10
  268. package/dist/storybook/decorators.d.ts +0 -3
  269. package/dist/structs.d.ts +0 -1
  270. package/dist/typeguards.test.d.ts +0 -1
  271. package/dist/unique.d.ts +0 -10
  272. package/dist/unique.test.d.ts +0 -1
  273. package/dist/use-async-op.d.ts +0 -6
  274. package/dist/use-document-background-color.d.ts +0 -4
  275. package/dist/use-form.d.ts +0 -29
  276. package/dist/use-is-installed.d.ts +0 -8
  277. package/dist/use-media-query.d.ts +0 -1
  278. package/dist/use-reverting-state.d.ts +0 -5
  279. package/dist/use-scroll-restoration.d.ts +0 -25
  280. package/dist/useEnsureValue.d.ts +0 -6
  281. package/dist/useInvokeClient.d.ts +0 -25
  282. package/dist/useIsVisible.d.ts +0 -4
  283. package/dist/utm.d.ts +0 -58
  284. package/dist/utm.test.d.ts +0 -1
  285. package/dist/validations.d.ts +0 -3
  286. package/dist/vars.css.d.ts +0 -10
@@ -0,0 +1,80 @@
1
+ import { type ReactNode } from "react";
2
+ import type { IndieTabletopClient } from "../client.ts";
3
+ import { createStrictContext } from "../createStrictContext.ts";
4
+ import type { AppHrefs } from "../hrefs.ts";
5
+ import type { ModernIDB } from "../ModernIDB/index.ts";
6
+ import type { DatabaseAppMachineMethods } from "../store/index.tsx";
7
+ import type { AppkitFormatters } from "./formatters.tsx";
8
+
9
+ export type AppConfig = {
10
+ app: {
11
+ /**
12
+ * The app's name, e.g. Space Gits. Do not include the word App in this
13
+ * title -- it will be added automatically in places where it's needed.
14
+ */
15
+ name: string;
16
+
17
+ /**
18
+ * The URL to the app's icon. This should be a maskable-style icon. In
19
+ * other words, it should not include its own transparency.
20
+ */
21
+ icon: string;
22
+ };
23
+
24
+ /**
25
+ * Usually the value of `import.meta.env.DEV` when using Vite.
26
+ *
27
+ * This is used primarily by the DocumentTitle component, to make it clear
28
+ * which browser tab is in DEV mode.
29
+ */
30
+ isDev: boolean;
31
+
32
+ /**
33
+ * A reference to the ITC client.
34
+ *
35
+ * This is necessary in order for prefab components to make thier own calls.
36
+ */
37
+ client: IndieTabletopClient;
38
+
39
+ /**
40
+ * A hrefs configuration.
41
+ *
42
+ * This is necessary so that prefab components can navigate around the app
43
+ * without hard-coded values.
44
+ */
45
+ hrefs: AppHrefs;
46
+
47
+ /**
48
+ * Customize input placeholders so that they fit their given app thematically.
49
+ */
50
+ placeholders: {
51
+ email: string;
52
+ };
53
+
54
+ /**
55
+ * Formatters accessible to prefab components.
56
+ *
57
+ * You might want to create different formatters based on the app's locale.
58
+ */
59
+ fmt: AppkitFormatters;
60
+
61
+ database: ModernIDB<any, any> & DatabaseAppMachineMethods;
62
+ };
63
+
64
+ const [AppConfigContext, useAppConfig] = createStrictContext<AppConfig>();
65
+
66
+ export { createFormatters } from "./formatters.tsx";
67
+
68
+ export { useAppConfig };
69
+
70
+ export function useClient() {
71
+ return useAppConfig().client;
72
+ }
73
+
74
+ export function AppConfigProvider(props: {
75
+ config: AppConfig;
76
+ children: ReactNode;
77
+ }) {
78
+ const { config, children } = props;
79
+ return <AppConfigContext value={config}>{children}</AppConfigContext>;
80
+ }
@@ -0,0 +1,48 @@
1
+ // English only uses "one" and "other"
2
+ type EnglishCardinalRule = Extract<Intl.LDMLPluralRule, "one" | "other">;
3
+
4
+ export type AppkitFormatters = ReturnType<typeof createFormatters>;
5
+
6
+ // Currently, we only support localizing English variants. Not translating the
7
+ // app into other locales.
8
+ type EnglishLocale = "en" | `en-${string}`;
9
+
10
+ /**
11
+ * Creates formatters that can be used across the app.
12
+ */
13
+ export function createFormatters(locale: EnglishLocale) {
14
+ const cardinalRules = new Intl.PluralRules(locale);
15
+
16
+ const dateTimeFmt = new Intl.DateTimeFormat(locale);
17
+
18
+ const dateFmt = new Intl.DateTimeFormat(locale, { dateStyle: "long" });
19
+
20
+ const conjunctionFmt = new Intl.ListFormat(locale, {
21
+ style: "long",
22
+ type: "conjunction",
23
+ });
24
+
25
+ const disjunctionFmt = new Intl.ListFormat(locale, {
26
+ style: "long",
27
+ type: "disjunction",
28
+ });
29
+
30
+ return {
31
+ plural(count: number, rules: Record<EnglishCardinalRule, string>) {
32
+ const tag = cardinalRules.select(count) as EnglishCardinalRule;
33
+ return rules[tag].replace("#", count.toString());
34
+ },
35
+ dateTime(date: Date | string | number) {
36
+ return dateTimeFmt.format(new Date(date));
37
+ },
38
+ date(date: Date | string | number) {
39
+ return dateFmt.format(new Date(date));
40
+ },
41
+ conjunction(items: string[]) {
42
+ return conjunctionFmt.format(items);
43
+ },
44
+ disjunction(items: string[]) {
45
+ return disjunctionFmt.format(items);
46
+ },
47
+ };
48
+ }
@@ -0,0 +1,34 @@
1
+ import { fn } from "storybook/test";
2
+ import preview from "../../.storybook/preview.tsx";
3
+ import { AuthCard } from "./AuthCard.tsx";
4
+
5
+ const meta = preview.meta({
6
+ title: "Account/Auth Card",
7
+ component: AuthCard,
8
+ tags: ["autodocs"],
9
+ args: {
10
+ onLogout: fn(),
11
+ },
12
+ });
13
+
14
+ /**
15
+ * The default case where elements are correctly separated with middots.
16
+ */
17
+ export const Authenticated = meta.story({
18
+ args: {
19
+ currentUser: {
20
+ id: "martin",
21
+ email: "martin@example.com",
22
+ isVerified: true,
23
+ },
24
+ },
25
+ });
26
+
27
+ /**
28
+ * The default case in which all steps of the flow succeed.
29
+ */
30
+ export const Anonymous = meta.story({
31
+ args: {
32
+ currentUser: null,
33
+ },
34
+ });
@@ -0,0 +1,64 @@
1
+ import { Button } from "@ariakit/react";
2
+ import { Link } from "wouter";
3
+ import { useAppConfig } from "../AppConfig/AppConfig.tsx";
4
+ import { interactiveText } from "../common.css.ts";
5
+ import { IndieTabletopClubLogo } from "../IndieTabletopClubLogo.tsx";
6
+ import { LetterheadParagraph } from "../Letterhead/index.tsx";
7
+ import { button } from "../Letterhead/style.css.ts";
8
+ import { MiddotSeparated } from "../MiddotSeparated/MiddotSeparated.tsx";
9
+ import type { CurrentUser } from "../types.ts";
10
+ import { card } from "./style.css.ts";
11
+
12
+ /**
13
+ * Small, ITC-branded card that shows authentication status.
14
+ *
15
+ * Primarily intended to be used within the sidenav.
16
+ */
17
+ export function AuthCard(props: {
18
+ onLogout: () => void;
19
+ currentUser: CurrentUser | null;
20
+ }) {
21
+ const { currentUser, onLogout } = props;
22
+ const { hrefs } = useAppConfig();
23
+ const align = !currentUser ? "center" : "start";
24
+
25
+ return (
26
+ <div className={card.container({ align })}>
27
+ <IndieTabletopClubLogo className={card.logo({ align })} />
28
+
29
+ {currentUser ? (
30
+ <>
31
+ <LetterheadParagraph>{currentUser.email}</LetterheadParagraph>
32
+
33
+ <MiddotSeparated className={card.loggedInAction}>
34
+ <Link className={interactiveText} href={hrefs.account()}>
35
+ Account
36
+ </Link>
37
+
38
+ <Button className={interactiveText} onClick={() => onLogout()}>
39
+ Log out
40
+ </Button>
41
+ </MiddotSeparated>
42
+ </>
43
+ ) : (
44
+ <>
45
+ <LetterheadParagraph size="small">
46
+ Enable backup & sync, access your pledge data, and more!
47
+ </LetterheadParagraph>
48
+
49
+ <Link href={hrefs.join()} className={button()}>
50
+ Join
51
+ </Link>
52
+
53
+ <LetterheadParagraph size="small">
54
+ {"Already have an account? "}
55
+ <Link href={hrefs.login()} className={interactiveText}>
56
+ Log in
57
+ </Link>
58
+ {"."}
59
+ </LetterheadParagraph>
60
+ </>
61
+ )}
62
+ </div>
63
+ );
64
+ }
@@ -0,0 +1,49 @@
1
+ import { style } from "@vanilla-extract/css";
2
+ import { recipe } from "@vanilla-extract/recipes";
3
+
4
+ export const card = {
5
+ container: recipe({
6
+ base: {
7
+ display: "flex",
8
+ flexDirection: "column",
9
+ gap: "0.75rem",
10
+ backgroundColor: "white",
11
+ padding: "1.5rem",
12
+ borderRadius: "0.5rem",
13
+ color: "black",
14
+ },
15
+
16
+ variants: {
17
+ align: {
18
+ center: {
19
+ textAlign: "center",
20
+ },
21
+ start: {
22
+ textAlign: "start",
23
+ },
24
+ },
25
+ },
26
+ }),
27
+
28
+ logo: recipe({
29
+ base: {
30
+ maxInlineSize: "11rem",
31
+ },
32
+
33
+ variants: {
34
+ align: {
35
+ center: {
36
+ marginInline: "auto",
37
+ },
38
+ start: {
39
+ marginInline: "0",
40
+ },
41
+ },
42
+ },
43
+ }),
44
+
45
+ loggedInAction: style({
46
+ borderBlockStart: "1px solid hsl(0 0% 0% / 0.1)",
47
+ paddingBlockStart: "0.75rem",
48
+ }),
49
+ };
@@ -0,0 +1,20 @@
1
+ import { useCurrentUser } from "@indietabletop/appkit";
2
+ import { useMemo, type ReactNode } from "react";
3
+ import { SWRConfig } from "swr";
4
+
5
+ /**
6
+ * Links SWR cache to the current user. This makes sure that if a user logs
7
+ * out and continues using the app in an anonymous state, they will not be
8
+ * shown stale data.
9
+ */
10
+ export function CacheProvider(props: { children: ReactNode }) {
11
+ const currentUser = useCurrentUser();
12
+ const cacheKey = currentUser ? currentUser.id : "anonymous";
13
+
14
+ const provider = useMemo(() => {
15
+ console.info(`Using SWR cache for "${cacheKey}"`);
16
+ return () => new Map();
17
+ }, [cacheKey]);
18
+
19
+ return <SWRConfig value={{ provider }}>{props.children}</SWRConfig>;
20
+ }
@@ -0,0 +1,36 @@
1
+ import {
2
+ DialogProvider,
3
+ useDialogContext,
4
+ useStoreState,
5
+ } from "@ariakit/react";
6
+ import type { ReactElement, ReactNode } from "react";
7
+
8
+ function DialogGuard(props: { children: ReactNode }) {
9
+ const dialog = useDialogContext();
10
+ const isMounted = useStoreState(dialog, (store) => store?.mounted);
11
+ if (!isMounted) {
12
+ return null;
13
+ }
14
+ return props.children;
15
+ }
16
+
17
+ /**
18
+ * Wraps AriaKit's DialogProvider, but takes a tuple of Dialog a DialogDisclosure
19
+ * elements as children, and makes sure that the Dialog component is not
20
+ * rendered when it is hidden.
21
+ *
22
+ * This is important in cases where the dialog contains a form that should only
23
+ * be initialized and re-initialized when the dialog opens, not when it is first
24
+ * rendered.
25
+ */
26
+ export function DialogTrigger(props: {
27
+ children: [ReactElement, ReactElement];
28
+ }) {
29
+ const [dialog, button] = props.children;
30
+ return (
31
+ <DialogProvider>
32
+ <DialogGuard>{dialog}</DialogGuard>
33
+ {button}
34
+ </DialogProvider>
35
+ );
36
+ }
@@ -0,0 +1,10 @@
1
+ import { useAppConfig } from "../AppConfig/AppConfig.tsx";
2
+
3
+ export function DocumentTitle(props: { children: string }) {
4
+ const { children: children } = props;
5
+ const { app, isDev } = useAppConfig();
6
+ const itc = `${app.name} · Indie Tabletop Club`;
7
+ const title = children ? `${children} | ${itc}` : itc;
8
+
9
+ return <title>{isDev ? `[DEV] ${title}` : title}</title>;
10
+ }
@@ -0,0 +1,50 @@
1
+ type InputValues<K extends string | number, V> = Record<K, V> | Array<[K, V]>;
2
+
3
+ /**
4
+ * Handles mapping enums to arbitrary values.
5
+ */
6
+ export class EnumMapper<K extends string | number, V> {
7
+ private map: Map<K, V>;
8
+ private fallback: V;
9
+
10
+ constructor(values: InputValues<K, V>, fallback: V) {
11
+ const entries = Array.isArray(values)
12
+ ? values
13
+ : (Object.entries(values) as Array<[K, V]>);
14
+ this.map = new Map(entries);
15
+ this.fallback = fallback;
16
+ }
17
+
18
+ /**
19
+ * Returns a value corresponding to the provided key.
20
+ *
21
+ * If no match is found, returns the fallback value provided in the constructor.
22
+ *
23
+ * Note that TypeScript will make sure that we only ever use the right types
24
+ * as the enum param, but it can still happen at runtime that different
25
+ * values are provided.
26
+ */
27
+ get(key: K | undefined): V {
28
+ if (key === undefined) {
29
+ return this.fallback;
30
+ }
31
+
32
+ const value = this.map.get(key);
33
+ if (value === undefined) {
34
+ return this.fallback;
35
+ }
36
+
37
+ return value;
38
+ }
39
+
40
+ /**
41
+ * All enums known by this mapper.
42
+ */
43
+ get enums() {
44
+ return Array.from(this.map.keys());
45
+ }
46
+
47
+ static from<K extends string>(values: InputValues<K, string>) {
48
+ return new EnumMapper(values, "Unknown");
49
+ }
50
+ }
@@ -0,0 +1,10 @@
1
+ import type { AnchorHTMLAttributes } from "react";
2
+
3
+ export type ExternalLinkProps = Omit<
4
+ AnchorHTMLAttributes<HTMLAnchorElement>,
5
+ "rel" | "target"
6
+ >;
7
+
8
+ export function ExternalLink(props: ExternalLinkProps) {
9
+ return <a {...props} target="_blank" rel="noreferrer noopener" />;
10
+ }
@@ -0,0 +1,23 @@
1
+ import { useEffect } from "react";
2
+
3
+ function preventDefaultEscHandling(event: KeyboardEvent) {
4
+ if (event.key === "Escape") {
5
+ event.preventDefault();
6
+ }
7
+ }
8
+
9
+ /**
10
+ * This component prevents the default MacOS behaviour where a fullscreen window
11
+ * gets minimized by pressing Escape.
12
+ */
13
+ export function FullscreenDismissBlocker() {
14
+ useEffect(() => {
15
+ window.addEventListener("keydown", preventDefaultEscHandling);
16
+
17
+ return () => {
18
+ window.removeEventListener("keydown", preventDefaultEscHandling);
19
+ };
20
+ }, []);
21
+
22
+ return null;
23
+ }
@@ -7,12 +7,15 @@
7
7
  * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html
8
8
  */
9
9
  export interface HistoryState {
10
- emailValue?: string;
10
+ emailValue?: string;
11
11
  }
12
+
12
13
  /**
13
14
  * Get's window history state with correct typings.
14
15
  *
15
16
  * Note that this is not a reactive value. It will not trigger re-renders if
16
17
  * it is changed.
17
18
  */
18
- export declare function getHistoryState(): HistoryState | null;
19
+ export function getHistoryState() {
20
+ return window.history.state as HistoryState | null;
21
+ }
@@ -0,0 +1,44 @@
1
+ import type { SVGAttributes } from "react";
2
+
3
+ type IndieTabletopClubLogoProps = Omit<
4
+ SVGAttributes<SVGElement>,
5
+ "width" | "height" | "viewBox"
6
+ > & {
7
+ textColor?: string;
8
+ symbolColor?: string;
9
+ };
10
+
11
+ export function IndieTabletopClubLogo(props: IndieTabletopClubLogoProps) {
12
+ const { textColor = "#161615", symbolColor = "#FF5937", ...svgProps } = props;
13
+
14
+ // prettier-ignore
15
+ return (
16
+ <svg {...svgProps} width="200px" height="13px" viewBox="0 0 200 13">
17
+ <g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
18
+ <g transform="translate(-720, -746)" fillRule="nonzero">
19
+ <g transform="translate(720, 746)">
20
+ <path fill={textColor} d="M162.319043,13 C160.39468,13 158.856429,12.433618 157.706354,11.3007467 C156.560409,10.1678541 155.987436,8.6527232 155.987436,6.75532194 C155.987436,5.27087812 156.347738,3.76969784 157.068341,2.25177041 L162.384083,0 C164.685265,0 166.250358,0.625027117 167.07833,1.87508242 L164.464335,4.2356719 C163.658044,3.15862455 162.711348,2.42755671 161.625281,2.04250049 L160.101483,2.04250049 C159.838226,3.28697663 159.70608,4.32217213 159.70608,5.14810843 C159.70608,6.76090433 160.056058,8.03885336 160.754982,8.98197696 C161.453905,9.91951817 162.380986,10.3882888 163.537255,10.3882888 C163.854197,10.3882888 164.179397,10.3408545 164.512857,10.2459861 C164.846317,10.1511176 165.387286,9.95858417 166.134731,9.66839641 L166.61066,10.4217724 L164.053446,13 L162.319043,13 Z" />
21
+ <polygon fill={textColor} points="171.687921 10.7314717 176.244861 10.7314717 175.584135 12.7572036 168.147879 12.7572036 168.147879 0.242755671 171.687921 0.159047705" />
22
+ <path fill={textColor} d="M184.113686,0.242755671 L187.646502,0.159047705 L187.646502,12.7572036 L184.113686,12.840993 L184.113686,11.8699146 L181.435684,13 C179.893303,13 178.79588,12.6512347 178.145478,11.9535969 C177.500239,11.2560662 177.177103,10.078568 177.177103,8.42113445 L177.177103,0.242755671 L180.709918,0.159047705 L180.709918,7.96073207 C180.709918,8.59133836 180.742955,9.07964196 180.806962,9.42564289 C180.877164,9.77163309 181.021698,10.0701998 181.242628,10.3213215 C181.462526,10.572454 181.763982,10.7426151 182.145964,10.8319761 C182.533107,10.9156584 183.057558,10.9575531 183.718283,10.9575531 C183.982573,9.7465177 184.113686,8.7113222 184.113686,7.85190228 L184.113686,0.242755671 Z" />
23
+ <path fill={textColor} d="M197.176432,5.36574657 C198.069443,5.42155974 198.763205,5.69221449 199.257716,6.17772155 C199.752228,6.65765693 200,7.29664216 200,8.09466652 C200,8.95407573 199.690285,9.76047903 199.071887,10.513855 L193.757178,12.7572036 L189.788697,12.7572036 L189.788697,0.242755671 L195.273749,0.242755671 C198.015759,0.242755671 199.386764,1.15239351 199.386764,2.97167348 C199.386764,3.48508176 199.160672,4.06546799 198.709521,4.71282144 L197.176432,5.36574657 Z M194.595474,2.26851757 L193.329772,2.26851757 L193.329772,5.34901012 L195.44306,5.34901012 C195.59895,4.80210751 195.674314,4.40310069 195.66812,4.15196822 C195.66812,3.29813069 195.310915,2.67032095 194.595474,2.26851757 Z M196.031519,10.7314717 C196.197732,10.1846012 196.281355,9.69908348 196.281355,9.27496126 C196.281355,8.40438728 195.907633,7.77098444 195.160187,7.37476345 L193.329772,7.37476345 L193.329772,10.7314717 L196.031519,10.7314717 Z" />
24
+ <polygon fill={textColor} points="0 0.242755671 3.54075462 0.159047705 3.54075462 12.7572036 0 12.840993" />
25
+ <polygon fill={textColor} points="13.6033016 0.242755671 15.5551254 0.159047705 15.5551254 12.7572036 13.2403156 13 7.6267315 5.50804925 7.6267315 12.7572036 5.67487669 12.840993 5.67487669 0.242755671 7.98967617 0 13.6033016 7.55892869" />
26
+ <path fill={textColor} d="M23.8028354,0.242755671 C25.6203462,0.242755671 27.0425574,0.77291326 28.0695723,1.83323058 C29.1019556,2.88795909 29.6181472,4.30543568 29.6181472,6.08564964 C29.6181472,7.48079668 29.2605297,8.95687228 28.5453978,10.513855 L23.2221198,12.7572036 L17.7053733,12.7572036 L17.7053733,0.242755671 L23.8028354,0.242755671 Z M25.5047193,10.7314717 C25.7681835,9.41447811 25.8999156,8.39880489 25.8999156,7.68449492 C25.8999156,5.03370698 24.9588982,3.22837762 23.0769668,2.26851757 L21.2461382,2.26851757 L21.2461382,10.7314717 L25.5047193,10.7314717 Z" />
27
+ <polygon fill={textColor} points="31.090842 0.242755671 34.6316069 0.159047705 34.6316069 12.7572036 31.090842 12.840993" />
28
+ <polygon fill={textColor} points="40.3065146 7.34127984 40.3065146 10.7314717 45.19423 10.7314717 44.532782 12.7572036 36.7657497 12.7572036 36.7657497 0.242755671 45.19423 0.242755671 44.532782 2.26851757 40.3065146 2.26851757 40.3065146 5.31552651 44.3634712 5.31552651 43.7020232 7.34127984" />
29
+ <polygon fill={textColor} points="60.8105757 0.242755671 60.1572836 2.26851757 57.2134427 2.26851757 57.2134427 12.7572036 53.6807303 12.840993 53.6807303 2.26851757 50.0593362 2.26851757 50.720681 0.242755671" />
30
+ <path fill={textColor} d="M67.1548807,13 L65.9773443,9.65164925 L62.2107972,9.65164925 L61.1219425,12.7572036 L59.0087572,13 L63.5012763,0.242755671 L66.3080167,0 L70.6553827,12.3136127 L67.1548807,13 Z M62.9205607,7.63426414 L65.2675808,7.63426414 L64.0980971,4.31938629 L62.9205607,7.63426414 Z" />
31
+ <path fill={textColor} d="M79.1127698,5.36574657 C80.0053684,5.42155974 80.6990267,5.69221449 81.1937448,6.17772155 C81.6883596,6.65765693 81.9357187,7.29664216 81.9357187,8.09466652 C81.9357187,8.95407573 81.6265199,9.76047903 81.0082255,10.513855 L75.6930002,12.7572036 L71.7248286,12.7572036 L71.7248286,0.242755671 L77.2093647,0.242755671 C79.9515812,0.242755671 81.3227927,1.15239351 81.3227927,2.97167348 C81.3227927,3.48508176 81.0969072,4.06546799 80.6452396,4.71282144 L79.1127698,5.36574657 Z M76.5318116,2.26851757 L75.2655935,2.26851757 L75.2655935,5.34901012 L77.3787788,5.34901012 C77.5346687,4.80210751 77.6099295,4.40310069 77.6045611,4.15196822 C77.6045611,3.29813069 77.2470467,2.67032095 76.5318116,2.26851757 Z M77.967547,10.7314717 C78.1341737,10.1846012 78.2175903,9.69908348 78.2175903,9.27496126 C78.2175903,8.40438728 77.8438675,7.77098444 77.096422,7.37476345 L75.2655935,7.37476345 L75.2655935,10.7314717 L77.967547,10.7314717 Z" />
32
+ <polygon fill={textColor} points="86.8282863 10.7314717 91.3853293 10.7314717 90.7238813 12.7572036 83.2875213 12.7572036 83.2875213 0.242755671 86.8282863 0.159047705" />
33
+ <polygon fill={textColor} points="96.0035927 7.34127984 96.0035927 10.7314717 100.891308 10.7314717 100.22986 12.7572036 92.4628277 12.7572036 92.4628277 0.242755671 100.891308 0.242755671 100.22986 2.26851757 96.0035927 2.26851757 96.0035927 5.31552651 100.060549 5.31552651 99.3992045 7.34127984" />
34
+ <polygon fill={textColor} points="111.848921 0.242755671 111.195422 2.26851757 108.252098 2.26851757 108.252098 12.7572036 104.719282 12.840993 104.719282 2.26851757 101.097785 2.26851757 101.759129 0.242755671" />
35
+ <path fill={textColor} d="M117.951339,0 C119.876733,0 121.411887,0.566431327 122.5568,1.69929612 C123.701713,2.83215663 124.274686,4.34728752 124.274686,6.24468878 C124.274686,7.7291326 123.917482,9.23031287 123.20204,10.7481867 L117.887331,13 C115.961936,13 114.423685,12.433618 113.27361,11.3007467 C112.127665,10.1678541 111.555724,8.6527232 111.555724,6.75532194 C111.555724,5.27087812 111.916026,3.76969784 112.636629,2.25177041 L117.951339,0 Z M120.161671,10.9575531 C120.424929,9.71303409 120.559139,8.67783859 120.564301,7.85190228 C120.564301,5.02812459 119.46791,3.09165733 117.274095,2.04250049 L115.668739,2.04250049 C115.405481,3.28697663 115.273336,4.32217213 115.273336,5.14810843 C115.273336,7.97188613 116.37076,9.9083641 118.564574,10.9575531 L120.161671,10.9575531 Z" />
36
+ <path fill={textColor} d="M131.070865,0.242755671 C131.796631,0.242755671 132.44187,0.312514094 133.006584,0.452028798 C133.57646,0.585963257 134.033805,0.764542892 134.377589,0.987766633 C134.727567,1.21099252 135.01457,1.47886143 135.240661,1.79137874 C135.466753,2.09830295 135.622643,2.40523787 135.708331,2.71217279 C135.800213,3.01910771 135.845638,3.34557563 135.845638,3.69156584 C135.845638,4.61795299 135.535923,5.4522468 134.917525,6.19446871 L129.602816,8.4378709 L129.287939,8.4378709 L129.287939,12.7572036 L125.747897,12.840993 L125.747897,0.242755671 L131.070865,0.242755671 Z M131.877157,6.41211757 C132.044403,5.86521495 132.126993,5.35179596 132.126993,4.87187129 C132.126993,3.66087877 131.713008,2.79309063 130.885036,2.26851757 L129.287939,2.26851757 L129.287939,6.41211757 L131.877157,6.41211757 Z" />
37
+
38
+ <polygon fill={symbolColor} points="150.825519 4.65625824 149.752873 9.89656716 144.843891 11.5521149 141.007554 7.96730021 142.080201 2.7269913 146.990216 1.07147567" />
39
+ </g>
40
+ </g>
41
+ </g>
42
+ </svg>
43
+ );
44
+ }
@@ -0,0 +1,37 @@
1
+ import type { SVGAttributes } from "react";
2
+
3
+ type IndieTabletopClubSymbolProps = Omit<
4
+ SVGAttributes<SVGElement>,
5
+ "width" | "height" | "viewBox"
6
+ > & {
7
+ backgroundColor?: string;
8
+ symbolColor?: string;
9
+ };
10
+
11
+ export function IndieTabletopClubSymbol(props: IndieTabletopClubSymbolProps) {
12
+ const {
13
+ symbolColor = "#FF5937",
14
+ backgroundColor = "#F0F0F0",
15
+ ...svgProps
16
+ } = props;
17
+
18
+ return (
19
+ <svg {...svgProps} width="65px" height="65px" viewBox="0 0 65 65">
20
+ <g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
21
+ <rect
22
+ fill={backgroundColor}
23
+ x="0"
24
+ y="0"
25
+ width="65"
26
+ height="65"
27
+ rx="11"
28
+ />
29
+ <polygon
30
+ fill={symbolColor}
31
+ fillRule="nonzero"
32
+ points="52.2105164 26.1156583 47.8803714 46.1156174 28.0633944 52.4341166 12.5765623 38.7524522 16.9067073 18.7524931 36.7278519 12.4341166"
33
+ />
34
+ </g>
35
+ </svg>
36
+ );
37
+ }
@@ -0,0 +1,46 @@
1
+ import { Heading, HeadingLevel } from "@ariakit/react";
2
+ import { LoadingIndicator } from "@indietabletop/appkit";
3
+ import type { ReactNode } from "react";
4
+ import * as css from "./style.css.ts";
5
+
6
+ export function InfoPage(props: {
7
+ heading: string;
8
+ description: ReactNode;
9
+ action?: ReactNode;
10
+ }) {
11
+ return (
12
+ <HeadingLevel>
13
+ <div className={css.page}>
14
+ <Heading className={css.heading}>{props.heading}</Heading>
15
+ <p className={css.description}>{props.description}</p>
16
+ {props.action && (
17
+ <div
18
+ style={{
19
+ marginBlockStart: "1rem",
20
+ marginInline: "auto",
21
+ inlineSize: "fit-content",
22
+ }}
23
+ >
24
+ {props.action}
25
+ </div>
26
+ )}
27
+ </div>
28
+ </HeadingLevel>
29
+ );
30
+ }
31
+
32
+ export function LoadingPage() {
33
+ return (
34
+ <div className={css.loadingPage}>
35
+ <LoadingIndicator />
36
+ </div>
37
+ );
38
+ }
39
+
40
+ export function LoadingView() {
41
+ return (
42
+ <div className={css.loadingView}>
43
+ <LoadingIndicator />
44
+ </div>
45
+ );
46
+ }
@@ -0,0 +1,36 @@
1
+ import { interactiveText } from "@indietabletop/appkit/common.css.ts";
2
+ import { Link } from "wouter";
3
+ import { InfoPage } from "./index.tsx";
4
+
5
+ export function NotFoundPage() {
6
+ return (
7
+ <InfoPage
8
+ heading="Nothing here..."
9
+ description={
10
+ <>
11
+ The link you have followed might be broken.{" "}
12
+ <Link href="/" className={interactiveText}>
13
+ Back to dashboard
14
+ </Link>
15
+ .
16
+ </>
17
+ }
18
+ />
19
+ );
20
+ }
21
+
22
+ export function ClientSideErrorPage() {
23
+ const description = (
24
+ <>
25
+ Sorry, this wasn't supposed to happen. If the error persists, please{" "}
26
+ <a className={interactiveText} href={`mailto:support@indietabletop.club`}>
27
+ get in touch
28
+ </a>
29
+ .
30
+ </>
31
+ );
32
+
33
+ return (
34
+ <InfoPage heading="An wild Error appears!" description={description} />
35
+ );
36
+ }
@@ -0,0 +1,36 @@
1
+ import { manofa } from "@indietabletop/appkit/common.css.ts";
2
+ import { style } from "@vanilla-extract/css";
3
+
4
+ export const page = style({
5
+ minBlockSize: "100svh",
6
+ paddingBlockStart: "30svh",
7
+ paddingInline: "clamp(1rem, 5vw, 3rem)",
8
+ textAlign: "center",
9
+ });
10
+
11
+ export const heading = style([
12
+ manofa,
13
+ {
14
+ fontSize: "1.5rem",
15
+ lineHeight: 1.2,
16
+ },
17
+ ]);
18
+
19
+ export const description = style({
20
+ marginBlockStart: "0.5rem",
21
+ fontSize: "1rem",
22
+ });
23
+
24
+ export const loadingPage = style([
25
+ page,
26
+ { display: "flex", justifyContent: "center" },
27
+ ]);
28
+
29
+ export const loadingView = style({
30
+ display: "flex",
31
+ alignItems: "center",
32
+ justifyContent: "center",
33
+ paddingInline: "clamp(1rem, 5vw, 3rem)",
34
+ textAlign: "center",
35
+ minBlockSize: "30svh",
36
+ });