@indietabletop/appkit 7.0.0-0 → 7.0.0-rc.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 (279) hide show
  1. package/lib/AppConfig/AppConfig.tsx +80 -0
  2. package/lib/AppConfig/formatters.tsx +43 -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/LoadingIndicator.tsx +40 -0
  27. package/lib/MiddotSeparated/MiddotSeparated.stories.ts +26 -0
  28. package/lib/MiddotSeparated/MiddotSeparated.tsx +26 -0
  29. package/lib/MiddotSeparated/style.css.ts +10 -0
  30. package/lib/ModalDialog/index.tsx +28 -0
  31. package/lib/ModalDialog/style.css.ts +88 -0
  32. package/lib/ModernIDB/Cursor.ts +91 -0
  33. package/lib/ModernIDB/ModernIDB.ts +337 -0
  34. package/lib/ModernIDB/ModernIDBError.ts +9 -0
  35. package/lib/ModernIDB/ObjectStore.ts +195 -0
  36. package/lib/ModernIDB/ObjectStoreIndex.ts +102 -0
  37. package/lib/ModernIDB/README.md +9 -0
  38. package/lib/ModernIDB/Transaction.ts +40 -0
  39. package/lib/ModernIDB/VersionChangeManager.ts +57 -0
  40. package/lib/ModernIDB/bindings/factory.tsx +165 -0
  41. package/lib/ModernIDB/bindings/index.ts +2 -0
  42. package/{dist/ModernIDB/bindings/types.d.ts → lib/ModernIDB/bindings/types.ts} +32 -13
  43. package/lib/ModernIDB/bindings/utils.tsx +32 -0
  44. package/lib/ModernIDB/index.ts +10 -0
  45. package/lib/ModernIDB/types.ts +120 -0
  46. package/lib/ModernIDB/utils.ts +51 -0
  47. package/lib/QRCode/QRCode.stories.tsx +41 -0
  48. package/lib/QRCode/QRCode.tsx +54 -0
  49. package/lib/QRCode/style.css.ts +23 -0
  50. package/lib/ReleaseInfo/index.tsx +29 -0
  51. package/lib/RulesetResolver.ts +214 -0
  52. package/lib/SafariCheck/SafariCheck.stories.tsx +99 -0
  53. package/lib/SafariCheck/SafariCheck.tsx +273 -0
  54. package/lib/SafariCheck/addToDock.svg +13 -0
  55. package/lib/SafariCheck/addToHomeScreen.svg +12 -0
  56. package/lib/SafariCheck/safari.svg +32 -0
  57. package/lib/SafariCheck/shareIcon.svg +11 -0
  58. package/lib/SafariCheck/style.css.ts +106 -0
  59. package/lib/ServiceWorkerHandler.tsx +53 -0
  60. package/lib/ShareButton/ShareButton.stories.tsx +58 -0
  61. package/lib/ShareButton/ShareButton.tsx +153 -0
  62. package/lib/ShareButton/test.css.ts +3 -0
  63. package/lib/SubscribeCard/LetterheadInfoCard.tsx +23 -0
  64. package/lib/SubscribeCard/SubscribeByEmailCard.stories.tsx +69 -0
  65. package/lib/SubscribeCard/SubscribeByEmailCard.tsx +183 -0
  66. package/lib/SubscribeCard/SubscribeByPledgeCard.stories.tsx +133 -0
  67. package/lib/SubscribeCard/SubscribeByPledgeCard.tsx +127 -0
  68. package/lib/SubscribeCard/style.css.ts +14 -0
  69. package/lib/Sync/SyncIcon.stories.tsx +67 -0
  70. package/lib/Sync/SyncIcon.tsx +102 -0
  71. package/lib/Sync/SyncLog.tsx +222 -0
  72. package/lib/Sync/SyncLogList.stories.tsx +219 -0
  73. package/lib/Sync/style.css.ts +126 -0
  74. package/lib/account/AccountIcon.tsx +15 -0
  75. package/lib/account/AccountIssueView.tsx +44 -0
  76. package/lib/account/AlreadyLoggedInView.tsx +47 -0
  77. package/lib/account/CurrentUserFetcher.stories.tsx +292 -0
  78. package/lib/account/CurrentUserFetcher.tsx +118 -0
  79. package/lib/account/FailureFallbackView.tsx +36 -0
  80. package/lib/account/JoinCard.stories.tsx +257 -0
  81. package/lib/account/JoinCard.tsx +301 -0
  82. package/lib/account/LoadingView.tsx +14 -0
  83. package/lib/account/LoginCard.stories.tsx +288 -0
  84. package/lib/account/LoginCard.tsx +100 -0
  85. package/lib/account/LoginView.tsx +151 -0
  86. package/lib/account/NoConnectionView.tsx +34 -0
  87. package/lib/account/PasswordResetCard.stories.tsx +242 -0
  88. package/lib/account/PasswordResetCard.tsx +296 -0
  89. package/lib/account/UserMismatchView.tsx +62 -0
  90. package/lib/account/VerifyPage.tsx +195 -0
  91. package/lib/account/iconMask.svg +3 -0
  92. package/lib/account/style.css.ts +81 -0
  93. package/{dist/account/types.d.ts → lib/account/types.ts} +6 -3
  94. package/lib/account/useFetchCurrentUser.tsx +63 -0
  95. package/lib/account/useRedirectPath.ts +21 -0
  96. package/lib/animations.css.ts +17 -0
  97. package/lib/append-copy-to-text.ts +35 -0
  98. package/lib/async-op.ts +286 -0
  99. package/lib/atomic.css.ts +11 -0
  100. package/{dist/caught-value.d.ts → lib/caught-value.ts} +11 -1
  101. package/{dist/class-names.d.ts → lib/class-names.ts} +17 -6
  102. package/lib/client.ts +662 -0
  103. package/lib/common.css.ts +48 -0
  104. package/lib/copyrightRange.ts +10 -0
  105. package/lib/createSafeStorage.ts +91 -0
  106. package/lib/createStrictContext.ts +15 -0
  107. package/lib/failureMessages.ts +108 -0
  108. package/lib/form/FormSubmitButton.tsx +58 -0
  109. package/lib/form/SubmitErrorAlert.tsx +21 -0
  110. package/lib/form/style.css.ts +9 -0
  111. package/lib/globals.css.ts +62 -0
  112. package/lib/groupBy.ts +25 -0
  113. package/lib/hrefs.ts +48 -0
  114. package/lib/idToDate.ts +8 -0
  115. package/lib/ids.ts +6 -0
  116. package/lib/index.ts +75 -0
  117. package/lib/internal.css.ts +10 -0
  118. package/lib/mailto.ts +40 -0
  119. package/lib/media.ts +50 -0
  120. package/lib/random.ts +19 -0
  121. package/lib/result/swr.ts +18 -0
  122. package/{dist/sleep.d.ts → lib/sleep.ts} +3 -1
  123. package/lib/store/index.tsx +294 -0
  124. package/lib/store/store.ts +482 -0
  125. package/lib/store/types.ts +45 -0
  126. package/lib/store/utils.ts +54 -0
  127. package/lib/storybook/decorators.tsx +10 -0
  128. package/lib/structs.ts +3 -0
  129. package/{dist/typeguards.d.ts → lib/typeguards.ts} +3 -1
  130. package/{dist/types.d.ts → lib/types.ts} +23 -12
  131. package/lib/unique.ts +24 -0
  132. package/lib/use-async-op.ts +16 -0
  133. package/lib/use-document-background-color.ts +16 -0
  134. package/lib/use-form.ts +78 -0
  135. package/lib/use-is-installed.ts +17 -0
  136. package/lib/use-media-query.ts +21 -0
  137. package/lib/use-reverting-state.ts +32 -0
  138. package/lib/use-scroll-restoration.ts +99 -0
  139. package/lib/useEnsureValue.ts +31 -0
  140. package/lib/useInvokeClient.ts +54 -0
  141. package/lib/useIsVisible.ts +27 -0
  142. package/lib/utm.ts +92 -0
  143. package/lib/validations.ts +25 -0
  144. package/lib/vars.css.ts +13 -0
  145. package/package.json +23 -29
  146. package/dist/AppConfig/AppConfig.d.ts +0 -29
  147. package/dist/AuthCard/AuthCard.d.ts +0 -10
  148. package/dist/AuthCard/AuthCard.stories.d.ts +0 -34
  149. package/dist/AuthCard/style.css.d.ts +0 -23
  150. package/dist/DialogTrigger/index.d.ts +0 -13
  151. package/dist/DocumentTitle/DocumentTitle.d.ts +0 -3
  152. package/dist/EnumMapper.d.ts +0 -25
  153. package/dist/ExternalLink.d.ts +0 -3
  154. package/dist/FullscreenDismissBlocker.d.ts +0 -5
  155. package/dist/IndieTabletopClubLogo.d.ts +0 -7
  156. package/dist/IndieTabletopClubSymbol.d.ts +0 -7
  157. package/dist/InfoPage/index.d.ts +0 -8
  158. package/dist/InfoPage/pages.d.ts +0 -2
  159. package/dist/InfoPage/style.css.d.ts +0 -5
  160. package/dist/Letterhead/index.d.ts +0 -19
  161. package/dist/Letterhead/stories.d.ts +0 -13
  162. package/dist/Letterhead/style.css.d.ts +0 -46
  163. package/dist/LetterheadForm/LetterheadReadonlyTextField.stories.d.ts +0 -17
  164. package/dist/LetterheadForm/LetterheadSubmitError.stories.d.ts +0 -11
  165. package/dist/LetterheadForm/LetterheadTextField.stories.d.ts +0 -336
  166. package/dist/LetterheadForm/index.d.ts +0 -44
  167. package/dist/LetterheadForm/style.css.d.ts +0 -8
  168. package/dist/LoadingIndicator.d.ts +0 -3
  169. package/dist/MiddotSeparated/MiddotSeparated.d.ts +0 -8
  170. package/dist/MiddotSeparated/MiddotSeparated.stories.d.ts +0 -586
  171. package/dist/MiddotSeparated/style.css.d.ts +0 -1
  172. package/dist/ModalDialog/index.d.ts +0 -12
  173. package/dist/ModalDialog/style.css.d.ts +0 -58
  174. package/dist/ModernIDB/Cursor.d.ts +0 -56
  175. package/dist/ModernIDB/ModernIDB.d.ts +0 -66
  176. package/dist/ModernIDB/ModernIDBError.d.ts +0 -3
  177. package/dist/ModernIDB/ObjectStore.d.ts +0 -112
  178. package/dist/ModernIDB/ObjectStoreIndex.d.ts +0 -53
  179. package/dist/ModernIDB/Transaction.d.ts +0 -16
  180. package/dist/ModernIDB/VersionChangeManager.d.ts +0 -30
  181. package/dist/ModernIDB/bindings/factory.d.ts +0 -12
  182. package/dist/ModernIDB/bindings/index.d.ts +0 -2
  183. package/dist/ModernIDB/bindings/utils.d.ts +0 -2
  184. package/dist/ModernIDB/index.d.ts +0 -10
  185. package/dist/ModernIDB/types.d.ts +0 -88
  186. package/dist/ModernIDB/utils.d.ts +0 -4
  187. package/dist/QRCode/QRCode.d.ts +0 -7
  188. package/dist/QRCode/QRCode.stories.d.ts +0 -33
  189. package/dist/QRCode/style.css.d.ts +0 -4
  190. package/dist/ReleaseInfo/index.d.ts +0 -5
  191. package/dist/RulesetResolver.d.ts +0 -87
  192. package/dist/SafariCheck/SafariCheck.d.ts +0 -23
  193. package/dist/SafariCheck/SafariCheck.stories.d.ts +0 -73
  194. package/dist/SafariCheck/style.css.d.ts +0 -17
  195. package/dist/ServiceWorkerHandler.d.ts +0 -11
  196. package/dist/ShareButton/ShareButton.d.ts +0 -57
  197. package/dist/ShareButton/ShareButton.stories.d.ts +0 -1577
  198. package/dist/ShareButton/test.css.d.ts +0 -1
  199. package/dist/SubscribeCard/LetterheadInfoCard.d.ts +0 -2
  200. package/dist/SubscribeCard/SubscribeByEmailCard.d.ts +0 -24
  201. package/dist/SubscribeCard/SubscribeByEmailCard.stories.d.ts +0 -10
  202. package/dist/SubscribeCard/SubscribeByPledgeCard.d.ts +0 -36
  203. package/dist/SubscribeCard/SubscribeByPledgeCard.stories.d.ts +0 -65
  204. package/dist/SubscribeCard/style.css.d.ts +0 -4
  205. package/dist/account/AccountIssueView.d.ts +0 -3
  206. package/dist/account/AlreadyLoggedInView.d.ts +0 -5
  207. package/dist/account/CurrentUserFetcher.d.ts +0 -20
  208. package/dist/account/CurrentUserFetcher.stories.d.ts +0 -136
  209. package/dist/account/FailureFallbackView.d.ts +0 -1
  210. package/dist/account/JoinCard.d.ts +0 -14
  211. package/dist/account/JoinCard.stories.d.ts +0 -143
  212. package/dist/account/LoadingView.d.ts +0 -1
  213. package/dist/account/LoginCard.d.ts +0 -39
  214. package/dist/account/LoginCard.stories.d.ts +0 -217
  215. package/dist/account/LoginView.d.ts +0 -10
  216. package/dist/account/NoConnectionView.d.ts +0 -4
  217. package/dist/account/PasswordResetCard.d.ts +0 -15
  218. package/dist/account/PasswordResetCard.stories.d.ts +0 -128
  219. package/dist/account/UserMismatchView.d.ts +0 -6
  220. package/dist/account/VerifyPage.d.ts +0 -13
  221. package/dist/account/style.css.d.ts +0 -10
  222. package/dist/account/useFetchCurrentUser.d.ts +0 -28
  223. package/dist/account/useRedirectPath.d.ts +0 -6
  224. package/dist/animations.css.d.ts +0 -3
  225. package/dist/append-copy-to-text.d.ts +0 -10
  226. package/dist/append-copy-to-text.test.d.ts +0 -1
  227. package/dist/appkit.css +0 -1
  228. package/dist/appkit.js +0 -10692
  229. package/dist/async-op.d.ts +0 -101
  230. package/dist/atomic.css.d.ts +0 -6
  231. package/dist/client.d.ts +0 -424
  232. package/dist/common.css.d.ts +0 -5
  233. package/dist/copyrightRange.d.ts +0 -1
  234. package/dist/copyrightRange.test.d.ts +0 -1
  235. package/dist/createSafeStorage.d.ts +0 -34
  236. package/dist/failureMessages.d.ts +0 -20
  237. package/dist/failureMessages.test.d.ts +0 -1
  238. package/dist/form/FormSubmitButton.d.ts +0 -17
  239. package/dist/form/SubmitErrorAlert.d.ts +0 -5
  240. package/dist/form/style.css.d.ts +0 -3
  241. package/dist/globals.css.d.ts +0 -0
  242. package/dist/groupBy.d.ts +0 -1
  243. package/dist/groupBy.test.d.ts +0 -1
  244. package/dist/hrefs.d.ts +0 -32
  245. package/dist/hrefs.test.d.ts +0 -1
  246. package/dist/idToDate.d.ts +0 -5
  247. package/dist/idToDate.test.d.ts +0 -1
  248. package/dist/ids.d.ts +0 -1
  249. package/dist/ids.test.d.ts +0 -1
  250. package/dist/index.d.ts +0 -64
  251. package/dist/internal.css.d.ts +0 -2
  252. package/dist/mailto.d.ts +0 -8
  253. package/dist/mailto.test.d.ts +0 -1
  254. package/dist/media.d.ts +0 -39
  255. package/dist/random.d.ts +0 -3
  256. package/dist/result/swr.d.ts +0 -4
  257. package/dist/store/index.d.ts +0 -237
  258. package/dist/store/store.d.ts +0 -144
  259. package/dist/store/types.d.ts +0 -49
  260. package/dist/store/utils.d.ts +0 -10
  261. package/dist/storybook/decorators.d.ts +0 -3
  262. package/dist/structs.d.ts +0 -1
  263. package/dist/typeguards.test.d.ts +0 -1
  264. package/dist/unique.d.ts +0 -10
  265. package/dist/unique.test.d.ts +0 -1
  266. package/dist/use-async-op.d.ts +0 -6
  267. package/dist/use-document-background-color.d.ts +0 -4
  268. package/dist/use-form.d.ts +0 -29
  269. package/dist/use-is-installed.d.ts +0 -8
  270. package/dist/use-media-query.d.ts +0 -1
  271. package/dist/use-reverting-state.d.ts +0 -5
  272. package/dist/use-scroll-restoration.d.ts +0 -25
  273. package/dist/useEnsureValue.d.ts +0 -6
  274. package/dist/useInvokeClient.d.ts +0 -25
  275. package/dist/useIsVisible.d.ts +0 -4
  276. package/dist/utm.d.ts +0 -58
  277. package/dist/utm.test.d.ts +0 -1
  278. package/dist/validations.d.ts +0 -3
  279. package/dist/vars.css.d.ts +0 -10
@@ -0,0 +1,85 @@
1
+ import { Heading, type HeadingProps } from "@ariakit/react";
2
+ import type { RecipeVariants } from "@vanilla-extract/recipes";
3
+ import type { ComponentPropsWithoutRef, ReactNode } from "react";
4
+ import { cx } from "../class-names.ts";
5
+ import { interactiveText } from "../common.css.ts";
6
+ import { ExternalLink } from "../ExternalLink.tsx";
7
+ import {
8
+ FormSubmitButton,
9
+ type FormSubmitButtonProps,
10
+ } from "../form/FormSubmitButton.tsx";
11
+ import { IndieTabletopClubLogo } from "../IndieTabletopClubLogo.tsx";
12
+ import { IndieTabletopClubSymbol } from "../IndieTabletopClubSymbol.tsx";
13
+ import { LoadingIndicator } from "../LoadingIndicator.tsx";
14
+ import * as css from "./style.css.ts";
15
+
16
+ export type LetterheadHeadingProps = RecipeVariants<typeof css.heading> &
17
+ HeadingProps;
18
+
19
+ export function LetterheadHeading(props: LetterheadHeadingProps) {
20
+ const { align, margin, ...rest } = props;
21
+ return <Heading {...rest} {...cx(props, css.heading({ align, margin }))} />;
22
+ }
23
+
24
+ type LetterheadParagraphProps = RecipeVariants<typeof css.paragraph> &
25
+ ComponentPropsWithoutRef<"p">;
26
+
27
+ export function LetterheadParagraph(props: LetterheadParagraphProps) {
28
+ const { size, align, ...rest } = props;
29
+ return <p {...rest} {...cx(props, css.paragraph({ size, align }))} />;
30
+ }
31
+
32
+ type LetterheadFooterProps = ComponentPropsWithoutRef<"div">;
33
+
34
+ export function LetterheadFooter(props: LetterheadFooterProps) {
35
+ return (
36
+ <div {...props} {...cx(props, css.letterheadFooter)}>
37
+ <IndieTabletopClubLogo {...cx(css.letterheadFooterLogo)} />
38
+
39
+ <LetterheadParagraph {...cx(css.letterheadFooterInfo)} size="small">
40
+ Indie Tabletop Club supports independent game creators with premium
41
+ digital tools.{" "}
42
+ <ExternalLink
43
+ href="https://indietabletop.club"
44
+ className={interactiveText}
45
+ >
46
+ Learn more
47
+ </ExternalLink>
48
+ .
49
+ </LetterheadParagraph>
50
+ </div>
51
+ );
52
+ }
53
+
54
+ type LetterheadSubmitButton = RecipeVariants<typeof css.button> &
55
+ Omit<FormSubmitButtonProps, "loading">;
56
+
57
+ export function LetterheadSubmitButton(props: LetterheadSubmitButton) {
58
+ const { marginBlockStart, ...rest } = props;
59
+ return (
60
+ <FormSubmitButton
61
+ {...rest}
62
+ {...cx(css.button({ marginBlockStart }), props)}
63
+ loading={<LoadingIndicator />}
64
+ />
65
+ );
66
+ }
67
+
68
+ export type LetterheadProps = RecipeVariants<typeof css.letterhead> & {
69
+ headerIcon?: ReactNode;
70
+ children: ReactNode;
71
+ };
72
+
73
+ export function Letterhead(props: LetterheadProps) {
74
+ const { children, textAlign, headerIcon = true } = props;
75
+
76
+ return (
77
+ <div className={css.letterhead({ textAlign })}>
78
+ {headerIcon && <IndieTabletopClubSymbol {...cx(css.letterheadSymbol)} />}
79
+
80
+ {children}
81
+
82
+ <LetterheadFooter />
83
+ </div>
84
+ );
85
+ }
@@ -0,0 +1,41 @@
1
+ import { FormProvider } from "@ariakit/react";
2
+ import preview from "../../.storybook/preview.tsx";
3
+ import {
4
+ Letterhead,
5
+ LetterheadHeading,
6
+ LetterheadParagraph,
7
+ LetterheadSubmitButton,
8
+ } from "./index.tsx";
9
+
10
+ const meta = preview.meta({
11
+ title: "Components/Letterhead",
12
+ component: Letterhead,
13
+ tags: ["autodocs"],
14
+ args: {
15
+ textAlign: "start",
16
+ },
17
+ });
18
+
19
+ export const Default = meta.story({
20
+ args: {
21
+ children: (
22
+ <>
23
+ <LetterheadHeading align="center" margin="letterhead">
24
+ Lorem ipsum dolor
25
+ </LetterheadHeading>
26
+
27
+ <LetterheadParagraph>
28
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut enim ad
29
+ minima veniam, quis <em>nostrum</em> exercitationem ullam corporis
30
+ suscipit laboriosam.
31
+ </LetterheadParagraph>
32
+
33
+ <FormProvider>
34
+ <LetterheadSubmitButton marginBlockStart="footerMargin">
35
+ Lorem ipsum
36
+ </LetterheadSubmitButton>
37
+ </FormProvider>
38
+ </>
39
+ ),
40
+ },
41
+ });
@@ -0,0 +1,152 @@
1
+ import { createTheme, style } from "@vanilla-extract/css";
2
+ import { recipe } from "@vanilla-extract/recipes";
3
+ import { textVariants } from "../atomic.css.ts";
4
+ import { manofa, minion } from "../common.css.ts";
5
+ import { Hover, MinWidth } from "../media.ts";
6
+
7
+ const align = {
8
+ start: textVariants({ textAlign: "start" }),
9
+ center: textVariants({ textAlign: "center" }),
10
+ end: textVariants({ textAlign: "end" }),
11
+ };
12
+
13
+ export const [letterheadTheme, { padding, footerMargin }] = createTheme({
14
+ padding: "1.25rem",
15
+ footerMargin: "3rem",
16
+ });
17
+
18
+ export const letterhead = recipe({
19
+ base: [
20
+ letterheadTheme,
21
+ minion,
22
+ {
23
+ backgroundColor: "white",
24
+ padding: `calc(${padding} / 2) ${padding} ${padding}`,
25
+ borderRadius: "1rem",
26
+ marginInline: "auto",
27
+ maxInlineSize: "36rem",
28
+ transition: "height 200ms",
29
+ height: "calc-size(auto)",
30
+
31
+ "@media": {
32
+ [MinWidth.SMALL]: {
33
+ vars: {
34
+ [padding]: `clamp(1.5rem, 8%, 4rem)`,
35
+ },
36
+ },
37
+ },
38
+ },
39
+ ],
40
+
41
+ defaultVariants: {
42
+ textAlign: "center",
43
+ },
44
+
45
+ variants: {
46
+ textAlign: align,
47
+ },
48
+ });
49
+
50
+ export const letterheadSymbol = style({
51
+ marginBlockEnd: "0.5rem",
52
+ marginInline: "auto",
53
+ display: "block",
54
+ inlineSize: "2.5rem",
55
+ blockSize: "2.5rem",
56
+ });
57
+
58
+ export const heading = recipe({
59
+ base: [
60
+ manofa,
61
+ {
62
+ fontWeight: 400,
63
+ fontSize: "1.5rem",
64
+ marginBlockEnd: "1rem",
65
+ lineHeight: 1.2,
66
+ },
67
+ ],
68
+
69
+ variants: {
70
+ align,
71
+
72
+ margin: {
73
+ letterhead: {
74
+ marginBlockEnd: `min(calc(${padding} / 2), 1.5rem)`,
75
+ },
76
+ },
77
+ },
78
+ });
79
+
80
+ export const paragraph = recipe({
81
+ base: [
82
+ minion,
83
+ {
84
+ lineHeight: 1.5,
85
+ selectors: {
86
+ "& + &": { marginTop: "0.5lh" },
87
+ },
88
+ },
89
+ ],
90
+
91
+ defaultVariants: {
92
+ size: "default",
93
+ },
94
+
95
+ variants: {
96
+ size: {
97
+ small: { fontSize: "0.875rem" },
98
+ default: { fontSize: "1rem" },
99
+ },
100
+ align,
101
+ },
102
+ });
103
+
104
+ export const button = recipe({
105
+ base: [
106
+ manofa,
107
+ {
108
+ letterSpacing: 0,
109
+ textTransform: "uppercase",
110
+ backgroundColor: "black",
111
+ color: "white",
112
+ width: "100%",
113
+ border: "none",
114
+ borderRadius: "0.5rem",
115
+ padding: "1rem 1.5rem",
116
+ fontSize: "0.875rem",
117
+ textAlign: "center",
118
+
119
+ "@media": {
120
+ [Hover.HOVER]: {
121
+ transition: "box-shadow 400ms",
122
+
123
+ ":hover": {
124
+ boxShadow: "inset 0 0 0 2px hsl(0 0% 100% / 0.5)",
125
+ },
126
+ },
127
+ },
128
+ },
129
+ ],
130
+
131
+ variants: {
132
+ marginBlockStart: {
133
+ footerMargin: { marginBlockStart: `calc(${footerMargin} - 0.5rem)` },
134
+ },
135
+ },
136
+ });
137
+
138
+ export const letterheadFooter = style({
139
+ textAlign: "center",
140
+ marginBlockStart: footerMargin,
141
+ paddingBlockStart: "2rem",
142
+ borderBlockStart: "1px solid #ececec",
143
+ });
144
+
145
+ export const letterheadFooterLogo = style({
146
+ margin: "0 auto 1.125rem",
147
+ });
148
+
149
+ export const letterheadFooterInfo = style({
150
+ margin: "0 auto",
151
+ maxInlineSize: "25rem",
152
+ });
@@ -0,0 +1,17 @@
1
+ import preview from "../../.storybook/preview.tsx";
2
+ import { LetterheadReadonlyTextField } from "./index.tsx";
3
+
4
+ const meta = preview.meta({
5
+ title: "Components/ReadonlyTextField",
6
+ component: LetterheadReadonlyTextField,
7
+ tags: ["autodocs"],
8
+ args: {},
9
+ });
10
+
11
+ export const Default = meta.story({
12
+ args: {
13
+ label: "Email",
14
+ value: "john@example.com",
15
+ placeholder: "john@example.com",
16
+ },
17
+ });
@@ -0,0 +1,19 @@
1
+ import preview from "../../.storybook/preview.tsx";
2
+ import { form } from "../storybook/decorators.tsx";
3
+ import { LetterheadSubmitError } from "./index.tsx";
4
+
5
+ const meta = preview.meta({
6
+ title: "Components/LetterheadSubmitError",
7
+ component: LetterheadSubmitError,
8
+ tags: ["autodocs"],
9
+ args: {},
10
+ decorators: [
11
+ form({ defaultErrors: { submit: "This is an error message." } }),
12
+ ],
13
+ });
14
+
15
+ export const Default = meta.story({
16
+ args: {
17
+ name: "submit",
18
+ },
19
+ });
@@ -0,0 +1,19 @@
1
+ import preview from "../../.storybook/preview.tsx";
2
+ import { form } from "../storybook/decorators.tsx";
3
+ import { LetterheadTextField } from "./index.tsx";
4
+
5
+ const meta = preview.meta({
6
+ title: "Components/LetterheadTextField",
7
+ component: LetterheadTextField,
8
+ tags: ["autodocs"],
9
+ args: {},
10
+ decorators: [form()],
11
+ });
12
+
13
+ export const Default = meta.story({
14
+ args: {
15
+ label: "Email",
16
+ placeholder: "john@example.com",
17
+ name: "foo",
18
+ },
19
+ });
@@ -0,0 +1,137 @@
1
+ import {
2
+ FormCheckbox,
3
+ type FormCheckboxProps,
4
+ FormError,
5
+ FormInput,
6
+ type FormInputProps,
7
+ FormLabel,
8
+ } from "@ariakit/react";
9
+ import { type ReactNode } from "react";
10
+ import { cx } from "../class-names.ts";
11
+ import { SubmitErrorAlert } from "../form/SubmitErrorAlert.tsx";
12
+ import * as css from "./style.css.ts";
13
+
14
+ export type LetterheadTextFieldProps = FormInputProps & {
15
+ label: string;
16
+ hint?: ReactNode;
17
+ };
18
+
19
+ export function LetterheadTextField(props: LetterheadTextFieldProps) {
20
+ const { name, label, hint, ...inputProps } = props;
21
+
22
+ return (
23
+ <div>
24
+ <div className={css.field}>
25
+ <FormLabel name={name} className={css.fieldLabel}>
26
+ {label}
27
+ </FormLabel>
28
+
29
+ <FormInput {...inputProps} name={name} className={css.fieldInput} />
30
+ </div>
31
+
32
+ <FormError name={name} className={css.fieldIssue} />
33
+
34
+ {hint && <div className={css.fieldHint}>{hint}</div>}
35
+ </div>
36
+ );
37
+ }
38
+
39
+ export function LetterheadCheckboxField(
40
+ props: FormCheckboxProps & { label: ReactNode },
41
+ ) {
42
+ const { label, name, ...inputProps } = props;
43
+
44
+ return (
45
+ <div {...cx(css.checkboxField)}>
46
+ <div>
47
+ <FormCheckbox name={name} {...inputProps} />{" "}
48
+ <FormLabel name={name}>{label}</FormLabel>
49
+ </div>
50
+
51
+ <FormError name={name} className={css.fieldIssue} />
52
+ </div>
53
+ );
54
+ }
55
+
56
+ type LetterheadReadonlyTextFieldProps = {
57
+ label: string;
58
+ value: string;
59
+ placeholder?: string;
60
+ hint?: ReactNode;
61
+ type?: "text" | "email" | "password";
62
+ };
63
+
64
+ /**
65
+ * Renders a read-only text field.
66
+ *
67
+ * For an editable text field, use {@link LetterheadTextField} along with
68
+ * Ariakit form store.
69
+ */
70
+ export function LetterheadReadonlyTextField(
71
+ props: LetterheadReadonlyTextFieldProps,
72
+ ) {
73
+ return (
74
+ <div>
75
+ <label className={css.field}>
76
+ <span className={css.fieldLabel}>{props.label}</span>
77
+
78
+ <input
79
+ className={css.fieldInput}
80
+ type={props.type ?? "text"}
81
+ value={props.value}
82
+ placeholder={props.placeholder}
83
+ readOnly
84
+ />
85
+ </label>
86
+
87
+ {props.hint && <div className={css.fieldHint}>{props.hint}</div>}
88
+ </div>
89
+ );
90
+ }
91
+
92
+ type LetterheadSubmitErrorProps = {
93
+ name: string;
94
+ };
95
+
96
+ /**
97
+ * Renders an error message from form context.
98
+ *
99
+ * If there is no error message, will be completely omitted from DOM, so there
100
+ * is no need to guard it with an if statement.
101
+ */
102
+ export function LetterheadSubmitError(props: LetterheadSubmitErrorProps) {
103
+ return <SubmitErrorAlert {...props} className={css.submitError} />;
104
+ }
105
+
106
+ export function LetterheadHeader(props: { children: ReactNode }) {
107
+ return <header className={css.header}>{props.children}</header>;
108
+ }
109
+
110
+ export function LetterheadFormActions(props: { children: ReactNode }) {
111
+ return (
112
+ <div
113
+ style={{
114
+ marginBlockStart: "2rem",
115
+ display: "flex",
116
+ flexDirection: "column",
117
+ gap: "1.125rem",
118
+ }}
119
+ >
120
+ {props.children}
121
+ </div>
122
+ );
123
+ }
124
+
125
+ export function InputsStack(props: { children: ReactNode }) {
126
+ return (
127
+ <div
128
+ style={{
129
+ display: "flex",
130
+ flexDirection: "column",
131
+ gap: "1.125rem",
132
+ }}
133
+ >
134
+ {props.children}
135
+ </div>
136
+ );
137
+ }
@@ -0,0 +1,89 @@
1
+ import { style } from "@vanilla-extract/css";
2
+ import { manofa, minion } from "../common.css.ts";
3
+ import { Color } from "../vars.css.ts";
4
+
5
+ const border = style({
6
+ borderRadius: "0.5rem",
7
+ border: `1px solid ${Color.GRAY}`,
8
+ });
9
+
10
+ export const field = style({
11
+ display: "block",
12
+ });
13
+
14
+ export const fieldLabel = style([
15
+ manofa,
16
+ {
17
+ display: "block",
18
+ textTransform: "uppercase",
19
+ fontSize: "0.75rem",
20
+ fontWeight: 600,
21
+ marginBottom: "0.5rem",
22
+ textAlign: "start",
23
+ },
24
+ ]);
25
+
26
+ export const fieldInput = style([
27
+ border,
28
+ minion,
29
+ {
30
+ display: "block",
31
+ width: "100%",
32
+ fontSize: "1rem",
33
+ lineHeight: "1.25rem",
34
+ padding: "1rem 0 1rem 1rem",
35
+ textAlign: "start",
36
+
37
+ ":read-only": {
38
+ backgroundColor: "hsl(0 0% 0% / 0.05)",
39
+ },
40
+
41
+ // Hide MS Edge widgets -- we handle them manually
42
+ "::-ms-clear": {
43
+ display: "none",
44
+ },
45
+ "::-ms-reveal": {
46
+ display: "none",
47
+ },
48
+ },
49
+ ]);
50
+
51
+ export const checkboxField = style({
52
+ textAlign: "start",
53
+ });
54
+
55
+ export const fieldIssue = style({
56
+ color: Color.PURPLE,
57
+ fontSize: "0.875rem",
58
+ marginTop: "0.5rem",
59
+ textAlign: "start",
60
+
61
+ ":empty": {
62
+ display: "none",
63
+ },
64
+ });
65
+
66
+ export const fieldHint = style({
67
+ color: Color.MID_GRAY,
68
+ fontSize: "0.875rem",
69
+ marginTop: "0.5rem",
70
+ textAlign: "start",
71
+
72
+ selectors: {
73
+ [`${fieldIssue}:not(:empty) + &`]: {
74
+ display: "none",
75
+ },
76
+ },
77
+ });
78
+
79
+ export const submitError = style({
80
+ padding: "1rem",
81
+ color: Color.PURPLE,
82
+ backgroundColor: Color.PALE_GRAY,
83
+ borderRadius: "0.75rem",
84
+ textAlign: "start",
85
+ });
86
+
87
+ export const header = style({
88
+ marginBlockEnd: "3rem",
89
+ });
@@ -0,0 +1,40 @@
1
+ import { assignInlineVars } from "@vanilla-extract/dynamic";
2
+ import { animationDelay, dot } from "./internal.css.ts";
3
+
4
+ export function LoadingIndicator(props: { className?: string }) {
5
+ const diameter = 10;
6
+ const radius = diameter / 2;
7
+ const gap = diameter;
8
+ const cy = diameter;
9
+ const height = cy * 2;
10
+ const width = diameter * 3 + gap;
11
+ const initialDelay = 300;
12
+ const interBounceDelay = 150;
13
+
14
+ return (
15
+ <svg
16
+ viewBox={`0 0 ${width} ${height}`}
17
+ width={width}
18
+ height={height}
19
+ className={props.className}
20
+ preserveAspectRatio="xMidYMid meet"
21
+ >
22
+ <g stroke="none" fill="inherit">
23
+ {Array.from({ length: 3 }, (_, index) => {
24
+ const delay = `${initialDelay + interBounceDelay * index}ms`;
25
+
26
+ return (
27
+ <circle
28
+ key={index}
29
+ cx={radius * (index + 1) + gap * index}
30
+ cy={cy}
31
+ r={radius}
32
+ className={dot}
33
+ style={assignInlineVars({ [animationDelay]: delay })}
34
+ />
35
+ );
36
+ })}
37
+ </g>
38
+ </svg>
39
+ );
40
+ }
@@ -0,0 +1,26 @@
1
+ import preview from "../../.storybook/preview.tsx";
2
+ import { MiddotSeparated } from "./MiddotSeparated.tsx";
3
+
4
+ const meta = preview.meta({
5
+ title: "Components/Middot Separated",
6
+ component: MiddotSeparated,
7
+ tags: ["autodocs"],
8
+ });
9
+
10
+ /**
11
+ * The default case in which all steps of the flow succeed.
12
+ */
13
+ export const Default = meta.story({
14
+ args: {
15
+ children: ["Lorem", "Ipsum", " Dolor"],
16
+ },
17
+ });
18
+
19
+ /**
20
+ * Edge case when it comes to handling children in React.
21
+ */
22
+ export const SingleElement = meta.story({
23
+ args: {
24
+ children: "Lorem",
25
+ },
26
+ });
@@ -0,0 +1,26 @@
1
+ import { type HTMLAttributes, Children } from "react";
2
+ import { withMiddlot } from "./style.css.ts";
3
+
4
+ type MiddotSeparatedProps = HTMLAttributes<HTMLDivElement>;
5
+
6
+ /**
7
+ * A utility component that wraps children into spans and adds middledots
8
+ * between each item using CSS ::before pseudo elements.
9
+ */
10
+ export function MiddotSeparated(props: MiddotSeparatedProps) {
11
+ const { children, ...divProps } = props;
12
+
13
+ return (
14
+ <div {...divProps}>
15
+ {Children.toArray(children)
16
+ .filter((item) => item !== "")
17
+ .map((item, index) => {
18
+ return (
19
+ <span className={withMiddlot} key={index}>
20
+ {item}
21
+ </span>
22
+ );
23
+ })}
24
+ </div>
25
+ );
26
+ }
@@ -0,0 +1,10 @@
1
+ import { style } from "@vanilla-extract/css";
2
+
3
+ export const withMiddlot = style({
4
+ selectors: {
5
+ "& + &::before": {
6
+ content: " · ",
7
+ opacity: 0.6,
8
+ },
9
+ },
10
+ });
@@ -0,0 +1,28 @@
1
+ import { Dialog, type DialogProps } from "@ariakit/react";
2
+ import type { RecipeVariants } from "@vanilla-extract/recipes";
3
+ import type { ReactNode } from "react";
4
+ import { cx } from "../class-names.ts";
5
+ import * as css from "./style.css.ts";
6
+
7
+ type Size = NonNullable<NonNullable<RecipeVariants<typeof css.dialog>>["size"]>;
8
+
9
+ export type ModalDialogProps = Omit<DialogProps, "modal" | "backdrop"> & {
10
+ children: ReactNode;
11
+ size: Size;
12
+ backdropClassName?: string;
13
+ };
14
+
15
+ export function ModalDialog(props: ModalDialogProps) {
16
+ const { size, backdropClassName, className, ...dialogProps } = props;
17
+
18
+ return (
19
+ <Dialog
20
+ {...dialogProps}
21
+ {...cx(className, css.dialog({ size }))}
22
+ backdrop={<div {...cx(css.backdrop, backdropClassName)} />}
23
+ modal
24
+ >
25
+ {props.children}
26
+ </Dialog>
27
+ );
28
+ }